zen-gitsync 2.18.8 → 2.18.10
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/README.md +2 -2
- package/package.json +2 -1
- package/src/cli/ai/agent.js +7 -0
- package/src/cli/ai/runtime.test.js +22 -1
- package/src/cli/ai/tools.js +153 -2
- package/src/cli/ai/tools.test.js +71 -2
- package/src/cli/ai/transport.js +8 -3
- package/src/config.js +7 -5
- package/src/mcp/tools/workbench.js +1 -1
- package/src/ui/public/assets/{AgentView-DZx3n-So.css → AgentView-BnEgu3NT.css} +1 -1
- package/src/ui/public/assets/AgentView-DQQe_ivW.js +1 -0
- package/src/ui/public/assets/{AppVersionBadge-Bg5lrtKb.js → AppVersionBadge-D7PiBP0p.js} +2 -2
- package/src/ui/public/assets/{BranchSelector-CxjTqAkl.js → BranchSelector-BzHoMBOc.js} +1 -1
- package/src/ui/public/assets/{CommitForm-BWWrOvj5.js → CommitForm-CNTjLYTR.js} +2 -2
- package/src/ui/public/assets/{CommonDialog-x5jfL4Lq.js → CommonDialog-j_53ORvj.js} +1 -1
- package/src/ui/public/assets/CopySessionButton-Dy5t8Mjy.js +20 -0
- package/src/ui/public/assets/EditorView-CwcdA0Ei.js +1 -0
- package/src/ui/public/assets/{EditorView-BUiVsBv7.css → EditorView-Ims2BUK_.css} +1 -1
- package/src/ui/public/assets/{FlowExecutionViewer-BkZ20jxN.js → FlowExecutionViewer-CQ-TPhwF.js} +1 -1
- package/src/ui/public/assets/{FlowOrchestrationWorkspace-aZBYu29g.js → FlowOrchestrationWorkspace-CJHpEBCw.js} +1 -1
- package/src/ui/public/assets/{LogList-CSIbmUMK.js → LogList-KUePBjAt.js} +4 -4
- package/src/ui/public/assets/{MindmapView-JYLp185X.js → MindmapView-CwdvsuEK.js} +1 -1
- package/src/ui/public/assets/{MonitorView-BS2Mh-I7.js → MonitorView-CjEnnrTL.js} +1 -1
- package/src/ui/public/assets/{ProjectStartupButton-DAEP6ZU5.js → ProjectStartupButton-B36lRb6-.js} +1 -1
- package/src/ui/public/assets/RecentDirectoriesChat-7fzSkSmc.css +1 -0
- package/src/ui/public/assets/RecentDirectoriesChat-DNiji9Pr.js +1 -0
- package/src/ui/public/assets/{RemoteManagerDialog-aaNmsKpy.js → RemoteManagerDialog-Dj_GpA-c.js} +1 -1
- package/src/ui/public/assets/{RemoteRepoCard-DndI8rNZ.js → RemoteRepoCard-C8u9M6dn.js} +1 -1
- package/src/ui/public/assets/{SourceMapView-BTD9-R8t.js → SourceMapView-eng0B9U2.js} +1 -1
- package/src/ui/public/assets/{SvgIcon-0n6uuKFm.js → SvgIcon-5AlG3IfR.js} +1 -1
- package/src/ui/public/assets/{UserInputNode-B-mDg9Wy.js → UserInputNode-BKP869D6.js} +1 -1
- package/src/ui/public/assets/WorkbenchView-CZO18THH.js +6 -0
- package/src/ui/public/assets/WorkbenchView-DogERhHQ.css +1 -0
- package/src/ui/public/assets/{_plugin-vue_export-helper-C3o7kvRL.js → _plugin-vue_export-helper-Csn085FF.js} +4 -4
- package/src/ui/public/assets/agentConversations-De3wKTsN.js +10 -0
- package/src/ui/public/assets/configStore-DOaPZ6Mq.js +1 -0
- package/src/ui/public/assets/index-DQ82h1aq.js +57 -0
- package/src/ui/public/assets/index-NYzaTfbS.css +1 -0
- package/src/ui/public/assets/{useOrchestrator-CS9sn7nV.js → useOrchestrator-BjC7oHpt.js} +1 -1
- package/src/ui/public/index.html +6 -6
- package/src/ui/server/index.js +8 -0
- package/src/ui/server/routes/fileOpen.js +57 -1
- package/src/ui/server/routes/fileOpen.test.js +1 -1
- package/src/ui/server/routes/git/clone.js +5 -13
- package/src/ui/server/routes/workbench/agentChat.js +75 -10
- package/src/ui/server/routes/workbench/agentChatExtensions.test.js +290 -0
- package/src/ui/server/routes/workbench/agentEngines.js +8 -4
- package/src/ui/server/routes/workbench/agentExtensions.js +157 -0
- package/src/ui/server/routes/workbench/agentMarketplace.js +12 -0
- package/src/ui/server/routes/workbench/agentParity.test.js +16 -0
- package/src/ui/server/routes/workbench/agentRoutes.js +99 -7
- package/src/ui/server/routes/workbench/agentRoutes.test.js +141 -1
- package/src/ui/server/routes/workbench/executorModels.js +30 -5
- package/src/ui/server/routes/workbench/executorModels.test.js +16 -4
- package/src/ui/server/routes/workbench/index.js +17 -5
- package/src/ui/server/routes/workbench/jobActivity.js +3 -3
- package/src/ui/server/routes/workbench/jobActivity.test.js +1 -0
- package/src/ui/server/routes/workbench/runExternalTurn.js +22 -25
- package/src/ui/server/routes/workbench/runExternalTurn.test.js +34 -0
- package/src/ui/server/routes/workbench/scheduler.js +3 -0
- package/src/ui/server/routes/workbench/taskRunner.codebuddy.test.js +275 -0
- package/src/ui/server/routes/workbench/taskRunner.js +311 -24
- package/src/ui/server/routes/workbench/taskRunner.opencode.test.js +2 -1
- package/src/utils/gitRepoName.js +33 -0
- package/src/ui/public/assets/AgentView-BRAUZCtA.js +0 -1
- package/src/ui/public/assets/CopySessionButton-D0wFpk8a.js +0 -20
- package/src/ui/public/assets/EditorView-DmaGiI-z.js +0 -1
- package/src/ui/public/assets/RecentDirectoriesChat-B19uAf8k.css +0 -1
- package/src/ui/public/assets/RecentDirectoriesChat-CVFTShrU.js +0 -1
- package/src/ui/public/assets/WorkbenchView-CfSrCIbp.js +0 -8
- package/src/ui/public/assets/WorkbenchView-D6NRqZ5W.css +0 -1
- package/src/ui/public/assets/agentConversations-DpiGplZB.js +0 -8
- package/src/ui/public/assets/configStore-BdL3uW2E.js +0 -1
- package/src/ui/public/assets/index-BS7BDFG4.js +0 -57
- package/src/ui/public/assets/index-DwJWiCiN.css +0 -1
package/README.md
CHANGED
|
@@ -436,7 +436,7 @@ A dedicated view (robot icon in the activity bar) for chatting with the built-in
|
|
|
436
436
|
|
|
437
437
|
| Feature | Description |
|
|
438
438
|
|---|---|
|
|
439
|
-
| Session list | Browse, search, rename, and delete past conversations; sessions created via `g ai` in the terminal also appear here with a **CLI** badge |
|
|
439
|
+
| Session list | Browse, search, rename, and delete past conversations; sessions created via `g ai` in the terminal also appear here with a **CLI** badge. A finished scheduled-task run lands here on its own (no manual refresh needed), and whatever **View session** on a task card opens is always listed and highlighted — even when that session belongs to another project (the list itself is filtered per project; that one is merged in as the exception) |
|
|
440
440
|
| Engine choice | Run new sessions on the built-in **g ai** or hand them to an external CLI — **Claude Code**, **OpenCode** or **Codex**. The selector sits at the right of the chat tabs; engines whose CLI is not installed are greyed out and clicking one opens the install guide. The same selector lives in the file-space **g ai** chat panel. The engine is locked once a session is persisted, so switching means starting a new session |
|
|
441
441
|
| Live session entry | Sending the first message of a new session makes it show up in the list **immediately** with a "Generating..." badge, instead of waiting for the whole turn to finish; once the reply ends and the server persists the session, the entry is replaced by the real timestamp and message count |
|
|
442
442
|
| Streaming chat | SSE-based real-time streaming with thinking process, content, tool calls, and tool results rendered inline |
|
|
@@ -1172,7 +1172,7 @@ Activity Bar 中的机器人图标视图,可直接在浏览器中与内置 AI
|
|
|
1172
1172
|
|
|
1173
1173
|
| 功能 | 说明 |
|
|
1174
1174
|
|---|---|
|
|
1175
|
-
| 会话列表 | 浏览、搜索、重命名、删除历史对话;通过 `g ai` 在终端创建的会话也会出现在这里,带 **CLI**
|
|
1175
|
+
| 会话列表 | 浏览、搜索、重命名、删除历史对话;通过 `g ai` 在终端创建的会话也会出现在这里,带 **CLI** 标记。定时任务跑完那一轮会**自动入列**(不用手动刷新);点任务卡片上的「查看会话」打开的会话也一定在列表里并高亮 —— 哪怕它属于别的项目(列表本身按当前项目过滤,这一条是作为例外补进去的) |
|
|
1176
1176
|
| 引擎选择 | 新建会话可跑内置 **g ai**,也可交给外部 CLI —— **Claude Code** / **OpenCode** / **Codex**。选择器在对话 Tab 行右端;未安装的引擎会置灰,点一下直接开安装引导。文件空间的 **g ai** 对话面板头部有同一个选择器。会话一旦落盘引擎就锁定,要换请新建会话 |
|
|
1177
1177
|
| 会话实时入列 | 新会话发出第一条消息后,左侧列表**立刻**出现这一条(带「正在生成中…」标记),不用等整轮回答跑完;回答结束、服务端落盘后自动替换成真实的时间与条数 |
|
|
1178
1178
|
| 流式对话 | 基于 SSE 的实时流式输出,包含思考过程、正文内容、工具调用和工具结果的内联渲染 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zen-gitsync",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.10",
|
|
4
4
|
"description": "Auto commit, scheduled sync, and visual GUI for Git. Run `g` in any repo for one-key commit & push, AI commit messages, scheduled background sync, and a drag-and-drop workflow builder.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"verify:wb-card-cover:reverse": "node scripts/verify-wb-card-cover.cjs --reverse",
|
|
75
75
|
"verify:wb-list-view": "node scripts/verify-wb-list-view.cjs",
|
|
76
76
|
"verify:wb-executor-models": "node scripts/verify-wb-executor-models.cjs",
|
|
77
|
+
"verify:wb-codebuddy-env": "node scripts/verify-wb-codebuddy-env.mjs",
|
|
77
78
|
"verify:wb-task-sound": "node scripts/verify-wb-task-sound.cjs",
|
|
78
79
|
"verify:agent-ask-sound": "node scripts/verify-agent-ask-sound.cjs",
|
|
79
80
|
"verify:wb-proj-branch": "node scripts/verify-workbench-proj-branch.cjs",
|
package/src/cli/ai/agent.js
CHANGED
|
@@ -320,6 +320,9 @@ ${isWin ? `- 当前是 Windows cmd.exe,以下 Unix 命令**不存在**,用了必
|
|
|
320
320
|
|
|
321
321
|
# 输出
|
|
322
322
|
- 你的文本输出直接显示在用户终端,用简体中文交流
|
|
323
|
+
- 想让用户**看到**图(截图/图表/示意图),就在回答正文里写 Markdown 图片 \`\` ——
|
|
324
|
+
本机绝对路径、或相对当前工作目录的路径都可以,界面会自动加载渲染;
|
|
325
|
+
只贴一条路径、或把路径放进代码块,用户看到的只是一行字
|
|
323
326
|
- 完成任务后用一两句话汇报结果,不要复述过程细节`
|
|
324
327
|
}
|
|
325
328
|
return `You are "g ai" — the terminal coding agent built into the zen-gitsync CLI. You use tools to perform coding tasks on the user's real machine.
|
|
@@ -423,6 +426,10 @@ ${isWin ? `- This is Windows cmd.exe. The following Unix commands do NOT exist h
|
|
|
423
426
|
|
|
424
427
|
# Output
|
|
425
428
|
- Your text output goes straight to the user's terminal; reply in English
|
|
429
|
+
- To **show** the user an image (screenshot / chart / diagram), embed it in your reply as a Markdown
|
|
430
|
+
image \`\` — a local absolute path, or a path relative to the working directory,
|
|
431
|
+
both work and the UI loads and renders it; pasting a bare path, or wrapping it in a code block,
|
|
432
|
+
only shows the user a line of text
|
|
426
433
|
- Report results in one or two sentences; do not narrate the process`
|
|
427
434
|
}
|
|
428
435
|
|
|
@@ -60,7 +60,7 @@ test('unsupported stream_options retries once without requesting usage', async (
|
|
|
60
60
|
})
|
|
61
61
|
|
|
62
62
|
// 这两条关心的都是"失败时怎么收场",不是"重试几次" —— 一律 maxRetries: 0,
|
|
63
|
-
// 否则要真等退避(最多 10 次、单次封顶
|
|
63
|
+
// 否则要真等退避(最多 10 次、单次封顶 60s),一个用例就跑到分钟级。
|
|
64
64
|
// 重试本身的行为在文件末尾那组用例里单独验(那里注入 sleepFn,不真等)。
|
|
65
65
|
test('truncated streams do not yield executable tool calls', async () => {
|
|
66
66
|
await assert.rejects(streamChatOnce({ model, messages: [], maxRetries: 0, fetchFn: async () => response([
|
|
@@ -136,6 +136,27 @@ test('重试次数用尽后抛出最后一次的错误', async () => {
|
|
|
136
136
|
assert.equal(calls, 4, '首次 + 3 次重试')
|
|
137
137
|
})
|
|
138
138
|
|
|
139
|
+
test('重试退避是指数放慢、分钟级封顶(2026-10-12 口径:2s 起步 / 60s 封顶)', async () => {
|
|
140
|
+
// 每次都吐半截就断(可重试),注入 sleepFn 把每次退避的时长记下来,不真等。
|
|
141
|
+
// 钉这件事是因为 429 限流场景下亚秒级重试等于白刷请求 —— 用户看到的就是
|
|
142
|
+
// 重试提示连续弹。抖动区间是 exp/2 + random(exp/2),逐档断言落点。
|
|
143
|
+
const delays = []
|
|
144
|
+
await assert.rejects(streamChatOnce({
|
|
145
|
+
model, messages: [], maxRetries: 10,
|
|
146
|
+
fetchFn: async () => response([event({ choices: [{ delta: { content: '半截' } }] })]),
|
|
147
|
+
sleepFn: async ms => { delays.push(ms) },
|
|
148
|
+
}), /中断/)
|
|
149
|
+
assert.equal(delays.length, 10)
|
|
150
|
+
// exp = min(60s, 2s × 2^attempt):1~2s / 2~4s / 4~8s / 8~16s / 16~32s / 之后 30~60s
|
|
151
|
+
const bands = [[1000, 2000], [2000, 4000], [4000, 8000], [8000, 16000], [16000, 32000], [30000, 60000]]
|
|
152
|
+
for (let i = 0; i < 10; i++) {
|
|
153
|
+
const [lo, hi] = bands[Math.min(i, bands.length - 1)]
|
|
154
|
+
assert.ok(delays[i] >= lo && delays[i] <= hi,
|
|
155
|
+
`第 ${i + 1} 次退避 ${delays[i]}ms 不在 [${lo}, ${hi}] —— 退避口径被改了?`)
|
|
156
|
+
}
|
|
157
|
+
assert.ok(delays[0] >= 1000, '首次重试不再亚秒级')
|
|
158
|
+
})
|
|
159
|
+
|
|
139
160
|
test('4xx(重试也没用)不重试,网关原话照传', async () => {
|
|
140
161
|
let calls = 0
|
|
141
162
|
await assert.rejects(streamChatOnce({
|
package/src/cli/ai/tools.js
CHANGED
|
@@ -37,6 +37,8 @@ import { trackChild } from '../cleanup.js'
|
|
|
37
37
|
import { checkDangerousCommand } from './safety.js'
|
|
38
38
|
import { guardCommand } from './platformGuard.js'
|
|
39
39
|
import { augmentEnvPath, isCommandNotFound, pathValueOf } from '../../utils/shellPath.js'
|
|
40
|
+
// 从远程地址推导仓库目录名 —— 与 GUI 的 /api/clone 共用同一份规则(见 utils/gitRepoName.js)
|
|
41
|
+
import { repoNameFromUrl } from '../../utils/gitRepoName.js'
|
|
40
42
|
import { checkImageFile, imageToDataUrl, formatBytes, isImagePath, SUPPORTED_IMAGE_EXTS } from './images.js'
|
|
41
43
|
// 定时任务库:CLI 与 GUI 共享同一份文件(~/.zen-gitsync/schedules.json)。
|
|
42
44
|
// 本工具只负责登记/管理,真正的到点执行由 g ui 服务端的调度器完成。
|
|
@@ -223,6 +225,24 @@ export const TOOL_DEFINITIONS = [
|
|
|
223
225
|
},
|
|
224
226
|
},
|
|
225
227
|
},
|
|
228
|
+
{
|
|
229
|
+
type: 'function',
|
|
230
|
+
function: {
|
|
231
|
+
name: 'register_project',
|
|
232
|
+
description: '把一个目录登记进用户的「常用目录」—— 就是 g ui「切换工作目录」弹窗里那份清单(首屏「最近项目」面板是同一份数据)。'
|
|
233
|
+
+ '什么时候用:你**刚创建或克隆了一个新项目**(git init / git clone / 各种脚手架新建出来的目录)之后,顺手把它登记进去 —— '
|
|
234
|
+
+ '用户下次就能在界面上一键切过去,不用自己去翻路径。'
|
|
235
|
+
+ '路径必须是**已存在**的目录(绝对路径);重复登记同一个目录没有副作用(会挪到最前)。'
|
|
236
|
+
+ '只在 g ui(GUI 界面)的内置智能体里可用;命令行 g ai 没有「常用目录」这个概念,不用调用。',
|
|
237
|
+
parameters: {
|
|
238
|
+
type: 'object',
|
|
239
|
+
properties: {
|
|
240
|
+
path: { type: 'string', description: '要登记的项目目录(绝对路径,必须已存在)' },
|
|
241
|
+
},
|
|
242
|
+
required: ['path'],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
226
246
|
{
|
|
227
247
|
type: 'function',
|
|
228
248
|
function: {
|
|
@@ -317,7 +337,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
317
337
|
},
|
|
318
338
|
executor: {
|
|
319
339
|
type: 'string',
|
|
320
|
-
enum: ['claude', 'opencode', 'codex'],
|
|
340
|
+
enum: ['claude', 'opencode', 'codex', 'codebuddy'],
|
|
321
341
|
description: '用哪个本地 CLI 执行这条任务。不传则用控制台当前选中的执行器,再退到配置里的全局默认。',
|
|
322
342
|
},
|
|
323
343
|
auto_run: {
|
|
@@ -492,6 +512,98 @@ function execCommand(command, options) {
|
|
|
492
512
|
})
|
|
493
513
|
}
|
|
494
514
|
|
|
515
|
+
// ──────────────────────────────────────────────
|
|
516
|
+
// 「建了仓库」的识别:run_command 之后把新项目顺手登记进常用目录
|
|
517
|
+
// ──────────────────────────────────────────────
|
|
518
|
+
//
|
|
519
|
+
// 为什么要在**命令文本**上做这件事(而不是只靠模型记得调 register_project):
|
|
520
|
+
// g ai 帮用户建项目(git clone / git init)之后,新目录理应出现在「常用目录」里,
|
|
521
|
+
// 否则用户还得自己去界面里再找一遍路径 —— 而这步本来就该由动手的人顺手做掉。
|
|
522
|
+
// 登记常用目录是"顺手做的事",指望每一轮模型都记得并不可靠;这两条命令又足够典型
|
|
523
|
+
// (克隆 / 初始化仓库是"建项目"最常见的两步),所以在工具层兜一道。
|
|
524
|
+
// register_project 工具是通用兜底:脚手架(npm create / npx create-vite …)建出来的
|
|
525
|
+
// 目录这里认不出来,模型可以显式补一记。
|
|
526
|
+
const REPO_CREATE_HINT_RE = /(?:^|[\s;&|()])(?:git\s+(?:-C\s+\S+\s+)?(?:clone|init)\b|gh\s+repo\s+create\b)/i
|
|
527
|
+
|
|
528
|
+
/** 按空白切参数,保留引号里的整体(`"a b"` 算一个 token) */
|
|
529
|
+
function tokenizeArgs(text) {
|
|
530
|
+
return String(text || '').match(/"[^"]*"|'[^']*'|\S+/g) || []
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/** 去掉 token 两端成对的引号 */
|
|
534
|
+
function unquoteToken(token) {
|
|
535
|
+
const t = String(token || '')
|
|
536
|
+
const pair = t.length >= 2
|
|
537
|
+
&& ((t[0] === '"' && t.endsWith('"')) || (t[0] === "'" && t.endsWith("'")))
|
|
538
|
+
return pair ? t.slice(1, -1) : t
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* 从一条疑似"建仓库"的命令里抽出**可能新建的仓库目录**(绝对路径)。
|
|
543
|
+
* 纯字符串解析,**不做存在性判断** —— 调用方自己 fs.stat 确认落到了磁盘上。
|
|
544
|
+
* 认不出来返回空数组(宁可漏登记,也不要凭空登记一个不存在的路径)。
|
|
545
|
+
*
|
|
546
|
+
* 覆盖三种写法:
|
|
547
|
+
* git clone <url> [<dir>] —— 没给 dir 时按仓库名猜(与 /api/clone 同一规则)
|
|
548
|
+
* git init [<dir>] —— 没给 dir 时就是 cwd
|
|
549
|
+
* gh repo create … --clone —— 本地子目录名取仓库名
|
|
550
|
+
* 外加命令里出现过的 `cd <dir>` / `git -C <dir>`:链式相对 cd(`cd a && cd b`)不精确,
|
|
551
|
+
* 但 `mkdir x && cd x && git init` 这类常见写法能命中。
|
|
552
|
+
*/
|
|
553
|
+
export function detectRepoCreateTargets(command, cwd) {
|
|
554
|
+
const cmd = String(command || '')
|
|
555
|
+
if (!REPO_CREATE_HINT_RE.test(cmd)) return []
|
|
556
|
+
const base = path.resolve(cwd || process.cwd())
|
|
557
|
+
const abs = (p) => (path.isAbsolute(p) ? path.normalize(p) : path.resolve(base, p))
|
|
558
|
+
const out = new Set()
|
|
559
|
+
let m
|
|
560
|
+
|
|
561
|
+
// `cd [ /d ] <dir>`(Windows 的 `cd /d` 也认):后续 clone/init 的相对落点按它解析
|
|
562
|
+
const cdRe = /(?:^|[\s;&|()])cd(?:\s+\/d)?\s+("[^"]*"|'[^']*'|[^\s;&|()]+)/gi
|
|
563
|
+
while ((m = cdRe.exec(cmd))) out.add(abs(unquoteToken(m[1])))
|
|
564
|
+
|
|
565
|
+
const gitRe = /(?:^|[\s;&|()])git(?:\s+-C\s+("[^"]*"|'[^']*'|[^\s;&|()]+))?\s+(clone|init)\b([^\n;&|]*)/gi
|
|
566
|
+
while ((m = gitRe.exec(cmd))) {
|
|
567
|
+
const cDir = m[1] ? unquoteToken(m[1]) : '' // git -C <dir>
|
|
568
|
+
if (cDir) out.add(abs(cDir))
|
|
569
|
+
const positionals = tokenizeArgs(m[3]).filter(t => !t.startsWith('-'))
|
|
570
|
+
if (m[2].toLowerCase() === 'clone') {
|
|
571
|
+
const [url, dir] = positionals
|
|
572
|
+
if (dir) out.add(abs(unquoteToken(dir)))
|
|
573
|
+
else {
|
|
574
|
+
const name = url ? repoNameFromUrl(unquoteToken(url)) : ''
|
|
575
|
+
if (name) out.add(abs(name))
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
// init 的落点:显式目录 > `git -C <dir>` > cwd
|
|
579
|
+
out.add(abs(unquoteToken(positionals[0] || cDir || '.')))
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// gh repo create [owner/]name …:只有 --clone(且不是从本地 --source 建)才会建出目录
|
|
584
|
+
const ghRe = /(?:^|[\s;&|()])gh\s+repo\s+create\b([^\n;&|]*)/gi
|
|
585
|
+
while ((m = ghRe.exec(cmd))) {
|
|
586
|
+
const rest = m[1]
|
|
587
|
+
if (!/(?:^|\s)--clone(?:[=\s]|$)/.test(rest)) continue
|
|
588
|
+
if (/(?:^|\s)--source(?:[=\s]|$)/.test(rest)) continue
|
|
589
|
+
const name = tokenizeArgs(rest).filter(t => !t.startsWith('-'))[0] || ''
|
|
590
|
+
const leaf = unquoteToken(name).split('/').filter(Boolean).pop() || ''
|
|
591
|
+
if (leaf) out.add(abs(leaf))
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return Array.from(out)
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** 目录是不是一个 Git 仓库的根(普通仓库里 .git 是目录;worktree/submodule 里是文件) */
|
|
598
|
+
async function isGitRepoRoot(dir) {
|
|
599
|
+
try {
|
|
600
|
+
await fs.stat(path.join(dir, '.git'))
|
|
601
|
+
return true
|
|
602
|
+
} catch {
|
|
603
|
+
return false
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
495
607
|
// ──────────────────────────────────────────────
|
|
496
608
|
// 各工具实现
|
|
497
609
|
// ──────────────────────────────────────────────
|
|
@@ -554,6 +666,19 @@ async function toolRunCommand(args, ctx) {
|
|
|
554
666
|
}
|
|
555
667
|
}
|
|
556
668
|
|
|
669
|
+
// 命令成功建出了仓库 → 顺手登记进常用目录(见 detectRepoCreateTargets 的注释)。
|
|
670
|
+
// 只在 GUI 注入了 registerProject 时生效;CLI 没有「常用目录」这个概念,静默跳过。
|
|
671
|
+
// 整段包在 try 里:登记失败绝不能影响命令本身的结果。
|
|
672
|
+
if (result.code === 0 && typeof ctx.registerProject === 'function') {
|
|
673
|
+
try {
|
|
674
|
+
for (const dir of detectRepoCreateTargets(command, cwd)) {
|
|
675
|
+
if (await isGitRepoRoot(dir)) await ctx.registerProject(dir)
|
|
676
|
+
}
|
|
677
|
+
} catch {
|
|
678
|
+
// 锦上添花,失败就跳过
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
557
682
|
const parts = []
|
|
558
683
|
if (result.cancelled) parts.push('[命令已由用户停止]')
|
|
559
684
|
if (result.killed) parts.push(`[命令超时被终止(>${timeoutSec}s)]`)
|
|
@@ -807,6 +932,27 @@ async function toolListProjects(args, ctx) {
|
|
|
807
932
|
return ctx.listProjects({ refresh: args.refresh === true })
|
|
808
933
|
}
|
|
809
934
|
|
|
935
|
+
// register_project 的实现同样由 GUI 侧注入(ctx.registerProject)—— 最近目录是
|
|
936
|
+
// configManager 的东西,CLI/Web 共用的本模块只该知道"有这么个工具"。
|
|
937
|
+
// 与 list_projects 同一手法:没有实现时给一句能照着做的话,而不是崩掉。
|
|
938
|
+
async function toolRegisterProject(args, ctx) {
|
|
939
|
+
if (typeof ctx.registerProject !== 'function') {
|
|
940
|
+
return '错误: register_project 只在 g ui(GUI 界面)的内置智能体里可用。'
|
|
941
|
+
+ '命令行 g ai 下没有「常用目录」这个概念,无需调用。'
|
|
942
|
+
}
|
|
943
|
+
const raw = String(args.path || '').trim()
|
|
944
|
+
if (!raw) return '错误: path 不能为空'
|
|
945
|
+
const dir = resolvePath(ctx, raw)
|
|
946
|
+
try {
|
|
947
|
+
const st = await fs.stat(dir)
|
|
948
|
+
if (!st.isDirectory()) return `错误: ${dir} 不是目录,未登记。`
|
|
949
|
+
} catch {
|
|
950
|
+
return `错误: 目录不存在: ${dir}(未登记)。`
|
|
951
|
+
}
|
|
952
|
+
await ctx.registerProject(dir)
|
|
953
|
+
return `已把「${dir}」加入常用目录。`
|
|
954
|
+
}
|
|
955
|
+
|
|
810
956
|
async function toolAskUser(args, ctx) {
|
|
811
957
|
const question = String(args.question || '').trim()
|
|
812
958
|
if (!question) return 'Error: ask_user requires a non-empty question.'
|
|
@@ -1003,6 +1149,7 @@ const TOOL_HANDLERS = {
|
|
|
1003
1149
|
list_files: toolListFiles,
|
|
1004
1150
|
search_text: toolSearchText,
|
|
1005
1151
|
list_projects: toolListProjects,
|
|
1152
|
+
register_project: toolRegisterProject,
|
|
1006
1153
|
update_plan: toolUpdatePlan,
|
|
1007
1154
|
ask_user: toolAskUser,
|
|
1008
1155
|
dispatch_task: toolDispatchTask,
|
|
@@ -1018,7 +1165,11 @@ const TOOL_HANDLERS = {
|
|
|
1018
1165
|
*
|
|
1019
1166
|
* @param {string} name - 工具名
|
|
1020
1167
|
* @param {object} args - 已解析的参数对象
|
|
1021
|
-
* @param {{ cwd: string, onChild?: (child: object) => void
|
|
1168
|
+
* @param {{ cwd: string, onChild?: (child: object) => void,
|
|
1169
|
+
* listProjects?: (args: object) => Promise<string>,
|
|
1170
|
+
* registerProject?: (dir: string) => Promise<void> }} ctx
|
|
1171
|
+
* listProjects / registerProject 都由 GUI 侧注入(GUI 才有最近目录);
|
|
1172
|
+
* CLI 下缺省 undefined,对应工具会回一句可照做的说明。
|
|
1022
1173
|
* @returns {Promise<string | { text: string, images: string[] }>}
|
|
1023
1174
|
*/
|
|
1024
1175
|
export async function executeTool(name, args, ctx) {
|
package/src/cli/ai/tools.test.js
CHANGED
|
@@ -19,7 +19,7 @@ import assert from 'node:assert/strict'
|
|
|
19
19
|
import { promises as fs } from 'node:fs'
|
|
20
20
|
import os from 'node:os'
|
|
21
21
|
import path from 'node:path'
|
|
22
|
-
import { TOOL_DEFINITIONS, executeTool, resolveCommandTimeout, normalizePlanSteps, isPlanToolName, splitToolOutput, toolMessageContent } from './tools.js'
|
|
22
|
+
import { TOOL_DEFINITIONS, executeTool, resolveCommandTimeout, normalizePlanSteps, isPlanToolName, splitToolOutput, toolMessageContent, detectRepoCreateTargets } from './tools.js'
|
|
23
23
|
|
|
24
24
|
// 1×1 红色 PNG。用真字节而不是造一个空文件:checkImageFile 只校验扩展名与体积,
|
|
25
25
|
// 但"读出来能还原成原图"这件事值得顺手钉一下(imageToDataUrl 会把内容 base64)。
|
|
@@ -347,7 +347,7 @@ test('dispatch_task schema 要求 text,并声明三条可选口径', async ()
|
|
|
347
347
|
const definition = TOOL_DEFINITIONS.find(tool => tool.function.name === 'dispatch_task')
|
|
348
348
|
assert.ok(definition, '工具表里必须有 dispatch_task —— 主 Agent 控制台的派发就靠它')
|
|
349
349
|
assert.deepEqual(definition.function.parameters.required, ['text'])
|
|
350
|
-
assert.deepEqual(definition.function.parameters.properties.executor.enum, ['claude', 'opencode', 'codex'])
|
|
350
|
+
assert.deepEqual(definition.function.parameters.properties.executor.enum, ['claude', 'opencode', 'codex', 'codebuddy'])
|
|
351
351
|
assert.ok(definition.function.parameters.properties.project_path)
|
|
352
352
|
assert.ok(definition.function.parameters.properties.auto_run)
|
|
353
353
|
assert.ok(definition.function.parameters.properties.use_default_prompt)
|
|
@@ -505,3 +505,72 @@ test('read_image 与 read_file 的描述互指 —— 模型选错工具时能
|
|
|
505
505
|
assert.match(readFile.function.description, /read_image/)
|
|
506
506
|
assert.match(readImage.function.description, /read_file/)
|
|
507
507
|
})
|
|
508
|
+
|
|
509
|
+
// ========== 建仓库后自动登记「常用目录」 ==========
|
|
510
|
+
// g ai 帮用户建/克隆了新项目之后,新目录本该出现在「常用目录」里(否则用户还得
|
|
511
|
+
// 自己去界面里找路径)。这一步在工具层兜底:命令文本里出现 git clone / git init /
|
|
512
|
+
// gh repo create --clone 就登记落点。register_project 是通用兜底(脚手架建的目录)。
|
|
513
|
+
|
|
514
|
+
test('detectRepoCreateTargets:只认"建仓库"的命令,抽出落点', () => {
|
|
515
|
+
const base = path.resolve(os.tmpdir(), 'ws-root')
|
|
516
|
+
const rel = (list) => list.map(p => path.relative(base, p) || '.').sort()
|
|
517
|
+
|
|
518
|
+
// 克隆:给了目标目录用它;没给就按仓库名猜(与 /api/clone 同一规则)
|
|
519
|
+
assert.deepEqual(rel(detectRepoCreateTargets('git clone https://github.com/o/demo.git', base)), ['demo'])
|
|
520
|
+
assert.deepEqual(rel(detectRepoCreateTargets('git clone git@gitee.com:o/x.git custom', base)), ['custom'])
|
|
521
|
+
// init:没给目录就是 cwd;`git -C` / `cd` 链按它们解析
|
|
522
|
+
assert.deepEqual(rel(detectRepoCreateTargets('git init', base)), ['.'])
|
|
523
|
+
assert.deepEqual(rel(detectRepoCreateTargets('mkdir p && cd p && git init', base)), ['.', 'p'])
|
|
524
|
+
assert.deepEqual(rel(detectRepoCreateTargets('git -C sub init', base)), ['sub'])
|
|
525
|
+
// gh repo create:只有 --clone 才在本地建出目录
|
|
526
|
+
assert.deepEqual(rel(detectRepoCreateTargets('gh repo create o/n --clone', base)), ['n'])
|
|
527
|
+
assert.deepEqual(rel(detectRepoCreateTargets('gh repo create o/n --public', base)), [])
|
|
528
|
+
// 不是建仓库的命令:一个都不给(不能因为智能体"逛"过某个仓库就登记它)
|
|
529
|
+
assert.deepEqual(detectRepoCreateTargets('git status', base), [])
|
|
530
|
+
assert.deepEqual(detectRepoCreateTargets('npm run build', base), [])
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
test('run_command 建了仓库后把落点交给注入的登记实现', async () => {
|
|
534
|
+
const repo = path.join(tmpDir, 'auto-registered-repo')
|
|
535
|
+
await fs.mkdir(path.join(repo, '.git'), { recursive: true })
|
|
536
|
+
const seen = []
|
|
537
|
+
// 命令文本里含 `git init` 即命中识别;这条用例不真跑 git(只验链路),
|
|
538
|
+
// 所以造一个假的 .git 目录 —— isGitRepoRoot 只 stat 它,不调 git。
|
|
539
|
+
const out = await executeTool('run_command', { command: 'echo git init', cwd: repo }, {
|
|
540
|
+
...ctx, registerProject: async (dir) => { seen.push(dir) },
|
|
541
|
+
})
|
|
542
|
+
assert.match(out, /exit 0/)
|
|
543
|
+
assert.deepEqual(seen, [repo])
|
|
544
|
+
await fs.rm(repo, { recursive: true, force: true })
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
test('run_command 普通命令不登记任何目录', async () => {
|
|
548
|
+
const repo = path.join(tmpDir, 'not-a-create-cmd')
|
|
549
|
+
await fs.mkdir(path.join(repo, '.git'), { recursive: true })
|
|
550
|
+
const seen = []
|
|
551
|
+
await executeTool('run_command', { command: 'echo hello', cwd: repo }, {
|
|
552
|
+
...ctx, registerProject: async (dir) => { seen.push(dir) },
|
|
553
|
+
})
|
|
554
|
+
assert.deepEqual(seen, [])
|
|
555
|
+
await fs.rm(repo, { recursive: true, force: true })
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
test('register_project 把已存在的目录交给注入的实现', async () => {
|
|
559
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'g-ai-reg-'))
|
|
560
|
+
const seen = []
|
|
561
|
+
const out = await executeTool('register_project', { path: dir }, {
|
|
562
|
+
...ctx, registerProject: async (d) => { seen.push(d) },
|
|
563
|
+
})
|
|
564
|
+
assert.deepEqual(seen, [dir])
|
|
565
|
+
assert.match(out, /常用目录/)
|
|
566
|
+
await fs.rm(dir, { recursive: true, force: true })
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
test('register_project:目录不存在 / 未注入实现 / 空路径都给可照做的错误', async () => {
|
|
570
|
+
const withImpl = { ...ctx, registerProject: async () => {} }
|
|
571
|
+
const missing = path.join(os.tmpdir(), `g-ai-reg-missing-${Date.now()}`)
|
|
572
|
+
assert.match(await executeTool('register_project', { path: missing }, withImpl), /目录不存在/)
|
|
573
|
+
assert.match(await executeTool('register_project', {}, withImpl), /path 不能为空/)
|
|
574
|
+
// CLI 下没有「常用目录」这个概念 —— 要回一句说明,而不是崩掉
|
|
575
|
+
assert.match(await executeTool('register_project', { path: tmpDir }, ctx), /只在 g ui/)
|
|
576
|
+
})
|
package/src/cli/ai/transport.js
CHANGED
|
@@ -18,12 +18,17 @@ const withoutStreamUsage = new Set()
|
|
|
18
18
|
// 判死的连接不再直接失败:交给下面这条自动重试接手,最多 MAX_LLM_RETRIES 次
|
|
19
19
|
// (口径对齐 Claude Code 的 MAX_RETRIES=10)。
|
|
20
20
|
//
|
|
21
|
+
// **退避是分钟级的(2026-10-12 改)**:基准 2s、封顶 60s。原先 500ms/30s,打
|
|
22
|
+
// 429 限流时前几次都在亚秒级重试 —— 限流窗口远长于这个间隔,等于白刷请求,
|
|
23
|
+
// 用户看到的是重试提示连续弹。现在第 1 次等 1~2s(网络闪断仍能快速自愈),
|
|
24
|
+
// 第 4 次起 8~16s+,第 6 次起稳定在分钟级,10 次全失败约 4~5 分钟收手。
|
|
25
|
+
//
|
|
21
26
|
// 外层的两个调用点(CLI 的 turn.js / Web 的 agentChat.js)通过 onRetry 拿到
|
|
22
27
|
// "这次尝试吐了哪些字"的快照,据此把界面上那半截丢掉再重来。
|
|
23
28
|
export const DEFAULT_IDLE_TIMEOUT_MS = 300_000
|
|
24
29
|
export const MAX_LLM_RETRIES = 10
|
|
25
|
-
const RETRY_BASE_DELAY_MS =
|
|
26
|
-
const RETRY_MAX_DELAY_MS =
|
|
30
|
+
const RETRY_BASE_DELAY_MS = 2_000
|
|
31
|
+
const RETRY_MAX_DELAY_MS = 60_000
|
|
27
32
|
|
|
28
33
|
// 值得再试一次的 HTTP 状态:限流 / 请求超时 / 服务端 5xx —— 都是"再试一次可能就好了"。
|
|
29
34
|
// 其余 4xx(400 参数错、401/403 鉴权、404 模型名不对、422 校验失败)再试十次也一样,
|
|
@@ -72,7 +77,7 @@ function isRetryable(err) {
|
|
|
72
77
|
return true
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
/** 指数退避 + 抖动;网关给了 Retry-After
|
|
80
|
+
/** 指数退避 + 抖动;网关给了 Retry-After 就听它的(封顶 2×RETRY_MAX_DELAY_MS,免得被一个 3600 挂住)。 */
|
|
76
81
|
function retryDelayMs(attempt, err) {
|
|
77
82
|
const exp = Math.min(RETRY_MAX_DELAY_MS, RETRY_BASE_DELAY_MS * 2 ** attempt)
|
|
78
83
|
const jittered = exp / 2 + Math.random() * (exp / 2)
|
package/src/config.js
CHANGED
|
@@ -77,9 +77,11 @@ function normalizeAiMaxToolIterations(value) {
|
|
|
77
77
|
return int;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// 工作台任务执行器白名单。'claude' 是历史默认;'opencode' / 'codex'
|
|
81
|
-
//
|
|
82
|
-
|
|
80
|
+
// 工作台任务执行器白名单。'claude' 是历史默认;'opencode' / 'codex' / 'codebuddy'
|
|
81
|
+
// 为可选执行器(opencode run --format json / codex exec --json /
|
|
82
|
+
// codebuddy -p --output-format stream-json -y --port 0,模型都跟随各自 CLI 的配置)。
|
|
83
|
+
// ⚠️ taskRunner.js 里有一份同名单用于运行时分发(见那里的注释),加执行器两处都要改。
|
|
84
|
+
export const TASK_EXECUTORS = ['claude', 'opencode', 'codex', 'codebuddy'];
|
|
83
85
|
|
|
84
86
|
/**
|
|
85
87
|
* 规范化任务执行器。非法值返回 null(交给调用方取默认),不抛错 ——
|
|
@@ -294,7 +296,7 @@ const defaultConfig = {
|
|
|
294
296
|
// 见 workbench/chatPrompts.js)。空串 = 不注入。
|
|
295
297
|
// 归一化见 normalizeAgentDefaultPrompt。
|
|
296
298
|
agentDefaultPrompt: '',
|
|
297
|
-
// 工作台任务执行器(claude | opencode | codex)。全局配置,跨项目共享。
|
|
299
|
+
// 工作台任务执行器(claude | opencode | codex | codebuddy)。全局配置,跨项目共享。
|
|
298
300
|
// 决定「执行任务 / 执行子任务 / 从此处开始 / 简单任务续聊」这条链路
|
|
299
301
|
// 默认 spawn 哪个本地 CLI;执行入口可以按次覆盖(见 workbench 执行路由)。
|
|
300
302
|
taskExecutor: 'claude',
|
|
@@ -330,7 +332,7 @@ const defaultConfig = {
|
|
|
330
332
|
// 白名单式的默认空数组:以后新增工具默认就固定显示,不需要回头改默认值。
|
|
331
333
|
// 未勾选(= 落在本数组里)的工具连同未安装的一起收进顶栏右侧「更多」菜单。
|
|
332
334
|
headerToolsHidden: [],
|
|
333
|
-
// 工作台任务执行器「上次用过/选过的那个」(claude | opencode | codex),null = 还没选过,
|
|
335
|
+
// 工作台任务执行器「上次用过/选过的那个」(claude | opencode | codex | codebuddy),null = 还没选过,
|
|
334
336
|
// 回落顶层 taskExecutor(设置里配的默认值)。两者**故意分开**:后者是"配置的默认",
|
|
335
337
|
// 前者是"上次用的",语义不同,合并就再也分不清哪个是用户主动配的。
|
|
336
338
|
// 2026-09-30: 原先记在 localStorage(键 zen-gitsync-task-executor),而 GUI 每次启动都换一个
|
|
@@ -284,7 +284,7 @@ export const workbenchTools = [
|
|
|
284
284
|
properties: {
|
|
285
285
|
text: { type: 'string', description: '要派给那个项目的 agent 的完整指令' },
|
|
286
286
|
project_path: { type: 'string', description: '派到哪个项目目录(必须是已登记项目),不传则用控制台的默认目标' },
|
|
287
|
-
executor: { type: 'string', description: '可选,指定执行器(claude / codex / opencode / gai)' },
|
|
287
|
+
executor: { type: 'string', description: '可选,指定执行器(claude / codex / opencode / codebuddy / gai)' },
|
|
288
288
|
auto_run: { type: 'boolean', description: '是否建完就立刻执行,默认跟随控制台设置' },
|
|
289
289
|
use_default_prompt: { type: 'boolean', description: '是否拼上项目预设提示词,默认跟随控制台设置' },
|
|
290
290
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.marketplace-panel[data-v-536d7952]{background:var(--bg-container);flex-direction:column;height:100%;min-height:0;display:flex}.mp-toolbar[data-v-536d7952]{flex-shrink:0;align-items:center;gap:12px;padding:12px 16px 8px;display:flex}.mp-search[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);max-width:420px;height:32px;transition:border-color var(--transition-fast) ease;flex:1;align-items:center;gap:6px;padding:0 10px;display:flex}.mp-search[data-v-536d7952]:focus-within{border-color:var(--color-primary)}.mp-search .mp-search-icon[data-v-536d7952]{color:var(--text-meta);flex-shrink:0}.mp-search .mp-search-input[data-v-536d7952]{color:var(--text-primary);font-size:var(--font-size-mid);background:0 0;border:none;outline:none;flex:1;font-family:inherit}.mp-search .mp-search-input[data-v-536d7952]::placeholder{color:var(--text-meta)}.mp-target[data-v-536d7952]{flex-shrink:0}.mp-refresh[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);width:30px;height:30px;color:var(--text-secondary);cursor:pointer;transition:var(--transition-ui-fast);justify-content:center;align-items:center;display:flex}.mp-refresh[data-v-536d7952]:hover{color:var(--color-primary);border-color:var(--color-primary)}.mp-refresh.spinning svg[data-v-536d7952]{animation:.9s linear infinite mkt-spin-536d7952}@keyframes mkt-spin-536d7952{to{transform:rotate(360deg)}}.mp-toolbar-sub[data-v-536d7952]{flex-wrap:wrap;flex-shrink:0;align-items:center;gap:12px;padding:0 16px 10px;display:flex}.mp-target-hint[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-meta)}.mp-target-hint b[data-v-536d7952]{color:var(--color-primary);font-weight:600}.mp-source-filter[data-v-536d7952]{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.mp-chip[data-v-536d7952]{font-size:var(--font-size-sm);border:1px solid var(--border-color);border-radius:var(--radius-xl);color:var(--text-meta);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:2px 10px;font-family:inherit}.mp-chip[data-v-536d7952]:hover{color:var(--text-secondary);border-color:var(--text-tertiary)}.mp-chip.active[data-v-536d7952]{color:var(--color-primary);border-color:var(--color-primary);background:color-mix(in srgb, var(--color-primary) 8%, transparent)}.mp-chip.clear[data-v-536d7952]{color:var(--text-meta);border-style:dashed}.mp-body[data-v-536d7952]{flex:1;min-height:0;padding:0 16px 20px;overflow-y:auto}.mp-group[data-v-536d7952]{margin-bottom:20px}.mp-group.installed[data-v-536d7952]{border-top:1px dashed var(--border-color);padding-top:14px}.mp-group-header[data-v-536d7952]{align-items:center;gap:8px;margin-bottom:10px;display:flex}.mp-group-title[data-v-536d7952]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mp-group-count[data-v-536d7952]{min-width:20px;height:18px;font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-meta);justify-content:center;align-items:center;padding:0 6px;display:inline-flex}.mp-group-error[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--color-warning-dark);align-items:center;gap:4px;display:inline-flex}.mp-group-link[data-v-536d7952]{color:var(--text-meta);transition:color var(--transition-fast) ease;display:inline-flex}.mp-group-link[data-v-536d7952]:hover{color:var(--color-primary)}.mp-grid[data-v-536d7952]{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;display:grid}.mp-card[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);transition:border-color var(--transition-fast) ease, box-shadow var(--transition-fast) ease;flex-direction:column;gap:6px;padding:12px;display:flex}.mp-card[data-v-536d7952]:hover{border-color:color-mix(in srgb, var(--color-primary) 40%, var(--border-color));box-shadow:var(--shadow-sm)}.mp-card-head[data-v-536d7952]{align-items:center;gap:8px;display:flex}.mp-card-name[data-v-536d7952]{min-width:0;font-size:var(--font-size-mid);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;flex:1;font-weight:600;overflow:hidden}.mp-card-metric[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);flex-shrink:0;align-items:center;gap:3px;display:inline-flex}.mp-card-desc[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:36px;margin:0;line-height:1.5;display:-webkit-box;overflow:hidden}.mp-card-meta[data-v-536d7952]{flex-wrap:wrap;align-items:center;gap:6px;min-height:18px;display:flex}.mp-meta-pkg[data-v-536d7952],.mp-meta-repo[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);white-space:nowrap;text-overflow:ellipsis;max-width:220px;overflow:hidden}.mp-tag[data-v-536d7952]{font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-meta);flex-shrink:0;padding:1px 6px}.mp-tag.remote[data-v-536d7952]{background:color-mix(in srgb, var(--color-info,var(--action-teal)) 14%, transparent);color:var(--color-info,var(--action-teal))}.mp-tag.warn[data-v-536d7952]{background:color-mix(in srgb, var(--color-warning) 14%, transparent);color:var(--color-warning-dark)}.mp-card-foot[data-v-536d7952]{align-items:center;gap:8px;margin-top:2px;display:flex}.mp-card-link[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);text-decoration:none}.mp-card-link[data-v-536d7952]:hover{color:var(--color-primary);text-decoration:underline}.mp-foot-spacer[data-v-536d7952]{flex:1}.mp-install-btn[data-v-536d7952]{font-size:var(--font-size-sm);border:1px solid var(--color-primary);border-radius:var(--radius-base);color:var(--color-primary);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:4px 14px;font-family:inherit}.mp-install-btn[data-v-536d7952]:hover:not(:disabled){background:var(--color-primary);color:#fff}.mp-install-btn[data-v-536d7952]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.mp-installed-chip[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--color-success,var(--action-emerald));align-items:center;gap:3px;display:inline-flex}.mp-not-installable[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta)}.mp-empty[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-meta);padding:16px 0}.mp-empty.all[data-v-536d7952]{text-align:center;padding:48px 0}.mp-installed-block[data-v-536d7952]{margin-bottom:12px}.mp-installed-target[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px;font-weight:600}.mp-installed-list[data-v-536d7952]{flex-direction:column;gap:4px;display:flex}.mp-installed-row[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-base);background:var(--bg-panel);align-items:center;gap:10px;padding:6px 10px;display:flex}.mp-installed-name[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:500;overflow:hidden}.mp-installed-id[data-v-536d7952]{font-size:var(--font-size-xs);font-family:var(--font-mono);color:var(--text-meta);white-space:nowrap;text-overflow:ellipsis;max-width:40%;overflow:hidden}.mp-reveal-btn[data-v-536d7952],.mp-remove-btn[data-v-536d7952]{font-size:var(--font-size-xs);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-meta);cursor:pointer;white-space:nowrap;transition:var(--transition-ui-fast);background:0 0;align-items:center;gap:4px;padding:3px 10px;font-family:inherit;display:inline-flex}.mp-reveal-btn[data-v-536d7952]:disabled,.mp-remove-btn[data-v-536d7952]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.mp-reveal-btn[data-v-536d7952]:hover:not(:disabled){color:var(--text-primary);border-color:var(--text-tertiary)}.mp-remove-btn[data-v-536d7952]:hover:not(:disabled){color:var(--color-danger-dark);border-color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.mp-refresh.spinning svg[data-v-536d7952]{animation:none}}.mkt-form[data-v-536d7952]{flex-direction:column;gap:12px;display:flex}.mkt-form-name[data-v-536d7952]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mkt-field[data-v-536d7952]{flex-direction:column;gap:4px;display:flex}.mkt-field label[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-secondary);font-weight:600}.mkt-field input[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-container);height:30px;color:var(--text-primary);font-size:var(--font-size-mid);transition:border-color var(--transition-fast) ease;padding:0 8px;font-family:inherit}.mkt-field input[data-v-536d7952]:focus{border-color:var(--color-primary);outline:none}.mkt-hint[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);margin:0}.mkt-cancel[data-v-536d7952],.mkt-confirm[data-v-536d7952]{font-size:var(--font-size-mid);border-radius:var(--radius-base);cursor:pointer;transition:var(--transition-ui-fast);padding:6px 16px;font-family:inherit}.mkt-cancel[data-v-536d7952]{border:1px solid var(--border-color);color:var(--text-secondary);background:0 0;margin-right:8px}.mkt-cancel[data-v-536d7952]:hover{color:var(--text-primary);border-color:var(--text-tertiary)}.mkt-confirm[data-v-536d7952]{border:1px solid var(--color-primary);background:var(--color-primary);color:#fff}.mkt-confirm[data-v-536d7952]:hover{opacity:.9}.schedule-panel[data-v-75be84e5]{flex-direction:column;flex:1;gap:12px;min-height:0;padding:16px 20px 24px;display:flex;overflow-y:auto}.schedule-toolbar[data-v-75be84e5]{justify-content:space-between;align-items:center;gap:12px;display:flex}.schedule-summary[data-v-75be84e5]{color:var(--text-secondary);font-size:12px}.schedule-error[data-v-75be84e5]{color:var(--text-danger);background:color-mix(in srgb, var(--color-danger) 8%, transparent);border:1px solid color-mix(in srgb, var(--color-danger) 25%, transparent);border-radius:6px;padding:8px 10px;font-size:12px}.schedule-loading[data-v-75be84e5],.schedule-empty[data-v-75be84e5]{color:var(--text-secondary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:40px 20px;font-size:13px;display:flex}.schedule-empty-title[data-v-75be84e5]{color:var(--text-primary);margin:0;font-size:14px;font-weight:500}.schedule-empty-desc[data-v-75be84e5]{text-align:center;max-width:440px;color:var(--text-tertiary);margin:0;font-size:12px;line-height:1.7}.schedule-list[data-v-75be84e5]{flex-direction:column;gap:8px;display:flex}.schedule-card[data-v-75be84e5]{background:var(--bg-card);border:1px solid var(--border-color);border-radius:8px;justify-content:space-between;align-items:center;gap:12px;padding:10px 14px;transition:border-color .15s,background .15s;display:flex}.schedule-card[data-v-75be84e5]:hover{border-color:var(--border-color-medium)}.schedule-card.is-running[data-v-75be84e5]{border-color:var(--tint-primary-35);background:var(--tint-primary-04)}.schedule-card.is-disabled .schedule-name[data-v-75be84e5]{color:var(--text-secondary)}.schedule-card-body[data-v-75be84e5]{flex-direction:column;gap:4px;min-width:0;display:flex}.schedule-card-head[data-v-75be84e5]{align-items:center;gap:8px;min-width:0;display:flex}.schedule-name[data-v-75be84e5]{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;overflow:hidden}.schedule-running[data-v-75be84e5]{color:var(--color-primary);background:var(--tint-primary-10);white-space:nowrap;border-radius:4px;padding:1px 6px;font-size:11px}.schedule-card-sub[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;align-items:center;gap:6px;min-width:0;font-size:12px;display:flex;overflow:hidden}.schedule-desc[data-v-75be84e5]{text-overflow:ellipsis;overflow:hidden}.schedule-sep[data-v-75be84e5]{color:var(--text-tertiary)}.schedule-last[data-v-75be84e5]{text-overflow:ellipsis;overflow:hidden}.schedule-last.is-ok[data-v-75be84e5]{color:var(--text-success)}.schedule-last.is-error[data-v-75be84e5]{color:var(--text-danger)}.schedule-last.is-skipped[data-v-75be84e5]{color:var(--text-warning)}.schedule-last.is-muted[data-v-75be84e5]{color:var(--text-tertiary)}.sch-link[data-v-75be84e5]{color:var(--color-primary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.sch-link[data-v-75be84e5]:hover{text-decoration:underline}.schedule-card-side[data-v-75be84e5]{flex-shrink:0;align-items:center;gap:12px;display:flex}.schedule-next[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;font-size:12px}.schedule-next.is-muted[data-v-75be84e5]{color:var(--text-tertiary)}.schedule-actions[data-v-75be84e5]{align-items:center;gap:2px;display:flex}.sch-switch[data-v-75be84e5]{border:1px solid var(--border-color-medium);background:var(--bg-subtle);cursor:pointer;border-radius:10px;flex-shrink:0;width:34px;height:20px;padding:0;transition:background .15s,border-color .15s;position:relative}.sch-switch .sch-switch-knob[data-v-75be84e5]{background:var(--text-tertiary);border-radius:50%;width:14px;height:14px;transition:transform .15s,background .15s;position:absolute;top:2px;left:2px}.sch-switch.on[data-v-75be84e5]{background:var(--tint-primary-18);border-color:var(--tint-primary-45)}.sch-switch.on .sch-switch-knob[data-v-75be84e5]{background:var(--color-primary);transform:translate(14px)}.sch-btn[data-v-75be84e5]{border:1px solid var(--border-color);color:var(--text-secondary);cursor:pointer;background:0 0;border-radius:6px;padding:3px 10px;font-size:12px;transition:background .15s,color .15s,border-color .15s}.sch-btn[data-v-75be84e5]:hover:not(:disabled){background:var(--bg-subtle-hover);color:var(--text-primary);border-color:var(--border-color-medium)}.sch-btn[data-v-75be84e5]:disabled{opacity:.5;cursor:default}.sch-btn-primary[data-v-75be84e5]{background:var(--tint-primary-10);border-color:var(--tint-primary-35);color:var(--color-primary)}.sch-btn-primary[data-v-75be84e5]:hover:not(:disabled){background:var(--tint-primary-18);color:var(--color-primary);border-color:var(--tint-primary-45)}.sch-btn-danger[data-v-75be84e5]{color:var(--text-danger)}.sch-btn-danger[data-v-75be84e5]:hover:not(:disabled){background:color-mix(in srgb, var(--color-danger) 8%, transparent);color:var(--text-danger);border-color:color-mix(in srgb, var(--color-danger) 30%, transparent)}.sch-form[data-v-75be84e5]{flex-direction:column;gap:14px;display:flex}.sch-field[data-v-75be84e5]{flex-direction:column;gap:6px;display:flex}.sch-field-label[data-v-75be84e5]{color:var(--text-secondary);font-size:12px}.sch-input[data-v-75be84e5]{box-sizing:border-box;width:100%;color:var(--text-primary);background:var(--bg-container);border:1px solid var(--border-color-medium);border-radius:6px;outline:none;padding:6px 10px;font-family:inherit;font-size:13px;transition:border-color .15s}.sch-input[data-v-75be84e5]:focus{border-color:var(--tint-primary-55)}.sch-select[data-v-75be84e5]{cursor:pointer}.sch-select-sm[data-v-75be84e5]{width:auto;min-width:64px}.sch-input-cron[data-v-75be84e5]{font-family:var(--font-mono,monospace)}.sch-textarea[data-v-75be84e5]{resize:vertical;min-height:72px;line-height:1.6}.sch-freq-row[data-v-75be84e5]{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.sch-inline-label[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;font-size:12px}.sch-hint[data-v-75be84e5]{color:var(--text-tertiary);font-size:11px}.sch-radio-row[data-v-75be84e5]{flex-wrap:wrap;align-items:center;gap:16px;display:flex}.sch-radio[data-v-75be84e5]{color:var(--text-secondary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:inline-flex}.sch-radio input[data-v-75be84e5]{accent-color:var(--color-primary);cursor:pointer;margin:0}.sch-form-error[data-v-75be84e5]{color:var(--text-danger);margin:0;font-size:12px}.sch-form-footer[data-v-75be84e5]{justify-content:flex-end;gap:8px;margin-top:14px;display:flex}.sch-confirm-text[data-v-75be84e5]{color:var(--text-primary);margin:0;font-size:13px;line-height:1.7}.aps[data-v-ae77c09c]{background:var(--bg-container);flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.aps__scroll[data-v-ae77c09c]{flex-direction:column;flex:1;gap:14px;max-width:860px;min-height:0;padding:16px 18px 24px;line-height:1.5;display:flex;overflow-y:auto}.aps__head[data-v-ae77c09c]{flex-direction:column;gap:5px;display:flex}.aps__title[data-v-ae77c09c]{font-size:var(--font-size-lg);color:var(--text-primary);margin:0;font-weight:600}.aps__intro[data-v-ae77c09c]{font-size:var(--font-size-sm);color:var(--text-meta);margin:0;line-height:1.6}.aps__card[data-v-ae77c09c]{background:var(--bg-panel);border:1px solid var(--border-color);border-radius:var(--radius-lg);flex-direction:column;gap:9px;padding:14px 16px;display:flex}.aps__card-head[data-v-ae77c09c]{align-items:baseline;gap:8px;display:flex}.aps__card-title[data-v-ae77c09c]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.aps__label[data-v-ae77c09c]{font-size:var(--font-size-sm);color:var(--text-secondary);font-weight:500}.aps__count[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta);font-variant-numeric:tabular-nums;margin-left:auto}.aps__field[data-v-ae77c09c]{flex-direction:column;gap:5px;display:flex}.aps__hint[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta);margin:0;line-height:1.6}.aps__area[data-v-ae77c09c]{box-sizing:border-box;resize:vertical;width:100%;min-height:92px;max-height:320px;font-size:var(--font-size-mid);color:var(--text-primary);background:var(--bg-subtle);border:1px solid var(--border-color);border-radius:var(--radius-md);transition:border-color var(--transition-fast) var(--ease-custom);outline:none;padding:7px 9px;font-family:inherit;line-height:1.5}.aps__area[data-v-ae77c09c]:focus{border-color:var(--color-primary)}.aps__area[data-v-ae77c09c]::placeholder{color:var(--text-meta)}.aps__area[data-v-ae77c09c]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.aps__foot[data-v-ae77c09c]{align-items:center;gap:8px;display:flex}.aps__spacer[data-v-ae77c09c]{flex:1}.aps__saved[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta)}.aps__btn[data-v-ae77c09c]{color:var(--text-secondary);font-size:var(--font-size-sm);border-radius:var(--radius-md);cursor:pointer;transition:color var(--transition-fast) var(--ease-custom), background var(--transition-fast) var(--ease-custom);background:0 0;border:none;padding:0 12px;line-height:28px}.aps__btn[data-v-ae77c09c]:hover:not(:disabled){color:var(--color-primary);background:var(--bg-container-hover)}.aps__btn[data-v-ae77c09c]:disabled{opacity:var(--disabled-opacity);cursor:default}.aps__btn[data-v-ae77c09c]:focus-visible{outline:var(--focus-outline);outline-offset:1px}.aps__btn--primary[data-v-ae77c09c]{background:var(--color-primary);color:#fff}.aps__btn--primary[data-v-ae77c09c]:hover:not(:disabled){background:var(--color-primary);color:#fff;opacity:.88}.agent-view[data-v-287616d8]{background:var(--bg-container);height:100%;min-height:0;display:flex}.agent-sidebar[data-v-287616d8]{background:var(--bg-panel);border-right:1px solid var(--border-color);flex-direction:column;flex-shrink:0;display:flex;overflow:hidden}.agent-conversations[data-v-287616d8]{flex:1;min-height:0;padding:10px 6px 8px 12px}.sidebar-resizer[data-v-287616d8]{cursor:col-resize;width:4px;transition:background var(--transition-fast) ease;background:0 0;flex-shrink:0}.sidebar-resizer[data-v-287616d8]:hover,.sidebar-resizer.active[data-v-287616d8]{background:var(--color-primary);opacity:.3}.agent-chat-area[data-v-287616d8]{flex-direction:column;flex:1;min-width:0;display:flex;position:relative;overflow:hidden}.agent-engine[data-v-287616d8]{margin-bottom:7px;margin-left:auto}.agent-copy[data-v-287616d8]{margin-bottom:7px;margin-left:2px}.agent-tabs[data-v-287616d8]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:4px;padding:8px 12px 0;display:flex}.agent-tab[data-v-287616d8]{color:var(--text-meta);font-size:var(--font-size-mid);cursor:pointer;transition:color var(--transition-fast) ease, border-color var(--transition-fast) ease, background var(--transition-fast) ease;border-radius:var(--radius-base) var(--radius-base) 0 0;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;padding:7px 14px 9px;font-family:inherit;display:inline-flex}.agent-tab[data-v-287616d8]:hover{color:var(--text-secondary);background:var(--bg-hover)}.agent-tab.active[data-v-287616d8]{color:var(--color-primary);border-bottom-color:var(--color-primary);font-weight:600}.agent-tab-body[data-v-287616d8]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-pane[data-v-287616d8]{flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.agent-tab-body[data-v-287616d8]>.marketplace-panel{flex:1;min-height:0}.chat-loading[data-v-287616d8]{color:var(--text-meta);font-size:var(--font-size-base);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}.agent-list-page[data-v-287616d8]{background:var(--bg-panel);flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-list-page .agent-conversations[data-v-287616d8]{padding:12px 12px 10px 14px}.agent-page-bar[data-v-287616d8]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:6px;height:34px;padding:0 12px 0 6px;display:flex}.agent-page-back[data-v-287616d8]{border-radius:var(--radius-xs);width:24px;height:24px;color:var(--text-meta);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:flex}.agent-page-back[data-v-287616d8]:hover{background:var(--bg-hover);color:var(--text-secondary)}.agent-page-title[data-v-287616d8]{min-width:0;font-size:var(--font-size-mid);color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.agent-chat-host[data-v-287616d8]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-host[data-v-287616d8] .acu-avatar--left{background:0 0}.agent-chat-host[data-v-287616d8] .acu-bubble-row.is-assistant .acu-bubble-main{width:var(--acu-bubble-max-width);max-width:var(--acu-bubble-max-width);position:relative}.agent-chat-host[data-v-287616d8] .acu-bubble-row.is-assistant .acu-bubble{align-self:flex-start}.agent-chat-host[data-v-287616d8] .acu-message-meta{margin:0;position:absolute;top:0;right:0}.agent-chat-host[data-v-287616d8] .acu-input-queue{--acu-queue-edge:var(--role-pending-edge);--acu-queue-surface:var(--role-pending-surface);--acu-queue-ink:var(--role-pending-ink);--acu-queue-wash:var(--role-pending-wash)}.agent-chat-host[data-v-287616d8] .acu-welcome-logo{background:var(--welcome-avatar) center/46px 46px no-repeat;width:56px;height:56px;box-shadow:none}.agent-chat-host[data-v-287616d8] .acu-welcome-logo>svg{display:none}.agent-chat-host[data-v-287616d8] .acu-welcome-grid{flex-wrap:wrap;display:flex}.agent-chat-host[data-v-287616d8] .acu-welcome-grid>.acu-preset-q{flex:260px;min-width:0}[data-theme=dark]{background:var(--bg-panel)}
|
|
1
|
+
.marketplace-panel[data-v-536d7952]{background:var(--bg-container);flex-direction:column;height:100%;min-height:0;display:flex}.mp-toolbar[data-v-536d7952]{flex-shrink:0;align-items:center;gap:12px;padding:12px 16px 8px;display:flex}.mp-search[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);max-width:420px;height:32px;transition:border-color var(--transition-fast) ease;flex:1;align-items:center;gap:6px;padding:0 10px;display:flex}.mp-search[data-v-536d7952]:focus-within{border-color:var(--color-primary)}.mp-search .mp-search-icon[data-v-536d7952]{color:var(--text-meta);flex-shrink:0}.mp-search .mp-search-input[data-v-536d7952]{color:var(--text-primary);font-size:var(--font-size-mid);background:0 0;border:none;outline:none;flex:1;font-family:inherit}.mp-search .mp-search-input[data-v-536d7952]::placeholder{color:var(--text-meta)}.mp-target[data-v-536d7952]{flex-shrink:0}.mp-refresh[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);width:30px;height:30px;color:var(--text-secondary);cursor:pointer;transition:var(--transition-ui-fast);justify-content:center;align-items:center;display:flex}.mp-refresh[data-v-536d7952]:hover{color:var(--color-primary);border-color:var(--color-primary)}.mp-refresh.spinning svg[data-v-536d7952]{animation:.9s linear infinite mkt-spin-536d7952}@keyframes mkt-spin-536d7952{to{transform:rotate(360deg)}}.mp-toolbar-sub[data-v-536d7952]{flex-wrap:wrap;flex-shrink:0;align-items:center;gap:12px;padding:0 16px 10px;display:flex}.mp-target-hint[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-meta)}.mp-target-hint b[data-v-536d7952]{color:var(--color-primary);font-weight:600}.mp-source-filter[data-v-536d7952]{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.mp-chip[data-v-536d7952]{font-size:var(--font-size-sm);border:1px solid var(--border-color);border-radius:var(--radius-xl);color:var(--text-meta);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:2px 10px;font-family:inherit}.mp-chip[data-v-536d7952]:hover{color:var(--text-secondary);border-color:var(--text-tertiary)}.mp-chip.active[data-v-536d7952]{color:var(--color-primary);border-color:var(--color-primary);background:color-mix(in srgb, var(--color-primary) 8%, transparent)}.mp-chip.clear[data-v-536d7952]{color:var(--text-meta);border-style:dashed}.mp-body[data-v-536d7952]{flex:1;min-height:0;padding:0 16px 20px;overflow-y:auto}.mp-group[data-v-536d7952]{margin-bottom:20px}.mp-group.installed[data-v-536d7952]{border-top:1px dashed var(--border-color);padding-top:14px}.mp-group-header[data-v-536d7952]{align-items:center;gap:8px;margin-bottom:10px;display:flex}.mp-group-title[data-v-536d7952]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mp-group-count[data-v-536d7952]{min-width:20px;height:18px;font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-meta);justify-content:center;align-items:center;padding:0 6px;display:inline-flex}.mp-group-error[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--color-warning-dark);align-items:center;gap:4px;display:inline-flex}.mp-group-link[data-v-536d7952]{color:var(--text-meta);transition:color var(--transition-fast) ease;display:inline-flex}.mp-group-link[data-v-536d7952]:hover{color:var(--color-primary)}.mp-grid[data-v-536d7952]{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;display:grid}.mp-card[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-panel);transition:border-color var(--transition-fast) ease, box-shadow var(--transition-fast) ease;flex-direction:column;gap:6px;padding:12px;display:flex}.mp-card[data-v-536d7952]:hover{border-color:color-mix(in srgb, var(--color-primary) 40%, var(--border-color));box-shadow:var(--shadow-sm)}.mp-card-head[data-v-536d7952]{align-items:center;gap:8px;display:flex}.mp-card-name[data-v-536d7952]{min-width:0;font-size:var(--font-size-mid);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;flex:1;font-weight:600;overflow:hidden}.mp-card-metric[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);flex-shrink:0;align-items:center;gap:3px;display:inline-flex}.mp-card-desc[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:36px;margin:0;line-height:1.5;display:-webkit-box;overflow:hidden}.mp-card-meta[data-v-536d7952]{flex-wrap:wrap;align-items:center;gap:6px;min-height:18px;display:flex}.mp-meta-pkg[data-v-536d7952],.mp-meta-repo[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);white-space:nowrap;text-overflow:ellipsis;max-width:220px;overflow:hidden}.mp-tag[data-v-536d7952]{font-size:var(--font-size-xs);border-radius:var(--radius-lg);background:var(--bg-hover);color:var(--text-meta);flex-shrink:0;padding:1px 6px}.mp-tag.remote[data-v-536d7952]{background:color-mix(in srgb, var(--color-info,var(--action-teal)) 14%, transparent);color:var(--color-info,var(--action-teal))}.mp-tag.warn[data-v-536d7952]{background:color-mix(in srgb, var(--color-warning) 14%, transparent);color:var(--color-warning-dark)}.mp-card-foot[data-v-536d7952]{align-items:center;gap:8px;margin-top:2px;display:flex}.mp-card-link[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);text-decoration:none}.mp-card-link[data-v-536d7952]:hover{color:var(--color-primary);text-decoration:underline}.mp-foot-spacer[data-v-536d7952]{flex:1}.mp-install-btn[data-v-536d7952]{font-size:var(--font-size-sm);border:1px solid var(--color-primary);border-radius:var(--radius-base);color:var(--color-primary);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;padding:4px 14px;font-family:inherit}.mp-install-btn[data-v-536d7952]:hover:not(:disabled){background:var(--color-primary);color:#fff}.mp-install-btn[data-v-536d7952]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.mp-installed-chip[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--color-success,var(--action-emerald));align-items:center;gap:3px;display:inline-flex}.mp-not-installable[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta)}.mp-empty[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-meta);padding:16px 0}.mp-empty.all[data-v-536d7952]{text-align:center;padding:48px 0}.mp-installed-block[data-v-536d7952]{margin-bottom:12px}.mp-installed-target[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px;font-weight:600}.mp-installed-list[data-v-536d7952]{flex-direction:column;gap:4px;display:flex}.mp-installed-row[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-base);background:var(--bg-panel);align-items:center;gap:10px;padding:6px 10px;display:flex}.mp-installed-name[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:500;overflow:hidden}.mp-installed-id[data-v-536d7952]{font-size:var(--font-size-xs);font-family:var(--font-mono);color:var(--text-meta);white-space:nowrap;text-overflow:ellipsis;max-width:40%;overflow:hidden}.mp-reveal-btn[data-v-536d7952],.mp-remove-btn[data-v-536d7952]{font-size:var(--font-size-xs);border:1px solid var(--border-color);border-radius:var(--radius-xs);color:var(--text-meta);cursor:pointer;white-space:nowrap;transition:var(--transition-ui-fast);background:0 0;align-items:center;gap:4px;padding:3px 10px;font-family:inherit;display:inline-flex}.mp-reveal-btn[data-v-536d7952]:disabled,.mp-remove-btn[data-v-536d7952]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.mp-reveal-btn[data-v-536d7952]:hover:not(:disabled){color:var(--text-primary);border-color:var(--text-tertiary)}.mp-remove-btn[data-v-536d7952]:hover:not(:disabled){color:var(--color-danger-dark);border-color:var(--color-danger)}@media (prefers-reduced-motion:reduce){.mp-refresh.spinning svg[data-v-536d7952]{animation:none}}.mkt-form[data-v-536d7952]{flex-direction:column;gap:12px;display:flex}.mkt-form-name[data-v-536d7952]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.mkt-field[data-v-536d7952]{flex-direction:column;gap:4px;display:flex}.mkt-field label[data-v-536d7952]{font-size:var(--font-size-sm);color:var(--text-secondary);font-weight:600}.mkt-field input[data-v-536d7952]{border:1px solid var(--border-color);border-radius:var(--radius-md);background:var(--bg-container);height:30px;color:var(--text-primary);font-size:var(--font-size-mid);transition:border-color var(--transition-fast) ease;padding:0 8px;font-family:inherit}.mkt-field input[data-v-536d7952]:focus{border-color:var(--color-primary);outline:none}.mkt-hint[data-v-536d7952]{font-size:var(--font-size-xs);color:var(--text-meta);margin:0}.mkt-cancel[data-v-536d7952],.mkt-confirm[data-v-536d7952]{font-size:var(--font-size-mid);border-radius:var(--radius-base);cursor:pointer;transition:var(--transition-ui-fast);padding:6px 16px;font-family:inherit}.mkt-cancel[data-v-536d7952]{border:1px solid var(--border-color);color:var(--text-secondary);background:0 0;margin-right:8px}.mkt-cancel[data-v-536d7952]:hover{color:var(--text-primary);border-color:var(--text-tertiary)}.mkt-confirm[data-v-536d7952]{border:1px solid var(--color-primary);background:var(--color-primary);color:#fff}.mkt-confirm[data-v-536d7952]:hover{opacity:.9}.schedule-panel[data-v-75be84e5]{flex-direction:column;flex:1;gap:12px;min-height:0;padding:16px 20px 24px;display:flex;overflow-y:auto}.schedule-toolbar[data-v-75be84e5]{justify-content:space-between;align-items:center;gap:12px;display:flex}.schedule-summary[data-v-75be84e5]{color:var(--text-secondary);font-size:12px}.schedule-error[data-v-75be84e5]{color:var(--text-danger);background:color-mix(in srgb, var(--color-danger) 8%, transparent);border:1px solid color-mix(in srgb, var(--color-danger) 25%, transparent);border-radius:6px;padding:8px 10px;font-size:12px}.schedule-loading[data-v-75be84e5],.schedule-empty[data-v-75be84e5]{color:var(--text-secondary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:40px 20px;font-size:13px;display:flex}.schedule-empty-title[data-v-75be84e5]{color:var(--text-primary);margin:0;font-size:14px;font-weight:500}.schedule-empty-desc[data-v-75be84e5]{text-align:center;max-width:440px;color:var(--text-tertiary);margin:0;font-size:12px;line-height:1.7}.schedule-list[data-v-75be84e5]{flex-direction:column;gap:8px;display:flex}.schedule-card[data-v-75be84e5]{background:var(--bg-card);border:1px solid var(--border-color);border-radius:8px;justify-content:space-between;align-items:center;gap:12px;padding:10px 14px;transition:border-color .15s,background .15s;display:flex}.schedule-card[data-v-75be84e5]:hover{border-color:var(--border-color-medium)}.schedule-card.is-running[data-v-75be84e5]{border-color:var(--tint-primary-35);background:var(--tint-primary-04)}.schedule-card.is-disabled .schedule-name[data-v-75be84e5]{color:var(--text-secondary)}.schedule-card-body[data-v-75be84e5]{flex-direction:column;gap:4px;min-width:0;display:flex}.schedule-card-head[data-v-75be84e5]{align-items:center;gap:8px;min-width:0;display:flex}.schedule-name[data-v-75be84e5]{color:var(--text-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;overflow:hidden}.schedule-running[data-v-75be84e5]{color:var(--color-primary);background:var(--tint-primary-10);white-space:nowrap;border-radius:4px;padding:1px 6px;font-size:11px}.schedule-card-sub[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;align-items:center;gap:6px;min-width:0;font-size:12px;display:flex;overflow:hidden}.schedule-desc[data-v-75be84e5]{text-overflow:ellipsis;overflow:hidden}.schedule-sep[data-v-75be84e5]{color:var(--text-tertiary)}.schedule-last[data-v-75be84e5]{text-overflow:ellipsis;overflow:hidden}.schedule-last.is-ok[data-v-75be84e5]{color:var(--text-success)}.schedule-last.is-error[data-v-75be84e5]{color:var(--text-danger)}.schedule-last.is-skipped[data-v-75be84e5]{color:var(--text-warning)}.schedule-last.is-muted[data-v-75be84e5]{color:var(--text-tertiary)}.sch-link[data-v-75be84e5]{color:var(--color-primary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.sch-link[data-v-75be84e5]:hover{text-decoration:underline}.schedule-card-side[data-v-75be84e5]{flex-shrink:0;align-items:center;gap:12px;display:flex}.schedule-next[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;font-size:12px}.schedule-next.is-muted[data-v-75be84e5]{color:var(--text-tertiary)}.schedule-actions[data-v-75be84e5]{align-items:center;gap:2px;display:flex}.sch-switch[data-v-75be84e5]{border:1px solid var(--border-color-medium);background:var(--bg-subtle);cursor:pointer;border-radius:10px;flex-shrink:0;width:34px;height:20px;padding:0;transition:background .15s,border-color .15s;position:relative}.sch-switch .sch-switch-knob[data-v-75be84e5]{background:var(--text-tertiary);border-radius:50%;width:14px;height:14px;transition:transform .15s,background .15s;position:absolute;top:2px;left:2px}.sch-switch.on[data-v-75be84e5]{background:var(--tint-primary-18);border-color:var(--tint-primary-45)}.sch-switch.on .sch-switch-knob[data-v-75be84e5]{background:var(--color-primary);transform:translate(14px)}.sch-btn[data-v-75be84e5]{border:1px solid var(--border-color);color:var(--text-secondary);cursor:pointer;background:0 0;border-radius:6px;padding:3px 10px;font-size:12px;transition:background .15s,color .15s,border-color .15s}.sch-btn[data-v-75be84e5]:hover:not(:disabled){background:var(--bg-subtle-hover);color:var(--text-primary);border-color:var(--border-color-medium)}.sch-btn[data-v-75be84e5]:disabled{opacity:.5;cursor:default}.sch-btn-primary[data-v-75be84e5]{background:var(--tint-primary-10);border-color:var(--tint-primary-35);color:var(--color-primary)}.sch-btn-primary[data-v-75be84e5]:hover:not(:disabled){background:var(--tint-primary-18);color:var(--color-primary);border-color:var(--tint-primary-45)}.sch-btn-danger[data-v-75be84e5]{color:var(--text-danger)}.sch-btn-danger[data-v-75be84e5]:hover:not(:disabled){background:color-mix(in srgb, var(--color-danger) 8%, transparent);color:var(--text-danger);border-color:color-mix(in srgb, var(--color-danger) 30%, transparent)}.sch-form[data-v-75be84e5]{flex-direction:column;gap:14px;display:flex}.sch-field[data-v-75be84e5]{flex-direction:column;gap:6px;display:flex}.sch-field-label[data-v-75be84e5]{color:var(--text-secondary);font-size:12px}.sch-input[data-v-75be84e5]{box-sizing:border-box;width:100%;color:var(--text-primary);background:var(--bg-container);border:1px solid var(--border-color-medium);border-radius:6px;outline:none;padding:6px 10px;font-family:inherit;font-size:13px;transition:border-color .15s}.sch-input[data-v-75be84e5]:focus{border-color:var(--tint-primary-55)}.sch-select[data-v-75be84e5]{cursor:pointer}.sch-select-sm[data-v-75be84e5]{width:auto;min-width:64px}.sch-input-cron[data-v-75be84e5]{font-family:var(--font-mono,monospace)}.sch-textarea[data-v-75be84e5]{resize:vertical;min-height:72px;line-height:1.6}.sch-freq-row[data-v-75be84e5]{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.sch-inline-label[data-v-75be84e5]{color:var(--text-secondary);white-space:nowrap;font-size:12px}.sch-hint[data-v-75be84e5]{color:var(--text-tertiary);font-size:11px}.sch-radio-row[data-v-75be84e5]{flex-wrap:wrap;align-items:center;gap:16px;display:flex}.sch-radio[data-v-75be84e5]{color:var(--text-secondary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:inline-flex}.sch-radio input[data-v-75be84e5]{accent-color:var(--color-primary);cursor:pointer;margin:0}.sch-form-error[data-v-75be84e5]{color:var(--text-danger);margin:0;font-size:12px}.sch-form-footer[data-v-75be84e5]{justify-content:flex-end;gap:8px;margin-top:14px;display:flex}.sch-confirm-text[data-v-75be84e5]{color:var(--text-primary);margin:0;font-size:13px;line-height:1.7}.aps[data-v-ae77c09c]{background:var(--bg-container);flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.aps__scroll[data-v-ae77c09c]{flex-direction:column;flex:1;gap:14px;max-width:860px;min-height:0;padding:16px 18px 24px;line-height:1.5;display:flex;overflow-y:auto}.aps__head[data-v-ae77c09c]{flex-direction:column;gap:5px;display:flex}.aps__title[data-v-ae77c09c]{font-size:var(--font-size-lg);color:var(--text-primary);margin:0;font-weight:600}.aps__intro[data-v-ae77c09c]{font-size:var(--font-size-sm);color:var(--text-meta);margin:0;line-height:1.6}.aps__card[data-v-ae77c09c]{background:var(--bg-panel);border:1px solid var(--border-color);border-radius:var(--radius-lg);flex-direction:column;gap:9px;padding:14px 16px;display:flex}.aps__card-head[data-v-ae77c09c]{align-items:baseline;gap:8px;display:flex}.aps__card-title[data-v-ae77c09c]{font-size:var(--font-size-mid);color:var(--text-primary);margin:0;font-weight:600}.aps__label[data-v-ae77c09c]{font-size:var(--font-size-sm);color:var(--text-secondary);font-weight:500}.aps__count[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta);font-variant-numeric:tabular-nums;margin-left:auto}.aps__field[data-v-ae77c09c]{flex-direction:column;gap:5px;display:flex}.aps__hint[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta);margin:0;line-height:1.6}.aps__area[data-v-ae77c09c]{box-sizing:border-box;resize:vertical;width:100%;min-height:92px;max-height:320px;font-size:var(--font-size-mid);color:var(--text-primary);background:var(--bg-subtle);border:1px solid var(--border-color);border-radius:var(--radius-md);transition:border-color var(--transition-fast) var(--ease-custom);outline:none;padding:7px 9px;font-family:inherit;line-height:1.5}.aps__area[data-v-ae77c09c]:focus{border-color:var(--color-primary)}.aps__area[data-v-ae77c09c]::placeholder{color:var(--text-meta)}.aps__area[data-v-ae77c09c]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.aps__foot[data-v-ae77c09c]{align-items:center;gap:8px;display:flex}.aps__spacer[data-v-ae77c09c]{flex:1}.aps__saved[data-v-ae77c09c]{font-size:var(--font-size-xs);color:var(--text-meta)}.aps__btn[data-v-ae77c09c]{color:var(--text-secondary);font-size:var(--font-size-sm);border-radius:var(--radius-md);cursor:pointer;transition:color var(--transition-fast) var(--ease-custom), background var(--transition-fast) var(--ease-custom);background:0 0;border:none;padding:0 12px;line-height:28px}.aps__btn[data-v-ae77c09c]:hover:not(:disabled){color:var(--color-primary);background:var(--bg-container-hover)}.aps__btn[data-v-ae77c09c]:disabled{opacity:var(--disabled-opacity);cursor:default}.aps__btn[data-v-ae77c09c]:focus-visible{outline:var(--focus-outline);outline-offset:1px}.aps__btn--primary[data-v-ae77c09c]{background:var(--color-primary);color:#fff}.aps__btn--primary[data-v-ae77c09c]:hover:not(:disabled){background:var(--color-primary);color:#fff;opacity:.88}.agent-view[data-v-aabe911d]{background:var(--bg-container);height:100%;min-height:0;display:flex}.agent-sidebar[data-v-aabe911d]{background:var(--bg-panel);border-right:1px solid var(--border-color);flex-direction:column;flex-shrink:0;display:flex;overflow:hidden}.agent-conversations[data-v-aabe911d]{flex:1;min-height:0;padding:10px 6px 8px 12px}.sidebar-resizer[data-v-aabe911d]{cursor:col-resize;width:4px;transition:background var(--transition-fast) ease;background:0 0;flex-shrink:0}.sidebar-resizer[data-v-aabe911d]:hover,.sidebar-resizer.active[data-v-aabe911d]{background:var(--color-primary);opacity:.3}.agent-chat-area[data-v-aabe911d]{flex-direction:column;flex:1;min-width:0;display:flex;position:relative;overflow:hidden}.agent-engine[data-v-aabe911d]{margin-bottom:7px;margin-left:auto}.agent-copy[data-v-aabe911d]{margin-bottom:7px;margin-left:2px}.agent-tabs[data-v-aabe911d]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:4px;padding:8px 12px 0;display:flex}.agent-tab[data-v-aabe911d]{color:var(--text-meta);font-size:var(--font-size-mid);cursor:pointer;transition:color var(--transition-fast) ease, border-color var(--transition-fast) ease, background var(--transition-fast) ease;border-radius:var(--radius-base) var(--radius-base) 0 0;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;padding:7px 14px 9px;font-family:inherit;display:inline-flex}.agent-tab[data-v-aabe911d]:hover{color:var(--text-secondary);background:var(--bg-hover)}.agent-tab.active[data-v-aabe911d]{color:var(--color-primary);border-bottom-color:var(--color-primary);font-weight:600}.agent-tab-body[data-v-aabe911d]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-pane[data-v-aabe911d]{flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.agent-tab-body[data-v-aabe911d]>.marketplace-panel{flex:1;min-height:0}.chat-loading[data-v-aabe911d]{color:var(--text-meta);font-size:var(--font-size-base);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}.agent-list-page[data-v-aabe911d]{background:var(--bg-panel);flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-list-page .agent-conversations[data-v-aabe911d]{padding:12px 12px 10px 14px}.agent-page-bar[data-v-aabe911d]{border-bottom:1px solid var(--border-color);background:var(--bg-panel);flex-shrink:0;align-items:center;gap:6px;height:34px;padding:0 12px 0 6px;display:flex}.agent-page-back[data-v-aabe911d]{border-radius:var(--radius-xs);width:24px;height:24px;color:var(--text-meta);cursor:pointer;transition:var(--transition-ui-fast);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:flex}.agent-page-back[data-v-aabe911d]:hover{background:var(--bg-hover);color:var(--text-secondary)}.agent-page-title[data-v-aabe911d]{min-width:0;font-size:var(--font-size-mid);color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.agent-chat-host[data-v-aabe911d]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.agent-chat-host[data-v-aabe911d] .acu-avatar--left{background:0 0}.agent-chat-host[data-v-aabe911d] .acu-bubble-row.is-assistant .acu-bubble-main{width:var(--acu-bubble-max-width);max-width:var(--acu-bubble-max-width);position:relative}.agent-chat-host[data-v-aabe911d] .acu-bubble-row.is-assistant .acu-bubble{align-self:flex-start}.agent-chat-host[data-v-aabe911d] .acu-message-meta{margin:0;position:absolute;top:0;right:0}.agent-chat-host[data-v-aabe911d] .acu-input-queue{--acu-queue-edge:var(--role-pending-edge);--acu-queue-surface:var(--role-pending-surface);--acu-queue-ink:var(--role-pending-ink);--acu-queue-wash:var(--role-pending-wash)}.agent-chat-host[data-v-aabe911d] .acu-welcome-logo{background:var(--welcome-avatar) center/46px 46px no-repeat;width:56px;height:56px;box-shadow:none}.agent-chat-host[data-v-aabe911d] .acu-welcome-logo>svg{display:none}.agent-chat-host[data-v-aabe911d] .acu-welcome-grid{flex-wrap:wrap;display:flex}.agent-chat-host[data-v-aabe911d] .acu-welcome-grid>.acu-preset-q{flex:260px;min-width:0}[data-theme=dark]{background:var(--bg-panel)}
|