@auto-ai/agent 2.1.91 → 2.1.92

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 (105) hide show
  1. package/dist/404/index.html +1 -1
  2. package/dist/404.html +1 -1
  3. package/dist/_next/static/{QzTH1dZvjSJ6sqcbYmX8n → IV9dkeTt0V-ZE8jl01i6B}/_buildManifest.js +1 -1
  4. package/dist/_next/static/IV9dkeTt0V-ZE8jl01i6B/_ssgManifest.js +1 -0
  5. package/dist/_next/static/chunks/091dc4a67d911a93.js +1 -0
  6. package/dist/_next/static/chunks/0b5fd45c6d5ed376.js +1 -0
  7. package/dist/_next/static/chunks/0c059f531456fce2.js +1 -0
  8. package/dist/_next/static/chunks/15734e910215c5c7.js +1 -0
  9. package/dist/_next/static/chunks/1f4af280db551c9d.js +1 -0
  10. package/dist/_next/static/chunks/2b6b9fdaaa345603.js +1 -0
  11. package/dist/_next/static/chunks/34b34d02b7d6b4cb.js +1 -0
  12. package/dist/_next/static/chunks/3740042834e8f1fa.js +1 -0
  13. package/dist/_next/static/chunks/3a17a1f5303a1c2c.js +1 -0
  14. package/dist/_next/static/chunks/40268f8e3ff0314e.js +1 -0
  15. package/dist/_next/static/chunks/4247f46093e522c6.js +1 -0
  16. package/dist/_next/static/chunks/4456351ffa1be45f.js +1 -0
  17. package/dist/_next/static/chunks/{2fa3e4168e941aef.js → 52e2164e45febae6.js} +1 -1
  18. package/dist/_next/static/chunks/620e3011cd69dfc9.js +1 -0
  19. package/dist/_next/static/chunks/67c7406790a840c1.js +1 -0
  20. package/dist/_next/static/chunks/6831f547a9403a0f.js +1 -0
  21. package/dist/_next/static/chunks/763710bf823861a8.js +1 -0
  22. package/dist/_next/static/chunks/76a71d344cc15a9f.js +1 -0
  23. package/dist/_next/static/chunks/7988d5ea63356e10.js +1 -0
  24. package/dist/_next/static/chunks/8c0da143ceae2767.js +1 -0
  25. package/dist/_next/static/chunks/8d0a29ce5f05a73d.js +1 -0
  26. package/dist/_next/static/chunks/{e99db8276524ccf5.js → 8dc694eabda7878d.js} +1 -1
  27. package/dist/_next/static/chunks/91adb7bdb9870c6a.js +1 -0
  28. package/dist/_next/static/chunks/ad4ba491cf12423f.js +5 -0
  29. package/dist/_next/static/chunks/c889d3f6eb8ab09e.css +1 -0
  30. package/dist/_next/static/chunks/ce0cac88dd992956.css +4 -0
  31. package/dist/_next/static/chunks/d9726d84bd7d40ff.js +1 -0
  32. package/dist/_next/static/chunks/e4675b3a8b7605e4.js +1 -0
  33. package/dist/_next/static/chunks/ebcd85ff4a1db0dc.js +5 -0
  34. package/dist/_next/static/chunks/{turbopack-8a0e770cd106af0c.js → turbopack-030a42d60560a927.js} +1 -1
  35. package/dist/_next/static/chunks/{turbopack-cd5b40c9e0ee1fe0.js → turbopack-3d84668fefd38b4b.js} +1 -1
  36. package/dist/_next/static/chunks/{turbopack-25a49bf58581b314.js → turbopack-8b41433c9a94981f.js} +1 -1
  37. package/dist/agent-office/accents.js +28 -0
  38. package/dist/agent-office/api.js +142 -0
  39. package/dist/agent-office/list.js +79 -0
  40. package/dist/agent-office/main.js +38 -0
  41. package/dist/agent-office/officeController.js +13 -0
  42. package/dist/agent-office/ui.js +264 -0
  43. package/dist/agent-office.html +307 -0
  44. package/dist/index.html +1 -1
  45. package/dist/index.txt +29 -19
  46. package/dist/manage/about/index.html +2 -0
  47. package/dist/manage/about/index.txt +37 -0
  48. package/dist/manage/add-account/basic/index.html +2 -0
  49. package/dist/manage/add-account/basic/index.txt +39 -0
  50. package/dist/manage/add-account/index.html +2 -1
  51. package/dist/manage/add-account/index.txt +34 -27
  52. package/dist/manage/add-account/prompt/index.html +2 -0
  53. package/dist/manage/add-account/prompt/index.txt +40 -0
  54. package/dist/manage/agent-teams/index.html +2 -2
  55. package/dist/manage/agent-teams/index.txt +34 -26
  56. package/dist/manage/env/index.html +2 -2
  57. package/dist/manage/env/index.txt +34 -26
  58. package/dist/manage/general/index.html +2 -0
  59. package/dist/manage/general/index.txt +37 -0
  60. package/dist/manage/index.html +1 -0
  61. package/dist/manage/index.txt +33 -0
  62. package/dist/manage/mcp/index.html +2 -2
  63. package/dist/manage/mcp/index.txt +34 -26
  64. package/dist/manage/permissions/index.html +2 -0
  65. package/dist/manage/permissions/index.txt +37 -0
  66. package/dist/manage/skills/index.html +2 -2
  67. package/dist/manage/skills/index.txt +34 -26
  68. package/dist/manage/task/index.html +1 -0
  69. package/dist/manage/task/index.txt +38 -0
  70. package/dist/manage/teams/index.html +1 -0
  71. package/dist/manage/teams/index.txt +37 -0
  72. package/dist/manage/tools/index.html +2 -2
  73. package/dist/manage/tools/index.txt +34 -26
  74. package/dist/ws-test.html +516 -27
  75. package/package.json +6 -6
  76. package/dist/_next/static/QzTH1dZvjSJ6sqcbYmX8n/_ssgManifest.js +0 -1
  77. package/dist/_next/static/chunks/01037955b0804f69.js +0 -1
  78. package/dist/_next/static/chunks/071c2b2eece424b8.js +0 -1
  79. package/dist/_next/static/chunks/19d949d5c8e7fc66.js +0 -1
  80. package/dist/_next/static/chunks/39dac725d46ff2cf.js +0 -5
  81. package/dist/_next/static/chunks/3a00f465f3afdd13.js +0 -1
  82. package/dist/_next/static/chunks/43c3e97de0c89c14.js +0 -1
  83. package/dist/_next/static/chunks/479bb32e1848b26b.js +0 -1
  84. package/dist/_next/static/chunks/573efa1cd3d0872c.js +0 -1
  85. package/dist/_next/static/chunks/6a8dfef8eb153262.js +0 -1
  86. package/dist/_next/static/chunks/6ea69f45a19b4f00.js +0 -1
  87. package/dist/_next/static/chunks/75622a4fe3b7b015.js +0 -1
  88. package/dist/_next/static/chunks/80a811d77e9d2ba6.js +0 -1
  89. package/dist/_next/static/chunks/8508beba62ed11df.js +0 -1
  90. package/dist/_next/static/chunks/8915ded29d610342.js +0 -1
  91. package/dist/_next/static/chunks/93e645e175860ad2.js +0 -1
  92. package/dist/_next/static/chunks/9597a4f1aa937100.js +0 -1
  93. package/dist/_next/static/chunks/9923762f97969b52.css +0 -4
  94. package/dist/_next/static/chunks/9c9c063cb0b2e562.js +0 -1
  95. package/dist/_next/static/chunks/a32559d6604a11fb.js +0 -5
  96. package/dist/_next/static/chunks/a6c743f3d7975ca2.css +0 -1
  97. package/dist/_next/static/chunks/ab6655809333a412.js +0 -1
  98. package/dist/_next/static/chunks/acb68dccafc14ac1.js +0 -1
  99. package/dist/_next/static/chunks/b1e8db918a2dcc7c.js +0 -1
  100. package/dist/_next/static/chunks/ca3c520aa0575c69.js +0 -1
  101. package/dist/_next/static/chunks/cdd193032944dfed.js +0 -1
  102. package/dist/_next/static/chunks/d9cb9883957b864c.js +0 -1
  103. package/dist/manage/agent/index.html +0 -2
  104. package/dist/manage/agent/index.txt +0 -32
  105. /package/dist/_next/static/{QzTH1dZvjSJ6sqcbYmX8n → IV9dkeTt0V-ZE8jl01i6B}/_clientMiddlewareManifest.json +0 -0
package/dist/ws-test.html CHANGED
@@ -72,6 +72,10 @@
72
72
  justify-content: center;
73
73
  min-width: 0;
74
74
  }
75
+ .agent-switch-wrap {
76
+ position: relative;
77
+ display: inline-flex;
78
+ }
75
79
  .sidebar-avatar {
76
80
  width: 40px;
77
81
  height: 40px;
@@ -87,7 +91,140 @@
87
91
  line-height: 1;
88
92
  box-shadow: var(--ds-shadow);
89
93
  user-select: none;
90
- cursor: default;
94
+ cursor: pointer;
95
+ padding: 0;
96
+ font-family: inherit;
97
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
98
+ }
99
+ .sidebar-avatar:hover,
100
+ .agent-switch-wrap.open .sidebar-avatar {
101
+ border-color: var(--ds-accent);
102
+ box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.14);
103
+ }
104
+ /* 浮层挂 body,fixed 定位,避免侧栏 overflow:hidden 裁剪 */
105
+ .agent-switch-dropdown {
106
+ display: none;
107
+ position: fixed;
108
+ z-index: 10050;
109
+ min-width: 168px;
110
+ width: max-content;
111
+ max-width: min(260px, calc(100vw - 24px));
112
+ max-height: min(360px, calc(100vh - 24px));
113
+ overflow: hidden;
114
+ background: var(--ds-bg);
115
+ border: 1px solid rgba(0, 0, 0, 0.08);
116
+ border-radius: 14px;
117
+ box-shadow:
118
+ 0 4px 6px rgba(15, 23, 42, 0.05),
119
+ 0 16px 40px rgba(15, 23, 42, 0.14);
120
+ flex-direction: column;
121
+ }
122
+ .agent-switch-dropdown.is-open {
123
+ display: flex;
124
+ }
125
+ .agent-switch-dropdown-head {
126
+ flex-shrink: 0;
127
+ padding: 10px 12px 8px;
128
+ font-size: 12px;
129
+ font-weight: 600;
130
+ color: var(--ds-muted);
131
+ letter-spacing: 0.02em;
132
+ border-bottom: 1px solid var(--ds-border);
133
+ background: #fafafa;
134
+ border-radius: 14px 14px 0 0;
135
+ }
136
+ .agent-switch-dropdown-list {
137
+ overflow-y: auto;
138
+ padding: 6px;
139
+ min-height: 0;
140
+ }
141
+ .agent-switch-item {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: space-between;
145
+ gap: 10px;
146
+ width: 100%;
147
+ text-align: left;
148
+ padding: 8px 10px;
149
+ border: none;
150
+ border-radius: 10px;
151
+ background: transparent;
152
+ color: var(--ds-text);
153
+ font-size: 13px;
154
+ cursor: pointer;
155
+ }
156
+ .agent-switch-item:hover {
157
+ background: var(--ds-item-hover);
158
+ }
159
+ .agent-switch-item.is-current {
160
+ background: var(--ds-item-active);
161
+ color: var(--ds-accent);
162
+ }
163
+ .agent-switch-item-main {
164
+ min-width: 0;
165
+ display: flex;
166
+ flex-direction: column;
167
+ gap: 1px;
168
+ }
169
+ .agent-switch-item-name {
170
+ font-weight: 600;
171
+ line-height: 1.25;
172
+ overflow: hidden;
173
+ text-overflow: ellipsis;
174
+ white-space: nowrap;
175
+ }
176
+ .agent-switch-item-id {
177
+ font-size: 11px;
178
+ color: var(--ds-muted);
179
+ line-height: 1.2;
180
+ overflow: hidden;
181
+ text-overflow: ellipsis;
182
+ white-space: nowrap;
183
+ }
184
+ .agent-switch-item.is-current .agent-switch-item-id {
185
+ color: var(--ds-accent);
186
+ opacity: 0.85;
187
+ }
188
+ .agent-switch-item-check {
189
+ flex-shrink: 0;
190
+ width: 16px;
191
+ height: 16px;
192
+ color: var(--ds-accent);
193
+ opacity: 0;
194
+ }
195
+ .agent-switch-item.is-current .agent-switch-item-check {
196
+ opacity: 1;
197
+ }
198
+ .agent-switch-loading,
199
+ .agent-switch-empty {
200
+ padding: 14px 12px;
201
+ font-size: 13px;
202
+ color: var(--ds-muted);
203
+ }
204
+ .agent-switch-dropdown-foot {
205
+ flex-shrink: 0;
206
+ border-top: 1px solid var(--ds-border);
207
+ padding: 6px;
208
+ background: #fafafa;
209
+ border-radius: 0 0 14px 14px;
210
+ }
211
+ .agent-switch-manage-btn {
212
+ display: flex;
213
+ width: 100%;
214
+ align-items: center;
215
+ justify-content: center;
216
+ gap: 6px;
217
+ border: none;
218
+ border-radius: 10px;
219
+ background: transparent;
220
+ color: var(--ds-accent);
221
+ font-size: 13px;
222
+ font-weight: 600;
223
+ padding: 8px 10px;
224
+ cursor: pointer;
225
+ }
226
+ .agent-switch-manage-btn:hover {
227
+ background: var(--ds-item-hover);
91
228
  }
92
229
  .sidebar-brand-ws {
93
230
  margin-top: 0.45rem;
@@ -2348,16 +2485,34 @@
2348
2485
  <aside class="sidebar">
2349
2486
  <div class="sidebar-brand">
2350
2487
  <div class="sidebar-brand-title-row">
2351
- <div
2352
- class="sidebar-avatar"
2353
- id="brandAgentName"
2354
- title="agent: qihoo"
2355
- aria-label="agent: qihoo"
2356
- >Q</div>
2488
+ <div class="agent-switch-wrap" id="agentSwitchWrap">
2489
+ <button
2490
+ type="button"
2491
+ class="sidebar-avatar"
2492
+ id="brandAgentName"
2493
+ title="agent: qihoo"
2494
+ aria-label="agent: qihoo"
2495
+ aria-haspopup="listbox"
2496
+ aria-expanded="false"
2497
+ >Q</button>
2498
+ </div>
2357
2499
  </div>
2358
2500
  </div>
2359
2501
 
2360
2502
  <div class="sidebar-drawers sidebar-icon-rail" aria-label="左侧管理导航">
2503
+ <button
2504
+ type="button"
2505
+ class="sidebar-nav-item"
2506
+ id="btnManageAgents"
2507
+ title="返回办公室"
2508
+ aria-label="返回办公室"
2509
+ >
2510
+ <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
2511
+ <rect x="4" y="4" width="16" height="16" rx="4"/>
2512
+ <circle cx="12" cy="10" r="2.6"/>
2513
+ <path d="M7.5 17.5c.8-2.2 2.4-3.5 4.5-3.5s3.7 1.3 4.5 3.5"/>
2514
+ </svg>
2515
+ </button>
2361
2516
  <button
2362
2517
  type="button"
2363
2518
  class="sidebar-nav-item"
@@ -2963,11 +3118,33 @@
2963
3118
  </div>
2964
3119
  </div>
2965
3120
 
3121
+ </div>
3122
+
2966
3123
  <div id="sidebarHoverTip" class="sidebar-hover-tip" role="tooltip" hidden></div>
3124
+ <div
3125
+ class="agent-switch-dropdown"
3126
+ id="agentSwitchDropdown"
3127
+ role="listbox"
3128
+ aria-label="切换 agent"
3129
+ hidden
3130
+ ></div>
2967
3131
 
2968
3132
  <script src="https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js"></script>
2969
3133
  <script>
2970
3134
  (function () {
3135
+ /** ws-test 必须有合法 ?agent= 参数,否则回到办公室首页 */
3136
+ ;(function wsTestRequireAgentParam() {
3137
+ try {
3138
+ const ag = new URLSearchParams(window.location.search).get('agent')
3139
+ const id = ag ? String(ag).trim() : ''
3140
+ if (!id || !/^[a-zA-Z0-9_-]{1,64}$/.test(id)) {
3141
+ location.replace('/')
3142
+ }
3143
+ } catch {
3144
+ location.replace('/')
3145
+ }
3146
+ })()
3147
+
2971
3148
  const $ = (id) => document.getElementById(id)
2972
3149
  const logEl = $('log')
2973
3150
  const chatThreadEl = $('chatThread')
@@ -3071,6 +3248,8 @@
3071
3248
  const scheduleCronRow = $('scheduleCronRow')
3072
3249
  const btnScheduleCreateCancel = $('btnScheduleCreateCancel')
3073
3250
  const btnScheduleCreateSubmit = $('btnScheduleCreateSubmit')
3251
+ const btnManageAgents = $('btnManageAgents')
3252
+ const DEFAULT_AGENT_ID = 'qihoo'
3074
3253
  const mcpPackageMeta = $('mcpPackageMeta')
3075
3254
  const mcpPackageList = $('mcpPackageList')
3076
3255
  const btnMcpPackageModalClose = $('btnMcpPackageModalClose')
@@ -3085,6 +3264,9 @@
3085
3264
  const mainTitleEl = $('mainTitle')
3086
3265
  const mainSubEl = $('mainSub')
3087
3266
  const brandAgentNameEl = $('brandAgentName')
3267
+ const agentSwitchWrapEl = $('agentSwitchWrap')
3268
+ const agentSwitchDropdownEl = $('agentSwitchDropdown')
3269
+ let agentSwitchOpen = false
3088
3270
  const sidebarHoverTipEl = $('sidebarHoverTip')
3089
3271
  const sidebarAsideEl = document.querySelector('aside.sidebar')
3090
3272
  let sidebarHoverTipHideTimer = null
@@ -3140,7 +3322,7 @@
3140
3322
  }
3141
3323
  function wireSidebarHoverTips() {
3142
3324
  if (!sidebarAsideEl || !sidebarHoverTipEl) return
3143
- const nodes = sidebarAsideEl.querySelectorAll('#brandAgentName, .sidebar-nav-item')
3325
+ const nodes = sidebarAsideEl.querySelectorAll('#brandAgentName, #btnManageAgents, .sidebar-nav-item')
3144
3326
  for (let i = 0; i < nodes.length; i++) {
3145
3327
  const el = nodes[i]
3146
3328
  el.addEventListener('pointerenter', function () {
@@ -3238,7 +3420,7 @@
3238
3420
  let refreshSkillPickerRows = null
3239
3421
  let remoteMcpServers = []
3240
3422
  const WS_PERMISSION_MODE_KEY = 'WS_PERMISSION_MODE'
3241
- const ANTHROPIC_MODEL_KEY = 'ANTHROPIC_MODEL'
3423
+ const LLM_MODEL_KEY = 'LLM_MODEL'
3242
3424
  const WS_PERMISSION_MODE_ALLOWED = new Set([
3243
3425
  'acceptEdits',
3244
3426
  'plan',
@@ -3254,17 +3436,71 @@
3254
3436
  return typeof envObj[key] === 'string' ? envObj[key].trim() : ''
3255
3437
  }
3256
3438
 
3439
+ /** 项目根 .env 中的 LLM 默认值(agent.json 未配置时用于新 session 展示) */
3440
+ let projectEnvDefaults = { LLM_MODEL: '' }
3441
+
3442
+ function parseDotEnvValue(content, key) {
3443
+ if (!content || typeof content !== 'string' || !key) return ''
3444
+ const lines = content.split('\n')
3445
+ for (let i = 0; i < lines.length; i++) {
3446
+ const trimmed = lines[i].trim()
3447
+ if (!trimmed || trimmed.charAt(0) === '#') continue
3448
+ const eq = trimmed.indexOf('=')
3449
+ if (eq <= 0) continue
3450
+ if (trimmed.slice(0, eq).trim() !== key) continue
3451
+ let value = trimmed.slice(eq + 1).trim()
3452
+ if (
3453
+ (value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') ||
3454
+ (value.charAt(0) === "'" && value.charAt(value.length - 1) === "'")
3455
+ ) {
3456
+ value = value.slice(1, -1)
3457
+ }
3458
+ return value
3459
+ }
3460
+ return ''
3461
+ }
3462
+
3463
+ function buildSystemEnvApiUrl() {
3464
+ const u = new URL('/api/system/env', httpOriginForApi() + '/')
3465
+ u.searchParams.set('agent', currentAgentParam())
3466
+ return u.toString()
3467
+ }
3468
+
3469
+ async function loadProjectEnvDefaults() {
3470
+ try {
3471
+ const r = await fetch(buildSystemEnvApiUrl())
3472
+ if (!r.ok) return
3473
+ const body = await r.json().catch(function () {
3474
+ return {}
3475
+ })
3476
+ const content = typeof body.content === 'string' ? body.content : ''
3477
+ projectEnvDefaults = {
3478
+ LLM_MODEL: parseDotEnvValue(content, LLM_MODEL_KEY),
3479
+ }
3480
+ } catch {
3481
+ /* 项目 .env 不可读时不阻塞 composer */
3482
+ }
3483
+ }
3484
+
3485
+ /** 新 session 默认模型:agent.json.env → agent.json.model → 项目 .env */
3486
+ function readDefaultLlmModel() {
3487
+ const fromAgentEnv = readAgentEnvString(LLM_MODEL_KEY)
3488
+ if (fromAgentEnv) return fromAgentEnv
3489
+ const fromAgentModel =
3490
+ typeof agentConfigState.model === 'string' ? agentConfigState.model.trim() : ''
3491
+ if (fromAgentModel) return fromAgentModel
3492
+ return projectEnvDefaults.LLM_MODEL || ''
3493
+ }
3494
+
3257
3495
  /**
3258
3496
  * 业务语义:三个会话级配置的初始化顺序必须稳定:
3259
- * 1) 先读取环境变量(agent.json.env);
3260
- * 2) 若未配置,再回退到产品默认值(自动/空/默认);
3497
+ * 1) 先读取 agent.json.env / agent.json.model;
3498
+ * 2) 再回退到项目 .env 的 LLM_MODEL;
3261
3499
  * 3) 将结果投影为 sessionOverrideState,保证 UI 与后端 PATCH 入参一致。
3262
3500
  */
3263
3501
  function buildDefaultSessionOverrideState() {
3264
- const model = readAgentEnvString(ANTHROPIC_MODEL_KEY)
3265
- // 新 session 产品默认权限模式为 default,不继承 agent.json 中的 plan
3266
3502
  return {
3267
- model: model,
3503
+ model: readDefaultLlmModel(),
3268
3504
  env: {
3269
3505
  [WS_PERMISSION_MODE_KEY]: 'default',
3270
3506
  },
@@ -4175,11 +4411,195 @@
4175
4411
  typeof name === 'string' && name.trim() ? name.trim() : currentAgentParam()
4176
4412
  const initial = id.charAt(0).toUpperCase() || 'A'
4177
4413
  brandAgentNameEl.textContent = initial
4178
- const tip = 'agent: ' + id
4414
+ const tip = 'agent: ' + id + '(点击切换)'
4179
4415
  brandAgentNameEl.setAttribute('title', tip)
4180
4416
  brandAgentNameEl.setAttribute('aria-label', tip)
4181
4417
  }
4182
4418
 
4419
+ /** 构建 agent 列表 API 地址,用于侧栏头像切换 workspace agent */
4420
+ function buildAgentsListUrl() {
4421
+ const u = new URL('/api/agents', httpOriginForApi() + '/')
4422
+ u.searchParams.set('agent', currentAgentParam())
4423
+ return u.toString()
4424
+ }
4425
+
4426
+ /** 构建单个 agent 的 REST 地址,用于详情/修改/删除 */
4427
+ function buildAgentItemUrl(id) {
4428
+ const u = new URL(
4429
+ '/api/agents/' + encodeURIComponent(String(id || '').trim()),
4430
+ httpOriginForApi() + '/'
4431
+ )
4432
+ u.searchParams.set('agent', currentAgentParam())
4433
+ return u.toString()
4434
+ }
4435
+
4436
+ /** 关闭 agent 切换下拉,恢复头像按钮状态 */
4437
+ function closeAgentSwitchMenu() {
4438
+ agentSwitchOpen = false
4439
+ if (agentSwitchWrapEl) agentSwitchWrapEl.classList.remove('open')
4440
+ if (agentSwitchDropdownEl) {
4441
+ agentSwitchDropdownEl.classList.remove('is-open')
4442
+ agentSwitchDropdownEl.hidden = true
4443
+ agentSwitchDropdownEl.style.left = ''
4444
+ agentSwitchDropdownEl.style.top = ''
4445
+ }
4446
+ if (brandAgentNameEl) brandAgentNameEl.setAttribute('aria-expanded', 'false')
4447
+ }
4448
+
4449
+ /** 根据头像位置计算浮层坐标,显示在侧栏右侧避免被 overflow 裁剪 */
4450
+ function positionAgentSwitchDropdown() {
4451
+ if (!brandAgentNameEl || !agentSwitchDropdownEl || !agentSwitchOpen) return
4452
+ requestAnimationFrame(function () {
4453
+ if (!agentSwitchOpen || !brandAgentNameEl || !agentSwitchDropdownEl) return
4454
+ const rect = brandAgentNameEl.getBoundingClientRect()
4455
+ const gap = 10
4456
+ const menuW = agentSwitchDropdownEl.offsetWidth
4457
+ const menuH = agentSwitchDropdownEl.offsetHeight
4458
+ let left = rect.right + gap
4459
+ let top = rect.top
4460
+ if (left + menuW > window.innerWidth - 12) {
4461
+ left = rect.left
4462
+ top = rect.bottom + gap
4463
+ }
4464
+ left = Math.max(12, Math.min(left, window.innerWidth - menuW - 12))
4465
+ top = Math.max(12, Math.min(top, window.innerHeight - menuH - 12))
4466
+ agentSwitchDropdownEl.style.left = left + 'px'
4467
+ agentSwitchDropdownEl.style.top = top + 'px'
4468
+ })
4469
+ }
4470
+
4471
+ /** 在 agent 切换下拉底部追加「管理 Agent」入口 */
4472
+ function appendAgentSwitchManageFooter() {
4473
+ if (!agentSwitchDropdownEl) return
4474
+ const foot = document.createElement('div')
4475
+ foot.className = 'agent-switch-dropdown-foot'
4476
+ const manageBtn = document.createElement('button')
4477
+ manageBtn.type = 'button'
4478
+ manageBtn.className = 'agent-switch-manage-btn'
4479
+ manageBtn.textContent = '管理 Agent…'
4480
+ manageBtn.addEventListener('click', function (ev) {
4481
+ ev.preventDefault()
4482
+ ev.stopPropagation()
4483
+ closeAgentSwitchMenu()
4484
+ const cur = currentAgentParam()
4485
+ window.location.href = cur ? '/?agent=' + encodeURIComponent(cur) : '/'
4486
+ })
4487
+ foot.appendChild(manageBtn)
4488
+ agentSwitchDropdownEl.appendChild(foot)
4489
+ }
4490
+
4491
+ /** 渲染 agent 列表项;当前 agent 高亮,点击后立即切换 workspace */
4492
+ function renderAgentSwitchList(agents) {
4493
+ if (!agentSwitchDropdownEl) return
4494
+ agentSwitchDropdownEl.innerHTML = ''
4495
+ const current = currentAgentParam()
4496
+ const head = document.createElement('div')
4497
+ head.className = 'agent-switch-dropdown-head'
4498
+ head.textContent = '切换 Agent'
4499
+ agentSwitchDropdownEl.appendChild(head)
4500
+ if (!Array.isArray(agents) || !agents.length) {
4501
+ const empty = document.createElement('div')
4502
+ empty.className = 'agent-switch-empty'
4503
+ empty.textContent = '暂无 agent'
4504
+ agentSwitchDropdownEl.appendChild(empty)
4505
+ appendAgentSwitchManageFooter()
4506
+ positionAgentSwitchDropdown()
4507
+ return
4508
+ }
4509
+ const list = document.createElement('div')
4510
+ list.className = 'agent-switch-dropdown-list'
4511
+ const frag = document.createDocumentFragment()
4512
+ for (let i = 0; i < agents.length; i++) {
4513
+ const row = agents[i]
4514
+ const id = String(row && row.id != null ? row.id : '').trim()
4515
+ if (!id) continue
4516
+ const displayName =
4517
+ row && typeof row.displayName === 'string' && row.displayName.trim()
4518
+ ? row.displayName.trim()
4519
+ : id
4520
+ const btn = document.createElement('button')
4521
+ btn.type = 'button'
4522
+ btn.className = 'agent-switch-item' + (id === current ? ' is-current' : '')
4523
+ btn.setAttribute('role', 'option')
4524
+ btn.setAttribute('aria-selected', id === current ? 'true' : 'false')
4525
+ const mainEl = document.createElement('span')
4526
+ mainEl.className = 'agent-switch-item-main'
4527
+ const nameEl = document.createElement('span')
4528
+ nameEl.className = 'agent-switch-item-name'
4529
+ nameEl.textContent = displayName
4530
+ mainEl.appendChild(nameEl)
4531
+ if (displayName !== id) {
4532
+ const idEl = document.createElement('span')
4533
+ idEl.className = 'agent-switch-item-id'
4534
+ idEl.textContent = id
4535
+ mainEl.appendChild(idEl)
4536
+ }
4537
+ btn.appendChild(mainEl)
4538
+ const checkEl = document.createElement('span')
4539
+ checkEl.className = 'agent-switch-item-check'
4540
+ checkEl.setAttribute('aria-hidden', 'true')
4541
+ checkEl.innerHTML =
4542
+ '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 8.2 6.6 11.3 12.5 4.8"/></svg>'
4543
+ btn.appendChild(checkEl)
4544
+ btn.addEventListener('click', function (ev) {
4545
+ ev.preventDefault()
4546
+ ev.stopPropagation()
4547
+ selectWorkspaceAgent(id)
4548
+ })
4549
+ frag.appendChild(btn)
4550
+ }
4551
+ list.appendChild(frag)
4552
+ agentSwitchDropdownEl.appendChild(list)
4553
+ appendAgentSwitchManageFooter()
4554
+ positionAgentSwitchDropdown()
4555
+ }
4556
+
4557
+ /** 选中目标 agent:复用 onAgentChanged 完成 WS 切换、会话刷新与配置重载 */
4558
+ function selectWorkspaceAgent(nextId) {
4559
+ const id = String(nextId || '').trim()
4560
+ if (!id || !agentIdInput) return
4561
+ closeAgentSwitchMenu()
4562
+ if (id === currentAgentParam()) return
4563
+ agentIdInput.value = id
4564
+ onAgentChanged()
4565
+ }
4566
+
4567
+ /** 打开 agent 切换下拉,按需拉取 /api/agents 列表 */
4568
+ async function openAgentSwitchMenu() {
4569
+ if (!agentSwitchWrapEl || !agentSwitchDropdownEl || !brandAgentNameEl) return
4570
+ hideSidebarHoverTip()
4571
+ agentSwitchOpen = true
4572
+ agentSwitchWrapEl.classList.add('open')
4573
+ agentSwitchDropdownEl.hidden = false
4574
+ agentSwitchDropdownEl.classList.add('is-open')
4575
+ brandAgentNameEl.setAttribute('aria-expanded', 'true')
4576
+ agentSwitchDropdownEl.innerHTML = '<div class="agent-switch-loading">加载中…</div>'
4577
+ positionAgentSwitchDropdown()
4578
+ try {
4579
+ const r = await fetch(buildAgentsListUrl())
4580
+ const body = await r.json().catch(function () {
4581
+ return {}
4582
+ })
4583
+ if (!r.ok) {
4584
+ throw new Error(body.message || body.error || r.statusText)
4585
+ }
4586
+ renderAgentSwitchList(body.agents)
4587
+ } catch (e) {
4588
+ agentSwitchDropdownEl.innerHTML =
4589
+ '<div class="agent-switch-empty">加载失败: ' + escapeHtml(String(e)) + '</div>'
4590
+ positionAgentSwitchDropdown()
4591
+ }
4592
+ }
4593
+
4594
+ /** 点击头像时切换下拉开关 */
4595
+ async function toggleAgentSwitchMenu() {
4596
+ if (agentSwitchOpen) {
4597
+ closeAgentSwitchMenu()
4598
+ return
4599
+ }
4600
+ await openAgentSwitchMenu()
4601
+ }
4602
+
4183
4603
  function rewriteSameOriginNavLinks() {
4184
4604
  const agent = currentAgentParam()
4185
4605
  const origin = window.location.origin
@@ -5342,10 +5762,6 @@
5342
5762
 
5343
5763
  async function deleteSessionById(sessionId) {
5344
5764
  if (!sessionId) return
5345
- const ok = window.confirm(
5346
- '确定删除该会话?将删除磁盘上的 transcript 与相关目录,不可恢复。\n\n' + sessionId,
5347
- )
5348
- if (!ok) return
5349
5765
  const delUrl = buildSessionDeleteUrl(sessionId)
5350
5766
  try {
5351
5767
  const r = await fetch(delUrl, { method: 'DELETE' })
@@ -5438,12 +5854,23 @@
5438
5854
  const nextSid = typeof id === 'string' ? id : ''
5439
5855
  sessionIdInput.value = nextSid
5440
5856
  void loadPendingPrompts()
5857
+ if (nextSid) {
5858
+ void loadSessionOverridesIntoComposer()
5859
+ } else {
5860
+ void loadProjectEnvDefaults().then(function () {
5861
+ resetSessionOverrideStateToDefault()
5862
+ })
5863
+ }
5441
5864
  // 优先走「单 WS、多子进程」路径:复用当前连接,仅让后端 kill+respawn 子进程
5442
5865
  if (socket && socket.readyState === WebSocket.OPEN) {
5443
5866
  serverReady = false
5444
5867
  resetChatUi()
5445
5868
  pendingSessionOverrides = null
5446
- resetSessionOverrideStateToDefault()
5869
+ if (nextSid) {
5870
+ /* 已在上方拉取 overrides;切换中勿清空 composer 模型 */
5871
+ } else {
5872
+ resetSessionOverrideStateToDefault()
5873
+ }
5447
5874
  if (window.__lastSessions) renderSessionList(window.__lastSessions)
5448
5875
  else updateMainHeader()
5449
5876
  const payload = {
@@ -5468,7 +5895,9 @@
5468
5895
  disconnectIfOpen()
5469
5896
  if (window.__lastSessions) renderSessionList(window.__lastSessions)
5470
5897
  else updateMainHeader()
5471
- resetSessionOverrideStateToDefault()
5898
+ if (!nextSid) {
5899
+ resetSessionOverrideStateToDefault()
5900
+ }
5472
5901
  connectWebSocket()
5473
5902
  }
5474
5903
 
@@ -5869,7 +6298,7 @@
5869
6298
  const model = typeof sessionOverrideState.model === 'string'
5870
6299
  ? sessionOverrideState.model.trim()
5871
6300
  : ''
5872
- env[ANTHROPIC_MODEL_KEY] = model
6301
+ env[LLM_MODEL_KEY] = model
5873
6302
  }
5874
6303
 
5875
6304
  function normalizePermissionMode(value) {
@@ -6027,8 +6456,8 @@
6027
6456
  : {}
6028
6457
  sessionOverrideState = {
6029
6458
  model:
6030
- typeof ovEnv[ANTHROPIC_MODEL_KEY] === 'string'
6031
- ? String(ovEnv[ANTHROPIC_MODEL_KEY]).trim()
6459
+ typeof ovEnv[LLM_MODEL_KEY] === 'string'
6460
+ ? String(ovEnv[LLM_MODEL_KEY]).trim()
6032
6461
  : defaults.model,
6033
6462
  env: {
6034
6463
  [WS_PERMISSION_MODE_KEY]:
@@ -6047,7 +6476,7 @@
6047
6476
  const env = getSessionOverrideEnv()
6048
6477
  const patchEnv = {}
6049
6478
  const defaults = buildDefaultSessionOverrideState()
6050
- patchEnv[ANTHROPIC_MODEL_KEY] =
6479
+ patchEnv[LLM_MODEL_KEY] =
6051
6480
  typeof sessionOverrideState.model === 'string'
6052
6481
  ? sessionOverrideState.model.trim()
6053
6482
  : defaults.model
@@ -6244,7 +6673,13 @@
6244
6673
  }
6245
6674
  renderBindChips()
6246
6675
  syncModelInputFromState()
6247
- void loadSessionOverridesIntoComposer()
6676
+ void loadProjectEnvDefaults().then(function () {
6677
+ if (!sessionIdInput || !sessionIdInput.value.trim()) {
6678
+ resetSessionOverrideStateToDefault()
6679
+ } else {
6680
+ void loadSessionOverridesIntoComposer()
6681
+ }
6682
+ })
6248
6683
  logLine('agent-config', 'load failed ' + (body.message || r.status))
6249
6684
  return
6250
6685
  }
@@ -6288,7 +6723,13 @@
6288
6723
  }
6289
6724
  renderBindChips()
6290
6725
  syncModelInputFromState()
6291
- void loadSessionOverridesIntoComposer()
6726
+ void loadProjectEnvDefaults().then(function () {
6727
+ if (!sessionIdInput || !sessionIdInput.value.trim()) {
6728
+ resetSessionOverrideStateToDefault()
6729
+ } else {
6730
+ void loadSessionOverridesIntoComposer()
6731
+ }
6732
+ })
6292
6733
  } catch (e) {
6293
6734
  logLine('agent-config', String(e))
6294
6735
  }
@@ -7739,6 +8180,15 @@
7739
8180
  })
7740
8181
  })
7741
8182
 
8183
+ if (btnManageAgents) {
8184
+ btnManageAgents.addEventListener('click', function (ev) {
8185
+ ev.preventDefault()
8186
+ ev.stopPropagation()
8187
+ const cur = currentAgentParam()
8188
+ window.location.href = cur ? '/?agent=' + encodeURIComponent(cur) : '/'
8189
+ })
8190
+ }
8191
+
7742
8192
  function closeAgentMdModal() {
7743
8193
  if (!agentMdModal) return
7744
8194
  agentMdModal.classList.remove('is-open')
@@ -8587,6 +9037,10 @@
8587
9037
  }
8588
9038
  document.addEventListener('keydown', function (ev) {
8589
9039
  if (ev.key !== 'Escape') return
9040
+ if (agentSwitchOpen) {
9041
+ closeAgentSwitchMenu()
9042
+ return
9043
+ }
8590
9044
  if (agentPickerModal && agentPickerModal.classList.contains('is-open')) {
8591
9045
  closeAgentPickerModal()
8592
9046
  return
@@ -8607,6 +9061,10 @@
8607
9061
  closeAgentEnvModal()
8608
9062
  return
8609
9063
  }
9064
+ if (scheduleManageModal && scheduleManageModal.classList.contains('is-open')) {
9065
+ closeScheduleManageModal()
9066
+ return
9067
+ }
8610
9068
  if (toolFilesModal && toolFilesModal.classList.contains('is-open')) {
8611
9069
  closeToolFilesModal()
8612
9070
  return
@@ -8657,6 +9115,37 @@
8657
9115
  rewriteSameOriginNavLinks()
8658
9116
  })
8659
9117
  }
9118
+ if (brandAgentNameEl) {
9119
+ brandAgentNameEl.addEventListener('click', function (ev) {
9120
+ ev.preventDefault()
9121
+ ev.stopPropagation()
9122
+ void toggleAgentSwitchMenu()
9123
+ })
9124
+ }
9125
+ if (agentSwitchDropdownEl) {
9126
+ agentSwitchDropdownEl.addEventListener('click', function (ev) {
9127
+ ev.stopPropagation()
9128
+ })
9129
+ }
9130
+ document.addEventListener('click', function (ev) {
9131
+ if (!agentSwitchOpen) return
9132
+ const t = ev.target
9133
+ if (t instanceof Node) {
9134
+ if (agentSwitchWrapEl && agentSwitchWrapEl.contains(t)) return
9135
+ if (agentSwitchDropdownEl && agentSwitchDropdownEl.contains(t)) return
9136
+ }
9137
+ closeAgentSwitchMenu()
9138
+ })
9139
+ window.addEventListener('resize', function () {
9140
+ if (agentSwitchOpen) positionAgentSwitchDropdown()
9141
+ })
9142
+ window.addEventListener(
9143
+ 'scroll',
9144
+ function () {
9145
+ if (agentSwitchOpen) positionAgentSwitchDropdown()
9146
+ },
9147
+ true
9148
+ )
8660
9149
 
8661
9150
  updateBrandAgent()
8662
9151
  rewriteSameOriginNavLinks()