@trusty-squire/mcp 1.1.13-rc.8 → 1.1.13
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 +139 -62
- package/assets/login/vnc-input.js +9 -0
- package/assets/login/vnc.html +214 -202
- package/assets/screencaps/connect-walkthrough.png +0 -0
- package/assets/screencaps/connect-walkthrough.svg +1 -1
- package/dist/api-client.d.ts +26 -3
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +19 -31
- package/dist/api-client.js.map +1 -1
- package/dist/bin.js +2 -3
- package/dist/bin.js.map +1 -1
- package/dist/bot/browser.d.ts +134 -77
- package/dist/bot/browser.d.ts.map +1 -1
- package/dist/bot/browser.js +1788 -1543
- package/dist/bot/browser.js.map +1 -1
- package/dist/bot/compact-observation-v2.d.ts +167 -0
- package/dist/bot/compact-observation-v2.d.ts.map +1 -0
- package/dist/bot/compact-observation-v2.js +1038 -0
- package/dist/bot/compact-observation-v2.js.map +1 -0
- package/dist/bot/credential-shape.d.ts +2 -0
- package/dist/bot/credential-shape.d.ts.map +1 -1
- package/dist/bot/credential-shape.js +21 -8
- package/dist/bot/credential-shape.js.map +1 -1
- package/dist/bot/element-fingerprint.d.ts +9 -0
- package/dist/bot/element-fingerprint.d.ts.map +1 -0
- package/dist/bot/element-fingerprint.js +147 -0
- package/dist/bot/element-fingerprint.js.map +1 -0
- package/dist/bot/email-verification.d.ts +7 -1
- package/dist/bot/email-verification.d.ts.map +1 -1
- package/dist/bot/email-verification.js +48 -14
- package/dist/bot/email-verification.js.map +1 -1
- package/dist/bot/google-login.d.ts +28 -52
- package/dist/bot/google-login.d.ts.map +1 -1
- package/dist/bot/google-login.js +246 -1119
- package/dist/bot/google-login.js.map +1 -1
- package/dist/bot/install-completion.d.ts +1 -2
- package/dist/bot/install-completion.d.ts.map +1 -1
- package/dist/bot/install-completion.js +1 -2
- package/dist/bot/install-completion.js.map +1 -1
- package/dist/bot/login-state.d.ts +13 -7
- package/dist/bot/login-state.d.ts.map +1 -1
- package/dist/bot/login-state.js +50 -114
- package/dist/bot/login-state.js.map +1 -1
- package/dist/bot/oauth-providers.d.ts +1 -1
- package/dist/bot/oauth-providers.d.ts.map +1 -1
- package/dist/bot/oauth-providers.js +3 -3
- package/dist/bot/oauth-providers.js.map +1 -1
- package/dist/bot/oauth-scope.d.ts +4 -0
- package/dist/bot/oauth-scope.d.ts.map +1 -0
- package/dist/bot/oauth-scope.js +58 -0
- package/dist/bot/oauth-scope.js.map +1 -0
- package/dist/bot/operator-browser-watchdog.d.ts +127 -0
- package/dist/bot/operator-browser-watchdog.d.ts.map +1 -0
- package/dist/bot/operator-browser-watchdog.js +438 -0
- package/dist/bot/operator-browser-watchdog.js.map +1 -0
- package/dist/bot/owner-process-reaper-worker.d.ts +2 -0
- package/dist/bot/owner-process-reaper-worker.d.ts.map +1 -0
- package/dist/bot/owner-process-reaper-worker.js +17 -0
- package/dist/bot/owner-process-reaper-worker.js.map +1 -0
- package/dist/bot/owner-process-reaper.d.ts +103 -0
- package/dist/bot/owner-process-reaper.d.ts.map +1 -0
- package/dist/bot/owner-process-reaper.js +1058 -0
- package/dist/bot/owner-process-reaper.js.map +1 -0
- package/dist/bot/pay-operator.d.ts +13 -2
- package/dist/bot/pay-operator.d.ts.map +1 -1
- package/dist/bot/pay-operator.js +319 -123
- package/dist/bot/pay-operator.js.map +1 -1
- package/dist/bot/profile.d.ts +10 -1
- package/dist/bot/profile.d.ts.map +1 -1
- package/dist/bot/profile.js +137 -11
- package/dist/bot/profile.js.map +1 -1
- package/dist/bot/promote-to-skill.js +1 -1
- package/dist/bot/promote-to-skill.js.map +1 -1
- package/dist/bot/provision-session.d.ts +60 -164
- package/dist/bot/provision-session.d.ts.map +1 -1
- package/dist/bot/provision-session.js +2049 -1546
- package/dist/bot/provision-session.js.map +1 -1
- package/dist/bot/remote-login-display.d.ts +61 -0
- package/dist/bot/remote-login-display.d.ts.map +1 -0
- package/dist/bot/remote-login-display.js +765 -0
- package/dist/bot/remote-login-display.js.map +1 -0
- package/dist/bot/session/hosts.d.ts +8 -0
- package/dist/bot/session/hosts.d.ts.map +1 -0
- package/dist/bot/session/hosts.js +36 -0
- package/dist/bot/session/hosts.js.map +1 -0
- package/dist/bot/session/lifecycle.d.ts +56 -0
- package/dist/bot/session/lifecycle.d.ts.map +1 -0
- package/dist/bot/session/lifecycle.js +962 -0
- package/dist/bot/session/lifecycle.js.map +1 -0
- package/dist/bot/session/model.d.ts +175 -0
- package/dist/bot/session/model.d.ts.map +1 -0
- package/dist/bot/session/model.js +77 -0
- package/dist/bot/session/model.js.map +1 -0
- package/dist/install/cli.d.ts +29 -9
- package/dist/install/cli.d.ts.map +1 -1
- package/dist/install/cli.js +243 -322
- package/dist/install/cli.js.map +1 -1
- package/dist/install/interactive.d.ts +1 -0
- package/dist/install/interactive.d.ts.map +1 -1
- package/dist/install/interactive.js +19 -5
- package/dist/install/interactive.js.map +1 -1
- package/dist/install/ui.d.ts.map +1 -1
- package/dist/install/ui.js +3 -15
- package/dist/install/ui.js.map +1 -1
- package/dist/operator-env.js +1 -1
- package/dist/operator-env.js.map +1 -1
- package/dist/server-instance-registry.d.ts +103 -0
- package/dist/server-instance-registry.d.ts.map +1 -0
- package/dist/server-instance-registry.js +392 -0
- package/dist/server-instance-registry.js.map +1 -0
- package/dist/server.d.ts +15 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +164 -62
- package/dist/server.js.map +1 -1
- package/dist/session-guard.d.ts +28 -0
- package/dist/session-guard.d.ts.map +1 -0
- package/dist/session-guard.js +84 -0
- package/dist/session-guard.js.map +1 -0
- package/dist/session.d.ts +57 -13
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +246 -127
- package/dist/session.js.map +1 -1
- package/dist/tools/audit-log.d.ts +16 -2
- package/dist/tools/audit-log.d.ts.map +1 -1
- package/dist/tools/audit-log.js +223 -13
- package/dist/tools/audit-log.js.map +1 -1
- package/dist/tools/audit-rollup.d.ts +80 -0
- package/dist/tools/audit-rollup.d.ts.map +1 -0
- package/dist/tools/audit-rollup.js +0 -0
- package/dist/tools/audit-rollup.js.map +1 -0
- package/dist/tools/fetch-credential.d.ts +37 -0
- package/dist/tools/fetch-credential.d.ts.map +1 -0
- package/dist/tools/fetch-credential.js +153 -0
- package/dist/tools/fetch-credential.js.map +1 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/operate-pay.d.ts +4 -4
- package/dist/tools/operate-pay.d.ts.map +1 -1
- package/dist/tools/operate-pay.js +163 -96
- package/dist/tools/operate-pay.js.map +1 -1
- package/dist/tools/provision-drive.d.ts +43 -35
- package/dist/tools/provision-drive.d.ts.map +1 -1
- package/dist/tools/provision-drive.js +268 -164
- package/dist/tools/provision-drive.js.map +1 -1
- package/dist/tools/use-credential.d.ts.map +1 -1
- package/dist/tools/use-credential.js +3 -2
- package/dist/tools/use-credential.js.map +1 -1
- package/package.json +4 -6
- package/dist/bot/operator-direct-identity.d.ts +0 -26
- package/dist/bot/operator-direct-identity.d.ts.map +0 -1
- package/dist/bot/operator-direct-identity.js +0 -120
- package/dist/bot/operator-direct-identity.js.map +0 -1
- package/dist/bot/operator-profile-pool.d.ts +0 -97
- package/dist/bot/operator-profile-pool.d.ts.map +0 -1
- package/dist/bot/operator-profile-pool.js +0 -855
- package/dist/bot/operator-profile-pool.js.map +0 -1
- package/dist/bot/xvfb.d.ts +0 -13
- package/dist/bot/xvfb.d.ts.map +0 -1
- package/dist/bot/xvfb.js +0 -146
- package/dist/bot/xvfb.js.map +0 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// Self-clean stale prior `mcp server` instances at startup.
|
|
2
|
+
//
|
|
3
|
+
// A host agent relaunches `mcp server` on every reconnect but does not
|
|
4
|
+
// reliably terminate the instance it superseded. A live box carried a
|
|
5
|
+
// superseded claude-code server sitting beside its replacement, plus two
|
|
6
|
+
// codex-identity servers orphaned to init for ~31 hours — each keeping a
|
|
7
|
+
// browser/reaper child tree resident. The owner-process reaper next door
|
|
8
|
+
// only reaps a dead owner's CHILDREN; nothing reaped a wedged owner itself.
|
|
9
|
+
// This registry does.
|
|
10
|
+
//
|
|
11
|
+
// The gate is deliberately narrow, because one shared box legitimately runs
|
|
12
|
+
// many concurrent servers — including several of the SAME agent identity,
|
|
13
|
+
// one per project/lane. So there is no name-based or blanket kill anywhere
|
|
14
|
+
// here. A prior instance is a candidate only when all of these hold:
|
|
15
|
+
// * its recorded agent identity EXACTLY matches ours (and ours is set),
|
|
16
|
+
// * it is not us, and its birth identity still names a live process,
|
|
17
|
+
// * and it is either orphaned — its spawning host is gone, i.e. PPid
|
|
18
|
+
// collapsed to init when the instance did not start that way — past a
|
|
19
|
+
// short grace, or quiet past the very bound it should have self-exited
|
|
20
|
+
// on (server.ts's idle backstop, mirrored here).
|
|
21
|
+
// A non-orphan is therefore only reaped after it already failed its own
|
|
22
|
+
// exit policy, and an instance still serving a client is never a candidate.
|
|
23
|
+
import { chmodSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
24
|
+
import { homedir } from "node:os";
|
|
25
|
+
import { join, resolve } from "node:path";
|
|
26
|
+
import { randomUUID } from "node:crypto";
|
|
27
|
+
import { sweepOrphanedOwnerProcesses } from "./bot/owner-process-reaper.js";
|
|
28
|
+
import { processBirthIdentity, processBirthIdentityState, } from "./bot/profile.js";
|
|
29
|
+
import { VERSION } from "./version.js";
|
|
30
|
+
// Idle self-exit bounds. transport.onclose / stdin EOF / SIGTERM already exit
|
|
31
|
+
// the process on a well-behaved disconnect; these bound the case a live box
|
|
32
|
+
// surfaced instead — a host that spawns a *new* server on reconnect without
|
|
33
|
+
// ever closing the old child's stdio or signaling it. They live here rather
|
|
34
|
+
// than in server.ts because the startup reaper enforces the same policy from
|
|
35
|
+
// the outside for an instance that failed to enforce it on itself.
|
|
36
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 20 * 60 * 1_000; // 20m, no open session
|
|
37
|
+
const DEFAULT_IDLE_TIMEOUT_WITH_SESSION_MS = 12 * 60 * 60 * 1_000; // 12h, session open
|
|
38
|
+
const DEFAULT_IDLE_CHECK_INTERVAL_MS = 5 * 60 * 1_000; // 5m — must stay well under the 20m bound
|
|
39
|
+
// An orphan's stdio peer is gone, so a well-behaved instance exits within
|
|
40
|
+
// milliseconds. Still alive and quiet this long past that means wedged.
|
|
41
|
+
const DEFAULT_ORPHAN_GRACE_MS = 60 * 1_000;
|
|
42
|
+
const DEFAULT_HEARTBEAT_INTERVAL_MS = 30 * 1_000;
|
|
43
|
+
const DEFAULT_REAP_GRACE_MS = 2_000;
|
|
44
|
+
function envMs(name, fallback) {
|
|
45
|
+
const raw = process.env[name];
|
|
46
|
+
if (raw === undefined)
|
|
47
|
+
return fallback;
|
|
48
|
+
const parsed = Number(raw);
|
|
49
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
50
|
+
}
|
|
51
|
+
export function idleTimeoutMs() {
|
|
52
|
+
return envMs("TRUSTY_SQUIRE_SERVER_IDLE_TIMEOUT_MS", DEFAULT_IDLE_TIMEOUT_MS);
|
|
53
|
+
}
|
|
54
|
+
export function idleTimeoutWithSessionMs() {
|
|
55
|
+
return envMs("TRUSTY_SQUIRE_SERVER_IDLE_TIMEOUT_WITH_SESSION_MS", DEFAULT_IDLE_TIMEOUT_WITH_SESSION_MS);
|
|
56
|
+
}
|
|
57
|
+
export function idleCheckIntervalMs() {
|
|
58
|
+
return envMs("TRUSTY_SQUIRE_SERVER_IDLE_CHECK_INTERVAL_MS", DEFAULT_IDLE_CHECK_INTERVAL_MS);
|
|
59
|
+
}
|
|
60
|
+
export function heartbeatIntervalMs() {
|
|
61
|
+
return envMs("TRUSTY_SQUIRE_SERVER_HEARTBEAT_INTERVAL_MS", DEFAULT_HEARTBEAT_INTERVAL_MS);
|
|
62
|
+
}
|
|
63
|
+
export function serverReapBounds() {
|
|
64
|
+
return {
|
|
65
|
+
orphanGraceMs: envMs("TRUSTY_SQUIRE_SERVER_REAP_ORPHAN_GRACE_MS", DEFAULT_ORPHAN_GRACE_MS),
|
|
66
|
+
idleMs: idleTimeoutMs(),
|
|
67
|
+
idleWithSessionMs: idleTimeoutWithSessionMs(),
|
|
68
|
+
idleSlackMs: idleCheckIntervalMs(),
|
|
69
|
+
graceMs: envMs("TRUSTY_SQUIRE_SERVER_REAP_GRACE_MS", DEFAULT_REAP_GRACE_MS),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function serverInstanceRootDir() {
|
|
73
|
+
const configured = (process.env.TRUSTY_SQUIRE_SERVER_INSTANCE_DIR ?? "").trim();
|
|
74
|
+
return configured.length > 0
|
|
75
|
+
? resolve(configured)
|
|
76
|
+
: join(homedir(), ".trusty-squire", "server-instances");
|
|
77
|
+
}
|
|
78
|
+
function agentIdentity() {
|
|
79
|
+
return (process.env.TRUSTY_SQUIRE_AGENT_IDENTITY ?? "").trim();
|
|
80
|
+
}
|
|
81
|
+
function ensurePrivateDir(path) {
|
|
82
|
+
mkdirSync(path, { recursive: true, mode: 0o700 });
|
|
83
|
+
chmodSync(path, 0o700);
|
|
84
|
+
}
|
|
85
|
+
function isServerInstanceRecord(value) {
|
|
86
|
+
if (value === null || typeof value !== "object")
|
|
87
|
+
return false;
|
|
88
|
+
const record = value;
|
|
89
|
+
const numbers = [
|
|
90
|
+
record.pid,
|
|
91
|
+
record.parent_pid,
|
|
92
|
+
record.started_at,
|
|
93
|
+
record.heartbeat_at,
|
|
94
|
+
record.last_activity_at,
|
|
95
|
+
record.active_sessions,
|
|
96
|
+
record.in_flight_calls,
|
|
97
|
+
];
|
|
98
|
+
return (record.version === 1 &&
|
|
99
|
+
typeof record.agent_identity === "string" &&
|
|
100
|
+
typeof record.start_time === "string" &&
|
|
101
|
+
typeof record.server_version === "string" &&
|
|
102
|
+
numbers.every((entry) => Number.isSafeInteger(entry)) &&
|
|
103
|
+
(record.pid ?? 0) > 0);
|
|
104
|
+
}
|
|
105
|
+
export function readServerInstanceRecord(path) {
|
|
106
|
+
try {
|
|
107
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
108
|
+
return isServerInstanceRecord(parsed) ? parsed : null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function writeServerInstanceRecord(path, record) {
|
|
115
|
+
const temporary = `${path}.tmp-${randomUUID()}`;
|
|
116
|
+
try {
|
|
117
|
+
writeFileSync(temporary, `${JSON.stringify(record)}\n`, { mode: 0o600, flag: "wx" });
|
|
118
|
+
renameSync(temporary, path);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
rmSync(temporary, { force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** PPid is field 4 of /proc/<pid>/stat — index 1 after the comm close-paren. */
|
|
125
|
+
function linuxParentPid(pid) {
|
|
126
|
+
try {
|
|
127
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
128
|
+
const closeParen = stat.lastIndexOf(")");
|
|
129
|
+
if (closeParen < 0)
|
|
130
|
+
return "unknown";
|
|
131
|
+
const parent = Number(stat
|
|
132
|
+
.slice(closeParen + 2)
|
|
133
|
+
.trim()
|
|
134
|
+
.split(/\s+/)[1]);
|
|
135
|
+
return Number.isSafeInteger(parent) && parent >= 0 ? parent : "unknown";
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
const code = error.code;
|
|
139
|
+
return code === "ENOENT" || code === "ESRCH" ? "stale" : "unknown";
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function linuxProcessIds() {
|
|
143
|
+
try {
|
|
144
|
+
return readdirSync("/proc")
|
|
145
|
+
.filter((entry) => /^\d+$/.test(entry))
|
|
146
|
+
.map(Number);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Descendants by PPid chain — never by process group. A stdio server shares
|
|
154
|
+
* its parent's process group, so `kill(-pgid)` would take the host agent
|
|
155
|
+
* down with it.
|
|
156
|
+
*/
|
|
157
|
+
export function processDescendantIdentities(pid, readers = {}) {
|
|
158
|
+
const readProcessIds = readers.readProcessIds ?? linuxProcessIds;
|
|
159
|
+
const readParentPid = readers.readParentPid ?? linuxParentPid;
|
|
160
|
+
const readBirthIdentity = readers.readBirthIdentity ?? processBirthIdentity;
|
|
161
|
+
const children = new Map();
|
|
162
|
+
for (const candidate of readProcessIds()) {
|
|
163
|
+
if (candidate === pid)
|
|
164
|
+
continue;
|
|
165
|
+
const parent = readParentPid(candidate);
|
|
166
|
+
if (typeof parent !== "number")
|
|
167
|
+
continue;
|
|
168
|
+
const siblings = children.get(parent);
|
|
169
|
+
if (siblings === undefined)
|
|
170
|
+
children.set(parent, [candidate]);
|
|
171
|
+
else
|
|
172
|
+
siblings.push(candidate);
|
|
173
|
+
}
|
|
174
|
+
const seen = new Set([pid]);
|
|
175
|
+
const descendants = [];
|
|
176
|
+
const queue = [pid];
|
|
177
|
+
while (queue.length > 0) {
|
|
178
|
+
for (const child of children.get(queue.shift()) ?? []) {
|
|
179
|
+
if (seen.has(child))
|
|
180
|
+
continue;
|
|
181
|
+
seen.add(child);
|
|
182
|
+
queue.push(child);
|
|
183
|
+
const identity = readBirthIdentity(child);
|
|
184
|
+
if (identity !== null)
|
|
185
|
+
descendants.push(identity);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return descendants;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The whole safety contract, as one pure function. `forget` means the record
|
|
192
|
+
* names no live process — delete the file, signal nothing.
|
|
193
|
+
*/
|
|
194
|
+
export function serverInstanceReapDecision(record, self, liveness, parentPid, now, bounds) {
|
|
195
|
+
if (record.pid === self.pid)
|
|
196
|
+
return "keep";
|
|
197
|
+
// A record naming a process that is already gone is file GC, not a kill —
|
|
198
|
+
// safe for any identity, and the only thing that keeps the directory from
|
|
199
|
+
// growing for an identity that never launches again.
|
|
200
|
+
if (liveness === "stale" || parentPid === "stale")
|
|
201
|
+
return "forget";
|
|
202
|
+
// Guard rail: identity is the outer fence on SIGNALLING. An unset identity
|
|
203
|
+
// matches nothing, so a host that never set one is never a target.
|
|
204
|
+
if (self.agent_identity.length === 0)
|
|
205
|
+
return "keep";
|
|
206
|
+
if (record.agent_identity !== self.agent_identity)
|
|
207
|
+
return "keep";
|
|
208
|
+
// A pid we cannot read is a pid we do not kill.
|
|
209
|
+
if (liveness === "unknown" || parentPid === "unknown")
|
|
210
|
+
return "keep";
|
|
211
|
+
const quietMs = now - record.last_activity_at;
|
|
212
|
+
// Its spawning host is gone, so no client can still be attached over the
|
|
213
|
+
// stdio pipe it was handed. A host that was ALREADY init at registration
|
|
214
|
+
// (container PID 1) never reads as orphaned.
|
|
215
|
+
const orphaned = record.parent_pid !== 1 && parentPid === 1;
|
|
216
|
+
if (orphaned)
|
|
217
|
+
return quietMs >= bounds.orphanGraceMs ? "reap" : "keep";
|
|
218
|
+
// Not orphaned: mirror the instance's own idle bound, so we only ever reap
|
|
219
|
+
// one that already blew past the deadline it should have exited on itself.
|
|
220
|
+
// The slack is that bound's poll interval — an instance whose own idle timer
|
|
221
|
+
// is working exits on its next poll, so anything still here past bound +
|
|
222
|
+
// interval demonstrably failed to.
|
|
223
|
+
const busy = record.active_sessions > 0 || record.in_flight_calls > 0;
|
|
224
|
+
const threshold = (busy ? bounds.idleWithSessionMs : bounds.idleMs) + bounds.idleSlackMs;
|
|
225
|
+
return quietMs >= threshold ? "reap" : "keep";
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Publish this instance's heartbeat so a later launch of the same identity can
|
|
229
|
+
* tell "still serving a client" from "wedged". Returns null when there is
|
|
230
|
+
* nothing to publish (non-Linux, no agent identity, unreadable birth identity).
|
|
231
|
+
*/
|
|
232
|
+
export function registerServerInstance(options = {}) {
|
|
233
|
+
if (process.platform !== "linux")
|
|
234
|
+
return null;
|
|
235
|
+
const identity = options.identity ?? agentIdentity();
|
|
236
|
+
if (identity.length === 0)
|
|
237
|
+
return null;
|
|
238
|
+
const birth = processBirthIdentity(process.pid);
|
|
239
|
+
if (birth === null)
|
|
240
|
+
return null;
|
|
241
|
+
const parent = linuxParentPid(process.pid);
|
|
242
|
+
const now = options.now ?? Date.now;
|
|
243
|
+
const rootDir = resolve(options.rootDir ?? serverInstanceRootDir());
|
|
244
|
+
const startedAt = now();
|
|
245
|
+
let record = {
|
|
246
|
+
version: 1,
|
|
247
|
+
agent_identity: identity,
|
|
248
|
+
pid: birth.pid,
|
|
249
|
+
start_time: birth.start_time,
|
|
250
|
+
parent_pid: typeof parent === "number" ? parent : 0,
|
|
251
|
+
started_at: startedAt,
|
|
252
|
+
heartbeat_at: startedAt,
|
|
253
|
+
last_activity_at: startedAt,
|
|
254
|
+
active_sessions: 0,
|
|
255
|
+
in_flight_calls: 0,
|
|
256
|
+
server_version: VERSION,
|
|
257
|
+
};
|
|
258
|
+
const path = join(rootDir, `${birth.pid}-${randomUUID()}.json`);
|
|
259
|
+
try {
|
|
260
|
+
ensurePrivateDir(rootDir);
|
|
261
|
+
writeServerInstanceRecord(path, record);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
let released = false;
|
|
267
|
+
return {
|
|
268
|
+
path,
|
|
269
|
+
heartbeat: (activity) => {
|
|
270
|
+
if (released)
|
|
271
|
+
return;
|
|
272
|
+
record = {
|
|
273
|
+
...record,
|
|
274
|
+
heartbeat_at: now(),
|
|
275
|
+
last_activity_at: activity.lastActivityAt,
|
|
276
|
+
active_sessions: activity.activeSessions,
|
|
277
|
+
in_flight_calls: activity.inFlightCalls,
|
|
278
|
+
};
|
|
279
|
+
try {
|
|
280
|
+
writeServerInstanceRecord(path, record);
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// A heartbeat that cannot be written only costs this instance its
|
|
284
|
+
// protection from a later launch; it must never break serving.
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
release: () => {
|
|
288
|
+
released = true;
|
|
289
|
+
rmSync(path, { force: true });
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
async function terminateServerInstanceTree(record, bounds, runtime) {
|
|
294
|
+
const readBirthState = runtime.readBirthState ?? processBirthIdentityState;
|
|
295
|
+
const readDescendants = runtime.readDescendants ?? ((pid) => processDescendantIdentities(pid));
|
|
296
|
+
const kill = runtime.kill ?? ((pid, signal) => process.kill(pid, signal));
|
|
297
|
+
const wait = runtime.wait ??
|
|
298
|
+
(async (ms) => await new Promise((done) => setTimeout(done, ms).unref()));
|
|
299
|
+
// Snapshot the tree BEFORE signalling: once the owner dies its children are
|
|
300
|
+
// re-parented to init and the PPid chain that identifies them is gone. Each
|
|
301
|
+
// entry carries a birth identity so a pid recycled during the grace window
|
|
302
|
+
// is not escalated to SIGKILL by mistake.
|
|
303
|
+
const tree = [
|
|
304
|
+
{ pid: record.pid, start_time: record.start_time },
|
|
305
|
+
...readDescendants(record.pid).filter((entry) => entry.pid !== process.pid),
|
|
306
|
+
];
|
|
307
|
+
const signalled = [];
|
|
308
|
+
const signal = (signalName) => {
|
|
309
|
+
const alive = [];
|
|
310
|
+
for (const identity of tree) {
|
|
311
|
+
if (readBirthState(identity) !== "matching")
|
|
312
|
+
continue;
|
|
313
|
+
alive.push(identity);
|
|
314
|
+
try {
|
|
315
|
+
kill(identity.pid, signalName);
|
|
316
|
+
if (!signalled.includes(identity.pid))
|
|
317
|
+
signalled.push(identity.pid);
|
|
318
|
+
}
|
|
319
|
+
catch { }
|
|
320
|
+
}
|
|
321
|
+
return alive;
|
|
322
|
+
};
|
|
323
|
+
signal("SIGTERM");
|
|
324
|
+
await wait(bounds.graceMs);
|
|
325
|
+
if (signal("SIGKILL").length > 0)
|
|
326
|
+
await wait(bounds.graceMs);
|
|
327
|
+
return signalled;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Reap stale prior instances of OUR agent identity. Never throws: a startup
|
|
331
|
+
* housekeeping pass must not be able to stop the server from serving.
|
|
332
|
+
*/
|
|
333
|
+
export async function reapStaleServerInstances(runtime = {}) {
|
|
334
|
+
const summary = { reaped: 0, forgotten: 0, kept: 0, signalled: [] };
|
|
335
|
+
if (process.platform !== "linux" && runtime.self === undefined)
|
|
336
|
+
return summary;
|
|
337
|
+
const birth = processBirthIdentity(process.pid);
|
|
338
|
+
const self = runtime.self ?? {
|
|
339
|
+
agent_identity: agentIdentity(),
|
|
340
|
+
pid: process.pid,
|
|
341
|
+
start_time: birth?.start_time ?? "unknown",
|
|
342
|
+
};
|
|
343
|
+
if (self.agent_identity.length === 0)
|
|
344
|
+
return summary;
|
|
345
|
+
const rootDir = resolve(runtime.rootDir ?? serverInstanceRootDir());
|
|
346
|
+
const bounds = runtime.bounds ?? serverReapBounds();
|
|
347
|
+
const now = (runtime.now ?? Date.now)();
|
|
348
|
+
const readBirthState = runtime.readBirthState ?? processBirthIdentityState;
|
|
349
|
+
const readParentPid = runtime.readParentPid ?? linuxParentPid;
|
|
350
|
+
let entries;
|
|
351
|
+
try {
|
|
352
|
+
entries = readdirSync(rootDir).filter((entry) => entry.endsWith(".json"));
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return summary;
|
|
356
|
+
}
|
|
357
|
+
for (const entry of entries) {
|
|
358
|
+
const path = join(rootDir, entry);
|
|
359
|
+
const record = readServerInstanceRecord(path);
|
|
360
|
+
if (record === null)
|
|
361
|
+
continue;
|
|
362
|
+
const decision = serverInstanceReapDecision(record, self, readBirthState(record), readParentPid(record.pid), now, bounds);
|
|
363
|
+
if (decision === "keep") {
|
|
364
|
+
summary.kept += 1;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (decision === "forget") {
|
|
368
|
+
summary.forgotten += 1;
|
|
369
|
+
rmSync(path, { force: true });
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
summary.signalled.push(...(await terminateServerInstanceTree(record, bounds, runtime)));
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
summary.reaped += 1;
|
|
379
|
+
if (readBirthState(record) === "stale")
|
|
380
|
+
rmSync(path, { force: true });
|
|
381
|
+
process.stderr.write(`[trusty-squire] reaped stale prior server pid=${record.pid} ` +
|
|
382
|
+
`identity=${record.agent_identity} v${record.server_version}\n`);
|
|
383
|
+
}
|
|
384
|
+
if (summary.reaped > 0) {
|
|
385
|
+
// Their owner-reaper manifests now name a dead owner, so the existing
|
|
386
|
+
// sweep collects any browser the tree walk missed (already re-parented
|
|
387
|
+
// to init before the snapshot).
|
|
388
|
+
await (runtime.sweep ?? sweepOrphanedOwnerProcesses)().catch(() => 0);
|
|
389
|
+
}
|
|
390
|
+
return summary;
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=server-instance-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-instance-registry.js","sourceRoot":"","sources":["../src/server-instance-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
2
|
import { ApiClient } from "./api-client.js";
|
|
3
|
+
import { type SessionGuard } from "./session-guard.js";
|
|
3
4
|
export declare function shouldIdleExit(now: number, lastActivityAt: number, sessionCount: number, timeoutMs: number, timeoutWithSessionMs: number): boolean;
|
|
4
|
-
export declare
|
|
5
|
+
export declare const SERVER_INSTRUCTIONS = "This is Trusty Squire \u2014 it drives a real browser through signup, provisioning,\nand checkout flows on the user's behalf (`operate_start`/`operate_observe`/\n`operate_act`/`operate_pay`/`operate_finish`, plus recipe replay), and backs it\nwith a write-only credential vault.\nThe user's secrets (API keys, tokens, passwords) live in the vault encrypted;\nthey are NOT in the conversation context. Reading one back is possible but\ncostly \u2014 see fetch_credential below.\nRouting rules for THIS server's vault tools:\n\n- User pastes a secret-shaped value (sk-\u2026, ghp_\u2026, AKIA\u2026, eyJ\u2026) into chat\n \u2192 call store_credential AUTOMATICALLY; don't ask permission.\n- User refers to a saved credential by name or service ('my OpenAI key',\n 'the Stripe token') \u2192 call list_credentials to resolve the reference.\n- User wants an authenticated API call \u2192 call use_credential with the\n service/reference + the HTTP request, using ${SECRET} (single-field)\n or ${SECRET.<field>} (multi-field) placeholders. The server injects\n the secret and returns only the upstream response; you never see the\n value. The target host must be on the credential's allowed_hosts.\n- User wants to change allowed_hosts/login_hosts/name without changing the\n secret \u2192 call edit_credential. User wants a saved credential removed \u2192 call\n delete_credential. Both return a Telegram/passkey approval link first; resume\n with the returned approval_id only after the user signs the exact mutation.\n- Rotating a secret value = call store_credential again with the new value (it\n overwrites). edit_credential cannot read or change secret fields.\n- The raw value reaches you ONLY via fetch_credential, and only after the\n user signs a passkey approval. It then lives in your transcript forever,\n so use it only when the plaintext must land somewhere you control (a\n GitHub Actions secret, a .env, a config file) with no server-side\n injection path. For calling an API, use_credential is always the answer.";
|
|
6
|
+
export interface ServerCallLifecycle {
|
|
7
|
+
started(): boolean;
|
|
8
|
+
finished(): void;
|
|
9
|
+
}
|
|
10
|
+
export interface ServerCallAdmission extends ServerCallLifecycle {
|
|
11
|
+
closeAndDrain(): Promise<void>;
|
|
12
|
+
inFlightCount(): number;
|
|
13
|
+
}
|
|
14
|
+
export type AccountSessionLoader = () => Promise<ApiClient | null>;
|
|
15
|
+
export declare function createServerCallAdmission(): ServerCallAdmission;
|
|
16
|
+
export declare function buildServer(api: ApiClient | null, callLifecycle?: ServerCallLifecycle, loadPublishedAccountSession?: AccountSessionLoader, sessionGuard?: SessionGuard): Promise<Server>;
|
|
17
|
+
/** Compact V2 is a model wire protocol; indentation adds no information. */
|
|
18
|
+
export declare function compactToolResultText(result: unknown): string;
|
|
5
19
|
export declare function installServerProcessGuards(): void;
|
|
6
20
|
export declare function runServer(): Promise<void>;
|
|
7
21
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAkB5C,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA+BhG,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAGT;AAKD,eAAO,MAAM,mBAAmB,8/DA4B2C,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,OAAO,CAAC;IACnB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,aAAa,IAAI,MAAM,CAAC;CACzB;AAMD,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;AAEnE,wBAAgB,yBAAyB,IAAI,mBAAmB,CA4B/D;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,GAAG,IAAI,EACrB,aAAa,CAAC,EAAE,mBAAmB,EACnC,2BAA2B,CAAC,EAAE,oBAAoB,EAClD,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,CA+GjB;AAiCD,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAU7D;AA0BD,wBAAgB,0BAA0B,IAAI,IAAI,CAajD;AAID,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAmK/C"}
|