@auto-ai/agent 2.1.93 → 2.1.94
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.
- package/dist/404/index.html +1 -1
- package/dist/404.html +1 -1
- package/dist/_next/static/chunks/24ad0472395a5554.js +1 -0
- package/dist/_next/static/chunks/{ce0cac88dd992956.css → 6a750155591ba201.css} +1 -1
- package/dist/agent-office.html +580 -1
- package/dist/index.html +1 -1
- package/dist/index.txt +6 -6
- package/dist/manage/about/index.html +2 -2
- package/dist/manage/about/index.txt +3 -3
- package/dist/manage/add-account/basic/index.html +2 -2
- package/dist/manage/add-account/basic/index.txt +6 -5
- package/dist/manage/add-account/index.html +2 -2
- package/dist/manage/add-account/index.txt +5 -6
- package/dist/manage/add-account/prompt/index.html +2 -2
- package/dist/manage/add-account/prompt/index.txt +3 -3
- package/dist/manage/agent-teams/index.html +2 -2
- package/dist/manage/agent-teams/index.txt +3 -3
- package/dist/manage/env/index.html +2 -2
- package/dist/manage/env/index.txt +3 -3
- package/dist/manage/general/index.html +2 -2
- package/dist/manage/general/index.txt +3 -3
- package/dist/manage/index.html +1 -1
- package/dist/manage/index.txt +3 -3
- package/dist/manage/mcp/index.html +2 -2
- package/dist/manage/mcp/index.txt +3 -3
- package/dist/manage/permissions/index.html +2 -2
- package/dist/manage/permissions/index.txt +3 -3
- package/dist/manage/skills/index.html +2 -2
- package/dist/manage/skills/index.txt +3 -3
- package/dist/manage/task/index.html +1 -1
- package/dist/manage/task/index.txt +3 -3
- package/dist/manage/teams/index.html +1 -1
- package/dist/manage/teams/index.txt +3 -3
- package/dist/manage/tools/index.html +2 -2
- package/dist/manage/tools/index.txt +3 -3
- package/dist/slash-command-ui-patch.css +49 -0
- package/dist/slash-command-ui-patch.js +101 -0
- package/dist/ws-test.html +111 -2
- package/package.json +6 -6
- package/dist/_next/static/chunks/091dc4a67d911a93.js +0 -1
- package/dist/agent-office/accents.js +0 -28
- package/dist/agent-office/api.js +0 -142
- package/dist/agent-office/list.js +0 -79
- package/dist/agent-office/main.js +0 -38
- package/dist/agent-office/officeController.js +0 -13
- package/dist/agent-office/ui.js +0 -264
- /package/dist/_next/static/{nFW2vz8zx3Bz5bWQhlf33 → 8ct8wdwNecCOvJ8dbcAlk}/_buildManifest.js +0 -0
- /package/dist/_next/static/{nFW2vz8zx3Bz5bWQhlf33 → 8ct8wdwNecCOvJ8dbcAlk}/_clientMiddlewareManifest.json +0 -0
- /package/dist/_next/static/{nFW2vz8zx3Bz5bWQhlf33 → 8ct8wdwNecCOvJ8dbcAlk}/_ssgManifest.js +0 -0
package/dist/agent-office.html
CHANGED
|
@@ -302,6 +302,585 @@
|
|
|
302
302
|
<div id="officeToast" role="status" aria-live="polite"></div>
|
|
303
303
|
</div>
|
|
304
304
|
|
|
305
|
-
<script
|
|
305
|
+
<script>
|
|
306
|
+
;(function () {
|
|
307
|
+
'use strict'
|
|
308
|
+
|
|
309
|
+
/** 列表/写操作 API 上下文:固定使用已存在的默认 agent */
|
|
310
|
+
const DEFAULT_CONTEXT_AGENT = 'qihoo'
|
|
311
|
+
|
|
312
|
+
/** 解析 API 基址:支持 ?apiBase= 或当前页面 origin(与 ws-test 一致) */
|
|
313
|
+
function httpOriginForApi() {
|
|
314
|
+
try {
|
|
315
|
+
const fromQuery = new URLSearchParams(window.location.search).get('apiBase')
|
|
316
|
+
if (fromQuery && String(fromQuery).trim()) {
|
|
317
|
+
return String(fromQuery).trim().replace(/\/$/, '')
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
/* ignore */
|
|
321
|
+
}
|
|
322
|
+
return window.location.origin
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** 构建 GET/POST /api/agents 列表地址 */
|
|
326
|
+
function buildAgentsListUrl(contextAgent) {
|
|
327
|
+
const u = new URL('/api/agents', httpOriginForApi() + '/')
|
|
328
|
+
u.searchParams.set('agent', contextAgent || DEFAULT_CONTEXT_AGENT)
|
|
329
|
+
return u.toString()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** 构建单个 agent 的 REST 地址 */
|
|
333
|
+
function buildAgentItemUrl(id, contextAgent) {
|
|
334
|
+
const u = new URL(
|
|
335
|
+
'/api/agents/' + encodeURIComponent(String(id || '').trim()),
|
|
336
|
+
httpOriginForApi() + '/',
|
|
337
|
+
)
|
|
338
|
+
u.searchParams.set('agent', contextAgent || DEFAULT_CONTEXT_AGENT)
|
|
339
|
+
return u.toString()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** 校验新建 agent id:字母数字下划线中划线,1~64 */
|
|
343
|
+
function isValidAgentIdInput(id) {
|
|
344
|
+
return /^[a-zA-Z0-9_-]{1,64}$/.test(String(id || '').trim())
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* 基于已有 agent.json 构造 PATCH config,仅更新 whentouse;
|
|
349
|
+
* effort 为 null 时不写入,避免覆盖服务端默认值。
|
|
350
|
+
*/
|
|
351
|
+
function buildAgentConfigPatch(baseConfig, whentouse) {
|
|
352
|
+
const c = baseConfig && typeof baseConfig === 'object' ? baseConfig : {}
|
|
353
|
+
const env = c.env && typeof c.env === 'object' && !Array.isArray(c.env) ? c.env : {}
|
|
354
|
+
const patch = {
|
|
355
|
+
tools: Array.isArray(c.tools) ? c.tools.map(String) : [],
|
|
356
|
+
disallowedTools: Array.isArray(c.disallowedTools)
|
|
357
|
+
? c.disallowedTools.map(String)
|
|
358
|
+
: [],
|
|
359
|
+
mcpServers: Array.isArray(c.mcpServers) ? c.mcpServers.map(String) : [],
|
|
360
|
+
skills: Array.isArray(c.skills) ? c.skills.map(String) : [],
|
|
361
|
+
agentTeams: Array.isArray(c.agentTeams) ? c.agentTeams.map(String) : [],
|
|
362
|
+
model: typeof c.model === 'string' ? c.model : '',
|
|
363
|
+
background: c.background === true,
|
|
364
|
+
isolation: typeof c.isolation === 'string' ? c.isolation : '',
|
|
365
|
+
whentouse: typeof whentouse === 'string' ? whentouse : '',
|
|
366
|
+
env,
|
|
367
|
+
}
|
|
368
|
+
if (typeof c.effort === 'string' || typeof c.effort === 'number') {
|
|
369
|
+
patch.effort = c.effort
|
|
370
|
+
}
|
|
371
|
+
return patch
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** 拉取 agent 列表 */
|
|
375
|
+
async function fetchAgentsList(contextAgent) {
|
|
376
|
+
const r = await fetch(buildAgentsListUrl(contextAgent))
|
|
377
|
+
const body = await r.json().catch(() => ({}))
|
|
378
|
+
if (!r.ok) {
|
|
379
|
+
throw new Error(body.message || body.error || r.statusText)
|
|
380
|
+
}
|
|
381
|
+
return Array.isArray(body.agents) ? body.agents : []
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** 拉取单个 agent 详情(含 config、prompt) */
|
|
385
|
+
async function fetchAgentDetail(id, contextAgent) {
|
|
386
|
+
const r = await fetch(buildAgentItemUrl(id, contextAgent))
|
|
387
|
+
const body = await r.json().catch(() => ({}))
|
|
388
|
+
if (!r.ok) {
|
|
389
|
+
throw new Error(body.message || body.error || r.statusText)
|
|
390
|
+
}
|
|
391
|
+
return body.agent || { id }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** 删除 agent;默认 agent qihoo 不可删 */
|
|
395
|
+
async function deleteAgent(id, contextAgent) {
|
|
396
|
+
const agentId = String(id || '').trim()
|
|
397
|
+
if (!agentId) throw new Error('缺少 agent id')
|
|
398
|
+
if (agentId === DEFAULT_CONTEXT_AGENT) {
|
|
399
|
+
throw new Error('默认 Agent(' + DEFAULT_CONTEXT_AGENT + ')不可删除')
|
|
400
|
+
}
|
|
401
|
+
const r = await fetch(buildAgentItemUrl(agentId, contextAgent), { method: 'DELETE' })
|
|
402
|
+
const body = await r.json().catch(() => ({}))
|
|
403
|
+
if (!r.ok) {
|
|
404
|
+
throw new Error(body.message || body.error || r.statusText)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* 保存 agent:新建走 POST + PATCH whentouse;编辑走 PATCH prompt + config。
|
|
410
|
+
*/
|
|
411
|
+
async function saveAgent(params) {
|
|
412
|
+
const { id, whentouse, prompt, isEdit, baseConfig, contextAgent } = params
|
|
413
|
+
if (isEdit) {
|
|
414
|
+
const patchRes = await fetch(buildAgentItemUrl(id, contextAgent), {
|
|
415
|
+
method: 'PATCH',
|
|
416
|
+
headers: { 'content-type': 'application/json; charset=utf-8' },
|
|
417
|
+
body: JSON.stringify({
|
|
418
|
+
prompt,
|
|
419
|
+
config: buildAgentConfigPatch(baseConfig, whentouse),
|
|
420
|
+
}),
|
|
421
|
+
})
|
|
422
|
+
const patchBody = await patchRes.json().catch(() => ({}))
|
|
423
|
+
if (!patchRes.ok) {
|
|
424
|
+
throw new Error(patchBody.message || patchBody.error || patchRes.statusText)
|
|
425
|
+
}
|
|
426
|
+
return id
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const createRes = await fetch(buildAgentsListUrl(contextAgent), {
|
|
430
|
+
method: 'POST',
|
|
431
|
+
headers: { 'content-type': 'application/json; charset=utf-8' },
|
|
432
|
+
body: JSON.stringify({ name: id, prompt }),
|
|
433
|
+
})
|
|
434
|
+
const createBody = await createRes.json().catch(() => ({}))
|
|
435
|
+
if (!createRes.ok) {
|
|
436
|
+
throw new Error(createBody.message || createBody.error || createRes.statusText)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const cfgBody = await fetchAgentDetail(id, contextAgent)
|
|
440
|
+
const baseCfg =
|
|
441
|
+
cfgBody.config && typeof cfgBody.config === 'object' ? cfgBody.config : null
|
|
442
|
+
const patchRes = await fetch(buildAgentItemUrl(id, contextAgent), {
|
|
443
|
+
method: 'PATCH',
|
|
444
|
+
headers: { 'content-type': 'application/json; charset=utf-8' },
|
|
445
|
+
body: JSON.stringify({
|
|
446
|
+
config: buildAgentConfigPatch(baseCfg, whentouse),
|
|
447
|
+
}),
|
|
448
|
+
})
|
|
449
|
+
const patchBody = await patchRes.json().catch(() => ({}))
|
|
450
|
+
if (!patchRes.ok) {
|
|
451
|
+
throw new Error(patchBody.message || patchBody.error || patchRes.statusText)
|
|
452
|
+
}
|
|
453
|
+
return id
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const AGENT_ACCENT_COLORS = [
|
|
457
|
+
'#22d3c5',
|
|
458
|
+
'#4da3ff',
|
|
459
|
+
'#8b5cf6',
|
|
460
|
+
'#e84855',
|
|
461
|
+
'#f5c518',
|
|
462
|
+
'#c5e84c',
|
|
463
|
+
]
|
|
464
|
+
|
|
465
|
+
const KNOWN_ACCENTS = {
|
|
466
|
+
dev: '#22d3c5',
|
|
467
|
+
edr: '#4da3ff',
|
|
468
|
+
qihoo: '#8b5cf6',
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** 根据 agent id 分配列表左侧色带 */
|
|
472
|
+
function accentColorForId(id) {
|
|
473
|
+
const key = String(id || '').trim().toLowerCase()
|
|
474
|
+
if (KNOWN_ACCENTS[key]) return KNOWN_ACCENTS[key]
|
|
475
|
+
const s = String(id || 'a')
|
|
476
|
+
let h = 0
|
|
477
|
+
for (let i = 0; i < s.length; i++) {
|
|
478
|
+
h = (h + s.charCodeAt(i) * 17) % AGENT_ACCENT_COLORS.length
|
|
479
|
+
}
|
|
480
|
+
return AGENT_ACCENT_COLORS[h]
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** 列表页选中状态:仅维护当前 agent id */
|
|
484
|
+
class OfficeController {
|
|
485
|
+
constructor() {
|
|
486
|
+
this.selectedId = null
|
|
487
|
+
this.onSelect = null
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** 选中或取消选中,并通知侧栏 UI */
|
|
491
|
+
selectAgent(id) {
|
|
492
|
+
this.selectedId = id || null
|
|
493
|
+
if (this.onSelect) this.onSelect(this.selectedId)
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function truncateListDesc(text, max) {
|
|
498
|
+
const s = String(text || '').replace(/\s+/g, ' ').trim()
|
|
499
|
+
if (!s) return '暂无使用说明'
|
|
500
|
+
return s.length <= max ? s : s.slice(0, max - 1) + '…'
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** Agent 列表 DOM 渲染 */
|
|
504
|
+
class AgentList {
|
|
505
|
+
constructor(container, onPick) {
|
|
506
|
+
this.container = container
|
|
507
|
+
this.onPick = onPick
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
render(agents, selectedId) {
|
|
511
|
+
if (!this.container) return
|
|
512
|
+
this.container.innerHTML = ''
|
|
513
|
+
|
|
514
|
+
if (!agents.length) {
|
|
515
|
+
const empty = document.createElement('div')
|
|
516
|
+
empty.className = 'agent-list-empty'
|
|
517
|
+
empty.textContent = '暂无 Agent,点击右上角「新建 Agent」创建'
|
|
518
|
+
this.container.appendChild(empty)
|
|
519
|
+
return
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const ul = document.createElement('ul')
|
|
523
|
+
ul.className = 'agent-list'
|
|
524
|
+
ul.setAttribute('role', 'list')
|
|
525
|
+
|
|
526
|
+
for (let i = 0; i < agents.length; i++) {
|
|
527
|
+
const row = agents[i]
|
|
528
|
+
const id = String(row.id || '').trim()
|
|
529
|
+
if (!id) continue
|
|
530
|
+
|
|
531
|
+
const li = document.createElement('li')
|
|
532
|
+
const btn = document.createElement('button')
|
|
533
|
+
btn.type = 'button'
|
|
534
|
+
btn.className =
|
|
535
|
+
'agent-list-item' + (selectedId === id ? ' is-selected' : '')
|
|
536
|
+
btn.setAttribute('aria-pressed', selectedId === id ? 'true' : 'false')
|
|
537
|
+
|
|
538
|
+
const accent = document.createElement('span')
|
|
539
|
+
accent.className = 'agent-list-accent'
|
|
540
|
+
accent.style.background = accentColorForId(id)
|
|
541
|
+
|
|
542
|
+
const body = document.createElement('span')
|
|
543
|
+
body.className = 'agent-list-body'
|
|
544
|
+
|
|
545
|
+
const title = document.createElement('span')
|
|
546
|
+
title.className = 'agent-list-id'
|
|
547
|
+
title.textContent = id
|
|
548
|
+
|
|
549
|
+
const desc = document.createElement('span')
|
|
550
|
+
desc.className = 'agent-list-desc'
|
|
551
|
+
desc.textContent = truncateListDesc(row.whentouse, 80)
|
|
552
|
+
|
|
553
|
+
body.appendChild(title)
|
|
554
|
+
body.appendChild(desc)
|
|
555
|
+
|
|
556
|
+
const arrow = document.createElement('span')
|
|
557
|
+
arrow.className = 'agent-list-arrow'
|
|
558
|
+
arrow.textContent = '›'
|
|
559
|
+
|
|
560
|
+
btn.appendChild(accent)
|
|
561
|
+
btn.appendChild(body)
|
|
562
|
+
btn.appendChild(arrow)
|
|
563
|
+
|
|
564
|
+
btn.addEventListener('click', () => {
|
|
565
|
+
if (this.onPick) this.onPick(id)
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
li.appendChild(btn)
|
|
569
|
+
ul.appendChild(li)
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
this.container.appendChild(ul)
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** 列表 + 侧栏 CRUD 与 URL ?agent= 同步 */
|
|
577
|
+
class OfficeUI {
|
|
578
|
+
constructor(root, controller, list, hooks) {
|
|
579
|
+
this.root = root
|
|
580
|
+
this.controller = controller
|
|
581
|
+
this.list = list
|
|
582
|
+
this.hooks = hooks || {}
|
|
583
|
+
this.contextAgent = DEFAULT_CONTEXT_AGENT
|
|
584
|
+
this.agents = []
|
|
585
|
+
this.editingId = null
|
|
586
|
+
this.baseConfig = null
|
|
587
|
+
this.mode = 'idle'
|
|
588
|
+
|
|
589
|
+
this.panelEl = root.querySelector('#officePanel')
|
|
590
|
+
this.panelTitleEl = root.querySelector('#officePanelTitle')
|
|
591
|
+
this.panelMetaEl = root.querySelector('#officePanelMeta')
|
|
592
|
+
this.formEl = root.querySelector('#officeAgentForm')
|
|
593
|
+
this.idInput = root.querySelector('#officeAgentId')
|
|
594
|
+
this.whenInput = root.querySelector('#officeAgentWhen')
|
|
595
|
+
this.promptInput = root.querySelector('#officeAgentPrompt')
|
|
596
|
+
this.btnNew = root.querySelector('#btnOfficeNewAgent')
|
|
597
|
+
this.btnSave = root.querySelector('#btnOfficeSave')
|
|
598
|
+
this.btnDelete = root.querySelector('#btnOfficeDelete')
|
|
599
|
+
this.btnWorkbench = root.querySelector('#btnOfficeWorkbench')
|
|
600
|
+
this.btnClose = root.querySelector('#btnOfficePanelClose')
|
|
601
|
+
this.toastEl = root.querySelector('#officeToast')
|
|
602
|
+
|
|
603
|
+
this.bindEvents()
|
|
604
|
+
this.hidePanel()
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
bindEvents() {
|
|
608
|
+
if (this.btnNew) {
|
|
609
|
+
this.btnNew.addEventListener('click', () => this.showCreateForm())
|
|
610
|
+
}
|
|
611
|
+
if (this.btnClose) {
|
|
612
|
+
this.btnClose.addEventListener('click', () => {
|
|
613
|
+
this.hidePanel()
|
|
614
|
+
this.controller.selectAgent(null)
|
|
615
|
+
this.clearUrlAgentParam()
|
|
616
|
+
})
|
|
617
|
+
}
|
|
618
|
+
if (this.btnSave) {
|
|
619
|
+
this.btnSave.addEventListener('click', () => void this.submitForm())
|
|
620
|
+
}
|
|
621
|
+
if (this.btnDelete) {
|
|
622
|
+
this.btnDelete.addEventListener('click', () => void this.handleDelete())
|
|
623
|
+
}
|
|
624
|
+
if (this.btnWorkbench) {
|
|
625
|
+
this.btnWorkbench.addEventListener('click', () => {
|
|
626
|
+
const id =
|
|
627
|
+
this.editingId || (this.idInput ? this.idInput.value.trim() : '')
|
|
628
|
+
if (!id) return
|
|
629
|
+
window.location.href =
|
|
630
|
+
'/ws-test.html?agent=' + encodeURIComponent(id)
|
|
631
|
+
})
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
showToast(msg, isError) {
|
|
636
|
+
if (!this.toastEl) return
|
|
637
|
+
this.toastEl.textContent = msg
|
|
638
|
+
this.toastEl.classList.toggle('is-error', !!isError)
|
|
639
|
+
this.toastEl.classList.add('is-visible')
|
|
640
|
+
clearTimeout(this._toastTimer)
|
|
641
|
+
this._toastTimer = setTimeout(() => {
|
|
642
|
+
this.toastEl.classList.remove('is-visible')
|
|
643
|
+
}, 3200)
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
hidePanel() {
|
|
647
|
+
if (this.panelEl) this.panelEl.classList.remove('is-open')
|
|
648
|
+
this.editingId = null
|
|
649
|
+
this.baseConfig = null
|
|
650
|
+
this.mode = 'idle'
|
|
651
|
+
this.list.render(this.agents, null)
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
showPanelForAgent(id) {
|
|
655
|
+
if (!this.panelEl) return
|
|
656
|
+
this.panelEl.classList.add('is-open')
|
|
657
|
+
this.list.render(this.agents, id)
|
|
658
|
+
void this.loadAgentIntoForm(id)
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
showCreateForm() {
|
|
662
|
+
if (!this.panelEl || !this.formEl) return
|
|
663
|
+
this.panelEl.classList.add('is-open')
|
|
664
|
+
this.mode = 'create'
|
|
665
|
+
this.editingId = null
|
|
666
|
+
this.baseConfig = null
|
|
667
|
+
if (this.panelTitleEl) this.panelTitleEl.textContent = '新建 Agent'
|
|
668
|
+
if (this.panelMetaEl) {
|
|
669
|
+
this.panelMetaEl.textContent = '创建后可从列表进入工作台'
|
|
670
|
+
}
|
|
671
|
+
if (this.idInput) {
|
|
672
|
+
this.idInput.value = ''
|
|
673
|
+
this.idInput.readOnly = false
|
|
674
|
+
}
|
|
675
|
+
if (this.whenInput) this.whenInput.value = ''
|
|
676
|
+
if (this.promptInput) this.promptInput.value = ''
|
|
677
|
+
if (this.btnDelete) this.btnDelete.disabled = true
|
|
678
|
+
if (this.btnWorkbench) this.btnWorkbench.disabled = true
|
|
679
|
+
this.list.render(this.agents, null)
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
async loadAgentIntoForm(id) {
|
|
683
|
+
const agentId = String(id || '').trim()
|
|
684
|
+
if (!agentId) return
|
|
685
|
+
this.mode = 'edit'
|
|
686
|
+
this.editingId = agentId
|
|
687
|
+
if (this.panelTitleEl) this.panelTitleEl.textContent = 'Agent · ' + agentId
|
|
688
|
+
if (this.panelMetaEl) this.panelMetaEl.textContent = '加载中…'
|
|
689
|
+
if (this.btnDelete) {
|
|
690
|
+
this.btnDelete.disabled = agentId === DEFAULT_CONTEXT_AGENT
|
|
691
|
+
}
|
|
692
|
+
if (this.btnWorkbench) this.btnWorkbench.disabled = false
|
|
693
|
+
try {
|
|
694
|
+
const agent = await fetchAgentDetail(agentId, this.contextAgent)
|
|
695
|
+
this.baseConfig =
|
|
696
|
+
agent.config && typeof agent.config === 'object' ? agent.config : null
|
|
697
|
+
if (this.idInput) {
|
|
698
|
+
this.idInput.value = agentId
|
|
699
|
+
this.idInput.readOnly = true
|
|
700
|
+
}
|
|
701
|
+
const whentouse =
|
|
702
|
+
agent.config && typeof agent.config.whentouse === 'string'
|
|
703
|
+
? agent.config.whentouse
|
|
704
|
+
: typeof agent.whentouse === 'string'
|
|
705
|
+
? agent.whentouse
|
|
706
|
+
: ''
|
|
707
|
+
if (this.whenInput) this.whenInput.value = whentouse
|
|
708
|
+
if (this.promptInput) {
|
|
709
|
+
this.promptInput.value =
|
|
710
|
+
typeof agent.prompt === 'string' ? agent.prompt : ''
|
|
711
|
+
}
|
|
712
|
+
if (this.panelMetaEl) {
|
|
713
|
+
this.panelMetaEl.textContent =
|
|
714
|
+
'共 ' +
|
|
715
|
+
String(this.agents.length) +
|
|
716
|
+
' 个 Agent · 上下文:' +
|
|
717
|
+
this.contextAgent
|
|
718
|
+
}
|
|
719
|
+
} catch (e) {
|
|
720
|
+
if (this.panelMetaEl) this.panelMetaEl.textContent = '加载失败'
|
|
721
|
+
this.showToast('加载 Agent 失败: ' + String(e), true)
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
async refreshAgents() {
|
|
726
|
+
this.agents = await fetchAgentsList(this.contextAgent)
|
|
727
|
+
this.list.render(this.agents, this.controller.selectedId)
|
|
728
|
+
if (this.hooks.onAgentsLoaded) this.hooks.onAgentsLoaded(this.agents)
|
|
729
|
+
return this.agents
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
async submitForm() {
|
|
733
|
+
const isEdit = this.mode === 'edit' && !!this.editingId
|
|
734
|
+
const id = isEdit
|
|
735
|
+
? this.editingId
|
|
736
|
+
: this.idInput
|
|
737
|
+
? this.idInput.value.trim()
|
|
738
|
+
: ''
|
|
739
|
+
const whentouse = this.whenInput ? this.whenInput.value : ''
|
|
740
|
+
const prompt = this.promptInput ? this.promptInput.value : ''
|
|
741
|
+
if (!isEdit && !isValidAgentIdInput(id)) {
|
|
742
|
+
this.showToast(
|
|
743
|
+
'Agent ID 仅支持字母、数字、下划线和中划线,长度 1~64',
|
|
744
|
+
true,
|
|
745
|
+
)
|
|
746
|
+
return
|
|
747
|
+
}
|
|
748
|
+
try {
|
|
749
|
+
await saveAgent({
|
|
750
|
+
id,
|
|
751
|
+
whentouse,
|
|
752
|
+
prompt,
|
|
753
|
+
isEdit,
|
|
754
|
+
baseConfig: this.baseConfig,
|
|
755
|
+
contextAgent: this.contextAgent,
|
|
756
|
+
})
|
|
757
|
+
await this.refreshAgents()
|
|
758
|
+
this.mode = 'edit'
|
|
759
|
+
this.editingId = id
|
|
760
|
+
if (this.idInput) {
|
|
761
|
+
this.idInput.value = id
|
|
762
|
+
this.idInput.readOnly = true
|
|
763
|
+
}
|
|
764
|
+
if (this.btnDelete) {
|
|
765
|
+
this.btnDelete.disabled = id === DEFAULT_CONTEXT_AGENT
|
|
766
|
+
}
|
|
767
|
+
if (this.btnWorkbench) this.btnWorkbench.disabled = false
|
|
768
|
+
if (this.panelTitleEl) this.panelTitleEl.textContent = 'Agent · ' + id
|
|
769
|
+
this.controller.selectAgent(id)
|
|
770
|
+
this.syncUrlAgentParam(id)
|
|
771
|
+
this.showToast(isEdit ? '已保存' : '已创建')
|
|
772
|
+
} catch (e) {
|
|
773
|
+
this.showToast((isEdit ? '保存失败: ' : '创建失败: ') + String(e), true)
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
async handleDelete() {
|
|
778
|
+
const id = this.editingId
|
|
779
|
+
if (!id || id === DEFAULT_CONTEXT_AGENT) return
|
|
780
|
+
if (!window.confirm('确定删除 Agent「' + id + '」?此操作不可恢复。')) {
|
|
781
|
+
return
|
|
782
|
+
}
|
|
783
|
+
try {
|
|
784
|
+
await deleteAgent(id, this.contextAgent)
|
|
785
|
+
await this.refreshAgents()
|
|
786
|
+
this.hidePanel()
|
|
787
|
+
this.clearUrlAgentParam()
|
|
788
|
+
this.showToast('已删除')
|
|
789
|
+
} catch (e) {
|
|
790
|
+
this.showToast('删除失败: ' + String(e), true)
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/** 支持通过 ?agent= 深链打开侧栏 */
|
|
795
|
+
async handleUrlAgentParam() {
|
|
796
|
+
let param = ''
|
|
797
|
+
try {
|
|
798
|
+
param = new URLSearchParams(window.location.search).get('agent') || ''
|
|
799
|
+
} catch {
|
|
800
|
+
return
|
|
801
|
+
}
|
|
802
|
+
const id = String(param).trim()
|
|
803
|
+
if (!id) return
|
|
804
|
+
|
|
805
|
+
const exists = this.agents.some((a) => String(a.id) === id)
|
|
806
|
+
if (!exists) {
|
|
807
|
+
this.showToast('agent 不存在,请先创建', true)
|
|
808
|
+
this.clearUrlAgentParam()
|
|
809
|
+
return
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
this.controller.selectAgent(id)
|
|
813
|
+
this.showPanelForAgent(id)
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
syncUrlAgentParam(id) {
|
|
817
|
+
try {
|
|
818
|
+
const u = new URL(window.location.href)
|
|
819
|
+
u.searchParams.set('agent', id)
|
|
820
|
+
window.history.replaceState(null, '', u.pathname + u.search)
|
|
821
|
+
} catch {
|
|
822
|
+
/* ignore */
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
clearUrlAgentParam() {
|
|
827
|
+
try {
|
|
828
|
+
const u = new URL(window.location.href)
|
|
829
|
+
u.searchParams.delete('agent')
|
|
830
|
+
const qs = u.searchParams.toString()
|
|
831
|
+
window.history.replaceState(null, '', u.pathname + (qs ? '?' + qs : ''))
|
|
832
|
+
} catch {
|
|
833
|
+
/* ignore */
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
onSelect(id) {
|
|
838
|
+
if (!id) {
|
|
839
|
+
this.hidePanel()
|
|
840
|
+
this.clearUrlAgentParam()
|
|
841
|
+
return
|
|
842
|
+
}
|
|
843
|
+
this.showPanelForAgent(id)
|
|
844
|
+
this.syncUrlAgentParam(id)
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/** Agent 列表页入口 */
|
|
849
|
+
async function main() {
|
|
850
|
+
const app = document.getElementById('officeApp')
|
|
851
|
+
const listRoot = document.getElementById('agentListRoot')
|
|
852
|
+
if (!app || !listRoot) return
|
|
853
|
+
|
|
854
|
+
const controller = new OfficeController()
|
|
855
|
+
const list = new AgentList(listRoot, (id) => controller.selectAgent(id))
|
|
856
|
+
|
|
857
|
+
const ui = new OfficeUI(app, controller, list, {
|
|
858
|
+
onAgentsLoaded(agents) {
|
|
859
|
+
const subtitle = document.getElementById('officeSubtitle')
|
|
860
|
+
if (subtitle) {
|
|
861
|
+
subtitle.textContent =
|
|
862
|
+
String(agents.length) + ' 个 Agent · 点击列表项管理'
|
|
863
|
+
}
|
|
864
|
+
list.render(agents, controller.selectedId)
|
|
865
|
+
},
|
|
866
|
+
})
|
|
867
|
+
|
|
868
|
+
controller.onSelect = (id) => ui.onSelect(id)
|
|
869
|
+
|
|
870
|
+
try {
|
|
871
|
+
await ui.refreshAgents()
|
|
872
|
+
await ui.handleUrlAgentParam()
|
|
873
|
+
} catch (e) {
|
|
874
|
+
ui.showToast('加载 Agent 失败: ' + String(e), true)
|
|
875
|
+
const subtitle = document.getElementById('officeSubtitle')
|
|
876
|
+
if (subtitle) subtitle.textContent = '加载失败'
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
main().catch((e) => {
|
|
881
|
+
console.error(e)
|
|
882
|
+
})
|
|
883
|
+
})()
|
|
884
|
+
</script>
|
|
306
885
|
</body>
|
|
307
886
|
</html>
|