colana 1.0.0-beta.40 → 1.0.0-beta.41
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/public/app.js +35 -2
- package/server/personal-agent-routes.js +44 -10
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -1514,9 +1514,10 @@ async function sendPersonalChatMessage() {
|
|
|
1514
1514
|
assistantBubble.className = 'chat-bubble error';
|
|
1515
1515
|
|
|
1516
1516
|
const isAuthError = err.code === 'GATEWAY_AUTH_FAILED' || err.code === 'GATEWAY_AUTH_MISSING';
|
|
1517
|
+
const isTokenError = err.code === 'GATEWAY_TOKEN_MISSING' || err.code === 'GATEWAY_TOKEN_STALE';
|
|
1517
1518
|
|
|
1518
1519
|
if (isAuthError) {
|
|
1519
|
-
//
|
|
1520
|
+
// Provider API key error: show "Add API Key" button
|
|
1520
1521
|
const msgSpan = document.createElement('span');
|
|
1521
1522
|
msgSpan.textContent = err.message || 'No valid API key found for your model provider.';
|
|
1522
1523
|
assistantBubble.appendChild(msgSpan);
|
|
@@ -1527,7 +1528,6 @@ async function sendPersonalChatMessage() {
|
|
|
1527
1528
|
addKeyBtn.addEventListener('click', (e) => {
|
|
1528
1529
|
e.preventDefault();
|
|
1529
1530
|
openSettingsModal();
|
|
1530
|
-
// Scroll to Personal AI Agents section after modal opens
|
|
1531
1531
|
setTimeout(() => {
|
|
1532
1532
|
const modelSection = document.getElementById('openclaw-model-config');
|
|
1533
1533
|
if (modelSection) modelSection.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
@@ -1535,6 +1535,39 @@ async function sendPersonalChatMessage() {
|
|
|
1535
1535
|
});
|
|
1536
1536
|
assistantBubble.appendChild(addKeyBtn);
|
|
1537
1537
|
|
|
1538
|
+
if (err.fix) {
|
|
1539
|
+
const fixHint = document.createElement('div');
|
|
1540
|
+
fixHint.className = 'chat-error-fix-hint';
|
|
1541
|
+
fixHint.textContent = err.fix;
|
|
1542
|
+
assistantBubble.appendChild(fixHint);
|
|
1543
|
+
}
|
|
1544
|
+
} else if (isTokenError) {
|
|
1545
|
+
// Gateway token auth error: show "Restart Gateway" button
|
|
1546
|
+
const msgSpan = document.createElement('span');
|
|
1547
|
+
msgSpan.textContent = err.message || 'Gateway authentication failed.';
|
|
1548
|
+
assistantBubble.appendChild(msgSpan);
|
|
1549
|
+
|
|
1550
|
+
const restartBtn = document.createElement('button');
|
|
1551
|
+
restartBtn.className = 'chat-error-action-btn';
|
|
1552
|
+
restartBtn.textContent = 'Restart Gateway';
|
|
1553
|
+
restartBtn.addEventListener('click', async (e) => {
|
|
1554
|
+
e.preventDefault();
|
|
1555
|
+
restartBtn.disabled = true;
|
|
1556
|
+
restartBtn.textContent = 'Restarting...';
|
|
1557
|
+
try {
|
|
1558
|
+
await fetch('/api/personal-agent/restart-gateway', {
|
|
1559
|
+
method: 'POST',
|
|
1560
|
+
headers: getAuthHeaders(),
|
|
1561
|
+
});
|
|
1562
|
+
restartBtn.textContent = 'Restarted — try again';
|
|
1563
|
+
showToast('Gateway restarted. Try sending your message again.', 'success');
|
|
1564
|
+
} catch {
|
|
1565
|
+
restartBtn.textContent = 'Restart Failed';
|
|
1566
|
+
showToast('Gateway restart failed. Open Settings to troubleshoot.', 'error');
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1569
|
+
assistantBubble.appendChild(restartBtn);
|
|
1570
|
+
|
|
1538
1571
|
if (err.fix) {
|
|
1539
1572
|
const fixHint = document.createElement('div');
|
|
1540
1573
|
fixHint.className = 'chat-error-fix-hint';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOpenClawAuthToken, getOpenClawGatewayPort, getOpenClawDefaultModel, isChatCompletionsEnabled, ensureChatCompletionsEnabled, ensureAuthProfile, readAuthStore } from './openclaw-config.js';
|
|
1
|
+
import { getOpenClawAuthToken, getOpenClawGatewayPort, getOpenClawDefaultModel, getOpenClawConfig, isChatCompletionsEnabled, ensureChatCompletionsEnabled, ensureAuthProfile, readAuthStore } from './openclaw-config.js';
|
|
2
2
|
import { validate, personalChatSchema, openclawModelSetSchema, openclawModelAuthSchema } from './validation.js';
|
|
3
3
|
import { setSetting } from './settings-store.js';
|
|
4
4
|
import { restartOpenClawGateway } from './pty-manager.js';
|
|
@@ -99,6 +99,15 @@ export function registerPersonalAgentRoutes(app, { sensitiveLimiter }) {
|
|
|
99
99
|
const authToken = getOpenClawAuthToken();
|
|
100
100
|
if (authToken) {
|
|
101
101
|
headers['Authorization'] = `Bearer ${authToken}`;
|
|
102
|
+
} else {
|
|
103
|
+
// Gateway auth token not found — the gateway will reject with 401.
|
|
104
|
+
// Log config state for diagnosis on fresh installs.
|
|
105
|
+
const cfg = getOpenClawConfig();
|
|
106
|
+
const hasConfig = !!cfg;
|
|
107
|
+
const hasGateway = !!cfg?.gateway;
|
|
108
|
+
const hasAuth = !!cfg?.gateway?.auth;
|
|
109
|
+
const authMode = cfg?.gateway?.auth?.mode || 'none';
|
|
110
|
+
console.warn(`[personal-agent] No gateway auth token found — config:${hasConfig} gateway:${hasGateway} auth:${hasAuth} mode:${authMode}`);
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
// 60-second timeout
|
|
@@ -131,22 +140,47 @@ export function registerPersonalAgentRoutes(app, { sensitiveLimiter }) {
|
|
|
131
140
|
}
|
|
132
141
|
const status = gatewayRes.status;
|
|
133
142
|
|
|
134
|
-
// For 401,
|
|
143
|
+
// For 401, distinguish gateway-level token auth vs model provider key failure
|
|
135
144
|
if (status === 401) {
|
|
145
|
+
// If we didn't send a gateway auth token, the 401 is almost certainly
|
|
146
|
+
// a gateway token rejection — not a model provider key issue.
|
|
147
|
+
if (!authToken) {
|
|
148
|
+
return res.status(401).json({
|
|
149
|
+
error: 'Gateway authentication failed — no gateway auth token found.',
|
|
150
|
+
code: 'GATEWAY_TOKEN_MISSING',
|
|
151
|
+
fix: 'Restart the gateway in Settings > Personal AI Agents, or run "openclaw onboard" to regenerate the config.',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Token was sent but rejected — could be stale token or provider key issue
|
|
136
156
|
const currentModel = getOpenClawDefaultModel() || '';
|
|
137
157
|
const slash = currentModel.indexOf('/');
|
|
138
158
|
const provider = slash > 0 ? currentModel.substring(0, slash).toLowerCase() : null;
|
|
139
159
|
const providerLabel = provider || null;
|
|
140
160
|
const envVar = provider ? PROVIDER_ENV_MAP[provider] : null;
|
|
161
|
+
|
|
162
|
+
// Check if the error body hints at provider-level auth failure
|
|
163
|
+
const isProviderAuth = errText.includes('api_key') || errText.includes('API key')
|
|
164
|
+
|| errText.includes('invalid_api_key') || errText.includes('authentication_error');
|
|
165
|
+
|
|
166
|
+
if (isProviderAuth) {
|
|
167
|
+
return res.status(401).json({
|
|
168
|
+
error: providerLabel
|
|
169
|
+
? `Authentication failed — your ${providerLabel} API key may be missing or invalid.`
|
|
170
|
+
: 'Authentication failed — your API key may be missing or invalid.',
|
|
171
|
+
code: 'GATEWAY_AUTH_FAILED',
|
|
172
|
+
fix: envVar
|
|
173
|
+
? `Add or update your ${envVar} in Settings > Personal AI Agents.`
|
|
174
|
+
: 'Add your API key in Settings > Personal AI Agents.',
|
|
175
|
+
provider: provider || null,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Default: gateway token mismatch (token exists locally but doesn't match gateway)
|
|
141
180
|
return res.status(401).json({
|
|
142
|
-
error:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
code: 'GATEWAY_AUTH_FAILED',
|
|
146
|
-
fix: envVar
|
|
147
|
-
? `Add or update your ${envVar} in Settings > Personal AI Agents.`
|
|
148
|
-
: `Add your API key in Settings > Personal AI Agents.`,
|
|
149
|
-
provider: provider || null,
|
|
181
|
+
error: 'Gateway authentication failed — the auth token may be stale.',
|
|
182
|
+
code: 'GATEWAY_TOKEN_STALE',
|
|
183
|
+
fix: 'Restart the gateway in Settings > Personal AI Agents to resync the auth token.',
|
|
150
184
|
});
|
|
151
185
|
}
|
|
152
186
|
|