nexrall-code 0.5.55 → 0.5.57
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 +294 -85
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15375,6 +15375,63 @@ var require_rules = __commonJS({
|
|
|
15375
15375
|
}
|
|
15376
15376
|
});
|
|
15377
15377
|
|
|
15378
|
+
// ../core/dist/permissions/bashClassify.js
|
|
15379
|
+
var require_bashClassify = __commonJS({
|
|
15380
|
+
"../core/dist/permissions/bashClassify.js"(exports) {
|
|
15381
|
+
"use strict";
|
|
15382
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15383
|
+
exports.bashNeedsRepoLock = bashNeedsRepoLock;
|
|
15384
|
+
var MUTATING_BASH_VERBS = /* @__PURE__ */ new Set([
|
|
15385
|
+
"git",
|
|
15386
|
+
"npm",
|
|
15387
|
+
"pnpm",
|
|
15388
|
+
"yarn",
|
|
15389
|
+
"bun",
|
|
15390
|
+
"cargo",
|
|
15391
|
+
"go",
|
|
15392
|
+
"pip",
|
|
15393
|
+
"pip3",
|
|
15394
|
+
"poetry",
|
|
15395
|
+
"uv",
|
|
15396
|
+
"bundle",
|
|
15397
|
+
"composer",
|
|
15398
|
+
"gradle",
|
|
15399
|
+
"mvn",
|
|
15400
|
+
"make",
|
|
15401
|
+
"terraform",
|
|
15402
|
+
"helm",
|
|
15403
|
+
"docker",
|
|
15404
|
+
"vsce",
|
|
15405
|
+
"tsc",
|
|
15406
|
+
"pytest",
|
|
15407
|
+
"dotnet",
|
|
15408
|
+
"swift",
|
|
15409
|
+
"gem"
|
|
15410
|
+
]);
|
|
15411
|
+
function bashNeedsRepoLock(command) {
|
|
15412
|
+
if (!command)
|
|
15413
|
+
return false;
|
|
15414
|
+
const segments = command.split(/\|\||&&|[;|&\n()]|\$\(/);
|
|
15415
|
+
for (const seg of segments) {
|
|
15416
|
+
for (const tokenRaw of seg.trim().split(/\s+/)) {
|
|
15417
|
+
const token = tokenRaw.replace(/^["']|["']$/g, "");
|
|
15418
|
+
if (!token)
|
|
15419
|
+
continue;
|
|
15420
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token))
|
|
15421
|
+
continue;
|
|
15422
|
+
if (token === "sudo" || token === "time" || token === "nice" || token === "env")
|
|
15423
|
+
continue;
|
|
15424
|
+
const verb = token.split("/").pop() ?? token;
|
|
15425
|
+
if (MUTATING_BASH_VERBS.has(verb))
|
|
15426
|
+
return true;
|
|
15427
|
+
break;
|
|
15428
|
+
}
|
|
15429
|
+
}
|
|
15430
|
+
return false;
|
|
15431
|
+
}
|
|
15432
|
+
}
|
|
15433
|
+
});
|
|
15434
|
+
|
|
15378
15435
|
// ../core/dist/agent/planMode.js
|
|
15379
15436
|
var require_planMode = __commonJS({
|
|
15380
15437
|
"../core/dist/agent/planMode.js"(exports) {
|
|
@@ -15897,12 +15954,15 @@ var require_loop = __commonJS({
|
|
|
15897
15954
|
};
|
|
15898
15955
|
}();
|
|
15899
15956
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15900
|
-
exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.ToolNotAllowedError = exports.AGENT_MEMORY_TOOL_SCHEMA = exports.AGENT_MEMORY_TOOL = exports._stallLimits = void 0;
|
|
15957
|
+
exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.ToolNotAllowedError = exports.AGENT_MEMORY_TOOL_SCHEMA = exports.AGENT_MEMORY_TOOL = exports._stallLimits = exports.bashNeedsRepoLock = void 0;
|
|
15901
15958
|
exports.errorRoundSignature = errorRoundSignature;
|
|
15902
15959
|
exports.executeAgentMemoryWrite = executeAgentMemoryWrite;
|
|
15903
15960
|
exports.stopReasonNotice = stopReasonNotice;
|
|
15904
15961
|
exports.resolveMaxIterations = resolveMaxIterations;
|
|
15962
|
+
exports.lockPathsFor = lockPathsFor;
|
|
15963
|
+
exports.resolveMaxConcurrentSubtasks = resolveMaxConcurrentSubtasks;
|
|
15905
15964
|
exports.createLimiter = createLimiter;
|
|
15965
|
+
exports._resetSubTaskLimiter = _resetSubTaskLimiter;
|
|
15906
15966
|
exports.resolveSubtaskTimeoutMs = resolveSubtaskTimeoutMs;
|
|
15907
15967
|
exports.extractSubTaskText = extractSubTaskText;
|
|
15908
15968
|
exports.capSubTaskText = capSubTaskText;
|
|
@@ -15928,6 +15988,10 @@ var require_loop = __commonJS({
|
|
|
15928
15988
|
var agentTypes_1 = require_agentTypes();
|
|
15929
15989
|
var skills_1 = require_skills();
|
|
15930
15990
|
var rules_1 = require_rules();
|
|
15991
|
+
var bashClassify_1 = require_bashClassify();
|
|
15992
|
+
Object.defineProperty(exports, "bashNeedsRepoLock", { enumerable: true, get: function() {
|
|
15993
|
+
return bashClassify_1.bashNeedsRepoLock;
|
|
15994
|
+
} });
|
|
15931
15995
|
var planMode_1 = require_planMode();
|
|
15932
15996
|
var agentRegistry_1 = require_agentRegistry();
|
|
15933
15997
|
var sandbox_1 = require_sandbox();
|
|
@@ -16144,10 +16208,41 @@ ${ctx.repeatError}
|
|
|
16144
16208
|
_fileLocks.delete(absPath);
|
|
16145
16209
|
}
|
|
16146
16210
|
}
|
|
16147
|
-
|
|
16148
|
-
const
|
|
16149
|
-
|
|
16150
|
-
|
|
16211
|
+
async function withFileLocks(absPaths, fn) {
|
|
16212
|
+
const unique = [...new Set(absPaths.filter(Boolean))].sort();
|
|
16213
|
+
if (unique.length === 0)
|
|
16214
|
+
return fn();
|
|
16215
|
+
const [first, ...rest] = unique;
|
|
16216
|
+
return withFileLock(first, () => rest.length ? withFileLocks(rest, fn) : fn());
|
|
16217
|
+
}
|
|
16218
|
+
var WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
16219
|
+
"write_file",
|
|
16220
|
+
"edit_file",
|
|
16221
|
+
"multi_edit",
|
|
16222
|
+
"delete_file",
|
|
16223
|
+
"move_file",
|
|
16224
|
+
"copy_file",
|
|
16225
|
+
"notebook_edit"
|
|
16226
|
+
]);
|
|
16227
|
+
var REPO_STATE_LOCK = "\0repo-state";
|
|
16228
|
+
function lockPathsFor(name, input, workDir) {
|
|
16229
|
+
if (!WRITE_TOOLS.has(name))
|
|
16230
|
+
return [];
|
|
16231
|
+
const raw = [input.path, input.source, input.destination, input.dest].filter((p) => typeof p === "string" && p.length > 0);
|
|
16232
|
+
const abs = raw.map((p) => workDir ? path6.resolve(workDir, p) : p);
|
|
16233
|
+
return abs.length ? abs : [name];
|
|
16234
|
+
}
|
|
16235
|
+
var DEFAULT_MAX_CONCURRENT_SUBTASKS = 4;
|
|
16236
|
+
function resolveMaxConcurrentSubtasks(settingsRaw = {}) {
|
|
16237
|
+
const clamp = (n) => Math.min(Math.floor(n), 16);
|
|
16238
|
+
const fromEnv = Number(process.env.NEXRALL_MAX_CONCURRENT_SUBTASKS);
|
|
16239
|
+
if (Number.isFinite(fromEnv) && fromEnv > 0)
|
|
16240
|
+
return clamp(fromEnv);
|
|
16241
|
+
const fromSettings = Number(settingsRaw.maxConcurrentSubtasks);
|
|
16242
|
+
if (Number.isFinite(fromSettings) && fromSettings > 0)
|
|
16243
|
+
return clamp(fromSettings);
|
|
16244
|
+
return DEFAULT_MAX_CONCURRENT_SUBTASKS;
|
|
16245
|
+
}
|
|
16151
16246
|
function createLimiter(max) {
|
|
16152
16247
|
let active = 0;
|
|
16153
16248
|
const queue = [];
|
|
@@ -16166,7 +16261,20 @@ ${ctx.repeatError}
|
|
|
16166
16261
|
}
|
|
16167
16262
|
};
|
|
16168
16263
|
}
|
|
16169
|
-
var
|
|
16264
|
+
var _subTaskLimitInstance = null;
|
|
16265
|
+
var _subTaskLimitMax = 0;
|
|
16266
|
+
var _inFlightSubTasks = 0;
|
|
16267
|
+
function subTaskLimiter(workDir) {
|
|
16268
|
+
if (!_subTaskLimitInstance) {
|
|
16269
|
+
_subTaskLimitMax = resolveMaxConcurrentSubtasks(workDir ? (0, rules_1.loadSettings)(workDir).raw : {});
|
|
16270
|
+
_subTaskLimitInstance = createLimiter(_subTaskLimitMax);
|
|
16271
|
+
}
|
|
16272
|
+
return { run: _subTaskLimitInstance, max: _subTaskLimitMax };
|
|
16273
|
+
}
|
|
16274
|
+
function _resetSubTaskLimiter() {
|
|
16275
|
+
_subTaskLimitInstance = null;
|
|
16276
|
+
_subTaskLimitMax = 0;
|
|
16277
|
+
}
|
|
16170
16278
|
function humanDescription(name, input) {
|
|
16171
16279
|
switch (name) {
|
|
16172
16280
|
case "read_file":
|
|
@@ -17255,7 +17363,20 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17255
17363
|
if (!permitted) {
|
|
17256
17364
|
result = { error: deniedReason ?? "Permission denied by user" };
|
|
17257
17365
|
} else if (name === "task") {
|
|
17258
|
-
|
|
17366
|
+
if (depth === 0) {
|
|
17367
|
+
const { run: limitRun, max: limitMax } = subTaskLimiter(options.workDir);
|
|
17368
|
+
if (_inFlightSubTasks >= limitMax) {
|
|
17369
|
+
(options.onNotice ?? options.onText)(`\u23F3 Queued: ${limitMax} sub-agents are already running, so this one starts when a slot frees up (raise "maxConcurrentSubtasks" in .nexrall/settings.json to widen it).`);
|
|
17370
|
+
}
|
|
17371
|
+
_inFlightSubTasks++;
|
|
17372
|
+
try {
|
|
17373
|
+
result = await limitRun(() => runSubTask(input, options, agentTypes));
|
|
17374
|
+
} finally {
|
|
17375
|
+
_inFlightSubTasks--;
|
|
17376
|
+
}
|
|
17377
|
+
} else {
|
|
17378
|
+
result = await runSubTask(input, options, agentTypes);
|
|
17379
|
+
}
|
|
17259
17380
|
} else {
|
|
17260
17381
|
const pre = runToolHooks(hooks.PreToolUse, "PreToolUse", name, input, options.workDir);
|
|
17261
17382
|
if (pre.block) {
|
|
@@ -17275,15 +17396,10 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17275
17396
|
result = { output: mcpOutput ?? "" };
|
|
17276
17397
|
} else {
|
|
17277
17398
|
options.checkpointManager?.recordBeforeMutation(name, input);
|
|
17278
|
-
const WRITE_TOOLS = /* @__PURE__ */ new Set(["write_file", "edit_file", "multi_edit", "delete_file", "move_file", "copy_file", "notebook_edit"]);
|
|
17279
17399
|
const onStream = options.onToolStreamChunk ? (chunk) => options.onToolStreamChunk(name, chunk) : void 0;
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
result = await withFileLock(absTarget || name, () => (0, executor_1.executeTool)(name, input, options.abortSignal, sandboxCfg, options.workDir, agentScope, onStream));
|
|
17284
|
-
} else {
|
|
17285
|
-
result = await (0, executor_1.executeTool)(name, input, options.abortSignal, sandboxCfg, options.workDir, agentScope, onStream);
|
|
17286
|
-
}
|
|
17400
|
+
const run = () => (0, executor_1.executeTool)(name, input, options.abortSignal, sandboxCfg, options.workDir, agentScope, onStream);
|
|
17401
|
+
const locks = name === "bash" ? (0, bashClassify_1.bashNeedsRepoLock)(String(input.command ?? "")) ? [REPO_STATE_LOCK] : [] : lockPathsFor(name, input, options.workDir);
|
|
17402
|
+
result = locks.length ? await withFileLocks(locks, run) : await run();
|
|
17287
17403
|
}
|
|
17288
17404
|
} catch (err) {
|
|
17289
17405
|
result = { error: `Tool execution failed: ${err.message}` };
|
|
@@ -18512,6 +18628,95 @@ var require_manager2 = __commonJS({
|
|
|
18512
18628
|
}
|
|
18513
18629
|
});
|
|
18514
18630
|
|
|
18631
|
+
// ../core/dist/permissions/modePolicy.js
|
|
18632
|
+
var require_modePolicy = __commonJS({
|
|
18633
|
+
"../core/dist/permissions/modePolicy.js"(exports) {
|
|
18634
|
+
"use strict";
|
|
18635
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18636
|
+
exports.BASH_TOOLS = exports.FILE_MUTATE_TOOLS = exports.FILE_WRITE_TOOLS = exports.READ_ONLY_TOOLS = void 0;
|
|
18637
|
+
exports.isReadOnlyBash = isReadOnlyBash;
|
|
18638
|
+
exports.decide = decide;
|
|
18639
|
+
exports.describeMode = describeMode2;
|
|
18640
|
+
exports.parseMode = parseMode2;
|
|
18641
|
+
var bashClassify_1 = require_bashClassify();
|
|
18642
|
+
exports.READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
18643
|
+
"read_file",
|
|
18644
|
+
"list_directory",
|
|
18645
|
+
"search_files",
|
|
18646
|
+
"glob",
|
|
18647
|
+
"grep",
|
|
18648
|
+
"fetch_url",
|
|
18649
|
+
"web_search",
|
|
18650
|
+
"bash_output",
|
|
18651
|
+
"kill_shell",
|
|
18652
|
+
"todo_read",
|
|
18653
|
+
"todo_write",
|
|
18654
|
+
"memory_read",
|
|
18655
|
+
"use_skill",
|
|
18656
|
+
"notebook_read",
|
|
18657
|
+
"get_diagnostics",
|
|
18658
|
+
"go_to_definition",
|
|
18659
|
+
"find_references",
|
|
18660
|
+
"get_symbols",
|
|
18661
|
+
"get_workspace_symbols",
|
|
18662
|
+
"get_hover"
|
|
18663
|
+
]);
|
|
18664
|
+
exports.FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
18665
|
+
"write_file",
|
|
18666
|
+
"create_file",
|
|
18667
|
+
"edit_file",
|
|
18668
|
+
"multi_edit",
|
|
18669
|
+
"notebook_edit"
|
|
18670
|
+
]);
|
|
18671
|
+
exports.FILE_MUTATE_TOOLS = /* @__PURE__ */ new Set([
|
|
18672
|
+
"delete_file",
|
|
18673
|
+
"move_file",
|
|
18674
|
+
"copy_file"
|
|
18675
|
+
]);
|
|
18676
|
+
exports.BASH_TOOLS = /* @__PURE__ */ new Set(["bash", "run_command", "execute_command"]);
|
|
18677
|
+
function isReadOnlyBash(command) {
|
|
18678
|
+
return !(0, bashClassify_1.bashNeedsRepoLock)(command);
|
|
18679
|
+
}
|
|
18680
|
+
function decide(req) {
|
|
18681
|
+
const { tool, mode } = req;
|
|
18682
|
+
const command = String(req.input.command ?? req.input.cmd ?? "");
|
|
18683
|
+
if (exports.READ_ONLY_TOOLS.has(tool))
|
|
18684
|
+
return "allow";
|
|
18685
|
+
if (exports.BASH_TOOLS.has(tool) && isReadOnlyBash(command) && !req.destructive)
|
|
18686
|
+
return "allow";
|
|
18687
|
+
if (req.destructive)
|
|
18688
|
+
return "confirm";
|
|
18689
|
+
if (mode === "plan")
|
|
18690
|
+
return "deny";
|
|
18691
|
+
if (req.bypass)
|
|
18692
|
+
return "allow";
|
|
18693
|
+
if (exports.FILE_WRITE_TOOLS.has(tool) || exports.FILE_MUTATE_TOOLS.has(tool)) {
|
|
18694
|
+
return mode === "ask" ? "ask" : "allow";
|
|
18695
|
+
}
|
|
18696
|
+
if (exports.BASH_TOOLS.has(tool)) {
|
|
18697
|
+
return mode === "auto" ? "allow" : "ask";
|
|
18698
|
+
}
|
|
18699
|
+
return "ask";
|
|
18700
|
+
}
|
|
18701
|
+
function describeMode2(mode) {
|
|
18702
|
+
switch (mode) {
|
|
18703
|
+
case "plan":
|
|
18704
|
+
return "plan \u2014 read-only, produces a plan for approval";
|
|
18705
|
+
case "ask":
|
|
18706
|
+
return "ask \u2014 approves reads; asks before edits and commands";
|
|
18707
|
+
case "edit":
|
|
18708
|
+
return "edit \u2014 edits files freely; asks before shell commands";
|
|
18709
|
+
case "auto":
|
|
18710
|
+
return "auto \u2014 edits and runs commands; still confirms irreversible actions";
|
|
18711
|
+
}
|
|
18712
|
+
}
|
|
18713
|
+
function parseMode2(raw) {
|
|
18714
|
+
const s2 = String(raw ?? "").trim().toLowerCase();
|
|
18715
|
+
return s2 === "plan" || s2 === "ask" || s2 === "edit" || s2 === "auto" ? s2 : "ask";
|
|
18716
|
+
}
|
|
18717
|
+
}
|
|
18718
|
+
});
|
|
18719
|
+
|
|
18515
18720
|
// ../core/dist/permissions/destructive.js
|
|
18516
18721
|
var require_destructive = __commonJS({
|
|
18517
18722
|
"../core/dist/permissions/destructive.js"(exports) {
|
|
@@ -19274,6 +19479,8 @@ var require_dist2 = __commonJS({
|
|
|
19274
19479
|
__exportStar(require_planMode(), exports);
|
|
19275
19480
|
__exportStar(require_agentRegistry(), exports);
|
|
19276
19481
|
__exportStar(require_rules(), exports);
|
|
19482
|
+
__exportStar(require_modePolicy(), exports);
|
|
19483
|
+
__exportStar(require_bashClassify(), exports);
|
|
19277
19484
|
__exportStar(require_destructive(), exports);
|
|
19278
19485
|
__exportStar(require_plugins(), exports);
|
|
19279
19486
|
__exportStar(require_installer(), exports);
|
|
@@ -53599,7 +53806,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
53599
53806
|
var source_default = chalk;
|
|
53600
53807
|
|
|
53601
53808
|
// src/index.ts
|
|
53602
|
-
var
|
|
53809
|
+
var import_code_core6 = __toESM(require_dist2(), 1);
|
|
53603
53810
|
|
|
53604
53811
|
// src/commands/auth.ts
|
|
53605
53812
|
import * as readline from "readline";
|
|
@@ -54686,14 +54893,14 @@ var import_code_core2 = __toESM(require_dist2(), 1);
|
|
|
54686
54893
|
var autoApproved = /* @__PURE__ */ new Set();
|
|
54687
54894
|
var _rules = { allow: [], ask: [], deny: [] };
|
|
54688
54895
|
var _workDir = process.cwd();
|
|
54689
|
-
var _mode = "
|
|
54896
|
+
var _mode = "ask";
|
|
54690
54897
|
function initPermissions(workDir) {
|
|
54691
54898
|
_workDir = workDir;
|
|
54692
54899
|
_rules = (0, import_code_core2.loadSettings)(workDir).permissions;
|
|
54693
54900
|
return _rules;
|
|
54694
54901
|
}
|
|
54695
54902
|
function setMode(mode) {
|
|
54696
|
-
_mode = mode
|
|
54903
|
+
_mode = (0, import_code_core2.parseMode)(mode);
|
|
54697
54904
|
}
|
|
54698
54905
|
function setAutoApprove(category) {
|
|
54699
54906
|
autoApproved.add(category);
|
|
@@ -54708,22 +54915,30 @@ var _replInterface = null;
|
|
|
54708
54915
|
function setReadlineInterface(rl) {
|
|
54709
54916
|
_replInterface = rl;
|
|
54710
54917
|
}
|
|
54918
|
+
var _promptChain = Promise.resolve();
|
|
54919
|
+
function serialisePrompt(fn) {
|
|
54920
|
+
const next = _promptChain.then(fn, fn);
|
|
54921
|
+
_promptChain = next.catch(() => void 0);
|
|
54922
|
+
return next;
|
|
54923
|
+
}
|
|
54711
54924
|
function askUser(question) {
|
|
54712
|
-
|
|
54713
|
-
|
|
54925
|
+
return serialisePrompt(() => {
|
|
54926
|
+
if (_replInterface) {
|
|
54927
|
+
const rl = _replInterface;
|
|
54928
|
+
return new Promise((resolve3) => {
|
|
54929
|
+
rl.question(question, (answer) => resolve3(answer.trim()));
|
|
54930
|
+
});
|
|
54931
|
+
}
|
|
54714
54932
|
return new Promise((resolve3) => {
|
|
54715
|
-
rl
|
|
54716
|
-
|
|
54717
|
-
|
|
54718
|
-
|
|
54719
|
-
|
|
54720
|
-
|
|
54721
|
-
|
|
54722
|
-
|
|
54723
|
-
|
|
54724
|
-
rl.question(question, (answer) => {
|
|
54725
|
-
rl.close();
|
|
54726
|
-
resolve3(answer.trim());
|
|
54933
|
+
const rl = readline2.createInterface({
|
|
54934
|
+
input: process.stdin,
|
|
54935
|
+
output: process.stderr,
|
|
54936
|
+
terminal: true
|
|
54937
|
+
});
|
|
54938
|
+
rl.question(question, (answer) => {
|
|
54939
|
+
rl.close();
|
|
54940
|
+
resolve3(answer.trim());
|
|
54941
|
+
});
|
|
54727
54942
|
});
|
|
54728
54943
|
});
|
|
54729
54944
|
}
|
|
@@ -54752,31 +54967,18 @@ async function requestPermission(req) {
|
|
|
54752
54967
|
}
|
|
54753
54968
|
if (decision === "allow")
|
|
54754
54969
|
return true;
|
|
54755
|
-
const
|
|
54756
|
-
|
|
54757
|
-
|
|
54758
|
-
|
|
54759
|
-
"
|
|
54760
|
-
|
|
54761
|
-
"
|
|
54762
|
-
|
|
54763
|
-
|
|
54764
|
-
|
|
54765
|
-
"memory_read",
|
|
54766
|
-
"memory_write",
|
|
54767
|
-
"use_skill",
|
|
54768
|
-
"notebook_read",
|
|
54769
|
-
"get_diagnostics",
|
|
54770
|
-
"go_to_definition",
|
|
54771
|
-
"find_references",
|
|
54772
|
-
"get_symbols",
|
|
54773
|
-
"get_workspace_symbols",
|
|
54774
|
-
"get_hover",
|
|
54775
|
-
"open_in_browser"
|
|
54776
|
-
];
|
|
54777
|
-
if (readOnlyTools.includes(tool))
|
|
54970
|
+
const verdict = (0, import_code_core2.decide)({
|
|
54971
|
+
tool,
|
|
54972
|
+
input,
|
|
54973
|
+
mode: _mode,
|
|
54974
|
+
bypass: isAutoApproved("all"),
|
|
54975
|
+
// The destructive case was already handled above with the strong confirm flow
|
|
54976
|
+
// (type "yes", no "approve all"), so it must not be re-triggered here.
|
|
54977
|
+
destructive: false
|
|
54978
|
+
});
|
|
54979
|
+
if (verdict === "allow")
|
|
54778
54980
|
return true;
|
|
54779
|
-
if (
|
|
54981
|
+
if (verdict === "deny") {
|
|
54780
54982
|
console.error(source_default.yellow(` \u2298 Plan mode \u2014 refused ${tool} (read-only until you switch mode).`));
|
|
54781
54983
|
return false;
|
|
54782
54984
|
}
|
|
@@ -54926,6 +55128,9 @@ async function requestPermission(req) {
|
|
|
54926
55128
|
return answer === "y" || answer === "yes";
|
|
54927
55129
|
}
|
|
54928
55130
|
|
|
55131
|
+
// src/commands/chat.ts
|
|
55132
|
+
var import_code_core4 = __toESM(require_dist2(), 1);
|
|
55133
|
+
|
|
54929
55134
|
// src/commands/sessions.ts
|
|
54930
55135
|
import * as fs3 from "fs";
|
|
54931
55136
|
import * as path from "path";
|
|
@@ -64349,7 +64554,7 @@ var InkReadlineAdapter = class extends EventEmitter3 {
|
|
|
64349
64554
|
};
|
|
64350
64555
|
|
|
64351
64556
|
// src/commands/chat.ts
|
|
64352
|
-
var CLI_VERSION = "0.5.
|
|
64557
|
+
var CLI_VERSION = "0.5.57";
|
|
64353
64558
|
var MODEL_LABELS = {
|
|
64354
64559
|
turbo: "Nexrall Turbo",
|
|
64355
64560
|
pro: "Nexrall Pro",
|
|
@@ -65412,11 +65617,15 @@ ${dirList}`;
|
|
|
65412
65617
|
case "/mode": {
|
|
65413
65618
|
const modeArg = arg.toLowerCase();
|
|
65414
65619
|
if (!modeArg) {
|
|
65415
|
-
console.log(source_default.dim(` Current: ${source_default.cyan(agentMode)}
|
|
65620
|
+
console.log(source_default.dim(` Current: ${source_default.cyan(agentMode)}`));
|
|
65621
|
+
for (const m2 of ["ask", "edit", "auto", "plan"]) {
|
|
65622
|
+
const marker = m2 === agentMode ? source_default.cyan("\u276F") : " ";
|
|
65623
|
+
console.log(` ${marker} ${source_default.bold(m2.padEnd(5))} ${source_default.dim((0, import_code_core4.describeMode)(m2).replace(`${m2} \u2014 `, ""))}`);
|
|
65624
|
+
}
|
|
65416
65625
|
} else if (["ask", "edit", "plan", "auto"].includes(modeArg)) {
|
|
65417
65626
|
agentMode = modeArg;
|
|
65418
65627
|
updateFooter();
|
|
65419
|
-
console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`));
|
|
65628
|
+
console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`) + source_default.dim(` ${(0, import_code_core4.describeMode)(modeArg).replace(`${modeArg} \u2014 `, "")}`));
|
|
65420
65629
|
} else {
|
|
65421
65630
|
console.log(source_default.red(` Unknown: ${modeArg}`));
|
|
65422
65631
|
}
|
|
@@ -65706,7 +65915,7 @@ ${caption}` : `[Attached: ${rel}]`;
|
|
|
65706
65915
|
|
|
65707
65916
|
// src/commands/plugin.ts
|
|
65708
65917
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
65709
|
-
var
|
|
65918
|
+
var import_code_core5 = __toESM(require_dist2(), 1);
|
|
65710
65919
|
function describeInspection(i2, name, ctx) {
|
|
65711
65920
|
console.log();
|
|
65712
65921
|
console.log(source_default.bold(` Plugin: ${name}`) + (i2.meta.version ? source_default.dim(` v${i2.meta.version}`) : ""));
|
|
@@ -65782,14 +65991,14 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
65782
65991
|
let registryName;
|
|
65783
65992
|
const isShortName = /^[\w.-]+$/.test(spec.trim()) && !spec.includes("/");
|
|
65784
65993
|
if (isShortName) {
|
|
65785
|
-
const alias = (0,
|
|
65994
|
+
const alias = (0, import_code_core5.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
|
|
65786
65995
|
if (alias) {
|
|
65787
65996
|
source2 = alias.spec;
|
|
65788
65997
|
console.log(source_default.dim(` Source: ${alias.name} (${alias.tier}) \u2190 ${alias.spec}`));
|
|
65789
65998
|
}
|
|
65790
65999
|
}
|
|
65791
66000
|
if (isShortName && source2 === spec) {
|
|
65792
|
-
const entry = await (0,
|
|
66001
|
+
const entry = await (0, import_code_core5.getRegistryPlugin)(spec.trim()).catch(() => null);
|
|
65793
66002
|
if (entry) {
|
|
65794
66003
|
source2 = entry.source;
|
|
65795
66004
|
registryName = entry.name;
|
|
@@ -65804,7 +66013,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
65804
66013
|
return;
|
|
65805
66014
|
}
|
|
65806
66015
|
}
|
|
65807
|
-
const res = await (0,
|
|
66016
|
+
const res = await (0, import_code_core5.installPlugin)(source2, {
|
|
65808
66017
|
scope,
|
|
65809
66018
|
workDir: process.cwd(),
|
|
65810
66019
|
name: opts.name ?? registryName,
|
|
@@ -65812,7 +66021,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
65812
66021
|
confirm: (i2, name, ctx) => confirmInstall(i2, name, opts.yes === true, ctx)
|
|
65813
66022
|
});
|
|
65814
66023
|
if (registryName)
|
|
65815
|
-
(0,
|
|
66024
|
+
(0, import_code_core5.reportInstall)(registryName);
|
|
65816
66025
|
console.log();
|
|
65817
66026
|
console.log(source_default.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`) + (res.sha ? source_default.dim(` @ ${res.sha.slice(0, 7)}`) : ""));
|
|
65818
66027
|
if (res.inspection.commands.length) {
|
|
@@ -65826,7 +66035,7 @@ async function pluginInstallCommand(spec, opts) {
|
|
|
65826
66035
|
}
|
|
65827
66036
|
function pluginRemoveCommand(name, opts) {
|
|
65828
66037
|
try {
|
|
65829
|
-
const dir = (0,
|
|
66038
|
+
const dir = (0, import_code_core5.removePlugin)(name, {
|
|
65830
66039
|
scope: opts.project ? "project" : void 0,
|
|
65831
66040
|
// no flag → search both scopes
|
|
65832
66041
|
workDir: process.cwd()
|
|
@@ -65839,14 +66048,14 @@ function pluginRemoveCommand(name, opts) {
|
|
|
65839
66048
|
}
|
|
65840
66049
|
async function pluginUpdateCommand(name, opts) {
|
|
65841
66050
|
const workDir = process.cwd();
|
|
65842
|
-
const targets = name ? [name] : (0,
|
|
66051
|
+
const targets = name ? [name] : (0, import_code_core5.loadPlugins)(workDir).filter((p) => (0, import_code_core5.readReceipt)(p.dir)?.kind === "github").map((p) => p.name);
|
|
65843
66052
|
if (!targets.length) {
|
|
65844
66053
|
console.log(source_default.dim(" No updatable plugins (only GitHub-installed plugins with receipts can update)."));
|
|
65845
66054
|
return;
|
|
65846
66055
|
}
|
|
65847
66056
|
for (const t2 of targets) {
|
|
65848
66057
|
try {
|
|
65849
|
-
const res = await (0,
|
|
66058
|
+
const res = await (0, import_code_core5.updatePlugin)(t2, {
|
|
65850
66059
|
workDir,
|
|
65851
66060
|
confirm: (i2, n, ctx) => confirmInstall(i2, n, opts.yes === true, ctx)
|
|
65852
66061
|
});
|
|
@@ -65863,7 +66072,7 @@ function badgeFor(p) {
|
|
|
65863
66072
|
}
|
|
65864
66073
|
async function pluginSearchCommand(query) {
|
|
65865
66074
|
try {
|
|
65866
|
-
const results = await (0,
|
|
66075
|
+
const results = await (0, import_code_core5.searchRegistry)(query);
|
|
65867
66076
|
if (!results.length) {
|
|
65868
66077
|
console.log(source_default.dim(query ? ` No plugins matching "${query}".` : " Registry is empty."));
|
|
65869
66078
|
return;
|
|
@@ -65886,7 +66095,7 @@ async function pluginSearchCommand(query) {
|
|
|
65886
66095
|
}
|
|
65887
66096
|
async function pluginInfoCommand(name) {
|
|
65888
66097
|
try {
|
|
65889
|
-
const p = await (0,
|
|
66098
|
+
const p = await (0, import_code_core5.getRegistryPlugin)(name);
|
|
65890
66099
|
if (!p) {
|
|
65891
66100
|
console.error(source_default.red(` \u2717 "${name}" not found in the registry.`));
|
|
65892
66101
|
process.exitCode = 1;
|
|
@@ -65922,7 +66131,7 @@ async function pluginInfoCommand(name) {
|
|
|
65922
66131
|
}
|
|
65923
66132
|
}
|
|
65924
66133
|
function pluginListCommand() {
|
|
65925
|
-
const plugins = (0,
|
|
66134
|
+
const plugins = (0, import_code_core5.loadPlugins)(process.cwd());
|
|
65926
66135
|
if (!plugins.length) {
|
|
65927
66136
|
console.log(source_default.dim(" No plugins installed."));
|
|
65928
66137
|
console.log(source_default.dim(" Install one: nex plugin install owner/repo"));
|
|
@@ -65931,10 +66140,10 @@ function pluginListCommand() {
|
|
|
65931
66140
|
console.log();
|
|
65932
66141
|
console.log(source_default.bold(" Installed plugins:"));
|
|
65933
66142
|
for (const p of plugins) {
|
|
65934
|
-
const receipt = (0,
|
|
66143
|
+
const receipt = (0, import_code_core5.readReceipt)(p.dir);
|
|
65935
66144
|
const src = receipt ? source_default.dim(` \u2190 ${receipt.source}`) : source_default.dim(" (manual)");
|
|
65936
66145
|
const at = receipt?.sha ? source_default.dim(` @ ${receipt.sha.slice(0, 7)}`) : "";
|
|
65937
|
-
const insp = (0,
|
|
66146
|
+
const insp = (0, import_code_core5.inspectPluginDir)(p.dir);
|
|
65938
66147
|
const runs = insp.hasHooks || insp.hasMcp ? source_default.yellow(` \u26A0 ${[insp.hasHooks && "hooks", insp.hasMcp && "mcp"].filter(Boolean).join("+")}`) : "";
|
|
65939
66148
|
console.log(
|
|
65940
66149
|
" " + source_default.cyan(p.name.padEnd(24)) + source_default.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src + at + runs
|
|
@@ -65944,8 +66153,8 @@ function pluginListCommand() {
|
|
|
65944
66153
|
}
|
|
65945
66154
|
function pluginSourceListCommand() {
|
|
65946
66155
|
const workDir = process.cwd();
|
|
65947
|
-
const sources = (0,
|
|
65948
|
-
const patterns = (0,
|
|
66156
|
+
const sources = (0, import_code_core5.loadDeclaredSources)(workDir, { includeProject: true });
|
|
66157
|
+
const patterns = (0, import_code_core5.allowedSourcePatterns)();
|
|
65949
66158
|
if (patterns) {
|
|
65950
66159
|
console.log();
|
|
65951
66160
|
console.log(source_default.bold(" Organisation policy: ") + source_default.dim(`installs restricted to ${patterns.join(", ")}`));
|
|
@@ -65960,7 +66169,7 @@ function pluginSourceListCommand() {
|
|
|
65960
66169
|
console.log(source_default.bold(" Declared plugin sources:"));
|
|
65961
66170
|
for (const s2 of sources) {
|
|
65962
66171
|
const tier = s2.tier === "project" ? source_default.yellow(s2.tier.padEnd(9)) : source_default.dim(s2.tier.padEnd(9));
|
|
65963
|
-
const blocked = !(0,
|
|
66172
|
+
const blocked = !(0, import_code_core5.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
|
|
65964
66173
|
console.log(" " + source_default.cyan(s2.name.padEnd(20)) + tier + source_default.white(s2.spec) + blocked);
|
|
65965
66174
|
}
|
|
65966
66175
|
console.log();
|
|
@@ -65970,17 +66179,17 @@ function pluginSourceListCommand() {
|
|
|
65970
66179
|
}
|
|
65971
66180
|
function pluginSourceAddCommand(name, spec, opts) {
|
|
65972
66181
|
try {
|
|
65973
|
-
(0,
|
|
65974
|
-
const patterns = (0,
|
|
65975
|
-
if (patterns && !(0,
|
|
66182
|
+
(0, import_code_core5.parsePluginSource)(spec);
|
|
66183
|
+
const patterns = (0, import_code_core5.allowedSourcePatterns)();
|
|
66184
|
+
if (patterns && !(0, import_code_core5.isSourceAllowed)(spec, patterns)) {
|
|
65976
66185
|
console.error(source_default.red(` \u2717 "${spec}" is not permitted by your organisation's policy.`));
|
|
65977
66186
|
console.error(source_default.dim(` Allowed: ${patterns.join(", ")}`));
|
|
65978
66187
|
process.exitCode = 1;
|
|
65979
66188
|
return;
|
|
65980
66189
|
}
|
|
65981
66190
|
const scope = opts.project ? "project" : "user";
|
|
65982
|
-
const file = (0,
|
|
65983
|
-
(0,
|
|
66191
|
+
const file = (0, import_code_core5.sourcesFileFor)(scope, process.cwd());
|
|
66192
|
+
(0, import_code_core5.writeDeclaredSource)(file, name, spec);
|
|
65984
66193
|
console.log();
|
|
65985
66194
|
console.log(source_default.green(` \u2713 Declared "${name}" \u2192 ${spec}`) + source_default.dim(` (${scope})`));
|
|
65986
66195
|
console.log(source_default.dim(` ${file}`));
|
|
@@ -65994,13 +66203,13 @@ function pluginSourceAddCommand(name, spec, opts) {
|
|
|
65994
66203
|
function pluginSourceRemoveCommand(name, opts) {
|
|
65995
66204
|
const workDir = process.cwd();
|
|
65996
66205
|
const scope = opts.project ? "project" : "user";
|
|
65997
|
-
const file = (0,
|
|
65998
|
-
if ((0,
|
|
66206
|
+
const file = (0, import_code_core5.sourcesFileFor)(scope, workDir);
|
|
66207
|
+
if ((0, import_code_core5.removeDeclaredSource)(file, name)) {
|
|
65999
66208
|
console.log(source_default.green(` \u2713 Removed source "${name}" (${scope})`));
|
|
66000
66209
|
console.log(source_default.dim(" Plugins already installed from it are untouched \u2014 remove them with nex plugin remove <name>"));
|
|
66001
66210
|
return;
|
|
66002
66211
|
}
|
|
66003
|
-
const found = (0,
|
|
66212
|
+
const found = (0, import_code_core5.resolveSourceAlias)(name, workDir, { includeProject: true });
|
|
66004
66213
|
if (found) {
|
|
66005
66214
|
console.error(source_default.red(` \u2717 "${name}" is declared in the ${found.tier} tier, not ${scope}.`));
|
|
66006
66215
|
console.error(source_default.dim(` ${found.file}`));
|
|
@@ -66016,7 +66225,7 @@ function pluginSourceRemoveCommand(name, opts) {
|
|
|
66016
66225
|
|
|
66017
66226
|
// src/index.ts
|
|
66018
66227
|
var program2 = new Command();
|
|
66019
|
-
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.
|
|
66228
|
+
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.57").enablePositionalOptions();
|
|
66020
66229
|
program2.command("auth").description("Login to your Nexrall account").action(authCommand);
|
|
66021
66230
|
program2.command("logout").description("Log out of your Nexrall account").action(logoutCommand);
|
|
66022
66231
|
program2.command("update").description("Update nex to the latest version").option("-c, --check", "Check for updates without installing").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
@@ -66088,7 +66297,7 @@ program2.command("sessions").description("List or delete saved chat sessions").o
|
|
|
66088
66297
|
console.log();
|
|
66089
66298
|
});
|
|
66090
66299
|
program2.option("-p, --pro", "Use Nexrall Pro (Claude Opus, most capable)").option("-t, --turbo", "Use Nexrall Turbo (Claude Sonnet, fast)").option("-u, --ultra", "Use Ultra (Claude Fable 5, 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: turbo | pro | ultra").option("-r, --resume [id]", "Resume last session, or a specific session id").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)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
|
|
66091
|
-
if (!(0,
|
|
66300
|
+
if (!(0, import_code_core6.isAuthenticated)()) {
|
|
66092
66301
|
console.error("Not logged in. Run: nex auth");
|
|
66093
66302
|
process.exit(1);
|
|
66094
66303
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexrall-code",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.57",
|
|
4
4
|
"description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"react": "^19.2.8",
|
|
42
42
|
"readline": "^1.3.0",
|
|
43
43
|
"string-width": "^7.2.0",
|
|
44
|
-
"@nexrall/code-core": "1.4.
|
|
44
|
+
"@nexrall/code-core": "1.4.32"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@aws-sdk/client-s3": "^3.600.0",
|