phewsh 0.14.3 → 0.14.5
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/commands/serve.js +46 -0
- package/lib/projects-index.js +5 -2
- package/package.json +1 -1
package/commands/serve.js
CHANGED
|
@@ -264,6 +264,51 @@ function main() {
|
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
// Mission control state — the same five rows bare `phewsh` shows, so
|
|
268
|
+
// the web cockpit (phewsh.com/cockpit) mirrors the CLI to a T.
|
|
269
|
+
if (url.pathname === '/cockpit' && req.method === 'GET') {
|
|
270
|
+
try {
|
|
271
|
+
const { listHarnesses, HARNESSES } = require('../lib/harnesses');
|
|
272
|
+
const { outcomeStats, pendingDecisions, bypassStats } = require('../lib/outcomes');
|
|
273
|
+
const { listProjects } = require('../lib/projects-index');
|
|
274
|
+
|
|
275
|
+
let config = {};
|
|
276
|
+
try { config = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.phewsh', 'config.json'), 'utf-8')) || {}; } catch { /* none */ }
|
|
277
|
+
|
|
278
|
+
const harnessList = listHarnesses().map(h => ({
|
|
279
|
+
id: h.id, label: h.label, role: h.role, installed: h.installed, headless: h.headless,
|
|
280
|
+
}));
|
|
281
|
+
|
|
282
|
+
// Same route precedence as the CLI session
|
|
283
|
+
const chatCapable = harnessList.filter(h => h.installed && h.headless);
|
|
284
|
+
let routeId = null;
|
|
285
|
+
if (config.defaultRoute === 'api' && config.apiKey) routeId = 'api';
|
|
286
|
+
else if (config.defaultRoute && chatCapable.some(h => h.id === config.defaultRoute)) routeId = config.defaultRoute;
|
|
287
|
+
else if (config.apiKey) routeId = 'api';
|
|
288
|
+
else if (chatCapable.length > 0) routeId = chatCapable[0].id;
|
|
289
|
+
|
|
290
|
+
const intentFiles = ['vision.md', 'plan.md', 'next.md']
|
|
291
|
+
.filter(f => fs.existsSync(path.join(process.cwd(), '.intent', f)));
|
|
292
|
+
|
|
293
|
+
return json(res, {
|
|
294
|
+
project: { name: path.basename(process.cwd()), cwd: process.cwd(), intentFiles },
|
|
295
|
+
route: routeId === 'api'
|
|
296
|
+
? { id: 'api', label: `API (${config.provider || 'anthropic'} key)` }
|
|
297
|
+
: routeId ? { id: routeId, label: HARNESSES[routeId].label } : null,
|
|
298
|
+
fallback: config.fallback === 'auto' ? 'auto' : 'ask',
|
|
299
|
+
harnesses: harnessList,
|
|
300
|
+
web: { loggedIn: !!config.supabaseUserId, email: config.email || null },
|
|
301
|
+
record: outcomeStats(),
|
|
302
|
+
pending: pendingDecisions().length,
|
|
303
|
+
bypasses: bypassStats(),
|
|
304
|
+
recentProjects: listProjects().slice(0, 5).map(p => ({ name: p.name, path: p.path, lastOpened: p.lastOpened })),
|
|
305
|
+
version: require('../package.json').version,
|
|
306
|
+
});
|
|
307
|
+
} catch (err) {
|
|
308
|
+
return json(res, { error: err.message }, 500);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
267
312
|
// The proof trail — same merged data as `phewsh receipts` and the MCP
|
|
268
313
|
// bridge's /receipts, so the web can show evidence regardless of which
|
|
269
314
|
// local bridge is running.
|
|
@@ -298,6 +343,7 @@ function main() {
|
|
|
298
343
|
console.log(` ${g('Live execution bridge for phewsh.com/intent')}`);
|
|
299
344
|
console.log('');
|
|
300
345
|
console.log(` ${green('●')} Running on ${w(`http://localhost:${port}`)}`);
|
|
346
|
+
console.log(` ${g('Web cockpit:')} ${w('phewsh.com/cockpit')} ${g('— mirrors this machine live')}`);
|
|
301
347
|
console.log('');
|
|
302
348
|
console.log(` ${b('Connected runtimes:')}`);
|
|
303
349
|
runtimes.forEach(r => {
|
package/lib/projects-index.js
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
// so running `phewsh` at machine root becomes mission-control bootstrap
|
|
5
5
|
// ("where do you want to work?") instead of "no project found, goodbye."
|
|
6
6
|
//
|
|
7
|
-
// Storage: ~/.phewsh/
|
|
7
|
+
// Storage: ~/.phewsh/project-index.json. Local-first; web sync layers on top.
|
|
8
|
+
// NOT projects.json — that file belongs to `phewsh mcp` (web project cache,
|
|
9
|
+
// array-shaped). Claiming it caused a startup crash AND would have clobbered
|
|
10
|
+
// MCP data on first write. One file, one owner.
|
|
8
11
|
|
|
9
12
|
const fs = require('fs');
|
|
10
13
|
const path = require('path');
|
|
11
14
|
const os = require('os');
|
|
12
15
|
|
|
13
|
-
const INDEX_FILE = path.join(os.homedir(), '.phewsh', '
|
|
16
|
+
const INDEX_FILE = path.join(os.homedir(), '.phewsh', 'project-index.json');
|
|
14
17
|
|
|
15
18
|
// Shallow-scanned roots when the user asks to find projects. One level deep,
|
|
16
19
|
// opt-in only — deep-scanning someone's machine uninvited is invasive.
|