minecodex 2.0.13 → 2.0.14
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 +10 -10
- package/apps/dashboard/app.js +3 -36
- package/apps/dashboard/assets/data-transfer.js +2 -2
- package/apps/dashboard/styles.css +2 -6
- package/features/file-navigation/assets/folder-tree.svg +16 -0
- package/features/file-navigation/codex-feature.json +5 -5
- package/features/hide-upsell-banner/codex-feature.json +4 -4
- package/features/images/codex-feature.json +4 -4
- package/features/images/src/adapters/codex/native-image-modules.mjs +13 -2
- package/features/images/src/library-prompt-source.mjs +2 -2
- package/features/markdown-reading/codex-feature.json +4 -4
- package/features/model-slider/codex-feature.json +4 -4
- package/features/notes/codex-feature.json +4 -4
- package/features/session-status/codex-feature.json +6 -3
- package/features/sidebar-focus/codex-feature.json +2 -2
- package/features/sidebar-focus/src/sidebar-focus.mjs +13 -5
- package/features/sites/codex-feature.json +4 -4
- package/features/usage-meter/codex-feature.json +6 -3
- package/package.json +1 -1
- package/packages/cli/src/config.mjs +2 -2
- package/packages/cli/src/control-server.mjs +11 -6
- package/packages/runtime-host/src/codex-injection.mjs +1 -1
- package/packages/runtime-host/src/codex-runtime.mjs +13 -1
- package/packages/ui/src/native/theme.mjs +2 -1
- package/packages/ui/src/native/tokens.mjs +0 -4
package/README.md
CHANGED
|
@@ -10,16 +10,16 @@ MineCodex 给 Codex Desktop 增加一组轻量、本地优先的扩展功能。
|
|
|
10
10
|
|
|
11
11
|
| 插件 | 说明 |
|
|
12
12
|
| --- | --- |
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
| **
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
13
|
+
| **模型窗口** · Model Panel | 快速切换模型和思考强度,收藏常用模型。 |
|
|
14
|
+
| **提示词库** · Prompt Library | 分类保存常用提示词,需要时一键填入输入框。 |
|
|
15
|
+
| **额度环** · Usage Ring | 在侧栏查看五小时和每周剩余额度,点击打开用量详情。 |
|
|
16
|
+
| **会话状态** · Session Status | 查看回复速度、Token 用量和上下文占用,了解对话消耗。 |
|
|
17
|
+
| **Markdown 阅读增强** · Markdown Reader | 让 Markdown 文档更易读,支持章节目录、表格展开和代码复制。 |
|
|
18
|
+
| **文件级联浏览** · Cascading File Browser | 点击文件顶部路径,分列浏览文件夹并快速切换文件。 |
|
|
19
|
+
| **图片集合** · Image Collection | 集中浏览生成的图片,查看提示词并复用创作思路。 |
|
|
20
|
+
| **站点收藏** · Saved Sites | 发现项目正在运行的网页,收藏常用网址,随时打开。 |
|
|
21
|
+
| **侧栏聚焦** · Sidebar Focus | 一键收起侧栏中的其他分组,再次点击恢复原来的展开状态。 |
|
|
22
|
+
| **隐藏额度推广** · Hide Usage Promotions | 隐藏输入框上方的套餐升级推广,让对话更清爽。 |
|
|
23
23
|
|
|
24
24
|
## 安装
|
|
25
25
|
|
package/apps/dashboard/app.js
CHANGED
|
@@ -211,35 +211,9 @@ function createPluginCard(feature) {
|
|
|
211
211
|
return card;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
function createPluginOption(feature) {
|
|
215
|
-
const option = element("div", "plugin-option");
|
|
216
|
-
option.dataset.featureId = feature.id;
|
|
217
|
-
const label = element("label");
|
|
218
|
-
const input = element("input");
|
|
219
|
-
input.type = "checkbox";
|
|
220
|
-
input.name = `feature-${feature.id}`;
|
|
221
|
-
const name = element("span", "plugin-option-name");
|
|
222
|
-
const dot = element("span", "status-dot");
|
|
223
|
-
label.append(input, name, dot);
|
|
224
|
-
option.append(label);
|
|
225
|
-
return option;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
214
|
function updatePluginCard(card, feature) {
|
|
229
215
|
for (const button of elements.languageButtons) button.disabled = pendingFeatureIds.size > 0;
|
|
230
216
|
const status = featureState(feature);
|
|
231
|
-
if (card.classList.contains("plugin-option")) {
|
|
232
|
-
const input = card.querySelector("input");
|
|
233
|
-
input.checked = Boolean(feature.enabled);
|
|
234
|
-
input.disabled = pendingFeatureIds.has(feature.id);
|
|
235
|
-
input.setAttribute("aria-label", feature.label);
|
|
236
|
-
card.querySelector(".plugin-option-name").textContent = feature.label;
|
|
237
|
-
const dot = card.querySelector(".status-dot");
|
|
238
|
-
dot.className = `status-dot ${status.className}`;
|
|
239
|
-
dot.setAttribute("aria-label", status.label);
|
|
240
|
-
dot.title = status.label;
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
217
|
const input = card.querySelector('input[type="checkbox"]');
|
|
244
218
|
const image = card.querySelector(".plugin-icon img");
|
|
245
219
|
const name = card.querySelector(".plugin-name");
|
|
@@ -247,7 +221,7 @@ function updatePluginCard(card, feature) {
|
|
|
247
221
|
const dot = card.querySelector(".plugin-state .status-dot");
|
|
248
222
|
const stateLabel = card.querySelector(".plugin-state-label");
|
|
249
223
|
card.dataset.featureId = feature.id;
|
|
250
|
-
image.src = `${feature.iconUrl}?v=
|
|
224
|
+
image.src = `${feature.iconUrl}?v=resource-1`;
|
|
251
225
|
name.textContent = feature.label;
|
|
252
226
|
description.textContent = feature.description;
|
|
253
227
|
input.checked = Boolean(feature.enabled);
|
|
@@ -271,16 +245,9 @@ function renderPluginCards(features) {
|
|
|
271
245
|
for (const feature of features) {
|
|
272
246
|
let card = findPluginCard(feature.id);
|
|
273
247
|
if (!card) {
|
|
274
|
-
|
|
275
|
-
const parent = findPluginCard("markdown-reading");
|
|
276
|
-
if (!parent) continue;
|
|
277
|
-
card = createPluginOption(feature);
|
|
278
|
-
parent.append(card);
|
|
279
|
-
} else {
|
|
280
|
-
card = createPluginCard(feature);
|
|
281
|
-
elements.pluginList.append(card);
|
|
282
|
-
}
|
|
248
|
+
card = createPluginCard(feature);
|
|
283
249
|
}
|
|
250
|
+
elements.pluginList.append(card);
|
|
284
251
|
updatePluginCard(card, feature);
|
|
285
252
|
}
|
|
286
253
|
for (const card of [...elements.pluginList.querySelectorAll("[data-feature-id]")]) {
|
|
@@ -7,7 +7,7 @@ const t = (cn, en) => zh ? cn : en;
|
|
|
7
7
|
const dialog = document.querySelector('#data-dialog');
|
|
8
8
|
const entry = document.querySelector('#data-button');
|
|
9
9
|
const list = document.querySelector('#data-list');
|
|
10
|
-
const featureNames = { notes: '
|
|
10
|
+
const featureNames = { notes: t('提示词库', 'Prompt Library'), sites: t('站点收藏', 'Saved Sites'), 'model-slider': t('模型窗口', 'Model Panel') };
|
|
11
11
|
const status = document.querySelector('#data-status');
|
|
12
12
|
const exportButton = document.querySelector('#data-export');
|
|
13
13
|
const importButton = document.querySelector('#data-import');
|
|
@@ -69,7 +69,7 @@ function showInventory(data) {
|
|
|
69
69
|
for (const feature of data.features.filter(item => item.portable)) {
|
|
70
70
|
const detail = feature.id === 'notes' ? t(`${feature.categories} 个分类`, `${feature.categories} categories`) : '';
|
|
71
71
|
const hint = feature.id === 'model-slider' && !feature.initialized
|
|
72
|
-
? t('
|
|
72
|
+
? t('旧收藏在新版模型窗口首次启动后收录。', 'Legacy favorites are collected when the updated slider first starts.') + ' ' + featureHints[feature.id]
|
|
73
73
|
: featureHints[feature.id];
|
|
74
74
|
row(featureNames[feature.id] || feature.id, detail, t(`${feature.count} 项`, `${feature.count} items`), hint);
|
|
75
75
|
}
|
|
@@ -186,8 +186,8 @@ h2 { font-size: 14px; font-weight: 620; }
|
|
|
186
186
|
.plugin-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--grid-gap); }
|
|
187
187
|
.plugin-card { display: flex; flex-direction: column; align-items: stretch; min-width: 0; min-height: 216px; padding: var(--card-padding); border: 1px solid var(--border); border-radius: var(--card-radius); background: var(--surface); box-shadow: 0 3px 0 var(--block-shadow); }
|
|
188
188
|
.plugin-topline { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
|
|
189
|
-
.plugin-icon { display: grid; place-items: center; width: 28px; height: 28px; }
|
|
190
|
-
.plugin-icon img { width: 24px; height: 24px; opacity: 0.75; }
|
|
189
|
+
.plugin-icon { display: grid; place-items: center; width: 28px; height: 28px; flex: none; }
|
|
190
|
+
.plugin-icon img { display: block; width: 24px; height: 24px; object-fit: contain; opacity: 0.75; }
|
|
191
191
|
.plugin-copy { flex: 1; }
|
|
192
192
|
.plugin-name { font-size: 16px; font-weight: 600; line-height: 1.5; letter-spacing: -0.01em; }
|
|
193
193
|
.plugin-description { margin-top: 8px; font-size: 14px; line-height: 1.65; }
|
|
@@ -266,10 +266,6 @@ h2 { font-size: 14px; font-weight: 620; }
|
|
|
266
266
|
*, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
.plugin-option { margin-top:12px; padding-top:12px; border-top:1px solid var(--border); }
|
|
270
|
-
.plugin-option label { display:flex; align-items:center; gap:8px; font-size:13px; }
|
|
271
|
-
.plugin-option input { margin:0; accent-color:var(--ink); }
|
|
272
|
-
.plugin-option .status-dot { margin-left:auto; }
|
|
273
269
|
|
|
274
270
|
/* 数据迁移沿用控制台的不透明表面与卡片尺寸。 */
|
|
275
271
|
.data-dialog { width: min(520px, calc(100vw - 32px)); max-height: calc(100dvh - 48px); padding: 24px; border: 1px solid var(--border); border-bottom: 3px solid var(--block-shadow); border-radius: var(--card-radius); background: var(--surface); color: var(--ink); box-shadow: var(--shadow); overflow-y: auto; }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg
|
|
2
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3
|
+
width="24"
|
|
4
|
+
height="24"
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
stroke-width="2"
|
|
9
|
+
stroke-linecap="round"
|
|
10
|
+
stroke-linejoin="round"
|
|
11
|
+
>
|
|
12
|
+
<path d="M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z" />
|
|
13
|
+
<path d="M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z" />
|
|
14
|
+
<path d="M3 5a2 2 0 0 0 2 2h3" />
|
|
15
|
+
<path d="M3 3v13a2 2 0 0 0 2 2h3" />
|
|
16
|
+
</svg>
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "file-navigation",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Cascading File Browser",
|
|
7
|
+
"zh-CN": "文件级联浏览"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Click the path above a file to browse folders in columns and open another file.",
|
|
11
|
+
"zh-CN": "点击文件顶部路径,分列浏览文件夹并快速切换文件。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "page-script",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"icon": {
|
|
22
|
-
"resource": "assets/
|
|
22
|
+
"resource": "assets/folder-tree.svg"
|
|
23
23
|
},
|
|
24
24
|
"placement": {
|
|
25
25
|
"order": 91
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "hide-upsell-banner",
|
|
4
4
|
"version": "0.1.11",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "Hide
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Hide Usage Promotions",
|
|
7
|
+
"zh-CN": "隐藏额度推广"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "Hide
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Hide plan upgrade banners above the message box for a cleaner chat.",
|
|
11
|
+
"zh-CN": "隐藏输入框上方的套餐升级推广,让对话更清爽。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "page-script",
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "images",
|
|
4
4
|
"version": "0.1.12",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Image Collection",
|
|
7
|
+
"zh-CN": "图片集合"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "Browse generated images and
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Browse generated images in one place and revisit their prompts.",
|
|
11
|
+
"zh-CN": "集中浏览生成的图片,查看提示词并复用创作思路。"
|
|
12
12
|
},
|
|
13
13
|
"icon": {
|
|
14
14
|
"viewBox": "0 0 24 24",
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
// 以调用位置和参数结构识别角色,不绑定压缩后的局部变量名。
|
|
2
|
+
export function discoverImageActionBinding(source, role) {
|
|
3
|
+
const patterns = {
|
|
4
|
+
switchMode: /([\w$]+)\([\w$]+,[\w$]+\);let [\w$]+=[\w$]+\.length===1/,
|
|
5
|
+
attachChatImages: /await ([\w$]+)\([\w$]+,[\w$]+,\[[\w$]+\],\{isTemporaryChat:/,
|
|
6
|
+
};
|
|
7
|
+
const match = source.match(patterns[role]);
|
|
8
|
+
if (!match) throw new Error(`Native Images action contract changed: ${role}`);
|
|
9
|
+
return match[1];
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
// 按文件预览的调用关系读取角色,不依赖构建时分配的短变量名。
|
|
2
13
|
export function discoverFilePreviewComposerBindings(source) {
|
|
3
14
|
const starts = [...source.matchAll(/function [\w$]+\(/g)].map(match => match.index);
|
|
@@ -111,7 +122,7 @@ export function createNativeImageModules({read = async url => (await fetch(url))
|
|
|
111
122
|
const [moveDialog,dialogs]=await Promise.all([module("library-move-dialog",selection.source),module("library-item-dialogs",selection.source)]);
|
|
112
123
|
const routerLocal = selection.source.match(/get\(([\w$]+)\)\.prepareNavigation\(/)?.[1];
|
|
113
124
|
const routerAtom = await binding(selection.source, selection.url, routerLocal);
|
|
114
|
-
const switchLocal = selection.source
|
|
125
|
+
const switchLocal = discoverImageActionBinding(selection.source, "switchMode");
|
|
115
126
|
const switchMode = await binding(selection.source, selection.url, switchLocal);
|
|
116
127
|
const draftLocal = selection.source.match(/let u=([\w$]+)\(e,\[\]\);e.set/)?.[1];
|
|
117
128
|
const createChatDraft = await binding(selection.source, selection.url, draftLocal);
|
|
@@ -140,7 +151,7 @@ export function createNativeImageModules({read = async url => (await fetch(url))
|
|
|
140
151
|
const imageActions = component(menu.exports,source=>/onOpenedInNewTab:/.test(source),"image actions");
|
|
141
152
|
const imageActionSource = String(imageActions);
|
|
142
153
|
const imageFileLocal = imageActionSource.match(/let\{file:[\w$]+\}=([\w$]+)\(/)?.[1];
|
|
143
|
-
const attachLocal = imageActionSource
|
|
154
|
+
const attachLocal = discoverImageActionBinding(imageActionSource, "attachChatImages");
|
|
144
155
|
const downloadLocal = imageActionSource.match(/await ([\w$]+)\(\{downloadSrc:/)?.[1];
|
|
145
156
|
const [imageFile,attachChatImages,downloadImage] = await Promise.all([imageFileLocal,attachLocal,downloadLocal].map(local=>binding(menuCoreSource,menuCoreUrl,local)));
|
|
146
157
|
const toolbarClass = selection.source.match(/className:`(pointer-events-auto flex h-toolbar[^`]+)`/)?.[1];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createCloudImageActions } from "./frontend/cloud-image-actions.mjs";
|
|
2
2
|
import { createImageSourcesAdapter } from "./adapters/codex/image-sources.mjs";
|
|
3
3
|
import { createNativeImageSource } from "./adapters/codex/native-image-source.mjs";
|
|
4
|
-
import {createNativeImageModules, discoverFilePreviewComposerBindings} from "./adapters/codex/native-image-modules.mjs";
|
|
4
|
+
import {createNativeImageModules, discoverImageActionBinding, discoverFilePreviewComposerBindings} from "./adapters/codex/native-image-modules.mjs";
|
|
5
5
|
import { installLocalImageSource } from "./frontend/local-image-source.mjs";
|
|
6
6
|
import { createLibraryApi } from "./adapters/codex/library-api.mjs";
|
|
7
7
|
import { createLibraryViewerAdapter } from "./adapters/codex/library-viewer.mjs";
|
|
@@ -11,7 +11,7 @@ import { promptResolverSource } from "./adapters/codex/prompt-resolver-source.mj
|
|
|
11
11
|
export async function createPageScriptSource() {
|
|
12
12
|
const source=await readFile(new URL("./library-prompt-page.mjs",import.meta.url),"utf8");
|
|
13
13
|
const promptGlyphSource=await readFile(new URL("./assets/prompts-menu.svg",import.meta.url),"utf8");
|
|
14
|
-
const functions={createCloudImageActions,createImageSourcesAdapter,discoverFilePreviewComposerBindings,createNativeImageModules,createNativeImageSource,installLocalImageSource,createLibraryApi,createLibraryViewerAdapter};
|
|
14
|
+
const functions={createCloudImageActions,createImageSourcesAdapter,discoverImageActionBinding,discoverFilePreviewComposerBindings,createNativeImageModules,createNativeImageSource,installLocalImageSource,createLibraryApi,createLibraryViewerAdapter};
|
|
15
15
|
const declarations=Object.entries(functions).map(([name,fn])=>`const ${name}=${fn.toString()};`).join("\n");
|
|
16
16
|
return `${declarations}\nconst promptGlyphSource=${JSON.stringify(promptGlyphSource)};\nconst promptFromConversation=${promptResolverSource()};\n${source}`;
|
|
17
17
|
}
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "markdown-reading",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "Markdown
|
|
7
|
-
"zh-CN": "Markdown
|
|
6
|
+
"en": "Markdown Reader",
|
|
7
|
+
"zh-CN": "Markdown 阅读增强"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "Read Markdown
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Read Markdown with a chapter outline, expandable tables, and copyable code blocks.",
|
|
11
|
+
"zh-CN": "让 Markdown 文档更易读,支持章节目录、表格展开和代码复制。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "page-script",
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "model-slider",
|
|
4
4
|
"version": "0.1.12",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "Model
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Model Panel",
|
|
7
|
+
"zh-CN": "模型窗口"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "Switch models and thinking levels
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Switch models and thinking levels, and keep favorites close at hand.",
|
|
11
|
+
"zh-CN": "快速切换模型和思考强度,收藏常用模型。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "composer-model-selector"
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "notes",
|
|
4
4
|
"version": "0.1.11",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Prompt Library",
|
|
7
|
+
"zh-CN": "提示词库"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Save prompts by category and insert them into your message with one click.",
|
|
11
|
+
"zh-CN": "分类保存常用提示词,需要时一键填入输入框。"
|
|
12
12
|
},
|
|
13
13
|
"surfaceUrl": "http://127.0.0.1:47832/",
|
|
14
14
|
"healthUrl": "http://127.0.0.1:47832/api/health",
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "session-status",
|
|
4
4
|
"version": "0.1.0",
|
|
5
|
-
"label": {
|
|
5
|
+
"label": {
|
|
6
|
+
"en": "Session Status",
|
|
7
|
+
"zh-CN": "会话状态"
|
|
8
|
+
},
|
|
6
9
|
"description": {
|
|
7
|
-
"en": "See response speed, token usage and context
|
|
8
|
-
"zh-CN": "
|
|
10
|
+
"en": "See response speed, token usage, and how much context your chat uses.",
|
|
11
|
+
"zh-CN": "查看回复速度、Token 用量和上下文占用,了解对话消耗。"
|
|
9
12
|
},
|
|
10
13
|
"entry": { "kind": "page-script", "script": "src/session-status.mjs", "sourceFactory": "src/injection-source.mjs" },
|
|
11
14
|
"icon": {
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"zh-CN": "侧栏聚焦"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Collapse other sidebar groups with one click, then click again to restore them.",
|
|
11
|
+
"zh-CN": "一键收起侧栏中的其他分组,再次点击恢复原来的展开状态。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "page-script",
|
|
@@ -4,7 +4,7 @@ const EXPAND_GLYPH = "<svg aria-hidden=\"true\"\n xmlns=\"http://www.w3.org/200
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const states = new Map();
|
|
7
|
-
let active = false, restoring = false, button, timer, disposed = false;
|
|
7
|
+
let active = false, restoring = false, button, timer = null, disposed = false;
|
|
8
8
|
const text = (en, cn) => (document.documentElement.lang || navigator.language).startsWith("zh") ? cn : en;
|
|
9
9
|
|
|
10
10
|
|
|
@@ -74,8 +74,8 @@ function reconcile() {
|
|
|
74
74
|
if (change) { change.toggle(); schedule(); }
|
|
75
75
|
}
|
|
76
76
|
function schedule() {
|
|
77
|
-
|
|
78
|
-
timer =
|
|
77
|
+
if (disposed || timer !== null) return;
|
|
78
|
+
timer = requestAnimationFrame(() => { timer = null; reconcile(); });
|
|
79
79
|
}
|
|
80
80
|
document.addEventListener("click", event => {
|
|
81
81
|
if (!active || !event.isTrusted) return;
|
|
@@ -83,7 +83,15 @@ document.addEventListener("click", event => {
|
|
|
83
83
|
active = false; states.clear(); schedule();
|
|
84
84
|
}
|
|
85
85
|
}, { capture:true, signal });
|
|
86
|
-
const observer = new MutationObserver(
|
|
86
|
+
const observer = new MutationObserver(records => {
|
|
87
|
+
// 流式回复等侧栏外更新不应推迟或重复触发布局整理。
|
|
88
|
+
if (records.some(record =>
|
|
89
|
+
record.target.closest?.("#app-shell-sidebar")
|
|
90
|
+
|| record.type === "attributes" && ["data-above-composer-conversation-id", "lang"].includes(record.attributeName)
|
|
91
|
+
|| [...record.addedNodes ?? [], ...record.removedNodes ?? []].some(node =>
|
|
92
|
+
node.matches?.("#app-shell-sidebar") || node.querySelector?.("#app-shell-sidebar"))
|
|
93
|
+
)) schedule();
|
|
94
|
+
});
|
|
87
95
|
observer.observe(document.documentElement, { subtree:true, childList:true, attributes:true, attributeFilter:[
|
|
88
96
|
"aria-expanded", "aria-pressed", "data-app-action-sidebar-thread-selected",
|
|
89
97
|
"data-app-action-sidebar-section-collapsed", "data-above-composer-conversation-id", "lang"
|
|
@@ -97,4 +105,4 @@ config.registerSelfCheck?.(() => {
|
|
|
97
105
|
return {state:available ? "available" : "unavailable",reason:available ? null : "sidebar-focus-anchor-unavailable",
|
|
98
106
|
checks:[{name:"sidebar-focus-anchor",available}],scopes:[{name:"sidebar",element:sidebar}]};
|
|
99
107
|
});
|
|
100
|
-
return () => { disposed = true;
|
|
108
|
+
return () => { disposed = true; cancelAnimationFrame(timer); observer.disconnect(); button?.remove(); };
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"id": "sites",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"label": {
|
|
6
|
-
"en": "
|
|
7
|
-
"zh-CN": "
|
|
6
|
+
"en": "Saved Sites",
|
|
7
|
+
"zh-CN": "站点收藏"
|
|
8
8
|
},
|
|
9
9
|
"description": {
|
|
10
|
-
"en": "Find project
|
|
11
|
-
"zh-CN": "
|
|
10
|
+
"en": "Find running project sites and save useful links for quick access.",
|
|
11
|
+
"zh-CN": "发现项目正在运行的网页,收藏常用网址,随时打开。"
|
|
12
12
|
},
|
|
13
13
|
"entry": {
|
|
14
14
|
"kind": "page-script",
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "usage-meter",
|
|
4
4
|
"version": "0.1.0",
|
|
5
|
-
"label": {
|
|
5
|
+
"label": {
|
|
6
|
+
"en": "Usage Ring",
|
|
7
|
+
"zh-CN": "额度环"
|
|
8
|
+
},
|
|
6
9
|
"description": {
|
|
7
|
-
"en": "Check your
|
|
8
|
-
"zh-CN": "
|
|
10
|
+
"en": "Check your five-hour and weekly allowance in the sidebar; click for details.",
|
|
11
|
+
"zh-CN": "在侧栏查看五小时和每周剩余额度,点击打开用量详情。"
|
|
9
12
|
},
|
|
10
13
|
"entry": { "kind": "page-script", "script": "src/usage-meter.mjs", "sourceFactory": "src/injection-source.mjs" },
|
|
11
14
|
"icon": { "viewBox": "0 0 24 24", "markup": "<circle cx=\"12\" cy=\"12\" r=\"9\"></circle><circle cx=\"12\" cy=\"12\" r=\"5\"></circle>" },
|
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ import { createDataTransfer, MAX_TRANSFER_BYTES } from "./data-transfer/service.
|
|
|
14
14
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
15
15
|
const packageMetadata = JSON.parse(await readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
16
16
|
const MAX_BODY_BYTES = 64 * 1024;
|
|
17
|
+
const DASHBOARD_FEATURE_ORDER = ["model-slider", "notes", "usage-meter", "session-status", "markdown-reading", "file-navigation", "images", "sites", "sidebar-focus", "hide-upsell-banner"];
|
|
17
18
|
const CONTENT_TYPES = new Map([
|
|
18
19
|
[".css", "text/css; charset=utf-8"],
|
|
19
20
|
[".html", "text/html; charset=utf-8"],
|
|
@@ -93,7 +94,7 @@ function acceptedHealth(featureId, health) {
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
async function loadFeatureDefinitions(paths, locale = "en") {
|
|
96
|
-
return Promise.all(FEATURE_IDS.map(async (id) => {
|
|
97
|
+
return Promise.all([...FEATURE_IDS].sort((a, b) => DASHBOARD_FEATURE_ORDER.indexOf(a) - DASHBOARD_FEATURE_ORDER.indexOf(b)).map(async (id) => {
|
|
97
98
|
const manifestPath = path.join(paths.featuresRoot, id, "codex-feature.json");
|
|
98
99
|
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
99
100
|
return {
|
|
@@ -206,11 +207,15 @@ async function iconResponse(id, paths, response) {
|
|
|
206
207
|
iconPath = path.join(paths.featuresRoot, id, "assets", "icons", "book-open.svg");
|
|
207
208
|
} else if (FEATURE_IDS.includes(id)) {
|
|
208
209
|
const manifest = JSON.parse(await readFile(path.join(paths.featuresRoot, id, "codex-feature.json"), "utf8"));
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
if (manifest.icon?.resource) {
|
|
211
|
+
iconPath = path.resolve(paths.featuresRoot, id, manifest.icon.resource);
|
|
212
|
+
} else {
|
|
213
|
+
const viewBox = manifest.icon?.viewBox ?? "0 0 24 24";
|
|
214
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round">${manifest.icon.markup}</svg>`;
|
|
215
|
+
response.writeHead(200, { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=3600" });
|
|
216
|
+
response.end(svg);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
214
219
|
} else {
|
|
215
220
|
json(response, 404, { error: "NOT_FOUND" });
|
|
216
221
|
return;
|
|
@@ -737,7 +737,7 @@ export function createInjectionSource(features, {
|
|
|
737
737
|
"--codex-summary-row-line-height": "24px",
|
|
738
738
|
"--codex-summary-label-font-size": tokens["--text-base"] ?? "14px",
|
|
739
739
|
"--codex-summary-label-line-height": tokens["--text-base--line-height"] ?? "1.5",
|
|
740
|
-
"--codex-summary-font-weight":
|
|
740
|
+
"--codex-summary-font-weight": style.fontWeight || "445",
|
|
741
741
|
"--codex-summary-icon-size": "18px",
|
|
742
742
|
"--codex-summary-icon-stroke-width": "1.5px",
|
|
743
743
|
"--codex-summary-panel-radius": panelRadius,
|
|
@@ -109,6 +109,7 @@ export class CodexRuntime {
|
|
|
109
109
|
this.rendererTargetIds = new Set();
|
|
110
110
|
this.targetFailures = new Map();
|
|
111
111
|
this.targetChecks = new Map();
|
|
112
|
+
this.targetCheckDeadlines = new Map();
|
|
112
113
|
this.clients = new Map();
|
|
113
114
|
this.scriptIds = new Map();
|
|
114
115
|
this.bindingTokens = new Map();
|
|
@@ -245,6 +246,7 @@ export class CodexRuntime {
|
|
|
245
246
|
this.rendererTargetIds.clear();
|
|
246
247
|
this.targetFailures.clear();
|
|
247
248
|
this.targetChecks.clear();
|
|
249
|
+
this.targetCheckDeadlines.clear();
|
|
248
250
|
this.rendererDiscovered = false;
|
|
249
251
|
this.browserClient?.socket.close();
|
|
250
252
|
this.browserClient = null;
|
|
@@ -714,6 +716,7 @@ export class CodexRuntime {
|
|
|
714
716
|
this.scriptIds.delete(id);
|
|
715
717
|
this.bindingTokens.delete(id);
|
|
716
718
|
this.targetChecks.delete(id);
|
|
719
|
+
this.targetCheckDeadlines.delete(id);
|
|
717
720
|
this.hostActionChains.delete(id);
|
|
718
721
|
this.injectedTargets.delete(id);
|
|
719
722
|
this.targetFailures.delete(id);
|
|
@@ -735,6 +738,7 @@ export class CodexRuntime {
|
|
|
735
738
|
this.bindingTokens.delete(target.id);
|
|
736
739
|
this.injectedTargets.delete(target.id);
|
|
737
740
|
this.targetChecks.delete(target.id);
|
|
741
|
+
this.targetCheckDeadlines.delete(target.id);
|
|
738
742
|
}
|
|
739
743
|
if (target.type !== "page" || target.url !== "app://-/index.html" || this.injectedTargets.has(target.id)) {
|
|
740
744
|
continue;
|
|
@@ -759,6 +763,7 @@ export class CodexRuntime {
|
|
|
759
763
|
if (this.clients.get(target.id) !== client) return;
|
|
760
764
|
// 新文档撤销启动检查,下一次接入周期重新检查一次。
|
|
761
765
|
this.targetChecks.delete(target.id);
|
|
766
|
+
this.targetCheckDeadlines.delete(target.id);
|
|
762
767
|
this.notifyStatusChange();
|
|
763
768
|
});
|
|
764
769
|
client.on?.("Runtime.bindingCalled", (params) => {
|
|
@@ -825,7 +830,12 @@ export class CodexRuntime {
|
|
|
825
830
|
async checkTarget(targetId) {
|
|
826
831
|
const client=this.clients.get(targetId);
|
|
827
832
|
if (!client || this.stopping) return false;
|
|
828
|
-
|
|
833
|
+
const previous = this.targetChecks.get(targetId);
|
|
834
|
+
const needsRetry = !previous?.checkedAt || previous.plugins.some(plugin =>
|
|
835
|
+
["unknown", "unavailable", "degraded"].includes(plugin.state));
|
|
836
|
+
if (previous && (!needsRetry || Date.now() >= this.targetCheckDeadlines.get(targetId))) return true;
|
|
837
|
+
// 页面启动时锚点尚未就绪:借用发现周期有限重试,稳定后停止检查。
|
|
838
|
+
if (!this.targetCheckDeadlines.has(targetId)) this.targetCheckDeadlines.set(targetId, Date.now() + 30_000);
|
|
829
839
|
try {
|
|
830
840
|
const response=await client.send("Runtime.evaluate", {
|
|
831
841
|
expression:`(() => { const runtime=window.__codexPersonalRuntime; return runtime?.version === ${RUNTIME_VERSION} && runtime.sessionId === ${JSON.stringify(this.runtimeSessionId)} ? runtime.selfCheck() : null; })()`,
|
|
@@ -876,6 +886,7 @@ export class CodexRuntime {
|
|
|
876
886
|
client.socket.close();
|
|
877
887
|
this.injectedTargets.delete(targetId);
|
|
878
888
|
this.targetChecks.delete(targetId);
|
|
889
|
+
this.targetCheckDeadlines.delete(targetId);
|
|
879
890
|
this.notifyStatusChange();
|
|
880
891
|
}
|
|
881
892
|
}
|
|
@@ -920,6 +931,7 @@ export class CodexRuntime {
|
|
|
920
931
|
this.rendererTargetIds.clear();
|
|
921
932
|
this.targetFailures.clear();
|
|
922
933
|
this.targetChecks.clear();
|
|
934
|
+
this.targetCheckDeadlines.clear();
|
|
923
935
|
this.rendererDiscovered = false;
|
|
924
936
|
this.notifyStatusChange();
|
|
925
937
|
this.monitorPromise = null;
|
|
@@ -67,5 +67,6 @@ export function createNativeThemeAdapter(themeTokenNames,themeTokenAliases,theme
|
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
// 根清单仅展示已定义变量;必要值缺失仍由控件作用域检查报告。
|
|
71
|
+
return {read,dispose,checkTokens,bindScope,diagnostics:() => checkTokens(document.documentElement,themeTokenNames).filter(token => token.available)};
|
|
71
72
|
}
|
|
@@ -30,7 +30,6 @@ export const CODEX_THEME_TOKENS = Object.freeze([
|
|
|
30
30
|
"--color-token-text-tertiary",
|
|
31
31
|
"--color-token-border",
|
|
32
32
|
"--color-token-focus-border",
|
|
33
|
-
"--color-token-conversation-summary-trailing",
|
|
34
33
|
"--color-token-bg-primary",
|
|
35
34
|
"--color-token-bg-secondary",
|
|
36
35
|
"--color-token-bg-tertiary",
|
|
@@ -51,8 +50,6 @@ export const CODEX_THEME_TOKENS = Object.freeze([
|
|
|
51
50
|
"--color-background-button-secondary-hover",
|
|
52
51
|
"--color-background-button-tertiary-hover",
|
|
53
52
|
"--color-text-button-tertiary",
|
|
54
|
-
"--color-token-button-background",
|
|
55
|
-
"--color-token-button-foreground",
|
|
56
53
|
"--color-text-foreground",
|
|
57
54
|
"--color-text-foreground-secondary",
|
|
58
55
|
"--color-text-foreground-tertiary",
|
|
@@ -82,7 +79,6 @@ export const CODEX_THEME_TOKENS = Object.freeze([
|
|
|
82
79
|
"--leading-relaxed",
|
|
83
80
|
"--font-weight-normal",
|
|
84
81
|
"--font-weight-medium",
|
|
85
|
-
"--vscode-font-weight",
|
|
86
82
|
"--default-mono-font-family",
|
|
87
83
|
"--text-heading-lg",
|
|
88
84
|
"--text-heading-md",
|