claude-simple 0.2.9 → 0.2.11
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 +13 -5
- package/dist/app.0.2.9.min.js +143 -139
- package/dist/style.0.2.9.min.css +1 -1
- package/package.json +11 -3
- package/public/chat.js +5 -5
- package/public/files.js +5 -5
- package/public/index.html +6 -7
- package/public/lib.js +1 -1
- package/public/router.js +36 -8
- package/public/settings.js +54 -2
- package/public/shell/boot.js +7 -7
- package/public/shell/layout.js +2 -3
- package/public/shell/session-list.js +5 -12
- package/public/shell/templates.js +34 -28
- package/public/shell/util.js +3 -1
- package/public/shell.js +54 -13
- package/public/state.js +36 -5
- package/public/style.css +13 -0
- package/public/sw.js +6 -2
- package/public/ui.min.css +2 -0
- package/public/vendor/highlight-dark.min.css +10 -0
- package/public/vendor/highlight.min.js +1262 -0
- package/public/vendor/jszip.min.js +13 -0
- package/public/vendor/mammoth.browser.min.js +21 -0
- package/public/vendor/marked.min.js +6 -0
- package/public/vendor/mini-react.min.js +4 -0
- package/public/vendor/pdf.min.js +22 -0
- package/public/vendor/pdf.worker.min.js +22 -0
- package/public/vendor/xlsx.full.min.js +22 -0
- package/src/agents/cursor.js +189 -0
- package/src/agents/gemini.js +182 -0
- package/src/agents/meta-agent.js +9 -5
- package/src/agents/models.js +112 -2
- package/src/agents/sessions.js +303 -14
- package/src/app.js +119 -7
- package/src/mcp.js +275 -0
package/public/shell.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
expandedFolders, collapsedFolders, filesPath, viewingFile, filteredSessions, projectGroups,
|
|
8
8
|
currentProject, currentTab, filesRoot, gitRoot,
|
|
9
9
|
currentModel, currentEffort, currentPermission, currentAgent, setAgent, setCurrentModel,
|
|
10
|
-
sidebarView, agentFilter, timeRange, activityHits, activityLoading,
|
|
10
|
+
sidebarView, agentFilter, agentFilters, timeRange, activityHits, activityLoading,
|
|
11
11
|
chatDensity, setChatDensity,
|
|
12
12
|
favoritesOnly, showHiddenOnly, hubMode, hubMachineReady, selectedMachineId, setSelectedMachine,
|
|
13
13
|
machinesList, AGENT_LABELS, getDefaultModel, sessionMetaMap, ctx,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
connectWS, clearMessages, appendMsg, appendSystemMsg, sendMessage, stopProcessing,
|
|
21
21
|
applyChatDensity,
|
|
22
22
|
} from './chat.js';
|
|
23
|
-
import { syncHash } from './router.js';
|
|
23
|
+
import { syncHash, currentSessionShareUrl } from './router.js';
|
|
24
24
|
import { initSettings, openSettings } from './settings.js';
|
|
25
25
|
import { openMetaAgent, toggleMetaAgent } from './agent-panel.js';
|
|
26
26
|
import {
|
|
@@ -322,20 +322,31 @@ export function initShell(opts = {}) {
|
|
|
322
322
|
});
|
|
323
323
|
document.addEventListener('router:home', goHome);
|
|
324
324
|
|
|
325
|
-
document.addEventListener('router:session', async ({ detail: { id, tab } }) => {
|
|
325
|
+
document.addEventListener('router:session', async ({ detail: { id, tab, machineId, agent } }) => {
|
|
326
326
|
const s = sessionsData.peek().find(x => x.sessionId === id);
|
|
327
327
|
const last = getLastSessionContext();
|
|
328
328
|
await resumeSession(
|
|
329
329
|
id,
|
|
330
330
|
s?.cwd || (last?.sessionId === id ? last.cwd : null) || null,
|
|
331
331
|
s?.configDir || (last?.sessionId === id ? last.configDir : null) || null,
|
|
332
|
-
s?.agent || (last?.sessionId === id ? last.agent : null) || null,
|
|
333
|
-
s?.machineId || (last?.sessionId === id ? last.machineId : null) || null,
|
|
332
|
+
agent || s?.agent || (last?.sessionId === id ? last.agent : null) || null,
|
|
333
|
+
machineId || s?.machineId || (last?.sessionId === id ? last.machineId : null) || null,
|
|
334
334
|
{ tab: tab || 'chat' },
|
|
335
335
|
);
|
|
336
336
|
});
|
|
337
337
|
|
|
338
338
|
delegate.on('click', '#btn-home', goHome);
|
|
339
|
+
delegate.on('click', '#btn-share-session', async (_, el) => {
|
|
340
|
+
const url = currentSessionShareUrl();
|
|
341
|
+
if (!url) return;
|
|
342
|
+
try {
|
|
343
|
+
await navigator.clipboard.writeText(url);
|
|
344
|
+
el.textContent = '已复制';
|
|
345
|
+
setTimeout(() => { el.textContent = '分享'; }, 1400);
|
|
346
|
+
} catch {
|
|
347
|
+
window.prompt('复制会话链接:', url);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
339
350
|
delegate.on('click', '#auth-btn', submitAuth);
|
|
340
351
|
delegate.on('submit', '#auth-form', e => { e.preventDefault(); submitAuth(); });
|
|
341
352
|
delegate.on('keydown', '#auth-username, #auth-password', e => { if (e.key === 'Enter') submitAuth(); });
|
|
@@ -353,6 +364,41 @@ export function initShell(opts = {}) {
|
|
|
353
364
|
sessionSearch.value = el.value;
|
|
354
365
|
scheduleActivitySearch(el.value);
|
|
355
366
|
});
|
|
367
|
+
delegate.on('click', '#sidebar-filter-toggle', () => {
|
|
368
|
+
const menu = $('sidebar-filter-menu');
|
|
369
|
+
if (!menu) return;
|
|
370
|
+
const open = menu.classList.toggle('hidden');
|
|
371
|
+
$('sidebar-filter-toggle')?.setAttribute('aria-expanded', String(!open));
|
|
372
|
+
});
|
|
373
|
+
delegate.on('change', '[data-agent-option]', (_, el) => {
|
|
374
|
+
const next = new Set(agentFilters.peek());
|
|
375
|
+
if (el.checked) next.add(el.dataset.agentOption);
|
|
376
|
+
else next.delete(el.dataset.agentOption);
|
|
377
|
+
const values = [...next];
|
|
378
|
+
agentFilters.value = values;
|
|
379
|
+
localStorage.setItem('agentFilters', JSON.stringify(values));
|
|
380
|
+
agentFilter.value = values.length === 1 ? values[0] : 'all';
|
|
381
|
+
});
|
|
382
|
+
delegate.on('change', '#filter-favorites', (_, el) => {
|
|
383
|
+
favoritesOnly.value = el.checked;
|
|
384
|
+
localStorage.setItem('favoritesOnly', el.checked ? '1' : '0');
|
|
385
|
+
});
|
|
386
|
+
delegate.on('change', '#filter-hidden', (_, el) => {
|
|
387
|
+
showHiddenOnly.value = el.checked;
|
|
388
|
+
localStorage.setItem('showHiddenOnly', el.checked ? '1' : '0');
|
|
389
|
+
});
|
|
390
|
+
delegate.on('click', '#filter-clear', () => {
|
|
391
|
+
agentFilters.value = [];
|
|
392
|
+
agentFilter.value = 'all';
|
|
393
|
+
favoritesOnly.value = false;
|
|
394
|
+
showHiddenOnly.value = false;
|
|
395
|
+
localStorage.setItem('agentFilters', '[]');
|
|
396
|
+
localStorage.setItem('favoritesOnly', '0');
|
|
397
|
+
localStorage.setItem('showHiddenOnly', '0');
|
|
398
|
+
document.querySelectorAll('[data-agent-option]').forEach(el => { el.checked = false; });
|
|
399
|
+
if ($('filter-favorites')) $('filter-favorites').checked = false;
|
|
400
|
+
if ($('filter-hidden')) $('filter-hidden').checked = false;
|
|
401
|
+
});
|
|
356
402
|
delegate.on('click', '#session-filter-badge', () => { sessionFilter.value = null; });
|
|
357
403
|
delegate.on('click', '[data-ws-tab]', (_, el) => { sessionFilter.value = el.dataset.wsTab || null; });
|
|
358
404
|
delegate.on('click', '#sidebar-refresh', () => {
|
|
@@ -368,12 +414,6 @@ export function initShell(opts = {}) {
|
|
|
368
414
|
localStorage.setItem('agentFilter', el.dataset.agentFilter);
|
|
369
415
|
if (sessionSearch.peek().trim()) scheduleActivitySearch(sessionSearch.peek());
|
|
370
416
|
});
|
|
371
|
-
delegate.on('change', '#time-range', (_, el) => {
|
|
372
|
-
timeRange.value = el.value;
|
|
373
|
-
localStorage.setItem('timeRange', el.value);
|
|
374
|
-
loadAllSessions({ waitFresh: true });
|
|
375
|
-
if (sessionSearch.peek().trim()) scheduleActivitySearch(sessionSearch.peek());
|
|
376
|
-
});
|
|
377
417
|
delegate.on('dblclick', '[data-project-cwd]', (_, el) => {
|
|
378
418
|
const cwd = el.dataset.projectCwd;
|
|
379
419
|
if (!cwd) return;
|
|
@@ -783,8 +823,9 @@ export function initShell(opts = {}) {
|
|
|
783
823
|
applyChatDensity();
|
|
784
824
|
const dens = $('sel-density');
|
|
785
825
|
if (dens) dens.value = chatDensity.peek() || 'normal';
|
|
786
|
-
|
|
787
|
-
if (
|
|
826
|
+
document.querySelectorAll('[data-agent-option]').forEach(el => { el.checked = agentFilters.peek().includes(el.dataset.agentOption); });
|
|
827
|
+
if ($('filter-favorites')) $('filter-favorites').checked = favoritesOnly.peek();
|
|
828
|
+
if ($('filter-hidden')) $('filter-hidden').checked = showHiddenOnly.peek();
|
|
788
829
|
document.querySelectorAll('[data-agent-filter]').forEach(btn => {
|
|
789
830
|
btn.classList.toggle('active', btn.dataset.agentFilter === agentFilter.peek());
|
|
790
831
|
});
|
package/public/state.js
CHANGED
|
@@ -55,7 +55,7 @@ export function setCurrentModel(model, agent = currentAgent.peek(), sessionId =
|
|
|
55
55
|
currentModel.value = value;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
export const currentAgent = signal(initialAgent); // 'claude'|'codex'|'grok'
|
|
58
|
+
export const currentAgent = signal(initialAgent); // 'claude'|'codex'|'grok'|'gemini'|'cursor'
|
|
59
59
|
export const currentModel = signal('claude-sonnet-4-5');
|
|
60
60
|
export const currentEffort = signal('');
|
|
61
61
|
// All local agents are trusted by default; users can still choose another mode
|
|
@@ -67,7 +67,13 @@ export const agentsMeta = signal(null); // from /api/agents (dynamic model l
|
|
|
67
67
|
|
|
68
68
|
// Sidebar project-management filters
|
|
69
69
|
export const sidebarView = signal(localStorage.getItem('sidebarView') || 'projects'); // 'projects' | 'timeline'
|
|
70
|
-
export const agentFilter = signal(localStorage.getItem('agentFilter') || 'all'); // all|claude|codex|grok
|
|
70
|
+
export const agentFilter = signal(localStorage.getItem('agentFilter') || 'all'); // all|claude|codex|grok|gemini|cursor
|
|
71
|
+
export const agentFilters = signal((() => {
|
|
72
|
+
try {
|
|
73
|
+
const saved = JSON.parse(localStorage.getItem('agentFilters') || '[]');
|
|
74
|
+
return Array.isArray(saved) ? saved.filter(Boolean) : [];
|
|
75
|
+
} catch { return []; }
|
|
76
|
+
})()); // multi-select sidebar filter; empty means all agents
|
|
71
77
|
export const timeRange = signal(localStorage.getItem('timeRange') || '14'); // '0'|'1'|'7'|'14'|'30'
|
|
72
78
|
export const activityHits = signal(null); // null | { q, results, loading, error }
|
|
73
79
|
export const activityLoading = signal(false);
|
|
@@ -147,6 +153,8 @@ export const AGENT_LABELS = {
|
|
|
147
153
|
claude: 'Claude',
|
|
148
154
|
codex: 'Codex',
|
|
149
155
|
grok: 'Grok',
|
|
156
|
+
gemini: 'Gemini',
|
|
157
|
+
cursor: 'Cursor',
|
|
150
158
|
};
|
|
151
159
|
|
|
152
160
|
/** Static fallbacks when /api/agents has not loaded yet. */
|
|
@@ -171,12 +179,32 @@ export const AGENT_MODELS = {
|
|
|
171
179
|
{ value: 'grok-3', label: 'grok-3' },
|
|
172
180
|
{ value: 'grok-3-mini', label: 'grok-3-mini' },
|
|
173
181
|
],
|
|
182
|
+
gemini: [
|
|
183
|
+
{ value: 'gemini-3.7-flash-high', label: 'Gemini 3.7 Flash (High)' },
|
|
184
|
+
{ value: 'gemini-3.7-flash-medium', label: 'Gemini 3.7 Flash (Medium)' },
|
|
185
|
+
{ value: 'gemini-3.7-flash-low', label: 'Gemini 3.7 Flash (Low)' },
|
|
186
|
+
{ value: 'gemini-3.6-flash-high', label: 'Gemini 3.6 Flash (High)' },
|
|
187
|
+
{ value: 'gemini-3.6-flash-medium', label: 'Gemini 3.6 Flash (Medium)' },
|
|
188
|
+
{ value: 'gemini-3.6-flash-low', label: 'Gemini 3.6 Flash (Low)' },
|
|
189
|
+
{ value: 'gemini-3.5-flash-high', label: 'Gemini 3.5 Flash (High)' },
|
|
190
|
+
{ value: 'gemini-3.5-flash-medium', label: 'Gemini 3.5 Flash (Medium)' },
|
|
191
|
+
{ value: 'gemini-3.5-flash-low', label: 'Gemini 3.5 Flash (Low)' },
|
|
192
|
+
{ value: 'gemini-3.1-pro-high', label: 'Gemini 3.1 Pro (High)' },
|
|
193
|
+
{ value: 'gemini-3.1-pro-low', label: 'Gemini 3.1 Pro (Low)' },
|
|
194
|
+
],
|
|
195
|
+
cursor: [
|
|
196
|
+
{ value: 'auto', label: 'Auto' },
|
|
197
|
+
{ value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
|
|
198
|
+
{ value: 'composer-2.5', label: 'Composer 2.5' },
|
|
199
|
+
],
|
|
174
200
|
};
|
|
175
201
|
|
|
176
202
|
export const AGENT_DEFAULT_MODEL = {
|
|
177
203
|
claude: 'claude-sonnet-4-5',
|
|
178
204
|
codex: 'gpt-5.4',
|
|
179
205
|
grok: 'grok-4.5',
|
|
206
|
+
gemini: 'gemini-3.7-flash-high',
|
|
207
|
+
cursor: 'auto',
|
|
180
208
|
};
|
|
181
209
|
|
|
182
210
|
function normalizeModelEntry(m) {
|
|
@@ -294,6 +322,7 @@ export function getDefaultEffort(agent, modelId) {
|
|
|
294
322
|
const m = models.find(x => x.value === modelId);
|
|
295
323
|
if (m?.defaultEffort) return String(m.defaultEffort);
|
|
296
324
|
if (a === 'grok') return 'low';
|
|
325
|
+
if (a === 'gemini') return String(modelId || '').match(/-(low|medium|high)$/i)?.[1]?.toLowerCase() || '';
|
|
297
326
|
return '';
|
|
298
327
|
}
|
|
299
328
|
|
|
@@ -314,7 +343,7 @@ export function setAgent(agent) {
|
|
|
314
343
|
}
|
|
315
344
|
const defEffort = getDefaultEffort(a, currentModel.peek());
|
|
316
345
|
if (defEffort) currentEffort.value = defEffort;
|
|
317
|
-
else if (a !== 'grok') currentEffort.value = '';
|
|
346
|
+
else if (a !== 'grok' && a !== 'gemini') currentEffort.value = '';
|
|
318
347
|
}
|
|
319
348
|
|
|
320
349
|
function matchesAgentFilter(s, filter) {
|
|
@@ -359,7 +388,7 @@ export const filteredSessions = computed(() => {
|
|
|
359
388
|
const search = sessionSearch.value.toLowerCase().trim();
|
|
360
389
|
const sort = sessionSort.value;
|
|
361
390
|
const aFilter = agentFilter.value;
|
|
362
|
-
const
|
|
391
|
+
const aFilters = agentFilters.value;
|
|
363
392
|
const favOnly = favoritesOnly.value;
|
|
364
393
|
const hiddenOnly = showHiddenOnly.value;
|
|
365
394
|
const metaMap = sessionMetaMap.value;
|
|
@@ -375,7 +404,9 @@ export const filteredSessions = computed(() => {
|
|
|
375
404
|
if (hubMode.value && mid) {
|
|
376
405
|
list = list.filter(s => s && (!s.machineId || s.machineId === mid));
|
|
377
406
|
}
|
|
378
|
-
list = list.filter(s => s &&
|
|
407
|
+
list = list.filter(s => s && (aFilters.length
|
|
408
|
+
? aFilters.includes(s.agent || 'claude')
|
|
409
|
+
: matchesAgentFilter(s, aFilter)));
|
|
379
410
|
// Hidden sessions: excluded by default; "Hidden" filter shows only them
|
|
380
411
|
if (hiddenOnly) {
|
|
381
412
|
list = list.filter(s => s && metaMap?.[metaKey(s.agent, s.sessionId, s.machineId)]?.hidden);
|
package/public/style.css
CHANGED
|
@@ -1141,6 +1141,18 @@ html.pwa-standalone .ma-panel {
|
|
|
1141
1141
|
#recent-menu.recent-menu-open {
|
|
1142
1142
|
display: block; /* beat .hidden if both race */
|
|
1143
1143
|
}
|
|
1144
|
+
.topbar-icon-btn {
|
|
1145
|
+
gap: .35rem;
|
|
1146
|
+
min-width: 2rem;
|
|
1147
|
+
padding-inline: .45rem;
|
|
1148
|
+
}
|
|
1149
|
+
.topbar-icon {
|
|
1150
|
+
width: 1rem;
|
|
1151
|
+
height: 1rem;
|
|
1152
|
+
display: block;
|
|
1153
|
+
flex: 0 0 auto;
|
|
1154
|
+
}
|
|
1155
|
+
.topbar-icon-label { display: inline; }
|
|
1144
1156
|
@media (max-width: 640px) {
|
|
1145
1157
|
#recent-menu {
|
|
1146
1158
|
min-width: 0;
|
|
@@ -1161,6 +1173,7 @@ html.pwa-standalone .ma-panel {
|
|
|
1161
1173
|
#btn-pwa-install {
|
|
1162
1174
|
display: none !important;
|
|
1163
1175
|
}
|
|
1176
|
+
.topbar-icon-label { display: none; }
|
|
1164
1177
|
#topbar-project {
|
|
1165
1178
|
font-size: 11px;
|
|
1166
1179
|
max-width: 30vw;
|
package/public/sw.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/* Agent UI service worker — cache shell assets only.
|
|
2
2
|
* Never intercepts WebSocket or mutates API semantics beyond offline fallback.
|
|
3
3
|
* Bump CACHE when shipping UI that must invalidate old shells. */
|
|
4
|
-
const CACHE = 'agent-ui-shell-
|
|
4
|
+
const CACHE = 'agent-ui-shell-v16';
|
|
5
5
|
const PRECACHE = [
|
|
6
6
|
'/',
|
|
7
7
|
'/index.html',
|
|
8
8
|
'/manifest.webmanifest',
|
|
9
9
|
'/style.css?v=ui-11',
|
|
10
10
|
'/style.css',
|
|
11
|
+
'/ui.min.css',
|
|
12
|
+
'/vendor/mini-react.min.js',
|
|
13
|
+
'/vendor/marked.min.js',
|
|
14
|
+
'/vendor/highlight.min.js',
|
|
15
|
+
'/vendor/highlight-dark.min.css',
|
|
11
16
|
'/app.js',
|
|
12
17
|
'/icons/icon-192.png',
|
|
13
18
|
'/icons/icon-512.png',
|
|
@@ -60,7 +65,6 @@ self.addEventListener('fetch', (event) => {
|
|
|
60
65
|
// Let the browser handle API + anything that might upgrade to WebSocket.
|
|
61
66
|
if (isApiOrRealtime(url)) return;
|
|
62
67
|
|
|
63
|
-
// Cross-origin (CDN daisyui/tailwind/marked): network only — do not cache opaque forever.
|
|
64
68
|
if (url.origin !== self.location.origin) return;
|
|
65
69
|
|
|
66
70
|
// Navigations: network-first so deploys show up; offline → cached shell.
|