@auto-ai/agent 2.1.220 → 2.1.222

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 (45) hide show
  1. package/dist/safe-a/404/index.html +1 -1
  2. package/dist/safe-a/404.html +1 -1
  3. package/dist/safe-a/index.html +2 -2
  4. package/dist/safe-a/index.txt +1 -1
  5. package/dist/safe-a/manage/about/index.html +2 -2
  6. package/dist/safe-a/manage/about/index.txt +1 -1
  7. package/dist/safe-a/manage/env/index.html +2 -2
  8. package/dist/safe-a/manage/env/index.txt +1 -1
  9. package/dist/safe-a/manage/geelib/index.html +2 -2
  10. package/dist/safe-a/manage/geelib/index.txt +1 -1
  11. package/dist/safe-a/manage/general/index.html +2 -2
  12. package/dist/safe-a/manage/general/index.txt +1 -1
  13. package/dist/safe-a/manage/git/index.html +2 -2
  14. package/dist/safe-a/manage/git/index.txt +1 -1
  15. package/dist/safe-a/manage/im/index.html +2 -2
  16. package/dist/safe-a/manage/im/index.txt +1 -1
  17. package/dist/safe-a/manage/index.html +2 -2
  18. package/dist/safe-a/manage/index.txt +1 -1
  19. package/dist/safe-a/manage/library/index.html +2 -2
  20. package/dist/safe-a/manage/library/index.txt +1 -1
  21. package/dist/safe-a/manage/mcp/index.html +2 -2
  22. package/dist/safe-a/manage/mcp/index.txt +1 -1
  23. package/dist/safe-a/manage/permissions/index.html +2 -2
  24. package/dist/safe-a/manage/permissions/index.txt +1 -1
  25. package/dist/safe-a/manage/skills/index.html +2 -2
  26. package/dist/safe-a/manage/skills/index.txt +1 -1
  27. package/dist/safe-a/manage/task/index.html +2 -2
  28. package/dist/safe-a/manage/task/index.txt +1 -1
  29. package/dist/safe-a/manage/teams/index.html +2 -2
  30. package/dist/safe-a/manage/teams/index.txt +1 -1
  31. package/dist/safe-a/manage/tools/index.html +2 -2
  32. package/dist/safe-a/manage/tools/index.txt +1 -1
  33. package/dist/ws-test/agent-teams.html +1400 -0
  34. package/dist/ws-test/team-chat.js +760 -0
  35. package/dist/ws-test/ws-test.css +613 -6
  36. package/dist/ws-test/ws-test.html +23 -7
  37. package/dist/ws-test/ws-test.js +303 -86
  38. package/mcps-runtime/claude-tuitui-channel/server/index.mjs +5 -0
  39. package/package.json +6 -6
  40. package/tools-runtime/git-tool/index.cjs +32 -31
  41. package/tools-runtime/git-tool/src/workspace.ts +42 -5
  42. package/tools-runtime/git-tool/src/wsInit.ts +13 -2
  43. /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_buildManifest.js +0 -0
  44. /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_clientMiddlewareManifest.json +0 -0
  45. /package/dist/safe-a/_next/static/{tLBo5EqCFXrKR3ERjvMIi → O9azldpveh8Nr32O4nBb7}/_ssgManifest.js +0 -0
@@ -0,0 +1,760 @@
1
+ /**
2
+ * 团队群聊 UI:服务端按 seq 追加,前端按到达顺序 append,不排序。
3
+ */
4
+ ;(function (global) {
5
+ 'use strict'
6
+
7
+ var AVATAR_COLORS = ['#6366f1', '#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899']
8
+
9
+ function escapeHtml(str) {
10
+ return String(str || '')
11
+ .replace(/&/g, '&')
12
+ .replace(/</g, '&lt;')
13
+ .replace(/>/g, '&gt;')
14
+ .replace(/"/g, '&quot;')
15
+ }
16
+
17
+ function hashColor(id) {
18
+ var s = String(id || '')
19
+ var h = 0
20
+ for (var i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0
21
+ return AVATAR_COLORS[h % AVATAR_COLORS.length]
22
+ }
23
+
24
+ function renderMd(text) {
25
+ if (!text) return ''
26
+ try {
27
+ if (typeof marked !== 'undefined' && marked.parse) {
28
+ return marked.parse(text, { async: false })
29
+ }
30
+ } catch (e) {
31
+ return '<pre>' + escapeHtml(String(e)) + '</pre>'
32
+ }
33
+ return '<pre>' + escapeHtml(text) + '</pre>'
34
+ }
35
+
36
+ function normalizeUserPromptText(text) {
37
+ var trimmed = String(text || '').trim()
38
+ var stripped = trimmed.replace(/^@([a-zA-Z0-9_-]{1,64})\b\s*/, '').trim()
39
+ return stripped.length > 0 ? stripped : trimmed
40
+ }
41
+
42
+ function teamUserRoundKey(text) {
43
+ var trimmed = String(text || '').trim()
44
+ var match = trimmed.match(/^@([a-zA-Z0-9_-]{1,64})\b\s*/)
45
+ var mention = match ? match[1] : '*'
46
+ return mention + '\0' + normalizeUserPromptText(trimmed)
47
+ }
48
+
49
+ function buildRoundIdFromUser(user) {
50
+ return teamUserRoundKey(user.text || '') + '\0' + (user.ts || '')
51
+ }
52
+
53
+ function parseTimelineSeq(data) {
54
+ var raw = data && data.seq
55
+ if (typeof raw === 'number' && Number.isInteger(raw) && raw > 0) {
56
+ return raw
57
+ }
58
+ if (typeof raw === 'string' && /^\d+$/.test(raw)) {
59
+ var parsed = parseInt(raw, 10)
60
+ return parsed > 0 ? parsed : null
61
+ }
62
+ return null
63
+ }
64
+
65
+ function readPromptText(el) {
66
+ if (!el) return ''
67
+ if (typeof el.value === 'string') return el.value
68
+ return String(el.innerText || el.textContent || '')
69
+ }
70
+
71
+ function writePromptText(el, text) {
72
+ if (!el) return
73
+ if (typeof el.value === 'string') {
74
+ el.value = text
75
+ return
76
+ }
77
+ el.textContent = text
78
+ }
79
+
80
+ function setPromptDisabled(el, disabled) {
81
+ if (!el) return
82
+ if ('disabled' in el) {
83
+ el.disabled = disabled
84
+ return
85
+ }
86
+ el.contentEditable = disabled ? 'false' : 'true'
87
+ el.classList.toggle('is-disabled', !!disabled)
88
+ if (disabled) el.setAttribute('aria-disabled', 'true')
89
+ else el.removeAttribute('aria-disabled')
90
+ }
91
+
92
+ function TeamChat(opts) {
93
+ this.threadEl = opts.threadEl
94
+ this.promptEl = opts.promptEl
95
+ this.statusEl = opts.statusEl
96
+ this.sendBtn = opts.sendBtn
97
+ this.abortBtn = opts.abortBtn || null
98
+ this.clearBtn = opts.clearBtn || null
99
+ this.httpOrigin = opts.httpOrigin || window.location.origin
100
+ this.placeholderEl = opts.placeholderEl || null
101
+
102
+ this.socket = null
103
+ this.serverReady = false
104
+ this.turnActive = false
105
+ this.teamId = null
106
+ this.sessionId = null
107
+ this.idleHint = ''
108
+ this.hydrateGen = 0
109
+ this.replayInProgress = false
110
+ this.pendingTimeline = []
111
+ this.seenEventIds = new Set()
112
+ this.rows = []
113
+ this.seenSeq = new Set()
114
+ this.membersById = new Map()
115
+ this.activeQueryAgents = new Set()
116
+
117
+ setPromptDisabled(this.promptEl, true)
118
+
119
+ var self = this
120
+ if (this.sendBtn) {
121
+ this.sendBtn.addEventListener('click', function () {
122
+ self.sendPrompt()
123
+ })
124
+ }
125
+ if (this.abortBtn) {
126
+ this.abortBtn.addEventListener('click', function () {
127
+ self.abortTurn()
128
+ })
129
+ }
130
+ if (this.clearBtn) {
131
+ this.clearBtn.addEventListener('click', function () {
132
+ void self.clearChatHistory()
133
+ })
134
+ }
135
+ if (this.promptEl) {
136
+ this.promptEl.addEventListener('keydown', function (e) {
137
+ if (e.key === 'Enter' && !e.shiftKey) {
138
+ e.preventDefault()
139
+ self.sendPrompt()
140
+ }
141
+ })
142
+ }
143
+ }
144
+
145
+ TeamChat.prototype.setMembers = function (agents) {
146
+ this.membersById = new Map()
147
+ var list = Array.isArray(agents) ? agents : []
148
+ for (var i = 0; i < list.length; i++) {
149
+ var a = list[i]
150
+ if (!a) continue
151
+ var id = String(a.id || a.agentId || '').trim()
152
+ if (!id) continue
153
+ this.membersById.set(id, a)
154
+ }
155
+ this.render()
156
+ }
157
+
158
+ TeamChat.prototype.resolveSenderMeta = function (sourceAgent, role) {
159
+ if (role === 'user') {
160
+ return { label: '你', initial: '我', color: '#71717a' }
161
+ }
162
+ var id = String(sourceAgent || '').trim()
163
+ var member = id ? this.membersById.get(id) : null
164
+ var label = member && member.displayName ? String(member.displayName) : id || 'assistant'
165
+ var initial = (label.charAt(0) || id.charAt(0) || '?').toUpperCase()
166
+ return { label: label, initial: initial, color: hashColor(id || label) }
167
+ }
168
+
169
+ TeamChat.prototype.setStatus = function (text, kind) {
170
+ if (!this.statusEl) return
171
+ this.statusEl.textContent = text
172
+ this.statusEl.classList.remove('ready', 'err')
173
+ if (kind) this.statusEl.classList.add(kind)
174
+ }
175
+
176
+ TeamChat.prototype.setIdleHint = function (hint) {
177
+ this.idleHint = typeof hint === 'string' ? hint : ''
178
+ this.render()
179
+ }
180
+
181
+ TeamChat.prototype.syncTurnActive = function () {
182
+ this.turnActive = this.activeQueryAgents.size > 0
183
+ this.updateComposer()
184
+ if (this.rows.length > 0) this.render()
185
+ }
186
+
187
+ TeamChat.prototype.updateComposer = function () {
188
+ var disabled =
189
+ !this.teamId || !this.serverReady || this.turnActive || this.replayInProgress
190
+ setPromptDisabled(this.promptEl, disabled)
191
+ if (this.sendBtn) this.sendBtn.disabled = disabled
192
+ var wsOpen = this.socket && this.socket.readyState === WebSocket.OPEN
193
+ if (this.abortBtn) {
194
+ this.abortBtn.disabled = !wsOpen || !this.serverReady
195
+ }
196
+ if (this.clearBtn) {
197
+ this.clearBtn.disabled = !this.teamId || !this.serverReady || this.replayInProgress
198
+ }
199
+ }
200
+
201
+ TeamChat.prototype.disconnect = function () {
202
+ this.hydrateGen += 1
203
+ if (this.socket) {
204
+ try {
205
+ this.socket.close()
206
+ } catch (e) {
207
+ /* ignore */
208
+ }
209
+ this.socket = null
210
+ }
211
+ this.serverReady = false
212
+ this.turnActive = false
213
+ this.activeQueryAgents = new Set()
214
+ this.teamId = null
215
+ this.sessionId = null
216
+ this.idleHint = ''
217
+ this.resetMessages()
218
+ this.setStatus('未连接', '')
219
+ this.updateComposer()
220
+ }
221
+
222
+ TeamChat.prototype.resetMessages = function () {
223
+ this.rows = []
224
+ this.seenSeq = new Set()
225
+ this.seenEventIds = new Set()
226
+ this.pendingTimeline = []
227
+ this.render()
228
+ }
229
+
230
+ TeamChat.prototype.teamSessionId = function (teamId) {
231
+ return 'team-' + String(teamId || '').trim()
232
+ }
233
+
234
+ TeamChat.prototype.wsUrl = function () {
235
+ var proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
236
+ return proto + '//' + window.location.host + '/ws/team?teamId=' + encodeURIComponent(this.teamId)
237
+ }
238
+
239
+ TeamChat.prototype.apiPath = function (path) {
240
+ var p = path.indexOf('/') === 0 ? path : '/' + path
241
+ try {
242
+ if (
243
+ typeof window !== 'undefined' &&
244
+ window.location &&
245
+ (window.location.protocol === 'http:' || window.location.protocol === 'https:') &&
246
+ this.httpOrigin === window.location.origin
247
+ ) {
248
+ return p
249
+ }
250
+ } catch (e) {
251
+ /* ignore */
252
+ }
253
+ return new URL(p, this.httpOrigin + '/').toString()
254
+ }
255
+
256
+ TeamChat.prototype.replayUrl = function () {
257
+ return this.apiPath('/api/teams/' + encodeURIComponent(this.teamId) + '/chat/replay')
258
+ }
259
+
260
+ TeamChat.prototype.connect = function (teamId) {
261
+ var tid = String(teamId || '').trim()
262
+ if (!tid) {
263
+ this.disconnect()
264
+ return
265
+ }
266
+ var sid = this.teamSessionId(tid)
267
+ if (this.teamId === tid && this.sessionId === sid && this.socket) {
268
+ return
269
+ }
270
+ this.disconnect()
271
+ this.teamId = tid
272
+ this.sessionId = sid
273
+ this.idleHint = ''
274
+ this.setStatus('连接中…', '')
275
+ this.updateComposer()
276
+
277
+ var self = this
278
+ var ws
279
+ try {
280
+ ws = new WebSocket(this.wsUrl())
281
+ } catch (e) {
282
+ this.setStatus('连接失败', 'err')
283
+ return
284
+ }
285
+ this.socket = ws
286
+
287
+ ws.onopen = function () {
288
+ self.setStatus('等待就绪…', '')
289
+ }
290
+ ws.onclose = function () {
291
+ if (self.socket === ws) {
292
+ self.serverReady = false
293
+ self.activeQueryAgents = new Set()
294
+ self.turnActive = false
295
+ self.setStatus('已断开', 'err')
296
+ self.updateComposer()
297
+ }
298
+ }
299
+ ws.onerror = function () {
300
+ if (self.socket === ws) {
301
+ self.setStatus('连接错误', 'err')
302
+ }
303
+ }
304
+ ws.onmessage = function (ev) {
305
+ var data
306
+ try {
307
+ data = JSON.parse(String(ev.data || ''))
308
+ } catch (e2) {
309
+ return
310
+ }
311
+ self.applyEnvelope(data)
312
+ }
313
+ }
314
+
315
+ TeamChat.prototype.resolveEnvelopeSourceAgent = function (data, payload) {
316
+ if (payload && typeof payload.sourceAgent === 'string' && payload.sourceAgent) {
317
+ return payload.sourceAgent
318
+ }
319
+ if (typeof data.agent_name === 'string' && data.agent_name) {
320
+ return data.agent_name
321
+ }
322
+ return 'assistant'
323
+ }
324
+
325
+ TeamChat.prototype.dropOptimisticUserRows = function (roundKey) {
326
+ var next = []
327
+ for (var i = 0; i < this.rows.length; i++) {
328
+ var row = this.rows[i]
329
+ if (!row) continue
330
+ if (row.optimistic && row.entry && row.entry.kind === 'user') {
331
+ if (teamUserRoundKey(row.entry.text || '') === roundKey) {
332
+ continue
333
+ }
334
+ }
335
+ next.push(row)
336
+ }
337
+ this.rows = next
338
+ }
339
+
340
+ TeamChat.prototype.ingestTimelineEnvelope = function (data) {
341
+ var payload = data.data && typeof data.data === 'object' ? data.data : {}
342
+ var entry = payload.entry
343
+ if (!entry || typeof entry !== 'object' || !entry.kind) return false
344
+ var seq = parseTimelineSeq(data)
345
+ if (seq == null) return false
346
+ if (this.seenSeq.has(seq)) return false
347
+ if (entry.kind === 'user') {
348
+ this.dropOptimisticUserRows(teamUserRoundKey(entry.text || ''))
349
+ }
350
+ this.seenSeq.add(seq)
351
+ this.rows.push({
352
+ seq: seq,
353
+ roundId:
354
+ typeof payload.roundId === 'string' && payload.roundId.trim()
355
+ ? payload.roundId.trim()
356
+ : entry.kind === 'user'
357
+ ? buildRoundIdFromUser(entry)
358
+ : '',
359
+ entry: entry,
360
+ })
361
+ return true
362
+ }
363
+
364
+ TeamChat.prototype.ingestTimelineEnvelopes = function (envelopes) {
365
+ if (!Array.isArray(envelopes)) return
366
+ for (var i = 0; i < envelopes.length; i++) {
367
+ this.ingestTimelineEnvelope(envelopes[i])
368
+ }
369
+ }
370
+
371
+ TeamChat.prototype.groupRowsIntoRounds = function () {
372
+ var rounds = []
373
+ var indexByRoundId = new Map()
374
+ for (var i = 0; i < this.rows.length; i++) {
375
+ var row = this.rows[i]
376
+ if (!row || !row.entry) continue
377
+ if (row.entry.kind === 'user') {
378
+ var roundId =
379
+ typeof row.roundId === 'string' && row.roundId.trim()
380
+ ? row.roundId.trim()
381
+ : buildRoundIdFromUser(row.entry)
382
+ var round = {
383
+ user: row.entry,
384
+ roundId: roundId,
385
+ items: [],
386
+ }
387
+ rounds.push(round)
388
+ indexByRoundId.set(roundId, rounds.length - 1)
389
+ continue
390
+ }
391
+ var rid =
392
+ typeof row.roundId === 'string' && row.roundId.trim() ? row.roundId.trim() : ''
393
+ var idx = rid ? indexByRoundId.get(rid) : undefined
394
+ if (idx == null && rounds.length > 0) {
395
+ idx = rounds.length - 1
396
+ }
397
+ if (idx != null) {
398
+ rounds[idx].items.push(row)
399
+ }
400
+ }
401
+ return rounds
402
+ }
403
+
404
+ TeamChat.prototype.applyEnvelope = function (data) {
405
+ if (!data || typeof data !== 'object' || data.protocolVersion !== 3) return
406
+ var type = typeof data.type === 'string' ? data.type : ''
407
+ var payload = data.data && typeof data.data === 'object' ? data.data : {}
408
+ var sourceAgent = this.resolveEnvelopeSourceAgent(data, payload)
409
+
410
+ if (type === 'team.timeline' && this.replayInProgress) {
411
+ this.pendingTimeline.push(data)
412
+ return
413
+ }
414
+ if (typeof data.eventId === 'string' && data.eventId) {
415
+ if (this.seenEventIds.has(data.eventId)) return
416
+ this.seenEventIds.add(data.eventId)
417
+ }
418
+
419
+ if (type === 'team.timeline') {
420
+ if (this.ingestTimelineEnvelope(data)) {
421
+ var timelineEntry = payload.entry
422
+ if (
423
+ timelineEntry &&
424
+ timelineEntry.kind === 'dispatch' &&
425
+ timelineEntry.toAgent
426
+ ) {
427
+ this.activeQueryAgents.add(String(timelineEntry.toAgent).trim())
428
+ this.syncTurnActive()
429
+ } else if (
430
+ timelineEntry &&
431
+ timelineEntry.kind === 'reply' &&
432
+ timelineEntry.fromAgent
433
+ ) {
434
+ this.activeQueryAgents.delete(String(timelineEntry.fromAgent).trim())
435
+ this.syncTurnActive()
436
+ } else {
437
+ this.render()
438
+ }
439
+ }
440
+ return
441
+ }
442
+
443
+ if (type === 'turn.terminal') {
444
+ this.activeQueryAgents.delete(sourceAgent)
445
+ this.syncTurnActive()
446
+ return
447
+ }
448
+
449
+ if (type === 'team.chat.cleared') {
450
+ this.activeQueryAgents = new Set()
451
+ this.syncTurnActive()
452
+ this.resetMessages()
453
+ return
454
+ }
455
+
456
+ if (type === 'query.progress') {
457
+ var phase = typeof payload.phase === 'string' ? payload.phase : ''
458
+ if (phase && phase !== 'idle') {
459
+ this.activeQueryAgents.add(sourceAgent)
460
+ } else {
461
+ this.activeQueryAgents.delete(sourceAgent)
462
+ }
463
+ this.syncTurnActive()
464
+ return
465
+ }
466
+
467
+ if (type === 'session.ready') {
468
+ this.serverReady = true
469
+ this.setStatus('已就绪', 'ready')
470
+ void this.hydrateHistory()
471
+ this.updateComposer()
472
+ return
473
+ }
474
+
475
+ if (type === 'session.error') {
476
+ var errMsg =
477
+ payload && typeof payload.message === 'string' ? payload.message : 'unknown'
478
+ this.setStatus('错误: ' + errMsg, 'err')
479
+ this.activeQueryAgents = new Set()
480
+ this.syncTurnActive()
481
+ }
482
+ }
483
+
484
+ TeamChat.prototype.flushPendingTimeline = function () {
485
+ this.ingestTimelineEnvelopes(this.pendingTimeline.splice(0))
486
+ }
487
+
488
+ TeamChat.prototype.hydrateHistory = async function () {
489
+ if (!this.teamId) return
490
+ var gen = ++this.hydrateGen
491
+ var wasReady = this.serverReady
492
+ var hydrateError = ''
493
+ this.replayInProgress = true
494
+ this.pendingTimeline = []
495
+ this.resetMessages()
496
+ try {
497
+ var r = await fetch(this.replayUrl())
498
+ if (gen !== this.hydrateGen) return
499
+ var contentType = (r.headers && r.headers.get('content-type')) || ''
500
+ if (!r.ok) {
501
+ hydrateError = '回放失败 HTTP ' + r.status
502
+ } else if (contentType.indexOf('json') < 0) {
503
+ hydrateError = '回放接口未返回 JSON,请确认 WS 服务已更新并重启'
504
+ } else {
505
+ var body = await r.json()
506
+ var envelopes = Array.isArray(body.envelopes) ? body.envelopes : []
507
+ this.ingestTimelineEnvelopes(envelopes)
508
+ }
509
+ } catch (e) {
510
+ hydrateError = '回放失败: ' + String(e && e.message ? e.message : e)
511
+ } finally {
512
+ if (gen === this.hydrateGen) {
513
+ this.replayInProgress = false
514
+ this.flushPendingTimeline()
515
+ this.render()
516
+ if (wasReady) {
517
+ this.serverReady = true
518
+ if (hydrateError) {
519
+ this.setStatus(hydrateError, 'err')
520
+ } else {
521
+ this.setStatus('已就绪', 'ready')
522
+ }
523
+ }
524
+ this.updateComposer()
525
+ } else {
526
+ this.replayInProgress = false
527
+ }
528
+ }
529
+ }
530
+
531
+ TeamChat.prototype.sendPrompt = function () {
532
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) return
533
+ if (!this.serverReady || this.turnActive) return
534
+ var text = readPromptText(this.promptEl).trim()
535
+ if (!text) return
536
+ var user = { kind: 'user', text: text, ts: new Date().toISOString() }
537
+ var roundId = buildRoundIdFromUser(user)
538
+ this.rows.push({ roundId: roundId, entry: user, optimistic: true })
539
+ this.render()
540
+ this.socket.send(JSON.stringify({ type: 'prompt', text: text }))
541
+ writePromptText(this.promptEl, '')
542
+ this.updateComposer()
543
+ }
544
+
545
+ TeamChat.prototype.abortTurn = function () {
546
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) return
547
+ if (!this.serverReady) return
548
+ this.socket.send(JSON.stringify({ type: 'abort' }))
549
+ }
550
+
551
+ TeamChat.prototype.clearChatHistory = async function () {
552
+ if (!this.teamId || !this.serverReady) return
553
+ if (
554
+ typeof window !== 'undefined' &&
555
+ window.confirm &&
556
+ !window.confirm('确定清空该团队的聊天记录?此操作不可恢复。')
557
+ ) {
558
+ return
559
+ }
560
+ try {
561
+ var r = await fetch(
562
+ this.apiPath('/api/teams/' + encodeURIComponent(this.teamId) + '/chat'),
563
+ { method: 'DELETE' },
564
+ )
565
+ if (!r.ok) {
566
+ var errBody = {}
567
+ try {
568
+ errBody = await r.json()
569
+ } catch (e2) {
570
+ /* ignore */
571
+ }
572
+ throw new Error(
573
+ (errBody && errBody.message) || '清理失败 HTTP ' + r.status,
574
+ )
575
+ }
576
+ this.activeQueryAgents = new Set()
577
+ this.syncTurnActive()
578
+ this.resetMessages()
579
+ this.setStatus('已就绪', 'ready')
580
+ this.updateComposer()
581
+ } catch (e) {
582
+ this.setStatus(
583
+ '清理失败: ' + String(e && e.message ? e.message : e),
584
+ 'err',
585
+ )
586
+ }
587
+ }
588
+
589
+ TeamChat.prototype.render = function () {
590
+ if (!this.threadEl) return
591
+ this.threadEl.innerHTML = ''
592
+
593
+ if (this.rows.length === 0) {
594
+ var ph = document.createElement('div')
595
+ ph.className = 'chat-placeholder'
596
+ ph.textContent =
597
+ this.idleHint ||
598
+ (this.teamId ? '在下方输入消息,向团队发起协作' : '选择团队以开始群聊')
599
+ this.threadEl.appendChild(ph)
600
+ return
601
+ }
602
+
603
+ var rounds = this.groupRowsIntoRounds()
604
+ for (var i = 0; i < rounds.length; i++) {
605
+ this.threadEl.appendChild(this.buildRoundBlock(rounds[i], i === rounds.length - 1))
606
+ }
607
+
608
+ this.threadEl.scrollTop = this.threadEl.scrollHeight
609
+ }
610
+
611
+ TeamChat.prototype.buildRoundBlock = function (round, isLast) {
612
+ var wrap = document.createElement('section')
613
+ wrap.className = 'chat-round' + (isLast ? ' chat-round--active' : '')
614
+
615
+ var thread = document.createElement('div')
616
+ thread.className = 'chat-round-thread'
617
+
618
+ thread.appendChild(this.buildUserBubble(round.user))
619
+
620
+ var items = round.items || []
621
+ for (var j = 0; j < items.length; j++) {
622
+ var entry = items[j].entry
623
+ if (!entry) continue
624
+ if (entry.kind === 'dispatch') {
625
+ thread.appendChild(this.buildDispatchBubble(entry))
626
+ } else if (entry.kind === 'reply' && entry.text) {
627
+ thread.appendChild(this.buildReplyBubble(entry.text, entry.fromAgent))
628
+ }
629
+ }
630
+
631
+ if (isLast && this.turnActive) {
632
+ var self = this
633
+ this.activeQueryAgents.forEach(function (agentId) {
634
+ var hasContent = items.some(function (row) {
635
+ var e = row.entry
636
+ if (!e) return false
637
+ if (e.kind === 'reply' && e.fromAgent === agentId) return true
638
+ if (e.kind === 'dispatch' && e.fromAgent === agentId) return true
639
+ return false
640
+ })
641
+ if (!hasContent) {
642
+ thread.appendChild(self.buildTypingBubble(agentId))
643
+ }
644
+ })
645
+ }
646
+
647
+ wrap.appendChild(thread)
648
+ return wrap
649
+ }
650
+
651
+ TeamChat.prototype.buildUserBubble = function (user) {
652
+ return this.buildMessageRow(String(user.text || '').trim(), 'user', 'user', false)
653
+ }
654
+
655
+ TeamChat.prototype.buildDispatchBubble = function (entry) {
656
+ var fromMeta = this.resolveSenderMeta(entry.fromAgent, 'assistant')
657
+ var toId = String(entry.toAgent || '').trim()
658
+ var mention = toId ? '@' + toId : ''
659
+ var bodyText = mention
660
+ ? mention +
661
+ (entry.prompt ? ' ' + entry.prompt : entry.description ? ' ' + entry.description : '')
662
+ : entry.prompt || entry.description || '调度队员'
663
+
664
+ var wrap = document.createElement('div')
665
+ wrap.className = 'chat-msg-row chat-msg-row--dispatch'
666
+
667
+ var avatar = document.createElement('span')
668
+ avatar.className = 'chat-msg-avatar'
669
+ avatar.textContent = fromMeta.initial
670
+ avatar.style.background = fromMeta.color
671
+
672
+ var bodyWrap = document.createElement('div')
673
+ bodyWrap.className = 'chat-msg-body-wrap'
674
+
675
+ var sender = document.createElement('div')
676
+ sender.className = 'chat-msg-sender'
677
+ sender.textContent = fromMeta.label
678
+
679
+ var body = document.createElement('div')
680
+ body.className = 'chat-dispatch-card'
681
+ body.textContent = bodyText
682
+
683
+ bodyWrap.appendChild(sender)
684
+ bodyWrap.appendChild(body)
685
+ wrap.appendChild(avatar)
686
+ wrap.appendChild(bodyWrap)
687
+ return wrap
688
+ }
689
+
690
+ TeamChat.prototype.buildReplyBubble = function (text, fromAgent) {
691
+ return this.buildMessageRow(text, 'assistant', fromAgent, true)
692
+ }
693
+
694
+ TeamChat.prototype.buildTypingBubble = function (fromAgent) {
695
+ var meta = this.resolveSenderMeta(fromAgent, 'assistant')
696
+ var wrap = document.createElement('div')
697
+ wrap.className = 'chat-msg-row chat-msg-row--assistant chat-msg-row--typing'
698
+
699
+ var avatar = document.createElement('span')
700
+ avatar.className = 'chat-msg-avatar'
701
+ avatar.textContent = meta.initial
702
+ avatar.style.background = meta.color
703
+
704
+ var bodyWrap = document.createElement('div')
705
+ bodyWrap.className = 'chat-msg-body-wrap'
706
+
707
+ var sender = document.createElement('div')
708
+ sender.className = 'chat-msg-sender'
709
+ sender.textContent = meta.label
710
+
711
+ var body = document.createElement('div')
712
+ body.className = 'chat-typing-body'
713
+ body.textContent = '正在输入…'
714
+
715
+ bodyWrap.appendChild(sender)
716
+ bodyWrap.appendChild(body)
717
+ wrap.appendChild(avatar)
718
+ wrap.appendChild(bodyWrap)
719
+ return wrap
720
+ }
721
+
722
+ TeamChat.prototype.buildMessageRow = function (text, role, sourceAgent, isMarkdown) {
723
+ var meta = this.resolveSenderMeta(sourceAgent, role)
724
+ var wrap = document.createElement('div')
725
+ wrap.className =
726
+ 'chat-msg-row ' + (role === 'user' ? 'chat-msg-row--user' : 'chat-msg-row--assistant')
727
+
728
+ var avatar = document.createElement('span')
729
+ avatar.className = 'chat-msg-avatar'
730
+ avatar.textContent = meta.initial
731
+ avatar.style.background = meta.color
732
+
733
+ var bodyWrap = document.createElement('div')
734
+ bodyWrap.className = 'chat-msg-body-wrap'
735
+
736
+ var sender = document.createElement('div')
737
+ sender.className = 'chat-msg-sender'
738
+ sender.textContent = meta.label
739
+
740
+ var body = document.createElement('div')
741
+ if (role === 'user') {
742
+ body.className = 'chat-user-body'
743
+ body.textContent = text
744
+ } else if (isMarkdown) {
745
+ body.className = 'chat-md-body'
746
+ body.innerHTML = renderMd(text)
747
+ } else {
748
+ body.className = 'chat-user-body'
749
+ body.textContent = text
750
+ }
751
+
752
+ bodyWrap.appendChild(sender)
753
+ bodyWrap.appendChild(body)
754
+ wrap.appendChild(avatar)
755
+ wrap.appendChild(bodyWrap)
756
+ return wrap
757
+ }
758
+
759
+ global.TeamChat = TeamChat
760
+ })(typeof window !== 'undefined' ? window : global)