relay-companion 0.1.84 → 0.1.85
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/overlay/main.cjs +19 -9
- package/package.json +1 -1
- package/src/channel-server.js +26 -0
package/overlay/main.cjs
CHANGED
|
@@ -2110,17 +2110,27 @@ async function openPacketInCurrent(packetId) {
|
|
|
2110
2110
|
},
|
|
2111
2111
|
});
|
|
2112
2112
|
};
|
|
2113
|
-
// WAKE TIER (live-proven): when
|
|
2114
|
-
// push the instruction as a channel event — the
|
|
2115
|
-
// it even when idle, which hook staging can
|
|
2116
|
-
//
|
|
2117
|
-
//
|
|
2118
|
-
//
|
|
2119
|
-
// event somehow never gets picked up (server died between
|
|
2120
|
-
// watcher falls
|
|
2113
|
+
// WAKE TIER (live-proven): when the resolved CURRENT chat is itself a
|
|
2114
|
+
// relay-channel session, push the instruction as a channel event — the
|
|
2115
|
+
// session takes a REAL turn on it even when idle, which hook staging can
|
|
2116
|
+
// never cause. The join is by working directory: the channel instance's
|
|
2117
|
+
// recorded cwd must uniquely match the target session's rendezvous cwd, so
|
|
2118
|
+
// a click aimed at a desktop chat NEVER wakes some other terminal session.
|
|
2119
|
+
// If the claimed event somehow never gets picked up (server died between
|
|
2120
|
+
// heartbeats), the watcher falls back to hook staging — never a dead end.
|
|
2121
2121
|
const tryChannelWake = () =>
|
|
2122
2122
|
loadChannelDeps().then((channel) => {
|
|
2123
|
-
|
|
2123
|
+
let targetCwd = "";
|
|
2124
|
+
try {
|
|
2125
|
+
const rendezvousPath = path.join(
|
|
2126
|
+
claudeInject.rendezvousDir(RELAY_HOME),
|
|
2127
|
+
`${claudeInject.safeSessionKey(target.sessionId)}.json`,
|
|
2128
|
+
);
|
|
2129
|
+
targetCwd = String(JSON.parse(fs.readFileSync(rendezvousPath, "utf8")).cwd || "");
|
|
2130
|
+
} catch {
|
|
2131
|
+
return false; // no rendezvous -> no join evidence -> hook path
|
|
2132
|
+
}
|
|
2133
|
+
if (!channel.liveChannelInstanceForCwd(RELAY_HOME, targetCwd)) return false;
|
|
2124
2134
|
const instruction = claudeInject.buildInjectionInstruction({
|
|
2125
2135
|
relayId: packetId,
|
|
2126
2136
|
senderName: row.senderName || "",
|
package/package.json
CHANGED
package/src/channel-server.js
CHANGED
|
@@ -83,6 +83,32 @@ export function channelInstanceAlive(homeDir = storeDir(), opts = {}) {
|
|
|
83
83
|
return countLiveChannelInstances(homeDir, opts) > 0;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// The single live channel instance matching a session's working directory, or
|
|
87
|
+
// null. "Current chat" means the chat the user is looking at: the wake tier
|
|
88
|
+
// must fire only when the channel session IS the resolved target, and the only
|
|
89
|
+
// join available today is cwd (channel presence records its process cwd; hook
|
|
90
|
+
// rendezvous records the session's). One instance per cwd; ambiguity -> null.
|
|
91
|
+
export function liveChannelInstanceForCwd(homeDir = storeDir(), cwd, { maxAgeMs = PRESENCE_MS * 3, nowMs = Date.now() } = {}) {
|
|
92
|
+
const wanted = String(cwd || "").replace(/\/+$/, "");
|
|
93
|
+
if (!wanted) return null;
|
|
94
|
+
let entries = [];
|
|
95
|
+
try {
|
|
96
|
+
entries = fs.readdirSync(channelPresenceDir(homeDir));
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const matches = [];
|
|
101
|
+
for (const name of entries) {
|
|
102
|
+
if (!name.endsWith(".json")) continue;
|
|
103
|
+
try {
|
|
104
|
+
const row = JSON.parse(fs.readFileSync(path.join(channelPresenceDir(homeDir), name), "utf8"));
|
|
105
|
+
if (nowMs - (Number(row.heartbeatAt) || 0) > maxAgeMs) continue;
|
|
106
|
+
if (String(row.cwd || "").replace(/\/+$/, "") === wanted) matches.push(row);
|
|
107
|
+
} catch {}
|
|
108
|
+
}
|
|
109
|
+
return matches.length === 1 ? matches[0] : null;
|
|
110
|
+
}
|
|
111
|
+
|
|
86
112
|
function consumeEventFile(file) {
|
|
87
113
|
const claimed = `${file}.${process.pid}.claimed`;
|
|
88
114
|
try {
|