aws-runtime-bridge 1.1.1 → 1.1.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 (117) hide show
  1. package/dist/index.js +5 -0
  2. package/dist/services/auto-register.d.ts.map +1 -1
  3. package/dist/services/auto-register.js +40 -9
  4. package/dist/services/auto-register.test.d.ts +2 -0
  5. package/dist/services/auto-register.test.d.ts.map +1 -0
  6. package/dist/services/auto-register.test.js +154 -0
  7. package/dist/services/aws-client-agent-mcp.d.ts +6 -1
  8. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  9. package/dist/services/aws-client-agent-mcp.js +96 -20
  10. package/dist/services/aws-client-agent-mcp.test.js +74 -4
  11. package/dist/services/cli-commands.d.ts +20 -0
  12. package/dist/services/cli-commands.d.ts.map +1 -0
  13. package/dist/services/cli-commands.js +55 -0
  14. package/dist/services/cli-commands.test.d.ts +2 -0
  15. package/dist/services/cli-commands.test.d.ts.map +1 -0
  16. package/dist/services/cli-commands.test.js +92 -0
  17. package/dist/services/startup-config-wizard.d.ts +2 -1
  18. package/dist/services/startup-config-wizard.d.ts.map +1 -1
  19. package/dist/services/startup-config-wizard.js +69 -14
  20. package/dist/services/startup-config-wizard.test.js +83 -2
  21. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +166 -0
  22. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -0
  23. package/package/aws-client-agent-mcp/dist/agent-client.js +602 -0
  24. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -0
  25. package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts +2 -0
  26. package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts.map +1 -0
  27. package/package/aws-client-agent-mcp/dist/agent-client.test.js +534 -0
  28. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -0
  29. package/package/aws-client-agent-mcp/dist/config.d.ts +22 -0
  30. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -0
  31. package/package/aws-client-agent-mcp/dist/config.js +106 -0
  32. package/package/aws-client-agent-mcp/dist/config.js.map +1 -0
  33. package/package/aws-client-agent-mcp/dist/config.test.d.ts +2 -0
  34. package/package/aws-client-agent-mcp/dist/config.test.d.ts.map +1 -0
  35. package/package/aws-client-agent-mcp/dist/config.test.js +139 -0
  36. package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -0
  37. package/package/aws-client-agent-mcp/dist/constants.d.ts +15 -0
  38. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -0
  39. package/package/aws-client-agent-mcp/dist/constants.js +19 -0
  40. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -0
  41. package/package/aws-client-agent-mcp/dist/http-client.d.ts +28 -0
  42. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -0
  43. package/package/aws-client-agent-mcp/dist/http-client.js +96 -0
  44. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -0
  45. package/package/aws-client-agent-mcp/dist/http-client.test.d.ts +2 -0
  46. package/package/aws-client-agent-mcp/dist/http-client.test.d.ts.map +1 -0
  47. package/package/aws-client-agent-mcp/dist/http-client.test.js +228 -0
  48. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -0
  49. package/package/aws-client-agent-mcp/dist/index.d.ts +14 -0
  50. package/package/aws-client-agent-mcp/dist/index.d.ts.map +1 -0
  51. package/package/aws-client-agent-mcp/dist/index.js +30 -0
  52. package/package/aws-client-agent-mcp/dist/index.js.map +1 -0
  53. package/package/aws-client-agent-mcp/dist/logger.d.ts +7 -0
  54. package/package/aws-client-agent-mcp/dist/logger.d.ts.map +1 -0
  55. package/package/aws-client-agent-mcp/dist/logger.js +19 -0
  56. package/package/aws-client-agent-mcp/dist/logger.js.map +1 -0
  57. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +77 -0
  58. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -0
  59. package/package/aws-client-agent-mcp/dist/mcp-server.js +438 -0
  60. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -0
  61. package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts +2 -0
  62. package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts.map +1 -0
  63. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +624 -0
  64. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -0
  65. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +78 -0
  66. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -0
  67. package/package/aws-client-agent-mcp/dist/mcp-tools.js +420 -0
  68. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -0
  69. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +61 -0
  70. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -0
  71. package/package/aws-client-agent-mcp/dist/memory-store.js +268 -0
  72. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -0
  73. package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts +2 -0
  74. package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts.map +1 -0
  75. package/package/aws-client-agent-mcp/dist/memory-store.test.js +164 -0
  76. package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -0
  77. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +87 -0
  78. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -0
  79. package/package/aws-client-agent-mcp/dist/message-buffer.js +185 -0
  80. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -0
  81. package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts +2 -0
  82. package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts.map +1 -0
  83. package/package/aws-client-agent-mcp/dist/message-buffer.test.js +44 -0
  84. package/package/aws-client-agent-mcp/dist/message-buffer.test.js.map +1 -0
  85. package/package/aws-client-agent-mcp/dist/messageContent.d.ts +53 -0
  86. package/package/aws-client-agent-mcp/dist/messageContent.d.ts.map +1 -0
  87. package/package/aws-client-agent-mcp/dist/messageContent.js +125 -0
  88. package/package/aws-client-agent-mcp/dist/messageContent.js.map +1 -0
  89. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +3 -0
  90. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -0
  91. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +50 -0
  92. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -0
  93. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts +2 -0
  94. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts.map +1 -0
  95. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +90 -0
  96. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -0
  97. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +66 -0
  98. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -0
  99. package/package/aws-client-agent-mcp/dist/status-reporter.js +237 -0
  100. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -0
  101. package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts +2 -0
  102. package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts.map +1 -0
  103. package/package/aws-client-agent-mcp/dist/status-reporter.test.js +19 -0
  104. package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -0
  105. package/package/aws-client-agent-mcp/dist/types.d.ts +309 -0
  106. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -0
  107. package/package/aws-client-agent-mcp/dist/types.js +9 -0
  108. package/package/aws-client-agent-mcp/dist/types.js.map +1 -0
  109. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +94 -0
  110. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -0
  111. package/package/aws-client-agent-mcp/dist/websocket-client.js +316 -0
  112. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -0
  113. package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts +2 -0
  114. package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts.map +1 -0
  115. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +191 -0
  116. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -0
  117. package/package.json +1 -1
@@ -0,0 +1,55 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { readFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { configureStartupConfig } from "./startup-config-wizard.js";
6
+ function getDefaultPackageRoot() {
7
+ const currentFile = fileURLToPath(import.meta.url);
8
+ return path.resolve(path.dirname(currentFile), "..", "..");
9
+ }
10
+ export function readPackageVersion(packageRoot = getDefaultPackageRoot()) {
11
+ const packageJsonPath = path.join(packageRoot, "package.json");
12
+ const metadata = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
13
+ return metadata.version || "unknown";
14
+ }
15
+ function defaultRunCommand(command, args) {
16
+ const result = spawnSync(command, args, {
17
+ shell: process.platform === "win32",
18
+ stdio: "inherit",
19
+ });
20
+ return { status: result.status, error: result.error };
21
+ }
22
+ function isVersionCommand(command) {
23
+ return command === "-v" || command === "--version" || command === "version";
24
+ }
25
+ export async function handleCliCommand(options = {}) {
26
+ const argv = options.argv || process.argv.slice(2);
27
+ const command = argv[0];
28
+ const stdout = options.stdout || console.log;
29
+ const stderr = options.stderr || console.error;
30
+ if (isVersionCommand(command)) {
31
+ stdout(`aws-runtime-bridge ${readPackageVersion(options.packageRoot)}`);
32
+ return { handled: true, exitCode: 0 };
33
+ }
34
+ if (command === "update") {
35
+ stdout("[runtime-bridge] 正在更新 aws-runtime-bridge 到最新版本...");
36
+ const runCommand = options.runCommand || defaultRunCommand;
37
+ const result = runCommand("npm", ["install", "-g", "aws-runtime-bridge@latest"]);
38
+ if (result.error) {
39
+ stderr(`[runtime-bridge] 更新失败: ${result.error.message}`);
40
+ return { handled: true, exitCode: 1 };
41
+ }
42
+ if (result.status !== 0) {
43
+ stderr(`[runtime-bridge] 更新失败,npm 退出码: ${result.status ?? "unknown"}`);
44
+ return { handled: true, exitCode: result.status ?? 1 };
45
+ }
46
+ stdout("[runtime-bridge] 更新完成。请重新运行 awsb -v 查看当前版本。");
47
+ return { handled: true, exitCode: 0 };
48
+ }
49
+ if (command === "config") {
50
+ const configure = options.configure || configureStartupConfig;
51
+ const result = await configure();
52
+ return { handled: true, exitCode: result === "configured" ? 0 : 1 };
53
+ }
54
+ return { handled: false, exitCode: 0 };
55
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli-commands.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-commands.test.d.ts","sourceRoot":"","sources":["../../src/services/cli-commands.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } 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 { handleCliCommand, readPackageVersion } from "./cli-commands.js";
6
+ const tempRoots = [];
7
+ function createPackageRoot(version = "9.8.7") {
8
+ const root = mkdtempSync(path.join(os.tmpdir(), "aws-bridge-cli-"));
9
+ tempRoots.push(root);
10
+ mkdirSync(root, { recursive: true });
11
+ writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "aws-runtime-bridge", version }), "utf-8");
12
+ return root;
13
+ }
14
+ afterEach(() => {
15
+ for (const root of tempRoots.splice(0)) {
16
+ rmSync(root, { recursive: true, force: true });
17
+ }
18
+ });
19
+ describe("cli commands", () => {
20
+ it("reads package version from package root", () => {
21
+ const packageRoot = createPackageRoot("1.2.3");
22
+ expect(readPackageVersion(packageRoot)).toBe("1.2.3");
23
+ });
24
+ it("prints version for -v", async () => {
25
+ const packageRoot = createPackageRoot("1.2.3");
26
+ const output = [];
27
+ const result = await handleCliCommand({
28
+ argv: ["-v"],
29
+ packageRoot,
30
+ stdout: (message) => output.push(message),
31
+ });
32
+ expect(result).toEqual({ handled: true, exitCode: 0 });
33
+ expect(output).toEqual(["aws-runtime-bridge 1.2.3"]);
34
+ });
35
+ it("prints version for version command", async () => {
36
+ const packageRoot = createPackageRoot("2.0.0");
37
+ const output = [];
38
+ const result = await handleCliCommand({
39
+ argv: ["version"],
40
+ packageRoot,
41
+ stdout: (message) => output.push(message),
42
+ });
43
+ expect(result).toEqual({ handled: true, exitCode: 0 });
44
+ expect(output).toEqual(["aws-runtime-bridge 2.0.0"]);
45
+ });
46
+ it("runs npm global update for update command", async () => {
47
+ const output = [];
48
+ const commands = [];
49
+ const result = await handleCliCommand({
50
+ argv: ["update"],
51
+ stdout: (message) => output.push(message),
52
+ runCommand: (command, args) => {
53
+ commands.push({ command, args });
54
+ return { status: 0 };
55
+ },
56
+ });
57
+ expect(result).toEqual({ handled: true, exitCode: 0 });
58
+ expect(commands).toEqual([
59
+ { command: "npm", args: ["install", "-g", "aws-runtime-bridge@latest"] },
60
+ ]);
61
+ expect(output.at(-1)).toBe("[runtime-bridge] 更新完成。请重新运行 awsb -v 查看当前版本。");
62
+ });
63
+ it("returns npm exit code when update fails", async () => {
64
+ const errors = [];
65
+ const result = await handleCliCommand({
66
+ argv: ["update"],
67
+ stdout: () => undefined,
68
+ stderr: (message) => errors.push(message),
69
+ runCommand: () => ({ status: 7 }),
70
+ });
71
+ expect(result).toEqual({ handled: true, exitCode: 7 });
72
+ expect(errors).toEqual(["[runtime-bridge] 更新失败,npm 退出码: 7"]);
73
+ });
74
+ it("runs interactive config command", async () => {
75
+ const result = await handleCliCommand({
76
+ argv: ["config"],
77
+ configure: async () => "configured",
78
+ });
79
+ expect(result).toEqual({ handled: true, exitCode: 0 });
80
+ });
81
+ it("returns non-zero when config command fails", async () => {
82
+ const result = await handleCliCommand({
83
+ argv: ["config"],
84
+ configure: async () => "failed",
85
+ });
86
+ expect(result).toEqual({ handled: true, exitCode: 1 });
87
+ });
88
+ it("does not handle normal startup arguments", async () => {
89
+ const result = await handleCliCommand({ argv: [] });
90
+ expect(result).toEqual({ handled: false, exitCode: 0 });
91
+ });
92
+ });
@@ -9,7 +9,8 @@ interface EnsureStartupConfigOptions {
9
9
  env?: NodeJS.ProcessEnv;
10
10
  generateConnectionKey?: () => string;
11
11
  }
12
- export type StartupConfigWizardResult = "exists" | "created" | "skipped" | "non-interactive" | "failed";
12
+ export type StartupConfigWizardResult = "exists" | "created" | "configured" | "skipped" | "non-interactive" | "failed";
13
13
  export declare function ensureStartupConfig(options?: EnsureStartupConfigOptions): Promise<StartupConfigWizardResult>;
14
+ export declare function configureStartupConfig(options?: EnsureStartupConfigOptions): Promise<StartupConfigWizardResult>;
14
15
  export {};
15
16
  //# sourceMappingURL=startup-config-wizard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup-config-wizard.d.ts","sourceRoot":"","sources":["../../src/services/startup-config-wizard.ts"],"names":[],"mappings":"AAqBA,UAAU,QAAQ;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,UAAU,0BAA0B;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,yBAAyB,GACjC,QAAQ,GACR,SAAS,GACT,SAAS,GACT,iBAAiB,GACjB,QAAQ,CAAC;AAiGb,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,yBAAyB,CAAC,CAmDpC"}
1
+ {"version":3,"file":"startup-config-wizard.d.ts","sourceRoot":"","sources":["../../src/services/startup-config-wizard.ts"],"names":[],"mappings":"AAuBA,UAAU,QAAQ;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,UAAU,0BAA0B;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,yBAAyB,GACjC,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,SAAS,GACT,iBAAiB,GACjB,QAAQ,CAAC;AAqKb,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,yBAAyB,CAAC,CAiDpC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,yBAAyB,CAAC,CA0BpC"}
@@ -1,11 +1,11 @@
1
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
1
  import { randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
- import { createInterface } from "node:readline/promises";
6
5
  import { stdin as input, stdout as output } from "node:process";
7
- import { getAutoRegisterConfigFilePath } from "./auto-register.js";
6
+ import { createInterface } from "node:readline/promises";
8
7
  import { logger } from "../utils/logger.js";
8
+ import { getAutoRegisterConfigFilePath } from "./auto-register.js";
9
9
  function normalizeAnswer(answer) {
10
10
  return answer.trim().toLowerCase();
11
11
  }
@@ -19,6 +19,22 @@ function writeConfigFile(configPath, config) {
19
19
  mkdirSync(path.dirname(configPath), { recursive: true });
20
20
  writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
21
21
  }
22
+ function readExistingConfig(configPath) {
23
+ if (!existsSync(configPath)) {
24
+ return {};
25
+ }
26
+ try {
27
+ const parsed = JSON.parse(readFileSync(configPath, "utf-8"));
28
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
29
+ ? parsed
30
+ : {};
31
+ }
32
+ catch (error) {
33
+ const err = error;
34
+ logger.warn(`[runtime-bridge] 读取现有配置失败,将使用空默认值: ${err.message}`);
35
+ return {};
36
+ }
37
+ }
22
38
  function generateDefaultConnectionKey() {
23
39
  return `awsb_${randomBytes(24).toString("base64url")}`;
24
40
  }
@@ -32,15 +48,20 @@ function writeSkippedConfig(configPath, generateConnectionKey) {
32
48
  output.write(`${message}\n`);
33
49
  }
34
50
  async function askOptional(prompt, label, defaultValue) {
35
- const answer = await prompt.question(`${label} (${defaultValue}): `);
51
+ const answer = await prompt.question(`${label}(默认使用当前值 ${defaultValue},直接回车保留): `);
36
52
  return answer.trim() || defaultValue;
37
53
  }
38
- async function askRequired(prompt, label) {
54
+ async function askRequired(prompt, label, currentValue) {
39
55
  for (;;) {
40
- const answer = (await prompt.question(`${label}: `)).trim();
56
+ const answer = (await prompt.question(currentValue
57
+ ? `${label}(默认使用当前值 ${currentValue},直接回车保留): `
58
+ : `${label}: `)).trim();
41
59
  if (answer) {
42
60
  return answer;
43
61
  }
62
+ if (currentValue) {
63
+ return currentValue;
64
+ }
44
65
  output.write(`${label} 不能为空,请重新输入。\n`);
45
66
  }
46
67
  }
@@ -56,19 +77,22 @@ async function askShouldConfigure(prompt) {
56
77
  output.write("请输入 Y 继续配置,或输入 n 跳过。\n");
57
78
  }
58
79
  }
59
- async function collectStartupConfig(prompt) {
80
+ async function collectStartupConfig(prompt, existingConfig = {}) {
81
+ const existingTarget = existingConfig.autoRegisterTargets?.[0] || {};
60
82
  const defaultServerUrl = "http://127.0.0.1:8080";
61
83
  const defaultInstanceName = os.hostname() || "AgentsWork Runtime Bridge";
62
84
  const defaultRegisterIp = "127.0.0.1";
63
- const connectionKey = await askRequired(prompt, "connectionKey(面板连接 Bridge 的密钥)");
64
- const serverUrl = await askOptional(prompt, "serverUrl(调度中心地址)", defaultServerUrl);
65
- const instanceName = await askOptional(prompt, "instanceName(实例名称)", defaultInstanceName);
66
- const userKey = await askRequired(prompt, "userKey(用户 API Key)");
67
- const registerIp = await askOptional(prompt, "registerIp(Bridge 对外访问 IP)", defaultRegisterIp);
85
+ const connectionKey = await askRequired(prompt, "connectionKey(面板连接 Bridge 的密钥)", existingConfig.connectionKey);
86
+ const serverUrl = await askOptional(prompt, "serverUrl(调度中心地址)", existingTarget.serverUrl || defaultServerUrl);
87
+ const instanceName = await askOptional(prompt, "instanceName(实例名称)", existingTarget.instanceName || defaultInstanceName);
88
+ const userKey = await askRequired(prompt, "userKey(用户 API Key)", existingTarget.userKey);
89
+ const registerIp = await askOptional(prompt, "registerIp(Bridge 对外访问 IP)", existingTarget.registerIp || defaultRegisterIp);
68
90
  return {
91
+ ...existingConfig,
69
92
  connectionKey,
70
93
  autoRegisterTargets: [
71
94
  {
95
+ ...existingTarget,
72
96
  serverUrl,
73
97
  instanceName,
74
98
  userKey,
@@ -77,6 +101,12 @@ async function collectStartupConfig(prompt) {
77
101
  ],
78
102
  };
79
103
  }
104
+ async function createPrompt(options) {
105
+ return {
106
+ prompt: options.prompt || createInterface({ input, output, terminal: true }),
107
+ shouldClosePrompt: !options.prompt,
108
+ };
109
+ }
80
110
  export async function ensureStartupConfig(options = {}) {
81
111
  const configPath = options.configPath || getAutoRegisterConfigFilePath();
82
112
  const generateConnectionKey = options.generateConnectionKey || generateDefaultConnectionKey;
@@ -95,8 +125,7 @@ export async function ensureStartupConfig(options = {}) {
95
125
  logger.info(`[runtime-bridge] 未检测到配置文件: ${configPath};当前为非交互环境,跳过首次配置引导`);
96
126
  return "non-interactive";
97
127
  }
98
- const prompt = options.prompt || createInterface({ input, output, terminal: true });
99
- const shouldClosePrompt = !options.prompt;
128
+ const { prompt, shouldClosePrompt } = await createPrompt(options);
100
129
  try {
101
130
  const shouldConfigure = await askShouldConfigure(prompt);
102
131
  if (!shouldConfigure) {
@@ -120,3 +149,29 @@ export async function ensureStartupConfig(options = {}) {
120
149
  }
121
150
  }
122
151
  }
152
+ export async function configureStartupConfig(options = {}) {
153
+ const configPath = options.configPath || getAutoRegisterConfigFilePath();
154
+ const interactive = options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
155
+ if (!interactive) {
156
+ logger.warn("[runtime-bridge] awsb config 需要交互式终端");
157
+ return "failed";
158
+ }
159
+ const { prompt, shouldClosePrompt } = await createPrompt(options);
160
+ try {
161
+ const existingConfig = readExistingConfig(configPath);
162
+ const config = await collectStartupConfig(prompt, existingConfig);
163
+ writeConfigFile(configPath, config);
164
+ logger.info(`[runtime-bridge] 已更新配置文件: ${configPath}`);
165
+ return "configured";
166
+ }
167
+ catch (error) {
168
+ const err = error;
169
+ logger.warn(`[runtime-bridge] 配置引导失败: ${err.message}`);
170
+ return "failed";
171
+ }
172
+ finally {
173
+ if (shouldClosePrompt) {
174
+ prompt.close();
175
+ }
176
+ }
177
+ }
@@ -2,14 +2,16 @@ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "nod
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 { ensureStartupConfig } from "./startup-config-wizard.js";
5
+ import { configureStartupConfig, ensureStartupConfig, } from "./startup-config-wizard.js";
6
6
  class FakePrompt {
7
7
  constructor(answers) {
8
8
  this.answers = answers;
9
9
  this.index = 0;
10
10
  this.closed = false;
11
+ this.prompts = [];
11
12
  }
12
- async question() {
13
+ async question(prompt) {
14
+ this.prompts.push(prompt);
13
15
  return this.answers[this.index++] ?? "";
14
16
  }
15
17
  close() {
@@ -100,4 +102,83 @@ describe("startup config wizard", () => {
100
102
  connectionKey: "awsb_env_skip_key",
101
103
  });
102
104
  });
105
+ it("reconfigures existing config and keeps current values on empty input", async () => {
106
+ const configPath = createConfigPath();
107
+ mkdirSync(path.dirname(configPath), { recursive: true });
108
+ writeFileSync(configPath, JSON.stringify({
109
+ connectionKey: "old-connection-key",
110
+ autoRegisterTargets: [
111
+ {
112
+ serverUrl: "http://old-server:7380",
113
+ instanceName: "old-instance",
114
+ userKey: "old-user-key",
115
+ registerIp: "10.0.0.8",
116
+ },
117
+ ],
118
+ }, null, 2), "utf-8");
119
+ const prompt = new FakePrompt(["", "", "", "", ""]);
120
+ const result = await configureStartupConfig({
121
+ configPath,
122
+ interactive: true,
123
+ prompt,
124
+ });
125
+ expect(result).toBe("configured");
126
+ expect(JSON.parse(readFileSync(configPath, "utf-8"))).toEqual({
127
+ connectionKey: "old-connection-key",
128
+ autoRegisterTargets: [
129
+ {
130
+ serverUrl: "http://old-server:7380",
131
+ instanceName: "old-instance",
132
+ userKey: "old-user-key",
133
+ registerIp: "10.0.0.8",
134
+ },
135
+ ],
136
+ });
137
+ expect(prompt.prompts).toEqual([
138
+ "connectionKey(面板连接 Bridge 的密钥)(默认使用当前值 old-connection-key,直接回车保留): ",
139
+ "serverUrl(调度中心地址)(默认使用当前值 http://old-server:7380,直接回车保留): ",
140
+ "instanceName(实例名称)(默认使用当前值 old-instance,直接回车保留): ",
141
+ "userKey(用户 API Key)(默认使用当前值 old-user-key,直接回车保留): ",
142
+ "registerIp(Bridge 对外访问 IP)(默认使用当前值 10.0.0.8,直接回车保留): ",
143
+ ]);
144
+ });
145
+ it("reconfigures existing config with changed values", async () => {
146
+ const configPath = createConfigPath();
147
+ mkdirSync(path.dirname(configPath), { recursive: true });
148
+ writeFileSync(configPath, JSON.stringify({
149
+ connectionKey: "old-connection-key",
150
+ autoRegisterTargets: [
151
+ {
152
+ serverUrl: "http://old-server:7380",
153
+ instanceName: "old-instance",
154
+ userKey: "old-user-key",
155
+ registerIp: "10.0.0.8",
156
+ },
157
+ ],
158
+ }), "utf-8");
159
+ const prompt = new FakePrompt([
160
+ "new-connection-key",
161
+ "http://new-server:7380",
162
+ "new-instance",
163
+ "new-user-key",
164
+ "10.0.0.9",
165
+ ]);
166
+ const result = await configureStartupConfig({
167
+ configPath,
168
+ interactive: true,
169
+ prompt,
170
+ });
171
+ expect(result).toBe("configured");
172
+ expect(JSON.parse(readFileSync(configPath, "utf-8"))).toEqual({
173
+ connectionKey: "new-connection-key",
174
+ autoRegisterTargets: [
175
+ {
176
+ serverUrl: "http://new-server:7380",
177
+ instanceName: "new-instance",
178
+ userKey: "new-user-key",
179
+ registerIp: "10.0.0.9",
180
+ },
181
+ ],
182
+ });
183
+ });
103
184
  });
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Agent 客户端核心模块
3
+ * 负责与调度中心通信,管理消息循环
4
+ */
5
+ import { StatusReporter } from "./status-reporter.js";
6
+ import type { AgentConfig, DirectMessage, DmHistoryResponse, GroupHistoryResponse, GroupRoomsResponse, HireColleagueArgs, HireColleaguesBatchArgs, HireBatchResult, HiredColleagueResult, MessageHandler, OnlineListResponse, ProfileInfo, RegisterResult, SendDmResult, SendMessageResult, UnreadMessagesResult } from "./types.js";
7
+ export type ProfileHandler = (profile: ProfileInfo) => void;
8
+ export declare class AgentClient {
9
+ private wsClient;
10
+ private httpClient;
11
+ private agentConfig;
12
+ private serverConfig;
13
+ private agentId;
14
+ private displayName;
15
+ private projectName;
16
+ private isRunning;
17
+ private messageHandler;
18
+ private profileHandler;
19
+ private pollTimer;
20
+ private statusReporter;
21
+ /**
22
+ * Profile 缓存
23
+ * 用于处理 PROFILE_INFO 消息在 profileHandler 设置之前到达的情况
24
+ */
25
+ private cachedProfile;
26
+ constructor();
27
+ initialize(): Promise<void>;
28
+ private setupWebSocketListeners;
29
+ /**
30
+ * 注册 Agent 上线
31
+ */
32
+ register(): Promise<RegisterResult>;
33
+ private hasPresetAgentId;
34
+ /**
35
+ * 使用预设 AgentID 注册(绑定已有实例)
36
+ */
37
+ private registerWithExistingAgentId;
38
+ /**
39
+ * 作为新 Agent 注册
40
+ */
41
+ private registerAsNewAgent;
42
+ /**
43
+ * 注销 Agent 下线
44
+ */
45
+ unregister(): Promise<void>;
46
+ /**
47
+ * 获取当前 Agent 可见的同事列表(包含离线 Agent)。
48
+ */
49
+ discoverColleagues(): Promise<OnlineListResponse>;
50
+ /**
51
+ * 获取当前 Agent 在关系图中可发现的群组列表。
52
+ */
53
+ discoverGroupRooms(): Promise<GroupRoomsResponse>;
54
+ /**
55
+ * 招聘同事并创建新的 Agent 实例。
56
+ * 主流程:校验当前实例已注册 -> 透传创建角色参数到服务端 MCP tool -> 返回新实例信息。
57
+ */
58
+ hireColleague(args: HireColleagueArgs): Promise<HiredColleagueResult>;
59
+ /**
60
+ * 批量发起招聘审批请求。
61
+ * 主流程:校验当前实例已注册 -> 透传批量招聘参数到服务端 MCP tool -> 返回整批审批与创建结果。
62
+ */
63
+ hireColleaguesBatch(args: HireColleaguesBatchArgs): Promise<HireBatchResult>;
64
+ /**
65
+ * 发送群消息
66
+ * @param content 消息内容
67
+ * @param projectName 目标项目名,不传则使用 Agent 所属项目(由服务端决定)
68
+ * @param roomId 目标群房间 ID,小组群场景下优先使用以避免误发到项目公共群
69
+ */
70
+ sendGroupMessage(content: string, projectName?: string, roomId?: string): Promise<SendMessageResult>;
71
+ /**
72
+ * 发送私信
73
+ */
74
+ sendDirectMessage(targetId: string, content: string, waitReply?: boolean, replyToCallId?: string, timeoutMs?: number): Promise<SendDmResult>;
75
+ /**
76
+ * 发送私信并等待回复(阻塞式)
77
+ */
78
+ sendCallAndWaitReply(targetId: string, content: string, timeoutMs?: number): Promise<DirectMessage>;
79
+ /**
80
+ * 回复调用式消息
81
+ */
82
+ replyToCall(callId: string, targetId: string, content: string): Promise<SendDmResult>;
83
+ /**
84
+ * 获取私信历史消息
85
+ */
86
+ getDmHistory(targetUserId?: string, limit?: number, since?: string): Promise<DmHistoryResponse>;
87
+ /**
88
+ * 获取群消息历史记录
89
+ */
90
+ getGroupHistory(limit?: number, roomId?: string, since?: string): Promise<GroupHistoryResponse>;
91
+ /**
92
+ * 拉取当前 Agent 尚未消费的未读消息。
93
+ * 主流程:校验注册状态 -> 获取未读私信 -> 获取未读群消息 -> 合并返回。
94
+ * @param since 可选的起始时间(ISO 8601),早于该时间的消息将被过滤
95
+ */
96
+ fetchUnreadMessages(since?: string): Promise<UnreadMessagesResult>;
97
+ /**
98
+ * 收集当前项目下 Agent 可访问的群房间 ID,避免离线补拉和历史查询遗漏小组群。
99
+ */
100
+ private collectRoomIds;
101
+ /**
102
+ * 获取当前 Agent 的个人信息
103
+ */
104
+ getProfile(): Promise<ProfileInfo>;
105
+ private getProfileByAgentId;
106
+ /**
107
+ * 获取当前 Agent 被分配的流程线任务列表
108
+ */
109
+ getMyTasks(): Promise<unknown[]>;
110
+ /**
111
+ * 开始处理流程线任务节点(将 PENDING 状态转为 PROCESSING)
112
+ */
113
+ startTask(nodeId: string): Promise<unknown>;
114
+ /**
115
+ * 提交流程线任务结果
116
+ */
117
+ submitTaskResult(nodeId: string, outputPayload: string): Promise<unknown>;
118
+ /**
119
+ * 拒绝流程线任务
120
+ */
121
+ rejectTask(nodeId: string, reason: string): Promise<unknown>;
122
+ /**
123
+ * 终止流程线任务(终止后不再流转)
124
+ */
125
+ terminateTask(taskInstanceId: string, reason: string): Promise<unknown>;
126
+ /**
127
+ * 启动消息监听
128
+ */
129
+ start(handler: MessageHandler, options?: {
130
+ pollMode?: boolean;
131
+ profileHandler?: ProfileHandler;
132
+ }): void;
133
+ /**
134
+ * 停止消息监听
135
+ */
136
+ stop(): void;
137
+ private messageLoop;
138
+ private handleIncomingDm;
139
+ private handleIncomingGroup;
140
+ /**
141
+ * 处理收到的 Profile 信息
142
+ * 由服务端在 Agent 连接时自动推送
143
+ */
144
+ private handleProfileInfo;
145
+ private processMessage;
146
+ private ensureRegistered;
147
+ private delay;
148
+ getState(): {
149
+ agentId: string | null;
150
+ displayName: string | null;
151
+ projectName: string | null;
152
+ isConnected: boolean;
153
+ isRunning: boolean;
154
+ };
155
+ getAgentConfig(): AgentConfig;
156
+ reloadConfig(): void;
157
+ /**
158
+ * 初始化状态报告器
159
+ */
160
+ private initializeStatusReporter;
161
+ /**
162
+ * 获取状态报告器(供 MCP Server 使用)
163
+ */
164
+ getStatusReporter(): StatusReporter | null;
165
+ }
166
+ //# sourceMappingURL=agent-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../src/agent-client.ts"],"names":[],"mappings":"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"}