nexrall-code 0.5.100 → 0.5.101

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 +70 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -153214,6 +153214,59 @@ function normaliseModelId(model) {
153214
153214
  return "claude-sonnet-5";
153215
153215
  return LEGACY_MODEL_ALIASES[raw.toLowerCase()] ?? raw;
153216
153216
  }
153217
+ var MODEL_EFFORT_STYLE = {
153218
+ "gpt-5.4": "openai_gated",
153219
+ "gpt-5.4-mini": "openai_gated",
153220
+ "gpt-4.1": "none",
153221
+ "gpt-4o-mini": "none",
153222
+ "deepseek-v4-pro": "deepseek",
153223
+ "deepseek-v4-flash": "deepseek",
153224
+ "qwen3.7-max": "qwen",
153225
+ "glm-5.3": "glm"
153226
+ // Everything else (all claude-* ids) falls through to 'anthropic' below.
153227
+ };
153228
+ var EFFORT_STYLE_CONFIG = {
153229
+ // Anthropic's real output_config.effort enum is low|medium|high|xhigh|max
153230
+ // (docs.claude.com extended output). 'extra'/'ultra' are legacy UI labels
153231
+ // this codebase invented, translated server-side by routes/code.js's
153232
+ // EFFORT_MAP (extra->xhigh, ultra->max) — kept as the wire values here
153233
+ // (rather than switching to 'xhigh'/'max' directly) only for backward
153234
+ // compatibility with saved sessions/scripts already passing them.
153235
+ anthropic: { levels: ["low", "medium", "high", "extra", "ultra"], names: ["Low", "Medium", "High", "Extra High", "Max"] },
153236
+ // DeepSeek V4 has THREE real buckets — live-verified against
153237
+ // api.deepseek.com 2026-08-30 (see streamFactory.test.js's DEEPSEEK case):
153238
+ // low->low, medium/high/xhigh->high, max->max.
153239
+ deepseek: { levels: ["low", "high", "max"], names: ["Low", "Standard", "Max"] },
153240
+ // Qwen3.7-Max's knob is a boolean (enable_thinking), not a graded scale.
153241
+ qwen: { levels: ["low", "high"], names: ["Thinking Off", "Thinking On"] },
153242
+ // GLM-5.3 cannot disable reasoning at all (a hard 400 if you try) and has
153243
+ // 3 real buckets (low/high/max) via a FLAT top-level `reasoning_effort`
153244
+ // string — live-verified against api.z.ai 2026-08-30 (see
153245
+ // streamFactory.test.js's GLM_THINKING_LEVEL case).
153246
+ glm: { levels: ["low", "high", "max"], names: ["Low", "High", "Max"] },
153247
+ // Effectively a no-op today whenever the turn has tools (almost always true
153248
+ // for nexrall-code) — see backend modelRegistry.js's OPENAI_GATED doc
153249
+ // comment. Still forwards a real value for the rare tool-less turn.
153250
+ openai_gated: { levels: ["low", "medium", "high"], names: ["Low", "Medium", "High"] },
153251
+ // No reasoning-effort concept on this model at all (gpt-4.1, gpt-4o-mini).
153252
+ none: { levels: ["medium"], names: ["N/A"] }
153253
+ };
153254
+ function effortStyleFor(modelId) {
153255
+ return MODEL_EFFORT_STYLE[normaliseModelId(modelId)] ?? "anthropic";
153256
+ }
153257
+ function effortConfigFor(modelId) {
153258
+ return EFFORT_STYLE_CONFIG[effortStyleFor(modelId)];
153259
+ }
153260
+ function clampEffortForModel(effort, modelId) {
153261
+ const config = effortConfigFor(modelId);
153262
+ if (config.levels.includes(effort))
153263
+ return effort;
153264
+ return defaultEffortForModel(modelId);
153265
+ }
153266
+ function defaultEffortForModel(modelId) {
153267
+ const levels = effortConfigFor(modelId).levels;
153268
+ return levels[Math.min(1, levels.length - 1)];
153269
+ }
153217
153270
  function resolveModelLabel(alias) {
153218
153271
  const id = normaliseModelId(alias);
153219
153272
  return MODEL_LABELS[id] ?? id;
@@ -153755,7 +153808,7 @@ function printHelp() {
153755
153808
  ["/help", "Show this help"],
153756
153809
  ["/model [name]", "Switch model (e.g. claude-opus-5, gpt-5.4)"],
153757
153810
  ["/mode [ask|edit|plan|auto]", "Set agent mode"],
153758
- ["/effort [low|medium|high|extra]", "Set thinking effort level"],
153811
+ ["/effort [level]", "Set thinking effort level (options depend on the current model \u2014 run /effort with no argument to see them)"],
153759
153812
  ["/yolo", "Auto-approve all permissions"],
153760
153813
  ["/balance", "Show wallet balance"],
153761
153814
  ["/add <filepath>", "Add a file to conversation context"],
@@ -153876,8 +153929,7 @@ Set ${TRUST_ENV_VAR}=1 to confirm non-interactively, or run \`nex\` interactivel
153876
153929
  let sessionId = crypto4.randomBytes(8).toString("hex");
153877
153930
  let sessionTitle = "";
153878
153931
  let agentMode = "auto";
153879
- const VALID_EFFORT_LEVELS = ["low", "medium", "high", "extra"];
153880
- let effortLevel = options.effort && VALID_EFFORT_LEVELS.includes(options.effort) ? options.effort : "medium";
153932
+ let effortLevel = options.effort ? clampEffortForModel(options.effort, modelAlias) : defaultEffortForModel(modelAlias);
153881
153933
  const permRules = initPermissions(workDir);
153882
153934
  const ruleCount = permRules.allow.length + permRules.ask.length + permRules.deny.length;
153883
153935
  if (ruleCount && !headless)
@@ -154356,7 +154408,13 @@ ${dirList}`;
154356
154408
  console.log(source_default.dim(` Options: ${SELECTABLE_MODELS.map(modelWithCostHint).join(" \xB7 ")}`));
154357
154409
  } else if (SELECTABLE_MODELS.includes(normaliseModelId(requested))) {
154358
154410
  modelAlias = normaliseModelId(requested);
154411
+ const clamped = clampEffortForModel(effortLevel, modelAlias);
154412
+ const effortChanged = clamped !== effortLevel;
154413
+ effortLevel = clamped;
154359
154414
  console.log(source_default.green(` Model \u2192 ${source_default.bold(resolveModelLabel(modelAlias))}`));
154415
+ if (effortChanged) {
154416
+ console.log(source_default.dim(` Effort reset \u2192 ${effortLevel} (previous level not available on this model)`));
154417
+ }
154360
154418
  } else {
154361
154419
  console.log(source_default.red(` Unknown: ${requested}. Options: ${SELECTABLE_MODELS.join(", ")}`));
154362
154420
  }
@@ -154383,13 +154441,15 @@ ${dirList}`;
154383
154441
  }
154384
154442
  case "/effort": {
154385
154443
  const effortArg = arg.toLowerCase();
154444
+ const config = effortConfigFor(modelAlias);
154445
+ const optionsLine = config.levels.map((v, i2) => `${v} (${config.names[i2]})`).join(" \xB7 ");
154386
154446
  if (!effortArg) {
154387
- console.log(source_default.dim(` Current: ${source_default.cyan(effortLevel)} Options: low \xB7 medium \xB7 high \xB7 extra`));
154388
- } else if (["low", "medium", "high", "extra"].includes(effortArg)) {
154447
+ console.log(source_default.dim(` Current: ${source_default.cyan(effortLevel)} Options: ${optionsLine}`));
154448
+ } else if (config.levels.includes(effortArg)) {
154389
154449
  effortLevel = effortArg;
154390
154450
  console.log(source_default.green(` Effort \u2192 ${source_default.bold(effortArg)}`));
154391
154451
  } else {
154392
- console.log(source_default.red(` Unknown: ${effortArg}`));
154452
+ console.log(source_default.red(` Unknown: ${effortArg}. Options: ${optionsLine}`));
154393
154453
  }
154394
154454
  rl.prompt();
154395
154455
  return;
@@ -155151,7 +155211,7 @@ program2.command("sessions").description("List or delete saved chat sessions").o
155151
155211
  console.log(source_default.dim(" nex sessions --delete <id> to remove one"));
155152
155212
  console.log();
155153
155213
  });
155154
- program2.option("-p, --pro", "Use Claude Opus 5 (most capable)").option("-t, --turbo", "Use Claude Sonnet 5 (fast, default)").option("-u, --ultra", "Use 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, e.g. claude-opus-5 | gpt-5.4 | gpt-4.1").option("-r, --resume [id]", "Resume last session, or a specific session id").option("-e, --effort <level>", "Thinking effort: low | medium | high | extra (default: medium)").option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option("--audit [path]", "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
155214
+ program2.option("-p, --pro", "Use Claude Opus 5 (most capable)").option("-t, --turbo", "Use Claude Sonnet 5 (fast, default)").option("-u, --ultra", "Use 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, e.g. claude-opus-5 | gpt-5.4 | gpt-4.1").option("-r, --resume [id]", "Resume last session, or a specific session id").option("-e, --effort <level>", "Thinking effort \u2014 real levels depend on the model (e.g. DeepSeek: low|high|max, Qwen: low|high); run `nex --model <id>` then `/effort` with no argument to see a model's scale").option("--no-banner", "Skip the ASCII banner (useful in scripts/pipes)").option("--output-format <fmt>", "One-shot output format: text | json | stream-json (implies auto-approve)").option("--audit [path]", "Log every tool call (and refusal) to a JSONL trail (default: .nexrall/audit/<session>.jsonl)").argument("[prompt...]", "One-shot prompt \u2014 if omitted, starts interactive mode").action(async (promptParts, options) => {
155155
155215
  if (!(0, import_code_core7.isAuthenticated)()) {
155156
155216
  console.error("Not logged in. Run: nex auth");
155157
155217
  process.exit(1);
@@ -155186,8 +155246,9 @@ program2.option("-p, --pro", "Use Claude Opus 5 (most capable)").option("-t, --t
155186
155246
  let effort;
155187
155247
  if (options.effort) {
155188
155248
  const lvl = String(options.effort).toLowerCase();
155189
- if (!["low", "medium", "high", "extra"].includes(lvl)) {
155190
- console.error(`Invalid --effort "${options.effort}". Use: low | medium | high | extra`);
155249
+ const config = effortConfigFor(normaliseModelId(model));
155250
+ if (!config.levels.includes(lvl)) {
155251
+ console.error(`Invalid --effort "${options.effort}" for model "${model}". Use: ${config.levels.join(" | ")}`);
155191
155252
  process.exit(1);
155192
155253
  }
155193
155254
  effort = lvl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.100",
3
+ "version": "0.5.101",
4
4
  "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",