nothumanallowed 16.0.60 → 16.0.61

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "16.0.60",
3
+ "version": "16.0.61",
4
4
  "description": "Local AI assistant: 80 tools (Gmail, Calendar, Drive, GitHub, Slack, browser, code, files), 38 agents, visual workflows (Studio, AWF, WebCraft). Install with `npm i -g nothumanallowed`, run with `nha ui`. Free tier built-in (Liara), no API key required. Your data stays on your PC — OAuth tokens local, no cloud. Open-source MIT.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '16.0.60';
8
+ export const VERSION = '16.0.61';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -634,34 +634,23 @@ export async function callOpenRouter(apiKey, model, systemPrompt, userMessage, s
634
634
  });
635
635
  if (!res.ok) {
636
636
  const err = await res.text();
637
- // Auto-recovery: if OpenRouter routed to OpenAI (model is openai/*) and
638
- // returned 401 mentioning platform.openai.com, the OpenRouter account has
639
- // BYOK enabled with an invalid/missing OpenAI key. Retry once with safe
640
- // default model anthropic/claude-sonnet-4.5 (works with OpenRouter credit).
641
- const isBYOKFailure = res.status === 401 &&
642
- /platform\.openai\.com|Incorrect API key/i.test(err) &&
643
- model.startsWith('openai/') &&
644
- !opts._retriedFromByokFailure;
645
- if (isBYOKFailure) {
646
- if (process.env.NHA_LOG_OPENROUTER === '1') {
647
- console.error(`[openrouter] BYOK failure on ${model}, retrying with anthropic/claude-sonnet-4.5`);
648
- }
649
- return callOpenRouter(apiKey, 'anthropic/claude-sonnet-4.5', systemPrompt, userMessage, stream, { ...opts, _retriedFromByokFailure: true });
650
- }
651
- // OpenRouter often passes through misleading "platform.openai.com" key errors
652
- // when the real cause is (a) invalid OpenRouter key, (b) model name without
653
- // vendor prefix, (c) model requires BYOK. Provide an actionable hint.
637
+ // OpenRouter passes through provider-side errors verbatim. The most confusing
638
+ // case is "platform.openai.com" 401 — this means: OpenRouter forwarded the
639
+ // request to OpenAI in BYOK mode (Bring Your Own Key) and OpenAI rejected
640
+ // the key. We DO NOT silently swap the user's model they chose it on purpose.
654
641
  let hint = '';
655
642
  if (res.status === 401) {
656
643
  if (/platform\.openai\.com/i.test(err)) {
657
- hint = `\n → 401 with "platform.openai.com" hint: model "${model}" routes via OpenAI but your OpenRouter account either lacks credit or has BYOK enabled with an invalid OpenAI key.\n Fix: (1) use an Anthropic/Gemini model instead (e.g. "anthropic/claude-sonnet-4.5"), OR (2) add credit at openrouter.ai/credits, OR (3) disable BYOK in OpenRouter Settings Integrations.`;
644
+ hint = `\n → BYOK mode rejected: model "${model}" is being routed via OpenAI in BYOK (Bring Your Own Key) mode, and the OpenAI key configured on your OpenRouter account is invalid or missing.\n Fix (keep using ${model}):\n 1. Go to openrouter.ai/settings/integrations\n 2. Either DISABLE the OpenAI integration (so OpenRouter uses its own credit), OR add a valid OpenAI key there.\n Note: NHA will NOT silently switch to a different model — your config stays as you set it.`;
658
645
  } else {
659
- hint = '\n → 401 from OpenRouter: your sk-or-v1-... key is invalid/expired. Regenerate at openrouter.ai/keys.';
646
+ hint = '\n → 401 from OpenRouter: your sk-or-v1-... key is invalid/expired. Regenerate at openrouter.ai/keys and run `nha config set key <new-key>`.';
660
647
  }
661
648
  } else if (res.status === 404) {
662
- hint = '\n → 404 from OpenRouter: model "' + model + '" does not exist. See openrouter.ai/models for valid IDs.';
649
+ hint = `\n → 404 from OpenRouter: model "${model}" does not exist. See openrouter.ai/models for valid IDs (need vendor prefix like "openai/", "anthropic/", "google/").`;
663
650
  } else if (res.status === 402) {
664
651
  hint = '\n → 402 from OpenRouter: insufficient credits. Top up at openrouter.ai/credits.';
652
+ } else if (res.status === 429) {
653
+ hint = '\n → 429 from OpenRouter: rate limited. Wait a few seconds or upgrade your tier at openrouter.ai/settings.';
665
654
  }
666
655
  throw new Error(`OpenRouter ${res.status}: ${err}${hint}`);
667
656
  }
@@ -1099,7 +1088,19 @@ async function _callOpenAIWithTools(apiKey, model, systemPrompt, messages, tools
1099
1088
  headers,
1100
1089
  body: JSON.stringify(body),
1101
1090
  });
1102
- if (!res.ok) { const err = await res.text(); throw new Error(`${opts.baseUrl ? 'OpenRouter' : 'OpenAI'} ${res.status}: ${err}`); }
1091
+ if (!res.ok) {
1092
+ const err = await res.text();
1093
+ const isOR = !!opts.baseUrl;
1094
+ let hint = '';
1095
+ if (isOR && res.status === 401 && /platform\.openai\.com/i.test(err)) {
1096
+ hint = `\n → BYOK mode rejected for model "${body.model}". OpenRouter forwarded the request to OpenAI in BYOK (Bring Your Own Key) mode, and the OpenAI key on your OpenRouter account is invalid/missing.\n Fix: openrouter.ai/settings/integrations → either DISABLE the OpenAI integration (so OpenRouter uses its own credit), OR add a valid OpenAI key there. NHA will keep your chosen model.`;
1097
+ } else if (isOR && res.status === 404) {
1098
+ hint = `\n → 404 from OpenRouter: model "${body.model}" not found. Must be in vendor/model format (e.g. "openai/gpt-4o", "anthropic/claude-sonnet-4.5").`;
1099
+ } else if (isOR && res.status === 402) {
1100
+ hint = '\n → 402 from OpenRouter: insufficient credits. Top up at openrouter.ai/credits.';
1101
+ }
1102
+ throw new Error(`${isOR ? 'OpenRouter' : 'OpenAI'} ${res.status}: ${err}${hint}`);
1103
+ }
1103
1104
 
1104
1105
  const reader = res.body.getReader();
1105
1106
  const dec = new TextDecoder();