@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.
Files changed (162) hide show
  1. package/README.md +139 -62
  2. package/assets/login/vnc-input.js +9 -0
  3. package/assets/login/vnc.html +214 -202
  4. package/assets/screencaps/connect-walkthrough.png +0 -0
  5. package/assets/screencaps/connect-walkthrough.svg +1 -1
  6. package/dist/api-client.d.ts +26 -3
  7. package/dist/api-client.d.ts.map +1 -1
  8. package/dist/api-client.js +19 -31
  9. package/dist/api-client.js.map +1 -1
  10. package/dist/bin.js +2 -3
  11. package/dist/bin.js.map +1 -1
  12. package/dist/bot/browser.d.ts +134 -77
  13. package/dist/bot/browser.d.ts.map +1 -1
  14. package/dist/bot/browser.js +1788 -1543
  15. package/dist/bot/browser.js.map +1 -1
  16. package/dist/bot/compact-observation-v2.d.ts +167 -0
  17. package/dist/bot/compact-observation-v2.d.ts.map +1 -0
  18. package/dist/bot/compact-observation-v2.js +1038 -0
  19. package/dist/bot/compact-observation-v2.js.map +1 -0
  20. package/dist/bot/credential-shape.d.ts +2 -0
  21. package/dist/bot/credential-shape.d.ts.map +1 -1
  22. package/dist/bot/credential-shape.js +21 -8
  23. package/dist/bot/credential-shape.js.map +1 -1
  24. package/dist/bot/element-fingerprint.d.ts +9 -0
  25. package/dist/bot/element-fingerprint.d.ts.map +1 -0
  26. package/dist/bot/element-fingerprint.js +147 -0
  27. package/dist/bot/element-fingerprint.js.map +1 -0
  28. package/dist/bot/email-verification.d.ts +7 -1
  29. package/dist/bot/email-verification.d.ts.map +1 -1
  30. package/dist/bot/email-verification.js +48 -14
  31. package/dist/bot/email-verification.js.map +1 -1
  32. package/dist/bot/google-login.d.ts +28 -52
  33. package/dist/bot/google-login.d.ts.map +1 -1
  34. package/dist/bot/google-login.js +246 -1119
  35. package/dist/bot/google-login.js.map +1 -1
  36. package/dist/bot/install-completion.d.ts +1 -2
  37. package/dist/bot/install-completion.d.ts.map +1 -1
  38. package/dist/bot/install-completion.js +1 -2
  39. package/dist/bot/install-completion.js.map +1 -1
  40. package/dist/bot/login-state.d.ts +13 -7
  41. package/dist/bot/login-state.d.ts.map +1 -1
  42. package/dist/bot/login-state.js +50 -114
  43. package/dist/bot/login-state.js.map +1 -1
  44. package/dist/bot/oauth-providers.d.ts +1 -1
  45. package/dist/bot/oauth-providers.d.ts.map +1 -1
  46. package/dist/bot/oauth-providers.js +3 -3
  47. package/dist/bot/oauth-providers.js.map +1 -1
  48. package/dist/bot/oauth-scope.d.ts +4 -0
  49. package/dist/bot/oauth-scope.d.ts.map +1 -0
  50. package/dist/bot/oauth-scope.js +58 -0
  51. package/dist/bot/oauth-scope.js.map +1 -0
  52. package/dist/bot/operator-browser-watchdog.d.ts +127 -0
  53. package/dist/bot/operator-browser-watchdog.d.ts.map +1 -0
  54. package/dist/bot/operator-browser-watchdog.js +438 -0
  55. package/dist/bot/operator-browser-watchdog.js.map +1 -0
  56. package/dist/bot/owner-process-reaper-worker.d.ts +2 -0
  57. package/dist/bot/owner-process-reaper-worker.d.ts.map +1 -0
  58. package/dist/bot/owner-process-reaper-worker.js +17 -0
  59. package/dist/bot/owner-process-reaper-worker.js.map +1 -0
  60. package/dist/bot/owner-process-reaper.d.ts +103 -0
  61. package/dist/bot/owner-process-reaper.d.ts.map +1 -0
  62. package/dist/bot/owner-process-reaper.js +1058 -0
  63. package/dist/bot/owner-process-reaper.js.map +1 -0
  64. package/dist/bot/pay-operator.d.ts +13 -2
  65. package/dist/bot/pay-operator.d.ts.map +1 -1
  66. package/dist/bot/pay-operator.js +319 -123
  67. package/dist/bot/pay-operator.js.map +1 -1
  68. package/dist/bot/profile.d.ts +10 -1
  69. package/dist/bot/profile.d.ts.map +1 -1
  70. package/dist/bot/profile.js +137 -11
  71. package/dist/bot/profile.js.map +1 -1
  72. package/dist/bot/promote-to-skill.js +1 -1
  73. package/dist/bot/promote-to-skill.js.map +1 -1
  74. package/dist/bot/provision-session.d.ts +60 -164
  75. package/dist/bot/provision-session.d.ts.map +1 -1
  76. package/dist/bot/provision-session.js +2049 -1546
  77. package/dist/bot/provision-session.js.map +1 -1
  78. package/dist/bot/remote-login-display.d.ts +61 -0
  79. package/dist/bot/remote-login-display.d.ts.map +1 -0
  80. package/dist/bot/remote-login-display.js +765 -0
  81. package/dist/bot/remote-login-display.js.map +1 -0
  82. package/dist/bot/session/hosts.d.ts +8 -0
  83. package/dist/bot/session/hosts.d.ts.map +1 -0
  84. package/dist/bot/session/hosts.js +36 -0
  85. package/dist/bot/session/hosts.js.map +1 -0
  86. package/dist/bot/session/lifecycle.d.ts +56 -0
  87. package/dist/bot/session/lifecycle.d.ts.map +1 -0
  88. package/dist/bot/session/lifecycle.js +962 -0
  89. package/dist/bot/session/lifecycle.js.map +1 -0
  90. package/dist/bot/session/model.d.ts +175 -0
  91. package/dist/bot/session/model.d.ts.map +1 -0
  92. package/dist/bot/session/model.js +77 -0
  93. package/dist/bot/session/model.js.map +1 -0
  94. package/dist/install/cli.d.ts +29 -9
  95. package/dist/install/cli.d.ts.map +1 -1
  96. package/dist/install/cli.js +243 -322
  97. package/dist/install/cli.js.map +1 -1
  98. package/dist/install/interactive.d.ts +1 -0
  99. package/dist/install/interactive.d.ts.map +1 -1
  100. package/dist/install/interactive.js +19 -5
  101. package/dist/install/interactive.js.map +1 -1
  102. package/dist/install/ui.d.ts.map +1 -1
  103. package/dist/install/ui.js +3 -15
  104. package/dist/install/ui.js.map +1 -1
  105. package/dist/operator-env.js +1 -1
  106. package/dist/operator-env.js.map +1 -1
  107. package/dist/server-instance-registry.d.ts +103 -0
  108. package/dist/server-instance-registry.d.ts.map +1 -0
  109. package/dist/server-instance-registry.js +392 -0
  110. package/dist/server-instance-registry.js.map +1 -0
  111. package/dist/server.d.ts +15 -1
  112. package/dist/server.d.ts.map +1 -1
  113. package/dist/server.js +164 -62
  114. package/dist/server.js.map +1 -1
  115. package/dist/session-guard.d.ts +28 -0
  116. package/dist/session-guard.d.ts.map +1 -0
  117. package/dist/session-guard.js +84 -0
  118. package/dist/session-guard.js.map +1 -0
  119. package/dist/session.d.ts +57 -13
  120. package/dist/session.d.ts.map +1 -1
  121. package/dist/session.js +246 -127
  122. package/dist/session.js.map +1 -1
  123. package/dist/tools/audit-log.d.ts +16 -2
  124. package/dist/tools/audit-log.d.ts.map +1 -1
  125. package/dist/tools/audit-log.js +223 -13
  126. package/dist/tools/audit-log.js.map +1 -1
  127. package/dist/tools/audit-rollup.d.ts +80 -0
  128. package/dist/tools/audit-rollup.d.ts.map +1 -0
  129. package/dist/tools/audit-rollup.js +0 -0
  130. package/dist/tools/audit-rollup.js.map +1 -0
  131. package/dist/tools/fetch-credential.d.ts +37 -0
  132. package/dist/tools/fetch-credential.d.ts.map +1 -0
  133. package/dist/tools/fetch-credential.js +153 -0
  134. package/dist/tools/fetch-credential.js.map +1 -0
  135. package/dist/tools/index.d.ts +3 -1
  136. package/dist/tools/index.d.ts.map +1 -1
  137. package/dist/tools/index.js +7 -3
  138. package/dist/tools/index.js.map +1 -1
  139. package/dist/tools/operate-pay.d.ts +4 -4
  140. package/dist/tools/operate-pay.d.ts.map +1 -1
  141. package/dist/tools/operate-pay.js +163 -96
  142. package/dist/tools/operate-pay.js.map +1 -1
  143. package/dist/tools/provision-drive.d.ts +43 -35
  144. package/dist/tools/provision-drive.d.ts.map +1 -1
  145. package/dist/tools/provision-drive.js +268 -164
  146. package/dist/tools/provision-drive.js.map +1 -1
  147. package/dist/tools/use-credential.d.ts.map +1 -1
  148. package/dist/tools/use-credential.js +3 -2
  149. package/dist/tools/use-credential.js.map +1 -1
  150. package/package.json +4 -6
  151. package/dist/bot/operator-direct-identity.d.ts +0 -26
  152. package/dist/bot/operator-direct-identity.d.ts.map +0 -1
  153. package/dist/bot/operator-direct-identity.js +0 -120
  154. package/dist/bot/operator-direct-identity.js.map +0 -1
  155. package/dist/bot/operator-profile-pool.d.ts +0 -97
  156. package/dist/bot/operator-profile-pool.d.ts.map +0 -1
  157. package/dist/bot/operator-profile-pool.js +0 -855
  158. package/dist/bot/operator-profile-pool.js.map +0 -1
  159. package/dist/bot/xvfb.d.ts +0 -13
  160. package/dist/bot/xvfb.d.ts.map +0 -1
  161. package/dist/bot/xvfb.js +0 -146
  162. 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 function buildServer(api: ApiClient | null): Promise<Server>;
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
@@ -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;AAmE5C,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;AAgCD,wBAAsB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAwFxE;AAyDD,wBAAgB,0BAA0B,IAAI,IAAI,CAajD;AAID,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAgH/C"}
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"}