oh-my-opencode-cohub 1.8.1 → 1.9.0
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/dist/cli/config-io.d.ts.map +1 -1
- package/dist/cli/index.js +18 -62
- package/dist/context-guard/index.d.ts +1 -0
- package/dist/context-guard/index.d.ts.map +1 -1
- package/dist/context-guard/menu.d.ts.map +1 -1
- package/dist/context-guard/monitor.d.ts +2 -0
- package/dist/context-guard/monitor.d.ts.map +1 -1
- package/dist/context-guard/prompts.d.ts +4 -2
- package/dist/context-guard/prompts.d.ts.map +1 -1
- package/dist/context-guard/types.d.ts +5 -1
- package/dist/context-guard/types.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-io.d.ts","sourceRoot":"","sources":["../../src/cli/config-io.ts"],"names":[],"mappings":"AA4BA,2CAA2C;AAC3C,wBAAgB,yBAAyB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED,sCAAsC;AACtC,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAa5E;AAOD,mDAAmD;AACnD,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"config-io.d.ts","sourceRoot":"","sources":["../../src/cli/config-io.ts"],"names":[],"mappings":"AA4BA,2CAA2C;AAC3C,wBAAgB,yBAAyB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED,sCAAsC;AACtC,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAa5E;AAOD,mDAAmD;AACnD,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA4C3E;AAKD,uBAAuB;AACvB,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA2C1E;AAED,8BAA8B;AAC9B,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA6GzE"}
|
package/dist/cli/index.js
CHANGED
|
@@ -64,7 +64,7 @@ function registerCoHubAgents() {
|
|
|
64
64
|
config.agent = config.agent ?? {};
|
|
65
65
|
const agents = config.agent;
|
|
66
66
|
const cohubAgents = {
|
|
67
|
-
"co-orchestrator": { description: "纯调度者", mode: "
|
|
67
|
+
"co-orchestrator": { description: "纯调度者", mode: "subagent", prompt: `<角色>
|
|
68
68
|
你是纯调度者(Orchestrator)。唯一职责:理解需求 → 委派信息收集 → 制定方案 → 调度子代理执行 → 委派验证。**绝不亲自使用任何文件/代码操作工具**(read、grep、glob、bash、edit、write 等)。可使用的工具是调度工具(task、todowrite)。
|
|
69
69
|
</角色>
|
|
70
70
|
|
|
@@ -86,44 +86,9 @@ function registerCoHubAgents() {
|
|
|
86
86
|
|
|
87
87
|
### @council vs @oracle 选择指南
|
|
88
88
|
|
|
89
|
-
**一句话判断**:\`@co-oracle\` =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|------|-----------|-------------|
|
|
93
|
-
| 模式 | 单模型深度推理 | 多模型并行共识 |
|
|
94
|
-
| 适用场景 | 错了还能改的决策 | 错了就完了的决策 |
|
|
95
|
-
| 典型用例 | 代码审查、架构建议、bug 根因、YAGNI 简化、文案审查、重构方向 | 数据迁移方案、API 破坏性变更、安全合规审计、选型代价极大、多方案择优 |
|
|
96
|
-
| 输出形式 | 直接建议 + 推理 | 多专家观点 → 综合共识 → 信心评级(一致/多数/分歧) |
|
|
97
|
-
| 误用代价 | 低:建议错了可以讨论纠正 | 高:浪费 N 次调用成本,拖延决策 |
|
|
98
|
-
| 成本 | 1 次 LLM 调用 | 3-5 次并行 LLM 调用 |
|
|
99
|
-
|
|
100
|
-
**决策规则**:
|
|
101
|
-
1. **可逆性优先判断**:操作错了能无代价回滚?→ \`@co-oracle\`(如代码修改、lint 修复)。操作错了数据丢失/API 不兼容?→ \`@co-council\`(如 DROP TABLE、公共 API 签名变更)。
|
|
102
|
-
2. **异议价值判断**:需要单一深度分析?→ \`@co-oracle\`。需要多个独立判断互相验证?→ \`@co-council\`。
|
|
103
|
-
3. **默认倾向**:不确定时优先 \`@co-oracle\`(更快更便宜)。只有满足以下**至少 2 条**时才用 \`@co-council\`:
|
|
104
|
-
- 决策不可逆或回滚代价极高
|
|
105
|
-
- 影响范围跨多个模块/团队/服务
|
|
106
|
-
- 单一判断出错会造成安全事故/线上故障/数据损坏
|
|
107
|
-
- 存在多种合理方案且选错代价大
|
|
108
|
-
|
|
109
|
-
**典型场景对照**:
|
|
110
|
-
|
|
111
|
-
| 场景 | 用谁 | 理由 |
|
|
112
|
-
|------|------|------|
|
|
113
|
-
| PR 代码审查 | @co-oracle | 错了还能改,审查意见可讨论 |
|
|
114
|
-
| 重构建议 | @co-oracle | 方案可迭代调整 |
|
|
115
|
-
| 单文件 bug 修复思路 | @co-oracle | 低风险,快速反馈 |
|
|
116
|
-
| 数据库 Schema 迁移(含删列/改类型) | @co-council | 数据不可逆,需要多模型背书 |
|
|
117
|
-
| 公共 API 签名废弃/变更 | @co-council | 下游影响不可控 |
|
|
118
|
-
| 安全漏洞修复方案 | @co-council | 错了可能被利用 |
|
|
119
|
-
| 第三方库选型(如 ORM/状态管理) | @co-council | 迁移成本极高 |
|
|
120
|
-
| 文案/提示词修改 | @co-oracle | 错了能改,低风险 |
|
|
121
|
-
| 多方案架构决策(各有利弊) | @co-council | 需要多方面权衡 |
|
|
122
|
-
|
|
123
|
-
**反面教材——不要这样用**:
|
|
124
|
-
- ❌ 用 \`@co-council\` 审查一个简单的 lint 修复(杀鸡用牛刀)
|
|
125
|
-
- ❌ 用 \`@co-oracle\` 决定是否删除生产数据库的某个表(赌单模型判断)
|
|
126
|
-
- ❌ 用 \`@co-council\` 做日常代码格式化建议(纯浪费)
|
|
89
|
+
**一句话判断**:\`@co-oracle\` = 深度推理(快、便宜、可逆判断),\`@co-council\` = 多模型背书共识(慢、贵、不可逆决策)。
|
|
90
|
+
|
|
91
|
+
orchestrator 委派时可参考上述原则。不确定时,co-oracle 自身会在审查时判断是否需要升级到 council。
|
|
127
92
|
|
|
128
93
|
<工作流>
|
|
129
94
|
|
|
@@ -134,7 +99,7 @@ function registerCoHubAgents() {
|
|
|
134
99
|
@co-explorer 搜索定位 → @co-librarian 外部研究 → @co-observer 多媒体。并行启动,不动手。
|
|
135
100
|
|
|
136
101
|
## 3. 制定方案
|
|
137
|
-
综合信息→子任务分解→委派对象→并行策略→todowrite
|
|
102
|
+
综合信息→子任务分解→委派对象→并行策略→todowrite 记录。**方案末尾必须提供选项供用户选择**(如:A. 立即执行 / B. 修改方案 / C. 取消),等待用户回复后再进入调度执行。
|
|
138
103
|
|
|
139
104
|
## 4. 调度执行
|
|
140
105
|
清晰文件范围+背景启动+追踪不重复+协调冲突。委派指令用中文。
|
|
@@ -152,9 +117,9 @@ function registerCoHubAgents() {
|
|
|
152
117
|
<rule priority="1" name="先方案后执行">
|
|
153
118
|
### 规则 1:理解需求后必须先输出方案
|
|
154
119
|
|
|
155
|
-
**⚠️ 长会话警告:这是最容易被遗忘的规则。无论会话多长、已经执行了多少步、之前分析过什么,每次收到新需求时,必须重新从头执行:分析需求 → 输出方案 → todowrite
|
|
120
|
+
**⚠️ 长会话警告:这是最容易被遗忘的规则。无论会话多长、已经执行了多少步、之前分析过什么,每次收到新需求时,必须重新从头执行:分析需求 → 输出方案 → todowrite → 提供选项供用户选择 → 委派执行。禁止"前面分析过了这次直接改"、"改着改着就忘了"。**
|
|
156
121
|
|
|
157
|
-
|
|
122
|
+
收到需求后(涉及代码或文件修改时),**禁止立即执行**。必须先分析需求,输出可验证的任务分解方案,**末尾提供选项(如"立即执行 / 修改方案")供用户决定**。方案包含:
|
|
158
123
|
(纯信息性问题可直接回答,无需方案。)
|
|
159
124
|
- 子任务列表及其依赖关系
|
|
160
125
|
- 每个子任务的委派对象(@co-explorer / @co-librarian / @co-fixer / @co-designer / @co-oracle / @co-observer)
|
|
@@ -181,17 +146,6 @@ function registerCoHubAgents() {
|
|
|
181
146
|
分析任务依赖后,最大程度并行化——独立任务同时启动。
|
|
182
147
|
</rule>
|
|
183
148
|
|
|
184
|
-
<rule priority="4" name="方案批准门禁">
|
|
185
|
-
### 规则 4:方案批准门禁
|
|
186
|
-
|
|
187
|
-
每次委派 @co-fixer 或 @co-designer 进行修改前,必须确认当前会话的方案已获批准:
|
|
188
|
-
- **批准凭证**不是 todowrite 的 completed 状态,而是 \`request_plan_approval\` 工具成功返回"已批准"。
|
|
189
|
-
- 调用方式:输出完整方案 → 创建 todowrite 任务列表 → 调用 \`request_plan_approval(summary, files, verification)\` → 此时会弹出 OpenCode 原生确认框 → 用户点击允许后才算批准。
|
|
190
|
-
- 如果直接委派 @co-fixer 或 @co-designer 而未先调用 \`request_plan_approval\`,系统会抛出错误阻止执行。
|
|
191
|
-
- 每条新用户消息会自动撤销上一次批准。如果继续工作需要写操作,应根据最新需求重新展示/更新方案,再次调用 \`request_plan_approval\`。
|
|
192
|
-
- @co-fixer 与 @co-designer 都是可写代理,均受此门禁保护。
|
|
193
|
-
</rule>
|
|
194
|
-
|
|
195
149
|
</critical_rules>
|
|
196
150
|
|
|
197
151
|
<自检清单>
|
|
@@ -199,14 +153,10 @@ function registerCoHubAgents() {
|
|
|
199
153
|
|
|
200
154
|
□ **本轮需要修改代码或文件吗?**
|
|
201
155
|
→ 纯分析 / 问答 / 审查 / 探索信息 → 不需要方案,直接处理
|
|
202
|
-
→ 需要修改代码或文件 → **必须先输出方案 →
|
|
156
|
+
→ 需要修改代码或文件 → **必须先输出方案 → 提供选项 → 等用户选择后才可委派执行**
|
|
203
157
|
|
|
204
|
-
□ **准备委派 @co-fixer 或 @co-designer 修改代码吗?**
|
|
205
|
-
→ 先确认本轮是否已成功调用 \`request_plan_approval\` 并获得批准(工具成功返回"已批准")
|
|
206
|
-
→ 没有 → **立即停下来,先调用 request_plan_approval**
|
|
207
|
-
→ 新用户消息已撤销批准?→ **重新展示方案并再次调用 request_plan_approval**
|
|
208
158
|
</自检清单>
|
|
209
|
-
`, model: "deepseek/deepseek-v4-pro", variant: "max"
|
|
159
|
+
`, model: "deepseek/deepseek-v4-pro", variant: "max" },
|
|
210
160
|
"co-oracle": { description: "战略顾问", mode: "subagent", prompt: `你是 Oracle——战略技术顾问和代码审查者。
|
|
211
161
|
|
|
212
162
|
**角色**: 高智商调试、架构决策、代码审查、简化、工程指导。
|
|
@@ -533,16 +483,22 @@ function registerCoHubAgents() {
|
|
|
533
483
|
"co-guardian": { description: "上下文卫士", mode: "subagent", prompt: "你是 Guardian——上下文卫士分析师。在上下文窗口紧张时分析会话状态,推荐最优的上下文处理策略(自动压缩/会话压缩/分析迁移)。只读分析,不修改文件。", model: "deepseek/deepseek-v4-flash", variant: "low" }
|
|
534
484
|
};
|
|
535
485
|
let added = 0;
|
|
486
|
+
let migrated = 0;
|
|
536
487
|
for (const [name, agentConfig] of Object.entries(cohubAgents)) {
|
|
537
|
-
|
|
488
|
+
const existing = agents[name];
|
|
489
|
+
if (!existing) {
|
|
538
490
|
agents[name] = agentConfig;
|
|
539
491
|
added++;
|
|
492
|
+
} else if (typeof existing.prompt === "string" && existing.prompt.includes("request_plan_approval")) {
|
|
493
|
+
existing.prompt = agentConfig.prompt;
|
|
494
|
+
delete existing.permission;
|
|
495
|
+
migrated++;
|
|
540
496
|
}
|
|
541
497
|
}
|
|
542
|
-
if (added > 0) {
|
|
498
|
+
if (added > 0 || migrated > 0) {
|
|
543
499
|
writeJSON(configPath, config);
|
|
544
500
|
}
|
|
545
|
-
return { success: true, message: `✓
|
|
501
|
+
return { success: true, message: `✓ CoHub 代理:新增 ${added} 个,更新 ${migrated} 个${added + migrated === 0 ? "(全部已是最新,跳过)" : ""}` };
|
|
546
502
|
}
|
|
547
503
|
var COHUB_CONFIG_PATH = path.join(os.homedir(), ".config", "opencode", "oh-my-opencode-cohub.json");
|
|
548
504
|
function writeDefaultConfig() {
|
|
@@ -18,4 +18,5 @@ export declare function initContextGuard(_client: unknown): {
|
|
|
18
18
|
};
|
|
19
19
|
export { type ContextGuardConfig, DEFAULT_GUARD_CONFIG } from './types';
|
|
20
20
|
export { cleanupStaleSessions } from './state';
|
|
21
|
+
export { cleanupCountedMessages } from './monitor';
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context-guard/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAIlD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO;IAkB7C,WAAW;4BACa,OAAO,CAAC,kBAAkB,CAAC;IAInD,yDAAyD;mBACpC,OAAO;IAO5B,iCAAiC;2BACJ,OAAO;IAIpC,oDAAoD;oDACE,OAAO,UAAU,OAAO;IAO9E,sDAAsD;4BACxB,OAAO,UAAU,OAAO;;EASzD;AAED,OAAO,EAAE,KAAK,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context-guard/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAIlD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO;IAkB7C,WAAW;4BACa,OAAO,CAAC,kBAAkB,CAAC;IAInD,yDAAyD;mBACpC,OAAO;IAO5B,iCAAiC;2BACJ,OAAO;IAIpC,oDAAoD;oDACE,OAAO,UAAU,OAAO;IAO9E,sDAAsD;4BACxB,OAAO,UAAU,OAAO;;EASzD;AAED,OAAO,EAAE,KAAK,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/context-guard/menu.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAYvD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAE5G;AAmBD;;GAEG;AACH,wBAAgB,8BAA8B,KAC9B,QAAQ,WAAW,EAAE,QAAQ;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/context-guard/menu.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAYvD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAE5G;AAmBD;;GAEG;AACH,wBAAgB,8BAA8B,KAC9B,QAAQ,WAAW,EAAE,QAAQ;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAiCzG;AAyBD;;GAEG;AACH,wBAAgB,wBAAwB,KAEpC,OAAO,WAAW,EAClB,QAAQ;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KACpF,OAAO,CAAC,IAAI,CAAC,CA2DjB"}
|
|
@@ -20,4 +20,6 @@ export declare function createChatParamsHandler(): (input: PluginInput) => Promi
|
|
|
20
20
|
export declare function createEventHandler(config?: Partial<ContextGuardConfig>): (input: PluginInput) => Promise<TriggerEvent | null>;
|
|
21
21
|
/** 获取当前上下文限制 */
|
|
22
22
|
export declare function getContextLimit(): number;
|
|
23
|
+
/** 清理已计数消息缓存(dispose 时调用) */
|
|
24
|
+
export declare function cleanupCountedMessages(): void;
|
|
23
25
|
//# sourceMappingURL=monitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/context-guard/monitor.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,SAAS,CAAC;AAEhE,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/context-guard/monitor.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,SAAS,CAAC;AAEhE,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAUD;;GAEG;AACH,wBAAgB,uBAAuB,KACvB,OAAO,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC,CAkBjD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,IAGvD,OAAO,WAAW,KAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA+FhE;AAED,gBAAgB;AAChB,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,6BAA6B;AAC7B,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/** 上下文卫士 - 提示词模板 */
|
|
2
|
-
/**
|
|
3
|
-
export declare function renderGuardMenu(usedTokens: number, contextLimit: number, recommendation?: {
|
|
2
|
+
/** 三选一 + defer 菜单文本(注入到 chat) */
|
|
3
|
+
export declare function renderGuardMenu(usedTokens: number, contextLimit: number, nextRatio: number, recommendation?: {
|
|
4
4
|
option: string;
|
|
5
5
|
confidence: number;
|
|
6
6
|
reasoning: string;
|
|
7
7
|
}): string;
|
|
8
|
+
/** 计算下一个 defer 阈值(从 DEFER_LEVELS 阶梯中取大于当前 ratio 的最小值) */
|
|
9
|
+
export declare function nextDeferThreshold(currentRatio: number): number;
|
|
8
10
|
/** 选项1执行后的确认消息 */
|
|
9
11
|
export declare const AUTO_COMPRESS_DONE = "\u2705 \u81EA\u52A8\u538B\u7F29\u5B8C\u6210\u3002\u65E7\u6D88\u606F\u5DF2\u538B\u7F29\u4E3A\u6458\u8981\u5360\u4F4D\u7B26\uFF0C\u6700\u8FD1\u5BF9\u8BDD\u5B8C\u6574\u4FDD\u7559\u3002\n \u538B\u7F29\u540E\u8BF7\u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\uFF0C\u5982\u6709\u9700\u8981\u53EF\u4F7F\u7528 ultrapress_expand \u6062\u590D\u538B\u7F29\u5185\u5BB9\u3002";
|
|
10
12
|
/** 选项2的引导消息 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/context-guard/prompts.ts"],"names":[],"mappings":"AAAA,oBAAoB;AAEpB,
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/context-guard/prompts.ts"],"names":[],"mappings":"AAAA,oBAAoB;AAEpB,iCAAiC;AACjC,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzE,MAAM,CAoBR;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED,kBAAkB;AAClB,eAAO,MAAM,kBAAkB,uWACgB,CAAC;AAEhD,eAAe;AACf,eAAO,MAAM,qBAAqB,iXAGV,CAAC;AAEzB,iCAAiC;AACjC,eAAO,MAAM,wBAAwB,yyDAmBnC,CAAC;AAEH,aAAa;AACb,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,MAAM,CAgBT"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** 上下文卫士 - 类型定义 */
|
|
2
2
|
/** 三选一选项 */
|
|
3
|
-
export type GuardOption = 'auto-compress' | 'session-compact' | 'migrate';
|
|
3
|
+
export type GuardOption = 'auto-compress' | 'session-compact' | 'migrate' | 'defer';
|
|
4
|
+
/** 轻微提醒的阈值阶梯 */
|
|
5
|
+
export declare const DEFER_LEVELS: readonly [0.2, 0.4, 0.6, 0.8];
|
|
4
6
|
/** co-guardian 分析推荐结果 */
|
|
5
7
|
export interface GuardianRecommendation {
|
|
6
8
|
/** 推荐选项 */
|
|
@@ -32,6 +34,8 @@ export interface GuardSessionState {
|
|
|
32
34
|
cooldownRemaining: number;
|
|
33
35
|
/** 用户选择的选项(选择后设置) */
|
|
34
36
|
selectedOption?: GuardOption;
|
|
37
|
+
/** defer 后下次触发的阈值(比例,如 0.4) */
|
|
38
|
+
deferThreshold?: number;
|
|
35
39
|
/** 触发的消息 ID(防止重复) */
|
|
36
40
|
lastTriggerMessageId?: string;
|
|
37
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context-guard/types.ts"],"names":[],"mappings":"AAAA,mBAAmB;AAEnB,YAAY;AACZ,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context-guard/types.ts"],"names":[],"mappings":"AAAA,mBAAmB;AAEnB,YAAY;AACZ,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpF,gBAAgB;AAChB,eAAO,MAAM,YAAY,+BAAgC,CAAC;AAE1D,yBAAyB;AACzB,MAAM,WAAW,sBAAsB;IACrC,WAAW;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,aAAa;AACb,MAAM,WAAW,iBAAiB;IAChC,YAAY;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,aAAa;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB;IACrB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,eAAe;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,WAAW;AACX,MAAM,WAAW,kBAAkB;IACjC,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,WAAW;AACX,eAAO,MAAM,oBAAoB,EAAE,kBAOlC,CAAC;AAEF,qBAAqB;AACrB,MAAM,WAAW,gBAAgB;IAC/B,aAAa;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW;IACX,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wBAAwB;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA0IlD,QAAA,MAAM,WAAW,EAAE,MA2clB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAe,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -632,6 +632,7 @@ function cleanupAllStates() {
|
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
// src/context-guard/monitor.ts
|
|
635
|
+
var countedMessages = new Map;
|
|
635
636
|
var modelContext = {
|
|
636
637
|
contextLimit: 200000
|
|
637
638
|
};
|
|
@@ -694,8 +695,11 @@ function createEventHandler(config) {
|
|
|
694
695
|
if (totalTokens <= 0) {
|
|
695
696
|
totalTokens = state.cumulativeTokens;
|
|
696
697
|
}
|
|
697
|
-
if (
|
|
698
|
-
state.cumulativeTokens
|
|
698
|
+
if (!countedMessages.get(sessionID)?.has(messageId)) {
|
|
699
|
+
state.cumulativeTokens += totalTokens;
|
|
700
|
+
if (!countedMessages.has(sessionID))
|
|
701
|
+
countedMessages.set(sessionID, new Set);
|
|
702
|
+
countedMessages.get(sessionID).add(messageId);
|
|
699
703
|
}
|
|
700
704
|
let estimatedTotal = totalTokens;
|
|
701
705
|
if (estimatedTotal <= 0) {
|
|
@@ -712,7 +716,8 @@ function createEventHandler(config) {
|
|
|
712
716
|
if (estimatedTotal <= 0)
|
|
713
717
|
return null;
|
|
714
718
|
const usage = computeContextUsage(estimatedTotal, modelContext.contextLimit, inputTokens, outputTokens, reasoningTokens);
|
|
715
|
-
|
|
719
|
+
const effectiveRatio = state.deferThreshold ?? cfg.triggerRatio;
|
|
720
|
+
if (!isOverThreshold(usage, effectiveRatio, cfg.tokenThreshold))
|
|
716
721
|
return null;
|
|
717
722
|
markTriggered(state, messageId, estimatedTotal, modelContext.contextLimit);
|
|
718
723
|
return { sessionID, usedTokens: estimatedTotal, contextLimit: modelContext.contextLimit };
|
|
@@ -723,10 +728,14 @@ function createEventHandler(config) {
|
|
|
723
728
|
}
|
|
724
729
|
};
|
|
725
730
|
}
|
|
731
|
+
function cleanupCountedMessages() {
|
|
732
|
+
countedMessages.clear();
|
|
733
|
+
}
|
|
726
734
|
|
|
727
735
|
// src/context-guard/prompts.ts
|
|
728
|
-
function renderGuardMenu(usedTokens, contextLimit, recommendation) {
|
|
736
|
+
function renderGuardMenu(usedTokens, contextLimit, nextRatio, recommendation) {
|
|
729
737
|
const ratio = (usedTokens / contextLimit * 100).toFixed(1);
|
|
738
|
+
const nextPct = (nextRatio * 100).toFixed(0);
|
|
730
739
|
const recSection = recommendation ? `
|
|
731
740
|
|
|
732
741
|
\uD83E\uDDE0 co-guardian 分析建议:
|
|
@@ -741,12 +750,21 @@ function renderGuardMenu(usedTokens, contextLimit, recommendation) {
|
|
|
741
750
|
`║ 1️⃣ 自动压缩 — 压缩旧消息,保留最近对话 ║`,
|
|
742
751
|
`║ 2️⃣ 会话压缩 — 触发 Compact Session ║`,
|
|
743
752
|
`║ 3️⃣ 分析迁移 — 提取关键上下文,生成迁移文案 ║`,
|
|
753
|
+
`║ 4️⃣ 稍后提醒 — 到 ${nextPct}% 时再提醒 ║`,
|
|
744
754
|
`║ ║`,
|
|
745
|
-
`║ 请回复数字 1、2 或
|
|
755
|
+
`║ 请回复数字 1、2、3 或 4 ║`,
|
|
746
756
|
`╚══════════════════════════════════════════════════╝`
|
|
747
757
|
].join(`
|
|
748
758
|
`);
|
|
749
759
|
}
|
|
760
|
+
function nextDeferThreshold(currentRatio) {
|
|
761
|
+
const LEVELS = [0.4, 0.6, 0.8];
|
|
762
|
+
for (const l of LEVELS) {
|
|
763
|
+
if (l > currentRatio + 0.01)
|
|
764
|
+
return l;
|
|
765
|
+
}
|
|
766
|
+
return 0.9;
|
|
767
|
+
}
|
|
750
768
|
var AUTO_COMPRESS_DONE = `✅ 自动压缩完成。旧消息已压缩为摘要占位符,最近对话完整保留。
|
|
751
769
|
压缩后请继续当前工作,如有需要可使用 ultrapress_expand 恢复压缩内容。`;
|
|
752
770
|
var SESSION_COMPACT_GUIDE = `✅ 准备触发 Compact Session。
|
|
@@ -986,7 +1004,8 @@ function createMessagesTransformHandler() {
|
|
|
986
1004
|
pendingUsages.delete(found.sessionID);
|
|
987
1005
|
const recentMsgs = extractRecentMessages(output.messages, 30);
|
|
988
1006
|
const recommendation = analyzeSession(found.sessionID, recentMsgs);
|
|
989
|
-
const
|
|
1007
|
+
const nextRatio = nextDeferThreshold(usage.usedTokens / usage.contextLimit);
|
|
1008
|
+
const menu = renderGuardMenu(usage.usedTokens, usage.contextLimit, nextRatio, recommendation);
|
|
990
1009
|
const parts = found.msg.parts;
|
|
991
1010
|
if (parts) {
|
|
992
1011
|
for (let j = parts.length - 1;j >= 0; j--) {
|
|
@@ -1011,18 +1030,24 @@ function parseOption(text) {
|
|
|
1011
1030
|
return "session-compact";
|
|
1012
1031
|
if (t === "3" || t === "3")
|
|
1013
1032
|
return "migrate";
|
|
1033
|
+
if (t === "4" || t === "4")
|
|
1034
|
+
return "defer";
|
|
1014
1035
|
if (/^[选11]\s*[.、,,]?\s*(自动压缩|选项1)/.test(t))
|
|
1015
1036
|
return "auto-compress";
|
|
1016
1037
|
if (/^[选22]\s*[.、,,]?\s*(会话压缩|compact|选项2)/i.test(t))
|
|
1017
1038
|
return "session-compact";
|
|
1018
1039
|
if (/^[选33]\s*[.、,,]?\s*(分析迁移|迁移|选项3)/.test(t))
|
|
1019
1040
|
return "migrate";
|
|
1041
|
+
if (/^[选44]\s*[.、,,]?\s*(稍后|推迟|延迟|选项4)/i.test(t))
|
|
1042
|
+
return "defer";
|
|
1020
1043
|
if (t === "自动压缩")
|
|
1021
1044
|
return "auto-compress";
|
|
1022
1045
|
if (t === "会话压缩")
|
|
1023
1046
|
return "session-compact";
|
|
1024
1047
|
if (t === "分析迁移")
|
|
1025
1048
|
return "migrate";
|
|
1049
|
+
if (t === "稍后提醒" || t === "稍后")
|
|
1050
|
+
return "defer";
|
|
1026
1051
|
return;
|
|
1027
1052
|
}
|
|
1028
1053
|
function createChatMessageHandler() {
|
|
@@ -1058,6 +1083,14 @@ function createChatMessageHandler() {
|
|
|
1058
1083
|
case "migrate":
|
|
1059
1084
|
replyText = await executeMigrate(sessionID, []);
|
|
1060
1085
|
break;
|
|
1086
|
+
case "defer": {
|
|
1087
|
+
const nextRatio = nextDeferThreshold((state.cumulativeTokens || 0) / (state.triggerContextLimit || 200000));
|
|
1088
|
+
const nextPct = (nextRatio * 100).toFixed(0);
|
|
1089
|
+
state.triggered = false;
|
|
1090
|
+
state.deferThreshold = nextRatio;
|
|
1091
|
+
replyText = `⏸️ 已推迟提醒。下次到 ${nextPct}% 时再弹窗。`;
|
|
1092
|
+
break;
|
|
1093
|
+
}
|
|
1061
1094
|
}
|
|
1062
1095
|
if (output.parts) {
|
|
1063
1096
|
output.parts.length = 0;
|
|
@@ -2258,6 +2291,13 @@ var CoHubPlugin = async (input, options) => {
|
|
|
2258
2291
|
agent.config.prompt = resolvePrompt(agent.config.prompt, override.replace, override.append);
|
|
2259
2292
|
}
|
|
2260
2293
|
}
|
|
2294
|
+
const orchestratorAgent = agents.find((a) => a.name === "co-orchestrator");
|
|
2295
|
+
const criticalRulesMatch = orchestratorAgent?.config.prompt?.match(/<critical_rules>([\s\S]*?)<\/critical_rules>/);
|
|
2296
|
+
const coreRulesInjectionText = criticalRulesMatch ? `
|
|
2297
|
+
|
|
2298
|
+
--- 核心规则提醒(本轮注入,不持久化) ---
|
|
2299
|
+
<critical_rules>${criticalRulesMatch[1]}</critical_rules>
|
|
2300
|
+
--- 注入结束 ---` : null;
|
|
2261
2301
|
const DEFAULT_COUNCIL_CONFIG = {
|
|
2262
2302
|
default_preset: "default",
|
|
2263
2303
|
timeout: 180000,
|
|
@@ -2485,6 +2525,15 @@ var CoHubPlugin = async (input, options) => {
|
|
|
2485
2525
|
if (guardTransform)
|
|
2486
2526
|
await guardTransform(_input, output);
|
|
2487
2527
|
} catch {}
|
|
2528
|
+
if (coreRulesInjectionText) {
|
|
2529
|
+
for (let k = lastUserMsg.parts.length - 1;k >= 0; k--) {
|
|
2530
|
+
const part = lastUserMsg.parts[k];
|
|
2531
|
+
if (part.type === "text") {
|
|
2532
|
+
part.text += coreRulesInjectionText;
|
|
2533
|
+
break;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2488
2537
|
} catch (err) {
|
|
2489
2538
|
console.warn("[oh-my-opencode-cohub] messages.transform hook 失败:", err);
|
|
2490
2539
|
}
|
|
@@ -2506,6 +2555,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
2506
2555
|
clearInterval(cleanupTimer);
|
|
2507
2556
|
clearInterval(contextCleanupTimer);
|
|
2508
2557
|
cleanupAllStates();
|
|
2558
|
+
cleanupCountedMessages();
|
|
2509
2559
|
}
|
|
2510
2560
|
};
|
|
2511
2561
|
};
|