nothumanallowed 16.0.55 → 16.0.56
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 +1 -1
- package/src/constants.mjs +1 -1
- package/src/services/llm.mjs +53 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.56",
|
|
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.
|
|
8
|
+
export const VERSION = '16.0.56';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/llm.mjs
CHANGED
|
@@ -563,6 +563,41 @@ export async function callGrok(apiKey, model, systemPrompt, userMessage, stream
|
|
|
563
563
|
return data.choices?.[0]?.message?.content || '';
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
+
/**
|
|
567
|
+
* Auto-prefix a model name for OpenRouter. OpenRouter requires `vendor/model`
|
|
568
|
+
* format (e.g. `anthropic/claude-sonnet-4.5`). Agent cards in NHA often have
|
|
569
|
+
* bare model names like `claude-sonnet-4-20250514` or `gpt-4o`. Without the
|
|
570
|
+
* prefix, OpenRouter falls back to an OpenAI-like endpoint that returns a
|
|
571
|
+
* misleading "Incorrect API key provided" error (it's actually a model
|
|
572
|
+
* routing issue). We auto-prefix by inspecting the bare model name.
|
|
573
|
+
*/
|
|
574
|
+
export function _autoPrefixOpenRouterModel(model) {
|
|
575
|
+
if (!model || typeof model !== 'string') return 'anthropic/claude-sonnet-4.5';
|
|
576
|
+
// Already in vendor/model format — leave alone
|
|
577
|
+
if (model.includes('/')) return model;
|
|
578
|
+
const lower = model.toLowerCase();
|
|
579
|
+
// Anthropic Claude family
|
|
580
|
+
if (lower.startsWith('claude')) return 'anthropic/' + model;
|
|
581
|
+
// OpenAI GPT family
|
|
582
|
+
if (lower.startsWith('gpt') || lower.startsWith('o1') || lower.startsWith('o3') || lower.startsWith('o4') || lower.startsWith('chatgpt') || lower === 'davinci' || lower === 'curie') return 'openai/' + model;
|
|
583
|
+
// Google Gemini family
|
|
584
|
+
if (lower.startsWith('gemini') || lower.startsWith('palm')) return 'google/' + model;
|
|
585
|
+
// Meta Llama family
|
|
586
|
+
if (lower.startsWith('llama') || lower.startsWith('codellama')) return 'meta-llama/' + model;
|
|
587
|
+
// DeepSeek
|
|
588
|
+
if (lower.startsWith('deepseek')) return 'deepseek/' + model;
|
|
589
|
+
// Mistral / Mixtral
|
|
590
|
+
if (lower.startsWith('mistral') || lower.startsWith('mixtral') || lower.startsWith('codestral')) return 'mistralai/' + model;
|
|
591
|
+
// Qwen
|
|
592
|
+
if (lower.startsWith('qwen')) return 'qwen/' + model;
|
|
593
|
+
// xAI Grok
|
|
594
|
+
if (lower.startsWith('grok')) return 'x-ai/' + model;
|
|
595
|
+
// Cohere
|
|
596
|
+
if (lower.startsWith('command') || lower.startsWith('cohere')) return 'cohere/' + model;
|
|
597
|
+
// Unknown vendor — default to anthropic prefix (most likely sandbox use case)
|
|
598
|
+
return 'anthropic/' + model;
|
|
599
|
+
}
|
|
600
|
+
|
|
566
601
|
/**
|
|
567
602
|
* OpenRouter — aggregator that exposes 100+ models (Claude, GPT, Gemini,
|
|
568
603
|
* Mistral, Llama, Qwen, DeepSeek, etc.) via a single OpenAI-compatible API.
|
|
@@ -570,6 +605,7 @@ export async function callGrok(apiKey, model, systemPrompt, userMessage, stream
|
|
|
570
605
|
* Model names: "anthropic/claude-sonnet-4.5", "openai/gpt-4o", "google/gemini-2.5-pro"...
|
|
571
606
|
*/
|
|
572
607
|
export async function callOpenRouter(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
608
|
+
model = _autoPrefixOpenRouterModel(model);
|
|
573
609
|
const body = {
|
|
574
610
|
model: model || 'anthropic/claude-sonnet-4.5',
|
|
575
611
|
max_tokens: opts.max_tokens || 8192,
|
|
@@ -594,7 +630,18 @@ export async function callOpenRouter(apiKey, model, systemPrompt, userMessage, s
|
|
|
594
630
|
});
|
|
595
631
|
if (!res.ok) {
|
|
596
632
|
const err = await res.text();
|
|
597
|
-
|
|
633
|
+
// OpenRouter often passes through misleading "platform.openai.com" key errors
|
|
634
|
+
// when the real cause is (a) invalid OpenRouter key, (b) model name without
|
|
635
|
+
// vendor prefix, (c) model requires BYOK. Provide an actionable hint.
|
|
636
|
+
let hint = '';
|
|
637
|
+
if (res.status === 401) {
|
|
638
|
+
hint = '\n → 401 from OpenRouter usually means: (1) your sk-or-v1-... key is invalid/expired (regenerate at openrouter.ai/keys), or (2) the model name "' + model + '" needs a vendor prefix like "anthropic/' + model.replace(/^[a-z-]+\//, '') + '". This call auto-prefixed to "' + model + '".';
|
|
639
|
+
} else if (res.status === 404) {
|
|
640
|
+
hint = '\n → 404 from OpenRouter usually means the model "' + model + '" does not exist. See openrouter.ai/models for valid IDs.';
|
|
641
|
+
} else if (res.status === 402) {
|
|
642
|
+
hint = '\n → 402 from OpenRouter means insufficient credits. Top up at openrouter.ai/credits.';
|
|
643
|
+
}
|
|
644
|
+
throw new Error(`OpenRouter ${res.status}: ${err}${hint}`);
|
|
598
645
|
}
|
|
599
646
|
if (stream) return streamSSE(res, 'openai');
|
|
600
647
|
const data = await res.json();
|
|
@@ -828,9 +875,12 @@ export async function callLLMWithTools(config, systemPrompt, messages, tools, on
|
|
|
828
875
|
}
|
|
829
876
|
|
|
830
877
|
// OpenRouter — uses OpenAI-compatible function calling schema. We reuse the
|
|
831
|
-
// OpenAI tool-call implementation but point to OpenRouter's endpoint
|
|
878
|
+
// OpenAI tool-call implementation but point to OpenRouter's endpoint and
|
|
879
|
+
// auto-prefix the model (anthropic/, openai/, etc) so bare names from agent
|
|
880
|
+
// cards work without manual edit.
|
|
832
881
|
if (provider === 'openrouter') {
|
|
833
|
-
|
|
882
|
+
const orModel = _autoPrefixOpenRouterModel(model);
|
|
883
|
+
return _callOpenAIWithTools(apiKey, orModel, systemPrompt, messages, tools, onText, onToolCall, { ...opts, baseUrl: 'https://openrouter.ai/api/v1', referer: 'https://nothumanallowed.com', xTitle: 'NotHumanAllowed CLI' });
|
|
834
884
|
}
|
|
835
885
|
|
|
836
886
|
// Other providers: fallback to text-based tool calling (old system)
|