claude-simple 0.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/README.md +225 -0
- package/client.js +139 -0
- package/dist/addon-fit.min.js +2 -0
- package/dist/app.0.1.0.min.js +825 -0
- package/dist/highlight.min.css +10 -0
- package/dist/highlight.min.js +1244 -0
- package/dist/index.html +16 -0
- package/dist/marked.min.js +6 -0
- package/dist/style.0.1.0.min.css +1050 -0
- package/dist/xterm.min.css +209 -0
- package/dist/xterm.min.js +2 -0
- package/gateway.js +349 -0
- package/package.json +41 -0
- package/public/addon-fit.min.js +2 -0
- package/public/agent-panel.js +1079 -0
- package/public/api.js +78 -0
- package/public/app.js +95 -0
- package/public/base.css +4 -0
- package/public/cache.js +27 -0
- package/public/chat.js +1087 -0
- package/public/files.js +476 -0
- package/public/git.js +130 -0
- package/public/index.html +61 -0
- package/public/lib.js +2 -0
- package/public/router.js +71 -0
- package/public/settings.js +90 -0
- package/public/shell/boot.js +159 -0
- package/public/shell/dashboard.js +269 -0
- package/public/shell/hub.js +192 -0
- package/public/shell/layout.js +195 -0
- package/public/shell/notes.js +323 -0
- package/public/shell/session-context.js +19 -0
- package/public/shell/session-list.js +442 -0
- package/public/shell/session-nav.js +299 -0
- package/public/shell/templates.js +342 -0
- package/public/shell/util.js +63 -0
- package/public/shell.js +589 -0
- package/public/state.js +362 -0
- package/public/style.css +1048 -0
- package/public/terminal.js +177 -0
- package/public/xterm.min.css +209 -0
- package/public/xterm.min.js +2 -0
- package/server.js +12 -0
- package/src/agents/claude.js +58 -0
- package/src/agents/codex.js +284 -0
- package/src/agents/grok.js +318 -0
- package/src/agents/meta-agent.js +1952 -0
- package/src/agents/models.js +339 -0
- package/src/agents/sessions.js +1508 -0
- package/src/app.js +1282 -0
package/public/api.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// api.js — HTTP + WebSocket helpers
|
|
2
|
+
import { ctx, hubMode, selectedMachineId } from './state.js';
|
|
3
|
+
|
|
4
|
+
/** Active edge machine id (hub). */
|
|
5
|
+
export function currentMachineId(opts = {}) {
|
|
6
|
+
if (opts.machineId !== undefined) return opts.machineId;
|
|
7
|
+
return ctx.machineId || selectedMachineId.peek() || null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Hub endpoints that must NOT be proxied to an edge. */
|
|
11
|
+
function isHubOnlyPath(path) {
|
|
12
|
+
const p = path.split('?')[0];
|
|
13
|
+
return p === '/api/hub'
|
|
14
|
+
|| p === '/api/machines'
|
|
15
|
+
|| p.startsWith('/api/auth/');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function api(method, path, body, signal, opts = {}) {
|
|
19
|
+
const machineId = currentMachineId(opts);
|
|
20
|
+
const headers = {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
...(ctx.token ? { Authorization: `Bearer ${ctx.token}` } : {}),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Hub mode: route data APIs to the selected edge (sessions/files/git/…)
|
|
26
|
+
if (hubMode.peek() && machineId && !isHubOnlyPath(path)) {
|
|
27
|
+
headers['X-Machine-Id'] = machineId;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const res = await fetch(path, {
|
|
31
|
+
method,
|
|
32
|
+
signal,
|
|
33
|
+
headers,
|
|
34
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
35
|
+
});
|
|
36
|
+
const data = await res.json().catch(() => ({}));
|
|
37
|
+
if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function sendWs(data) {
|
|
42
|
+
if (ctx.ws?.readyState === WebSocket.OPEN) ctx.ws.send(JSON.stringify(data));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Query string for download links (token + machine in hub mode). */
|
|
46
|
+
export function authQuery(extra = {}) {
|
|
47
|
+
const q = new URLSearchParams(extra);
|
|
48
|
+
if (ctx.token) q.set('token', ctx.token);
|
|
49
|
+
const mid = currentMachineId();
|
|
50
|
+
if (hubMode.peek() && mid) q.set('machine', mid);
|
|
51
|
+
return q.toString();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Headers for raw fetch (e.g. file upload) in hub mode. */
|
|
55
|
+
export function authHeaders(extra = {}) {
|
|
56
|
+
const h = { ...extra };
|
|
57
|
+
if (ctx.token) h.Authorization = `Bearer ${ctx.token}`;
|
|
58
|
+
const mid = currentMachineId();
|
|
59
|
+
if (hubMode.peek() && mid) h['X-Machine-Id'] = mid;
|
|
60
|
+
return h;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function probeHub() {
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch('/api/hub');
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
hubMode.value = false;
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const data = await res.json();
|
|
71
|
+
if (data?.hub) {
|
|
72
|
+
hubMode.value = true;
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
} catch { /* standalone */ }
|
|
76
|
+
hubMode.value = false;
|
|
77
|
+
return false;
|
|
78
|
+
}
|
package/public/app.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// app.js — Entry point
|
|
2
|
+
import { ctx } from './state.js';
|
|
3
|
+
import { probeHub } from './api.js';
|
|
4
|
+
import { initShell, showApp, initAuth, resumeSession, switchTab, shouldRestoreSessionOnBoot } from './shell.js';
|
|
5
|
+
import { initChat } from './chat.js';
|
|
6
|
+
import { initFilesTab } from './files.js';
|
|
7
|
+
import { initGitTab } from './git.js';
|
|
8
|
+
import { initSettings } from './settings.js';
|
|
9
|
+
import { initTerminal } from './terminal.js';
|
|
10
|
+
import { initImagePaste } from './chat.js';
|
|
11
|
+
import { initMetaAgent } from './agent-panel.js';
|
|
12
|
+
import { initRouter, applyInitialRoute, parseHashPath } from './router.js';
|
|
13
|
+
|
|
14
|
+
function markBootReady() {
|
|
15
|
+
const root = document.documentElement;
|
|
16
|
+
root.classList.add('boot-ready');
|
|
17
|
+
root.classList.remove('boot-pending');
|
|
18
|
+
// Keep boot-restore until welcome is intentionally shown (goHome)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function clearBootRestore() {
|
|
22
|
+
document.documentElement.classList.remove('boot-restore');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const deepLink = parseHashPath(location.hash.slice(1) || '/');
|
|
26
|
+
const restoreSession = shouldRestoreSessionOnBoot() || !!(ctx.token && deepLink?.id);
|
|
27
|
+
|
|
28
|
+
// 1. Build DOM (welcome already suppressed via html.boot-restore CSS when restoring)
|
|
29
|
+
initShell({ restoreSession });
|
|
30
|
+
|
|
31
|
+
// 2. Feature panels
|
|
32
|
+
initChat();
|
|
33
|
+
initFilesTab();
|
|
34
|
+
initGitTab();
|
|
35
|
+
initSettings();
|
|
36
|
+
initTerminal();
|
|
37
|
+
initImagePaste();
|
|
38
|
+
initMetaAgent();
|
|
39
|
+
initRouter(resumeSession, switchTab);
|
|
40
|
+
|
|
41
|
+
// 3. Boot data
|
|
42
|
+
(async () => {
|
|
43
|
+
const hubPromise = probeHub();
|
|
44
|
+
|
|
45
|
+
if (ctx.token) {
|
|
46
|
+
try {
|
|
47
|
+
const auth = document.getElementById('auth-screen');
|
|
48
|
+
const app = document.getElementById('app');
|
|
49
|
+
if (auth) { auth.style.display = 'none'; auth.classList.add('hidden'); }
|
|
50
|
+
if (app) { app.style.display = 'flex'; app.classList.remove('hidden'); }
|
|
51
|
+
|
|
52
|
+
if (restoreSession) {
|
|
53
|
+
document.documentElement.classList.add('boot-restore');
|
|
54
|
+
const welcome = document.getElementById('welcome');
|
|
55
|
+
const pv = document.getElementById('project-view');
|
|
56
|
+
if (welcome) {
|
|
57
|
+
welcome.classList.add('hidden');
|
|
58
|
+
welcome.style.display = 'none';
|
|
59
|
+
}
|
|
60
|
+
if (pv) {
|
|
61
|
+
pv.classList.remove('hidden');
|
|
62
|
+
pv.style.cssText = 'display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const hub = await hubPromise;
|
|
67
|
+
await showApp({ hub, deepLink });
|
|
68
|
+
if (!deepLink?.id) {
|
|
69
|
+
applyInitialRoute();
|
|
70
|
+
// Home: allow calendar; drop restore lock
|
|
71
|
+
if (!(location.hash || '').startsWith('#/session/')) clearBootRestore();
|
|
72
|
+
}
|
|
73
|
+
// Reveal only after shell + route/session start settled
|
|
74
|
+
requestAnimationFrame(() => {
|
|
75
|
+
requestAnimationFrame(markBootReady);
|
|
76
|
+
});
|
|
77
|
+
} catch (e) {
|
|
78
|
+
console.error('[boot]', e);
|
|
79
|
+
ctx.token = null;
|
|
80
|
+
localStorage.removeItem('token');
|
|
81
|
+
clearBootRestore();
|
|
82
|
+
await initAuth();
|
|
83
|
+
markBootReady();
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
clearBootRestore();
|
|
87
|
+
await initAuth();
|
|
88
|
+
markBootReady();
|
|
89
|
+
}
|
|
90
|
+
})();
|
|
91
|
+
|
|
92
|
+
// When user goes home later, allow welcome again
|
|
93
|
+
document.addEventListener('router:home', () => {
|
|
94
|
+
clearBootRestore();
|
|
95
|
+
});
|
package/public/base.css
ADDED
package/public/cache.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// cache.js — IndexedDB-backed cache for sessions and workspaces
|
|
2
|
+
import { idb } from './lib.js';
|
|
3
|
+
|
|
4
|
+
const db = idb('claude-ui');
|
|
5
|
+
const SESSIONS_TTL = 5 * 60 * 1000; // 5 minutes
|
|
6
|
+
|
|
7
|
+
export async function getCachedSessions() {
|
|
8
|
+
try { return await db.get('sessions') ?? null; }
|
|
9
|
+
catch { return null; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function setCachedSessions(sessions) {
|
|
13
|
+
try { await db.set('sessions', sessions, { ttl: SESSIONS_TTL }); }
|
|
14
|
+
catch {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function getCachedWorkspaces() {
|
|
18
|
+
try { return await db.get('workspaces') ?? null; }
|
|
19
|
+
catch { return null; }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function setCachedWorkspaces(workspaces) {
|
|
23
|
+
try { await db.set('workspaces', workspaces, { ttl: 60 * 60 * 1000 }); } // 1 hour
|
|
24
|
+
catch {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// lastSessionContext lives in shell/session-context.js (avoid stale cache.js in browsers)
|