@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,58 @@
1
+ const BASIC_OAUTH_SCOPES = new Set([
2
+ "openid",
3
+ "email",
4
+ "profile",
5
+ "https://www.googleapis.com/auth/userinfo.email",
6
+ "https://www.googleapis.com/auth/userinfo.profile",
7
+ ]);
8
+ export function extractOAuthScopes(rawUrl) {
9
+ const scopes = [];
10
+ const visit = (urlStr, depth) => {
11
+ if (scopes.length > 0 || depth > 8)
12
+ return;
13
+ let url;
14
+ try {
15
+ url = new URL(urlStr);
16
+ }
17
+ catch {
18
+ return;
19
+ }
20
+ const scope = url.searchParams.get("scope");
21
+ if (scope !== null && scope.trim().length > 0) {
22
+ for (const value of scope.split(/[\s,+]+/)) {
23
+ const trimmed = value.trim();
24
+ if (trimmed.length > 0)
25
+ scopes.push(trimmed);
26
+ }
27
+ return;
28
+ }
29
+ for (const value of url.searchParams.values()) {
30
+ if (/^https?:\/\//i.test(value.trim()))
31
+ visit(value, depth + 1);
32
+ }
33
+ };
34
+ visit(rawUrl, 0);
35
+ return scopes.length > 0 ? scopes : null;
36
+ }
37
+ export function scopesAreBasic(scopes) {
38
+ return scopes.length > 0 && scopes.every((scope) => BASIC_OAUTH_SCOPES.has(scope));
39
+ }
40
+ export function scrapeGoogleScopePhrases(text) {
41
+ const patterns = [
42
+ /see\s+(?:and\s+download|and\s+manage)\s+[^.\n]+/gi,
43
+ /manage\s+(?:your|all|all\s+your)\s+(?:contacts|google\s+drive|photos|calendars?|tasks|mail|gmail|files|account|youtube)[^.\n]*/gi,
44
+ /edit\s+(?:your|all)\s+(?:contacts|google\s+drive|photos|calendars?|tasks|mail|gmail|files)[^.\n]*/gi,
45
+ /send\s+(?:email|mail|messages)\s+(?:on\s+your\s+behalf|as\s+you)[^.\n]*/gi,
46
+ /view\s+(?:your|all|all\s+your)\s+(?:contacts|google\s+drive|photos|calendars?|tasks|mail|gmail|files|youtube|location\s+history)[^.\n]*/gi,
47
+ /access\s+your\s+(?:google\s+drive|gmail|contacts|calendars?|photos|youtube)[^.\n]*/gi,
48
+ /delete\s+(?:your|all)\s+[^.\n]+/gi,
49
+ ];
50
+ const matches = new Set();
51
+ for (const pattern of patterns) {
52
+ for (const match of text.matchAll(pattern)) {
53
+ matches.add(match[0].slice(0, 80).trim());
54
+ }
55
+ }
56
+ return Array.from(matches);
57
+ }
58
+ //# sourceMappingURL=oauth-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-scope.js","sourceRoot":"","sources":["../../src/bot/oauth-scope.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IACtD,QAAQ;IACR,OAAO;IACP,SAAS;IACT,gDAAgD;IAChD,kDAAkD;CACnD,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,CAAC,MAAc,EAAE,KAAa,EAAQ,EAAE;QACpD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO;QAC3C,IAAI,GAAQ,CAAC;QACb,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;oBAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO;QACT,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAAE,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAyB;IACtD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,MAAM,QAAQ,GAAa;QACzB,mDAAmD;QACnD,kIAAkI;QAClI,qGAAqG;QACrG,2EAA2E;QAC3E,2IAA2I;QAC3I,sFAAsF;QACtF,mCAAmC;KACpC,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,127 @@
1
+ export declare const DEFAULT_OPERATOR_SESSION_IDLE_TIMEOUT_MS: number;
2
+ export declare const DEFAULT_OPERATOR_BROWSER_MAX_LIFETIME_MS: number;
3
+ export declare const DEFAULT_OPERATOR_BROWSER_WATCHDOG_INTERVAL_MS = 5000;
4
+ export declare const DEFAULT_OPERATOR_BROWSER_CPU_CEILING_PERCENT = 200;
5
+ export declare const DEFAULT_OPERATOR_BROWSER_CPU_CONSECUTIVE_SAMPLES = 3;
6
+ export declare const LINUX_PROCESS_TICKS_PER_SECOND = 100;
7
+ export declare const OPERATOR_BROWSER_MARKER_ENV = "TRUSTY_SQUIRE_OPERATOR_BROWSER_MARKER";
8
+ export interface ProcessCpuRecord {
9
+ pid: number;
10
+ parentPid: number;
11
+ cpuTicks: number;
12
+ }
13
+ export interface OperatorBrowserProcessRecord extends ProcessCpuRecord {
14
+ startTime: number;
15
+ marker: string;
16
+ }
17
+ export interface CpuSample {
18
+ at: number;
19
+ ticks: number;
20
+ }
21
+ export type OperatorBrowserWatchdogReason = {
22
+ kind: "idle_timeout";
23
+ idle_ms: number;
24
+ timeout_ms: number;
25
+ } | {
26
+ kind: "max_lifetime";
27
+ lifetime_ms: number;
28
+ timeout_ms: number;
29
+ } | {
30
+ kind: "cpu_budget_exceeded";
31
+ cpu_percent: number;
32
+ ceiling_percent: number;
33
+ consecutive_samples: number;
34
+ };
35
+ export interface OperatorBrowserWatchdogOptions {
36
+ startedAt: number;
37
+ lastActivityAt: () => number;
38
+ hasActiveCall: () => boolean;
39
+ processMarker: () => string | null;
40
+ onTerminate: (reason: OperatorBrowserWatchdogReason) => boolean | void | Promise<boolean | void>;
41
+ now?: () => number;
42
+ idleTimeoutMs?: number;
43
+ maxLifetimeMs?: number;
44
+ intervalMs?: number;
45
+ registerProcessWatchdog?: (marker: string, onTerminate: (reason: OperatorBrowserWatchdogReason) => boolean | void | Promise<boolean | void>) => () => void;
46
+ }
47
+ export interface OperatorBrowserProcessWatchdogOptions {
48
+ readProcesses?: () => OperatorBrowserProcessRecord[];
49
+ processMatches?: (pid: number, startTime: number, marker: string) => boolean;
50
+ kill?: (pid: number, signal: NodeJS.Signals) => unknown;
51
+ onTerminate?: (marker: string, reason: OperatorBrowserWatchdogReason) => boolean | void | Promise<boolean | void>;
52
+ now?: () => number;
53
+ intervalMs?: number;
54
+ maxLifetimeMs?: number;
55
+ cpuCeilingPercent?: number;
56
+ cpuConsecutiveSamples?: number;
57
+ ticksPerSecond?: number;
58
+ }
59
+ export declare function operatorBrowserWatchdogConfig(): {
60
+ idleTimeoutMs: number;
61
+ maxLifetimeMs: number;
62
+ intervalMs: number;
63
+ cpuCeilingPercent: number;
64
+ cpuConsecutiveSamples: number;
65
+ };
66
+ export declare function createOperatorBrowserMarker(startedAt?: number, nonce?: string): string;
67
+ export declare function operatorBrowserMarkerStartedAt(marker: string): number | null;
68
+ export declare function processTreeCpuTicks(rootPid: number, processes: readonly ProcessCpuRecord[]): number | null;
69
+ export declare function cpuPercentBetween(previous: CpuSample, current: CpuSample, ticksPerSecond?: number): number | null;
70
+ export declare function isOperatorChromiumCommand(command: string): boolean;
71
+ export type OperatorBrowserProcessCommandState = "matching" | "stale" | "unknown";
72
+ export declare function operatorBrowserProcessCommandState(pid: number, readers?: {
73
+ readCommand?: (pid: number) => string;
74
+ readExecutable?: (pid: number) => string;
75
+ }): OperatorBrowserProcessCommandState;
76
+ export type OperatorBrowserProcessMarkerState = {
77
+ state: "present";
78
+ marker: string;
79
+ } | {
80
+ state: "missing" | "unknown";
81
+ };
82
+ export declare function operatorBrowserProcessMarkerState(pid: number, readEnvironment?: (pid: number) => string): OperatorBrowserProcessMarkerState;
83
+ export declare function operatorBrowserProcessMarker(pid: number): string | null;
84
+ export declare function operatorBrowserProcessMatchesMarker(pid: number, marker: string): boolean;
85
+ export declare function linuxOperatorBrowserProcesses(): OperatorBrowserProcessRecord[];
86
+ export declare class OperatorBrowserProcessWatchdog {
87
+ private readonly options;
88
+ private readonly readProcesses;
89
+ private readonly processMatches;
90
+ private readonly kill;
91
+ private readonly now;
92
+ private readonly intervalMs;
93
+ private readonly maxLifetimeMs;
94
+ private readonly cpuCeilingPercent;
95
+ private readonly cpuConsecutiveSamples;
96
+ private readonly ticksPerSecond;
97
+ private readonly samples;
98
+ private readonly terminating;
99
+ private timer;
100
+ constructor(options?: OperatorBrowserProcessWatchdogOptions);
101
+ start(): void;
102
+ stop(): void;
103
+ check(now?: number): Promise<OperatorBrowserWatchdogReason[]>;
104
+ private terminate;
105
+ }
106
+ export declare function dispatchOperatorBrowserProcessTermination(marker: string, reason: OperatorBrowserWatchdogReason): Promise<boolean>;
107
+ export declare function startGlobalOperatorBrowserProcessWatchdog(): void;
108
+ export declare function registerOperatorBrowserProcessWatchdog(marker: string, onTerminate: (reason: OperatorBrowserWatchdogReason) => boolean | void | Promise<boolean | void>): () => void;
109
+ export declare class OperatorBrowserWatchdog {
110
+ private readonly options;
111
+ private readonly now;
112
+ private readonly idleTimeoutMs;
113
+ private readonly intervalMs;
114
+ private timer;
115
+ private unregisterProcessWatchdog;
116
+ private terminated;
117
+ private terminationPromise;
118
+ constructor(options: OperatorBrowserWatchdogOptions);
119
+ start(): void;
120
+ stop(): void;
121
+ dispose(): void;
122
+ check(now?: number): OperatorBrowserWatchdogReason | null;
123
+ private terminate;
124
+ private terminateAndWait;
125
+ private beginTermination;
126
+ }
127
+ //# sourceMappingURL=operator-browser-watchdog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operator-browser-watchdog.d.ts","sourceRoot":"","sources":["../../src/bot/operator-browser-watchdog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,438 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readdirSync, readFileSync, readlinkSync } from "node:fs";
3
+ export const DEFAULT_OPERATOR_SESSION_IDLE_TIMEOUT_MS = 60 * 60 * 1_000;
4
+ export const DEFAULT_OPERATOR_BROWSER_MAX_LIFETIME_MS = 30 * 60 * 1_000;
5
+ export const DEFAULT_OPERATOR_BROWSER_WATCHDOG_INTERVAL_MS = 5_000;
6
+ export const DEFAULT_OPERATOR_BROWSER_CPU_CEILING_PERCENT = 200;
7
+ export const DEFAULT_OPERATOR_BROWSER_CPU_CONSECUTIVE_SAMPLES = 3;
8
+ export const LINUX_PROCESS_TICKS_PER_SECOND = 100;
9
+ export const OPERATOR_BROWSER_MARKER_ENV = "TRUSTY_SQUIRE_OPERATOR_BROWSER_MARKER";
10
+ function positiveEnvNumber(name, fallback) {
11
+ const parsed = Number(process.env[name]);
12
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
13
+ }
14
+ export function operatorBrowserWatchdogConfig() {
15
+ return {
16
+ idleTimeoutMs: positiveEnvNumber("TRUSTY_SQUIRE_SESSION_IDLE_TIMEOUT_MS", DEFAULT_OPERATOR_SESSION_IDLE_TIMEOUT_MS),
17
+ maxLifetimeMs: positiveEnvNumber("TRUSTY_SQUIRE_OPERATOR_BROWSER_MAX_LIFETIME_MS", DEFAULT_OPERATOR_BROWSER_MAX_LIFETIME_MS),
18
+ intervalMs: positiveEnvNumber("TRUSTY_SQUIRE_OPERATOR_BROWSER_WATCHDOG_INTERVAL_MS", DEFAULT_OPERATOR_BROWSER_WATCHDOG_INTERVAL_MS),
19
+ cpuCeilingPercent: positiveEnvNumber("TRUSTY_SQUIRE_OPERATOR_BROWSER_CPU_CEILING_PERCENT", DEFAULT_OPERATOR_BROWSER_CPU_CEILING_PERCENT),
20
+ cpuConsecutiveSamples: Math.max(1, Math.floor(positiveEnvNumber("TRUSTY_SQUIRE_OPERATOR_BROWSER_CPU_CONSECUTIVE_SAMPLES", DEFAULT_OPERATOR_BROWSER_CPU_CONSECUTIVE_SAMPLES))),
21
+ };
22
+ }
23
+ export function createOperatorBrowserMarker(startedAt = Date.now(), nonce = randomUUID()) {
24
+ return `v1:${Math.floor(startedAt)}:${nonce}`;
25
+ }
26
+ export function operatorBrowserMarkerStartedAt(marker) {
27
+ const match = /^v1:(\d+):[A-Za-z0-9_-]+$/.exec(marker);
28
+ if (match === null)
29
+ return null;
30
+ const startedAt = Number(match[1]);
31
+ return Number.isSafeInteger(startedAt) && startedAt > 0 ? startedAt : null;
32
+ }
33
+ export function processTreeCpuTicks(rootPid, processes) {
34
+ const byParent = new Map();
35
+ const byPid = new Map();
36
+ for (const process of processes) {
37
+ byPid.set(process.pid, process);
38
+ const children = byParent.get(process.parentPid) ?? [];
39
+ children.push(process);
40
+ byParent.set(process.parentPid, children);
41
+ }
42
+ if (!byPid.has(rootPid))
43
+ return null;
44
+ let ticks = 0;
45
+ const pending = [rootPid];
46
+ const visited = new Set();
47
+ while (pending.length > 0) {
48
+ const pid = pending.pop();
49
+ if (visited.has(pid))
50
+ continue;
51
+ visited.add(pid);
52
+ const process = byPid.get(pid);
53
+ if (process === undefined)
54
+ continue;
55
+ ticks += process.cpuTicks;
56
+ for (const child of byParent.get(pid) ?? [])
57
+ pending.push(child.pid);
58
+ }
59
+ return ticks;
60
+ }
61
+ export function cpuPercentBetween(previous, current, ticksPerSecond = LINUX_PROCESS_TICKS_PER_SECOND) {
62
+ const elapsedMs = current.at - previous.at;
63
+ const ticks = current.ticks - previous.ticks;
64
+ if (elapsedMs <= 0 || ticks < 0 || ticksPerSecond <= 0)
65
+ return null;
66
+ return (ticks * 100_000) / (elapsedMs * ticksPerSecond);
67
+ }
68
+ function parseProcessStat(pid) {
69
+ try {
70
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
71
+ const closeParen = stat.lastIndexOf(")");
72
+ if (closeParen < 0)
73
+ return null;
74
+ const fields = stat
75
+ .slice(closeParen + 2)
76
+ .trim()
77
+ .split(/\s+/);
78
+ const parentPid = Number(fields[1]);
79
+ const utime = Number(fields[11]);
80
+ const stime = Number(fields[12]);
81
+ const startTime = Number(fields[19]);
82
+ if (!Number.isSafeInteger(parentPid) ||
83
+ !Number.isFinite(utime) ||
84
+ !Number.isFinite(stime) ||
85
+ !Number.isSafeInteger(startTime)) {
86
+ return null;
87
+ }
88
+ return { parentPid, cpuTicks: utime + stime, startTime };
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ function isOperatorChromiumExecutable(executable) {
95
+ return /(?:^|\/)(?:chrome|google-chrome(?:-stable)?|chromium(?:-browser)?|chrome-headless-shell|headless_shell|chrome_crashpad_handler|chromium_crashpad_handler)$/i.test(executable);
96
+ }
97
+ export function isOperatorChromiumCommand(command) {
98
+ const entries = command.split("\0").filter((entry) => entry.length > 0);
99
+ const firstEntry = entries[0] ?? "";
100
+ const rewrittenTitle = entries.length === 1 && /\s/.test(firstEntry);
101
+ const executable = rewrittenTitle
102
+ ? (/^(?:"([^"]+)"|'([^']+)'|(\S+))(?:\s|$)/.exec(firstEntry)?.slice(1).find(Boolean) ?? "")
103
+ : firstEntry;
104
+ return isOperatorChromiumExecutable(executable);
105
+ }
106
+ export function operatorBrowserProcessCommandState(pid, readers = {}) {
107
+ const readCommand = readers.readCommand ?? ((processId) => readFileSync(`/proc/${processId}/cmdline`, "utf8"));
108
+ const readExecutable = readers.readExecutable ?? ((processId) => readlinkSync(`/proc/${processId}/exe`));
109
+ let commandDefinitive = false;
110
+ try {
111
+ const command = readCommand(pid);
112
+ if (isOperatorChromiumCommand(command))
113
+ return "matching";
114
+ const entries = command.split("\0").filter((entry) => entry.length > 0);
115
+ commandDefinitive = entries.length > 1 || (entries.length === 1 && !/\s/.test(entries[0]));
116
+ }
117
+ catch (error) {
118
+ const code = error.code;
119
+ if (code === "ENOENT" || code === "ESRCH")
120
+ return "stale";
121
+ }
122
+ try {
123
+ return isOperatorChromiumExecutable(readExecutable(pid)) ? "matching" : "stale";
124
+ }
125
+ catch (error) {
126
+ const code = error.code;
127
+ if (code === "ENOENT" || code === "ESRCH")
128
+ return "stale";
129
+ return commandDefinitive ? "stale" : "unknown";
130
+ }
131
+ }
132
+ export function operatorBrowserProcessMarkerState(pid, readEnvironment = (processId) => readFileSync(`/proc/${processId}/environ`, "utf8")) {
133
+ try {
134
+ const prefix = `${OPERATOR_BROWSER_MARKER_ENV}=`;
135
+ for (const entry of readEnvironment(pid).split("\0")) {
136
+ if (entry.startsWith(prefix)) {
137
+ return { state: "present", marker: entry.slice(prefix.length) };
138
+ }
139
+ }
140
+ }
141
+ catch (error) {
142
+ const code = error.code;
143
+ return { state: code === "ENOENT" || code === "ESRCH" ? "missing" : "unknown" };
144
+ }
145
+ return { state: "missing" };
146
+ }
147
+ export function operatorBrowserProcessMarker(pid) {
148
+ const result = operatorBrowserProcessMarkerState(pid);
149
+ return result.state === "present" ? result.marker : null;
150
+ }
151
+ function readOperatorBrowserProcess(pid) {
152
+ if (operatorBrowserProcessCommandState(pid) !== "matching")
153
+ return null;
154
+ const marker = operatorBrowserProcessMarker(pid);
155
+ if (marker === null || operatorBrowserMarkerStartedAt(marker) === null)
156
+ return null;
157
+ const stat = parseProcessStat(pid);
158
+ return stat === null ? null : { pid, marker, ...stat };
159
+ }
160
+ export function operatorBrowserProcessMatchesMarker(pid, marker) {
161
+ if (process.platform !== "linux")
162
+ return false;
163
+ return (operatorBrowserProcessMarker(pid) === marker &&
164
+ operatorBrowserProcessCommandState(pid) === "matching");
165
+ }
166
+ export function linuxOperatorBrowserProcesses() {
167
+ if (process.platform !== "linux")
168
+ return [];
169
+ try {
170
+ return readdirSync("/proc").flatMap((entry) => {
171
+ if (!/^\d+$/.test(entry))
172
+ return [];
173
+ const record = readOperatorBrowserProcess(Number(entry));
174
+ return record === null ? [] : [record];
175
+ });
176
+ }
177
+ catch {
178
+ return [];
179
+ }
180
+ }
181
+ export class OperatorBrowserProcessWatchdog {
182
+ options;
183
+ readProcesses;
184
+ processMatches;
185
+ kill;
186
+ now;
187
+ intervalMs;
188
+ maxLifetimeMs;
189
+ cpuCeilingPercent;
190
+ cpuConsecutiveSamples;
191
+ ticksPerSecond;
192
+ samples = new Map();
193
+ terminating = new Set();
194
+ timer = null;
195
+ constructor(options = {}) {
196
+ this.options = options;
197
+ const config = operatorBrowserWatchdogConfig();
198
+ this.readProcesses = options.readProcesses ?? linuxOperatorBrowserProcesses;
199
+ this.processMatches =
200
+ options.processMatches ??
201
+ ((pid, startTime, marker) => {
202
+ const current = readOperatorBrowserProcess(pid);
203
+ return current?.startTime === startTime && current.marker === marker;
204
+ });
205
+ this.kill = options.kill ?? process.kill;
206
+ this.now = options.now ?? Date.now;
207
+ this.intervalMs = options.intervalMs ?? config.intervalMs;
208
+ this.maxLifetimeMs = options.maxLifetimeMs ?? config.maxLifetimeMs;
209
+ this.cpuCeilingPercent = options.cpuCeilingPercent ?? config.cpuCeilingPercent;
210
+ this.cpuConsecutiveSamples = options.cpuConsecutiveSamples ?? config.cpuConsecutiveSamples;
211
+ this.ticksPerSecond = options.ticksPerSecond ?? LINUX_PROCESS_TICKS_PER_SECOND;
212
+ }
213
+ start() {
214
+ if (this.timer !== null)
215
+ return;
216
+ this.timer = setInterval(() => void this.check(), this.intervalMs);
217
+ this.timer.unref();
218
+ }
219
+ stop() {
220
+ if (this.timer !== null)
221
+ clearInterval(this.timer);
222
+ this.timer = null;
223
+ }
224
+ async check(now = this.now()) {
225
+ const processes = this.readProcesses();
226
+ const groups = new Map();
227
+ for (const record of processes) {
228
+ const group = groups.get(record.marker) ?? [];
229
+ group.push(record);
230
+ groups.set(record.marker, group);
231
+ }
232
+ for (const marker of [...this.samples.keys()]) {
233
+ if (!groups.has(marker))
234
+ this.samples.delete(marker);
235
+ }
236
+ const reasons = [];
237
+ for (const [marker, records] of groups) {
238
+ if (this.terminating.has(marker))
239
+ continue;
240
+ const startedAt = operatorBrowserMarkerStartedAt(marker);
241
+ if (startedAt === null)
242
+ continue;
243
+ const lifetimeMs = now - startedAt;
244
+ if (lifetimeMs >= this.maxLifetimeMs) {
245
+ const reason = {
246
+ kind: "max_lifetime",
247
+ lifetime_ms: lifetimeMs,
248
+ timeout_ms: this.maxLifetimeMs,
249
+ };
250
+ reasons.push(reason);
251
+ void this.terminate(marker, records, reason);
252
+ continue;
253
+ }
254
+ const previous = this.samples.get(marker);
255
+ const currentProcesses = new Map(records.map((record) => [`${record.pid}:${record.startTime}`, record.cpuTicks]));
256
+ let cpuPercent = null;
257
+ if (previous !== undefined && now > previous.at) {
258
+ let ticks = 0;
259
+ for (const [identity, currentTicks] of currentProcesses) {
260
+ const previousTicks = previous.processes.get(identity);
261
+ if (previousTicks !== undefined && currentTicks >= previousTicks) {
262
+ ticks += currentTicks - previousTicks;
263
+ }
264
+ else if (previousTicks === undefined && currentTicks >= 0) {
265
+ ticks += currentTicks;
266
+ }
267
+ }
268
+ cpuPercent = (ticks * 100_000) / ((now - previous.at) * this.ticksPerSecond);
269
+ }
270
+ const breachCount = cpuPercent !== null && cpuPercent > this.cpuCeilingPercent
271
+ ? (previous?.breachCount ?? 0) + 1
272
+ : 0;
273
+ this.samples.set(marker, { at: now, processes: currentProcesses, breachCount });
274
+ if (cpuPercent === null || breachCount < this.cpuConsecutiveSamples)
275
+ continue;
276
+ const reason = {
277
+ kind: "cpu_budget_exceeded",
278
+ cpu_percent: Math.round(cpuPercent),
279
+ ceiling_percent: this.cpuCeilingPercent,
280
+ consecutive_samples: breachCount,
281
+ };
282
+ reasons.push(reason);
283
+ void this.terminate(marker, records, reason);
284
+ }
285
+ return reasons;
286
+ }
287
+ async terminate(marker, records, reason) {
288
+ this.terminating.add(marker);
289
+ process.stderr.write(`[operator] process watchdog terminate marker=${marker} reason=${JSON.stringify(reason)}\n`);
290
+ let maySignal = true;
291
+ if (this.options.onTerminate !== undefined) {
292
+ try {
293
+ maySignal = (await this.options.onTerminate(marker, reason)) !== false;
294
+ }
295
+ catch (error) {
296
+ maySignal = false;
297
+ const detail = error instanceof Error ? error.message : String(error);
298
+ process.stderr.write(`[operator] process watchdog teardown failed: ${detail}\n`);
299
+ }
300
+ }
301
+ if (!maySignal) {
302
+ this.terminating.delete(marker);
303
+ return;
304
+ }
305
+ const current = this.readProcesses().filter((record) => record.marker === marker);
306
+ const candidates = current.length > 0 ? current : records;
307
+ for (const record of candidates) {
308
+ if (!this.processMatches(record.pid, record.startTime, marker))
309
+ continue;
310
+ try {
311
+ this.kill(record.pid, "SIGKILL");
312
+ }
313
+ catch {
314
+ continue;
315
+ }
316
+ }
317
+ this.samples.delete(marker);
318
+ this.terminating.delete(marker);
319
+ }
320
+ }
321
+ const processTerminationCallbacks = new Map();
322
+ let globalProcessWatchdog = null;
323
+ export async function dispatchOperatorBrowserProcessTermination(marker, reason) {
324
+ const callback = processTerminationCallbacks.get(marker);
325
+ return callback !== undefined && (await callback(reason)) !== false;
326
+ }
327
+ export function startGlobalOperatorBrowserProcessWatchdog() {
328
+ if (process.platform !== "linux" || globalProcessWatchdog !== null)
329
+ return;
330
+ globalProcessWatchdog = new OperatorBrowserProcessWatchdog({
331
+ onTerminate: dispatchOperatorBrowserProcessTermination,
332
+ });
333
+ globalProcessWatchdog.start();
334
+ }
335
+ export function registerOperatorBrowserProcessWatchdog(marker, onTerminate) {
336
+ startGlobalOperatorBrowserProcessWatchdog();
337
+ processTerminationCallbacks.set(marker, onTerminate);
338
+ return () => {
339
+ if (processTerminationCallbacks.get(marker) === onTerminate) {
340
+ processTerminationCallbacks.delete(marker);
341
+ }
342
+ };
343
+ }
344
+ export class OperatorBrowserWatchdog {
345
+ options;
346
+ now;
347
+ idleTimeoutMs;
348
+ intervalMs;
349
+ timer = null;
350
+ unregisterProcessWatchdog = null;
351
+ terminated = false;
352
+ terminationPromise = null;
353
+ constructor(options) {
354
+ this.options = options;
355
+ const config = operatorBrowserWatchdogConfig();
356
+ this.now = options.now ?? Date.now;
357
+ this.idleTimeoutMs = options.idleTimeoutMs ?? config.idleTimeoutMs;
358
+ this.intervalMs = options.intervalMs ?? config.intervalMs;
359
+ }
360
+ start() {
361
+ if (this.unregisterProcessWatchdog === null) {
362
+ const marker = this.options.processMarker();
363
+ if (marker !== null) {
364
+ this.unregisterProcessWatchdog = (this.options.registerProcessWatchdog ?? registerOperatorBrowserProcessWatchdog)(marker, async (_reason) => {
365
+ if (this.options.hasActiveCall())
366
+ return false;
367
+ const idleMs = this.now() - this.options.lastActivityAt();
368
+ if (idleMs < this.idleTimeoutMs)
369
+ return false;
370
+ return await this.terminateAndWait({
371
+ kind: "idle_timeout",
372
+ idle_ms: idleMs,
373
+ timeout_ms: this.idleTimeoutMs,
374
+ });
375
+ });
376
+ }
377
+ }
378
+ if (this.timer !== null || this.terminated)
379
+ return;
380
+ this.timer = setInterval(() => this.check(), this.intervalMs);
381
+ this.timer.unref();
382
+ }
383
+ stop() {
384
+ if (this.timer !== null)
385
+ clearInterval(this.timer);
386
+ this.timer = null;
387
+ }
388
+ dispose() {
389
+ this.stop();
390
+ this.unregisterProcessWatchdog?.();
391
+ this.unregisterProcessWatchdog = null;
392
+ }
393
+ check(now = this.now()) {
394
+ if (this.terminated)
395
+ return null;
396
+ if (this.options.hasActiveCall())
397
+ return null;
398
+ const idleMs = now - this.options.lastActivityAt();
399
+ if (idleMs < this.idleTimeoutMs)
400
+ return null;
401
+ return this.terminate({
402
+ kind: "idle_timeout",
403
+ idle_ms: idleMs,
404
+ timeout_ms: this.idleTimeoutMs,
405
+ });
406
+ }
407
+ terminate(reason) {
408
+ if (this.terminated)
409
+ return reason;
410
+ void this.beginTermination(reason);
411
+ return reason;
412
+ }
413
+ async terminateAndWait(reason) {
414
+ return await this.beginTermination(reason);
415
+ }
416
+ beginTermination(reason) {
417
+ if (this.terminationPromise !== null)
418
+ return this.terminationPromise;
419
+ this.terminationPromise = (async () => {
420
+ const accepted = (await this.options.onTerminate(reason)) !== false;
421
+ if (accepted) {
422
+ this.terminated = true;
423
+ this.stop();
424
+ }
425
+ else {
426
+ this.terminationPromise = null;
427
+ }
428
+ return accepted;
429
+ })().catch((error) => {
430
+ const detail = error instanceof Error ? error.message : String(error);
431
+ process.stderr.write(`[operator] browser watchdog teardown failed: ${detail}\n`);
432
+ this.terminationPromise = null;
433
+ return false;
434
+ });
435
+ return this.terminationPromise;
436
+ }
437
+ }
438
+ //# sourceMappingURL=operator-browser-watchdog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operator-browser-watchdog.js","sourceRoot":"","sources":["../../src/bot/operator-browser-watchdog.ts"],"names":[],"mappings":"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"}