nothumanallowed 13.5.91 → 13.5.92
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/commands/ui.mjs +1 -1
- package/src/services/llm.mjs +26 -17
- package/src/services/web-ui.mjs +35 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.92",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -3856,7 +3856,7 @@ ${completedHeadings ? `## SECTIONS ALREADY WRITTEN (headings only):\n${completed
|
|
|
3856
3856
|
return;
|
|
3857
3857
|
}
|
|
3858
3858
|
try {
|
|
3859
|
-
const result = await callLLM(config, body.system, body.user, { max_tokens: body.max_tokens ||
|
|
3859
|
+
const result = await callLLM(config, body.system, body.user, { max_tokens: body.max_tokens || 8192, temperature: 0.15 });
|
|
3860
3860
|
sendJSON(res, 200, { text: result });
|
|
3861
3861
|
} catch (e) {
|
|
3862
3862
|
sendJSON(res, 500, { error: e.message });
|
package/src/services/llm.mjs
CHANGED
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
// ── Providers ──────────────────────────────────────────────────────────────
|
|
9
9
|
|
|
10
|
-
export async function callAnthropic(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
10
|
+
export async function callAnthropic(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
11
11
|
const body = {
|
|
12
12
|
model: model || 'claude-sonnet-4-20250514',
|
|
13
|
-
max_tokens: 8192,
|
|
13
|
+
max_tokens: opts.max_tokens || 8192,
|
|
14
14
|
system: systemPrompt,
|
|
15
15
|
messages: [{ role: 'user', content: userMessage }],
|
|
16
16
|
stream,
|
|
17
17
|
};
|
|
18
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
18
19
|
const res = await fetch('https://api.anthropic.com/v1/messages', {
|
|
19
20
|
method: 'POST',
|
|
20
21
|
headers: {
|
|
@@ -33,16 +34,17 @@ export async function callAnthropic(apiKey, model, systemPrompt, userMessage, st
|
|
|
33
34
|
return data.content?.[0]?.text || '';
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
export async function callOpenAI(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
37
|
+
export async function callOpenAI(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
37
38
|
const body = {
|
|
38
39
|
model: model || 'gpt-4o',
|
|
39
|
-
max_tokens: 8192,
|
|
40
|
+
max_tokens: opts.max_tokens || 8192,
|
|
40
41
|
messages: [
|
|
41
42
|
{ role: 'system', content: systemPrompt },
|
|
42
43
|
{ role: 'user', content: userMessage },
|
|
43
44
|
],
|
|
44
45
|
stream,
|
|
45
46
|
};
|
|
47
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
46
48
|
const res = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
47
49
|
method: 'POST',
|
|
48
50
|
headers: {
|
|
@@ -60,13 +62,15 @@ export async function callOpenAI(apiKey, model, systemPrompt, userMessage, strea
|
|
|
60
62
|
return data.choices?.[0]?.message?.content || '';
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
export async function callGemini(apiKey, model, systemPrompt, userMessage, _stream = false) {
|
|
65
|
+
export async function callGemini(apiKey, model, systemPrompt, userMessage, _stream = false, opts = {}) {
|
|
64
66
|
const m = model || 'gemini-2.5-pro-preview-05-06';
|
|
65
67
|
const url = `https://generativelanguage.googleapis.com/v1beta/models/${m}:generateContent?key=${apiKey}`;
|
|
68
|
+
const generationConfig = { maxOutputTokens: opts.max_tokens || 8192 };
|
|
69
|
+
if (opts.temperature !== undefined) generationConfig.temperature = opts.temperature;
|
|
66
70
|
const body = {
|
|
67
71
|
system_instruction: { parts: [{ text: systemPrompt }] },
|
|
68
72
|
contents: [{ parts: [{ text: userMessage }] }],
|
|
69
|
-
generationConfig
|
|
73
|
+
generationConfig,
|
|
70
74
|
};
|
|
71
75
|
const res = await fetch(url, {
|
|
72
76
|
method: 'POST',
|
|
@@ -81,16 +85,17 @@ export async function callGemini(apiKey, model, systemPrompt, userMessage, _stre
|
|
|
81
85
|
return data.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
export async function callDeepSeek(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
88
|
+
export async function callDeepSeek(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
85
89
|
const body = {
|
|
86
90
|
model: model || 'deepseek-chat',
|
|
87
|
-
max_tokens: 8192,
|
|
91
|
+
max_tokens: opts.max_tokens || 8192,
|
|
88
92
|
messages: [
|
|
89
93
|
{ role: 'system', content: systemPrompt },
|
|
90
94
|
{ role: 'user', content: userMessage },
|
|
91
95
|
],
|
|
92
96
|
stream,
|
|
93
97
|
};
|
|
98
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
94
99
|
const res = await fetch('https://api.deepseek.com/v1/chat/completions', {
|
|
95
100
|
method: 'POST',
|
|
96
101
|
headers: {
|
|
@@ -108,16 +113,17 @@ export async function callDeepSeek(apiKey, model, systemPrompt, userMessage, str
|
|
|
108
113
|
return data.choices?.[0]?.message?.content || '';
|
|
109
114
|
}
|
|
110
115
|
|
|
111
|
-
export async function callGrok(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
116
|
+
export async function callGrok(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
112
117
|
const body = {
|
|
113
118
|
model: model || 'grok-3-latest',
|
|
114
|
-
max_tokens: 8192,
|
|
119
|
+
max_tokens: opts.max_tokens || 8192,
|
|
115
120
|
messages: [
|
|
116
121
|
{ role: 'system', content: systemPrompt },
|
|
117
122
|
{ role: 'user', content: userMessage },
|
|
118
123
|
],
|
|
119
124
|
stream,
|
|
120
125
|
};
|
|
126
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
121
127
|
const res = await fetch('https://api.x.ai/v1/chat/completions', {
|
|
122
128
|
method: 'POST',
|
|
123
129
|
headers: {
|
|
@@ -135,16 +141,17 @@ export async function callGrok(apiKey, model, systemPrompt, userMessage, stream
|
|
|
135
141
|
return data.choices?.[0]?.message?.content || '';
|
|
136
142
|
}
|
|
137
143
|
|
|
138
|
-
export async function callMistral(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
144
|
+
export async function callMistral(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
139
145
|
const body = {
|
|
140
146
|
model: model || 'mistral-large-latest',
|
|
141
|
-
max_tokens: 8192,
|
|
147
|
+
max_tokens: opts.max_tokens || 8192,
|
|
142
148
|
messages: [
|
|
143
149
|
{ role: 'system', content: systemPrompt },
|
|
144
150
|
{ role: 'user', content: userMessage },
|
|
145
151
|
],
|
|
146
152
|
stream,
|
|
147
153
|
};
|
|
154
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
148
155
|
const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
|
|
149
156
|
method: 'POST',
|
|
150
157
|
headers: {
|
|
@@ -162,13 +169,14 @@ export async function callMistral(apiKey, model, systemPrompt, userMessage, stre
|
|
|
162
169
|
return data.choices?.[0]?.message?.content || '';
|
|
163
170
|
}
|
|
164
171
|
|
|
165
|
-
export async function callCohere(apiKey, model, systemPrompt, userMessage, _stream = false) {
|
|
172
|
+
export async function callCohere(apiKey, model, systemPrompt, userMessage, _stream = false, opts = {}) {
|
|
166
173
|
const body = {
|
|
167
174
|
model: model || 'command-r-plus',
|
|
168
|
-
max_tokens: 8192,
|
|
175
|
+
max_tokens: opts.max_tokens || 8192,
|
|
169
176
|
preamble: systemPrompt,
|
|
170
177
|
message: userMessage,
|
|
171
178
|
};
|
|
179
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
172
180
|
const res = await fetch('https://api.cohere.ai/v1/chat', {
|
|
173
181
|
method: 'POST',
|
|
174
182
|
headers: {
|
|
@@ -236,7 +244,7 @@ export async function streamSSE(res, format) {
|
|
|
236
244
|
* NHA Free (Liara) — free LLM tier, no API key required.
|
|
237
245
|
* Qwen3 32B on Hetzner RTX 6000 Pro 96GB. Supports thinking mode.
|
|
238
246
|
*/
|
|
239
|
-
export async function callNHA(apiKey, model, systemPrompt, userMessage, stream = false) {
|
|
247
|
+
export async function callNHA(apiKey, model, systemPrompt, userMessage, stream = false, opts = {}) {
|
|
240
248
|
// Read thinking preference from config
|
|
241
249
|
let thinkingEnabled = false; // OFF by default for speed
|
|
242
250
|
try {
|
|
@@ -266,7 +274,7 @@ export async function callNHA(apiKey, model, systemPrompt, userMessage, stream =
|
|
|
266
274
|
|
|
267
275
|
const body = {
|
|
268
276
|
model: model || '/opt/models/qwen3-32b',
|
|
269
|
-
max_tokens: thinkingEnabled ? 16384 : 8192,
|
|
277
|
+
max_tokens: opts.max_tokens || (thinkingEnabled ? 16384 : 8192),
|
|
270
278
|
messages: [
|
|
271
279
|
{ role: 'system', content: sanitizeForSentinel(systemPrompt) },
|
|
272
280
|
{ role: 'user', content: sanitizeForSentinel(userMessage) },
|
|
@@ -274,6 +282,7 @@ export async function callNHA(apiKey, model, systemPrompt, userMessage, stream =
|
|
|
274
282
|
stream,
|
|
275
283
|
chat_template_kwargs: { enable_thinking: thinkingEnabled },
|
|
276
284
|
};
|
|
285
|
+
if (opts.temperature !== undefined) body.temperature = opts.temperature;
|
|
277
286
|
// Route through NHA server proxy (SENTINEL protection) instead of direct to Hetzner
|
|
278
287
|
const res = await fetch('https://nothumanallowed.com/api/v1/liara/chat', {
|
|
279
288
|
method: 'POST',
|
|
@@ -338,7 +347,7 @@ export async function callLLM(config, systemPrompt, userMessage, opts = {}) {
|
|
|
338
347
|
const callFn = getProviderCall(provider);
|
|
339
348
|
if (!callFn) throw new Error(`Unknown provider: ${provider}`);
|
|
340
349
|
|
|
341
|
-
return callFn(apiKey, model, systemPrompt, userMessage, false);
|
|
350
|
+
return callFn(apiKey, model, systemPrompt, userMessage, false, opts);
|
|
342
351
|
}
|
|
343
352
|
|
|
344
353
|
/**
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -7987,15 +7987,43 @@ async function wcGenerate() {
|
|
|
7987
7987
|
_wcGenStartTime = Date.now();
|
|
7988
7988
|
_wcTokIn = 0; _wcTokOut = 0; // reset global counters for this generation run
|
|
7989
7989
|
|
|
7990
|
-
//
|
|
7990
|
+
// CSS files that need two-pass generation (too long for one call)
|
|
7991
|
+
var WC_CSS_SPLIT = {
|
|
7992
|
+
'public/css/base.css': [
|
|
7993
|
+
'PART 1 of 2. Generate the FIRST HALF of public/css/base.css. Include: (1) all CSS custom properties / design tokens (colors, spacing, font sizes, shadows, radii, transitions, z-index scale, dark/light mode via prefers-color-scheme data-theme), (2) CSS reset (*, box-sizing, margin, padding), (3) base typography (body, h1-h6, p, a, code, pre, blockquote), (4) utility classes (flex, grid helpers, spacing, text alignment, visibility, truncation). End the file at a natural boundary (closing brace). Do NOT generate components. Output raw CSS only.',
|
|
7994
|
+
'PART 2 of 2. Continue (do NOT repeat) public/css/base.css from where part 1 ended. Generate: (5) layout helpers (.container, .grid, .col-*, .stack, .cluster, .sidebar-layout), (6) responsive breakpoint utilities (768px, 480px), (7) animation keyframes (@keyframes fadeIn, slideUp, pulse, spin), (8) scrollbar styling, (9) selection styles, (10) print styles. Output raw CSS only, starting directly from where part 1 ended — no repetition.'
|
|
7995
|
+
],
|
|
7996
|
+
'public/css/components.css': [
|
|
7997
|
+
'PART 1 of 2. Generate the FIRST HALF of public/css/components.css using strict BEM. Include components: (1) .btn (--primary, --secondary, --danger, --ghost, --sm, --lg, disabled state, loading state with spinner), (2) .form (.form__group, .form__label, .form__input, .form__textarea, .form__select, .form__error, .form__hint, .form__input--invalid, focus states), (3) .card (.card__header, .card__body, .card__footer, .card--interactive hover/active), (4) .badge (--success, --error, --warning, --info, --neutral), (5) .alert (--success, --error, --warning, --info with icon space). Output raw CSS only.',
|
|
7998
|
+
'PART 2 of 2. Continue (do NOT repeat) public/css/components.css from where part 1 ended. Include components: (6) .nav (.nav__brand, .nav__links, .nav__link, .nav__link--active, .nav__toggle mobile hamburger, .nav--sticky), (7) .modal (.modal__overlay, .modal__content, .modal__header, .modal__body, .modal__footer, open/close transition), (8) .spinner (sizes: sm/md/lg, colors), (9) .dropdown (.dropdown__menu, .dropdown__item, open state), (10) .avatar (.avatar--sm/md/lg, .avatar--initials), (11) .progress (.progress__bar, animated fill), (12) .table (.table__head, .table__row, .table__cell, striped, hover). Output raw CSS only, starting directly from where part 1 ended.'
|
|
7999
|
+
]
|
|
8000
|
+
};
|
|
8001
|
+
|
|
8002
|
+
// Helper: strip markdown fences from LLM output
|
|
8003
|
+
function wcStripFences(content) {
|
|
8004
|
+
var _nl2 = String.fromCharCode(10);
|
|
8005
|
+
var _fence = String.fromCharCode(96,96,96);
|
|
8006
|
+
var lines = content.split(_nl2);
|
|
8007
|
+
if (lines.length > 0 && lines[0].indexOf(_fence) === 0) lines.shift();
|
|
8008
|
+
if (lines.length > 0 && lines[lines.length-1].trim() === _fence) lines.pop();
|
|
8009
|
+
return lines.join(_nl2).trim();
|
|
8010
|
+
}
|
|
8011
|
+
|
|
8012
|
+
// Helper: generate one file (with two-pass split for large CSS files)
|
|
7991
8013
|
async function wcGenOneFile(fp, signal) {
|
|
7992
8014
|
var _nl2 = String.fromCharCode(10);
|
|
8015
|
+
var splitPrompts = WC_CSS_SPLIT[fp.name];
|
|
8016
|
+
if (splitPrompts) {
|
|
8017
|
+
// Two-pass generation: call LLM twice and concatenate
|
|
8018
|
+
var part1 = await wcCallLLM(sysPreamble, splitPrompts[0] + _nl2 + _nl2 + 'File: ' + fp.name, signal, fp.lang);
|
|
8019
|
+
part1 = wcStripFences(part1);
|
|
8020
|
+
if (signal && signal.aborted) return part1;
|
|
8021
|
+
var part2 = await wcCallLLM(sysPreamble, splitPrompts[1] + _nl2 + _nl2 + 'File: ' + fp.name, signal, fp.lang);
|
|
8022
|
+
part2 = wcStripFences(part2);
|
|
8023
|
+
return part1 + _nl2 + _nl2 + part2;
|
|
8024
|
+
}
|
|
7993
8025
|
var content = await wcCallLLM(sysPreamble, fp.prompt + _nl2 + _nl2 + 'File to generate: ' + fp.name, signal, fp.lang);
|
|
7994
|
-
|
|
7995
|
-
var wcLines = content.split(_nl2);
|
|
7996
|
-
if (wcLines.length > 0 && wcLines[0].indexOf(_fence) === 0) wcLines.shift();
|
|
7997
|
-
if (wcLines.length > 0 && wcLines[wcLines.length-1].trim() === _fence) wcLines.pop();
|
|
7998
|
-
return wcLines.join(_nl2).trim();
|
|
8026
|
+
return wcStripFences(content);
|
|
7999
8027
|
}
|
|
8000
8028
|
|
|
8001
8029
|
wcStartGenTimer();
|
|
@@ -8234,7 +8262,7 @@ async function wcCallLLMRaw(sys, user, signal) {
|
|
|
8234
8262
|
var fetchOpts = {
|
|
8235
8263
|
method: 'POST',
|
|
8236
8264
|
headers: {'Content-Type':'application/json'},
|
|
8237
|
-
body: JSON.stringify({system: sys, user: user, max_tokens:
|
|
8265
|
+
body: JSON.stringify({system: sys, user: user, max_tokens: 16384})
|
|
8238
8266
|
};
|
|
8239
8267
|
if (signal) fetchOpts.signal = signal;
|
|
8240
8268
|
for (var attempt = 0; attempt < 3; attempt++) {
|