dsh-agy-link 0.4.43 → 0.4.46
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 +108 -0
- package/README.md +3 -0
- package/dist/client.js +510 -131
- package/dist/index.js +1438 -373
- package/docs/KNOWN-GAPS.md +16 -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/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -39,6 +39,25 @@ window.__ModuleLoader__.load({
|
|
|
39
39
|
"section.label": "Antigravity",
|
|
40
40
|
"code.title": "代码",
|
|
41
41
|
"code.inspect": "检查",
|
|
42
|
+
"tv.command": "命令",
|
|
43
|
+
"tv.write": "写入",
|
|
44
|
+
"tv.edit": "编辑",
|
|
45
|
+
"tv.read": "读取",
|
|
46
|
+
"tv.search": "搜索",
|
|
47
|
+
"tv.webSearch": "网页搜索",
|
|
48
|
+
"tv.list": "列表",
|
|
49
|
+
"tv.delete": "删除",
|
|
50
|
+
"tv.tool": "工具",
|
|
51
|
+
"tv.noOutput": "(无输出)",
|
|
52
|
+
"tv.noMatches": "(无匹配)",
|
|
53
|
+
"tv.noChanges": "(无文本变更)",
|
|
54
|
+
"tv.emptyDir": "(空目录)",
|
|
55
|
+
"tv.noDetail": "(无详情)",
|
|
56
|
+
"tv.hint.expandInspect": "点击展开 · 右键检查",
|
|
57
|
+
"tv.hint.collapseInspect": "点击收起 · 右键检查",
|
|
58
|
+
"tv.hint.expand": "点击展开",
|
|
59
|
+
"tv.hint.collapse": "点击收起",
|
|
60
|
+
"tv.diffMore": "… 其余 {count} 行未渲染",
|
|
42
61
|
"code.copy": "复制",
|
|
43
62
|
"code.copied": "已复制",
|
|
44
63
|
"console.title": "Antigravity 管理控制台",
|
|
@@ -74,6 +93,7 @@ window.__ModuleLoader__.load({
|
|
|
74
93
|
"quota.weekly": "周额度",
|
|
75
94
|
"quota.refreshed": "额度已刷新",
|
|
76
95
|
"proxy.button": "代理",
|
|
96
|
+
"pool.winIsolationWarn": "Windows 提示:agy 的登录凭据存在系统级 Credential Manager(单槽位),多账号池无法隔离凭据——轮巡只切换工作目录,实际仍消耗系统登录账号(issue #45)。",
|
|
77
97
|
"proxy.placeholder": "专属代理 URL(如:http://127.0.0.1:7890;留空则使用全局)",
|
|
78
98
|
"proxy.save": "保存",
|
|
79
99
|
"proxy.saved": "代理已保存",
|
|
@@ -121,6 +141,9 @@ window.__ModuleLoader__.load({
|
|
|
121
141
|
"pool.label": "号池调度:",
|
|
122
142
|
"pool.sequential": "顺次耗尽",
|
|
123
143
|
"pool.roundRobin": "轮询均衡",
|
|
144
|
+
"models.label": "模型显示:",
|
|
145
|
+
"models.empty": "模型目录还没有可用模型,发一次对话或点“刷新额度”后再来管理",
|
|
146
|
+
"models.hint": "点击切换显示/隐藏;关闭的模型不在模型选择器中列出,进行中的会话不受影响。",
|
|
124
147
|
"header.refreshQuota": "刷新额度",
|
|
125
148
|
"header.refreshing": "刷新中",
|
|
126
149
|
"console.close": "关闭(Esc)",
|
|
@@ -131,6 +154,25 @@ window.__ModuleLoader__.load({
|
|
|
131
154
|
"console.title": "Antigravity Management Console",
|
|
132
155
|
"code.title": "Code",
|
|
133
156
|
"code.inspect": "Inspect",
|
|
157
|
+
"tv.command": "Command",
|
|
158
|
+
"tv.write": "Write",
|
|
159
|
+
"tv.edit": "Edit",
|
|
160
|
+
"tv.read": "Read",
|
|
161
|
+
"tv.search": "Search",
|
|
162
|
+
"tv.webSearch": "Web Search",
|
|
163
|
+
"tv.list": "List",
|
|
164
|
+
"tv.delete": "Delete",
|
|
165
|
+
"tv.tool": "Tool",
|
|
166
|
+
"tv.noOutput": "(no output)",
|
|
167
|
+
"tv.noMatches": "(no matches)",
|
|
168
|
+
"tv.noChanges": "(no textual changes)",
|
|
169
|
+
"tv.emptyDir": "(empty directory)",
|
|
170
|
+
"tv.noDetail": "(no detail)",
|
|
171
|
+
"tv.hint.expandInspect": "Click to expand · right-click to inspect",
|
|
172
|
+
"tv.hint.collapseInspect": "Click to collapse · right-click to inspect",
|
|
173
|
+
"tv.hint.expand": "Click to expand",
|
|
174
|
+
"tv.hint.collapse": "Click to collapse",
|
|
175
|
+
"tv.diffMore": "… {count} more lines not rendered",
|
|
134
176
|
"code.copy": "Copy",
|
|
135
177
|
"code.copied": "Copied",
|
|
136
178
|
"status.ready": "Ready",
|
|
@@ -165,6 +207,7 @@ window.__ModuleLoader__.load({
|
|
|
165
207
|
"quota.weekly": "Weekly quota",
|
|
166
208
|
"quota.refreshed": "Quota refreshed",
|
|
167
209
|
"proxy.button": "Proxy",
|
|
210
|
+
"pool.winIsolationWarn": "Windows: agy keeps its login in the system-wide Credential Manager (single slot), so the account pool cannot isolate credentials — rotation switches workspaces only, and generation still bills the system login (issue #45).",
|
|
168
211
|
"proxy.placeholder": "Dedicated proxy URL (for example: http://127.0.0.1:7890; leave blank to use the global proxy)",
|
|
169
212
|
"proxy.save": "Save",
|
|
170
213
|
"proxy.saved": "Proxy saved",
|
|
@@ -212,6 +255,9 @@ window.__ModuleLoader__.load({
|
|
|
212
255
|
"pool.label": "Account-pool scheduling:",
|
|
213
256
|
"pool.sequential": "Use sequentially",
|
|
214
257
|
"pool.roundRobin": "Round-robin",
|
|
258
|
+
"models.label": "Model visibility:",
|
|
259
|
+
"models.empty": "No models in the catalog yet — send a message or click \"Refresh quota\", then come back to manage them",
|
|
260
|
+
"models.hint": "Click to show/hide. Hidden models are not listed in the model picker; ongoing sessions are unaffected.",
|
|
215
261
|
"header.refreshQuota": "Refresh quota",
|
|
216
262
|
"header.refreshing": "Refreshing...",
|
|
217
263
|
"console.close": "Close (Esc)",
|
|
@@ -222,6 +268,25 @@ window.__ModuleLoader__.load({
|
|
|
222
268
|
"console.title": "Console de gerenciamento do Antigravity",
|
|
223
269
|
"code.title": "Código",
|
|
224
270
|
"code.inspect": "Inspecionar",
|
|
271
|
+
"tv.command": "Comando",
|
|
272
|
+
"tv.write": "Escrever",
|
|
273
|
+
"tv.edit": "Editar",
|
|
274
|
+
"tv.read": "Ler",
|
|
275
|
+
"tv.search": "Buscar",
|
|
276
|
+
"tv.webSearch": "Busca na web",
|
|
277
|
+
"tv.list": "Listar",
|
|
278
|
+
"tv.delete": "Excluir",
|
|
279
|
+
"tv.tool": "Ferramenta",
|
|
280
|
+
"tv.noOutput": "(sem saída)",
|
|
281
|
+
"tv.noMatches": "(nenhuma correspondência)",
|
|
282
|
+
"tv.noChanges": "(sem alterações de texto)",
|
|
283
|
+
"tv.emptyDir": "(diretório vazio)",
|
|
284
|
+
"tv.noDetail": "(sem detalhes)",
|
|
285
|
+
"tv.hint.expandInspect": "Clique para expandir · clique direito para inspecionar",
|
|
286
|
+
"tv.hint.collapseInspect": "Clique para recolher · clique direito para inspecionar",
|
|
287
|
+
"tv.hint.expand": "Clique para expandir",
|
|
288
|
+
"tv.hint.collapse": "Clique para recolher",
|
|
289
|
+
"tv.diffMore": "… {count} linhas restantes não renderizadas",
|
|
225
290
|
"code.copy": "Copiar",
|
|
226
291
|
"code.copied": "Copiado",
|
|
227
292
|
"status.ready": "Pronto",
|
|
@@ -256,6 +321,7 @@ window.__ModuleLoader__.load({
|
|
|
256
321
|
"quota.weekly": "Cota semanal",
|
|
257
322
|
"quota.refreshed": "Cota atualizada",
|
|
258
323
|
"proxy.button": "Proxy",
|
|
324
|
+
"pool.winIsolationWarn": "Windows: o agy guarda o login no Credential Manager do sistema (um único slot), então o pool de contas não isola credenciais — a rotação troca apenas os diretórios e o consumo continua na conta do sistema (issue #45).",
|
|
259
325
|
"proxy.placeholder": "URL do proxy exclusivo (por exemplo: http://127.0.0.1:7890; deixe vazio para usar o proxy global)",
|
|
260
326
|
"proxy.save": "Salvar",
|
|
261
327
|
"proxy.saved": "Proxy salvo",
|
|
@@ -303,6 +369,9 @@ window.__ModuleLoader__.load({
|
|
|
303
369
|
"pool.label": "Agendamento do pool de contas:",
|
|
304
370
|
"pool.sequential": "Usar em sequência",
|
|
305
371
|
"pool.roundRobin": "Rodízio",
|
|
372
|
+
"models.label": "Visibilidade dos modelos:",
|
|
373
|
+
"models.empty": "Ainda não há modelos no catálogo — envie uma mensagem ou clique em \"Atualizar cota\" e volte para gerenciá-los",
|
|
374
|
+
"models.hint": "Clique para mostrar/ocultar. Modelos ocultos não aparecem no seletor de modelos; as sessões em andamento não são afetadas.",
|
|
306
375
|
"header.refreshQuota": "Atualizar cota",
|
|
307
376
|
"header.refreshing": "Atualizando...",
|
|
308
377
|
"console.close": "Fechar (Esc)",
|
|
@@ -313,6 +382,25 @@ window.__ModuleLoader__.load({
|
|
|
313
382
|
"console.title": "Consola de administración de Antigravity",
|
|
314
383
|
"code.title": "Código",
|
|
315
384
|
"code.inspect": "Inspeccionar",
|
|
385
|
+
"tv.command": "Comando",
|
|
386
|
+
"tv.write": "Escribir",
|
|
387
|
+
"tv.edit": "Editar",
|
|
388
|
+
"tv.read": "Leer",
|
|
389
|
+
"tv.search": "Buscar",
|
|
390
|
+
"tv.webSearch": "Búsqueda web",
|
|
391
|
+
"tv.list": "Listar",
|
|
392
|
+
"tv.delete": "Eliminar",
|
|
393
|
+
"tv.tool": "Herramienta",
|
|
394
|
+
"tv.noOutput": "(sin salida)",
|
|
395
|
+
"tv.noMatches": "(sin coincidencias)",
|
|
396
|
+
"tv.noChanges": "(sin cambios de texto)",
|
|
397
|
+
"tv.emptyDir": "(directorio vacío)",
|
|
398
|
+
"tv.noDetail": "(sin detalles)",
|
|
399
|
+
"tv.hint.expandInspect": "Clic para expandir · clic derecho para inspeccionar",
|
|
400
|
+
"tv.hint.collapseInspect": "Clic para contraer · clic derecho para inspeccionar",
|
|
401
|
+
"tv.hint.expand": "Clic para expandir",
|
|
402
|
+
"tv.hint.collapse": "Clic para contraer",
|
|
403
|
+
"tv.diffMore": "… {count} líneas restantes no renderizadas",
|
|
316
404
|
"code.copy": "Copiar",
|
|
317
405
|
"code.copied": "Copiado",
|
|
318
406
|
"status.ready": "Listo",
|
|
@@ -347,6 +435,7 @@ window.__ModuleLoader__.load({
|
|
|
347
435
|
"quota.weekly": "Cuota semanal",
|
|
348
436
|
"quota.refreshed": "Cuota actualizada",
|
|
349
437
|
"proxy.button": "Proxy",
|
|
438
|
+
"pool.winIsolationWarn": "Windows: agy guarda el inicio de sesión en el Credential Manager del sistema (un único espacio), por lo que el pool de cuentas no puede aislar credenciales — la rotación solo cambia de directorio y el consumo sigue en la cuenta del sistema (issue #45).",
|
|
350
439
|
"proxy.placeholder": "URL de proxy exclusivo (por ejemplo: http://127.0.0.1:7890; déjelo vacío para usar el proxy global)",
|
|
351
440
|
"proxy.save": "Guardar",
|
|
352
441
|
"proxy.saved": "Proxy guardado",
|
|
@@ -394,6 +483,9 @@ window.__ModuleLoader__.load({
|
|
|
394
483
|
"pool.label": "Programación del pool de cuentas:",
|
|
395
484
|
"pool.sequential": "Usar en secuencia",
|
|
396
485
|
"pool.roundRobin": "Turno rotativo",
|
|
486
|
+
"models.label": "Visibilidad de modelos:",
|
|
487
|
+
"models.empty": "Aún no hay modelos en el catálogo: envía un mensaje o haz clic en \"Actualizar cuota\" y vuelve para gestionarlos",
|
|
488
|
+
"models.hint": "Haz clic para mostrar/ocultar. Los modelos ocultos no aparecen en el selector de modelos; las sesiones en curso no se ven afectadas.",
|
|
397
489
|
"header.refreshQuota": "Actualizar cuota",
|
|
398
490
|
"header.refreshing": "Actualizando...",
|
|
399
491
|
"console.close": "Cerrar (Esc)",
|
|
@@ -693,7 +785,9 @@ window.__ModuleLoader__.load({
|
|
|
693
785
|
"grep_search",
|
|
694
786
|
"search",
|
|
695
787
|
"search_file_content",
|
|
696
|
-
"grep"
|
|
788
|
+
"grep",
|
|
789
|
+
"search_web",
|
|
790
|
+
"web_search"
|
|
697
791
|
]);
|
|
698
792
|
const LIST_TOOLS = /* @__PURE__ */ new Set(["list_dir", "ls"]);
|
|
699
793
|
const DELETE_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -821,15 +915,30 @@ window.__ModuleLoader__.load({
|
|
|
821
915
|
function cls(...names) {
|
|
822
916
|
return names.filter((n) => typeof n === "string" && n !== "").join(" ");
|
|
823
917
|
}
|
|
824
|
-
|
|
918
|
+
/**
|
|
919
|
+
* Locale lookup with an English fallback: the mirror card renders through
|
|
920
|
+
* host-provided `t` when the registration declares the namespace, but tests
|
|
921
|
+
* and hosts without the seat call it bare. The old literals were mixed
|
|
922
|
+
* 中文 and English as BOTH fallback and primary, so non-Chinese users saw
|
|
923
|
+
* Chinese buttons on mirror cards.
|
|
924
|
+
*/
|
|
925
|
+
function tr(t, key, fallback, params) {
|
|
926
|
+
if (typeof t === "function") try {
|
|
927
|
+
const v = t(key, params);
|
|
928
|
+
if (typeof v === "string" && v !== "" && v !== key) return v;
|
|
929
|
+
} catch {}
|
|
930
|
+
if (params !== void 0 && params.count !== void 0 && fallback.includes("{count}")) return fallback.replace("{count}", String(params.count));
|
|
931
|
+
return fallback;
|
|
932
|
+
}
|
|
933
|
+
function displayTitle(model, t) {
|
|
825
934
|
switch (model.kind) {
|
|
826
|
-
case "terminal": return "Command";
|
|
827
|
-
case "diff": return model.tool === "write_to_file" || model.tool === "write_file" || model.tool === "create_file" ? "Write" : "Edit";
|
|
828
|
-
case "read": return "Read";
|
|
829
|
-
case "search": return "Search";
|
|
830
|
-
case "list": return "List";
|
|
831
|
-
case "delete": return "Delete";
|
|
832
|
-
default: return model.tool ? model.tool.replace(/_/g, " ") : "Tool";
|
|
935
|
+
case "terminal": return tr(t, "tv.command", "Command");
|
|
936
|
+
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");
|
|
937
|
+
case "read": return tr(t, "tv.read", "Read");
|
|
938
|
+
case "search": return model.tool === "search_web" || model.tool === "web_search" ? tr(t, "tv.webSearch", "Web Search") : tr(t, "tv.search", "Search");
|
|
939
|
+
case "list": return tr(t, "tv.list", "List");
|
|
940
|
+
case "delete": return tr(t, "tv.delete", "Delete");
|
|
941
|
+
default: return model.tool ? model.tool.replace(/_/g, " ") : tr(t, "tv.tool", "Tool");
|
|
833
942
|
}
|
|
834
943
|
}
|
|
835
944
|
function displaySummary(model, cwd, home) {
|
|
@@ -839,7 +948,7 @@ window.__ModuleLoader__.load({
|
|
|
839
948
|
const rawPath = model.path ?? "";
|
|
840
949
|
return rawPath !== "" ? relativize(rawPath, cwd, home) : model.title;
|
|
841
950
|
}
|
|
842
|
-
if (model.kind === "search") return model.title.replace(/^Search\s*/i, "") || model.title;
|
|
951
|
+
if (model.kind === "search") return model.title.replace(/^(Web search|Search)\s*/i, "") || model.title;
|
|
843
952
|
if (model.kind === "list") return model.title.replace(/^List\s*(directory\s*)?/i, "") || model.title;
|
|
844
953
|
return model.title;
|
|
845
954
|
}
|
|
@@ -853,16 +962,18 @@ window.__ModuleLoader__.load({
|
|
|
853
962
|
if (oldLines === 0) return `+${newLines}`;
|
|
854
963
|
return `+${newLines} -${oldLines}`;
|
|
855
964
|
}
|
|
856
|
-
function CopyButton({ text, labels }) {
|
|
965
|
+
function CopyButton({ text, labels, t }) {
|
|
857
966
|
const [copied, setCopied] = react().useState(false);
|
|
858
|
-
const copyLabel = labels?.[0] ?? "
|
|
859
|
-
const copiedLabel = labels?.[1] ?? "
|
|
967
|
+
const copyLabel = labels?.[0] ?? tr(t, "code.copy", "Copy");
|
|
968
|
+
const copiedLabel = labels?.[1] ?? tr(t, "code.copied", "Copied");
|
|
860
969
|
const onCopy = (e) => {
|
|
861
970
|
e.stopPropagation();
|
|
862
971
|
if (typeof navigator !== "undefined" && navigator.clipboard) navigator.clipboard.writeText(text).then(() => {
|
|
863
972
|
setCopied(true);
|
|
864
973
|
setTimeout(() => setCopied(false), 1500);
|
|
865
|
-
}).catch(() => {
|
|
974
|
+
}).catch(() => {
|
|
975
|
+
setCopied(false);
|
|
976
|
+
});
|
|
866
977
|
};
|
|
867
978
|
return hx("button", {
|
|
868
979
|
type: "button",
|
|
@@ -871,39 +982,51 @@ window.__ModuleLoader__.load({
|
|
|
871
982
|
title: copied ? copiedLabel : copyLabel
|
|
872
983
|
}, copied ? IconCheckOutline14(11) : IconCopyOutline16(11), hx("span", null, copied ? copiedLabel : copyLabel));
|
|
873
984
|
}
|
|
874
|
-
|
|
985
|
+
/** Per-side render cap: a 5000-line write_to_file used to build 10k DOM rows
|
|
986
|
+
* inside a max-height:280px pane (99% of them invisible). */
|
|
987
|
+
const DIFF_MAX_LINES = 400;
|
|
988
|
+
function DiffBody({ model, t }) {
|
|
875
989
|
const h = hx;
|
|
876
990
|
const oldText = model.oldText ?? "";
|
|
877
991
|
const newText = model.newText ?? "";
|
|
878
992
|
const rows = [];
|
|
993
|
+
const moreRow = (count, key) => h("div", {
|
|
994
|
+
key,
|
|
995
|
+
className: "agy-tv-diff-line",
|
|
996
|
+
style: { color: "var(--dsw-alias-label-tertiary)" }
|
|
997
|
+
}, tr(t, "tv.diffMore", "… {count} more lines not rendered", { count }));
|
|
879
998
|
if (oldText !== "") {
|
|
880
999
|
const lines = oldText.split("\n");
|
|
881
|
-
|
|
1000
|
+
const shown = Math.min(lines.length, DIFF_MAX_LINES);
|
|
1001
|
+
for (let i = 0; i < shown; i++) {
|
|
882
1002
|
const line = lines[i];
|
|
883
1003
|
rows.push(h("div", {
|
|
884
1004
|
key: "del-" + i,
|
|
885
1005
|
className: "agy-tv-diff-line agy-tv-diff-del"
|
|
886
1006
|
}, h("span", { className: "agy-tv-diff-marker" }, "-"), h("span", { style: { flex: 1 } }, line === "" ? " " : line)));
|
|
887
1007
|
}
|
|
1008
|
+
if (lines.length > shown) rows.push(moreRow(lines.length - shown, "del-more"));
|
|
888
1009
|
}
|
|
889
1010
|
if (newText !== "") {
|
|
890
1011
|
const lines = newText.split("\n");
|
|
891
|
-
|
|
1012
|
+
const shown = Math.min(lines.length, DIFF_MAX_LINES);
|
|
1013
|
+
for (let i = 0; i < shown; i++) {
|
|
892
1014
|
const line = lines[i];
|
|
893
1015
|
rows.push(h("div", {
|
|
894
1016
|
key: "add-" + i,
|
|
895
1017
|
className: "agy-tv-diff-line agy-tv-diff-add"
|
|
896
1018
|
}, h("span", { className: "agy-tv-diff-marker" }, "+"), h("span", { style: { flex: 1 } }, line === "" ? " " : line)));
|
|
897
1019
|
}
|
|
1020
|
+
if (lines.length > shown) rows.push(moreRow(lines.length - shown, "add-more"));
|
|
898
1021
|
}
|
|
899
1022
|
if (rows.length === 0) rows.push(h("div", {
|
|
900
1023
|
key: "empty",
|
|
901
1024
|
className: "agy-tv-diff-line",
|
|
902
1025
|
style: { color: "var(--dsw-alias-label-tertiary)" }
|
|
903
|
-
}, "(no textual changes)"));
|
|
1026
|
+
}, tr(t, "tv.noChanges", "(no textual changes)")));
|
|
904
1027
|
return h("div", { className: "agy-tv-diff-list" }, ...rows);
|
|
905
1028
|
}
|
|
906
|
-
function CardBody({ model, openFile, cwd, home, inspect }) {
|
|
1029
|
+
function CardBody({ model, openFile, cwd, home, inspect, t }) {
|
|
907
1030
|
const h = hx;
|
|
908
1031
|
const inspectNode = inspect !== void 0 ? h("div", {
|
|
909
1032
|
key: "ins",
|
|
@@ -912,10 +1035,10 @@ window.__ModuleLoader__.load({
|
|
|
912
1035
|
type: "button",
|
|
913
1036
|
className: "agy-tv-inspect-btn",
|
|
914
1037
|
onClick: inspect
|
|
915
|
-
}, IconInspectOutline12(12), "
|
|
1038
|
+
}, IconInspectOutline12(12), tr(t, "code.inspect", "Inspect"))) : null;
|
|
916
1039
|
switch (model.kind) {
|
|
917
1040
|
case "terminal": {
|
|
918
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no output)";
|
|
1041
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noOutput", "(no output)");
|
|
919
1042
|
const copyText = model.output !== void 0 && model.output !== "" ? model.output : model.command ?? "";
|
|
920
1043
|
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", {
|
|
921
1044
|
key: "cwd",
|
|
@@ -923,7 +1046,10 @@ window.__ModuleLoader__.load({
|
|
|
923
1046
|
}, model.cwd)] : [], h("span", {
|
|
924
1047
|
className: "agy-tv-card-cmd",
|
|
925
1048
|
title: model.command
|
|
926
|
-
}, model.command ?? "")), h(CopyButton, {
|
|
1049
|
+
}, model.command ?? "")), h(CopyButton, {
|
|
1050
|
+
text: copyText,
|
|
1051
|
+
t
|
|
1052
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
927
1053
|
}
|
|
928
1054
|
case "diff": {
|
|
929
1055
|
const pathLabel = relativize(model.path ?? "file", cwd, home);
|
|
@@ -936,38 +1062,51 @@ window.__ModuleLoader__.load({
|
|
|
936
1062
|
model,
|
|
937
1063
|
openFile,
|
|
938
1064
|
cwd,
|
|
939
|
-
home
|
|
1065
|
+
home,
|
|
1066
|
+
t
|
|
940
1067
|
}), inspectNode);
|
|
941
1068
|
}
|
|
942
1069
|
case "read": {
|
|
943
1070
|
const pathLabel = relativize(model.path ?? "file", cwd, home);
|
|
944
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no output)";
|
|
945
|
-
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, {
|
|
1071
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noOutput", "(no output)");
|
|
1072
|
+
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, {
|
|
1073
|
+
text: model.output ?? "",
|
|
1074
|
+
t
|
|
1075
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
946
1076
|
}
|
|
947
1077
|
case "search": {
|
|
948
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(no matches)";
|
|
949
|
-
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, {
|
|
1078
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.noMatches", "(no matches)");
|
|
1079
|
+
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, {
|
|
1080
|
+
text: model.output ?? "",
|
|
1081
|
+
t
|
|
1082
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
950
1083
|
}
|
|
951
1084
|
case "list": {
|
|
952
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : "(empty directory)";
|
|
953
|
-
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, {
|
|
1085
|
+
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : tr(t, "tv.emptyDir", "(empty directory)");
|
|
1086
|
+
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, {
|
|
1087
|
+
text: model.output ?? "",
|
|
1088
|
+
t
|
|
1089
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
954
1090
|
}
|
|
955
1091
|
default: {
|
|
956
1092
|
const copyText = model.output !== void 0 && model.output !== "" ? model.output : model.raw ?? "";
|
|
957
|
-
const rawBody = model.output !== void 0 && model.output !== "" ? trimTrailingBlankLines(model.output) : model.raw !== void 0 && model.raw !== "" ? clip(model.raw, 4e3) : "(no detail)";
|
|
958
|
-
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, {
|
|
1093
|
+
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)");
|
|
1094
|
+
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, {
|
|
1095
|
+
text: copyText,
|
|
1096
|
+
t
|
|
1097
|
+
})), h("pre", { className: "agy-tv-card-content" }, clip(rawBody, 16e3)), inspectNode);
|
|
959
1098
|
}
|
|
960
1099
|
}
|
|
961
1100
|
}
|
|
962
1101
|
function AgyMirrorToolView(props) {
|
|
963
1102
|
const [open, setOpen] = useToggle(false);
|
|
964
1103
|
const h = hx;
|
|
965
|
-
const { block, cwd, home, openFile, inspect } = props;
|
|
1104
|
+
const { block, cwd, home, openFile, inspect, t } = props;
|
|
966
1105
|
const settle = isSettled(block);
|
|
967
1106
|
const err = isError(block);
|
|
968
1107
|
const model = mirrorCardModel(block, cwd, home);
|
|
969
1108
|
const state = !settle ? "run" : err ? "err" : "ok";
|
|
970
|
-
const title = displayTitle(model);
|
|
1109
|
+
const title = displayTitle(model, t);
|
|
971
1110
|
const summary = displaySummary(model, cwd, home);
|
|
972
1111
|
const stat = diffStat(model);
|
|
973
1112
|
const preview = !open && model.kind !== "diff" ? previewLine(model, cwd, home) : void 0;
|
|
@@ -1004,7 +1143,7 @@ window.__ModuleLoader__.load({
|
|
|
1004
1143
|
setOpen();
|
|
1005
1144
|
}
|
|
1006
1145
|
},
|
|
1007
|
-
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",
|
|
1146
|
+
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"),
|
|
1008
1147
|
onContextMenu: inspect !== void 0 ? (e) => {
|
|
1009
1148
|
e.preventDefault();
|
|
1010
1149
|
inspect();
|
|
@@ -1032,7 +1171,8 @@ window.__ModuleLoader__.load({
|
|
|
1032
1171
|
openFile,
|
|
1033
1172
|
cwd,
|
|
1034
1173
|
home,
|
|
1035
|
-
inspect
|
|
1174
|
+
inspect,
|
|
1175
|
+
t
|
|
1036
1176
|
}))] : []);
|
|
1037
1177
|
}
|
|
1038
1178
|
/** Extract the agy mirror cursor (and tool name) from a run_code program. */
|
|
@@ -1104,7 +1244,7 @@ window.__ModuleLoader__.load({
|
|
|
1104
1244
|
setOpen();
|
|
1105
1245
|
}
|
|
1106
1246
|
},
|
|
1107
|
-
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",
|
|
1247
|
+
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"),
|
|
1108
1248
|
onContextMenu: inspect !== void 0 ? (e) => {
|
|
1109
1249
|
e.preventDefault();
|
|
1110
1250
|
inspect();
|
|
@@ -1147,18 +1287,21 @@ window.__ModuleLoader__.load({
|
|
|
1147
1287
|
const block = typed?.block;
|
|
1148
1288
|
const mirror = parseAgyMirrorFromCode(block !== void 0 ? parsedArgsRaw(block) : "{}");
|
|
1149
1289
|
if (mirror === null) return AgyCodeToolView(typed);
|
|
1150
|
-
return AgyMirrorToolView({
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1290
|
+
return AgyMirrorToolView({
|
|
1291
|
+
block: {
|
|
1292
|
+
...block,
|
|
1293
|
+
call: {
|
|
1294
|
+
...block?.call ?? {},
|
|
1295
|
+
name: "agy_tool",
|
|
1296
|
+
argsRaw: JSON.stringify({
|
|
1297
|
+
run: mirror.run,
|
|
1298
|
+
step: mirror.step,
|
|
1299
|
+
...mirror.tool !== void 0 ? { tool: mirror.tool } : {}
|
|
1300
|
+
})
|
|
1301
|
+
}
|
|
1302
|
+
},
|
|
1303
|
+
t: typed?.t
|
|
1304
|
+
});
|
|
1162
1305
|
}
|
|
1163
1306
|
function installAgyToolView(ctx) {
|
|
1164
1307
|
ctx.slots.inject("tool.call.toolview", () => {
|
|
@@ -1166,7 +1309,8 @@ window.__ModuleLoader__.load({
|
|
|
1166
1309
|
name: "tool.call.toolview",
|
|
1167
1310
|
key: "agy_tool",
|
|
1168
1311
|
id: "agy-tool-view",
|
|
1169
|
-
label: "Antigravity tool"
|
|
1312
|
+
label: "Antigravity tool",
|
|
1313
|
+
locale: NS
|
|
1170
1314
|
}, AgyMirrorToolView);
|
|
1171
1315
|
const d2 = ctx.slots.register({
|
|
1172
1316
|
name: "tool.call.toolview",
|
|
@@ -1589,12 +1733,25 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1589
1733
|
white-space: pre-wrap;
|
|
1590
1734
|
padding: 10px 12px;
|
|
1591
1735
|
}
|
|
1736
|
+
/* Prevent Mermaid's internal error DOM or leaked temporary nodes from escaping into document.body.
|
|
1737
|
+
The generic .error-icon/.error-text classes are scoped to OUR mounts and the
|
|
1738
|
+
leaked-body id shapes only — unqualified, they hid host UI using the same
|
|
1739
|
+
class names. */
|
|
1740
|
+
div[data-agy-mermaid-svg] .error-icon,
|
|
1741
|
+
div[data-agy-mermaid-svg] .error-text,
|
|
1742
|
+
body > [id^="dagy-mmd"] .error-icon,
|
|
1743
|
+
body > [id^="iagy-mmd"] .error-icon {
|
|
1744
|
+
display: none !important;
|
|
1745
|
+
}
|
|
1592
1746
|
`;
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1747
|
+
/**
|
|
1748
|
+
* The bundle ships mermaid.min.js and serves it from the plugin route. There
|
|
1749
|
+
* is deliberately NO public-CDN fallback: a floating-version, unsigned
|
|
1750
|
+
* script executing inside the DSH web origin (with reach into every local
|
|
1751
|
+
* HTTP API) is a supply-chain hazard that outweighs offline convenience.
|
|
1752
|
+
* When the local asset is missing the source block simply stays visible.
|
|
1753
|
+
*/
|
|
1754
|
+
const CDN_URLS = ["/plugins/agy-link/mermaid.min.js"];
|
|
1598
1755
|
let loadPromise = null;
|
|
1599
1756
|
let loadFailedAt = 0;
|
|
1600
1757
|
const LOAD_RETRY_MS = 6e4;
|
|
@@ -1612,9 +1769,13 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1612
1769
|
const s = document.createElement("script");
|
|
1613
1770
|
s.src = src;
|
|
1614
1771
|
s.async = true;
|
|
1772
|
+
let settled = false;
|
|
1615
1773
|
const done = (ok) => {
|
|
1774
|
+
if (settled) return;
|
|
1775
|
+
settled = true;
|
|
1616
1776
|
s.removeEventListener("load", onLoad);
|
|
1617
1777
|
s.removeEventListener("error", onError);
|
|
1778
|
+
if (!ok) s.remove();
|
|
1618
1779
|
resolve(ok);
|
|
1619
1780
|
};
|
|
1620
1781
|
const onLoad = () => done(true);
|
|
@@ -1637,7 +1798,8 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1637
1798
|
startOnLoad: false,
|
|
1638
1799
|
securityLevel: "strict",
|
|
1639
1800
|
theme: "neutral",
|
|
1640
|
-
fontFamily: "inherit"
|
|
1801
|
+
fontFamily: "inherit",
|
|
1802
|
+
suppressErrorRendering: true
|
|
1641
1803
|
});
|
|
1642
1804
|
} catch {}
|
|
1643
1805
|
return window.mermaid;
|
|
@@ -1719,6 +1881,16 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1719
1881
|
function readSource(block) {
|
|
1720
1882
|
return ((block.querySelector("[data-code-block-content] code") ?? block.querySelector("[data-code-block-content] pre") ?? block.querySelector("[data-code-block-content]"))?.textContent ?? "").trim();
|
|
1721
1883
|
}
|
|
1884
|
+
function cleanupTempElements(id) {
|
|
1885
|
+
if (typeof document === "undefined") return;
|
|
1886
|
+
if (id) {
|
|
1887
|
+
document.getElementById("d" + id)?.remove();
|
|
1888
|
+
document.getElementById("i" + id)?.remove();
|
|
1889
|
+
document.getElementById(id)?.remove();
|
|
1890
|
+
}
|
|
1891
|
+
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-\"]");
|
|
1892
|
+
for (let i = 0; i < stray.length; i++) stray[i]?.remove();
|
|
1893
|
+
}
|
|
1722
1894
|
async function renderInto(block, source) {
|
|
1723
1895
|
block.querySelector("[data-agy-mermaid-svg]")?.remove();
|
|
1724
1896
|
const mount = document.createElement("div");
|
|
@@ -1731,28 +1903,32 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1731
1903
|
mount.textContent = "Mermaid renderer unavailable (offline). Diagram source stays below.";
|
|
1732
1904
|
return;
|
|
1733
1905
|
}
|
|
1906
|
+
renderSeq += 1;
|
|
1907
|
+
const id = "agy-mmd-" + renderSeq;
|
|
1734
1908
|
try {
|
|
1735
|
-
|
|
1736
|
-
const
|
|
1737
|
-
const { svg } = await api.render(id, source);
|
|
1909
|
+
if (typeof api.parse === "function") await api.parse(source);
|
|
1910
|
+
const { svg } = await api.render(id, source, mount);
|
|
1738
1911
|
mount.innerHTML = svg;
|
|
1739
1912
|
block.setAttribute("data-agy-mermaid", "done");
|
|
1740
1913
|
} catch (e) {
|
|
1741
1914
|
block.setAttribute("data-agy-mermaid", "error");
|
|
1742
1915
|
mount.setAttribute("data-agy-mermaid-error", "1");
|
|
1743
1916
|
mount.textContent = "Mermaid render failed: " + (e instanceof Error ? e.message : String(e));
|
|
1917
|
+
} finally {
|
|
1918
|
+
cleanupTempElements(id);
|
|
1744
1919
|
}
|
|
1745
1920
|
}
|
|
1746
|
-
let scanTimer = null;
|
|
1747
|
-
function scheduleScan() {
|
|
1748
|
-
if (scanTimer !== null) return;
|
|
1749
|
-
scanTimer = setTimeout(() => {
|
|
1750
|
-
scanTimer = null;
|
|
1921
|
+
let scanTimer$1 = null;
|
|
1922
|
+
function scheduleScan$1() {
|
|
1923
|
+
if (scanTimer$1 !== null) return;
|
|
1924
|
+
scanTimer$1 = setTimeout(() => {
|
|
1925
|
+
scanTimer$1 = null;
|
|
1751
1926
|
scan();
|
|
1752
1927
|
}, 150);
|
|
1753
1928
|
}
|
|
1754
1929
|
function scan() {
|
|
1755
1930
|
if (typeof document === "undefined") return;
|
|
1931
|
+
cleanupTempElements();
|
|
1756
1932
|
const blocks = document.querySelectorAll(".md-code-block");
|
|
1757
1933
|
for (let i = 0; i < blocks.length; i++) {
|
|
1758
1934
|
const block = blocks[i];
|
|
@@ -1767,14 +1943,25 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1767
1943
|
renderInto(block, source);
|
|
1768
1944
|
}
|
|
1769
1945
|
}
|
|
1946
|
+
let activeObserver$1 = null;
|
|
1947
|
+
let domContentLoadedHandler$1 = null;
|
|
1948
|
+
/**
|
|
1949
|
+
* Install the mermaid overlay. Returns a disposer that disconnects the
|
|
1950
|
+
* MutationObserver and cancels pending setup — wrap it in ctx.effect so a
|
|
1951
|
+
* plugin reload cannot stack observers over the same document.
|
|
1952
|
+
*/
|
|
1770
1953
|
function installMermaidRendering() {
|
|
1771
|
-
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1954
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
1955
|
+
disposeMermaidRendering();
|
|
1772
1956
|
injectStyles$1();
|
|
1957
|
+
cleanupTempElements();
|
|
1773
1958
|
const observer = new MutationObserver(() => {
|
|
1774
|
-
scheduleScan();
|
|
1959
|
+
scheduleScan$1();
|
|
1775
1960
|
});
|
|
1961
|
+
activeObserver$1 = observer;
|
|
1776
1962
|
const setup = () => {
|
|
1777
1963
|
if (document.body) {
|
|
1964
|
+
cleanupTempElements();
|
|
1778
1965
|
observer.observe(document.body, {
|
|
1779
1966
|
childList: true,
|
|
1780
1967
|
subtree: true
|
|
@@ -1782,8 +1969,26 @@ div[data-agy-mermaid-svg][data-agy-mermaid-error] {
|
|
|
1782
1969
|
scan();
|
|
1783
1970
|
}
|
|
1784
1971
|
};
|
|
1785
|
-
if (document.readyState === "loading")
|
|
1786
|
-
|
|
1972
|
+
if (document.readyState === "loading") {
|
|
1973
|
+
domContentLoadedHandler$1 = setup;
|
|
1974
|
+
window.addEventListener("DOMContentLoaded", setup, { once: true });
|
|
1975
|
+
} else setup();
|
|
1976
|
+
return disposeMermaidRendering;
|
|
1977
|
+
}
|
|
1978
|
+
/** Disconnect the observer and cancel pending setup work. */
|
|
1979
|
+
function disposeMermaidRendering() {
|
|
1980
|
+
if (activeObserver$1 !== null) {
|
|
1981
|
+
activeObserver$1.disconnect();
|
|
1982
|
+
activeObserver$1 = null;
|
|
1983
|
+
}
|
|
1984
|
+
if (domContentLoadedHandler$1 !== null) {
|
|
1985
|
+
window.removeEventListener("DOMContentLoaded", domContentLoadedHandler$1);
|
|
1986
|
+
domContentLoadedHandler$1 = null;
|
|
1987
|
+
}
|
|
1988
|
+
if (scanTimer$1 !== null) {
|
|
1989
|
+
clearTimeout(scanTimer$1);
|
|
1990
|
+
scanTimer$1 = null;
|
|
1991
|
+
}
|
|
1787
1992
|
}
|
|
1788
1993
|
//#endregion
|
|
1789
1994
|
//#region src/client/reasoning.ts
|
|
@@ -1845,9 +2050,16 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1845
2050
|
* Try to expand a thinking row once when its body contains real prose
|
|
1846
2051
|
* (not a bare [agy thinking turn · N tokens] chip). Uses the host's own
|
|
1847
2052
|
* disclosure control when present — never mutates thinkBody children.
|
|
2053
|
+
*
|
|
2054
|
+
* A row the user manually COLLAPSED is recorded in a WeakSet keyed by the
|
|
2055
|
+
* row element; React keeps the same element identity across its own
|
|
2056
|
+
* re-renders, so the scanner stops re-expanding it (the old data attribute
|
|
2057
|
+
* survived only until React rebuilt the node).
|
|
1848
2058
|
*/
|
|
2059
|
+
const userCollapsed = typeof WeakSet !== "undefined" ? /* @__PURE__ */ new WeakSet() : null;
|
|
1849
2060
|
function tryExpandThinkRow(root) {
|
|
1850
2061
|
if (root.dataset.agyExpanded === "true") return;
|
|
2062
|
+
if (userCollapsed?.has(root) === true) return;
|
|
1851
2063
|
const body = root.querySelector("[class*=\"thinkBody\"]");
|
|
1852
2064
|
if (!body) return;
|
|
1853
2065
|
const text = (body.textContent ?? "").trim();
|
|
@@ -1859,10 +2071,15 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1859
2071
|
return;
|
|
1860
2072
|
}
|
|
1861
2073
|
const toggle = root.querySelector("[data-disclosure-row]") ?? root.querySelector("[class*=\"disclosure\"]") ?? root.querySelector("button");
|
|
1862
|
-
if (toggle)
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
2074
|
+
if (toggle) {
|
|
2075
|
+
userCollapsed?.add(root);
|
|
2076
|
+
try {
|
|
2077
|
+
toggle.click();
|
|
2078
|
+
root.dataset.agyExpanded = "true";
|
|
2079
|
+
} catch {
|
|
2080
|
+
userCollapsed?.delete(root);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
1866
2083
|
}
|
|
1867
2084
|
function scanThinkingRows() {
|
|
1868
2085
|
if (typeof document === "undefined") return;
|
|
@@ -1872,12 +2089,29 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1872
2089
|
if (row) tryExpandThinkRow(row);
|
|
1873
2090
|
}
|
|
1874
2091
|
}
|
|
2092
|
+
let scanTimer = null;
|
|
2093
|
+
function scheduleScan() {
|
|
2094
|
+
if (scanTimer !== null) return;
|
|
2095
|
+
scanTimer = setTimeout(() => {
|
|
2096
|
+
scanTimer = null;
|
|
2097
|
+
scanThinkingRows();
|
|
2098
|
+
}, 200);
|
|
2099
|
+
}
|
|
2100
|
+
let activeObserver = null;
|
|
2101
|
+
let domContentLoadedHandler = null;
|
|
2102
|
+
/**
|
|
2103
|
+
* Install the auto-expand reasoning overlay. Returns a disposer that
|
|
2104
|
+
* disconnects the MutationObserver — wrap it in ctx.effect so a plugin
|
|
2105
|
+
* reload cannot stack observers.
|
|
2106
|
+
*/
|
|
1875
2107
|
function installAutoExpandReasoning() {
|
|
1876
|
-
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
2108
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {};
|
|
2109
|
+
disposeAutoExpandReasoning();
|
|
1877
2110
|
injectStyles();
|
|
1878
2111
|
const observer = new MutationObserver(() => {
|
|
1879
|
-
|
|
2112
|
+
scheduleScan();
|
|
1880
2113
|
});
|
|
2114
|
+
activeObserver = observer;
|
|
1881
2115
|
const setupObserver = () => {
|
|
1882
2116
|
if (document.body) {
|
|
1883
2117
|
observer.observe(document.body, {
|
|
@@ -1887,8 +2121,26 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1887
2121
|
scanThinkingRows();
|
|
1888
2122
|
}
|
|
1889
2123
|
};
|
|
1890
|
-
if (document.readyState === "loading")
|
|
1891
|
-
|
|
2124
|
+
if (document.readyState === "loading") {
|
|
2125
|
+
domContentLoadedHandler = setupObserver;
|
|
2126
|
+
window.addEventListener("DOMContentLoaded", setupObserver, { once: true });
|
|
2127
|
+
} else setupObserver();
|
|
2128
|
+
return disposeAutoExpandReasoning;
|
|
2129
|
+
}
|
|
2130
|
+
/** Disconnect the observer and cancel pending work. */
|
|
2131
|
+
function disposeAutoExpandReasoning() {
|
|
2132
|
+
if (activeObserver !== null) {
|
|
2133
|
+
activeObserver.disconnect();
|
|
2134
|
+
activeObserver = null;
|
|
2135
|
+
}
|
|
2136
|
+
if (domContentLoadedHandler !== null) {
|
|
2137
|
+
window.removeEventListener("DOMContentLoaded", domContentLoadedHandler);
|
|
2138
|
+
domContentLoadedHandler = null;
|
|
2139
|
+
}
|
|
2140
|
+
if (scanTimer !== null) {
|
|
2141
|
+
clearTimeout(scanTimer);
|
|
2142
|
+
scanTimer = null;
|
|
2143
|
+
}
|
|
1892
2144
|
}
|
|
1893
2145
|
//#endregion
|
|
1894
2146
|
//#region src/client/index.ts
|
|
@@ -1906,7 +2158,9 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1906
2158
|
let statusCache = null;
|
|
1907
2159
|
async function getStatus() {
|
|
1908
2160
|
try {
|
|
1909
|
-
const
|
|
2161
|
+
const init = {};
|
|
2162
|
+
if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") init.signal = AbortSignal.timeout(5e3);
|
|
2163
|
+
const res = await win.fetch?.(base + "/plugins/agy-link/status", init);
|
|
1910
2164
|
if (!res || !res.ok) return null;
|
|
1911
2165
|
const payload = await res.json();
|
|
1912
2166
|
statusCache = payload;
|
|
@@ -1924,7 +2178,12 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1924
2178
|
});
|
|
1925
2179
|
if (!res) return null;
|
|
1926
2180
|
try {
|
|
1927
|
-
|
|
2181
|
+
const payload = await res.json();
|
|
2182
|
+
if (!res.ok && payload !== null && typeof payload === "object") return {
|
|
2183
|
+
ok: false,
|
|
2184
|
+
...payload
|
|
2185
|
+
};
|
|
2186
|
+
return payload;
|
|
1928
2187
|
} catch {
|
|
1929
2188
|
return { ok: res.ok };
|
|
1930
2189
|
}
|
|
@@ -1932,6 +2191,58 @@ div[data-variant="think"] [class*="thinkBody"] {
|
|
|
1932
2191
|
return null;
|
|
1933
2192
|
}
|
|
1934
2193
|
}
|
|
2194
|
+
const statusListeners = /* @__PURE__ */ new Set();
|
|
2195
|
+
let statusPollTimer = null;
|
|
2196
|
+
let statusFetchSeq = 0;
|
|
2197
|
+
function notifyStatus(st) {
|
|
2198
|
+
statusCache = st;
|
|
2199
|
+
for (const fn of [...statusListeners]) try {
|
|
2200
|
+
fn(st);
|
|
2201
|
+
} catch {}
|
|
2202
|
+
}
|
|
2203
|
+
async function statusPollTick() {
|
|
2204
|
+
const seq = ++statusFetchSeq;
|
|
2205
|
+
const st = await getStatus();
|
|
2206
|
+
if (st !== null && seq === statusFetchSeq) notifyStatus(st);
|
|
2207
|
+
}
|
|
2208
|
+
function ensureStatusPolling() {
|
|
2209
|
+
if (statusPollTimer !== null) return;
|
|
2210
|
+
statusPollTick();
|
|
2211
|
+
statusPollTimer = setInterval(() => {
|
|
2212
|
+
statusPollTick();
|
|
2213
|
+
}, 3e3);
|
|
2214
|
+
}
|
|
2215
|
+
function stopStatusPollingIfIdle() {
|
|
2216
|
+
if (statusListeners.size === 0 && statusPollTimer !== null) {
|
|
2217
|
+
clearInterval(statusPollTimer);
|
|
2218
|
+
statusPollTimer = null;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
/**
|
|
2222
|
+
* Subscribe a component to the shared status poll. Returns the latest
|
|
2223
|
+
* snapshot plus a manual refresh that keeps the last good snapshot on a
|
|
2224
|
+
* transient failure (a failed refresh used to flip the whole panel back to
|
|
2225
|
+
* its loading state).
|
|
2226
|
+
*/
|
|
2227
|
+
function useAgyStatus() {
|
|
2228
|
+
const [status, setStatus] = useState(statusCache);
|
|
2229
|
+
useEffect(() => {
|
|
2230
|
+
statusListeners.add(setStatus);
|
|
2231
|
+
ensureStatusPolling();
|
|
2232
|
+
return () => {
|
|
2233
|
+
statusListeners.delete(setStatus);
|
|
2234
|
+
stopStatusPollingIfIdle();
|
|
2235
|
+
};
|
|
2236
|
+
}, []);
|
|
2237
|
+
const refresh = async () => {
|
|
2238
|
+
const st = await getStatus();
|
|
2239
|
+
if (st !== null) notifyStatus(st);
|
|
2240
|
+
};
|
|
2241
|
+
return {
|
|
2242
|
+
status,
|
|
2243
|
+
refresh
|
|
2244
|
+
};
|
|
2245
|
+
}
|
|
1935
2246
|
/** Global modal state for opening Antigravity console dialog from footer shortcut or header status */
|
|
1936
2247
|
const agyModalStore = {
|
|
1937
2248
|
open: false,
|
|
@@ -2642,7 +2953,7 @@ body.dark,
|
|
|
2642
2953
|
};
|
|
2643
2954
|
const AgySettingsSection = (props) => {
|
|
2644
2955
|
const t = useAgyTranslation();
|
|
2645
|
-
const
|
|
2956
|
+
const { status, refresh } = useAgyStatus();
|
|
2646
2957
|
const [aliasInput, setAliasInput] = useState("");
|
|
2647
2958
|
const [proxyInputs, setProxyInputs] = useState({});
|
|
2648
2959
|
const [editingProxyId, setEditingProxyId] = useState(null);
|
|
@@ -2651,24 +2962,10 @@ body.dark,
|
|
|
2651
2962
|
const [loadingAction, setLoadingAction] = useState(null);
|
|
2652
2963
|
const [toast, setToast] = useState(null);
|
|
2653
2964
|
const [expandedModels, setExpandedModels] = useState({});
|
|
2965
|
+
const [, setTimeTick] = useState(0);
|
|
2654
2966
|
useEffect(() => {
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
const tick = async () => {
|
|
2658
|
-
const st = await getStatus();
|
|
2659
|
-
if (!alive || !st) return;
|
|
2660
|
-
const json = JSON.stringify(st);
|
|
2661
|
-
if (json !== lastJson) {
|
|
2662
|
-
lastJson = json;
|
|
2663
|
-
setStatus(st);
|
|
2664
|
-
}
|
|
2665
|
-
};
|
|
2666
|
-
tick();
|
|
2667
|
-
const timer = setInterval(tick, 3e3);
|
|
2668
|
-
return () => {
|
|
2669
|
-
alive = false;
|
|
2670
|
-
clearInterval(timer);
|
|
2671
|
-
};
|
|
2967
|
+
const timer = setInterval(() => setTimeTick((n) => n + 1), 3e4);
|
|
2968
|
+
return () => clearInterval(timer);
|
|
2672
2969
|
}, []);
|
|
2673
2970
|
const flowStartedRef = useRef(false);
|
|
2674
2971
|
const safeMessage = (code) => {
|
|
@@ -2694,18 +2991,24 @@ body.dark,
|
|
|
2694
2991
|
status?.poolAuth?.phase,
|
|
2695
2992
|
status?.poolAuth?.code
|
|
2696
2993
|
]);
|
|
2994
|
+
const toastTimerRef = useRef(null);
|
|
2995
|
+
useEffect(() => () => {
|
|
2996
|
+
if (toastTimerRef.current !== null) clearTimeout(toastTimerRef.current);
|
|
2997
|
+
}, []);
|
|
2697
2998
|
const showToast = (text, type = "info") => {
|
|
2698
2999
|
setToast({
|
|
2699
3000
|
text,
|
|
2700
3001
|
type,
|
|
2701
3002
|
id: Date.now()
|
|
2702
3003
|
});
|
|
2703
|
-
|
|
2704
|
-
|
|
3004
|
+
if (toastTimerRef.current !== null) clearTimeout(toastTimerRef.current);
|
|
3005
|
+
toastTimerRef.current = setTimeout(() => {
|
|
3006
|
+
toastTimerRef.current = null;
|
|
3007
|
+
setToast((prev) => prev !== null && prev.text === text ? null : prev);
|
|
2705
3008
|
}, 6e3);
|
|
2706
3009
|
};
|
|
2707
|
-
const
|
|
2708
|
-
|
|
3010
|
+
const actionFailed = () => {
|
|
3011
|
+
showToast(t("api.genericError"), "error");
|
|
2709
3012
|
};
|
|
2710
3013
|
const handleBeginAddAccount = async () => {
|
|
2711
3014
|
setLoadingAction("pool:beginAdd");
|
|
@@ -2743,30 +3046,62 @@ body.dark,
|
|
|
2743
3046
|
};
|
|
2744
3047
|
const setCfg = async (key, value) => {
|
|
2745
3048
|
setLoadingAction(`config:${key}`);
|
|
2746
|
-
await postJson("/plugins/agy-link/config", {
|
|
3049
|
+
const res = await postJson("/plugins/agy-link/config", {
|
|
2747
3050
|
key,
|
|
2748
3051
|
value
|
|
2749
3052
|
});
|
|
3053
|
+
if (res === null || res?.ok === false) {
|
|
3054
|
+
setLoadingAction(null);
|
|
3055
|
+
actionFailed();
|
|
3056
|
+
return;
|
|
3057
|
+
}
|
|
2750
3058
|
await refresh();
|
|
2751
3059
|
setLoadingAction(null);
|
|
2752
3060
|
};
|
|
3061
|
+
const hiddenPendingRef = useRef(null);
|
|
3062
|
+
const toggleModelHidden = async (id, hide) => {
|
|
3063
|
+
const next = new Set(hiddenPendingRef.current ?? status?.hiddenModels ?? []);
|
|
3064
|
+
if (hide) next.add(id);
|
|
3065
|
+
else next.delete(id);
|
|
3066
|
+
hiddenPendingRef.current = next;
|
|
3067
|
+
try {
|
|
3068
|
+
await setCfg("hiddenModels", Array.from(next));
|
|
3069
|
+
} finally {
|
|
3070
|
+
if (hiddenPendingRef.current === next) hiddenPendingRef.current = null;
|
|
3071
|
+
}
|
|
3072
|
+
};
|
|
2753
3073
|
const setPrimary = async (id) => {
|
|
2754
3074
|
setLoadingAction(`primary:${id}`);
|
|
2755
|
-
await postJson("/plugins/agy-link/pool/primary", { id });
|
|
3075
|
+
const res = await postJson("/plugins/agy-link/pool/primary", { id });
|
|
3076
|
+
if (res === null || res?.ok === false) {
|
|
3077
|
+
setLoadingAction(null);
|
|
3078
|
+
actionFailed();
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
2756
3081
|
await refresh();
|
|
2757
3082
|
setLoadingAction(null);
|
|
2758
3083
|
showToast(t("account.setPrimary"), "success");
|
|
2759
3084
|
};
|
|
2760
3085
|
const removeAccount = async (id, alias) => {
|
|
2761
3086
|
setLoadingAction(`remove:${id}`);
|
|
2762
|
-
await postJson("/plugins/agy-link/pool/remove", { id });
|
|
3087
|
+
const res = await postJson("/plugins/agy-link/pool/remove", { id });
|
|
3088
|
+
if (res === null || res?.ok === false) {
|
|
3089
|
+
setLoadingAction(null);
|
|
3090
|
+
actionFailed();
|
|
3091
|
+
return;
|
|
3092
|
+
}
|
|
2763
3093
|
await refresh();
|
|
2764
3094
|
setLoadingAction(null);
|
|
2765
3095
|
showToast(t("account.removed", { alias }), "info");
|
|
2766
3096
|
};
|
|
2767
3097
|
const refreshQuota = async (id) => {
|
|
2768
3098
|
setLoadingAction(id ? `refresh:${id}` : "refresh:all");
|
|
2769
|
-
await postJson("/plugins/agy-link/pool/refresh-quota", { id });
|
|
3099
|
+
const res = await postJson("/plugins/agy-link/pool/refresh-quota", { id });
|
|
3100
|
+
if (res === null || res?.ok === false) {
|
|
3101
|
+
setLoadingAction(null);
|
|
3102
|
+
actionFailed();
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
2770
3105
|
await refresh();
|
|
2771
3106
|
setLoadingAction(null);
|
|
2772
3107
|
showToast(t("quota.refreshed"), "success");
|
|
@@ -2774,10 +3109,15 @@ body.dark,
|
|
|
2774
3109
|
const saveProxy = async (id) => {
|
|
2775
3110
|
setLoadingAction(`proxy:${id}`);
|
|
2776
3111
|
const proxyUrl = proxyInputs[id];
|
|
2777
|
-
await postJson("/plugins/agy-link/pool/proxy", {
|
|
3112
|
+
const res = await postJson("/plugins/agy-link/pool/proxy", {
|
|
2778
3113
|
id,
|
|
2779
3114
|
proxyUrl
|
|
2780
3115
|
});
|
|
3116
|
+
if (res === null || res?.ok === false) {
|
|
3117
|
+
setLoadingAction(null);
|
|
3118
|
+
actionFailed();
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
2781
3121
|
setEditingProxyId(null);
|
|
2782
3122
|
await refresh();
|
|
2783
3123
|
setLoadingAction(null);
|
|
@@ -2785,13 +3125,23 @@ body.dark,
|
|
|
2785
3125
|
};
|
|
2786
3126
|
const setMode = async (mode) => {
|
|
2787
3127
|
setLoadingAction(`mode:${mode}`);
|
|
2788
|
-
await postJson("/plugins/agy-link/pool/mode", { mode });
|
|
3128
|
+
const res = await postJson("/plugins/agy-link/pool/mode", { mode });
|
|
3129
|
+
if (res === null || res?.ok === false) {
|
|
3130
|
+
setLoadingAction(null);
|
|
3131
|
+
actionFailed();
|
|
3132
|
+
return;
|
|
3133
|
+
}
|
|
2789
3134
|
await refresh();
|
|
2790
3135
|
setLoadingAction(null);
|
|
2791
3136
|
};
|
|
2792
3137
|
const clearCooldown = async (id) => {
|
|
2793
3138
|
setLoadingAction(id ? `clearCooldown:${id}` : "clearCooldown:all");
|
|
2794
|
-
await postJson("/plugins/agy-link/pool/clear-cooldown", { id });
|
|
3139
|
+
const res = await postJson("/plugins/agy-link/pool/clear-cooldown", { id });
|
|
3140
|
+
if (res === null || res?.ok === false) {
|
|
3141
|
+
setLoadingAction(null);
|
|
3142
|
+
actionFailed();
|
|
3143
|
+
return;
|
|
3144
|
+
}
|
|
2795
3145
|
await refresh();
|
|
2796
3146
|
setLoadingAction(null);
|
|
2797
3147
|
showToast(t("account.clearCooldown"), "success");
|
|
@@ -2804,6 +3154,8 @@ body.dark,
|
|
|
2804
3154
|
};
|
|
2805
3155
|
const authPhase = status?.auth?.phase ?? "unknown";
|
|
2806
3156
|
const pool = status?.pool;
|
|
3157
|
+
const catalogModels = status?.catalogModels ?? [];
|
|
3158
|
+
const hiddenModelSet = new Set(status?.hiddenModels ?? []);
|
|
2807
3159
|
const accounts = pool?.accounts ?? [];
|
|
2808
3160
|
const isAuthed = authPhase === "ok" || accounts.length > 0;
|
|
2809
3161
|
const isBusy = loadingAction !== null;
|
|
@@ -3313,7 +3665,21 @@ body.dark,
|
|
|
3313
3665
|
},
|
|
3314
3666
|
disabled: isBusy,
|
|
3315
3667
|
onClick: () => void refreshQuota()
|
|
3316
|
-
}, loadingAction === "refresh:all" ? [renderSpinner(), t("header.refreshing")] : [uiIcon("refresh", 12, "var(--agy-text-btn)"), ` ${t("header.refreshQuota")}`]))), renderToastBanner(),
|
|
3668
|
+
}, loadingAction === "refresh:all" ? [renderSpinner(), t("header.refreshing")] : [uiIcon("refresh", 12, "var(--agy-text-btn)"), ` ${t("header.refreshQuota")}`]))), renderToastBanner(), status?.credentialIsolationLimited === true ? h("div", {
|
|
3669
|
+
key: "win-isolation",
|
|
3670
|
+
style: {
|
|
3671
|
+
display: "flex",
|
|
3672
|
+
alignItems: "flex-start",
|
|
3673
|
+
gap: "6px",
|
|
3674
|
+
padding: "8px 10px",
|
|
3675
|
+
marginBottom: "8px",
|
|
3676
|
+
background: "var(--agy-amber-soft, rgba(245, 158, 11, 0.12))",
|
|
3677
|
+
border: "1px solid rgba(245, 158, 11, 0.45)",
|
|
3678
|
+
borderRadius: "7px",
|
|
3679
|
+
fontSize: "11.5px",
|
|
3680
|
+
color: "var(--agy-text-primary)"
|
|
3681
|
+
}
|
|
3682
|
+
}, h("span", { style: { flexShrink: 0 } }, "⚠️"), h("span", null, t("pool.winIsolationWarn"))) : null, addAccountSection, renderedAccountCards, h("div", { style: {
|
|
3317
3683
|
marginTop: "16px",
|
|
3318
3684
|
paddingTop: "12px",
|
|
3319
3685
|
borderTop: "1px solid var(--agy-border-divider)"
|
|
@@ -3386,7 +3752,33 @@ body.dark,
|
|
|
3386
3752
|
type: "button",
|
|
3387
3753
|
style: pool?.mode === "round-robin" ? S.segBtnActive : S.segBtn,
|
|
3388
3754
|
onClick: () => void setMode("round-robin")
|
|
3389
|
-
}, t("pool.roundRobin"))))
|
|
3755
|
+
}, t("pool.roundRobin")))), h("div", { style: {
|
|
3756
|
+
display: "flex",
|
|
3757
|
+
flexDirection: "column",
|
|
3758
|
+
gap: "6px"
|
|
3759
|
+
} }, h("span", { style: {
|
|
3760
|
+
color: "var(--agy-text-primary)",
|
|
3761
|
+
fontWeight: 600,
|
|
3762
|
+
fontSize: "12.5px"
|
|
3763
|
+
} }, t("models.label")), catalogModels.length === 0 ? h("span", { style: S.muted }, t("models.empty")) : h("div", { style: {
|
|
3764
|
+
display: "flex",
|
|
3765
|
+
flexWrap: "wrap",
|
|
3766
|
+
gap: "6px"
|
|
3767
|
+
} }, catalogModels.map((m) => {
|
|
3768
|
+
const isHidden = hiddenModelSet.has(m.id);
|
|
3769
|
+
return h("button", {
|
|
3770
|
+
type: "button",
|
|
3771
|
+
key: m.id,
|
|
3772
|
+
title: m.id,
|
|
3773
|
+
disabled: loadingAction === "config:hiddenModels",
|
|
3774
|
+
style: isHidden ? {
|
|
3775
|
+
...S.segBtn,
|
|
3776
|
+
opacity: .45,
|
|
3777
|
+
textDecoration: "line-through"
|
|
3778
|
+
} : S.segBtnActive,
|
|
3779
|
+
onClick: () => void toggleModelHidden(m.id, !isHidden)
|
|
3780
|
+
}, m.name);
|
|
3781
|
+
})), h("span", { style: S.muted }, t("models.hint"))))));
|
|
3390
3782
|
};
|
|
3391
3783
|
/** Modal dialog container rendered into document.body */
|
|
3392
3784
|
const AgyModalDialog = () => {
|
|
@@ -3466,37 +3858,24 @@ body.dark,
|
|
|
3466
3858
|
/** Session Header badge in chat toolbar */
|
|
3467
3859
|
const AgySessionStatus = () => {
|
|
3468
3860
|
const t = useAgyTranslation();
|
|
3469
|
-
const
|
|
3861
|
+
const { status } = useAgyStatus();
|
|
3862
|
+
const [, setTimeTick] = useState(0);
|
|
3470
3863
|
useEffect(() => {
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
const tick = async () => {
|
|
3474
|
-
const st = await getStatus();
|
|
3475
|
-
if (!alive || !st) return;
|
|
3476
|
-
const json = JSON.stringify(st);
|
|
3477
|
-
if (json !== lastJson) {
|
|
3478
|
-
lastJson = json;
|
|
3479
|
-
setStatus(st);
|
|
3480
|
-
}
|
|
3481
|
-
};
|
|
3482
|
-
tick();
|
|
3483
|
-
const timer = setInterval(tick, 3e3);
|
|
3484
|
-
return () => {
|
|
3485
|
-
alive = false;
|
|
3486
|
-
clearInterval(timer);
|
|
3487
|
-
};
|
|
3864
|
+
const timer = setInterval(() => setTimeTick((n) => n + 1), 3e4);
|
|
3865
|
+
return () => clearInterval(timer);
|
|
3488
3866
|
}, []);
|
|
3489
3867
|
const pool = status?.pool;
|
|
3490
3868
|
const accounts = pool?.accounts ?? [];
|
|
3491
3869
|
const rawActiveId = pool?.activeAccountId ?? pool?.lastActiveAccountId ?? pool?.activeAccountIds?.google ?? pool?.primaryAccountId;
|
|
3492
3870
|
const activeAcc = accounts.find((a) => a.id === rawActiveId && a.enabled && !a.authRequired) ?? accounts.find((a) => a.enabled && !a.authRequired) ?? accounts[0];
|
|
3493
|
-
const activeHasCooldown = activeAcc ? Object.entries(activeAcc.cooldowns).some(([, cd]) => cd && cd.cooldownUntil > Date.now()) : false;
|
|
3494
|
-
const allInCooldown = accounts.length > 0 && accounts.every((a) => !a.enabled || a.authRequired || Object.entries(a.cooldowns).some(([, cd]) => cd && cd.cooldownUntil > Date.now()));
|
|
3871
|
+
const activeHasCooldown = activeAcc ? Object.entries(activeAcc.cooldowns ?? {}).some(([, cd]) => cd && cd.cooldownUntil > Date.now()) : false;
|
|
3872
|
+
const allInCooldown = accounts.length > 0 && accounts.every((a) => !a.enabled || a.authRequired || Object.entries(a.cooldowns ?? {}).some(([, cd]) => cd && cd.cooldownUntil > Date.now()));
|
|
3495
3873
|
const isAuthed = status?.auth?.phase === "ok" || accounts.length > 0;
|
|
3496
3874
|
const color = status === null ? "#64748b" : status.dormantReason ? "#f59e0b" : allInCooldown ? "#f59e0b" : activeHasCooldown ? "#f59e0b" : isAuthed ? "#10b981" : "#f59e0b";
|
|
3497
3875
|
const legacyDefault = activeAcc && activeAcc.defaultAlias === void 0 && activeAcc.systemHome && activeAcc.alias === "主账号 (系统登录)";
|
|
3498
3876
|
const displayAlias = activeAcc ? activeAcc.defaultAlias || legacyDefault ? activeAcc.systemHome ? t("account.defaultAlias") : t("account.aliasDefault", { number: accounts.indexOf(activeAcc) + 1 }) : activeAcc.alias : "";
|
|
3499
|
-
const
|
|
3877
|
+
const activeEligible = activeAcc !== void 0 && activeAcc.enabled && !activeAcc.authRequired;
|
|
3878
|
+
const activeDetail = activeAcc !== void 0 && activeEligible ? ` · ${t("status.inUse")}: ${displayAlias}${activeAcc.email ? ` (${activeAcc.email})` : ""}` : "";
|
|
3500
3879
|
const badgeTitle = `${t("header.badgeTitle", { count: accounts.length })}${activeDetail}`;
|
|
3501
3880
|
const buttonLabel = displayAlias ? `AGY · ${displayAlias}` : `AGY (${accounts.length})`;
|
|
3502
3881
|
const badge = h("button", {
|
|
@@ -3547,8 +3926,8 @@ body.dark,
|
|
|
3547
3926
|
}, AgySettingsSection);
|
|
3548
3927
|
});
|
|
3549
3928
|
installAgyToolView(ctx);
|
|
3550
|
-
installAutoExpandReasoning();
|
|
3551
|
-
installMermaidRendering();
|
|
3929
|
+
ctx.effect(() => installAutoExpandReasoning());
|
|
3930
|
+
ctx.effect(() => installMermaidRendering());
|
|
3552
3931
|
}
|
|
3553
3932
|
//#endregion
|
|
3554
3933
|
exports.apply = apply;
|