nexrall-code 0.5.167 → 0.5.169
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/index.js +902 -216
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11355,7 +11355,7 @@ var require_memory = __commonJS({
|
|
|
11355
11355
|
}();
|
|
11356
11356
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11357
11357
|
exports2.AGENT_MEMORY_MAX_BYTES = exports2.AGENT_MEMORY_INJECT_MAX = exports2.MEMORY_ARCHIVE_MAX_BYTES = exports2.MEMORY_HARD_CAP_BYTES = exports2.MEMORY_COMPACT_TRIGGER_BYTES = exports2.MEMORY_MAX_BYTES = exports2.MEMORY_ENTRY_MAX_CHARS = void 0;
|
|
11358
|
-
exports2.memoryFilePath =
|
|
11358
|
+
exports2.memoryFilePath = memoryFilePath2;
|
|
11359
11359
|
exports2.writeMemory = writeMemory2;
|
|
11360
11360
|
exports2.readMemory = readMemory2;
|
|
11361
11361
|
exports2.readAllMemory = readAllMemory2;
|
|
@@ -11374,7 +11374,7 @@ var require_memory = __commonJS({
|
|
|
11374
11374
|
var crypto9 = __importStar(__require("crypto"));
|
|
11375
11375
|
var MEMORY_ROOT = process.env.NEXRALL_MEMORY_DIR || path28.join(os17.homedir(), ".nexrall", "memory");
|
|
11376
11376
|
var GLOBAL_FILE = path28.join(MEMORY_ROOT, "global.md");
|
|
11377
|
-
function
|
|
11377
|
+
function memoryFilePath2(scope, workDir) {
|
|
11378
11378
|
if (scope === "global" || !workDir)
|
|
11379
11379
|
return GLOBAL_FILE;
|
|
11380
11380
|
const key = crypto9.createHash("sha1").update(path28.resolve(workDir)).digest("hex").slice(0, 16);
|
|
@@ -11468,7 +11468,7 @@ ${SUPERSEDED_HEADER}
|
|
|
11468
11468
|
trimmed = trimmed.slice(0, budget - 1).trimEnd() + "\u2026";
|
|
11469
11469
|
}
|
|
11470
11470
|
const body = prefix2 && budget > 0 ? prefix2 + trimmed : trimmed;
|
|
11471
|
-
const file =
|
|
11471
|
+
const file = memoryFilePath2(scope, workDir);
|
|
11472
11472
|
return withLock(file, async () => {
|
|
11473
11473
|
const existing = readMemoryFile(file);
|
|
11474
11474
|
let { active, archived } = parseSections(existing);
|
|
@@ -11503,7 +11503,7 @@ ${SUPERSEDED_HEADER}
|
|
|
11503
11503
|
});
|
|
11504
11504
|
}
|
|
11505
11505
|
function readMemory2(scope, workDir, opts = {}) {
|
|
11506
|
-
const file =
|
|
11506
|
+
const file = memoryFilePath2(scope, workDir);
|
|
11507
11507
|
const { active, archived } = parseSections(readMemoryFile(file));
|
|
11508
11508
|
if (!opts.includeArchived)
|
|
11509
11509
|
return active.length ? serializeSections(active, []).trim() : "";
|
|
@@ -11524,14 +11524,14 @@ ${projMem}`);
|
|
|
11524
11524
|
return parts.join("\n\n");
|
|
11525
11525
|
}
|
|
11526
11526
|
function clearMemory2(scope, workDir) {
|
|
11527
|
-
const file =
|
|
11527
|
+
const file = memoryFilePath2(scope, workDir);
|
|
11528
11528
|
try {
|
|
11529
11529
|
fs28.rmSync(file, { force: true });
|
|
11530
11530
|
} catch {
|
|
11531
11531
|
}
|
|
11532
11532
|
}
|
|
11533
11533
|
function memoryStats2(scope, workDir) {
|
|
11534
|
-
const file =
|
|
11534
|
+
const file = memoryFilePath2(scope, workDir);
|
|
11535
11535
|
const content = readMemoryFile(file);
|
|
11536
11536
|
const { active, archived } = parseSections(content);
|
|
11537
11537
|
return {
|
|
@@ -11545,7 +11545,7 @@ ${projMem}`);
|
|
|
11545
11545
|
return reply.split("\n").map((l2) => l2.trimEnd()).filter((l2) => /^-\s\[\d{4}-\d{2}-\d{2}\]\s*\S/.test(l2));
|
|
11546
11546
|
}
|
|
11547
11547
|
async function compactMemoryIfNeeded2(scope, workDir, summarize) {
|
|
11548
|
-
const file =
|
|
11548
|
+
const file = memoryFilePath2(scope, workDir);
|
|
11549
11549
|
return withLock(file, async () => {
|
|
11550
11550
|
const content = readMemoryFile(file);
|
|
11551
11551
|
if (Buffer.byteLength(content, "utf-8") <= exports2.MEMORY_COMPACT_TRIGGER_BYTES)
|
|
@@ -106910,8 +106910,11 @@ var require_loop = __commonJS({
|
|
|
106910
106910
|
}();
|
|
106911
106911
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
106912
106912
|
exports2.VERIFY_CMD_RE = exports2.WRITE_TOOL_NAMES = exports2.ToolNotAllowedError = exports2.AGENT_MEMORY_TOOL_SCHEMA = exports2.AGENT_MEMORY_TOOL = exports2._stallLimits = exports2._emptyTurnRetry = exports2.bashNeedsRepoLock = void 0;
|
|
106913
|
+
exports2.loadHooks = loadHooks;
|
|
106914
|
+
exports2.parsePromptHookReply = parsePromptHookReply;
|
|
106915
|
+
exports2.classifyStopFailure = classifyStopFailure;
|
|
106913
106916
|
exports2.runLifecycleHooks = runLifecycleHooks;
|
|
106914
|
-
exports2.runPermissionRequestHooks =
|
|
106917
|
+
exports2.runPermissionRequestHooks = runPermissionRequestHooks3;
|
|
106915
106918
|
exports2.fireNotificationHooks = fireNotificationHooks2;
|
|
106916
106919
|
exports2.fireManualPostCompactHook = fireManualPostCompactHook2;
|
|
106917
106920
|
exports2.fireManualPreCompactHook = fireManualPreCompactHook2;
|
|
@@ -107027,8 +107030,42 @@ var require_loop = __commonJS({
|
|
|
107027
107030
|
...extra
|
|
107028
107031
|
];
|
|
107029
107032
|
}
|
|
107033
|
+
for (const phase of ENTRY_LIST_PHASES) {
|
|
107034
|
+
const list = merged[phase];
|
|
107035
|
+
if (Array.isArray(list) && list.length) {
|
|
107036
|
+
merged[phase] = toHookEntries(list);
|
|
107037
|
+
}
|
|
107038
|
+
}
|
|
107030
107039
|
return merged;
|
|
107031
107040
|
}
|
|
107041
|
+
var ENTRY_LIST_PHASES = [
|
|
107042
|
+
"PreToolUse",
|
|
107043
|
+
"PostToolUse",
|
|
107044
|
+
"SessionStart",
|
|
107045
|
+
"UserPromptSubmit",
|
|
107046
|
+
"PreCompact",
|
|
107047
|
+
"PermissionRequest",
|
|
107048
|
+
"Notification",
|
|
107049
|
+
"PostToolUseFailure",
|
|
107050
|
+
"SubagentStart",
|
|
107051
|
+
"PostCompact",
|
|
107052
|
+
"SessionEnd",
|
|
107053
|
+
"FileChanged",
|
|
107054
|
+
"InstructionsLoaded",
|
|
107055
|
+
"StopFailure"
|
|
107056
|
+
];
|
|
107057
|
+
function toHookEntries(list) {
|
|
107058
|
+
return list.map((it) => {
|
|
107059
|
+
const e2 = it;
|
|
107060
|
+
if (Array.isArray(e2.hooks))
|
|
107061
|
+
return { matcher: e2.matcher, hooks: e2.hooks };
|
|
107062
|
+
const { matcher, ...rest } = e2;
|
|
107063
|
+
const hook = { ...rest };
|
|
107064
|
+
if (!isKnownHandlerType(hook.type))
|
|
107065
|
+
hook.type = "command";
|
|
107066
|
+
return { matcher, hooks: [hook] };
|
|
107067
|
+
});
|
|
107068
|
+
}
|
|
107032
107069
|
function spawnHook(command, opts) {
|
|
107033
107070
|
return new Promise((resolve11) => {
|
|
107034
107071
|
let stdout = "";
|
|
@@ -107098,8 +107135,206 @@ var require_loop = __commonJS({
|
|
|
107098
107135
|
async function runHookHandler(hook, payload, opts) {
|
|
107099
107136
|
if (hook.type === "http")
|
|
107100
107137
|
return httpHook(hook, payload, opts.timeoutMs);
|
|
107138
|
+
if (hook.type === "prompt" || hook.type === "agent") {
|
|
107139
|
+
return promptHook(hook, payload, { ...opts, envCtx: opts.hookEnv });
|
|
107140
|
+
}
|
|
107101
107141
|
return spawnHook(String(hook.command ?? ""), { cwd: opts.cwd, timeout: opts.timeoutMs, input: payload, env: opts.env });
|
|
107102
107142
|
}
|
|
107143
|
+
var HOOK_AGENT_TOOLS = [
|
|
107144
|
+
{
|
|
107145
|
+
name: "read_file",
|
|
107146
|
+
description: "Read a file from the working directory.",
|
|
107147
|
+
input_schema: {
|
|
107148
|
+
type: "object",
|
|
107149
|
+
properties: {
|
|
107150
|
+
path: { type: "string", description: "File path, relative to the working directory." },
|
|
107151
|
+
offset: { type: "number", description: "0-based line to start from." },
|
|
107152
|
+
limit: { type: "number", description: "Maximum number of lines." }
|
|
107153
|
+
},
|
|
107154
|
+
required: ["path"]
|
|
107155
|
+
}
|
|
107156
|
+
},
|
|
107157
|
+
{
|
|
107158
|
+
name: "search_files",
|
|
107159
|
+
description: "Search file contents (regex) or find files by name in the working directory.",
|
|
107160
|
+
input_schema: {
|
|
107161
|
+
type: "object",
|
|
107162
|
+
properties: {
|
|
107163
|
+
pattern: { type: "string", description: "Regex or literal string to search for." },
|
|
107164
|
+
path: { type: "string", description: "Directory to search in." },
|
|
107165
|
+
type: { type: "string", description: "files (paths only) | content (matching lines) | filename." }
|
|
107166
|
+
},
|
|
107167
|
+
required: ["pattern"]
|
|
107168
|
+
}
|
|
107169
|
+
},
|
|
107170
|
+
{
|
|
107171
|
+
name: "list_directory",
|
|
107172
|
+
description: "List the files and directories at a path.",
|
|
107173
|
+
input_schema: { type: "object", properties: { path: { type: "string" } } }
|
|
107174
|
+
},
|
|
107175
|
+
{
|
|
107176
|
+
name: "glob",
|
|
107177
|
+
description: 'Find files matching a glob pattern, e.g. "**/*.ts".',
|
|
107178
|
+
input_schema: { type: "object", properties: { pattern: { type: "string" }, path: { type: "string" } }, required: ["pattern"] }
|
|
107179
|
+
}
|
|
107180
|
+
];
|
|
107181
|
+
var NO_TOOLS_MARKER = "\0hook-no-tools";
|
|
107182
|
+
function parsePromptHookReply(reply) {
|
|
107183
|
+
const text = String(reply ?? "");
|
|
107184
|
+
const start = text.indexOf("{");
|
|
107185
|
+
const end = text.lastIndexOf("}");
|
|
107186
|
+
if (start < 0 || end <= start)
|
|
107187
|
+
return null;
|
|
107188
|
+
try {
|
|
107189
|
+
const j = JSON.parse(text.slice(start, end + 1));
|
|
107190
|
+
if (typeof j.ok !== "boolean" && typeof j.decision !== "string")
|
|
107191
|
+
return null;
|
|
107192
|
+
return {
|
|
107193
|
+
ok: typeof j.ok === "boolean" ? j.ok : void 0,
|
|
107194
|
+
reason: typeof j.reason === "string" ? j.reason : void 0,
|
|
107195
|
+
additionalContext: typeof j.additionalContext === "string" ? j.additionalContext : void 0,
|
|
107196
|
+
decision: typeof j.decision === "string" ? j.decision : void 0
|
|
107197
|
+
};
|
|
107198
|
+
} catch {
|
|
107199
|
+
return null;
|
|
107200
|
+
}
|
|
107201
|
+
}
|
|
107202
|
+
var PROMPT_HOOK_RULES = `You are a hook evaluator for a coding agent. The hook input JSON is given below, followed by the hook's own instruction. Decide whether the agent action described in the input should proceed. Reply with ONLY one JSON object and nothing else: {"ok":true} to allow, or {"ok":false,"reason":"short explanation"} to block.`;
|
|
107203
|
+
async function promptHook(hook, payload, opts) {
|
|
107204
|
+
const instruction = String(hook.prompt ?? "");
|
|
107205
|
+
if (!instruction)
|
|
107206
|
+
return { status: 1, stdout: "", stderr: 'prompt hook has no "prompt"' };
|
|
107207
|
+
const body = instruction.replace(/\\\$ARGUMENTS/g, "").replace(/\$ARGUMENTS/g, payload).replace(/\u0001/g, "$ARGUMENTS");
|
|
107208
|
+
const ctl = { aborted: false };
|
|
107209
|
+
const timer = setTimeout(() => {
|
|
107210
|
+
ctl.aborted = true;
|
|
107211
|
+
}, Math.max(1e3, opts.timeoutMs));
|
|
107212
|
+
const outerPoll = opts.abortSignal ? setInterval(() => {
|
|
107213
|
+
if (opts.abortSignal?.aborted)
|
|
107214
|
+
ctl.aborted = true;
|
|
107215
|
+
}, 100) : void 0;
|
|
107216
|
+
if (opts.abortSignal?.aborted) {
|
|
107217
|
+
clearTimeout(timer);
|
|
107218
|
+
if (outerPoll)
|
|
107219
|
+
clearInterval(outerPoll);
|
|
107220
|
+
return { status: 1, stdout: "", stderr: "aborted" };
|
|
107221
|
+
}
|
|
107222
|
+
try {
|
|
107223
|
+
return await runModel();
|
|
107224
|
+
} finally {
|
|
107225
|
+
clearTimeout(timer);
|
|
107226
|
+
if (outerPoll)
|
|
107227
|
+
clearInterval(outerPoll);
|
|
107228
|
+
}
|
|
107229
|
+
async function runModel() {
|
|
107230
|
+
const messages = [{
|
|
107231
|
+
role: "user",
|
|
107232
|
+
content: [{ type: "text", text: `${PROMPT_HOOK_RULES}
|
|
107233
|
+
|
|
107234
|
+
Hook input:
|
|
107235
|
+
${payload}
|
|
107236
|
+
|
|
107237
|
+
Hook instruction:
|
|
107238
|
+
${body}` }]
|
|
107239
|
+
}];
|
|
107240
|
+
const isAgent = hook.type === "agent";
|
|
107241
|
+
try {
|
|
107242
|
+
let replyText = "";
|
|
107243
|
+
for (let round = 0; round < (isAgent ? 6 : 1); round++) {
|
|
107244
|
+
const msg = await (0, client_1.streamChat)(messages, {
|
|
107245
|
+
model: hook.model ?? opts.model ?? "turbo",
|
|
107246
|
+
env: opts.envCtx ?? { cwd: opts.cwd },
|
|
107247
|
+
abortSignal: ctl,
|
|
107248
|
+
// Wire the tools by allowlist rather than a separate channel: the backend
|
|
107249
|
+
// filters builtins+extra against it, so an agent hook sees ONLY the four
|
|
107250
|
+
// read-only tools and a prompt hook sees none (the marker matches nothing).
|
|
107251
|
+
toolAllowlist: isAgent ? HOOK_AGENT_TOOLS.map((t2) => t2.name) : [NO_TOOLS_MARKER],
|
|
107252
|
+
extraTools: isAgent ? HOOK_AGENT_TOOLS : void 0
|
|
107253
|
+
}, () => {
|
|
107254
|
+
});
|
|
107255
|
+
const blocks = Array.isArray(msg.content) ? msg.content : [];
|
|
107256
|
+
const toolUses = blocks.filter((b) => b.type === "tool_use");
|
|
107257
|
+
if (!toolUses.length || !isAgent) {
|
|
107258
|
+
replyText = blocks.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
|
|
107259
|
+
break;
|
|
107260
|
+
}
|
|
107261
|
+
messages.push({ role: "assistant", content: msg.content });
|
|
107262
|
+
const results = [];
|
|
107263
|
+
for (const tu of toolUses) {
|
|
107264
|
+
let out;
|
|
107265
|
+
try {
|
|
107266
|
+
out = getHookToolExecutors().includes(String(tu.name)) ? await (0, executor_1.executeTool)(String(tu.name), tu.input ?? {}, ctl, void 0, opts.cwd) : { error: `Tool ${String(tu.name)} is not available to a hook \u2014 only ${getHookToolExecutors().join(", ")}.` };
|
|
107267
|
+
} catch (err) {
|
|
107268
|
+
out = { error: err.message || "tool failed" };
|
|
107269
|
+
}
|
|
107270
|
+
results.push({
|
|
107271
|
+
type: "tool_result",
|
|
107272
|
+
tool_use_id: String(tu.id),
|
|
107273
|
+
content: out.error ? out.output ? `Error: ${out.error}
|
|
107274
|
+
|
|
107275
|
+
${out.output}` : `Error: ${out.error}` : out.output ?? "",
|
|
107276
|
+
is_error: out.error !== void 0
|
|
107277
|
+
});
|
|
107278
|
+
}
|
|
107279
|
+
messages.push({ role: "user", content: results });
|
|
107280
|
+
}
|
|
107281
|
+
const parsed = parsePromptHookReply(replyText);
|
|
107282
|
+
if (!parsed) {
|
|
107283
|
+
return { status: 1, stdout: "", stderr: "prompt hook returned no decision" };
|
|
107284
|
+
}
|
|
107285
|
+
const decided = parsed.ok === false || parsed.decision === "block" || parsed.decision === "deny";
|
|
107286
|
+
if (decided)
|
|
107287
|
+
return { status: 2, stdout: "", stderr: parsed.reason || `Blocked by ${hook.type} hook` };
|
|
107288
|
+
const passthrough2 = parsed.additionalContext ? JSON.stringify({ additionalContext: parsed.additionalContext }) : "";
|
|
107289
|
+
return { status: 0, stdout: passthrough2, stderr: "" };
|
|
107290
|
+
} catch (err) {
|
|
107291
|
+
if (ctl.aborted)
|
|
107292
|
+
return { status: 1, stdout: "", stderr: "prompt hook timed out" };
|
|
107293
|
+
return { status: 1, stdout: "", stderr: `prompt hook failed: ${err.message}` };
|
|
107294
|
+
}
|
|
107295
|
+
}
|
|
107296
|
+
}
|
|
107297
|
+
function getHookToolExecutors() {
|
|
107298
|
+
return ["read_file", "search_files", "list_directory", "glob"];
|
|
107299
|
+
}
|
|
107300
|
+
function hookRunOptsFor(options) {
|
|
107301
|
+
return { model: options.model ?? "turbo", abortSignal: options.abortSignal, hookEnv: options.env };
|
|
107302
|
+
}
|
|
107303
|
+
function classifyStopFailure(err) {
|
|
107304
|
+
const status = err?.status;
|
|
107305
|
+
const code = err?.code;
|
|
107306
|
+
const details = [status ? `HTTP ${status}` : "", code ? String(code) : ""].filter(Boolean).join(" ") || void 0;
|
|
107307
|
+
if (status === 429)
|
|
107308
|
+
return { error: "rate_limit", error_details: details };
|
|
107309
|
+
if (status === 529)
|
|
107310
|
+
return { error: "overloaded", error_details: details };
|
|
107311
|
+
if (status === 401)
|
|
107312
|
+
return { error: "authentication_failed", error_details: details };
|
|
107313
|
+
if (status === 402)
|
|
107314
|
+
return { error: "billing_error", error_details: details };
|
|
107315
|
+
if (status === 403)
|
|
107316
|
+
return { error: "authentication_failed", error_details: details };
|
|
107317
|
+
if (status === 400 || status === 422)
|
|
107318
|
+
return { error: "invalid_request", error_details: details };
|
|
107319
|
+
if (status === 404)
|
|
107320
|
+
return { error: "model_not_found", error_details: details };
|
|
107321
|
+
if (typeof status === "number" && status >= 500)
|
|
107322
|
+
return { error: "server_error", error_details: details };
|
|
107323
|
+
return { error: "unknown", error_details: details };
|
|
107324
|
+
}
|
|
107325
|
+
function apiFailureForStopReason(stopReason) {
|
|
107326
|
+
if (stopReason === "output-limit")
|
|
107327
|
+
return { error: "max_output_tokens" };
|
|
107328
|
+
if (stopReason === "no-balance")
|
|
107329
|
+
return { error: "billing_error", error_details: "wallet empty (402)" };
|
|
107330
|
+
if (stopReason === "no-team-budget")
|
|
107331
|
+
return { error: "billing_error", error_details: "team pool empty (402)" };
|
|
107332
|
+
if (stopReason === "reported-elsewhere")
|
|
107333
|
+
return { error: "billing_error", error_details: "pre-flight 402" };
|
|
107334
|
+
if (stopReason === "team-unavailable")
|
|
107335
|
+
return { error: "account_on_hold", error_details: "team billing unusable (403)" };
|
|
107336
|
+
return null;
|
|
107337
|
+
}
|
|
107103
107338
|
function hookTimeoutMs(hook, fallbackMs = 6e4) {
|
|
107104
107339
|
if (typeof hook.timeout_ms === "number" && hook.timeout_ms > 0)
|
|
107105
107340
|
return Math.min(hook.timeout_ms, 6e5);
|
|
@@ -107115,7 +107350,7 @@ var require_loop = __commonJS({
|
|
|
107115
107350
|
return norm === toolName || norm === alt && toolName.includes(alt);
|
|
107116
107351
|
});
|
|
107117
107352
|
}
|
|
107118
|
-
async function runToolHooks(entries, phase, toolName, input, workDir, result) {
|
|
107353
|
+
async function runToolHooks(entries, phase, toolName, input, workDir, result, hookOpts) {
|
|
107119
107354
|
const outcome = { block: false };
|
|
107120
107355
|
if (!entries?.length)
|
|
107121
107356
|
return outcome;
|
|
@@ -107129,11 +107364,7 @@ var require_loop = __commonJS({
|
|
|
107129
107364
|
if (!hookMatches(entry.matcher, toolName))
|
|
107130
107365
|
continue;
|
|
107131
107366
|
for (const hook of entry.hooks ?? []) {
|
|
107132
|
-
if (hook
|
|
107133
|
-
continue;
|
|
107134
|
-
if (hook.type === "command" && !hook.command)
|
|
107135
|
-
continue;
|
|
107136
|
-
if (hook.type === "http" && !hook.url)
|
|
107367
|
+
if (!isRunnableHook(hook))
|
|
107137
107368
|
continue;
|
|
107138
107369
|
const hookTimeout = hookTimeoutMs(hook, 6e4);
|
|
107139
107370
|
const r2 = await runHookHandler(hook, payload, {
|
|
@@ -107144,7 +107375,8 @@ var require_loop = __commonJS({
|
|
|
107144
107375
|
NEXRALL_TOOL_NAME: toolName,
|
|
107145
107376
|
NEXRALL_TOOL_INPUT: JSON.stringify(input),
|
|
107146
107377
|
NEXRALL_HOOK_PHASE: phase
|
|
107147
|
-
}
|
|
107378
|
+
},
|
|
107379
|
+
...hookOpts
|
|
107148
107380
|
});
|
|
107149
107381
|
const out = (r2.stdout ?? "").toString().trim();
|
|
107150
107382
|
if (out.startsWith("{")) {
|
|
@@ -107169,17 +107401,13 @@ var require_loop = __commonJS({
|
|
|
107169
107401
|
}
|
|
107170
107402
|
return outcome;
|
|
107171
107403
|
}
|
|
107172
|
-
async function runSimpleHooks(defs, workDir, extraEnv) {
|
|
107404
|
+
async function runSimpleHooks(defs, workDir, extraEnv, hookOpts) {
|
|
107173
107405
|
if (!defs?.length)
|
|
107174
107406
|
return;
|
|
107175
107407
|
for (const hook of defs) {
|
|
107176
|
-
if (hook
|
|
107408
|
+
if (!isRunnableHook(hook))
|
|
107177
107409
|
continue;
|
|
107178
|
-
|
|
107179
|
-
continue;
|
|
107180
|
-
if (hook.type === "http" && !hook.url)
|
|
107181
|
-
continue;
|
|
107182
|
-
await runHookHandler(hook, "", { cwd: workDir, timeoutMs: hookTimeoutMs(hook, 1e4), env: extraEnv ? { ...process.env, ...extraEnv } : void 0 });
|
|
107410
|
+
await runHookHandler(hook, "", { cwd: workDir, timeoutMs: hookTimeoutMs(hook, 1e4), env: extraEnv ? { ...process.env, ...extraEnv } : void 0, ...hookOpts });
|
|
107183
107411
|
}
|
|
107184
107412
|
}
|
|
107185
107413
|
function flattenHookDefs(items, matchValue) {
|
|
@@ -107190,26 +107418,34 @@ var require_loop = __commonJS({
|
|
|
107190
107418
|
if (m2 && m2 !== "*" && matchValue !== void 0 && !m2.split("|").map((x2) => x2.trim()).includes(matchValue))
|
|
107191
107419
|
continue;
|
|
107192
107420
|
out.push(...it.hooks);
|
|
107193
|
-
} else if (it && (it.type
|
|
107421
|
+
} else if (it && isKnownHandlerType(it.type))
|
|
107194
107422
|
out.push(it);
|
|
107195
107423
|
}
|
|
107196
107424
|
return out;
|
|
107197
107425
|
}
|
|
107198
|
-
|
|
107426
|
+
function isKnownHandlerType(t2) {
|
|
107427
|
+
return t2 === "command" || t2 === "http" || t2 === "prompt" || t2 === "agent";
|
|
107428
|
+
}
|
|
107429
|
+
function isRunnableHook(hook) {
|
|
107430
|
+
if (!isKnownHandlerType(hook.type))
|
|
107431
|
+
return false;
|
|
107432
|
+
if (hook.type === "command")
|
|
107433
|
+
return !!hook.command;
|
|
107434
|
+
if (hook.type === "http")
|
|
107435
|
+
return !!hook.url;
|
|
107436
|
+
return !!hook.prompt;
|
|
107437
|
+
}
|
|
107438
|
+
async function runLifecycleHooks(items, event, workDir, payload, matchValue, hookOpts) {
|
|
107199
107439
|
const outcome = { block: false };
|
|
107200
107440
|
const defs = flattenHookDefs(items, matchValue);
|
|
107201
107441
|
if (!defs.length)
|
|
107202
107442
|
return outcome;
|
|
107203
107443
|
const input = JSON.stringify({ hook_event_name: event, cwd: workDir, ...payload });
|
|
107204
107444
|
for (const hook of defs) {
|
|
107205
|
-
if (hook
|
|
107206
|
-
continue;
|
|
107207
|
-
if (hook.type === "command" && !hook.command)
|
|
107208
|
-
continue;
|
|
107209
|
-
if (hook.type === "http" && !hook.url)
|
|
107445
|
+
if (!isRunnableHook(hook))
|
|
107210
107446
|
continue;
|
|
107211
|
-
const timeout = hookTimeoutMs(hook, 3e4);
|
|
107212
|
-
const r2 = await runHookHandler(hook, input, { cwd: workDir, timeoutMs: timeout, env: { ...process.env, NEXRALL_HOOK_PHASE: event } });
|
|
107447
|
+
const timeout = hookTimeoutMs(hook, hook.type === "agent" ? 6e4 : hook.type === "prompt" ? 3e4 : 3e4);
|
|
107448
|
+
const r2 = await runHookHandler(hook, input, { cwd: workDir, timeoutMs: timeout, env: { ...process.env, NEXRALL_HOOK_PHASE: event }, ...hookOpts });
|
|
107213
107449
|
const out = (r2.stdout ?? "").toString().trim();
|
|
107214
107450
|
if (out.startsWith("{")) {
|
|
107215
107451
|
try {
|
|
@@ -107229,6 +107465,10 @@ var require_loop = __commonJS({
|
|
|
107229
107465
|
}
|
|
107230
107466
|
if (typeof j.additionalContext === "string" && j.additionalContext)
|
|
107231
107467
|
outcome.context = (outcome.context ? outcome.context + "\n" : "") + j.additionalContext;
|
|
107468
|
+
if (event === "FileChanged" && Array.isArray(j.watchPaths))
|
|
107469
|
+
outcome.watchPaths = j.watchPaths.filter((p) => typeof p === "string");
|
|
107470
|
+
if (typeof j.systemMessage === "string" && j.systemMessage)
|
|
107471
|
+
outcome.systemMessage = j.systemMessage;
|
|
107232
107472
|
} catch {
|
|
107233
107473
|
}
|
|
107234
107474
|
} else if (out && (event === "SessionStart" || event === "UserPromptSubmit") && r2.status === 0) {
|
|
@@ -107241,7 +107481,7 @@ var require_loop = __commonJS({
|
|
|
107241
107481
|
}
|
|
107242
107482
|
return outcome;
|
|
107243
107483
|
}
|
|
107244
|
-
async function
|
|
107484
|
+
async function runPermissionRequestHooks3(workDir, tool, input, sessionId = "") {
|
|
107245
107485
|
try {
|
|
107246
107486
|
const items = loadHooks(workDir).PermissionRequest;
|
|
107247
107487
|
if (!items?.length)
|
|
@@ -108089,7 +108329,7 @@ ${stats}${isoNote}`;
|
|
|
108089
108329
|
const subAgentName = agent?.name ?? (typeof input.subagent_type === "string" && input.subagent_type ? input.subagent_type : "general-purpose");
|
|
108090
108330
|
const startItems = loadHooks(options.workDir).SubagentStart;
|
|
108091
108331
|
if (startItems?.length) {
|
|
108092
|
-
const o = await runLifecycleHooks(startItems, "SubagentStart", options.workDir, { session_id: options.sessionId ?? "", agent_type: subAgentName, description: String(input.description ?? "") }, subAgentName).catch(() => ({ block: false }));
|
|
108332
|
+
const o = await runLifecycleHooks(startItems, "SubagentStart", options.workDir, { session_id: options.sessionId ?? "", agent_type: subAgentName, description: String(input.description ?? "") }, subAgentName, hookRunOptsFor(options)).catch(() => ({ block: false }));
|
|
108093
108333
|
if (o.context) {
|
|
108094
108334
|
const last = subMessages[subMessages.length - 1];
|
|
108095
108335
|
if (last && Array.isArray(last.content)) {
|
|
@@ -108649,7 +108889,7 @@ Do NOT call any tools and do NOT continue the task. Reply with text only: a conc
|
|
|
108649
108889
|
if (cut < 2)
|
|
108650
108890
|
return false;
|
|
108651
108891
|
if ((options._depth ?? 0) === 0) {
|
|
108652
|
-
await runLifecycleHooks(loadHooks(options.workDir).PreCompact, "PreCompact", options.workDir, { trigger: "auto", session_id: options.sessionId ?? "", messages_to_summarize: cut }, "auto").catch(() => void 0);
|
|
108892
|
+
await runLifecycleHooks(loadHooks(options.workDir).PreCompact, "PreCompact", options.workDir, { trigger: "auto", session_id: options.sessionId ?? "", messages_to_summarize: cut }, "auto", hookRunOptsFor(options)).catch(() => void 0);
|
|
108653
108893
|
}
|
|
108654
108894
|
const beforeCompact = messages.length;
|
|
108655
108895
|
const afterCompact = cut > 0 ? messages.length - cut + 1 : messages.length;
|
|
@@ -108662,7 +108902,7 @@ Do NOT call any tools and do NOT continue the task. Reply with text only: a conc
|
|
|
108662
108902
|
options.onCompact?.({ trigger: "auto", before: beforeCompact, after: afterCompact });
|
|
108663
108903
|
} catch {
|
|
108664
108904
|
}
|
|
108665
|
-
await runLifecycleHooks(loadHooks(options.workDir).PostCompact, "PostCompact", options.workDir, { trigger: "auto", session_id: options.sessionId ?? "", messages_summarized: cut }, "auto").catch(() => void 0);
|
|
108905
|
+
await runLifecycleHooks(loadHooks(options.workDir).PostCompact, "PostCompact", options.workDir, { trigger: "auto", session_id: options.sessionId ?? "", messages_summarized: cut }, "auto", hookRunOptsFor(options)).catch(() => void 0);
|
|
108666
108906
|
};
|
|
108667
108907
|
const originalTask = originalTaskText(toSummarize);
|
|
108668
108908
|
const summaryPrompt = `Summarize this coding-session transcript into concise bullet points the assistant needs to continue the work: key decisions, files changed (and how), commands run, unresolved problems, and user preferences. Max 400 words.
|
|
@@ -108910,6 +109150,26 @@ Continue the work from here.` }] });
|
|
|
108910
109150
|
const messages = [...initialMessages];
|
|
108911
109151
|
const model = options.model ?? "turbo";
|
|
108912
109152
|
const hooks = options.disableHooks ? withAgentHooks({}, options._agentHooks) : withAgentHooks(loadHooks(options.workDir), options._agentHooks);
|
|
109153
|
+
const fireStopFailure = async (failure) => {
|
|
109154
|
+
if (depth !== 0)
|
|
109155
|
+
return;
|
|
109156
|
+
const items = hooks.StopFailure;
|
|
109157
|
+
if (!items?.length)
|
|
109158
|
+
return;
|
|
109159
|
+
let last = "";
|
|
109160
|
+
for (let i2 = messages.length - 1; i2 >= 0 && !last; i2--) {
|
|
109161
|
+
const m2 = messages[i2];
|
|
109162
|
+
if (m2?.role === "assistant" && Array.isArray(m2.content)) {
|
|
109163
|
+
last = m2.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n").trim().slice(0, 2e3);
|
|
109164
|
+
}
|
|
109165
|
+
}
|
|
109166
|
+
await runLifecycleHooks(items, "StopFailure", options.workDir, {
|
|
109167
|
+
session_id: options.sessionId ?? "",
|
|
109168
|
+
error: failure.error,
|
|
109169
|
+
...failure.error_details ? { error_details: failure.error_details } : {},
|
|
109170
|
+
last_assistant_message: last
|
|
109171
|
+
}, failure.error, hookRunOptsFor(options)).catch(() => void 0);
|
|
109172
|
+
};
|
|
108913
109173
|
const depth = options._depth ?? 0;
|
|
108914
109174
|
const agentScope = options._agentScope ?? "root";
|
|
108915
109175
|
const isMainAgent = depth === 0;
|
|
@@ -108930,13 +109190,13 @@ ${ctx}
|
|
|
108930
109190
|
const sid = options.sessionId || PROCESS_BUDGET_KEY;
|
|
108931
109191
|
if (isPrompt && !_sessionStarted.has(sid) && (hooks.SessionStart?.length ?? 0) > 0) {
|
|
108932
109192
|
_sessionStarted.add(sid);
|
|
108933
|
-
const o = await runLifecycleHooks(hooks.SessionStart, "SessionStart", options.workDir, { session_id: options.sessionId ?? "", source: messages.length > 1 ? "resume" : "startup" }, messages.length > 1 ? "resume" : "startup");
|
|
109193
|
+
const o = await runLifecycleHooks(hooks.SessionStart, "SessionStart", options.workDir, { session_id: options.sessionId ?? "", source: messages.length > 1 ? "resume" : "startup" }, messages.length > 1 ? "resume" : "startup", hookRunOptsFor(options));
|
|
108934
109194
|
if (o.context)
|
|
108935
109195
|
addContext(o.context);
|
|
108936
109196
|
} else if (isPrompt)
|
|
108937
109197
|
_sessionStarted.add(sid);
|
|
108938
109198
|
if (isPrompt && (hooks.UserPromptSubmit?.length ?? 0) > 0) {
|
|
108939
|
-
const o = await runLifecycleHooks(hooks.UserPromptSubmit, "UserPromptSubmit", options.workDir, { session_id: options.sessionId ?? "", prompt: promptText });
|
|
109199
|
+
const o = await runLifecycleHooks(hooks.UserPromptSubmit, "UserPromptSubmit", options.workDir, { session_id: options.sessionId ?? "", prompt: promptText }, void 0, hookRunOptsFor(options));
|
|
108940
109200
|
if (o.block) {
|
|
108941
109201
|
options.onText(`
|
|
108942
109202
|
\u26D4 Prompt blocked by a UserPromptSubmit hook: ${o.reason ?? "no reason given"}
|
|
@@ -109204,7 +109464,8 @@ ${ctx}
|
|
|
109204
109464
|
stopReason = "team-unavailable";
|
|
109205
109465
|
break;
|
|
109206
109466
|
}
|
|
109207
|
-
await runSimpleHooks(hooks.OnError, options.workDir);
|
|
109467
|
+
await runSimpleHooks(hooks.OnError, options.workDir, void 0, hookRunOptsFor(options));
|
|
109468
|
+
await fireStopFailure(classifyStopFailure(err));
|
|
109208
109469
|
throw new types_1.AgentTurnError(`Stream failed: ${err.message}`, trimToResumableBoundary(messages), completedRounds, err);
|
|
109209
109470
|
}
|
|
109210
109471
|
if (options.abortSignal?.aborted) {
|
|
@@ -109245,7 +109506,7 @@ ${ctx}
|
|
|
109245
109506
|
continue;
|
|
109246
109507
|
}
|
|
109247
109508
|
if (depth === 0)
|
|
109248
|
-
await runSimpleHooks(hooks.PostMessageComplete, options.workDir);
|
|
109509
|
+
await runSimpleHooks(hooks.PostMessageComplete, options.workDir, void 0, hookRunOptsFor(options));
|
|
109249
109510
|
stopReason = assistantMessage.stopReason === "max_tokens" ? "output-limit" : "empty-response";
|
|
109250
109511
|
break;
|
|
109251
109512
|
}
|
|
@@ -109329,13 +109590,14 @@ ${ctx}
|
|
|
109329
109590
|
}
|
|
109330
109591
|
}
|
|
109331
109592
|
if (depth === 0)
|
|
109332
|
-
await runSimpleHooks(hooks.PostMessageComplete, options.workDir);
|
|
109593
|
+
await runSimpleHooks(hooks.PostMessageComplete, options.workDir, void 0, hookRunOptsFor(options));
|
|
109333
109594
|
stopReason = "clean";
|
|
109334
109595
|
break;
|
|
109335
109596
|
}
|
|
109336
109597
|
const prefetchSafe = prefetchOn && (0, toolPrefetch_1.isPrefetchSafeMessage)(toolUseBlocks.map((b) => b.name));
|
|
109337
109598
|
const toolResults = await Promise.all(toolUseBlocks.map(async (block) => {
|
|
109338
|
-
const { id, name
|
|
109599
|
+
const { id, name } = block;
|
|
109600
|
+
let input = block.input;
|
|
109339
109601
|
const toolMeta = { id };
|
|
109340
109602
|
options.onToolUse(name, input, void 0, toolMeta);
|
|
109341
109603
|
let result;
|
|
@@ -109366,7 +109628,31 @@ ${ctx}
|
|
|
109366
109628
|
let permitted;
|
|
109367
109629
|
let deniedReason = null;
|
|
109368
109630
|
try {
|
|
109369
|
-
|
|
109631
|
+
const pd = await options.requestPermission({ tool: name, input, description });
|
|
109632
|
+
if (typeof pd === "boolean") {
|
|
109633
|
+
permitted = pd;
|
|
109634
|
+
} else {
|
|
109635
|
+
permitted = pd.granted;
|
|
109636
|
+
if (permitted && pd.updatedInput && typeof pd.updatedInput === "object") {
|
|
109637
|
+
input = pd.updatedInput;
|
|
109638
|
+
if (options.planMode) {
|
|
109639
|
+
const r2 = (0, planMode_1.checkPlanMode)(name, input);
|
|
109640
|
+
if (r2) {
|
|
109641
|
+
permitted = false;
|
|
109642
|
+
deniedReason = r2.message;
|
|
109643
|
+
}
|
|
109644
|
+
}
|
|
109645
|
+
if (permitted && options.worktree) {
|
|
109646
|
+
const r2 = (0, worktreeEnforcement_1.checkWorktreeIsolation)(name, input, options.worktree, options.workDir);
|
|
109647
|
+
if (r2) {
|
|
109648
|
+
permitted = false;
|
|
109649
|
+
deniedReason = r2.message;
|
|
109650
|
+
}
|
|
109651
|
+
}
|
|
109652
|
+
}
|
|
109653
|
+
if (!permitted && pd.message)
|
|
109654
|
+
deniedReason = deniedReason ?? pd.message;
|
|
109655
|
+
}
|
|
109370
109656
|
} catch (err) {
|
|
109371
109657
|
permitted = false;
|
|
109372
109658
|
if (err instanceof ToolNotAllowedError)
|
|
@@ -109377,12 +109663,12 @@ ${ctx}
|
|
|
109377
109663
|
} else if (name === "task") {
|
|
109378
109664
|
const wantsBackground = input.run_in_background === true || input.run_in_background !== false && !!(0, agentTypes_1.findAgentType)(agentTypes, String(input.subagent_type ?? ""))?.background;
|
|
109379
109665
|
const taskOptions = { ...auditOptions, _taskToolUseId: id };
|
|
109380
|
-
const preTask = await runToolHooks(hooks.PreToolUse, "PreToolUse", name, input, options.workDir);
|
|
109666
|
+
const preTask = await runToolHooks(hooks.PreToolUse, "PreToolUse", name, input, options.workDir, void 0, hookRunOptsFor(options));
|
|
109381
109667
|
if (preTask.block) {
|
|
109382
109668
|
result = { error: `Blocked by PreToolUse hook: ${preTask.reason}` };
|
|
109383
109669
|
} else {
|
|
109384
109670
|
result = wantsBackground && depth === 0 && options.backgroundAgents && !input.resume_agent_id ? dispatchBackgroundSubAgent(input, taskOptions, agentTypes, options.backgroundAgents) : await dispatchSubAgent(input, taskOptions, agentTypes);
|
|
109385
|
-
const postTask = await runToolHooks(hooks.PostToolUse, "PostToolUse", name, input, options.workDir, result);
|
|
109671
|
+
const postTask = await runToolHooks(hooks.PostToolUse, "PostToolUse", name, input, options.workDir, result, hookRunOptsFor(options));
|
|
109386
109672
|
const injectedTask = [preTask.context, postTask.context].filter(Boolean).join("\n");
|
|
109387
109673
|
if (injectedTask) {
|
|
109388
109674
|
if (result.error !== void 0)
|
|
@@ -109399,7 +109685,7 @@ ${ctx}
|
|
|
109399
109685
|
}
|
|
109400
109686
|
}
|
|
109401
109687
|
} else {
|
|
109402
|
-
const pre = await runToolHooks(hooks.PreToolUse, "PreToolUse", name, input, options.workDir);
|
|
109688
|
+
const pre = await runToolHooks(hooks.PreToolUse, "PreToolUse", name, input, options.workDir, void 0, hookRunOptsFor(options));
|
|
109403
109689
|
if (pre.block) {
|
|
109404
109690
|
result = { error: `Blocked by PreToolUse hook: ${pre.reason}` };
|
|
109405
109691
|
} else {
|
|
@@ -109445,9 +109731,9 @@ ${ctx}
|
|
|
109445
109731
|
const scope = input.scope === "global" ? "global" : "project";
|
|
109446
109732
|
void maybeCompactMemory(scope, options);
|
|
109447
109733
|
}
|
|
109448
|
-
const post = await runToolHooks(hooks.PostToolUse, "PostToolUse", name, input, options.workDir, result);
|
|
109734
|
+
const post = await runToolHooks(hooks.PostToolUse, "PostToolUse", name, input, options.workDir, result, hookRunOptsFor(options));
|
|
109449
109735
|
if (result.error !== void 0 && (hooks.PostToolUseFailure?.length ?? 0) > 0) {
|
|
109450
|
-
const f3 = await runLifecycleHooks(hooks.PostToolUseFailure, "PostToolUseFailure", options.workDir, { session_id: options.sessionId ?? "", tool_name: name, tool_input: input, error: String(result.error).slice(0, 4e3) }, name).catch(() => ({ block: false }));
|
|
109736
|
+
const f3 = await runLifecycleHooks(hooks.PostToolUseFailure, "PostToolUseFailure", options.workDir, { session_id: options.sessionId ?? "", tool_name: name, tool_input: input, error: String(result.error).slice(0, 4e3) }, name, hookRunOptsFor(options)).catch(() => ({ block: false }));
|
|
109451
109737
|
if (f3.context)
|
|
109452
109738
|
post.context = [post.context, f3.context].filter(Boolean).join("\n");
|
|
109453
109739
|
if (f3.block) {
|
|
@@ -109569,6 +109855,9 @@ ${result.output}` : `Error: ${result.error}` : result.output ?? "",
|
|
|
109569
109855
|
stopReason = "budget";
|
|
109570
109856
|
if (options.abortSignal?.aborted)
|
|
109571
109857
|
stopReason = "aborted";
|
|
109858
|
+
const apiFailure = apiFailureForStopReason(stopReason);
|
|
109859
|
+
if (apiFailure)
|
|
109860
|
+
await fireStopFailure(apiFailure);
|
|
109572
109861
|
const notice = stopReasonNotice(stopReason, { budget, repeatError: stalledRepeatError });
|
|
109573
109862
|
if (options._onStopReason)
|
|
109574
109863
|
options._onStopReason(stopReason, notice || null);
|
|
@@ -109583,12 +109872,12 @@ ${result.output}` : `Error: ${result.error}` : result.output ?? "",
|
|
|
109583
109872
|
throw new types_1.AgentTurnError(err?.message || "The turn ended unexpectedly", trimToResumableBoundary(messages), completedRounds, err);
|
|
109584
109873
|
} finally {
|
|
109585
109874
|
if (depth === 0 && (hooks.SessionEnd?.length ?? 0) > 0) {
|
|
109586
|
-
await runLifecycleHooks(hooks.SessionEnd, "SessionEnd", options.workDir, { session_id: options.sessionId ?? "", reason: stopReason }, stopReason).catch(() => void 0);
|
|
109875
|
+
await runLifecycleHooks(hooks.SessionEnd, "SessionEnd", options.workDir, { session_id: options.sessionId ?? "", reason: stopReason }, stopReason, hookRunOptsFor(options)).catch(() => void 0);
|
|
109587
109876
|
}
|
|
109588
109877
|
if (depth === 0)
|
|
109589
|
-
await runSimpleHooks(hooks.OnStop, options.workDir);
|
|
109878
|
+
await runSimpleHooks(hooks.OnStop, options.workDir, void 0, hookRunOptsFor(options));
|
|
109590
109879
|
else
|
|
109591
|
-
await runSimpleHooks(hooks.SubagentStop, options.workDir, { NEXRALL_AGENT_NAME: options._agentTypeName ?? "general-purpose" });
|
|
109880
|
+
await runSimpleHooks(hooks.SubagentStop, options.workDir, { NEXRALL_AGENT_NAME: options._agentTypeName ?? "general-purpose" }, hookRunOptsFor(options));
|
|
109592
109881
|
}
|
|
109593
109882
|
return messages;
|
|
109594
109883
|
}
|
|
@@ -109610,6 +109899,251 @@ ${result.output}` : `Error: ${result.error}` : result.output ?? "",
|
|
|
109610
109899
|
}
|
|
109611
109900
|
});
|
|
109612
109901
|
|
|
109902
|
+
// ../core/dist/agent/lifecycleHost.js
|
|
109903
|
+
var require_lifecycleHost = __commonJS({
|
|
109904
|
+
"../core/dist/agent/lifecycleHost.js"(exports2) {
|
|
109905
|
+
"use strict";
|
|
109906
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m2, k, k2) {
|
|
109907
|
+
if (k2 === void 0)
|
|
109908
|
+
k2 = k;
|
|
109909
|
+
var desc = Object.getOwnPropertyDescriptor(m2, k);
|
|
109910
|
+
if (!desc || ("get" in desc ? !m2.__esModule : desc.writable || desc.configurable)) {
|
|
109911
|
+
desc = { enumerable: true, get: function() {
|
|
109912
|
+
return m2[k];
|
|
109913
|
+
} };
|
|
109914
|
+
}
|
|
109915
|
+
Object.defineProperty(o, k2, desc);
|
|
109916
|
+
} : function(o, m2, k, k2) {
|
|
109917
|
+
if (k2 === void 0)
|
|
109918
|
+
k2 = k;
|
|
109919
|
+
o[k2] = m2[k];
|
|
109920
|
+
});
|
|
109921
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
109922
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
109923
|
+
} : function(o, v) {
|
|
109924
|
+
o["default"] = v;
|
|
109925
|
+
});
|
|
109926
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
109927
|
+
var ownKeys = function(o) {
|
|
109928
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
109929
|
+
var ar = [];
|
|
109930
|
+
for (var k in o2)
|
|
109931
|
+
if (Object.prototype.hasOwnProperty.call(o2, k))
|
|
109932
|
+
ar[ar.length] = k;
|
|
109933
|
+
return ar;
|
|
109934
|
+
};
|
|
109935
|
+
return ownKeys(o);
|
|
109936
|
+
};
|
|
109937
|
+
return function(mod) {
|
|
109938
|
+
if (mod && mod.__esModule)
|
|
109939
|
+
return mod;
|
|
109940
|
+
var result = {};
|
|
109941
|
+
if (mod != null) {
|
|
109942
|
+
for (var k = ownKeys(mod), i2 = 0; i2 < k.length; i2++)
|
|
109943
|
+
if (k[i2] !== "default")
|
|
109944
|
+
__createBinding(result, mod, k[i2]);
|
|
109945
|
+
}
|
|
109946
|
+
__setModuleDefault(result, mod);
|
|
109947
|
+
return result;
|
|
109948
|
+
};
|
|
109949
|
+
}();
|
|
109950
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
109951
|
+
exports2.fireInstructionsLoadedHooks = fireInstructionsLoadedHooks2;
|
|
109952
|
+
exports2.startFileChangedWatcher = startFileChangedWatcher2;
|
|
109953
|
+
exports2.filesChangedSinceSnapshot = filesChangedSinceSnapshot;
|
|
109954
|
+
var fs28 = __importStar(__require("fs"));
|
|
109955
|
+
var path28 = __importStar(__require("path"));
|
|
109956
|
+
var loop_1 = require_loop();
|
|
109957
|
+
async function fireInstructionsLoadedHooks2(workDir, sessionId, files) {
|
|
109958
|
+
if (!files.length)
|
|
109959
|
+
return;
|
|
109960
|
+
try {
|
|
109961
|
+
const items = (0, loop_1.loadHooks)(workDir).InstructionsLoaded;
|
|
109962
|
+
if (!items?.length)
|
|
109963
|
+
return;
|
|
109964
|
+
for (const f3 of files) {
|
|
109965
|
+
await (0, loop_1.runLifecycleHooks)(items, "InstructionsLoaded", workDir, {
|
|
109966
|
+
session_id: sessionId,
|
|
109967
|
+
file_path: f3.file_path,
|
|
109968
|
+
memory_type: f3.memory_type,
|
|
109969
|
+
load_reason: f3.load_reason,
|
|
109970
|
+
...f3.globs ? { globs: f3.globs } : {}
|
|
109971
|
+
}, f3.load_reason).catch(() => void 0);
|
|
109972
|
+
}
|
|
109973
|
+
} catch {
|
|
109974
|
+
}
|
|
109975
|
+
}
|
|
109976
|
+
function isWatchableName(name) {
|
|
109977
|
+
return !!name && !name.includes("/") && !name.includes("\\") && !name.includes("*") && !name.includes("?") && name !== "." && name !== "..";
|
|
109978
|
+
}
|
|
109979
|
+
function startFileChangedWatcher2(workDir, sessionId, opts) {
|
|
109980
|
+
let items;
|
|
109981
|
+
try {
|
|
109982
|
+
items = (0, loop_1.loadHooks)(workDir).FileChanged;
|
|
109983
|
+
} catch {
|
|
109984
|
+
items = void 0;
|
|
109985
|
+
}
|
|
109986
|
+
if (!items?.length)
|
|
109987
|
+
return null;
|
|
109988
|
+
const staticNames = /* @__PURE__ */ new Set();
|
|
109989
|
+
for (const it of items) {
|
|
109990
|
+
if (it && Array.isArray(it.hooks)) {
|
|
109991
|
+
const m2 = it.matcher;
|
|
109992
|
+
if (!m2 || m2 === "*")
|
|
109993
|
+
continue;
|
|
109994
|
+
for (const raw of m2.split("|")) {
|
|
109995
|
+
const name = raw.trim();
|
|
109996
|
+
if (isWatchableName(name))
|
|
109997
|
+
staticNames.add(name);
|
|
109998
|
+
}
|
|
109999
|
+
}
|
|
110000
|
+
}
|
|
110001
|
+
if (!staticNames.size)
|
|
110002
|
+
return null;
|
|
110003
|
+
const dynamicNames = /* @__PURE__ */ new Set();
|
|
110004
|
+
const watched = () => /* @__PURE__ */ new Set([...staticNames, ...dynamicNames]);
|
|
110005
|
+
const known = /* @__PURE__ */ new Set();
|
|
110006
|
+
const seedKnown = (names) => {
|
|
110007
|
+
for (const n of names) {
|
|
110008
|
+
try {
|
|
110009
|
+
if (fs28.existsSync(path28.join(workDir, n)))
|
|
110010
|
+
known.add(n);
|
|
110011
|
+
} catch {
|
|
110012
|
+
}
|
|
110013
|
+
}
|
|
110014
|
+
};
|
|
110015
|
+
seedKnown(staticNames);
|
|
110016
|
+
const stamp = (name) => {
|
|
110017
|
+
try {
|
|
110018
|
+
const st = fs28.statSync(path28.join(workDir, name));
|
|
110019
|
+
return `${st.mtimeMs}:${st.size}`;
|
|
110020
|
+
} catch {
|
|
110021
|
+
return "";
|
|
110022
|
+
}
|
|
110023
|
+
};
|
|
110024
|
+
const seen = /* @__PURE__ */ new Map();
|
|
110025
|
+
const snapshot = (names) => {
|
|
110026
|
+
for (const n of names)
|
|
110027
|
+
seen.set(n, stamp(n));
|
|
110028
|
+
};
|
|
110029
|
+
snapshot(staticNames);
|
|
110030
|
+
const pending = /* @__PURE__ */ new Map();
|
|
110031
|
+
let closed = false;
|
|
110032
|
+
const scheduleFire = (name) => {
|
|
110033
|
+
const prev = pending.get(name);
|
|
110034
|
+
if (prev)
|
|
110035
|
+
clearTimeout(prev);
|
|
110036
|
+
pending.set(name, setTimeout(() => {
|
|
110037
|
+
pending.delete(name);
|
|
110038
|
+
let exists = true;
|
|
110039
|
+
try {
|
|
110040
|
+
exists = fs28.existsSync(path28.join(workDir, name));
|
|
110041
|
+
} catch {
|
|
110042
|
+
exists = false;
|
|
110043
|
+
}
|
|
110044
|
+
const event = !exists ? "unlink" : known.has(name) ? "change" : "add";
|
|
110045
|
+
if (exists)
|
|
110046
|
+
known.add(name);
|
|
110047
|
+
else
|
|
110048
|
+
known.delete(name);
|
|
110049
|
+
seen.set(name, stamp(name));
|
|
110050
|
+
void fireChanged(workDir, sessionId, name, event, items, dynamicNames.has(name)).then((o) => {
|
|
110051
|
+
if (!o)
|
|
110052
|
+
return;
|
|
110053
|
+
if (o.systemMessage && opts?.onSystemMessage) {
|
|
110054
|
+
try {
|
|
110055
|
+
opts.onSystemMessage(o.systemMessage);
|
|
110056
|
+
} catch {
|
|
110057
|
+
}
|
|
110058
|
+
}
|
|
110059
|
+
if (o.watchPaths) {
|
|
110060
|
+
dynamicNames.clear();
|
|
110061
|
+
for (const p of o.watchPaths) {
|
|
110062
|
+
const n = isWatchableName(path28.basename(p)) ? path28.basename(p) : "";
|
|
110063
|
+
if (n)
|
|
110064
|
+
dynamicNames.add(n);
|
|
110065
|
+
}
|
|
110066
|
+
seedKnown(dynamicNames);
|
|
110067
|
+
snapshot(dynamicNames);
|
|
110068
|
+
}
|
|
110069
|
+
}).catch(() => {
|
|
110070
|
+
});
|
|
110071
|
+
}, 250));
|
|
110072
|
+
};
|
|
110073
|
+
let watcher = null;
|
|
110074
|
+
try {
|
|
110075
|
+
watcher = fs28.watch(workDir, { persistent: false }, (_eventType, filename) => {
|
|
110076
|
+
if (closed)
|
|
110077
|
+
return;
|
|
110078
|
+
const name = filename ? path28.basename(String(filename)) : "";
|
|
110079
|
+
if (!name || !watched().has(name))
|
|
110080
|
+
return;
|
|
110081
|
+
scheduleFire(name);
|
|
110082
|
+
});
|
|
110083
|
+
watcher.on("error", () => {
|
|
110084
|
+
});
|
|
110085
|
+
} catch {
|
|
110086
|
+
return null;
|
|
110087
|
+
}
|
|
110088
|
+
const armGraceMs = opts?.armGraceMs ?? 400;
|
|
110089
|
+
const reconcileTimer = armGraceMs > 0 ? setTimeout(() => {
|
|
110090
|
+
if (closed)
|
|
110091
|
+
return;
|
|
110092
|
+
for (const n of filesChangedSinceSnapshot(watched(), seen, stamp))
|
|
110093
|
+
scheduleFire(n);
|
|
110094
|
+
}, armGraceMs) : null;
|
|
110095
|
+
return {
|
|
110096
|
+
stop() {
|
|
110097
|
+
closed = true;
|
|
110098
|
+
if (reconcileTimer)
|
|
110099
|
+
clearTimeout(reconcileTimer);
|
|
110100
|
+
for (const t2 of pending.values())
|
|
110101
|
+
clearTimeout(t2);
|
|
110102
|
+
pending.clear();
|
|
110103
|
+
try {
|
|
110104
|
+
watcher?.close();
|
|
110105
|
+
} catch {
|
|
110106
|
+
}
|
|
110107
|
+
watcher = null;
|
|
110108
|
+
},
|
|
110109
|
+
updateWatchPaths(paths) {
|
|
110110
|
+
dynamicNames.clear();
|
|
110111
|
+
for (const p of paths) {
|
|
110112
|
+
const n = isWatchableName(path28.basename(p)) ? path28.basename(p) : "";
|
|
110113
|
+
if (n)
|
|
110114
|
+
dynamicNames.add(n);
|
|
110115
|
+
}
|
|
110116
|
+
seedKnown(dynamicNames);
|
|
110117
|
+
snapshot(dynamicNames);
|
|
110118
|
+
},
|
|
110119
|
+
watchedFiles() {
|
|
110120
|
+
return [...watched()].sort();
|
|
110121
|
+
}
|
|
110122
|
+
};
|
|
110123
|
+
}
|
|
110124
|
+
function filesChangedSinceSnapshot(names, seen, stamp) {
|
|
110125
|
+
const out = [];
|
|
110126
|
+
for (const n of names)
|
|
110127
|
+
if (stamp(n) !== (seen.get(n) ?? ""))
|
|
110128
|
+
out.push(n);
|
|
110129
|
+
return out;
|
|
110130
|
+
}
|
|
110131
|
+
async function fireChanged(workDir, sessionId, name, event, items, isDynamic) {
|
|
110132
|
+
const abs = path28.join(workDir, name);
|
|
110133
|
+
try {
|
|
110134
|
+
const o = await (0, loop_1.runLifecycleHooks)(items, "FileChanged", workDir, {
|
|
110135
|
+
session_id: sessionId,
|
|
110136
|
+
file_path: abs,
|
|
110137
|
+
event
|
|
110138
|
+
}, isDynamic ? void 0 : name);
|
|
110139
|
+
return { watchPaths: o.watchPaths, systemMessage: o.systemMessage };
|
|
110140
|
+
} catch {
|
|
110141
|
+
return null;
|
|
110142
|
+
}
|
|
110143
|
+
}
|
|
110144
|
+
}
|
|
110145
|
+
});
|
|
110146
|
+
|
|
109613
110147
|
// ../core/dist/mcp/client.js
|
|
109614
110148
|
var require_client2 = __commonJS({
|
|
109615
110149
|
"../core/dist/mcp/client.js"(exports2) {
|
|
@@ -111826,6 +112360,7 @@ var require_dist3 = __commonJS({
|
|
|
111826
112360
|
__exportStar(require_client(), exports2);
|
|
111827
112361
|
__exportStar(require_executor(), exports2);
|
|
111828
112362
|
__exportStar(require_loop(), exports2);
|
|
112363
|
+
__exportStar(require_lifecycleHost(), exports2);
|
|
111829
112364
|
__exportStar(require_modelCatalogue(), exports2);
|
|
111830
112365
|
__exportStar(require_testIntegrity(), exports2);
|
|
111831
112366
|
__exportStar(require_editCompleteness(), exports2);
|
|
@@ -145693,7 +146228,7 @@ var {
|
|
|
145693
146228
|
} = import_index.default;
|
|
145694
146229
|
|
|
145695
146230
|
// src/index.ts
|
|
145696
|
-
var
|
|
146231
|
+
var import_code_core21 = __toESM(require_dist3(), 1);
|
|
145697
146232
|
import * as path27 from "path";
|
|
145698
146233
|
import * as fs27 from "fs";
|
|
145699
146234
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -151602,7 +152137,7 @@ function confirmMatches(env4, typed) {
|
|
|
151602
152137
|
}
|
|
151603
152138
|
|
|
151604
152139
|
// src/commands/chat.ts
|
|
151605
|
-
var
|
|
152140
|
+
var import_code_core17 = __toESM(require_dist3(), 1);
|
|
151606
152141
|
import * as os15 from "os";
|
|
151607
152142
|
import * as crypto7 from "crypto";
|
|
151608
152143
|
import { createRequire } from "module";
|
|
@@ -152512,8 +153047,82 @@ async function askFlow(req) {
|
|
|
152512
153047
|
return await choose({ title: `Allow ${tool}?`, risk: riskOf(tool, input), alwaysLabel: null }) !== "n";
|
|
152513
153048
|
}
|
|
152514
153049
|
|
|
152515
|
-
// src/
|
|
153050
|
+
// src/permissions/promptTool.ts
|
|
153051
|
+
function parsePromptToolAnswer(raw) {
|
|
153052
|
+
if (raw === null)
|
|
153053
|
+
return { error: "the permission tool is not connected (check `nex mcp list`)" };
|
|
153054
|
+
const text = String(raw).trim();
|
|
153055
|
+
let j;
|
|
153056
|
+
try {
|
|
153057
|
+
j = JSON.parse(text);
|
|
153058
|
+
} catch {
|
|
153059
|
+
return { error: `the permission tool returned non-JSON: ${text.slice(0, 200) || "(empty)"}` };
|
|
153060
|
+
}
|
|
153061
|
+
if (!j || typeof j !== "object" || Array.isArray(j)) {
|
|
153062
|
+
return { error: `the permission tool returned JSON that is not an object: ${text.slice(0, 200)}` };
|
|
153063
|
+
}
|
|
153064
|
+
const o = j;
|
|
153065
|
+
const behavior = o.behavior === "allow" || o.behavior === "deny" ? o.behavior : o.decision === "allow" || o.decision === "deny" ? o.decision : null;
|
|
153066
|
+
if (!behavior) {
|
|
153067
|
+
return { error: `the permission tool did not return a behavior/decision of "allow" or "deny": ${text.slice(0, 200)}` };
|
|
153068
|
+
}
|
|
153069
|
+
const message = typeof o.message === "string" && o.message ? o.message : typeof o.reason === "string" && o.reason ? o.reason : void 0;
|
|
153070
|
+
if (behavior === "allow" && o.updatedInput !== void 0) {
|
|
153071
|
+
if (!o.updatedInput || typeof o.updatedInput !== "object" || Array.isArray(o.updatedInput)) {
|
|
153072
|
+
return { error: `the permission tool returned an updatedInput that is not an object: ${text.slice(0, 200)}` };
|
|
153073
|
+
}
|
|
153074
|
+
return { behavior, updatedInput: o.updatedInput, message };
|
|
153075
|
+
}
|
|
153076
|
+
return { behavior, message };
|
|
153077
|
+
}
|
|
153078
|
+
async function askPermissionPromptTool(host, toolName, req, abortSignal) {
|
|
153079
|
+
if (!host)
|
|
153080
|
+
return { error: `--permission-prompt-tool "${toolName}" needs MCP, but no MCP servers are configured for this run` };
|
|
153081
|
+
if (!host.isMcpTool(toolName)) {
|
|
153082
|
+
return { error: `--permission-prompt-tool "${toolName}" is not a tool of any connected MCP server (check \`nex mcp list\`)` };
|
|
153083
|
+
}
|
|
153084
|
+
let raw;
|
|
153085
|
+
try {
|
|
153086
|
+
raw = await host.callTool(toolName, {
|
|
153087
|
+
tool_name: req.tool,
|
|
153088
|
+
input: req.input,
|
|
153089
|
+
...req.description ? { description: req.description } : {},
|
|
153090
|
+
cwd: req.cwd,
|
|
153091
|
+
permission_mode: req.mode,
|
|
153092
|
+
...req.sessionId ? { session_id: req.sessionId } : {}
|
|
153093
|
+
}, abortSignal);
|
|
153094
|
+
} catch (err) {
|
|
153095
|
+
return { error: `the permission tool failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
153096
|
+
}
|
|
153097
|
+
return parsePromptToolAnswer(raw);
|
|
153098
|
+
}
|
|
153099
|
+
|
|
153100
|
+
// src/permissions/headlessHook.ts
|
|
152516
153101
|
var import_code_core7 = __toESM(require_dist3(), 1);
|
|
153102
|
+
async function runHeadlessPermissionHooks(ctx, emit, emitEvent2) {
|
|
153103
|
+
const locked = ctx.policyDeny || ctx.reason === "rule";
|
|
153104
|
+
const destructive = ctx.reason === "destructive" && !!ctx.destructive;
|
|
153105
|
+
if (locked || destructive)
|
|
153106
|
+
return { handled: null };
|
|
153107
|
+
const hook = await (0, import_code_core7.runPermissionRequestHooks)(ctx.workDir, ctx.tool, ctx.input, ctx.sessionId);
|
|
153108
|
+
if (hook.answer === "allow") {
|
|
153109
|
+
emit({ type: "permission_granted", tool: ctx.tool, reason: "hook" });
|
|
153110
|
+
emitEvent2("permission.granted", { tool: ctx.tool, reason: "hook" });
|
|
153111
|
+
return { handled: "allow" };
|
|
153112
|
+
}
|
|
153113
|
+
if (hook.answer === "deny") {
|
|
153114
|
+
emit({ type: "permission_denied", tool: ctx.tool, reason: "hook" });
|
|
153115
|
+
emitEvent2("permission.denied", { tool: ctx.tool, reason: "hook" });
|
|
153116
|
+
return {
|
|
153117
|
+
handled: "deny",
|
|
153118
|
+
message: hook.reason ? `Permission denied by hook: ${hook.reason}` : "Permission denied by hook"
|
|
153119
|
+
};
|
|
153120
|
+
}
|
|
153121
|
+
return { handled: null };
|
|
153122
|
+
}
|
|
153123
|
+
|
|
153124
|
+
// src/audit.ts
|
|
153125
|
+
var import_code_core8 = __toESM(require_dist3(), 1);
|
|
152517
153126
|
import * as path7 from "path";
|
|
152518
153127
|
var _state;
|
|
152519
153128
|
var _sinks = /* @__PURE__ */ new Map();
|
|
@@ -152533,7 +153142,7 @@ function currentAudit() {
|
|
|
152533
153142
|
const target = resolveAuditPath(_state);
|
|
152534
153143
|
let sink = _sinks.get(target);
|
|
152535
153144
|
if (!sink) {
|
|
152536
|
-
sink = (0,
|
|
153145
|
+
sink = (0, import_code_core8.createJsonlAuditSink)(target);
|
|
152537
153146
|
_sinks.set(target, sink);
|
|
152538
153147
|
}
|
|
152539
153148
|
const cfg = {
|
|
@@ -152546,14 +153155,14 @@ function currentAudit() {
|
|
|
152546
153155
|
// request that caused it. Same trap as @nexrall/agent's and Desktop's.
|
|
152547
153156
|
sessionId: _state.getSessionId()
|
|
152548
153157
|
};
|
|
152549
|
-
const email = (0,
|
|
153158
|
+
const email = (0, import_code_core8.loadAuth)()?.email;
|
|
152550
153159
|
if (email)
|
|
152551
153160
|
cfg.userId = email;
|
|
152552
153161
|
return cfg;
|
|
152553
153162
|
}
|
|
152554
153163
|
|
|
152555
153164
|
// src/commands/chat.ts
|
|
152556
|
-
var
|
|
153165
|
+
var import_code_core18 = __toESM(require_dist3(), 1);
|
|
152557
153166
|
|
|
152558
153167
|
// src/headlessFlags.ts
|
|
152559
153168
|
import * as fs7 from "fs";
|
|
@@ -152699,6 +153308,8 @@ function checkHeadlessOnly(f3) {
|
|
|
152699
153308
|
return "--no-session-persistence only works with --output-format (a one-shot, non-interactive run).";
|
|
152700
153309
|
if (f3.maxTurns !== void 0)
|
|
152701
153310
|
return "--max-turns only works with --output-format (a one-shot, non-interactive run).";
|
|
153311
|
+
if (f3.permissionPromptTool !== void 0)
|
|
153312
|
+
return "--permission-prompt-tool only works with --output-format (a one-shot, non-interactive run).";
|
|
152702
153313
|
return null;
|
|
152703
153314
|
}
|
|
152704
153315
|
function headlessVerdict(i2) {
|
|
@@ -152887,6 +153498,15 @@ function readPromptFile(file, cwd2, flag = "--append-system-prompt-file") {
|
|
|
152887
153498
|
return { ok: false, error: `${flag}: "${file}" is empty` };
|
|
152888
153499
|
return { ok: true, value: text.trim() };
|
|
152889
153500
|
}
|
|
153501
|
+
function normalizePermissionPromptTool(raw) {
|
|
153502
|
+
let name = String(raw).trim();
|
|
153503
|
+
if (name.startsWith("mcp__"))
|
|
153504
|
+
name = name.slice("mcp__".length);
|
|
153505
|
+
if (!name || !name.includes("__")) {
|
|
153506
|
+
return { ok: false, error: `--permission-prompt-tool: "${raw}" is not an MCP tool name. Use mcp__server__tool (the name shown in /mcp or \`nex mcp list\`)` };
|
|
153507
|
+
}
|
|
153508
|
+
return { ok: true, value: name };
|
|
153509
|
+
}
|
|
152890
153510
|
var CLAUDE_TOOL_ALIASES = {
|
|
152891
153511
|
Read: ["read_file", "list_directory", "search_files", "glob", "notebook_read"],
|
|
152892
153512
|
Edit: ["edit_file", "multi_edit", "notebook_edit"],
|
|
@@ -153093,7 +153713,7 @@ function parseAgentsArg(raw, cwd2) {
|
|
|
153093
153713
|
}
|
|
153094
153714
|
|
|
153095
153715
|
// src/commands/chat.ts
|
|
153096
|
-
var
|
|
153716
|
+
var import_code_core19 = __toESM(require_dist3(), 1);
|
|
153097
153717
|
|
|
153098
153718
|
// src/debugLog.ts
|
|
153099
153719
|
import fs8 from "fs";
|
|
@@ -153140,14 +153760,14 @@ function debugLog(event, fields) {
|
|
|
153140
153760
|
}
|
|
153141
153761
|
|
|
153142
153762
|
// src/commands/doctor.ts
|
|
153143
|
-
var
|
|
153763
|
+
var import_code_core10 = __toESM(require_dist3(), 1);
|
|
153144
153764
|
import fs10 from "fs";
|
|
153145
153765
|
import os4 from "os";
|
|
153146
153766
|
import path11 from "path";
|
|
153147
153767
|
import { spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
|
|
153148
153768
|
|
|
153149
153769
|
// src/commands/sessionTools.ts
|
|
153150
|
-
var
|
|
153770
|
+
var import_code_core9 = __toESM(require_dist3(), 1);
|
|
153151
153771
|
import { spawnSync, execFileSync } from "child_process";
|
|
153152
153772
|
import fs9 from "fs";
|
|
153153
153773
|
import path10 from "path";
|
|
@@ -153196,7 +153816,7 @@ function nextMode(current) {
|
|
|
153196
153816
|
return MODE_CYCLE[(i2 + 1) % MODE_CYCLE.length];
|
|
153197
153817
|
}
|
|
153198
153818
|
function textOf(m2) {
|
|
153199
|
-
return m2.content.filter((b) => b.type === "text" && !(0,
|
|
153819
|
+
return m2.content.filter((b) => b.type === "text" && !(0, import_code_core9.isRuntimeContextBlock)(b)).map((b) => b.text).join("\n").trim();
|
|
153200
153820
|
}
|
|
153201
153821
|
function lastAssistantText(messages) {
|
|
153202
153822
|
for (let i2 = messages.length - 1; i2 >= 0; i2--) {
|
|
@@ -153222,7 +153842,7 @@ function exportMarkdown(messages, meta) {
|
|
|
153222
153842
|
for (const m2 of messages) {
|
|
153223
153843
|
const parts = [];
|
|
153224
153844
|
for (const b of m2.content) {
|
|
153225
|
-
if ((0,
|
|
153845
|
+
if ((0, import_code_core9.isRuntimeContextBlock)(b))
|
|
153226
153846
|
continue;
|
|
153227
153847
|
if (b.type === "text") {
|
|
153228
153848
|
if (b.text.trim())
|
|
@@ -153580,17 +154200,17 @@ function realProbes(c) {
|
|
|
153580
154200
|
return { inRepo: false };
|
|
153581
154201
|
}
|
|
153582
154202
|
},
|
|
153583
|
-
hasToken: () => !!(0,
|
|
154203
|
+
hasToken: () => !!(0, import_code_core10.getToken)(),
|
|
153584
154204
|
verifyAuth: async () => {
|
|
153585
154205
|
try {
|
|
153586
|
-
await (0,
|
|
154206
|
+
await (0, import_code_core10.getBalance)();
|
|
153587
154207
|
return { ok: true, detail: "signed in, token accepted" };
|
|
153588
154208
|
} catch (e2) {
|
|
153589
154209
|
return { ok: false, detail: `token rejected \u2014 ${e2.message.slice(0, 120)}` };
|
|
153590
154210
|
}
|
|
153591
154211
|
},
|
|
153592
|
-
reach: () => reachHost(
|
|
153593
|
-
apiBase:
|
|
154212
|
+
reach: () => reachHost(import_code_core10.API_BASE),
|
|
154213
|
+
apiBase: import_code_core10.API_BASE,
|
|
153594
154214
|
isTTY: !!process.stdout.isTTY,
|
|
153595
154215
|
columns: process.stdout.columns,
|
|
153596
154216
|
rows: process.stdout.rows,
|
|
@@ -153598,7 +154218,7 @@ function realProbes(c) {
|
|
|
153598
154218
|
mcp: () => {
|
|
153599
154219
|
let configured = 0;
|
|
153600
154220
|
try {
|
|
153601
|
-
configured = Object.keys(
|
|
154221
|
+
configured = Object.keys(import_code_core10.McpManager.loadConfig(c.workDir).mcpServers).length;
|
|
153602
154222
|
} catch {
|
|
153603
154223
|
}
|
|
153604
154224
|
return { configured, rows: c.mcpRows ?? [] };
|
|
@@ -163456,7 +164076,7 @@ var useBoxMetrics = (ref) => {
|
|
|
163456
164076
|
var use_box_metrics_default = useBoxMetrics;
|
|
163457
164077
|
|
|
163458
164078
|
// src/ui/themeSettings.ts
|
|
163459
|
-
var
|
|
164079
|
+
var import_code_core11 = __toESM(require_dist3(), 1);
|
|
163460
164080
|
import * as fs17 from "fs";
|
|
163461
164081
|
import * as os9 from "os";
|
|
163462
164082
|
import * as path17 from "path";
|
|
@@ -163490,13 +164110,13 @@ function applyThemeConfig(cfg, opts = {}) {
|
|
|
163490
164110
|
return { resolved, notes };
|
|
163491
164111
|
}
|
|
163492
164112
|
function applyTrustedTheme(env4 = process.env) {
|
|
163493
|
-
const settings = (0,
|
|
164113
|
+
const settings = (0, import_code_core11.loadSettings)(os9.homedir());
|
|
163494
164114
|
const cfg = readThemeConfig(settings.raw);
|
|
163495
164115
|
const { resolved, notes } = applyThemeConfig(cfg, { env: env4 });
|
|
163496
164116
|
return { ...cfg, resolved, notes };
|
|
163497
164117
|
}
|
|
163498
164118
|
function loadAndApplyTheme(workDir, env4 = process.env) {
|
|
163499
|
-
const settings = (0,
|
|
164119
|
+
const settings = (0, import_code_core11.loadSettings)(workDir);
|
|
163500
164120
|
const cfg = readThemeConfig(settings.raw);
|
|
163501
164121
|
const { resolved, notes } = applyThemeConfig(cfg, { env: env4 });
|
|
163502
164122
|
return { ...cfg, resolved, notes };
|
|
@@ -167212,7 +167832,7 @@ function orderByRecents(entries, recents) {
|
|
|
167212
167832
|
}
|
|
167213
167833
|
|
|
167214
167834
|
// src/ui/memoryNote.ts
|
|
167215
|
-
var
|
|
167835
|
+
var import_code_core12 = __toESM(require_dist3(), 1);
|
|
167216
167836
|
function stripEscape(line) {
|
|
167217
167837
|
return line.startsWith("\\#") ? line.slice(1) : line;
|
|
167218
167838
|
}
|
|
@@ -167229,7 +167849,7 @@ function parseMemoryNote(line) {
|
|
|
167229
167849
|
return text ? { scope: "project", text } : null;
|
|
167230
167850
|
}
|
|
167231
167851
|
async function saveNote(note, workDir) {
|
|
167232
|
-
const r2 = await (0,
|
|
167852
|
+
const r2 = await (0, import_code_core12.writeMemory)(note.text, note.scope, workDir, { source: "cli" });
|
|
167233
167853
|
return { ok: r2.ok, already: r2.already, superseded: r2.superseded === true, scope: r2.scope, file: r2.file, text: note.text };
|
|
167234
167854
|
}
|
|
167235
167855
|
function parseMemoryAdd(arg) {
|
|
@@ -167251,7 +167871,7 @@ function interpretPrompt(line) {
|
|
|
167251
167871
|
}
|
|
167252
167872
|
|
|
167253
167873
|
// src/ui/mcpPanel.ts
|
|
167254
|
-
var
|
|
167874
|
+
var import_code_core13 = __toESM(require_dist3(), 1);
|
|
167255
167875
|
function parseMcpArgs(arg) {
|
|
167256
167876
|
const parts = arg.trim().split(/\s+/).filter(Boolean);
|
|
167257
167877
|
if (parts.length === 0)
|
|
@@ -167352,7 +167972,7 @@ function formatMcpDetail(input) {
|
|
|
167352
167972
|
const desc = (t2.description ?? "").split("\n")[0].trim();
|
|
167353
167973
|
const head = ` ${t2.name.padEnd(nameWidth)}`;
|
|
167354
167974
|
const maxSuffix = Math.max(0, budget - head.length);
|
|
167355
|
-
let suffix = (0,
|
|
167975
|
+
let suffix = (0, import_code_core13.describeStats)(byTool.get(t2.name));
|
|
167356
167976
|
if (suffix) {
|
|
167357
167977
|
suffix = ` ${suffix}`;
|
|
167358
167978
|
if (suffix.length > maxSuffix) {
|
|
@@ -167566,9 +168186,9 @@ function planModelSwitch(next, effort, clamp) {
|
|
|
167566
168186
|
}
|
|
167567
168187
|
|
|
167568
168188
|
// src/ui/keybindingsStore.ts
|
|
167569
|
-
var
|
|
168189
|
+
var import_code_core14 = __toESM(require_dist3(), 1);
|
|
167570
168190
|
function loadAndApplyKeybindings(workDir) {
|
|
167571
|
-
const settings = (0,
|
|
168191
|
+
const settings = (0, import_code_core14.loadSettings)(workDir);
|
|
167572
168192
|
const raw = settings.raw.keybindings;
|
|
167573
168193
|
const result = parseKeybindings(raw);
|
|
167574
168194
|
setBindings(result);
|
|
@@ -167618,7 +168238,7 @@ function resetKeybindings(workDir, scope = "user") {
|
|
|
167618
168238
|
return result;
|
|
167619
168239
|
}
|
|
167620
168240
|
function readRawBlock(workDir) {
|
|
167621
|
-
const settings = (0,
|
|
168241
|
+
const settings = (0, import_code_core14.loadSettings)(workDir);
|
|
167622
168242
|
const raw = settings.raw.keybindings;
|
|
167623
168243
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : {};
|
|
167624
168244
|
}
|
|
@@ -167818,7 +168438,7 @@ function formatTaskGraph(input) {
|
|
|
167818
168438
|
}
|
|
167819
168439
|
|
|
167820
168440
|
// src/ui/contextPanel.ts
|
|
167821
|
-
var
|
|
168441
|
+
var import_code_core15 = __toESM(require_dist3(), 1);
|
|
167822
168442
|
var KIND_LABEL2 = {
|
|
167823
168443
|
tool_result: "tool results",
|
|
167824
168444
|
reply: "model replies",
|
|
@@ -167893,8 +168513,8 @@ function textHead(block) {
|
|
|
167893
168513
|
var TOP_DEFAULT = 3;
|
|
167894
168514
|
var TOP_ALL = 10;
|
|
167895
168515
|
function measureContext(messages, topN = TOP_DEFAULT) {
|
|
167896
|
-
const bytes = (0,
|
|
167897
|
-
const tokens = (0,
|
|
168516
|
+
const bytes = (0, import_code_core15.estimateBodyBytes)(messages);
|
|
168517
|
+
const tokens = (0, import_code_core15.estimateTokensRough)(messages);
|
|
167898
168518
|
const toolNames = /* @__PURE__ */ new Map();
|
|
167899
168519
|
const buckets = /* @__PURE__ */ new Map();
|
|
167900
168520
|
const all = [];
|
|
@@ -168074,7 +168694,7 @@ function formatContextPanel(input) {
|
|
|
168074
168694
|
}
|
|
168075
168695
|
|
|
168076
168696
|
// src/ui/permDashboard.ts
|
|
168077
|
-
var
|
|
168697
|
+
var import_code_core16 = __toESM(require_dist3(), 1);
|
|
168078
168698
|
var DASHBOARD_ACTIONS = [
|
|
168079
168699
|
{ group: "Filesystem", label: "read a project file", tool: "read_file", input: { path: "src/app.ts" } },
|
|
168080
168700
|
{ group: "Filesystem", label: "edit a project file", tool: "edit_file", input: { path: "src/app.ts", old_string: "a", new_string: "b" } },
|
|
@@ -168105,15 +168725,15 @@ var NOT_A_READ = /* @__PURE__ */ new Set(["todo_write", "use_skill"]);
|
|
|
168105
168725
|
function capOf(tool) {
|
|
168106
168726
|
if (tool === "task")
|
|
168107
168727
|
return "delegate";
|
|
168108
|
-
if (
|
|
168728
|
+
if (import_code_core16.BASH_TOOLS.has(tool))
|
|
168109
168729
|
return "shell";
|
|
168110
|
-
if (
|
|
168730
|
+
if (import_code_core16.FILE_WRITE_TOOLS.has(tool) || import_code_core16.FILE_MUTATE_TOOLS.has(tool))
|
|
168111
168731
|
return "write";
|
|
168112
168732
|
if (NETWORK_TOOLS.has(tool))
|
|
168113
168733
|
return "network";
|
|
168114
168734
|
if (tool === "bash_output" || tool === "kill_shell")
|
|
168115
168735
|
return "shell";
|
|
168116
|
-
if (
|
|
168736
|
+
if (import_code_core16.READ_ONLY_TOOLS.has(tool) && !NOT_A_READ.has(tool))
|
|
168117
168737
|
return "read";
|
|
168118
168738
|
return null;
|
|
168119
168739
|
}
|
|
@@ -168141,19 +168761,19 @@ function capPhrase(caps) {
|
|
|
168141
168761
|
return parts.length ? parts.join(", ") : "nothing";
|
|
168142
168762
|
}
|
|
168143
168763
|
function explainAction(rules, mode, workDir, action, opts = {}) {
|
|
168144
|
-
const rule = (0,
|
|
168764
|
+
const rule = (0, import_code_core16.evaluatePermission)(rules, action.tool, action.input, workDir);
|
|
168145
168765
|
if (rule === "deny")
|
|
168146
168766
|
return { mark: "\u2717", reason: "denied by a permission rule" };
|
|
168147
|
-
if ((0,
|
|
168767
|
+
if ((0, import_code_core16.isDestructiveBash)(action.tool, action.input) && !opts.allowDestructive) {
|
|
168148
168768
|
return { mark: "\u26A0", reason: 'irreversible \u2014 always asks (type "yes")' };
|
|
168149
168769
|
}
|
|
168150
168770
|
if (rule === "allow")
|
|
168151
168771
|
return { mark: "\u2713", reason: "allowed by a permission rule" };
|
|
168152
|
-
const verdict = (0,
|
|
168772
|
+
const verdict = (0, import_code_core16.decide)({ tool: action.tool, input: action.input, mode, bypass: opts.yolo, destructive: false });
|
|
168153
168773
|
if (verdict === "allow") {
|
|
168154
168774
|
if (capOf(action.tool) === "read")
|
|
168155
168775
|
return { mark: "\u2713", reason: "read-only \u2014 allowed in every mode" };
|
|
168156
|
-
if (
|
|
168776
|
+
if (import_code_core16.BASH_TOOLS.has(action.tool) && (0, import_code_core16.isReadOnlyBash)(String(action.input.command ?? ""))) {
|
|
168157
168777
|
return { mark: "\u2713", reason: "read-only command \u2014 allowed in every mode" };
|
|
168158
168778
|
}
|
|
168159
168779
|
if (action.tool === "fetch_url" || action.tool === "web_search") {
|
|
@@ -168611,7 +169231,7 @@ function agentTypeModel(type, workDir) {
|
|
|
168611
169231
|
if (!agentTypeCache || agentTypeCache.workDir !== workDir || now - agentTypeCache.at > 1e3) {
|
|
168612
169232
|
const models = /* @__PURE__ */ new Map();
|
|
168613
169233
|
try {
|
|
168614
|
-
for (const t2 of (0,
|
|
169234
|
+
for (const t2 of (0, import_code_core17.loadAgentTypesWithWarnings)(workDir).types)
|
|
168615
169235
|
if (t2.model)
|
|
168616
169236
|
models.set(t2.name, t2.model);
|
|
168617
169237
|
} catch {
|
|
@@ -168676,13 +169296,13 @@ function agentPanelContext(v, cols, now) {
|
|
|
168676
169296
|
}
|
|
168677
169297
|
let maxConcurrent;
|
|
168678
169298
|
try {
|
|
168679
|
-
maxConcurrent = (0,
|
|
169299
|
+
maxConcurrent = (0, import_code_core19.resolveMaxConcurrentSubtasks)((0, import_code_core19.loadSettings)(v.workDir).raw);
|
|
168680
169300
|
} catch {
|
|
168681
169301
|
maxConcurrent = void 0;
|
|
168682
169302
|
}
|
|
168683
169303
|
const types3 = (() => {
|
|
168684
169304
|
try {
|
|
168685
|
-
return (0,
|
|
169305
|
+
return (0, import_code_core17.loadAgentTypesWithWarnings)(v.workDir).types.map((t2) => ({
|
|
168686
169306
|
name: t2.name,
|
|
168687
169307
|
description: t2.description,
|
|
168688
169308
|
...t2.model ? { model: t2.model } : {},
|
|
@@ -168782,7 +169402,7 @@ function printMergeReview(dir, cols) {
|
|
|
168782
169402
|
function printTaskGraph(workDir, cols) {
|
|
168783
169403
|
let tasks = [];
|
|
168784
169404
|
try {
|
|
168785
|
-
tasks = (0,
|
|
169405
|
+
tasks = (0, import_code_core19.listSharedTasks)(workDir);
|
|
168786
169406
|
} catch (e2) {
|
|
168787
169407
|
console.log(paint.red(" Could not read the shared task list: " + e2.message));
|
|
168788
169408
|
return;
|
|
@@ -168897,13 +169517,13 @@ var NO_PDF_MODELS = /* @__PURE__ */ new Set([
|
|
|
168897
169517
|
...NO_VISION_MODELS
|
|
168898
169518
|
]);
|
|
168899
169519
|
function needsVisionSidecar(model) {
|
|
168900
|
-
return !(0,
|
|
169520
|
+
return !(0, import_code_core17.liveSupportsImageInput)(model, !NO_VISION_MODELS.has(model));
|
|
168901
169521
|
}
|
|
168902
169522
|
function needsPdfSidecar(model) {
|
|
168903
|
-
return !(0,
|
|
169523
|
+
return !(0, import_code_core17.liveSupportsPdfInput)(model, !NO_PDF_MODELS.has(model));
|
|
168904
169524
|
}
|
|
168905
169525
|
function selectableModelIds() {
|
|
168906
|
-
return (0,
|
|
169526
|
+
return (0, import_code_core17.liveSelectableModelIds)() ?? SELECTABLE_MODELS;
|
|
168907
169527
|
}
|
|
168908
169528
|
function normaliseModelId(model) {
|
|
168909
169529
|
const raw = (model ?? "").trim();
|
|
@@ -168964,9 +169584,9 @@ var _BACKEND_STYLE_TO_LOCAL = {
|
|
|
168964
169584
|
};
|
|
168965
169585
|
function effortStyleFor(modelId) {
|
|
168966
169586
|
const id = normaliseModelId(modelId);
|
|
168967
|
-
if ((0,
|
|
169587
|
+
if ((0, import_code_core17.liveVendorFor)(id) === "Anthropic")
|
|
168968
169588
|
return "anthropic";
|
|
168969
|
-
const liveStyle = (0,
|
|
169589
|
+
const liveStyle = (0, import_code_core17.liveReasoningEffortStyle)(id);
|
|
168970
169590
|
if (liveStyle && _BACKEND_STYLE_TO_LOCAL[liveStyle])
|
|
168971
169591
|
return _BACKEND_STYLE_TO_LOCAL[liveStyle];
|
|
168972
169592
|
return MODEL_EFFORT_STYLE[id] ?? "anthropic";
|
|
@@ -168986,7 +169606,7 @@ function defaultEffortForModel(modelId) {
|
|
|
168986
169606
|
}
|
|
168987
169607
|
function resolveModelLabel(alias) {
|
|
168988
169608
|
const id = normaliseModelId(alias);
|
|
168989
|
-
return (0,
|
|
169609
|
+
return (0, import_code_core17.liveLabelFor)(id, MODEL_LABELS[id] ?? id);
|
|
168990
169610
|
}
|
|
168991
169611
|
function tryExec(cmd, cwd2) {
|
|
168992
169612
|
try {
|
|
@@ -169063,22 +169683,39 @@ var tryRead = (p) => {
|
|
|
169063
169683
|
return null;
|
|
169064
169684
|
}
|
|
169065
169685
|
};
|
|
169686
|
+
var lastLoadedInstructions = [];
|
|
169066
169687
|
function readNexrallMd(workDir) {
|
|
169688
|
+
lastLoadedInstructions = [];
|
|
169067
169689
|
if (noDiscovery)
|
|
169068
169690
|
return void 0;
|
|
169069
169691
|
const parts = [];
|
|
169070
|
-
const
|
|
169071
|
-
|
|
169692
|
+
const noteLoaded = (file, memoryType) => {
|
|
169693
|
+
try {
|
|
169694
|
+
if (fs25.existsSync(file))
|
|
169695
|
+
lastLoadedInstructions.push({ file_path: file, memory_type: memoryType, load_reason: "session_start" });
|
|
169696
|
+
} catch {
|
|
169697
|
+
}
|
|
169698
|
+
};
|
|
169699
|
+
const memContent = (0, import_code_core17.readAllMemory)(workDir);
|
|
169700
|
+
if (memContent) {
|
|
169072
169701
|
parts.push(memContent);
|
|
169073
|
-
|
|
169074
|
-
|
|
169702
|
+
noteLoaded((0, import_code_core17.memoryFilePath)("global"), "User");
|
|
169703
|
+
if (workDir)
|
|
169704
|
+
noteLoaded((0, import_code_core17.memoryFilePath)("project", workDir), "Project");
|
|
169705
|
+
}
|
|
169706
|
+
const globalNexrall = path25.join(os15.homedir(), ".nexrall", "nexrall.md");
|
|
169707
|
+
const globalContent = tryRead(globalNexrall);
|
|
169708
|
+
if (globalContent) {
|
|
169075
169709
|
parts.push(`[Global instructions]
|
|
169076
169710
|
${globalContent}`);
|
|
169711
|
+
noteLoaded(globalNexrall, "User");
|
|
169712
|
+
}
|
|
169077
169713
|
for (const candidate of NEXRALL_MD_CANDIDATES) {
|
|
169078
169714
|
const content = tryRead(path25.join(workDir, candidate));
|
|
169079
169715
|
if (content) {
|
|
169080
169716
|
parts.push(`[Project instructions \u2014 ${candidate}]
|
|
169081
169717
|
${content}`);
|
|
169718
|
+
noteLoaded(path25.join(workDir, candidate), "Project");
|
|
169082
169719
|
break;
|
|
169083
169720
|
}
|
|
169084
169721
|
}
|
|
@@ -169301,7 +169938,7 @@ var Spinner = class {
|
|
|
169301
169938
|
return this.interval !== null;
|
|
169302
169939
|
}
|
|
169303
169940
|
};
|
|
169304
|
-
var cliBackgroundAgents = new
|
|
169941
|
+
var cliBackgroundAgents = new import_code_core17.BackgroundAgentHub();
|
|
169305
169942
|
function nextBackgroundChange() {
|
|
169306
169943
|
return new Promise((resolve11) => {
|
|
169307
169944
|
const off = cliBackgroundAgents.onChange(() => {
|
|
@@ -169319,7 +169956,7 @@ async function initMcp(workDir, override, strict) {
|
|
|
169319
169956
|
_mcpManager = null;
|
|
169320
169957
|
return;
|
|
169321
169958
|
}
|
|
169322
|
-
_mcpConfig = strict && override ? { mcpServers: {} } :
|
|
169959
|
+
_mcpConfig = strict && override ? { mcpServers: {} } : import_code_core17.McpManager.loadConfig(workDir);
|
|
169323
169960
|
if (override)
|
|
169324
169961
|
Object.assign(_mcpConfig.mcpServers, override.mcpServers);
|
|
169325
169962
|
if (Object.keys(_mcpConfig.mcpServers).length === 0) {
|
|
@@ -169330,12 +169967,12 @@ async function initMcp(workDir, override, strict) {
|
|
|
169330
169967
|
await injectMcpTokens(_mcpConfig);
|
|
169331
169968
|
} catch {
|
|
169332
169969
|
}
|
|
169333
|
-
const manager = new
|
|
169970
|
+
const manager = new import_code_core17.McpManager();
|
|
169334
169971
|
await manager.connectAll(_mcpConfig);
|
|
169335
169972
|
_mcpManager = manager;
|
|
169336
169973
|
}
|
|
169337
169974
|
function formatAgentsList(workDir) {
|
|
169338
|
-
const { types: types3, warnings } = (0,
|
|
169975
|
+
const { types: types3, warnings } = (0, import_code_core17.loadAgentTypesWithWarnings)(workDir);
|
|
169339
169976
|
if (!types3.length)
|
|
169340
169977
|
return paint.dim(" No agent types found (this should not happen \u2014 builtins always register).");
|
|
169341
169978
|
const lines = types3.map((t2) => {
|
|
@@ -169520,7 +170157,7 @@ function startSessionLog(id, resumed, extra = {}) {
|
|
|
169520
170157
|
}
|
|
169521
170158
|
var failureLedger = new FailureLedger();
|
|
169522
170159
|
var networkLedger = new NetworkLedger();
|
|
169523
|
-
var networkApiHost = hostOf(
|
|
170160
|
+
var networkApiHost = hostOf(import_code_core19.API_BASE) ?? import_code_core19.API_BASE;
|
|
169524
170161
|
var notifier = new Notifier({ env: process.env, isTTY: Boolean(process.stdout.isTTY) });
|
|
169525
170162
|
var userActiveThisTurn = false;
|
|
169526
170163
|
var failureBannerShown = "";
|
|
@@ -169727,7 +170364,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
169727
170364
|
setMode(mode);
|
|
169728
170365
|
console.log();
|
|
169729
170366
|
spinner.start("thinking\u2026", { hint: false, verbs: true });
|
|
169730
|
-
const result = await (0,
|
|
170367
|
+
const result = await (0, import_code_core17.runAgentLoop)(messages, {
|
|
169731
170368
|
workDir,
|
|
169732
170369
|
sessionId: activeSessionIdGetter(),
|
|
169733
170370
|
model: modelAlias,
|
|
@@ -170071,12 +170708,12 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env4
|
|
|
170071
170708
|
sessionId: activeSessionIdGetter(),
|
|
170072
170709
|
cwd: workDir,
|
|
170073
170710
|
model: modelAlias,
|
|
170074
|
-
tools: _headlessPolicy.onlyTools ? [..._headlessPolicy.onlyTools].sort() : (0,
|
|
170711
|
+
tools: _headlessPolicy.onlyTools ? [..._headlessPolicy.onlyTools].sort() : (0, import_code_core17.knownToolNames)(),
|
|
170075
170712
|
permissionMode: _headlessPolicy.permissionMode
|
|
170076
170713
|
}));
|
|
170077
170714
|
emit({ type: "start", model: modelAlias, workDir });
|
|
170078
170715
|
verbose(`[verbose] model=${modelAlias} cwd=${workDir} mode=${mode} session=${activeSessionIdGetter() ?? "-"}`);
|
|
170079
|
-
const result = await (0,
|
|
170716
|
+
const result = await (0, import_code_core17.runAgentLoop)(messages, {
|
|
170080
170717
|
workDir,
|
|
170081
170718
|
sessionId: activeSessionIdGetter(),
|
|
170082
170719
|
model: modelAlias,
|
|
@@ -170217,16 +170854,43 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env4
|
|
|
170217
170854
|
emit({ type: "permission_denied", tool, reason: "tools" });
|
|
170218
170855
|
return false;
|
|
170219
170856
|
}
|
|
170220
|
-
const d = (0,
|
|
170857
|
+
const d = (0, import_code_core17.isDestructiveBash)(tool, input);
|
|
170858
|
+
const policy = (0, import_code_core18.decide)({ tool, input, mode: (0, import_code_core19.parseMode)(mode), bypass: isYoloMode(), destructive: !!d });
|
|
170221
170859
|
const v = headlessVerdict({
|
|
170222
|
-
rule: (0,
|
|
170860
|
+
rule: (0, import_code_core19.evaluatePermission)((0, import_code_core19.loadSettings)(workDir).permissions, tool, input, workDir),
|
|
170223
170861
|
destructive: !!d,
|
|
170224
170862
|
allowDestructive: process.env.NEXRALL_ALLOW_DESTRUCTIVE === "1",
|
|
170225
170863
|
strict: _headlessPolicy.strict,
|
|
170226
|
-
policy
|
|
170864
|
+
policy
|
|
170227
170865
|
});
|
|
170228
170866
|
if (v.verdict === "allow")
|
|
170229
170867
|
return true;
|
|
170868
|
+
const hookGate = await runHeadlessPermissionHooks(
|
|
170869
|
+
{ tool, input, workDir, sessionId: activeSessionIdGetter() ?? "", reason: v.reason, policyDeny: policy === "deny", destructive: d },
|
|
170870
|
+
emit,
|
|
170871
|
+
emitEvent
|
|
170872
|
+
);
|
|
170873
|
+
if (hookGate.handled === "allow")
|
|
170874
|
+
return true;
|
|
170875
|
+
if (hookGate.handled === "deny")
|
|
170876
|
+
return { granted: false, message: hookGate.message };
|
|
170877
|
+
const toolFlag = _headlessPolicy.permissionPromptTool;
|
|
170878
|
+
if (toolFlag && v.reason !== "rule" && !(policy === "deny")) {
|
|
170879
|
+
const ans = await askPermissionPromptTool(_mcpManager, toolFlag, { tool, input, cwd: workDir, mode, sessionId: activeSessionIdGetter() ?? void 0 }, _abortSignal);
|
|
170880
|
+
if ("error" in ans) {
|
|
170881
|
+
emit({ type: "error", error: `--permission-prompt-tool ${toolFlag}: ${ans.error}` });
|
|
170882
|
+
emitEvent("permission.denied", { tool, reason: "prompt-tool-error" });
|
|
170883
|
+
return { granted: false, message: `Permission denied: ${ans.error}` };
|
|
170884
|
+
}
|
|
170885
|
+
if (ans.behavior === "allow") {
|
|
170886
|
+
emit({ type: "permission_granted", tool, reason: "prompt-tool" });
|
|
170887
|
+
emitEvent("permission.granted", { tool, reason: "prompt-tool" });
|
|
170888
|
+
return ans.updatedInput ? { granted: true, updatedInput: ans.updatedInput } : true;
|
|
170889
|
+
}
|
|
170890
|
+
emit({ type: "permission_denied", tool, reason: "prompt-tool" });
|
|
170891
|
+
emitEvent("permission.denied", { tool, reason: "prompt-tool" });
|
|
170892
|
+
return { granted: false, message: ans.message ? `Permission denied by ${toolFlag}: ${ans.message}` : `Permission denied by ${toolFlag}` };
|
|
170893
|
+
}
|
|
170230
170894
|
if (v.reason === "destructive" && d) {
|
|
170231
170895
|
emit({ type: "error", error: `Destructive command blocked in headless mode (${d.category}): ${d.reason}. Set NEXRALL_ALLOW_DESTRUCTIVE=1 to permit.` });
|
|
170232
170896
|
} else {
|
|
@@ -170464,7 +171128,7 @@ async function startChatSession(options) {
|
|
|
170464
171128
|
if (options.bare)
|
|
170465
171129
|
setNoDiscovery(true);
|
|
170466
171130
|
_cliAgentTypes = (options.agents ?? []).map((a) => ({ ...a, source: "programmatic" }));
|
|
170467
|
-
(0,
|
|
171131
|
+
(0, import_code_core17.enableAgentTranscriptPersistence)();
|
|
170468
171132
|
const headless = options.outputFormat === "json" || options.outputFormat === "stream-json";
|
|
170469
171133
|
const requestedWorkDir = options.workDir;
|
|
170470
171134
|
let workDir = requestedWorkDir;
|
|
@@ -170473,7 +171137,7 @@ async function startChatSession(options) {
|
|
|
170473
171137
|
let peerInbox;
|
|
170474
171138
|
const peerInboxQueue = [];
|
|
170475
171139
|
let modelAlias = options.model;
|
|
170476
|
-
void (0,
|
|
171140
|
+
void (0, import_code_core17.getModelCatalogue)().catch(() => {
|
|
170477
171141
|
});
|
|
170478
171142
|
const canPrompt = !headless && !options.prompt && !options.stdinText && process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
170479
171143
|
if (!trustGrantedByEnv()) {
|
|
@@ -170501,21 +171165,21 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
|
|
|
170501
171165
|
}
|
|
170502
171166
|
const themeConfig = loadAndApplyTheme(workDir);
|
|
170503
171167
|
const keyConfig = loadAndApplyKeybindings(workDir);
|
|
170504
|
-
liveDiffEnabled = readLiveDiffSetting((0,
|
|
170505
|
-
mouseEnabled = readMouseSetting((0,
|
|
170506
|
-
notifier.setMode(readNotifySetting((0,
|
|
171168
|
+
liveDiffEnabled = readLiveDiffSetting((0, import_code_core19.loadSettings)(workDir).raw);
|
|
171169
|
+
mouseEnabled = readMouseSetting((0, import_code_core19.loadSettings)(workDir).raw);
|
|
171170
|
+
notifier.setMode(readNotifySetting((0, import_code_core19.loadSettings)(workDir).raw));
|
|
170507
171171
|
setAskNotifier((what) => {
|
|
170508
171172
|
notifier.notify(needsYouNote(what));
|
|
170509
171173
|
emitEvent("permission.requested", { what });
|
|
170510
|
-
(0,
|
|
171174
|
+
(0, import_code_core18.fireNotificationHooks)(workDir, `Nexrall needs your permission: ${what}`);
|
|
170511
171175
|
});
|
|
170512
171176
|
setPermissionObserver((tool, granted) => emitEvent(granted ? "permission.granted" : "permission.denied", { tool }));
|
|
170513
171177
|
let activeThemeName = themeConfig.theme;
|
|
170514
171178
|
if (options.worktree !== void 0) {
|
|
170515
171179
|
const requestedName = typeof options.worktree === "string" ? options.worktree : void 0;
|
|
170516
|
-
const existing = requestedName ? (0,
|
|
171180
|
+
const existing = requestedName ? (0, import_code_core17.findWorktreeByName)(requestedWorkDir, requestedName) : null;
|
|
170517
171181
|
if (existing) {
|
|
170518
|
-
const entered = (0,
|
|
171182
|
+
const entered = (0, import_code_core17.enterWorktree)(existing);
|
|
170519
171183
|
if (!entered.ok) {
|
|
170520
171184
|
process.stderr.write(`Failed to resume worktree "${requestedName}": ${entered.error}
|
|
170521
171185
|
`);
|
|
@@ -170525,7 +171189,7 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
|
|
|
170525
171189
|
if (!headless)
|
|
170526
171190
|
console.log(paint.dim(` Resumed worktree: ${paint.bold(existing.name)} (${existing.worktreePath})`));
|
|
170527
171191
|
} else {
|
|
170528
|
-
const created = (0,
|
|
171192
|
+
const created = (0, import_code_core17.createWorktree)(requestedWorkDir, requestedName);
|
|
170529
171193
|
if (!created.ok || !created.state) {
|
|
170530
171194
|
process.stderr.write(`Failed to create worktree: ${created.error ?? "unknown error"}
|
|
170531
171195
|
`);
|
|
@@ -170544,7 +171208,7 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
|
|
|
170544
171208
|
process.on("exit", () => {
|
|
170545
171209
|
if (!worktreeState)
|
|
170546
171210
|
return;
|
|
170547
|
-
const hadWork = (0,
|
|
171211
|
+
const hadWork = (0, import_code_core17.worktreeHasWork)(worktreeState);
|
|
170548
171212
|
if (hadWork) {
|
|
170549
171213
|
process.stderr.write(
|
|
170550
171214
|
`
|
|
@@ -170555,7 +171219,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170555
171219
|
);
|
|
170556
171220
|
return;
|
|
170557
171221
|
}
|
|
170558
|
-
(0,
|
|
171222
|
+
(0, import_code_core17.removeWorktree)(worktreeState);
|
|
170559
171223
|
});
|
|
170560
171224
|
}
|
|
170561
171225
|
const env4 = collectEnv(workDir);
|
|
@@ -170564,7 +171228,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170564
171228
|
const nexrallMd = [agentPrefix, briefBase, options.appendSystemPrompt?.trim(), addDirNote(options.addDirs ?? []), options.jsonSchema ? schemaInstruction(options.jsonSchema) : ""].filter(Boolean).join("\n\n") || void 0;
|
|
170565
171229
|
const agentTools = options.selectedAgent?.tools;
|
|
170566
171230
|
const toolAllow = agentTools && options.onlyTools ? options.onlyTools.filter((t2) => agentTools.includes(t2)) : options.onlyTools ?? agentTools;
|
|
170567
|
-
_headlessPolicy = { strict: !!options.strictPermissions, budgetUsd: options.budgetUsd, spent: 0, schema: options.jsonSchema, maxTurns: options.maxTurns, onlyTools: toolAllow ? new Set(toolAllow) : void 0 };
|
|
171231
|
+
_headlessPolicy = { strict: !!options.strictPermissions, budgetUsd: options.budgetUsd, spent: 0, schema: options.jsonSchema, maxTurns: options.maxTurns, onlyTools: toolAllow ? new Set(toolAllow) : void 0, permissionPromptTool: options.permissionPromptTool };
|
|
170568
171232
|
_headlessPolicy.verbose = !!options.verbose;
|
|
170569
171233
|
_headlessPolicy.includePartial = !!options.includePartialMessages;
|
|
170570
171234
|
_headlessPolicy.permissionMode = String(options.initialMode ?? "");
|
|
@@ -170573,8 +171237,8 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170573
171237
|
const interactive = !headless && !options.prompt && !options.stdinText;
|
|
170574
171238
|
let peerHeartbeatTimer;
|
|
170575
171239
|
if (interactive) {
|
|
170576
|
-
const handle2 = (0,
|
|
170577
|
-
const inbox = (0,
|
|
171240
|
+
const handle2 = (0, import_code_core17.registerPeer)({ clientType: "cli", workDir: requestedWorkDir });
|
|
171241
|
+
const inbox = (0, import_code_core17.startPeerInbox)(handle2.record.id, { onMessage: (m2) => peerInboxQueue.push(m2) });
|
|
170578
171242
|
handle2.record.socketPath = inbox.socketPath;
|
|
170579
171243
|
handle2.heartbeat();
|
|
170580
171244
|
peerHandle = handle2;
|
|
@@ -170646,6 +171310,18 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170646
171310
|
let sessionId = options.newSessionId ?? crypto7.randomBytes(8).toString("hex");
|
|
170647
171311
|
activeSessionIdGetter = () => sessionId;
|
|
170648
171312
|
let sessionTitle = options.sessionName ?? "";
|
|
171313
|
+
const fileWatcher = noDiscovery ? null : (0, import_code_core17.startFileChangedWatcher)(workDir, sessionId, {
|
|
171314
|
+
// A hook's {"systemMessage":"…"} is the event's one user-visible field.
|
|
171315
|
+
onSystemMessage: (m2) => console.log(paint.dim(` ${m2}`))
|
|
171316
|
+
});
|
|
171317
|
+
if (fileWatcher) {
|
|
171318
|
+
const watching = fileWatcher.watchedFiles();
|
|
171319
|
+
if (watching.length && !headless)
|
|
171320
|
+
console.log(paint.dim(` FileChanged hook: watching ${watching.join(", ")}`));
|
|
171321
|
+
if (options.verbose)
|
|
171322
|
+
process.stderr.write("[verbose] FileChanged hook: " + watching.join(", ") + "\n");
|
|
171323
|
+
}
|
|
171324
|
+
void (0, import_code_core17.fireInstructionsLoadedHooks)(workDir, sessionId, lastLoadedInstructions);
|
|
170649
171325
|
const modeLocked = options.lockMode === true;
|
|
170650
171326
|
let agentMode = modeLocked ? "plan" : options.initialMode ?? "auto";
|
|
170651
171327
|
const refuseIfLocked = (what) => {
|
|
@@ -170667,7 +171343,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170667
171343
|
for (const n of themeConfig.notes)
|
|
170668
171344
|
console.log(paint.dim(" theme: " + n));
|
|
170669
171345
|
}
|
|
170670
|
-
let skills = noDiscovery ? [] : (0,
|
|
171346
|
+
let skills = noDiscovery ? [] : (0, import_code_core17.loadSkills)(workDir);
|
|
170671
171347
|
if (skills.length && !headless)
|
|
170672
171348
|
console.log(paint.dim(` ${skills.length} skill(s) loaded`));
|
|
170673
171349
|
let contextSet = loadContextSet(workDir);
|
|
@@ -170732,7 +171408,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170732
171408
|
}
|
|
170733
171409
|
startSessionLog(sessionId, true, options.forkSession ? { workDir, forkOf: stored.id } : { workDir });
|
|
170734
171410
|
try {
|
|
170735
|
-
const compacted = await (0,
|
|
171411
|
+
const compacted = await (0, import_code_core17.compactMessagesForResume)(messages, {
|
|
170736
171412
|
workDir,
|
|
170737
171413
|
model: modelAlias,
|
|
170738
171414
|
clientType: "cli"
|
|
@@ -170748,7 +171424,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170748
171424
|
}
|
|
170749
171425
|
if (!(options.resume || options.continueLast))
|
|
170750
171426
|
startSessionLog(sessionId, false, { workDir });
|
|
170751
|
-
const checkpoints = new
|
|
171427
|
+
const checkpoints = new import_code_core17.CheckpointManager(workDir, sessionId);
|
|
170752
171428
|
const commitCheckpoint = () => {
|
|
170753
171429
|
checkpoints.commitTurn();
|
|
170754
171430
|
emitEvent("checkpoint.created", { turns: checkpoints.list().length });
|
|
@@ -170770,7 +171446,7 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
170770
171446
|
sessionTitle = raw.length > 60 ? raw.slice(0, 60) + "\u2026" : raw;
|
|
170771
171447
|
};
|
|
170772
171448
|
const recoverTurn = (err, current) => {
|
|
170773
|
-
const salvaged = (0,
|
|
171449
|
+
const salvaged = (0, import_code_core17.salvageHistory)(err);
|
|
170774
171450
|
printErrorReport(err, abortSignal.aborted);
|
|
170775
171451
|
printTurnSummary(abortSignal.aborted ? "interrupted" : "failed");
|
|
170776
171452
|
if (!salvaged)
|
|
@@ -170828,7 +171504,7 @@ ${text}` : "");
|
|
|
170828
171504
|
throw e2;
|
|
170829
171505
|
const from = modelAlias;
|
|
170830
171506
|
modelAlias = options.fallbackModel;
|
|
170831
|
-
const salvagedMsgs = (0,
|
|
171507
|
+
const salvagedMsgs = (0, import_code_core17.salvageHistory)(e2);
|
|
170832
171508
|
if (salvagedMsgs)
|
|
170833
171509
|
messages = salvagedMsgs;
|
|
170834
171510
|
const note = `Model ${from} failed (${String(e2.message).slice(0, 120)}); retrying on ${modelAlias}`;
|
|
@@ -170847,7 +171523,7 @@ ${text}` : "");
|
|
|
170847
171523
|
continue;
|
|
170848
171524
|
}
|
|
170849
171525
|
const notes = cliBackgroundAgents.takeNotifications();
|
|
170850
|
-
messages.push({ role: "user", content: [{ type: "text", text: (0,
|
|
171526
|
+
messages.push({ role: "user", content: [{ type: "text", text: (0, import_code_core17.formatBackgroundNotifications)(notes) }] });
|
|
170851
171527
|
result = await runOnce();
|
|
170852
171528
|
messages = result.messages;
|
|
170853
171529
|
}
|
|
@@ -170865,7 +171541,7 @@ ${text}` : "");
|
|
|
170865
171541
|
await nextBackgroundChange();
|
|
170866
171542
|
continue;
|
|
170867
171543
|
}
|
|
170868
|
-
messages.push({ role: "user", content: [{ type: "text", text: (0,
|
|
171544
|
+
messages.push({ role: "user", content: [{ type: "text", text: (0, import_code_core17.formatBackgroundNotifications)(cliBackgroundAgents.takeNotifications()) }] });
|
|
170869
171545
|
result = await runOnce();
|
|
170870
171546
|
messages = result.messages;
|
|
170871
171547
|
}
|
|
@@ -170878,7 +171554,7 @@ ${text}` : "");
|
|
|
170878
171554
|
await new Promise((r2) => setImmediate(r2));
|
|
170879
171555
|
process.exit(process.exitCode ?? 0);
|
|
170880
171556
|
} catch (err) {
|
|
170881
|
-
const salvaged = (0,
|
|
171557
|
+
const salvaged = (0, import_code_core17.salvageHistory)(err);
|
|
170882
171558
|
if (salvaged) {
|
|
170883
171559
|
messages = salvaged;
|
|
170884
171560
|
try {
|
|
@@ -170911,12 +171587,12 @@ ${text}` : "");
|
|
|
170911
171587
|
console.log(paint.dim(" Type a message, /help for commands, or Ctrl+C to exit."));
|
|
170912
171588
|
console.log();
|
|
170913
171589
|
const footerExtras = () => {
|
|
170914
|
-
const win = (0,
|
|
171590
|
+
const win = (0, import_code_core17.contextWindowFor)(modelAlias);
|
|
170915
171591
|
return {
|
|
170916
171592
|
nav: transcriptNav ? navLabel(transcriptNav) : void 0,
|
|
170917
171593
|
model: resolveModelLabel(modelAlias),
|
|
170918
171594
|
branch: gitBranch(workDir) ?? void 0,
|
|
170919
|
-
ctxPct: messages.length ? Math.min(100, (0,
|
|
171595
|
+
ctxPct: messages.length ? Math.min(100, (0, import_code_core17.estimateTokensRough)(messages) / win * 100) : 0,
|
|
170920
171596
|
costUsd: sessionUsage.costReported ? sessionUsage.cost : void 0,
|
|
170921
171597
|
// Live sub-agents (spec §37). Recomputed per footer render, which is also what
|
|
170922
171598
|
// retires a background agent's row the moment the hub drops it.
|
|
@@ -170986,7 +171662,7 @@ ${text}` : "");
|
|
|
170986
171662
|
console.log(paint.green(` \u2713 Saved to ${saved.scope} memory`) + paint.dim(` \u2014 ${saved.file}`) + (saved.superseded ? paint.dim(" (the older fact moved to Superseded)") : ""));
|
|
170987
171663
|
}
|
|
170988
171664
|
};
|
|
170989
|
-
const allSlashEntries = () => [...BUILTIN_SLASH_COMMANDS, ...skillEntries((0,
|
|
171665
|
+
const allSlashEntries = () => [...BUILTIN_SLASH_COMMANDS, ...skillEntries((0, import_code_core17.userInvokableSkills)(skills))];
|
|
170990
171666
|
let slashRecents = loadRecents();
|
|
170991
171667
|
const syncSlashMenu = () => {
|
|
170992
171668
|
if (interactive)
|
|
@@ -171028,7 +171704,7 @@ ${text}` : "");
|
|
|
171028
171704
|
};
|
|
171029
171705
|
const modelPickerNote = (id) => {
|
|
171030
171706
|
const parts = [];
|
|
171031
|
-
const mult = (0,
|
|
171707
|
+
const mult = (0, import_code_core17.liveCostMultiplierFor)(id, MODEL_COST_MULTIPLIER[id]);
|
|
171032
171708
|
if (mult !== void 0 && mult !== 1)
|
|
171033
171709
|
parts.push(`${mult}x`);
|
|
171034
171710
|
if (needsVisionSidecar(id))
|
|
@@ -171223,7 +171899,7 @@ ${text}` : "");
|
|
|
171223
171899
|
return;
|
|
171224
171900
|
}
|
|
171225
171901
|
const row2 = matches[0];
|
|
171226
|
-
const scope =
|
|
171902
|
+
const scope = import_code_core17.McpManager.serverScope(workDir, row2.name);
|
|
171227
171903
|
if (action.kind === "detail") {
|
|
171228
171904
|
const st = _mcpManager?.getStatus().find((x2) => x2.name === row2.name);
|
|
171229
171905
|
const tools = (st?.tools ?? []).map((t2) => ({ name: t2.name, description: t2.description }));
|
|
@@ -171247,7 +171923,7 @@ ${text}` : "");
|
|
|
171247
171923
|
let signedIn = false;
|
|
171248
171924
|
let attempted = false;
|
|
171249
171925
|
if (!plan.refuse && plan.persist) {
|
|
171250
|
-
|
|
171926
|
+
import_code_core17.McpManager.setServerDisabled(workDir, row2.name, plan.persist.disabled, plan.persist.scope);
|
|
171251
171927
|
noteDisabledInConfig(row2.name, plan.persist.disabled);
|
|
171252
171928
|
}
|
|
171253
171929
|
if (!plan.refuse) {
|
|
@@ -171432,12 +172108,12 @@ ${text}` : "");
|
|
|
171432
172108
|
rl.prompt();
|
|
171433
172109
|
return;
|
|
171434
172110
|
}
|
|
171435
|
-
if ((0,
|
|
172111
|
+
if ((0, import_code_core19.evaluatePermission)(permRules, "bash", { command: cmd }, workDir) === "deny") {
|
|
171436
172112
|
console.log(paint.red(" \u2716 Denied by permission rule: bash"));
|
|
171437
172113
|
rl.prompt();
|
|
171438
172114
|
return;
|
|
171439
172115
|
}
|
|
171440
|
-
if (modeLocked && !(0,
|
|
172116
|
+
if (modeLocked && !(0, import_code_core19.isReadOnlyBash)(cmd)) {
|
|
171441
172117
|
console.log(paint.yellow(" \u2298 Read-only session (--readonly): only read-only commands can run with !."));
|
|
171442
172118
|
rl.prompt();
|
|
171443
172119
|
return;
|
|
@@ -171592,7 +172268,7 @@ ${text}` : "");
|
|
|
171592
172268
|
emitEvent("session.completed", { id: liveSessionId, reason: "clear" });
|
|
171593
172269
|
sessionId = crypto7.randomBytes(8).toString("hex");
|
|
171594
172270
|
sessionTitle = "";
|
|
171595
|
-
(0,
|
|
172271
|
+
(0, import_code_core19.resetSessionSubAgentBudget)();
|
|
171596
172272
|
sessionUsage.reset();
|
|
171597
172273
|
sessionStartedAt = Date.now();
|
|
171598
172274
|
sessionToolCalls = 0;
|
|
@@ -171688,7 +172364,7 @@ ${text}` : "");
|
|
|
171688
172364
|
startSessionLog(sessionId, true, { workDir });
|
|
171689
172365
|
const beforeCompact = messages.length;
|
|
171690
172366
|
try {
|
|
171691
|
-
await (0,
|
|
172367
|
+
await (0, import_code_core17.compactMessagesForResume)(messages, {
|
|
171692
172368
|
workDir,
|
|
171693
172369
|
model: modelAlias,
|
|
171694
172370
|
clientType: "cli"
|
|
@@ -171742,7 +172418,7 @@ ${text}` : "");
|
|
|
171742
172418
|
}
|
|
171743
172419
|
rl.pause();
|
|
171744
172420
|
console.log(paint.dim(" Compacting conversation\u2026"));
|
|
171745
|
-
await (0,
|
|
172421
|
+
await (0, import_code_core18.fireManualPreCompactHook)(workDir, sessionId, Math.max(0, messages.length - 4));
|
|
171746
172422
|
const KEEP = 4;
|
|
171747
172423
|
const toSummarize = messages.slice(0, -KEEP);
|
|
171748
172424
|
const kept = messages.slice(-KEEP);
|
|
@@ -171788,7 +172464,7 @@ ${summaryText}` }] },
|
|
|
171788
172464
|
saveSession2(sessionId, sessionTitle || "Untitled", workDir, messages);
|
|
171789
172465
|
console.log(paint.green(` Compacted ${toSummarize.length} messages \u2192 ${messages.length} messages.`));
|
|
171790
172466
|
emitEvent("context.compacted", { where: "manual", before: toSummarize.length + KEEP, after: messages.length });
|
|
171791
|
-
await (0,
|
|
172467
|
+
await (0, import_code_core18.fireManualPostCompactHook)(workDir, sessionId, toSummarize.length);
|
|
171792
172468
|
if (pin.attachments.length)
|
|
171793
172469
|
console.log(paint.dim(` ${pin.attachments.length} pinned file(s) re-attached.`));
|
|
171794
172470
|
for (const n of pin.notes)
|
|
@@ -171864,13 +172540,13 @@ ${dirList}`;
|
|
|
171864
172540
|
const sub = arg.trim().toLowerCase();
|
|
171865
172541
|
console.log();
|
|
171866
172542
|
if (sub === "list") {
|
|
171867
|
-
const all = (0,
|
|
172543
|
+
const all = (0, import_code_core17.listWorktrees)(requestedWorkDir);
|
|
171868
172544
|
if (!all.length) {
|
|
171869
172545
|
console.log(paint.dim(" No worktrees under this project."));
|
|
171870
172546
|
} else {
|
|
171871
172547
|
console.log(paint.bold(` Worktrees (${all.length})`));
|
|
171872
172548
|
for (const w of all) {
|
|
171873
|
-
const dirty = (0,
|
|
172549
|
+
const dirty = (0, import_code_core17.worktreeHasWork)(w) ? paint.yellow("dirty") : paint.dim("clean");
|
|
171874
172550
|
console.log(` ${paint.cyan(w.name)} ${paint.dim(w.worktreePath)} [${dirty}]`);
|
|
171875
172551
|
}
|
|
171876
172552
|
console.log();
|
|
@@ -171908,7 +172584,7 @@ ${dirList}`;
|
|
|
171908
172584
|
if (!targetName || !text) {
|
|
171909
172585
|
console.log(paint.dim(" Usage: /peers send <name> <message>"));
|
|
171910
172586
|
} else {
|
|
171911
|
-
const target = (0,
|
|
172587
|
+
const target = (0, import_code_core17.listPeers)().find((p) => p.name === targetName);
|
|
171912
172588
|
if (!target) {
|
|
171913
172589
|
console.log(paint.red(` No live session named "${targetName}". Use /peers to list who's reachable.`));
|
|
171914
172590
|
} else if (!target.socketPath) {
|
|
@@ -171925,7 +172601,7 @@ ${dirList}`;
|
|
|
171925
172601
|
console.log(paint.dim(" Usage: /peers broadcast <message>"));
|
|
171926
172602
|
} else {
|
|
171927
172603
|
const { broadcastPeerMessage } = await Promise.resolve().then(() => __toESM(require_dist3(), 1));
|
|
171928
|
-
const targets = (0,
|
|
172604
|
+
const targets = (0, import_code_core17.listPeers)(peerHandle.record.id).filter((p) => p.id !== peerHandle.record.id && p.socketPath && p.inbound !== "refuse").map((p) => ({ name: p.name, socketPath: p.socketPath }));
|
|
171929
172605
|
if (!targets.length) {
|
|
171930
172606
|
console.log(paint.dim(" No other reachable Nexrall Code sessions to broadcast to."));
|
|
171931
172607
|
} else {
|
|
@@ -171937,7 +172613,7 @@ ${dirList}`;
|
|
|
171937
172613
|
}
|
|
171938
172614
|
}
|
|
171939
172615
|
} else {
|
|
171940
|
-
const peers = (0,
|
|
172616
|
+
const peers = (0, import_code_core17.listPeers)(peerHandle.record.id);
|
|
171941
172617
|
if (peers.length <= 1) {
|
|
171942
172618
|
console.log(paint.dim(" No other Nexrall Code sessions are currently discoverable on this machine."));
|
|
171943
172619
|
} else {
|
|
@@ -171979,7 +172655,7 @@ ${dirList}`;
|
|
|
171979
172655
|
const label = memScope === "global" ? "GLOBAL" : "this PROJECT's";
|
|
171980
172656
|
const answer = await new Promise((resolve11) => rl.question(paint.yellow(` Clear ${label} memory? This cannot be undone. [y/n] `), (a) => resolve11(a.trim())));
|
|
171981
172657
|
if (answer === "y" || answer === "yes") {
|
|
171982
|
-
(0,
|
|
172658
|
+
(0, import_code_core17.clearMemory)(memScope, workDir);
|
|
171983
172659
|
console.log(paint.green(` ${memScope === "global" ? "Global" : "Project"} memory cleared.`));
|
|
171984
172660
|
} else {
|
|
171985
172661
|
console.log(paint.dim(" Cancelled."));
|
|
@@ -171990,20 +172666,20 @@ ${dirList}`;
|
|
|
171990
172666
|
}
|
|
171991
172667
|
console.log();
|
|
171992
172668
|
if (wantsGlobalOnly) {
|
|
171993
|
-
const stats = (0,
|
|
171994
|
-
const content = (0,
|
|
172669
|
+
const stats = (0, import_code_core17.memoryStats)("global");
|
|
172670
|
+
const content = (0, import_code_core17.readMemory)("global", void 0, { includeArchived: wantsArchived });
|
|
171995
172671
|
const archivedNote = stats.archived > 0 ? `, ${stats.archived} archived` : "";
|
|
171996
172672
|
console.log(paint.bold(" Global memory ") + paint.dim(`(${stats.entries} entries${archivedNote}, ${(stats.bytes / 1024).toFixed(1)}KB) \u2014 ${stats.file}`));
|
|
171997
172673
|
console.log();
|
|
171998
172674
|
console.log(content || paint.dim(" No global memories saved yet."));
|
|
171999
172675
|
} else {
|
|
172000
|
-
const projStats = (0,
|
|
172001
|
-
const globalStats = (0,
|
|
172676
|
+
const projStats = (0, import_code_core17.memoryStats)("project", workDir);
|
|
172677
|
+
const globalStats = (0, import_code_core17.memoryStats)("global");
|
|
172002
172678
|
const projArchived = projStats.archived > 0 ? `+${projStats.archived} archived ` : "";
|
|
172003
172679
|
const globalArchived = globalStats.archived > 0 ? `+${globalStats.archived} archived ` : "";
|
|
172004
172680
|
console.log(paint.bold(" Memory") + paint.dim(` \u2014 project: ${projStats.entries} ${projArchived}entries (${(projStats.bytes / 1024).toFixed(1)}KB) \xB7 global: ${globalStats.entries} ${globalArchived}entries (${(globalStats.bytes / 1024).toFixed(1)}KB)`));
|
|
172005
172681
|
console.log();
|
|
172006
|
-
const merged = (0,
|
|
172682
|
+
const merged = (0, import_code_core17.readAllMemory)(workDir, { includeArchived: wantsArchived });
|
|
172007
172683
|
console.log(merged || paint.dim(" No memories saved yet."));
|
|
172008
172684
|
}
|
|
172009
172685
|
console.log();
|
|
@@ -172038,12 +172714,12 @@ ${dirList}`;
|
|
|
172038
172714
|
console.log(paint.dim(` Current: ${paint.cyan(agentMode)}`));
|
|
172039
172715
|
for (const m2 of ["ask", "edit", "auto", "plan"]) {
|
|
172040
172716
|
const marker = m2 === agentMode ? paint.cyan("\u276F") : " ";
|
|
172041
|
-
console.log(` ${marker} ${paint.bold(m2.padEnd(5))} ${paint.dim((0,
|
|
172717
|
+
console.log(` ${marker} ${paint.bold(m2.padEnd(5))} ${paint.dim((0, import_code_core19.describeMode)(m2).replace(`${m2} \u2014 `, ""))}`);
|
|
172042
172718
|
}
|
|
172043
172719
|
} else if (["ask", "edit", "plan", "auto"].includes(modeArg)) {
|
|
172044
172720
|
agentMode = modeArg;
|
|
172045
172721
|
updateFooter();
|
|
172046
|
-
console.log(paint.green(` Mode \u2192 ${paint.bold(modeArg)}`) + paint.dim(` ${(0,
|
|
172722
|
+
console.log(paint.green(` Mode \u2192 ${paint.bold(modeArg)}`) + paint.dim(` ${(0, import_code_core19.describeMode)(modeArg).replace(`${modeArg} \u2014 `, "")}`));
|
|
172047
172723
|
} else {
|
|
172048
172724
|
console.log(paint.red(` Unknown: ${modeArg}`));
|
|
172049
172725
|
}
|
|
@@ -172084,22 +172760,22 @@ ${dirList}`;
|
|
|
172084
172760
|
if (target === void 0) {
|
|
172085
172761
|
console.log(paint.red(" Usage: /team use <team id|personal> (/team lists the ids)"));
|
|
172086
172762
|
} else {
|
|
172087
|
-
await (0,
|
|
172763
|
+
await (0, import_code_core17.setBillingTarget)(target);
|
|
172088
172764
|
console.log(paint.green(` \u2713 Usage will now be billed to ${target === null ? "your personal wallet" : `team ${target}`}.`));
|
|
172089
172765
|
if (target !== null)
|
|
172090
172766
|
console.log(paint.dim(" This applies to every product and client on this account, not just the CLI."));
|
|
172091
172767
|
}
|
|
172092
172768
|
} else {
|
|
172093
172769
|
try {
|
|
172094
|
-
const orgs = await (0,
|
|
172095
|
-
const pin = (0,
|
|
172770
|
+
const orgs = await (0, import_code_core17.getOrgs)();
|
|
172771
|
+
const pin = (0, import_code_core17.billingOverrideFields)();
|
|
172096
172772
|
for (const l2 of billingLines(orgs, "teamId" in pin ? pin.teamId : void 0)) {
|
|
172097
172773
|
console.log(l2.startsWith("!") ? paint.yellow(" " + l2) : " " + l2);
|
|
172098
172774
|
}
|
|
172099
172775
|
} catch (orgErr) {
|
|
172100
172776
|
if (cmd === "/team")
|
|
172101
172777
|
throw orgErr;
|
|
172102
|
-
const bal = await (0,
|
|
172778
|
+
const bal = await (0, import_code_core17.getBalance)();
|
|
172103
172779
|
console.log(paint.dim(" Balance: ") + paint.cyan(`$${bal.toFixed(4)}`));
|
|
172104
172780
|
}
|
|
172105
172781
|
}
|
|
@@ -172493,7 +173169,7 @@ ${dirList}`;
|
|
|
172493
173169
|
}
|
|
172494
173170
|
agentMode = "plan";
|
|
172495
173171
|
updateFooter();
|
|
172496
|
-
console.log(paint.green(` Mode \u2192 ${paint.bold("plan")}`) + paint.dim(` ${(0,
|
|
173172
|
+
console.log(paint.green(` Mode \u2192 ${paint.bold("plan")}`) + paint.dim(` ${(0, import_code_core19.describeMode)("plan").replace("plan \u2014 ", "")} (/mode auto to leave)`));
|
|
172497
173173
|
rl.prompt();
|
|
172498
173174
|
return;
|
|
172499
173175
|
}
|
|
@@ -172501,7 +173177,7 @@ ${dirList}`;
|
|
|
172501
173177
|
const parts2 = arg.trim().split(/\s+/).filter(Boolean);
|
|
172502
173178
|
const scope = parts2.includes("--project") ? "project" : "user";
|
|
172503
173179
|
const want = (parts2.find((x2) => x2 !== "--project") ?? "").toLowerCase();
|
|
172504
|
-
const customColorsNow = () => readThemeConfig((0,
|
|
173180
|
+
const customColorsNow = () => readThemeConfig((0, import_code_core19.loadSettings)(workDir).raw).custom;
|
|
172505
173181
|
const switchTheme = (name, persist) => {
|
|
172506
173182
|
const out = applyThemeConfig({ theme: name, custom: name === "custom" ? customColorsNow() : {}, errors: [] });
|
|
172507
173183
|
activeThemeName = name;
|
|
@@ -172519,7 +173195,7 @@ ${dirList}`;
|
|
|
172519
173195
|
const w = clearThemeKeys(workDir, scope);
|
|
172520
173196
|
if (!w.ok)
|
|
172521
173197
|
console.log(paint.yellow(` Could not write ${w.path}: ${w.error}`));
|
|
172522
|
-
const after = readThemeConfig((0,
|
|
173198
|
+
const after = readThemeConfig((0, import_code_core19.loadSettings)(workDir).raw);
|
|
172523
173199
|
const out = applyThemeConfig(after);
|
|
172524
173200
|
activeThemeName = after.theme;
|
|
172525
173201
|
console.log(" " + paint.green(`Theme reset: ${out.resolved}`) + paint.dim(` \xB7 removed theme/themeColors from ${settingsPath(workDir, scope)}`));
|
|
@@ -172610,7 +173286,7 @@ ${dirList}`;
|
|
|
172610
173286
|
}
|
|
172611
173287
|
const types3 = (() => {
|
|
172612
173288
|
try {
|
|
172613
|
-
return (0,
|
|
173289
|
+
return (0, import_code_core17.loadAgentTypesWithWarnings)(workDir).types.map((t2) => ({
|
|
172614
173290
|
name: t2.name,
|
|
172615
173291
|
description: t2.description,
|
|
172616
173292
|
...t2.tools ? { tools: t2.tools } : {},
|
|
@@ -172623,7 +173299,7 @@ ${dirList}`;
|
|
|
172623
173299
|
for (const l2 of formatPermissions({
|
|
172624
173300
|
rules: permRules,
|
|
172625
173301
|
workDir,
|
|
172626
|
-
mode: (0,
|
|
173302
|
+
mode: (0, import_code_core19.parseMode)(agentMode),
|
|
172627
173303
|
yolo: isYoloMode(),
|
|
172628
173304
|
agents: types3,
|
|
172629
173305
|
// The guard the dashboard describes is the one the handler actually runs, so the
|
|
@@ -172828,7 +173504,7 @@ ${caption}` : `[Attached: ${rel}]`;
|
|
|
172828
173504
|
if (needsSidecar) {
|
|
172829
173505
|
console.log(paint.dim(` ${resolveModelLabel(modelAlias)} can't read ${isPdf ? "PDFs" : "images"} directly \u2014 describing ${rel} with Claude Sonnet 5.5 first\u2026`));
|
|
172830
173506
|
try {
|
|
172831
|
-
const { text } = await (0,
|
|
173507
|
+
const { text } = await (0, import_code_core17.describeAttachment)(isPdf ? "pdf" : "image", data, mimeType, rel);
|
|
172832
173508
|
content.push({ type: "text", text: `<attachment_description>
|
|
172833
173509
|
${text}
|
|
172834
173510
|
</attachment_description>` });
|
|
@@ -172872,7 +173548,7 @@ ${text}
|
|
|
172872
173548
|
process.exit(0);
|
|
172873
173549
|
}
|
|
172874
173550
|
case "/plugins": {
|
|
172875
|
-
const plugins = (0,
|
|
173551
|
+
const plugins = (0, import_code_core17.loadPlugins)(workDir);
|
|
172876
173552
|
if (!plugins.length) {
|
|
172877
173553
|
console.log(paint.dim(" No plugins installed. Install one: nex plugin install owner/repo"));
|
|
172878
173554
|
} else {
|
|
@@ -172885,7 +173561,7 @@ ${text}
|
|
|
172885
173561
|
}
|
|
172886
173562
|
console.log();
|
|
172887
173563
|
}
|
|
172888
|
-
skills = (0,
|
|
173564
|
+
skills = (0, import_code_core17.loadSkills)(workDir);
|
|
172889
173565
|
syncSlashMenu();
|
|
172890
173566
|
rl.prompt();
|
|
172891
173567
|
return;
|
|
@@ -173076,7 +173752,7 @@ ${text}
|
|
|
173076
173752
|
return;
|
|
173077
173753
|
}
|
|
173078
173754
|
case "/handoff": {
|
|
173079
|
-
const types3 = (0,
|
|
173755
|
+
const types3 = (0, import_code_core17.loadAgentTypesWithWarnings)(workDir).types.map((t2) => t2.name);
|
|
173080
173756
|
const parsed = parseHandoffArgs(arg, types3);
|
|
173081
173757
|
if ("error" in parsed) {
|
|
173082
173758
|
console.log(paint.red(" " + parsed.error));
|
|
@@ -173109,8 +173785,8 @@ ${text}
|
|
|
173109
173785
|
return;
|
|
173110
173786
|
}
|
|
173111
173787
|
const measure = measureContext(messages, parsed.all ? TOP_ALL : TOP_DEFAULT);
|
|
173112
|
-
const window2 = (0,
|
|
173113
|
-
const thresholds = (0,
|
|
173788
|
+
const window2 = (0, import_code_core17.contextWindowFor)(modelAlias);
|
|
173789
|
+
const thresholds = (0, import_code_core17.compactionThresholds)(window2);
|
|
173114
173790
|
for (const line of formatContextPanel({
|
|
173115
173791
|
measure,
|
|
173116
173792
|
window: window2,
|
|
@@ -173127,9 +173803,9 @@ ${text}
|
|
|
173127
173803
|
}
|
|
173128
173804
|
case "/skills":
|
|
173129
173805
|
case "/commands": {
|
|
173130
|
-
skills = (0,
|
|
173806
|
+
skills = (0, import_code_core17.loadSkills)(workDir);
|
|
173131
173807
|
syncSlashMenu();
|
|
173132
|
-
const invocable = (0,
|
|
173808
|
+
const invocable = (0, import_code_core17.userInvokableSkills)(skills);
|
|
173133
173809
|
if (!invocable.length) {
|
|
173134
173810
|
console.log(paint.dim(" No skills. Add .nexrall/skills/<name>/SKILL.md (or .nexrall/commands/<name>.md) to create one."));
|
|
173135
173811
|
} else {
|
|
@@ -173305,15 +173981,15 @@ ${text}
|
|
|
173305
173981
|
return;
|
|
173306
173982
|
}
|
|
173307
173983
|
default: {
|
|
173308
|
-
const custom = (0,
|
|
173984
|
+
const custom = (0, import_code_core17.findSkill)(skills, cmd);
|
|
173309
173985
|
if (!custom) {
|
|
173310
173986
|
console.log(paint.red(` Unknown command: ${cmd}`));
|
|
173311
173987
|
console.log(paint.dim(" Type /help for built-ins or /skills for custom ones."));
|
|
173312
173988
|
rl.prompt();
|
|
173313
173989
|
return;
|
|
173314
173990
|
}
|
|
173315
|
-
const expanded = (0,
|
|
173316
|
-
const turnModel = (0,
|
|
173991
|
+
const expanded = (0, import_code_core17.expandSkill)(custom, arg, workDir);
|
|
173992
|
+
const turnModel = (0, import_code_core17.resolveSubAgentModel)(custom.model, modelAlias) ?? modelAlias;
|
|
173317
173993
|
const turnMode = modeLocked ? "plan" : custom.mode ?? agentMode;
|
|
173318
173994
|
console.log(paint.dim(` Running /${custom.name}\u2026`));
|
|
173319
173995
|
checkpoints.beginTurn(`/${custom.name} ${arg}`.trim(), messages.length);
|
|
@@ -173348,7 +174024,7 @@ ${text}
|
|
|
173348
174024
|
}
|
|
173349
174025
|
checkpoints.beginTurn(userInput, messages.length);
|
|
173350
174026
|
const mentions = expandMentions(userInput, workDir, {
|
|
173351
|
-
isDenied: (abs) => (0,
|
|
174027
|
+
isDenied: (abs) => (0, import_code_core19.evaluatePermission)(permRules, "read_file", { path: abs }, workDir) === "deny"
|
|
173352
174028
|
});
|
|
173353
174029
|
for (const a of mentions.attachments) {
|
|
173354
174030
|
console.log(paint.dim(` + ${a.kind === "dir" ? a.rel + "/" : a.rel} (${a.lines} ${a.kind === "dir" ? "entries" : "lines"}${a.truncated ? ", truncated" : ""})`));
|
|
@@ -173389,7 +174065,7 @@ ${text}
|
|
|
173389
174065
|
const notes = cliBackgroundAgents.takeNotifications();
|
|
173390
174066
|
console.log(paint.dim(` \u2699 background agent${notes.length > 1 ? "s" : ""} ${notes.map((n) => `"${n.description}"`).join(", ")} finished \u2014 continuing`));
|
|
173391
174067
|
notifier.notify(bgAgentNote(notes.map((n) => n.description)));
|
|
173392
|
-
rl.emit("line", (0,
|
|
174068
|
+
rl.emit("line", (0, import_code_core17.formatBackgroundNotifications)(notes));
|
|
173393
174069
|
}, 400);
|
|
173394
174070
|
}
|
|
173395
174071
|
cliBackgroundAgents.onChange(() => {
|
|
@@ -173400,6 +174076,7 @@ ${text}
|
|
|
173400
174076
|
deliverBackgroundWhenIdle();
|
|
173401
174077
|
});
|
|
173402
174078
|
rl.on("close", () => {
|
|
174079
|
+
fileWatcher?.stop();
|
|
173403
174080
|
updateTitle();
|
|
173404
174081
|
if (messages.length)
|
|
173405
174082
|
saveSession2(sessionId, sessionTitle || "Untitled", workDir, messages);
|
|
@@ -173410,7 +174087,7 @@ ${text}
|
|
|
173410
174087
|
|
|
173411
174088
|
// src/commands/plugin.ts
|
|
173412
174089
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
173413
|
-
var
|
|
174090
|
+
var import_code_core20 = __toESM(require_dist3(), 1);
|
|
173414
174091
|
function describeInspection(i2, name, ctx) {
|
|
173415
174092
|
console.log();
|
|
173416
174093
|
console.log(paint.bold(` Plugin: ${name}`) + (i2.meta.version ? paint.dim(` v${i2.meta.version}`) : ""));
|
|
@@ -173486,14 +174163,14 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
173486
174163
|
let registryName;
|
|
173487
174164
|
const isShortName = /^[\w.-]+$/.test(spec.trim()) && !spec.includes("/");
|
|
173488
174165
|
if (isShortName) {
|
|
173489
|
-
const alias = (0,
|
|
174166
|
+
const alias = (0, import_code_core20.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
|
|
173490
174167
|
if (alias) {
|
|
173491
174168
|
source2 = alias.spec;
|
|
173492
174169
|
console.log(paint.dim(` Source: ${alias.name} (${alias.tier}) \u2190 ${alias.spec}`));
|
|
173493
174170
|
}
|
|
173494
174171
|
}
|
|
173495
174172
|
if (isShortName && source2 === spec) {
|
|
173496
|
-
const entry = await (0,
|
|
174173
|
+
const entry = await (0, import_code_core20.getRegistryPlugin)(spec.trim()).catch(() => null);
|
|
173497
174174
|
if (entry) {
|
|
173498
174175
|
source2 = entry.source;
|
|
173499
174176
|
registryName = entry.name;
|
|
@@ -173508,7 +174185,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
173508
174185
|
return;
|
|
173509
174186
|
}
|
|
173510
174187
|
}
|
|
173511
|
-
const res = await (0,
|
|
174188
|
+
const res = await (0, import_code_core20.installPlugin)(source2, {
|
|
173512
174189
|
scope,
|
|
173513
174190
|
workDir: process.cwd(),
|
|
173514
174191
|
name: opts.name ?? registryName,
|
|
@@ -173516,7 +174193,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
173516
174193
|
confirm: (i2, name, ctx) => confirmInstall(i2, name, opts.yes === true, ctx)
|
|
173517
174194
|
});
|
|
173518
174195
|
if (registryName)
|
|
173519
|
-
(0,
|
|
174196
|
+
(0, import_code_core20.reportInstall)(registryName);
|
|
173520
174197
|
console.log();
|
|
173521
174198
|
console.log(paint.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`) + (res.sha ? paint.dim(` @ ${res.sha.slice(0, 7)}`) : ""));
|
|
173522
174199
|
if (res.inspection.commands.length) {
|
|
@@ -173530,7 +174207,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
173530
174207
|
}
|
|
173531
174208
|
function pluginRemoveCommand(name, opts) {
|
|
173532
174209
|
try {
|
|
173533
|
-
const dir = (0,
|
|
174210
|
+
const dir = (0, import_code_core20.removePlugin)(name, {
|
|
173534
174211
|
scope: opts.project ? "project" : void 0,
|
|
173535
174212
|
// no flag → search both scopes
|
|
173536
174213
|
workDir: process.cwd()
|
|
@@ -173543,14 +174220,14 @@ function pluginRemoveCommand(name, opts) {
|
|
|
173543
174220
|
}
|
|
173544
174221
|
async function pluginUpdateCommand(name, opts) {
|
|
173545
174222
|
const workDir = process.cwd();
|
|
173546
|
-
const targets = name ? [name] : (0,
|
|
174223
|
+
const targets = name ? [name] : (0, import_code_core20.loadPlugins)(workDir).filter((p) => (0, import_code_core20.readReceipt)(p.dir)?.kind === "github").map((p) => p.name);
|
|
173547
174224
|
if (!targets.length) {
|
|
173548
174225
|
console.log(paint.dim(" No updatable plugins (only GitHub-installed plugins with receipts can update)."));
|
|
173549
174226
|
return;
|
|
173550
174227
|
}
|
|
173551
174228
|
for (const t2 of targets) {
|
|
173552
174229
|
try {
|
|
173553
|
-
const res = await (0,
|
|
174230
|
+
const res = await (0, import_code_core20.updatePlugin)(t2, {
|
|
173554
174231
|
workDir,
|
|
173555
174232
|
confirm: (i2, n, ctx) => confirmInstall(i2, n, opts.yes === true, ctx)
|
|
173556
174233
|
});
|
|
@@ -173567,7 +174244,7 @@ function badgeFor(p) {
|
|
|
173567
174244
|
}
|
|
173568
174245
|
async function pluginSearchCommand(query) {
|
|
173569
174246
|
try {
|
|
173570
|
-
const results = await (0,
|
|
174247
|
+
const results = await (0, import_code_core20.searchRegistry)(query);
|
|
173571
174248
|
if (!results.length) {
|
|
173572
174249
|
console.log(paint.dim(query ? ` No plugins matching "${query}".` : " Registry is empty."));
|
|
173573
174250
|
return;
|
|
@@ -173590,7 +174267,7 @@ async function pluginSearchCommand(query) {
|
|
|
173590
174267
|
}
|
|
173591
174268
|
async function pluginInfoCommand(name) {
|
|
173592
174269
|
try {
|
|
173593
|
-
const p = await (0,
|
|
174270
|
+
const p = await (0, import_code_core20.getRegistryPlugin)(name);
|
|
173594
174271
|
if (!p) {
|
|
173595
174272
|
console.error(paint.red(` \u2717 "${name}" not found in the registry.`));
|
|
173596
174273
|
process.exitCode = 1;
|
|
@@ -173626,7 +174303,7 @@ async function pluginInfoCommand(name) {
|
|
|
173626
174303
|
}
|
|
173627
174304
|
}
|
|
173628
174305
|
function pluginListCommand() {
|
|
173629
|
-
const plugins = (0,
|
|
174306
|
+
const plugins = (0, import_code_core20.loadPlugins)(process.cwd());
|
|
173630
174307
|
if (!plugins.length) {
|
|
173631
174308
|
console.log(paint.dim(" No plugins installed."));
|
|
173632
174309
|
console.log(paint.dim(" Install one: nex plugin install owner/repo"));
|
|
@@ -173635,10 +174312,10 @@ function pluginListCommand() {
|
|
|
173635
174312
|
console.log();
|
|
173636
174313
|
console.log(paint.bold(" Installed plugins:"));
|
|
173637
174314
|
for (const p of plugins) {
|
|
173638
|
-
const receipt = (0,
|
|
174315
|
+
const receipt = (0, import_code_core20.readReceipt)(p.dir);
|
|
173639
174316
|
const src = receipt ? paint.dim(` \u2190 ${receipt.source}`) : paint.dim(" (manual)");
|
|
173640
174317
|
const at = receipt?.sha ? paint.dim(` @ ${receipt.sha.slice(0, 7)}`) : "";
|
|
173641
|
-
const insp = (0,
|
|
174318
|
+
const insp = (0, import_code_core20.inspectPluginDir)(p.dir);
|
|
173642
174319
|
const runs2 = insp.hasHooks || insp.hasMcp ? paint.yellow(` \u26A0 ${[insp.hasHooks && "hooks", insp.hasMcp && "mcp"].filter(Boolean).join("+")}`) : "";
|
|
173643
174320
|
console.log(
|
|
173644
174321
|
" " + paint.cyan(p.name.padEnd(24)) + paint.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src + at + runs2
|
|
@@ -173648,8 +174325,8 @@ function pluginListCommand() {
|
|
|
173648
174325
|
}
|
|
173649
174326
|
function pluginSourceListCommand() {
|
|
173650
174327
|
const workDir = process.cwd();
|
|
173651
|
-
const sources = (0,
|
|
173652
|
-
const patterns = (0,
|
|
174328
|
+
const sources = (0, import_code_core20.loadDeclaredSources)(workDir, { includeProject: true });
|
|
174329
|
+
const patterns = (0, import_code_core20.allowedSourcePatterns)();
|
|
173653
174330
|
if (patterns) {
|
|
173654
174331
|
console.log();
|
|
173655
174332
|
console.log(paint.bold(" Organisation policy: ") + paint.dim(`installs restricted to ${patterns.join(", ")}`));
|
|
@@ -173664,7 +174341,7 @@ function pluginSourceListCommand() {
|
|
|
173664
174341
|
console.log(paint.bold(" Declared plugin sources:"));
|
|
173665
174342
|
for (const s2 of sources) {
|
|
173666
174343
|
const tier2 = s2.tier === "project" ? paint.yellow(s2.tier.padEnd(9)) : paint.dim(s2.tier.padEnd(9));
|
|
173667
|
-
const blocked = !(0,
|
|
174344
|
+
const blocked = !(0, import_code_core20.isSourceAllowed)(s2.spec, patterns) ? paint.red(" \u2717 blocked by policy") : "";
|
|
173668
174345
|
console.log(" " + paint.cyan(s2.name.padEnd(20)) + tier2 + paint.white(s2.spec) + blocked);
|
|
173669
174346
|
}
|
|
173670
174347
|
console.log();
|
|
@@ -173674,17 +174351,17 @@ function pluginSourceListCommand() {
|
|
|
173674
174351
|
}
|
|
173675
174352
|
function pluginSourceAddCommand(name, spec, opts) {
|
|
173676
174353
|
try {
|
|
173677
|
-
(0,
|
|
173678
|
-
const patterns = (0,
|
|
173679
|
-
if (patterns && !(0,
|
|
174354
|
+
(0, import_code_core20.parsePluginSource)(spec);
|
|
174355
|
+
const patterns = (0, import_code_core20.allowedSourcePatterns)();
|
|
174356
|
+
if (patterns && !(0, import_code_core20.isSourceAllowed)(spec, patterns)) {
|
|
173680
174357
|
console.error(paint.red(` \u2717 "${spec}" is not permitted by your organisation's policy.`));
|
|
173681
174358
|
console.error(paint.dim(` Allowed: ${patterns.join(", ")}`));
|
|
173682
174359
|
process.exitCode = 1;
|
|
173683
174360
|
return;
|
|
173684
174361
|
}
|
|
173685
174362
|
const scope = opts.project ? "project" : "user";
|
|
173686
|
-
const file = (0,
|
|
173687
|
-
(0,
|
|
174363
|
+
const file = (0, import_code_core20.sourcesFileFor)(scope, process.cwd());
|
|
174364
|
+
(0, import_code_core20.writeDeclaredSource)(file, name, spec);
|
|
173688
174365
|
console.log();
|
|
173689
174366
|
console.log(paint.green(` \u2713 Declared "${name}" \u2192 ${spec}`) + paint.dim(` (${scope})`));
|
|
173690
174367
|
console.log(paint.dim(` ${file}`));
|
|
@@ -173698,13 +174375,13 @@ function pluginSourceAddCommand(name, spec, opts) {
|
|
|
173698
174375
|
function pluginSourceRemoveCommand(name, opts) {
|
|
173699
174376
|
const workDir = process.cwd();
|
|
173700
174377
|
const scope = opts.project ? "project" : "user";
|
|
173701
|
-
const file = (0,
|
|
173702
|
-
if ((0,
|
|
174378
|
+
const file = (0, import_code_core20.sourcesFileFor)(scope, workDir);
|
|
174379
|
+
if ((0, import_code_core20.removeDeclaredSource)(file, name)) {
|
|
173703
174380
|
console.log(paint.green(` \u2713 Removed source "${name}" (${scope})`));
|
|
173704
174381
|
console.log(paint.dim(" Plugins already installed from it are untouched \u2014 remove them with nex plugin remove <name>"));
|
|
173705
174382
|
return;
|
|
173706
174383
|
}
|
|
173707
|
-
const found = (0,
|
|
174384
|
+
const found = (0, import_code_core20.resolveSourceAlias)(name, workDir, { includeProject: true });
|
|
173708
174385
|
if (found) {
|
|
173709
174386
|
console.error(paint.red(` \u2717 "${name}" is declared in the ${found.tier} tier, not ${scope}.`));
|
|
173710
174387
|
console.error(paint.dim(` ${found.file}`));
|
|
@@ -173719,7 +174396,7 @@ function pluginSourceRemoveCommand(name, opts) {
|
|
|
173719
174396
|
}
|
|
173720
174397
|
|
|
173721
174398
|
// src/index.ts
|
|
173722
|
-
var
|
|
174399
|
+
var import_code_core22 = __toESM(require_dist3(), 1);
|
|
173723
174400
|
|
|
173724
174401
|
// src/commands/bgJobs.ts
|
|
173725
174402
|
import * as fs26 from "node:fs";
|
|
@@ -173948,7 +174625,7 @@ var program2 = new Command();
|
|
|
173948
174625
|
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version(NEX_VERSION).enablePositionalOptions();
|
|
173949
174626
|
var auth = program2.command("auth").description("Login to your Nexrall account").action(authCommand);
|
|
173950
174627
|
auth.command("status").description("Show whether you are logged in (exit 0 = yes, 1 = no). --json for scripts; the token is never printed").option("--json", "Machine-readable output").action((opts) => {
|
|
173951
|
-
const r2 = authStatusReport((0,
|
|
174628
|
+
const r2 = authStatusReport((0, import_code_core22.loadAuth)(), process.env);
|
|
173952
174629
|
if (opts.json)
|
|
173953
174630
|
console.log(JSON.stringify(r2));
|
|
173954
174631
|
else if (!r2.loggedIn)
|
|
@@ -174194,8 +174871,8 @@ program2.command("sessions").description("List, export, import, or delete saved
|
|
|
174194
174871
|
console.log(paint.dim(" nex sessions --events <id> [--json] to follow its event stream"));
|
|
174195
174872
|
console.log();
|
|
174196
174873
|
});
|
|
174197
|
-
program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, --turbo", "Use Claude Sonnet 5.5 (fast)").option("-u, --ultra", "Use Claude Fable 5.1 (most powerful)").option("-y, --yolo", "Auto-approve all tool calls (no permission prompts)").option("-d, --dir <path>", "Set working directory (default: current directory)").option("-m, --model <name>", "Explicit model, e.g. claude-opus-5-5 | gpt-5.4 | gpt-4.1").option("-r, --resume [id]", "Resume last session, or a specific session id").option("-c, --continue", "Continue the latest conversation in this folder").option("--plan", "Start in plan mode (read-only; /mode or Shift+Tab can leave it)").option("--readonly", "Read-only for the whole session: plan mode that cannot be switched off").option("--auto", "Start in auto mode (the default \u2014 edits and commands run without asking)").option("--mode <mode>", "Starting permission mode: ask | edit | auto | plan").option("--fullscreen", "Draw the whole session on the terminal's alternate screen: the transcript re-wraps on resize and PgUp/PgDn page through it (no terminal scrollback while it is on; /fullscreen toggles it)").option("--bg", "Run the prompt in the background (headless); returns a job id. See: nex jobs | logs | attach | kill").option("--debug", "Write request timing, retries and errors to a debug log file").option("--no-color", "Disable colored output (also honours NO_COLOR)").option("-w, --worktree [name]", "Isolate this session in its own worktree \u2014 a separate directory (and, in a git repo, its own branch) so it can never overwrite files another session (or you) are touching in the main checkout. Omit a name for an auto-generated one; pass an existing name to resume that same worktree.").option("-e, --effort <level>", "Thinking effort \u2014 real levels depend on the model (e.g. DeepSeek: low|high|max, Qwen: low|high); run `nex --model <id>` then `/effort` with no argument to see a model's scale").option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option("--audit [path]", "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)").option("--permission-mode <mode>", "Permission mode: ask | edit | auto | plan (also Claude Code names: default | acceptEdits | bypassPermissions). With --output-format, anything that would prompt is DENIED instead of auto-approved").option("--allowedTools, --allowed-tools <tools...>", 'Tools/rules to allow without asking, e.g. "Bash(git *)" Edit (comma or space separated; put the prompt BEFORE this flag)').option("--disallowedTools, --disallowed-tools <tools...>", 'Tools/rules to deny, e.g. "Bash(rm *)" (deny always wins)').option("--append-system-prompt <text>", "Extra instructions appended to the project brief for this run").option("--max-budget-usd <amount>", "Stop a one-shot run once it has spent this many dollars (needs --output-format)").option("--mcp-config <configs...>", 'Load MCP servers from JSON files or inline JSON ({"mcpServers":{\u2026}}) for this run').option("--strict-mcp-config", "With --mcp-config: use ONLY those servers, ignoring ~/.nexrall/mcp.json and the project one").option("--add-dir <dirs...>", "Extra directories the agent may read and edit besides the project folder").option("--input-format <format>", "text (default) | stream-json \u2014 read the prompt as Claude-Code-style NDJSON user messages on stdin").option("--json-schema <schema>", 'JSON Schema (inline or file) the final answer must satisfy; needs --output-format. Result gains "structured_output"; exit 3 if it does not validate').option("--no-session-persistence", "Do not save this run to disk (needs --output-format; it cannot be resumed)").option("--max-turns <n>", "Stop a headless run after N agent rounds (needs --output-format; exit 4 when it hits the limit)").option("--append-system-prompt-file <path>", "Like --append-system-prompt, read from a file").option("--system-prompt <text>", "REPLACE the project brief (nexrall.md + memory + global instructions) with this text for this run").option("--system-prompt-file <path>", "Like --system-prompt, read from a file").option("--verbose", "Print progress detail (tool calls, timings, usage) to stderr while a one-shot run works").option("--include-partial-messages", "Stream model deltas as they arrive (needs --output-format stream-json)").option("--replay-user-messages", "Echo each stdin message back on stdout as it is consumed (needs --input-format stream-json --output-format stream-json)").option("--agents <json-or-file>", 'Define extra sub-agents for this run: a JSON object { "name": { "description", "prompt", "tools", "model" } } or @file.json').option("--agent <name>", "Run this session AS that agent (its prompt, tools and model), from .nexrall/agents, a plugin, --agents or a builtin").option("--bare", "Start without discovery: no nexrall.md/memory, skills, plugins, hooks or MCP config files").option("--safe-mode", "Same as --bare (Claude Code's troubleshooting name)").option("--tools <list>", 'Exactly these built-in tools ("Bash,Read,Edit", "default", or "" for none); the rest are removed, not just unapproved').option("--session-id <id>", "Use this id for a NEW conversation (letters, digits, - _), so a script can find it again").option("-n, --name <name>", "Name the conversation; `nex -r <name>` resumes it by that name").option("--fork-session", "With --resume/--continue: branch into a new session instead of continuing the original").option("--fallback-model <name>", "If the main model is overloaded or unreachable, retry the turn once on this model (needs --output-format)").option("--settings <file|json>", "Settings (permissions, hooks\u2026) for this run only: a JSON file or an inline JSON object; merged over the user/project settings").option("--debug-file <path>", "Write the --debug diagnostics log to this file (implies --debug)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
|
|
174198
|
-
if (!(0,
|
|
174874
|
+
program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, --turbo", "Use Claude Sonnet 5.5 (fast)").option("-u, --ultra", "Use Claude Fable 5.1 (most powerful)").option("-y, --yolo", "Auto-approve all tool calls (no permission prompts)").option("-d, --dir <path>", "Set working directory (default: current directory)").option("-m, --model <name>", "Explicit model, e.g. claude-opus-5-5 | gpt-5.4 | gpt-4.1").option("-r, --resume [id]", "Resume last session, or a specific session id").option("-c, --continue", "Continue the latest conversation in this folder").option("--plan", "Start in plan mode (read-only; /mode or Shift+Tab can leave it)").option("--readonly", "Read-only for the whole session: plan mode that cannot be switched off").option("--auto", "Start in auto mode (the default \u2014 edits and commands run without asking)").option("--mode <mode>", "Starting permission mode: ask | edit | auto | plan").option("--fullscreen", "Draw the whole session on the terminal's alternate screen: the transcript re-wraps on resize and PgUp/PgDn page through it (no terminal scrollback while it is on; /fullscreen toggles it)").option("--bg", "Run the prompt in the background (headless); returns a job id. See: nex jobs | logs | attach | kill").option("--debug", "Write request timing, retries and errors to a debug log file").option("--no-color", "Disable colored output (also honours NO_COLOR)").option("-w, --worktree [name]", "Isolate this session in its own worktree \u2014 a separate directory (and, in a git repo, its own branch) so it can never overwrite files another session (or you) are touching in the main checkout. Omit a name for an auto-generated one; pass an existing name to resume that same worktree.").option("-e, --effort <level>", "Thinking effort \u2014 real levels depend on the model (e.g. DeepSeek: low|high|max, Qwen: low|high); run `nex --model <id>` then `/effort` with no argument to see a model's scale").option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option("--audit [path]", "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)").option("--permission-mode <mode>", "Permission mode: ask | edit | auto | plan (also Claude Code names: default | acceptEdits | bypassPermissions). With --output-format, anything that would prompt is DENIED instead of auto-approved").option("--allowedTools, --allowed-tools <tools...>", 'Tools/rules to allow without asking, e.g. "Bash(git *)" Edit (comma or space separated; put the prompt BEFORE this flag)').option("--disallowedTools, --disallowed-tools <tools...>", 'Tools/rules to deny, e.g. "Bash(rm *)" (deny always wins)').option("--append-system-prompt <text>", "Extra instructions appended to the project brief for this run").option("--max-budget-usd <amount>", "Stop a one-shot run once it has spent this many dollars (needs --output-format)").option("--mcp-config <configs...>", 'Load MCP servers from JSON files or inline JSON ({"mcpServers":{\u2026}}) for this run').option("--strict-mcp-config", "With --mcp-config: use ONLY those servers, ignoring ~/.nexrall/mcp.json and the project one").option("--add-dir <dirs...>", "Extra directories the agent may read and edit besides the project folder").option("--input-format <format>", "text (default) | stream-json \u2014 read the prompt as Claude-Code-style NDJSON user messages on stdin").option("--json-schema <schema>", 'JSON Schema (inline or file) the final answer must satisfy; needs --output-format. Result gains "structured_output"; exit 3 if it does not validate').option("--no-session-persistence", "Do not save this run to disk (needs --output-format; it cannot be resumed)").option("--max-turns <n>", "Stop a headless run after N agent rounds (needs --output-format; exit 4 when it hits the limit)").option("--permission-prompt-tool <t>", "MCP tool (mcp__server__tool) that answers permission prompts in non-interactive runs \u2014 instead of nex denying them").option("--append-system-prompt-file <path>", "Like --append-system-prompt, read from a file").option("--system-prompt <text>", "REPLACE the project brief (nexrall.md + memory + global instructions) with this text for this run").option("--system-prompt-file <path>", "Like --system-prompt, read from a file").option("--verbose", "Print progress detail (tool calls, timings, usage) to stderr while a one-shot run works").option("--include-partial-messages", "Stream model deltas as they arrive (needs --output-format stream-json)").option("--replay-user-messages", "Echo each stdin message back on stdout as it is consumed (needs --input-format stream-json --output-format stream-json)").option("--agents <json-or-file>", 'Define extra sub-agents for this run: a JSON object { "name": { "description", "prompt", "tools", "model" } } or @file.json').option("--agent <name>", "Run this session AS that agent (its prompt, tools and model), from .nexrall/agents, a plugin, --agents or a builtin").option("--bare", "Start without discovery: no nexrall.md/memory, skills, plugins, hooks or MCP config files").option("--safe-mode", "Same as --bare (Claude Code's troubleshooting name)").option("--tools <list>", 'Exactly these built-in tools ("Bash,Read,Edit", "default", or "" for none); the rest are removed, not just unapproved').option("--session-id <id>", "Use this id for a NEW conversation (letters, digits, - _), so a script can find it again").option("-n, --name <name>", "Name the conversation; `nex -r <name>` resumes it by that name").option("--fork-session", "With --resume/--continue: branch into a new session instead of continuing the original").option("--fallback-model <name>", "If the main model is overloaded or unreachable, retry the turn once on this model (needs --output-format)").option("--settings <file|json>", "Settings (permissions, hooks\u2026) for this run only: a JSON file or an inline JSON object; merged over the user/project settings").option("--debug-file <path>", "Write the --debug diagnostics log to this file (implies --debug)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
|
|
174875
|
+
if (!(0, import_code_core21.isAuthenticated)()) {
|
|
174199
174876
|
console.error("Not logged in. Run: nex auth");
|
|
174200
174877
|
process.exit(1);
|
|
174201
174878
|
}
|
|
@@ -174261,11 +174938,11 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
|
|
|
174261
174938
|
console.error(st.error);
|
|
174262
174939
|
process.exit(1);
|
|
174263
174940
|
}
|
|
174264
|
-
(0,
|
|
174941
|
+
(0, import_code_core22.setSessionSettings)(st.value);
|
|
174265
174942
|
}
|
|
174266
174943
|
const allowRules = parseToolList(options.allowedTools);
|
|
174267
174944
|
const denyRules = parseToolList(options.disallowedTools);
|
|
174268
|
-
(0,
|
|
174945
|
+
(0, import_code_core22.setSessionRules)({ allow: allowRules, deny: denyRules });
|
|
174269
174946
|
let budgetUsd;
|
|
174270
174947
|
if (options.maxBudgetUsd !== void 0) {
|
|
174271
174948
|
const b = parseBudget(options.maxBudgetUsd);
|
|
@@ -174286,7 +174963,16 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
|
|
|
174286
174963
|
}
|
|
174287
174964
|
maxTurns = t2.value;
|
|
174288
174965
|
}
|
|
174289
|
-
|
|
174966
|
+
let permissionPromptTool;
|
|
174967
|
+
if (options.permissionPromptTool !== void 0) {
|
|
174968
|
+
const t2 = normalizePermissionPromptTool(options.permissionPromptTool);
|
|
174969
|
+
if (!t2.ok) {
|
|
174970
|
+
console.error(t2.error);
|
|
174971
|
+
process.exit(1);
|
|
174972
|
+
}
|
|
174973
|
+
permissionPromptTool = t2.value;
|
|
174974
|
+
}
|
|
174975
|
+
const headlessErr = checkHeadlessOnly({ outputFormat: options.outputFormat, budget: budgetUsd, noSessionPersistence: options.sessionPersistence === false, maxTurns, permissionPromptTool });
|
|
174290
174976
|
if (headlessErr) {
|
|
174291
174977
|
console.error(headlessErr);
|
|
174292
174978
|
process.exit(1);
|
|
@@ -174310,8 +174996,8 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
|
|
|
174310
174996
|
}
|
|
174311
174997
|
let selectedAgent;
|
|
174312
174998
|
if (options.agent) {
|
|
174313
|
-
const catalogue = (0,
|
|
174314
|
-
selectedAgent = (0,
|
|
174999
|
+
const catalogue = (0, import_code_core22.loadAgentTypesWithWarnings)(process.cwd(), extraTypes).types;
|
|
175000
|
+
selectedAgent = (0, import_code_core22.findAgentType)(catalogue, String(options.agent));
|
|
174315
175001
|
if (!selectedAgent) {
|
|
174316
175002
|
console.error(`Unknown agent "${options.agent}". Available: ${catalogue.map((t2) => t2.name).join(", ")}`);
|
|
174317
175003
|
process.exit(1);
|
|
@@ -174333,7 +175019,7 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
|
|
|
174333
175019
|
}
|
|
174334
175020
|
let onlyTools;
|
|
174335
175021
|
if (options.tools !== void 0) {
|
|
174336
|
-
const t2 = parseToolsFlag(options.tools === true ? "" : options.tools, (0,
|
|
175022
|
+
const t2 = parseToolsFlag(options.tools === true ? "" : options.tools, (0, import_code_core22.knownToolNames)());
|
|
174337
175023
|
if (!t2.ok) {
|
|
174338
175024
|
console.error(t2.error);
|
|
174339
175025
|
process.exit(1);
|
|
@@ -174475,7 +175161,7 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
|
|
|
174475
175161
|
}
|
|
174476
175162
|
effort = lvl;
|
|
174477
175163
|
}
|
|
174478
|
-
await startChatSession({ model, workDir, prompt: prompt2, resume, continueLast: !!options.continue, initialMode: modeRes.mode, lockMode: modeRes.locked, debug: !!options.debug || debugFile !== void 0, debugFile, fallbackModel, maxTurns, onlyTools, newSessionId, sessionName, forkSession: !!options.forkSession, stdinText, stdinFollowUps, showBanner, outputFormat, effort, audit: options.audit, worktree, fullscreen: !!options.fullscreen, strictPermissions: options.permissionMode !== void 0, budgetUsd, appendSystemPrompt, mcpOverride, strictMcp: !!options.strictMcpConfig, systemPrompt: sysPrompt.value, verbose: !!options.verbose, includePartialMessages: !!options.includePartialMessages, agents: agentsParsed.value, selectedAgent: selectedAgent ? { name: selectedAgent.name, prompt: selectedAgent.prompt, tools: selectedAgent.tools, model: selectedAgent.model } : void 0, replayUserMessages: !!options.replayUserMessages, inputFormatWasStreamJson: options.inputFormat !== void 0 && String(options.inputFormat).toLowerCase() === "stream-json", bare: !!(options.bare || options.safeMode), noSessionPersistence: options.sessionPersistence === false, addDirs: addDirs.value, jsonSchema });
|
|
175164
|
+
await startChatSession({ model, workDir, prompt: prompt2, resume, continueLast: !!options.continue, initialMode: modeRes.mode, lockMode: modeRes.locked, debug: !!options.debug || debugFile !== void 0, debugFile, fallbackModel, maxTurns, onlyTools, newSessionId, sessionName, forkSession: !!options.forkSession, stdinText, stdinFollowUps, showBanner, outputFormat, effort, audit: options.audit, worktree, fullscreen: !!options.fullscreen, strictPermissions: options.permissionMode !== void 0, budgetUsd, appendSystemPrompt, mcpOverride, strictMcp: !!options.strictMcpConfig, systemPrompt: sysPrompt.value, verbose: !!options.verbose, includePartialMessages: !!options.includePartialMessages, agents: agentsParsed.value, selectedAgent: selectedAgent ? { name: selectedAgent.name, prompt: selectedAgent.prompt, tools: selectedAgent.tools, model: selectedAgent.model } : void 0, replayUserMessages: !!options.replayUserMessages, inputFormatWasStreamJson: options.inputFormat !== void 0 && String(options.inputFormat).toLowerCase() === "stream-json", bare: !!(options.bare || options.safeMode), noSessionPersistence: options.sessionPersistence === false, addDirs: addDirs.value, jsonSchema, permissionPromptTool });
|
|
174479
175165
|
});
|
|
174480
175166
|
program2.parse();
|
|
174481
175167
|
/*! Bundled license information:
|