aws-runtime-bridge 1.3.1 → 1.3.5

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 (61) hide show
  1. package/README.md +17 -3
  2. package/dist/config.d.ts +1 -7
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +2 -18
  5. package/dist/middleware/auth.d.ts +2 -2
  6. package/dist/middleware/auth.d.ts.map +1 -1
  7. package/dist/middleware/auth.js +4 -10
  8. package/dist/routes/instance.d.ts.map +1 -1
  9. package/dist/routes/instance.js +8 -2
  10. package/dist/routes/runtime-binding.d.ts.map +1 -1
  11. package/dist/routes/runtime-binding.js +3 -11
  12. package/dist/services/auto-register.d.ts.map +1 -1
  13. package/dist/services/auto-register.js +15 -8
  14. package/dist/services/auto-register.test.js +4 -0
  15. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  16. package/dist/services/aws-client-agent-mcp.js +1 -6
  17. package/dist/services/aws-client-agent-mcp.test.js +0 -2
  18. package/dist/services/cli-commands.d.ts +7 -0
  19. package/dist/services/cli-commands.d.ts.map +1 -1
  20. package/dist/services/cli-commands.js +214 -4
  21. package/dist/services/cli-commands.test.js +140 -2
  22. package/dist/services/orphan-monitor.d.ts.map +1 -1
  23. package/dist/services/orphan-monitor.js +8 -2
  24. package/dist/services/runtime-binding.d.ts +1 -0
  25. package/dist/services/runtime-binding.d.ts.map +1 -1
  26. package/dist/services/runtime-binding.js +31 -3
  27. package/dist/services/runtime-binding.test.js +42 -2
  28. package/dist/services/session-output.d.ts.map +1 -1
  29. package/dist/services/session-output.js +21 -4
  30. package/dist/utils/file-utils.d.ts.map +1 -1
  31. package/dist/utils/file-utils.js +7 -2
  32. package/dist/utils/file-utils.test.js +3 -1
  33. package/package/aws-client-agent-mcp/README.md +0 -1
  34. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +0 -1
  35. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  36. package/package/aws-client-agent-mcp/dist/agent-client.js +0 -12
  37. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  38. package/package/aws-client-agent-mcp/dist/agent-client.test.js +3 -11
  39. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
  40. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  41. package/package/aws-client-agent-mcp/dist/config.js +0 -1
  42. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  43. package/package/aws-client-agent-mcp/dist/config.test.js +0 -7
  44. package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -1
  45. package/package/aws-client-agent-mcp/dist/http-client.test.js +0 -1
  46. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  47. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  48. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +0 -3
  49. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  50. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +14 -5
  51. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
  52. package/package/aws-client-agent-mcp/dist/types.d.ts +4 -0
  53. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  54. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  55. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +3 -0
  56. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  57. package/package/aws-client-agent-mcp/dist/websocket-client.js +64 -5
  58. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  59. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +218 -0
  60. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  61. package/package.json +1 -1
@@ -1,8 +1,10 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { readFileSync } from "node:fs";
2
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { configureStartupConfig } from "./startup-config-wizard.js";
6
+ const SYSTEMD_SERVICE_NAME = "awsb.service";
7
+ const DEFAULT_SYSTEMD_UNIT_PATH = `/etc/systemd/system/${SYSTEMD_SERVICE_NAME}`;
6
8
  function getDefaultPackageRoot() {
7
9
  const currentFile = fileURLToPath(import.meta.url);
8
10
  return path.resolve(path.dirname(currentFile), "..", "..");
@@ -19,14 +21,215 @@ function defaultRunCommand(command, args) {
19
21
  });
20
22
  return { status: result.status, error: result.error };
21
23
  }
24
+ function defaultStdout(message) {
25
+ process.stdout.write(`${message}\n`);
26
+ }
27
+ function defaultStderr(message) {
28
+ process.stderr.write(`${message}\n`);
29
+ }
22
30
  function isVersionCommand(command) {
23
31
  return command === "-v" || command === "--version" || command === "version";
24
32
  }
33
+ function quoteSystemdExecArg(value) {
34
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
35
+ }
36
+ function getDefaultExecutablePath() {
37
+ return process.argv[1]
38
+ ? path.resolve(process.argv[1])
39
+ : fileURLToPath(import.meta.url);
40
+ }
41
+ /**
42
+ * 生成 systemd unit 内容,主流程是用当前 Node 可执行文件启动当前 CLI 入口。
43
+ */
44
+ export function createSystemdUnitContent(executablePath) {
45
+ const execStart = [process.execPath, executablePath]
46
+ .map((part) => quoteSystemdExecArg(part))
47
+ .join(" ");
48
+ return [
49
+ "[Unit]",
50
+ "Description=AgentsWorkStudio Runtime Bridge",
51
+ "After=network-online.target",
52
+ "Wants=network-online.target",
53
+ "",
54
+ "[Service]",
55
+ "Type=simple",
56
+ "Environment=AWS_BRIDGE_SKIP_SETUP=true",
57
+ `ExecStart=${execStart}`,
58
+ "Restart=on-failure",
59
+ "RestartSec=5s",
60
+ "",
61
+ "[Install]",
62
+ "WantedBy=multi-user.target",
63
+ "",
64
+ ].join("\n");
65
+ }
66
+ function runSystemctl(runCommand, args) {
67
+ return runCommand("systemctl", args);
68
+ }
69
+ function systemctlFailureMessage(action, result) {
70
+ if (result.error) {
71
+ return `[runtime-bridge] ${action}失败: ${result.error.message}`;
72
+ }
73
+ return `[runtime-bridge] ${action}失败,systemctl 退出码: ${result.status ?? "unknown"}`;
74
+ }
75
+ function commandSucceeded(result) {
76
+ return !result.error && result.status === 0;
77
+ }
78
+ function ensureLinuxSystemd(platform, stderr) {
79
+ if (platform === "linux") {
80
+ return true;
81
+ }
82
+ stderr("[runtime-bridge] service 命令仅支持 Linux systemd 环境。");
83
+ return false;
84
+ }
85
+ function printServiceUsage(stdout) {
86
+ stdout("Usage: awsb service <install|uninstall>");
87
+ }
88
+ /**
89
+ * 安装 systemd 服务,主干流程是写入 unit、重载 systemd、启用开机自启,并在未运行时启动服务。
90
+ */
91
+ function installSystemdService(options) {
92
+ if (!ensureLinuxSystemd(options.platform, options.stderr)) {
93
+ return { handled: true, exitCode: 1 };
94
+ }
95
+ const unitContent = createSystemdUnitContent(options.executablePath);
96
+ try {
97
+ mkdirSync(path.dirname(options.serviceUnitPath), { recursive: true });
98
+ writeFileSync(options.serviceUnitPath, unitContent, {
99
+ encoding: "utf-8",
100
+ mode: 0o644,
101
+ });
102
+ }
103
+ catch (error) {
104
+ const err = error instanceof Error ? error : new Error(String(error));
105
+ options.stderr(`[runtime-bridge] 写入 systemd unit 失败: ${err.message}`);
106
+ return { handled: true, exitCode: 1 };
107
+ }
108
+ const daemonReloadResult = runSystemctl(options.runCommand, ["daemon-reload"]);
109
+ if (!commandSucceeded(daemonReloadResult)) {
110
+ options.stderr(systemctlFailureMessage("重载 systemd", daemonReloadResult));
111
+ return { handled: true, exitCode: daemonReloadResult.status ?? 1 };
112
+ }
113
+ const enableResult = runSystemctl(options.runCommand, [
114
+ "enable",
115
+ SYSTEMD_SERVICE_NAME,
116
+ ]);
117
+ if (!commandSucceeded(enableResult)) {
118
+ options.stderr(systemctlFailureMessage("启用 awsb 开机自启", enableResult));
119
+ return { handled: true, exitCode: enableResult.status ?? 1 };
120
+ }
121
+ const activeResult = runSystemctl(options.runCommand, [
122
+ "is-active",
123
+ "--quiet",
124
+ SYSTEMD_SERVICE_NAME,
125
+ ]);
126
+ if (activeResult.error) {
127
+ options.stderr(systemctlFailureMessage("检查 awsb 服务状态", activeResult));
128
+ return { handled: true, exitCode: 1 };
129
+ }
130
+ if (activeResult.status !== 0) {
131
+ const startResult = runSystemctl(options.runCommand, [
132
+ "start",
133
+ SYSTEMD_SERVICE_NAME,
134
+ ]);
135
+ if (!commandSucceeded(startResult)) {
136
+ options.stderr(systemctlFailureMessage("启动 awsb 服务", startResult));
137
+ return { handled: true, exitCode: startResult.status ?? 1 };
138
+ }
139
+ options.stdout("[runtime-bridge] awsb systemd 服务已安装、已启用开机自启并已启动。");
140
+ return { handled: true, exitCode: 0 };
141
+ }
142
+ options.stdout("[runtime-bridge] awsb systemd 服务已安装并已启用开机自启;服务已在运行。");
143
+ return { handled: true, exitCode: 0 };
144
+ }
145
+ /**
146
+ * 卸载 systemd 服务,主干流程是按需停止、禁用自启、删除 unit,并重载 systemd。
147
+ */
148
+ function uninstallSystemdService(options) {
149
+ if (!ensureLinuxSystemd(options.platform, options.stderr)) {
150
+ return { handled: true, exitCode: 1 };
151
+ }
152
+ const unitExists = existsSync(options.serviceUnitPath);
153
+ const activeResult = runSystemctl(options.runCommand, [
154
+ "is-active",
155
+ "--quiet",
156
+ SYSTEMD_SERVICE_NAME,
157
+ ]);
158
+ if (activeResult.error) {
159
+ options.stderr(systemctlFailureMessage("检查 awsb 服务状态", activeResult));
160
+ return { handled: true, exitCode: 1 };
161
+ }
162
+ if (activeResult.status === 0) {
163
+ const stopResult = runSystemctl(options.runCommand, [
164
+ "stop",
165
+ SYSTEMD_SERVICE_NAME,
166
+ ]);
167
+ if (!commandSucceeded(stopResult)) {
168
+ options.stderr(systemctlFailureMessage("停止 awsb 服务", stopResult));
169
+ return { handled: true, exitCode: stopResult.status ?? 1 };
170
+ }
171
+ }
172
+ const disableResult = runSystemctl(options.runCommand, [
173
+ "disable",
174
+ SYSTEMD_SERVICE_NAME,
175
+ ]);
176
+ if (disableResult.error || (disableResult.status !== 0 && unitExists)) {
177
+ options.stderr(systemctlFailureMessage("禁用 awsb 开机自启", disableResult));
178
+ return { handled: true, exitCode: disableResult.status ?? 1 };
179
+ }
180
+ if (unitExists) {
181
+ try {
182
+ unlinkSync(options.serviceUnitPath);
183
+ }
184
+ catch (error) {
185
+ const err = error instanceof Error ? error : new Error(String(error));
186
+ options.stderr(`[runtime-bridge] 删除 systemd unit 失败: ${err.message}`);
187
+ return { handled: true, exitCode: 1 };
188
+ }
189
+ }
190
+ else {
191
+ options.stdout("[runtime-bridge] awsb systemd unit 不存在,跳过删除。");
192
+ }
193
+ const daemonReloadResult = runSystemctl(options.runCommand, ["daemon-reload"]);
194
+ if (!commandSucceeded(daemonReloadResult)) {
195
+ options.stderr(systemctlFailureMessage("重载 systemd", daemonReloadResult));
196
+ return { handled: true, exitCode: daemonReloadResult.status ?? 1 };
197
+ }
198
+ options.stdout("[runtime-bridge] awsb systemd 服务已卸载。");
199
+ return { handled: true, exitCode: 0 };
200
+ }
201
+ function handleServiceCommand(argv, options, stdout, stderr) {
202
+ const subcommand = argv[1];
203
+ if (!subcommand ||
204
+ subcommand === "-h" ||
205
+ subcommand === "--help" ||
206
+ subcommand === "help") {
207
+ printServiceUsage(stdout);
208
+ return { handled: true, exitCode: subcommand ? 0 : 1 };
209
+ }
210
+ const serviceOptions = {
211
+ stdout,
212
+ stderr,
213
+ runCommand: options.runCommand || defaultRunCommand,
214
+ platform: options.platform || process.platform,
215
+ serviceUnitPath: options.serviceUnitPath || DEFAULT_SYSTEMD_UNIT_PATH,
216
+ executablePath: options.executablePath || getDefaultExecutablePath(),
217
+ };
218
+ if (subcommand === "install") {
219
+ return installSystemdService(serviceOptions);
220
+ }
221
+ if (subcommand === "uninstall") {
222
+ return uninstallSystemdService(serviceOptions);
223
+ }
224
+ stderr(`[runtime-bridge] 未知 service 子命令: ${subcommand}`);
225
+ printServiceUsage(stdout);
226
+ return { handled: true, exitCode: 1 };
227
+ }
25
228
  export async function handleCliCommand(options = {}) {
26
229
  const argv = options.argv || process.argv.slice(2);
27
230
  const command = argv[0];
28
- const stdout = options.stdout || console.log;
29
- const stderr = options.stderr || console.error;
231
+ const stdout = options.stdout || defaultStdout;
232
+ const stderr = options.stderr || defaultStderr;
30
233
  if (isVersionCommand(command)) {
31
234
  stdout(`aws-runtime-bridge ${readPackageVersion(options.packageRoot)}`);
32
235
  return { handled: true, exitCode: 0 };
@@ -34,7 +237,11 @@ export async function handleCliCommand(options = {}) {
34
237
  if (command === "update") {
35
238
  stdout("[runtime-bridge] 正在更新 aws-runtime-bridge 到最新版本...");
36
239
  const runCommand = options.runCommand || defaultRunCommand;
37
- const result = runCommand("npm", ["install", "-g", "aws-runtime-bridge@latest"]);
240
+ const result = runCommand("npm", [
241
+ "install",
242
+ "-g",
243
+ "aws-runtime-bridge@latest",
244
+ ]);
38
245
  if (result.error) {
39
246
  stderr(`[runtime-bridge] 更新失败: ${result.error.message}`);
40
247
  return { handled: true, exitCode: 1 };
@@ -51,5 +258,8 @@ export async function handleCliCommand(options = {}) {
51
258
  const result = await configure();
52
259
  return { handled: true, exitCode: result === "configured" ? 0 : 1 };
53
260
  }
261
+ if (command === "service") {
262
+ return handleServiceCommand(argv, options, stdout, stderr);
263
+ }
54
264
  return { handled: false, exitCode: 0 };
55
265
  }
@@ -1,8 +1,8 @@
1
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
1
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { afterEach, describe, expect, it } from "vitest";
5
- import { handleCliCommand, readPackageVersion } from "./cli-commands.js";
5
+ import { createSystemdUnitContent, handleCliCommand, readPackageVersion, } from "./cli-commands.js";
6
6
  const tempRoots = [];
7
7
  function createPackageRoot(version = "9.8.7") {
8
8
  const root = mkdtempSync(path.join(os.tmpdir(), "aws-bridge-cli-"));
@@ -11,6 +11,14 @@ function createPackageRoot(version = "9.8.7") {
11
11
  writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "aws-runtime-bridge", version }), "utf-8");
12
12
  return root;
13
13
  }
14
+ function createServiceUnitPath() {
15
+ const root = mkdtempSync(path.join(os.tmpdir(), "aws-bridge-service-"));
16
+ tempRoots.push(root);
17
+ return path.join(root, "systemd", "awsb.service");
18
+ }
19
+ function quotedSystemdArg(value) {
20
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
21
+ }
14
22
  afterEach(() => {
15
23
  for (const root of tempRoots.splice(0)) {
16
24
  rmSync(root, { recursive: true, force: true });
@@ -85,6 +93,136 @@ describe("cli commands", () => {
85
93
  });
86
94
  expect(result).toEqual({ handled: true, exitCode: 1 });
87
95
  });
96
+ it("creates a systemd unit that starts the current executable with setup skipped", () => {
97
+ const executablePath = "/opt/aws-runtime-bridge/dist/index.js";
98
+ const unit = createSystemdUnitContent(executablePath);
99
+ expect(unit).toContain("Description=AgentsWorkStudio Runtime Bridge");
100
+ expect(unit).toContain("Environment=AWS_BRIDGE_SKIP_SETUP=true");
101
+ expect(unit).toContain(`ExecStart=${quotedSystemdArg(process.execPath)} ${quotedSystemdArg(executablePath)}`);
102
+ expect(unit).toContain("Restart=on-failure");
103
+ expect(unit).toContain("WantedBy=multi-user.target");
104
+ });
105
+ it("installs service, enables autostart, and starts when inactive", async () => {
106
+ const output = [];
107
+ const commands = [];
108
+ const serviceUnitPath = createServiceUnitPath();
109
+ const executablePath = "/usr/local/bin/awsb";
110
+ const result = await handleCliCommand({
111
+ argv: ["service", "install"],
112
+ platform: "linux",
113
+ serviceUnitPath,
114
+ executablePath,
115
+ stdout: (message) => output.push(message),
116
+ runCommand: (command, args) => {
117
+ commands.push({ command, args });
118
+ if (args[0] === "is-active") {
119
+ return { status: 3 };
120
+ }
121
+ return { status: 0 };
122
+ },
123
+ });
124
+ expect(result).toEqual({ handled: true, exitCode: 0 });
125
+ expect(readFileSync(serviceUnitPath, "utf-8")).toContain(`ExecStart=${quotedSystemdArg(process.execPath)} ${quotedSystemdArg(executablePath)}`);
126
+ expect(commands).toEqual([
127
+ { command: "systemctl", args: ["daemon-reload"] },
128
+ { command: "systemctl", args: ["enable", "awsb.service"] },
129
+ { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
130
+ { command: "systemctl", args: ["start", "awsb.service"] },
131
+ ]);
132
+ expect(output.at(-1)).toBe("[runtime-bridge] awsb systemd 服务已安装、已启用开机自启并已启动。");
133
+ });
134
+ it("does not start service during install when it is already active", async () => {
135
+ const commands = [];
136
+ const serviceUnitPath = createServiceUnitPath();
137
+ const result = await handleCliCommand({
138
+ argv: ["service", "install"],
139
+ platform: "linux",
140
+ serviceUnitPath,
141
+ executablePath: "/usr/local/bin/awsb",
142
+ runCommand: (command, args) => {
143
+ commands.push({ command, args });
144
+ return { status: 0 };
145
+ },
146
+ });
147
+ expect(result).toEqual({ handled: true, exitCode: 0 });
148
+ expect(commands).toEqual([
149
+ { command: "systemctl", args: ["daemon-reload"] },
150
+ { command: "systemctl", args: ["enable", "awsb.service"] },
151
+ { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
152
+ ]);
153
+ });
154
+ it("uninstalls service by stopping, disabling, removing unit, and reloading systemd", async () => {
155
+ const output = [];
156
+ const commands = [];
157
+ const serviceUnitPath = createServiceUnitPath();
158
+ mkdirSync(path.dirname(serviceUnitPath), { recursive: true });
159
+ writeFileSync(serviceUnitPath, "unit", "utf-8");
160
+ const result = await handleCliCommand({
161
+ argv: ["service", "uninstall"],
162
+ platform: "linux",
163
+ serviceUnitPath,
164
+ stdout: (message) => output.push(message),
165
+ runCommand: (command, args) => {
166
+ commands.push({ command, args });
167
+ return { status: 0 };
168
+ },
169
+ });
170
+ expect(result).toEqual({ handled: true, exitCode: 0 });
171
+ expect(existsSync(serviceUnitPath)).toBe(false);
172
+ expect(commands).toEqual([
173
+ { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
174
+ { command: "systemctl", args: ["stop", "awsb.service"] },
175
+ { command: "systemctl", args: ["disable", "awsb.service"] },
176
+ { command: "systemctl", args: ["daemon-reload"] },
177
+ ]);
178
+ expect(output.at(-1)).toBe("[runtime-bridge] awsb systemd 服务已卸载。");
179
+ });
180
+ it("tolerates uninstall when service is inactive and unit is absent", async () => {
181
+ const output = [];
182
+ const commands = [];
183
+ const serviceUnitPath = createServiceUnitPath();
184
+ const result = await handleCliCommand({
185
+ argv: ["service", "uninstall"],
186
+ platform: "linux",
187
+ serviceUnitPath,
188
+ stdout: (message) => output.push(message),
189
+ runCommand: (command, args) => {
190
+ commands.push({ command, args });
191
+ if (args[0] === "is-active" || args[0] === "disable") {
192
+ return { status: 1 };
193
+ }
194
+ return { status: 0 };
195
+ },
196
+ });
197
+ expect(result).toEqual({ handled: true, exitCode: 0 });
198
+ expect(commands).toEqual([
199
+ { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
200
+ { command: "systemctl", args: ["disable", "awsb.service"] },
201
+ { command: "systemctl", args: ["daemon-reload"] },
202
+ ]);
203
+ expect(output).toContain("[runtime-bridge] awsb systemd unit 不存在,跳过删除。");
204
+ });
205
+ it("fails service commands clearly on non-linux platforms", async () => {
206
+ const errors = [];
207
+ const result = await handleCliCommand({
208
+ argv: ["service", "install"],
209
+ platform: "win32",
210
+ stderr: (message) => errors.push(message),
211
+ });
212
+ expect(result).toEqual({ handled: true, exitCode: 1 });
213
+ expect(errors).toEqual([
214
+ "[runtime-bridge] service 命令仅支持 Linux systemd 环境。",
215
+ ]);
216
+ });
217
+ it("prints service help for missing subcommand", async () => {
218
+ const output = [];
219
+ const result = await handleCliCommand({
220
+ argv: ["service"],
221
+ stdout: (message) => output.push(message),
222
+ });
223
+ expect(result).toEqual({ handled: true, exitCode: 1 });
224
+ expect(output).toEqual(["Usage: awsb service <install|uninstall>"]);
225
+ });
88
226
  it("does not handle normal startup arguments", async () => {
89
227
  const result = await handleCliCommand({ argv: [] });
90
228
  expect(result).toEqual({ handled: false, exitCode: 0 });
@@ -1 +1 @@
1
- {"version":3,"file":"orphan-monitor.d.ts","sourceRoot":"","sources":["../../src/services/orphan-monitor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,GACrB,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,OAAO,CAAkB;IAEjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0E3B;;OAEG;YACW,oBAAoB;IA8BlC;;OAEG;YACW,iBAAiB;IAgC/B;;OAEG;YACW,eAAe;IA0B7B;;OAEG;YACW,mBAAmB;IAsBjC;;OAEG;YACW,iBAAiB;IAwC/B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAOtD;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACH,SAAS,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAO3E;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
1
+ {"version":3,"file":"orphan-monitor.d.ts","sourceRoot":"","sources":["../../src/services/orphan-monitor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,GACrB,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,OAAO,CAAkB;IAEjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0E3B;;OAEG;YACW,oBAAoB;IA8BlC;;OAEG;YACW,iBAAiB;IAgC/B;;OAEG;YACW,eAAe;IA0B7B;;OAEG;YACW,mBAAmB;IAsBjC;;OAEG;YACW,iBAAiB;IA8C/B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAOtD;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACH,SAAS,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAO3E;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
@@ -6,7 +6,8 @@
6
6
  import { createLogger } from '../utils/logger.js';
7
7
  import { loadPersistedSessions, savePersistedSessions } from './terminal-persistence.js';
8
8
  import { detectOrphanProcesses, checkAllSessionsHealth, terminateProcessTree, waitForProcessExit } from './process-detector.js';
9
- import { ORPHAN_SCAN_INTERVAL, ORPHAN_AUTO_CLEAN_MODE, ORPHAN_SCAN_ENABLED, schedulerBaseUrl, runtimeToken } from '../config.js';
9
+ import { ORPHAN_SCAN_INTERVAL, ORPHAN_AUTO_CLEAN_MODE, ORPHAN_SCAN_ENABLED, schedulerBaseUrl } from '../config.js';
10
+ import { getRuntimeAccessToken } from './runtime-binding.js';
10
11
  const logger = createLogger('orphan-monitor');
11
12
  /**
12
13
  * 孤儿进程监控器
@@ -227,11 +228,16 @@ export class OrphanMonitor {
227
228
  return;
228
229
  }
229
230
  try {
231
+ const runtimeAccessToken = getRuntimeAccessToken(undefined, schedulerBaseUrl) || getRuntimeAccessToken();
232
+ if (!runtimeAccessToken) {
233
+ logger.debug(`缺少 runtimeAccessToken,跳过上报: ${eventType}`);
234
+ return;
235
+ }
230
236
  const response = await fetch(`${schedulerBaseUrl}/api/runtime/orphan-event`, {
231
237
  method: 'POST',
232
238
  headers: {
233
239
  'Content-Type': 'application/json',
234
- 'Authorization': `Bearer ${runtimeToken}`,
240
+ 'Authorization': `Bearer ${runtimeAccessToken}`,
235
241
  },
236
242
  body: JSON.stringify({
237
243
  agentId,
@@ -25,6 +25,7 @@ export declare function saveScopedRuntimeAccessToken(input: {
25
25
  accessToken: string;
26
26
  }): string;
27
27
  export declare function getScopedRuntimeAccessToken(userId: unknown, serverBaseUrl: unknown): string | undefined;
28
+ export declare function clearScopedRuntimeAccessToken(userId: unknown, serverBaseUrl: unknown): boolean;
28
29
  export declare function loadRuntimeBinding(): RuntimeBindingState;
29
30
  export declare function getRuntimeBindingPublicState(): Omit<RuntimeBindingState, "tokenHash" | "accessToken"> & {
30
31
  paired: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2DF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAoBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,CAYR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAepB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAwCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C"}
1
+ {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2DF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAiCD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,CAYR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,OAAO,CAeT;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAepB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAwCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C"}
@@ -99,15 +99,26 @@ function normalizeServerIp(serverBaseUrl) {
99
99
  .toLowerCase();
100
100
  }
101
101
  }
102
+ function normalizeRuntimeTokenServerUrl(serverBaseUrl) {
103
+ const normalized = normalizeSchedulerBaseUrl(serverBaseUrl);
104
+ if (normalized) {
105
+ return normalized;
106
+ }
107
+ const raw = String(serverBaseUrl || "").trim();
108
+ if (!raw) {
109
+ return "";
110
+ }
111
+ return raw.replace(/\/+$/, "").toLowerCase();
112
+ }
102
113
  export function buildRuntimeTokenKey(userId, serverBaseUrl) {
103
114
  const normalizedUserId = String(userId || "").trim();
104
- const serverIp = normalizeServerIp(serverBaseUrl);
105
- if (!normalizedUserId || !serverIp) {
115
+ const serverUrl = normalizeRuntimeTokenServerUrl(serverBaseUrl);
116
+ if (!normalizedUserId || !serverUrl) {
106
117
  throw new Error("userId and serverBaseUrl are required to build runtime token key");
107
118
  }
108
119
  return crypto
109
120
  .createHash("md5")
110
- .update(`${normalizedUserId}:${serverIp}`, "utf8")
121
+ .update(`${normalizedUserId}:${serverUrl}`, "utf8")
111
122
  .digest("hex");
112
123
  }
113
124
  function loadRuntimeTokenStore() {
@@ -168,6 +179,23 @@ export function getScopedRuntimeAccessToken(userId, serverBaseUrl) {
168
179
  return undefined;
169
180
  }
170
181
  }
182
+ export function clearScopedRuntimeAccessToken(userId, serverBaseUrl) {
183
+ if (!userId || !serverBaseUrl) {
184
+ return false;
185
+ }
186
+ try {
187
+ const key = buildRuntimeTokenKey(userId, serverBaseUrl);
188
+ const tokens = loadRuntimeTokenStore();
189
+ const removed = tokens.delete(key);
190
+ if (removed) {
191
+ saveRuntimeTokenStore(tokens);
192
+ }
193
+ return removed;
194
+ }
195
+ catch {
196
+ return false;
197
+ }
198
+ }
171
199
  function validateRuntimeTokenStore(token) {
172
200
  if (!token) {
173
201
  return false;
@@ -1,5 +1,25 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { normalizeSchedulerBaseUrl } from './runtime-binding.js';
1
+ import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { buildRuntimeTokenKey, clearScopedRuntimeAccessToken, getScopedRuntimeAccessToken, normalizeSchedulerBaseUrl, saveScopedRuntimeAccessToken, } from "./runtime-binding.js";
6
+ const originalEnv = { ...process.env };
7
+ const tempRoots = [];
8
+ function useRuntimeHome() {
9
+ const runtimeHome = mkdtempSync(path.join(os.tmpdir(), "aws-runtime-binding-"));
10
+ tempRoots.push(runtimeHome);
11
+ mkdirSync(runtimeHome, { recursive: true });
12
+ process.env.AWS_RUNTIME_HOME_DIR = runtimeHome;
13
+ process.env.HOME = runtimeHome;
14
+ process.env.USERPROFILE = runtimeHome;
15
+ return runtimeHome;
16
+ }
17
+ afterEach(() => {
18
+ process.env = { ...originalEnv };
19
+ for (const root of tempRoots.splice(0)) {
20
+ rmSync(root, { recursive: true, force: true });
21
+ }
22
+ });
3
23
  describe('runtime binding scheduler URL normalization', () => {
4
24
  it('repairs duplicated scheduler ports', () => {
5
25
  expect(normalizeSchedulerBaseUrl('http://127.0.0.1:8080:8080')).toBe('http://127.0.0.1:8080');
@@ -8,4 +28,24 @@ describe('runtime binding scheduler URL normalization', () => {
8
28
  expect(normalizeSchedulerBaseUrl('ws://127.0.0.1:8080/ws/agent')).toBe('http://127.0.0.1:8080');
9
29
  expect(normalizeSchedulerBaseUrl('wss://example.com/ws/agent')).toBe('https://example.com');
10
30
  });
31
+ it("scopes runtime tokens by user and full scheduler origin", () => {
32
+ useRuntimeHome();
33
+ const key7380 = saveScopedRuntimeAccessToken({
34
+ userId: "user-a",
35
+ serverBaseUrl: "http://scheduler.local:7380",
36
+ accessToken: "runtime-token-7380-123456",
37
+ });
38
+ const key8080 = saveScopedRuntimeAccessToken({
39
+ userId: "user-a",
40
+ serverBaseUrl: "http://scheduler.local:8080",
41
+ accessToken: "runtime-token-8080-123456",
42
+ });
43
+ expect(key7380).not.toBe(key8080);
44
+ expect(buildRuntimeTokenKey("user-a", "http://scheduler.local:7380/api")).toBe(key7380);
45
+ expect(getScopedRuntimeAccessToken("user-a", "http://scheduler.local:7380")).toBe("runtime-token-7380-123456");
46
+ expect(getScopedRuntimeAccessToken("user-a", "http://scheduler.local:8080")).toBe("runtime-token-8080-123456");
47
+ expect(clearScopedRuntimeAccessToken("user-a", "http://scheduler.local:7380")).toBe(true);
48
+ expect(getScopedRuntimeAccessToken("user-a", "http://scheduler.local:7380")).toBeUndefined();
49
+ expect(getScopedRuntimeAccessToken("user-a", "http://scheduler.local:8080")).toBe("runtime-token-8080-123456");
50
+ });
11
51
  });
@@ -1 +1 @@
1
- {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,IAAI,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBnC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
1
+ {"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAO3C,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,IAAI,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBnC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
@@ -4,7 +4,12 @@
4
4
  * 管理终端会话的输出缓冲和刷新机制
5
5
  */
6
6
  import axios from 'axios';
7
- import { schedulerBaseUrl, runtimeToken } from '../config.js';
7
+ import { schedulerBaseUrl } from '../config.js';
8
+ import { getRuntimeAccessToken } from './runtime-binding.js';
9
+ function runtimeAuthHeaders() {
10
+ const token = getRuntimeAccessToken(undefined, schedulerBaseUrl) || getRuntimeAccessToken();
11
+ return token ? { 'X-Runtime-Token': token } : undefined;
12
+ }
8
13
  /** 活跃会话存储 */
9
14
  export const sessions = new Map();
10
15
  /**
@@ -31,7 +36,11 @@ export async function sendStatus(agentId, sessionId, status, actionInfo, usage)
31
36
  payload.inputTokens = usage.inputTokens;
32
37
  payload.outputTokens = usage.outputTokens;
33
38
  }
34
- return axios.post(`${schedulerBaseUrl}/api/runtime/callback/status`, payload, { headers: { 'X-Runtime-Token': runtimeToken } }).catch(() => undefined);
39
+ const headers = runtimeAuthHeaders();
40
+ if (!headers) {
41
+ return undefined;
42
+ }
43
+ return axios.post(`${schedulerBaseUrl}/api/runtime/callback/status`, payload, { headers }).catch(() => undefined);
35
44
  }
36
45
  /**
37
46
  * 发送输出到调度器
@@ -43,7 +52,11 @@ export async function sendStatus(agentId, sessionId, status, actionInfo, usage)
43
52
  */
44
53
  export async function sendOutput(agentId, output, sessionId, seq) {
45
54
  try {
46
- await axios.post(`${schedulerBaseUrl}/api/runtime/callback/output`, { agentId, output, sessionId, seq }, { headers: { 'X-Runtime-Token': runtimeToken } });
55
+ const headers = runtimeAuthHeaders();
56
+ if (!headers) {
57
+ return;
58
+ }
59
+ await axios.post(`${schedulerBaseUrl}/api/runtime/callback/output`, { agentId, output, sessionId, seq }, { headers });
47
60
  }
48
61
  catch {
49
62
  // ignore transient callback failures
@@ -58,7 +71,11 @@ export async function sendOutput(agentId, output, sessionId, seq) {
58
71
  */
59
72
  export async function sendQuestionRequest(agentId, sessionId, questions) {
60
73
  try {
61
- await axios.post(`${schedulerBaseUrl}/api/runtime/callback/question`, { agentId, sessionId, questions }, { headers: { 'X-Runtime-Token': runtimeToken } });
74
+ const headers = runtimeAuthHeaders();
75
+ if (!headers) {
76
+ return;
77
+ }
78
+ await axios.post(`${schedulerBaseUrl}/api/runtime/callback/question`, { agentId, sessionId, questions }, { headers });
62
79
  }
63
80
  catch {
64
81
  // ignore transient callback failures
@@ -1 +1 @@
1
- {"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI5E,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAqBjG;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxF;AAED,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F;AAED,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0ChC;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhG;AAED,wBAAsB,oCAAoC,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASlG;AAED,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,QAAQ,CAW1E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAM1D;AAED,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhF;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,WAAW,EAChB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyBhC"}
1
+ {"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/utils/file-utils.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI5E,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAqBjG;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxF;AAED,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F;AAED,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA+ChC;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhG;AAED,wBAAsB,oCAAoC,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASlG;AAED,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,QAAQ,CAW1E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAM1D;AAED,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhF;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,WAAW,EAChB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyBhC"}