claude-code-hub 1.0.3 → 1.1.0
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 +5 -5
- package/public/app.js +39 -4
- package/public/index.html +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-hub",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Unified hub for Claude Code tools — Marketplace + Kanban in one PWA",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"homepage": "https://github.com/NikiforovAll/claude-code-hub#readme",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"claude-code-cost": "1.
|
|
49
|
-
"claude-code-kanban": "5.
|
|
50
|
-
"claude-code-marketplace": "1.
|
|
51
|
-
"claude-code-memory-explorer": "1.
|
|
48
|
+
"claude-code-cost": "1.1.0",
|
|
49
|
+
"claude-code-kanban": "5.2.0",
|
|
50
|
+
"claude-code-marketplace": "1.1.0",
|
|
51
|
+
"claude-code-memory-explorer": "1.1.0",
|
|
52
52
|
"express": "^4.21.0",
|
|
53
53
|
"open": "^10.1.0"
|
|
54
54
|
},
|
package/public/app.js
CHANGED
|
@@ -229,6 +229,7 @@ async function init() {
|
|
|
229
229
|
listenKeys();
|
|
230
230
|
bindPalette();
|
|
231
231
|
registerSW();
|
|
232
|
+
bindErrorToast();
|
|
232
233
|
showUpdateToast();
|
|
233
234
|
}
|
|
234
235
|
|
|
@@ -273,6 +274,37 @@ async function showUpdateToast() {
|
|
|
273
274
|
arm();
|
|
274
275
|
}
|
|
275
276
|
|
|
277
|
+
const ERROR_TOAST_MS = 8_000;
|
|
278
|
+
let errorToastTimer = 0;
|
|
279
|
+
|
|
280
|
+
function hideErrorToast() {
|
|
281
|
+
clearTimeout(errorToastTimer);
|
|
282
|
+
const toast = document.getElementById('error-toast');
|
|
283
|
+
toast.classList.add('leaving');
|
|
284
|
+
setTimeout(() => (toast.hidden = true), 200);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// A 401 means the hub_token cookie no longer matches the token file. Opening /?token=… sets a new
|
|
288
|
+
// cookie; reloading lands on the locked page, where the token can be pasted instead.
|
|
289
|
+
function showErrorToast(action, err) {
|
|
290
|
+
const unauthorized = err.status === 401;
|
|
291
|
+
document.getElementById('error-title').textContent = unauthorized ? `${action}: hub token rejected` : action;
|
|
292
|
+
document.getElementById('error-detail').textContent = unauthorized
|
|
293
|
+
? `This browser has an old hub token. Open the link the hub printed in the terminal (${location.origin}/?token=…) to renew it.`
|
|
294
|
+
: err.message;
|
|
295
|
+
document.getElementById('error-actions').hidden = !unauthorized;
|
|
296
|
+
const toast = document.getElementById('error-toast');
|
|
297
|
+
toast.classList.remove('leaving');
|
|
298
|
+
toast.hidden = false;
|
|
299
|
+
clearTimeout(errorToastTimer);
|
|
300
|
+
if (!unauthorized) errorToastTimer = setTimeout(hideErrorToast, ERROR_TOAST_MS);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function bindErrorToast() {
|
|
304
|
+
document.getElementById('error-close').addEventListener('click', hideErrorToast);
|
|
305
|
+
document.getElementById('error-reload').addEventListener('click', () => location.reload());
|
|
306
|
+
}
|
|
307
|
+
|
|
276
308
|
// The hub has no visible chrome, so the window/tab title is the only place the active config dir
|
|
277
309
|
// shows. Only a non-default dir is named, and by basename alone — the PWA window prepends the
|
|
278
310
|
// manifest name, so a product name here would read as "Claude Code Hub - .claude-eom · Hub".
|
|
@@ -722,7 +754,7 @@ async function removeConfigDir(dirPath) {
|
|
|
722
754
|
try {
|
|
723
755
|
palette.configDirs = await sendJson('DELETE', '/api/config-dirs', { path: dirPath });
|
|
724
756
|
} catch (err) {
|
|
725
|
-
|
|
757
|
+
showErrorToast('Could not remove config dir', err);
|
|
726
758
|
return;
|
|
727
759
|
}
|
|
728
760
|
if (dirPath in themeState.colorThemes) {
|
|
@@ -993,7 +1025,10 @@ function openPalette(mode) {
|
|
|
993
1025
|
.then(() => {
|
|
994
1026
|
if (palette.open && palette.mode === mode) renderPalette();
|
|
995
1027
|
})
|
|
996
|
-
.catch((err) =>
|
|
1028
|
+
.catch((err) => {
|
|
1029
|
+
if (err.status === 401) showErrorToast('Could not load the list', err);
|
|
1030
|
+
else console.warn(`${mode} list unavailable:`, err.message);
|
|
1031
|
+
});
|
|
997
1032
|
}
|
|
998
1033
|
|
|
999
1034
|
function closePalette() {
|
|
@@ -1057,7 +1092,7 @@ async function commitConfigDir(row) {
|
|
|
1057
1092
|
try {
|
|
1058
1093
|
target = (await withPaletteBusy(() => sendJson('POST', '/api/config-dirs', { path: row.path }))).path;
|
|
1059
1094
|
} catch (err) {
|
|
1060
|
-
|
|
1095
|
+
showErrorToast('Could not add config dir', err);
|
|
1061
1096
|
return;
|
|
1062
1097
|
}
|
|
1063
1098
|
}
|
|
@@ -1075,7 +1110,7 @@ async function commitConfigDir(row) {
|
|
|
1075
1110
|
applyHubTheme();
|
|
1076
1111
|
reloadIframes();
|
|
1077
1112
|
} catch (err) {
|
|
1078
|
-
|
|
1113
|
+
showErrorToast('Could not switch config dir', err);
|
|
1079
1114
|
hideLoading();
|
|
1080
1115
|
}
|
|
1081
1116
|
}
|
package/public/index.html
CHANGED
|
@@ -376,6 +376,7 @@
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
.update-toast-close:hover { color: var(--text); }
|
|
379
|
+
.error-toast { z-index: 25; border-left-color: #e5484d; }
|
|
379
380
|
</style>
|
|
380
381
|
</head>
|
|
381
382
|
<body>
|
|
@@ -448,6 +449,17 @@
|
|
|
448
449
|
<button class="update-toast-close" id="update-close" type="button" aria-label="Close">×</button>
|
|
449
450
|
</div>
|
|
450
451
|
|
|
452
|
+
<div class="update-toast error-toast" id="error-toast" role="alert" hidden>
|
|
453
|
+
<div class="update-toast-body">
|
|
454
|
+
<div class="update-toast-title" id="error-title"></div>
|
|
455
|
+
<div class="update-toast-meta" id="error-detail"></div>
|
|
456
|
+
<div class="update-toast-actions" id="error-actions" hidden>
|
|
457
|
+
<button class="update-toast-skip" id="error-reload" type="button">Paste token instead</button>
|
|
458
|
+
</div>
|
|
459
|
+
</div>
|
|
460
|
+
<button class="update-toast-close" id="error-close" type="button" aria-label="Close">×</button>
|
|
461
|
+
</div>
|
|
462
|
+
|
|
451
463
|
<script src="/app.js"></script>
|
|
452
464
|
</body>
|
|
453
465
|
</html>
|