aws-runtime-bridge 1.9.98 → 1.9.101

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 (126) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +7 -1
  2. package/dist/adapter/AcodeSdkAdapter.js +5 -5
  3. package/dist/adapter/ClaudeSdkAdapter.d.ts +4 -0
  4. package/dist/adapter/ClaudeSdkAdapter.js +2 -2
  5. package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
  6. package/dist/adapter/CodexSdkAdapter.js +3 -3
  7. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  8. package/dist/adapter/OpencodeSdkAdapter.js +2 -2
  9. package/dist/adapter/idle-poll-loop.d.ts +4 -1
  10. package/dist/adapter/idle-poll-loop.js +1 -1
  11. package/dist/adapter/types.d.ts +4 -2
  12. package/dist/browser/browser-bootstrap.d.ts +11 -0
  13. package/dist/browser/browser-bootstrap.js +4 -0
  14. package/dist/browser/browser-connect-token.d.ts +10 -0
  15. package/dist/browser/browser-connect-token.js +2 -0
  16. package/dist/browser/browser-pool.d.ts +75 -0
  17. package/dist/browser/browser-pool.js +2 -0
  18. package/dist/browser/browser-profile-store.d.ts +28 -0
  19. package/dist/browser/browser-profile-store.js +2 -0
  20. package/dist/browser/browser-ws-bridge.d.ts +12 -0
  21. package/dist/browser/browser-ws-bridge.js +6 -0
  22. package/dist/browser/built-in-browser-tools.d.ts +27 -0
  23. package/dist/browser/built-in-browser-tools.js +2 -0
  24. package/dist/browser/element-locator.d.ts +24 -0
  25. package/dist/browser/element-locator.js +2 -0
  26. package/dist/browser/element-picker.d.ts +17 -0
  27. package/dist/browser/element-picker.js +2 -0
  28. package/dist/browser/input-dispatcher.d.ts +34 -0
  29. package/dist/browser/input-dispatcher.js +2 -0
  30. package/dist/browser/listener-store.d.ts +32 -0
  31. package/dist/browser/listener-store.js +2 -0
  32. package/dist/browser/page-listener-manager.d.ts +106 -0
  33. package/dist/browser/page-listener-manager.js +307 -0
  34. package/dist/browser/page-listener-types.d.ts +90 -0
  35. package/dist/browser/page-listener-types.js +1 -0
  36. package/dist/browser/screencast-manager.d.ts +42 -0
  37. package/dist/browser/screencast-manager.js +2 -0
  38. package/dist/browser/snapshot-serializer.d.ts +15 -0
  39. package/dist/browser/snapshot-serializer.js +5 -0
  40. package/dist/browser/ssrf-guard.d.ts +15 -0
  41. package/dist/browser/ssrf-guard.js +2 -0
  42. package/dist/browser/stealth.d.ts +7 -0
  43. package/dist/browser/stealth.js +173 -0
  44. package/dist/browser/step-archive.d.ts +52 -0
  45. package/dist/browser/step-archive.js +2 -0
  46. package/dist/browser/types.d.ts +192 -0
  47. package/dist/browser/types.js +2 -0
  48. package/dist/browser/ws-server.d.ts +67 -0
  49. package/dist/browser/ws-server.js +2 -0
  50. package/dist/index.js +1 -1
  51. package/dist/middleware/auth.d.ts +2 -0
  52. package/dist/middleware/auth.js +1 -1
  53. package/dist/remote-desktop/computer-control.d.ts +30 -0
  54. package/dist/remote-desktop/computer-control.js +2 -0
  55. package/dist/remote-desktop/coords.d.ts +13 -0
  56. package/dist/remote-desktop/coords.js +2 -0
  57. package/dist/remote-desktop/frame-backpressure.d.ts +7 -0
  58. package/dist/remote-desktop/frame-backpressure.js +2 -0
  59. package/dist/remote-desktop/index.d.ts +7 -0
  60. package/dist/remote-desktop/index.js +4 -0
  61. package/dist/remote-desktop/input-backends/interface.d.ts +17 -0
  62. package/dist/remote-desktop/input-backends/interface.js +1 -0
  63. package/dist/remote-desktop/input-backends/key-map.d.ts +2 -0
  64. package/dist/remote-desktop/input-backends/key-map.js +2 -0
  65. package/dist/remote-desktop/input-dispatcher.d.ts +11 -0
  66. package/dist/remote-desktop/input-dispatcher.js +2 -0
  67. package/dist/remote-desktop/permission-manager.d.ts +7 -0
  68. package/dist/remote-desktop/permission-manager.js +2 -0
  69. package/dist/remote-desktop/screen-capture.d.ts +27 -0
  70. package/dist/remote-desktop/screen-capture.js +2 -0
  71. package/dist/remote-desktop/session-manager.d.ts +59 -0
  72. package/dist/remote-desktop/session-manager.js +2 -0
  73. package/dist/remote-desktop/system-backend.d.ts +65 -0
  74. package/dist/remote-desktop/system-backend.js +5 -0
  75. package/dist/remote-desktop/types.d.ts +68 -0
  76. package/dist/remote-desktop/types.js +1 -0
  77. package/dist/remote-desktop/ui-automation.d.ts +48 -0
  78. package/dist/remote-desktop/ui-automation.js +31 -0
  79. package/dist/remote-desktop/win32-api.d.ts +29 -0
  80. package/dist/remote-desktop/win32-api.js +2 -0
  81. package/dist/routes/background-tasks.d.ts +2 -0
  82. package/dist/routes/background-tasks.js +2 -0
  83. package/dist/routes/browser-listeners.d.ts +2 -0
  84. package/dist/routes/browser-listeners.js +2 -0
  85. package/dist/routes/browser-sessions.d.ts +2 -0
  86. package/dist/routes/browser-sessions.js +2 -0
  87. package/dist/routes/pty.js +3 -3
  88. package/dist/routes/terminal.js +30 -30
  89. package/dist/services/agent-pty-manager.d.ts +22 -0
  90. package/dist/services/agent-pty-manager.js +5 -0
  91. package/dist/services/browser-session-manager.d.ts +55 -0
  92. package/dist/services/browser-session-manager.js +12 -0
  93. package/dist/services/cli-commands.d.ts +4 -0
  94. package/dist/services/cli-commands.js +5 -5
  95. package/package/acode/dist/await-complete-tool.d.ts +17 -0
  96. package/package/acode/dist/await-complete-tool.js +21 -0
  97. package/package/acode/dist/background-command-manager.d.ts +148 -0
  98. package/package/acode/dist/background-command-manager.js +8 -0
  99. package/package/acode/dist/background-command-store.d.ts +46 -0
  100. package/package/acode/dist/background-command-store.js +2 -0
  101. package/package/acode/dist/background-command-tools.d.ts +5 -0
  102. package/package/acode/dist/background-command-tools.js +18 -0
  103. package/package/acode/dist/background-output-ringbuffer.d.ts +23 -0
  104. package/package/acode/dist/background-output-ringbuffer.js +3 -0
  105. package/package/acode/dist/built-in-file-tools.d.ts +8 -1
  106. package/package/acode/dist/built-in-file-tools.js +2 -2
  107. package/package/acode/dist/compaction.js +6 -6
  108. package/package/acode/dist/index.d.ts +1 -0
  109. package/package/acode/dist/index.js +1 -1
  110. package/package/acode/dist/runtime.d.ts +6 -0
  111. package/package/acode/dist/runtime.js +27 -27
  112. package/package/acode/dist/sub-agent-tools.d.ts +0 -1
  113. package/package/acode/dist/sub-agent-tools.js +11 -28
  114. package/package/acode/dist/terminal-tool.d.ts +7 -0
  115. package/package/acode/dist/terminal-tool.js +2 -0
  116. package/package/acode/dist/terminal-types.d.ts +38 -0
  117. package/package/acode/dist/terminal-types.js +1 -0
  118. package/package/acode/dist/types.d.ts +10 -1
  119. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +3 -1
  120. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  121. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -0
  122. package/package/aws-client-agent-mcp/dist/logger.js +1 -1
  123. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +8 -0
  124. package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -19
  125. package/package/aws-client-agent-mcp/dist/types.d.ts +25 -0
  126. package/package.json +6 -2
@@ -0,0 +1,173 @@
1
+ const t=["--disable-blink-features=AutomationControlled"],r=["--enable-automation"];function n(e){return`
2
+ (function () {
3
+ 'use strict';
4
+
5
+ // 1. navigator.webdriver -> false\uFF08\u53CC\u4FDD\u9669\uFF1Alaunch \u5DF2\u79FB\u9664 --enable-automation\uFF09
6
+ try {
7
+ Object.defineProperty(Navigator.prototype, 'webdriver', {
8
+ configurable: true,
9
+ get: function () { return false; },
10
+ });
11
+ } catch (e) {}
12
+
13
+ // 2. window.chrome \u5B58\u5728\u6027\uFF08headless \u65E7\u7248\u7F3A\u5931\uFF0C\u90E8\u5206\u68C0\u6D4B\u76F4\u63A5\u5224\u65E0 chrome \u5373 bot\uFF09
14
+ try {
15
+ if (!window.chrome || !window.chrome.runtime) {
16
+ Object.defineProperty(window, 'chrome', {
17
+ configurable: true,
18
+ get: function () {
19
+ return {
20
+ runtime: {
21
+ connect: function () { return {}; },
22
+ sendMessage: function () {},
23
+ onMessage: { addListener: function () {}, removeListener: function () {} },
24
+ getManifest: function () { return {}; },
25
+ getURL: function () { return ''; },
26
+ },
27
+ loadTimes: function () {},
28
+ csi: function () {},
29
+ app: {},
30
+ };
31
+ },
32
+ });
33
+ }
34
+ } catch (e) {}
35
+
36
+ // 3. plugins / mimeTypes \u2014\u2014 \u7ED3\u6784\u6B63\u786E\u7684 PluginArray / Plugin / MimeType\u3002
37
+ // \u5173\u952E\uFF1A\u5FC5\u987B\u652F\u6301\u4E0B\u6807\u8BBF\u95EE plugins[i] / plugin[i]\uFF08\u963F\u91CC\u7B49\u98CE\u63A7\u904D\u5386
38
+ // plugins[i].name \u91C7\u96C6\u6307\u7EB9\uFF1B\u7F3A\u4E0B\u6807\u8BBF\u95EE\u4F1A\u629B\u9519\u5E76\u5BFC\u81F4\u9875\u9762 JS \u5D29\u6E83 \u2192 \u7A7A\u767D\u9875\uFF09\u3002
39
+ try {
40
+ var mkMime = function (type, suffixes, description, plugin) {
41
+ var m = { type: type, suffixes: suffixes, description: description, enabledPlugin: plugin || null };
42
+ if (window.MimeType) { try { Object.setPrototypeOf(m, MimeType.prototype); } catch (e) {} }
43
+ return m;
44
+ };
45
+ var mkPlugin = function (name, description, filename, mimeDefs) {
46
+ var p = { name: name, description: description, filename: filename };
47
+ var mimes = mimeDefs.map(function (md) { return mkMime(md[0], md[1], md[2], p); });
48
+ p.length = mimes.length;
49
+ for (var i = 0; i < mimes.length; i++) { p[i] = mimes[i]; }
50
+ p.item = function (i) { return this[i] !== undefined ? this[i] : null; };
51
+ p.namedItem = function (n) { for (var i = 0; i < this.length; i++) { if (this[i].type === n) return this[i]; } return null; };
52
+ if (window.Plugin) { try { Object.setPrototypeOf(p, Plugin.prototype); } catch (e) {} }
53
+ return p;
54
+ };
55
+ var pdfMimes = [['application/pdf', 'pdf', ''], ['text/pdf', 'pdf', '']];
56
+ var pluginDefs = [
57
+ ['PDF Viewer', 'Portable Document Format', 'internal-pdf-viewer'],
58
+ ['Chrome PDF Viewer', 'Portable Document Format', 'internal-pdf-viewer'],
59
+ ['Chromium PDF Viewer', 'Portable Document Format', 'internal-pdf-viewer'],
60
+ ['Microsoft Edge PDF Viewer', 'Portable Document Format', 'internal-pdf-viewer'],
61
+ ['WebKit built-in PDF', 'Portable Document Format', 'internal-pdf-viewer']
62
+ ];
63
+ var pluginList = pluginDefs.map(function (d) { return mkPlugin(d[0], d[1], d[2], pdfMimes); });
64
+ var pluginsArray = { length: pluginList.length };
65
+ for (var j = 0; j < pluginList.length; j++) { pluginsArray[j] = pluginList[j]; }
66
+ pluginsArray.item = function (i) { return this[i] !== undefined ? this[i] : null; };
67
+ pluginsArray.namedItem = function (n) { for (var i = 0; i < this.length; i++) { if (this[i].name === n) return this[i]; } return null; };
68
+ pluginsArray.refresh = function () {};
69
+ if (window.PluginArray) { try { Object.setPrototypeOf(pluginsArray, PluginArray.prototype); } catch (e) {} }
70
+ Object.defineProperty(Navigator.prototype, 'plugins', {
71
+ configurable: true,
72
+ get: function () { return pluginsArray; }
73
+ });
74
+
75
+ // mimeTypes\uFF1A\u6240\u6709\u63D2\u4EF6 mime \u7684\u6241\u5E73\u96C6\u5408\uFF0C\u540C\u6837\u652F\u6301\u4E0B\u6807\u8BBF\u95EE
76
+ var allMimes = [];
77
+ pluginList.forEach(function (p) { for (var i = 0; i < p.length; i++) { allMimes.push(p[i]); } });
78
+ var mimeArray = { length: allMimes.length };
79
+ for (var k = 0; k < allMimes.length; k++) { mimeArray[k] = allMimes[k]; }
80
+ mimeArray.item = function (i) { return this[i] !== undefined ? this[i] : null; };
81
+ mimeArray.namedItem = function (n) { for (var i = 0; i < this.length; i++) { if (this[i].type === n) return this[i]; } return null; };
82
+ if (window.MimeTypeArray) { try { Object.setPrototypeOf(mimeArray, MimeTypeArray.prototype); } catch (e) {} }
83
+ Object.defineProperty(Navigator.prototype, 'mimeTypes', {
84
+ configurable: true,
85
+ get: function () { return mimeArray; }
86
+ });
87
+ } catch (e) {}
88
+
89
+ // 4. hardwareConcurrency / deviceMemory \u5408\u7406\u503C\uFF08\u7F3A\u5931\u4F1A\u88AB\u5224\u4E3A\u65E0\u5934\uFF09
90
+ try {
91
+ Object.defineProperty(Navigator.prototype, 'hardwareConcurrency', { configurable: true, get: function () { return 8; } });
92
+ Object.defineProperty(Navigator.prototype, 'deviceMemory', { configurable: true, get: function () { return 8; } });
93
+ } catch (e) {}
94
+
95
+ // 5. language / languages \u5408\u7406\uFF08\u4E2D\u6587\u73AF\u5883\u4F18\u5148\uFF09
96
+ try {
97
+ Object.defineProperty(Navigator.prototype, 'language', { configurable: true, get: function () { return 'zh-CN'; } });
98
+ Object.defineProperty(Navigator.prototype, 'languages', { configurable: true, get: function () { return ['zh-CN', 'zh', 'en-US', 'en']; } });
99
+ } catch (e) {}
100
+
101
+ // 6. screen \u4E0E\u89C6\u53E3\u4E00\u81F4\uFF08headless \u4E0B screen.* \u53EF\u80FD\u4E3A 0\uFF09
102
+ try {
103
+ Object.defineProperty(window, 'screen', {
104
+ configurable: true,
105
+ get: function () {
106
+ return {
107
+ width: window.innerWidth,
108
+ height: window.innerHeight,
109
+ availWidth: window.innerWidth,
110
+ availHeight: window.innerHeight,
111
+ colorDepth: 24,
112
+ pixelDepth: 24,
113
+ orientation: { type: 'landscape-primary', angle: 0, onchange: null, addEventListener: function () {}, removeEventListener: function () {} }
114
+ };
115
+ }
116
+ });
117
+ } catch (e) {}
118
+
119
+ // 7. WebGL vendor/renderer \u4F2A\u88C5\uFF08\u907F\u514D\u66B4\u9732 SwiftShader \u8F6F\u4EF6\u6E32\u67D3\uFF09
120
+ try {
121
+ var G = window.WebGLRenderingContext;
122
+ var UNMASKED_VENDOR = 0x9245;
123
+ var UNMASKED_RENDERER = 0x9246;
124
+ var origGetContext = HTMLCanvasElement.prototype.getContext;
125
+ HTMLCanvasElement.prototype.getContext = function (type) {
126
+ var ctx = origGetContext.apply(this, arguments);
127
+ if (!ctx) return ctx;
128
+ if (type === 'webgl' || type === 'webgl2' || type === 'experimental-webgl') {
129
+ var origGetParam = ctx.getParameter;
130
+ ctx.getParameter = function (p) {
131
+ if (p === UNMASKED_VENDOR) return 'Intel Inc.';
132
+ if (p === UNMASKED_RENDERER) return 'Intel(R) Iris(TM) Plus Graphics 655';
133
+ return origGetParam.call(this, p);
134
+ };
135
+ var origGetExt = ctx.getExtension;
136
+ ctx.getExtension = function (name) {
137
+ if (name === 'WEBGL_debug_renderer_info') {
138
+ return { UNMASKED_VENDOR_WEBGL: UNMASKED_VENDOR, UNMASKED_RENDERER_WEBGL: UNMASKED_RENDERER };
139
+ }
140
+ return origGetExt.call(this, name);
141
+ };
142
+ }
143
+ return ctx;
144
+ };
145
+ } catch (e) {}
146
+
147
+ // 8. platform / oscpu / userAgentData.platform \u4F2A\u88C5\u4E3A Windows\uFF0C\u907F\u514D\u4E0E Windows UA \u51B2\u7A81
148
+ try {
149
+ Object.defineProperty(Navigator.prototype, 'platform', { configurable: true, get: function () { return 'Win32'; } });
150
+ } catch (e) {}
151
+ try {
152
+ Object.defineProperty(Navigator.prototype, 'oscpu', { configurable: true, get: function () { return 'Windows NT 10.0; Win64; x64'; } });
153
+ } catch (e) {}
154
+ try {
155
+ if (navigator.userAgentData) {
156
+ var spoofedUAD = {
157
+ brands: [
158
+ { brand: 'Chromium', version: '${e}' },
159
+ { brand: 'Google Chrome', version: '${e}' },
160
+ { brand: 'Not=A?Brand', version: '24' }
161
+ ],
162
+ mobile: false,
163
+ platform: 'Windows',
164
+ };
165
+ Object.defineProperty(Navigator.prototype, 'userAgentData', {
166
+ configurable: true,
167
+ get: function () { return spoofedUAD; },
168
+ });
169
+ }
170
+ } catch (e) {}
171
+ })();
172
+ `}export{r as STEALTH_IGNORE_ARGS,t as STEALTH_LAUNCH_ARGS,n as buildStealthInitScript};
173
+
@@ -0,0 +1,52 @@
1
+
2
+ import type { JsonObject, StepArchiveConfig } from "./types.js";
3
+
4
+ export interface StepRecord {
5
+
6
+ tool: string;
7
+
8
+ args: JsonObject;
9
+
10
+ beforeUrl: string;
11
+
12
+ afterUrl: string;
13
+
14
+ beforeScreenshot?: string;
15
+
16
+ afterScreenshot?: string;
17
+
18
+ durationMs: number;
19
+
20
+ error?: string;
21
+
22
+ timestamp: number;
23
+ }
24
+
25
+ export interface StepRecordInput {
26
+ tool: string;
27
+ args: JsonObject;
28
+ beforeUrl: string;
29
+ afterUrl: string;
30
+ beforeScreenshot?: string;
31
+ afterScreenshot?: string;
32
+ durationMs: number;
33
+ error?: string;
34
+ }
35
+
36
+ export declare class StepArchive {
37
+ private readonly steps;
38
+ private readonly maxSteps;
39
+ readonly screenshotQuality: number;
40
+ constructor(config?: StepArchiveConfig);
41
+
42
+ record(step: StepRecordInput): void;
43
+
44
+ toJSON(): {
45
+ steps: StepRecord[];
46
+ totalSteps: number;
47
+ };
48
+
49
+ clear(): void;
50
+
51
+ getSteps(): readonly StepRecord[];
52
+ }
@@ -0,0 +1,2 @@
1
+ const h=100,p=60;class i{constructor(t){this.steps=[],this.maxSteps=t?.maxSteps??100,this.screenshotQuality=t?.screenshotQuality??60}record(t){const s={...t,timestamp:Date.now()};for(this.steps.push(s);this.steps.length>this.maxSteps;)this.steps.shift()}toJSON(){return{steps:this.steps.slice(),totalSteps:this.steps.length}}clear(){this.steps.length=0}getSteps(){return this.steps}}export{i as StepArchive};
2
+
@@ -0,0 +1,192 @@
1
+
2
+ import type { Browser, BrowserContext, Page } from "playwright";
3
+ import type { ScreencastManager } from "./screencast-manager.js";
4
+ import type { StepArchive } from "./step-archive.js";
5
+ import type { PageListenerManager } from "./page-listener-manager.js";
6
+
7
+ export declare const DEFAULT_BROWSER_ID = "default";
8
+
9
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
10
+ [key: string]: JsonValue;
11
+ };
12
+
13
+ export type JsonObject = {
14
+ [key: string]: JsonValue;
15
+ };
16
+
17
+ export interface ScreencastFrame {
18
+
19
+ dataUrl: string;
20
+
21
+ base64: string;
22
+
23
+ width: number;
24
+
25
+ height: number;
26
+
27
+ timestamp: number;
28
+
29
+ url: string;
30
+ }
31
+
32
+ export type FrameSubscriber = (frame: ScreencastFrame) => void;
33
+
34
+ export interface SessionBrowser {
35
+
36
+ agentId: string;
37
+
38
+ scopeKey: string;
39
+
40
+ browserId: string;
41
+
42
+ title: string;
43
+
44
+ browser: Browser;
45
+
46
+ context: BrowserContext;
47
+
48
+ pages: Page[];
49
+
50
+ activePageIndex: number;
51
+
52
+ screencast: ScreencastManager;
53
+
54
+ archive: StepArchive;
55
+
56
+ launchedAt: number;
57
+
58
+ lastActivityAt: number;
59
+
60
+ humanTakeover: boolean;
61
+
62
+ takeoverClientId?: string;
63
+
64
+ qualityPreset: QualityPreset;
65
+
66
+ listenerManager: PageListenerManager;
67
+
68
+ autoSaveTimer?: ReturnType<typeof setInterval>;
69
+ }
70
+
71
+ export declare function makeBrowserKey(agentId: string, browserId: string): string;
72
+
73
+ export declare function parseBrowserKey(key: string): {
74
+ agentId: string;
75
+ browserId: string;
76
+ } | null;
77
+
78
+ export interface ScreencastConfig {
79
+
80
+ quality?: number;
81
+
82
+ maxWidth?: number;
83
+
84
+ maxHeight?: number;
85
+
86
+ everyNthFrame?: number;
87
+
88
+ maxFramesPerSecond?: number;
89
+
90
+ format?: "jpeg" | "png";
91
+ }
92
+
93
+ export interface StepArchiveConfig {
94
+
95
+ maxSteps?: number;
96
+
97
+ screenshotQuality?: number;
98
+ }
99
+
100
+ export interface SsrfConfig {
101
+
102
+ allowPrivate?: boolean;
103
+
104
+ blocklist?: string[];
105
+
106
+ allowlist?: string[];
107
+ }
108
+
109
+ export interface WsServerConfig {
110
+
111
+ port?: number;
112
+
113
+ host?: string;
114
+
115
+ maxSendBytes?: number;
116
+
117
+ idleTimeoutMs?: number;
118
+
119
+ heartbeatMs?: number;
120
+ }
121
+
122
+ export interface BrowserPoolConfig {
123
+
124
+ headless?: boolean;
125
+
126
+ executablePath?: string;
127
+
128
+ stealth?: boolean;
129
+
130
+ viewportWidth?: number;
131
+
132
+ viewportHeight?: number;
133
+
134
+ maxPagesPerSession?: number;
135
+
136
+ maxSessionDurationMs?: number;
137
+
138
+ idleTimeoutMs?: number;
139
+
140
+ launchArgs?: string[];
141
+
142
+ screencastConfig?: ScreencastConfig;
143
+
144
+ archiveConfig?: StepArchiveConfig;
145
+
146
+ ssrfConfig?: SsrfConfig;
147
+
148
+ userAgent?: string;
149
+
150
+ locale?: string;
151
+
152
+ timezone?: string;
153
+
154
+ profileDir?: string;
155
+ }
156
+
157
+ export declare const MAX_SESSIONS = 8;
158
+
159
+ export declare const MAX_SESSIONS_PER_AGENT = 4;
160
+
161
+ export declare const MAX_PAGES_PER_SESSION = 5;
162
+
163
+ export declare const SESSION_TIMEOUT_MS = 0;
164
+
165
+ export declare const IDLE_TIMEOUT_MS = 0;
166
+
167
+ export declare const WS_PORT = 7891;
168
+
169
+ export declare const WS_HOST = "127.0.0.1";
170
+
171
+ export declare const WS_DEFAULT_MAX_SEND_BYTES: number;
172
+
173
+ export declare const WS_DEFAULT_HEARTBEAT_MS: number;
174
+
175
+ export declare const WS_DEFAULT_IDLE_TIMEOUT_MS: number;
176
+
177
+ export declare const IDLE_CHECK_INTERVAL_MS: number;
178
+
179
+ export type QualityPreset = "original" | "hd" | "smooth";
180
+
181
+ export interface QualityPresetConfig {
182
+
183
+ quality: number;
184
+
185
+ maxWidth: number;
186
+
187
+ maxHeight: number;
188
+ }
189
+
190
+ export declare const QUALITY_PRESETS: Record<QualityPreset, QualityPresetConfig>;
191
+
192
+ export declare function isQualityPreset(value: unknown): value is QualityPreset;
@@ -0,0 +1,2 @@
1
+ const r="default";function e(t,o){return`${t}::${o}`}function S(t){const o=t.indexOf("::");return o<0?null:{agentId:t.slice(0,o),browserId:t.slice(o+2)}}const _=8,n=4,E=5,s=0,x=0,i=7891,c="127.0.0.1",T=2*1024*1024,p=10*1e3,I=30*1e3,a=60*1e3,A={original:{quality:80,maxWidth:1280,maxHeight:800},hd:{quality:60,maxWidth:1024,maxHeight:640},smooth:{quality:45,maxWidth:800,maxHeight:500}};function M(t){return t==="original"||t==="hd"||t==="smooth"}export{r as DEFAULT_BROWSER_ID,a as IDLE_CHECK_INTERVAL_MS,x as IDLE_TIMEOUT_MS,E as MAX_PAGES_PER_SESSION,_ as MAX_SESSIONS,n as MAX_SESSIONS_PER_AGENT,A as QUALITY_PRESETS,s as SESSION_TIMEOUT_MS,p as WS_DEFAULT_HEARTBEAT_MS,I as WS_DEFAULT_IDLE_TIMEOUT_MS,T as WS_DEFAULT_MAX_SEND_BYTES,c as WS_HOST,i as WS_PORT,M as isQualityPreset,e as makeBrowserKey,S as parseBrowserKey};
2
+
@@ -0,0 +1,67 @@
1
+
2
+ import type { BrowserPool } from "./browser-pool.js";
3
+ import { type WsServerConfig } from "./types.js";
4
+ import type { PageListenerInfo } from "./page-listener-types.js";
5
+
6
+ export declare class BrowserWsServer {
7
+ private readonly pool;
8
+ private readonly config;
9
+ private wss;
10
+ private serverPort;
11
+ private readonly clients;
12
+
13
+ private readonly inputDispatcher;
14
+
15
+ private mainHeartbeat;
16
+
17
+ private lastCursorQueryAt;
18
+
19
+ private lastCursor;
20
+ constructor(pool: BrowserPool, config?: WsServerConfig);
21
+
22
+ start(): Promise<{
23
+ port: number;
24
+ host: string;
25
+ }>;
26
+
27
+ private tryStart;
28
+
29
+ stop(): Promise<void>;
30
+
31
+ getPort(): number;
32
+
33
+ getUrl(agentId: string, browserId?: string): string;
34
+ private attachHandlers;
35
+ private handleConnection;
36
+
37
+ private handleInputMessage;
38
+
39
+ private queryAndPushSelection;
40
+
41
+ private queryAndPushCursor;
42
+
43
+ private sendFrame;
44
+
45
+ private sendJson;
46
+
47
+ private closeClient;
48
+
49
+ private startMainHeartbeat;
50
+ private stopMainHeartbeat;
51
+
52
+ broadcastListenerUpdate(agentId: string, browserId: string, listeners: PageListenerInfo[]): void;
53
+
54
+ broadcastListenerTriggered(agentId: string, browserId: string, payload: {
55
+ listenerId: string;
56
+ selector: string;
57
+ prompt: string;
58
+ url: string;
59
+ text: string;
60
+ at: number;
61
+ changeType?: "added" | "removed" | "changed" | "exists";
62
+ }): void;
63
+ }
64
+
65
+ export declare function getBrowserWsServer(pool: BrowserPool, config?: WsServerConfig): Promise<BrowserWsServer>;
66
+
67
+ export declare function stopBrowserWsServer(): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import{WebSocketServer as y,WebSocket as p}from"ws";import{DEFAULT_BROWSER_ID as f}from"./types.js";import{WS_DEFAULT_HEARTBEAT_MS as m,WS_DEFAULT_IDLE_TIMEOUT_MS as w,WS_DEFAULT_MAX_SEND_BYTES as k,WS_HOST as b,WS_PORT as v,isQualityPreset as _,QUALITY_PRESETS as I}from"./types.js";import{InputDispatcher as S}from"./input-dispatcher.js";import{installPickerOverlay as P,removePickerOverlay as C,pickElementAt as T,pickElementParent as J}from"./element-picker.js";const A="localhost";class E{constructor(e,r){this.wss=null,this.clients=new Set,this.mainHeartbeat=null,this.lastCursorQueryAt=0,this.lastCursor=null,this.pool=e,this.config={port:r?.port??v,host:r?.host??b,maxSendBytes:r?.maxSendBytes??k,idleTimeoutMs:r?.idleTimeoutMs??w,heartbeatMs:r?.heartbeatMs??m},this.inputDispatcher=new S(e),this.serverPort=this.config.port,this.pool.onSessionClose((t,s)=>{this.inputDispatcher.clearSession(t,s)})}start(){return this.wss?Promise.resolve({port:this.serverPort,host:this.config.host}):this.tryStart(this.config.port).catch(e=>{if(this.config.port===0)throw e;return console.warn(`[browser-ws] port ${this.config.port} bind failed (${e.message}); falling back to OS-assigned port`),this.tryStart(0)})}tryStart(e){return new Promise((r,t)=>{const s=new y({host:this.config.host,port:e,verifyClient:(o,i)=>{if(!o.origin){i(!0);return}/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(o.origin)?i(!0):i(!1,403,"origin not allowed")}});s.on("listening",()=>{const o=s.address(),i=typeof o=="object"&&o?o.port:e;this.serverPort=i,this.wss=s,this.attachHandlers(s),this.startMainHeartbeat(),r({port:i,host:this.config.host})}),s.on("error",o=>{this.wss||t(o)})})}async stop(){this.stopMainHeartbeat();for(const e of Array.from(this.clients))this.closeClient(e,1001,"server shutting down");this.wss&&(await new Promise(e=>{this.wss.close(()=>e())}),this.wss=null)}getPort(){return this.serverPort}getUrl(e,r){const t=this.config.host==="0.0.0.0"?A:this.config.host,s=r&&r.trim()?r.trim():f;return s===f?`ws://${t}:${this.serverPort}/agent/${encodeURIComponent(e)}`:`ws://${t}:${this.serverPort}/agent/${encodeURIComponent(e)}/${encodeURIComponent(s)}`}attachHandlers(e){e.on("connection",(r,t)=>{this.handleConnection(r,t).catch(()=>{try{r.close(1011,"internal error")}catch{}})})}async handleConnection(e,r){const t=new URL(r.url||"/","http://internal"),s=t.pathname.match(/^\/agent\/([^/]+)(?:\/([^/]+))?$/);if(!s){this.sendJson(e,{type:"error",message:`Invalid path; expected /agent/{agentId} or /agent/{agentId}/{browserId}, got ${t.pathname}`}),e.close(1008,"invalid path");return}const o=decodeURIComponent(s[1]),i=s[2]?decodeURIComponent(s[2]):f,n=this.pool.get(o,i);if(!n){this.sendJson(e,{type:"error",message:`Browser session not launched for ${o}/${i}. Call browser_launch first.`}),e.close(1008,"session not launched");return}const a={agentId:o,browserId:n.browserId,clientId:`${o}::${n.browserId}::${Date.now()}::${Math.random().toString(36).slice(2,8)}`,socket:e,heartbeatTimer:null,lastPongAt:Date.now(),unsubscribe:null},l=n.screencast.subscribe(u=>{this.sendFrame(e,u)});a.unsubscribe=l,e.on("pong",()=>{a.lastPongAt=Date.now()}),e.on("message",u=>{try{const d=u.toString("utf-8"),c=JSON.parse(d);if(c.type==="ping"){a.lastPongAt=Date.now(),this.sendJson(e,{type:"pong"});return}if(c.type==="input"&&typeof c.action=="string"){this.handleInputMessage(a,n,c.action,c);return}}catch{}}),e.on("close",()=>{this.closeClient(a,1e3,"client closed")}),e.on("error",()=>{this.closeClient(a,1011,"socket error")}),this.clients.add(a),this.sendJson(e,{type:"ready",agentId:o,browserId:n.browserId,viewport:{width:n.pages[n.activePageIndex]?.viewportSize()?.width??0,height:n.pages[n.activePageIndex]?.viewportSize()?.height??0},qualityPreset:n.qualityPreset})}async handleInputMessage(e,r,t,s){if(this.pool.touchActivity(e.agentId,e.browserId),t==="takeover"){const i=this.inputDispatcher.acquireTakeover(e.agentId,e.browserId,e.clientId);this.sendJson(e.socket,{type:"takeover_state",active:i?!0:r.humanTakeover,ok:i,error:i?void 0:"another client is taking over"});return}if(t==="release_takeover"){this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),this.sendJson(e.socket,{type:"takeover_state",active:!1,ok:!0});return}if(t==="set_quality"){const i=s.preset;if(!_(i)){this.sendJson(e.socket,{type:"quality_changed",ok:!1,error:`invalid preset: ${String(s.preset)}`});return}const n=I[i];let a=!1;try{a=await r.screencast.updateQuality(n)}catch{a=!1}a&&(r.qualityPreset=i),this.sendJson(e.socket,{type:"quality_changed",preset:i,ok:a});return}if(t==="go_back"||t==="go_forward"||t==="reload"){if(!r.humanTakeover||r.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:"not in takeover mode"});return}const i=r.pages[r.activePageIndex];if(!i||i.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:"active page is closed"});return}try{let n=!0,a="";try{a=i.url()}catch{}if(t==="go_back"?n=await i.goBack({waitUntil:"domcontentloaded",timeout:15e3}):t==="go_forward"?n=await i.goForward({waitUntil:"domcontentloaded",timeout:15e3}):await i.reload({waitUntil:"domcontentloaded",timeout:15e3}),n===null){let l="";try{l=i.url()}catch{}l&&l!==a&&(n=!0)}if(n===null&&t==="go_back"){const l=r.pages.indexOf(i);if(l>0){await this.pool.closePage(e.agentId,l,e.browserId);const u=r.pages[r.activePageIndex];u&&!u.isClosed()&&await r.screencast.forceCaptureAndPush(u).catch(()=>{}),this.sendJson(e.socket,{type:"input_result",ok:!0,action:t});return}}if(n===null){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:t==="go_back"?"no previous page in history":"no next page in history"});return}await new Promise(l=>setTimeout(l,200)),await r.screencast.restartAfterNavigation(i),this.sendJson(e.socket,{type:"input_result",ok:!0,action:t})}catch(n){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:n instanceof Error?n.message:String(n)})}return}if(t==="picker_start"||t==="picker_move"||t==="picker_stop"||t==="picker_parent"){if(!r.humanTakeover||r.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:"not in takeover mode"});return}const i=r.pages[r.activePageIndex];if(!i||i.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:"active page is closed"});return}try{if(t==="picker_start")await P(i);else if(t==="picker_stop")await C(i);else if(t==="picker_parent"){const n=await J(i);this.sendJson(e.socket,{type:"picker_result",selector:n.selector,found:n.found,tag:n.tag,text:n.text})}else{const n=typeof s.x=="number"?s.x:0,a=typeof s.y=="number"?s.y:0,l=await T(i,n,a);this.sendJson(e.socket,{type:"picker_result",selector:l.selector,found:l.found,tag:l.tag,text:l.text})}this.sendJson(e.socket,{type:"input_result",ok:!0,action:t})}catch(n){this.sendJson(e.socket,{type:"input_result",ok:!1,action:t,error:n instanceof Error?n.message:String(n)})}return}const o=await this.inputDispatcher.dispatch(e.agentId,e.browserId,t,s);t==="mousemove"&&o.ok&&this.queryAndPushCursor(e,r,s),t==="press_key"&&o.ok&&typeof s.key=="string"&&(s.key==="Control+c"||s.key==="Meta+c")&&this.queryAndPushSelection(e,r),this.sendJson(e.socket,{type:"input_result",ok:o.ok,action:t,error:o.error})}async queryAndPushSelection(e,r){const t=r.pages[r.activePageIndex];if(!(!t||t.isClosed()))try{const s=await t.evaluate(()=>globalThis.getSelection?.()?.toString()??"");typeof s=="string"&&s.length>0&&this.sendJson(e.socket,{type:"selection_text",text:s})}catch{}}async queryAndPushCursor(e,r,t){const s=typeof t.x=="number"?t.x:void 0,o=typeof t.y=="number"?t.y:void 0;if(s===void 0||o===void 0)return;const i=Date.now();if(i-this.lastCursorQueryAt<60)return;this.lastCursorQueryAt=i;const n=r.pages[r.activePageIndex];if(!(!n||n.isClosed()))try{const a=await n.evaluate(l=>{const u=globalThis,d=u.document?.elementFromPoint(l.x,l.y);return d?u.window?.getComputedStyle(d)?.cursor??"default":"default"},{x:s,y:o});typeof a=="string"&&a!==this.lastCursor&&(this.lastCursor=a,this.sendJson(e.socket,{type:"cursor_changed",cursor:a}))}catch{}}sendFrame(e,r){if(e.readyState!==p.OPEN)return;const t=JSON.stringify({type:"frame",frame:r}),s=Buffer.byteLength(t,"utf-8");if(s>this.config.maxSendBytes){console.warn(`[browser-ws] frame payload ${s} bytes exceeds maxSendBytes ${this.config.maxSendBytes}; dropping`);return}try{e.send(t)}catch{}}sendJson(e,r){if(e.readyState===p.OPEN)try{e.send(JSON.stringify(r))}catch{}}closeClient(e,r,t){if(this.clients.has(e)){if(this.clients.delete(e),e.unsubscribe){try{e.unsubscribe()}catch{}e.unsubscribe=null}if(this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.socket.readyState===p.OPEN)try{e.socket.close(r,t)}catch{}}}startMainHeartbeat(){this.mainHeartbeat||(this.mainHeartbeat=setInterval(()=>{const e=Date.now();for(const r of Array.from(this.clients)){if(r.socket.readyState===p.OPEN)try{r.socket.ping()}catch{}e-r.lastPongAt>this.config.idleTimeoutMs&&this.closeClient(r,1001,"idle timeout")}},this.config.heartbeatMs),this.mainHeartbeat.unref&&this.mainHeartbeat.unref())}stopMainHeartbeat(){this.mainHeartbeat&&(clearInterval(this.mainHeartbeat),this.mainHeartbeat=null)}broadcastListenerUpdate(e,r,t){const s={type:"listener_update",agentId:e,browserId:r,listeners:t};for(const o of this.clients)o.agentId===e&&o.browserId===r&&this.sendJson(o.socket,s)}broadcastListenerTriggered(e,r,t){const s={type:"listener_triggered",agentId:e,browserId:r,...t};for(const o of this.clients)o.agentId===e&&o.browserId===r&&this.sendJson(o.socket,s)}}let h=null;async function B(g,e){return h||(h=new E(g,e),await h.start()),h}async function O(){h&&(await h.stop(),h=null)}export{E as BrowserWsServer,B as getBrowserWsServer,O as stopBrowserWsServer};
2
+
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import I from"express";import E from"cors";import{existsSync as D,readFileSync as B}from"node:fs";import x from"node:path";import O from"node:os";import{allowedCorsOrigins as P,port as w,validateProductionToken as G}from"./config.js";import{propertiesRouter as F}from"./routes/properties.js";import{ymlRouter as K}from"./routes/yml.js";import{instanceRouter as M,setGracefulShutdownFn as N}from"./routes/instance.js";import{skillsRouter as _}from"./routes/skills.js";import{mcpRouter as L}from"./routes/mcp.js";import{terminalRouter as j,sdkSessions as S}from"./routes/terminal.js";import{sessionsRouter as U}from"./routes/sessions.js";import{gitRouter as W}from"./routes/git.js";import{fileSnapshotRouter as z}from"./routes/file-snapshot.js";import{acodeTodosRouter as J}from"./routes/acode-todos.js";import{subAgentsRouter as Y}from"./routes/sub-agents.js";import{fileBrowserRouter as H}from"./routes/file-browser.js";import{aiSourcesRouter as Z}from"./routes/ai-sources.js";import{processesRouter as q}from"./routes/processes.js";import{systemMetricsRouter as Q}from"./routes/system-metrics.js";import{taskContextRouter as V}from"./routes/task-context.js";import{fileDiffRollbackRouter as X}from"./routes/file-diff-rollback.js";import{attachPtyWebSocketServer as ee,closeAllPtySessions as re,ptyRouter as te,ptySessions as ie}from"./routes/pty.js";import{runtimeBindingRouter as ne,logRuntimeBindingStartupState as oe}from"./routes/runtime-binding.js";import{dashboardRouter as se}from"./routes/dashboard.js";import{eventsRouter as ae}from"./routes/events.js";import{loadPersistedSessions as y,savePersistedSessions as $}from"./services/terminal-persistence.js";import{detectOrphanProcesses as me}from"./services/process-detector.js";import{startOrphanMonitor as ue,stopOrphanMonitor as ce}from"./services/orphan-monitor.js";import{getAgentProcessManager as C}from"./services/agent-process-manager.js";import{adapterRegistry as de}from"./adapter/index.js";import{logger as e}from"./utils/logger.js";import{autoRegister as pe,unregister as ge,bridgeRestartCleanup as fe,cancelBackgroundRegisterRetries as le}from"./services/auto-register.js";import{stopTunnelClient as be}from"./services/tunnel-client.js";import{ensureAwsClientAgentMcpReleased as he}from"./services/aws-client-agent-mcp.js";import{ensureAcodePackageReleased as we}from"./services/acode-package.js";import{ensureStartupConfig as Se}from"./services/startup-config-wizard.js";import{handleCliCommand as Re}from"./services/cli-commands.js";import{migrateOldPathsOnStartup as Ie}from"./services/legacy-path-migration.js";import{subAgentStore as Pe}from"./services/sub-agent-manager-instance.js";import{buildGracefulShutdownPlan as ye,shouldCleanupPersistedSessionsOnStartup as $e}from"./services/runtime-lifecycle-policy.js";import{deliverPendingBridgeLifecycleNotifications as Ce}from"./services/lifecycle-state.js";const k=await Re();k.handled&&process.exit(k.exitCode),await Se(),G(),he(),we(),Ie(),oe();async function ke(){try{if(await pe())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:i}=await import("./services/auto-register.js"),o=i();!!o.userKey&&o.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info("[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ~/.aws-bridge/config.json"))}}catch(r){const i=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",i.message)}}ke().then(()=>Te()).then(()=>Ce()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)});async function Te(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),i=r();if(!i.registered||!i.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const o=await fe();o.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${o.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${o.error}`)}catch(r){const i=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",i.message)}}async function ve(){try{const r=await y();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await C().rebuildRegistry(r.map(o=>({agentId:o.agentId,sessionId:o.sessionId,pid:o.pid,workspacePath:o.workspacePath,command:o.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const i=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",i.message)}}ve().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function Ae(){try{const r=await import("node:fs/promises"),i=await import("node:path"),o=await import("node:os"),f=i.join(o.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await y();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!$e(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await C().rebuildRegistry(a.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const c=await me(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(c.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${c.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of c)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of c)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:s}=await import("node:child_process");s(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(s){const d=s;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${d.message}`)}await new Promise(t=>setTimeout(t,1e3))}await $([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${c.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const i=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",i.message)}}Ae().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),ue().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const n=I();n.use(E({origin(r,i){if(!r){i(null,!0);return}if(P.includes("*")){i(null,!0);return}if(P.includes(r)){i(null,!0);return}try{if(new URL(r).port===String(w)){i(null,!0);return}}catch{}i(new Error(`[runtime-bridge] CORS origin is not allowed: ${r}`))}})),n.use(I.json({limit:"1mb"})),n.use("/runtime",ne),n.use("/runtime",F),n.use("/runtime",K),n.use("/runtime",M),n.use("/runtime",_),n.use("/runtime",L),n.use("/runtime",j),n.use("/runtime",U),n.use("/runtime",q),n.use("/runtime",Q),n.use("/runtime",ae),n.use("/runtime",W),n.use("/runtime",z),n.use("/runtime",J),n.use("/runtime",Y),n.use("/runtime",Z),n.use("/runtime",V),n.use("/runtime",X),n.use("/pty",te),n.use("/",se),n.use("/api/file-browser",H);function Ee(){const r=n.listen(w,()=>{e.info(`[runtime-bridge] listening on ${w}`)});return ee(r),r.on("error",i=>{if(i.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${w} is already in use. Stop the existing runtime-bridge process or set AWS_RUNTIME_BRIDGE_PORT to another port before starting.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",i),process.exitCode=1}),r}let T=!1;async function b(r,i,o=!1){if(T){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}T=!0,o||R()&&(o=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${o})`);const f=Date.now(),u=ye(o);try{const a=S.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,s]of S.entries())try{const d=s.providerId||"claude-code",p=de.get(d);let g="";try{const m=p.getSessionPid?.(t);m&&(g=` (PID: ${m})`)}catch{}await p.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${g}`),S.delete(t)}catch(d){const p=d;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,p.message),S.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=ie.size;if(u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),re("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`),e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7..."),ce(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:s}=await import("./services/process-detector.js"),{loadPersistedSessions:d}=await import("./services/terminal-persistence.js"),p=await d();if(p.length>0){const g=await t(p.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(g.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${g.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of g)if(m.process.pid){const A=await s(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${A.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const s=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",s.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await ge()}catch(t){const s=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(le(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),be()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await $([])}catch(t){const s=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");const c=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${c}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),i.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}Pe.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const h=Ee(),v=x.join(O.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(D(v)){const r=B(v,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}N(async(r,i)=>{await b(r,h,i)}),process.on("SIGTERM",()=>{const r=R();b("SIGTERM",h,r)}),process.on("SIGINT",()=>{const r=R();b("SIGINT",h,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=R();b("SIGBREAK",h,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",h)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
2
+ import I from"express";import B from"cors";import{existsSync as D,readFileSync as E}from"node:fs";import x from"node:path";import M from"node:os";import{allowedCorsOrigins as y,port as h,validateProductionToken as O}from"./config.js";import{propertiesRouter as G}from"./routes/properties.js";import{ymlRouter as _}from"./routes/yml.js";import{instanceRouter as F,setGracefulShutdownFn as K}from"./routes/instance.js";import{skillsRouter as L}from"./routes/skills.js";import{mcpRouter as N}from"./routes/mcp.js";import{terminalRouter as j,sdkSessions as S}from"./routes/terminal.js";import{sessionsRouter as W}from"./routes/sessions.js";import{gitRouter as U}from"./routes/git.js";import{fileSnapshotRouter as z}from"./routes/file-snapshot.js";import{acodeTodosRouter as J}from"./routes/acode-todos.js";import{backgroundTasksRouter as Y}from"./routes/background-tasks.js";import{subAgentsRouter as q}from"./routes/sub-agents.js";import{browserSessionsRouter as H}from"./routes/browser-sessions.js";import{browserListenersRouter as Z}from"./routes/browser-listeners.js";import{fileBrowserRouter as Q}from"./routes/file-browser.js";import{aiSourcesRouter as V}from"./routes/ai-sources.js";import{processesRouter as X}from"./routes/processes.js";import{systemMetricsRouter as ee}from"./routes/system-metrics.js";import{taskContextRouter as re}from"./routes/task-context.js";import{fileDiffRollbackRouter as te}from"./routes/file-diff-rollback.js";import{attachPtyWebSocketServer as ie,closeAllPtySessions as ne,ptyRouter as oe,ptySessions as se}from"./routes/pty.js";import{runtimeBindingRouter as ae,logRuntimeBindingStartupState as me}from"./routes/runtime-binding.js";import{dashboardRouter as ue}from"./routes/dashboard.js";import{eventsRouter as ce}from"./routes/events.js";import{attachRemoteDesktopWebSocketServer as de}from"./remote-desktop/index.js";import{attachBrowserWebSocketServer as ge}from"./browser/browser-ws-bridge.js";import{loadPersistedSessions as P,savePersistedSessions as $}from"./services/terminal-persistence.js";import{detectOrphanProcesses as pe}from"./services/process-detector.js";import{startOrphanMonitor as fe,stopOrphanMonitor as le}from"./services/orphan-monitor.js";import{getAgentProcessManager as k}from"./services/agent-process-manager.js";import{adapterRegistry as be}from"./adapter/index.js";import{logger as e}from"./utils/logger.js";import{autoRegister as we,unregister as he,bridgeRestartCleanup as Se,cancelBackgroundRegisterRetries as Re}from"./services/auto-register.js";import{stopTunnelClient as Ie}from"./services/tunnel-client.js";import{ensureAwsClientAgentMcpReleased as ye}from"./services/aws-client-agent-mcp.js";import{ensureAcodePackageReleased as Pe}from"./services/acode-package.js";import{ensureStartupConfig as $e}from"./services/startup-config-wizard.js";import{handleCliCommand as ke}from"./services/cli-commands.js";import{migrateOldPathsOnStartup as Ce}from"./services/legacy-path-migration.js";import{subAgentStore as Te}from"./services/sub-agent-manager-instance.js";import{disposeBrowserSessionManager as ve}from"./services/browser-session-manager.js";import{buildGracefulShutdownPlan as Ae,shouldCleanupPersistedSessionsOnStartup as Be}from"./services/runtime-lifecycle-policy.js";import{deliverPendingBridgeLifecycleNotifications as De}from"./services/lifecycle-state.js";const C=await ke();C.handled&&process.exit(C.exitCode),await $e(),O(),ye(),Pe(),Ce(),me();async function Ee(){try{if(await we())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:i}=await import("./services/auto-register.js"),s=i();!!s.userKey&&s.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info("[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ~/.aws-bridge/config.json"))}}catch(r){const i=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",i.message)}}Ee().then(()=>xe()).then(()=>De()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)});async function xe(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),i=r();if(!i.registered||!i.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const s=await Se();s.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${s.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${s.error}`)}catch(r){const i=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",i.message)}}async function Me(){try{const r=await P();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await k().rebuildRegistry(r.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const i=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",i.message)}}Me().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function Oe(){try{const r=await import("node:fs/promises"),i=await import("node:path"),s=await import("node:os"),f=i.join(s.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await P();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Be(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await k().rebuildRegistry(a.map(o=>({agentId:o.agentId,sessionId:o.sessionId,pid:o.pid,workspacePath:o.workspacePath,command:o.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await pe(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:o}=await import("node:child_process");o(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(o){const c=o;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await $([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const i=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",i.message)}}Oe().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),fe().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const n=I();n.use(B({origin(r,i){if(!r){i(null,!0);return}if(y.includes("*")){i(null,!0);return}if(y.includes(r)){i(null,!0);return}try{if(new URL(r).port===String(h)){i(null,!0);return}}catch{}i(new Error(`[runtime-bridge] CORS origin is not allowed: ${r}`))}})),n.use(I.json({limit:"1mb"})),n.use("/runtime",ae),n.use("/runtime",G),n.use("/runtime",_),n.use("/runtime",F),n.use("/runtime",L),n.use("/runtime",N),n.use("/runtime",j),n.use("/runtime",W),n.use("/runtime",X),n.use("/runtime",ee),n.use("/runtime",ce),n.use("/runtime",U),n.use("/runtime",z),n.use("/runtime",J),n.use("/runtime",Y),n.use("/runtime",q),n.use("/runtime",H),n.use("/runtime",Z),n.use("/runtime",V),n.use("/runtime",re),n.use("/runtime",te),n.use("/pty",oe),n.use("/",ue),n.use("/api/file-browser",Q);function Ge(){const r=n.listen(h,()=>{e.info(`[runtime-bridge] listening on ${h}`)});return ie(r),de(r),ge(r),r.on("error",i=>{if(i.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${h} is already in use. Stop the existing runtime-bridge process or set AWS_RUNTIME_BRIDGE_PORT to another port before starting.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",i),process.exitCode=1}),r}let T=!1;async function b(r,i,s=!1){if(T){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}T=!0,s||R()&&(s=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${s})`);const f=Date.now(),u=Ae(s);try{const a=S.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,o]of S.entries())try{const c=o.providerId||"claude-code",g=be.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),S.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),S.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=se.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),ne("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`),e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+require("path").join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(le(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:o}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const A=await o(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${A.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const o=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",o.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await he()}catch(t){const o=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",o.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(Re(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Ie()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await $([])}catch(t){const o=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",o.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await ve(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),i.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}Te.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const w=Ge(),v=x.join(M.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(D(v)){const r=E(v,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}K(async(r,i)=>{await b(r,w,i)}),process.on("SIGTERM",()=>{const r=R();b("SIGTERM",w,r)}),process.on("SIGINT",()=>{const r=R();b("SIGINT",w,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=R();b("SIGBREAK",w,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",w)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
3
3
 
@@ -5,4 +5,6 @@ export declare function isRuntimeTokenValid(token: unknown): boolean;
5
5
 
6
6
  export declare function validateToken(req: Request, res: Response, next: NextFunction): void;
7
7
 
8
+ export declare function validateTokenOrLoopback(req: Request, res: Response, next: NextFunction): void;
9
+
8
10
  export declare function validateTokenOrPanelSession(req: Request, res: Response, next: NextFunction): void;
@@ -1,2 +1,2 @@
1
- import{hasRuntimeBinding as u,validateRuntimeBindingToken as c}from"../services/runtime-binding.js";import{getConfiguredConnectionKeys as f}from"../services/auto-register.js";import{validateSession as d}from"../services/panel-auth.js";function o(n){const t=n.header("X-Runtime-Token");return t?t.trim():(n.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||""}function m(n){return n?!!f().includes(n):!1}function s(n){const t=String(n||"").trim();return c(t)||m(t)}function v(n,t,e){const i=o(n);if(s(i)){e();return}if(!u()){t.status(401).json({error:"runtime_bridge_unpaired",message:"Runtime bridge is not paired. Add this instance from the panel first."});return}t.status(401).json({error:"unauthorized"})}const l="panel_sid";function h(n){const t={};if(!n)return t;for(const e of n.split(";")){const i=e.indexOf("=");if(i===-1)continue;const r=e.slice(0,i).trim(),a=e.slice(i+1).trim();r&&(t[r]=a)}return t}function k(n){return h(n.headers.cookie)[l]}function x(n,t,e){const i=o(n);if(s(i)){e();return}const r=k(n);if(r&&d(r)){e();return}t.status(401).json({error:"unauthorized"})}export{s as isRuntimeTokenValid,v as validateToken,x as validateTokenOrPanelSession};
1
+ import{hasRuntimeBinding as u,validateRuntimeBindingToken as c}from"../services/runtime-binding.js";import{getConfiguredConnectionKeys as f}from"../services/auto-register.js";import{validateSession as d}from"../services/panel-auth.js";function o(n){const t=n.header("X-Runtime-Token");return t?t.trim():(n.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||""}function m(n){return n?!!f().includes(n):!1}function s(n){const t=String(n||"").trim();return c(t)||m(t)}function l(n,t,e){const i=o(n);if(s(i)){e();return}if(!u()){t.status(401).json({error:"runtime_bridge_unpaired",message:"Runtime bridge is not paired. Add this instance from the panel first."});return}t.status(401).json({error:"unauthorized"})}function x(n,t,e){const i=n.ip||n.socket.remoteAddress||"";if(i==="127.0.0.1"||i==="::1"||i==="::ffff:127.0.0.1"){e();return}l(n,t,e)}const k="panel_sid";function p(n){const t={};if(!n)return t;for(const e of n.split(";")){const i=e.indexOf("=");if(i===-1)continue;const r=e.slice(0,i).trim(),a=e.slice(i+1).trim();r&&(t[r]=a)}return t}function h(n){return p(n.headers.cookie)[k]}function z(n,t,e){const i=o(n);if(s(i)){e();return}const r=h(n);if(r&&d(r)){e();return}t.status(401).json({error:"unauthorized"})}export{s as isRuntimeTokenValid,l as validateToken,x as validateTokenOrLoopback,z as validateTokenOrPanelSession};
2
2
 
@@ -0,0 +1,30 @@
1
+ import type { ScreenCapture } from "./screen-capture.js";
2
+ import type { InputBackend } from "./input-backends/interface.js";
3
+ import type { ScreenInfo, ScreenshotResult, AppInfo, UIElement } from "./types.js";
4
+
5
+ export declare class ComputerControl {
6
+ private screenCapture;
7
+ private inputBackend;
8
+ private uiAutomation;
9
+ constructor(screenCapture: ScreenCapture, inputBackend: InputBackend);
10
+ screenshot(screenId?: string): Promise<ScreenshotResult>;
11
+ moveMouse(x: number, y: number): Promise<void>;
12
+ click(x: number, y: number, button?: 'left' | 'right'): Promise<void>;
13
+ doubleClick(x: number, y: number): Promise<void>;
14
+ mouseDown(button?: 'left' | 'right'): Promise<void>;
15
+ mouseUp(button?: 'left' | 'right'): Promise<void>;
16
+ scroll(direction: 'up' | 'down' | 'left' | 'right', amount: number): Promise<void>;
17
+ type(text: string): Promise<void>;
18
+ keyPress(keys: string[]): Promise<void>;
19
+ keyDown(key: string): Promise<void>;
20
+ keyUp(key: string): Promise<void>;
21
+ listScreens(): Promise<ScreenInfo[]>;
22
+ getScreenSize(): {
23
+ width: number;
24
+ height: number;
25
+ };
26
+ listApplications(): Promise<AppInfo[]>;
27
+ getUIElements(pid: number): Promise<UIElement[]>;
28
+ clickElement(elementId: string): Promise<void>;
29
+ setElementValue(elementId: string, value: string): Promise<void>;
30
+ }
@@ -0,0 +1,2 @@
1
+ import{UIAutomation as i}from"./ui-automation.js";class c{constructor(t,e){this.screenCapture=t,this.inputBackend=e,this.uiAutomation=new i}async screenshot(t){return this.screenCapture.captureVirtualDesktop()}async moveMouse(t,e){await this.inputBackend.moveMouse(t,e)}async click(t,e,n="left"){await this.inputBackend.click(t,e,n)}async doubleClick(t,e){await this.inputBackend.doubleClick(t,e)}async mouseDown(t="left"){await this.inputBackend.mouseDown(t)}async mouseUp(t="left"){await this.inputBackend.mouseUp(t)}async scroll(t,e){await this.inputBackend.scroll(t,e)}async type(t){await this.inputBackend.type(t)}async keyPress(t){await this.inputBackend.keyPress(t)}async keyDown(t){await this.inputBackend.keyDown(t)}async keyUp(t){await this.inputBackend.keyUp(t)}async listScreens(){return this.screenCapture.listScreens()}getScreenSize(){return this.inputBackend.getScreenSize()}async listApplications(){return this.uiAutomation.listApplications()}async getUIElements(t){return this.uiAutomation.getUIElements(t)}async clickElement(t){return this.uiAutomation.clickElement(t)}async setElementValue(t,e){return this.uiAutomation.setElementValue(t,e)}}export{c as ComputerControl};
2
+