aws-runtime-bridge 1.2.1 → 1.3.1

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 (76) hide show
  1. package/dist/adapter/ClaudeSdkAdapter.d.ts +1 -0
  2. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/ClaudeSdkAdapter.js +7 -3
  4. package/dist/adapter/ClaudeSdkAdapter.test.js +2 -2
  5. package/dist/adapter/CodexSdkAdapter.d.ts.map +1 -1
  6. package/dist/adapter/CodexSdkAdapter.js +7 -4
  7. package/dist/adapter/CodexSdkAdapter.test.js +4 -2
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  9. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  10. package/dist/adapter/OpencodeSdkAdapter.js +15 -1
  11. package/dist/adapter/OpencodeSdkAdapter.test.js +5 -0
  12. package/dist/routes/runtime-binding.d.ts.map +1 -1
  13. package/dist/routes/runtime-binding.js +8 -13
  14. package/dist/routes/terminal.js +2 -5
  15. package/dist/routes/terminal.test.js +3 -4
  16. package/dist/services/auto-register.d.ts +6 -0
  17. package/dist/services/auto-register.d.ts.map +1 -1
  18. package/dist/services/auto-register.js +63 -1
  19. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  20. package/dist/services/aws-client-agent-mcp.js +4 -4
  21. package/dist/services/aws-client-agent-mcp.test.js +14 -0
  22. package/dist/services/mcp-launch-binding-queue.d.ts +0 -2
  23. package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
  24. package/dist/services/mcp-launch-binding-queue.js +44 -16
  25. package/dist/services/mcp-launch-binding-queue.test.js +42 -37
  26. package/dist/services/runtime-binding.d.ts +1 -0
  27. package/dist/services/runtime-binding.d.ts.map +1 -1
  28. package/dist/services/runtime-binding.js +39 -5
  29. package/dist/services/runtime-binding.test.d.ts +2 -0
  30. package/dist/services/runtime-binding.test.d.ts.map +1 -0
  31. package/dist/services/runtime-binding.test.js +11 -0
  32. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +1 -0
  33. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  34. package/package/aws-client-agent-mcp/dist/agent-client.js +12 -0
  35. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  36. package/package/aws-client-agent-mcp/dist/agent-client.test.js +31 -0
  37. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
  38. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  39. package/package/aws-client-agent-mcp/dist/config.js +96 -13
  40. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  41. package/package/aws-client-agent-mcp/dist/config.test.js +26 -8
  42. package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -1
  43. package/package/aws-client-agent-mcp/dist/constants.d.ts +0 -1
  44. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  45. package/package/aws-client-agent-mcp/dist/constants.js +0 -1
  46. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  47. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  48. package/package/aws-client-agent-mcp/dist/http-client.js +49 -13
  49. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  50. package/package/aws-client-agent-mcp/dist/http-client.test.js +40 -13
  51. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  52. package/package/aws-client-agent-mcp/dist/index.js +11 -6
  53. package/package/aws-client-agent-mcp/dist/index.js.map +1 -1
  54. package/package/aws-client-agent-mcp/dist/logger.d.ts +11 -1
  55. package/package/aws-client-agent-mcp/dist/logger.d.ts.map +1 -1
  56. package/package/aws-client-agent-mcp/dist/logger.js +91 -6
  57. package/package/aws-client-agent-mcp/dist/logger.js.map +1 -1
  58. package/package/aws-client-agent-mcp/dist/logger.test.d.ts +2 -0
  59. package/package/aws-client-agent-mcp/dist/logger.test.d.ts.map +1 -0
  60. package/package/aws-client-agent-mcp/dist/logger.test.js +27 -0
  61. package/package/aws-client-agent-mcp/dist/logger.test.js.map +1 -0
  62. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  63. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +18 -14
  64. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  65. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +51 -21
  66. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
  67. package/package/aws-client-agent-mcp/dist/types.d.ts +3 -2
  68. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  69. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  70. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +1 -0
  71. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  72. package/package/aws-client-agent-mcp/dist/websocket-client.js +18 -0
  73. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  74. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +53 -2
  75. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  76. package/package.json +1 -1
@@ -72,6 +72,7 @@ export declare class ClaudeSdkAdapter extends EventEmitter implements BaseProvid
72
72
  private sendIdlePrompt;
73
73
  private isTaskPollingIdleCommand;
74
74
  private isMessagePollingIdleCommand;
75
+ private buildMessagePollingIdlePrompt;
75
76
  /**
76
77
  * 执行空闲命令(支持 [enter], [wait:n] 等 token)
77
78
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"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"}
@@ -413,9 +413,9 @@ export class ClaudeSdkAdapter extends EventEmitter {
413
413
  if (commands.idleInputCommand) {
414
414
  // 解析空闲命令,提取实际要执行的指令
415
415
  const command = commands.idleInputCommand;
416
- // 如果空闲命令包含 poll_message,发送一个提示让 AI 执行
416
+ // 如果空闲命令包含 poll_message/get_message,引导 AI 进入阻塞式消息轮询。
417
417
  if (this.isMessagePollingIdleCommand(command)) {
418
- this.sendIdlePrompt(sessionId, '请使用 poll_message 工具检查是否有新消息,如果有的话处理它们。');
418
+ this.sendIdlePrompt(sessionId, this.buildMessagePollingIdlePrompt());
419
419
  }
420
420
  else {
421
421
  // 其他命令,直接作为消息发送给 AI
@@ -457,7 +457,11 @@ export class ClaudeSdkAdapter extends EventEmitter {
457
457
  if (!normalized) {
458
458
  return false;
459
459
  }
460
- return normalized.toLowerCase().includes('poll_message') || normalized.includes('取消息');
460
+ const lower = normalized.toLowerCase();
461
+ return lower.includes('poll_message') || lower.includes('get_message') || normalized.includes('取消息');
462
+ }
463
+ buildMessagePollingIdlePrompt() {
464
+ return '请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。';
461
465
  }
462
466
  /**
463
467
  * 执行空闲命令(支持 [enter], [wait:n] 等 token)
@@ -34,7 +34,7 @@ describe('ClaudeSdkAdapter', () => {
34
34
  expect(sentPrompts).toHaveLength(0);
35
35
  expect(sendIdlePrompt).not.toHaveBeenCalled();
36
36
  });
37
- it('still auto-wakes Claude for poll_message-style idle commands', async () => {
37
+ it('starts a blocking poll turn for poll_message-style idle commands', async () => {
38
38
  vi.useFakeTimers();
39
39
  const adapter = new ClaudeSdkAdapter();
40
40
  const sentPrompts = [];
@@ -61,7 +61,7 @@ describe('ClaudeSdkAdapter', () => {
61
61
  await vi.advanceTimersByTimeAsync(1000);
62
62
  expect(sentPrompts).toHaveLength(0);
63
63
  await vi.advanceTimersByTimeAsync(600);
64
- expect(sentPrompts).toEqual(['请使用 poll_message 工具检查是否有新消息,如果有的话处理它们。']);
64
+ expect(sentPrompts).toEqual(['请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。']);
65
65
  });
66
66
  it('still auto-wakes Claude for regular idle commands', async () => {
67
67
  vi.useFakeTimers();
@@ -1 +1 @@
1
- {"version":3,"file":"CodexSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/CodexSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAEV,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EAEnB,aAAa,EAEd,MAAM,YAAY,CAAC;AAgRpB,qBAAa,eAAgB,SAAQ,YAAa,YAAW,mBAAmB;IAC9E,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,WAAW,WAAW;IAE/B,OAAO,CAAC,QAAQ,CAAwC;IAElD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkE5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC9D,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAanG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlD,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC;IA2BhB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrD,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,kBAAkB;YAqCZ,OAAO;IAiCrB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,gBAAgB;IA+ExB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,kBAAkB;IAuD1B,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;YAcR,cAAc;IAuB5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,2BAA2B;CAMpC"}
1
+ {"version":3,"file":"CodexSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/CodexSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAEV,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EAEnB,aAAa,EAEd,MAAM,YAAY,CAAC;AAgRpB,qBAAa,eAAgB,SAAQ,YAAa,YAAW,mBAAmB;IAC9E,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,WAAW,WAAW;IAE/B,OAAO,CAAC,QAAQ,CAAwC;IAElD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkE5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC9D,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAanG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlD,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC;IA2BhB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrD,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,kBAAkB;YAqCZ,OAAO;IAiCrB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,gBAAgB;IA+ExB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,kBAAkB;IAuD1B,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;YAcR,cAAc;IAuB5B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,2BAA2B;CAOpC"}
@@ -687,8 +687,6 @@ export class CodexSdkAdapter extends EventEmitter {
687
687
  const session = this.sessions.get(sessionId);
688
688
  if (!session?.idleCommands?.idleInputCommand)
689
689
  return;
690
- if (this.isMessagePollingIdleCommand(session.idleCommands.idleInputCommand))
691
- return;
692
690
  session.lastActivityAt = Date.now();
693
691
  const timer = setInterval(() => {
694
692
  this.checkIdleState(sessionId);
@@ -739,12 +737,17 @@ export class CodexSdkAdapter extends EventEmitter {
739
737
  }
740
738
  }
741
739
  toIdlePrompt(command) {
742
- return command.trim();
740
+ const trimmed = command.trim();
741
+ if (this.isMessagePollingIdleCommand(trimmed)) {
742
+ return '请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。';
743
+ }
744
+ return trimmed;
743
745
  }
744
746
  isMessagePollingIdleCommand(command) {
745
747
  const normalized = command.trim();
746
748
  if (!normalized)
747
749
  return false;
748
- return normalized.toLowerCase().includes('poll_message') || normalized.includes('取消息');
750
+ const lower = normalized.toLowerCase();
751
+ return lower.includes('poll_message') || lower.includes('get_message') || normalized.includes('取消息');
749
752
  }
750
753
  }
@@ -177,7 +177,7 @@ describe('CodexSdkAdapter', () => {
177
177
  expect(runMessages).toContain('continue');
178
178
  expect(adapter.getConversation('session-1').some((message) => message.content === 'continue')).toBe(false);
179
179
  });
180
- it('does not auto-wake Codex for poll_message-style idle commands', async () => {
180
+ it('starts a blocking poll turn for poll_message-style idle commands', async () => {
181
181
  vi.useFakeTimers();
182
182
  const adapter = new CodexSdkAdapter();
183
183
  await adapter.startSession('session-1', {
@@ -202,8 +202,10 @@ describe('CodexSdkAdapter', () => {
202
202
  idleInputCommand: 'system: 醒来了吗?使用get_profile获取自己的信息,继续未完成的任务或使用poll_message阻塞获取消息',
203
203
  nonInputCommand: '',
204
204
  });
205
- await vi.advanceTimersByTimeAsync(3000);
205
+ await vi.advanceTimersByTimeAsync(1000);
206
206
  expect(runMessages).toHaveLength(0);
207
+ await vi.advanceTimersByTimeAsync(600);
208
+ expect(runMessages).toEqual(['请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。']);
207
209
  const userMessages = adapter.getConversation('session-1').filter((message) => message.role === 'user');
208
210
  expect(userMessages).toHaveLength(0);
209
211
  });
@@ -41,5 +41,7 @@ export declare class OpencodeSdkAdapter extends EventEmitter implements BaseProv
41
41
  private startIdleDetection;
42
42
  private stopIdleDetection;
43
43
  private checkIdleState;
44
+ private toIdlePrompt;
45
+ private isMessagePollingIdleCommand;
44
46
  }
45
47
  //# sourceMappingURL=OpencodeSdkAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OpencodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/OpencodeSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa3C,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EAGpB,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AA4FpB,qBAAa,kBAAmB,SAAQ,YAAa,YAAW,mBAAmB;IACjF,QAAQ,CAAC,UAAU,cAAc;IACjC,QAAQ,CAAC,WAAW,cAAc;IAElC,OAAO,CAAC,QAAQ,CAA2C;IAErD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+H5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwC9D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOnG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAclD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpD,OAAO,IAAI,IAAI;YAaD,aAAa;IAmB3B,OAAO,CAAC,YAAY;YAYN,UAAU;IAuBxB,OAAO,CAAC,mBAAmB;IA6H3B,OAAO,CAAC,gBAAgB;IA6GxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;CAQvB"}
1
+ {"version":3,"file":"OpencodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/OpencodeSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa3C,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EAGpB,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AA4FpB,qBAAa,kBAAmB,SAAQ,YAAa,YAAW,mBAAmB;IACjF,QAAQ,CAAC,UAAU,cAAc;IACjC,QAAQ,CAAC,WAAW,cAAc;IAElC,OAAO,CAAC,QAAQ,CAA2C;IAErD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+H5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwC9D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAOnG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAclD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpD,OAAO,IAAI,IAAI;YAaD,aAAa;IAmB3B,OAAO,CAAC,YAAY;YAYN,UAAU;IAuBxB,OAAO,CAAC,mBAAmB;IA6H3B,OAAO,CAAC,gBAAgB;IA6GxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,2BAA2B;CAOpC"}
@@ -616,7 +616,21 @@ export class OpencodeSdkAdapter extends EventEmitter {
616
616
  return;
617
617
  if (!session.idleCommands?.idleInputCommand)
618
618
  return;
619
- void this.sendMessage(sessionId, session.idleCommands.idleInputCommand);
619
+ void this.sendMessage(sessionId, this.toIdlePrompt(session.idleCommands.idleInputCommand));
620
620
  this.stopIdleDetection(sessionId);
621
621
  }
622
+ toIdlePrompt(command) {
623
+ const trimmed = command.trim();
624
+ if (this.isMessagePollingIdleCommand(trimmed)) {
625
+ return '请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。';
626
+ }
627
+ return trimmed;
628
+ }
629
+ isMessagePollingIdleCommand(command) {
630
+ const normalized = command.trim();
631
+ if (!normalized)
632
+ return false;
633
+ const lower = normalized.toLowerCase();
634
+ return lower.includes('poll_message') || lower.includes('get_message') || normalized.includes('取消息');
635
+ }
622
636
  }
@@ -11,4 +11,9 @@ describe('OpencodeSdkAdapter', () => {
11
11
  expect(adapter.hasSession('missing-session')).toBe(false);
12
12
  expect(adapter.getSessionStatus('missing-session')).toBeUndefined();
13
13
  });
14
+ it('normalizes poll_message-style idle commands into a blocking poll prompt', () => {
15
+ const adapter = new OpencodeSdkAdapter();
16
+ const prompt = Reflect.get(adapter, 'toIdlePrompt').call(adapter, 'system: 醒来了吗?使用get_profile获取自己的信息,继续未完成的任务或使用poll_message阻塞获取消息');
17
+ expect(prompt).toBe('请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。');
18
+ });
14
19
  });
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/routes/runtime-binding.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,oBAAoB,4CAAW,CAAC;AAqO7C,wBAAgB,6BAA6B,IAAI,IAAI,CAapD"}
1
+ {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/routes/runtime-binding.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,oBAAoB,4CAAW,CAAC;AAgO7C,wBAAgB,6BAA6B,IAAI,IAAI,CAapD"}
@@ -2,7 +2,7 @@ import { Router } from "express";
2
2
  import { clearRuntimeBinding, getRuntimeAccessToken, getRuntimeBindingPublicState, getRuntimePairingCode, hasRuntimeBinding, saveRuntimeBinding, validateRuntimeBindingToken, validateRuntimePairingCode, } from "../services/runtime-binding.js";
3
3
  import { validateToken } from "../middleware/auth.js";
4
4
  import { runtimeToken } from "../config.js";
5
- import { requestRuntimeAccessTokenRefresh } from "../services/auto-register.js";
5
+ import { requestRuntimeAccessTokenRefresh, requestRuntimeAccessTokenRefreshForServer } from "../services/auto-register.js";
6
6
  import { claimMcpLaunchBinding, getMcpLaunchQueueSize } from "../services/mcp-launch-binding-queue.js";
7
7
  import { createLogger } from "../utils/logger.js";
8
8
  const log = createLogger("runtime-binding-route");
@@ -84,7 +84,10 @@ runtimeBindingRouter.post("/binding/request-token", async (req, res) => {
84
84
  });
85
85
  return;
86
86
  }
87
- const result = await requestRuntimeAccessTokenRefresh();
87
+ const requestedServerUrl = serverUrl || schedulerBaseUrl;
88
+ const result = requestedServerUrl
89
+ ? await requestRuntimeAccessTokenRefreshForServer(String(requestedServerUrl))
90
+ : await requestRuntimeAccessTokenRefresh();
88
91
  if (!result.success || !result.runtimeAccessToken) {
89
92
  res.status(400).json({
90
93
  ok: false,
@@ -103,15 +106,7 @@ runtimeBindingRouter.post("/binding/claim-agent", (req, res) => {
103
106
  res.status(403).json({ ok: false, error: "loopback request required" });
104
107
  return;
105
108
  }
106
- const { agentId, bindingId, workspacePath, serverUrl } = req.body || {};
107
- if (!agentId || !String(agentId).trim()) {
108
- res.status(400).json({ ok: false, error: "agentId is required" });
109
- return;
110
- }
111
- if (!bindingId || !String(bindingId).trim()) {
112
- res.status(400).json({ ok: false, error: "bindingId is required" });
113
- return;
114
- }
109
+ const { workspacePath, serverUrl } = req.body || {};
115
110
  if (!workspacePath || !String(workspacePath).trim()) {
116
111
  res.status(400).json({ ok: false, error: "workspacePath is required" });
117
112
  return;
@@ -120,11 +115,11 @@ runtimeBindingRouter.post("/binding/claim-agent", (req, res) => {
120
115
  res.status(400).json({ ok: false, error: "serverUrl is required" });
121
116
  return;
122
117
  }
123
- const claimed = claimMcpLaunchBinding({ agentId, bindingId, workspacePath, serverUrl });
118
+ const claimed = claimMcpLaunchBinding({ workspacePath, serverUrl });
124
119
  if (!claimed) {
125
120
  res.status(404).json({
126
121
  ok: false,
127
- error: "launch binding not found",
122
+ error: "launch binding not found for workspacePath and serverUrl",
128
123
  queueSize: getMcpLaunchQueueSize(workspacePath),
129
124
  });
130
125
  return;
@@ -80,7 +80,7 @@ terminalRouter.post('/start', validateToken, async (req, res) => {
80
80
  });
81
81
  // SDK 模式
82
82
  if (mode === 'sdk') {
83
- await startSdkSession(req, res, queuedBinding?.id);
83
+ await startSdkSession(req, res);
84
84
  return;
85
85
  }
86
86
  // PTY 模式(原有逻辑)
@@ -110,7 +110,6 @@ terminalRouter.post('/start', validateToken, async (req, res) => {
110
110
  env: {
111
111
  ...process.env,
112
112
  AWS_AGENT_ID: String(agentId),
113
- AWS_MCP_LAUNCH_BINDING_ID: queuedBinding?.id || '',
114
113
  AWS_MCP_CLAIM_LAUNCH_BINDING: 'true',
115
114
  },
116
115
  });
@@ -176,14 +175,13 @@ terminalRouter.post('/start', validateToken, async (req, res) => {
176
175
  workspacePath,
177
176
  command: actualCommand,
178
177
  mode: 'pty',
179
- mcpLaunchBindingId: queuedBinding?.id,
180
178
  });
181
179
  });
182
180
  /**
183
181
  * 启动 SDK 会话
184
182
  * 支持 MCP 配置和空闲命令
185
183
  */
186
- async function startSdkSession(req, res, mcpLaunchBindingId) {
184
+ async function startSdkSession(req, res) {
187
185
  const { agentId, workspacePath, command, autoAccept = true, initialPrompt,
188
186
  // MCP 配置 - 加载 aws-client-agent-mcp
189
187
  mcpConfigPath, extraMcpServers,
@@ -213,7 +211,6 @@ async function startSdkSession(req, res, mcpLaunchBindingId) {
213
211
  envOverrides: {
214
212
  AWS_AGENT_ID: String(agentId),
215
213
  AWS_WORKSPACE_PATH: String(workspacePath),
216
- AWS_MCP_LAUNCH_BINDING_ID: mcpLaunchBindingId || '',
217
214
  AWS_MCP_CLAIM_LAUNCH_BINDING: 'true',
218
215
  },
219
216
  };
@@ -56,15 +56,14 @@ describe('terminal configuration', () => {
56
56
  expect(getShellConfig('linux').shell).toBe('bash');
57
57
  });
58
58
  it('builds correct terminal environment', () => {
59
- const buildTerminalEnv = (agentId, bindingId, baseEnv) => ({
59
+ const buildTerminalEnv = (agentId, baseEnv) => ({
60
60
  ...baseEnv,
61
61
  AWS_AGENT_ID: agentId,
62
- AWS_MCP_LAUNCH_BINDING_ID: bindingId,
63
62
  AWS_MCP_CLAIM_LAUNCH_BINDING: 'true',
64
63
  });
65
- const env = buildTerminalEnv('agent-123', 'binding-456', { PATH: '/usr/bin' });
64
+ const env = buildTerminalEnv('agent-123', { PATH: '/usr/bin' });
66
65
  expect(env.AWS_AGENT_ID).toBe('agent-123');
67
- expect(env.AWS_MCP_LAUNCH_BINDING_ID).toBe('binding-456');
66
+ expect(env.AWS_MCP_LAUNCH_BINDING_ID).toBeUndefined();
68
67
  expect(env.AWS_MCP_CLAIM_LAUNCH_BINDING).toBe('true');
69
68
  });
70
69
  });
@@ -75,6 +75,12 @@ export declare function requestRuntimeAccessTokenRefresh(): Promise<{
75
75
  updated?: boolean;
76
76
  error?: string;
77
77
  }>;
78
+ export declare function requestRuntimeAccessTokenRefreshForServer(serverBaseUrl: string): Promise<{
79
+ success: boolean;
80
+ runtimeAccessToken?: string;
81
+ updated?: boolean;
82
+ error?: string;
83
+ }>;
78
84
  export declare function unregister(): Promise<boolean>;
79
85
  /**
80
86
  * 获取注册状态
@@ -1 +1 @@
1
- {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA+CH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwBD,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AA6DD;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAGtD;AAyJD;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,kBAAkB,CA2C/C;AAED,wBAAgB,WAAW,IAAI,kBAAkB,EAAE,CA0ClD;AA4OD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACzC,OAAO,CAAC,OAAO,CAAC,CAalB;AAyHD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAqED;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAuBnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;gBAlzBtB,OAAO;iBACN,MAAM;mBACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACvB,IAAI;YACV,MAAM;EAgzBf;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA2ED"}
1
+ {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiDH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwBD,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAiED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAGtD;AAyJD;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,kBAAkB,CA2C/C;AAED,wBAAgB,WAAW,IAAI,kBAAkB,EAAE,CA0ClD;AA4OD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACzC,OAAO,CAAC,OAAO,CAAC,CAalB;AAyHD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAqED;AAED,wBAAsB,yCAAyC,CAC7D,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA2ED;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAuBnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;gBA14BtB,OAAO;iBACN,MAAM;mBACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACvB,IAAI;YACV,MAAM;EAw4Bf;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA2ED"}
@@ -13,7 +13,7 @@ import path from "node:path";
13
13
  import fs from "node:fs";
14
14
  import { logger } from "../utils/logger.js";
15
15
  import { schedulerBaseUrl, runtimeToken } from "../config.js";
16
- import { getRuntimeAccessToken, getRuntimeBindingPublicState, loadRuntimeBinding, saveRuntimeBinding, } from "./runtime-binding.js";
16
+ import { getRuntimeAccessToken, getRuntimeBindingPublicState, loadRuntimeBinding, normalizeSchedulerBaseUrl, saveRuntimeBinding, saveScopedRuntimeAccessToken, } from "./runtime-binding.js";
17
17
  // 默认配置
18
18
  const DEFAULT_CONFIG = {
19
19
  enabled: false,
@@ -37,6 +37,9 @@ function normalizeOptionalString(value) {
37
37
  const normalized = String(value).trim();
38
38
  return normalized || undefined;
39
39
  }
40
+ function normalizeSchedulerHttpBaseUrl(value) {
41
+ return normalizeSchedulerBaseUrl(value);
42
+ }
40
43
  function normalizeOptionalBoolean(value) {
41
44
  if (typeof value === "boolean") {
42
45
  return value;
@@ -649,6 +652,65 @@ export async function requestRuntimeAccessTokenRefresh() {
649
652
  return { success: false, error: message };
650
653
  }
651
654
  }
655
+ export async function requestRuntimeAccessTokenRefreshForServer(serverBaseUrl) {
656
+ const targetServerUrl = normalizeSchedulerHttpBaseUrl(serverBaseUrl);
657
+ if (!targetServerUrl) {
658
+ return { success: false, error: "serverUrl is required for runtime token refresh" };
659
+ }
660
+ const config = loadConfigs().find((item) => normalizeSchedulerHttpBaseUrl(item.serverUrl) === targetServerUrl) || loadPrimaryLifecycleConfig();
661
+ if (!config.userKey) {
662
+ return {
663
+ success: false,
664
+ error: "userKey is required for runtime token refresh",
665
+ };
666
+ }
667
+ const state = getRuntimeBindingPublicState();
668
+ const localIp = getLocalIpAddress(targetServerUrl);
669
+ const runtimeBridgePort = process.env.AWS_RUNTIME_BRIDGE_PORT || 18081;
670
+ const runtimeBridgeBaseUrl = `http://${config.registerIp || config.virtualIp || localIp}:${runtimeBridgePort}`;
671
+ try {
672
+ const response = await axios.post(`${targetServerUrl}/api/instances/runtime-tokens/refresh`, {
673
+ tenantId: config.tenantId,
674
+ userKey: config.userKey,
675
+ instanceId: state.instanceId,
676
+ instanceName: config.instanceName,
677
+ runtimeBridgeBaseUrl,
678
+ }, {
679
+ headers: {
680
+ "Content-Type": "application/json",
681
+ "X-Runtime-Token": runtimeToken,
682
+ },
683
+ timeout: 10000,
684
+ });
685
+ if (!response.data.success || !response.data.runtimeAccessToken) {
686
+ return {
687
+ success: false,
688
+ error: response.data.message ||
689
+ "scheduler did not return runtimeAccessToken",
690
+ };
691
+ }
692
+ const userId = response.data.userId || config.userKey;
693
+ const previousToken = getRuntimeAccessToken(userId, targetServerUrl);
694
+ const updated = previousToken !== response.data.runtimeAccessToken;
695
+ saveScopedRuntimeAccessToken({
696
+ userId,
697
+ serverBaseUrl: targetServerUrl,
698
+ accessToken: response.data.runtimeAccessToken,
699
+ });
700
+ return {
701
+ success: true,
702
+ runtimeAccessToken: response.data.runtimeAccessToken,
703
+ updated,
704
+ };
705
+ }
706
+ catch (error) {
707
+ const err = error;
708
+ const message = err.response?.data
709
+ ? JSON.stringify(err.response.data)
710
+ : err.message;
711
+ return { success: false, error: message };
712
+ }
713
+ }
652
714
  export async function unregister() {
653
715
  if (!registrationState.registered || !registrationState.instanceId) {
654
716
  logger.info("[AutoRegister] 实例未注册,无需注销");
@@ -1 +1 @@
1
- {"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAuB7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC3C;AAuBD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAgLD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,MAAM,GAAG,IAAI,CAoDf;AA2ED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAEpB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAsBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,kBAAkB,CAwBpB;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAgBtD"}
1
+ {"version":3,"file":"aws-client-agent-mcp.d.ts","sourceRoot":"","sources":["../../src/services/aws-client-agent-mcp.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAsB7C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,sCAAsC;IACrD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,sCAAsC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC3C;AAuBD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAgLD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,MAAM,GAAG,IAAI,CAoDf;AA2ED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAEpB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,sCAA2C,GACnD,kBAAkB,CAsBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,kBAAkB,CA0BpB;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAgBtD"}
@@ -4,10 +4,9 @@ import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { getRuntimeHomeDir, port, schedulerBaseUrl } from "../config.js";
6
6
  import { logger } from "../utils/logger.js";
7
- import { getRuntimeAccessToken, loadRuntimeBinding, } from "./runtime-binding.js";
7
+ import { getRuntimeAccessToken, loadRuntimeBinding, normalizeSchedulerBaseUrl, } from "./runtime-binding.js";
8
8
  export const AWS_MCP_SERVER_NAME = "aws-mcp";
9
9
  const AWS_MCP_ALLOWED_ENV_KEYS = [
10
- "AWS_INTERNAL_API_KEY",
11
10
  "AWS_PROJECT_NAME",
12
11
  "AWS_PROMPT",
13
12
  "AWS_ROLE_NAME",
@@ -236,7 +235,7 @@ function parseAwsClientAgentMcpArgs(raw) {
236
235
  return [];
237
236
  }
238
237
  function toWebSocketUrl(baseUrl) {
239
- const url = new URL("/ws/agent", baseUrl);
238
+ const url = new URL("/ws/agent", normalizeSchedulerBaseUrl(baseUrl) || baseUrl);
240
239
  if (url.protocol === "https:") {
241
240
  url.protocol = "wss:";
242
241
  }
@@ -246,7 +245,7 @@ function toWebSocketUrl(baseUrl) {
246
245
  return url.toString();
247
246
  }
248
247
  function toMcpHttpUrl(baseUrl) {
249
- return new URL("/mcp/call", baseUrl).toString();
248
+ return new URL("/mcp/call", normalizeSchedulerBaseUrl(baseUrl) || baseUrl).toString();
250
249
  }
251
250
  function resolveSchedulerBaseUrlForMcp() {
252
251
  const envSchedulerBaseUrl = String(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL || "").trim();
@@ -297,6 +296,7 @@ export function buildAwsMcpServerConfig(input) {
297
296
  AWS_SERVER_URL: env.AWS_SERVER_URL || toWebSocketUrl(effectiveSchedulerBaseUrl),
298
297
  AWS_MCP_HTTP_URL: env.AWS_MCP_HTTP_URL || toMcpHttpUrl(effectiveSchedulerBaseUrl),
299
298
  AWS_RUNTIME_BRIDGE_BASE_URL: env.AWS_RUNTIME_BRIDGE_BASE_URL || `http://127.0.0.1:${port}`,
299
+ AWS_MCP_CLAIM_LAUNCH_BINDING: env.AWS_MCP_CLAIM_LAUNCH_BINDING || "true",
300
300
  ...(issuedRuntimeAccessToken
301
301
  ? { AWS_RUNTIME_ACCESS_TOKEN: issuedRuntimeAccessToken }
302
302
  : {}),
@@ -216,6 +216,20 @@ describe('aws-client-agent-mcp service', () => {
216
216
  expect(config.env.AWS_RUNTIME_CALLBACK_TOKEN).toBeUndefined();
217
217
  expect(config.env.CUSTOM_SECRET).toBeUndefined();
218
218
  });
219
+ it('repairs duplicated scheduler ports when building MCP URLs', async () => {
220
+ process.env.AWS_CLIENT_AGENT_MCP_COMMAND = 'aws-client-agent-mcp';
221
+ process.env.AWS_RUNTIME_HOME_DIR = mkdtempSync(path.join(os.tmpdir(), 'aws-mcp-config-'));
222
+ process.env.AWS_RUNTIME_SCHEDULER_BASE_URL = 'http://127.0.0.1:8080:8080';
223
+ process.env.AWS_SERVER_URL = '';
224
+ process.env.AWS_MCP_HTTP_URL = '';
225
+ const mod = await import('./aws-client-agent-mcp.js');
226
+ const config = mod.buildAwsMcpServerConfig({
227
+ agentId: 'agent-1',
228
+ workspacePath: '/workspace/demo',
229
+ });
230
+ expect(config.env.AWS_SERVER_URL).toBe('ws://127.0.0.1:8080/ws/agent');
231
+ expect(config.env.AWS_MCP_HTTP_URL).toBe('http://127.0.0.1:8080/mcp/call');
232
+ });
219
233
  it('ignores malformed AWS_CLIENT_AGENT_MCP_ARGS JSON', async () => {
220
234
  process.env.AWS_CLIENT_AGENT_MCP_COMMAND = 'custom-aws-client-agent-mcp';
221
235
  process.env.AWS_CLIENT_AGENT_MCP_ARGS = '{bad json';
@@ -24,8 +24,6 @@ export interface ClaimedMcpLaunchBinding extends McpLaunchBinding {
24
24
  schedulerBaseUrl?: string;
25
25
  }
26
26
  export interface McpLaunchBindingClaimRequest {
27
- agentId: unknown;
28
- bindingId?: unknown;
29
27
  workspacePath: unknown;
30
28
  serverUrl?: unknown;
31
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAqCD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CAoB7F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,GAAG,IAAI,CAoC3G;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAMpE;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
1
+ {"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAmDD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CA+B7F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,GAAG,IAAI,CA0C3G;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAOpE;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
@@ -1,5 +1,7 @@
1
1
  import path from "node:path";
2
- import { getRuntimeAccessToken, loadRuntimeBinding } from "./runtime-binding.js";
2
+ import { schedulerBaseUrl as defaultSchedulerBaseUrl } from "../config.js";
3
+ import { getRuntimeAccessToken, loadRuntimeBinding, normalizeSchedulerBaseUrl } from "./runtime-binding.js";
4
+ const LAUNCH_BINDING_TTL_MS = 5 * 60 * 1000;
3
5
  const launchBindings = [];
4
6
  function normalizeWorkspacePath(workspacePath) {
5
7
  const raw = String(workspacePath || "").trim();
@@ -11,57 +13,82 @@ function normalizeWorkspacePath(workspacePath) {
11
13
  function normalizeOptionalUrl(value) {
12
14
  return String(value || "").trim();
13
15
  }
14
- function normalizeServerUrl(serverUrl) {
15
- const raw = String(serverUrl || "").trim();
16
+ function normalizeSchedulerOrigin(serverUrl) {
17
+ const raw = normalizeSchedulerBaseUrl(serverUrl) || String(serverUrl || "").trim();
16
18
  if (!raw) {
17
19
  return "";
18
20
  }
19
21
  try {
20
22
  const url = new URL(raw);
21
- url.protocol = url.protocol.toLowerCase();
23
+ if (url.protocol === "ws:") {
24
+ url.protocol = "http:";
25
+ }
26
+ else if (url.protocol === "wss:") {
27
+ url.protocol = "https:";
28
+ }
29
+ else {
30
+ url.protocol = url.protocol.toLowerCase();
31
+ }
22
32
  url.hostname = url.hostname.toLowerCase();
23
- url.pathname = url.pathname.replace(/\/+$/, "");
24
- return url.toString().replace(/\/+$/, "");
33
+ return url.origin;
25
34
  }
26
35
  catch {
27
36
  return raw.replace(/\/+$/, "").toLowerCase();
28
37
  }
29
38
  }
39
+ function pruneExpiredBindings(now = Date.now()) {
40
+ for (let index = launchBindings.length - 1; index >= 0; index -= 1) {
41
+ const enqueuedAt = Date.parse(launchBindings[index]?.enqueuedAt || "");
42
+ if (!Number.isFinite(enqueuedAt) || now - enqueuedAt > LAUNCH_BINDING_TTL_MS) {
43
+ launchBindings.splice(index, 1);
44
+ }
45
+ }
46
+ }
30
47
  function createBindingId(agentId) {
31
48
  return `${agentId}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
32
49
  }
33
50
  export function enqueueMcpLaunchBinding(input) {
51
+ pruneExpiredBindings();
34
52
  const agentId = String(input.agentId || "").trim();
35
53
  const workspaceKey = normalizeWorkspacePath(input.workspacePath);
36
54
  if (!agentId || !workspaceKey) {
37
55
  return null;
38
56
  }
57
+ const runtimeState = loadRuntimeBinding();
58
+ const schedulerUrl = normalizeSchedulerBaseUrl(input.serverUrl || input.schedulerBaseUrl || runtimeState.schedulerBaseUrl || defaultSchedulerBaseUrl) || normalizeOptionalUrl(input.serverUrl || input.schedulerBaseUrl || runtimeState.schedulerBaseUrl || defaultSchedulerBaseUrl);
59
+ const schedulerBindingBaseUrl = normalizeSchedulerBaseUrl(input.schedulerBaseUrl || runtimeState.schedulerBaseUrl || defaultSchedulerBaseUrl) || normalizeOptionalUrl(input.schedulerBaseUrl || runtimeState.schedulerBaseUrl || defaultSchedulerBaseUrl);
39
60
  const binding = {
40
61
  id: createBindingId(agentId),
41
62
  agentId,
42
63
  workspacePath: path.resolve(String(input.workspacePath)),
43
- serverUrl: normalizeOptionalUrl(input.serverUrl || input.schedulerBaseUrl),
64
+ serverUrl: schedulerUrl,
44
65
  mcpHttpUrl: normalizeOptionalUrl(input.mcpHttpUrl),
45
66
  runtimeAccessToken: normalizeOptionalUrl(input.runtimeAccessToken),
46
67
  userId: normalizeOptionalUrl(input.userId),
47
- schedulerBaseUrl: normalizeOptionalUrl(input.schedulerBaseUrl),
68
+ schedulerBaseUrl: schedulerBindingBaseUrl,
48
69
  enqueuedAt: new Date().toISOString(),
49
70
  };
50
71
  launchBindings.push(binding);
51
72
  return binding;
52
73
  }
53
74
  export function claimMcpLaunchBinding(request) {
54
- const agentId = String(request.agentId || "").trim();
55
- const bindingId = String(request.bindingId || "").trim();
75
+ pruneExpiredBindings();
56
76
  const workspaceKey = normalizeWorkspacePath(request.workspacePath);
57
- const serverKey = normalizeServerUrl(request.serverUrl);
58
- if (!agentId || !bindingId || !workspaceKey || !serverKey) {
77
+ const serverKey = normalizeSchedulerOrigin(request.serverUrl);
78
+ if (!workspaceKey) {
59
79
  return null;
60
80
  }
61
- const bindingIndex = launchBindings.findIndex((binding) => binding.agentId === agentId &&
62
- binding.id === bindingId &&
63
- normalizeWorkspacePath(binding.workspacePath) === workspaceKey &&
64
- normalizeServerUrl(binding.serverUrl || binding.schedulerBaseUrl) === serverKey);
81
+ let bindingIndex = launchBindings.findIndex((binding) => normalizeWorkspacePath(binding.workspacePath) === workspaceKey &&
82
+ serverKey &&
83
+ normalizeSchedulerOrigin(binding.serverUrl || binding.schedulerBaseUrl) === serverKey);
84
+ if (bindingIndex < 0) {
85
+ const workspaceMatches = launchBindings
86
+ .map((binding, index) => ({ binding, index }))
87
+ .filter(({ binding }) => normalizeWorkspacePath(binding.workspacePath) === workspaceKey);
88
+ if (workspaceMatches.length === 1) {
89
+ bindingIndex = workspaceMatches[0]?.index ?? -1;
90
+ }
91
+ }
65
92
  if (bindingIndex < 0) {
66
93
  return null;
67
94
  }
@@ -81,6 +108,7 @@ export function claimMcpLaunchBinding(request) {
81
108
  };
82
109
  }
83
110
  export function getMcpLaunchQueueSize(workspacePath) {
111
+ pruneExpiredBindings();
84
112
  const workspaceKey = normalizeWorkspacePath(workspacePath);
85
113
  if (!workspaceKey) {
86
114
  return 0;