4runr-os 2.10.72 → 2.10.73

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/watchdog.js CHANGED
@@ -99,6 +99,15 @@ function stopContainers() {
99
99
  // Docker unavailable
100
100
  }
101
101
  }
102
+ /**
103
+ * Stop the local Gateway Node process and Postgres/Redis containers (volumes preserved).
104
+ * Used on TUI disconnect from localhost and on full `4r` exit via `stopWatchdog()`.
105
+ */
106
+ export function shutdownLocalGatewayStack() {
107
+ killGateway();
108
+ stopContainers();
109
+ process.stderr.write('[4Runr] Local Gateway stopped; Postgres + Redis containers stop attempted (volumes preserved).\n');
110
+ }
102
111
  /**
103
112
  * Kill any autostarted Gateway process (Windows: full process tree + listener fallback).
104
113
  * Prints verification lines to stderr so you can trust cleanup without running netstat.
@@ -130,78 +139,78 @@ export function startWatchdog(parentPid) {
130
139
  // Write parent PID for watchdog to monitor
131
140
  fs.writeFileSync(getParentPidPath(), String(parentPid), 'utf-8');
132
141
  // Spawn detached watchdog process
133
- const watchdogScript = `
134
- const fs = require('fs');
135
- const os = require('os');
136
- const path = require('path');
137
- const { execSync } = require('child_process');
138
-
139
- const parentPidPath = path.join(os.tmpdir(), '${PARENT_PID_FILE}');
140
- const watchdogPidPath = path.join(os.tmpdir(), '${WATCHDOG_PID_FILE}');
141
-
142
- // Write our own PID
143
- fs.writeFileSync(watchdogPidPath, String(process.pid), 'utf-8');
144
-
145
- function isRunning(pid) {
146
- try { process.kill(pid, 0); return true; } catch { return false; }
147
- }
148
-
149
- function cleanup() {
150
- try {
151
- // Kill Gateway (Windows: taskkill /T — npm-spawn leaves child Node alive after SIGTERM)
152
- const gwPid = path.join(os.tmpdir(), '4runr-os-local-gateway.pid');
153
- if (fs.existsSync(gwPid)) {
154
- try {
155
- const pid = parseInt(fs.readFileSync(gwPid, 'utf-8').trim(), 10);
156
- if (pid > 0 && isRunning(pid)) {
157
- if (process.platform === 'win32') {
158
- try { execSync('taskkill /PID ' + pid + ' /T /F', { stdio: 'pipe', timeout: 20000, windowsHide: true }); } catch {}
159
- } else {
160
- try { process.kill(pid, 'SIGTERM'); } catch {}
161
- }
162
- }
163
- } catch {}
164
- try { fs.unlinkSync(gwPid); } catch {}
165
- }
166
-
167
- try {
168
- execSync('docker exec 4runr-redis redis-cli SAVE', { stdio: 'pipe', timeout: 5000, windowsHide: process.platform === 'win32' });
169
- } catch {}
170
- try {
171
- execSync('docker stop -t 30 4runr-postgres', { stdio: 'pipe', timeout: 35000, windowsHide: process.platform === 'win32' });
172
- } catch {}
173
- try {
174
- execSync('docker stop -t 30 4runr-redis', { stdio: 'pipe', timeout: 35000, windowsHide: process.platform === 'win32' });
175
- } catch {}
176
- try {
177
- const composeDir = process.platform === 'win32'
178
- ? path.join(process.env.APPDATA || '', '4runr')
179
- : path.join(process.env.HOME || '', '.4runr');
180
- const composePath = path.join(composeDir, 'docker-compose.yml');
181
- if (fs.existsSync(composePath)) {
182
- execSync(\`docker compose -f "\${composePath}" stop\`, { stdio: 'pipe', timeout: 30000, windowsHide: process.platform === 'win32' });
183
- }
184
- } catch {}
185
- } catch {}
186
-
187
- // Cleanup PID files
188
- try { fs.unlinkSync(parentPidPath); } catch {}
189
- try { fs.unlinkSync(watchdogPidPath); } catch {}
190
- process.exit(0);
191
- }
192
-
193
- // Monitor parent process
194
- const parentPid = parseInt(fs.readFileSync(parentPidPath, 'utf-8').trim(), 10);
195
- const interval = setInterval(() => {
196
- if (!isRunning(parentPid)) {
197
- clearInterval(interval);
198
- cleanup();
199
- }
200
- }, 1000); // Check every second
201
-
202
- // Cleanup on watchdog exit signals
203
- process.on('SIGTERM', cleanup);
204
- process.on('SIGINT', cleanup);
142
+ const watchdogScript = `
143
+ const fs = require('fs');
144
+ const os = require('os');
145
+ const path = require('path');
146
+ const { execSync } = require('child_process');
147
+
148
+ const parentPidPath = path.join(os.tmpdir(), '${PARENT_PID_FILE}');
149
+ const watchdogPidPath = path.join(os.tmpdir(), '${WATCHDOG_PID_FILE}');
150
+
151
+ // Write our own PID
152
+ fs.writeFileSync(watchdogPidPath, String(process.pid), 'utf-8');
153
+
154
+ function isRunning(pid) {
155
+ try { process.kill(pid, 0); return true; } catch { return false; }
156
+ }
157
+
158
+ function cleanup() {
159
+ try {
160
+ // Kill Gateway (Windows: taskkill /T — npm-spawn leaves child Node alive after SIGTERM)
161
+ const gwPid = path.join(os.tmpdir(), '4runr-os-local-gateway.pid');
162
+ if (fs.existsSync(gwPid)) {
163
+ try {
164
+ const pid = parseInt(fs.readFileSync(gwPid, 'utf-8').trim(), 10);
165
+ if (pid > 0 && isRunning(pid)) {
166
+ if (process.platform === 'win32') {
167
+ try { execSync('taskkill /PID ' + pid + ' /T /F', { stdio: 'pipe', timeout: 20000, windowsHide: true }); } catch {}
168
+ } else {
169
+ try { process.kill(pid, 'SIGTERM'); } catch {}
170
+ }
171
+ }
172
+ } catch {}
173
+ try { fs.unlinkSync(gwPid); } catch {}
174
+ }
175
+
176
+ try {
177
+ execSync('docker exec 4runr-redis redis-cli SAVE', { stdio: 'pipe', timeout: 5000, windowsHide: process.platform === 'win32' });
178
+ } catch {}
179
+ try {
180
+ execSync('docker stop -t 30 4runr-postgres', { stdio: 'pipe', timeout: 35000, windowsHide: process.platform === 'win32' });
181
+ } catch {}
182
+ try {
183
+ execSync('docker stop -t 30 4runr-redis', { stdio: 'pipe', timeout: 35000, windowsHide: process.platform === 'win32' });
184
+ } catch {}
185
+ try {
186
+ const composeDir = process.platform === 'win32'
187
+ ? path.join(process.env.APPDATA || '', '4runr')
188
+ : path.join(process.env.HOME || '', '.4runr');
189
+ const composePath = path.join(composeDir, 'docker-compose.yml');
190
+ if (fs.existsSync(composePath)) {
191
+ execSync(\`docker compose -p 4runr -f "\${composePath}" stop\`, { stdio: 'pipe', timeout: 30000, windowsHide: process.platform === 'win32' });
192
+ }
193
+ } catch {}
194
+ } catch {}
195
+
196
+ // Cleanup PID files
197
+ try { fs.unlinkSync(parentPidPath); } catch {}
198
+ try { fs.unlinkSync(watchdogPidPath); } catch {}
199
+ process.exit(0);
200
+ }
201
+
202
+ // Monitor parent process
203
+ const parentPid = parseInt(fs.readFileSync(parentPidPath, 'utf-8').trim(), 10);
204
+ const interval = setInterval(() => {
205
+ if (!isRunning(parentPid)) {
206
+ clearInterval(interval);
207
+ cleanup();
208
+ }
209
+ }, 1000); // Check every second
210
+
211
+ // Cleanup on watchdog exit signals
212
+ process.on('SIGTERM', cleanup);
213
+ process.on('SIGINT', cleanup);
205
214
  `;
206
215
  const child = spawn(process.execPath, ['-e', watchdogScript], {
207
216
  detached: true,
@@ -227,9 +236,7 @@ export function stopWatchdog() {
227
236
  }
228
237
  }
229
238
  // Manual cleanup since watchdog is being stopped gracefully
230
- killGateway();
231
- stopContainers();
232
- process.stderr.write(`[4Runr] Docker (Postgres/Redis named containers): stop attempted — data volumes preserved.\n`);
239
+ shutdownLocalGatewayStack();
233
240
  // Cleanup PID files
234
241
  try {
235
242
  fs.unlinkSync(watchdogPidPath);
@@ -1 +1 @@
1
- {"version":3,"file":"watchdog.js","sourceRoot":"","sources":["../src/watchdog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watchdog.js","sourceRoot":"","sources":["../src/watchdog.ts"],"names":[],"mappings":"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"}
@@ -1214,6 +1214,13 @@ fn main() -> Result<()> {
1214
1214
  "✓ [{}] Disconnected from Gateway",
1215
1215
  short_id
1216
1216
  ));
1217
+ if let Some(msg) =
1218
+ obj.get("message").and_then(|v| v.as_str())
1219
+ {
1220
+ if !msg.is_empty() {
1221
+ app.add_log(msg.to_string());
1222
+ }
1223
+ }
1217
1224
  app.add_log(format!("[MODE] Switched to LOCAL mode"));
1218
1225
  app.state.pending_gateway_observability_id = None;
1219
1226
  app.state.pending_monitoring_refresh_id = None;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.10.72",
3
+ "version": "2.10.73",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.72: Auto-generate Gateway Prisma client at boot (fixes false boot fail + repair window launching degraded TUI).",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.73: Disconnect stops local Gateway + Postgres/Redis; reconnect ensures Docker stack before /ready.",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * OS-first smoke for 4Runr Tools (Sentinel + Shield) against a live Gateway.
4
4
  *