pilotlynx 0.1.2 → 0.2.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/README.md +40 -40
- package/dist/agents/improve.agent.d.ts +42 -1
- package/dist/agents/improve.agent.js +102 -7
- package/dist/agents/improve.agent.js.map +1 -1
- package/dist/agents/run.agent.d.ts +0 -1
- package/dist/agents/run.agent.js +10 -7
- package/dist/agents/run.agent.js.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +51 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/eval.d.ts +2 -0
- package/dist/commands/eval.js +47 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/improve.js +83 -5
- package/dist/commands/improve.js.map +1 -1
- package/dist/commands/init.js +17 -27
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/insights.js +63 -0
- package/dist/commands/insights.js.map +1 -1
- package/dist/commands/logs.d.ts +1 -0
- package/dist/commands/logs.js +23 -1
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/relay.js +250 -124
- package/dist/commands/relay.js.map +1 -1
- package/dist/commands/run.js +21 -2
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/schedule.js +7 -1
- package/dist/commands/schedule.js.map +1 -1
- package/dist/commands/status.js +9 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/lib/agent-runner.d.ts +5 -1
- package/dist/lib/agent-runner.js +41 -1
- package/dist/lib/agent-runner.js.map +1 -1
- package/dist/lib/audit.d.ts +7 -0
- package/dist/lib/audit.js +63 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/callbacks.d.ts +12 -1
- package/dist/lib/callbacks.js +147 -19
- package/dist/lib/callbacks.js.map +1 -1
- package/dist/lib/command-ops/doctor-ops.js +41 -6
- package/dist/lib/command-ops/doctor-ops.js.map +1 -1
- package/dist/lib/command-ops/eval-ops.d.ts +7 -0
- package/dist/lib/command-ops/eval-ops.js +111 -0
- package/dist/lib/command-ops/eval-ops.js.map +1 -0
- package/dist/lib/command-ops/improve-ops.d.ts +14 -1
- package/dist/lib/command-ops/improve-ops.js +369 -17
- package/dist/lib/command-ops/improve-ops.js.map +1 -1
- package/dist/lib/command-ops/run-ops.d.ts +8 -1
- package/dist/lib/command-ops/run-ops.js +25 -4
- package/dist/lib/command-ops/run-ops.js.map +1 -1
- package/dist/lib/command-ops/secrets-migration-ops.js +1 -1
- package/dist/lib/command-ops/secrets-migration-ops.js.map +1 -1
- package/dist/lib/command-ops/status-ops.d.ts +1 -0
- package/dist/lib/command-ops/status-ops.js +19 -7
- package/dist/lib/command-ops/status-ops.js.map +1 -1
- package/dist/lib/config.js +3 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/cron.d.ts +1 -1
- package/dist/lib/cron.js +2 -2
- package/dist/lib/cron.js.map +1 -1
- package/dist/lib/global-config.js +1 -1
- package/dist/lib/global-config.js.map +1 -1
- package/dist/lib/observation.d.ts +60 -2
- package/dist/lib/observation.js +261 -13
- package/dist/lib/observation.js.map +1 -1
- package/dist/lib/registry.d.ts +0 -1
- package/dist/lib/registry.js +1 -1
- package/dist/lib/registry.js.map +1 -1
- package/dist/lib/relay/admin.d.ts +29 -0
- package/dist/lib/relay/admin.js +176 -0
- package/dist/lib/relay/admin.js.map +1 -0
- package/dist/lib/relay/bindings.d.ts +8 -0
- package/dist/lib/relay/bindings.js +50 -0
- package/dist/lib/relay/bindings.js.map +1 -0
- package/dist/lib/relay/config.d.ts +3 -3
- package/dist/lib/relay/config.js +18 -10
- package/dist/lib/relay/config.js.map +1 -1
- package/dist/lib/relay/context.d.ts +31 -0
- package/dist/lib/relay/context.js +118 -0
- package/dist/lib/relay/context.js.map +1 -0
- package/dist/lib/relay/db.d.ts +38 -0
- package/dist/lib/relay/db.js +252 -0
- package/dist/lib/relay/db.js.map +1 -0
- package/dist/lib/relay/executor.d.ts +2 -0
- package/dist/lib/relay/executor.js +108 -0
- package/dist/lib/relay/executor.js.map +1 -0
- package/dist/lib/relay/feedback.d.ts +29 -0
- package/dist/lib/relay/feedback.js +142 -0
- package/dist/lib/relay/feedback.js.map +1 -0
- package/dist/lib/relay/notifier.d.ts +30 -0
- package/dist/lib/relay/notifier.js +78 -0
- package/dist/lib/relay/notifier.js.map +1 -0
- package/dist/lib/relay/notify.d.ts +3 -4
- package/dist/lib/relay/notify.js +43 -159
- package/dist/lib/relay/notify.js.map +1 -1
- package/dist/lib/relay/platform.d.ts +52 -0
- package/dist/lib/relay/platform.js +5 -0
- package/dist/lib/relay/platform.js.map +1 -0
- package/dist/lib/relay/platforms/slack.d.ts +37 -0
- package/dist/lib/relay/platforms/slack.js +240 -0
- package/dist/lib/relay/platforms/slack.js.map +1 -0
- package/dist/lib/relay/platforms/telegram.d.ts +29 -0
- package/dist/lib/relay/platforms/telegram.js +193 -0
- package/dist/lib/relay/platforms/telegram.js.map +1 -0
- package/dist/lib/relay/poster.d.ts +24 -0
- package/dist/lib/relay/poster.js +136 -0
- package/dist/lib/relay/poster.js.map +1 -0
- package/dist/lib/relay/queue.d.ts +18 -0
- package/dist/lib/relay/queue.js +85 -0
- package/dist/lib/relay/queue.js.map +1 -0
- package/dist/lib/relay/router.d.ts +25 -2
- package/dist/lib/relay/router.js +259 -168
- package/dist/lib/relay/router.js.map +1 -1
- package/dist/lib/relay/service.d.ts +31 -7
- package/dist/lib/relay/service.js +281 -200
- package/dist/lib/relay/service.js.map +1 -1
- package/dist/lib/relay/types.d.ts +189 -34
- package/dist/lib/relay/types.js +68 -28
- package/dist/lib/relay/types.js.map +1 -1
- package/dist/lib/sandbox.d.ts +9 -1
- package/dist/lib/sandbox.js +17 -2
- package/dist/lib/sandbox.js.map +1 -1
- package/dist/lib/schedule.d.ts +4 -5
- package/dist/lib/schedule.js +7 -8
- package/dist/lib/schedule.js.map +1 -1
- package/dist/lib/secrets.js +11 -1
- package/dist/lib/secrets.js.map +1 -1
- package/dist/lib/types.d.ts +80 -0
- package/dist/lib/types.js +9 -1
- package/dist/lib/types.js.map +1 -1
- package/package.json +18 -18
- package/prompts/improve.yaml +114 -6
- package/prompts/relay.yaml +29 -0
- package/prompts/run.yaml +36 -2
- package/template/CLAUDE.md +34 -5
- package/template/RUNBOOK.md +5 -5
- package/template/evals/sample.json +16 -0
- package/template/memory/MEMORY.md +6 -0
- package/template/memory/procedures/.gitkeep +0 -0
- package/template/schedule.yaml +1 -1
- package/template/workflows/daily_feedback.ts +78 -2
- package/template/workflows/project_review.ts +51 -2
- package/prompts/relay-chat.yaml +0 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/lib/relay/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/lib/relay/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { RelayConfig } from './types.js';
|
|
2
|
+
import { RelayNotifier } from './notifier.js';
|
|
3
|
+
export interface RelayServiceStatus {
|
|
4
4
|
running: boolean;
|
|
5
|
-
|
|
5
|
+
uptime: number;
|
|
6
|
+
platforms: string[];
|
|
7
|
+
activeRuns: number;
|
|
8
|
+
totalRunsProcessed: number;
|
|
6
9
|
}
|
|
7
|
-
export declare
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
export declare class RelayService {
|
|
11
|
+
private config;
|
|
12
|
+
private db;
|
|
13
|
+
private platforms;
|
|
14
|
+
private pool;
|
|
15
|
+
private router;
|
|
16
|
+
private notifier;
|
|
17
|
+
private healthServer;
|
|
18
|
+
private cleanupTimer;
|
|
19
|
+
private startedAt;
|
|
20
|
+
private _running;
|
|
21
|
+
constructor(config: RelayConfig);
|
|
22
|
+
get running(): boolean;
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
getStatus(): RelayServiceStatus;
|
|
26
|
+
getNotifier(): RelayNotifier | null;
|
|
27
|
+
private getUptime;
|
|
28
|
+
private initSlack;
|
|
29
|
+
private initTelegram;
|
|
30
|
+
private recoverPendingMessages;
|
|
31
|
+
}
|
|
32
|
+
export declare function startRelayService(): Promise<RelayService>;
|
|
33
|
+
export declare function stopRelayByPid(): boolean;
|
|
@@ -1,222 +1,303 @@
|
|
|
1
|
-
|
|
1
|
+
// ── Relay Service Orchestrator ──
|
|
2
|
+
// Starts/stops the relay service, wires together all components.
|
|
3
|
+
import { writeFileSync, existsSync, readFileSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
2
4
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
+
import { createServer } from 'node:http';
|
|
6
|
+
import { loadRelayConfig, getRelayDbPath } from './config.js';
|
|
5
7
|
import { getConfigRoot } from '../config.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
import { loadRootEnv } from '../env-loader.js';
|
|
9
|
+
import { initDb, cleanupStaleData, getPendingMessages, getRunStats } from './db.js';
|
|
10
|
+
import { AgentPool } from './queue.js';
|
|
11
|
+
import { RelayRouter } from './router.js';
|
|
12
|
+
import { RelayNotifier } from './notifier.js';
|
|
13
|
+
const PID_FILE = () => join(getConfigRoot(), 'relay.pid');
|
|
14
|
+
const ENV_FILE = () => join(getConfigRoot(), '.env');
|
|
15
|
+
export class RelayService {
|
|
16
|
+
config;
|
|
17
|
+
db = null;
|
|
18
|
+
platforms = new Map();
|
|
19
|
+
pool = null;
|
|
20
|
+
router = null;
|
|
21
|
+
notifier = null;
|
|
22
|
+
healthServer = null;
|
|
23
|
+
cleanupTimer = null;
|
|
24
|
+
startedAt = null;
|
|
25
|
+
_running = false;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = config;
|
|
17
28
|
}
|
|
18
|
-
|
|
19
|
-
return
|
|
29
|
+
get running() {
|
|
30
|
+
return this._running;
|
|
20
31
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
async start() {
|
|
33
|
+
if (this._running)
|
|
34
|
+
throw new Error('Relay service is already running.');
|
|
35
|
+
// Check for sandbox if required
|
|
36
|
+
if (this.config.agent.requireKernelSandbox) {
|
|
37
|
+
const { assertSandboxAvailable } = await import('../sandbox.js');
|
|
38
|
+
assertSandboxAvailable();
|
|
39
|
+
}
|
|
40
|
+
// Check PID file — refuse to start if another instance is running
|
|
41
|
+
const pidFile = PID_FILE();
|
|
42
|
+
if (existsSync(pidFile)) {
|
|
43
|
+
const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
|
|
44
|
+
if (isProcessRunning(pid)) {
|
|
45
|
+
throw new Error(`Another relay instance is running (PID ${pid}). Stop it first with \`pilotlynx relay stop\`.`);
|
|
46
|
+
}
|
|
47
|
+
// Stale PID file — clean it up
|
|
48
|
+
unlinkSync(pidFile);
|
|
49
|
+
}
|
|
50
|
+
// Initialize SQLite
|
|
51
|
+
const dbPath = getRelayDbPath();
|
|
52
|
+
const dbDir = dirname(dbPath);
|
|
53
|
+
if (!existsSync(dbDir))
|
|
54
|
+
mkdirSync(dbDir, { recursive: true });
|
|
55
|
+
this.db = initDb(dbPath);
|
|
56
|
+
// Initialize agent pool
|
|
57
|
+
this.pool = new AgentPool(this.config.agent.maxConcurrent, this.config.limits.projectQueueDepth, this.config.agent.maxMemoryMB);
|
|
58
|
+
// Initialize router
|
|
59
|
+
this.router = new RelayRouter(this.db, this.pool, this.config);
|
|
60
|
+
// Load env for platform tokens
|
|
61
|
+
const env = loadRootEnv(ENV_FILE());
|
|
62
|
+
// Initialize platforms
|
|
63
|
+
if (this.config.platforms.slack.enabled) {
|
|
64
|
+
const slackPlatform = await this.initSlack(env);
|
|
65
|
+
if (slackPlatform) {
|
|
66
|
+
this.platforms.set('slack', slackPlatform);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (this.config.platforms.telegram.enabled) {
|
|
70
|
+
const telegramPlatform = await this.initTelegram(env);
|
|
71
|
+
if (telegramPlatform) {
|
|
72
|
+
this.platforms.set('telegram', telegramPlatform);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (this.platforms.size === 0) {
|
|
76
|
+
throw new Error('No platforms enabled or configured. Enable at least one platform in relay.yaml.');
|
|
77
|
+
}
|
|
78
|
+
// Initialize notifier
|
|
79
|
+
this.notifier = new RelayNotifier(this.platforms, this.db, this.config);
|
|
80
|
+
// Wire platform handlers to router
|
|
81
|
+
for (const platform of this.platforms.values()) {
|
|
82
|
+
platform.onMessage = (msg) => this.router.routeMessage(platform, msg);
|
|
83
|
+
platform.onReaction = (channelId, messageId, userId, emoji) => this.router.routeReaction(platform, channelId, messageId, userId, emoji);
|
|
84
|
+
platform.onCommand = (channelId, userId, command, args) => this.router.routeCommand(platform, channelId, userId, command, args);
|
|
85
|
+
}
|
|
86
|
+
// Start all platforms
|
|
87
|
+
for (const [name, platform] of this.platforms) {
|
|
88
|
+
try {
|
|
89
|
+
await platform.start();
|
|
90
|
+
console.log(`[relay] ${name} platform started.`);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`[relay] Failed to start ${name}:`, err);
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Recover pending messages from previous crash
|
|
98
|
+
await this.recoverPendingMessages();
|
|
99
|
+
// Start periodic cleanup (every hour)
|
|
100
|
+
this.cleanupTimer = setInterval(() => {
|
|
101
|
+
if (this.db) {
|
|
102
|
+
cleanupStaleData(this.db, 24, 7, 30);
|
|
103
|
+
}
|
|
104
|
+
}, 3_600_000);
|
|
105
|
+
this.cleanupTimer.unref();
|
|
106
|
+
// Initial cleanup
|
|
107
|
+
cleanupStaleData(this.db, 24, 7, 30);
|
|
108
|
+
// Write PID file
|
|
109
|
+
writeFileSync(pidFile, String(process.pid), 'utf8');
|
|
110
|
+
// Start health endpoint
|
|
111
|
+
this.healthServer = createServer((req, res) => {
|
|
112
|
+
if (req.url === '/healthz') {
|
|
113
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
114
|
+
res.end(JSON.stringify({ status: 'ok', uptime: this.getUptime() }));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
res.writeHead(404);
|
|
118
|
+
res.end();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
this.healthServer.listen(9100);
|
|
122
|
+
this.healthServer.unref();
|
|
123
|
+
this.startedAt = new Date();
|
|
124
|
+
this._running = true;
|
|
125
|
+
console.log(`[relay] Service started. Platforms: ${[...this.platforms.keys()].join(', ')}`);
|
|
25
126
|
}
|
|
26
|
-
|
|
27
|
-
|
|
127
|
+
async stop() {
|
|
128
|
+
if (!this._running)
|
|
129
|
+
return;
|
|
130
|
+
console.log('[relay] Stopping service...');
|
|
131
|
+
this._running = false;
|
|
132
|
+
// Stop accepting new work
|
|
133
|
+
if (this.cleanupTimer) {
|
|
134
|
+
clearInterval(this.cleanupTimer);
|
|
135
|
+
this.cleanupTimer = null;
|
|
136
|
+
}
|
|
137
|
+
// Stop health server
|
|
138
|
+
if (this.healthServer) {
|
|
139
|
+
this.healthServer.close();
|
|
140
|
+
this.healthServer = null;
|
|
141
|
+
}
|
|
142
|
+
// Drain the pool (wait up to 5 min for in-flight runs)
|
|
143
|
+
if (this.pool) {
|
|
144
|
+
const drainTimeout = setTimeout(() => {
|
|
145
|
+
console.warn('[relay] Drain timeout reached, force-stopping.');
|
|
146
|
+
}, 300_000);
|
|
147
|
+
drainTimeout.unref();
|
|
148
|
+
try {
|
|
149
|
+
await this.pool.shutdown();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Best effort
|
|
153
|
+
}
|
|
154
|
+
clearTimeout(drainTimeout);
|
|
155
|
+
}
|
|
156
|
+
// Stop platforms
|
|
157
|
+
for (const [name, platform] of this.platforms) {
|
|
158
|
+
try {
|
|
159
|
+
await platform.stop();
|
|
160
|
+
console.log(`[relay] ${name} platform stopped.`);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
console.error(`[relay] Error stopping ${name}:`, err);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
this.platforms.clear();
|
|
167
|
+
// Close database
|
|
168
|
+
if (this.db) {
|
|
169
|
+
this.db.close();
|
|
170
|
+
this.db = null;
|
|
171
|
+
}
|
|
172
|
+
// Remove PID file
|
|
173
|
+
const pidFile = PID_FILE();
|
|
174
|
+
if (existsSync(pidFile)) {
|
|
175
|
+
try {
|
|
176
|
+
unlinkSync(pidFile);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Non-fatal
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
console.log('[relay] Service stopped.');
|
|
28
183
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const plynxBin = resolvePlynxBin();
|
|
38
|
-
const configRoot = getConfigRoot();
|
|
39
|
-
return `[Unit]
|
|
40
|
-
Description=PilotLynx Relay (Telegram bot)
|
|
41
|
-
After=network-online.target
|
|
42
|
-
Wants=network-online.target
|
|
43
|
-
|
|
44
|
-
[Service]
|
|
45
|
-
Type=simple
|
|
46
|
-
ExecStart=${nodePath} ${plynxBin} relay start
|
|
47
|
-
Restart=on-failure
|
|
48
|
-
RestartSec=5
|
|
49
|
-
StartLimitBurst=3
|
|
50
|
-
Environment=PILOTLYNX_ROOT=${configRoot}
|
|
51
|
-
Environment=PATH=${process.env.PATH}
|
|
52
|
-
Environment=HOME=${homedir()}
|
|
53
|
-
Environment=NODE_ENV=production
|
|
54
|
-
|
|
55
|
-
[Install]
|
|
56
|
-
WantedBy=default.target
|
|
57
|
-
`;
|
|
58
|
-
}
|
|
59
|
-
function installLinux() {
|
|
60
|
-
const servicePath = systemdServicePath();
|
|
61
|
-
mkdirSync(dirname(servicePath), { recursive: true });
|
|
62
|
-
writeFileSync(servicePath, generateSystemdUnit(), 'utf8');
|
|
63
|
-
try {
|
|
64
|
-
execFileSync('loginctl', ['enable-linger', process.env.USER ?? ''], { stdio: 'pipe' });
|
|
184
|
+
getStatus() {
|
|
185
|
+
return {
|
|
186
|
+
running: this._running,
|
|
187
|
+
uptime: this.getUptime(),
|
|
188
|
+
platforms: [...this.platforms.keys()],
|
|
189
|
+
activeRuns: this.pool?.getActiveCount() ?? 0,
|
|
190
|
+
totalRunsProcessed: this.db ? getRunStats(this.db).totalRuns : 0,
|
|
191
|
+
};
|
|
65
192
|
}
|
|
66
|
-
|
|
67
|
-
|
|
193
|
+
getNotifier() {
|
|
194
|
+
return this.notifier;
|
|
68
195
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
execFileSync('systemctl', ['--user', 'stop', SYSTEMD_SERVICE_NAME], { stdio: 'pipe' });
|
|
196
|
+
// ── Private ──
|
|
197
|
+
getUptime() {
|
|
198
|
+
if (!this.startedAt)
|
|
199
|
+
return 0;
|
|
200
|
+
return Date.now() - this.startedAt.getTime();
|
|
75
201
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
unlinkSync(servicePath);
|
|
84
|
-
try {
|
|
85
|
-
execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'pipe' });
|
|
86
|
-
}
|
|
87
|
-
catch { /* best effort */ }
|
|
88
|
-
}
|
|
89
|
-
function statusLinux() {
|
|
90
|
-
const installed = existsSync(systemdServicePath());
|
|
91
|
-
let running = false;
|
|
92
|
-
if (installed) {
|
|
93
|
-
try {
|
|
94
|
-
const result = execFileSync('systemctl', ['--user', 'is-active', SYSTEMD_SERVICE_NAME], {
|
|
95
|
-
encoding: 'utf8',
|
|
96
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
97
|
-
}).trim();
|
|
98
|
-
running = result === 'active';
|
|
202
|
+
async initSlack(env) {
|
|
203
|
+
const botToken = env.SLACK_BOT_TOKEN;
|
|
204
|
+
const appToken = env.SLACK_APP_TOKEN;
|
|
205
|
+
const signingSecret = env.SLACK_SIGNING_SECRET;
|
|
206
|
+
if (!botToken || !appToken) {
|
|
207
|
+
console.warn('[relay] Slack enabled but SLACK_BOT_TOKEN or SLACK_APP_TOKEN missing in .env');
|
|
208
|
+
return null;
|
|
99
209
|
}
|
|
100
|
-
catch { /* inactive or failed */ }
|
|
101
|
-
}
|
|
102
|
-
return { installed, running, platform: 'linux' };
|
|
103
|
-
}
|
|
104
|
-
// ── macOS (launchd user agent) ──
|
|
105
|
-
const LAUNCHD_LABEL = 'com.pilotlynx.relay';
|
|
106
|
-
function launchdPlistPath() {
|
|
107
|
-
return join(homedir(), 'Library', 'LaunchAgents', `${LAUNCHD_LABEL}.plist`);
|
|
108
|
-
}
|
|
109
|
-
function generateLaunchdPlist() {
|
|
110
|
-
const nodePath = resolveNodePath();
|
|
111
|
-
const plynxBin = resolvePlynxBin();
|
|
112
|
-
const configRoot = getConfigRoot();
|
|
113
|
-
const logDir = join(homedir(), 'Library', 'Logs', 'pilotlynx');
|
|
114
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
115
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
116
|
-
<plist version="1.0">
|
|
117
|
-
<dict>
|
|
118
|
-
<key>Label</key>
|
|
119
|
-
<string>${LAUNCHD_LABEL}</string>
|
|
120
|
-
<key>ProgramArguments</key>
|
|
121
|
-
<array>
|
|
122
|
-
<string>${nodePath}</string>
|
|
123
|
-
<string>${plynxBin}</string>
|
|
124
|
-
<string>relay</string>
|
|
125
|
-
<string>start</string>
|
|
126
|
-
</array>
|
|
127
|
-
<key>RunAtLoad</key>
|
|
128
|
-
<true/>
|
|
129
|
-
<key>KeepAlive</key>
|
|
130
|
-
<true/>
|
|
131
|
-
<key>EnvironmentVariables</key>
|
|
132
|
-
<dict>
|
|
133
|
-
<key>PILOTLYNX_ROOT</key>
|
|
134
|
-
<string>${configRoot}</string>
|
|
135
|
-
<key>PATH</key>
|
|
136
|
-
<string>${process.env.PATH}</string>
|
|
137
|
-
<key>HOME</key>
|
|
138
|
-
<string>${homedir()}</string>
|
|
139
|
-
</dict>
|
|
140
|
-
<key>StandardOutPath</key>
|
|
141
|
-
<string>${logDir}/relay.log</string>
|
|
142
|
-
<key>StandardErrorPath</key>
|
|
143
|
-
<string>${logDir}/relay-error.log</string>
|
|
144
|
-
</dict>
|
|
145
|
-
</plist>
|
|
146
|
-
`;
|
|
147
|
-
}
|
|
148
|
-
function installMacos() {
|
|
149
|
-
const plistPath = launchdPlistPath();
|
|
150
|
-
mkdirSync(dirname(plistPath), { recursive: true });
|
|
151
|
-
const logDir = join(homedir(), 'Library', 'Logs', 'pilotlynx');
|
|
152
|
-
mkdirSync(logDir, { recursive: true });
|
|
153
|
-
writeFileSync(plistPath, generateLaunchdPlist(), 'utf8');
|
|
154
|
-
execFileSync('launchctl', ['load', plistPath], { stdio: 'pipe' });
|
|
155
|
-
}
|
|
156
|
-
function uninstallMacos() {
|
|
157
|
-
const plistPath = launchdPlistPath();
|
|
158
|
-
if (existsSync(plistPath)) {
|
|
159
210
|
try {
|
|
160
|
-
|
|
211
|
+
const { SlackAdapter } = await import('./platforms/slack.js');
|
|
212
|
+
return new SlackAdapter({
|
|
213
|
+
botToken,
|
|
214
|
+
appToken,
|
|
215
|
+
signingSecret: signingSecret ?? '',
|
|
216
|
+
mode: this.config.platforms.slack.mode,
|
|
217
|
+
port: this.config.platforms.slack.port,
|
|
218
|
+
mainChannel: this.config.platforms.slack.mainChannel,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
console.error('[relay] Failed to load Slack adapter. Is @slack/bolt installed?', err);
|
|
223
|
+
return null;
|
|
161
224
|
}
|
|
162
|
-
catch { /* may not be loaded */ }
|
|
163
|
-
unlinkSync(plistPath);
|
|
164
225
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
226
|
+
async initTelegram(env) {
|
|
227
|
+
const botToken = env.TELEGRAM_BOT_TOKEN;
|
|
228
|
+
if (!botToken) {
|
|
229
|
+
console.warn('[relay] Telegram enabled but TELEGRAM_BOT_TOKEN missing in .env');
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
170
232
|
try {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
233
|
+
const { TelegramAdapter } = await import('./platforms/telegram.js');
|
|
234
|
+
return new TelegramAdapter({
|
|
235
|
+
botToken,
|
|
236
|
+
streamMode: this.config.platforms.telegram.streamMode,
|
|
237
|
+
editIntervalMs: this.config.platforms.telegram.editIntervalMs,
|
|
174
238
|
});
|
|
175
|
-
running = result.includes(LAUNCHD_LABEL);
|
|
176
239
|
}
|
|
177
|
-
catch {
|
|
240
|
+
catch (err) {
|
|
241
|
+
console.error('[relay] Failed to load Telegram adapter. Is grammy installed?', err);
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async recoverPendingMessages() {
|
|
246
|
+
if (!this.db)
|
|
247
|
+
return;
|
|
248
|
+
const pending = getPendingMessages(this.db, 10); // 10 min TTL
|
|
249
|
+
if (pending.length === 0)
|
|
250
|
+
return;
|
|
251
|
+
console.log(`[relay] Recovering ${pending.length} pending message(s) from previous session.`);
|
|
252
|
+
for (const msg of pending) {
|
|
253
|
+
const platform = this.platforms.get(msg.platform);
|
|
254
|
+
if (!platform)
|
|
255
|
+
continue;
|
|
256
|
+
try {
|
|
257
|
+
await platform.sendMessage(msg.channelId, `_Recovered from previous session. Your message "${msg.text.slice(0, 50)}..." is being re-processed._`, msg.conversationId);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Best effort recovery notification
|
|
261
|
+
}
|
|
262
|
+
}
|
|
178
263
|
}
|
|
179
|
-
return { installed, running, platform: 'macos' };
|
|
180
|
-
}
|
|
181
|
-
// ── Windows (instructions only — node-windows is optional) ──
|
|
182
|
-
function installWindows() {
|
|
183
|
-
throw new Error('Automatic Windows service installation requires the "node-windows" package.\n' +
|
|
184
|
-
'Install it with: npm install -g node-windows\n' +
|
|
185
|
-
'Then run: pilotlynx relay install\n\n' +
|
|
186
|
-
'Alternatively, run "pilotlynx relay start" manually or create a Task Scheduler entry.');
|
|
187
|
-
}
|
|
188
|
-
function uninstallWindows() {
|
|
189
|
-
throw new Error('Automatic Windows service uninstallation requires the "node-windows" package.\n' +
|
|
190
|
-
'Remove the service manually via services.msc or Task Scheduler.');
|
|
191
|
-
}
|
|
192
|
-
function statusWindows() {
|
|
193
|
-
return { installed: false, running: false, platform: 'windows' };
|
|
194
264
|
}
|
|
195
|
-
// ──
|
|
196
|
-
export function
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
265
|
+
// ── Service Management ──
|
|
266
|
+
export async function startRelayService() {
|
|
267
|
+
const config = loadRelayConfig();
|
|
268
|
+
if (!config) {
|
|
269
|
+
throw new Error('No relay.yaml found. Create one in your pilotlynx/ config directory.');
|
|
270
|
+
}
|
|
271
|
+
const service = new RelayService(config);
|
|
272
|
+
await service.start();
|
|
273
|
+
// Handle graceful shutdown
|
|
274
|
+
const shutdown = async () => {
|
|
275
|
+
await service.stop();
|
|
276
|
+
process.exit(0);
|
|
277
|
+
};
|
|
278
|
+
process.on('SIGTERM', shutdown);
|
|
279
|
+
process.on('SIGINT', shutdown);
|
|
280
|
+
return service;
|
|
204
281
|
}
|
|
205
|
-
export function
|
|
206
|
-
const
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
282
|
+
export function stopRelayByPid() {
|
|
283
|
+
const pidFile = PID_FILE();
|
|
284
|
+
if (!existsSync(pidFile))
|
|
285
|
+
return false;
|
|
286
|
+
const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
|
|
287
|
+
if (!isProcessRunning(pid)) {
|
|
288
|
+
unlinkSync(pidFile);
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
process.kill(pid, 'SIGTERM');
|
|
292
|
+
return true;
|
|
213
293
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
294
|
+
function isProcessRunning(pid) {
|
|
295
|
+
try {
|
|
296
|
+
process.kill(pid, 0);
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
221
302
|
}
|
|
222
303
|
//# sourceMappingURL=service.js.map
|