project-cypher 0.19.0 → 0.20.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 (2) hide show
  1. package/bin/cypher.js +14 -1
  2. package/package.json +1 -1
package/bin/cypher.js CHANGED
@@ -287,7 +287,7 @@ const cmds = {
287
287
  connect() {
288
288
  const autoOn = id => !!rawCfg().autoApprove?.[id];
289
289
  const announce = () => [{ id: 'root', name: 'Root', root: true, auto: autoOn('root') }, ...readRegistry().map(({ id, name, summary }) => ({ id, name, summary, auto: autoOn(id) }))];
290
- const hello = () => ({ type: 'hello', name: devName(), projects: announce(), running: [...runs].map(([projectId, ch]) => ({ projectId, reqId: ch.reqId })) }); // running: lets the relay know which prompts are still in progress after a reconnect
290
+ const hello = () => ({ type: 'hello', ver: require('../package.json').version, npm: fs.realpathSync(__filename).includes(path.sep + 'node_modules' + path.sep), name: devName(), projects: announce(), running: [...runs].map(([projectId, ch]) => ({ projectId, reqId: ch.reqId })) }); // running: lets the relay know which prompts are still in progress after a reconnect
291
291
  const WebSocket = require('ws'); let c = load(); if (!c.token) return console.log('not linked yet. Run: cypher link');
292
292
  ensureRoot();
293
293
  const runs = new Map(); let retry = 1000; let tx = () => false;
@@ -341,6 +341,19 @@ const cmds = {
341
341
  if (m.type === 'rmproject') { if (m.projectId !== 'root') writeRegistry(readRegistry().filter(x => x.id !== m.projectId)); return; }
342
342
  if (m.type === 'autoapprove') { const k = rawCfg(); k.autoApprove = { ...(k.autoApprove || {}) }; if (m.on) k.autoApprove[m.projectId] = true; else delete k.autoApprove[m.projectId]; save(k); console.log(`[${m.projectId}] auto-approve ${m.on ? 'ON' : 'off'}`); return tx(hello()); }
343
343
  if (m.type === 'reset') { const k = load(); if (k.sessions) { delete k.sessions[m.projectId]; save(k); } return; }
344
+ if (m.type === 'update') { // phone asked this computer to update itself (fixed npm command only)
345
+ const say = (ok, message) => tx({ type: 'updated', ok, message });
346
+ const cur = require('../package.json').version;
347
+ if (!fs.realpathSync(__filename).includes(path.sep + 'node_modules' + path.sep)) return say(false, 'This copy runs from a source folder. Update it with git pull.');
348
+ if (runs.size) return say(false, 'Claude is working. Try again when it finishes.');
349
+ const cp = require('child_process'); const win = process.platform === 'win32';
350
+ cp.execFile('npm', ['i', '-g', 'project-cypher@latest', '--prefer-online'], { shell: win, timeout: 300000 }, (err, so, se) => {
351
+ if (err) return say(false, ('Update failed: ' + (String(se).trim().split('\n').filter(Boolean).pop() || err.message)).slice(0, 200));
352
+ say(true, 'Updated. Restarting.'); console.log('updated from ' + cur + ' via the app');
353
+ setTimeout(() => { if (SVC.running()) SVC.start(); else process.exit(0); }, 800);
354
+ });
355
+ return;
356
+ }
344
357
  if (m.type === 'sessions') { if (!proj) return; return tx({ ...ctx, type: 'sessions', list: listSessions(proj.path, load().sessions?.[proj.id]) }); }
345
358
  if (m.type === 'usesession') { // switch the project to an older Claude session and send its chat back
346
359
  if (!proj || !SID.test(String(m.id))) return tx({ ...ctx, type: 'error', message: 'Unknown session.' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-cypher",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Connect your machine's Claude Code projects to the Project Cypher phone app.",
5
5
  "bin": {
6
6
  "cypher": "bin/cypher.js"