@specship/specship-win32-arm64 0.12.0 → 0.13.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/lib/dist/bin/specship.js +48 -12
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/db/migrations.d.ts +1 -1
- package/lib/dist/db/migrations.d.ts.map +1 -1
- package/lib/dist/db/migrations.js +16 -1
- package/lib/dist/db/migrations.js.map +1 -1
- package/lib/dist/db/schema.sql +10 -0
- package/lib/dist/db/spec-queries.d.ts +6 -0
- package/lib/dist/db/spec-queries.d.ts.map +1 -1
- package/lib/dist/db/spec-queries.js +8 -0
- package/lib/dist/db/spec-queries.js.map +1 -1
- package/lib/dist/index.d.ts +8 -0
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +9 -0
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/server/cli.js +9 -7
- package/lib/dist/server/product-version.js +44 -0
- package/lib/dist/server/routes/claude.js +153 -42
- package/lib/dist/server/routes/config.js +35 -0
- package/lib/dist/server/routes/graph.js +22 -1
- package/lib/dist/server/routes/mcp.js +510 -0
- package/lib/dist/server/routes/projects.js +31 -3
- package/lib/dist/server/routes/status.js +3 -0
- package/lib/dist/server/routes/workflow.js +44 -3
- package/lib/dist/server/server-config.js +38 -0
- package/lib/dist/server/server.js +128 -58
- package/lib/dist/statusline/active-run.d.ts +2 -2
- package/lib/dist/statusline/active-run.d.ts.map +1 -1
- package/lib/dist/statusline/active-run.js +2 -2
- package/lib/dist/statusline/active-run.js.map +1 -1
- package/lib/dist/statusline/render.d.ts.map +1 -1
- package/lib/dist/statusline/render.js +41 -5
- package/lib/dist/statusline/render.js.map +1 -1
- package/lib/dist/statusline/types.d.ts +15 -0
- package/lib/dist/statusline/types.d.ts.map +1 -1
- package/lib/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/lib/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/lib/dist/ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/lib/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/lib/dist/ui/assets/index-D8e4LiVb.js +51 -0
- package/lib/dist/ui/assets/index-ezwX2EfG.css +1 -0
- package/lib/dist/ui/favicon-16.png +0 -0
- package/lib/dist/ui/favicon-180.png +0 -0
- package/lib/dist/ui/favicon-32.png +0 -0
- package/lib/dist/ui/favicon.svg +20 -0
- package/lib/dist/ui/index.html +17 -0
- package/lib/dist/update/resolve-latest.d.ts +14 -0
- package/lib/dist/update/resolve-latest.d.ts.map +1 -0
- package/lib/dist/update/resolve-latest.js +29 -0
- package/lib/dist/update/resolve-latest.js.map +1 -0
- package/lib/dist/update/run-installer.d.ts +13 -0
- package/lib/dist/update/run-installer.d.ts.map +1 -0
- package/lib/dist/update/run-installer.js +43 -0
- package/lib/dist/update/run-installer.js.map +1 -0
- package/lib/dist/update/updater.d.ts +53 -0
- package/lib/dist/update/updater.d.ts.map +1 -0
- package/lib/dist/update/updater.js +164 -0
- package/lib/dist/update/updater.js.map +1 -0
- package/lib/dist/workflows/eta.d.ts +42 -0
- package/lib/dist/workflows/eta.d.ts.map +1 -0
- package/lib/dist/workflows/eta.js +146 -0
- package/lib/dist/workflows/eta.js.map +1 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +25 -6
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/dist/workflows/runners/prompt.d.ts +6 -0
- package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
- package/lib/dist/workflows/runners/prompt.js +10 -0
- package/lib/dist/workflows/runners/prompt.js.map +1 -1
- package/lib/dist/workflows/runners/types.d.ts +12 -0
- package/lib/dist/workflows/runners/types.d.ts.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +3 -2
- package/package.json +1 -1
- package/lib/dist/server/ssr/md.mjs +0 -83
- package/lib/dist/server/ssr/public/app.css +0 -1
- package/lib/dist/server/ssr/render.mjs +0 -564
- package/lib/dist/server/ssr/routes.js +0 -73
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted server runtime config — the settings the dashboard can change
|
|
3
|
+
* at runtime and that must survive a restart (REQ-DESKTOP-028.A2). Lives at
|
|
4
|
+
* `~/.specship/server-config.json` (user-level, not per-project: the ingest
|
|
5
|
+
* watcher reads every project's transcripts). `SPECSHIP_SERVER_CONFIG`
|
|
6
|
+
* overrides the path so tests never touch the real home directory.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as os from 'node:os';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
export function serverConfigPath() {
|
|
12
|
+
return process.env.SPECSHIP_SERVER_CONFIG
|
|
13
|
+
?? path.join(os.homedir(), '.specship', 'server-config.json');
|
|
14
|
+
}
|
|
15
|
+
export function readServerConfig() {
|
|
16
|
+
try {
|
|
17
|
+
const raw = fs.readFileSync(serverConfigPath(), 'utf-8');
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (parsed && typeof parsed === 'object')
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
catch { /* missing or corrupt → defaults */ }
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Merge `patch` into the stored config and write it back atomically:
|
|
27
|
+
* write to a sibling temp file, then rename over the target. A crash
|
|
28
|
+
* mid-write can never leave a truncated JSON file behind.
|
|
29
|
+
*/
|
|
30
|
+
export function writeServerConfig(patch) {
|
|
31
|
+
const merged = { ...readServerConfig(), ...patch };
|
|
32
|
+
const file = serverConfigPath();
|
|
33
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
34
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
35
|
+
fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
|
|
36
|
+
fs.renameSync(tmp, file);
|
|
37
|
+
return merged;
|
|
38
|
+
}
|
|
@@ -33,6 +33,9 @@ import { registerReflectRoutes } from './routes/reflect.js';
|
|
|
33
33
|
import { registerMaintainabilityRoutes } from './routes/maintainability.js';
|
|
34
34
|
import { registerDomainRoutes } from './routes/domain.js';
|
|
35
35
|
import { registerChatRoutes } from './routes/chat.js';
|
|
36
|
+
import { registerMcpRoutes } from './routes/mcp.js';
|
|
37
|
+
import { registerConfigRoutes } from './routes/config.js';
|
|
38
|
+
import { readServerConfig } from './server-config.js';
|
|
36
39
|
/**
|
|
37
40
|
* Lazy-import the specship core. Two delivery shapes are supported:
|
|
38
41
|
*
|
|
@@ -43,11 +46,37 @@ import { registerChatRoutes } from './routes/chat.js';
|
|
|
43
46
|
* resolution finding `@specship/specship` (it won't, the
|
|
44
47
|
* bundle stages a single package by name `@specship/specship`).
|
|
45
48
|
*
|
|
46
|
-
* 2. **Workspace / dev** — `
|
|
47
|
-
* the workspace `file
|
|
49
|
+
* 2. **Workspace / dev** — `server/dist/server.js` imports via
|
|
50
|
+
* the workspace `file:..` dep. Falls through to the named import.
|
|
48
51
|
*
|
|
49
52
|
* The function caches the resolved module so the lookup only runs once.
|
|
50
53
|
*/
|
|
54
|
+
/**
|
|
55
|
+
* Locate the built desktop SPA (REQ-DESKTOP-017.A1) when the caller didn't
|
|
56
|
+
* pass an explicit `webDir`. Two delivery shapes, probed relative to this
|
|
57
|
+
* file so cwd never matters:
|
|
58
|
+
*
|
|
59
|
+
* 1. **Bundled** — `build-server-bundle.mjs` copies `ui/dist/**` to the
|
|
60
|
+
* root `dist/ui/`, which the platform tarball ships as
|
|
61
|
+
* `<bundle>/lib/dist/ui/` next to `dist/server/` (this file).
|
|
62
|
+
* 2. **Workspace / dev** — `server/{src,dist}/server.*` →
|
|
63
|
+
* repo root → `ui/dist/` (present only after `cd ui && npm run build`).
|
|
64
|
+
*
|
|
65
|
+
* Returns null when neither exists — the server then simply has no SPA
|
|
66
|
+
* mount, same as `webDir: null`.
|
|
67
|
+
*/
|
|
68
|
+
export function resolveDefaultWebDir() {
|
|
69
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
70
|
+
const candidates = [
|
|
71
|
+
path.resolve(here, '..', 'ui'), // bundled: dist/server → dist/ui
|
|
72
|
+
path.resolve(here, '..', '..', 'ui', 'dist'), // workspace: server/dist → <root>/ui/dist
|
|
73
|
+
];
|
|
74
|
+
for (const dir of candidates) {
|
|
75
|
+
if (existsSync(path.join(dir, 'index.html')))
|
|
76
|
+
return dir;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
51
80
|
let cachedSpecShip = null;
|
|
52
81
|
async function loadSpecShip() {
|
|
53
82
|
if (cachedSpecShip)
|
|
@@ -110,59 +139,102 @@ export async function createServer(options) {
|
|
|
110
139
|
// provided one or explicitly opted out. Hooks into the primary project's
|
|
111
140
|
// SQLite handle — when there's no primary, analytics endpoints will return
|
|
112
141
|
// 409 until one is set (typically the next server restart with -p).
|
|
142
|
+
//
|
|
143
|
+
// The persisted runtime config (~/.specship/server-config.json) gates the
|
|
144
|
+
// start too: the Settings ingest toggle must survive a restart
|
|
145
|
+
// (REQ-DESKTOP-028.A2). CLI `--no-ingest` still wins over everything.
|
|
113
146
|
let watcher = options.watcher ?? null;
|
|
114
147
|
let ownedWatcher = false;
|
|
115
|
-
|
|
148
|
+
let ingestEnabled = watcher != null
|
|
149
|
+
|| (options.ingest !== false && readServerConfig().ingestEnabled !== false);
|
|
150
|
+
const startIngestWatcher = () => {
|
|
151
|
+
if (watcher)
|
|
152
|
+
return true;
|
|
153
|
+
if (!primaryCg)
|
|
154
|
+
return false;
|
|
116
155
|
const cgAny = primaryCg;
|
|
117
156
|
const dbHandle = cgAny.db?.getDb ? cgAny.db.getDb() : cgAny.queries?.db;
|
|
118
|
-
if (dbHandle)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
157
|
+
if (!dbHandle)
|
|
158
|
+
return false;
|
|
159
|
+
// Build a sync resolveGraph: for the primary project path return the
|
|
160
|
+
// already-open SpecShip instance (which satisfies GraphLike).
|
|
161
|
+
// Sessions from other project paths resolve to null — they'll be left
|
|
162
|
+
// as 'unresolved' and retried on the next boot when that project is primary.
|
|
163
|
+
// The stored project_path is the lossy-decoded slug (every '-' → '/'), so
|
|
164
|
+
// an exact compare against the real primaryPath never matched and savings
|
|
165
|
+
// stayed 0. primaryProjectMatcher accepts both the real path and its
|
|
166
|
+
// mangled stored form. Sessions from OTHER projects still resolve to null
|
|
167
|
+
// (left 'unresolved', retried when that project is primary).
|
|
168
|
+
const primaryPath = options.projectRoot ?? null;
|
|
169
|
+
const isPrimary = primaryPath ? primaryProjectMatcher(primaryPath) : () => false;
|
|
170
|
+
const resolveGraph = (projectPath) => primaryPath && isPrimary(projectPath) ? primaryCg : null;
|
|
171
|
+
watcher = startWatcher(dbHandle, { verbose, resolveGraph });
|
|
172
|
+
ownedWatcher = true;
|
|
173
|
+
if (verbose)
|
|
174
|
+
console.error('[specship-server] JSONL ingest watcher started');
|
|
175
|
+
// Backfill displaced_files / resolution for pre-upgrade rows (is_specship=1,
|
|
176
|
+
// resolution IS NULL). Idempotent — safe to run on every boot. Non-fatal:
|
|
177
|
+
// a failure here must never abort server startup.
|
|
178
|
+
try {
|
|
179
|
+
backfillDisplaced(dbHandle, resolveGraph);
|
|
133
180
|
if (verbose)
|
|
134
|
-
console.error('[specship-server]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
console.error(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
181
|
+
console.error('[specship-server] specship-impact backfill complete');
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
console.error('[specship-server] specship-impact backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
|
|
185
|
+
}
|
|
186
|
+
// Re-cost prompts ingested while their model family was unpriced,
|
|
187
|
+
// e.g. fable sessions stuck at $0 (REQ-DASHINT-001.A2). Idempotent.
|
|
188
|
+
try {
|
|
189
|
+
const recosted = recostUnpricedPrompts(dbHandle);
|
|
190
|
+
if (verbose && recosted > 0)
|
|
191
|
+
console.error(`[specship-server] re-costed ${recosted} unpriced prompts`);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
console.error('[specship-server] pricing backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
};
|
|
198
|
+
if (!watcher && ingestEnabled) {
|
|
199
|
+
if (primaryCg) {
|
|
200
|
+
startIngestWatcher();
|
|
201
|
+
}
|
|
202
|
+
else if (verbose) {
|
|
203
|
+
console.error('[specship-server] no primary project — analytics will be empty until one is set');
|
|
156
204
|
}
|
|
157
|
-
}
|
|
158
|
-
else if (!primaryCg && options.ingest !== false && verbose) {
|
|
159
|
-
console.error('[specship-server] no primary project — analytics will be empty until one is set');
|
|
160
205
|
}
|
|
161
206
|
// Decorate the Fastify instance so route handlers can access shared state
|
|
162
207
|
// without globals or DI containers.
|
|
163
208
|
app.decorate('projects', registry);
|
|
164
209
|
app.decorate('primaryCg', primaryCg);
|
|
165
210
|
app.decorate('watcher', watcher);
|
|
211
|
+
// Runtime ingest control for GET/PUT /api/config (REQ-DESKTOP-028.A2).
|
|
212
|
+
// `enabled` is the configured intent (round-trips even when no primary
|
|
213
|
+
// project can host a watcher yet); `active` is whether one is running.
|
|
214
|
+
// start/stop keep `app.watcher` in sync so /api/refresh always sees the
|
|
215
|
+
// live handle.
|
|
216
|
+
app.decorate('ingestControl', {
|
|
217
|
+
enabled: () => ingestEnabled,
|
|
218
|
+
active: () => watcher != null,
|
|
219
|
+
start: () => {
|
|
220
|
+
ingestEnabled = true;
|
|
221
|
+
const started = startIngestWatcher();
|
|
222
|
+
app.watcher = watcher;
|
|
223
|
+
return started;
|
|
224
|
+
},
|
|
225
|
+
stop: () => {
|
|
226
|
+
ingestEnabled = false;
|
|
227
|
+
if (watcher) {
|
|
228
|
+
try {
|
|
229
|
+
watcher.stop();
|
|
230
|
+
}
|
|
231
|
+
catch { /* ignore */ }
|
|
232
|
+
}
|
|
233
|
+
watcher = null;
|
|
234
|
+
ownedWatcher = false;
|
|
235
|
+
app.watcher = null;
|
|
236
|
+
},
|
|
237
|
+
});
|
|
166
238
|
// activeCg(req): resolve `?project=<slug>` → SpecShip instance, with the
|
|
167
239
|
// primary as fallback. Returns null when nothing is selectable; route
|
|
168
240
|
// handlers respond 409 in that case.
|
|
@@ -193,19 +265,17 @@ export async function createServer(options) {
|
|
|
193
265
|
await registerMaintainabilityRoutes(app);
|
|
194
266
|
await registerDomainRoutes(app);
|
|
195
267
|
await registerChatRoutes(app);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (options.webDir) {
|
|
208
|
-
const indexPath = path.join(options.webDir, 'index.html');
|
|
268
|
+
await registerMcpRoutes(app);
|
|
269
|
+
await registerConfigRoutes(app);
|
|
270
|
+
// Serve the built desktop SPA (the `ui/` module) from `webDir` and fall back
|
|
271
|
+
// to index.html for client-side routes. This is the dashboard's only surface
|
|
272
|
+
// (REQ-DESKTOP-033 — the server-rendered dashboard retired). Must register
|
|
273
|
+
// AFTER the /api/* routes so they take precedence over the SPA wildcard. When
|
|
274
|
+
// the caller passed no webDir at all, auto-detect the SPA shipped next to the
|
|
275
|
+
// server build; `null` explicitly opts out (headless / API only).
|
|
276
|
+
const webDir = options.webDir === undefined ? resolveDefaultWebDir() : options.webDir;
|
|
277
|
+
if (webDir) {
|
|
278
|
+
const indexPath = path.join(webDir, 'index.html');
|
|
209
279
|
let indexBuffer = null;
|
|
210
280
|
try {
|
|
211
281
|
indexBuffer = await fs.readFile(indexPath);
|
|
@@ -217,7 +287,7 @@ export async function createServer(options) {
|
|
|
217
287
|
}
|
|
218
288
|
if (indexBuffer) {
|
|
219
289
|
const cachedIndex = indexBuffer;
|
|
220
|
-
const serveStatic = makeStaticHandler(
|
|
290
|
+
const serveStatic = makeStaticHandler(webDir);
|
|
221
291
|
// A single 404 handler does both jobs:
|
|
222
292
|
// 1. Try the requested URL as a real file under webDir → serve it
|
|
223
293
|
// with the right content-type. Covers the SPA's chunk-*.js,
|
|
@@ -250,7 +320,7 @@ export async function createServer(options) {
|
|
|
250
320
|
reply.code(200).type('text/html').send(cachedIndex);
|
|
251
321
|
});
|
|
252
322
|
if (verbose)
|
|
253
|
-
console.error(`[specship-server] serving SPA from ${
|
|
323
|
+
console.error(`[specship-server] serving SPA from ${webDir}`);
|
|
254
324
|
}
|
|
255
325
|
}
|
|
256
326
|
await app.listen({ host, port });
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* the `workflow_runs` table (which would mean a DB connection on the render
|
|
7
7
|
* path). `clearActiveRun` removes the marker when no run is active.
|
|
8
8
|
*/
|
|
9
|
-
import { ActiveRun } from './types';
|
|
9
|
+
import { ActiveRun, ActiveRunEta } from './types';
|
|
10
10
|
/** Atomically record the active run. Best-effort; never throws. */
|
|
11
|
-
export declare function writeActiveRun(projectRoot: string, specId: string | null, status: string): void;
|
|
11
|
+
export declare function writeActiveRun(projectRoot: string, specId: string | null, status: string, eta?: ActiveRunEta): void;
|
|
12
12
|
/** Remove the active-run marker (e.g. once a run is merged/cancelled). */
|
|
13
13
|
export declare function clearActiveRun(projectRoot: string): void;
|
|
14
14
|
/** Read the active-run marker, or null when none. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-run.d.ts","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"active-run.d.ts","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGlD,mEAAmE;AACnE,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,YAAY,GACjB,IAAI,CAON;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGnE"}
|
|
@@ -47,8 +47,8 @@ exports.readActiveRun = readActiveRun;
|
|
|
47
47
|
const fs = __importStar(require("fs"));
|
|
48
48
|
const paths_1 = require("./paths");
|
|
49
49
|
/** Atomically record the active run. Best-effort; never throws. */
|
|
50
|
-
function writeActiveRun(projectRoot, specId, status) {
|
|
51
|
-
const data = { v: 1, specId, status, updatedAt: Date.now() };
|
|
50
|
+
function writeActiveRun(projectRoot, specId, status, eta) {
|
|
51
|
+
const data = { v: 1, specId, status, updatedAt: Date.now(), ...(eta ? { eta } : {}) };
|
|
52
52
|
try {
|
|
53
53
|
(0, paths_1.writeJsonAtomic)((0, paths_1.activeRunPath)(projectRoot), data);
|
|
54
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-run.js","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,
|
|
1
|
+
{"version":3,"file":"active-run.js","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,wCAYC;AAGD,wCAMC;AAGD,sCAGC;AAhCD,uCAAyB;AAEzB,mCAAuE;AAEvE,mEAAmE;AACnE,SAAgB,cAAc,CAC5B,WAAmB,EACnB,MAAqB,EACrB,MAAc,EACd,GAAkB;IAElB,MAAM,IAAI,GAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACjG,IAAI,CAAC;QACH,IAAA,uBAAe,EAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,SAAgB,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,SAAgB,aAAa,CAAC,WAAmB;IAC/C,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAY,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA0ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAoExD"}
|
|
@@ -18,6 +18,35 @@ function bar(pct) {
|
|
|
18
18
|
const filled = Math.max(0, Math.min(cells, Math.round((pct / 100) * cells)));
|
|
19
19
|
return `❮${'▰'.repeat(filled)}${'▱'.repeat(cells - filled)}❯`;
|
|
20
20
|
}
|
|
21
|
+
/** Compact duration for the run ETA element: `4m`, `1h20m`, `<1m`. */
|
|
22
|
+
function fmtEtaDur(ms) {
|
|
23
|
+
const m = Math.round(ms / 60_000);
|
|
24
|
+
if (m < 1)
|
|
25
|
+
return '<1m';
|
|
26
|
+
if (m < 60)
|
|
27
|
+
return `${m}m`;
|
|
28
|
+
const h = Math.floor(m / 60);
|
|
29
|
+
const rest = m % 60;
|
|
30
|
+
return rest === 0 ? `${h}h` : `${h}h${rest}m`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* ETA suffix for the active-run element (REQ-STATUSLINE-011): a compact
|
|
34
|
+
* range for a running run, a waiting signal for a gated one, '' when the
|
|
35
|
+
* marker carries no estimate (older writer / no history).
|
|
36
|
+
*/
|
|
37
|
+
function etaSuffix(run) {
|
|
38
|
+
const eta = run.eta;
|
|
39
|
+
if (!eta)
|
|
40
|
+
return '';
|
|
41
|
+
if (eta.kind === 'range') {
|
|
42
|
+
const low = fmtEtaDur(eta.lowMs);
|
|
43
|
+
const high = fmtEtaDur(eta.highMs);
|
|
44
|
+
return low === high ? ` ≈${low} left` : ` ≈${low}–${high} left`;
|
|
45
|
+
}
|
|
46
|
+
if (eta.kind === 'waiting')
|
|
47
|
+
return ' waiting on you';
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
21
50
|
/**
|
|
22
51
|
* Format a reset instant in the machine's local timezone: time-only when it
|
|
23
52
|
* falls on the same local day as `now` (e.g. `(4pm)`), date + time otherwise
|
|
@@ -84,11 +113,15 @@ function renderSegment(input) {
|
|
|
84
113
|
// Session call count — the honest usage signal. Zero placeholder when no marker.
|
|
85
114
|
const calls = marker ? marker.calls : 0;
|
|
86
115
|
parts.push(c(COLOR.calls, `${calls} ${calls === 1 ? 'call' : 'calls'}`));
|
|
87
|
-
// Active workflow run, only when one exists
|
|
116
|
+
// Active workflow run, only when one exists — with its remaining-time
|
|
117
|
+
// estimate when the marker carries one (REQ-STATUSLINE-011).
|
|
88
118
|
if (run) {
|
|
89
119
|
const label = run.specId ? `${run.specId}·${run.status}` : run.status;
|
|
90
|
-
parts.push(c(COLOR.run, label));
|
|
120
|
+
parts.push(c(COLOR.run, `${label}${etaSuffix(run)}`));
|
|
91
121
|
}
|
|
122
|
+
// Telemetry elements render on their own SECOND line (REQ-STATUSLINE-010):
|
|
123
|
+
// the SpecShip identity stays scannable while capacity bars get room.
|
|
124
|
+
const telemetry = [];
|
|
92
125
|
// Context-usage element (REQ-STATUSLINE-009) — Claude's real context %, with
|
|
93
126
|
// an escalating compaction warning past the threshold. Advisory only;
|
|
94
127
|
// SpecShip cannot compact. Omitted when no real percentage is available.
|
|
@@ -96,7 +129,7 @@ function renderSegment(input) {
|
|
|
96
129
|
const warn = context >= (ctxWarnPct ?? 80);
|
|
97
130
|
const color = warn ? COLOR.pending : COLOR.calls; // amber when high, else gold
|
|
98
131
|
const hint = warn ? ' ⚠ compact' : '';
|
|
99
|
-
|
|
132
|
+
telemetry.push(c(color, `CTX ${bar(context)} ${Math.round(context)}%${hint}`));
|
|
100
133
|
}
|
|
101
134
|
// Usage-limit sub-segment (REQ-STATUSLINE-008) — ONLY for windows with real
|
|
102
135
|
// numbers; SpecShip never estimates. `now` formats reset times in local time.
|
|
@@ -105,11 +138,14 @@ function renderSegment(input) {
|
|
|
105
138
|
if (!w)
|
|
106
139
|
return;
|
|
107
140
|
const reset = Number.isFinite(w.resetAt) ? ` ${formatReset(w.resetAt, now)}` : '';
|
|
108
|
-
|
|
141
|
+
telemetry.push(c(COLOR.calls, `${label} ${bar(w.pctUsed)} ${Math.round(w.pctUsed)}%${reset}`));
|
|
109
142
|
};
|
|
110
143
|
win('5h', usage.session);
|
|
111
144
|
win('7d', usage.weekly);
|
|
112
145
|
}
|
|
113
|
-
|
|
146
|
+
const line1 = `${orn} ${brand}${sep}${parts.join(sep)} ${orn}`;
|
|
147
|
+
if (telemetry.length === 0)
|
|
148
|
+
return line1;
|
|
149
|
+
return `${line1}\n${orn} ${telemetry.join(sep)} ${orn}`;
|
|
114
150
|
}
|
|
115
151
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -78,6 +78,19 @@ export interface UsageLimits {
|
|
|
78
78
|
/** The weekly (7-day) window, or null when absent. */
|
|
79
79
|
weekly: UsageWindow | null;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Remaining-time estimate embedded in the run marker (REQ-STATUSLINE-011).
|
|
83
|
+
* Computed by the executor at marker-write time (WORKFLOW-ETA-DOC), so the
|
|
84
|
+
* render path never opens the DB. Absent when no estimate exists.
|
|
85
|
+
*/
|
|
86
|
+
export type ActiveRunEta = {
|
|
87
|
+
kind: 'range';
|
|
88
|
+
lowMs: number;
|
|
89
|
+
highMs: number;
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'waiting';
|
|
92
|
+
sinceMs?: number;
|
|
93
|
+
};
|
|
81
94
|
/** The active (or most recent) workflow run for the project. */
|
|
82
95
|
export interface ActiveRun {
|
|
83
96
|
v: 1;
|
|
@@ -87,5 +100,7 @@ export interface ActiveRun {
|
|
|
87
100
|
status: string;
|
|
88
101
|
/** ms epoch of the last status change. */
|
|
89
102
|
updatedAt: number;
|
|
103
|
+
/** Remaining-time estimate, when one exists (REQ-STATUSLINE-011). */
|
|
104
|
+
eta?: ActiveRunEta;
|
|
90
105
|
}
|
|
91
106
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB"}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|