Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
13 commits
Select commit Hold shift + click to select a range
b16313e
feat(stash): Codex 草稿暂存 — 输入框旁 push/pop + Usage 下方暂存面板
Cmochance Jun 23, 2026
5424517
Merge remote-tracking branch 'origin/main' into worktree-feat-codex-s…
Cmochance Jun 23, 2026
5922be0
fix(test): 同步 quota injector VERSION 断言 3→4
Cmochance Jun 23, 2026
ca091bf
fix(stash): 设置项说明压成单行(对齐设置页一行约定)
Cmochance Jun 23, 2026
0786404
feat(stash): 暂存/恢复支持图片附件(合成 paste)
Cmochance Jun 23, 2026
e95e1a7
docs(readme): 展示区合并为可折叠分组 + 新增 Stash 展示图(双语)
Cmochance Jun 23, 2026
688e31c
fix(stash): 修正 AI review 四项(换行/图片发送时机/写失败/解析缓存)
Cmochance Jun 23, 2026
26b371c
fix(stash): 修正 AI review 第二轮四项(空行/图片计数/恢复时序/清图范围)
Cmochance Jun 23, 2026
6151faa
fix(stash): 修正 AI review 第三轮(清空判定数全部附件 + 纯文本也等清空 + 块内 br)
Cmochance Jun 23, 2026
2b0a517
fix(stash): 修正 AI review 第四轮(文件附件计入清空判定 + 串行锁防重复发送)
Cmochance Jun 23, 2026
625448e
fix(stash): 修正 AI review 第五轮(写校验保留空行 + 发送提交成功才消费 + push 等图清空)
Cmochance Jun 23, 2026
d67f055
fix(stash): 修正 AI review 第六轮(校验保留前导/尾随空行 + push 遇文件附件中止)
Cmochance Jun 23, 2026
3baa0aa
fix(stash): 修正 AI review 第七轮(不支持附件统一拦截 + 配额溢出整体中止)
Cmochance Jun 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions README.en.md

Large diffs are not rendered by default.

34 changes: 31 additions & 3 deletions README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions frontend/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,8 @@ export default {
"settings.autoUnlockCodexPluginsHint": "Unlocks Codex plugins. Requires launching Codex from this app.",
"settings.codexQuotaEnabled": "Show usage in Codex",
"settings.codexQuotaEnabledHint": "Shows a usage panel in Codex (context, token rate/total, quota). Only when Codex is launched from this app.",
"settings.codexStashEnabled": "Enable draft stash in Codex",
"settings.codexStashEnabledHint": "Stash composer drafts to restore or send later. Only when Codex is launched from this app.",
"settings.pluginUnlockForce": "Force unlock",
"settings.pluginUnlockForced": "Force-unlock triggered",
"settings.pluginUnlockForceFailed": "Force unlock failed",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,9 @@ export default {
"settings.codexQuotaEnabled": "Codex 内显示用量信息",
"settings.codexQuotaEnabledHint":
"仅通过本应用启动 Codex 时生效,在 Codex 內显示用量面板:上下文占用、Tokens 速率与累计以及额度信息。",
"settings.codexStashEnabled": "Codex 内启用草稿暂存",
"settings.codexStashEnabledHint":
"仅通过本应用启动 Codex 时生效,可暂存输入框草稿,随后恢复到输入框或直接发送。",
"settings.pluginUnlockForce": "强制开启",
"settings.pluginUnlockForced": "已触发强制解锁",
"settings.pluginUnlockForceFailed": "强制开启失败",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/SettingsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ const autoApplyOnStart = toggle('autoApplyOnStart', true)
const restoreCodexOnExit = toggle('restoreCodexOnExit', true)
const autoWakeCodexPet = toggle('autoWakeCodexPet', true)
const codexQuotaEnabled = toggle('codexQuotaEnabled', false)
const codexStashEnabled = toggle('codexStashEnabled', false)
const codexNetworkAccess = toggle('codexNetworkAccess', false)
const exposeAllProviderModels = toggle('exposeAllProviderModels', false)
const showGrayProviders = toggle('showGrayProviders', false)
Expand Down Expand Up @@ -617,6 +618,9 @@ const UPDATE_REPO_URL = 'https://github.com/Cmochance/codex-app-transfer'
<SettingsRow :title="t('settings.codexQuotaEnabled')" :description="t('settings.codexQuotaEnabledHint')">
<AppSwitch v-model="codexQuotaEnabled" />
</SettingsRow>
<SettingsRow :title="t('settings.codexStashEnabled')" :description="t('settings.codexStashEnabledHint')">
<AppSwitch v-model="codexStashEnabled" />
</SettingsRow>
<RouterLink to="/codex-skin" class="nav-row">
<div class="nav-row__text">
<div class="nav-row__title">{{ t('theme.title') }}</div>
Expand Down
Binary file added img/codex-stash-dropdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/codex-stash-panel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion src-tauri/src/admin/services/desktop/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,14 @@ fn should_attach_debug_port() -> Vec<String> {
.and_then(|s| s.get("codexQuotaEnabled"))
.and_then(|v| v.as_bool())
.unwrap_or(false);
if !plugin_unlock_needs_port && !theme_enabled && !quota_enabled {
// 草稿暂存(Stash)注入 daemon 同样走 CDP,只开 stash 不开其它时也要端口。
let stash_enabled = cfg
.as_ref()
.and_then(|c| c.get("settings"))
.and_then(|s| s.get("codexStashEnabled"))
.and_then(|v| v.as_bool())
.unwrap_or(false);
if !plugin_unlock_needs_port && !theme_enabled && !quota_enabled && !stash_enabled {
return vec![];
}

Expand Down
14 changes: 10 additions & 4 deletions src-tauri/src/codex_quota_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const INSTALL_SCRIPT: &str = r##"
// [MOC-230] 版本化幂等 guard:同版本跳过(常态);版本变(应用升级后 INSTALL_SCRIPT 改了)
// → 先拆旧 observer + DOM 节点再重装,使新逻辑无需重启 Codex 即覆盖旧注入。旧版只有
// __catQuotaInstalled、无 __catQuotaVersion(undefined ≠ 当前版本)→ 同样触发重装。
var VERSION = 3; // [MOC-231] 加 breakdown caret/下拉 + convId 守卫 → bump,升级后免重启 Codex 即覆盖旧注入
var VERSION = 4; // 加「Stash 面板在场时让位坐到其前」的占位协调 → bump,升级后免重启 Codex 即覆盖旧注入
if (window.__catQuotaInstalled) {
if (window.__catQuotaVersion === VERSION) return;
try { if (window.__catQuotaObserver) window.__catQuotaObserver.disconnect(); } catch (e) {}
Expand Down Expand Up @@ -582,9 +582,15 @@ const INSTALL_SCRIPT: &str = r##"
node.id = 'cat-quota-entry';
scroller.appendChild(node);
fresh = true;
}
// 末尾归位:React 后续追加 section 会把条目挤到中间(appendChild/insertBefore 对已存在
// 节点是移动)。默认恒在 scroller 末尾;但若 Stash 面板(cat-stash-entry,codex_stash_injector)
// 在场,本额度条目须坐到它**之前**(「Usage 在 Stash 上面」),否则两个注入器每 tick 争抢
// lastElementChild。稳定不动时不写,避免自触发 observer churn。
var __stash = document.getElementById('cat-stash-entry');
if (__stash && __stash.parentElement === scroller) {
if (node.nextElementSibling !== __stash) scroller.insertBefore(node, __stash);
} else if (node !== scroller.lastElementChild) {
// React 后续往 scroller 追加 section 会把条目挤到中间;appendChild
// 对已存在节点是移动,保持条目恒在弹窗末尾
scroller.appendChild(node);
}
// 内容只在数据变化(或节点新建)时重建,避免 observer 高频 re-render churn
Expand Down Expand Up @@ -1850,7 +1856,7 @@ mod tests {
assert!(INSTALL_SCRIPT.contains("ctxUsed")); // 缓存上下文绝对值(used/window)
// [MOC-231] breakdown 的 convId 守卫(切对话不串)+ 版本化 guard 已 bump(升级免重启覆盖)
assert!(INSTALL_SCRIPT.contains("cqbdmismatch"));
assert!(INSTALL_SCRIPT.contains("var VERSION = 3"));
assert!(INSTALL_SCRIPT.contains("var VERSION = 4")); // bump:Stash 面板在场时让位占位协调
}

#[test]
Expand Down
Loading
Loading