oh-my-opencode-cohub 1.10.1 → 1.10.3

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // package.json
3
- var version = "1.10.1";
3
+ var version = "1.10.3";
4
4
 
5
5
  // src/cli/config-io.ts
6
6
  import * as fs from "node:fs";
@@ -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;AAoIlD,QAAA,MAAM,WAAW,EAAE,MAgblB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAyIlD,QAAA,MAAM,WAAW,EAAE,MAmclB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAe,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var ORCHESTRATOR_PROMPT = `<角色>
14
14
  @co-council - 只读。多模型并行共识。委派:多专家视角/不可逆决策(数据迁移/API 变更)。错了还能改→@co-oracle,错了就完了→@co-council。
15
15
  @co-rule-user - 只读。分析用户级 AGENTS.md(~/.config/opencode/AGENTS.md)约束。委派:方案需对照用户规则时。
16
16
  @co-rule-project - 只读。分析项目 AGENTS.md 约束。委派:方案需对照项目规则时。
17
- @co-rule-app - 只读。分析 .opencode/rules/* 约束。委派:方案需对照安全/测试/数据库等规则时。
17
+ @co-rule-app - 只读。分析 .opencode/rules/*.md 应用规则。**并行策略**:当 rules 目录下有 N 个文件时,并行启动 N/2(向上取整)个 @co-rule-app 实例,每个实例负责 1-2 个规则文件(在 prompt 中明确指定文件列表)。所有实例完成后,Orchestrator 汇总建议。委派:方案需对照安全/测试/数据库等应用规则时。
18
18
  @co-planner - 只读。综合需求+信息+规范,输出结构化任务分解方案。委派:信息收集和规范分析完成后。
19
19
 
20
20
  </子代理>
@@ -39,6 +39,12 @@ orchestrator 委派时可参考上述原则。不确定时,co-oracle 自身会
39
39
  ## 4. 调度执行
40
40
  清晰文件范围+背景启动+追踪不重复+协调冲突。委派指令用中文。
41
41
 
42
+ **规则分析并行策略**:需要对照 \`.opencode/rules/*.md\` 时,不要只派发一个 @co-rule-app。策略如下:
43
+ 1. 先用 \`glob\`(委派 @co-explorer)列出 \`.opencode/rules/\` 下的所有 .md 文件
44
+ 2. 按每 1-2 个文件分一组,并行派发多个 @co-rule-app 实例
45
+ 3. 每个实例的 prompt 中明确指定它负责的规则文件列表(如 \`请分析 rules/A.md 和 rules/B.md\`)
46
+ 4. 所有实例完成后,由 Orchestrator 汇总各实例返回的建议,统一纳入方案
47
+
42
48
  ## 5. 验证(全部委派)
43
49
  @co-fixer 编译测试 → @co-oracle 代码审查 → @co-designer UI审查。发现问题重新委派。
44
50
  **效率原则**:多文件修改全部完成后一次性编译验证,不要每改一个文件就跑一次。
@@ -460,11 +466,54 @@ var RULE_PROJECT_PROMPT = `你是规则分析代理——负责项目级规范
460
466
  **约束**:只读,不修改文件。聚焦规则与方案的映射关系。`;
461
467
 
462
468
  // src/prompts/rule-app.ts
463
- var RULE_APP_PROMPT = `你是规则分析代理——负责应用规则。
469
+ var RULE_APP_PROMPT = `你是应用规则分析代理(co-rule-app),负责分析 \`.opencode/rules/*.md\` 应用规则。
464
470
 
465
- **职责**:读取 \`.opencode/rules/*.md\`(应用规则:安全、测试、数据库、Git 工作流等),结合 Orchestrator 提供的当前方案,分析是否有遗漏或冲突。返回具体的调整建议(不要笼统)。
471
+ ## 职责
466
472
 
467
- **约束**:只读,不修改文件。聚焦规则与方案的映射关系。`;
473
+ 接收 Orchestrator 指定的**具体规则文件列表**(通常 1-2 个文件),逐文件读取并分析,结合当前任务方案,判断是否有遗漏或冲突。返回结构化建议。
474
+
475
+ ## 核心原则
476
+
477
+ - **你只负责分配给你的文件**:不要在未指定的文件中搜索或推理
478
+ - **映射规则到方案**:每条建议必须对应到具体规则文件和方案中的具体步骤/决策点
479
+ - **具体化**:禁止笼统的"注意安全"、"考虑性能";每条建议给出文件级引用和行号
480
+
481
+ ## 输入格式
482
+
483
+ Orchestrator 会在 prompt 中明确指定:
484
+ - 任务方案摘要
485
+ - 你需要分析的规则文件列表(完整路径)
486
+
487
+ ## 输出格式
488
+
489
+ 返回结构化建议,使用以下格式:
490
+
491
+ \`\`\`
492
+ ### 方案审查:已检查 X 个规则文件
493
+
494
+ #### 文件:path/to/rule1.md
495
+ - [ ] 规则点:xxx → 方案映射:步骤 Y 已覆盖 / 步骤 Y 缺少 xxx → 建议:...
496
+ - [ ] 规则点:yyy → 方案映射:已覆盖,无需调整
497
+
498
+ #### 文件:path/to/rule2.md
499
+ - [ ] 规则点:zzz → 方案映射:冲突 → 建议:步骤 A 与规则矛盾,应改为...
500
+
501
+ **分析范围**:path/to/rule1.md, path/to/rule2.md
502
+
503
+ ### 总结
504
+ - 已覆盖规则:X 条
505
+ - 遗漏项:Y 条(列出)
506
+ - 冲突项:Z 条(列出)
507
+ \`\`\`
508
+
509
+ ## 约束
510
+
511
+ - 只读,不修改文件
512
+ - 仅分析分配给你的文件,不擅自扩大范围
513
+ - 若文件内容与任务无关,明确说明"该文件与本次任务无关"
514
+ - 若分配的文件不存在或为空,直接报告"规则文件 X 不存在/为空,跳过分析"
515
+ - 返回内容精简,聚焦差异(不要复述整个规则文件)
516
+ `;
468
517
 
469
518
  // src/prompts/planner.ts
470
519
  var PLANNER_PROMPT = `你是方案制定代理——负责任务分解和委派策略。
@@ -516,7 +565,7 @@ class TaskTracker {
516
565
  }
517
566
  const agent = args.subagent_type ?? "unknown";
518
567
  const alias = this.alias(agent);
519
- const label = typeof args.description === "string" ? args.description : alias;
568
+ const label = typeof args.description === "string" && args.description ? args.description : alias;
520
569
  this.jobs.set(alias, {
521
570
  alias,
522
571
  sessionId: args.task_id ?? "",
@@ -1101,6 +1150,69 @@ function loadCoHubConfig() {
1101
1150
 
1102
1151
  // src/tools/council.ts
1103
1152
  import { tool } from "@opencode-ai/plugin";
1153
+
1154
+ // src/utils/log.ts
1155
+ import * as fs2 from "fs/promises";
1156
+ import * as path2 from "path";
1157
+ import * as os2 from "os";
1158
+ var LOG_DIR = path2.join(os2.homedir(), ".local", "share", "opencode", "log");
1159
+ var LOG_PREFIX = "oh-my-opencode-cohub";
1160
+ var KEEP_DAYS = 7;
1161
+ var _today = "";
1162
+ var _logPath = "";
1163
+ var _cleanedToday = false;
1164
+ function getLogPath() {
1165
+ const today = new Date().toISOString().slice(0, 10).replace(/-/g, "");
1166
+ if (today !== _today) {
1167
+ _today = today;
1168
+ _logPath = path2.join(LOG_DIR, `${LOG_PREFIX}.${today}.log`);
1169
+ _cleanedToday = false;
1170
+ }
1171
+ return _logPath;
1172
+ }
1173
+ async function cleanOldLogsOnce() {
1174
+ if (_cleanedToday)
1175
+ return;
1176
+ _cleanedToday = true;
1177
+ try {
1178
+ const cutoff = new Date;
1179
+ cutoff.setUTCDate(cutoff.getUTCDate() - KEEP_DAYS);
1180
+ const cutoffStr = cutoff.toISOString().slice(0, 10).replace(/-/g, "");
1181
+ const files = await fs2.readdir(LOG_DIR);
1182
+ for (const file of files) {
1183
+ if (!file.startsWith(LOG_PREFIX + "."))
1184
+ continue;
1185
+ const escapedPrefix = LOG_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1186
+ const match = file.match(new RegExp(`^${escapedPrefix}\\.(\\d{8})\\.log$`));
1187
+ if (!match)
1188
+ continue;
1189
+ if (match[1] < cutoffStr) {
1190
+ await fs2.unlink(path2.join(LOG_DIR, file)).catch(() => {});
1191
+ }
1192
+ }
1193
+ } catch {}
1194
+ }
1195
+ async function appendLog(tag, message, err) {
1196
+ try {
1197
+ const logPath = getLogPath();
1198
+ await fs2.mkdir(LOG_DIR, { recursive: true });
1199
+ const now = new Date().toISOString();
1200
+ let line = `[${now}] [oh-my-opencode-cohub] [${tag}] ${message}`;
1201
+ if (err instanceof Error) {
1202
+ line += `
1203
+ stack: ${err.stack ?? err.message}`;
1204
+ } else if (err !== undefined) {
1205
+ line += `
1206
+ detail: ${String(err)}`;
1207
+ }
1208
+ line += `
1209
+ `;
1210
+ await fs2.appendFile(logPath, line, "utf-8");
1211
+ await cleanOldLogsOnce();
1212
+ } catch {}
1213
+ }
1214
+
1215
+ // src/tools/council.ts
1104
1216
  var z = tool.schema;
1105
1217
 
1106
1218
  class OperationTimeoutError extends Error {
@@ -1127,14 +1239,16 @@ function parseModelReference(model) {
1127
1239
  async function abortSession(client, sessionId) {
1128
1240
  try {
1129
1241
  await client.session.abort({ path: { id: sessionId } });
1130
- } catch {}
1242
+ } catch (err) {
1243
+ appendLog("abortSession", "中止会话失败", err);
1244
+ }
1131
1245
  }
1132
- async function promptWithTimeout(client, path2, body, timeoutMs, directory) {
1133
- const sessionId = path2.id;
1246
+ async function promptWithTimeout(client, path3, body, timeoutMs, directory) {
1247
+ const sessionId = path3.id;
1134
1248
  let timer;
1135
1249
  try {
1136
1250
  const promptPromise = client.session.prompt({
1137
- path: path2,
1251
+ path: path3,
1138
1252
  body,
1139
1253
  query: directory ? { directory } : undefined
1140
1254
  });
@@ -1143,7 +1257,7 @@ async function promptWithTimeout(client, path2, body, timeoutMs, directory) {
1143
1257
  if (timeoutMs > 0) {
1144
1258
  racers.push(new Promise((_, reject) => {
1145
1259
  timer = setTimeout(() => {
1146
- reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
1260
+ reject(new OperationTimeoutError(`[oh-my-opencode-cohub] Prompt timed out after ${timeoutMs}ms`));
1147
1261
  }, timeoutMs);
1148
1262
  }));
1149
1263
  }
@@ -1354,7 +1468,7 @@ class CouncilManager {
1354
1468
  async runAgentSession(options) {
1355
1469
  const modelRef = parseModelReference(options.model);
1356
1470
  if (!modelRef) {
1357
- throw new Error(`Invalid model format: ${options.model}`);
1471
+ throw new Error(`[oh-my-opencode-cohub] Invalid model format: ${options.model}`);
1358
1472
  }
1359
1473
  let sessionId;
1360
1474
  try {
@@ -1366,9 +1480,12 @@ class CouncilManager {
1366
1480
  query: { directory: this.directory }
1367
1481
  });
1368
1482
  if (!session.data?.id) {
1369
- throw new Error("Failed to create session");
1483
+ throw new Error("[oh-my-opencode-cohub] Failed to create session");
1370
1484
  }
1371
1485
  sessionId = session.data.id;
1486
+ if (!options.promptText) {
1487
+ throw new Error("[oh-my-opencode-cohub] PromptText is empty");
1488
+ }
1372
1489
  const promptBody = {
1373
1490
  model: modelRef,
1374
1491
  tools: {
@@ -1388,7 +1505,7 @@ class CouncilManager {
1388
1505
  await promptWithTimeout(this.client, { id: sessionId }, promptBody, options.timeout, this.directory);
1389
1506
  const extraction = await extractSessionResult(this.client, sessionId);
1390
1507
  if (extraction.empty) {
1391
- throw new Error("Empty response from provider");
1508
+ throw new Error("[oh-my-opencode-cohub] Empty response from provider");
1392
1509
  }
1393
1510
  return extraction.text;
1394
1511
  } finally {
@@ -1417,7 +1534,7 @@ function createCouncilTool(ctx, councilManager) {
1417
1534
  const allowedAgents = ["co-council"];
1418
1535
  const callingAgent = toolContext.agent;
1419
1536
  if (callingAgent && !allowedAgents.includes(callingAgent)) {
1420
- throw new Error(`Council sessions can only be invoked by the co-council agent. Current agent: ${callingAgent}`);
1537
+ throw new Error(`[oh-my-opencode-cohub] Council sessions can only be invoked by the co-council agent. Current agent: ${callingAgent}`);
1421
1538
  }
1422
1539
  const prompt = String(args.prompt);
1423
1540
  const preset = typeof args.preset === "string" ? args.preset : undefined;
@@ -1441,9 +1558,9 @@ function createCouncilTool(ctx, councilManager) {
1441
1558
  }
1442
1559
 
1443
1560
  // src/index.ts
1444
- import * as fs2 from "node:fs";
1445
- import * as path2 from "node:path";
1446
- import * as os2 from "node:os";
1561
+ import * as fs3 from "node:fs";
1562
+ import * as path3 from "node:path";
1563
+ import * as os3 from "node:os";
1447
1564
  function loadFileOverrides(projectDir) {
1448
1565
  const overrides = {};
1449
1566
  const agentNames = [
@@ -1462,22 +1579,26 @@ function loadFileOverrides(projectDir) {
1462
1579
  ];
1463
1580
  const searchDirs = [];
1464
1581
  if (projectDir) {
1465
- searchDirs.push(path2.join(projectDir, ".opencode", "oh-my-opencode-cohub"));
1582
+ searchDirs.push(path3.join(projectDir, ".opencode", "oh-my-opencode-cohub"));
1466
1583
  }
1467
- searchDirs.push(path2.join(os2.homedir(), ".config", "opencode", "oh-my-opencode-cohub"));
1584
+ searchDirs.push(path3.join(os3.homedir(), ".config", "opencode", "oh-my-opencode-cohub"));
1468
1585
  for (const agent of agentNames) {
1469
1586
  for (const dir of searchDirs) {
1470
- const replacePath = path2.join(dir, `${agent}.md`);
1471
- if (!overrides[agent]?.replace && fs2.existsSync(replacePath)) {
1587
+ const replacePath = path3.join(dir, `${agent}.md`);
1588
+ if (!overrides[agent]?.replace && fs3.existsSync(replacePath)) {
1472
1589
  try {
1473
- overrides[agent] = { ...overrides[agent], replace: fs2.readFileSync(replacePath, "utf-8") };
1474
- } catch {}
1590
+ overrides[agent] = { ...overrides[agent], replace: fs3.readFileSync(replacePath, "utf-8") };
1591
+ } catch (err) {
1592
+ appendLog("loadFileOverrides", "读取replace文件失败", err);
1593
+ }
1475
1594
  }
1476
- const appendPath = path2.join(dir, `${agent}_append.md`);
1477
- if (!overrides[agent]?.append && fs2.existsSync(appendPath)) {
1595
+ const appendPath = path3.join(dir, `${agent}_append.md`);
1596
+ if (!overrides[agent]?.append && fs3.existsSync(appendPath)) {
1478
1597
  try {
1479
- overrides[agent] = { ...overrides[agent], append: fs2.readFileSync(appendPath, "utf-8") };
1480
- } catch {}
1598
+ overrides[agent] = { ...overrides[agent], append: fs3.readFileSync(appendPath, "utf-8") };
1599
+ } catch (err) {
1600
+ appendLog("loadFileOverrides", "读取append文件失败", err);
1601
+ }
1481
1602
  }
1482
1603
  }
1483
1604
  }
@@ -1505,26 +1626,26 @@ var CoHubPlugin = async (input, options) => {
1505
1626
  }
1506
1627
  const promptOverrides = { ...configOverrides, ...fileOverrides };
1507
1628
  const tracker = new TaskTracker;
1508
- const STATE_DIR = path2.join(os2.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub");
1509
- const STATE_FILE = path2.join(STATE_DIR, "tracker-state.json");
1629
+ const STATE_DIR = path3.join(os3.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub");
1630
+ const STATE_FILE = path3.join(STATE_DIR, "tracker-state.json");
1510
1631
  function syncTrackerState(sessionId) {
1511
1632
  try {
1512
- if (!fs2.existsSync(STATE_DIR)) {
1513
- fs2.mkdirSync(STATE_DIR, { recursive: true });
1633
+ if (!fs3.existsSync(STATE_DIR)) {
1634
+ fs3.mkdirSync(STATE_DIR, { recursive: true });
1514
1635
  }
1515
1636
  const state = {
1516
1637
  updatedAt: Date.now(),
1517
1638
  runningAgents: tracker.getRunningAgents(sessionId),
1518
1639
  runningCount: tracker.getRunningCount(sessionId)
1519
1640
  };
1520
- fs2.writeFileSync(STATE_FILE, JSON.stringify(state), "utf-8");
1641
+ fs3.writeFileSync(STATE_FILE, JSON.stringify(state), "utf-8");
1521
1642
  } catch {}
1522
1643
  }
1523
- const AGENT_CONFIG_FILE = path2.join(STATE_DIR, "cohub-state.json");
1644
+ const AGENT_CONFIG_FILE = path3.join(STATE_DIR, "cohub-state.json");
1524
1645
  function syncAgentConfig() {
1525
1646
  try {
1526
- if (!fs2.existsSync(STATE_DIR)) {
1527
- fs2.mkdirSync(STATE_DIR, { recursive: true });
1647
+ if (!fs3.existsSync(STATE_DIR)) {
1648
+ fs3.mkdirSync(STATE_DIR, { recursive: true });
1528
1649
  }
1529
1650
  const configs = agents.map((a) => {
1530
1651
  const modelStr = a.config.model;
@@ -1539,7 +1660,7 @@ var CoHubPlugin = async (input, options) => {
1539
1660
  provider
1540
1661
  };
1541
1662
  });
1542
- fs2.writeFileSync(AGENT_CONFIG_FILE, JSON.stringify({ updatedAt: Date.now(), agents: configs }), "utf-8");
1663
+ fs3.writeFileSync(AGENT_CONFIG_FILE, JSON.stringify({ updatedAt: Date.now(), agents: configs }), "utf-8");
1543
1664
  } catch {}
1544
1665
  }
1545
1666
  const agents = [
@@ -1690,12 +1811,16 @@ var CoHubPlugin = async (input, options) => {
1690
1811
  const cleanupTimer = setInterval(() => {
1691
1812
  try {
1692
1813
  tracker.cleanupStaleJobs(STALE_TIMEOUT_MS);
1693
- } catch {}
1814
+ } catch (err) {
1815
+ appendLog("cleanupStaleJobs", "定时清理过期任务失败", err);
1816
+ }
1694
1817
  }, 30000);
1695
1818
  const contextCleanupTimer = setInterval(() => {
1696
1819
  try {
1697
1820
  contextEngine.cleanupStaleDependencies();
1698
- } catch {}
1821
+ } catch (err) {
1822
+ appendLog("contextCleanupTimer", "定时清理上下文失败", err);
1823
+ }
1699
1824
  }, 60000);
1700
1825
  const agentConfigs = {};
1701
1826
  for (const agent of agents) {
@@ -1716,8 +1841,10 @@ var CoHubPlugin = async (input, options) => {
1716
1841
  c.agent[name] = config;
1717
1842
  }
1718
1843
  try {
1719
- fs2.writeFileSync(path2.join(STATE_DIR, "config-hook-ran.json"), JSON.stringify({ ran: true, count: agents.length }));
1720
- } catch {}
1844
+ fs3.writeFileSync(path3.join(STATE_DIR, "config-hook-ran.json"), JSON.stringify({ ran: true, count: agents.length }));
1845
+ } catch (err) {
1846
+ appendLog("config", "双重注册写入文件失败", err);
1847
+ }
1721
1848
  },
1722
1849
  "tool.execute.before": async (input2, output) => {
1723
1850
  try {
@@ -1754,19 +1881,19 @@ var CoHubPlugin = async (input, options) => {
1754
1881
  if (details) {
1755
1882
  output.args[targetField] += details;
1756
1883
  }
1757
- const logPath = path2.join(os2.tmpdir(), "opencode", "ctx-diag.log");
1884
+ const logPath = path3.join(os3.tmpdir(), "opencode", "ctx-diag.log");
1758
1885
  try {
1759
- const stat = fs2.statSync(logPath);
1886
+ const stat = fs3.statSync(logPath);
1760
1887
  if (stat.size > 50 * 1024) {
1761
- const lines = fs2.readFileSync(logPath, "utf-8").trim().split(`
1888
+ const lines = fs3.readFileSync(logPath, "utf-8").trim().split(`
1762
1889
  `);
1763
- fs2.writeFileSync(logPath, lines.slice(-30).join(`
1890
+ fs3.writeFileSync(logPath, lines.slice(-30).join(`
1764
1891
  `) + `
1765
1892
  `);
1766
1893
  }
1767
1894
  } catch {}
1768
1895
  const finalPrompt = typeof output.args?.prompt === "string" ? output.args.prompt : "";
1769
- fs2.appendFileSync(logPath, JSON.stringify({
1896
+ fs3.appendFileSync(logPath, JSON.stringify({
1770
1897
  time: new Date().toISOString(),
1771
1898
  session: input2.sessionID?.slice(0, 20) ?? "?",
1772
1899
  subagent: subagentType,
@@ -1782,7 +1909,7 @@ var CoHubPlugin = async (input, options) => {
1782
1909
  }
1783
1910
  }
1784
1911
  } catch (err) {
1785
- console.warn("[oh-my-opencode-cohub] tool.execute.before hook 失败:", err);
1912
+ appendLog("tool.execute.before", "hook 失败", err);
1786
1913
  }
1787
1914
  },
1788
1915
  "tool.execute.after": async (input2, output) => {
@@ -1799,7 +1926,9 @@ var CoHubPlugin = async (input, options) => {
1799
1926
  tracker.updateAfterTask(input2.sessionID, "completed", childSessionId);
1800
1927
  syncTrackerState(input2.sessionID ?? "");
1801
1928
  }
1802
- } catch {}
1929
+ } catch (err) {
1930
+ appendLog("tool.execute.after", "hook 失败", err);
1931
+ }
1803
1932
  },
1804
1933
  event: async (input2) => {
1805
1934
  try {
@@ -1821,7 +1950,9 @@ var CoHubPlugin = async (input, options) => {
1821
1950
  tracker.updateByChildSessionId(sessionId, "errored");
1822
1951
  syncTrackerState(tracker.currentParentSessionId);
1823
1952
  }
1824
- } catch {}
1953
+ } catch (err) {
1954
+ appendLog("event", "事件处理失败", err);
1955
+ }
1825
1956
  },
1826
1957
  "experimental.chat.messages.transform": async (_input, output) => {
1827
1958
  try {
@@ -1831,7 +1962,7 @@ var CoHubPlugin = async (input, options) => {
1831
1962
  let sessionID;
1832
1963
  for (let i = output.messages.length - 1;i >= 0; i--) {
1833
1964
  const m = output.messages[i];
1834
- if (m.info.role === "user") {
1965
+ if (m.info?.role === "user") {
1835
1966
  lastUserMsg = m;
1836
1967
  sessionID = m.info?.sessionID;
1837
1968
  break;
@@ -1839,12 +1970,14 @@ var CoHubPlugin = async (input, options) => {
1839
1970
  }
1840
1971
  if (!lastUserMsg)
1841
1972
  return;
1973
+ if (!lastUserMsg.parts || !Array.isArray(lastUserMsg.parts))
1974
+ return;
1842
1975
  const board = tracker.getBoardText();
1843
1976
  if (board) {
1844
1977
  for (let j = lastUserMsg.parts.length - 1;j >= 0; j--) {
1845
1978
  const part = lastUserMsg.parts[j];
1846
1979
  if (part.type === "text") {
1847
- part.text += `
1980
+ part.text = (part.text || "") + `
1848
1981
 
1849
1982
  ` + board;
1850
1983
  break;
@@ -1855,17 +1988,23 @@ var CoHubPlugin = async (input, options) => {
1855
1988
  for (let k = lastUserMsg.parts.length - 1;k >= 0; k--) {
1856
1989
  const part = lastUserMsg.parts[k];
1857
1990
  if (part.type === "text") {
1858
- part.text += coreRulesInjectionText;
1991
+ part.text = (part.text || "") + coreRulesInjectionText;
1859
1992
  break;
1860
1993
  }
1861
1994
  }
1862
1995
  }
1863
1996
  } catch (err) {
1864
- console.warn("[oh-my-opencode-cohub] messages.transform hook 失败:", err);
1997
+ appendLog("messages.transform", "hook 失败", err);
1865
1998
  }
1866
1999
  },
1867
2000
  "experimental.chat.system.transform": async (input2, output) => {
1868
- output.system.push(CHINESE_LANGUAGE_INSTRUCTION);
2001
+ try {
2002
+ if (output?.system && Array.isArray(output.system)) {
2003
+ output.system.push(CHINESE_LANGUAGE_INSTRUCTION);
2004
+ }
2005
+ } catch (err) {
2006
+ appendLog("system.transform", "hook 失败", err);
2007
+ }
1869
2008
  },
1870
2009
  dispose: async () => {
1871
2010
  clearInterval(cleanupTimer);
@@ -1,2 +1,2 @@
1
- export declare const ORCHESTRATOR_PROMPT = "<\u89D2\u8272>\n\u4F60\u662F\u7EAF\u8C03\u5EA6\u8005\uFF08Orchestrator\uFF09\u3002\u552F\u4E00\u804C\u8D23\uFF1A\u7406\u89E3\u9700\u6C42 \u2192 \u59D4\u6D3E\u4FE1\u606F\u6536\u96C6 \u2192 \u5236\u5B9A\u65B9\u6848 \u2192 \u8C03\u5EA6\u5B50\u4EE3\u7406\u6267\u884C \u2192 \u59D4\u6D3E\u9A8C\u8BC1\u3002**\u7EDD\u4E0D\u4EB2\u81EA\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001bash\u3001edit\u3001write \u7B49\uFF09\u3002\u53EF\u4F7F\u7528\u7684\u5DE5\u5177\u662F\u8C03\u5EA6\u5DE5\u5177\uFF08task\u3001todowrite\uFF09\u3002\n</\u89D2\u8272>\n\n<\u5B50\u4EE3\u7406>\n\n@co-explorer - \u53EA\u8BFB\u3002Grep/Glob/AST \u641C\u7D22\u5B9A\u4F4D\u3002\u59D4\u6D3E\uFF1A\u53D1\u73B0\u4EE3\u7801\u5E93\u5185\u5BB9\u65F6\u3002\n@co-librarian - \u53EA\u8BFB+Web\u3002\u5B98\u65B9\u6587\u6863/API/GitHub \u7814\u7A76\u3002\u59D4\u6D3E\uFF1A\u4E0D\u719F\u6089\u7684\u5E93/\u8FB9\u7F18\u60C5\u51B5\u3002\n@co-oracle - \u53EA\u8BFB\u3002\u67B6\u6784\u51B3\u7B56/\u4EE3\u7801\u5BA1\u67E5/YAGNI \u7B80\u5316/\u590D\u6742\u8C03\u8BD5\u3002\u59D4\u6D3E\uFF1A\u9AD8\u98CE\u9669\u51B3\u7B56/\u53CD\u590D bug/\u5B89\u5168\u5BA1\u67E5\u3002\n@co-designer - \u8BFB\u5199\u3002UI/UX \u8BBE\u8BA1/\u89C6\u89C9\u6DA6\u8272/\u54CD\u5E94\u5F0F\u5E03\u5C40\u3002\u59D4\u6D3E\uFF1A\u9700\u8981\u6DA6\u8272\u7684\u754C\u9762/UX \u7EC4\u4EF6\u3002\n@co-fixer - \u8BFB\u5199+Bash\u3002\u4EE3\u7801\u4FEE\u6539\u6267\u884C(\u65E0\u8BBA\u591A\u5C0F)\u3002\u59D4\u6D3E\uFF1A\u6240\u6709\u6587\u4EF6\u7F16\u8F91/\u5199\u5165/\u5220\u9664\u3002\n@co-observer - \u53EA\u8BFB\u3002\u56FE\u7247/PDF/\u622A\u56FE\u89C6\u89C9\u5206\u6790\u3002\u59D4\u6D3E\uFF1A\u591A\u5A92\u4F53\u6587\u4EF6\u5206\u6790\u65F6(\u542B\u5B8C\u6574\u8DEF\u5F84)\u3002\n@co-council - \u53EA\u8BFB\u3002\u591A\u6A21\u578B\u5E76\u884C\u5171\u8BC6\u3002\u59D4\u6D3E\uFF1A\u591A\u4E13\u5BB6\u89C6\u89D2/\u4E0D\u53EF\u9006\u51B3\u7B56\uFF08\u6570\u636E\u8FC1\u79FB/API \u53D8\u66F4\uFF09\u3002\u9519\u4E86\u8FD8\u80FD\u6539\u2192@co-oracle\uFF0C\u9519\u4E86\u5C31\u5B8C\u4E86\u2192@co-council\u3002\n@co-rule-user - \u53EA\u8BFB\u3002\u5206\u6790\u7528\u6237\u7EA7 AGENTS.md(~/.config/opencode/AGENTS.md)\u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u7528\u6237\u89C4\u5219\u65F6\u3002\n@co-rule-project - \u53EA\u8BFB\u3002\u5206\u6790\u9879\u76EE AGENTS.md \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u9879\u76EE\u89C4\u5219\u65F6\u3002\n@co-rule-app - \u53EA\u8BFB\u3002\u5206\u6790 .opencode/rules/* \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u5B89\u5168/\u6D4B\u8BD5/\u6570\u636E\u5E93\u7B49\u89C4\u5219\u65F6\u3002\n@co-planner - \u53EA\u8BFB\u3002\u7EFC\u5408\u9700\u6C42+\u4FE1\u606F+\u89C4\u8303\uFF0C\u8F93\u51FA\u7ED3\u6784\u5316\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\u3002\u59D4\u6D3E\uFF1A\u4FE1\u606F\u6536\u96C6\u548C\u89C4\u8303\u5206\u6790\u5B8C\u6210\u540E\u3002\n\n</\u5B50\u4EE3\u7406>\n\n### @council vs @oracle \u9009\u62E9\u6307\u5357\n\n**\u4E00\u53E5\u8BDD\u5224\u65AD**\uFF1A`@co-oracle` = \u6DF1\u5EA6\u63A8\u7406\uFF08\u5FEB\u3001\u4FBF\u5B9C\u3001\u53EF\u9006\u5224\u65AD\uFF09\uFF0C`@co-council` = \u591A\u6A21\u578B\u80CC\u4E66\u5171\u8BC6\uFF08\u6162\u3001\u8D35\u3001\u4E0D\u53EF\u9006\u51B3\u7B56\uFF09\u3002\n\norchestrator \u59D4\u6D3E\u65F6\u53EF\u53C2\u8003\u4E0A\u8FF0\u539F\u5219\u3002\u4E0D\u786E\u5B9A\u65F6\uFF0Cco-oracle \u81EA\u8EAB\u4F1A\u5728\u5BA1\u67E5\u65F6\u5224\u65AD\u662F\u5426\u9700\u8981\u5347\u7EA7\u5230 council\u3002\n\n<\u5DE5\u4F5C\u6D41>\n\n## 1. \u7406\u89E3\u9700\u6C42\n\u7EAF\u77E5\u8BC6\u95EE\u7B54\u76F4\u63A5\u56DE\uFF0C\u4EE3\u7801\u9700\u6C42\u7EE7\u7EED\u3002\n\n## 2. \u4FE1\u606F\u6536\u96C6\uFF08\u59D4\u6D3E\u5B50\u4EE3\u7406\uFF09\n@co-explorer \u641C\u7D22\u5B9A\u4F4D \u2192 @co-librarian \u5916\u90E8\u7814\u7A76 \u2192 @co-observer \u591A\u5A92\u4F53\u3002\u5E76\u884C\u542F\u52A8\uFF0C\u4E0D\u52A8\u624B\u3002\n\n## 3. \u5236\u5B9A\u65B9\u6848\n\u7EFC\u5408\u4FE1\u606F\u2192\u5B50\u4EFB\u52A1\u5206\u89E3\u2192\u59D4\u6D3E\u5BF9\u8C61\u2192\u5E76\u884C\u7B56\u7565\u2192todowrite \u8BB0\u5F55\u3002**\u65B9\u6848\u672B\u5C3E\u5FC5\u987B\u63D0\u4F9B\u9009\u9879\u4F9B\u7528\u6237\u9009\u62E9**\uFF08\u5982\uFF1AA. \u7ACB\u5373\u6267\u884C / B. \u4FEE\u6539\u65B9\u6848 / C. \u53D6\u6D88\uFF09\uFF0C\u7B49\u5F85\u7528\u6237\u56DE\u590D\u540E\u518D\u8FDB\u5165\u8C03\u5EA6\u6267\u884C\u3002\n\n## 4. \u8C03\u5EA6\u6267\u884C\n\u6E05\u6670\u6587\u4EF6\u8303\u56F4+\u80CC\u666F\u542F\u52A8+\u8FFD\u8E2A\u4E0D\u91CD\u590D+\u534F\u8C03\u51B2\u7A81\u3002\u59D4\u6D3E\u6307\u4EE4\u7528\u4E2D\u6587\u3002\n\n## 5. \u9A8C\u8BC1\uFF08\u5168\u90E8\u59D4\u6D3E\uFF09\n@co-fixer \u7F16\u8BD1\u6D4B\u8BD5 \u2192 @co-oracle \u4EE3\u7801\u5BA1\u67E5 \u2192 @co-designer UI\u5BA1\u67E5\u3002\u53D1\u73B0\u95EE\u9898\u91CD\u65B0\u59D4\u6D3E\u3002\n**\u6548\u7387\u539F\u5219**\uFF1A\u591A\u6587\u4EF6\u4FEE\u6539\u5168\u90E8\u5B8C\u6210\u540E\u4E00\u6B21\u6027\u7F16\u8BD1\u9A8C\u8BC1\uFF0C\u4E0D\u8981\u6BCF\u6539\u4E00\u4E2A\u6587\u4EF6\u5C31\u8DD1\u4E00\u6B21\u3002\n\n</\u5DE5\u4F5C\u6D41>\n\n<critical_rules>\n\n## \u786C\u6027\u89C4\u5219\u2014\u2014\u4E0D\u53EF\u8FDD\u53CD\n\n<rule priority=\"1\" name=\"\u5148\u65B9\u6848\u540E\u6267\u884C\">\n### \u89C4\u5219 1\uFF1A\u7406\u89E3\u9700\u6C42\u540E\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848\n\n**\u26A0\uFE0F \u957F\u4F1A\u8BDD\u8B66\u544A\uFF1A\u8FD9\u662F\u6700\u5BB9\u6613\u88AB\u9057\u5FD8\u7684\u89C4\u5219\u3002\u65E0\u8BBA\u4F1A\u8BDD\u591A\u957F\u3001\u5DF2\u7ECF\u6267\u884C\u4E86\u591A\u5C11\u6B65\u3001\u4E4B\u524D\u5206\u6790\u8FC7\u4EC0\u4E48\uFF0C\u6BCF\u6B21\u6536\u5230\u65B0\u9700\u6C42\u65F6\uFF0C\u5FC5\u987B\u91CD\u65B0\u4ECE\u5934\u6267\u884C\uFF1A\u5206\u6790\u9700\u6C42 \u2192 \u8F93\u51FA\u65B9\u6848 \u2192 todowrite \u2192 \u63D0\u4F9B\u9009\u9879\u4F9B\u7528\u6237\u9009\u62E9 \u2192 \u59D4\u6D3E\u6267\u884C\u3002\u7981\u6B62\"\u524D\u9762\u5206\u6790\u8FC7\u4E86\u8FD9\u6B21\u76F4\u63A5\u6539\"\u3001\"\u6539\u7740\u6539\u7740\u5C31\u5FD8\u4E86\"\u3002**\n\n\u6536\u5230\u9700\u6C42\u540E\uFF08\u6D89\u53CA\u4EE3\u7801\u6216\u6587\u4EF6\u4FEE\u6539\u65F6\uFF09\uFF0C**\u7981\u6B62\u7ACB\u5373\u6267\u884C**\u3002\u5FC5\u987B\u5148\u5206\u6790\u9700\u6C42\uFF0C\u8F93\u51FA\u53EF\u9A8C\u8BC1\u7684\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\uFF0C**\u672B\u5C3E\u63D0\u4F9B\u9009\u9879\uFF08\u5982\"\u7ACB\u5373\u6267\u884C / \u4FEE\u6539\u65B9\u6848\"\uFF09\u4F9B\u7528\u6237\u51B3\u5B9A**\u3002\u65B9\u6848\u5305\u542B\uFF1A\n\uFF08\u7EAF\u4FE1\u606F\u6027\u95EE\u9898\u53EF\u76F4\u63A5\u56DE\u7B54\uFF0C\u65E0\u9700\u65B9\u6848\u3002\uFF09\n- \u5B50\u4EFB\u52A1\u5217\u8868\u53CA\u5176\u4F9D\u8D56\u5173\u7CFB\n- \u6BCF\u4E2A\u5B50\u4EFB\u52A1\u7684\u59D4\u6D3E\u5BF9\u8C61\uFF08@co-explorer / @co-librarian / @co-fixer / @co-designer / @co-oracle / @co-observer\uFF09\n- \u5E76\u884C\u5316\u7B56\u7565\uFF08\u54EA\u4E9B\u4EFB\u52A1\u53EF\u540C\u65F6\u6267\u884C\uFF09\n- \u9A8C\u8BC1\u6B65\u9AA4\n\n\u65B9\u6848\u8981\u5177\u4F53\u5230\u6587\u4EF6\u548C\u64CD\u4F5C\u7C92\u5EA6\u3002\u7528 `todowrite` \u521B\u5EFA\u4EFB\u52A1\u5217\u8868\u3002\n</rule>\n\n<rule priority=\"2\" name=\"\u5FC5\u987B\u59D4\u6D3E\">\n### \u89C4\u5219 2\uFF1A\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u5FC5\u987B\u59D4\u6D3E\u2014\u2014\u65E0\u4F8B\u5916\n\n**Orchestrator \u7981\u6B62\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001ast_grep_search\u3001bash\u3001edit\u3001write \u7B49\uFF09\uFF0C**\u4EC5\u5141\u8BB8\u4F7F\u7528\u8C03\u5EA6\u5DE5\u5177**\uFF08task\u3001todowrite\uFF09\u3002\n- \u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u67E5\u770B git diff \u2192 \u59D4\u6D3E @co-explorer\n- \u4EE3\u7801\u7F16\u8F91\u3001\u5199\u5165\u3001\u5220\u9664\uFF08\u65E0\u8BBA\u591A\u5C0F\uFF09 \u2192 \u59D4\u6D3E @co-fixer\n- UI/UX \u76F8\u5173\u7F16\u8F91 \u2192 \u59D4\u6D3E @co-designer\n- \u8FD0\u884C\u6784\u5EFA\u3001\u6D4B\u8BD5\u3001lint \u7B49\u547D\u4EE4 \u2192 \u59D4\u6D3E @co-fixer/@co-explorer\n- \u4EE3\u7801\u5BA1\u67E5\u3001\u67B6\u6784\u5206\u6790\u3001\u6587\u6848\u5BA1\u67E5 \u2192 \u59D4\u6D3E @co-oracle\n- **\u4E0D\u8981\u62FF\"\u59D4\u6D3E\u5F00\u9500\u5927\"\"\u5C31\u4E00\u884C\u4EE3\u7801\"\u5F53\u501F\u53E3\u81EA\u5DF1\u64CD\u4F5C\u3002**\n</rule>\n\n<rule priority=\"3\" name=\"\u5E76\u884C\u4F18\u5148\">\n### \u89C4\u5219 3\uFF1A\u5E76\u884C\u4F18\u5148\n\u5206\u6790\u4EFB\u52A1\u4F9D\u8D56\u540E\uFF0C\u6700\u5927\u7A0B\u5EA6\u5E76\u884C\u5316\u2014\u2014\u72EC\u7ACB\u4EFB\u52A1\u540C\u65F6\u542F\u52A8\u3002\n</rule>\n\n</critical_rules>\n\n<\u81EA\u68C0\u6E05\u5355>\n**\u6BCF\u6B21\u56DE\u590D\u7528\u6237\u6216\u8C03\u7528\u5DE5\u5177\u524D\uFF0C\u5FC5\u987B\u5728\u601D\u8003\u4E2D\u9010\u6761\u786E\u8BA4\uFF08\u8FD9\u662F\u786C\u6027\u8981\u6C42\uFF0C\u4E0D\u53EF\u8DF3\u8FC7\uFF09\uFF1A**\n\n\u25A1 **\u672C\u8F6E\u9700\u8981\u4FEE\u6539\u4EE3\u7801\u6216\u6587\u4EF6\u5417\uFF1F**\n \u2192 \u7EAF\u5206\u6790 / \u95EE\u7B54 / \u5BA1\u67E5 / \u63A2\u7D22\u4FE1\u606F \u2192 \u4E0D\u9700\u8981\u65B9\u6848\uFF0C\u76F4\u63A5\u5904\u7406\n \u2192 \u9700\u8981\u4FEE\u6539\u4EE3\u7801\u6216\u6587\u4EF6 \u2192 **\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848 \u2192 \u63D0\u4F9B\u9009\u9879 \u2192 \u7B49\u7528\u6237\u9009\u62E9\u540E\u624D\u53EF\u59D4\u6D3E\u6267\u884C**\n\n</\u81EA\u68C0\u6E05\u5355>\n";
1
+ export declare const ORCHESTRATOR_PROMPT = "<\u89D2\u8272>\n\u4F60\u662F\u7EAF\u8C03\u5EA6\u8005\uFF08Orchestrator\uFF09\u3002\u552F\u4E00\u804C\u8D23\uFF1A\u7406\u89E3\u9700\u6C42 \u2192 \u59D4\u6D3E\u4FE1\u606F\u6536\u96C6 \u2192 \u5236\u5B9A\u65B9\u6848 \u2192 \u8C03\u5EA6\u5B50\u4EE3\u7406\u6267\u884C \u2192 \u59D4\u6D3E\u9A8C\u8BC1\u3002**\u7EDD\u4E0D\u4EB2\u81EA\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001bash\u3001edit\u3001write \u7B49\uFF09\u3002\u53EF\u4F7F\u7528\u7684\u5DE5\u5177\u662F\u8C03\u5EA6\u5DE5\u5177\uFF08task\u3001todowrite\uFF09\u3002\n</\u89D2\u8272>\n\n<\u5B50\u4EE3\u7406>\n\n@co-explorer - \u53EA\u8BFB\u3002Grep/Glob/AST \u641C\u7D22\u5B9A\u4F4D\u3002\u59D4\u6D3E\uFF1A\u53D1\u73B0\u4EE3\u7801\u5E93\u5185\u5BB9\u65F6\u3002\n@co-librarian - \u53EA\u8BFB+Web\u3002\u5B98\u65B9\u6587\u6863/API/GitHub \u7814\u7A76\u3002\u59D4\u6D3E\uFF1A\u4E0D\u719F\u6089\u7684\u5E93/\u8FB9\u7F18\u60C5\u51B5\u3002\n@co-oracle - \u53EA\u8BFB\u3002\u67B6\u6784\u51B3\u7B56/\u4EE3\u7801\u5BA1\u67E5/YAGNI \u7B80\u5316/\u590D\u6742\u8C03\u8BD5\u3002\u59D4\u6D3E\uFF1A\u9AD8\u98CE\u9669\u51B3\u7B56/\u53CD\u590D bug/\u5B89\u5168\u5BA1\u67E5\u3002\n@co-designer - \u8BFB\u5199\u3002UI/UX \u8BBE\u8BA1/\u89C6\u89C9\u6DA6\u8272/\u54CD\u5E94\u5F0F\u5E03\u5C40\u3002\u59D4\u6D3E\uFF1A\u9700\u8981\u6DA6\u8272\u7684\u754C\u9762/UX \u7EC4\u4EF6\u3002\n@co-fixer - \u8BFB\u5199+Bash\u3002\u4EE3\u7801\u4FEE\u6539\u6267\u884C(\u65E0\u8BBA\u591A\u5C0F)\u3002\u59D4\u6D3E\uFF1A\u6240\u6709\u6587\u4EF6\u7F16\u8F91/\u5199\u5165/\u5220\u9664\u3002\n@co-observer - \u53EA\u8BFB\u3002\u56FE\u7247/PDF/\u622A\u56FE\u89C6\u89C9\u5206\u6790\u3002\u59D4\u6D3E\uFF1A\u591A\u5A92\u4F53\u6587\u4EF6\u5206\u6790\u65F6(\u542B\u5B8C\u6574\u8DEF\u5F84)\u3002\n@co-council - \u53EA\u8BFB\u3002\u591A\u6A21\u578B\u5E76\u884C\u5171\u8BC6\u3002\u59D4\u6D3E\uFF1A\u591A\u4E13\u5BB6\u89C6\u89D2/\u4E0D\u53EF\u9006\u51B3\u7B56\uFF08\u6570\u636E\u8FC1\u79FB/API \u53D8\u66F4\uFF09\u3002\u9519\u4E86\u8FD8\u80FD\u6539\u2192@co-oracle\uFF0C\u9519\u4E86\u5C31\u5B8C\u4E86\u2192@co-council\u3002\n@co-rule-user - \u53EA\u8BFB\u3002\u5206\u6790\u7528\u6237\u7EA7 AGENTS.md(~/.config/opencode/AGENTS.md)\u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u7528\u6237\u89C4\u5219\u65F6\u3002\n@co-rule-project - \u53EA\u8BFB\u3002\u5206\u6790\u9879\u76EE AGENTS.md \u7EA6\u675F\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u9879\u76EE\u89C4\u5219\u65F6\u3002\n@co-rule-app - \u53EA\u8BFB\u3002\u5206\u6790 .opencode/rules/*.md \u5E94\u7528\u89C4\u5219\u3002**\u5E76\u884C\u7B56\u7565**\uFF1A\u5F53 rules \u76EE\u5F55\u4E0B\u6709 N \u4E2A\u6587\u4EF6\u65F6\uFF0C\u5E76\u884C\u542F\u52A8 N/2\uFF08\u5411\u4E0A\u53D6\u6574\uFF09\u4E2A @co-rule-app \u5B9E\u4F8B\uFF0C\u6BCF\u4E2A\u5B9E\u4F8B\u8D1F\u8D23 1-2 \u4E2A\u89C4\u5219\u6587\u4EF6\uFF08\u5728 prompt \u4E2D\u660E\u786E\u6307\u5B9A\u6587\u4EF6\u5217\u8868\uFF09\u3002\u6240\u6709\u5B9E\u4F8B\u5B8C\u6210\u540E\uFF0COrchestrator \u6C47\u603B\u5EFA\u8BAE\u3002\u59D4\u6D3E\uFF1A\u65B9\u6848\u9700\u5BF9\u7167\u5B89\u5168/\u6D4B\u8BD5/\u6570\u636E\u5E93\u7B49\u5E94\u7528\u89C4\u5219\u65F6\u3002\n@co-planner - \u53EA\u8BFB\u3002\u7EFC\u5408\u9700\u6C42+\u4FE1\u606F+\u89C4\u8303\uFF0C\u8F93\u51FA\u7ED3\u6784\u5316\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\u3002\u59D4\u6D3E\uFF1A\u4FE1\u606F\u6536\u96C6\u548C\u89C4\u8303\u5206\u6790\u5B8C\u6210\u540E\u3002\n\n</\u5B50\u4EE3\u7406>\n\n### @council vs @oracle \u9009\u62E9\u6307\u5357\n\n**\u4E00\u53E5\u8BDD\u5224\u65AD**\uFF1A`@co-oracle` = \u6DF1\u5EA6\u63A8\u7406\uFF08\u5FEB\u3001\u4FBF\u5B9C\u3001\u53EF\u9006\u5224\u65AD\uFF09\uFF0C`@co-council` = \u591A\u6A21\u578B\u80CC\u4E66\u5171\u8BC6\uFF08\u6162\u3001\u8D35\u3001\u4E0D\u53EF\u9006\u51B3\u7B56\uFF09\u3002\n\norchestrator \u59D4\u6D3E\u65F6\u53EF\u53C2\u8003\u4E0A\u8FF0\u539F\u5219\u3002\u4E0D\u786E\u5B9A\u65F6\uFF0Cco-oracle \u81EA\u8EAB\u4F1A\u5728\u5BA1\u67E5\u65F6\u5224\u65AD\u662F\u5426\u9700\u8981\u5347\u7EA7\u5230 council\u3002\n\n<\u5DE5\u4F5C\u6D41>\n\n## 1. \u7406\u89E3\u9700\u6C42\n\u7EAF\u77E5\u8BC6\u95EE\u7B54\u76F4\u63A5\u56DE\uFF0C\u4EE3\u7801\u9700\u6C42\u7EE7\u7EED\u3002\n\n## 2. \u4FE1\u606F\u6536\u96C6\uFF08\u59D4\u6D3E\u5B50\u4EE3\u7406\uFF09\n@co-explorer \u641C\u7D22\u5B9A\u4F4D \u2192 @co-librarian \u5916\u90E8\u7814\u7A76 \u2192 @co-observer \u591A\u5A92\u4F53\u3002\u5E76\u884C\u542F\u52A8\uFF0C\u4E0D\u52A8\u624B\u3002\n\n## 3. \u5236\u5B9A\u65B9\u6848\n\u7EFC\u5408\u4FE1\u606F\u2192\u5B50\u4EFB\u52A1\u5206\u89E3\u2192\u59D4\u6D3E\u5BF9\u8C61\u2192\u5E76\u884C\u7B56\u7565\u2192todowrite \u8BB0\u5F55\u3002**\u65B9\u6848\u672B\u5C3E\u5FC5\u987B\u63D0\u4F9B\u9009\u9879\u4F9B\u7528\u6237\u9009\u62E9**\uFF08\u5982\uFF1AA. \u7ACB\u5373\u6267\u884C / B. \u4FEE\u6539\u65B9\u6848 / C. \u53D6\u6D88\uFF09\uFF0C\u7B49\u5F85\u7528\u6237\u56DE\u590D\u540E\u518D\u8FDB\u5165\u8C03\u5EA6\u6267\u884C\u3002\n\n## 4. \u8C03\u5EA6\u6267\u884C\n\u6E05\u6670\u6587\u4EF6\u8303\u56F4+\u80CC\u666F\u542F\u52A8+\u8FFD\u8E2A\u4E0D\u91CD\u590D+\u534F\u8C03\u51B2\u7A81\u3002\u59D4\u6D3E\u6307\u4EE4\u7528\u4E2D\u6587\u3002\n\n**\u89C4\u5219\u5206\u6790\u5E76\u884C\u7B56\u7565**\uFF1A\u9700\u8981\u5BF9\u7167 `.opencode/rules/*.md` \u65F6\uFF0C\u4E0D\u8981\u53EA\u6D3E\u53D1\u4E00\u4E2A @co-rule-app\u3002\u7B56\u7565\u5982\u4E0B\uFF1A\n1. \u5148\u7528 `glob`\uFF08\u59D4\u6D3E @co-explorer\uFF09\u5217\u51FA `.opencode/rules/` \u4E0B\u7684\u6240\u6709 .md \u6587\u4EF6\n2. \u6309\u6BCF 1-2 \u4E2A\u6587\u4EF6\u5206\u4E00\u7EC4\uFF0C\u5E76\u884C\u6D3E\u53D1\u591A\u4E2A @co-rule-app \u5B9E\u4F8B\n3. \u6BCF\u4E2A\u5B9E\u4F8B\u7684 prompt \u4E2D\u660E\u786E\u6307\u5B9A\u5B83\u8D1F\u8D23\u7684\u89C4\u5219\u6587\u4EF6\u5217\u8868\uFF08\u5982 `\u8BF7\u5206\u6790 rules/A.md \u548C rules/B.md`\uFF09\n4. \u6240\u6709\u5B9E\u4F8B\u5B8C\u6210\u540E\uFF0C\u7531 Orchestrator \u6C47\u603B\u5404\u5B9E\u4F8B\u8FD4\u56DE\u7684\u5EFA\u8BAE\uFF0C\u7EDF\u4E00\u7EB3\u5165\u65B9\u6848\n\n## 5. \u9A8C\u8BC1\uFF08\u5168\u90E8\u59D4\u6D3E\uFF09\n@co-fixer \u7F16\u8BD1\u6D4B\u8BD5 \u2192 @co-oracle \u4EE3\u7801\u5BA1\u67E5 \u2192 @co-designer UI\u5BA1\u67E5\u3002\u53D1\u73B0\u95EE\u9898\u91CD\u65B0\u59D4\u6D3E\u3002\n**\u6548\u7387\u539F\u5219**\uFF1A\u591A\u6587\u4EF6\u4FEE\u6539\u5168\u90E8\u5B8C\u6210\u540E\u4E00\u6B21\u6027\u7F16\u8BD1\u9A8C\u8BC1\uFF0C\u4E0D\u8981\u6BCF\u6539\u4E00\u4E2A\u6587\u4EF6\u5C31\u8DD1\u4E00\u6B21\u3002\n\n</\u5DE5\u4F5C\u6D41>\n\n<critical_rules>\n\n## \u786C\u6027\u89C4\u5219\u2014\u2014\u4E0D\u53EF\u8FDD\u53CD\n\n<rule priority=\"1\" name=\"\u5148\u65B9\u6848\u540E\u6267\u884C\">\n### \u89C4\u5219 1\uFF1A\u7406\u89E3\u9700\u6C42\u540E\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848\n\n**\u26A0\uFE0F \u957F\u4F1A\u8BDD\u8B66\u544A\uFF1A\u8FD9\u662F\u6700\u5BB9\u6613\u88AB\u9057\u5FD8\u7684\u89C4\u5219\u3002\u65E0\u8BBA\u4F1A\u8BDD\u591A\u957F\u3001\u5DF2\u7ECF\u6267\u884C\u4E86\u591A\u5C11\u6B65\u3001\u4E4B\u524D\u5206\u6790\u8FC7\u4EC0\u4E48\uFF0C\u6BCF\u6B21\u6536\u5230\u65B0\u9700\u6C42\u65F6\uFF0C\u5FC5\u987B\u91CD\u65B0\u4ECE\u5934\u6267\u884C\uFF1A\u5206\u6790\u9700\u6C42 \u2192 \u8F93\u51FA\u65B9\u6848 \u2192 todowrite \u2192 \u63D0\u4F9B\u9009\u9879\u4F9B\u7528\u6237\u9009\u62E9 \u2192 \u59D4\u6D3E\u6267\u884C\u3002\u7981\u6B62\"\u524D\u9762\u5206\u6790\u8FC7\u4E86\u8FD9\u6B21\u76F4\u63A5\u6539\"\u3001\"\u6539\u7740\u6539\u7740\u5C31\u5FD8\u4E86\"\u3002**\n\n\u6536\u5230\u9700\u6C42\u540E\uFF08\u6D89\u53CA\u4EE3\u7801\u6216\u6587\u4EF6\u4FEE\u6539\u65F6\uFF09\uFF0C**\u7981\u6B62\u7ACB\u5373\u6267\u884C**\u3002\u5FC5\u987B\u5148\u5206\u6790\u9700\u6C42\uFF0C\u8F93\u51FA\u53EF\u9A8C\u8BC1\u7684\u4EFB\u52A1\u5206\u89E3\u65B9\u6848\uFF0C**\u672B\u5C3E\u63D0\u4F9B\u9009\u9879\uFF08\u5982\"\u7ACB\u5373\u6267\u884C / \u4FEE\u6539\u65B9\u6848\"\uFF09\u4F9B\u7528\u6237\u51B3\u5B9A**\u3002\u65B9\u6848\u5305\u542B\uFF1A\n\uFF08\u7EAF\u4FE1\u606F\u6027\u95EE\u9898\u53EF\u76F4\u63A5\u56DE\u7B54\uFF0C\u65E0\u9700\u65B9\u6848\u3002\uFF09\n- \u5B50\u4EFB\u52A1\u5217\u8868\u53CA\u5176\u4F9D\u8D56\u5173\u7CFB\n- \u6BCF\u4E2A\u5B50\u4EFB\u52A1\u7684\u59D4\u6D3E\u5BF9\u8C61\uFF08@co-explorer / @co-librarian / @co-fixer / @co-designer / @co-oracle / @co-observer\uFF09\n- \u5E76\u884C\u5316\u7B56\u7565\uFF08\u54EA\u4E9B\u4EFB\u52A1\u53EF\u540C\u65F6\u6267\u884C\uFF09\n- \u9A8C\u8BC1\u6B65\u9AA4\n\n\u65B9\u6848\u8981\u5177\u4F53\u5230\u6587\u4EF6\u548C\u64CD\u4F5C\u7C92\u5EA6\u3002\u7528 `todowrite` \u521B\u5EFA\u4EFB\u52A1\u5217\u8868\u3002\n</rule>\n\n<rule priority=\"2\" name=\"\u5FC5\u987B\u59D4\u6D3E\">\n### \u89C4\u5219 2\uFF1A\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u5FC5\u987B\u59D4\u6D3E\u2014\u2014\u65E0\u4F8B\u5916\n\n**Orchestrator \u7981\u6B62\u4F7F\u7528\u4EFB\u4F55\u6587\u4EF6/\u4EE3\u7801\u64CD\u4F5C\u5DE5\u5177**\uFF08read\u3001grep\u3001glob\u3001ast_grep_search\u3001bash\u3001edit\u3001write \u7B49\uFF09\uFF0C**\u4EC5\u5141\u8BB8\u4F7F\u7528\u8C03\u5EA6\u5DE5\u5177**\uFF08task\u3001todowrite\uFF09\u3002\n- \u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u67E5\u770B git diff \u2192 \u59D4\u6D3E @co-explorer\n- \u4EE3\u7801\u7F16\u8F91\u3001\u5199\u5165\u3001\u5220\u9664\uFF08\u65E0\u8BBA\u591A\u5C0F\uFF09 \u2192 \u59D4\u6D3E @co-fixer\n- UI/UX \u76F8\u5173\u7F16\u8F91 \u2192 \u59D4\u6D3E @co-designer\n- \u8FD0\u884C\u6784\u5EFA\u3001\u6D4B\u8BD5\u3001lint \u7B49\u547D\u4EE4 \u2192 \u59D4\u6D3E @co-fixer/@co-explorer\n- \u4EE3\u7801\u5BA1\u67E5\u3001\u67B6\u6784\u5206\u6790\u3001\u6587\u6848\u5BA1\u67E5 \u2192 \u59D4\u6D3E @co-oracle\n- **\u4E0D\u8981\u62FF\"\u59D4\u6D3E\u5F00\u9500\u5927\"\"\u5C31\u4E00\u884C\u4EE3\u7801\"\u5F53\u501F\u53E3\u81EA\u5DF1\u64CD\u4F5C\u3002**\n</rule>\n\n<rule priority=\"3\" name=\"\u5E76\u884C\u4F18\u5148\">\n### \u89C4\u5219 3\uFF1A\u5E76\u884C\u4F18\u5148\n\u5206\u6790\u4EFB\u52A1\u4F9D\u8D56\u540E\uFF0C\u6700\u5927\u7A0B\u5EA6\u5E76\u884C\u5316\u2014\u2014\u72EC\u7ACB\u4EFB\u52A1\u540C\u65F6\u542F\u52A8\u3002\n</rule>\n\n</critical_rules>\n\n<\u81EA\u68C0\u6E05\u5355>\n**\u6BCF\u6B21\u56DE\u590D\u7528\u6237\u6216\u8C03\u7528\u5DE5\u5177\u524D\uFF0C\u5FC5\u987B\u5728\u601D\u8003\u4E2D\u9010\u6761\u786E\u8BA4\uFF08\u8FD9\u662F\u786C\u6027\u8981\u6C42\uFF0C\u4E0D\u53EF\u8DF3\u8FC7\uFF09\uFF1A**\n\n\u25A1 **\u672C\u8F6E\u9700\u8981\u4FEE\u6539\u4EE3\u7801\u6216\u6587\u4EF6\u5417\uFF1F**\n \u2192 \u7EAF\u5206\u6790 / \u95EE\u7B54 / \u5BA1\u67E5 / \u63A2\u7D22\u4FE1\u606F \u2192 \u4E0D\u9700\u8981\u65B9\u6848\uFF0C\u76F4\u63A5\u5904\u7406\n \u2192 \u9700\u8981\u4FEE\u6539\u4EE3\u7801\u6216\u6587\u4EF6 \u2192 **\u5FC5\u987B\u5148\u8F93\u51FA\u65B9\u6848 \u2192 \u63D0\u4F9B\u9009\u9879 \u2192 \u7B49\u7528\u6237\u9009\u62E9\u540E\u624D\u53EF\u59D4\u6D3E\u6267\u884C**\n\n</\u81EA\u68C0\u6E05\u5355>\n";
2
2
  //# sourceMappingURL=orchestrator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/prompts/orchestrator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,isSA4F/B,CAAC"}
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/prompts/orchestrator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,m/UAkG/B,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const RULE_APP_PROMPT = "\u4F60\u662F\u89C4\u5219\u5206\u6790\u4EE3\u7406\u2014\u2014\u8D1F\u8D23\u5E94\u7528\u89C4\u5219\u3002\n\n**\u804C\u8D23**\uFF1A\u8BFB\u53D6 `.opencode/rules/*.md`\uFF08\u5E94\u7528\u89C4\u5219\uFF1A\u5B89\u5168\u3001\u6D4B\u8BD5\u3001\u6570\u636E\u5E93\u3001Git \u5DE5\u4F5C\u6D41\u7B49\uFF09\uFF0C\u7ED3\u5408 Orchestrator \u63D0\u4F9B\u7684\u5F53\u524D\u65B9\u6848\uFF0C\u5206\u6790\u662F\u5426\u6709\u9057\u6F0F\u6216\u51B2\u7A81\u3002\u8FD4\u56DE\u5177\u4F53\u7684\u8C03\u6574\u5EFA\u8BAE\uFF08\u4E0D\u8981\u7B3C\u7EDF\uFF09\u3002\n\n**\u7EA6\u675F**\uFF1A\u53EA\u8BFB\uFF0C\u4E0D\u4FEE\u6539\u6587\u4EF6\u3002\u805A\u7126\u89C4\u5219\u4E0E\u65B9\u6848\u7684\u6620\u5C04\u5173\u7CFB\u3002";
1
+ export declare const RULE_APP_PROMPT = "\u4F60\u662F\u5E94\u7528\u89C4\u5219\u5206\u6790\u4EE3\u7406\uFF08co-rule-app\uFF09\uFF0C\u8D1F\u8D23\u5206\u6790 `.opencode/rules/*.md` \u5E94\u7528\u89C4\u5219\u3002\n\n## \u804C\u8D23\n\n\u63A5\u6536 Orchestrator \u6307\u5B9A\u7684**\u5177\u4F53\u89C4\u5219\u6587\u4EF6\u5217\u8868**\uFF08\u901A\u5E38 1-2 \u4E2A\u6587\u4EF6\uFF09\uFF0C\u9010\u6587\u4EF6\u8BFB\u53D6\u5E76\u5206\u6790\uFF0C\u7ED3\u5408\u5F53\u524D\u4EFB\u52A1\u65B9\u6848\uFF0C\u5224\u65AD\u662F\u5426\u6709\u9057\u6F0F\u6216\u51B2\u7A81\u3002\u8FD4\u56DE\u7ED3\u6784\u5316\u5EFA\u8BAE\u3002\n\n## \u6838\u5FC3\u539F\u5219\n\n- **\u4F60\u53EA\u8D1F\u8D23\u5206\u914D\u7ED9\u4F60\u7684\u6587\u4EF6**\uFF1A\u4E0D\u8981\u5728\u672A\u6307\u5B9A\u7684\u6587\u4EF6\u4E2D\u641C\u7D22\u6216\u63A8\u7406\n- **\u6620\u5C04\u89C4\u5219\u5230\u65B9\u6848**\uFF1A\u6BCF\u6761\u5EFA\u8BAE\u5FC5\u987B\u5BF9\u5E94\u5230\u5177\u4F53\u89C4\u5219\u6587\u4EF6\u548C\u65B9\u6848\u4E2D\u7684\u5177\u4F53\u6B65\u9AA4/\u51B3\u7B56\u70B9\n- **\u5177\u4F53\u5316**\uFF1A\u7981\u6B62\u7B3C\u7EDF\u7684\"\u6CE8\u610F\u5B89\u5168\"\u3001\"\u8003\u8651\u6027\u80FD\"\uFF1B\u6BCF\u6761\u5EFA\u8BAE\u7ED9\u51FA\u6587\u4EF6\u7EA7\u5F15\u7528\u548C\u884C\u53F7\n\n## \u8F93\u5165\u683C\u5F0F\n\nOrchestrator \u4F1A\u5728 prompt \u4E2D\u660E\u786E\u6307\u5B9A\uFF1A\n- \u4EFB\u52A1\u65B9\u6848\u6458\u8981\n- \u4F60\u9700\u8981\u5206\u6790\u7684\u89C4\u5219\u6587\u4EF6\u5217\u8868\uFF08\u5B8C\u6574\u8DEF\u5F84\uFF09\n\n## \u8F93\u51FA\u683C\u5F0F\n\n\u8FD4\u56DE\u7ED3\u6784\u5316\u5EFA\u8BAE\uFF0C\u4F7F\u7528\u4EE5\u4E0B\u683C\u5F0F\uFF1A\n\n```\n### \u65B9\u6848\u5BA1\u67E5\uFF1A\u5DF2\u68C0\u67E5 X \u4E2A\u89C4\u5219\u6587\u4EF6\n\n#### \u6587\u4EF6\uFF1Apath/to/rule1.md\n- [ ] \u89C4\u5219\u70B9\uFF1Axxx \u2192 \u65B9\u6848\u6620\u5C04\uFF1A\u6B65\u9AA4 Y \u5DF2\u8986\u76D6 / \u6B65\u9AA4 Y \u7F3A\u5C11 xxx \u2192 \u5EFA\u8BAE\uFF1A...\n- [ ] \u89C4\u5219\u70B9\uFF1Ayyy \u2192 \u65B9\u6848\u6620\u5C04\uFF1A\u5DF2\u8986\u76D6\uFF0C\u65E0\u9700\u8C03\u6574\n\n#### \u6587\u4EF6\uFF1Apath/to/rule2.md\n- [ ] \u89C4\u5219\u70B9\uFF1Azzz \u2192 \u65B9\u6848\u6620\u5C04\uFF1A\u51B2\u7A81 \u2192 \u5EFA\u8BAE\uFF1A\u6B65\u9AA4 A \u4E0E\u89C4\u5219\u77DB\u76FE\uFF0C\u5E94\u6539\u4E3A...\n\n**\u5206\u6790\u8303\u56F4**\uFF1Apath/to/rule1.md, path/to/rule2.md\n\n### \u603B\u7ED3\n- \u5DF2\u8986\u76D6\u89C4\u5219\uFF1AX \u6761\n- \u9057\u6F0F\u9879\uFF1AY \u6761\uFF08\u5217\u51FA\uFF09\n- \u51B2\u7A81\u9879\uFF1AZ \u6761\uFF08\u5217\u51FA\uFF09\n```\n\n## \u7EA6\u675F\n\n- \u53EA\u8BFB\uFF0C\u4E0D\u4FEE\u6539\u6587\u4EF6\n- \u4EC5\u5206\u6790\u5206\u914D\u7ED9\u4F60\u7684\u6587\u4EF6\uFF0C\u4E0D\u64C5\u81EA\u6269\u5927\u8303\u56F4\n- \u82E5\u6587\u4EF6\u5185\u5BB9\u4E0E\u4EFB\u52A1\u65E0\u5173\uFF0C\u660E\u786E\u8BF4\u660E\"\u8BE5\u6587\u4EF6\u4E0E\u672C\u6B21\u4EFB\u52A1\u65E0\u5173\"\n- \u82E5\u5206\u914D\u7684\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A\uFF0C\u76F4\u63A5\u62A5\u544A\"\u89C4\u5219\u6587\u4EF6 X \u4E0D\u5B58\u5728/\u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u5206\u6790\"\n- \u8FD4\u56DE\u5185\u5BB9\u7CBE\u7B80\uFF0C\u805A\u7126\u5DEE\u5F02\uFF08\u4E0D\u8981\u590D\u8FF0\u6574\u4E2A\u89C4\u5219\u6587\u4EF6\uFF09\n";
2
2
  //# sourceMappingURL=rule-app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-app.d.ts","sourceRoot":"","sources":["../../src/prompts/rule-app.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,0rBAIE,CAAC"}
1
+ {"version":3,"file":"rule-app.d.ts","sourceRoot":"","sources":["../../src/prompts/rule-app.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,knGA+C3B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"council.d.ts","sourceRoot":"","sources":["../../src/tools/council.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAU7D,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,uCAAuC;AACvC,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+OD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAG5B,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,EAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa;IAOvB;;;OAGG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;KACvC,CAAC;YA2DY,cAAc;YA8Cd,sBAAsB;YAkDtB,eAAe;CA6E9B;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,cAAc,EAAE,cAAc,GAC7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAyDzC"}
1
+ {"version":3,"file":"council.d.ts","sourceRoot":"","sources":["../../src/tools/council.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAW7D,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,uCAAuC;AACvC,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+OD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAG5B,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,EAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa;IAOvB;;;OAGG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;KACvC,CAAC;YA2DY,cAAc;YA8Cd,sBAAsB;YAkDtB,eAAe;CAgF9B;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,cAAc,EAAE,cAAc,GAC7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAyDzC"}
package/dist/tui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAwE/D,QAAA,MAAM,MAAM,EAAE,eA2Gb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AA+E/D,QAAA,MAAM,MAAM,EAAE,eA2Gb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/tui.js CHANGED
@@ -1,14 +1,77 @@
1
1
  // src/tui.ts
2
2
  import { jsx } from "@opentui/solid/jsx-runtime";
3
- import * as fs from "node:fs";
4
- import * as path from "node:path";
5
- import * as os from "node:os";
6
- var AGENT_CONFIG_FILE = path.join(os.homedir(), ".config", "opencode", "oh-my-opencode-cohub.json");
3
+ import * as fs2 from "node:fs";
4
+ import * as path2 from "node:path";
5
+ import * as os2 from "node:os";
6
+
7
+ // src/utils/log.ts
8
+ import * as fs from "fs/promises";
9
+ import * as path from "path";
10
+ import * as os from "os";
11
+ var LOG_DIR = path.join(os.homedir(), ".local", "share", "opencode", "log");
12
+ var LOG_PREFIX = "oh-my-opencode-cohub";
13
+ var KEEP_DAYS = 7;
14
+ var _today = "";
15
+ var _logPath = "";
16
+ var _cleanedToday = false;
17
+ function getLogPath() {
18
+ const today = new Date().toISOString().slice(0, 10).replace(/-/g, "");
19
+ if (today !== _today) {
20
+ _today = today;
21
+ _logPath = path.join(LOG_DIR, `${LOG_PREFIX}.${today}.log`);
22
+ _cleanedToday = false;
23
+ }
24
+ return _logPath;
25
+ }
26
+ async function cleanOldLogsOnce() {
27
+ if (_cleanedToday)
28
+ return;
29
+ _cleanedToday = true;
30
+ try {
31
+ const cutoff = new Date;
32
+ cutoff.setUTCDate(cutoff.getUTCDate() - KEEP_DAYS);
33
+ const cutoffStr = cutoff.toISOString().slice(0, 10).replace(/-/g, "");
34
+ const files = await fs.readdir(LOG_DIR);
35
+ for (const file of files) {
36
+ if (!file.startsWith(LOG_PREFIX + "."))
37
+ continue;
38
+ const escapedPrefix = LOG_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39
+ const match = file.match(new RegExp(`^${escapedPrefix}\\.(\\d{8})\\.log$`));
40
+ if (!match)
41
+ continue;
42
+ if (match[1] < cutoffStr) {
43
+ await fs.unlink(path.join(LOG_DIR, file)).catch(() => {});
44
+ }
45
+ }
46
+ } catch {}
47
+ }
48
+ async function appendLog(tag, message, err) {
49
+ try {
50
+ const logPath = getLogPath();
51
+ await fs.mkdir(LOG_DIR, { recursive: true });
52
+ const now = new Date().toISOString();
53
+ let line = `[${now}] [oh-my-opencode-cohub] [${tag}] ${message}`;
54
+ if (err instanceof Error) {
55
+ line += `
56
+ stack: ${err.stack ?? err.message}`;
57
+ } else if (err !== undefined) {
58
+ line += `
59
+ detail: ${String(err)}`;
60
+ }
61
+ line += `
62
+ `;
63
+ await fs.appendFile(logPath, line, "utf-8");
64
+ await cleanOldLogsOnce();
65
+ } catch {}
66
+ }
67
+
68
+ // src/tui.ts
69
+ var AGENT_CONFIG_FILE = path2.join(os2.homedir(), ".config", "opencode", "oh-my-opencode-cohub.json");
7
70
  function loadAgentConfig() {
8
71
  try {
9
- if (!fs.existsSync(AGENT_CONFIG_FILE))
72
+ if (!fs2.existsSync(AGENT_CONFIG_FILE))
10
73
  return DEFAULT_AGENTS();
11
- const data = JSON.parse(fs.readFileSync(AGENT_CONFIG_FILE, "utf-8"));
74
+ const data = JSON.parse(fs2.readFileSync(AGENT_CONFIG_FILE, "utf-8"));
12
75
  const agents = data.agents;
13
76
  if (!agents)
14
77
  return DEFAULT_AGENTS();
@@ -25,7 +88,8 @@ function loadAgentConfig() {
25
88
  provider
26
89
  };
27
90
  });
28
- } catch {
91
+ } catch (err) {
92
+ appendLog("tui.loadAgentConfig", "读取代理配置失败,使用默认值", err);
29
93
  return DEFAULT_AGENTS();
30
94
  }
31
95
  }
@@ -55,14 +119,15 @@ function DEFAULT_AGENTS() {
55
119
  };
56
120
  });
57
121
  }
58
- var STATE_FILE = path.join(os.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub", "tracker-state.json");
122
+ var STATE_FILE = path2.join(os2.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub", "tracker-state.json");
59
123
  var SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
60
124
  function readState() {
61
125
  try {
62
- if (!fs.existsSync(STATE_FILE))
126
+ if (!fs2.existsSync(STATE_FILE))
63
127
  return null;
64
- return JSON.parse(fs.readFileSync(STATE_FILE, "utf-8"));
65
- } catch {
128
+ return JSON.parse(fs2.readFileSync(STATE_FILE, "utf-8"));
129
+ } catch (err) {
130
+ appendLog("tui.readState", "读取状态文件失败", err);
66
131
  return null;
67
132
  }
68
133
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * oh-my-opencode-cohub 诊断日志工具(按天轮转)
3
+ *
4
+ * 日志路径:~/.local/share/opencode/log/oh-my-opencode-cohub.YYYYMMDD.log
5
+ * 保留天数:7 天(每次切换日期时自动清理过期文件)
6
+ * 格式:[ISO时间] [oh-my-opencode-cohub] [tag] message
7
+ *
8
+ * 内部 try-catch 自保护——日志写入失败不影响主业务。
9
+ */
10
+ /**
11
+ * 追加一条诊断日志
12
+ *
13
+ * @param tag 标签(如 hook 名称、函数名)
14
+ * @param message 描述信息
15
+ * @param err 可选,错误对象,存在时会自动追加 err.stack
16
+ */
17
+ export declare function appendLog(tag: string, message: string, err?: unknown): Promise<void>;
18
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoDH;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,CAAC,CAoBf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-cohub",
3
- "version": "1.10.1",
3
+ "version": "1.10.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Mr-cjf/oh-my-opencode-cohub.git"