@lightupai/polaris 0.0.110 → 0.0.114
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/hooks/statusline.sh +20 -5
- package/package.json +1 -1
- package/src/daemon/daemon.ts +29 -4
package/hooks/statusline.sh
CHANGED
|
@@ -41,7 +41,7 @@ if [ -f "$INSTALLED_PKG" ]; then
|
|
|
41
41
|
NOW=$(date +%s 2>/dev/null || echo "0")
|
|
42
42
|
CACHE_AGE=$(( NOW - CACHE_TS )) 2>/dev/null || CACHE_AGE=9999
|
|
43
43
|
STALE=false
|
|
44
|
-
[ "$CACHE_AGE" -gt
|
|
44
|
+
[ "$CACHE_AGE" -gt 300 ] 2>/dev/null && STALE=true
|
|
45
45
|
else
|
|
46
46
|
STALE=true
|
|
47
47
|
fi
|
|
@@ -72,11 +72,26 @@ if [ "$CONNECTED" = "true" ]; then
|
|
|
72
72
|
if [ -n "$ACCOUNT" ]; then
|
|
73
73
|
ACCOUNT_TAG="[${ACCOUNT}] "
|
|
74
74
|
fi
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
|
|
76
|
+
# Liveness indicator: seconds since last delivered event
|
|
77
|
+
RECENCY=""
|
|
78
|
+
LAST_AGE=$(echo "$STATUS" | jq -r '.lastEventAge // ""' 2>/dev/null || echo "")
|
|
79
|
+
if [ -n "$LAST_AGE" ] && [ "$LAST_AGE" != "null" ]; then
|
|
80
|
+
if [ "$LAST_AGE" -lt 60 ] 2>/dev/null; then
|
|
81
|
+
RECENCY=" · just now"
|
|
82
|
+
elif [ "$LAST_AGE" -lt 3600 ] 2>/dev/null; then
|
|
83
|
+
RECENCY=" · $(( LAST_AGE / 60 ))m ago"
|
|
84
|
+
else
|
|
85
|
+
RECENCY=" · $(( LAST_AGE / 3600 ))h ago"
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Show Slack channel only when it differs from the project name (adds info, avoids duplication)
|
|
90
|
+
SLACK_TAG=""
|
|
91
|
+
if [ -n "$SLACK" ] && [ "$SLACK" != "$PROJECT" ]; then
|
|
92
|
+
SLACK_TAG=" → #${SLACK}"
|
|
79
93
|
fi
|
|
94
|
+
echo "polaris: ${ACCOUNT_TAG}#${PROJECT}/${SESSION} (${USER})${SLACK_TAG}${RECENCY}${UPDATE_MSG}"
|
|
80
95
|
else
|
|
81
96
|
echo "polaris: not connected${UPDATE_MSG}"
|
|
82
97
|
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightupai/polaris",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.114",
|
|
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/daemon/daemon.ts
CHANGED
|
@@ -707,6 +707,17 @@ export function startDaemon(port = Number(process.env.POLARIS_DAEMON_PORT ?? 432
|
|
|
707
707
|
};
|
|
708
708
|
sessions.set(body.ccSessionId, mapping);
|
|
709
709
|
|
|
710
|
+
// Evict stale alias entries that share this (project, session) pair.
|
|
711
|
+
// After a reconnect the old CC session ID still has an entry with the
|
|
712
|
+
// same pair; leaving it allows hook events from the old shell to
|
|
713
|
+
// alias-claim a future pending session or send duplicate events.
|
|
714
|
+
for (const [id, m] of sessions) {
|
|
715
|
+
if (id !== body.ccSessionId && m.project === mapping.project && m.session === mapping.session) {
|
|
716
|
+
sessions.delete(id);
|
|
717
|
+
console.error(`[daemon] Evicted stale alias ${id.slice(0, 8)} for ${mapping.project}/${mapping.session}`);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
710
721
|
// Ensure the session exists (create if not, claim driver)
|
|
711
722
|
// Retry with new name on 409 (collision with generated name)
|
|
712
723
|
let attempts = 0;
|
|
@@ -850,10 +861,16 @@ export function startDaemon(port = Number(process.env.POLARIS_DAEMON_PORT ?? 432
|
|
|
850
861
|
// ran polaris_connect. Always returns not_connected; hooks from
|
|
851
862
|
// unjoined shells are never auto-routed to an existing session.
|
|
852
863
|
let mapping = sessions.get(ccSessionId);
|
|
853
|
-
if (
|
|
854
|
-
// CC
|
|
855
|
-
//
|
|
856
|
-
// session
|
|
864
|
+
if (mapping && !mapping.project) {
|
|
865
|
+
// Known CC session ID but deliberately disconnected (project cleared
|
|
866
|
+
// by /disconnect). Hooks still fire after disconnect — do NOT
|
|
867
|
+
// alias-claim a pending session; the shell intentionally left.
|
|
868
|
+
return json({ status: "not_connected" });
|
|
869
|
+
}
|
|
870
|
+
if (!mapping) {
|
|
871
|
+
// Truly unknown CC session_id — the MCP client's UUID differs from
|
|
872
|
+
// CC's hook session_id. Match to a session with pendingMapping
|
|
873
|
+
// (most recent first) to learn the alias.
|
|
857
874
|
const pending = Array.from(sessions.values()).filter((m) => m.project && m.pendingMapping);
|
|
858
875
|
if (pending.length > 0) {
|
|
859
876
|
// Map the CC session ID to the most recently connected pending session
|
|
@@ -1042,6 +1059,13 @@ export function startDaemon(port = Number(process.env.POLARIS_DAEMON_PORT ?? 432
|
|
|
1042
1059
|
}
|
|
1043
1060
|
}
|
|
1044
1061
|
}
|
|
1062
|
+
// Include seconds since last delivered event so the status line can show
|
|
1063
|
+
// a liveness indicator (e.g. "· 2m ago") without a second request.
|
|
1064
|
+
let lastEventAge: number | null = null;
|
|
1065
|
+
const cp = await readCheckpoint(ccSessionId);
|
|
1066
|
+
if (cp && cp.project === mapping.project && cp.session === mapping.session) {
|
|
1067
|
+
lastEventAge = Math.floor((Date.now() - new Date(cp.lastEventTimestamp).getTime()) / 1000);
|
|
1068
|
+
}
|
|
1045
1069
|
return json({
|
|
1046
1070
|
connected: true,
|
|
1047
1071
|
project: mapping.project,
|
|
@@ -1049,6 +1073,7 @@ export function startDaemon(port = Number(process.env.POLARIS_DAEMON_PORT ?? 432
|
|
|
1049
1073
|
user: mapping.user,
|
|
1050
1074
|
slackChannel,
|
|
1051
1075
|
account: emailFromToken(await getTokenForProfile(mapping.profile)),
|
|
1076
|
+
lastEventAge,
|
|
1052
1077
|
});
|
|
1053
1078
|
}
|
|
1054
1079
|
|