instar 0.27.2 → 0.28.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.
- package/.claude/skills/build/SKILL.md +268 -0
- package/README.md +2 -1
- package/dashboard/index.html +501 -491
- package/dist/cli.js +81 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +16 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/listener.d.ts +46 -0
- package/dist/commands/listener.d.ts.map +1 -0
- package/dist/commands/listener.js +467 -0
- package/dist/commands/listener.js.map +1 -0
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +101 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +84 -21
- package/dist/commands/setup.js.map +1 -1
- package/dist/core/AgentRegistry.d.ts.map +1 -1
- package/dist/core/AgentRegistry.js +30 -2
- package/dist/core/AgentRegistry.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +2 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +29 -28
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +32 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +10 -2
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +87 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts +123 -0
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -0
- package/dist/threadline/PipeSessionSpawner.js +343 -0
- package/dist/threadline/PipeSessionSpawner.js.map +1 -0
- package/dist/threadline/ThreadResumeMap.d.ts +22 -0
- package/dist/threadline/ThreadResumeMap.d.ts.map +1 -1
- package/dist/threadline/ThreadResumeMap.js +37 -0
- package/dist/threadline/ThreadResumeMap.js.map +1 -1
- package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
- package/dist/threadline/ThreadlineBootstrap.js +155 -72
- package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
- package/dist/threadline/WakeSocketServer.d.ts +49 -0
- package/dist/threadline/WakeSocketServer.d.ts.map +1 -0
- package/dist/threadline/WakeSocketServer.js +115 -0
- package/dist/threadline/WakeSocketServer.js.map +1 -0
- package/dist/threadline/listener-daemon.d.ts +94 -0
- package/dist/threadline/listener-daemon.d.ts.map +1 -0
- package/dist/threadline/listener-daemon.js +550 -0
- package/dist/threadline/listener-daemon.js.map +1 -0
- package/package.json +2 -1
- package/src/data/builtin-manifest.json +91 -91
- package/upgrades/0.28.0.md +54 -0
- package/upgrades/NEXT.md +35 -0
- /package/.claude/skills/autonomous/{skill.md → SKILL.md} +0 -0
- /package/.claude/skills/secret-setup/{skill.md → SKILL.md} +0 -0
- /package/.claude/skills/setup-wizard/{skill.md → SKILL.md} +0 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Listener Daemon — Standalone process maintaining a persistent WebSocket
|
|
4
|
+
* connection to the Threadline relay, independent of the agent server lifecycle.
|
|
5
|
+
*
|
|
6
|
+
* Part of RFC: Persistent Listener Daemon Architecture (Phase 1).
|
|
7
|
+
*
|
|
8
|
+
* This process:
|
|
9
|
+
* - Connects to the relay via WebSocket with Ed25519 authentication
|
|
10
|
+
* - Decrypts incoming E2E-encrypted messages
|
|
11
|
+
* - Writes HMAC-signed entries to the inbox JSONL file
|
|
12
|
+
* - Signals the agent server via Unix domain socket for immediate pickup
|
|
13
|
+
* - Writes periodic health snapshots
|
|
14
|
+
* - Handles reconnection with exponential backoff
|
|
15
|
+
* - Exits gracefully (code 0) on displacement to prevent respawn loops
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* node listener-daemon.js --state-dir /path/to/.instar
|
|
19
|
+
*
|
|
20
|
+
* Environment:
|
|
21
|
+
* INSTAR_LISTENER_HMAC_KEY_FILE — Path to HMAC key file (0400 permissions)
|
|
22
|
+
* If not set, falls back to reading authToken from config.json and deriving key.
|
|
23
|
+
*/
|
|
24
|
+
import crypto from 'node:crypto';
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
import net from 'node:net';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { EventEmitter } from 'node:events';
|
|
29
|
+
import { RelayClient } from './client/RelayClient.js';
|
|
30
|
+
import { IdentityManager } from './client/IdentityManager.js';
|
|
31
|
+
import { MessageEncryptor } from './client/MessageEncryptor.js';
|
|
32
|
+
// ── Logging ───────────────────────────────────────────────────────────
|
|
33
|
+
class DaemonLogger {
|
|
34
|
+
logPath;
|
|
35
|
+
maxBytes;
|
|
36
|
+
constructor(logPath, maxBytes) {
|
|
37
|
+
this.logPath = logPath;
|
|
38
|
+
this.maxBytes = maxBytes;
|
|
39
|
+
const dir = path.dirname(logPath);
|
|
40
|
+
if (!fs.existsSync(dir))
|
|
41
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
write(level, msg) {
|
|
44
|
+
const line = `[${new Date().toISOString()}] [${level}] ${msg}\n`;
|
|
45
|
+
try {
|
|
46
|
+
// Rotate if needed
|
|
47
|
+
if (fs.existsSync(this.logPath)) {
|
|
48
|
+
const stat = fs.statSync(this.logPath);
|
|
49
|
+
if (stat.size > this.maxBytes) {
|
|
50
|
+
const rotated = `${this.logPath}.1`;
|
|
51
|
+
if (fs.existsSync(rotated))
|
|
52
|
+
fs.unlinkSync(rotated);
|
|
53
|
+
fs.renameSync(this.logPath, rotated);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
fs.appendFileSync(this.logPath, line);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Logging failure is non-critical
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
error(msg) { this.write('ERROR', msg); }
|
|
63
|
+
warn(msg) { this.write('WARN', msg); }
|
|
64
|
+
info(msg) { this.write('INFO', msg); }
|
|
65
|
+
debug(msg) { this.write('DEBUG', msg); }
|
|
66
|
+
}
|
|
67
|
+
// ── Listener Daemon ───────────────────────────────────────────────────
|
|
68
|
+
export class ListenerDaemon extends EventEmitter {
|
|
69
|
+
config;
|
|
70
|
+
log;
|
|
71
|
+
identity;
|
|
72
|
+
encryptor;
|
|
73
|
+
relay;
|
|
74
|
+
signingKey;
|
|
75
|
+
// Unix socket for wake signals
|
|
76
|
+
wakeSocket = null;
|
|
77
|
+
socketConnected = false;
|
|
78
|
+
// Metrics
|
|
79
|
+
startTime = Date.now();
|
|
80
|
+
msgsIn = 0;
|
|
81
|
+
msgsOut = 0;
|
|
82
|
+
disconnects = []; // timestamps of disconnects in last 10 min
|
|
83
|
+
lastMessageAt = null;
|
|
84
|
+
// Health timer
|
|
85
|
+
healthTimer = null;
|
|
86
|
+
// PID file
|
|
87
|
+
pidPath;
|
|
88
|
+
constructor(config) {
|
|
89
|
+
super();
|
|
90
|
+
this.config = config;
|
|
91
|
+
this.pidPath = path.join(config.stateDir, 'listener-daemon.pid');
|
|
92
|
+
this.log = new DaemonLogger(config.logPath, config.logMaxBytes);
|
|
93
|
+
// Load identity
|
|
94
|
+
const identityMgr = new IdentityManager(path.join(config.stateDir, 'threadline'));
|
|
95
|
+
const identity = identityMgr.get();
|
|
96
|
+
if (!identity) {
|
|
97
|
+
// Try legacy path
|
|
98
|
+
const legacyMgr = new IdentityManager(config.stateDir);
|
|
99
|
+
const legacyIdentity = legacyMgr.get();
|
|
100
|
+
if (!legacyIdentity) {
|
|
101
|
+
this.log.error('No identity found. Server must generate identity first.');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
this.identity = legacyIdentity;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.identity = identity;
|
|
108
|
+
}
|
|
109
|
+
// Create message encryptor for E2E decryption
|
|
110
|
+
this.encryptor = new MessageEncryptor(this.identity.privateKey, this.identity.publicKey);
|
|
111
|
+
// Load HMAC signing key
|
|
112
|
+
this.signingKey = this.loadSigningKey();
|
|
113
|
+
// Create relay client
|
|
114
|
+
const relayConfig = {
|
|
115
|
+
relayUrl: config.relayUrl,
|
|
116
|
+
name: config.agentName,
|
|
117
|
+
framework: 'instar-listener-daemon',
|
|
118
|
+
capabilities: ['listener'],
|
|
119
|
+
version: '1.0.0',
|
|
120
|
+
visibility: 'unlisted',
|
|
121
|
+
stateDir: config.stateDir,
|
|
122
|
+
};
|
|
123
|
+
this.relay = new RelayClient(relayConfig, this.identity);
|
|
124
|
+
this.log.info(`Listener daemon initialized for agent ${this.identity.fingerprint.slice(0, 8)}...`);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Load HMAC signing key from file or derive from authToken.
|
|
128
|
+
*/
|
|
129
|
+
loadSigningKey() {
|
|
130
|
+
// Try HMAC key file first (preferred — avoids env var exposure)
|
|
131
|
+
const hmacKeyFile = process.env.INSTAR_LISTENER_HMAC_KEY_FILE
|
|
132
|
+
|| path.join(this.config.stateDir, 'threadline', 'inbox-hmac.key');
|
|
133
|
+
if (fs.existsSync(hmacKeyFile)) {
|
|
134
|
+
try {
|
|
135
|
+
const keyHex = fs.readFileSync(hmacKeyFile, 'utf-8').trim();
|
|
136
|
+
this.log.info('HMAC key loaded from file');
|
|
137
|
+
return Buffer.from(keyHex, 'hex');
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
this.log.warn(`Failed to read HMAC key file: ${err}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Fallback: derive from authToken in config.json
|
|
144
|
+
const configPath = path.join(this.config.stateDir, 'config.json');
|
|
145
|
+
if (!fs.existsSync(configPath)) {
|
|
146
|
+
this.log.error('No HMAC key file and no config.json found');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
150
|
+
const authToken = config.authToken;
|
|
151
|
+
if (!authToken) {
|
|
152
|
+
this.log.error('No authToken in config.json and no HMAC key file');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
this.log.info('HMAC key derived from authToken (consider using key file instead)');
|
|
156
|
+
return Buffer.from(crypto.hkdfSync('sha256', Buffer.from(authToken, 'utf-8'), Buffer.alloc(32), Buffer.from('instar-inbox-signing', 'utf-8'), 32));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Start the daemon — connect to relay, begin processing.
|
|
160
|
+
*/
|
|
161
|
+
async start() {
|
|
162
|
+
// Write PID file
|
|
163
|
+
fs.writeFileSync(this.pidPath, String(process.pid));
|
|
164
|
+
this.log.info(`Daemon started (pid: ${process.pid})`);
|
|
165
|
+
// Wire relay events
|
|
166
|
+
this.relay.on('connected', (sessionId) => {
|
|
167
|
+
this.log.info(`Connected to relay (session: ${sessionId.slice(0, 8)}...)`);
|
|
168
|
+
this.writeHealth();
|
|
169
|
+
// Subscribe to presence changes for fast failover (Phase 3)
|
|
170
|
+
try {
|
|
171
|
+
this.relay.subscribe(); // Subscribe to all presence changes
|
|
172
|
+
this.log.info('Subscribed to relay presence changes');
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
this.log.warn(`Failed to subscribe to presence: ${err}`);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
this.relay.on('disconnected', (reason) => {
|
|
179
|
+
this.log.warn(`Disconnected from relay: ${reason}`);
|
|
180
|
+
this.disconnects.push(Date.now());
|
|
181
|
+
this.writeHealth();
|
|
182
|
+
});
|
|
183
|
+
this.relay.on('displaced', (reason) => {
|
|
184
|
+
this.log.warn(`DISPLACED by another connection: ${reason}`);
|
|
185
|
+
this.log.warn('Yielding gracefully — will NOT reconnect');
|
|
186
|
+
this.writeHealth();
|
|
187
|
+
// Write displacement alert file for server to pick up
|
|
188
|
+
this.writeDisplacementAlert(reason);
|
|
189
|
+
this.cleanup();
|
|
190
|
+
// Exit code 0 — prevents launchd/systemd respawn loops
|
|
191
|
+
process.exit(0);
|
|
192
|
+
});
|
|
193
|
+
this.relay.on('message', (envelope) => {
|
|
194
|
+
this.handleMessage(envelope);
|
|
195
|
+
});
|
|
196
|
+
// Phase 3: Subscribe to presence changes for fast failover
|
|
197
|
+
this.relay.on('presence-change', (change) => {
|
|
198
|
+
this.log.info(`Presence change: ${change.agentId.slice(0, 8)}... → ${change.status}`);
|
|
199
|
+
if (change.status === 'offline' || change.status === 'disconnected') {
|
|
200
|
+
// Signal server with FAILOVER_TRIGGER (byte 0x02) so it can evaluate failover
|
|
201
|
+
this.sendFailoverTrigger(change.agentId);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
this.relay.on('error', (error) => {
|
|
205
|
+
this.log.error(`Relay error: ${JSON.stringify(error)}`);
|
|
206
|
+
});
|
|
207
|
+
// Connect to Unix socket for wake signals
|
|
208
|
+
this.connectWakeSocket();
|
|
209
|
+
// Start health reporting
|
|
210
|
+
this.healthTimer = setInterval(() => this.writeHealth(), this.config.healthIntervalMs);
|
|
211
|
+
// Connect to relay
|
|
212
|
+
try {
|
|
213
|
+
await this.relay.connect();
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
this.log.error(`Failed to connect to relay: ${err}`);
|
|
217
|
+
// Relay client handles reconnection internally
|
|
218
|
+
}
|
|
219
|
+
// Handle process signals
|
|
220
|
+
process.on('SIGTERM', () => {
|
|
221
|
+
this.log.info('Received SIGTERM, shutting down');
|
|
222
|
+
this.cleanup();
|
|
223
|
+
process.exit(0);
|
|
224
|
+
});
|
|
225
|
+
process.on('SIGINT', () => {
|
|
226
|
+
this.log.info('Received SIGINT, shutting down');
|
|
227
|
+
this.cleanup();
|
|
228
|
+
process.exit(0);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Handle incoming relay message — decrypt, write to inbox, signal server.
|
|
233
|
+
*/
|
|
234
|
+
handleMessage(envelope) {
|
|
235
|
+
this.msgsIn++;
|
|
236
|
+
this.lastMessageAt = new Date().toISOString();
|
|
237
|
+
// Log metadata only (never log message content)
|
|
238
|
+
this.log.info(`Message received from ${envelope.from.slice(0, 8)}... thread:${envelope.threadId?.slice(0, 8) || 'none'}`);
|
|
239
|
+
let text;
|
|
240
|
+
let senderName;
|
|
241
|
+
try {
|
|
242
|
+
// Try E2E decryption
|
|
243
|
+
// Note: we need the sender's public keys for decryption.
|
|
244
|
+
// For now, pass the envelope as-is and let the server handle full decryption.
|
|
245
|
+
// The daemon writes the raw envelope to inbox for server-side processing.
|
|
246
|
+
// This is the simpler approach — daemon doesn't need all known agent keys.
|
|
247
|
+
text = JSON.stringify({
|
|
248
|
+
type: 'encrypted-envelope',
|
|
249
|
+
envelope,
|
|
250
|
+
});
|
|
251
|
+
senderName = envelope.from.slice(0, 8);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
this.log.error(`Failed to process message: ${err}`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Write HMAC-signed entry to inbox
|
|
258
|
+
const entry = this.writeInboxEntry({
|
|
259
|
+
from: envelope.from,
|
|
260
|
+
senderName,
|
|
261
|
+
threadId: envelope.threadId || crypto.randomUUID(),
|
|
262
|
+
text,
|
|
263
|
+
messageId: envelope.messageId,
|
|
264
|
+
});
|
|
265
|
+
if (entry) {
|
|
266
|
+
// Signal server via Unix socket
|
|
267
|
+
this.sendWakeSignal();
|
|
268
|
+
this.msgsOut++;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Write an HMAC-signed entry to the inbox JSONL file.
|
|
273
|
+
*/
|
|
274
|
+
writeInboxEntry(opts) {
|
|
275
|
+
const inboxPath = path.join(this.config.stateDir, 'threadline', 'inbox.jsonl.active');
|
|
276
|
+
const inboxDir = path.dirname(inboxPath);
|
|
277
|
+
if (!fs.existsSync(inboxDir)) {
|
|
278
|
+
fs.mkdirSync(inboxDir, { recursive: true });
|
|
279
|
+
}
|
|
280
|
+
const entryData = {
|
|
281
|
+
id: opts.messageId || crypto.randomUUID(),
|
|
282
|
+
timestamp: new Date().toISOString(),
|
|
283
|
+
from: opts.from,
|
|
284
|
+
senderName: opts.senderName,
|
|
285
|
+
trustLevel: 'unknown', // Server determines trust level
|
|
286
|
+
threadId: opts.threadId,
|
|
287
|
+
text: opts.text,
|
|
288
|
+
};
|
|
289
|
+
// Compute HMAC-SHA256
|
|
290
|
+
const hmac = crypto.createHmac('sha256', this.signingKey);
|
|
291
|
+
hmac.update(JSON.stringify(entryData));
|
|
292
|
+
const entry = { ...entryData, hmac: hmac.digest('hex') };
|
|
293
|
+
try {
|
|
294
|
+
// Append to active inbox file (atomic on local POSIX filesystems)
|
|
295
|
+
fs.appendFileSync(inboxPath, JSON.stringify(entry) + '\n');
|
|
296
|
+
this.log.debug(`Inbox entry written: ${entry.id.slice(0, 8)}...`);
|
|
297
|
+
return entry;
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
this.log.error(`Failed to write inbox entry: ${err}`);
|
|
301
|
+
// Retry up to 3 times
|
|
302
|
+
for (let i = 0; i < 3; i++) {
|
|
303
|
+
try {
|
|
304
|
+
fs.appendFileSync(inboxPath, JSON.stringify(entry) + '\n');
|
|
305
|
+
this.log.info(`Inbox entry written on retry ${i + 1}`);
|
|
306
|
+
return entry;
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Continue retrying
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
this.log.error('Inbox write failed after 3 retries');
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// ── Failover Trigger ──────────────────────────────────────────────
|
|
317
|
+
/**
|
|
318
|
+
* Send a FAILOVER_TRIGGER signal (byte 0x02) over the Unix socket
|
|
319
|
+
* when a peer agent disconnects from the relay.
|
|
320
|
+
* The server's MultiMachineCoordinator evaluates whether to promote.
|
|
321
|
+
*/
|
|
322
|
+
sendFailoverTrigger(disconnectedAgentId) {
|
|
323
|
+
// Write trigger info to a file the server can read
|
|
324
|
+
try {
|
|
325
|
+
const triggerPath = path.join(this.config.stateDir, 'failover-trigger.json');
|
|
326
|
+
fs.writeFileSync(triggerPath, JSON.stringify({
|
|
327
|
+
type: 'presence-change',
|
|
328
|
+
agentId: disconnectedAgentId,
|
|
329
|
+
timestamp: new Date().toISOString(),
|
|
330
|
+
daemonPid: process.pid,
|
|
331
|
+
}, null, 2), { mode: 0o600 });
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
this.log.error(`Failed to write failover trigger: ${err}`);
|
|
335
|
+
}
|
|
336
|
+
// Send byte 0x02 over Unix socket
|
|
337
|
+
if (this.socketConnected && this.wakeSocket) {
|
|
338
|
+
try {
|
|
339
|
+
this.wakeSocket.write(Buffer.from([0x02]));
|
|
340
|
+
this.log.info(`Failover trigger sent for ${disconnectedAgentId.slice(0, 8)}...`);
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
this.log.warn('Failed to send failover trigger via socket');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// ── Unix Socket Wake Signal ───────────────────────────────────────
|
|
348
|
+
/**
|
|
349
|
+
* Connect to the server's Unix domain socket for wake signals.
|
|
350
|
+
* Uses persistent connection (not per-message) to avoid TOCTOU attacks.
|
|
351
|
+
*/
|
|
352
|
+
connectWakeSocket() {
|
|
353
|
+
const socketPath = this.config.socketPath;
|
|
354
|
+
// Resolve symlinks before connecting (prevents symlink substitution attacks)
|
|
355
|
+
let resolvedPath;
|
|
356
|
+
try {
|
|
357
|
+
resolvedPath = fs.realpathSync(socketPath);
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// Socket doesn't exist yet — server may not be running
|
|
361
|
+
this.log.debug('Wake socket not available, will use sentinel file fallback');
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
this.wakeSocket = net.createConnection(resolvedPath);
|
|
366
|
+
this.wakeSocket.on('connect', () => {
|
|
367
|
+
this.socketConnected = true;
|
|
368
|
+
this.log.info('Connected to wake socket');
|
|
369
|
+
});
|
|
370
|
+
this.wakeSocket.on('error', (err) => {
|
|
371
|
+
this.socketConnected = false;
|
|
372
|
+
this.log.debug(`Wake socket error: ${err.message}`);
|
|
373
|
+
});
|
|
374
|
+
this.wakeSocket.on('close', () => {
|
|
375
|
+
this.socketConnected = false;
|
|
376
|
+
this.log.debug('Wake socket closed, will retry on next message');
|
|
377
|
+
this.wakeSocket = null;
|
|
378
|
+
// Try to reconnect after a delay
|
|
379
|
+
setTimeout(() => this.connectWakeSocket(), 5000);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
this.log.debug(`Failed to connect wake socket: ${err}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Send a 1-byte wake signal to the server.
|
|
388
|
+
* Falls back to touching the sentinel file if socket is unavailable.
|
|
389
|
+
*/
|
|
390
|
+
sendWakeSignal() {
|
|
391
|
+
if (this.socketConnected && this.wakeSocket) {
|
|
392
|
+
try {
|
|
393
|
+
this.wakeSocket.write(Buffer.from([0x01]));
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
this.socketConnected = false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Fallback: touch the wake sentinel file
|
|
401
|
+
try {
|
|
402
|
+
const sentinelPath = path.join(this.config.stateDir, 'state', 'listener-wake-sentinel');
|
|
403
|
+
const dir = path.dirname(sentinelPath);
|
|
404
|
+
if (!fs.existsSync(dir))
|
|
405
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
406
|
+
fs.writeFileSync(sentinelPath, String(Date.now()));
|
|
407
|
+
}
|
|
408
|
+
catch (err) {
|
|
409
|
+
this.log.error(`Failed to touch wake sentinel: ${err}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// ── Health Reporting ──────────────────────────────────────────────
|
|
413
|
+
/**
|
|
414
|
+
* Write health snapshot to disk (0600 permissions).
|
|
415
|
+
*/
|
|
416
|
+
writeHealth() {
|
|
417
|
+
const now = Date.now();
|
|
418
|
+
// Prune disconnects older than 10 minutes
|
|
419
|
+
const tenMinAgo = now - 10 * 60 * 1000;
|
|
420
|
+
this.disconnects = this.disconnects.filter(t => t > tenMinAgo);
|
|
421
|
+
const health = {
|
|
422
|
+
pid: process.pid,
|
|
423
|
+
uptime: Math.floor((now - this.startTime) / 1000),
|
|
424
|
+
state: this.relay.connectionState,
|
|
425
|
+
disconnects10m: this.disconnects.length,
|
|
426
|
+
msgsIn: this.msgsIn,
|
|
427
|
+
msgsOut: this.msgsOut,
|
|
428
|
+
reconnectDelay: 1000, // base reconnect delay
|
|
429
|
+
lastMessage: this.lastMessageAt,
|
|
430
|
+
snapshotAge: 0,
|
|
431
|
+
};
|
|
432
|
+
try {
|
|
433
|
+
const healthPath = path.join(this.config.stateDir, 'listener-health.json');
|
|
434
|
+
fs.writeFileSync(healthPath, JSON.stringify(health, null, 2), { mode: 0o600 });
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// Health write failure is non-critical
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Write displacement alert for the server's Attention Queue.
|
|
442
|
+
*/
|
|
443
|
+
writeDisplacementAlert(reason) {
|
|
444
|
+
try {
|
|
445
|
+
const alertPath = path.join(this.config.stateDir, 'listener-displaced-alert.json');
|
|
446
|
+
fs.writeFileSync(alertPath, JSON.stringify({
|
|
447
|
+
type: 'listener-displaced',
|
|
448
|
+
timestamp: new Date().toISOString(),
|
|
449
|
+
reason,
|
|
450
|
+
pid: process.pid,
|
|
451
|
+
}, null, 2), { mode: 0o600 });
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
// Non-critical
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// ── Cleanup ───────────────────────────────────────────────────────
|
|
458
|
+
cleanup() {
|
|
459
|
+
if (this.healthTimer) {
|
|
460
|
+
clearInterval(this.healthTimer);
|
|
461
|
+
this.healthTimer = null;
|
|
462
|
+
}
|
|
463
|
+
if (this.wakeSocket) {
|
|
464
|
+
this.wakeSocket.destroy();
|
|
465
|
+
this.wakeSocket = null;
|
|
466
|
+
}
|
|
467
|
+
this.relay.disconnect();
|
|
468
|
+
// Remove PID file
|
|
469
|
+
try {
|
|
470
|
+
if (fs.existsSync(this.pidPath)) {
|
|
471
|
+
fs.unlinkSync(this.pidPath);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
// Non-critical
|
|
476
|
+
}
|
|
477
|
+
// Write final health with state 'stopped'
|
|
478
|
+
try {
|
|
479
|
+
const healthPath = path.join(this.config.stateDir, 'listener-health.json');
|
|
480
|
+
fs.writeFileSync(healthPath, JSON.stringify({
|
|
481
|
+
pid: process.pid,
|
|
482
|
+
uptime: Math.floor((Date.now() - this.startTime) / 1000),
|
|
483
|
+
state: 'stopped',
|
|
484
|
+
disconnects10m: 0,
|
|
485
|
+
msgsIn: this.msgsIn,
|
|
486
|
+
msgsOut: this.msgsOut,
|
|
487
|
+
reconnectDelay: 0,
|
|
488
|
+
lastMessage: this.lastMessageAt,
|
|
489
|
+
snapshotAge: 0,
|
|
490
|
+
}, null, 2), { mode: 0o600 });
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
// Non-critical
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// ── CLI Entry Point ──────────────────────────────────────────────────
|
|
498
|
+
async function main() {
|
|
499
|
+
const args = process.argv.slice(2);
|
|
500
|
+
let stateDir = '.instar';
|
|
501
|
+
let relayUrl = 'wss://threadline-relay.fly.dev/v1/connect';
|
|
502
|
+
let agentName = 'unknown';
|
|
503
|
+
for (let i = 0; i < args.length; i++) {
|
|
504
|
+
if (args[i] === '--state-dir' && args[i + 1]) {
|
|
505
|
+
stateDir = args[++i];
|
|
506
|
+
}
|
|
507
|
+
else if (args[i] === '--relay-url' && args[i + 1]) {
|
|
508
|
+
relayUrl = args[++i];
|
|
509
|
+
}
|
|
510
|
+
else if (args[i] === '--name' && args[i + 1]) {
|
|
511
|
+
agentName = args[++i];
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// Load config for relay URL and agent name if not provided
|
|
515
|
+
const configPath = path.join(stateDir, 'config.json');
|
|
516
|
+
if (fs.existsSync(configPath)) {
|
|
517
|
+
try {
|
|
518
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
519
|
+
if (!relayUrl || relayUrl === 'wss://threadline-relay.fly.dev/v1/connect') {
|
|
520
|
+
relayUrl = config?.threadline?.relayUrl || config?.relay?.url || relayUrl;
|
|
521
|
+
}
|
|
522
|
+
if (agentName === 'unknown') {
|
|
523
|
+
agentName = config?.name || config?.agentName || 'unknown';
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
// Use defaults
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const daemon = new ListenerDaemon({
|
|
531
|
+
stateDir,
|
|
532
|
+
relayUrl,
|
|
533
|
+
agentName,
|
|
534
|
+
healthIntervalMs: 10 * 60 * 1000, // 10 minutes
|
|
535
|
+
logPath: path.join(stateDir, 'logs', 'listener-daemon.log'),
|
|
536
|
+
logMaxBytes: 10 * 1024 * 1024, // 10MB
|
|
537
|
+
socketPath: path.join(stateDir, 'listener.sock'),
|
|
538
|
+
});
|
|
539
|
+
await daemon.start();
|
|
540
|
+
}
|
|
541
|
+
// Run if executed directly
|
|
542
|
+
const isDirectRun = process.argv[1]?.endsWith('listener-daemon.js')
|
|
543
|
+
|| process.argv[1]?.endsWith('listener-daemon.ts');
|
|
544
|
+
if (isDirectRun) {
|
|
545
|
+
main().catch(err => {
|
|
546
|
+
console.error('Listener daemon fatal error:', err);
|
|
547
|
+
process.exit(1);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
//# sourceMappingURL=listener-daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener-daemon.js","sourceRoot":"","sources":["../../src/threadline/listener-daemon.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Persistent autonomy infrastructure for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
".claude/skills/setup-wizard",
|
|
74
74
|
".claude/skills/secret-setup",
|
|
75
75
|
".claude/skills/autonomous",
|
|
76
|
+
".claude/skills/build",
|
|
76
77
|
".claude/hooks",
|
|
77
78
|
".claude/settings.json"
|
|
78
79
|
],
|