nexrall-code 0.5.198 → 0.5.200

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +140 -38
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -80,7 +80,7 @@ Run `nex --help` for the full list.
80
80
 
81
81
  ## Issues
82
82
 
83
- Bug reports and feature requests: **[github.com/Maxrall-Inc/nexrall-issue](https://github.com/Maxrall-Inc/nexrall-issue/issues)**.
83
+ Bug reports and feature requests: **[github.com/Maxrall-Inc/nexrall-issues](https://github.com/Maxrall-Inc/nexrall-issues/issues)**.
84
84
 
85
85
  ## License
86
86
 
package/dist/index.js CHANGED
@@ -10647,6 +10647,13 @@ var require_client = __commonJS({
10647
10647
  break;
10648
10648
  }
10649
10649
  case "context_warning": {
10650
+ const message = typeof evt.message === "string" ? evt.message : "";
10651
+ onEvent({
10652
+ type: "context_warning",
10653
+ message,
10654
+ ...typeof evt.reason === "string" ? { reason: evt.reason } : {},
10655
+ ...typeof evt.trimmed === "number" ? { trimmed: evt.trimmed } : {}
10656
+ });
10650
10657
  break;
10651
10658
  }
10652
10659
  case "notice": {
@@ -14912,7 +14919,7 @@ var require_agentTypes = __commonJS({
14912
14919
  };
14913
14920
  }();
14914
14921
  Object.defineProperty(exports, "__esModule", { value: true });
14915
- exports.MODEL_TIER_ALIASES = exports.VALID_MODELS = void 0;
14922
+ exports.SUGGESTED_MODELS = exports.MODEL_TIER_ALIASES = exports.VALID_MODELS = void 0;
14916
14923
  exports.normaliseToolName = normaliseToolName;
14917
14924
  exports.parseModel = parseModel;
14918
14925
  exports.parseAgentHooks = parseAgentHooks;
@@ -15183,13 +15190,15 @@ var require_agentTypes = __commonJS({
15183
15190
  "gpt-5.4",
15184
15191
  "gpt-5.4-mini",
15185
15192
  "gpt-4.1",
15186
- // Legacy tier aliases — still accepted, still resolved by the backend.
15193
+ // Legacy tier words — accepted from older files (and still resolved by the
15194
+ // backend), never suggested: they say nothing about which model runs now.
15187
15195
  "turbo",
15188
15196
  "pro",
15189
15197
  "ultra",
15190
15198
  "fast"
15191
15199
  ];
15192
15200
  exports.MODEL_TIER_ALIASES = ["turbo", "pro", "ultra", "fast"];
15201
+ exports.SUGGESTED_MODELS = exports.VALID_MODELS.filter((m2) => !exports.MODEL_TIER_ALIASES.includes(m2));
15193
15202
  function parseModel(v) {
15194
15203
  const raw = (v ?? "").trim();
15195
15204
  if (!raw)
@@ -15284,7 +15293,7 @@ var require_agentTypes = __commonJS({
15284
15293
  warnings.push({
15285
15294
  file: full,
15286
15295
  agent: name,
15287
- message: `has model: "${meta.model}", which this version does not recognise \u2014 expected one of ${exports.VALID_MODELS.join(", ")}, or omit the line to inherit the current session's model. It will still be sent; the server decides whether it is valid.`
15296
+ message: `has model: "${meta.model}", which this version does not recognise \u2014 expected one of ${exports.SUGGESTED_MODELS.join(", ")}, or omit the line to inherit the current session's model. It will still be sent; the server decides whether it is valid.`
15288
15297
  });
15289
15298
  }
15290
15299
  const unknown = (tools ?? []).filter((t2) => !KNOWN_TOOL_NAMES.has(t2) && !t2.includes("__"));
@@ -15901,7 +15910,7 @@ var require_skills = __commonJS({
15901
15910
  warnings.push({
15902
15911
  file,
15903
15912
  name: effectiveName,
15904
- message: `has model: "${meta.model}", which this version does not recognise \u2014 expected one of ${agentTypes_1.VALID_MODELS.join(", ")}, or omit the line to inherit the current session's model. It will still be sent; the server decides whether it is valid.`
15913
+ message: `has model: "${meta.model}", which this version does not recognise \u2014 expected one of ${agentTypes_1.SUGGESTED_MODELS.join(", ")}, or omit the line to inherit the current session's model. It will still be sent; the server decides whether it is valid.`
15905
15914
  });
15906
15915
  }
15907
15916
  const ctx = meta.context?.trim().toLowerCase();
@@ -24034,7 +24043,7 @@ ${body}`
24034
24043
  let replyText = "";
24035
24044
  for (let round = 0; round < (isAgent ? 6 : 1); round++) {
24036
24045
  const msg = await (0, client_1.streamChat)(messages, {
24037
- model: hook.model ?? opts.model ?? "turbo",
24046
+ model: hook.model ?? opts.model ?? "claude-sonnet-5-5",
24038
24047
  env: opts.envCtx ?? { cwd: opts.cwd },
24039
24048
  abortSignal: ctl,
24040
24049
  // Wire the tools by allowlist rather than a separate channel: the backend
@@ -24092,7 +24101,7 @@ ${out.output}` : `Error: ${out.error}` : out.output ?? "",
24092
24101
  return ["read_file", "search_files", "list_directory", "glob"];
24093
24102
  }
24094
24103
  function hookRunOptsFor(options) {
24095
- return { model: options.model ?? "turbo", abortSignal: options.abortSignal, hookEnv: options.env };
24104
+ return { model: options.model ?? "claude-sonnet-5-5", abortSignal: options.abortSignal, hookEnv: options.env };
24096
24105
  }
24097
24106
  function classifyStopFailure(err) {
24098
24107
  const status = err?.status;
@@ -24551,8 +24560,10 @@ var require_compaction = __commonJS({
24551
24560
  "../core/dist/agent/compaction.js"(exports) {
24552
24561
  "use strict";
24553
24562
  Object.defineProperty(exports, "__esModule", { value: true });
24554
- exports.CompactionUnavailableError = exports.PRUNE_KEEP_RECENT = exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.MAX_BODY_BYTES = exports.COMPACT_MAX_FAILURES = exports.COMPACT_MIN_RECLAIM_BYTES = exports.COMPACT_KEEP_MIN = exports._lastApiCallEndedAt = exports.PRUNE_MIN_RECLAIM_BYTES = exports.MODEL_CONTEXT_TOKENS = void 0;
24563
+ exports.BYTES_PER_TOKEN_ESTIMATE = exports.CompactionUnavailableError = exports.PRUNE_KEEP_RECENT = exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.MAX_BODY_BYTES = exports.COMPACT_MAX_FAILURES = exports.COMPACT_MIN_RECLAIM_BYTES = exports.COMPACT_KEEP_MIN = exports._lastApiCallEndedAt = exports.PRUNE_MIN_RECLAIM_BYTES = exports.MODEL_CONTEXT_TOKENS = void 0;
24555
24564
  exports.contextWindowFor = contextWindowFor2;
24565
+ exports.outputReserveFor = outputReserveFor;
24566
+ exports.serverMessageBudgetFor = serverMessageBudgetFor;
24556
24567
  exports.compactionLimits = compactionLimits;
24557
24568
  exports.compactionThresholds = compactionThresholds2;
24558
24569
  exports.pruneReclaimFloor = pruneReclaimFloor;
@@ -24582,8 +24593,9 @@ var require_compaction = __commonJS({
24582
24593
  var safeSlice_1 = require_safeSlice();
24583
24594
  var hooks_1 = require_hooks();
24584
24595
  exports.MODEL_CONTEXT_TOKENS = {
24585
- // Tier aliases — still sent by older clients, saved settings and sub-agent
24586
- // frontmatter, so they must keep resolving.
24596
+ // Legacy tier words — VALUES from older clients, saved settings and sub-agent
24597
+ // frontmatter must keep resolving (2026-10-05: the words were removed from
24598
+ // every surface; nothing offers them anymore, but saved data still carries them).
24587
24599
  turbo: 1e6,
24588
24600
  pro: 1e6,
24589
24601
  ultra: 1e6,
@@ -24625,7 +24637,7 @@ var require_compaction = __commonJS({
24625
24637
  "glm-5.3": 1048576
24626
24638
  };
24627
24639
  function contextWindowFor2(model) {
24628
- const fallback = exports.MODEL_CONTEXT_TOKENS[model ?? "turbo"] ?? 128e3;
24640
+ const fallback = exports.MODEL_CONTEXT_TOKENS[model ?? "claude-sonnet-5-5"] ?? 128e3;
24629
24641
  return (0, modelCatalogue_1.liveContextWindowFor)(model, fallback);
24630
24642
  }
24631
24643
  function envFraction(name, fallback) {
@@ -24644,17 +24656,34 @@ var require_compaction = __commonJS({
24644
24656
  return fromSettings;
24645
24657
  return void 0;
24646
24658
  }
24647
- function compactionLimits(contextWindow, settingsRaw) {
24659
+ var SERVER_ESTIMATE_RATIO = 0.875;
24660
+ var SERVER_OVERHEAD_TOKENS = 4e4;
24661
+ var SERVER_BUDGET_SAFETY = 0.9;
24662
+ var MIN_SERVER_AWARE_COMPACT = 15e3;
24663
+ function outputReserveFor(contextWindow, model) {
24664
+ return (0, modelCatalogue_1.liveMaxOutputTokensFor)(model, Math.min(128e3, Math.max(16384, Math.floor(contextWindow * 0.2))));
24665
+ }
24666
+ function serverMessageBudgetFor(contextWindow, model) {
24667
+ const hard = contextWindow - outputReserveFor(contextWindow, model) - SERVER_OVERHEAD_TOKENS - Math.floor(contextWindow * 0.03);
24668
+ return Math.max(0, hard);
24669
+ }
24670
+ function serverAwareCompactLine(contextWindow, model) {
24671
+ const converted = Math.floor(serverMessageBudgetFor(contextWindow, model) * SERVER_ESTIMATE_RATIO * SERVER_BUDGET_SAFETY);
24672
+ return Math.max(MIN_SERVER_AWARE_COMPACT, converted);
24673
+ }
24674
+ function compactionLimits(contextWindow, settingsRaw, model) {
24648
24675
  const cap = compactWindowCap(settingsRaw);
24649
24676
  const eff = cap === void 0 ? contextWindow : Math.min(contextWindow, cap);
24650
24677
  const compactFrac = envFraction("NEXRALL_COMPACT_THRESHOLD", 0);
24651
24678
  const pruneFrac = envFraction("NEXRALL_PRUNE_THRESHOLD", 0);
24652
- const compact = compactFrac ? eff * compactFrac : Math.max(eff * 0.5, eff - Math.min(COMPACT_OUTPUT_RESERVE, eff * 0.1) - COMPACT_BUFFER_TOKENS);
24679
+ let compact = compactFrac ? eff * compactFrac : Math.max(eff * 0.5, eff - Math.min(COMPACT_OUTPUT_RESERVE, eff * 0.1) - COMPACT_BUFFER_TOKENS);
24680
+ if (model !== void 0)
24681
+ compact = Math.min(compact, serverAwareCompactLine(contextWindow, model));
24653
24682
  const prune = Math.min(pruneFrac ? eff * pruneFrac : eff * DEFAULT_PRUNE_FRACTION, compact * 0.9);
24654
24683
  return { prune: Math.floor(prune), compact: Math.floor(compact) };
24655
24684
  }
24656
- function compactionThresholds2(contextWindow = 1e6, settingsRaw) {
24657
- const { prune, compact } = compactionLimits(contextWindow, settingsRaw);
24685
+ function compactionThresholds2(contextWindow = 1e6, settingsRaw, model) {
24686
+ const { prune, compact } = compactionLimits(contextWindow, settingsRaw, model);
24658
24687
  return { prune: prune / contextWindow, compact: compact / contextWindow };
24659
24688
  }
24660
24689
  exports.PRUNE_MIN_RECLAIM_BYTES = 96 * 1024;
@@ -24897,11 +24926,22 @@ ${tail}`;
24897
24926
  }
24898
24927
  return reclaimed;
24899
24928
  }
24929
+ var ORIGINAL_TASK_MARKER = "ORIGINAL TASK (verbatim \u2014 keep working toward this, do not lose sight of it):\n";
24930
+ var COMPACT_PREAMBLE_PREFIX = "[Auto-compacted ";
24900
24931
  function originalTaskText(messages) {
24901
24932
  const first = messages.find((m2) => m2.role === "user");
24902
24933
  if (!first || !Array.isArray(first.content))
24903
24934
  return "";
24904
- return first.content.filter((b) => b.type === "text" && b.text && !(0, types_1.isRuntimeContextBlock)(b)).map((b) => b.text).join("\n").trim();
24935
+ const text = first.content.filter((b) => b.type === "text" && b.text && !(0, types_1.isRuntimeContextBlock)(b)).map((b) => b.text).join("\n").trim();
24936
+ if (text.startsWith(COMPACT_PREAMBLE_PREFIX)) {
24937
+ const at = text.indexOf(ORIGINAL_TASK_MARKER);
24938
+ if (at >= 0) {
24939
+ const rest = text.slice(at + ORIGINAL_TASK_MARKER.length);
24940
+ const end = rest.search(/\n\n(PROGRESS LEDGER|Summary of the earlier conversation so far:)/);
24941
+ return (end >= 0 ? rest.slice(0, end) : rest).trim();
24942
+ }
24943
+ }
24944
+ return text;
24905
24945
  }
24906
24946
  var CompactionUnavailableError = class extends Error {
24907
24947
  constructor() {
@@ -24981,7 +25021,7 @@ Do NOT call any tools and do NOT continue the task. Reply with text only: a conc
24981
25021
  // summarizeCached above, which must stay on the conversation's own model.
24982
25022
  // Never crosses providers; falls back to the session model if the
24983
25023
  // catalogue is not loaded.
24984
- model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "turbo") ?? options.model ?? "turbo",
25024
+ model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "claude-sonnet-5-5") ?? options.model ?? "claude-sonnet-5-5",
24985
25025
  mode: "ask",
24986
25026
  // summariser must not call tools; ask-mode discourages action
24987
25027
  env: options.env,
@@ -25000,8 +25040,7 @@ Do NOT call any tools and do NOT continue the task. Reply with text only: a conc
25000
25040
  }
25001
25041
  if (!summary)
25002
25042
  return false;
25003
- const taskBlock = originalTask ? `ORIGINAL TASK (verbatim \u2014 keep working toward this, do not lose sight of it):
25004
- ${originalTask}
25043
+ const taskBlock = originalTask ? `${ORIGINAL_TASK_MARKER}${originalTask}
25005
25044
 
25006
25045
  ` : "";
25007
25046
  const ledgerText = ledger ? ledgerSummary(ledger) : "";
@@ -25035,7 +25074,7 @@ Continue the work from here.`
25035
25074
  // (which silently billed Anthropic regardless of the user's provider).
25036
25075
  // Cheapest SAME-vendor model: a fresh prompt with no shared cache prefix,
25037
25076
  // and merging a few memory bullets does not need the session's top tier.
25038
- model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "turbo") ?? options.model ?? "turbo",
25077
+ model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "claude-sonnet-5-5") ?? options.model ?? "claude-sonnet-5-5",
25039
25078
  mode: "ask",
25040
25079
  env: options.env,
25041
25080
  clientType: options.clientType,
@@ -25050,9 +25089,9 @@ Continue the work from here.`
25050
25089
  } catch {
25051
25090
  }
25052
25091
  }
25053
- var RESUME_CHARS_PER_TOKEN = 4;
25092
+ exports.BYTES_PER_TOKEN_ESTIMATE = 4;
25054
25093
  function estimateTokensRough3(messages) {
25055
- return Math.ceil(estimateBodyBytes2(messages) / RESUME_CHARS_PER_TOKEN);
25094
+ return Math.ceil(estimateBodyBytes2(messages) / exports.BYTES_PER_TOKEN_ESTIMATE);
25056
25095
  }
25057
25096
  async function compactMessagesForResume2(messages, opts) {
25058
25097
  if (messages.length <= exports.COMPACT_KEEP_MIN + 2)
@@ -25060,10 +25099,10 @@ Continue the work from here.`
25060
25099
  const settings = (0, rules_1.loadSettings)(opts.workDir);
25061
25100
  if (!resolveAutoCompact(void 0, settings.raw))
25062
25101
  return false;
25063
- const contextWindow = (0, modelCatalogue_1.liveContextWindowFor)(opts.model, exports.MODEL_CONTEXT_TOKENS[opts.model ?? "turbo"] ?? 1e6);
25102
+ const contextWindow = contextWindowFor2(opts.model);
25064
25103
  let bodyBytes = estimateBodyBytes2(messages);
25065
25104
  let tokenGuess = estimateTokensRough3(messages);
25066
- const limits = compactionLimits(contextWindow, settings.raw);
25105
+ const limits = compactionLimits(contextWindow, settings.raw, opts.model);
25067
25106
  const overPruneThreshold = () => tokenGuess > limits.prune || bodyBytes > exports.MAX_BODY_BYTES;
25068
25107
  const overCompactThreshold = () => tokenGuess > limits.compact || bodyBytes > exports.MAX_BODY_BYTES;
25069
25108
  if (!overPruneThreshold())
@@ -26593,8 +26632,8 @@ var require_loop = __commonJS({
26593
26632
  "../core/dist/agent/loop.js"(exports) {
26594
26633
  "use strict";
26595
26634
  Object.defineProperty(exports, "__esModule", { value: true });
26596
- exports.stopReasonNotice = exports.executeAgentMemoryWrite = exports.AGENT_MEMORY_TOOL_SCHEMA = exports.AGENT_MEMORY_TOOL = exports._stallLimits = exports.errorRoundSignature = exports._emptyTurnRetry = exports.shouldRetryEmptyTurn = exports.emptyTurnBackoffMs = exports.compactMessagesForResume = exports.estimateTokensRough = exports.makeCachedSummarizer = exports.pruneOldToolResults = exports.ledgerSummary = exports.ledgerRecord = exports.createLedger = exports.transcriptOf = exports.persistRuntimeContext = exports.findSafeCutIndex = exports.VERIFY_CMD_RE = exports.allowsTestOnlyWrite = exports.WRITE_TOOL_NAMES = exports.estimateBodyBytes = exports.pruneReclaimFloor = exports.compactionThresholds = exports.compactionLimits = exports.contextWindowFor = exports.runElicitationResultHooks = exports.runElicitationHooks = exports.hasHookEventListener = exports.setHookEventListener = exports.queueHookDelivery = exports.resetHookOnceState = exports.setHookMcpCaller = exports.setHookStatusListener = exports.setHookWakeListener = exports.formatHookDeliveries = exports.hasPendingHookWake = exports.takeHookWakes = exports.drainHookDeliveries = exports.fireObserverHook = exports.fireManualPreCompactHook = exports.fireManualPostCompactHook = exports.fireNotificationHooks = exports.runPermissionRequestHooks = exports.runLifecycleHooks = exports.classifyStopFailure = exports.parsePromptHookReply = exports.loadHooks = exports.bashNeedsRepoLock = void 0;
26597
- exports.lastToolResults = exports.summariseSubTaskProgress = exports.capSubTaskText = exports.extractSubTaskText = exports.ToolNotAllowedError = exports.resolveSubtaskTimeoutMs = exports.canSpawnSubAgents = exports.intersectAllowlists = exports.noSpawnReason = exports.resolveMaxSubagentDepth = exports._sessionSubAgentCount = exports.resetSessionSubAgentBudget = exports._resetSubTaskLimiter = exports.createLimiter = exports.resolveMaxSubagentsPerSession = exports.resolveMaxConcurrentSubtasks = exports.lockPathsFor = exports.resolveMaxIterations = void 0;
26635
+ exports.AGENT_MEMORY_TOOL = exports._stallLimits = exports.errorRoundSignature = exports._emptyTurnRetry = exports.shouldRetryEmptyTurn = exports.emptyTurnBackoffMs = exports.BYTES_PER_TOKEN_ESTIMATE = exports.outputReserveFor = exports.serverMessageBudgetFor = exports.compactMessagesForResume = exports.estimateTokensRough = exports.makeCachedSummarizer = exports.pruneOldToolResults = exports.ledgerSummary = exports.ledgerRecord = exports.createLedger = exports.transcriptOf = exports.persistRuntimeContext = exports.findSafeCutIndex = exports.VERIFY_CMD_RE = exports.allowsTestOnlyWrite = exports.WRITE_TOOL_NAMES = exports.estimateBodyBytes = exports.pruneReclaimFloor = exports.compactionThresholds = exports.compactionLimits = exports.contextWindowFor = exports.runElicitationResultHooks = exports.runElicitationHooks = exports.hasHookEventListener = exports.setHookEventListener = exports.queueHookDelivery = exports.resetHookOnceState = exports.setHookMcpCaller = exports.setHookStatusListener = exports.setHookWakeListener = exports.formatHookDeliveries = exports.hasPendingHookWake = exports.takeHookWakes = exports.drainHookDeliveries = exports.fireObserverHook = exports.fireManualPreCompactHook = exports.fireManualPostCompactHook = exports.fireNotificationHooks = exports.runPermissionRequestHooks = exports.runLifecycleHooks = exports.classifyStopFailure = exports.parsePromptHookReply = exports.loadHooks = exports.bashNeedsRepoLock = void 0;
26636
+ exports.lastToolResults = exports.summariseSubTaskProgress = exports.capSubTaskText = exports.extractSubTaskText = exports.ToolNotAllowedError = exports.resolveSubtaskTimeoutMs = exports.canSpawnSubAgents = exports.intersectAllowlists = exports.noSpawnReason = exports.resolveMaxSubagentDepth = exports._sessionSubAgentCount = exports.resetSessionSubAgentBudget = exports._resetSubTaskLimiter = exports.createLimiter = exports.resolveMaxSubagentsPerSession = exports.resolveMaxConcurrentSubtasks = exports.lockPathsFor = exports.resolveMaxIterations = exports.stopReasonNotice = exports.executeAgentMemoryWrite = exports.AGENT_MEMORY_TOOL_SCHEMA = void 0;
26598
26637
  exports.dispatchSubAgent = dispatchSubAgent;
26599
26638
  exports.dispatchBackgroundSubAgent = dispatchBackgroundSubAgent;
26600
26639
  exports.dispatchForkedSubAgent = dispatchForkedSubAgent2;
@@ -26753,6 +26792,15 @@ var require_loop = __commonJS({
26753
26792
  Object.defineProperty(exports, "compactMessagesForResume", { enumerable: true, get: function() {
26754
26793
  return compaction_2.compactMessagesForResume;
26755
26794
  } });
26795
+ Object.defineProperty(exports, "serverMessageBudgetFor", { enumerable: true, get: function() {
26796
+ return compaction_2.serverMessageBudgetFor;
26797
+ } });
26798
+ Object.defineProperty(exports, "outputReserveFor", { enumerable: true, get: function() {
26799
+ return compaction_2.outputReserveFor;
26800
+ } });
26801
+ Object.defineProperty(exports, "BYTES_PER_TOKEN_ESTIMATE", { enumerable: true, get: function() {
26802
+ return compaction_2.BYTES_PER_TOKEN_ESTIMATE;
26803
+ } });
26756
26804
  var iterationPolicy_1 = require_iterationPolicy();
26757
26805
  var iterationPolicy_2 = require_iterationPolicy();
26758
26806
  Object.defineProperty(exports, "emptyTurnBackoffMs", { enumerable: true, get: function() {
@@ -27019,7 +27067,7 @@ var require_loop = __commonJS({
27019
27067
  }
27020
27068
  async function runAgentLoop2(initialMessages, options) {
27021
27069
  const messages = [...initialMessages];
27022
- const model = options.model ?? "turbo";
27070
+ const model = options.model ?? "claude-sonnet-5-5";
27023
27071
  const hooks = options.disableHooks ? (0, hooks_1.withAgentHooks)({}, options._agentHooks) : (0, hooks_1.withAgentHooks)((0, hooks_1.loadHooks)(options.workDir), options._agentHooks);
27024
27072
  const fireStopFailure = async (failure) => {
27025
27073
  if (depth !== 0)
@@ -27173,7 +27221,7 @@ ${ctx}
27173
27221
  const autoCompact = (0, compaction_1.resolveAutoCompact)(options.autoCompact, settings.raw);
27174
27222
  const verifyNudgeOn = (0, compaction_1.resolveVerificationNudge)(settings.raw);
27175
27223
  const contextWindow = (0, modelCatalogue_1.liveContextWindowFor)(model, compaction_1.MODEL_CONTEXT_TOKENS[model] ?? 2e5);
27176
- const compactLimits = (0, compaction_1.compactionLimits)(contextWindow, settings.raw);
27224
+ const compactLimits = (0, compaction_1.compactionLimits)(contextWindow, settings.raw, model);
27177
27225
  const readDedupe = new readDedupe_1.ReadDedupe(options.workDir);
27178
27226
  const drainBackgroundNotifications = () => depth === 0 ? options.backgroundAgents?.takeNotifications() ?? [] : [];
27179
27227
  const collectTaskEventTexts = async () => {
@@ -27210,6 +27258,9 @@ ${extra}` : extra;
27210
27258
  return texts;
27211
27259
  };
27212
27260
  let lastPromptTokens2 = 0;
27261
+ let serverTrimmed = false;
27262
+ let serverTrimNoticeShown = false;
27263
+ let contextWarnNoticeShown = false;
27213
27264
  let compacting = false;
27214
27265
  const hardCap = autoContinue ? Math.max(maxIterations, iterationPolicy_1.MAX_ITERATIONS_CEILING) : maxIterations;
27215
27266
  let stopReason = "unknown";
@@ -27240,8 +27291,9 @@ ${extra}` : extra;
27240
27291
  break;
27241
27292
  }
27242
27293
  let bodyBytes = (0, compaction_1.estimateBodyBytes)(messages);
27243
- const prunePressure = lastPromptTokens2 > compactLimits.prune;
27244
- const tokenPressure = lastPromptTokens2 > compactLimits.compact;
27294
+ const localTokens = Math.ceil(bodyBytes / compaction_1.BYTES_PER_TOKEN_ESTIMATE);
27295
+ const prunePressure = lastPromptTokens2 > compactLimits.prune || localTokens > compactLimits.prune;
27296
+ const tokenPressure = lastPromptTokens2 > compactLimits.compact || localTokens > compactLimits.compact || serverTrimmed;
27245
27297
  let bytePressure = bodyBytes > compaction_1.MAX_BODY_BYTES;
27246
27298
  if (autoCompact && !compacting && (prunePressure || bytePressure) && messages.length > compaction_1.PRUNE_KEEP_RECENT + 2) {
27247
27299
  const floor = depth === 0 ? (0, compaction_1.pruneReclaimFloor)(compaction_1._lastApiCallEndedAt.get(options.sessionId || subAgentBudget_1.PROCESS_BUDGET_KEY)) : compaction_1.PRUNE_MIN_RECLAIM_BYTES;
@@ -27272,9 +27324,12 @@ ${extra}` : extra;
27272
27324
  const reclaimed = bytesBefore - bytesAfter;
27273
27325
  if (did) {
27274
27326
  lastPromptTokens2 = 0;
27275
- const reason = bytePressure ? `body ~${(bodyBytes / (1024 * 1024)).toFixed(1)}MB` : "context window";
27327
+ serverTrimmed = false;
27276
27328
  bodyBytes = bytesAfter;
27277
27329
  bytePressure = bodyBytes > compaction_1.MAX_BODY_BYTES;
27330
+ if (isMainAgent) {
27331
+ (options.onNotice ?? options.onText)(`\u267B\uFE0F Auto-compacted this chat's earlier history to keep it within the context budget.`);
27332
+ }
27278
27333
  }
27279
27334
  if (unavailable) {
27280
27335
  } else if (did && reclaimed >= compaction_1.COMPACT_MIN_RECLAIM_BYTES) {
@@ -27337,6 +27392,24 @@ ${extra}` : extra;
27337
27392
  case "runtime_context":
27338
27393
  pendingRuntimeContext = event.text;
27339
27394
  break;
27395
+ case "context_warning": {
27396
+ if (event.reason === "overflow")
27397
+ break;
27398
+ if (event.reason === "history-trim") {
27399
+ serverTrimmed = true;
27400
+ if (isMainAgent && !serverTrimNoticeShown) {
27401
+ serverTrimNoticeShown = true;
27402
+ const what = typeof event.trimmed === "number" && event.trimmed > 0 ? `${event.trimmed} oldest message(s)` : "the oldest turns";
27403
+ (options.onNotice ?? options.onText)(`\u26A0\uFE0F This chat exceeds what ${model} can carry alongside its output budget \u2014 the server dropped ${what} from what the model saw this turn. ` + (autoCompact ? "Auto-compaction will summarise the history at the next step so it stops recurring." : "Enable autoCompact or run /compact to re-summarise the history."));
27404
+ }
27405
+ break;
27406
+ }
27407
+ if (isMainAgent && !contextWarnNoticeShown && event.message) {
27408
+ contextWarnNoticeShown = true;
27409
+ (options.onNotice ?? options.onText)(`\u26A0\uFE0F ${event.message}`);
27410
+ }
27411
+ break;
27412
+ }
27340
27413
  case "notice":
27341
27414
  options.onNotice?.(event.message);
27342
27415
  break;
@@ -106648,6 +106721,8 @@ ${text}` : "");
106648
106721
  void (0, import_code_core65.getModelCatalogue)().then((cat) => {
106649
106722
  if (!cat || !cat.isFreeTier || !cat.defaultModel)
106650
106723
  return;
106724
+ if (!cat.models.some((m2) => m2.id === cat.defaultModel))
106725
+ return;
106651
106726
  if (modelAlias === cat.defaultModel)
106652
106727
  return;
106653
106728
  const prev = resolveModelLabel(modelAlias);
@@ -106663,6 +106738,8 @@ ${text}` : "");
106663
106738
  void (0, import_code_core65.getModelCatalogue)().then((cat) => {
106664
106739
  if (!cat || cat.isFreeTier || !cat.defaultModel)
106665
106740
  return;
106741
+ if (!cat.models.some((m2) => m2.id === cat.defaultModel))
106742
+ return;
106666
106743
  if (options.modelExplicit !== false)
106667
106744
  return;
106668
106745
  if (agentRunning)
@@ -109838,7 +109915,7 @@ ${text}
109838
109915
  }
109839
109916
  const measure = measureContext(messages, parsed.all ? TOP_ALL : TOP_DEFAULT);
109840
109917
  const window2 = (0, import_code_core65.contextWindowFor)(modelAlias);
109841
- const thresholds = (0, import_code_core65.compactionThresholds)(window2);
109918
+ const thresholds = (0, import_code_core65.compactionThresholds)(window2, (0, import_code_core67.loadSettings)(workDir).raw, modelAlias);
109842
109919
  for (const line of formatContextPanel({
109843
109920
  measure,
109844
109921
  window: window2,
@@ -112011,6 +112088,27 @@ async function setupSessionPlugins(dirs = [], urls = []) {
112011
112088
  return { roots: roots2, errors, temps };
112012
112089
  }
112013
112090
 
112091
+ // src/removedFlags.ts
112092
+ var REMOVED_MODEL_SHORTCUTS = {
112093
+ "-t": "claude-sonnet-5-5",
112094
+ "--turbo": "claude-sonnet-5-5",
112095
+ "-p": "claude-opus-5-5",
112096
+ "--pro": "claude-opus-5-5",
112097
+ "-u": "claude-fable-5-1",
112098
+ "--ultra": "claude-fable-5-1"
112099
+ };
112100
+ function removedModelShortcutMessage(argv) {
112101
+ for (const token of argv) {
112102
+ if (token === "--" || !token.startsWith("-"))
112103
+ break;
112104
+ const replacement = REMOVED_MODEL_SHORTCUTS[token];
112105
+ if (replacement !== void 0) {
112106
+ return `The ${token} model shorthand was removed \u2014 select the model by name instead: nex -m ${replacement} (or --model <id>). Run \`nex --help\` for the current flags.`;
112107
+ }
112108
+ }
112109
+ return null;
112110
+ }
112111
+
112014
112112
  // src/managedVersion.ts
112015
112113
  var import_code_core73 = __toESM(require_dist2(), 1);
112016
112114
  var VERSION_GATE_EXEMPT = /* @__PURE__ */ new Set(["update", "doctor", "help"]);
@@ -113406,7 +113504,7 @@ program2.command("sessions").description("List, export, import, or delete saved
113406
113504
  console.log(paint.dim(" nex sessions --events <id> [--json] to follow its event stream"));
113407
113505
  console.log();
113408
113506
  });
113409
- 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(
113507
+ program2.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(
113410
113508
  "--auto",
113411
113509
  "Start in auto mode (the default \u2014 edits and commands run without asking; irreversible actions are still confirmed)"
113412
113510
  ).option("--mode <mode>", "Starting permission mode: ask | edit | auto | plan").option(
@@ -113424,10 +113522,7 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
113424
113522
  ).option(
113425
113523
  "-e, --effort <level>",
113426
113524
  "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"
113427
- ).option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option(
113428
- "--print",
113429
- "One-shot, non-interactive run that prints the answer and exits (same as --output-format text). Claude Code's `-p` is spelled --print here because `-p` already means --pro"
113430
- ).option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option(
113525
+ ).option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--print", "One-shot, non-interactive run that prints the answer and exits (same as --output-format text)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option(
113431
113526
  "--audit [path]",
113432
113527
  "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)"
113433
113528
  ).option(
@@ -113498,7 +113593,7 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
113498
113593
  console.error("Not logged in. Run: nex auth");
113499
113594
  process.exit(1);
113500
113595
  }
113501
- const model = options.model ? options.model : options.ultra ? "claude-fable-5-1" : options.pro ? "claude-opus-5-5" : options.turbo ? "claude-sonnet-5-5" : "deepseek-flash";
113596
+ const model = options.model ?? "deepseek-flash";
113502
113597
  const workDir = options.dir ? path35.resolve(options.dir) : process.cwd();
113503
113598
  {
113504
113599
  const dirs = Array.isArray(options.pluginDir) ? options.pluginDir : [];
@@ -113865,7 +113960,7 @@ program2.option("-p, --pro", "Use Claude Opus 5.5 (most capable)").option("-t, -
113865
113960
  }
113866
113961
  effort = lvl;
113867
113962
  }
113868
- const modelExplicit = !!(options.model || options.ultra || options.pro || options.turbo || selectedAgent?.model);
113963
+ const modelExplicit = !!(options.model || selectedAgent?.model);
113869
113964
  await startChatSession({
113870
113965
  model,
113871
113966
  modelExplicit,
@@ -113921,6 +114016,13 @@ var project = program2.command("project").description("Manage a project's local
113921
114016
  project.command("purge [dir]").description("Delete this project's local state: sessions, event logs, task board, checkpoints, prompt history").option("--dry-run", "List what would be removed without removing it").option("-y, --yes", "Skip the confirmation prompt (required when stdin is not a TTY)").action(async (dir, opts) => {
113922
114017
  await projectPurgeCommand(dir, opts);
113923
114018
  });
114019
+ {
114020
+ const removed = removedModelShortcutMessage(process.argv.slice(2));
114021
+ if (removed) {
114022
+ console.error(removed);
114023
+ process.exit(1);
114024
+ }
114025
+ }
113924
114026
  {
113925
114027
  const block = managedVersionBlock(NEX_VERSION, process.argv.slice(2));
113926
114028
  if (block) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.198",
3
+ "version": "0.5.200",
4
4
  "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",
@@ -13,7 +13,7 @@
13
13
  ],
14
14
  "homepage": "https://nexrall.com",
15
15
  "bugs": {
16
- "url": "https://github.com/Maxrall-Inc/nexrall-issue/issues"
16
+ "url": "https://github.com/Maxrall-Inc/nexrall-issues/issues"
17
17
  },
18
18
  "license": "MIT",
19
19
  "type": "module",