@sergeychuvayev/claude-fleet 0.3.0 → 0.4.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/managed.js +1 -1
- package/package.json +1 -1
- package/public/app.js +5 -1
- package/public/control.js +3 -0
- package/public/index.html +1 -1
- package/public/styles.css +3 -0
package/managed.js
CHANGED
|
@@ -149,7 +149,7 @@ class ManagedSessions extends EventEmitter {
|
|
|
149
149
|
turn:turnSummary(managedEvents(s.messages), { working: ACTIVE.has(s.status) && s.status !== 'approval' }),
|
|
150
150
|
error:s.error, currentTool:s.currentTool, resumeCmd:s.sessionId ? `claude --resume ${s.sessionId}` : null,
|
|
151
151
|
kind:s.kind || 'agent', teamId:s.teamId || null, teamName:s.teamName || null,
|
|
152
|
-
worktreeBranch:s.worktree?.branch || null,
|
|
152
|
+
worktreeBranch:s.worktree?.branch || null, costUsd:s.costUsd || 0,
|
|
153
153
|
}))
|
|
154
154
|
}
|
|
155
155
|
create(body) {
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -43,6 +43,10 @@ const STEP_ICON = { inspect: '▤', change: '✎', run: '⚡', delegate: '✳',
|
|
|
43
43
|
const STEP_WORD = { inspect: 'inspecting', change: 'changing files', run: 'running commands', delegate: 'delegating', ask: 'asking', other: 'other' }
|
|
44
44
|
const stepCategory = name => ['Read','Grep','Glob','LS','WebFetch','WebSearch'].includes(name) ? 'inspect' : ['Edit','Write','MultiEdit','NotebookEdit'].includes(name) ? 'change' : ['Bash','BashOutput','KillShell'].includes(name) ? 'run' : ['Task','Skill','Agent'].includes(name) ? 'delegate' : ['AskUserQuestion','ExitPlanMode','EnterPlanMode'].includes(name) ? 'ask' : 'other'
|
|
45
45
|
const elapsed = ms => ms < 60000 ? `${Math.max(1, Math.round(ms / 1000))}s` : ms < 3600000 ? `${Math.floor(ms / 60000)}m ${String(Math.round(ms % 60000 / 1000)).padStart(2, '0')}s` : `${Math.floor(ms / 3600000)}h ${Math.floor(ms % 3600000 / 60000)}m`
|
|
46
|
+
// What a managed conversation has cost so far. Only Fleet's own runs report a cost, so a
|
|
47
|
+
// monitored terminal session shows nothing rather than a misleading zero. Fractions of a
|
|
48
|
+
// cent round to $0.00 and read as broken, so anything non-zero but tiny says so instead.
|
|
49
|
+
const money = value => !(value > 0) ? null : value < 0.01 ? '<$0.01' : `$${value.toFixed(2)}`
|
|
46
50
|
function turnRow(s) {
|
|
47
51
|
const t = s.turn
|
|
48
52
|
if (!t || (!t.steps.length && !t.current && !t.last)) return ''
|
|
@@ -99,7 +103,7 @@ function render() {
|
|
|
99
103
|
renderArchiveBar(live.filter(s => s.state === 'dead'), archived.length)
|
|
100
104
|
update('session-list', shown.length ? shown.map(s => {
|
|
101
105
|
const p = percent(s)
|
|
102
|
-
return `<button class="session" data-session="${esc(key(s))}" aria-pressed="${selected === key(s)}" aria-controls="detail" title="${hasUnseen(s) ? 'New output since you last opened this' : ''}"><span><span class="session-top">${hasUnseen(s) ? '<span class="unseen" aria-label="New output"></span>' : ''}${status(s)}<span class="session-name">${esc((s.managed ? 'FLEET · ' : '') + (s.name || s.shortId || 'Unnamed session'))}</span>${spawnCounts.get(s.pid) ? `<span class="spawn-badge" title="Running ${spawnCounts.get(s.pid)} background session(s)">⑂ ${spawnCounts.get(s.pid)}</span>` : ''}${s.background ? `<span class="spawn-owner" title="Started by ${esc(s.spawnedByName || 'a program')}, not from a terminal">via ${esc(s.spawnedByName || 'a program')}</span>` : ''}${s.archived ? '<span class="archived-tag" title="Archived. Hidden from your fleet, still on disk and still resumable.">archived</span>' : ''}</span>${s.kind === 'initiative' ? `<span class="initiative-tag">Initiative · ${esc(s.teamName || s.teamId || 'Team')}</span>` : ''}<span class="session-title">${esc(s.title || s.lastPrompt || 'Untitled session')}</span><span class="session-meta"><span>${esc(s.cwd?.split('/').filter(Boolean).pop() || 'No project')}</span><span class="branch">⑂ ${esc(s.branch || 'No branch')}</span>${s.links?.length ? `<span>↗ ${s.links.length}</span>` : ''}</span>${turnRow(s)}</span><span class="session-context ${heat(p)}">${p === null ? '—' : Math.round(p)+'%'}<span class="mini-bar"><i class="${heat(p)}" style="width:${p || 0}%"></i></span><small>${age(s.lastActivity)} ago</small></span></button>`
|
|
106
|
+
return `<button class="session" data-session="${esc(key(s))}" aria-pressed="${selected === key(s)}" aria-controls="detail" title="${hasUnseen(s) ? 'New output since you last opened this' : ''}"><span><span class="session-top">${hasUnseen(s) ? '<span class="unseen" aria-label="New output"></span>' : ''}${status(s)}<span class="session-name">${esc((s.managed ? 'FLEET · ' : '') + (s.name || s.shortId || 'Unnamed session'))}</span>${spawnCounts.get(s.pid) ? `<span class="spawn-badge" title="Running ${spawnCounts.get(s.pid)} background session(s)">⑂ ${spawnCounts.get(s.pid)}</span>` : ''}${s.background ? `<span class="spawn-owner" title="Started by ${esc(s.spawnedByName || 'a program')}, not from a terminal">via ${esc(s.spawnedByName || 'a program')}</span>` : ''}${s.archived ? '<span class="archived-tag" title="Archived. Hidden from your fleet, still on disk and still resumable.">archived</span>' : ''}</span>${s.kind === 'initiative' ? `<span class="initiative-tag">Initiative · ${esc(s.teamName || s.teamId || 'Team')}</span>` : ''}<span class="session-title">${esc(s.title || s.lastPrompt || 'Untitled session')}</span><span class="session-meta"><span>${esc(s.cwd?.split('/').filter(Boolean).pop() || 'No project')}</span><span class="branch">⑂ ${esc(s.branch || 'No branch')}</span>${s.links?.length ? `<span>↗ ${s.links.length}</span>` : ''}${money(s.costUsd) ? `<span class="session-cost" title="What this conversation has cost so far">${esc(money(s.costUsd))}</span>` : ''}</span>${turnRow(s)}</span><span class="session-context ${heat(p)}">${p === null ? '—' : Math.round(p)+'%'}<span class="mini-bar"><i class="${heat(p)}" style="width:${p || 0}%"></i></span><small>${age(s.lastActivity)} ago</small></span></button>`
|
|
103
107
|
}).join('') : `<div class="empty">${filter === 'background' ? 'No background sessions right now.' : total ? 'No sessions match your filters.<br>Try another search or select All sessions.' : 'Your fleet is quiet.<br>Start a Claude Code session and it will appear here automatically.'}</div>`)
|
|
104
108
|
const current = shown.find(s => key(s) === selected)
|
|
105
109
|
if (current) markSeen(key(current), current.lastActivity)
|
package/public/control.js
CHANGED
|
@@ -18,6 +18,9 @@ async function initializeControls() {
|
|
|
18
18
|
if(!response.ok) throw new Error('Agent controls are unavailable. Restart the updated Fleet server.')
|
|
19
19
|
const data=await response.json()
|
|
20
20
|
controlToken=data.token
|
|
21
|
+
// The running server's version, not the version on disk: a restart is what picks up an
|
|
22
|
+
// update, and without this the difference is invisible until something 404s.
|
|
23
|
+
if(data.version) $('app-version').textContent=`v${data.version}`
|
|
21
24
|
if(!$('launch-cwd').value) $('launch-cwd').value=data.defaultCwd
|
|
22
25
|
}
|
|
23
26
|
let launchTeams=null, launchTeamsLoading=false
|
package/public/index.html
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="dark"><title>Fleet — Claude Code control room</title><link rel="manifest" href="/manifest.webmanifest"><link rel="icon" href="/icons/fleet-192.png" type="image/png"><link rel="apple-touch-icon" href="/icons/fleet-192.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-title" content="Fleet"><link rel="stylesheet" href="/theme.css"><link rel="stylesheet" href="/styles.css"><script src="/vendor/libs.js" defer></script><script src="/app.js" defer></script><script src="/blocks.js" defer></script><script src="/control.js" defer></script><script src="/ask.js" defer></script></head>
|
|
3
|
-
<body><header class="topbar"><a class="brand" href="/" aria-label="Fleet home"><span class="brandmark">✳</span> fleet <span class="brand-sub">/ CLAUDE CODE</span></a><div class="connection"><span id="connection-dot" class="dot busy"></span><span id="connection">Connecting</span><span class="local">LOCAL CONTROL ROOM</span></div><div class="refresh-info"><button id="update-pill" class="button update-pill" hidden></button><span id="updated">Waiting for first snapshot</span><button id="refresh" class="button">↻ Refresh</button><button id="ask-sessions" class="button" aria-expanded="false" aria-controls="ask-backdrop" title="Ask a question across every session on this machine">⌕ Ask <kbd id="ask-shortcut">⌘K</kbd></button><button id="new-session" class="button resume" aria-expanded="false" aria-controls="launch-backdrop">+ New agent</button></div></header>
|
|
3
|
+
<body><header class="topbar"><a class="brand" href="/" aria-label="Fleet home"><span class="brandmark">✳</span> fleet <span class="brand-sub">/ CLAUDE CODE</span></a><span class="app-version" id="app-version" title="The version of Fleet this server is running"></span><div class="connection"><span id="connection-dot" class="dot busy"></span><span id="connection">Connecting</span><span class="local">LOCAL CONTROL ROOM</span></div><div class="refresh-info"><button id="update-pill" class="button update-pill" hidden></button><span id="updated">Waiting for first snapshot</span><button id="refresh" class="button">↻ Refresh</button><button id="ask-sessions" class="button" aria-expanded="false" aria-controls="ask-backdrop" title="Ask a question across every session on this machine">⌕ Ask <kbd id="ask-shortcut">⌘K</kbd></button><button id="new-session" class="button resume" aria-expanded="false" aria-controls="launch-backdrop">+ New agent</button></div></header>
|
|
4
4
|
<main>
|
|
5
5
|
<div id="error" class="error" role="status" hidden></div>
|
|
6
6
|
<section class="workspace" aria-label="Sessions"><div class="sessions-pane"><div class="section-heading"><h2>Sessions <span id="shown-count">0</span></h2></div><div class="filters" id="filters" aria-label="Filter sessions by status"></div><div class="archive-bar" id="archive-bar" role="group" aria-label="Archive" hidden></div><div class="list-head"><span>SESSION / PROJECT</span><span>CONTEXT</span></div><div id="session-list" class="session-list"><div class="empty">Loading your sessions…</div></div></div><div id="splitter" class="splitter" role="separator" aria-orientation="vertical" aria-label="Resize the session inspector" aria-valuemin="25" aria-valuemax="75" aria-valuenow="58" tabindex="0" title="Drag to resize · double-click to reset"></div><aside id="detail" class="detail" aria-label="Session details"><section id="control-panel" aria-label="Agent controls"></section><button type="button" id="details-toggle" class="details-toggle" aria-expanded="true" aria-controls="detail-content" hidden><span class="details-chevron" aria-hidden="true">›</span>Session details</button><div id="detail-content"></div></aside></section>
|
package/public/styles.css
CHANGED
|
@@ -462,3 +462,6 @@ body[data-modal]{overflow:hidden}
|
|
|
462
462
|
.delegation-mandate>summary:focus-visible,.delegation-report>summary:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
|
|
463
463
|
.delegation-mandate .block-prose,.delegation-report .block-prose{padding:12px 0 0}
|
|
464
464
|
.delegation-mandate .block-plain,.delegation-report .block-plain{white-space:pre-wrap;overflow-wrap:anywhere}
|
|
465
|
+
|
|
466
|
+
.app-version{align-self:center;margin-left:8px;color:var(--muted);font-size:10px;letter-spacing:.04em;font-variant-numeric:tabular-nums}
|
|
467
|
+
.session-cost{font-variant-numeric:tabular-nums}
|