@lightupai/polaris 0.0.109 → 0.0.110
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/package.json +1 -1
- package/src/cli/cli.ts +45 -0
- package/src/client/client.ts +13 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightupai/polaris",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.110",
|
|
4
4
|
"description": "Record and stream Claude Code sessions to Slack. Like Gong for AI coding — capture every prompt, response, and tool call. Multiplayer collaboration across AI coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
package/src/cli/cli.ts
CHANGED
|
@@ -275,7 +275,52 @@ async function removeSystemdService(): Promise<void> {
|
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
// Platform dispatcher
|
|
278
|
+
// --- Session state migration ---
|
|
279
|
+
//
|
|
280
|
+
// When upgrading from a pre-0.0.109 daemon (which never wrote daemon-state.json),
|
|
281
|
+
// the new daemon would start with an empty session map and drop every connected
|
|
282
|
+
// session. This function fetches the running daemon's session list via GET /status
|
|
283
|
+
// and writes daemon-state.json before the daemon is stopped, so the new daemon
|
|
284
|
+
// can restore the map and reconnect cloud WebSockets without any user action.
|
|
285
|
+
// Best-effort: failures are silent (daemon may not be running, or already migrated).
|
|
286
|
+
async function migrateSessionState(): Promise<void> {
|
|
287
|
+
const stateFile = join(POLARIS_DIR, "sessions", "daemon-state.json");
|
|
288
|
+
// If a 0.0.109+ daemon already wrote the file, its state is more complete
|
|
289
|
+
// (includes learned hook aliases) — don't overwrite it.
|
|
290
|
+
try { await readFile(stateFile); return; } catch { /* doesn't exist — proceed */ }
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
const config = await loadConfig();
|
|
294
|
+
const secret = resolveDaemonSecret(config);
|
|
295
|
+
const headers: Record<string, string> = {};
|
|
296
|
+
if (secret) headers["x-polaris-daemon-secret"] = secret;
|
|
297
|
+
const res = await fetch("http://127.0.0.1:4322/status", {
|
|
298
|
+
headers,
|
|
299
|
+
signal: AbortSignal.timeout(2000),
|
|
300
|
+
});
|
|
301
|
+
if (!res.ok) return;
|
|
302
|
+
const data = await res.json() as { sessions?: Array<{ ccSessionId: string; project: string; session: string; user: string }> };
|
|
303
|
+
if (!data.sessions || data.sessions.length === 0) return;
|
|
304
|
+
|
|
305
|
+
const activeProfile = config?.active || "";
|
|
306
|
+
const sessions = data.sessions.map((s) => ({
|
|
307
|
+
ccSessionId: s.ccSessionId,
|
|
308
|
+
project: s.project,
|
|
309
|
+
session: s.session,
|
|
310
|
+
user: s.user,
|
|
311
|
+
agent: "agent:claude",
|
|
312
|
+
profile: activeProfile,
|
|
313
|
+
}));
|
|
314
|
+
|
|
315
|
+
await mkdir(join(POLARIS_DIR, "sessions"), { recursive: true });
|
|
316
|
+
await writeFile(stateFile, JSON.stringify({ sessions }));
|
|
317
|
+
console.log(` ✓ Migrated ${sessions.length} active session(s) to persistent state`);
|
|
318
|
+
} catch { /* best-effort — daemon not running or unreachable */ }
|
|
319
|
+
}
|
|
320
|
+
|
|
278
321
|
async function installDaemonService(daemonSecret?: string): Promise<void> {
|
|
322
|
+
// Migrate session state from older daemon before it is stopped
|
|
323
|
+
await migrateSessionState();
|
|
279
324
|
if (process.platform === "darwin") return installLaunchAgent(daemonSecret);
|
|
280
325
|
if (process.platform === "linux") return installSystemdService(daemonSecret);
|
|
281
326
|
// Windows and others: no managed service; daemon is started manually
|
package/src/client/client.ts
CHANGED
|
@@ -495,17 +495,25 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
495
495
|
return { content: [{ type: "text", text: `Polaris is already up to date (v${currentVersion}).` }] };
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
-
// Update
|
|
499
|
-
|
|
498
|
+
// Update the copy that's actually in use: ~/.polaris/mcp (no sudo required).
|
|
499
|
+
// This is the same location the version was read from, and where the daemon
|
|
500
|
+
// and MCP server binaries are resolved by run-daemon.sh and claude mcp add.
|
|
501
|
+
const mcpDir = `${homedir()}/.polaris/mcp`;
|
|
502
|
+
const npmResult = Bun.spawnSync(
|
|
503
|
+
["npm", "install", "--prefix", mcpDir, `@lightupai/polaris@${latestVersion}`],
|
|
504
|
+
{ stdout: "pipe", stderr: "pipe" }
|
|
505
|
+
);
|
|
500
506
|
if (npmResult.exitCode !== 0) {
|
|
501
507
|
return { content: [{ type: "text", text: `Update failed:\n${npmResult.stderr.toString().trim()}` }] };
|
|
502
508
|
}
|
|
503
509
|
|
|
504
|
-
// Refresh hooks,
|
|
505
|
-
|
|
510
|
+
// Refresh hooks, migrate session state, and restart the daemon using the
|
|
511
|
+
// local polaris binary (not relying on PATH, which may not include it).
|
|
512
|
+
const polarisBin = `${mcpDir}/node_modules/.bin/polaris`;
|
|
513
|
+
const installResult = Bun.spawnSync([polarisBin, "install"], { stdout: "pipe", stderr: "pipe" });
|
|
506
514
|
const msg = installResult.exitCode === 0
|
|
507
515
|
? `Updated Polaris from v${currentVersion} to v${latestVersion}.\n\nRestart Claude Code for the new MCP server to take effect.`
|
|
508
|
-
: `Updated
|
|
516
|
+
: `Updated package to v${latestVersion}, but \`polaris install\` failed — run it manually.\n${installResult.stderr.toString().trim()}`;
|
|
509
517
|
return { content: [{ type: "text", text: msg }] };
|
|
510
518
|
}
|
|
511
519
|
|