@inerrata/channel 0.1.3 → 0.1.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/dist/index.js +24 -4
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { ListToolsRequestSchema, CallToolRequestSchema, } from '@modelcontextpro
|
|
|
18
18
|
const API_BASE = process.env.ERRATA_API_URL ?? 'https://inerrata.fly.dev/api/v1';
|
|
19
19
|
const API_KEY = process.env.ERRATA_API_KEY ?? '';
|
|
20
20
|
const POLL_INTERVAL_MS = 15_000; // 15s polling fallback
|
|
21
|
+
const HEARTBEAT_INTERVAL_MS = 60_000; // 60s — server marks offline after 2min stale
|
|
21
22
|
if (!API_KEY) {
|
|
22
23
|
console.error('[inerrata-channel] ERRATA_API_KEY is required');
|
|
23
24
|
process.exit(1);
|
|
@@ -116,6 +117,22 @@ function apiFetch(path, init) {
|
|
|
116
117
|
});
|
|
117
118
|
}
|
|
118
119
|
// ---------------------------------------------------------------------------
|
|
120
|
+
// Channel presence — heartbeat keeps agent marked "channel online" on the server
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
function sendHeartbeat() {
|
|
123
|
+
apiFetch('/channel/heartbeat', { method: 'POST' }).catch(() => { });
|
|
124
|
+
}
|
|
125
|
+
function sendOffline() {
|
|
126
|
+
// Best-effort sync-ish DELETE on process exit — keepalive so it survives the shutdown
|
|
127
|
+
fetch(`${API_BASE}/channel/heartbeat`, {
|
|
128
|
+
method: 'DELETE',
|
|
129
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${API_KEY}` },
|
|
130
|
+
keepalive: true,
|
|
131
|
+
}).catch(() => { });
|
|
132
|
+
}
|
|
133
|
+
process.on('SIGTERM', () => { sendOffline(); process.exit(0); });
|
|
134
|
+
process.on('SIGINT', () => { sendOffline(); process.exit(0); });
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
119
136
|
// Deduplication — prevents double-delivery when both the poll and a
|
|
120
137
|
// server-side SSE push fire for the same notification.
|
|
121
138
|
// ---------------------------------------------------------------------------
|
|
@@ -188,18 +205,18 @@ async function pollInbox() {
|
|
|
188
205
|
const requests = reqRes.ok
|
|
189
206
|
? (await reqRes.json())
|
|
190
207
|
: [];
|
|
191
|
-
// Push unread messages newer than last check
|
|
208
|
+
// Push unread messages newer than last check, then mark as read so
|
|
209
|
+
// subsequent polls (and other running instances) don't re-deliver.
|
|
192
210
|
for (const msg of msgs) {
|
|
193
211
|
if (!msg.read && msg.createdAt > lastCheckedAt) {
|
|
194
|
-
// Resolve sender handle
|
|
195
|
-
const handleRes = await apiFetch(`/messages/inbox?limit=1`);
|
|
196
212
|
await pushNotification({
|
|
197
213
|
type: 'message.received',
|
|
198
214
|
messageId: msg.id,
|
|
199
215
|
threadId: msg.threadId,
|
|
200
|
-
fromHandle: msg.
|
|
216
|
+
fromHandle: msg.fromHandle ?? msg.fromAgent,
|
|
201
217
|
preview: msg.body.slice(0, 200),
|
|
202
218
|
});
|
|
219
|
+
apiFetch(`/messages/${msg.id}/read`, { method: 'PATCH' }).catch(() => { });
|
|
203
220
|
}
|
|
204
221
|
}
|
|
205
222
|
// Push pending requests
|
|
@@ -264,6 +281,9 @@ async function main() {
|
|
|
264
281
|
setInterval(pollInbox, POLL_INTERVAL_MS);
|
|
265
282
|
// Initial poll after a short delay (let MCP handshake complete)
|
|
266
283
|
setTimeout(pollInbox, 3000);
|
|
284
|
+
// Heartbeat — announce channel presence to the server
|
|
285
|
+
sendHeartbeat();
|
|
286
|
+
setInterval(sendHeartbeat, HEARTBEAT_INTERVAL_MS);
|
|
267
287
|
console.error('[inerrata-channel] Connected — polling every 15s');
|
|
268
288
|
}
|
|
269
289
|
main().catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inerrata/channel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Claude Code channel plugin for inErrata — real-time DM and notification alerts",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": [
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
7
9
|
"bin": {
|
|
8
10
|
"channel": "./dist/index.js",
|
|
9
11
|
"inerrata-channel": "./dist/index.js",
|