dsh-agy-link 0.4.44 → 0.4.49
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/CHANGELOG.md +210 -0
- package/README.md +1 -0
- package/dist/assets/mermaid.min.js +3636 -0
- package/dist/client.js +1948 -262
- package/dist/index.js +4957 -3033
- package/docs/KNOWN-GAPS.md +18 -0
- package/docs/README.en.md +1 -0
- package/docs/README.es.md +1 -0
- package/docs/README.pt-BR.md +1 -0
- package/docs/adr-012-account-pool.md +6 -2
- package/docs/merge-2026-10-13-review.md +102 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -8,12 +8,16 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
const BRAND_PATHS = {
|
|
9
9
|
gemini: "M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81",
|
|
10
10
|
claude: "m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z",
|
|
11
|
-
openai: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"
|
|
11
|
+
openai: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z",
|
|
12
|
+
chrome: "M12 0C8.21 0 4.831 1.757 2.632 4.501l3.953 6.848A5.454 5.454 0 0 1 12 6.545h10.73c-.911-3.794-4.321-6.545-8.384-6.545zM1.986 6.368A11.95 11.95 0 0 0 0 12c0 6.096 4.542 11.134 10.428 11.89l3.953-6.848a5.454 5.454 0 0 1-5.836-2.585L1.986 6.368zm14.569 5.632a5.454 5.454 0 0 1-1.127 3.327l-5.365 9.293C10.784 24.873 11.385 25 12 25c6.627 0 12-5.373 12-12 0-.341-.014-.679-.042-1.013H12v.013h4.555z",
|
|
13
|
+
edge: "M23.95 13.91c-.13-1.68-.78-3.23-1.83-4.47-.98-1.16-2.29-1.99-3.76-2.4-.64-.18-1.3-.28-1.97-.29-2.09-.03-4.08.74-5.63 2.16-1.57 1.44-2.48 3.44-2.55 5.56.08 1.47.66 2.87 1.66 3.96.99 1.09 2.37 1.76 3.86 1.88 1.34.1 2.69-.26 3.82-1.02.44-.3.84-.66 1.18-1.07l2.87 2.87c-1.35 1.44-3.04 2.51-4.92 3.12-1.89.6-3.9.7-5.84.28-2.67-.58-5.06-2.06-6.75-4.17-1.68-2.12-2.59-4.78-2.57-7.51.02-2.85 1.04-5.6 2.89-7.77C6.88 4.31 9.53 2.85 12.44 2.38c2.19-.35 4.43-.2 6.55.45 2.13.65 4.04 1.83 5.58 3.44l-2.9 2.9c-1.12-1.19-2.52-2.06-4.07-2.54-1.55-.47-3.19-.57-4.78-.3-2.14.36-4.08 1.45-5.46 3.06-1.38 1.62-2.13 3.69-2.13 5.84 0 2.05.69 4.04 1.98 5.62 1.28 1.58 3.1 2.64 5.12 3.01 1.47.27 2.99.17 4.42-.31 1.43-.48 2.7-1.33 3.69-2.46l-4.13-4.13c-.37.28-.8.48-1.26.58-.46.1-.94.09-1.4-.02-.57-.14-1.08-.47-1.46-.93-.38-.46-.59-1.04-.59-1.64.03-.84.4-1.63 1.03-2.2.63-.57 1.45-.88 2.3-.87.87.01 1.7.35 2.32.95.62.61.98 1.43 1 2.3h4.67z"
|
|
12
14
|
};
|
|
13
15
|
const BRAND_COLORS = {
|
|
14
16
|
gemini: "#8E75B2",
|
|
15
17
|
claude: "#D97757",
|
|
16
|
-
openai: "#10a37f"
|
|
18
|
+
openai: "#10a37f",
|
|
19
|
+
chrome: "#4285F4",
|
|
20
|
+
edge: "#0078D7"
|
|
17
21
|
};
|
|
18
22
|
const UI_PATHS = {
|
|
19
23
|
trash: "M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M10 11v6M14 11v6",
|
|
@@ -28,7 +32,10 @@ window.__ModuleLoader__.load({
|
|
|
28
32
|
check: "M20 6L9 17l-5-5",
|
|
29
33
|
x: "M18 6L6 18M6 6l12 12",
|
|
30
34
|
externalLink: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3",
|
|
31
|
-
alert: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0zM12 9v4M12 17h.01"
|
|
35
|
+
alert: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0zM12 9v4M12 17h.01",
|
|
36
|
+
move: "M9 5h.01M9 12h.01M9 19h.01M15 5h.01M15 12h.01M15 19h.01",
|
|
37
|
+
arrowUp: "M12 19V5M5 12l7-7 7 7",
|
|
38
|
+
arrowDown: "M12 5v14M19 12l-7 7-7-7"
|
|
32
39
|
};
|
|
33
40
|
//#endregion
|
|
34
41
|
//#region src/client/locales.ts
|
|
@@ -39,6 +46,25 @@ window.__ModuleLoader__.load({
|
|
|
39
46
|
"section.label": "Antigravity",
|
|
40
47
|
"code.title": "代码",
|
|
41
48
|
"code.inspect": "检查",
|
|
49
|
+
"tv.command": "命令",
|
|
50
|
+
"tv.write": "写入",
|
|
51
|
+
"tv.edit": "编辑",
|
|
52
|
+
"tv.read": "读取",
|
|
53
|
+
"tv.search": "搜索",
|
|
54
|
+
"tv.webSearch": "网页搜索",
|
|
55
|
+
"tv.list": "列表",
|
|
56
|
+
"tv.delete": "删除",
|
|
57
|
+
"tv.tool": "工具",
|
|
58
|
+
"tv.noOutput": "(无输出)",
|
|
59
|
+
"tv.noMatches": "(无匹配)",
|
|
60
|
+
"tv.noChanges": "(无文本变更)",
|
|
61
|
+
"tv.emptyDir": "(空目录)",
|
|
62
|
+
"tv.noDetail": "(无详情)",
|
|
63
|
+
"tv.hint.expandInspect": "点击展开 · 右键检查",
|
|
64
|
+
"tv.hint.collapseInspect": "点击收起 · 右键检查",
|
|
65
|
+
"tv.hint.expand": "点击展开",
|
|
66
|
+
"tv.hint.collapse": "点击收起",
|
|
67
|
+
"tv.diffMore": "… 其余 {count} 行未渲染",
|
|
42
68
|
"code.copy": "复制",
|
|
43
69
|
"code.copied": "已复制",
|
|
44
70
|
"console.title": "Antigravity 管理控制台",
|
|
@@ -52,6 +78,7 @@ window.__ModuleLoader__.load({
|
|
|
52
78
|
"account.add": "添加 Google 账号",
|
|
53
79
|
"account.aliasDefault": "备用 Google 账号 {number}",
|
|
54
80
|
"account.defaultAlias": "主账号(系统登录)",
|
|
81
|
+
"account.proxyPlaceholder": "专属代理 URL(如 http://127.0.0.1:7890,留空则继承全局)",
|
|
55
82
|
"account.aliasPlaceholder": "账号别名(例如:备用账号 2)",
|
|
56
83
|
"account.removeTitle": "移除此账号",
|
|
57
84
|
"aria.aliasInput": "账号别名",
|
|
@@ -62,6 +89,9 @@ window.__ModuleLoader__.load({
|
|
|
62
89
|
"account.settingPrimary": "设置中",
|
|
63
90
|
"account.details": "明细",
|
|
64
91
|
"account.collapse": "收起",
|
|
92
|
+
"account.expandOthers": "展开查看 Claude & GPT-OSS 模型额度",
|
|
93
|
+
"account.collapseOthers": "收起 Claude & GPT-OSS 模型额度",
|
|
94
|
+
"account.otherModels": "Claude / GPT 额度",
|
|
65
95
|
"account.sync": "同步",
|
|
66
96
|
"account.syncing": "同步中",
|
|
67
97
|
"account.syncTitle": "刷新此账号(换号后立即同步 email / 额度 / 模型)",
|
|
@@ -127,13 +157,46 @@ window.__ModuleLoader__.load({
|
|
|
127
157
|
"header.refreshQuota": "刷新额度",
|
|
128
158
|
"header.refreshing": "刷新中",
|
|
129
159
|
"console.close": "关闭(Esc)",
|
|
130
|
-
"header.badgeTitle": "Antigravity:{count} 个账号已就绪 · 点击打开控制台"
|
|
160
|
+
"header.badgeTitle": "Antigravity:{count} 个账号已就绪 · 点击打开控制台",
|
|
161
|
+
"header.badgeLoading": "Antigravity · 点击打开控制台",
|
|
162
|
+
"account.type.agy": "Google Antigravity (CLI / OAuth)",
|
|
163
|
+
"account.loginType": "登录方式:",
|
|
164
|
+
"account.dragHandle": "拖拽调整优先级",
|
|
165
|
+
"account.moveUp": "上移优先级",
|
|
166
|
+
"account.moveDown": "下移优先级",
|
|
167
|
+
"account.reordered": "账号优先级顺序已更新",
|
|
168
|
+
"account.collapseAll": "全部折叠",
|
|
169
|
+
"account.expandAll": "全部展开",
|
|
170
|
+
"account.cardCollapse": "收起详情",
|
|
171
|
+
"account.cardExpand": "展开详情",
|
|
172
|
+
"account.draggingTarget": "放置至此成为优先级 #{num}",
|
|
173
|
+
"account.dragBanner": "正在调整优先级:将【{alias}】移动至 #{num}",
|
|
174
|
+
"account.dragHint": "拖拽卡片可实时调整调度优先级"
|
|
131
175
|
};
|
|
132
176
|
const en = {
|
|
133
177
|
"section.label": "Antigravity",
|
|
134
178
|
"console.title": "Antigravity Management Console",
|
|
135
179
|
"code.title": "Code",
|
|
136
180
|
"code.inspect": "Inspect",
|
|
181
|
+
"tv.command": "Command",
|
|
182
|
+
"tv.write": "Write",
|
|
183
|
+
"tv.edit": "Edit",
|
|
184
|
+
"tv.read": "Read",
|
|
185
|
+
"tv.search": "Search",
|
|
186
|
+
"tv.webSearch": "Web Search",
|
|
187
|
+
"tv.list": "List",
|
|
188
|
+
"tv.delete": "Delete",
|
|
189
|
+
"tv.tool": "Tool",
|
|
190
|
+
"tv.noOutput": "(no output)",
|
|
191
|
+
"tv.noMatches": "(no matches)",
|
|
192
|
+
"tv.noChanges": "(no textual changes)",
|
|
193
|
+
"tv.emptyDir": "(empty directory)",
|
|
194
|
+
"tv.noDetail": "(no detail)",
|
|
195
|
+
"tv.hint.expandInspect": "Click to expand · right-click to inspect",
|
|
196
|
+
"tv.hint.collapseInspect": "Click to collapse · right-click to inspect",
|
|
197
|
+
"tv.hint.expand": "Click to expand",
|
|
198
|
+
"tv.hint.collapse": "Click to collapse",
|
|
199
|
+
"tv.diffMore": "… {count} more lines not rendered",
|
|
137
200
|
"code.copy": "Copy",
|
|
138
201
|
"code.copied": "Copied",
|
|
139
202
|
"status.ready": "Ready",
|
|
@@ -146,6 +209,7 @@ window.__ModuleLoader__.load({
|
|
|
146
209
|
"account.add": "Add Google account",
|
|
147
210
|
"account.aliasDefault": "Backup Google account {number}",
|
|
148
211
|
"account.defaultAlias": "Primary account (system sign-in)",
|
|
212
|
+
"account.proxyPlaceholder": "Dedicated proxy URL (e.g. http://127.0.0.1:7890; leave blank to inherit global)",
|
|
149
213
|
"account.aliasPlaceholder": "Account alias (for example: Backup account 2)",
|
|
150
214
|
"account.removeTitle": "Remove this account",
|
|
151
215
|
"aria.aliasInput": "Account alias",
|
|
@@ -156,6 +220,9 @@ window.__ModuleLoader__.load({
|
|
|
156
220
|
"account.settingPrimary": "Setting...",
|
|
157
221
|
"account.details": "Details",
|
|
158
222
|
"account.collapse": "Collapse",
|
|
223
|
+
"account.expandOthers": "Expand Claude & GPT-OSS quotas",
|
|
224
|
+
"account.collapseOthers": "Collapse Claude & GPT-OSS quotas",
|
|
225
|
+
"account.otherModels": "Claude / GPT quotas",
|
|
159
226
|
"account.sync": "Sync",
|
|
160
227
|
"account.syncing": "Syncing...",
|
|
161
228
|
"account.syncTitle": "Refresh this account (sync email, quota, and models after switching accounts)",
|
|
@@ -221,13 +288,46 @@ window.__ModuleLoader__.load({
|
|
|
221
288
|
"header.refreshQuota": "Refresh quota",
|
|
222
289
|
"header.refreshing": "Refreshing...",
|
|
223
290
|
"console.close": "Close (Esc)",
|
|
224
|
-
"header.badgeTitle": "Antigravity: {count} accounts ready · click to open the console"
|
|
291
|
+
"header.badgeTitle": "Antigravity: {count} accounts ready · click to open the console",
|
|
292
|
+
"header.badgeLoading": "Antigravity · click to open the console",
|
|
293
|
+
"account.type.agy": "Google Antigravity (CLI / OAuth)",
|
|
294
|
+
"account.loginType": "Login Method:",
|
|
295
|
+
"account.dragHandle": "Drag to reorder priority",
|
|
296
|
+
"account.moveUp": "Move up priority",
|
|
297
|
+
"account.moveDown": "Move down priority",
|
|
298
|
+
"account.reordered": "Account priorities reordered successfully",
|
|
299
|
+
"account.collapseAll": "Collapse all",
|
|
300
|
+
"account.expandAll": "Expand all",
|
|
301
|
+
"account.cardCollapse": "Collapse",
|
|
302
|
+
"account.cardExpand": "Expand details",
|
|
303
|
+
"account.draggingTarget": "Drop here to set priority #{num}",
|
|
304
|
+
"account.dragBanner": "Reordering: moving [{alias}] to priority #{num}",
|
|
305
|
+
"account.dragHint": "Drag cards to reorder scheduling priority in real time"
|
|
225
306
|
};
|
|
226
307
|
const ptBR = {
|
|
227
308
|
"section.label": "Antigravity",
|
|
228
309
|
"console.title": "Console de gerenciamento do Antigravity",
|
|
229
310
|
"code.title": "Código",
|
|
230
311
|
"code.inspect": "Inspecionar",
|
|
312
|
+
"tv.command": "Comando",
|
|
313
|
+
"tv.write": "Escrever",
|
|
314
|
+
"tv.edit": "Editar",
|
|
315
|
+
"tv.read": "Ler",
|
|
316
|
+
"tv.search": "Buscar",
|
|
317
|
+
"tv.webSearch": "Busca na web",
|
|
318
|
+
"tv.list": "Listar",
|
|
319
|
+
"tv.delete": "Excluir",
|
|
320
|
+
"tv.tool": "Ferramenta",
|
|
321
|
+
"tv.noOutput": "(sem saída)",
|
|
322
|
+
"tv.noMatches": "(nenhuma correspondência)",
|
|
323
|
+
"tv.noChanges": "(sem alterações de texto)",
|
|
324
|
+
"tv.emptyDir": "(diretório vazio)",
|
|
325
|
+
"tv.noDetail": "(sem detalhes)",
|
|
326
|
+
"tv.hint.expandInspect": "Clique para expandir · clique direito para inspecionar",
|
|
327
|
+
"tv.hint.collapseInspect": "Clique para recolher · clique direito para inspecionar",
|
|
328
|
+
"tv.hint.expand": "Clique para expandir",
|
|
329
|
+
"tv.hint.collapse": "Clique para recolher",
|
|
330
|
+
"tv.diffMore": "… {count} linhas restantes não renderizadas",
|
|
231
331
|
"code.copy": "Copiar",
|
|
232
332
|
"code.copied": "Copiado",
|
|
233
333
|
"status.ready": "Pronto",
|
|
@@ -240,6 +340,7 @@ window.__ModuleLoader__.load({
|
|
|
240
340
|
"account.add": "Adicionar conta Google",
|
|
241
341
|
"account.aliasDefault": "Conta Google reserva {number}",
|
|
242
342
|
"account.defaultAlias": "Conta principal (login do sistema)",
|
|
343
|
+
"account.proxyPlaceholder": "URL de proxy dedicada (ex.: http://127.0.0.1:7890; deixe vazio para herdar a global)",
|
|
243
344
|
"account.aliasPlaceholder": "Apelido da conta (por exemplo: Conta reserva 2)",
|
|
244
345
|
"account.removeTitle": "Remover esta conta",
|
|
245
346
|
"aria.aliasInput": "Apelido da conta",
|
|
@@ -250,6 +351,9 @@ window.__ModuleLoader__.load({
|
|
|
250
351
|
"account.settingPrimary": "Definindo...",
|
|
251
352
|
"account.details": "Detalhes",
|
|
252
353
|
"account.collapse": "Recolher",
|
|
354
|
+
"account.expandOthers": "Expandir cotas Claude e GPT-OSS",
|
|
355
|
+
"account.collapseOthers": "Recolher cotas Claude e GPT-OSS",
|
|
356
|
+
"account.otherModels": "Cotas Claude / GPT",
|
|
253
357
|
"account.sync": "Sincronizar",
|
|
254
358
|
"account.syncing": "Sincronizando...",
|
|
255
359
|
"account.syncTitle": "Atualizar esta conta (sincroniza e-mail, cota e modelos depois de trocar de conta)",
|
|
@@ -315,13 +419,46 @@ window.__ModuleLoader__.load({
|
|
|
315
419
|
"header.refreshQuota": "Atualizar cota",
|
|
316
420
|
"header.refreshing": "Atualizando...",
|
|
317
421
|
"console.close": "Fechar (Esc)",
|
|
318
|
-
"header.badgeTitle": "Antigravity: {count} contas prontas · clique para abrir o console"
|
|
422
|
+
"header.badgeTitle": "Antigravity: {count} contas prontas · clique para abrir o console",
|
|
423
|
+
"header.badgeLoading": "Antigravity · clique para abrir o console",
|
|
424
|
+
"account.type.agy": "Google Antigravity (CLI / OAuth)",
|
|
425
|
+
"account.loginType": "Tipo de login:",
|
|
426
|
+
"account.dragHandle": "Arrastar para reordenar prioridade",
|
|
427
|
+
"account.moveUp": "Subir prioridade",
|
|
428
|
+
"account.moveDown": "Descer prioridade",
|
|
429
|
+
"account.reordered": "Prioridade das contas reordenada com sucesso",
|
|
430
|
+
"account.collapseAll": "Recolher todos",
|
|
431
|
+
"account.expandAll": "Expandir todos",
|
|
432
|
+
"account.cardCollapse": "Recolher",
|
|
433
|
+
"account.cardExpand": "Expandir detalhes",
|
|
434
|
+
"account.draggingTarget": "Soltar aqui para prioridade #{num}",
|
|
435
|
+
"account.dragBanner": "Reordenando: movendo [{alias}] para #{num}",
|
|
436
|
+
"account.dragHint": "Arraste os cartões para reordenar a prioridade em tempo real"
|
|
319
437
|
};
|
|
320
438
|
const es = {
|
|
321
439
|
"section.label": "Antigravity",
|
|
322
440
|
"console.title": "Consola de administración de Antigravity",
|
|
323
441
|
"code.title": "Código",
|
|
324
442
|
"code.inspect": "Inspeccionar",
|
|
443
|
+
"tv.command": "Comando",
|
|
444
|
+
"tv.write": "Escribir",
|
|
445
|
+
"tv.edit": "Editar",
|
|
446
|
+
"tv.read": "Leer",
|
|
447
|
+
"tv.search": "Buscar",
|
|
448
|
+
"tv.webSearch": "Búsqueda web",
|
|
449
|
+
"tv.list": "Listar",
|
|
450
|
+
"tv.delete": "Eliminar",
|
|
451
|
+
"tv.tool": "Herramienta",
|
|
452
|
+
"tv.noOutput": "(sin salida)",
|
|
453
|
+
"tv.noMatches": "(sin coincidencias)",
|
|
454
|
+
"tv.noChanges": "(sin cambios de texto)",
|
|
455
|
+
"tv.emptyDir": "(directorio vacío)",
|
|
456
|
+
"tv.noDetail": "(sin detalles)",
|
|
457
|
+
"tv.hint.expandInspect": "Clic para expandir · clic derecho para inspeccionar",
|
|
458
|
+
"tv.hint.collapseInspect": "Clic para contraer · clic derecho para inspeccionar",
|
|
459
|
+
"tv.hint.expand": "Clic para expandir",
|
|
460
|
+
"tv.hint.collapse": "Clic para contraer",
|
|
461
|
+
"tv.diffMore": "… {count} líneas restantes no renderizadas",
|
|
325
462
|
"code.copy": "Copiar",
|
|
326
463
|
"code.copied": "Copiado",
|
|
327
464
|
"status.ready": "Listo",
|
|
@@ -334,6 +471,7 @@ window.__ModuleLoader__.load({
|
|
|
334
471
|
"account.add": "Añadir cuenta de Google",
|
|
335
472
|
"account.aliasDefault": "Cuenta de Google de respaldo {number}",
|
|
336
473
|
"account.defaultAlias": "Cuenta principal (inicio de sesión del sistema)",
|
|
474
|
+
"account.proxyPlaceholder": "URL de proxy dedicada (p. ej., http://127.0.0.1:7890; déjalo vacío para heredar la global)",
|
|
337
475
|
"account.aliasPlaceholder": "Alias de la cuenta (por ejemplo: Cuenta de respaldo 2)",
|
|
338
476
|
"account.removeTitle": "Eliminar esta cuenta",
|
|
339
477
|
"aria.aliasInput": "Alias de la cuenta",
|
|
@@ -344,6 +482,9 @@ window.__ModuleLoader__.load({
|
|
|
344
482
|
"account.settingPrimary": "Configurando...",
|
|
345
483
|
"account.details": "Detalles",
|
|
346
484
|
"account.collapse": "Contraer",
|
|
485
|
+
"account.expandOthers": "Expandir cuotas Claude y GPT-OSS",
|
|
486
|
+
"account.collapseOthers": "Contraer cuotas Claude y GPT-OSS",
|
|
487
|
+
"account.otherModels": "Cuotas Claude / GPT",
|
|
347
488
|
"account.sync": "Sincronizar",
|
|
348
489
|
"account.syncing": "Sincronizando...",
|
|
349
490
|
"account.syncTitle": "Actualizar esta cuenta (sincroniza correo, cuota y modelos tras cambiar de cuenta)",
|
|
@@ -409,9 +550,729 @@ window.__ModuleLoader__.load({
|
|
|
409
550
|
"header.refreshQuota": "Actualizar cuota",
|
|
410
551
|
"header.refreshing": "Actualizando...",
|
|
411
552
|
"console.close": "Cerrar (Esc)",
|
|
412
|
-
"header.badgeTitle": "Antigravity: {count} cuentas listas · haga clic para abrir la consola"
|
|
553
|
+
"header.badgeTitle": "Antigravity: {count} cuentas listas · haga clic para abrir la consola",
|
|
554
|
+
"header.badgeLoading": "Antigravity · haga clic para abrir la consola",
|
|
555
|
+
"account.type.agy": "Google Antigravity (CLI / OAuth)",
|
|
556
|
+
"account.loginType": "Tipo de inicio de sesión:",
|
|
557
|
+
"account.dragHandle": "Arrastrar para reordenar prioridad",
|
|
558
|
+
"account.moveUp": "Subir prioridad",
|
|
559
|
+
"account.moveDown": "Bajar prioridad",
|
|
560
|
+
"account.reordered": "Prioridad de cuentas reordenada con éxito",
|
|
561
|
+
"account.collapseAll": "Contraer todo",
|
|
562
|
+
"account.expandAll": "Expandir todo",
|
|
563
|
+
"account.cardCollapse": "Contraer",
|
|
564
|
+
"account.cardExpand": "Expandir detalles",
|
|
565
|
+
"account.draggingTarget": "Soltar aquí para prioridad #{num}",
|
|
566
|
+
"account.dragBanner": "Reordenando: moviendo [{alias}] a #{num}",
|
|
567
|
+
"account.dragHint": "Arrastre las tarjetas para reordenar la prioridad en tiempo real"
|
|
413
568
|
};
|
|
414
569
|
//#endregion
|
|
570
|
+
//#region src/client/decisions.ts
|
|
571
|
+
const DECISION_CSS = `
|
|
572
|
+
.agy-decision-container {
|
|
573
|
+
margin: 10px 0 6px 0;
|
|
574
|
+
padding: 10px 12px;
|
|
575
|
+
border-radius: 8px;
|
|
576
|
+
background: var(--dsw-alias-bg-l2, rgba(127, 127, 127, 0.07));
|
|
577
|
+
border: 1px dashed var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.3));
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.agy-decision-header {
|
|
581
|
+
font-size: 12px;
|
|
582
|
+
font-weight: 600;
|
|
583
|
+
color: var(--dsw-alias-label-secondary, #aaa);
|
|
584
|
+
margin-bottom: 8px;
|
|
585
|
+
display: flex;
|
|
586
|
+
align-items: center;
|
|
587
|
+
gap: 6px;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.agy-decision-chips {
|
|
591
|
+
display: flex;
|
|
592
|
+
flex-wrap: wrap;
|
|
593
|
+
gap: 8px;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.agy-decision-chip {
|
|
597
|
+
background: var(--dsw-alias-bg-l1, rgba(255, 255, 255, 0.05));
|
|
598
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.25));
|
|
599
|
+
color: var(--dsw-alias-label-primary, #eee);
|
|
600
|
+
padding: 5px 12px;
|
|
601
|
+
border-radius: 999px;
|
|
602
|
+
cursor: pointer;
|
|
603
|
+
font-size: 12px;
|
|
604
|
+
font-weight: 500;
|
|
605
|
+
display: inline-flex;
|
|
606
|
+
align-items: center;
|
|
607
|
+
gap: 6px;
|
|
608
|
+
transition: all 0.15s ease;
|
|
609
|
+
user-select: none;
|
|
610
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
611
|
+
text-align: left;
|
|
612
|
+
max-width: 100%;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.agy-decision-chip:hover {
|
|
616
|
+
background: var(--dsw-alias-bg-hover, rgba(127, 127, 127, 0.18));
|
|
617
|
+
border-color: var(--dsw-alias-border-l4, rgba(127, 127, 127, 0.5));
|
|
618
|
+
transform: translateY(-1px);
|
|
619
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.agy-decision-chip:active {
|
|
623
|
+
transform: translateY(0);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
.agy-decision-chip.selected {
|
|
627
|
+
background: rgba(16, 185, 129, 0.15);
|
|
628
|
+
border-color: #10b981;
|
|
629
|
+
color: #10b981;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.agy-decision-chip-num {
|
|
633
|
+
font-weight: 700;
|
|
634
|
+
opacity: 0.8;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.agy-decision-chip-text {
|
|
638
|
+
overflow: hidden;
|
|
639
|
+
text-overflow: ellipsis;
|
|
640
|
+
white-space: nowrap;
|
|
641
|
+
}
|
|
642
|
+
`;
|
|
643
|
+
function injectStyles$3() {
|
|
644
|
+
if (typeof document === "undefined") return;
|
|
645
|
+
const styleId = "dsh-agy-link-decisions-css";
|
|
646
|
+
if (document.getElementById(styleId) === null) {
|
|
647
|
+
const st = document.createElement("style");
|
|
648
|
+
st.id = styleId;
|
|
649
|
+
st.textContent = DECISION_CSS;
|
|
650
|
+
const host = document.head ?? document.documentElement;
|
|
651
|
+
if (host) host.appendChild(st);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Insert text directly into DSH's chat composer
|
|
656
|
+
*/
|
|
657
|
+
function insertTextIntoChatComposer(text) {
|
|
658
|
+
if (typeof document === "undefined" || !text) return false;
|
|
659
|
+
const inputEl = document.querySelector("[data-composer-input]") ?? document.querySelector("[role=\"textbox\"][contenteditable=\"true\"]") ?? document.querySelector("textarea");
|
|
660
|
+
if (!inputEl) return false;
|
|
661
|
+
inputEl.focus();
|
|
662
|
+
if (inputEl instanceof HTMLTextAreaElement || inputEl instanceof HTMLInputElement) {
|
|
663
|
+
const start = inputEl.selectionStart ?? inputEl.value.length;
|
|
664
|
+
const end = inputEl.selectionEnd ?? inputEl.value.length;
|
|
665
|
+
inputEl.setRangeText(text, start, end, "end");
|
|
666
|
+
inputEl.dispatchEvent(new Event("input", { bubbles: true }));
|
|
667
|
+
inputEl.dispatchEvent(new Event("change", { bubbles: true }));
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
if (document.execCommand("insertText", false, text)) return true;
|
|
672
|
+
} catch {}
|
|
673
|
+
const existing = inputEl.textContent?.trim() ?? "";
|
|
674
|
+
inputEl.textContent = existing ? `${existing} ${text}` : text;
|
|
675
|
+
inputEl.dispatchEvent(new InputEvent("input", {
|
|
676
|
+
bubbles: true,
|
|
677
|
+
inputType: "insertText",
|
|
678
|
+
data: text
|
|
679
|
+
}));
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
/** Check if text header suggests an actionable decision or choice prompt */
|
|
683
|
+
const DECISION_HEADER_REGEX = /(?:请(?:您)?(?:拍板|指示|决定|选择|决策)|decision|next\s+step|choose|拍板|选择方案)/i;
|
|
684
|
+
/** Extract numbered options or choice items from a decision list */
|
|
685
|
+
function extractOptionsFromList(container) {
|
|
686
|
+
const options = [];
|
|
687
|
+
const listItems = container.querySelectorAll("li");
|
|
688
|
+
if (listItems.length > 0) for (let i = 0; i < listItems.length; i++) {
|
|
689
|
+
const li = listItems[i];
|
|
690
|
+
if (!li) continue;
|
|
691
|
+
const text = (li.textContent ?? "").trim();
|
|
692
|
+
if (!text) continue;
|
|
693
|
+
const m = text.match(/^([0-9]+[、..:]\s*)?(.*?)(?:[::—\-·]|\n|$)/);
|
|
694
|
+
const num = m?.[1]?.trim() ?? `${i + 1}.`;
|
|
695
|
+
let title = m?.[2]?.trim() || text.slice(0, 50);
|
|
696
|
+
if (title.length > 40) title = title.slice(0, 40) + "…";
|
|
697
|
+
options.push({
|
|
698
|
+
num,
|
|
699
|
+
title,
|
|
700
|
+
fullText: text
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
return options;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Scan DOM for decision prompts and mount interactive choice chips
|
|
707
|
+
*/
|
|
708
|
+
function scanAndEnhanceDecisions() {
|
|
709
|
+
if (typeof document === "undefined") return;
|
|
710
|
+
const markdownContainers = document.querySelectorAll("div[class*=\"_markdown_\"], [data-markdown-variant]");
|
|
711
|
+
for (let i = 0; i < markdownContainers.length; i++) {
|
|
712
|
+
const container = markdownContainers[i];
|
|
713
|
+
if (!container || container.dataset.agyDecisionsScanned === "true") continue;
|
|
714
|
+
const headings = container.querySelectorAll("h2, h3, h4, p > strong");
|
|
715
|
+
for (let j = 0; j < headings.length; j++) {
|
|
716
|
+
const heading = headings[j];
|
|
717
|
+
if (!heading || heading.dataset.agyDecisionAttached === "true") continue;
|
|
718
|
+
const headingText = (heading.textContent ?? "").trim();
|
|
719
|
+
if (!DECISION_HEADER_REGEX.test(headingText)) continue;
|
|
720
|
+
let sibling = heading.nextElementSibling;
|
|
721
|
+
let targetList = null;
|
|
722
|
+
while (sibling) {
|
|
723
|
+
if (sibling.tagName === "OL" || sibling.tagName === "UL") {
|
|
724
|
+
targetList = sibling;
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
if (/^H[1-4]$/.test(sibling.tagName)) break;
|
|
728
|
+
sibling = sibling.nextElementSibling;
|
|
729
|
+
}
|
|
730
|
+
if (!targetList) continue;
|
|
731
|
+
const options = extractOptionsFromList(targetList);
|
|
732
|
+
if (options.length === 0) continue;
|
|
733
|
+
heading.dataset.agyDecisionAttached = "true";
|
|
734
|
+
const box = document.createElement("div");
|
|
735
|
+
box.className = "agy-decision-container";
|
|
736
|
+
const header = document.createElement("div");
|
|
737
|
+
header.className = "agy-decision-header";
|
|
738
|
+
header.innerHTML = "<span>💬 点击选项快速填入:</span>";
|
|
739
|
+
box.appendChild(header);
|
|
740
|
+
const chips = document.createElement("div");
|
|
741
|
+
chips.className = "agy-decision-chips";
|
|
742
|
+
for (const opt of options) {
|
|
743
|
+
const chip = document.createElement("button");
|
|
744
|
+
chip.type = "button";
|
|
745
|
+
chip.className = "agy-decision-chip";
|
|
746
|
+
chip.title = `点击填入: ${opt.fullText}`;
|
|
747
|
+
const numSpan = document.createElement("span");
|
|
748
|
+
numSpan.className = "agy-decision-chip-num";
|
|
749
|
+
numSpan.textContent = opt.num ?? "👉";
|
|
750
|
+
const textSpan = document.createElement("span");
|
|
751
|
+
textSpan.className = "agy-decision-chip-text";
|
|
752
|
+
textSpan.textContent = opt.title;
|
|
753
|
+
chip.appendChild(numSpan);
|
|
754
|
+
chip.appendChild(textSpan);
|
|
755
|
+
chip.onclick = (e) => {
|
|
756
|
+
e.stopPropagation();
|
|
757
|
+
const cleanText = opt.fullText.replace(/^[0-9]+[、..:]\s*/, "").trim();
|
|
758
|
+
insertTextIntoChatComposer(`我选择 ${opt.num ? opt.num + " " : ""}${cleanText}`);
|
|
759
|
+
chip.classList.add("selected");
|
|
760
|
+
setTimeout(() => chip.classList.remove("selected"), 1200);
|
|
761
|
+
};
|
|
762
|
+
chips.appendChild(chip);
|
|
763
|
+
}
|
|
764
|
+
box.appendChild(chips);
|
|
765
|
+
targetList.parentNode?.insertBefore(box, targetList.nextSibling);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
let decisionChipsDispose = null;
|
|
770
|
+
function installDecisionChips() {
|
|
771
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
772
|
+
decisionChipsDispose?.();
|
|
773
|
+
injectStyles$3();
|
|
774
|
+
const observer = new MutationObserver(() => {
|
|
775
|
+
scanAndEnhanceDecisions();
|
|
776
|
+
});
|
|
777
|
+
const setup = () => {
|
|
778
|
+
if (document.body) {
|
|
779
|
+
observer.observe(document.body, {
|
|
780
|
+
childList: true,
|
|
781
|
+
subtree: true
|
|
782
|
+
});
|
|
783
|
+
scanAndEnhanceDecisions();
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", setup, { once: true });
|
|
787
|
+
else setup();
|
|
788
|
+
const dispose = () => {
|
|
789
|
+
observer.disconnect();
|
|
790
|
+
window.removeEventListener("DOMContentLoaded", setup);
|
|
791
|
+
if (decisionChipsDispose === dispose) decisionChipsDispose = null;
|
|
792
|
+
};
|
|
793
|
+
decisionChipsDispose = dispose;
|
|
794
|
+
return dispose;
|
|
795
|
+
}
|
|
796
|
+
//#endregion
|
|
797
|
+
//#region src/client/images.ts
|
|
798
|
+
let lightboxOverlay = null;
|
|
799
|
+
let lightboxScale = 1;
|
|
800
|
+
let lightboxTranslateX = 0;
|
|
801
|
+
let lightboxTranslateY = 0;
|
|
802
|
+
let isDraggingLightbox = false;
|
|
803
|
+
let dragStartX = 0;
|
|
804
|
+
let dragStartY = 0;
|
|
805
|
+
const IMAGE_CSS = `
|
|
806
|
+
.agy-image-card {
|
|
807
|
+
display: inline-flex;
|
|
808
|
+
flex-direction: column;
|
|
809
|
+
margin: 6px 0;
|
|
810
|
+
max-width: 100%;
|
|
811
|
+
border-radius: 8px;
|
|
812
|
+
overflow: hidden;
|
|
813
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.25));
|
|
814
|
+
background: var(--dsw-alias-bg-l1, rgba(255, 255, 255, 0.03));
|
|
815
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
816
|
+
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
817
|
+
vertical-align: middle;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.agy-image-card:hover {
|
|
821
|
+
border-color: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.45));
|
|
822
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.agy-image-thumb-wrap {
|
|
826
|
+
position: relative;
|
|
827
|
+
overflow: hidden;
|
|
828
|
+
max-height: 480px;
|
|
829
|
+
cursor: zoom-in;
|
|
830
|
+
display: flex;
|
|
831
|
+
align-items: center;
|
|
832
|
+
justify-content: center;
|
|
833
|
+
background: repeating-conic-gradient(rgba(127,127,127,0.08) 0% 25%, transparent 0% 50%) 50% / 16px 16px;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.agy-image-thumb {
|
|
837
|
+
display: block;
|
|
838
|
+
max-width: 100%;
|
|
839
|
+
max-height: 480px;
|
|
840
|
+
height: auto;
|
|
841
|
+
object-fit: contain;
|
|
842
|
+
transition: transform 0.2s ease;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
.agy-image-card:hover .agy-image-thumb {
|
|
846
|
+
transform: scale(1.015);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.agy-image-caption {
|
|
850
|
+
padding: 6px 10px;
|
|
851
|
+
font-size: 11.5px;
|
|
852
|
+
color: var(--dsw-alias-label-secondary, #aaa);
|
|
853
|
+
background: var(--dsw-alias-bg-l2, rgba(127, 127, 127, 0.08));
|
|
854
|
+
border-top: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.15));
|
|
855
|
+
display: flex;
|
|
856
|
+
align-items: center;
|
|
857
|
+
justify-content: space-between;
|
|
858
|
+
gap: 8px;
|
|
859
|
+
overflow: hidden;
|
|
860
|
+
text-overflow: ellipsis;
|
|
861
|
+
white-space: nowrap;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.agy-image-link-chip {
|
|
865
|
+
display: inline-flex;
|
|
866
|
+
align-items: center;
|
|
867
|
+
gap: 4px;
|
|
868
|
+
padding: 2px 6px;
|
|
869
|
+
margin: 0 2px;
|
|
870
|
+
border-radius: 4px;
|
|
871
|
+
font-size: 12px;
|
|
872
|
+
background: var(--dsw-alias-bg-l2, rgba(127, 127, 127, 0.1));
|
|
873
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.2));
|
|
874
|
+
color: var(--dsw-alias-label-primary, #ddd);
|
|
875
|
+
cursor: pointer;
|
|
876
|
+
text-decoration: none;
|
|
877
|
+
transition: all 0.15s ease;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.agy-image-link-chip:hover {
|
|
881
|
+
background: var(--dsw-alias-bg-hover, rgba(127, 127, 127, 0.2));
|
|
882
|
+
border-color: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.35));
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/* Lightbox Modal */
|
|
886
|
+
.agy-lightbox-backdrop {
|
|
887
|
+
position: fixed;
|
|
888
|
+
inset: 0;
|
|
889
|
+
z-index: 999999;
|
|
890
|
+
background: rgba(0, 0, 0, 0.85);
|
|
891
|
+
backdrop-filter: blur(8px);
|
|
892
|
+
display: flex;
|
|
893
|
+
flex-direction: column;
|
|
894
|
+
user-select: none;
|
|
895
|
+
opacity: 0;
|
|
896
|
+
transition: opacity 0.2s ease;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.agy-lightbox-backdrop.open {
|
|
900
|
+
opacity: 1;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
.agy-lightbox-header {
|
|
904
|
+
height: 48px;
|
|
905
|
+
display: flex;
|
|
906
|
+
align-items: center;
|
|
907
|
+
justify-content: space-between;
|
|
908
|
+
padding: 0 16px;
|
|
909
|
+
background: rgba(20, 20, 20, 0.65);
|
|
910
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
911
|
+
color: #fff;
|
|
912
|
+
font-size: 13px;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
.agy-lightbox-title {
|
|
916
|
+
font-weight: 500;
|
|
917
|
+
overflow: hidden;
|
|
918
|
+
text-overflow: ellipsis;
|
|
919
|
+
white-space: nowrap;
|
|
920
|
+
max-width: 60%;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
.agy-lightbox-actions {
|
|
924
|
+
display: flex;
|
|
925
|
+
align-items: center;
|
|
926
|
+
gap: 8px;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.agy-lightbox-btn {
|
|
930
|
+
background: rgba(255, 255, 255, 0.1);
|
|
931
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
932
|
+
color: #fff;
|
|
933
|
+
border-radius: 6px;
|
|
934
|
+
padding: 4px 10px;
|
|
935
|
+
cursor: pointer;
|
|
936
|
+
font-size: 12px;
|
|
937
|
+
display: inline-flex;
|
|
938
|
+
align-items: center;
|
|
939
|
+
gap: 4px;
|
|
940
|
+
transition: all 0.15s ease;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.agy-lightbox-btn:hover {
|
|
944
|
+
background: rgba(255, 255, 255, 0.2);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
.agy-lightbox-btn-close {
|
|
948
|
+
background: rgba(239, 68, 68, 0.25);
|
|
949
|
+
border-color: rgba(239, 68, 68, 0.4);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.agy-lightbox-btn-close:hover {
|
|
953
|
+
background: rgba(239, 68, 68, 0.45);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.agy-lightbox-body {
|
|
957
|
+
flex: 1;
|
|
958
|
+
position: relative;
|
|
959
|
+
overflow: hidden;
|
|
960
|
+
display: flex;
|
|
961
|
+
align-items: center;
|
|
962
|
+
justify-content: center;
|
|
963
|
+
cursor: grab;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
.agy-lightbox-body.grabbing {
|
|
967
|
+
cursor: grabbing;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.agy-lightbox-img-wrap {
|
|
971
|
+
transform-origin: center center;
|
|
972
|
+
transition: transform 0.05s ease-out;
|
|
973
|
+
display: inline-block;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.agy-lightbox-img {
|
|
977
|
+
max-width: 90vw;
|
|
978
|
+
max-height: 85vh;
|
|
979
|
+
object-fit: contain;
|
|
980
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
|
981
|
+
border-radius: 4px;
|
|
982
|
+
pointer-events: none;
|
|
983
|
+
}
|
|
984
|
+
`;
|
|
985
|
+
function injectStyles$2() {
|
|
986
|
+
if (typeof document === "undefined") return;
|
|
987
|
+
const styleId = "dsh-agy-link-images-css";
|
|
988
|
+
if (document.getElementById(styleId) === null) {
|
|
989
|
+
const st = document.createElement("style");
|
|
990
|
+
st.id = styleId;
|
|
991
|
+
st.textContent = IMAGE_CSS;
|
|
992
|
+
const host = document.head ?? document.documentElement;
|
|
993
|
+
if (host) host.appendChild(st);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function getOrigin() {
|
|
997
|
+
if (typeof window !== "undefined" && window.location?.origin) return window.location.origin;
|
|
998
|
+
return "";
|
|
999
|
+
}
|
|
1000
|
+
/** Build media URL from path */
|
|
1001
|
+
function buildMediaUrl(rawPath) {
|
|
1002
|
+
return `${getOrigin()}/plugins/agy-link/media?path=${encodeURIComponent(rawPath.trim())}`;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Open fullscreen Lightbox modal
|
|
1006
|
+
*/
|
|
1007
|
+
function openLightbox(src, title = "Image Preview", rawPath) {
|
|
1008
|
+
if (typeof document === "undefined") return;
|
|
1009
|
+
injectStyles$2();
|
|
1010
|
+
if (lightboxOverlay) {
|
|
1011
|
+
lightboxOverlay.remove();
|
|
1012
|
+
lightboxOverlay = null;
|
|
1013
|
+
}
|
|
1014
|
+
lightboxScale = 1;
|
|
1015
|
+
lightboxTranslateX = 0;
|
|
1016
|
+
lightboxTranslateY = 0;
|
|
1017
|
+
const overlay = document.createElement("div");
|
|
1018
|
+
overlay.className = "agy-lightbox-backdrop";
|
|
1019
|
+
const header = document.createElement("div");
|
|
1020
|
+
header.className = "agy-lightbox-header";
|
|
1021
|
+
const titleEl = document.createElement("div");
|
|
1022
|
+
titleEl.className = "agy-lightbox-title";
|
|
1023
|
+
titleEl.textContent = title;
|
|
1024
|
+
header.appendChild(titleEl);
|
|
1025
|
+
const actions = document.createElement("div");
|
|
1026
|
+
actions.className = "agy-lightbox-actions";
|
|
1027
|
+
const btnZoomIn = document.createElement("button");
|
|
1028
|
+
btnZoomIn.className = "agy-lightbox-btn";
|
|
1029
|
+
btnZoomIn.textContent = "🔍+";
|
|
1030
|
+
btnZoomIn.title = "放大 / Zoom In";
|
|
1031
|
+
const btnZoomOut = document.createElement("button");
|
|
1032
|
+
btnZoomOut.className = "agy-lightbox-btn";
|
|
1033
|
+
btnZoomOut.textContent = "🔍-";
|
|
1034
|
+
btnZoomOut.title = "缩小 / Zoom Out";
|
|
1035
|
+
const btnReset = document.createElement("button");
|
|
1036
|
+
btnReset.className = "agy-lightbox-btn";
|
|
1037
|
+
btnReset.textContent = "1:1";
|
|
1038
|
+
btnReset.title = "实际大小 / Reset";
|
|
1039
|
+
actions.appendChild(btnZoomIn);
|
|
1040
|
+
actions.appendChild(btnZoomOut);
|
|
1041
|
+
actions.appendChild(btnReset);
|
|
1042
|
+
if (rawPath) {
|
|
1043
|
+
const btnCopyPath = document.createElement("button");
|
|
1044
|
+
btnCopyPath.className = "agy-lightbox-btn";
|
|
1045
|
+
btnCopyPath.textContent = "📋 复制路径";
|
|
1046
|
+
btnCopyPath.onclick = (e) => {
|
|
1047
|
+
e.stopPropagation();
|
|
1048
|
+
if (navigator.clipboard) navigator.clipboard.writeText(rawPath).then(() => {
|
|
1049
|
+
btnCopyPath.textContent = "✓ 已复制";
|
|
1050
|
+
setTimeout(() => {
|
|
1051
|
+
btnCopyPath.textContent = "📋 复制路径";
|
|
1052
|
+
}, 1500);
|
|
1053
|
+
}).catch(() => {});
|
|
1054
|
+
};
|
|
1055
|
+
actions.appendChild(btnCopyPath);
|
|
1056
|
+
}
|
|
1057
|
+
const btnClose = document.createElement("button");
|
|
1058
|
+
btnClose.className = "agy-lightbox-btn agy-lightbox-btn-close";
|
|
1059
|
+
btnClose.textContent = "✕ 关闭";
|
|
1060
|
+
actions.appendChild(btnClose);
|
|
1061
|
+
header.appendChild(actions);
|
|
1062
|
+
overlay.appendChild(header);
|
|
1063
|
+
const body = document.createElement("div");
|
|
1064
|
+
body.className = "agy-lightbox-body";
|
|
1065
|
+
const imgWrap = document.createElement("div");
|
|
1066
|
+
imgWrap.className = "agy-lightbox-img-wrap";
|
|
1067
|
+
const img = document.createElement("img");
|
|
1068
|
+
img.className = "agy-lightbox-img";
|
|
1069
|
+
img.src = src;
|
|
1070
|
+
img.alt = title;
|
|
1071
|
+
imgWrap.appendChild(img);
|
|
1072
|
+
body.appendChild(imgWrap);
|
|
1073
|
+
overlay.appendChild(body);
|
|
1074
|
+
const updateTransform = () => {
|
|
1075
|
+
imgWrap.style.transform = `translate(${lightboxTranslateX}px, ${lightboxTranslateY}px) scale(${lightboxScale})`;
|
|
1076
|
+
};
|
|
1077
|
+
btnZoomIn.onclick = (e) => {
|
|
1078
|
+
e.stopPropagation();
|
|
1079
|
+
lightboxScale = Math.min(lightboxScale * 1.3, 5);
|
|
1080
|
+
updateTransform();
|
|
1081
|
+
};
|
|
1082
|
+
btnZoomOut.onclick = (e) => {
|
|
1083
|
+
e.stopPropagation();
|
|
1084
|
+
lightboxScale = Math.max(lightboxScale / 1.3, .2);
|
|
1085
|
+
updateTransform();
|
|
1086
|
+
};
|
|
1087
|
+
btnReset.onclick = (e) => {
|
|
1088
|
+
e.stopPropagation();
|
|
1089
|
+
lightboxScale = 1;
|
|
1090
|
+
lightboxTranslateX = 0;
|
|
1091
|
+
lightboxTranslateY = 0;
|
|
1092
|
+
updateTransform();
|
|
1093
|
+
};
|
|
1094
|
+
const closeLightbox = () => {
|
|
1095
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
1096
|
+
overlay.classList.remove("open");
|
|
1097
|
+
setTimeout(() => {
|
|
1098
|
+
overlay.remove();
|
|
1099
|
+
if (lightboxOverlay === overlay) lightboxOverlay = null;
|
|
1100
|
+
}, 200);
|
|
1101
|
+
};
|
|
1102
|
+
btnClose.onclick = (e) => {
|
|
1103
|
+
e.stopPropagation();
|
|
1104
|
+
closeLightbox();
|
|
1105
|
+
};
|
|
1106
|
+
overlay.onclick = (e) => {
|
|
1107
|
+
if (e.target === overlay || e.target === body) closeLightbox();
|
|
1108
|
+
};
|
|
1109
|
+
const onKeyDown = (e) => {
|
|
1110
|
+
if (e.key === "Escape") closeLightbox();
|
|
1111
|
+
};
|
|
1112
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1113
|
+
body.onmousedown = (e) => {
|
|
1114
|
+
isDraggingLightbox = true;
|
|
1115
|
+
dragStartX = e.clientX - lightboxTranslateX;
|
|
1116
|
+
dragStartY = e.clientY - lightboxTranslateY;
|
|
1117
|
+
body.classList.add("grabbing");
|
|
1118
|
+
};
|
|
1119
|
+
const onMouseMove = (e) => {
|
|
1120
|
+
if (!isDraggingLightbox) return;
|
|
1121
|
+
lightboxTranslateX = e.clientX - dragStartX;
|
|
1122
|
+
lightboxTranslateY = e.clientY - dragStartY;
|
|
1123
|
+
updateTransform();
|
|
1124
|
+
};
|
|
1125
|
+
const onMouseUp = () => {
|
|
1126
|
+
if (isDraggingLightbox) {
|
|
1127
|
+
isDraggingLightbox = false;
|
|
1128
|
+
body.classList.remove("grabbing");
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
window.addEventListener("mousemove", onMouseMove);
|
|
1132
|
+
window.addEventListener("mouseup", onMouseUp);
|
|
1133
|
+
body.onwheel = (e) => {
|
|
1134
|
+
e.preventDefault();
|
|
1135
|
+
const factor = e.deltaY < 0 ? 1.15 : .87;
|
|
1136
|
+
lightboxScale = Math.max(.2, Math.min(lightboxScale * factor, 5));
|
|
1137
|
+
updateTransform();
|
|
1138
|
+
};
|
|
1139
|
+
document.body.appendChild(overlay);
|
|
1140
|
+
lightboxOverlay = overlay;
|
|
1141
|
+
requestAnimationFrame(() => overlay.classList.add("open"));
|
|
1142
|
+
}
|
|
1143
|
+
/** Check if a URL or path is an image */
|
|
1144
|
+
function isImageFile(pathOrUrl) {
|
|
1145
|
+
if (!pathOrUrl || typeof pathOrUrl !== "string") return false;
|
|
1146
|
+
const clean = pathOrUrl.split(/[?#]/)[0] ?? "";
|
|
1147
|
+
return /\.(png|jpe?g|webp|gif|svg|bmp|ico|avif)$/i.test(clean);
|
|
1148
|
+
}
|
|
1149
|
+
/** Get React props of a DOM element */
|
|
1150
|
+
function getReactProps(el) {
|
|
1151
|
+
const key = Object.keys(el).find((k) => k.startsWith("__reactProps"));
|
|
1152
|
+
if (!key) return null;
|
|
1153
|
+
return el[key];
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Scan DOM for imageAlt spans and enhance them with live rendered images
|
|
1157
|
+
*/
|
|
1158
|
+
function scanAndEnhanceImages() {
|
|
1159
|
+
if (typeof document === "undefined") return;
|
|
1160
|
+
const origin = getOrigin();
|
|
1161
|
+
if (origin && !origin.includes("127.0.0.1") && !origin.includes("localhost")) {
|
|
1162
|
+
const images = document.querySelectorAll("img[src*=\"/plugins/agy-link/media\"]");
|
|
1163
|
+
for (let i = 0; i < images.length; i++) {
|
|
1164
|
+
const img = images[i];
|
|
1165
|
+
if (img && img.src.includes("127.0.0.1")) {
|
|
1166
|
+
const u = new URL(img.src);
|
|
1167
|
+
img.src = `${origin}${u.pathname}${u.search}`;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
const markdownContainers = document.querySelectorAll("div[class*=\"_markdown_\"], [data-markdown-variant]");
|
|
1172
|
+
for (let i = 0; i < markdownContainers.length; i++) {
|
|
1173
|
+
const container = markdownContainers[i];
|
|
1174
|
+
if (!container) continue;
|
|
1175
|
+
const altSpans = container.querySelectorAll("span[class*=\"imageAlt\"], span[class*=\"_imageAlt_\"]");
|
|
1176
|
+
if (altSpans.length === 0) continue;
|
|
1177
|
+
const props = getReactProps(container);
|
|
1178
|
+
const mdText = typeof props?.text === "string" ? props.text : "";
|
|
1179
|
+
if (!mdText) continue;
|
|
1180
|
+
const imgMatches = [];
|
|
1181
|
+
const re = /!\[(.*?)\]\((file:\/\/\/[^\s)]+|file:\/\/[^\s)]+|[A-Za-z]:[\\/][^\s)]+|\/home\/[^\s)]+|\/mnt\/[a-zA-Z]\/[^\s)]+|\\\\wsl\.localhost\\[^\s)]+)\)/g;
|
|
1182
|
+
let m;
|
|
1183
|
+
while ((m = re.exec(mdText)) !== null) imgMatches.push({
|
|
1184
|
+
alt: m[1] ?? "",
|
|
1185
|
+
target: m[2] ?? ""
|
|
1186
|
+
});
|
|
1187
|
+
if (imgMatches.length === 0) continue;
|
|
1188
|
+
for (let j = 0; j < altSpans.length; j++) {
|
|
1189
|
+
const span = altSpans[j];
|
|
1190
|
+
if (!span || span.dataset.agyEnhanced === "true") continue;
|
|
1191
|
+
const altText = (span.textContent ?? "").trim();
|
|
1192
|
+
const match = imgMatches.find((im) => im.alt.trim() === altText) ?? imgMatches[j];
|
|
1193
|
+
if (!match) continue;
|
|
1194
|
+
span.dataset.agyEnhanced = "true";
|
|
1195
|
+
const mediaUrl = buildMediaUrl(match.target);
|
|
1196
|
+
const card = document.createElement("div");
|
|
1197
|
+
card.className = "agy-image-card";
|
|
1198
|
+
const thumbWrap = document.createElement("div");
|
|
1199
|
+
thumbWrap.className = "agy-image-thumb-wrap";
|
|
1200
|
+
thumbWrap.title = `${altText || "Image"} (点击全屏放大)`;
|
|
1201
|
+
const img = document.createElement("img");
|
|
1202
|
+
img.className = "agy-image-thumb";
|
|
1203
|
+
img.src = mediaUrl;
|
|
1204
|
+
img.alt = altText || "Preview";
|
|
1205
|
+
img.loading = "lazy";
|
|
1206
|
+
img.onerror = () => {
|
|
1207
|
+
card.style.display = "none";
|
|
1208
|
+
span.style.display = "";
|
|
1209
|
+
};
|
|
1210
|
+
thumbWrap.appendChild(img);
|
|
1211
|
+
card.appendChild(thumbWrap);
|
|
1212
|
+
if (altText) {
|
|
1213
|
+
const caption = document.createElement("div");
|
|
1214
|
+
caption.className = "agy-image-caption";
|
|
1215
|
+
caption.textContent = altText;
|
|
1216
|
+
card.appendChild(caption);
|
|
1217
|
+
}
|
|
1218
|
+
thumbWrap.onclick = (e) => {
|
|
1219
|
+
e.stopPropagation();
|
|
1220
|
+
openLightbox(mediaUrl, altText || "Image Preview", match.target);
|
|
1221
|
+
};
|
|
1222
|
+
span.style.display = "none";
|
|
1223
|
+
span.parentNode?.insertBefore(card, span);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
const links = document.querySelectorAll("a[href^=\"file://\"]");
|
|
1227
|
+
for (let i = 0; i < links.length; i++) {
|
|
1228
|
+
const link = links[i];
|
|
1229
|
+
if (!link || link.dataset.agyLinkEnhanced === "true") continue;
|
|
1230
|
+
const href = link.href ?? "";
|
|
1231
|
+
if (!isImageFile(href)) continue;
|
|
1232
|
+
link.dataset.agyLinkEnhanced = "true";
|
|
1233
|
+
const mediaUrl = buildMediaUrl(href);
|
|
1234
|
+
const linkText = link.textContent ?? "Image";
|
|
1235
|
+
link.onclick = (e) => {
|
|
1236
|
+
e.preventDefault();
|
|
1237
|
+
e.stopPropagation();
|
|
1238
|
+
openLightbox(mediaUrl, linkText, href);
|
|
1239
|
+
};
|
|
1240
|
+
if (!link.querySelector(".agy-image-link-icon")) {
|
|
1241
|
+
const badge = document.createElement("span");
|
|
1242
|
+
badge.className = "agy-image-link-chip agy-image-link-icon";
|
|
1243
|
+
badge.textContent = "🖼️ 预览";
|
|
1244
|
+
link.appendChild(badge);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
let imageEnhancerDispose = null;
|
|
1249
|
+
function installImageEnhancer() {
|
|
1250
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
1251
|
+
imageEnhancerDispose?.();
|
|
1252
|
+
injectStyles$2();
|
|
1253
|
+
const observer = new MutationObserver(() => {
|
|
1254
|
+
scanAndEnhanceImages();
|
|
1255
|
+
});
|
|
1256
|
+
const setup = () => {
|
|
1257
|
+
if (document.body) {
|
|
1258
|
+
observer.observe(document.body, {
|
|
1259
|
+
childList: true,
|
|
1260
|
+
subtree: true
|
|
1261
|
+
});
|
|
1262
|
+
scanAndEnhanceImages();
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", setup, { once: true });
|
|
1266
|
+
else setup();
|
|
1267
|
+
const dispose = () => {
|
|
1268
|
+
observer.disconnect();
|
|
1269
|
+
window.removeEventListener("DOMContentLoaded", setup);
|
|
1270
|
+
if (imageEnhancerDispose === dispose) imageEnhancerDispose = null;
|
|
1271
|
+
};
|
|
1272
|
+
imageEnhancerDispose = dispose;
|
|
1273
|
+
return dispose;
|
|
1274
|
+
}
|
|
1275
|
+
//#endregion
|
|
415
1276
|
//#region src/client/toolview.ts
|
|
416
1277
|
function react() {
|
|
417
1278
|
const mod = require("react");
|
|
@@ -604,6 +1465,40 @@ window.__ModuleLoader__.load({
|
|
|
604
1465
|
fill: "currentColor"
|
|
605
1466
|
}));
|
|
606
1467
|
}
|
|
1468
|
+
function IconQuestionOutline16(size = 14, className = "") {
|
|
1469
|
+
return hx("svg", {
|
|
1470
|
+
width: size,
|
|
1471
|
+
height: size,
|
|
1472
|
+
className: className || void 0,
|
|
1473
|
+
viewBox: "0 0 16 16",
|
|
1474
|
+
fill: "none",
|
|
1475
|
+
style: {
|
|
1476
|
+
display: "block",
|
|
1477
|
+
flexShrink: 0
|
|
1478
|
+
},
|
|
1479
|
+
"aria-hidden": true
|
|
1480
|
+
}, hx("path", {
|
|
1481
|
+
d: "M8 1C4.134 1 1 3.91 1 7.5c0 1.547.575 2.973 1.559 4.093L1.13 14.54a.5.5 0 00.627.63l3.238-1.079C5.875 14.316 6.91 14.5 8 14.5c3.866 0 7-2.91 7-6.5S11.866 1 8 1zm0 10.5a.75.75 0 110-1.5.75.75 0 010 1.5zm1.09-3.41c-.42.34-.59.54-.59.91H7.5v-.5c0-.66.36-1.12.82-1.48.44-.35.68-.61.68-1.02 0-.55-.45-1-1-1s-1 .45-1 1H6c0-1.1.9-2 2-2s2 .9 2 2c0 .73-.39 1.25-.91 1.67z",
|
|
1482
|
+
fill: "currentColor"
|
|
1483
|
+
}));
|
|
1484
|
+
}
|
|
1485
|
+
function IconImageOutline16(size = 14, className = "") {
|
|
1486
|
+
return hx("svg", {
|
|
1487
|
+
width: size,
|
|
1488
|
+
height: size,
|
|
1489
|
+
className: className || void 0,
|
|
1490
|
+
viewBox: "0 0 16 16",
|
|
1491
|
+
fill: "none",
|
|
1492
|
+
style: {
|
|
1493
|
+
display: "block",
|
|
1494
|
+
flexShrink: 0
|
|
1495
|
+
},
|
|
1496
|
+
"aria-hidden": true
|
|
1497
|
+
}, hx("path", {
|
|
1498
|
+
d: "M14 3H2a1 1 0 00-1 1v8a1 1 0 001 1h12a1 1 0 001-1V4a1 1 0 00-1-1zm-1 8H3l2.5-3.2 1.8 2.3 2.7-3.5L13 11zM5.5 6a1.5 1.5 0 110-3 1.5 1.5 0 010 3z",
|
|
1499
|
+
fill: "currentColor"
|
|
1500
|
+
}));
|
|
1501
|
+
}
|
|
607
1502
|
function toolIconFor(kind, size = 14) {
|
|
608
1503
|
switch (kind) {
|
|
609
1504
|
case "terminal": return IconApiOutline14(size);
|
|
@@ -612,6 +1507,8 @@ window.__ModuleLoader__.load({
|
|
|
612
1507
|
case "read": return IconBrowseOutline16(size);
|
|
613
1508
|
case "search":
|
|
614
1509
|
case "list": return IconSearchOutline16(size);
|
|
1510
|
+
case "question": return IconQuestionOutline16(size);
|
|
1511
|
+
case "image": return IconImageOutline16(size);
|
|
615
1512
|
default: return IconCodeOutline16(size);
|
|
616
1513
|
}
|
|
617
1514
|
}
|
|
@@ -705,7 +1602,9 @@ window.__ModuleLoader__.load({
|
|
|
705
1602
|
"grep_search",
|
|
706
1603
|
"search",
|
|
707
1604
|
"search_file_content",
|
|
708
|
-
"grep"
|
|
1605
|
+
"grep",
|
|
1606
|
+
"search_web",
|
|
1607
|
+
"web_search"
|
|
709
1608
|
]);
|
|
710
1609
|
const LIST_TOOLS = /* @__PURE__ */ new Set(["list_dir", "ls"]);
|
|
711
1610
|
const DELETE_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -713,6 +1612,16 @@ window.__ModuleLoader__.load({
|
|
|
713
1612
|
"remove_file",
|
|
714
1613
|
"rm"
|
|
715
1614
|
]);
|
|
1615
|
+
const QUESTION_TOOLS = /* @__PURE__ */ new Set([
|
|
1616
|
+
"ask_question",
|
|
1617
|
+
"ask",
|
|
1618
|
+
"question"
|
|
1619
|
+
]);
|
|
1620
|
+
const IMAGE_TOOLS = /* @__PURE__ */ new Set([
|
|
1621
|
+
"generate_image",
|
|
1622
|
+
"create_image",
|
|
1623
|
+
"render_image"
|
|
1624
|
+
]);
|
|
716
1625
|
function mirrorCardModel(block, cwd, home) {
|
|
717
1626
|
const info = mirrorInfo(block);
|
|
718
1627
|
const out = resultText(block);
|
|
@@ -724,6 +1633,33 @@ window.__ModuleLoader__.load({
|
|
|
724
1633
|
};
|
|
725
1634
|
const { tool, input } = info;
|
|
726
1635
|
const desc = pick(input, "Description", "description", "toolAction", "toolSummary", "Instruction", "instruction");
|
|
1636
|
+
if (QUESTION_TOOLS.has(tool)) {
|
|
1637
|
+
const questionsRaw = input.questions ?? input.Questions;
|
|
1638
|
+
const questions = Array.isArray(questionsRaw) ? questionsRaw : [];
|
|
1639
|
+
return {
|
|
1640
|
+
kind: "question",
|
|
1641
|
+
tool,
|
|
1642
|
+
title: questions[0]?.question ?? desc ?? "Ask Question",
|
|
1643
|
+
output: out,
|
|
1644
|
+
questions,
|
|
1645
|
+
raw: parsedArgsRaw(block)
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1648
|
+
if (IMAGE_TOOLS.has(tool)) {
|
|
1649
|
+
const prompt = pick(input, "Prompt", "prompt") ?? "";
|
|
1650
|
+
const name = pick(input, "ImageName", "image_name", "name") ?? "image";
|
|
1651
|
+
const ratio = pick(input, "AspectRatio", "aspect_ratio") ?? "1:1";
|
|
1652
|
+
return {
|
|
1653
|
+
kind: "image",
|
|
1654
|
+
tool,
|
|
1655
|
+
title: desc ?? `Generate Image · ${name}`,
|
|
1656
|
+
prompt,
|
|
1657
|
+
imageName: name,
|
|
1658
|
+
aspectRatio: ratio,
|
|
1659
|
+
output: out,
|
|
1660
|
+
raw: parsedArgsRaw(block)
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
727
1663
|
if (TERMINAL_TOOLS.has(tool)) {
|
|
728
1664
|
const command = pick(input, "CommandLine", "command_line", "command", "cmd", "Cmd") ?? JSON.stringify(input);
|
|
729
1665
|
const cwdVal = pick(input, "Cwd", "cwd", "WorkingDirectory", "working_directory") ?? cwd;
|
|
@@ -757,12 +1693,17 @@ window.__ModuleLoader__.load({
|
|
|
757
1693
|
const path = pick(input, "AbsolutePath", "absolute_path", "TargetFile", "target_file", "path", "file_path", "filename", "Path", "FilePath", "FileName", "targetFile") ?? "";
|
|
758
1694
|
const offset = num(input, "offset", "Offset") ?? num(input, "StartLine", "start_line");
|
|
759
1695
|
const line = offset !== void 0 ? offset > 0 && (tool === "view_file" || tool === "read_file") ? offset : offset + 1 : void 0;
|
|
1696
|
+
const isImg = isImageFile(path);
|
|
760
1697
|
return {
|
|
761
|
-
kind: "read",
|
|
1698
|
+
kind: isImg ? "image" : "read",
|
|
762
1699
|
tool,
|
|
763
1700
|
title: desc ? `${desc} · ${path}` : path !== "" ? "Read " + path : "Read",
|
|
764
1701
|
path,
|
|
765
1702
|
output: out,
|
|
1703
|
+
isImage: isImg,
|
|
1704
|
+
imagePath: isImg ? path : void 0,
|
|
1705
|
+
prompt: desc,
|
|
1706
|
+
imageName: path.split(/[/\\]/).pop() || "image",
|
|
766
1707
|
...path !== "" ? { location: {
|
|
767
1708
|
path,
|
|
768
1709
|
...line !== void 0 ? { line } : {}
|
|
@@ -833,15 +1774,32 @@ window.__ModuleLoader__.load({
|
|
|
833
1774
|
function cls(...names) {
|
|
834
1775
|
return names.filter((n) => typeof n === "string" && n !== "").join(" ");
|
|
835
1776
|
}
|
|
836
|
-
|
|
1777
|
+
/**
|
|
1778
|
+
* Locale lookup with an English fallback: the mirror card renders through
|
|
1779
|
+
* host-provided `t` when the registration declares the namespace, but tests
|
|
1780
|
+
* and hosts without the seat call it bare. The old literals were mixed
|
|
1781
|
+
* 中文 and English as BOTH fallback and primary, so non-Chinese users saw
|
|
1782
|
+
* Chinese buttons on mirror cards.
|
|
1783
|
+
*/
|
|
1784
|
+
function tr(t, key, fallback, params) {
|
|
1785
|
+
if (typeof t === "function") try {
|
|
1786
|
+
const v = t(key, params);
|
|
1787
|
+
if (typeof v === "string" && v !== "" && v !== key) return v;
|
|
1788
|
+
} catch {}
|
|
1789
|
+
if (params !== void 0 && params.count !== void 0 && fallback.includes("{count}")) return fallback.replace("{count}", String(params.count));
|
|
1790
|
+
return fallback;
|
|
1791
|
+
}
|
|
1792
|
+
function displayTitle(model, t) {
|
|
837
1793
|
switch (model.kind) {
|
|
838
|
-
case "terminal": return "Command";
|
|
839
|
-
case "diff": return model.tool === "write_to_file" || model.tool === "write_file" || model.tool === "create_file" ? "Write" : "Edit";
|
|
840
|
-
case "read": return "Read";
|
|
841
|
-
case "search": return "Search";
|
|
842
|
-
case "list": return "List";
|
|
843
|
-
case "delete": return "Delete";
|
|
844
|
-
|
|
1794
|
+
case "terminal": return tr(t, "tv.command", "Command");
|
|
1795
|
+
case "diff": return model.tool === "write_to_file" || model.tool === "write_file" || model.tool === "create_file" ? tr(t, "tv.write", "Write") : tr(t, "tv.edit", "Edit");
|
|
1796
|
+
case "read": return tr(t, "tv.read", "Read");
|
|
1797
|
+
case "search": return model.tool === "search_web" || model.tool === "web_search" ? tr(t, "tv.webSearch", "Web Search") : tr(t, "tv.search", "Search");
|
|
1798
|
+
case "list": return tr(t, "tv.list", "List");
|
|
1799
|
+
case "delete": return tr(t, "tv.delete", "Delete");
|
|
1800
|
+
case "question": return tr(t, "tv.question", "Question");
|
|
1801
|
+
case "image": return tr(t, "tv.image", "Image");
|
|
1802
|
+
default: return model.tool ? model.tool.replace(/_/g, " ") : tr(t, "tv.tool", "Tool");
|
|
845
1803
|
}
|
|
846
1804
|
}
|
|
847
1805
|
function displaySummary(model, cwd, home) {
|
|
@@ -851,8 +1809,10 @@ window.__ModuleLoader__.load({
|
|
|
851
1809
|
const rawPath = model.path ?? "";
|
|
852
1810
|
return rawPath !== "" ? relativize(rawPath, cwd, home) : model.title;
|
|
853
1811
|
}
|
|
854
|
-
if (model.kind === "search") return model.title.replace(/^Search\s*/i, "") || model.title;
|
|
1812
|
+
if (model.kind === "search") return model.title.replace(/^(Web search|Search)\s*/i, "") || model.title;
|
|
855
1813
|
if (model.kind === "list") return model.title.replace(/^List\s*(directory\s*)?/i, "") || model.title;
|
|
1814
|
+
if (model.kind === "question") return model.title;
|
|
1815
|
+
if (model.kind === "image") return model.prompt || model.title;
|
|
856
1816
|
return model.title;
|
|
857
1817
|
}
|
|
858
1818
|
function diffStat(model) {
|
|
@@ -865,16 +1825,18 @@ window.__ModuleLoader__.load({
|
|
|
865
1825
|
if (oldLines === 0) return `+${newLines}`;
|
|
866
1826
|
return `+${newLines} -${oldLines}`;
|
|
867
1827
|
}
|
|
868
|
-
function CopyButton({ text, labels }) {
|
|
1828
|
+
function CopyButton({ text, labels, t }) {
|
|
869
1829
|
const [copied, setCopied] = react().useState(false);
|
|
870
|
-
const copyLabel = labels?.[0] ?? "
|
|
871
|
-
const copiedLabel = labels?.[1] ?? "
|
|
1830
|
+
const copyLabel = labels?.[0] ?? tr(t, "code.copy", "Copy");
|
|
1831
|
+
const copiedLabel = labels?.[1] ?? tr(t, "code.copied", "Copied");
|
|
872
1832
|
const onCopy = (e) => {
|
|
873
1833
|
e.stopPropagation();
|
|
874
1834
|
if (typeof navigator !== "undefined" && navigator.clipboard) navigator.clipboard.writeText(text).then(() => {
|
|
875
1835
|
setCopied(true);
|
|
876
1836
|
setTimeout(() => setCopied(false), 1500);
|
|
877
|
-
}).catch(() => {
|
|
1837
|
+
}).catch(() => {
|
|
1838
|
+
setCopied(false);
|
|
1839
|
+
});
|
|
878
1840
|
};
|
|
879
1841
|
return hx("button", {
|
|
880
1842
|
type: "button",
|
|
@@ -883,39 +1845,146 @@ window.__ModuleLoader__.load({
|
|
|
883
1845
|
title: copied ? copiedLabel : copyLabel
|
|
884
1846
|
}, copied ? IconCheckOutline14(11) : IconCopyOutline16(11), hx("span", null, copied ? copiedLabel : copyLabel));
|
|
885
1847
|
}
|
|
886
|
-
|
|
1848
|
+
/** Per-side render cap: a 5000-line write_to_file used to build 10k DOM rows
|
|
1849
|
+
* inside a max-height:280px pane (99% of them invisible). */
|
|
1850
|
+
const DIFF_MAX_LINES = 400;
|
|
1851
|
+
function DiffBody({ model, t }) {
|
|
887
1852
|
const h = hx;
|
|
888
1853
|
const oldText = model.oldText ?? "";
|
|
889
1854
|
const newText = model.newText ?? "";
|
|
890
1855
|
const rows = [];
|
|
1856
|
+
const moreRow = (count, key) => h("div", {
|
|
1857
|
+
key,
|
|
1858
|
+
className: "agy-tv-diff-line",
|
|
1859
|
+
style: { color: "var(--dsw-alias-label-tertiary)" }
|
|
1860
|
+
}, tr(t, "tv.diffMore", "… {count} more lines not rendered", { count }));
|
|
891
1861
|
if (oldText !== "") {
|
|
892
1862
|
const lines = oldText.split("\n");
|
|
893
|
-
|
|
1863
|
+
const shown = Math.min(lines.length, DIFF_MAX_LINES);
|
|
1864
|
+
for (let i = 0; i < shown; i++) {
|
|
894
1865
|
const line = lines[i];
|
|
895
1866
|
rows.push(h("div", {
|
|
896
1867
|
key: "del-" + i,
|
|
897
1868
|
className: "agy-tv-diff-line agy-tv-diff-del"
|
|
898
1869
|
}, h("span", { className: "agy-tv-diff-marker" }, "-"), h("span", { style: { flex: 1 } }, line === "" ? " " : line)));
|
|
899
1870
|
}
|
|
1871
|
+
if (lines.length > shown) rows.push(moreRow(lines.length - shown, "del-more"));
|
|
900
1872
|
}
|
|
901
1873
|
if (newText !== "") {
|
|
902
1874
|
const lines = newText.split("\n");
|
|
903
|
-
|
|
1875
|
+
const shown = Math.min(lines.length, DIFF_MAX_LINES);
|
|
1876
|
+
for (let i = 0; i < shown; i++) {
|
|
904
1877
|
const line = lines[i];
|
|
905
1878
|
rows.push(h("div", {
|
|
906
1879
|
key: "add-" + i,
|
|
907
1880
|
className: "agy-tv-diff-line agy-tv-diff-add"
|
|
908
1881
|
}, h("span", { className: "agy-tv-diff-marker" }, "+"), h("span", { style: { flex: 1 } }, line === "" ? " " : line)));
|
|
909
1882
|
}
|
|
1883
|
+
if (lines.length > shown) rows.push(moreRow(lines.length - shown, "add-more"));
|
|
910
1884
|
}
|
|
911
1885
|
if (rows.length === 0) rows.push(h("div", {
|
|
912
1886
|
key: "empty",
|
|
913
1887
|
className: "agy-tv-diff-line",
|
|
914
1888
|
style: { color: "var(--dsw-alias-label-tertiary)" }
|
|
915
|
-
}, "(no textual changes)"));
|
|
1889
|
+
}, tr(t, "tv.noChanges", "(no textual changes)")));
|
|
916
1890
|
return h("div", { className: "agy-tv-diff-list" }, ...rows);
|
|
917
1891
|
}
|
|
918
|
-
function
|
|
1892
|
+
function QuestionCardBody({ model }) {
|
|
1893
|
+
const h = hx;
|
|
1894
|
+
const questions = model.questions ?? [];
|
|
1895
|
+
const [selectedMap, setSelectedMap] = react().useState({});
|
|
1896
|
+
const [inserted, setInserted] = react().useState(false);
|
|
1897
|
+
const toggleOption = (qIdx, opt, isMulti) => {
|
|
1898
|
+
setSelectedMap((prev) => {
|
|
1899
|
+
const next = { ...prev };
|
|
1900
|
+
const current = new Set(next[qIdx] ?? []);
|
|
1901
|
+
if (isMulti) {
|
|
1902
|
+
if (current.has(opt)) current.delete(opt);
|
|
1903
|
+
else current.add(opt);
|
|
1904
|
+
} else {
|
|
1905
|
+
current.clear();
|
|
1906
|
+
current.add(opt);
|
|
1907
|
+
}
|
|
1908
|
+
next[qIdx] = current;
|
|
1909
|
+
return next;
|
|
1910
|
+
});
|
|
1911
|
+
};
|
|
1912
|
+
const onInsert = () => {
|
|
1913
|
+
const parts = [];
|
|
1914
|
+
for (let i = 0; i < questions.length; i++) {
|
|
1915
|
+
const sel = Array.from(selectedMap[i] ?? []);
|
|
1916
|
+
if (sel.length > 0) parts.push(sel.join("; "));
|
|
1917
|
+
}
|
|
1918
|
+
if (parts.length > 0) {
|
|
1919
|
+
insertTextIntoChatComposer(parts.join("\n"));
|
|
1920
|
+
setInserted(true);
|
|
1921
|
+
setTimeout(() => setInserted(false), 1500);
|
|
1922
|
+
}
|
|
1923
|
+
};
|
|
1924
|
+
const qNodes = [];
|
|
1925
|
+
for (let i = 0; i < questions.length; i++) {
|
|
1926
|
+
const q = questions[i];
|
|
1927
|
+
if (!q) continue;
|
|
1928
|
+
const options = q.options ?? [];
|
|
1929
|
+
const isMulti = q.is_multi_select === true;
|
|
1930
|
+
const sel = selectedMap[i] ?? /* @__PURE__ */ new Set();
|
|
1931
|
+
const optNodes = options.map((opt, oIdx) => {
|
|
1932
|
+
const isChecked = sel.has(opt);
|
|
1933
|
+
return h("button", {
|
|
1934
|
+
key: "opt-" + oIdx,
|
|
1935
|
+
type: "button",
|
|
1936
|
+
className: cls("agy-tv-q-opt", isChecked && "selected"),
|
|
1937
|
+
onClick: (e) => {
|
|
1938
|
+
e.stopPropagation();
|
|
1939
|
+
toggleOption(i, opt, isMulti);
|
|
1940
|
+
}
|
|
1941
|
+
}, h("span", { className: cls("agy-tv-q-check", isMulti ? "checkbox" : "radio", isChecked && "checked") }), h("span", { className: "agy-tv-q-opt-text" }, opt));
|
|
1942
|
+
});
|
|
1943
|
+
qNodes.push(h("div", {
|
|
1944
|
+
key: "q-" + i,
|
|
1945
|
+
className: "agy-tv-q-item"
|
|
1946
|
+
}, h("div", { className: "agy-tv-q-prompt" }, q.question || "Please select:"), h("div", { className: "agy-tv-q-opts" }, ...optNodes)));
|
|
1947
|
+
}
|
|
1948
|
+
const hasSelection = Object.values(selectedMap).some((s) => s.size > 0);
|
|
1949
|
+
return h("div", { className: "agy-tv-question-wrap" }, ...qNodes, h("div", { className: "agy-tv-q-footer" }, h("button", {
|
|
1950
|
+
type: "button",
|
|
1951
|
+
className: cls("agy-tv-q-insert-btn", hasSelection && "active"),
|
|
1952
|
+
disabled: !hasSelection,
|
|
1953
|
+
onClick: (e) => {
|
|
1954
|
+
e.stopPropagation();
|
|
1955
|
+
onInsert();
|
|
1956
|
+
}
|
|
1957
|
+
}, inserted ? "✓ 已填入对话框" : "💬 填入对话框 / Insert into Chat"), model.output ? h("div", { className: "agy-tv-q-answered" }, `已记录: ${model.output}`) : null));
|
|
1958
|
+
}
|
|
1959
|
+
function ImageCardBody({ model }) {
|
|
1960
|
+
const h = hx;
|
|
1961
|
+
const prompt = model.prompt || "";
|
|
1962
|
+
const name = model.imageName || "image";
|
|
1963
|
+
const ratio = model.aspectRatio || "1:1";
|
|
1964
|
+
const path = model.imagePath || model.path || "";
|
|
1965
|
+
const mediaUrl = path ? buildMediaUrl(path) : null;
|
|
1966
|
+
return h("div", { className: "agy-tv-img-wrap" }, h("div", { className: "agy-tv-img-meta" }, h("div", {
|
|
1967
|
+
className: "agy-tv-img-prompt",
|
|
1968
|
+
title: prompt || name
|
|
1969
|
+
}, prompt ? `"${prompt}"` : name), h("div", { className: "agy-tv-img-badges" }, h("span", { className: "agy-tv-img-badge" }, ratio), ...path ? [h("span", {
|
|
1970
|
+
key: "path",
|
|
1971
|
+
className: "agy-tv-img-badge",
|
|
1972
|
+
title: path
|
|
1973
|
+
}, path.split(/[/\\]/).pop())] : [])), mediaUrl ? h("div", {
|
|
1974
|
+
className: "agy-tv-img-preview-box",
|
|
1975
|
+
onClick: (e) => {
|
|
1976
|
+
e.stopPropagation();
|
|
1977
|
+
openLightbox(mediaUrl, prompt || name, path);
|
|
1978
|
+
},
|
|
1979
|
+
title: "点击放大预览 / Click to open lightbox"
|
|
1980
|
+
}, h("img", {
|
|
1981
|
+
className: "agy-tv-img-thumb",
|
|
1982
|
+
src: mediaUrl,
|
|
1983
|
+
alt: prompt || name,
|
|
1984
|
+
loading: "lazy"
|
|
1985
|
+
})) : null);
|
|
1986
|
+
}
|
|
1987
|
+
function CardBody({ model, openFile, cwd, home, inspect, t }) {
|
|
919
1988
|
const h = hx;
|
|
920
1989
|
const inspectNode = inspect !== void 0 ? h("div", {
|
|
921
1990
|
key: "ins",
|
|
@@ -924,10 +1993,10 @@ window.__ModuleLoader__.load({
|
|
|
924
1993
|
type: "button",
|
|
925
1994
|
className: "agy-tv-inspect-btn",
|
|
926
1995
|
onClick: inspect
|
|
927
|
-
}, IconInspectOutline12(12), "
|
|
1996
|
+
}, IconInspectOutline12(12), tr(t, "code.inspect", "Inspect"))) : null;
|
|
928
1997
|
switch (model.kind) {
|
|
929
1998
|
case "terminal": {
|
|
930
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no output)";
|
|
1999
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noOutput", "(no output)");
|
|
931
2000
|
const copyText = model.output !== void 0 && model.output !== "" ? model.output : model.command ?? "";
|
|
932
2001
|
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, h("span", { className: "agy-tv-prompt-glyph" }, "❯"), ...model.cwd ? [h("span", {
|
|
933
2002
|
key: "cwd",
|
|
@@ -935,7 +2004,10 @@ window.__ModuleLoader__.load({
|
|
|
935
2004
|
}, model.cwd)] : [], h("span", {
|
|
936
2005
|
className: "agy-tv-card-cmd",
|
|
937
2006
|
title: model.command
|
|
938
|
-
}, model.command ?? "")), h(CopyButton, {
|
|
2007
|
+
}, model.command ?? "")), h(CopyButton, {
|
|
2008
|
+
text: copyText,
|
|
2009
|
+
t
|
|
2010
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
939
2011
|
}
|
|
940
2012
|
case "diff": {
|
|
941
2013
|
const pathLabel = relativize(model.path ?? "file", cwd, home);
|
|
@@ -948,38 +2020,53 @@ window.__ModuleLoader__.load({
|
|
|
948
2020
|
model,
|
|
949
2021
|
openFile,
|
|
950
2022
|
cwd,
|
|
951
|
-
home
|
|
2023
|
+
home,
|
|
2024
|
+
t
|
|
952
2025
|
}), inspectNode);
|
|
953
2026
|
}
|
|
954
2027
|
case "read": {
|
|
955
2028
|
const pathLabel = relativize(model.path ?? "file", cwd, home);
|
|
956
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no output)";
|
|
957
|
-
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconBrowseOutline16(13), h("span", { className: "agy-tv-card-path" }, pathLabel)), h(CopyButton, {
|
|
2029
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noOutput", "(no output)");
|
|
2030
|
+
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconBrowseOutline16(13), h("span", { className: "agy-tv-card-path" }, pathLabel)), h(CopyButton, {
|
|
2031
|
+
text: model.output ?? "",
|
|
2032
|
+
t
|
|
2033
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
958
2034
|
}
|
|
959
2035
|
case "search": {
|
|
960
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no matches)";
|
|
961
|
-
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconSearchOutline16(13), h("span", { className: "agy-tv-card-path" }, model.title)), h(CopyButton, {
|
|
2036
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noMatches", "(no matches)");
|
|
2037
|
+
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconSearchOutline16(13), h("span", { className: "agy-tv-card-path" }, model.title)), h(CopyButton, {
|
|
2038
|
+
text: model.output ?? "",
|
|
2039
|
+
t
|
|
2040
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
962
2041
|
}
|
|
963
2042
|
case "list": {
|
|
964
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(empty directory)";
|
|
965
|
-
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconBrowseOutline16(13), h("span", { className: "agy-tv-card-path" }, model.title)), h(CopyButton, {
|
|
2043
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.emptyDir", "(empty directory)");
|
|
2044
|
+
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconBrowseOutline16(13), h("span", { className: "agy-tv-card-path" }, model.title)), h(CopyButton, {
|
|
2045
|
+
text: model.output ?? "",
|
|
2046
|
+
t
|
|
2047
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
966
2048
|
}
|
|
2049
|
+
case "question": return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconQuestionOutline16(13), h("span", { className: "agy-tv-card-path" }, model.title)), h(CopyButton, { text: model.output ?? model.raw ?? "" })), h(QuestionCardBody, { model }), inspectNode);
|
|
2050
|
+
case "image": return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconImageOutline16(13), h("span", { className: "agy-tv-card-path" }, model.imageName || "Image")), h(CopyButton, { text: model.prompt || (model.raw ?? "") })), h(ImageCardBody, { model }), inspectNode);
|
|
967
2051
|
default: {
|
|
968
2052
|
const copyText = model.output !== void 0 && model.output !== "" ? model.output : model.raw ?? "";
|
|
969
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : model.raw !== void 0 && model.raw !== "" ? clip(model.raw, 4e3) : "(no detail)";
|
|
970
|
-
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconCodeOutline16(13), h("span", { className: "agy-tv-card-path" }, model.tool || "Tool")), h(CopyButton, {
|
|
2053
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : model.raw !== void 0 && model.raw !== "" ? clip(model.raw, 4e3) : tr(t, "tv.noDetail", "(no detail)");
|
|
2054
|
+
return h("div", { className: "agy-tv-card" }, h("div", { className: "agy-tv-card-header" }, h("div", { className: "agy-tv-card-header-left" }, IconCodeOutline16(13), h("span", { className: "agy-tv-card-path" }, model.tool || "Tool")), h(CopyButton, {
|
|
2055
|
+
text: copyText,
|
|
2056
|
+
t
|
|
2057
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
971
2058
|
}
|
|
972
2059
|
}
|
|
973
2060
|
}
|
|
974
2061
|
function AgyMirrorToolView(props) {
|
|
975
2062
|
const [open, setOpen] = useToggle(false);
|
|
976
2063
|
const h = hx;
|
|
977
|
-
const { block, cwd, home, openFile, inspect } = props;
|
|
2064
|
+
const { block, cwd, home, openFile, inspect, t } = props;
|
|
978
2065
|
const settle = isSettled(block);
|
|
979
2066
|
const err = isError(block);
|
|
980
2067
|
const model = mirrorCardModel(block, cwd, home);
|
|
981
2068
|
const state = !settle ? "run" : err ? "err" : "ok";
|
|
982
|
-
const title = displayTitle(model);
|
|
2069
|
+
const title = displayTitle(model, t);
|
|
983
2070
|
const summary = displaySummary(model, cwd, home);
|
|
984
2071
|
const stat = diffStat(model);
|
|
985
2072
|
const preview = !open && model.kind !== "diff" ? previewLine(model, cwd, home) : void 0;
|
|
@@ -1016,7 +2103,7 @@ window.__ModuleLoader__.load({
|
|
|
1016
2103
|
setOpen();
|
|
1017
2104
|
}
|
|
1018
2105
|
},
|
|
1019
|
-
title: inspect !== void 0 ? open ? "Click to collapse · right-click to inspect" : "Click to expand · right-click to inspect" : open ? "Click to collapse" : "Click to expand",
|
|
2106
|
+
title: inspect !== void 0 ? open ? tr(t, "tv.hint.collapseInspect", "Click to collapse · right-click to inspect") : tr(t, "tv.hint.expandInspect", "Click to expand · right-click to inspect") : open ? tr(t, "tv.hint.collapse", "Click to collapse") : tr(t, "tv.hint.expand", "Click to expand"),
|
|
1020
2107
|
onContextMenu: inspect !== void 0 ? (e) => {
|
|
1021
2108
|
e.preventDefault();
|
|
1022
2109
|
inspect();
|
|
@@ -1044,7 +2131,8 @@ window.__ModuleLoader__.load({
|
|
|
1044
2131
|
openFile,
|
|
1045
2132
|
cwd,
|
|
1046
2133
|
home,
|
|
1047
|
-
inspect
|
|
2134
|
+
inspect,
|
|
2135
|
+
t
|
|
1048
2136
|
}))] : []);
|
|
1049
2137
|
}
|
|
1050
2138
|
/** Extract the agy mirror cursor (and tool name) from a run_code program. */
|
|
@@ -1116,7 +2204,7 @@ window.__ModuleLoader__.load({
|
|
|
1116
2204
|
setOpen();
|
|
1117
2205
|
}
|
|
1118
2206
|
},
|
|
1119
|
-
title: inspect !== void 0 ? open ? "Click to collapse · right-click to inspect" : "Click to expand · right-click to inspect" : open ? "Click to collapse" : "Click to expand",
|
|
2207
|
+
title: inspect !== void 0 ? open ? tr(t, "tv.hint.collapseInspect", "Click to collapse · right-click to inspect") : tr(t, "tv.hint.expandInspect", "Click to expand · right-click to inspect") : open ? tr(t, "tv.hint.collapse", "Click to collapse") : tr(t, "tv.hint.expand", "Click to expand"),
|
|
1120
2208
|
onContextMenu: inspect !== void 0 ? (e) => {
|
|
1121
2209
|
e.preventDefault();
|
|
1122
2210
|
inspect();
|
|
@@ -1159,18 +2247,21 @@ window.__ModuleLoader__.load({
|
|
|
1159
2247
|
const block = typed?.block;
|
|
1160
2248
|
const mirror = parseAgyMirrorFromCode(block !== void 0 ? parsedArgsRaw(block) : "{}");
|
|
1161
2249
|
if (mirror === null) return AgyCodeToolView(typed);
|
|
1162
|
-
return AgyMirrorToolView({
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
2250
|
+
return AgyMirrorToolView({
|
|
2251
|
+
block: {
|
|
2252
|
+
...block,
|
|
2253
|
+
call: {
|
|
2254
|
+
...block?.call ?? {},
|
|
2255
|
+
name: "agy_tool",
|
|
2256
|
+
argsRaw: JSON.stringify({
|
|
2257
|
+
run: mirror.run,
|
|
2258
|
+
step: mirror.step,
|
|
2259
|
+
...mirror.tool !== void 0 ? { tool: mirror.tool } : {}
|
|
2260
|
+
})
|
|
2261
|
+
}
|
|
2262
|
+
},
|
|
2263
|
+
t: typed?.t
|
|
2264
|
+
});
|
|
1174
2265
|
}
|
|
1175
2266
|
function installAgyToolView(ctx) {
|
|
1176
2267
|
ctx.slots.inject("tool.call.toolview", () => {
|
|
@@ -1178,7 +2269,8 @@ window.__ModuleLoader__.load({
|
|
|
1178
2269
|
name: "tool.call.toolview",
|
|
1179
2270
|
key: "agy_tool",
|
|
1180
2271
|
id: "agy-tool-view",
|
|
1181
|
-
label: "Antigravity tool"
|
|
2272
|
+
label: "Antigravity tool",
|
|
2273
|
+
locale: NS
|
|
1182
2274
|
}, AgyMirrorToolView);
|
|
1183
2275
|
const d2 = ctx.slots.register({
|
|
1184
2276
|
name: "tool.call.toolview",
|
|
@@ -1548,20 +2640,170 @@ window.__ModuleLoader__.load({
|
|
|
1548
2640
|
align-self: flex-start;
|
|
1549
2641
|
align-items: center;
|
|
1550
2642
|
gap: 4px;
|
|
1551
|
-
margin: 4px 0 2px 4px;
|
|
1552
|
-
padding: 2px 8px;
|
|
2643
|
+
margin: 4px 0 2px 4px;
|
|
2644
|
+
padding: 2px 8px;
|
|
2645
|
+
font-size: 11px;
|
|
2646
|
+
line-height: 16px;
|
|
2647
|
+
transition: opacity 0.1s;
|
|
2648
|
+
display: inline-flex;
|
|
2649
|
+
}
|
|
2650
|
+
.agy-tv-root:hover .agy-tv-inspect-btn,
|
|
2651
|
+
.agy-tv-inspect-btn:focus-visible {
|
|
2652
|
+
opacity: 1;
|
|
2653
|
+
}
|
|
2654
|
+
.agy-tv-inspect-btn:hover {
|
|
2655
|
+
background: var(--dsw-alias-interactive-bg-hover-solid, #f1f5f9);
|
|
2656
|
+
color: var(--dsw-alias-label-primary, #0f172a);
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
/* Question Card Styles */
|
|
2660
|
+
.agy-tv-question-wrap {
|
|
2661
|
+
padding: 10px 14px;
|
|
2662
|
+
display: flex;
|
|
2663
|
+
flex-direction: column;
|
|
2664
|
+
gap: 10px;
|
|
2665
|
+
font-family: inherit;
|
|
2666
|
+
}
|
|
2667
|
+
.agy-tv-q-item {
|
|
2668
|
+
display: flex;
|
|
2669
|
+
flex-direction: column;
|
|
2670
|
+
gap: 6px;
|
|
2671
|
+
}
|
|
2672
|
+
.agy-tv-q-prompt {
|
|
2673
|
+
font-size: 13px;
|
|
2674
|
+
font-weight: 600;
|
|
2675
|
+
color: var(--dsw-alias-label-primary, #0f172a);
|
|
2676
|
+
}
|
|
2677
|
+
.agy-tv-q-opts {
|
|
2678
|
+
display: flex;
|
|
2679
|
+
flex-direction: column;
|
|
2680
|
+
gap: 6px;
|
|
2681
|
+
}
|
|
2682
|
+
.agy-tv-q-opt {
|
|
2683
|
+
display: flex;
|
|
2684
|
+
align-items: center;
|
|
2685
|
+
gap: 8px;
|
|
2686
|
+
padding: 6px 10px;
|
|
2687
|
+
border-radius: 6px;
|
|
2688
|
+
background: var(--dsw-alias-bg-l2, rgba(127, 127, 127, 0.08));
|
|
2689
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.2));
|
|
2690
|
+
color: var(--dsw-alias-label-primary, #334155);
|
|
2691
|
+
cursor: pointer;
|
|
2692
|
+
text-align: left;
|
|
2693
|
+
font-size: 12.5px;
|
|
2694
|
+
transition: all 0.15s ease;
|
|
2695
|
+
}
|
|
2696
|
+
.agy-tv-q-opt:hover {
|
|
2697
|
+
background: var(--dsw-alias-bg-hover, rgba(127, 127, 127, 0.15));
|
|
2698
|
+
border-color: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.35));
|
|
2699
|
+
}
|
|
2700
|
+
.agy-tv-q-opt.selected {
|
|
2701
|
+
background: rgba(16, 185, 129, 0.12);
|
|
2702
|
+
border-color: #10b981;
|
|
2703
|
+
color: #10b981;
|
|
2704
|
+
}
|
|
2705
|
+
.agy-tv-q-check {
|
|
2706
|
+
width: 14px;
|
|
2707
|
+
height: 14px;
|
|
2708
|
+
border: 1.5px solid currentColor;
|
|
2709
|
+
display: inline-flex;
|
|
2710
|
+
align-items: center;
|
|
2711
|
+
justify-content: center;
|
|
2712
|
+
flex-shrink: 0;
|
|
2713
|
+
}
|
|
2714
|
+
.agy-tv-q-check.radio {
|
|
2715
|
+
border-radius: 50%;
|
|
2716
|
+
}
|
|
2717
|
+
.agy-tv-q-check.checkbox {
|
|
2718
|
+
border-radius: 3px;
|
|
2719
|
+
}
|
|
2720
|
+
.agy-tv-q-check.checked:after {
|
|
2721
|
+
content: "";
|
|
2722
|
+
width: 6px;
|
|
2723
|
+
height: 6px;
|
|
2724
|
+
background: currentColor;
|
|
2725
|
+
border-radius: inherit;
|
|
2726
|
+
}
|
|
2727
|
+
.agy-tv-q-footer {
|
|
2728
|
+
display: flex;
|
|
2729
|
+
align-items: center;
|
|
2730
|
+
justify-content: space-between;
|
|
2731
|
+
padding-top: 6px;
|
|
2732
|
+
border-top: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.15));
|
|
2733
|
+
}
|
|
2734
|
+
.agy-tv-q-insert-btn {
|
|
2735
|
+
padding: 5px 12px;
|
|
2736
|
+
border-radius: 6px;
|
|
2737
|
+
font-size: 12px;
|
|
2738
|
+
font-weight: 600;
|
|
2739
|
+
background: rgba(16, 185, 129, 0.15);
|
|
2740
|
+
border: 1px solid #10b981;
|
|
2741
|
+
color: #10b981;
|
|
2742
|
+
cursor: pointer;
|
|
2743
|
+
transition: all 0.15s ease;
|
|
2744
|
+
}
|
|
2745
|
+
.agy-tv-q-insert-btn:disabled {
|
|
2746
|
+
opacity: 0.4;
|
|
2747
|
+
cursor: not-allowed;
|
|
2748
|
+
}
|
|
2749
|
+
.agy-tv-q-insert-btn:not(:disabled):hover {
|
|
2750
|
+
background: #10b981;
|
|
2751
|
+
color: #fff;
|
|
2752
|
+
}
|
|
2753
|
+
.agy-tv-q-answered {
|
|
2754
|
+
font-size: 11px;
|
|
2755
|
+
color: var(--dsw-alias-label-tertiary, #888);
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
/* Image Card Styles */
|
|
2759
|
+
.agy-tv-img-wrap {
|
|
2760
|
+
padding: 10px 14px;
|
|
2761
|
+
display: flex;
|
|
2762
|
+
flex-direction: column;
|
|
2763
|
+
gap: 8px;
|
|
2764
|
+
}
|
|
2765
|
+
.agy-tv-img-meta {
|
|
2766
|
+
display: flex;
|
|
2767
|
+
align-items: center;
|
|
2768
|
+
justify-content: space-between;
|
|
2769
|
+
gap: 8px;
|
|
2770
|
+
}
|
|
2771
|
+
.agy-tv-img-prompt {
|
|
2772
|
+
font-size: 12.5px;
|
|
2773
|
+
color: var(--dsw-alias-label-primary, #334155);
|
|
2774
|
+
font-style: italic;
|
|
2775
|
+
overflow: hidden;
|
|
2776
|
+
text-overflow: ellipsis;
|
|
2777
|
+
white-space: nowrap;
|
|
2778
|
+
}
|
|
2779
|
+
.agy-tv-img-badges {
|
|
2780
|
+
display: flex;
|
|
2781
|
+
gap: 4px;
|
|
2782
|
+
flex-shrink: 0;
|
|
2783
|
+
}
|
|
2784
|
+
.agy-tv-img-badge {
|
|
1553
2785
|
font-size: 11px;
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
2786
|
+
padding: 1px 6px;
|
|
2787
|
+
border-radius: 4px;
|
|
2788
|
+
background: var(--dsw-alias-bg-l2, rgba(127, 127, 127, 0.1));
|
|
2789
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.2));
|
|
2790
|
+
color: var(--dsw-alias-label-secondary, #888);
|
|
1557
2791
|
}
|
|
1558
|
-
.agy-tv-
|
|
1559
|
-
|
|
1560
|
-
|
|
2792
|
+
.agy-tv-img-preview-box {
|
|
2793
|
+
max-height: 320px;
|
|
2794
|
+
overflow: hidden;
|
|
2795
|
+
border-radius: 6px;
|
|
2796
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.2));
|
|
2797
|
+
display: flex;
|
|
2798
|
+
align-items: center;
|
|
2799
|
+
justify-content: center;
|
|
2800
|
+
background: repeating-conic-gradient(rgba(127,127,127,0.08) 0% 25%, transparent 0% 50%) 50% / 16px 16px;
|
|
2801
|
+
cursor: zoom-in;
|
|
1561
2802
|
}
|
|
1562
|
-
.agy-tv-
|
|
1563
|
-
|
|
1564
|
-
|
|
2803
|
+
.agy-tv-img-thumb {
|
|
2804
|
+
max-width: 100%;
|
|
2805
|
+
max-height: 320px;
|
|
2806
|
+
object-fit: contain;
|
|
1565
2807
|
}
|
|
1566
2808
|
`;
|
|
1567
2809
|
const gDoc = globalThis.document;
|
|
@@ -1601,12 +2843,25 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1601
2843
|
white-space: pre-wrap;
|
|
1602
2844
|
padding: 10px 12px;
|
|
1603
2845
|
}
|
|
2846
|
+
/* Prevent Mermaid's internal error DOM or leaked temporary nodes from escaping into document.body.
|
|
2847
|
+
The generic .error-icon/.error-text classes are scoped to OUR mounts and the
|
|
2848
|
+
leaked-body id shapes only — unqualified, they hid host UI using the same
|
|
2849
|
+
class names. */
|
|
2850
|
+
div[data-agy-mermaid-svg] .error-icon,
|
|
2851
|
+
div[data-agy-mermaid-svg] .error-text,
|
|
2852
|
+
body > [id^="dagy-mmd"] .error-icon,
|
|
2853
|
+
body > [id^="iagy-mmd"] .error-icon {
|
|
2854
|
+
display: none !important;
|
|
2855
|
+
}
|
|
1604
2856
|
`;
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
2857
|
+
/**
|
|
2858
|
+
* The bundle ships mermaid.min.js and serves it from the plugin route. There
|
|
2859
|
+
* is deliberately NO public-CDN fallback: a floating-version, unsigned
|
|
2860
|
+
* script executing inside the DSH web origin (with reach into every local
|
|
2861
|
+
* HTTP API) is a supply-chain hazard that outweighs offline convenience.
|
|
2862
|
+
* When the local asset is missing the source block simply stays visible.
|
|
2863
|
+
*/
|
|
2864
|
+
const CDN_URLS = ["/plugins/agy-link/mermaid.min.js"];
|
|
1610
2865
|
let loadPromise = null;
|
|
1611
2866
|
let loadFailedAt = 0;
|
|
1612
2867
|
const LOAD_RETRY_MS = 6e4;
|
|
@@ -1624,9 +2879,13 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1624
2879
|
const s = document.createElement("script");
|
|
1625
2880
|
s.src = src;
|
|
1626
2881
|
s.async = true;
|
|
2882
|
+
let settled = false;
|
|
1627
2883
|
const done = (ok) => {
|
|
2884
|
+
if (settled) return;
|
|
2885
|
+
settled = true;
|
|
1628
2886
|
s.removeEventListener("load", onLoad);
|
|
1629
2887
|
s.removeEventListener("error", onError);
|
|
2888
|
+
if (!ok) s.remove();
|
|
1630
2889
|
resolve(ok);
|
|
1631
2890
|
};
|
|
1632
2891
|
const onLoad = () => done(true);
|
|
@@ -1649,7 +2908,8 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1649
2908
|
startOnLoad: false,
|
|
1650
2909
|
securityLevel: "strict",
|
|
1651
2910
|
theme: "neutral",
|
|
1652
|
-
fontFamily: "inherit"
|
|
2911
|
+
fontFamily: "inherit",
|
|
2912
|
+
suppressErrorRendering: true
|
|
1653
2913
|
});
|
|
1654
2914
|
} catch {}
|
|
1655
2915
|
return window.mermaid;
|
|
@@ -1731,6 +2991,16 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1731
2991
|
function readSource(block) {
|
|
1732
2992
|
return ((block.querySelector("[data-code-block-content] code") ?? block.querySelector("[data-code-block-content] pre") ?? block.querySelector("[data-code-block-content]"))?.textContent ?? "").trim();
|
|
1733
2993
|
}
|
|
2994
|
+
function cleanupTempElements(id) {
|
|
2995
|
+
if (typeof document === "undefined") return;
|
|
2996
|
+
if (id) {
|
|
2997
|
+
document.getElementById("d" + id)?.remove();
|
|
2998
|
+
document.getElementById("i" + id)?.remove();
|
|
2999
|
+
document.getElementById(id)?.remove();
|
|
3000
|
+
}
|
|
3001
|
+
const stray = document.querySelectorAll("body > [id^=\"dagy-mmd\"], body > [id^=\"iagy-mmd\"], body > [id^=\"d_agy-mmd\"], body > [id^=\"i_agy-mmd\"], body > [id^=\"agy-mmd-\"]");
|
|
3002
|
+
for (let i = 0; i < stray.length; i++) stray[i]?.remove();
|
|
3003
|
+
}
|
|
1734
3004
|
async function renderInto(block, source) {
|
|
1735
3005
|
block.querySelector("[data-agy-mermaid-svg]")?.remove();
|
|
1736
3006
|
const mount = document.createElement("div");
|
|
@@ -1743,28 +3013,32 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1743
3013
|
mount.textContent = "Mermaid renderer unavailable (offline). Diagram source stays below.";
|
|
1744
3014
|
return;
|
|
1745
3015
|
}
|
|
3016
|
+
renderSeq += 1;
|
|
3017
|
+
const id = "agy-mmd-" + renderSeq;
|
|
1746
3018
|
try {
|
|
1747
|
-
|
|
1748
|
-
const
|
|
1749
|
-
const { svg } = await api.render(id, source);
|
|
3019
|
+
if (typeof api.parse === "function") await api.parse(source);
|
|
3020
|
+
const { svg } = await api.render(id, source, mount);
|
|
1750
3021
|
mount.innerHTML = svg;
|
|
1751
3022
|
block.setAttribute("data-agy-mermaid", "done");
|
|
1752
3023
|
} catch (e) {
|
|
1753
3024
|
block.setAttribute("data-agy-mermaid", "error");
|
|
1754
3025
|
mount.setAttribute("data-agy-mermaid-error", "1");
|
|
1755
3026
|
mount.textContent = "Mermaid render failed: " + (e instanceof Error ? e.message : String(e));
|
|
3027
|
+
} finally {
|
|
3028
|
+
cleanupTempElements(id);
|
|
1756
3029
|
}
|
|
1757
3030
|
}
|
|
1758
|
-
let scanTimer = null;
|
|
1759
|
-
function scheduleScan() {
|
|
1760
|
-
if (scanTimer !== null) return;
|
|
1761
|
-
scanTimer = setTimeout(() => {
|
|
1762
|
-
scanTimer = null;
|
|
3031
|
+
let scanTimer$1 = null;
|
|
3032
|
+
function scheduleScan$1() {
|
|
3033
|
+
if (scanTimer$1 !== null) return;
|
|
3034
|
+
scanTimer$1 = setTimeout(() => {
|
|
3035
|
+
scanTimer$1 = null;
|
|
1763
3036
|
scan();
|
|
1764
3037
|
}, 150);
|
|
1765
3038
|
}
|
|
1766
3039
|
function scan() {
|
|
1767
3040
|
if (typeof document === "undefined") return;
|
|
3041
|
+
cleanupTempElements();
|
|
1768
3042
|
const blocks = document.querySelectorAll(".md-code-block");
|
|
1769
3043
|
for (let i = 0; i < blocks.length; i++) {
|
|
1770
3044
|
const block = blocks[i];
|
|
@@ -1779,14 +3053,25 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1779
3053
|
renderInto(block, source);
|
|
1780
3054
|
}
|
|
1781
3055
|
}
|
|
3056
|
+
let activeObserver$1 = null;
|
|
3057
|
+
let domContentLoadedHandler$1 = null;
|
|
3058
|
+
/**
|
|
3059
|
+
* Install the mermaid overlay. Returns a disposer that disconnects the
|
|
3060
|
+
* MutationObserver and cancels pending setup — wrap it in ctx.effect so a
|
|
3061
|
+
* plugin reload cannot stack observers over the same document.
|
|
3062
|
+
*/
|
|
1782
3063
|
function installMermaidRendering() {
|
|
1783
|
-
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
3064
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
3065
|
+
disposeMermaidRendering();
|
|
1784
3066
|
injectStyles$1();
|
|
3067
|
+
cleanupTempElements();
|
|
1785
3068
|
const observer = new MutationObserver(() => {
|
|
1786
|
-
scheduleScan();
|
|
3069
|
+
scheduleScan$1();
|
|
1787
3070
|
});
|
|
3071
|
+
activeObserver$1 = observer;
|
|
1788
3072
|
const setup = () => {
|
|
1789
3073
|
if (document.body) {
|
|
3074
|
+
cleanupTempElements();
|
|
1790
3075
|
observer.observe(document.body, {
|
|
1791
3076
|
childList: true,
|
|
1792
3077
|
subtree: true
|
|
@@ -1794,8 +3079,26 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1794
3079
|
scan();
|
|
1795
3080
|
}
|
|
1796
3081
|
};
|
|
1797
|
-
if (document.readyState === "loading")
|
|
1798
|
-
|
|
3082
|
+
if (document.readyState === "loading") {
|
|
3083
|
+
domContentLoadedHandler$1 = setup;
|
|
3084
|
+
window.addEventListener("DOMContentLoaded", setup, { once: true });
|
|
3085
|
+
} else setup();
|
|
3086
|
+
return disposeMermaidRendering;
|
|
3087
|
+
}
|
|
3088
|
+
/** Disconnect the observer and cancel pending setup work. */
|
|
3089
|
+
function disposeMermaidRendering() {
|
|
3090
|
+
if (activeObserver$1 !== null) {
|
|
3091
|
+
activeObserver$1.disconnect();
|
|
3092
|
+
activeObserver$1 = null;
|
|
3093
|
+
}
|
|
3094
|
+
if (domContentLoadedHandler$1 !== null) {
|
|
3095
|
+
window.removeEventListener("DOMContentLoaded", domContentLoadedHandler$1);
|
|
3096
|
+
domContentLoadedHandler$1 = null;
|
|
3097
|
+
}
|
|
3098
|
+
if (scanTimer$1 !== null) {
|
|
3099
|
+
clearTimeout(scanTimer$1);
|
|
3100
|
+
scanTimer$1 = null;
|
|
3101
|
+
}
|
|
1799
3102
|
}
|
|
1800
3103
|
//#endregion
|
|
1801
3104
|
//#region src/client/reasoning.ts
|
|
@@ -1857,9 +3160,16 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1857
3160
|
* Try to expand a thinking row once when its body contains real prose
|
|
1858
3161
|
* (not a bare [agy thinking turn · N tokens] chip). Uses the host's own
|
|
1859
3162
|
* disclosure control when present — never mutates thinkBody children.
|
|
3163
|
+
*
|
|
3164
|
+
* A row the user manually COLLAPSED is recorded in a WeakSet keyed by the
|
|
3165
|
+
* row element; React keeps the same element identity across its own
|
|
3166
|
+
* re-renders, so the scanner stops re-expanding it (the old data attribute
|
|
3167
|
+
* survived only until React rebuilt the node).
|
|
1860
3168
|
*/
|
|
3169
|
+
const userCollapsed = typeof WeakSet !== "undefined" ? /* @__PURE__ */ new WeakSet() : null;
|
|
1861
3170
|
function tryExpandThinkRow(root) {
|
|
1862
3171
|
if (root.dataset.agyExpanded === "true") return;
|
|
3172
|
+
if (userCollapsed?.has(root) === true) return;
|
|
1863
3173
|
const body = root.querySelector("[class*=\"thinkBody\"]");
|
|
1864
3174
|
if (!body) return;
|
|
1865
3175
|
const text = (body.textContent ?? "").trim();
|
|
@@ -1871,10 +3181,15 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1871
3181
|
return;
|
|
1872
3182
|
}
|
|
1873
3183
|
const toggle = root.querySelector("[data-disclosure-row]") ?? root.querySelector("[class*=\"disclosure\"]") ?? root.querySelector("button");
|
|
1874
|
-
if (toggle)
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
3184
|
+
if (toggle) {
|
|
3185
|
+
userCollapsed?.add(root);
|
|
3186
|
+
try {
|
|
3187
|
+
toggle.click();
|
|
3188
|
+
root.dataset.agyExpanded = "true";
|
|
3189
|
+
} catch {
|
|
3190
|
+
userCollapsed?.delete(root);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
1878
3193
|
}
|
|
1879
3194
|
function scanThinkingRows() {
|
|
1880
3195
|
if (typeof document === "undefined") return;
|
|
@@ -1884,12 +3199,29 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1884
3199
|
if (row) tryExpandThinkRow(row);
|
|
1885
3200
|
}
|
|
1886
3201
|
}
|
|
3202
|
+
let scanTimer = null;
|
|
3203
|
+
function scheduleScan() {
|
|
3204
|
+
if (scanTimer !== null) return;
|
|
3205
|
+
scanTimer = setTimeout(() => {
|
|
3206
|
+
scanTimer = null;
|
|
3207
|
+
scanThinkingRows();
|
|
3208
|
+
}, 200);
|
|
3209
|
+
}
|
|
3210
|
+
let activeObserver = null;
|
|
3211
|
+
let domContentLoadedHandler = null;
|
|
3212
|
+
/**
|
|
3213
|
+
* Install the auto-expand reasoning overlay. Returns a disposer that
|
|
3214
|
+
* disconnects the MutationObserver — wrap it in ctx.effect so a plugin
|
|
3215
|
+
* reload cannot stack observers.
|
|
3216
|
+
*/
|
|
1887
3217
|
function installAutoExpandReasoning() {
|
|
1888
|
-
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
3218
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
3219
|
+
disposeAutoExpandReasoning();
|
|
1889
3220
|
injectStyles();
|
|
1890
3221
|
const observer = new MutationObserver(() => {
|
|
1891
|
-
|
|
3222
|
+
scheduleScan();
|
|
1892
3223
|
});
|
|
3224
|
+
activeObserver = observer;
|
|
1893
3225
|
const setupObserver = () => {
|
|
1894
3226
|
if (document.body) {
|
|
1895
3227
|
observer.observe(document.body, {
|
|
@@ -1899,26 +3231,57 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1899
3231
|
scanThinkingRows();
|
|
1900
3232
|
}
|
|
1901
3233
|
};
|
|
1902
|
-
if (document.readyState === "loading")
|
|
1903
|
-
|
|
3234
|
+
if (document.readyState === "loading") {
|
|
3235
|
+
domContentLoadedHandler = setupObserver;
|
|
3236
|
+
window.addEventListener("DOMContentLoaded", setupObserver, { once: true });
|
|
3237
|
+
} else setupObserver();
|
|
3238
|
+
return disposeAutoExpandReasoning;
|
|
3239
|
+
}
|
|
3240
|
+
/** Disconnect the observer and cancel pending work. */
|
|
3241
|
+
function disposeAutoExpandReasoning() {
|
|
3242
|
+
if (activeObserver !== null) {
|
|
3243
|
+
activeObserver.disconnect();
|
|
3244
|
+
activeObserver = null;
|
|
3245
|
+
}
|
|
3246
|
+
if (domContentLoadedHandler !== null) {
|
|
3247
|
+
window.removeEventListener("DOMContentLoaded", domContentLoadedHandler);
|
|
3248
|
+
domContentLoadedHandler = null;
|
|
3249
|
+
}
|
|
3250
|
+
if (scanTimer !== null) {
|
|
3251
|
+
clearTimeout(scanTimer);
|
|
3252
|
+
scanTimer = null;
|
|
3253
|
+
}
|
|
1904
3254
|
}
|
|
1905
3255
|
//#endregion
|
|
1906
3256
|
//#region src/client/index.ts
|
|
1907
3257
|
const { createElement: h, useState, useEffect, useRef } = require("react");
|
|
1908
3258
|
const reactDom = require("react-dom");
|
|
1909
3259
|
const win = globalThis;
|
|
1910
|
-
const bodyEl = win.document?.body ?? null;
|
|
1911
3260
|
const portalToBody = (node) => {
|
|
1912
|
-
|
|
3261
|
+
const body = win.document?.body ?? (typeof document !== "undefined" ? document.body : null);
|
|
3262
|
+
if (body && reactDom && typeof reactDom.createPortal === "function") return reactDom.createPortal(node, body);
|
|
1913
3263
|
return node;
|
|
1914
3264
|
};
|
|
1915
3265
|
const name = "dsh-agy-link-client";
|
|
1916
3266
|
const inject = ["slots", "locale"];
|
|
1917
3267
|
const base = win.location?.origin ?? "";
|
|
1918
|
-
|
|
3268
|
+
const STATUS_CACHE_KEY = "dsh_agy_status_cache";
|
|
3269
|
+
function loadInitialStatusCache() {
|
|
3270
|
+
try {
|
|
3271
|
+
const raw = win.localStorage?.getItem(STATUS_CACHE_KEY);
|
|
3272
|
+
if (raw) {
|
|
3273
|
+
const parsed = JSON.parse(raw);
|
|
3274
|
+
if (parsed && typeof parsed === "object") return parsed;
|
|
3275
|
+
}
|
|
3276
|
+
} catch {}
|
|
3277
|
+
return null;
|
|
3278
|
+
}
|
|
3279
|
+
let statusCache = loadInitialStatusCache();
|
|
1919
3280
|
async function getStatus() {
|
|
1920
3281
|
try {
|
|
1921
|
-
const
|
|
3282
|
+
const init = {};
|
|
3283
|
+
if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") init.signal = AbortSignal.timeout(5e3);
|
|
3284
|
+
const res = await win.fetch?.(base + "/plugins/agy-link/status", init);
|
|
1922
3285
|
if (!res || !res.ok) return null;
|
|
1923
3286
|
const payload = await res.json();
|
|
1924
3287
|
statusCache = payload;
|
|
@@ -1936,7 +3299,12 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1936
3299
|
});
|
|
1937
3300
|
if (!res) return null;
|
|
1938
3301
|
try {
|
|
1939
|
-
|
|
3302
|
+
const payload = await res.json();
|
|
3303
|
+
if (!res.ok && payload !== null && typeof payload === "object") return {
|
|
3304
|
+
ok: false,
|
|
3305
|
+
...payload
|
|
3306
|
+
};
|
|
3307
|
+
return payload;
|
|
1940
3308
|
} catch {
|
|
1941
3309
|
return { ok: res.ok };
|
|
1942
3310
|
}
|
|
@@ -1944,6 +3312,72 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1944
3312
|
return null;
|
|
1945
3313
|
}
|
|
1946
3314
|
}
|
|
3315
|
+
const statusListeners = /* @__PURE__ */ new Set();
|
|
3316
|
+
let statusPollTimer = null;
|
|
3317
|
+
let statusFetchSeq = 0;
|
|
3318
|
+
function isStatusEqual(a, b) {
|
|
3319
|
+
if (a === b) return true;
|
|
3320
|
+
if (a === null || b === null) return false;
|
|
3321
|
+
try {
|
|
3322
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3323
|
+
} catch {
|
|
3324
|
+
return false;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
function notifyStatus(st) {
|
|
3328
|
+
statusCache = st;
|
|
3329
|
+
try {
|
|
3330
|
+
win.localStorage?.setItem(STATUS_CACHE_KEY, JSON.stringify(st));
|
|
3331
|
+
} catch {}
|
|
3332
|
+
for (const fn of [...statusListeners]) try {
|
|
3333
|
+
fn(st);
|
|
3334
|
+
} catch {}
|
|
3335
|
+
}
|
|
3336
|
+
async function statusPollTick() {
|
|
3337
|
+
const seq = ++statusFetchSeq;
|
|
3338
|
+
const st = await getStatus();
|
|
3339
|
+
if (st !== null && seq === statusFetchSeq) {
|
|
3340
|
+
if (!isStatusEqual(statusCache, st)) notifyStatus(st);
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
function ensureStatusPolling() {
|
|
3344
|
+
if (statusPollTimer !== null) return;
|
|
3345
|
+
statusPollTick();
|
|
3346
|
+
statusPollTimer = setInterval(() => {
|
|
3347
|
+
statusPollTick();
|
|
3348
|
+
}, 3e3);
|
|
3349
|
+
}
|
|
3350
|
+
function stopStatusPollingIfIdle() {
|
|
3351
|
+
if (statusListeners.size === 0 && statusPollTimer !== null) {
|
|
3352
|
+
clearInterval(statusPollTimer);
|
|
3353
|
+
statusPollTimer = null;
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
/**
|
|
3357
|
+
* Subscribe a component to the shared status poll. Returns the latest
|
|
3358
|
+
* snapshot plus a manual refresh that keeps the last good snapshot on a
|
|
3359
|
+
* transient failure (a failed refresh used to flip the whole panel back to
|
|
3360
|
+
* its loading state).
|
|
3361
|
+
*/
|
|
3362
|
+
function useAgyStatus() {
|
|
3363
|
+
const [status, setStatus] = useState(statusCache);
|
|
3364
|
+
useEffect(() => {
|
|
3365
|
+
statusListeners.add(setStatus);
|
|
3366
|
+
ensureStatusPolling();
|
|
3367
|
+
return () => {
|
|
3368
|
+
statusListeners.delete(setStatus);
|
|
3369
|
+
stopStatusPollingIfIdle();
|
|
3370
|
+
};
|
|
3371
|
+
}, []);
|
|
3372
|
+
const refresh = async () => {
|
|
3373
|
+
const st = await getStatus();
|
|
3374
|
+
if (st !== null) notifyStatus(st);
|
|
3375
|
+
};
|
|
3376
|
+
return {
|
|
3377
|
+
status,
|
|
3378
|
+
refresh
|
|
3379
|
+
};
|
|
3380
|
+
}
|
|
1947
3381
|
/** Global modal state for opening Antigravity console dialog from footer shortcut or header status */
|
|
1948
3382
|
const agyModalStore = {
|
|
1949
3383
|
open: false,
|
|
@@ -1960,6 +3394,21 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1960
3394
|
}
|
|
1961
3395
|
};
|
|
1962
3396
|
/**
|
|
3397
|
+
* Singleton modal instance manager: ensures at most one modal dialog is
|
|
3398
|
+
* rendered into document.body at any time even when multiple session headers mount.
|
|
3399
|
+
*/
|
|
3400
|
+
let primaryModalInstanceId = null;
|
|
3401
|
+
const modalInstanceIds = /* @__PURE__ */ new Set();
|
|
3402
|
+
function registerModalInstance(id) {
|
|
3403
|
+
modalInstanceIds.add(id);
|
|
3404
|
+
if (primaryModalInstanceId === null || !modalInstanceIds.has(primaryModalInstanceId)) primaryModalInstanceId = id;
|
|
3405
|
+
return primaryModalInstanceId === id;
|
|
3406
|
+
}
|
|
3407
|
+
function unregisterModalInstance(id) {
|
|
3408
|
+
modalInstanceIds.delete(id);
|
|
3409
|
+
if (primaryModalInstanceId === id) primaryModalInstanceId = modalInstanceIds.values().next().value ?? null;
|
|
3410
|
+
}
|
|
3411
|
+
/**
|
|
1963
3412
|
* Format reset timestamp into readable date/time + relative countdown.
|
|
1964
3413
|
*/
|
|
1965
3414
|
function formatQuotaWindow(t, resetTimeStr) {
|
|
@@ -2333,12 +3782,13 @@ body.dark,
|
|
|
2333
3782
|
border-radius: 50%;
|
|
2334
3783
|
}
|
|
2335
3784
|
.agy-card-hover {
|
|
2336
|
-
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.
|
|
3785
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.18s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s ease;
|
|
2337
3786
|
}
|
|
2338
3787
|
.agy-card-hover:hover {
|
|
2339
3788
|
border-color: var(--agy-border-card-primary, #3b82f6) !important;
|
|
2340
3789
|
box-shadow: var(--agy-shadow-card-hover) !important;
|
|
2341
3790
|
}
|
|
3791
|
+
|
|
2342
3792
|
.agy-btn {
|
|
2343
3793
|
transition: all 0.15s ease;
|
|
2344
3794
|
user-select: none;
|
|
@@ -2393,6 +3843,17 @@ body.dark,
|
|
|
2393
3843
|
color: var(--agy-text-primary);
|
|
2394
3844
|
}
|
|
2395
3845
|
`;
|
|
3846
|
+
function injectGlobalStyles() {
|
|
3847
|
+
if (typeof document === "undefined") return;
|
|
3848
|
+
const styleId = "dsh-agy-link-global-css";
|
|
3849
|
+
if (document.getElementById(styleId) === null) {
|
|
3850
|
+
const st = document.createElement("style");
|
|
3851
|
+
st.id = styleId;
|
|
3852
|
+
st.textContent = GLOBAL_CSS;
|
|
3853
|
+
const host = document.head ?? document.documentElement;
|
|
3854
|
+
if (host) host.appendChild(st);
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
2396
3857
|
const S = {
|
|
2397
3858
|
container: {
|
|
2398
3859
|
lineHeight: 1.5,
|
|
@@ -2463,27 +3924,29 @@ body.dark,
|
|
|
2463
3924
|
card: {
|
|
2464
3925
|
background: "var(--agy-bg-card)",
|
|
2465
3926
|
border: "1px solid var(--agy-border-card)",
|
|
2466
|
-
borderRadius: "
|
|
2467
|
-
padding: "14px
|
|
2468
|
-
marginBottom: "
|
|
3927
|
+
borderRadius: "8px",
|
|
3928
|
+
padding: "10px 14px",
|
|
3929
|
+
marginBottom: "8px",
|
|
2469
3930
|
color: "var(--agy-text-primary)",
|
|
2470
|
-
boxShadow: "var(--agy-shadow-card)"
|
|
3931
|
+
boxShadow: "var(--agy-shadow-card)",
|
|
3932
|
+
transition: "all 0.18s cubic-bezier(0.16, 1, 0.3, 1)"
|
|
2471
3933
|
},
|
|
2472
3934
|
cardPrimary: {
|
|
2473
|
-
background: "var(--agy-bg-card
|
|
2474
|
-
border: "
|
|
2475
|
-
borderRadius: "
|
|
2476
|
-
padding: "14px
|
|
2477
|
-
marginBottom: "
|
|
2478
|
-
|
|
2479
|
-
|
|
3935
|
+
background: "var(--agy-bg-card)",
|
|
3936
|
+
border: "1px solid var(--agy-border-card)",
|
|
3937
|
+
borderRadius: "8px",
|
|
3938
|
+
padding: "10px 14px",
|
|
3939
|
+
marginBottom: "8px",
|
|
3940
|
+
color: "var(--agy-text-primary)",
|
|
3941
|
+
boxShadow: "var(--agy-shadow-card)",
|
|
3942
|
+
transition: "all 0.18s cubic-bezier(0.16, 1, 0.3, 1)"
|
|
2480
3943
|
},
|
|
2481
3944
|
quotaBox: {
|
|
2482
3945
|
background: "var(--agy-bg-box)",
|
|
2483
3946
|
border: "1px solid var(--agy-border-box)",
|
|
2484
3947
|
borderRadius: "8px",
|
|
2485
3948
|
padding: "8px 10px",
|
|
2486
|
-
marginTop: "
|
|
3949
|
+
marginTop: "8px"
|
|
2487
3950
|
},
|
|
2488
3951
|
progressBarBg: {
|
|
2489
3952
|
flex: "1",
|
|
@@ -2653,8 +4116,9 @@ body.dark,
|
|
|
2653
4116
|
return locale.bind(NS);
|
|
2654
4117
|
};
|
|
2655
4118
|
const AgySettingsSection = (props) => {
|
|
4119
|
+
injectGlobalStyles();
|
|
2656
4120
|
const t = useAgyTranslation();
|
|
2657
|
-
const
|
|
4121
|
+
const { status, refresh } = useAgyStatus();
|
|
2658
4122
|
const [aliasInput, setAliasInput] = useState("");
|
|
2659
4123
|
const [proxyInputs, setProxyInputs] = useState({});
|
|
2660
4124
|
const [editingProxyId, setEditingProxyId] = useState(null);
|
|
@@ -2663,24 +4127,11 @@ body.dark,
|
|
|
2663
4127
|
const [loadingAction, setLoadingAction] = useState(null);
|
|
2664
4128
|
const [toast, setToast] = useState(null);
|
|
2665
4129
|
const [expandedModels, setExpandedModels] = useState({});
|
|
4130
|
+
const [addProxyInput, setAddProxyInput] = useState("");
|
|
4131
|
+
const [, setTimeTick] = useState(0);
|
|
2666
4132
|
useEffect(() => {
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
const tick = async () => {
|
|
2670
|
-
const st = await getStatus();
|
|
2671
|
-
if (!alive || !st) return;
|
|
2672
|
-
const json = JSON.stringify(st);
|
|
2673
|
-
if (json !== lastJson) {
|
|
2674
|
-
lastJson = json;
|
|
2675
|
-
setStatus(st);
|
|
2676
|
-
}
|
|
2677
|
-
};
|
|
2678
|
-
tick();
|
|
2679
|
-
const timer = setInterval(tick, 3e3);
|
|
2680
|
-
return () => {
|
|
2681
|
-
alive = false;
|
|
2682
|
-
clearInterval(timer);
|
|
2683
|
-
};
|
|
4133
|
+
const timer = setInterval(() => setTimeTick((n) => n + 1), 3e4);
|
|
4134
|
+
return () => clearInterval(timer);
|
|
2684
4135
|
}, []);
|
|
2685
4136
|
const flowStartedRef = useRef(false);
|
|
2686
4137
|
const safeMessage = (code) => {
|
|
@@ -2696,6 +4147,7 @@ body.dark,
|
|
|
2696
4147
|
setAddingAccount(false);
|
|
2697
4148
|
setAuthCodeInput("");
|
|
2698
4149
|
setAliasInput("");
|
|
4150
|
+
setAddProxyInput("");
|
|
2699
4151
|
showToast(safeMessage(pa.code), "success");
|
|
2700
4152
|
} else if (pa.phase === "failed") {
|
|
2701
4153
|
flowStartedRef.current = false;
|
|
@@ -2706,23 +4158,33 @@ body.dark,
|
|
|
2706
4158
|
status?.poolAuth?.phase,
|
|
2707
4159
|
status?.poolAuth?.code
|
|
2708
4160
|
]);
|
|
4161
|
+
const toastTimerRef = useRef(null);
|
|
4162
|
+
useEffect(() => () => {
|
|
4163
|
+
if (toastTimerRef.current !== null) clearTimeout(toastTimerRef.current);
|
|
4164
|
+
}, []);
|
|
2709
4165
|
const showToast = (text, type = "info") => {
|
|
2710
4166
|
setToast({
|
|
2711
4167
|
text,
|
|
2712
4168
|
type,
|
|
2713
4169
|
id: Date.now()
|
|
2714
4170
|
});
|
|
2715
|
-
|
|
2716
|
-
|
|
4171
|
+
if (toastTimerRef.current !== null) clearTimeout(toastTimerRef.current);
|
|
4172
|
+
toastTimerRef.current = setTimeout(() => {
|
|
4173
|
+
toastTimerRef.current = null;
|
|
4174
|
+
setToast((prev) => prev !== null && prev.text === text ? null : prev);
|
|
2717
4175
|
}, 6e3);
|
|
2718
4176
|
};
|
|
2719
|
-
const
|
|
2720
|
-
|
|
4177
|
+
const actionFailed = () => {
|
|
4178
|
+
showToast(t("api.genericError"), "error");
|
|
2721
4179
|
};
|
|
2722
4180
|
const handleBeginAddAccount = async () => {
|
|
2723
4181
|
setLoadingAction("pool:beginAdd");
|
|
2724
4182
|
const alias = aliasInput.trim();
|
|
2725
|
-
const
|
|
4183
|
+
const proxyUrl = addProxyInput.trim();
|
|
4184
|
+
const res = await postJson("/plugins/agy-link/pool/begin-add", {
|
|
4185
|
+
...alias ? { alias } : {},
|
|
4186
|
+
...proxyUrl ? { proxyUrl } : {}
|
|
4187
|
+
});
|
|
2726
4188
|
setLoadingAction(null);
|
|
2727
4189
|
if (res && res.ok) {
|
|
2728
4190
|
flowStartedRef.current = true;
|
|
@@ -2740,6 +4202,7 @@ body.dark,
|
|
|
2740
4202
|
flowStartedRef.current = false;
|
|
2741
4203
|
setAuthCodeInput("");
|
|
2742
4204
|
setAliasInput("");
|
|
4205
|
+
setAddProxyInput("");
|
|
2743
4206
|
setAddingAccount(false);
|
|
2744
4207
|
await refresh();
|
|
2745
4208
|
showToast(safeMessage(res.code), "success");
|
|
@@ -2750,41 +4213,87 @@ body.dark,
|
|
|
2750
4213
|
await postJson("/plugins/agy-link/pool/cancel-add", {});
|
|
2751
4214
|
setAuthCodeInput("");
|
|
2752
4215
|
setAliasInput("");
|
|
4216
|
+
setAddProxyInput("");
|
|
2753
4217
|
setAddingAccount(false);
|
|
2754
4218
|
await refresh();
|
|
2755
4219
|
};
|
|
4220
|
+
const reorderAccounts = async (newIds) => {
|
|
4221
|
+
setLoadingAction("pool:reorder");
|
|
4222
|
+
const res = await postJson("/plugins/agy-link/pool/reorder", { ids: newIds });
|
|
4223
|
+
setLoadingAction(null);
|
|
4224
|
+
if (res && res.ok) {
|
|
4225
|
+
await refresh();
|
|
4226
|
+
showToast(t("account.reordered"), "success");
|
|
4227
|
+
} else actionFailed();
|
|
4228
|
+
};
|
|
4229
|
+
const moveAccount = async (accId, delta) => {
|
|
4230
|
+
const ids = (status?.pool?.accounts ?? []).map((a) => a.id);
|
|
4231
|
+
const idx = ids.indexOf(accId);
|
|
4232
|
+
if (idx === -1) return;
|
|
4233
|
+
const newIdx = idx + delta;
|
|
4234
|
+
if (newIdx < 0 || newIdx >= ids.length) return;
|
|
4235
|
+
const [moved] = ids.splice(idx, 1);
|
|
4236
|
+
if (moved) ids.splice(newIdx, 0, moved);
|
|
4237
|
+
await reorderAccounts(ids);
|
|
4238
|
+
};
|
|
2756
4239
|
const setCfg = async (key, value) => {
|
|
2757
4240
|
setLoadingAction(`config:${key}`);
|
|
2758
|
-
await postJson("/plugins/agy-link/config", {
|
|
4241
|
+
const res = await postJson("/plugins/agy-link/config", {
|
|
2759
4242
|
key,
|
|
2760
4243
|
value
|
|
2761
4244
|
});
|
|
4245
|
+
if (res === null || res?.ok === false) {
|
|
4246
|
+
setLoadingAction(null);
|
|
4247
|
+
actionFailed();
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
2762
4250
|
await refresh();
|
|
2763
4251
|
setLoadingAction(null);
|
|
2764
4252
|
};
|
|
4253
|
+
const hiddenPendingRef = useRef(null);
|
|
2765
4254
|
const toggleModelHidden = async (id, hide) => {
|
|
2766
|
-
const next = new Set(status?.hiddenModels ?? []);
|
|
4255
|
+
const next = new Set(hiddenPendingRef.current ?? status?.hiddenModels ?? []);
|
|
2767
4256
|
if (hide) next.add(id);
|
|
2768
4257
|
else next.delete(id);
|
|
2769
|
-
|
|
4258
|
+
hiddenPendingRef.current = next;
|
|
4259
|
+
try {
|
|
4260
|
+
await setCfg("hiddenModels", Array.from(next));
|
|
4261
|
+
} finally {
|
|
4262
|
+
if (hiddenPendingRef.current === next) hiddenPendingRef.current = null;
|
|
4263
|
+
}
|
|
2770
4264
|
};
|
|
2771
4265
|
const setPrimary = async (id) => {
|
|
2772
4266
|
setLoadingAction(`primary:${id}`);
|
|
2773
|
-
await postJson("/plugins/agy-link/pool/primary", { id });
|
|
4267
|
+
const res = await postJson("/plugins/agy-link/pool/primary", { id });
|
|
4268
|
+
if (res === null || res?.ok === false) {
|
|
4269
|
+
setLoadingAction(null);
|
|
4270
|
+
actionFailed();
|
|
4271
|
+
return;
|
|
4272
|
+
}
|
|
2774
4273
|
await refresh();
|
|
2775
4274
|
setLoadingAction(null);
|
|
2776
4275
|
showToast(t("account.setPrimary"), "success");
|
|
2777
4276
|
};
|
|
2778
4277
|
const removeAccount = async (id, alias) => {
|
|
2779
4278
|
setLoadingAction(`remove:${id}`);
|
|
2780
|
-
await postJson("/plugins/agy-link/pool/remove", { id });
|
|
4279
|
+
const res = await postJson("/plugins/agy-link/pool/remove", { id });
|
|
4280
|
+
if (res === null || res?.ok === false) {
|
|
4281
|
+
setLoadingAction(null);
|
|
4282
|
+
actionFailed();
|
|
4283
|
+
return;
|
|
4284
|
+
}
|
|
2781
4285
|
await refresh();
|
|
2782
4286
|
setLoadingAction(null);
|
|
2783
4287
|
showToast(t("account.removed", { alias }), "info");
|
|
2784
4288
|
};
|
|
2785
4289
|
const refreshQuota = async (id) => {
|
|
2786
4290
|
setLoadingAction(id ? `refresh:${id}` : "refresh:all");
|
|
2787
|
-
await postJson("/plugins/agy-link/pool/refresh-quota", { id });
|
|
4291
|
+
const res = await postJson("/plugins/agy-link/pool/refresh-quota", { id });
|
|
4292
|
+
if (res === null || res?.ok === false) {
|
|
4293
|
+
setLoadingAction(null);
|
|
4294
|
+
actionFailed();
|
|
4295
|
+
return;
|
|
4296
|
+
}
|
|
2788
4297
|
await refresh();
|
|
2789
4298
|
setLoadingAction(null);
|
|
2790
4299
|
showToast(t("quota.refreshed"), "success");
|
|
@@ -2792,10 +4301,15 @@ body.dark,
|
|
|
2792
4301
|
const saveProxy = async (id) => {
|
|
2793
4302
|
setLoadingAction(`proxy:${id}`);
|
|
2794
4303
|
const proxyUrl = proxyInputs[id];
|
|
2795
|
-
await postJson("/plugins/agy-link/pool/proxy", {
|
|
4304
|
+
const res = await postJson("/plugins/agy-link/pool/proxy", {
|
|
2796
4305
|
id,
|
|
2797
4306
|
proxyUrl
|
|
2798
4307
|
});
|
|
4308
|
+
if (res === null || res?.ok === false) {
|
|
4309
|
+
setLoadingAction(null);
|
|
4310
|
+
actionFailed();
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
2799
4313
|
setEditingProxyId(null);
|
|
2800
4314
|
await refresh();
|
|
2801
4315
|
setLoadingAction(null);
|
|
@@ -2803,13 +4317,23 @@ body.dark,
|
|
|
2803
4317
|
};
|
|
2804
4318
|
const setMode = async (mode) => {
|
|
2805
4319
|
setLoadingAction(`mode:${mode}`);
|
|
2806
|
-
await postJson("/plugins/agy-link/pool/mode", { mode });
|
|
4320
|
+
const res = await postJson("/plugins/agy-link/pool/mode", { mode });
|
|
4321
|
+
if (res === null || res?.ok === false) {
|
|
4322
|
+
setLoadingAction(null);
|
|
4323
|
+
actionFailed();
|
|
4324
|
+
return;
|
|
4325
|
+
}
|
|
2807
4326
|
await refresh();
|
|
2808
4327
|
setLoadingAction(null);
|
|
2809
4328
|
};
|
|
2810
4329
|
const clearCooldown = async (id) => {
|
|
2811
4330
|
setLoadingAction(id ? `clearCooldown:${id}` : "clearCooldown:all");
|
|
2812
|
-
await postJson("/plugins/agy-link/pool/clear-cooldown", { id });
|
|
4331
|
+
const res = await postJson("/plugins/agy-link/pool/clear-cooldown", { id });
|
|
4332
|
+
if (res === null || res?.ok === false) {
|
|
4333
|
+
setLoadingAction(null);
|
|
4334
|
+
actionFailed();
|
|
4335
|
+
return;
|
|
4336
|
+
}
|
|
2813
4337
|
await refresh();
|
|
2814
4338
|
setLoadingAction(null);
|
|
2815
4339
|
showToast(t("account.clearCooldown"), "success");
|
|
@@ -2980,9 +4504,15 @@ body.dark,
|
|
|
2980
4504
|
const dotColor = !acc.enabled ? "#64748b" : isAuthRequired ? "#ef4444" : hasCooldown ? "#f59e0b" : "#10b981";
|
|
2981
4505
|
const isEditingProxy = editingProxyId === acc.id;
|
|
2982
4506
|
const isExpanded = expandedModels[acc.id] ?? false;
|
|
2983
|
-
const
|
|
4507
|
+
const accIndex = accounts.indexOf(acc);
|
|
4508
|
+
const cardStyle = {
|
|
4509
|
+
...S.card,
|
|
4510
|
+
cursor: "default",
|
|
4511
|
+
padding: "10px 14px",
|
|
4512
|
+
marginBottom: "8px"
|
|
4513
|
+
};
|
|
2984
4514
|
const legacyDefault = acc.defaultAlias === void 0 && acc.systemHome && acc.alias === "主账号 (系统登录)";
|
|
2985
|
-
const displayAlias = acc.defaultAlias || legacyDefault ? acc.systemHome ? t("account.defaultAlias") : t("account.aliasDefault", { number:
|
|
4515
|
+
const displayAlias = acc.defaultAlias || legacyDefault ? acc.systemHome ? t("account.defaultAlias") : t("account.aliasDefault", { number: accIndex + 1 }) : acc.alias;
|
|
2986
4516
|
const googleModels = acc.quotas.google?.models ?? [];
|
|
2987
4517
|
const anthropicModels = acc.quotas.anthropic?.models ?? [];
|
|
2988
4518
|
const openaiModels = acc.quotas.openai?.models ?? [];
|
|
@@ -3008,155 +4538,278 @@ body.dark,
|
|
|
3008
4538
|
display: "flex",
|
|
3009
4539
|
alignItems: "center",
|
|
3010
4540
|
justifyContent: "space-between",
|
|
4541
|
+
userSelect: "none",
|
|
4542
|
+
gap: "8px",
|
|
3011
4543
|
marginBottom: "8px"
|
|
3012
4544
|
} }, h("div", { style: {
|
|
3013
4545
|
display: "flex",
|
|
3014
4546
|
alignItems: "center",
|
|
3015
|
-
gap: "
|
|
3016
|
-
flexWrap: "wrap"
|
|
4547
|
+
gap: "6px",
|
|
4548
|
+
flexWrap: "wrap",
|
|
4549
|
+
flex: "1",
|
|
4550
|
+
minWidth: 0
|
|
3017
4551
|
} }, h("span", {
|
|
4552
|
+
style: {
|
|
4553
|
+
...S.badgeTag,
|
|
4554
|
+
fontWeight: 700,
|
|
4555
|
+
fontSize: "10.5px",
|
|
4556
|
+
padding: "1px 5px",
|
|
4557
|
+
background: isPrimary ? "var(--agy-badge-primary-bg)" : "var(--agy-badge-tag-bg)",
|
|
4558
|
+
color: isPrimary ? "var(--agy-badge-primary-text)" : "var(--agy-badge-tag-text)",
|
|
4559
|
+
borderColor: isPrimary ? "var(--agy-badge-primary-border)" : "var(--agy-badge-tag-border)"
|
|
4560
|
+
},
|
|
4561
|
+
title: `优先级 #${accIndex + 1}`
|
|
4562
|
+
}, `#${accIndex + 1}`), accounts.length > 1 ? h("div", { style: {
|
|
4563
|
+
display: "inline-flex",
|
|
4564
|
+
gap: "2px",
|
|
4565
|
+
alignItems: "center"
|
|
4566
|
+
} }, accIndex > 0 ? h("button", {
|
|
4567
|
+
type: "button",
|
|
4568
|
+
className: "agy-btn",
|
|
4569
|
+
style: {
|
|
4570
|
+
...S.btnSm,
|
|
4571
|
+
padding: "1px 4px",
|
|
4572
|
+
fontSize: "10px",
|
|
4573
|
+
lineHeight: 1,
|
|
4574
|
+
height: "18px"
|
|
4575
|
+
},
|
|
4576
|
+
title: t("account.moveUp"),
|
|
4577
|
+
onClick: () => void moveAccount(acc.id, -1)
|
|
4578
|
+
}, uiIcon("arrowUp", 10)) : null, accIndex < accounts.length - 1 ? h("button", {
|
|
4579
|
+
type: "button",
|
|
4580
|
+
className: "agy-btn",
|
|
4581
|
+
style: {
|
|
4582
|
+
...S.btnSm,
|
|
4583
|
+
padding: "1px 4px",
|
|
4584
|
+
fontSize: "10px",
|
|
4585
|
+
lineHeight: 1,
|
|
4586
|
+
height: "18px"
|
|
4587
|
+
},
|
|
4588
|
+
title: t("account.moveDown"),
|
|
4589
|
+
onClick: () => void moveAccount(acc.id, 1)
|
|
4590
|
+
}, uiIcon("arrowDown", 10)) : null) : null, h("span", {
|
|
3018
4591
|
className: "agy-pulse-dot",
|
|
3019
4592
|
style: {
|
|
3020
4593
|
background: dotColor,
|
|
3021
|
-
boxShadow: `0 0
|
|
4594
|
+
boxShadow: `0 0 6px ${dotColor}aa`,
|
|
4595
|
+
marginLeft: "1px"
|
|
3022
4596
|
}
|
|
3023
|
-
}), h("span", {
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
4597
|
+
}), h("span", {
|
|
4598
|
+
style: {
|
|
4599
|
+
fontWeight: 700,
|
|
4600
|
+
fontSize: "13px",
|
|
4601
|
+
color: "var(--agy-text-primary)",
|
|
4602
|
+
whiteSpace: "nowrap"
|
|
4603
|
+
},
|
|
4604
|
+
title: displayAlias
|
|
4605
|
+
}, displayAlias), h("span", { style: {
|
|
4606
|
+
...S.badgeTag,
|
|
4607
|
+
background: "rgba(59, 130, 246, 0.12)",
|
|
4608
|
+
color: "#3b82f6",
|
|
4609
|
+
borderColor: "rgba(59, 130, 246, 0.35)",
|
|
4610
|
+
fontSize: "10px",
|
|
4611
|
+
padding: "1px 5px",
|
|
4612
|
+
fontWeight: 700
|
|
4613
|
+
} }, "AGY"), isAuthRequired ? h("span", { style: {
|
|
3028
4614
|
...S.badgeTag,
|
|
3029
4615
|
background: "var(--agy-badge-email-bg)",
|
|
3030
4616
|
color: "#ef4444",
|
|
3031
4617
|
borderColor: "#fca5a5",
|
|
3032
|
-
gap: "
|
|
4618
|
+
gap: "3px",
|
|
4619
|
+
fontSize: "10px",
|
|
4620
|
+
padding: "1px 5px",
|
|
3033
4621
|
fontWeight: 700
|
|
3034
|
-
} }, uiIcon("alert",
|
|
4622
|
+
} }, uiIcon("alert", 10, "#ef4444"), t("status.authRequired")) : null, hasCooldown ? h("span", { style: {
|
|
3035
4623
|
...S.badgeTag,
|
|
3036
|
-
background: "
|
|
3037
|
-
color: "
|
|
3038
|
-
borderColor: "
|
|
3039
|
-
gap: "
|
|
3040
|
-
|
|
4624
|
+
background: "rgba(245, 158, 11, 0.15)",
|
|
4625
|
+
color: "#f59e0b",
|
|
4626
|
+
borderColor: "rgba(245, 158, 11, 0.4)",
|
|
4627
|
+
gap: "3px",
|
|
4628
|
+
fontSize: "10px",
|
|
4629
|
+
padding: "1px 5px",
|
|
4630
|
+
fontWeight: 700
|
|
4631
|
+
} }, uiIcon("alert", 10, "#f59e0b"), "冷却中") : null, acc.email ? h("span", {
|
|
4632
|
+
style: {
|
|
4633
|
+
...S.badgeTag,
|
|
4634
|
+
background: "var(--agy-badge-email-bg)",
|
|
4635
|
+
color: "var(--agy-badge-email-text)",
|
|
4636
|
+
borderColor: "var(--agy-badge-email-border)",
|
|
4637
|
+
gap: "4px",
|
|
4638
|
+
fontSize: "11px",
|
|
4639
|
+
padding: "1px 6px",
|
|
4640
|
+
whiteSpace: "nowrap"
|
|
4641
|
+
},
|
|
4642
|
+
title: acc.email
|
|
4643
|
+
}, uiIcon("mail", 10, "var(--agy-badge-email-text)"), acc.email) : null, isPrimary ? h("span", { style: {
|
|
3041
4644
|
...S.badgePrimary,
|
|
3042
|
-
gap: "
|
|
4645
|
+
gap: "3px",
|
|
4646
|
+
fontSize: "10.5px",
|
|
4647
|
+
padding: "1px 5px"
|
|
3043
4648
|
} }, uiIcon("star", 10, "var(--agy-badge-primary-text)"), t("status.primary")) : null, isInUse ? h("span", {
|
|
3044
4649
|
style: {
|
|
3045
4650
|
...S.badgeTag,
|
|
3046
4651
|
background: "rgba(16, 185, 129, 0.12)",
|
|
3047
4652
|
color: "#10b981",
|
|
3048
4653
|
borderColor: "rgba(16, 185, 129, 0.45)",
|
|
3049
|
-
gap: "
|
|
4654
|
+
gap: "3px",
|
|
4655
|
+
fontSize: "10px",
|
|
4656
|
+
padding: "1px 5px",
|
|
3050
4657
|
fontWeight: 700
|
|
3051
4658
|
},
|
|
3052
4659
|
title: t("status.inUse")
|
|
3053
|
-
}, uiIcon("zap",
|
|
4660
|
+
}, uiIcon("zap", 10, "#10b981"), t("status.inUse")) : null, acc.proxyUrl ? h("span", { style: {
|
|
3054
4661
|
...S.badgeTag,
|
|
3055
4662
|
background: "var(--agy-badge-proxy-bg)",
|
|
3056
4663
|
color: "var(--agy-badge-proxy-text)",
|
|
3057
4664
|
borderColor: "var(--agy-badge-proxy-border)",
|
|
3058
|
-
gap: "
|
|
3059
|
-
|
|
4665
|
+
gap: "4px",
|
|
4666
|
+
fontSize: "10px",
|
|
4667
|
+
padding: "1px 5px"
|
|
4668
|
+
} }, uiIcon("globe", 10, "var(--agy-badge-proxy-text)"), t("status.proxy")) : null), h("div", { style: {
|
|
3060
4669
|
display: "flex",
|
|
3061
|
-
gap: "
|
|
3062
|
-
alignItems: "center"
|
|
3063
|
-
|
|
4670
|
+
gap: "4px",
|
|
4671
|
+
alignItems: "center",
|
|
4672
|
+
flexShrink: 0
|
|
4673
|
+
} }, h("button", {
|
|
3064
4674
|
type: "button",
|
|
3065
4675
|
className: "agy-btn",
|
|
3066
4676
|
style: isExpanded ? {
|
|
3067
4677
|
...S.btnSmPrimary,
|
|
3068
|
-
gap: "3px"
|
|
4678
|
+
gap: "3px",
|
|
4679
|
+
fontSize: "11px",
|
|
4680
|
+
padding: "2px 6px"
|
|
3069
4681
|
} : {
|
|
3070
4682
|
...S.btnSm,
|
|
3071
|
-
gap: "3px"
|
|
4683
|
+
gap: "3px",
|
|
4684
|
+
fontSize: "11px",
|
|
4685
|
+
padding: "2px 6px"
|
|
3072
4686
|
},
|
|
3073
4687
|
onClick: () => toggleExpand(acc.id)
|
|
3074
|
-
}, isExpanded ? [uiIcon("chevronUp",
|
|
4688
|
+
}, isExpanded ? [uiIcon("chevronUp", 10), ` ${t("account.collapse")}`] : [uiIcon("chevronDown", 10), ` ${t("account.otherModels")}`]), h("button", {
|
|
3075
4689
|
type: "button",
|
|
3076
4690
|
className: "agy-btn",
|
|
3077
4691
|
style: {
|
|
3078
4692
|
...S.btnSm,
|
|
3079
|
-
gap: "
|
|
4693
|
+
gap: "3px",
|
|
4694
|
+
fontSize: "11px",
|
|
4695
|
+
padding: "2px 6px"
|
|
3080
4696
|
},
|
|
3081
4697
|
title: t("account.syncTitle"),
|
|
3082
4698
|
disabled: isBusy,
|
|
3083
4699
|
onClick: () => void refreshQuota(acc.id)
|
|
3084
|
-
}, loadingAction === `refresh:${acc.id}` ? [renderSpinner(), t("account.syncing")] : [uiIcon("refresh",
|
|
4700
|
+
}, loadingAction === `refresh:${acc.id}` ? [renderSpinner(), t("account.syncing")] : [uiIcon("refresh", 10), ` ${t("account.sync")}`]), !isPrimary ? h("button", {
|
|
3085
4701
|
type: "button",
|
|
3086
4702
|
className: "agy-btn",
|
|
3087
4703
|
style: {
|
|
3088
4704
|
...S.btnSm,
|
|
3089
|
-
gap: "
|
|
4705
|
+
gap: "3px",
|
|
4706
|
+
fontSize: "11px",
|
|
4707
|
+
padding: "2px 6px"
|
|
3090
4708
|
},
|
|
3091
4709
|
disabled: isBusy,
|
|
3092
4710
|
onClick: () => void setPrimary(acc.id)
|
|
3093
|
-
}, loadingAction === `primary:${acc.id}` ? [renderSpinner(), t("account.settingPrimary")] : [uiIcon("star",
|
|
4711
|
+
}, loadingAction === `primary:${acc.id}` ? [renderSpinner(), t("account.settingPrimary")] : [uiIcon("star", 10), ` ${t("account.setPrimary")}`]) : null, h("button", {
|
|
3094
4712
|
type: "button",
|
|
3095
4713
|
className: "agy-btn",
|
|
3096
4714
|
style: isEditingProxy ? {
|
|
3097
4715
|
...S.btnSmPrimary,
|
|
3098
|
-
gap: "
|
|
4716
|
+
gap: "3px",
|
|
4717
|
+
fontSize: "11px",
|
|
4718
|
+
padding: "2px 6px"
|
|
3099
4719
|
} : {
|
|
3100
4720
|
...S.btnSm,
|
|
3101
|
-
gap: "
|
|
4721
|
+
gap: "3px",
|
|
4722
|
+
fontSize: "11px",
|
|
4723
|
+
padding: "2px 6px"
|
|
3102
4724
|
},
|
|
3103
4725
|
disabled: isBusy,
|
|
3104
4726
|
onClick: () => setEditingProxyId(isEditingProxy ? null : acc.id)
|
|
3105
|
-
}, [uiIcon("globe",
|
|
4727
|
+
}, [uiIcon("globe", 10), ` ${t("proxy.button")}`]), accounts.length > 1 ? h("button", {
|
|
3106
4728
|
type: "button",
|
|
3107
4729
|
className: "agy-btn",
|
|
3108
4730
|
style: {
|
|
3109
4731
|
...S.btnDanger,
|
|
3110
|
-
padding: "
|
|
4732
|
+
padding: "2px 6px",
|
|
4733
|
+
fontSize: "11px"
|
|
3111
4734
|
},
|
|
3112
4735
|
title: t("account.removeTitle"),
|
|
3113
4736
|
"aria-label": t("account.removeTitle"),
|
|
3114
4737
|
disabled: isBusy,
|
|
3115
4738
|
onClick: () => void removeAccount(acc.id, displayAlias)
|
|
3116
|
-
}, loadingAction === `remove:${acc.id}` ? renderSpinner() : uiIcon("trash",
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
fontSize: "11px"
|
|
3125
|
-
} }, t("account.models")), allChildModels.map(({ family, model }) => {
|
|
3126
|
-
const frac = model.remainingFraction ?? 1;
|
|
3127
|
-
const pct = Math.round(frac * 100);
|
|
3128
|
-
const w = formatQuotaWindow(t, model.resetTime);
|
|
3129
|
-
const pColor = pct <= 20 ? "var(--agy-quota-low-text)" : pct <= 50 ? "var(--agy-quota-med-text)" : "var(--agy-quota-high-text)";
|
|
3130
|
-
return h("div", {
|
|
3131
|
-
key: model.modelId,
|
|
3132
|
-
className: "agy-submodel-row"
|
|
3133
|
-
}, h("span", { style: {
|
|
3134
|
-
fontWeight: 500,
|
|
3135
|
-
color: "var(--agy-text-primary)"
|
|
3136
|
-
} }, `[${family}] ${model.displayName || model.modelId}`), h("div", { style: {
|
|
4739
|
+
}, loadingAction === `remove:${acc.id}` ? renderSpinner() : uiIcon("trash", 11, "var(--agy-danger-text)")) : null)), h("div", {
|
|
4740
|
+
key: "agy-body",
|
|
4741
|
+
style: S.quotaBox
|
|
4742
|
+
}, renderQuotaBar("Gemini", "google", acc), h("button", {
|
|
4743
|
+
type: "button",
|
|
4744
|
+
className: "agy-btn",
|
|
4745
|
+
style: {
|
|
4746
|
+
width: "100%",
|
|
3137
4747
|
display: "flex",
|
|
3138
4748
|
alignItems: "center",
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
4749
|
+
justifyContent: "center",
|
|
4750
|
+
gap: "5px",
|
|
4751
|
+
marginTop: "6px",
|
|
4752
|
+
padding: "5px 10px",
|
|
4753
|
+
fontSize: "11px",
|
|
4754
|
+
fontWeight: 600,
|
|
4755
|
+
cursor: "pointer",
|
|
4756
|
+
color: isExpanded ? "var(--dsw-alias-state-business-primary, #3b82f6)" : "var(--agy-text-secondary)",
|
|
4757
|
+
background: "var(--agy-bg-subbox)",
|
|
4758
|
+
border: "1px dashed var(--agy-border-box)",
|
|
4759
|
+
borderRadius: "6px"
|
|
4760
|
+
},
|
|
4761
|
+
onClick: () => toggleExpand(acc.id)
|
|
4762
|
+
}, uiIcon(isExpanded ? "chevronUp" : "chevronDown", 10), h("span", null, isExpanded ? t("account.collapseOthers") : t("account.expandOthers"))), isExpanded ? [
|
|
4763
|
+
renderQuotaBar("Claude", "anthropic", acc),
|
|
4764
|
+
renderQuotaBar("GPT-OSS", "openai", acc),
|
|
4765
|
+
allChildModels.length > 0 ? h("div", { style: {
|
|
4766
|
+
marginTop: "8px",
|
|
4767
|
+
paddingTop: "8px",
|
|
4768
|
+
borderTop: "1px solid var(--agy-border-box)"
|
|
4769
|
+
} }, h("div", { style: {
|
|
4770
|
+
color: "var(--agy-text-secondary)",
|
|
4771
|
+
marginBottom: "6px",
|
|
4772
|
+
fontWeight: 600,
|
|
4773
|
+
fontSize: "11px"
|
|
4774
|
+
} }, t("account.models")), allChildModels.map(({ family, model }) => {
|
|
4775
|
+
const frac = model.remainingFraction ?? 1;
|
|
4776
|
+
const pct = Math.round(frac * 100);
|
|
4777
|
+
const w = formatQuotaWindow(t, model.resetTime);
|
|
4778
|
+
const pColor = pct <= 20 ? "var(--agy-quota-low-text)" : pct <= 50 ? "var(--agy-quota-med-text)" : "var(--agy-quota-high-text)";
|
|
4779
|
+
return h("div", {
|
|
4780
|
+
key: `${family}-${model.modelId}`,
|
|
4781
|
+
className: "agy-submodel-row"
|
|
4782
|
+
}, h("span", { style: {
|
|
4783
|
+
fontWeight: 500,
|
|
4784
|
+
color: "var(--agy-text-primary)"
|
|
4785
|
+
} }, `[${family}] ${model.displayName || model.modelId}`), h("div", { style: {
|
|
4786
|
+
display: "flex",
|
|
4787
|
+
alignItems: "center",
|
|
4788
|
+
gap: "8px"
|
|
4789
|
+
} }, h("span", { style: {
|
|
4790
|
+
color: pColor,
|
|
4791
|
+
fontWeight: 700
|
|
4792
|
+
} }, `${pct}%`), w.resetText ? h("span", { style: {
|
|
4793
|
+
color: "var(--agy-text-tertiary)",
|
|
4794
|
+
fontSize: "10.5px"
|
|
4795
|
+
} }, `↻ ${w.resetText}`) : null));
|
|
4796
|
+
})) : null
|
|
4797
|
+
] : null), hasCooldown ? h("div", {
|
|
4798
|
+
key: "cd-body",
|
|
4799
|
+
style: {
|
|
4800
|
+
background: "var(--agy-warn-bg)",
|
|
4801
|
+
border: "1px solid var(--agy-warn-border)",
|
|
4802
|
+
borderRadius: "7px",
|
|
4803
|
+
padding: "6px 10px",
|
|
4804
|
+
color: "var(--agy-warn-text)",
|
|
4805
|
+
fontSize: "11.5px",
|
|
4806
|
+
fontWeight: 600,
|
|
4807
|
+
marginTop: "8px",
|
|
4808
|
+
display: "flex",
|
|
4809
|
+
alignItems: "center",
|
|
4810
|
+
justifyContent: "space-between"
|
|
4811
|
+
}
|
|
4812
|
+
}, h("div", { style: {
|
|
3160
4813
|
display: "flex",
|
|
3161
4814
|
alignItems: "center",
|
|
3162
4815
|
gap: "6px"
|
|
@@ -3172,13 +4825,16 @@ body.dark,
|
|
|
3172
4825
|
},
|
|
3173
4826
|
disabled: isBusy,
|
|
3174
4827
|
onClick: () => void clearCooldown(acc.id)
|
|
3175
|
-
}, loadingAction === `clearCooldown:${acc.id}` ? [renderSpinner(), ""] : [uiIcon("zap", 11, "var(--agy-warn-btn-text)"), ` ${t("account.clearCooldown")}`])) : null, isEditingProxy ? h("div", {
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
4828
|
+
}, loadingAction === `clearCooldown:${acc.id}` ? [renderSpinner(), ""] : [uiIcon("zap", 11, "var(--agy-warn-btn-text)"), ` ${t("account.clearCooldown")}`])) : null, isEditingProxy ? h("div", {
|
|
4829
|
+
key: "proxy-body",
|
|
4830
|
+
style: {
|
|
4831
|
+
marginTop: "8px",
|
|
4832
|
+
padding: "10px 12px",
|
|
4833
|
+
background: "var(--agy-bg-subbox)",
|
|
4834
|
+
borderRadius: "7px",
|
|
4835
|
+
border: "1px solid var(--agy-border-subbox)"
|
|
4836
|
+
}
|
|
4837
|
+
}, h("div", { style: {
|
|
3182
4838
|
display: "flex",
|
|
3183
4839
|
gap: "8px"
|
|
3184
4840
|
} }, h("input", {
|
|
@@ -3211,23 +4867,40 @@ body.dark,
|
|
|
3211
4867
|
role: "group",
|
|
3212
4868
|
"aria-label": t("account.add")
|
|
3213
4869
|
}, h("div", { style: {
|
|
4870
|
+
display: "flex",
|
|
4871
|
+
alignItems: "center",
|
|
4872
|
+
justifyContent: "space-between",
|
|
4873
|
+
marginBottom: "12px",
|
|
4874
|
+
flexWrap: "wrap",
|
|
4875
|
+
gap: "8px"
|
|
4876
|
+
} }, h("div", { style: {
|
|
3214
4877
|
fontWeight: 700,
|
|
3215
4878
|
fontSize: "13.5px",
|
|
3216
|
-
marginBottom: "10px",
|
|
3217
4879
|
display: "flex",
|
|
3218
4880
|
alignItems: "center",
|
|
3219
4881
|
gap: "6px",
|
|
3220
4882
|
color: "var(--agy-text-primary)"
|
|
3221
|
-
} }, uiIcon("plus", 13, "var(--agy-btn-primary-bg)"), t("account.add")), !flowActive ? h("div", null, h("div", { style: {
|
|
4883
|
+
} }, uiIcon("plus", 13, "var(--agy-btn-primary-bg)"), t("account.add"))), !flowActive ? h("div", null, h("div", { style: {
|
|
3222
4884
|
display: "flex",
|
|
3223
|
-
|
|
4885
|
+
flexDirection: "column",
|
|
4886
|
+
gap: "8px",
|
|
4887
|
+
marginBottom: "12px"
|
|
3224
4888
|
} }, h("input", {
|
|
3225
4889
|
style: S.input,
|
|
3226
4890
|
value: aliasInput,
|
|
3227
4891
|
placeholder: t("account.aliasPlaceholder"),
|
|
3228
4892
|
"aria-label": t("aria.aliasInput"),
|
|
3229
4893
|
onChange: (e) => setAliasInput(e.target.value)
|
|
3230
|
-
}), h("
|
|
4894
|
+
}), h("input", {
|
|
4895
|
+
style: S.input,
|
|
4896
|
+
value: addProxyInput,
|
|
4897
|
+
placeholder: t("account.proxyPlaceholder"),
|
|
4898
|
+
"aria-label": t("aria.proxyInput"),
|
|
4899
|
+
onChange: (e) => setAddProxyInput(e.target.value)
|
|
4900
|
+
})), h("div", { style: {
|
|
4901
|
+
display: "flex",
|
|
4902
|
+
gap: "8px"
|
|
4903
|
+
} }, h("button", {
|
|
3231
4904
|
type: "button",
|
|
3232
4905
|
className: "agy-btn",
|
|
3233
4906
|
style: {
|
|
@@ -3303,8 +4976,8 @@ body.dark,
|
|
|
3303
4976
|
display: "flex",
|
|
3304
4977
|
alignItems: "center",
|
|
3305
4978
|
justifyContent: "center"
|
|
3306
|
-
} }, h("
|
|
3307
|
-
return h("div", { style: S.container }, h("
|
|
4979
|
+
} }, h("span", { style: S.muted }, [renderSpinner(), t("status.loading")]));
|
|
4980
|
+
return h("div", { style: S.container }, h("div", { style: S.headerCard }, h("div", { style: {
|
|
3308
4981
|
display: "flex",
|
|
3309
4982
|
alignItems: "center",
|
|
3310
4983
|
gap: "8px"
|
|
@@ -3333,7 +5006,21 @@ body.dark,
|
|
|
3333
5006
|
},
|
|
3334
5007
|
disabled: isBusy,
|
|
3335
5008
|
onClick: () => void refreshQuota()
|
|
3336
|
-
}, loadingAction === "refresh:all" ? [renderSpinner(), t("header.refreshing")] : [uiIcon("refresh", 12, "var(--agy-text-btn)"), ` ${t("header.refreshQuota")}`]))), renderToastBanner(), addAccountSection,
|
|
5009
|
+
}, loadingAction === "refresh:all" ? [renderSpinner(), t("header.refreshing")] : [uiIcon("refresh", 12, "var(--agy-text-btn)"), ` ${t("header.refreshQuota")}`]))), renderToastBanner(), addAccountSection, h("div", { style: {
|
|
5010
|
+
display: "flex",
|
|
5011
|
+
alignItems: "center",
|
|
5012
|
+
justifyContent: "space-between",
|
|
5013
|
+
marginBottom: "8px",
|
|
5014
|
+
padding: "0 2px"
|
|
5015
|
+
} }, h("div", { style: {
|
|
5016
|
+
display: "flex",
|
|
5017
|
+
alignItems: "center",
|
|
5018
|
+
gap: "6px"
|
|
5019
|
+
} }, h("span", { style: {
|
|
5020
|
+
fontWeight: 700,
|
|
5021
|
+
fontSize: "12.5px",
|
|
5022
|
+
color: "var(--agy-text-primary)"
|
|
5023
|
+
} }, `账号池 (${accounts.length})`))), renderedAccountCards, h("div", { style: {
|
|
3337
5024
|
marginTop: "16px",
|
|
3338
5025
|
paddingTop: "12px",
|
|
3339
5026
|
borderTop: "1px solid var(--agy-border-divider)"
|
|
@@ -3436,9 +5123,19 @@ body.dark,
|
|
|
3436
5123
|
};
|
|
3437
5124
|
/** Modal dialog container rendered into document.body */
|
|
3438
5125
|
const AgyModalDialog = () => {
|
|
5126
|
+
const instanceIdRef = useRef(null);
|
|
5127
|
+
if (instanceIdRef.current === null) instanceIdRef.current = "modal_" + Math.random().toString(36).slice(2);
|
|
5128
|
+
const isPrimary = registerModalInstance(instanceIdRef.current);
|
|
5129
|
+
useEffect(() => {
|
|
5130
|
+
const id = instanceIdRef.current;
|
|
5131
|
+
return () => {
|
|
5132
|
+
unregisterModalInstance(id);
|
|
5133
|
+
};
|
|
5134
|
+
}, []);
|
|
3439
5135
|
const t = useAgyTranslation();
|
|
3440
5136
|
const [isOpen, setIsOpen] = useState(agyModalStore.open);
|
|
3441
5137
|
useEffect(() => {
|
|
5138
|
+
injectGlobalStyles();
|
|
3442
5139
|
return agyModalStore.subscribe(() => {
|
|
3443
5140
|
setIsOpen(agyModalStore.open);
|
|
3444
5141
|
});
|
|
@@ -3454,7 +5151,7 @@ body.dark,
|
|
|
3454
5151
|
win.addEventListener?.("keydown", onKey, true);
|
|
3455
5152
|
return () => win.removeEventListener?.("keydown", onKey, true);
|
|
3456
5153
|
}, [isOpen]);
|
|
3457
|
-
if (!isOpen) return null;
|
|
5154
|
+
if (!isOpen || !isPrimary) return null;
|
|
3458
5155
|
return h("div", {
|
|
3459
5156
|
className: "agy-modal-backdrop",
|
|
3460
5157
|
onClick: (e) => {
|
|
@@ -3512,39 +5209,26 @@ body.dark,
|
|
|
3512
5209
|
/** Session Header badge in chat toolbar */
|
|
3513
5210
|
const AgySessionStatus = () => {
|
|
3514
5211
|
const t = useAgyTranslation();
|
|
3515
|
-
const
|
|
5212
|
+
const { status } = useAgyStatus();
|
|
5213
|
+
const [, setTimeTick] = useState(0);
|
|
3516
5214
|
useEffect(() => {
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
const tick = async () => {
|
|
3520
|
-
const st = await getStatus();
|
|
3521
|
-
if (!alive || !st) return;
|
|
3522
|
-
const json = JSON.stringify(st);
|
|
3523
|
-
if (json !== lastJson) {
|
|
3524
|
-
lastJson = json;
|
|
3525
|
-
setStatus(st);
|
|
3526
|
-
}
|
|
3527
|
-
};
|
|
3528
|
-
tick();
|
|
3529
|
-
const timer = setInterval(tick, 3e3);
|
|
3530
|
-
return () => {
|
|
3531
|
-
alive = false;
|
|
3532
|
-
clearInterval(timer);
|
|
3533
|
-
};
|
|
5215
|
+
const timer = setInterval(() => setTimeTick((n) => n + 1), 3e4);
|
|
5216
|
+
return () => clearInterval(timer);
|
|
3534
5217
|
}, []);
|
|
3535
5218
|
const pool = status?.pool;
|
|
3536
5219
|
const accounts = pool?.accounts ?? [];
|
|
3537
5220
|
const rawActiveId = pool?.activeAccountId ?? pool?.lastActiveAccountId ?? pool?.activeAccountIds?.google ?? pool?.primaryAccountId;
|
|
3538
5221
|
const activeAcc = accounts.find((a) => a.id === rawActiveId && a.enabled && !a.authRequired) ?? accounts.find((a) => a.enabled && !a.authRequired) ?? accounts[0];
|
|
3539
|
-
const activeHasCooldown = activeAcc ? Object.entries(activeAcc.cooldowns).some(([, cd]) => cd && cd.cooldownUntil > Date.now()) : false;
|
|
3540
|
-
const allInCooldown = accounts.length > 0 && accounts.every((a) => !a.enabled || a.authRequired || Object.entries(a.cooldowns).some(([, cd]) => cd && cd.cooldownUntil > Date.now()));
|
|
5222
|
+
const activeHasCooldown = activeAcc ? Object.entries(activeAcc.cooldowns ?? {}).some(([, cd]) => cd && cd.cooldownUntil > Date.now()) : false;
|
|
5223
|
+
const allInCooldown = accounts.length > 0 && accounts.every((a) => !a.enabled || a.authRequired || Object.entries(a.cooldowns ?? {}).some(([, cd]) => cd && cd.cooldownUntil > Date.now()));
|
|
3541
5224
|
const isAuthed = status?.auth?.phase === "ok" || accounts.length > 0;
|
|
3542
5225
|
const color = status === null ? "#64748b" : status.dormantReason ? "#f59e0b" : allInCooldown ? "#f59e0b" : activeHasCooldown ? "#f59e0b" : isAuthed ? "#10b981" : "#f59e0b";
|
|
3543
5226
|
const legacyDefault = activeAcc && activeAcc.defaultAlias === void 0 && activeAcc.systemHome && activeAcc.alias === "主账号 (系统登录)";
|
|
3544
5227
|
const displayAlias = activeAcc ? activeAcc.defaultAlias || legacyDefault ? activeAcc.systemHome ? t("account.defaultAlias") : t("account.aliasDefault", { number: accounts.indexOf(activeAcc) + 1 }) : activeAcc.alias : "";
|
|
3545
|
-
const
|
|
3546
|
-
const
|
|
3547
|
-
const
|
|
5228
|
+
const activeEligible = activeAcc !== void 0 && activeAcc.enabled && !activeAcc.authRequired;
|
|
5229
|
+
const activeDetail = activeAcc !== void 0 && activeEligible ? ` · ${t("status.inUse")}: ${displayAlias}${activeAcc.email ? ` (${activeAcc.email})` : ""}` : "";
|
|
5230
|
+
const badgeTitle = status === null ? t("header.badgeLoading") : `${t("header.badgeTitle", { count: accounts.length })}${activeDetail}`;
|
|
5231
|
+
const buttonLabel = status === null ? "AGY" : displayAlias ? `AGY · ${displayAlias}` : `AGY (${accounts.length})`;
|
|
3548
5232
|
const badge = h("button", {
|
|
3549
5233
|
type: "button",
|
|
3550
5234
|
title: badgeTitle,
|
|
@@ -3593,8 +5277,10 @@ body.dark,
|
|
|
3593
5277
|
}, AgySettingsSection);
|
|
3594
5278
|
});
|
|
3595
5279
|
installAgyToolView(ctx);
|
|
3596
|
-
installAutoExpandReasoning();
|
|
3597
|
-
installMermaidRendering();
|
|
5280
|
+
ctx.effect(() => installAutoExpandReasoning());
|
|
5281
|
+
ctx.effect(() => installMermaidRendering());
|
|
5282
|
+
ctx.effect(() => installImageEnhancer());
|
|
5283
|
+
ctx.effect(() => installDecisionChips());
|
|
3598
5284
|
}
|
|
3599
5285
|
//#endregion
|
|
3600
5286
|
exports.apply = apply;
|