aws-runtime-bridge 1.1.1 → 1.1.2

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 (97) hide show
  1. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +166 -0
  2. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -0
  3. package/package/aws-client-agent-mcp/dist/agent-client.js +602 -0
  4. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -0
  5. package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts +2 -0
  6. package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts.map +1 -0
  7. package/package/aws-client-agent-mcp/dist/agent-client.test.js +534 -0
  8. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -0
  9. package/package/aws-client-agent-mcp/dist/config.d.ts +22 -0
  10. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -0
  11. package/package/aws-client-agent-mcp/dist/config.js +106 -0
  12. package/package/aws-client-agent-mcp/dist/config.js.map +1 -0
  13. package/package/aws-client-agent-mcp/dist/config.test.d.ts +2 -0
  14. package/package/aws-client-agent-mcp/dist/config.test.d.ts.map +1 -0
  15. package/package/aws-client-agent-mcp/dist/config.test.js +139 -0
  16. package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -0
  17. package/package/aws-client-agent-mcp/dist/constants.d.ts +15 -0
  18. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -0
  19. package/package/aws-client-agent-mcp/dist/constants.js +19 -0
  20. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -0
  21. package/package/aws-client-agent-mcp/dist/http-client.d.ts +28 -0
  22. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -0
  23. package/package/aws-client-agent-mcp/dist/http-client.js +96 -0
  24. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -0
  25. package/package/aws-client-agent-mcp/dist/http-client.test.d.ts +2 -0
  26. package/package/aws-client-agent-mcp/dist/http-client.test.d.ts.map +1 -0
  27. package/package/aws-client-agent-mcp/dist/http-client.test.js +228 -0
  28. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -0
  29. package/package/aws-client-agent-mcp/dist/index.d.ts +14 -0
  30. package/package/aws-client-agent-mcp/dist/index.d.ts.map +1 -0
  31. package/package/aws-client-agent-mcp/dist/index.js +30 -0
  32. package/package/aws-client-agent-mcp/dist/index.js.map +1 -0
  33. package/package/aws-client-agent-mcp/dist/logger.d.ts +7 -0
  34. package/package/aws-client-agent-mcp/dist/logger.d.ts.map +1 -0
  35. package/package/aws-client-agent-mcp/dist/logger.js +19 -0
  36. package/package/aws-client-agent-mcp/dist/logger.js.map +1 -0
  37. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +77 -0
  38. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -0
  39. package/package/aws-client-agent-mcp/dist/mcp-server.js +438 -0
  40. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -0
  41. package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts +2 -0
  42. package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts.map +1 -0
  43. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +624 -0
  44. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -0
  45. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +78 -0
  46. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -0
  47. package/package/aws-client-agent-mcp/dist/mcp-tools.js +420 -0
  48. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -0
  49. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +61 -0
  50. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -0
  51. package/package/aws-client-agent-mcp/dist/memory-store.js +268 -0
  52. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -0
  53. package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts +2 -0
  54. package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts.map +1 -0
  55. package/package/aws-client-agent-mcp/dist/memory-store.test.js +164 -0
  56. package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -0
  57. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +87 -0
  58. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -0
  59. package/package/aws-client-agent-mcp/dist/message-buffer.js +185 -0
  60. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -0
  61. package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts +2 -0
  62. package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts.map +1 -0
  63. package/package/aws-client-agent-mcp/dist/message-buffer.test.js +44 -0
  64. package/package/aws-client-agent-mcp/dist/message-buffer.test.js.map +1 -0
  65. package/package/aws-client-agent-mcp/dist/messageContent.d.ts +53 -0
  66. package/package/aws-client-agent-mcp/dist/messageContent.d.ts.map +1 -0
  67. package/package/aws-client-agent-mcp/dist/messageContent.js +125 -0
  68. package/package/aws-client-agent-mcp/dist/messageContent.js.map +1 -0
  69. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +3 -0
  70. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -0
  71. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +50 -0
  72. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -0
  73. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts +2 -0
  74. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts.map +1 -0
  75. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +90 -0
  76. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -0
  77. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +66 -0
  78. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -0
  79. package/package/aws-client-agent-mcp/dist/status-reporter.js +237 -0
  80. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -0
  81. package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts +2 -0
  82. package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts.map +1 -0
  83. package/package/aws-client-agent-mcp/dist/status-reporter.test.js +19 -0
  84. package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -0
  85. package/package/aws-client-agent-mcp/dist/types.d.ts +309 -0
  86. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -0
  87. package/package/aws-client-agent-mcp/dist/types.js +9 -0
  88. package/package/aws-client-agent-mcp/dist/types.js.map +1 -0
  89. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +94 -0
  90. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -0
  91. package/package/aws-client-agent-mcp/dist/websocket-client.js +316 -0
  92. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -0
  93. package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts +2 -0
  94. package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts.map +1 -0
  95. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +191 -0
  96. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -0
  97. package/package.json +1 -1
@@ -0,0 +1,185 @@
1
+ /**
2
+ * 消息缓冲与派发模块
3
+ * 负责消息的缓冲、分类和派发
4
+ */
5
+ import { logger } from './logger.js';
6
+ /**
7
+ * 消息缓冲区
8
+ * 管理消息的存储、分类和派发
9
+ */
10
+ export class MessageBuffer {
11
+ buffer = [];
12
+ resolvers = [];
13
+ onMessageArrived = null;
14
+ isPolling = false;
15
+ /**
16
+ * 设置消息到达回调
17
+ * 当有新消息到达且正在 poll 等待时,会立即调用此回调
18
+ */
19
+ setOnMessageArrived(callback) {
20
+ this.onMessageArrived = callback;
21
+ }
22
+ /**
23
+ * 设置是否正在 poll 等待
24
+ */
25
+ setIsPolling(polling) {
26
+ this.isPolling = polling;
27
+ }
28
+ /**
29
+ * 添加消息到缓冲区
30
+ */
31
+ push(message) {
32
+ this.buffer.push(message);
33
+ logger.info(`[MessageBuffer] 消息入缓冲区,当前数量: ${this.buffer.length}`);
34
+ // 如果正在 poll 等待,立即触发状态变化回调
35
+ if (this.isPolling && this.onMessageArrived) {
36
+ logger.info('[MessageBuffer] 检测到 poll 等待中,触发消息到达回调');
37
+ this.onMessageArrived();
38
+ }
39
+ this.tryDispatch();
40
+ }
41
+ /**
42
+ * 接收 Profile 推送。
43
+ * 主流程:记录日志 -> 不进入未读缓冲区 -> 引导调用方通过 get_profile 获取身份详情。
44
+ */
45
+ setProfileMessage(profile) {
46
+ logger.info(`[MessageBuffer] 收到 Profile 推送,displayName: ${profile.displayName}。身份信息请通过 get_profile 获取。`);
47
+ }
48
+ /**
49
+ * 移除 Profile 系统消息。
50
+ * 当前未再向未读消息注入 profile 信息,保留该方法仅为兼容既有调用链。
51
+ */
52
+ removeProfileMessage() {
53
+ logger.info('[MessageBuffer] removeProfileMessage 被调用,当前无需移除未读身份消息');
54
+ }
55
+ /**
56
+ * 检查是否有 Profile 消息。
57
+ * 当前身份信息不会进入未读消息,因此固定返回 false。
58
+ */
59
+ hasProfileMessage() {
60
+ return false;
61
+ }
62
+ /**
63
+ * 获取 Profile 消息。
64
+ * 当前身份信息不会进入未读消息,因此固定返回 null。
65
+ */
66
+ getProfileMessage() {
67
+ return null;
68
+ }
69
+ /**
70
+ * 阻塞等待新消息
71
+ * 如果缓冲区有消息则立即返回,否则阻塞等待
72
+ * @param timeoutMs 可选超时时间(毫秒),超时后返回空消息而不继续阻塞
73
+ */
74
+ poll(timeoutMs) {
75
+ logger.info(`[MessageBuffer] poll() 被调用,buffer: ${this.buffer.length}${timeoutMs ? `,超时: ${timeoutMs}ms` : ''}`);
76
+ // 缓冲区有消息则立即返回
77
+ if (this.buffer.length > 0) {
78
+ const messages = this.consumeAll();
79
+ logger.info(`[MessageBuffer] poll 立即返回,私聊: ${messages.directMessages.length},群聊: ${messages.groupMessages.length}`);
80
+ return Promise.resolve(messages);
81
+ }
82
+ // 标记正在 poll 等待
83
+ this.isPolling = true;
84
+ // 缓冲区为空,阻塞等待
85
+ return new Promise((resolve) => {
86
+ let timer = null;
87
+ const resolver = (messages) => {
88
+ // 从列表中移除自己
89
+ const index = this.resolvers.indexOf(resolver);
90
+ if (index > -1) {
91
+ this.resolvers.splice(index, 1);
92
+ }
93
+ // 清除超时定时器
94
+ if (timer) {
95
+ clearTimeout(timer);
96
+ timer = null;
97
+ }
98
+ // 标记不再 poll 等待
99
+ this.isPolling = false;
100
+ logger.info(`[MessageBuffer] poll 收到消息,私聊: ${messages.directMessages.length},群聊: ${messages.groupMessages.length}`);
101
+ resolve(messages);
102
+ };
103
+ this.resolvers.push(resolver);
104
+ // 处理竞态:注册后立即尝试派发
105
+ this.tryDispatch();
106
+ // 设置超时:超时后移除 resolver 并返回空消息
107
+ if (timeoutMs && timeoutMs > 0) {
108
+ timer = setTimeout(() => {
109
+ const index = this.resolvers.indexOf(resolver);
110
+ if (index > -1) {
111
+ this.resolvers.splice(index, 1);
112
+ }
113
+ // 标记不再 poll 等待
114
+ this.isPolling = false;
115
+ logger.info(`[MessageBuffer] poll 超时(${timeoutMs}ms),返回空消息`);
116
+ resolve({ directMessages: [], groupMessages: [] });
117
+ }, timeoutMs);
118
+ }
119
+ });
120
+ }
121
+ /**
122
+ * 非阻塞获取消息
123
+ */
124
+ get() {
125
+ if (this.buffer.length > 0) {
126
+ const messages = this.consumeAll();
127
+ logger.info(`[MessageBuffer] get 返回消息,私聊: ${messages.directMessages.length},群聊: ${messages.groupMessages.length}`);
128
+ return messages;
129
+ }
130
+ return { directMessages: [], groupMessages: [] };
131
+ }
132
+ /**
133
+ * 获取缓冲区大小
134
+ */
135
+ size() {
136
+ return this.buffer.length;
137
+ }
138
+ /**
139
+ * 清空缓冲区
140
+ */
141
+ clear() {
142
+ this.buffer = [];
143
+ this.resolvers = [];
144
+ }
145
+ /**
146
+ * 尝试派发缓冲区消息给等待的 resolver
147
+ */
148
+ tryDispatch() {
149
+ // 当有 buffer 消息时,派发给等待的 resolver
150
+ while (this.resolvers.length > 0 && this.buffer.length > 0) {
151
+ const resolver = this.resolvers.shift();
152
+ if (resolver) {
153
+ const messages = this.consumeAll();
154
+ resolver(messages);
155
+ }
156
+ }
157
+ }
158
+ /**
159
+ * 消费缓冲区所有消息并分类
160
+ */
161
+ consumeAll() {
162
+ const directMessages = [];
163
+ const groupMessages = [];
164
+ while (this.buffer.length > 0) {
165
+ const msg = this.buffer.shift();
166
+ if (msg) {
167
+ if (this.isDirectMessage(msg)) {
168
+ directMessages.push(msg);
169
+ }
170
+ else {
171
+ groupMessages.push(msg);
172
+ }
173
+ }
174
+ }
175
+ return { directMessages, groupMessages };
176
+ }
177
+ /**
178
+ * 判断消息类型
179
+ * DirectMessage 的 msgId 是 string,GroupMessage 的 msgId 是 number
180
+ */
181
+ isDirectMessage(msg) {
182
+ return typeof msg.msgId === 'string';
183
+ }
184
+ }
185
+ //# sourceMappingURL=message-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-buffer.js","sourceRoot":"","sources":["../src/message-buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=message-buffer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-buffer.test.d.ts","sourceRoot":"","sources":["../src/message-buffer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+ import { MessageBuffer } from './message-buffer.js';
4
+ describe('MessageBuffer poll', () => {
5
+ it('keeps waiting until a new direct message arrives', async () => {
6
+ const buffer = new MessageBuffer();
7
+ let settled = false;
8
+ const pendingPoll = buffer.poll().then((messages) => {
9
+ settled = true;
10
+ return messages;
11
+ });
12
+ await new Promise((resolve) => setTimeout(resolve, 30));
13
+ assert.equal(settled, false, 'poll should remain pending when no message arrives');
14
+ const directMessage = {
15
+ msgId: 'dm-1',
16
+ senderId: 'agent-1',
17
+ senderName: 'Agent One',
18
+ content: 'hello',
19
+ requireReply: false,
20
+ timestamp: new Date().toISOString()
21
+ };
22
+ buffer.push(directMessage);
23
+ const messages = await pendingPoll;
24
+ assert.equal(messages.directMessages.length, 1);
25
+ assert.deepEqual(messages.directMessages[0], directMessage);
26
+ assert.deepEqual(messages.groupMessages, []);
27
+ });
28
+ it('returns buffered group messages immediately without blocking', async () => {
29
+ const buffer = new MessageBuffer();
30
+ const groupMessage = {
31
+ msgId: 1,
32
+ senderId: 'human-1',
33
+ senderName: 'Human One',
34
+ content: 'announcement',
35
+ timestamp: new Date().toISOString()
36
+ };
37
+ buffer.push(groupMessage);
38
+ const messages = await buffer.poll();
39
+ assert.deepEqual(messages.directMessages, []);
40
+ assert.equal(messages.groupMessages.length, 1);
41
+ assert.deepEqual(messages.groupMessages[0], groupMessage);
42
+ });
43
+ });
44
+ //# sourceMappingURL=message-buffer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-buffer.test.js","sourceRoot":"","sources":["../src/message-buffer.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAClD,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,oDAAoD,CAAC,CAAC;QAEnF,MAAM,aAAa,GAAkB;YACnC,KAAK,EAAE,MAAM;YACb,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,WAAW;YACvB,OAAO,EAAE,OAAO;YAChB,YAAY,EAAE,KAAK;YACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAE3B,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC5D,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAEnC,MAAM,YAAY,GAAiB;YACjC,KAAK,EAAE,CAAC;YACR,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,WAAW;YACvB,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAE1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 消息内容解析工具
3
+ *
4
+ * 负责解析消息中的图片标记,支持两种格式:
5
+ * 1. [图片: url] 标记格式(推荐,与前端兼容)
6
+ * 2. JSON 格式 { text, attachments }(兼容旧消息)
7
+ */
8
+ /**
9
+ * 图片附件信息
10
+ */
11
+ export interface ImageAttachment {
12
+ type: "image";
13
+ url: string;
14
+ name: string;
15
+ mediaType: string;
16
+ size: number;
17
+ }
18
+ /**
19
+ * 解析后的消息内容
20
+ */
21
+ export interface ParsedMessageContent {
22
+ text: string;
23
+ attachments: ImageAttachment[];
24
+ hasImages: boolean;
25
+ }
26
+ /**
27
+ * 解析消息内容
28
+ *
29
+ * @param content 消息内容(可能是纯文本、[图片: url] 格式或 JSON 格式)
30
+ * @returns 解析后的内容
31
+ */
32
+ export declare function parseMessageContent(content: string): ParsedMessageContent;
33
+ /**
34
+ * 构造多模态消息内容块
35
+ *
36
+ * 用于 Claude Agent SDK 的流式输入模式。
37
+ * SDK 直接支持 URL 引用图片,无需下载转 Base64。
38
+ *
39
+ * @param parsedContent 解析后的消息内容
40
+ * @param _baseUrl 服务器基础 URL(未使用,SDK 直接处理 URL)
41
+ * @returns 内容块数组
42
+ */
43
+ export declare function buildMultimodalContentBlocks(parsedContent: ParsedMessageContent, _baseUrl: string): Array<{
44
+ type: string;
45
+ text?: string;
46
+ source?: {
47
+ type: string;
48
+ url?: string;
49
+ media_type?: string;
50
+ data?: string;
51
+ };
52
+ }>;
53
+ //# sourceMappingURL=messageContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageContent.d.ts","sourceRoot":"","sources":["../src/messageContent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,CA2DzE;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,oBAAoB,EACnC,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CA8BrH"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * 消息内容解析工具
3
+ *
4
+ * 负责解析消息中的图片标记,支持两种格式:
5
+ * 1. [图片: url] 标记格式(推荐,与前端兼容)
6
+ * 2. JSON 格式 { text, attachments }(兼容旧消息)
7
+ */
8
+ import { logger } from "./logger.js";
9
+ /**
10
+ * 解析消息内容
11
+ *
12
+ * @param content 消息内容(可能是纯文本、[图片: url] 格式或 JSON 格式)
13
+ * @returns 解析后的内容
14
+ */
15
+ export function parseMessageContent(content) {
16
+ if (!content) {
17
+ return { text: "", attachments: [], hasImages: false };
18
+ }
19
+ // 1. 尝试解析 [图片: url] 标记格式
20
+ const imageTagRegex = /\[图片\s*:\s*([^\]\n]+?)\s*\]/gi;
21
+ const attachments = [];
22
+ const seen = new Set();
23
+ let match = imageTagRegex.exec(content);
24
+ while (match !== null) {
25
+ const url = (match[1] || "").trim();
26
+ if (url && !seen.has(url)) {
27
+ seen.add(url);
28
+ attachments.push({
29
+ type: "image",
30
+ url,
31
+ name: getFileName(url),
32
+ mediaType: getMediaType(url),
33
+ size: 0,
34
+ });
35
+ }
36
+ match = imageTagRegex.exec(content);
37
+ }
38
+ // 移除图片标记,保留纯文本
39
+ const text = content.replace(imageTagRegex, "").replace(/\s+/g, " ").trim();
40
+ if (attachments.length > 0) {
41
+ return {
42
+ text,
43
+ attachments,
44
+ hasImages: true,
45
+ };
46
+ }
47
+ // 2. 尝试解析 JSON 格式(兼容旧消息)
48
+ try {
49
+ const parsed = JSON.parse(content);
50
+ // 检查是否是 JSON 格式(带 attachments)
51
+ if (parsed && typeof parsed === "object" && "text" in parsed) {
52
+ const imageAttachments = (parsed.attachments || []).filter((att) => att.type === "image");
53
+ return {
54
+ text: parsed.text || "",
55
+ attachments: imageAttachments,
56
+ hasImages: imageAttachments.length > 0,
57
+ };
58
+ }
59
+ }
60
+ catch {
61
+ // 不是 JSON
62
+ }
63
+ // 3. 纯文本消息
64
+ return { text: content, attachments: [], hasImages: false };
65
+ }
66
+ /**
67
+ * 从 URL 提取文件名
68
+ */
69
+ function getFileName(url) {
70
+ const normalized = (url || "").replace(/\\/g, "/");
71
+ const parts = normalized.split("/").filter(Boolean);
72
+ const lastPart = parts[parts.length - 1] || url;
73
+ return lastPart.split("?")[0] || url;
74
+ }
75
+ /**
76
+ * 从 URL 推断媒体类型
77
+ */
78
+ function getMediaType(url) {
79
+ const ext = (url || "").split(".").pop()?.toLowerCase()?.split("?")[0] || "";
80
+ switch (ext) {
81
+ case "png": return "image/png";
82
+ case "jpg":
83
+ case "jpeg": return "image/jpeg";
84
+ case "gif": return "image/gif";
85
+ case "webp": return "image/webp";
86
+ default: return "image/png";
87
+ }
88
+ }
89
+ /**
90
+ * 构造多模态消息内容块
91
+ *
92
+ * 用于 Claude Agent SDK 的流式输入模式。
93
+ * SDK 直接支持 URL 引用图片,无需下载转 Base64。
94
+ *
95
+ * @param parsedContent 解析后的消息内容
96
+ * @param _baseUrl 服务器基础 URL(未使用,SDK 直接处理 URL)
97
+ * @returns 内容块数组
98
+ */
99
+ export function buildMultimodalContentBlocks(parsedContent, _baseUrl) {
100
+ const blocks = [];
101
+ // 添加图片内容块 - 使用 URL 引用,SDK 会自动处理
102
+ for (const attachment of parsedContent.attachments) {
103
+ // 构造完整的 URL(如果是相对路径)
104
+ const fullUrl = attachment.url.startsWith("http")
105
+ ? attachment.url
106
+ : `${_baseUrl}${attachment.url}`;
107
+ logger.info(`[MessageContent] 添加图片 URL 引用: ${fullUrl}`);
108
+ blocks.push({
109
+ type: "image",
110
+ source: {
111
+ type: "url",
112
+ url: fullUrl,
113
+ },
114
+ });
115
+ }
116
+ // 添加文本内容块
117
+ if (parsedContent.text.trim()) {
118
+ blocks.push({
119
+ type: "text",
120
+ text: parsedContent.text,
121
+ });
122
+ }
123
+ return blocks;
124
+ }
125
+ //# sourceMappingURL=messageContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageContent.js","sourceRoot":"","sources":["../src/messageContent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentConfig, RuntimeLaunchBinding, ServerConfig } from "./types.js";
2
+ export declare function claimRuntimeLaunchBinding(agentConfig: AgentConfig, serverConfig: ServerConfig): Promise<RuntimeLaunchBinding | null>;
3
+ //# sourceMappingURL=runtime-launch-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-launch-binding.d.ts","sourceRoot":"","sources":["../src/runtime-launch-binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAWlF,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAgDtC"}
@@ -0,0 +1,50 @@
1
+ import { logger } from "./logger.js";
2
+ function shouldClaimLaunchBinding() {
3
+ return process.env.AWS_MCP_CLAIM_LAUNCH_BINDING === "true";
4
+ }
5
+ function normalizeBridgeBaseUrl(serverConfig) {
6
+ return String(serverConfig.runtimeBridgeBaseUrl || "").trim().replace(/\/$/, "");
7
+ }
8
+ export async function claimRuntimeLaunchBinding(agentConfig, serverConfig) {
9
+ if (!shouldClaimLaunchBinding()) {
10
+ return null;
11
+ }
12
+ const bridgeBaseUrl = normalizeBridgeBaseUrl(serverConfig);
13
+ if (!bridgeBaseUrl) {
14
+ logger.warn("[RuntimeLaunchBinding] 已请求认领启动绑定,但未配置 AWS_RUNTIME_BRIDGE_BASE_URL");
15
+ return null;
16
+ }
17
+ const workspacePath = String(agentConfig.workspacePath || "").trim();
18
+ if (!workspacePath) {
19
+ logger.warn("[RuntimeLaunchBinding] workspacePath 为空,无法认领启动绑定");
20
+ return null;
21
+ }
22
+ const agentId = String(agentConfig.agentId || process.env.AWS_AGENT_ID || "").trim();
23
+ if (!agentId) {
24
+ logger.warn("[RuntimeLaunchBinding] agentId 为空,无法安全认领启动绑定");
25
+ return null;
26
+ }
27
+ const bindingId = String(process.env.AWS_MCP_LAUNCH_BINDING_ID || "").trim();
28
+ if (!bindingId) {
29
+ logger.warn("[RuntimeLaunchBinding] bindingId 为空,无法安全认领启动绑定");
30
+ return null;
31
+ }
32
+ const response = await fetch(`${bridgeBaseUrl}/runtime/binding/claim-agent`, {
33
+ method: "POST",
34
+ headers: { "Content-Type": "application/json" },
35
+ body: JSON.stringify({ agentId, bindingId, workspacePath, serverUrl: serverConfig.serverUrl }),
36
+ });
37
+ if (response.status === 404) {
38
+ logger.warn(`[RuntimeLaunchBinding] 未找到待认领启动绑定: ${workspacePath}`);
39
+ return null;
40
+ }
41
+ if (!response.ok) {
42
+ throw new Error(`认领 runtime 启动绑定失败: ${response.status} ${response.statusText}`);
43
+ }
44
+ const payload = (await response.json());
45
+ if (!payload.agentId) {
46
+ throw new Error(payload.error || "runtime-bridge 未返回 agentId");
47
+ }
48
+ return payload;
49
+ }
50
+ //# sourceMappingURL=runtime-launch-binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-launch-binding.js","sourceRoot":"","sources":["../src/runtime-launch-binding.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,SAAS,wBAAwB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,MAAM,CAAC;AAC7D,CAAC;AAED,SAAS,sBAAsB,CAAC,YAA0B;IACxD,OAAO,MAAM,CAAC,YAAY,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,WAAwB,EACxB,YAA0B;IAE1B,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,sBAAsB,CAAC,YAAY,CAAC,CAAC;IAC3D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,8BAA8B,EAAE;QAC3E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC;KAC/F,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,sCAAsC,aAAa,EAAE,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA8C,CAAC;IACrF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,4BAA4B,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runtime-launch-binding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-launch-binding.test.d.ts","sourceRoot":"","sources":["../src/runtime-launch-binding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import assert from 'node:assert/strict';
2
+ import { afterEach, beforeEach, describe, it } from 'node:test';
3
+ import { claimRuntimeLaunchBinding } from './runtime-launch-binding.js';
4
+ describe('claimRuntimeLaunchBinding', () => {
5
+ const originalEnv = { ...process.env };
6
+ const originalFetch = global.fetch;
7
+ const agentConfig = {
8
+ roleName: '',
9
+ agentId: 'agent-a',
10
+ projectName: 'default',
11
+ workspacePath: 'C:/repo/demo',
12
+ prompt: '',
13
+ describe: '',
14
+ };
15
+ const serverConfig = {
16
+ serverUrl: 'ws://server:7380/ws/agent',
17
+ heartbeatInterval: 3000,
18
+ reconnectInterval: 200,
19
+ maxReconnectAttempts: -1,
20
+ runtimeBridgeBaseUrl: 'http://127.0.0.1:18081',
21
+ };
22
+ beforeEach(() => {
23
+ process.env = { ...originalEnv };
24
+ });
25
+ afterEach(() => {
26
+ process.env = { ...originalEnv };
27
+ global.fetch = originalFetch;
28
+ });
29
+ it('skips claim when launch binding flag is disabled', async () => {
30
+ delete process.env.AWS_MCP_CLAIM_LAUNCH_BINDING;
31
+ const result = await claimRuntimeLaunchBinding(agentConfig, serverConfig);
32
+ assert.equal(result, null);
33
+ });
34
+ it('claims queued agent identity from local runtime bridge', async () => {
35
+ process.env.AWS_MCP_CLAIM_LAUNCH_BINDING = 'true';
36
+ process.env.AWS_MCP_LAUNCH_BINDING_ID = 'binding-a';
37
+ let capturedUrl = '';
38
+ let capturedBody;
39
+ global.fetch = async (url, options) => {
40
+ capturedUrl = url.toString();
41
+ capturedBody = JSON.parse(String(options?.body));
42
+ return {
43
+ ok: true,
44
+ status: 200,
45
+ statusText: 'OK',
46
+ json: async () => ({
47
+ ok: true,
48
+ agentId: 'agent-a',
49
+ runtimeAccessToken: 'token-a',
50
+ userId: 'user-a',
51
+ }),
52
+ };
53
+ };
54
+ const result = await claimRuntimeLaunchBinding(agentConfig, serverConfig);
55
+ assert.equal(capturedUrl, 'http://127.0.0.1:18081/runtime/binding/claim-agent');
56
+ assert.deepEqual(capturedBody, {
57
+ agentId: 'agent-a',
58
+ bindingId: 'binding-a',
59
+ workspacePath: 'C:/repo/demo',
60
+ serverUrl: 'ws://server:7380/ws/agent',
61
+ });
62
+ assert.equal(result?.agentId, 'agent-a');
63
+ assert.equal(result?.runtimeAccessToken, 'token-a');
64
+ });
65
+ it('skips claim when agent id is missing', async () => {
66
+ process.env.AWS_MCP_CLAIM_LAUNCH_BINDING = 'true';
67
+ process.env.AWS_MCP_LAUNCH_BINDING_ID = 'binding-a';
68
+ let called = false;
69
+ global.fetch = async () => {
70
+ called = true;
71
+ throw new Error('fetch should not be called');
72
+ };
73
+ const result = await claimRuntimeLaunchBinding({ ...agentConfig, agentId: undefined }, serverConfig);
74
+ assert.equal(result, null);
75
+ assert.equal(called, false);
76
+ });
77
+ it('skips claim when binding id is missing', async () => {
78
+ process.env.AWS_MCP_CLAIM_LAUNCH_BINDING = 'true';
79
+ delete process.env.AWS_MCP_LAUNCH_BINDING_ID;
80
+ let called = false;
81
+ global.fetch = async () => {
82
+ called = true;
83
+ throw new Error('fetch should not be called');
84
+ };
85
+ const result = await claimRuntimeLaunchBinding(agentConfig, serverConfig);
86
+ assert.equal(result, null);
87
+ assert.equal(called, false);
88
+ });
89
+ });
90
+ //# sourceMappingURL=runtime-launch-binding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-launch-binding.test.js","sourceRoot":"","sources":["../src/runtime-launch-binding.test.ts"],"names":[],"mappings":"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"}