minecodex 2.0.44 → 2.0.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/README.md +0 -1
- package/apps/dashboard/app.js +1 -1
- package/apps/dashboard/assets/preview-content.js +4 -3
- package/features/file-navigation/src/adapters/codex/modules.mjs +10 -11
- package/features/files-auto-refresh/assets/folder-sync.svg +7 -0
- package/features/files-auto-refresh/codex-feature.json +17 -0
- package/features/files-auto-refresh/src/adapters/codex/directories.mjs +75 -0
- package/features/files-auto-refresh/src/entry.mjs +58 -0
- package/features/files-auto-refresh/src/injection-source.mjs +8 -0
- package/features/files-auto-refresh/src/refresh.mjs +32 -0
- package/features/files-auto-refresh/vendor/lucide-LICENSE +43 -0
- package/features/images/src/adapters/codex/native-image-modules.mjs +11 -4
- package/features/images/src/frontend/local-image-source.mjs +11 -1
- package/features/markdown-reading/src/adapters/codex/table-actions.mjs +16 -17
- package/features/markdown-reading/src/adapters/codex/tables.mjs +18 -4
- package/features/markdown-reading/src/injection-source.mjs +2 -1
- package/features/mermaid-diagrams/src/adapters/codex/native.mjs +14 -6
- package/features/model-slider/src/frontend/install.mjs +11 -2
- package/features/model-slider/src/injection-source.mjs +2 -1
- package/features/quick-chat/assets/close.svg +15 -0
- package/features/quick-chat/codex-feature.json +2 -1
- package/features/quick-chat/src/adapters/codex/lifecycle.mjs +27 -0
- package/features/quick-chat/src/adapters/codex/renderer.mjs +8 -5
- package/features/quick-chat/src/adapters/codex/shortcut.mjs +38 -14
- package/features/quick-chat/src/frontend/entry.mjs +33 -18
- package/features/quick-chat/src/injection-source.mjs +2 -1
- package/features/usage-meter/src/adapters/codex/renderer.mjs +14 -4
- package/features/usage-meter/src/usage-meter.mjs +24 -19
- package/package.json +6 -4
- package/packages/cli/src/config.mjs +4 -2
- package/packages/cli/src/control-server.mjs +1 -1
- package/packages/ui/src/native/tokens.mjs +2 -0
- package/features/hide-upsell-banner/codex-feature.json +0 -24
- package/features/hide-upsell-banner/src/hide-upsell-banner.mjs +0 -94
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// page-script feature body.
|
|
2
|
-
// Injected by CodexRuntimeHost into the Codex renderer through
|
|
3
|
-
// `new Function("signal", "window", "document", "MutationObserver", source)`,
|
|
4
|
-
// so this file is a function body: it runs once with those bindings in scope
|
|
5
|
-
// and may return a cleanup function. It hides the "You're out of Codex and
|
|
6
|
-
// Work usage" upsell banner that the desktop app renders above the composer
|
|
7
|
-
// when the account rate-limit snapshot marks the plan as exhausted. It never
|
|
8
|
-
// touches the rate-limit query path: `account/rateLimits/read` and the
|
|
9
|
-
// app-server JSON-RPC traffic stay intact.
|
|
10
|
-
const HIDDEN_MARKER = "data-codex-upsell-banner-hidden";
|
|
11
|
-
const hiddenBanners = new Map();
|
|
12
|
-
let disposed = false;
|
|
13
|
-
|
|
14
|
-
function isUpsellBanner(element) {
|
|
15
|
-
if (!(element instanceof window.HTMLElement)) return false;
|
|
16
|
-
// 文件侧栏也是 aside,正文中的用量说明不能使整个预览被隐藏。
|
|
17
|
-
if (element.querySelector("[role='tabpanel']")) return false;
|
|
18
|
-
const text = (element.textContent ?? "").trim();
|
|
19
|
-
if (!text) return false;
|
|
20
|
-
const title = (
|
|
21
|
-
element.querySelector("h1, h2, h3, [role='heading']")?.textContent
|
|
22
|
-
?? text.split("\n", 1)[0]
|
|
23
|
-
).trim();
|
|
24
|
-
return /out of Codex(?: and Work)? usage/i.test(title)
|
|
25
|
-
|| /out of Codex messages/i.test(title)
|
|
26
|
-
|| /Codex (?:message )?usage limit reached/i.test(title)
|
|
27
|
-
|| /Codex.*(?:用量|使用量|使用额度|额度|消息).*(?:用完|用尽|耗尽|已达|达到.*上限|上限)/i.test(title)
|
|
28
|
-
|| /(?:已达到|达到|已用完|已用尽|耗尽).{0,20}Codex.{0,20}(?:用量|使用量|额度|消息|上限)/i.test(title)
|
|
29
|
-
// 通用标题须同时具有原生用量横幅的关闭语义,不能仅按耗尽文案隐藏通知。
|
|
30
|
-
|| (/^you['’]re out of usage[.!]?$/i.test(title)
|
|
31
|
-
&& [...element.querySelectorAll("button[aria-label]")].some(button =>
|
|
32
|
-
/^(?:Dismiss usage banner|不再显示用量横幅|關閉用量橫幅|關閉用量橫額)$/i.test(button.getAttribute("aria-label") ?? "")));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function hideBanner(element) {
|
|
36
|
-
if (!hiddenBanners.has(element)) hiddenBanners.set(element, {
|
|
37
|
-
display:element.style.getPropertyValue("display"), priority:element.style.getPropertyPriority("display"),
|
|
38
|
-
});
|
|
39
|
-
if (!element.hasAttribute(HIDDEN_MARKER)) element.setAttribute(HIDDEN_MARKER, "");
|
|
40
|
-
// 标记不代表样式仍有效;只在需要时写入,避免 observer 自触发循环。
|
|
41
|
-
if (element.style.display !== "none") element.style.display = "none";
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function restoreBanner(element) {
|
|
45
|
-
const original = hiddenBanners.get(element);
|
|
46
|
-
element.removeAttribute(HIDDEN_MARKER);
|
|
47
|
-
if (element.style.display === "none") {
|
|
48
|
-
if (original.display) element.style.setProperty("display", original.display, original.priority);
|
|
49
|
-
else element.style.removeProperty("display");
|
|
50
|
-
}
|
|
51
|
-
hiddenBanners.delete(element);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function hideVisibleBanners(root = document) {
|
|
55
|
-
for (const element of hiddenBanners.keys()) if (!element.isConnected || !isUpsellBanner(element)) restoreBanner(element);
|
|
56
|
-
if (root.matches?.("aside") && isUpsellBanner(root)) hideBanner(root);
|
|
57
|
-
for (const element of root.querySelectorAll("aside")) {
|
|
58
|
-
if (isUpsellBanner(element)) hideBanner(element);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
let rescanQueued = false;
|
|
63
|
-
function rescanBanners() {
|
|
64
|
-
// React can render the banner in stages: an empty <aside> shell first, then
|
|
65
|
-
// text and style updates on the same element. A childList-only observer
|
|
66
|
-
// misses those later mutations, so every mutation triggers a full rescan
|
|
67
|
-
// instead of only inspecting freshly added nodes.
|
|
68
|
-
if (rescanQueued) return;
|
|
69
|
-
rescanQueued = true;
|
|
70
|
-
queueMicrotask(() => {
|
|
71
|
-
rescanQueued = false;
|
|
72
|
-
if (!disposed) hideVisibleBanners(document);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
hideVisibleBanners();
|
|
77
|
-
const observer = new MutationObserver(() => {
|
|
78
|
-
rescanBanners();
|
|
79
|
-
});
|
|
80
|
-
observer.observe(document.documentElement, {
|
|
81
|
-
childList: true,
|
|
82
|
-
subtree: true,
|
|
83
|
-
attributes: true,
|
|
84
|
-
attributeFilter: ["style", "class", "hidden", "aria-label"],
|
|
85
|
-
characterData: true,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
config.registerSelfCheck?.(() => ({state:hiddenBanners.size ? "available" : "not-applicable",reason:hiddenBanners.size ? null : "no-usage-banner",
|
|
89
|
-
checks:[...hiddenBanners.keys()].filter(node=>node.isConnected).map(()=>({name:"usage-banner-hidden",available:true}))}));
|
|
90
|
-
return () => {
|
|
91
|
-
disposed = true;
|
|
92
|
-
observer.disconnect();
|
|
93
|
-
for (const element of hiddenBanners.keys()) restoreBanner(element);
|
|
94
|
-
};
|