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.
Files changed (50) hide show
  1. package/README.md +225 -0
  2. package/client.js +139 -0
  3. package/dist/addon-fit.min.js +2 -0
  4. package/dist/app.0.1.0.min.js +825 -0
  5. package/dist/highlight.min.css +10 -0
  6. package/dist/highlight.min.js +1244 -0
  7. package/dist/index.html +16 -0
  8. package/dist/marked.min.js +6 -0
  9. package/dist/style.0.1.0.min.css +1050 -0
  10. package/dist/xterm.min.css +209 -0
  11. package/dist/xterm.min.js +2 -0
  12. package/gateway.js +349 -0
  13. package/package.json +41 -0
  14. package/public/addon-fit.min.js +2 -0
  15. package/public/agent-panel.js +1079 -0
  16. package/public/api.js +78 -0
  17. package/public/app.js +95 -0
  18. package/public/base.css +4 -0
  19. package/public/cache.js +27 -0
  20. package/public/chat.js +1087 -0
  21. package/public/files.js +476 -0
  22. package/public/git.js +130 -0
  23. package/public/index.html +61 -0
  24. package/public/lib.js +2 -0
  25. package/public/router.js +71 -0
  26. package/public/settings.js +90 -0
  27. package/public/shell/boot.js +159 -0
  28. package/public/shell/dashboard.js +269 -0
  29. package/public/shell/hub.js +192 -0
  30. package/public/shell/layout.js +195 -0
  31. package/public/shell/notes.js +323 -0
  32. package/public/shell/session-context.js +19 -0
  33. package/public/shell/session-list.js +442 -0
  34. package/public/shell/session-nav.js +299 -0
  35. package/public/shell/templates.js +342 -0
  36. package/public/shell/util.js +63 -0
  37. package/public/shell.js +589 -0
  38. package/public/state.js +362 -0
  39. package/public/style.css +1048 -0
  40. package/public/terminal.js +177 -0
  41. package/public/xterm.min.css +209 -0
  42. package/public/xterm.min.js +2 -0
  43. package/server.js +12 -0
  44. package/src/agents/claude.js +58 -0
  45. package/src/agents/codex.js +284 -0
  46. package/src/agents/grok.js +318 -0
  47. package/src/agents/meta-agent.js +1952 -0
  48. package/src/agents/models.js +339 -0
  49. package/src/agents/sessions.js +1508 -0
  50. 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
+ });
@@ -0,0 +1,4 @@
1
+ @import "tailwindcss";
2
+ @plugin "daisyui" {
3
+ themes: light, dark;
4
+ }
@@ -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)