nexrall-code 0.5.56 → 0.5.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +229 -111
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -9982,7 +9982,7 @@ var require_client = __commonJS({
9982
9982
  }
9983
9983
  var MAX_TOTAL_ATTEMPTS = (MAX_RETRIES + 1) * (MAX_RETRIES + 1);
9984
9984
  async function streamChat(messages, options, onEvent) {
9985
- const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore } = options;
9985
+ const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents } = options;
9986
9986
  let turnId = (0, crypto_1.randomUUID)();
9987
9987
  const controller = new AbortController();
9988
9988
  if (abortSignal?.aborted)
@@ -10023,7 +10023,7 @@ var require_client = __commonJS({
10023
10023
  {
10024
10024
  method: "POST",
10025
10025
  headers: authHeaders(),
10026
- body: JSON.stringify({ messages, model, env: env3, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore }),
10026
+ body: JSON.stringify({ messages, model, env: env3, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents }),
10027
10027
  signal: controller.signal
10028
10028
  }
10029
10029
  ];
@@ -15061,6 +15061,13 @@ var require_agentTypes = __commonJS({
15061
15061
  message: `lists unknown tool name(s): ${unknown.join(", ")}. An allowlist only grants, so these silently do nothing and the agent cannot use them. Tool names are lower_snake_case (read_file, search_files, glob, bash).`
15062
15062
  });
15063
15063
  }
15064
+ if ((tools ?? []).includes("task")) {
15065
+ warnings.push({
15066
+ file: full,
15067
+ agent: name,
15068
+ message: "lists `task`, which cannot be granted: sub-agents are never sent that tool because they cannot spawn further sub-agents. Remove it \u2014 delegation stays with the main agent."
15069
+ });
15070
+ }
15064
15071
  const strayKeys = Object.keys(meta).filter((k) => !KNOWN_META_KEYS.has(k));
15065
15072
  if (strayKeys.length) {
15066
15073
  warnings.push({
@@ -15375,6 +15382,63 @@ var require_rules = __commonJS({
15375
15382
  }
15376
15383
  });
15377
15384
 
15385
+ // ../core/dist/permissions/bashClassify.js
15386
+ var require_bashClassify = __commonJS({
15387
+ "../core/dist/permissions/bashClassify.js"(exports) {
15388
+ "use strict";
15389
+ Object.defineProperty(exports, "__esModule", { value: true });
15390
+ exports.bashNeedsRepoLock = bashNeedsRepoLock;
15391
+ var MUTATING_BASH_VERBS = /* @__PURE__ */ new Set([
15392
+ "git",
15393
+ "npm",
15394
+ "pnpm",
15395
+ "yarn",
15396
+ "bun",
15397
+ "cargo",
15398
+ "go",
15399
+ "pip",
15400
+ "pip3",
15401
+ "poetry",
15402
+ "uv",
15403
+ "bundle",
15404
+ "composer",
15405
+ "gradle",
15406
+ "mvn",
15407
+ "make",
15408
+ "terraform",
15409
+ "helm",
15410
+ "docker",
15411
+ "vsce",
15412
+ "tsc",
15413
+ "pytest",
15414
+ "dotnet",
15415
+ "swift",
15416
+ "gem"
15417
+ ]);
15418
+ function bashNeedsRepoLock(command) {
15419
+ if (!command)
15420
+ return false;
15421
+ const segments = command.split(/\|\||&&|[;|&\n()]|\$\(/);
15422
+ for (const seg of segments) {
15423
+ for (const tokenRaw of seg.trim().split(/\s+/)) {
15424
+ const token = tokenRaw.replace(/^["']|["']$/g, "");
15425
+ if (!token)
15426
+ continue;
15427
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token))
15428
+ continue;
15429
+ if (token === "sudo" || token === "time" || token === "nice" || token === "env")
15430
+ continue;
15431
+ const verb = token.split("/").pop() ?? token;
15432
+ if (MUTATING_BASH_VERBS.has(verb))
15433
+ return true;
15434
+ break;
15435
+ }
15436
+ }
15437
+ return false;
15438
+ }
15439
+ }
15440
+ });
15441
+
15378
15442
  // ../core/dist/agent/planMode.js
15379
15443
  var require_planMode = __commonJS({
15380
15444
  "../core/dist/agent/planMode.js"(exports) {
@@ -15897,16 +15961,16 @@ var require_loop = __commonJS({
15897
15961
  };
15898
15962
  }();
15899
15963
  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;
15964
+ exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.ToolNotAllowedError = exports.NO_NESTED_SUBAGENTS_MSG = exports.AGENT_MEMORY_TOOL_SCHEMA = exports.AGENT_MEMORY_TOOL = exports._stallLimits = exports.bashNeedsRepoLock = void 0;
15901
15965
  exports.errorRoundSignature = errorRoundSignature;
15902
15966
  exports.executeAgentMemoryWrite = executeAgentMemoryWrite;
15903
15967
  exports.stopReasonNotice = stopReasonNotice;
15904
15968
  exports.resolveMaxIterations = resolveMaxIterations;
15905
- exports.bashNeedsRepoLock = bashNeedsRepoLock;
15906
15969
  exports.lockPathsFor = lockPathsFor;
15907
15970
  exports.resolveMaxConcurrentSubtasks = resolveMaxConcurrentSubtasks;
15908
15971
  exports.createLimiter = createLimiter;
15909
15972
  exports._resetSubTaskLimiter = _resetSubTaskLimiter;
15973
+ exports.canSpawnSubAgents = canSpawnSubAgents;
15910
15974
  exports.resolveSubtaskTimeoutMs = resolveSubtaskTimeoutMs;
15911
15975
  exports.extractSubTaskText = extractSubTaskText;
15912
15976
  exports.capSubTaskText = capSubTaskText;
@@ -15932,6 +15996,10 @@ var require_loop = __commonJS({
15932
15996
  var agentTypes_1 = require_agentTypes();
15933
15997
  var skills_1 = require_skills();
15934
15998
  var rules_1 = require_rules();
15999
+ var bashClassify_1 = require_bashClassify();
16000
+ Object.defineProperty(exports, "bashNeedsRepoLock", { enumerable: true, get: function() {
16001
+ return bashClassify_1.bashNeedsRepoLock;
16002
+ } });
15935
16003
  var planMode_1 = require_planMode();
15936
16004
  var agentRegistry_1 = require_agentRegistry();
15937
16005
  var sandbox_1 = require_sandbox();
@@ -16165,54 +16233,6 @@ ${ctx.repeatError}
16165
16233
  "notebook_edit"
16166
16234
  ]);
16167
16235
  var REPO_STATE_LOCK = "\0repo-state";
16168
- var MUTATING_BASH_VERBS = /* @__PURE__ */ new Set([
16169
- "git",
16170
- "npm",
16171
- "pnpm",
16172
- "yarn",
16173
- "bun",
16174
- "cargo",
16175
- "go",
16176
- "pip",
16177
- "pip3",
16178
- "poetry",
16179
- "uv",
16180
- "bundle",
16181
- "composer",
16182
- "gradle",
16183
- "mvn",
16184
- "make",
16185
- "terraform",
16186
- "helm",
16187
- "docker",
16188
- "vsce",
16189
- "tsc",
16190
- "pytest",
16191
- "dotnet",
16192
- "swift",
16193
- "gem"
16194
- ]);
16195
- function bashNeedsRepoLock(command) {
16196
- if (!command)
16197
- return false;
16198
- const segments = command.split(/\|\||&&|[;|&\n()]|\$\(/);
16199
- for (const seg of segments) {
16200
- for (const tokenRaw of seg.trim().split(/\s+/)) {
16201
- const token = tokenRaw.replace(/^["']|["']$/g, "");
16202
- if (!token)
16203
- continue;
16204
- if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token))
16205
- continue;
16206
- if (token === "sudo" || token === "time" || token === "nice" || token === "env")
16207
- continue;
16208
- const verb = token.split("/").pop() ?? token;
16209
- if (MUTATING_BASH_VERBS.has(verb))
16210
- return true;
16211
- break;
16212
- }
16213
- }
16214
- return false;
16215
- }
16216
16236
  function lockPathsFor(name, input, workDir) {
16217
16237
  if (!WRITE_TOOLS.has(name))
16218
16238
  return [];
@@ -16345,6 +16365,12 @@ ${ctx.repeatError}
16345
16365
  }
16346
16366
  }
16347
16367
  var MAX_TASK_DEPTH = 1;
16368
+ exports.NO_NESTED_SUBAGENTS_MSG = "Sub-agents cannot spawn further sub-agents \u2014 this is a structural limit, not a permission, so no other agent type and no approval can lift it. Do this work directly with the tools you have, or report back so the main agent can delegate it.";
16369
+ function canSpawnSubAgents(depth, allowedTools) {
16370
+ if (depth >= MAX_TASK_DEPTH)
16371
+ return false;
16372
+ return allowedTools ? allowedTools.has("task") : true;
16373
+ }
16348
16374
  var _subTaskCounter = 0;
16349
16375
  var DEFAULT_SUBTASK_TIMEOUT_MS = 10 * 60 * 1e3;
16350
16376
  function resolveSubtaskTimeoutMs(settingsRaw) {
@@ -16473,7 +16499,7 @@ ${body}`);
16473
16499
  return { error: "task tool requires a non-empty prompt" };
16474
16500
  const depth = options._depth ?? 0;
16475
16501
  if (depth >= MAX_TASK_DEPTH) {
16476
- return { error: "Sub-agents cannot spawn further sub-agents. Do this work directly, or report back so the main agent can delegate it." };
16502
+ return { error: exports.NO_NESTED_SUBAGENTS_MSG };
16477
16503
  }
16478
16504
  const resumeId = typeof input.resume_agent_id === "string" ? input.resume_agent_id.trim() : "";
16479
16505
  const resumed = resumeId ? (0, agentRegistry_1.getAgent)(resumeId) : void 0;
@@ -16524,6 +16550,9 @@ ${inheritedMd}` : "") : options.nexrallMd;
16524
16550
  if (req.tool === exports.AGENT_MEMORY_TOOL && !(agent && memoryScope)) {
16525
16551
  throw new ToolNotAllowedError(`\`${exports.AGENT_MEMORY_TOOL}\` is only available to a sub-agent whose definition declares a \`memory:\` scope (project, user or local). Report anything worth remembering in your final message instead \u2014 the main agent decides what to persist.`);
16526
16552
  }
16553
+ if (req.tool === "task") {
16554
+ throw new ToolNotAllowedError(exports.NO_NESTED_SUBAGENTS_MSG);
16555
+ }
16527
16556
  if (allowed && !allowed.has(req.tool)) {
16528
16557
  throw new ToolNotAllowedError(`The "${agent.name}" sub-agent is not allowed to use \`${req.tool}\` \u2014 it is not in that agent's tool allowlist. This is a restriction of the agent definition, NOT a user decision: do not ask for approval, use one of the tools you do have, or report back that the task needs a different agent.`);
16529
16558
  }
@@ -17058,7 +17087,8 @@ Continue the work from here.` }] });
17058
17087
  const agentScope = options._agentScope ?? "root";
17059
17088
  const settings = (0, rules_1.loadSettings)(options.workDir);
17060
17089
  const agentTypes = (0, agentTypes_1.loadAgentTypes)(options.workDir).filter((t2) => (0, rules_1.evaluatePermission)(settings.permissions, "task", { subagent_type: t2.name }, options.workDir) !== "deny");
17061
- const agentsCatalogue = depth === 0 ? (0, agentTypes_1.summariseAgents)(agentTypes) : "";
17090
+ const maySpawn = canSpawnSubAgents(depth, options._allowedTools);
17091
+ const agentsCatalogue = maySpawn ? (0, agentTypes_1.summariseAgents)(agentTypes) : "";
17062
17092
  const skillsCatalogue = (0, skills_1.summariseSkills)((0, skills_1.loadSkills)(options.workDir));
17063
17093
  const planAwareNexrallMd = options.planMode ? planMode_1.PLAN_MODE_INSTRUCTIONS + (options.nexrallMd ? `
17064
17094
 
@@ -17208,6 +17238,9 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
17208
17238
  canWriteSharedMemory: options._allowedTools ? options._allowedTools.has("memory_write") : true,
17209
17239
  // no allowlist = main agent = may write
17210
17240
  hasOwnAgentStore: !!options._agentMemory,
17241
+ // Withholds the `task` schema and its instructions when this run cannot
17242
+ // delegate — see canSpawnSubAgents.
17243
+ canSpawnSubAgents: maySpawn,
17211
17244
  agents: agentsCatalogue || void 0,
17212
17245
  skills: skillsCatalogue || void 0,
17213
17246
  // Only allow a post-render restart when the caller actually implements the
@@ -17386,7 +17419,7 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
17386
17419
  options.checkpointManager?.recordBeforeMutation(name, input);
17387
17420
  const onStream = options.onToolStreamChunk ? (chunk) => options.onToolStreamChunk(name, chunk) : void 0;
17388
17421
  const run = () => (0, executor_1.executeTool)(name, input, options.abortSignal, sandboxCfg, options.workDir, agentScope, onStream);
17389
- const locks = name === "bash" ? bashNeedsRepoLock(String(input.command ?? "")) ? [REPO_STATE_LOCK] : [] : lockPathsFor(name, input, options.workDir);
17422
+ const locks = name === "bash" ? (0, bashClassify_1.bashNeedsRepoLock)(String(input.command ?? "")) ? [REPO_STATE_LOCK] : [] : lockPathsFor(name, input, options.workDir);
17390
17423
  result = locks.length ? await withFileLocks(locks, run) : await run();
17391
17424
  }
17392
17425
  } catch (err) {
@@ -18616,6 +18649,95 @@ var require_manager2 = __commonJS({
18616
18649
  }
18617
18650
  });
18618
18651
 
18652
+ // ../core/dist/permissions/modePolicy.js
18653
+ var require_modePolicy = __commonJS({
18654
+ "../core/dist/permissions/modePolicy.js"(exports) {
18655
+ "use strict";
18656
+ Object.defineProperty(exports, "__esModule", { value: true });
18657
+ exports.BASH_TOOLS = exports.FILE_MUTATE_TOOLS = exports.FILE_WRITE_TOOLS = exports.READ_ONLY_TOOLS = void 0;
18658
+ exports.isReadOnlyBash = isReadOnlyBash;
18659
+ exports.decide = decide;
18660
+ exports.describeMode = describeMode2;
18661
+ exports.parseMode = parseMode2;
18662
+ var bashClassify_1 = require_bashClassify();
18663
+ exports.READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
18664
+ "read_file",
18665
+ "list_directory",
18666
+ "search_files",
18667
+ "glob",
18668
+ "grep",
18669
+ "fetch_url",
18670
+ "web_search",
18671
+ "bash_output",
18672
+ "kill_shell",
18673
+ "todo_read",
18674
+ "todo_write",
18675
+ "memory_read",
18676
+ "use_skill",
18677
+ "notebook_read",
18678
+ "get_diagnostics",
18679
+ "go_to_definition",
18680
+ "find_references",
18681
+ "get_symbols",
18682
+ "get_workspace_symbols",
18683
+ "get_hover"
18684
+ ]);
18685
+ exports.FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
18686
+ "write_file",
18687
+ "create_file",
18688
+ "edit_file",
18689
+ "multi_edit",
18690
+ "notebook_edit"
18691
+ ]);
18692
+ exports.FILE_MUTATE_TOOLS = /* @__PURE__ */ new Set([
18693
+ "delete_file",
18694
+ "move_file",
18695
+ "copy_file"
18696
+ ]);
18697
+ exports.BASH_TOOLS = /* @__PURE__ */ new Set(["bash", "run_command", "execute_command"]);
18698
+ function isReadOnlyBash(command) {
18699
+ return !(0, bashClassify_1.bashNeedsRepoLock)(command);
18700
+ }
18701
+ function decide(req) {
18702
+ const { tool, mode } = req;
18703
+ const command = String(req.input.command ?? req.input.cmd ?? "");
18704
+ if (exports.READ_ONLY_TOOLS.has(tool))
18705
+ return "allow";
18706
+ if (exports.BASH_TOOLS.has(tool) && isReadOnlyBash(command) && !req.destructive)
18707
+ return "allow";
18708
+ if (req.destructive)
18709
+ return "confirm";
18710
+ if (mode === "plan")
18711
+ return "deny";
18712
+ if (req.bypass)
18713
+ return "allow";
18714
+ if (exports.FILE_WRITE_TOOLS.has(tool) || exports.FILE_MUTATE_TOOLS.has(tool)) {
18715
+ return mode === "ask" ? "ask" : "allow";
18716
+ }
18717
+ if (exports.BASH_TOOLS.has(tool)) {
18718
+ return mode === "auto" ? "allow" : "ask";
18719
+ }
18720
+ return "ask";
18721
+ }
18722
+ function describeMode2(mode) {
18723
+ switch (mode) {
18724
+ case "plan":
18725
+ return "plan \u2014 read-only, produces a plan for approval";
18726
+ case "ask":
18727
+ return "ask \u2014 approves reads; asks before edits and commands";
18728
+ case "edit":
18729
+ return "edit \u2014 edits files freely; asks before shell commands";
18730
+ case "auto":
18731
+ return "auto \u2014 edits and runs commands; still confirms irreversible actions";
18732
+ }
18733
+ }
18734
+ function parseMode2(raw) {
18735
+ const s2 = String(raw ?? "").trim().toLowerCase();
18736
+ return s2 === "plan" || s2 === "ask" || s2 === "edit" || s2 === "auto" ? s2 : "ask";
18737
+ }
18738
+ }
18739
+ });
18740
+
18619
18741
  // ../core/dist/permissions/destructive.js
18620
18742
  var require_destructive = __commonJS({
18621
18743
  "../core/dist/permissions/destructive.js"(exports) {
@@ -19378,6 +19500,8 @@ var require_dist2 = __commonJS({
19378
19500
  __exportStar(require_planMode(), exports);
19379
19501
  __exportStar(require_agentRegistry(), exports);
19380
19502
  __exportStar(require_rules(), exports);
19503
+ __exportStar(require_modePolicy(), exports);
19504
+ __exportStar(require_bashClassify(), exports);
19381
19505
  __exportStar(require_destructive(), exports);
19382
19506
  __exportStar(require_plugins(), exports);
19383
19507
  __exportStar(require_installer(), exports);
@@ -53703,7 +53827,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
53703
53827
  var source_default = chalk;
53704
53828
 
53705
53829
  // src/index.ts
53706
- var import_code_core5 = __toESM(require_dist2(), 1);
53830
+ var import_code_core6 = __toESM(require_dist2(), 1);
53707
53831
 
53708
53832
  // src/commands/auth.ts
53709
53833
  import * as readline from "readline";
@@ -54790,14 +54914,14 @@ var import_code_core2 = __toESM(require_dist2(), 1);
54790
54914
  var autoApproved = /* @__PURE__ */ new Set();
54791
54915
  var _rules = { allow: [], ask: [], deny: [] };
54792
54916
  var _workDir = process.cwd();
54793
- var _mode = "auto";
54917
+ var _mode = "ask";
54794
54918
  function initPermissions(workDir) {
54795
54919
  _workDir = workDir;
54796
54920
  _rules = (0, import_code_core2.loadSettings)(workDir).permissions;
54797
54921
  return _rules;
54798
54922
  }
54799
54923
  function setMode(mode) {
54800
- _mode = mode || "auto";
54924
+ _mode = (0, import_code_core2.parseMode)(mode);
54801
54925
  }
54802
54926
  function setAutoApprove(category) {
54803
54927
  autoApproved.add(category);
@@ -54864,31 +54988,18 @@ async function requestPermission(req) {
54864
54988
  }
54865
54989
  if (decision === "allow")
54866
54990
  return true;
54867
- const readOnlyTools = [
54868
- "read_file",
54869
- "list_directory",
54870
- "search_files",
54871
- "fetch_url",
54872
- "glob",
54873
- "bash_output",
54874
- "kill_shell",
54875
- "todo_read",
54876
- "todo_write",
54877
- "memory_read",
54878
- "memory_write",
54879
- "use_skill",
54880
- "notebook_read",
54881
- "get_diagnostics",
54882
- "go_to_definition",
54883
- "find_references",
54884
- "get_symbols",
54885
- "get_workspace_symbols",
54886
- "get_hover",
54887
- "open_in_browser"
54888
- ];
54889
- if (readOnlyTools.includes(tool))
54991
+ const verdict = (0, import_code_core2.decide)({
54992
+ tool,
54993
+ input,
54994
+ mode: _mode,
54995
+ bypass: isAutoApproved("all"),
54996
+ // The destructive case was already handled above with the strong confirm flow
54997
+ // (type "yes", no "approve all"), so it must not be re-triggered here.
54998
+ destructive: false
54999
+ });
55000
+ if (verdict === "allow")
54890
55001
  return true;
54891
- if (_mode === "plan") {
55002
+ if (verdict === "deny") {
54892
55003
  console.error(source_default.yellow(` \u2298 Plan mode \u2014 refused ${tool} (read-only until you switch mode).`));
54893
55004
  return false;
54894
55005
  }
@@ -55038,6 +55149,9 @@ async function requestPermission(req) {
55038
55149
  return answer === "y" || answer === "yes";
55039
55150
  }
55040
55151
 
55152
+ // src/commands/chat.ts
55153
+ var import_code_core4 = __toESM(require_dist2(), 1);
55154
+
55041
55155
  // src/commands/sessions.ts
55042
55156
  import * as fs3 from "fs";
55043
55157
  import * as path from "path";
@@ -64461,7 +64575,7 @@ var InkReadlineAdapter = class extends EventEmitter3 {
64461
64575
  };
64462
64576
 
64463
64577
  // src/commands/chat.ts
64464
- var CLI_VERSION = "0.5.56";
64578
+ var CLI_VERSION = "0.5.58";
64465
64579
  var MODEL_LABELS = {
64466
64580
  turbo: "Nexrall Turbo",
64467
64581
  pro: "Nexrall Pro",
@@ -65524,11 +65638,15 @@ ${dirList}`;
65524
65638
  case "/mode": {
65525
65639
  const modeArg = arg.toLowerCase();
65526
65640
  if (!modeArg) {
65527
- console.log(source_default.dim(` Current: ${source_default.cyan(agentMode)} Options: ask \xB7 edit \xB7 plan \xB7 auto`));
65641
+ console.log(source_default.dim(` Current: ${source_default.cyan(agentMode)}`));
65642
+ for (const m2 of ["ask", "edit", "auto", "plan"]) {
65643
+ const marker = m2 === agentMode ? source_default.cyan("\u276F") : " ";
65644
+ console.log(` ${marker} ${source_default.bold(m2.padEnd(5))} ${source_default.dim((0, import_code_core4.describeMode)(m2).replace(`${m2} \u2014 `, ""))}`);
65645
+ }
65528
65646
  } else if (["ask", "edit", "plan", "auto"].includes(modeArg)) {
65529
65647
  agentMode = modeArg;
65530
65648
  updateFooter();
65531
- console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`));
65649
+ console.log(source_default.green(` Mode \u2192 ${source_default.bold(modeArg)}`) + source_default.dim(` ${(0, import_code_core4.describeMode)(modeArg).replace(`${modeArg} \u2014 `, "")}`));
65532
65650
  } else {
65533
65651
  console.log(source_default.red(` Unknown: ${modeArg}`));
65534
65652
  }
@@ -65818,7 +65936,7 @@ ${caption}` : `[Attached: ${rel}]`;
65818
65936
 
65819
65937
  // src/commands/plugin.ts
65820
65938
  var import_prompts = __toESM(require_prompts3(), 1);
65821
- var import_code_core4 = __toESM(require_dist2(), 1);
65939
+ var import_code_core5 = __toESM(require_dist2(), 1);
65822
65940
  function describeInspection(i2, name, ctx) {
65823
65941
  console.log();
65824
65942
  console.log(source_default.bold(` Plugin: ${name}`) + (i2.meta.version ? source_default.dim(` v${i2.meta.version}`) : ""));
@@ -65894,14 +66012,14 @@ async function pluginInstallCommand(spec, opts) {
65894
66012
  let registryName;
65895
66013
  const isShortName = /^[\w.-]+$/.test(spec.trim()) && !spec.includes("/");
65896
66014
  if (isShortName) {
65897
- const alias = (0, import_code_core4.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
66015
+ const alias = (0, import_code_core5.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
65898
66016
  if (alias) {
65899
66017
  source2 = alias.spec;
65900
66018
  console.log(source_default.dim(` Source: ${alias.name} (${alias.tier}) \u2190 ${alias.spec}`));
65901
66019
  }
65902
66020
  }
65903
66021
  if (isShortName && source2 === spec) {
65904
- const entry = await (0, import_code_core4.getRegistryPlugin)(spec.trim()).catch(() => null);
66022
+ const entry = await (0, import_code_core5.getRegistryPlugin)(spec.trim()).catch(() => null);
65905
66023
  if (entry) {
65906
66024
  source2 = entry.source;
65907
66025
  registryName = entry.name;
@@ -65916,7 +66034,7 @@ async function pluginInstallCommand(spec, opts) {
65916
66034
  return;
65917
66035
  }
65918
66036
  }
65919
- const res = await (0, import_code_core4.installPlugin)(source2, {
66037
+ const res = await (0, import_code_core5.installPlugin)(source2, {
65920
66038
  scope,
65921
66039
  workDir: process.cwd(),
65922
66040
  name: opts.name ?? registryName,
@@ -65924,7 +66042,7 @@ async function pluginInstallCommand(spec, opts) {
65924
66042
  confirm: (i2, name, ctx) => confirmInstall(i2, name, opts.yes === true, ctx)
65925
66043
  });
65926
66044
  if (registryName)
65927
- (0, import_code_core4.reportInstall)(registryName);
66045
+ (0, import_code_core5.reportInstall)(registryName);
65928
66046
  console.log();
65929
66047
  console.log(source_default.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`) + (res.sha ? source_default.dim(` @ ${res.sha.slice(0, 7)}`) : ""));
65930
66048
  if (res.inspection.commands.length) {
@@ -65938,7 +66056,7 @@ async function pluginInstallCommand(spec, opts) {
65938
66056
  }
65939
66057
  function pluginRemoveCommand(name, opts) {
65940
66058
  try {
65941
- const dir = (0, import_code_core4.removePlugin)(name, {
66059
+ const dir = (0, import_code_core5.removePlugin)(name, {
65942
66060
  scope: opts.project ? "project" : void 0,
65943
66061
  // no flag → search both scopes
65944
66062
  workDir: process.cwd()
@@ -65951,14 +66069,14 @@ function pluginRemoveCommand(name, opts) {
65951
66069
  }
65952
66070
  async function pluginUpdateCommand(name, opts) {
65953
66071
  const workDir = process.cwd();
65954
- const targets = name ? [name] : (0, import_code_core4.loadPlugins)(workDir).filter((p) => (0, import_code_core4.readReceipt)(p.dir)?.kind === "github").map((p) => p.name);
66072
+ 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);
65955
66073
  if (!targets.length) {
65956
66074
  console.log(source_default.dim(" No updatable plugins (only GitHub-installed plugins with receipts can update)."));
65957
66075
  return;
65958
66076
  }
65959
66077
  for (const t2 of targets) {
65960
66078
  try {
65961
- const res = await (0, import_code_core4.updatePlugin)(t2, {
66079
+ const res = await (0, import_code_core5.updatePlugin)(t2, {
65962
66080
  workDir,
65963
66081
  confirm: (i2, n, ctx) => confirmInstall(i2, n, opts.yes === true, ctx)
65964
66082
  });
@@ -65975,7 +66093,7 @@ function badgeFor(p) {
65975
66093
  }
65976
66094
  async function pluginSearchCommand(query) {
65977
66095
  try {
65978
- const results = await (0, import_code_core4.searchRegistry)(query);
66096
+ const results = await (0, import_code_core5.searchRegistry)(query);
65979
66097
  if (!results.length) {
65980
66098
  console.log(source_default.dim(query ? ` No plugins matching "${query}".` : " Registry is empty."));
65981
66099
  return;
@@ -65998,7 +66116,7 @@ async function pluginSearchCommand(query) {
65998
66116
  }
65999
66117
  async function pluginInfoCommand(name) {
66000
66118
  try {
66001
- const p = await (0, import_code_core4.getRegistryPlugin)(name);
66119
+ const p = await (0, import_code_core5.getRegistryPlugin)(name);
66002
66120
  if (!p) {
66003
66121
  console.error(source_default.red(` \u2717 "${name}" not found in the registry.`));
66004
66122
  process.exitCode = 1;
@@ -66034,7 +66152,7 @@ async function pluginInfoCommand(name) {
66034
66152
  }
66035
66153
  }
66036
66154
  function pluginListCommand() {
66037
- const plugins = (0, import_code_core4.loadPlugins)(process.cwd());
66155
+ const plugins = (0, import_code_core5.loadPlugins)(process.cwd());
66038
66156
  if (!plugins.length) {
66039
66157
  console.log(source_default.dim(" No plugins installed."));
66040
66158
  console.log(source_default.dim(" Install one: nex plugin install owner/repo"));
@@ -66043,10 +66161,10 @@ function pluginListCommand() {
66043
66161
  console.log();
66044
66162
  console.log(source_default.bold(" Installed plugins:"));
66045
66163
  for (const p of plugins) {
66046
- const receipt = (0, import_code_core4.readReceipt)(p.dir);
66164
+ const receipt = (0, import_code_core5.readReceipt)(p.dir);
66047
66165
  const src = receipt ? source_default.dim(` \u2190 ${receipt.source}`) : source_default.dim(" (manual)");
66048
66166
  const at = receipt?.sha ? source_default.dim(` @ ${receipt.sha.slice(0, 7)}`) : "";
66049
- const insp = (0, import_code_core4.inspectPluginDir)(p.dir);
66167
+ const insp = (0, import_code_core5.inspectPluginDir)(p.dir);
66050
66168
  const runs = insp.hasHooks || insp.hasMcp ? source_default.yellow(` \u26A0 ${[insp.hasHooks && "hooks", insp.hasMcp && "mcp"].filter(Boolean).join("+")}`) : "";
66051
66169
  console.log(
66052
66170
  " " + source_default.cyan(p.name.padEnd(24)) + source_default.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src + at + runs
@@ -66056,8 +66174,8 @@ function pluginListCommand() {
66056
66174
  }
66057
66175
  function pluginSourceListCommand() {
66058
66176
  const workDir = process.cwd();
66059
- const sources = (0, import_code_core4.loadDeclaredSources)(workDir, { includeProject: true });
66060
- const patterns = (0, import_code_core4.allowedSourcePatterns)();
66177
+ const sources = (0, import_code_core5.loadDeclaredSources)(workDir, { includeProject: true });
66178
+ const patterns = (0, import_code_core5.allowedSourcePatterns)();
66061
66179
  if (patterns) {
66062
66180
  console.log();
66063
66181
  console.log(source_default.bold(" Organisation policy: ") + source_default.dim(`installs restricted to ${patterns.join(", ")}`));
@@ -66072,7 +66190,7 @@ function pluginSourceListCommand() {
66072
66190
  console.log(source_default.bold(" Declared plugin sources:"));
66073
66191
  for (const s2 of sources) {
66074
66192
  const tier = s2.tier === "project" ? source_default.yellow(s2.tier.padEnd(9)) : source_default.dim(s2.tier.padEnd(9));
66075
- const blocked = !(0, import_code_core4.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
66193
+ const blocked = !(0, import_code_core5.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
66076
66194
  console.log(" " + source_default.cyan(s2.name.padEnd(20)) + tier + source_default.white(s2.spec) + blocked);
66077
66195
  }
66078
66196
  console.log();
@@ -66082,17 +66200,17 @@ function pluginSourceListCommand() {
66082
66200
  }
66083
66201
  function pluginSourceAddCommand(name, spec, opts) {
66084
66202
  try {
66085
- (0, import_code_core4.parsePluginSource)(spec);
66086
- const patterns = (0, import_code_core4.allowedSourcePatterns)();
66087
- if (patterns && !(0, import_code_core4.isSourceAllowed)(spec, patterns)) {
66203
+ (0, import_code_core5.parsePluginSource)(spec);
66204
+ const patterns = (0, import_code_core5.allowedSourcePatterns)();
66205
+ if (patterns && !(0, import_code_core5.isSourceAllowed)(spec, patterns)) {
66088
66206
  console.error(source_default.red(` \u2717 "${spec}" is not permitted by your organisation's policy.`));
66089
66207
  console.error(source_default.dim(` Allowed: ${patterns.join(", ")}`));
66090
66208
  process.exitCode = 1;
66091
66209
  return;
66092
66210
  }
66093
66211
  const scope = opts.project ? "project" : "user";
66094
- const file = (0, import_code_core4.sourcesFileFor)(scope, process.cwd());
66095
- (0, import_code_core4.writeDeclaredSource)(file, name, spec);
66212
+ const file = (0, import_code_core5.sourcesFileFor)(scope, process.cwd());
66213
+ (0, import_code_core5.writeDeclaredSource)(file, name, spec);
66096
66214
  console.log();
66097
66215
  console.log(source_default.green(` \u2713 Declared "${name}" \u2192 ${spec}`) + source_default.dim(` (${scope})`));
66098
66216
  console.log(source_default.dim(` ${file}`));
@@ -66106,13 +66224,13 @@ function pluginSourceAddCommand(name, spec, opts) {
66106
66224
  function pluginSourceRemoveCommand(name, opts) {
66107
66225
  const workDir = process.cwd();
66108
66226
  const scope = opts.project ? "project" : "user";
66109
- const file = (0, import_code_core4.sourcesFileFor)(scope, workDir);
66110
- if ((0, import_code_core4.removeDeclaredSource)(file, name)) {
66227
+ const file = (0, import_code_core5.sourcesFileFor)(scope, workDir);
66228
+ if ((0, import_code_core5.removeDeclaredSource)(file, name)) {
66111
66229
  console.log(source_default.green(` \u2713 Removed source "${name}" (${scope})`));
66112
66230
  console.log(source_default.dim(" Plugins already installed from it are untouched \u2014 remove them with nex plugin remove <name>"));
66113
66231
  return;
66114
66232
  }
66115
- const found = (0, import_code_core4.resolveSourceAlias)(name, workDir, { includeProject: true });
66233
+ const found = (0, import_code_core5.resolveSourceAlias)(name, workDir, { includeProject: true });
66116
66234
  if (found) {
66117
66235
  console.error(source_default.red(` \u2717 "${name}" is declared in the ${found.tier} tier, not ${scope}.`));
66118
66236
  console.error(source_default.dim(` ${found.file}`));
@@ -66128,7 +66246,7 @@ function pluginSourceRemoveCommand(name, opts) {
66128
66246
 
66129
66247
  // src/index.ts
66130
66248
  var program2 = new Command();
66131
- program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.56").enablePositionalOptions();
66249
+ program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.58").enablePositionalOptions();
66132
66250
  program2.command("auth").description("Login to your Nexrall account").action(authCommand);
66133
66251
  program2.command("logout").description("Log out of your Nexrall account").action(logoutCommand);
66134
66252
  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) => {
@@ -66200,7 +66318,7 @@ program2.command("sessions").description("List or delete saved chat sessions").o
66200
66318
  console.log();
66201
66319
  });
66202
66320
  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) => {
66203
- if (!(0, import_code_core5.isAuthenticated)()) {
66321
+ if (!(0, import_code_core6.isAuthenticated)()) {
66204
66322
  console.error("Not logged in. Run: nex auth");
66205
66323
  process.exit(1);
66206
66324
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.56",
3
+ "version": "0.5.58",
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.31"
44
+ "@nexrall/code-core": "1.4.33"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@aws-sdk/client-s3": "^3.600.0",