@jait/gateway 0.1.10 → 0.1.11
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/bin/jait.mjs
CHANGED
|
@@ -139,6 +139,17 @@ function buildUnit({ port, host, envPath } = {}) {
|
|
|
139
139
|
|
|
140
140
|
const execStart = execArgs.join(" ");
|
|
141
141
|
|
|
142
|
+
// Build a PATH that includes common global-bin locations so that
|
|
143
|
+
// redeploy can find npm/node/jait, and codex can be discovered.
|
|
144
|
+
const home = homedir();
|
|
145
|
+
const extraPaths = [
|
|
146
|
+
join(home, ".local", "bin"),
|
|
147
|
+
join(home, ".npm-global", "bin"),
|
|
148
|
+
"/usr/local/bin",
|
|
149
|
+
"/usr/bin",
|
|
150
|
+
"/bin",
|
|
151
|
+
].join(":");
|
|
152
|
+
|
|
142
153
|
return `[Unit]
|
|
143
154
|
Description=Jait AI Gateway
|
|
144
155
|
After=network-online.target
|
|
@@ -146,6 +157,8 @@ Wants=network-online.target
|
|
|
146
157
|
|
|
147
158
|
[Service]
|
|
148
159
|
ExecStart=${execStart}
|
|
160
|
+
Environment=PATH=${extraPaths}
|
|
161
|
+
Environment=JAIT_UNIT=${SERVICE_NAME}
|
|
149
162
|
Restart=always
|
|
150
163
|
RestartSec=5
|
|
151
164
|
KillMode=process
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gateway.redeploy — Self-update tool for the Jait gateway.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Detects the runtime environment and uses the appropriate strategy:
|
|
5
|
+
*
|
|
6
|
+
* **systemd** (detected when INVOCATION_ID is set):
|
|
7
|
+
* 1. npm install -g @jait/gateway@latest
|
|
8
|
+
* 2. Spawn canary on PORT+1, health-check it
|
|
9
|
+
* 3. If healthy → kill canary, exit process.
|
|
10
|
+
* systemd's Restart=always automatically brings up the new version.
|
|
11
|
+
* 4. If unhealthy → kill canary, report failure, stay running.
|
|
12
|
+
*
|
|
13
|
+
* **Bare process** (no service manager):
|
|
14
|
+
* 1. npm install -g @jait/gateway@latest
|
|
15
|
+
* 2. Spawn canary on PORT+1, health-check it
|
|
16
|
+
* 3. If healthy → spawn fresh gateway on original port (detached),
|
|
17
|
+
* kill canary, then gracefully shut down current process.
|
|
18
|
+
* 4. If unhealthy → kill canary, report failure, stay running.
|
|
11
19
|
*/
|
|
12
20
|
import type { ToolDefinition } from "./contracts.js";
|
|
13
21
|
interface RedeployInput {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redeploy-tools.d.ts","sourceRoot":"","sources":["../../src/tools/redeploy-tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"redeploy-tools.d.ts","sourceRoot":"","sources":["../../src/tools/redeploy-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,gBAAgB,CAAC;AAE9E,UAAU,aAAa;IACrB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,YAAY;IACpB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAC,aAAa,CAAC,CAiCpF"}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gateway.redeploy — Self-update tool for the Jait gateway.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Detects the runtime environment and uses the appropriate strategy:
|
|
5
|
+
*
|
|
6
|
+
* **systemd** (detected when INVOCATION_ID is set):
|
|
7
|
+
* 1. npm install -g @jait/gateway@latest
|
|
8
|
+
* 2. Spawn canary on PORT+1, health-check it
|
|
9
|
+
* 3. If healthy → kill canary, exit process.
|
|
10
|
+
* systemd's Restart=always automatically brings up the new version.
|
|
11
|
+
* 4. If unhealthy → kill canary, report failure, stay running.
|
|
12
|
+
*
|
|
13
|
+
* **Bare process** (no service manager):
|
|
14
|
+
* 1. npm install -g @jait/gateway@latest
|
|
15
|
+
* 2. Spawn canary on PORT+1, health-check it
|
|
16
|
+
* 3. If healthy → spawn fresh gateway on original port (detached),
|
|
17
|
+
* kill canary, then gracefully shut down current process.
|
|
18
|
+
* 4. If unhealthy → kill canary, report failure, stay running.
|
|
11
19
|
*/
|
|
12
20
|
import { execSync, spawn } from "node:child_process";
|
|
13
21
|
export function createRedeployTool(deps) {
|
|
@@ -15,7 +23,8 @@ export function createRedeployTool(deps) {
|
|
|
15
23
|
name: "gateway.redeploy",
|
|
16
24
|
description: "Self-update the Jait gateway. Pulls the latest version via npm, " +
|
|
17
25
|
"verifies it in a canary process, then performs a zero-downtime " +
|
|
18
|
-
"switchover.
|
|
26
|
+
"switchover. Under systemd, uses `systemctl restart` for a clean " +
|
|
27
|
+
"handoff. Otherwise spawns a detached replacement process. " +
|
|
19
28
|
"This tool requires human consent.",
|
|
20
29
|
tier: "standard",
|
|
21
30
|
category: "gateway",
|
|
@@ -40,22 +49,28 @@ export function createRedeployTool(deps) {
|
|
|
40
49
|
},
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
|
-
// ──
|
|
52
|
+
// ── Environment detection ────────────────────────────────────────────
|
|
53
|
+
/** Returns true when the current process was started by systemd. */
|
|
54
|
+
function isSystemd() {
|
|
55
|
+
return !!process.env.INVOCATION_ID;
|
|
56
|
+
}
|
|
57
|
+
/** Try to resolve the systemd unit name that manages us. */
|
|
58
|
+
function systemdUnit() {
|
|
59
|
+
// The daemon installer writes this, but fall back to the well-known name.
|
|
60
|
+
return process.env.JAIT_UNIT ?? "jait-gateway";
|
|
61
|
+
}
|
|
62
|
+
// ── Core redeploy logic ─────────────────────────────────────────────
|
|
44
63
|
async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
45
64
|
const pkg = `@jait/gateway@${tag}`;
|
|
46
|
-
// 1.
|
|
65
|
+
// ── 1. Capture current version ────────────────────────────────────
|
|
47
66
|
let oldVersion = "unknown";
|
|
48
67
|
try {
|
|
49
|
-
|
|
50
|
-
encoding: "utf8",
|
|
51
|
-
timeout: 10_000,
|
|
52
|
-
}));
|
|
53
|
-
oldVersion = pkgJson;
|
|
68
|
+
oldVersion = execSync("node -e \"process.stdout.write(require('@jait/gateway/package.json').version)\"", { encoding: "utf8", timeout: 10_000 });
|
|
54
69
|
}
|
|
55
70
|
catch {
|
|
56
71
|
// non-critical
|
|
57
72
|
}
|
|
58
|
-
// 2. Install the
|
|
73
|
+
// ── 2. Install the new version ────────────────────────────────────
|
|
59
74
|
log(`⬇ Installing ${pkg}...\n`);
|
|
60
75
|
try {
|
|
61
76
|
execSync(`npm install -g ${pkg}`, {
|
|
@@ -68,7 +83,7 @@ async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
|
68
83
|
const msg = err instanceof Error ? err.message : String(err);
|
|
69
84
|
return { ok: false, message: `npm install failed: ${msg}` };
|
|
70
85
|
}
|
|
71
|
-
// 3. Read new version
|
|
86
|
+
// ── 3. Read new version ───────────────────────────────────────────
|
|
72
87
|
let newVersion = "unknown";
|
|
73
88
|
try {
|
|
74
89
|
newVersion = execSync("node -e \"process.stdout.write(require('@jait/gateway/package.json').version)\"", { encoding: "utf8", timeout: 10_000 });
|
|
@@ -77,8 +92,8 @@ async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
|
77
92
|
// non-critical
|
|
78
93
|
}
|
|
79
94
|
log(`✓ Installed @jait/gateway ${newVersion} (was ${oldVersion})\n`);
|
|
95
|
+
// ── 4. Canary health check ────────────────────────────────────────
|
|
80
96
|
if (!skipCanary) {
|
|
81
|
-
// 4. Canary — start the new version on PORT+1
|
|
82
97
|
const canaryPort = deps.port + 1;
|
|
83
98
|
log(`🐤 Starting canary on port ${canaryPort}...\n`);
|
|
84
99
|
const canary = spawn("jait", ["--port", String(canaryPort)], {
|
|
@@ -87,30 +102,74 @@ async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
|
87
102
|
env: { ...process.env, PORT: String(canaryPort), __JAIT_CLI: "1" },
|
|
88
103
|
});
|
|
89
104
|
canary.unref();
|
|
90
|
-
// 5. Wait for canary health (up to 30s)
|
|
91
105
|
const healthy = await waitForHealth(`http://127.0.0.1:${canaryPort}`, 30_000);
|
|
92
106
|
if (!healthy) {
|
|
93
|
-
// Kill canary and abort
|
|
94
107
|
try {
|
|
95
108
|
process.kill(-canary.pid, "SIGTERM");
|
|
96
109
|
}
|
|
97
110
|
catch { /* ignore */ }
|
|
98
111
|
return {
|
|
99
112
|
ok: false,
|
|
100
|
-
message: `Canary failed health check on port ${canaryPort}.
|
|
113
|
+
message: `Canary failed health check on port ${canaryPort}. ` +
|
|
114
|
+
`Update installed but NOT activated. Current gateway is still running.`,
|
|
101
115
|
data: { oldVersion, newVersion, canaryPort },
|
|
102
116
|
};
|
|
103
117
|
}
|
|
104
118
|
log(`✓ Canary healthy on port ${canaryPort}\n`);
|
|
105
|
-
// 6. Kill the canary (it was just a test)
|
|
106
119
|
try {
|
|
107
120
|
process.kill(-canary.pid, "SIGTERM");
|
|
108
121
|
}
|
|
109
122
|
catch { /* ignore */ }
|
|
110
|
-
// Brief wait for port release
|
|
111
123
|
await sleep(1_000);
|
|
112
124
|
}
|
|
113
|
-
//
|
|
125
|
+
// ── 5. Switchover ─────────────────────────────────────────────────
|
|
126
|
+
if (isSystemd()) {
|
|
127
|
+
return systemdSwitchover(oldVersion, newVersion, deps, log);
|
|
128
|
+
}
|
|
129
|
+
return bareProcessSwitchover(oldVersion, newVersion, deps, log);
|
|
130
|
+
}
|
|
131
|
+
// ── systemd switchover ──────────────────────────────────────────────
|
|
132
|
+
/**
|
|
133
|
+
* Under systemd: we just exit and let Restart=always bring the new
|
|
134
|
+
* binary back up automatically. A `systemctl restart` is cleaner
|
|
135
|
+
* because it waits for the old process to fully stop before starting
|
|
136
|
+
* the new one — no port conflicts.
|
|
137
|
+
*/
|
|
138
|
+
async function systemdSwitchover(oldVersion, newVersion, deps, log) {
|
|
139
|
+
const unit = systemdUnit();
|
|
140
|
+
log(`🔄 Restarting via systemd (${unit})...\n`);
|
|
141
|
+
// Schedule the restart *after* we return the tool result, so the
|
|
142
|
+
// HTTP response has time to flush.
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
try {
|
|
145
|
+
// `systemctl --user restart` replaces the process; exec in
|
|
146
|
+
// background because we're the process being restarted.
|
|
147
|
+
const child = spawn("systemctl", ["--user", "restart", unit], {
|
|
148
|
+
stdio: "ignore",
|
|
149
|
+
detached: true,
|
|
150
|
+
});
|
|
151
|
+
child.unref();
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// If systemctl fails, fall back to a plain exit so Restart=always
|
|
155
|
+
// can still pick us up.
|
|
156
|
+
deps.shutdown().catch(() => process.exit(0));
|
|
157
|
+
}
|
|
158
|
+
}, 500);
|
|
159
|
+
return {
|
|
160
|
+
ok: true,
|
|
161
|
+
message: `Gateway updated ${oldVersion} → ${newVersion}. ` +
|
|
162
|
+
`Restarting via systemd unit "${unit}". ` +
|
|
163
|
+
`The new version will be live in a few seconds.`,
|
|
164
|
+
data: { oldVersion, newVersion, strategy: "systemd", unit },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ── Bare-process switchover ─────────────────────────────────────────
|
|
168
|
+
/**
|
|
169
|
+
* Without a service manager: spawn a fresh `jait` process on the
|
|
170
|
+
* original port (detached so it survives), then shut ourselves down.
|
|
171
|
+
*/
|
|
172
|
+
async function bareProcessSwitchover(oldVersion, newVersion, deps, log) {
|
|
114
173
|
log(`🔄 Spawning new gateway on port ${deps.port}...\n`);
|
|
115
174
|
const fresh = spawn("jait", ["--port", String(deps.port)], {
|
|
116
175
|
stdio: "ignore",
|
|
@@ -118,7 +177,6 @@ async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
|
118
177
|
env: { ...process.env, PORT: String(deps.port), __JAIT_CLI: "1" },
|
|
119
178
|
});
|
|
120
179
|
fresh.unref();
|
|
121
|
-
// 8. Shut down the current process
|
|
122
180
|
log(`✓ New gateway spawned (PID ${fresh.pid}). Shutting down current process...\n`);
|
|
123
181
|
// Give the response time to be sent before shutdown
|
|
124
182
|
setTimeout(() => {
|
|
@@ -126,8 +184,10 @@ async function npmRedeploy(tag, skipCanary, deps, log) {
|
|
|
126
184
|
}, 500);
|
|
127
185
|
return {
|
|
128
186
|
ok: true,
|
|
129
|
-
message: `Gateway updated ${oldVersion} → ${newVersion}.
|
|
130
|
-
|
|
187
|
+
message: `Gateway updated ${oldVersion} → ${newVersion}. ` +
|
|
188
|
+
`New process (PID ${fresh.pid}) is starting on port ${deps.port}. ` +
|
|
189
|
+
`This instance is shutting down.`,
|
|
190
|
+
data: { oldVersion, newVersion, pid: fresh.pid, strategy: "bare" },
|
|
131
191
|
};
|
|
132
192
|
}
|
|
133
193
|
// ── Helpers ──────────────────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redeploy-tools.js","sourceRoot":"","sources":["../../src/tools/redeploy-tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"redeploy-tools.js","sourceRoot":"","sources":["../../src/tools/redeploy-tools.ts"],"names":[],"mappings":"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"}
|