agent-client-sdk 0.1.0

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.
@@ -0,0 +1,950 @@
1
+ import { ref, computed, readonly, getCurrentInstance, onMounted, onUnmounted } from 'vue';
2
+
3
+ /**
4
+ * 类型定义
5
+ */
6
+ /** 消息类型 */
7
+ var MessageType;
8
+ (function (MessageType) {
9
+ // 客户端 -> 服务端
10
+ MessageType["CLIENT_HANDSHAKE"] = "CLIENT_HANDSHAKE";
11
+ MessageType["CLIENT_UPDATE"] = "CLIENT_UPDATE";
12
+ MessageType["CLIENT_INPUT"] = "CLIENT_INPUT";
13
+ MessageType["CLIENT_RESULT"] = "CLIENT_RESULT";
14
+ MessageType["CLIENT_HEARTBEAT"] = "CLIENT_HEARTBEAT";
15
+ // 服务端 -> 客户端
16
+ MessageType["AGENT_MESSAGE"] = "AGENT_MESSAGE";
17
+ MessageType["AGENT_COMMAND"] = "AGENT_COMMAND";
18
+ MessageType["SERVER_ACK"] = "SERVER_ACK";
19
+ MessageType["SERVER_ERROR"] = "SERVER_ERROR";
20
+ MessageType["SERVER_HEARTBEAT"] = "SERVER_HEARTBEAT";
21
+ })(MessageType || (MessageType = {}));
22
+ /** 连接状态 */
23
+ var ConnectionStatus;
24
+ (function (ConnectionStatus) {
25
+ ConnectionStatus["DISCONNECTED"] = "disconnected";
26
+ ConnectionStatus["CONNECTING"] = "connecting";
27
+ ConnectionStatus["CONNECTED"] = "connected";
28
+ ConnectionStatus["RECONNECTING"] = "reconnecting";
29
+ ConnectionStatus["ERROR"] = "error";
30
+ })(ConnectionStatus || (ConnectionStatus = {}));
31
+
32
+ /**
33
+ * Agent客户端核心类
34
+ *
35
+ * 管理WebSocket连接、消息收发、命令执行
36
+ */
37
+ class AgentClient {
38
+ constructor(config) {
39
+ this.ws = null;
40
+ this.status = ConnectionStatus.DISCONNECTED;
41
+ this.reconnectAttempts = 0;
42
+ this.reconnectTimer = null;
43
+ this.heartbeatTimer = null;
44
+ this.messageListeners = [];
45
+ this.statusListeners = [];
46
+ this.commandHandlers = new Map();
47
+ this.chatMessages = [];
48
+ this.messageListenersChat = [];
49
+ this.pendingCommands = new Map();
50
+ this.messageQueue = [];
51
+ this.config = { ...AgentClient.DEFAULT_CONFIG, ...config };
52
+ this.sessionId = this.config.sessionId || this.generateSessionId();
53
+ // 注册默认命令处理器
54
+ this.registerDefaultCommandHandlers();
55
+ }
56
+ /**
57
+ * 生成会话ID
58
+ */
59
+ generateSessionId() {
60
+ // 优先从 localStorage 获取
61
+ const stored = typeof window !== 'undefined'
62
+ ? localStorage.getItem('agent_session_id')
63
+ : null;
64
+ if (stored)
65
+ return stored;
66
+ // 生成新的并存储
67
+ const newId = `session_${Date.now().toString(36)}_${Math.random().toString(36).substr(2, 5)}`;
68
+ if (typeof window !== 'undefined') {
69
+ localStorage.setItem('agent_session_id', newId);
70
+ }
71
+ return newId;
72
+ }
73
+ /**
74
+ * 日志输出
75
+ */
76
+ log(...args) {
77
+ if (this.config.debug) {
78
+ console.log('[AgentClient]', ...args);
79
+ }
80
+ }
81
+ /**
82
+ * 注册默认命令处理器
83
+ */
84
+ registerDefaultCommandHandlers() {
85
+ // 页面导航
86
+ this.commandHandlers.set('navigate', async (command) => {
87
+ const { target, params } = command;
88
+ this.log('Navigating to:', target, params);
89
+ try {
90
+ // 构建URL
91
+ let url = target;
92
+ if (params?.queryParams) {
93
+ const query = new URLSearchParams(params.queryParams).toString();
94
+ if (query) {
95
+ url += (url.includes('?') ? '&' : '?') + query;
96
+ }
97
+ }
98
+ // 使用Vue Router或原生导航
99
+ if (typeof window !== 'undefined') {
100
+ if (window.$router) {
101
+ await window.$router.push(url);
102
+ }
103
+ else {
104
+ window.location.href = url;
105
+ }
106
+ }
107
+ return { success: true, result: { url } };
108
+ }
109
+ catch (error) {
110
+ return { success: false, error: String(error) };
111
+ }
112
+ });
113
+ // 填充表单
114
+ this.commandHandlers.set('fillForm', async (command) => {
115
+ const { target, params } = command;
116
+ this.log('Filling form:', target, params);
117
+ try {
118
+ const form = document.querySelector(target);
119
+ if (!form) {
120
+ return { success: false, error: `Form not found: ${target}` };
121
+ }
122
+ const data = params?.data || {};
123
+ for (const [key, value] of Object.entries(data)) {
124
+ const input = form.querySelector(`[name="${key}"], #${key}`);
125
+ if (input) {
126
+ input.value = String(value);
127
+ input.dispatchEvent(new Event('input', { bubbles: true }));
128
+ input.dispatchEvent(new Event('change', { bubbles: true }));
129
+ }
130
+ }
131
+ // 自动提交
132
+ if (params?.submit) {
133
+ const submitBtn = form.querySelector('button[type="submit"], input[type="submit"]');
134
+ if (submitBtn) {
135
+ submitBtn.click();
136
+ }
137
+ else {
138
+ form.submit();
139
+ }
140
+ }
141
+ return { success: true, result: { filled: Object.keys(data) } };
142
+ }
143
+ catch (error) {
144
+ return { success: false, error: String(error) };
145
+ }
146
+ });
147
+ // 点击元素
148
+ this.commandHandlers.set('click', async (command) => {
149
+ const { target, params } = command;
150
+ this.log('Clicking element:', target);
151
+ try {
152
+ const element = document.querySelector(target);
153
+ if (!element) {
154
+ return { success: false, error: `Element not found: ${target}` };
155
+ }
156
+ element.click();
157
+ // 等待导航(如果需要)
158
+ if (params?.waitForNavigation) {
159
+ await new Promise(resolve => setTimeout(resolve, 500));
160
+ }
161
+ return { success: true };
162
+ }
163
+ catch (error) {
164
+ return { success: false, error: String(error) };
165
+ }
166
+ });
167
+ // 设置值
168
+ this.commandHandlers.set('setValue', async (command) => {
169
+ const { target, params } = command;
170
+ this.log('Setting value:', target, params?.value);
171
+ try {
172
+ const element = document.querySelector(target);
173
+ if (!element) {
174
+ return { success: false, error: `Element not found: ${target}` };
175
+ }
176
+ element.value = String(params?.value || '');
177
+ if (params?.triggerChange !== false) {
178
+ element.dispatchEvent(new Event('input', { bubbles: true }));
179
+ element.dispatchEvent(new Event('change', { bubbles: true }));
180
+ }
181
+ return { success: true };
182
+ }
183
+ catch (error) {
184
+ return { success: false, error: String(error) };
185
+ }
186
+ });
187
+ // 滚动页面
188
+ this.commandHandlers.set('scroll', async (command) => {
189
+ const { target, params } = command;
190
+ this.log('Scrolling:', target, params);
191
+ try {
192
+ const amount = params?.amount || 500;
193
+ switch (target) {
194
+ case 'up':
195
+ window.scrollBy({ top: -amount, behavior: 'smooth' });
196
+ break;
197
+ case 'down':
198
+ window.scrollBy({ top: amount, behavior: 'smooth' });
199
+ break;
200
+ case 'top':
201
+ window.scrollTo({ top: 0, behavior: 'smooth' });
202
+ break;
203
+ case 'bottom':
204
+ window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
205
+ break;
206
+ default:
207
+ return { success: false, error: `Unknown scroll direction: ${target}` };
208
+ }
209
+ return { success: true };
210
+ }
211
+ catch (error) {
212
+ return { success: false, error: String(error) };
213
+ }
214
+ });
215
+ }
216
+ /**
217
+ * 连接到WebSocket服务器
218
+ */
219
+ connect() {
220
+ if (this.ws?.readyState === WebSocket.OPEN) {
221
+ this.log('Already connected');
222
+ return;
223
+ }
224
+ this.setStatus(ConnectionStatus.CONNECTING);
225
+ try {
226
+ const url = new URL(this.config.serverUrl);
227
+ url.searchParams.set('session_id', this.sessionId);
228
+ this.ws = new WebSocket(url.toString());
229
+ this.ws.onopen = () => {
230
+ this.log('WebSocket connected');
231
+ this.reconnectAttempts = 0;
232
+ this.setStatus(ConnectionStatus.CONNECTED);
233
+ this.startHeartbeat();
234
+ this.sendHandshake();
235
+ // 发送缓存的消息
236
+ while (this.messageQueue.length > 0) {
237
+ const msg = this.messageQueue.shift();
238
+ if (msg)
239
+ this.sendMessage(msg);
240
+ }
241
+ };
242
+ this.ws.onmessage = (event) => {
243
+ try {
244
+ const message = JSON.parse(event.data);
245
+ this.handleMessage(message);
246
+ }
247
+ catch (error) {
248
+ this.log('Failed to parse message:', error);
249
+ }
250
+ };
251
+ this.ws.onclose = () => {
252
+ this.log('WebSocket closed');
253
+ this.stopHeartbeat();
254
+ this.setStatus(ConnectionStatus.DISCONNECTED);
255
+ this.attemptReconnect();
256
+ };
257
+ this.ws.onerror = (error) => {
258
+ this.log('WebSocket error:', error);
259
+ this.setStatus(ConnectionStatus.ERROR);
260
+ };
261
+ }
262
+ catch (error) {
263
+ this.log('Failed to connect:', error);
264
+ this.setStatus(ConnectionStatus.ERROR);
265
+ this.attemptReconnect();
266
+ }
267
+ }
268
+ /**
269
+ * 断开连接
270
+ */
271
+ disconnect() {
272
+ this.stopHeartbeat();
273
+ this.clearReconnectTimer();
274
+ if (this.ws) {
275
+ this.ws.close();
276
+ this.ws = null;
277
+ }
278
+ this.setStatus(ConnectionStatus.DISCONNECTED);
279
+ }
280
+ /**
281
+ * 尝试重连
282
+ */
283
+ attemptReconnect() {
284
+ if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
285
+ this.log('Max reconnect attempts reached');
286
+ return;
287
+ }
288
+ this.reconnectAttempts++;
289
+ this.setStatus(ConnectionStatus.RECONNECTING);
290
+ this.log(`Reconnecting... (${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);
291
+ this.reconnectTimer = setTimeout(() => {
292
+ this.connect();
293
+ }, this.config.reconnectInterval);
294
+ }
295
+ /**
296
+ * 清除重连定时器
297
+ */
298
+ clearReconnectTimer() {
299
+ if (this.reconnectTimer) {
300
+ clearTimeout(this.reconnectTimer);
301
+ this.reconnectTimer = null;
302
+ }
303
+ }
304
+ /**
305
+ * 启动心跳
306
+ */
307
+ startHeartbeat() {
308
+ this.heartbeatTimer = setInterval(() => {
309
+ this.sendMessage({
310
+ type: MessageType.CLIENT_HEARTBEAT,
311
+ sessionId: this.sessionId,
312
+ timestamp: new Date().toISOString(),
313
+ payload: {},
314
+ });
315
+ }, this.config.heartbeatInterval);
316
+ }
317
+ /**
318
+ * 停止心跳
319
+ */
320
+ stopHeartbeat() {
321
+ if (this.heartbeatTimer) {
322
+ clearInterval(this.heartbeatTimer);
323
+ this.heartbeatTimer = null;
324
+ }
325
+ }
326
+ /**
327
+ * 发送握手消息
328
+ */
329
+ sendHandshake() {
330
+ this.sendMessage({
331
+ type: MessageType.CLIENT_HANDSHAKE,
332
+ sessionId: this.sessionId,
333
+ timestamp: new Date().toISOString(),
334
+ payload: {
335
+ routes: this.config.routes,
336
+ capabilities: [],
337
+ userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
338
+ url: typeof window !== 'undefined' ? window.location.href : '',
339
+ },
340
+ });
341
+ }
342
+ /**
343
+ * 发送消息
344
+ */
345
+ sendMessage(message) {
346
+ if (this.ws?.readyState === WebSocket.OPEN) {
347
+ this.ws.send(JSON.stringify(message));
348
+ return true;
349
+ }
350
+ // 连接未建立时,缓存消息
351
+ this.messageQueue.push(message);
352
+ return false;
353
+ }
354
+ /**
355
+ * 处理接收到的消息
356
+ */
357
+ handleMessage(message) {
358
+ this.log('Received message:', message.type);
359
+ // 通知所有监听器
360
+ this.messageListeners.forEach(listener => listener(message));
361
+ switch (message.type) {
362
+ case MessageType.SERVER_ACK:
363
+ this.log('Server acknowledged:', message.payload);
364
+ break;
365
+ case MessageType.SERVER_ERROR:
366
+ console.error('[AgentClient] Server error:', message.payload);
367
+ break;
368
+ case MessageType.SERVER_HEARTBEAT:
369
+ // 心跳响应,无需处理
370
+ break;
371
+ case MessageType.AGENT_MESSAGE:
372
+ this.handleAgentMessage(message);
373
+ break;
374
+ case MessageType.AGENT_COMMAND:
375
+ this.handleAgentCommand(message);
376
+ break;
377
+ default:
378
+ this.log('Unknown message type:', message.type);
379
+ }
380
+ }
381
+ /**
382
+ * 处理Agent消息
383
+ */
384
+ handleAgentMessage(message) {
385
+ const payload = message.payload;
386
+ const chatMessage = {
387
+ id: `${Date.now()}_${Math.random().toString(36).substr(2, 5)}`,
388
+ role: 'agent',
389
+ content: payload.text || '',
390
+ timestamp: Date.now(),
391
+ type: 'text',
392
+ };
393
+ this.chatMessages.push(chatMessage);
394
+ this.notifyChatListeners();
395
+ }
396
+ /**
397
+ * 处理Agent控制指令
398
+ */
399
+ async handleAgentCommand(message) {
400
+ const command = message.payload;
401
+ // 添加到聊天消息
402
+ const chatMessage = {
403
+ id: command.commandId,
404
+ role: 'agent',
405
+ content: command.description,
406
+ timestamp: Date.now(),
407
+ type: 'command',
408
+ command: command,
409
+ };
410
+ this.chatMessages.push(chatMessage);
411
+ this.notifyChatListeners();
412
+ // 执行命令
413
+ const handler = this.commandHandlers.get(command.action);
414
+ let result;
415
+ if (handler) {
416
+ try {
417
+ result = await handler(command);
418
+ }
419
+ catch (error) {
420
+ result = { success: false, error: String(error) };
421
+ }
422
+ }
423
+ else {
424
+ result = { success: false, error: `Unknown command action: ${command.action}` };
425
+ }
426
+ // 发送执行结果
427
+ this.sendMessage({
428
+ type: MessageType.CLIENT_RESULT,
429
+ sessionId: this.sessionId,
430
+ timestamp: new Date().toISOString(),
431
+ payload: {
432
+ commandId: command.commandId,
433
+ success: result.success,
434
+ result: result.result,
435
+ error: result.error,
436
+ },
437
+ });
438
+ }
439
+ /**
440
+ * 发送用户输入
441
+ */
442
+ sendInput(text, context) {
443
+ // 添加到本地聊天记录
444
+ const chatMessage = {
445
+ id: `${Date.now()}_${Math.random().toString(36).substr(2, 5)}`,
446
+ role: 'user',
447
+ content: text,
448
+ timestamp: Date.now(),
449
+ type: 'text',
450
+ };
451
+ this.chatMessages.push(chatMessage);
452
+ this.notifyChatListeners();
453
+ // 发送到服务器
454
+ this.sendMessage({
455
+ type: MessageType.CLIENT_INPUT,
456
+ sessionId: this.sessionId,
457
+ timestamp: new Date().toISOString(),
458
+ payload: {
459
+ text,
460
+ context,
461
+ },
462
+ });
463
+ }
464
+ /**
465
+ * 更新页面能力
466
+ */
467
+ updateCapabilities(action, currentRoute, capabilities) {
468
+ this.sendMessage({
469
+ type: MessageType.CLIENT_UPDATE,
470
+ sessionId: this.sessionId,
471
+ timestamp: new Date().toISOString(),
472
+ payload: {
473
+ action,
474
+ currentRoute,
475
+ capabilities,
476
+ },
477
+ });
478
+ }
479
+ /**
480
+ * 设置连接状态
481
+ */
482
+ setStatus(status) {
483
+ this.status = status;
484
+ this.statusListeners.forEach(listener => listener(status));
485
+ }
486
+ /**
487
+ * 获取当前连接状态
488
+ */
489
+ getStatus() {
490
+ return this.status;
491
+ }
492
+ /**
493
+ * 获取会话ID
494
+ */
495
+ getSessionId() {
496
+ return this.sessionId;
497
+ }
498
+ /**
499
+ * 获取聊天记录
500
+ */
501
+ getChatMessages() {
502
+ return [...this.chatMessages];
503
+ }
504
+ /**
505
+ * 清空聊天记录
506
+ */
507
+ clearChatMessages() {
508
+ this.chatMessages = [];
509
+ this.notifyChatListeners();
510
+ }
511
+ /**
512
+ * 注册消息监听器
513
+ */
514
+ onMessage(listener) {
515
+ this.messageListeners.push(listener);
516
+ return () => {
517
+ const index = this.messageListeners.indexOf(listener);
518
+ if (index > -1) {
519
+ this.messageListeners.splice(index, 1);
520
+ }
521
+ };
522
+ }
523
+ /**
524
+ * 注册状态监听器
525
+ */
526
+ onStatusChange(listener) {
527
+ this.statusListeners.push(listener);
528
+ return () => {
529
+ const index = this.statusListeners.indexOf(listener);
530
+ if (index > -1) {
531
+ this.statusListeners.splice(index, 1);
532
+ }
533
+ };
534
+ }
535
+ /**
536
+ * 注册聊天消息监听器
537
+ */
538
+ onChatMessages(listener) {
539
+ this.messageListenersChat.push(listener);
540
+ return () => {
541
+ const index = this.messageListenersChat.indexOf(listener);
542
+ if (index > -1) {
543
+ this.messageListenersChat.splice(index, 1);
544
+ }
545
+ };
546
+ }
547
+ /**
548
+ * 通知聊天监听器
549
+ */
550
+ notifyChatListeners() {
551
+ this.messageListenersChat.forEach(listener => listener([...this.chatMessages]));
552
+ }
553
+ /**
554
+ * 注册自定义命令处理器
555
+ */
556
+ registerCommandHandler(action, handler) {
557
+ this.commandHandlers.set(action, handler);
558
+ }
559
+ /**
560
+ * 注销命令处理器
561
+ */
562
+ unregisterCommandHandler(action) {
563
+ this.commandHandlers.delete(action);
564
+ }
565
+ }
566
+ // 默认配置
567
+ AgentClient.DEFAULT_CONFIG = {
568
+ serverUrl: '',
569
+ routes: [],
570
+ reconnectInterval: 3000,
571
+ maxReconnectAttempts: 5,
572
+ heartbeatInterval: 30000,
573
+ debug: false,
574
+ sessionId: '',
575
+ };
576
+ // 单例实例
577
+ let globalClient = null;
578
+ /**
579
+ * 获取全局AgentClient实例
580
+ */
581
+ function getGlobalClient() {
582
+ return globalClient;
583
+ }
584
+ /**
585
+ * 设置全局AgentClient实例
586
+ */
587
+ function setGlobalClient(client) {
588
+ globalClient = client;
589
+ }
590
+
591
+ /**
592
+ * Agent全局状态管理组合式函数
593
+ *
594
+ * 提供响应式的连接状态、聊天记录等全局状态
595
+ */
596
+ // 全局状态(跨组件共享)
597
+ const globalStatus = ref(ConnectionStatus.DISCONNECTED);
598
+ const globalMessages = ref([]);
599
+ const globalIsConnected = computed(() => globalStatus.value === ConnectionStatus.CONNECTED);
600
+ /**
601
+ * 使用Agent全局状态
602
+ *
603
+ * @param config - 可选的配置,仅在首次调用时生效
604
+ * @returns Agent状态和操作方法
605
+ *
606
+ * @example
607
+ * ```ts
608
+ * // 在main.ts中初始化
609
+ * const { connect } = useAgent({
610
+ * serverUrl: 'ws://localhost:8987/ws/agent',
611
+ * routes: [...]
612
+ * });
613
+ * connect();
614
+ *
615
+ * // 在组件中使用
616
+ * const { status, messages, sendMessage } = useAgent();
617
+ * ```
618
+ */
619
+ function useAgent(config) {
620
+ let client = getGlobalClient();
621
+ // 如果提供了配置且全局客户端不存在,则创建
622
+ if (config && !client) {
623
+ client = new AgentClient(config);
624
+ setGlobalClient(client);
625
+ // 同步全局状态
626
+ client.onStatusChange((status) => {
627
+ globalStatus.value = status;
628
+ });
629
+ client.onChatMessages((messages) => {
630
+ globalMessages.value = messages;
631
+ });
632
+ }
633
+ // 如果客户端已存在,同步当前状态到全局
634
+ if (client) {
635
+ globalStatus.value = client.getStatus();
636
+ globalMessages.value = client.getChatMessages();
637
+ }
638
+ const sendMessage = (text) => {
639
+ if (client) {
640
+ client.sendInput(text);
641
+ }
642
+ else {
643
+ console.warn('[useAgent] AgentClient not initialized');
644
+ }
645
+ };
646
+ const clearMessages = () => {
647
+ if (client) {
648
+ client.clearChatMessages();
649
+ }
650
+ };
651
+ const connect = () => {
652
+ if (client) {
653
+ client.connect();
654
+ }
655
+ else {
656
+ console.warn('[useAgent] AgentClient not initialized, please provide config first');
657
+ }
658
+ };
659
+ const disconnect = () => {
660
+ if (client) {
661
+ client.disconnect();
662
+ }
663
+ };
664
+ return {
665
+ status: readonly(globalStatus),
666
+ isConnected: readonly(globalIsConnected),
667
+ messages: readonly(globalMessages),
668
+ sendMessage,
669
+ clearMessages,
670
+ connect,
671
+ disconnect,
672
+ };
673
+ }
674
+ /**
675
+ * 初始化AgentClient
676
+ *
677
+ * 应在应用入口(如main.ts)中调用一次
678
+ *
679
+ * @param config - SDK配置
680
+ * @returns AgentClient实例
681
+ *
682
+ * @example
683
+ * ```ts
684
+ * // main.ts
685
+ * import { createApp } from 'vue';
686
+ * import { initAgent } from 'agent-client-sdk';
687
+ * import App from './App.vue';
688
+ * import router from './router';
689
+ *
690
+ * const app = createApp(App);
691
+ * app.use(router);
692
+ *
693
+ * // 初始化Agent
694
+ * initAgent({
695
+ * serverUrl: 'ws://localhost:8987/ws/agent',
696
+ * routes: router.getRoutes().map(r => ({
697
+ * path: r.path,
698
+ * name: String(r.name || r.path),
699
+ * title: r.meta?.title || String(r.name || r.path)
700
+ * })),
701
+ * debug: true
702
+ * });
703
+ *
704
+ * app.mount('#app');
705
+ * ```
706
+ */
707
+ function initAgent(config) {
708
+ const client = new AgentClient(config);
709
+ setGlobalClient(client);
710
+ // 设置到 window,方便路由变化监听使用
711
+ if (typeof window !== 'undefined') {
712
+ window.$agentClient = client;
713
+ }
714
+ // 同步全局状态
715
+ client.onStatusChange((status) => {
716
+ globalStatus.value = status;
717
+ });
718
+ client.onChatMessages((messages) => {
719
+ globalMessages.value = messages;
720
+ });
721
+ // 自动连接
722
+ client.connect();
723
+ return client;
724
+ }
725
+
726
+ /**
727
+ * 组件能力注册组合式函数
728
+ *
729
+ * 在Vue组件中注册页面能力,供Agent调用
730
+ */
731
+ /**
732
+ * 注册组件能力给Agent
733
+ *
734
+ * 在组件挂载时自动注册能力,卸载时自动注销
735
+ *
736
+ * @param capabilities - 页面能力列表
737
+ * @param options - 配置选项
738
+ *
739
+ * @example
740
+ * ```vue
741
+ * <script setup>
742
+ * import { useAgentAction } from 'agent-client-sdk';
743
+ *
744
+ * // 注册表单能力
745
+ * useAgentAction([
746
+ * {
747
+ * id: 'profile-form',
748
+ * type: 'form',
749
+ * name: '个人资料表单',
750
+ * description: '用于编辑用户个人资料信息',
751
+ * selector: '#profile-form',
752
+ * actions: ['fill', 'submit'],
753
+ * metadata: {
754
+ * fields: ['name', 'email', 'phone']
755
+ * }
756
+ * }
757
+ * ]);
758
+ * </script>
759
+ *
760
+ * <template>
761
+ * <form id="profile-form">
762
+ * <input name="name" />
763
+ * <input name="email" />
764
+ * <button type="submit">保存</button>
765
+ * </form>
766
+ * </template>
767
+ * ```
768
+ */
769
+ function useAgentAction(capabilities, options = {}) {
770
+ const { autoRegister = true, autoUnregister = true, route, } = options;
771
+ const client = getGlobalClient();
772
+ const instance = getCurrentInstance();
773
+ // 生成组件唯一标识
774
+ const componentId = instance
775
+ ? `${instance.uid}_${Date.now().toString(36)}`
776
+ : `anonymous_${Date.now().toString(36)}`;
777
+ // 为能力添加组件标识
778
+ const taggedCapabilities = capabilities.map((cap) => ({
779
+ ...cap,
780
+ id: `${componentId}_${cap.id}`,
781
+ metadata: {
782
+ ...cap.metadata,
783
+ _componentId: componentId,
784
+ _originalId: cap.id,
785
+ },
786
+ }));
787
+ const register = () => {
788
+ if (!client) {
789
+ console.warn('[useAgentAction] AgentClient not initialized');
790
+ return;
791
+ }
792
+ client.updateCapabilities('mount', route, taggedCapabilities);
793
+ };
794
+ const unregister = () => {
795
+ if (!client) {
796
+ return;
797
+ }
798
+ client.updateCapabilities('unmount', route, taggedCapabilities);
799
+ };
800
+ const update = (newCapabilities) => {
801
+ if (!client) {
802
+ console.warn('[useAgentAction] AgentClient not initialized');
803
+ return;
804
+ }
805
+ const newTaggedCapabilities = newCapabilities.map((cap) => ({
806
+ ...cap,
807
+ id: `${componentId}_${cap.id}`,
808
+ metadata: {
809
+ ...cap.metadata,
810
+ _componentId: componentId,
811
+ _originalId: cap.id,
812
+ },
813
+ }));
814
+ client.updateCapabilities('update', route, newTaggedCapabilities);
815
+ };
816
+ // 自动注册/注销
817
+ if (autoRegister) {
818
+ onMounted(() => {
819
+ register();
820
+ });
821
+ }
822
+ if (autoUnregister) {
823
+ onUnmounted(() => {
824
+ unregister();
825
+ });
826
+ }
827
+ return {
828
+ register,
829
+ unregister,
830
+ update,
831
+ };
832
+ }
833
+ /**
834
+ * 注册按钮能力
835
+ *
836
+ * 便捷方法,用于快速注册按钮点击能力
837
+ *
838
+ * @param id - 按钮ID
839
+ * @param name - 按钮名称
840
+ * @param description - 按钮描述
841
+ * @param selector - CSS选择器(可选,默认使用ID)
842
+ *
843
+ * @example
844
+ * ```vue
845
+ * <script setup>
846
+ * import { useAgentButton } from 'agent-client-sdk';
847
+ *
848
+ * useAgentButton('save-btn', '保存按钮', '点击保存表单数据');
849
+ * </script>
850
+ *
851
+ * <template>
852
+ * <button id="save-btn">保存</button>
853
+ * </template>
854
+ * ```
855
+ */
856
+ function useAgentButton(id, name, description, selector) {
857
+ useAgentAction([
858
+ {
859
+ id,
860
+ type: 'button',
861
+ name,
862
+ description,
863
+ selector: selector || `#${id}`,
864
+ actions: ['click'],
865
+ },
866
+ ]);
867
+ }
868
+ /**
869
+ * 注册表单能力
870
+ *
871
+ * 便捷方法,用于快速注册表单填充能力
872
+ *
873
+ * @param id - 表单ID
874
+ * @param name - 表单名称
875
+ * @param description - 表单描述
876
+ * @param fields - 表单字段列表
877
+ * @param selector - CSS选择器(可选,默认使用ID)
878
+ * @param options - 额外选项
879
+ *
880
+ * @example
881
+ * ```vue
882
+ * <script setup>
883
+ * import { useAgentForm } from 'agent-client-sdk';
884
+ *
885
+ * useAgentForm(
886
+ * 'profile-form',
887
+ * '个人资料表单',
888
+ * '编辑用户个人资料',
889
+ * ['name', 'email', 'phone'],
890
+ * '#profile-form',
891
+ * { canSubmit: true }
892
+ * );
893
+ * </script>
894
+ * ```
895
+ */
896
+ function useAgentForm(id, name, description, fields, selector, options = {}) {
897
+ const actions = ['fill'];
898
+ if (options.canSubmit !== false) {
899
+ actions.push('submit');
900
+ }
901
+ useAgentAction([
902
+ {
903
+ id,
904
+ type: 'form',
905
+ name,
906
+ description,
907
+ selector: selector || `#${id}`,
908
+ actions,
909
+ metadata: { fields },
910
+ },
911
+ ]);
912
+ }
913
+ /**
914
+ * 注册输入框能力
915
+ *
916
+ * 便捷方法,用于快速注册输入框设置值能力
917
+ *
918
+ * @param id - 输入框ID
919
+ * @param name - 输入框名称
920
+ * @param description - 输入框描述
921
+ * @param selector - CSS选择器(可选,默认使用ID)
922
+ *
923
+ * @example
924
+ * ```vue
925
+ * <script setup>
926
+ * import { useAgentInput } from 'agent-client-sdk';
927
+ *
928
+ * useAgentInput('username', '用户名', '输入用户名');
929
+ * </script>
930
+ *
931
+ * <template>
932
+ * <input id="username" name="username" />
933
+ * </template>
934
+ * ```
935
+ */
936
+ function useAgentInput(id, name, description, selector) {
937
+ useAgentAction([
938
+ {
939
+ id,
940
+ type: 'input',
941
+ name,
942
+ description,
943
+ selector: selector || `#${id}`,
944
+ actions: ['setValue'],
945
+ },
946
+ ]);
947
+ }
948
+
949
+ export { AgentClient, ConnectionStatus, MessageType, getGlobalClient, initAgent, setGlobalClient, useAgent, useAgentAction, useAgentButton, useAgentForm, useAgentInput };
950
+ //# sourceMappingURL=index.esm.js.map