oh-my-opencode-cohub 1.10.0 → 1.10.2

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.0";
3
+ var version = "1.10.2";
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
@@ -516,7 +516,7 @@ class TaskTracker {
516
516
  }
517
517
  const agent = args.subagent_type ?? "unknown";
518
518
  const alias = this.alias(agent);
519
- const label = typeof args.description === "string" ? args.description : alias;
519
+ const label = typeof args.description === "string" && args.description ? args.description : alias;
520
520
  this.jobs.set(alias, {
521
521
  alias,
522
522
  sessionId: args.task_id ?? "",
@@ -1101,6 +1101,69 @@ function loadCoHubConfig() {
1101
1101
 
1102
1102
  // src/tools/council.ts
1103
1103
  import { tool } from "@opencode-ai/plugin";
1104
+
1105
+ // src/utils/log.ts
1106
+ import * as fs2 from "fs/promises";
1107
+ import * as path2 from "path";
1108
+ import * as os2 from "os";
1109
+ var LOG_DIR = path2.join(os2.homedir(), ".local", "share", "opencode", "log");
1110
+ var LOG_PREFIX = "oh-my-opencode-cohub";
1111
+ var KEEP_DAYS = 7;
1112
+ var _today = "";
1113
+ var _logPath = "";
1114
+ var _cleanedToday = false;
1115
+ function getLogPath() {
1116
+ const today = new Date().toISOString().slice(0, 10).replace(/-/g, "");
1117
+ if (today !== _today) {
1118
+ _today = today;
1119
+ _logPath = path2.join(LOG_DIR, `${LOG_PREFIX}.${today}.log`);
1120
+ _cleanedToday = false;
1121
+ }
1122
+ return _logPath;
1123
+ }
1124
+ async function cleanOldLogsOnce() {
1125
+ if (_cleanedToday)
1126
+ return;
1127
+ _cleanedToday = true;
1128
+ try {
1129
+ const cutoff = new Date;
1130
+ cutoff.setUTCDate(cutoff.getUTCDate() - KEEP_DAYS);
1131
+ const cutoffStr = cutoff.toISOString().slice(0, 10).replace(/-/g, "");
1132
+ const files = await fs2.readdir(LOG_DIR);
1133
+ for (const file of files) {
1134
+ if (!file.startsWith(LOG_PREFIX + "."))
1135
+ continue;
1136
+ const escapedPrefix = LOG_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1137
+ const match = file.match(new RegExp(`^${escapedPrefix}\\.(\\d{8})\\.log$`));
1138
+ if (!match)
1139
+ continue;
1140
+ if (match[1] < cutoffStr) {
1141
+ await fs2.unlink(path2.join(LOG_DIR, file)).catch(() => {});
1142
+ }
1143
+ }
1144
+ } catch {}
1145
+ }
1146
+ async function appendLog(tag, message, err) {
1147
+ try {
1148
+ const logPath = getLogPath();
1149
+ await fs2.mkdir(LOG_DIR, { recursive: true });
1150
+ const now = new Date().toISOString();
1151
+ let line = `[${now}] [oh-my-opencode-cohub] [${tag}] ${message}`;
1152
+ if (err instanceof Error) {
1153
+ line += `
1154
+ stack: ${err.stack ?? err.message}`;
1155
+ } else if (err !== undefined) {
1156
+ line += `
1157
+ detail: ${String(err)}`;
1158
+ }
1159
+ line += `
1160
+ `;
1161
+ await fs2.appendFile(logPath, line, "utf-8");
1162
+ await cleanOldLogsOnce();
1163
+ } catch {}
1164
+ }
1165
+
1166
+ // src/tools/council.ts
1104
1167
  var z = tool.schema;
1105
1168
 
1106
1169
  class OperationTimeoutError extends Error {
@@ -1127,14 +1190,16 @@ function parseModelReference(model) {
1127
1190
  async function abortSession(client, sessionId) {
1128
1191
  try {
1129
1192
  await client.session.abort({ path: { id: sessionId } });
1130
- } catch {}
1193
+ } catch (err) {
1194
+ appendLog("abortSession", "中止会话失败", err);
1195
+ }
1131
1196
  }
1132
- async function promptWithTimeout(client, path2, body, timeoutMs, directory) {
1133
- const sessionId = path2.id;
1197
+ async function promptWithTimeout(client, path3, body, timeoutMs, directory) {
1198
+ const sessionId = path3.id;
1134
1199
  let timer;
1135
1200
  try {
1136
1201
  const promptPromise = client.session.prompt({
1137
- path: path2,
1202
+ path: path3,
1138
1203
  body,
1139
1204
  query: directory ? { directory } : undefined
1140
1205
  });
@@ -1143,7 +1208,7 @@ async function promptWithTimeout(client, path2, body, timeoutMs, directory) {
1143
1208
  if (timeoutMs > 0) {
1144
1209
  racers.push(new Promise((_, reject) => {
1145
1210
  timer = setTimeout(() => {
1146
- reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
1211
+ reject(new OperationTimeoutError(`[oh-my-opencode-cohub] Prompt timed out after ${timeoutMs}ms`));
1147
1212
  }, timeoutMs);
1148
1213
  }));
1149
1214
  }
@@ -1354,7 +1419,7 @@ class CouncilManager {
1354
1419
  async runAgentSession(options) {
1355
1420
  const modelRef = parseModelReference(options.model);
1356
1421
  if (!modelRef) {
1357
- throw new Error(`Invalid model format: ${options.model}`);
1422
+ throw new Error(`[oh-my-opencode-cohub] Invalid model format: ${options.model}`);
1358
1423
  }
1359
1424
  let sessionId;
1360
1425
  try {
@@ -1366,9 +1431,12 @@ class CouncilManager {
1366
1431
  query: { directory: this.directory }
1367
1432
  });
1368
1433
  if (!session.data?.id) {
1369
- throw new Error("Failed to create session");
1434
+ throw new Error("[oh-my-opencode-cohub] Failed to create session");
1370
1435
  }
1371
1436
  sessionId = session.data.id;
1437
+ if (!options.promptText) {
1438
+ throw new Error("[oh-my-opencode-cohub] PromptText is empty");
1439
+ }
1372
1440
  const promptBody = {
1373
1441
  model: modelRef,
1374
1442
  tools: {
@@ -1388,7 +1456,7 @@ class CouncilManager {
1388
1456
  await promptWithTimeout(this.client, { id: sessionId }, promptBody, options.timeout, this.directory);
1389
1457
  const extraction = await extractSessionResult(this.client, sessionId);
1390
1458
  if (extraction.empty) {
1391
- throw new Error("Empty response from provider");
1459
+ throw new Error("[oh-my-opencode-cohub] Empty response from provider");
1392
1460
  }
1393
1461
  return extraction.text;
1394
1462
  } finally {
@@ -1417,7 +1485,7 @@ function createCouncilTool(ctx, councilManager) {
1417
1485
  const allowedAgents = ["co-council"];
1418
1486
  const callingAgent = toolContext.agent;
1419
1487
  if (callingAgent && !allowedAgents.includes(callingAgent)) {
1420
- throw new Error(`Council sessions can only be invoked by the co-council agent. Current agent: ${callingAgent}`);
1488
+ throw new Error(`[oh-my-opencode-cohub] Council sessions can only be invoked by the co-council agent. Current agent: ${callingAgent}`);
1421
1489
  }
1422
1490
  const prompt = String(args.prompt);
1423
1491
  const preset = typeof args.preset === "string" ? args.preset : undefined;
@@ -1441,9 +1509,9 @@ function createCouncilTool(ctx, councilManager) {
1441
1509
  }
1442
1510
 
1443
1511
  // src/index.ts
1444
- import * as fs2 from "node:fs";
1445
- import * as path2 from "node:path";
1446
- import * as os2 from "node:os";
1512
+ import * as fs3 from "node:fs";
1513
+ import * as path3 from "node:path";
1514
+ import * as os3 from "node:os";
1447
1515
  function loadFileOverrides(projectDir) {
1448
1516
  const overrides = {};
1449
1517
  const agentNames = [
@@ -1462,22 +1530,26 @@ function loadFileOverrides(projectDir) {
1462
1530
  ];
1463
1531
  const searchDirs = [];
1464
1532
  if (projectDir) {
1465
- searchDirs.push(path2.join(projectDir, ".opencode", "oh-my-opencode-cohub"));
1533
+ searchDirs.push(path3.join(projectDir, ".opencode", "oh-my-opencode-cohub"));
1466
1534
  }
1467
- searchDirs.push(path2.join(os2.homedir(), ".config", "opencode", "oh-my-opencode-cohub"));
1535
+ searchDirs.push(path3.join(os3.homedir(), ".config", "opencode", "oh-my-opencode-cohub"));
1468
1536
  for (const agent of agentNames) {
1469
1537
  for (const dir of searchDirs) {
1470
- const replacePath = path2.join(dir, `${agent}.md`);
1471
- if (!overrides[agent]?.replace && fs2.existsSync(replacePath)) {
1538
+ const replacePath = path3.join(dir, `${agent}.md`);
1539
+ if (!overrides[agent]?.replace && fs3.existsSync(replacePath)) {
1472
1540
  try {
1473
- overrides[agent] = { ...overrides[agent], replace: fs2.readFileSync(replacePath, "utf-8") };
1474
- } catch {}
1541
+ overrides[agent] = { ...overrides[agent], replace: fs3.readFileSync(replacePath, "utf-8") };
1542
+ } catch (err) {
1543
+ appendLog("loadFileOverrides", "读取replace文件失败", err);
1544
+ }
1475
1545
  }
1476
- const appendPath = path2.join(dir, `${agent}_append.md`);
1477
- if (!overrides[agent]?.append && fs2.existsSync(appendPath)) {
1546
+ const appendPath = path3.join(dir, `${agent}_append.md`);
1547
+ if (!overrides[agent]?.append && fs3.existsSync(appendPath)) {
1478
1548
  try {
1479
- overrides[agent] = { ...overrides[agent], append: fs2.readFileSync(appendPath, "utf-8") };
1480
- } catch {}
1549
+ overrides[agent] = { ...overrides[agent], append: fs3.readFileSync(appendPath, "utf-8") };
1550
+ } catch (err) {
1551
+ appendLog("loadFileOverrides", "读取append文件失败", err);
1552
+ }
1481
1553
  }
1482
1554
  }
1483
1555
  }
@@ -1505,26 +1577,26 @@ var CoHubPlugin = async (input, options) => {
1505
1577
  }
1506
1578
  const promptOverrides = { ...configOverrides, ...fileOverrides };
1507
1579
  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");
1580
+ const STATE_DIR = path3.join(os3.homedir(), ".local", "share", "opencode", "storage", "oh-my-opencode-cohub");
1581
+ const STATE_FILE = path3.join(STATE_DIR, "tracker-state.json");
1510
1582
  function syncTrackerState(sessionId) {
1511
1583
  try {
1512
- if (!fs2.existsSync(STATE_DIR)) {
1513
- fs2.mkdirSync(STATE_DIR, { recursive: true });
1584
+ if (!fs3.existsSync(STATE_DIR)) {
1585
+ fs3.mkdirSync(STATE_DIR, { recursive: true });
1514
1586
  }
1515
1587
  const state = {
1516
1588
  updatedAt: Date.now(),
1517
1589
  runningAgents: tracker.getRunningAgents(sessionId),
1518
1590
  runningCount: tracker.getRunningCount(sessionId)
1519
1591
  };
1520
- fs2.writeFileSync(STATE_FILE, JSON.stringify(state), "utf-8");
1592
+ fs3.writeFileSync(STATE_FILE, JSON.stringify(state), "utf-8");
1521
1593
  } catch {}
1522
1594
  }
1523
- const AGENT_CONFIG_FILE = path2.join(STATE_DIR, "cohub-state.json");
1595
+ const AGENT_CONFIG_FILE = path3.join(STATE_DIR, "cohub-state.json");
1524
1596
  function syncAgentConfig() {
1525
1597
  try {
1526
- if (!fs2.existsSync(STATE_DIR)) {
1527
- fs2.mkdirSync(STATE_DIR, { recursive: true });
1598
+ if (!fs3.existsSync(STATE_DIR)) {
1599
+ fs3.mkdirSync(STATE_DIR, { recursive: true });
1528
1600
  }
1529
1601
  const configs = agents.map((a) => {
1530
1602
  const modelStr = a.config.model;
@@ -1539,7 +1611,7 @@ var CoHubPlugin = async (input, options) => {
1539
1611
  provider
1540
1612
  };
1541
1613
  });
1542
- fs2.writeFileSync(AGENT_CONFIG_FILE, JSON.stringify({ updatedAt: Date.now(), agents: configs }), "utf-8");
1614
+ fs3.writeFileSync(AGENT_CONFIG_FILE, JSON.stringify({ updatedAt: Date.now(), agents: configs }), "utf-8");
1543
1615
  } catch {}
1544
1616
  }
1545
1617
  const agents = [
@@ -1690,12 +1762,16 @@ var CoHubPlugin = async (input, options) => {
1690
1762
  const cleanupTimer = setInterval(() => {
1691
1763
  try {
1692
1764
  tracker.cleanupStaleJobs(STALE_TIMEOUT_MS);
1693
- } catch {}
1765
+ } catch (err) {
1766
+ appendLog("cleanupStaleJobs", "定时清理过期任务失败", err);
1767
+ }
1694
1768
  }, 30000);
1695
1769
  const contextCleanupTimer = setInterval(() => {
1696
1770
  try {
1697
1771
  contextEngine.cleanupStaleDependencies();
1698
- } catch {}
1772
+ } catch (err) {
1773
+ appendLog("contextCleanupTimer", "定时清理上下文失败", err);
1774
+ }
1699
1775
  }, 60000);
1700
1776
  const agentConfigs = {};
1701
1777
  for (const agent of agents) {
@@ -1716,8 +1792,10 @@ var CoHubPlugin = async (input, options) => {
1716
1792
  c.agent[name] = config;
1717
1793
  }
1718
1794
  try {
1719
- fs2.writeFileSync(path2.join(STATE_DIR, "config-hook-ran.json"), JSON.stringify({ ran: true, count: agents.length }));
1720
- } catch {}
1795
+ fs3.writeFileSync(path3.join(STATE_DIR, "config-hook-ran.json"), JSON.stringify({ ran: true, count: agents.length }));
1796
+ } catch (err) {
1797
+ appendLog("config", "双重注册写入文件失败", err);
1798
+ }
1721
1799
  },
1722
1800
  "tool.execute.before": async (input2, output) => {
1723
1801
  try {
@@ -1754,19 +1832,19 @@ var CoHubPlugin = async (input, options) => {
1754
1832
  if (details) {
1755
1833
  output.args[targetField] += details;
1756
1834
  }
1757
- const logPath = path2.join(os2.tmpdir(), "opencode", "ctx-diag.log");
1835
+ const logPath = path3.join(os3.tmpdir(), "opencode", "ctx-diag.log");
1758
1836
  try {
1759
- const stat = fs2.statSync(logPath);
1837
+ const stat = fs3.statSync(logPath);
1760
1838
  if (stat.size > 50 * 1024) {
1761
- const lines = fs2.readFileSync(logPath, "utf-8").trim().split(`
1839
+ const lines = fs3.readFileSync(logPath, "utf-8").trim().split(`
1762
1840
  `);
1763
- fs2.writeFileSync(logPath, lines.slice(-30).join(`
1841
+ fs3.writeFileSync(logPath, lines.slice(-30).join(`
1764
1842
  `) + `
1765
1843
  `);
1766
1844
  }
1767
1845
  } catch {}
1768
1846
  const finalPrompt = typeof output.args?.prompt === "string" ? output.args.prompt : "";
1769
- fs2.appendFileSync(logPath, JSON.stringify({
1847
+ fs3.appendFileSync(logPath, JSON.stringify({
1770
1848
  time: new Date().toISOString(),
1771
1849
  session: input2.sessionID?.slice(0, 20) ?? "?",
1772
1850
  subagent: subagentType,
@@ -1782,7 +1860,7 @@ var CoHubPlugin = async (input, options) => {
1782
1860
  }
1783
1861
  }
1784
1862
  } catch (err) {
1785
- console.warn("[oh-my-opencode-cohub] tool.execute.before hook 失败:", err);
1863
+ appendLog("tool.execute.before", "hook 失败", err);
1786
1864
  }
1787
1865
  },
1788
1866
  "tool.execute.after": async (input2, output) => {
@@ -1799,7 +1877,9 @@ var CoHubPlugin = async (input, options) => {
1799
1877
  tracker.updateAfterTask(input2.sessionID, "completed", childSessionId);
1800
1878
  syncTrackerState(input2.sessionID ?? "");
1801
1879
  }
1802
- } catch {}
1880
+ } catch (err) {
1881
+ appendLog("tool.execute.after", "hook 失败", err);
1882
+ }
1803
1883
  },
1804
1884
  event: async (input2) => {
1805
1885
  try {
@@ -1821,7 +1901,9 @@ var CoHubPlugin = async (input, options) => {
1821
1901
  tracker.updateByChildSessionId(sessionId, "errored");
1822
1902
  syncTrackerState(tracker.currentParentSessionId);
1823
1903
  }
1824
- } catch {}
1904
+ } catch (err) {
1905
+ appendLog("event", "事件处理失败", err);
1906
+ }
1825
1907
  },
1826
1908
  "experimental.chat.messages.transform": async (_input, output) => {
1827
1909
  try {
@@ -1831,7 +1913,7 @@ var CoHubPlugin = async (input, options) => {
1831
1913
  let sessionID;
1832
1914
  for (let i = output.messages.length - 1;i >= 0; i--) {
1833
1915
  const m = output.messages[i];
1834
- if (m.info.role === "user") {
1916
+ if (m.info?.role === "user") {
1835
1917
  lastUserMsg = m;
1836
1918
  sessionID = m.info?.sessionID;
1837
1919
  break;
@@ -1839,12 +1921,14 @@ var CoHubPlugin = async (input, options) => {
1839
1921
  }
1840
1922
  if (!lastUserMsg)
1841
1923
  return;
1924
+ if (!lastUserMsg.parts || !Array.isArray(lastUserMsg.parts))
1925
+ return;
1842
1926
  const board = tracker.getBoardText();
1843
1927
  if (board) {
1844
1928
  for (let j = lastUserMsg.parts.length - 1;j >= 0; j--) {
1845
1929
  const part = lastUserMsg.parts[j];
1846
1930
  if (part.type === "text") {
1847
- part.text += `
1931
+ part.text = (part.text || "") + `
1848
1932
 
1849
1933
  ` + board;
1850
1934
  break;
@@ -1855,17 +1939,23 @@ var CoHubPlugin = async (input, options) => {
1855
1939
  for (let k = lastUserMsg.parts.length - 1;k >= 0; k--) {
1856
1940
  const part = lastUserMsg.parts[k];
1857
1941
  if (part.type === "text") {
1858
- part.text += coreRulesInjectionText;
1942
+ part.text = (part.text || "") + coreRulesInjectionText;
1859
1943
  break;
1860
1944
  }
1861
1945
  }
1862
1946
  }
1863
1947
  } catch (err) {
1864
- console.warn("[oh-my-opencode-cohub] messages.transform hook 失败:", err);
1948
+ appendLog("messages.transform", "hook 失败", err);
1865
1949
  }
1866
1950
  },
1867
1951
  "experimental.chat.system.transform": async (input2, output) => {
1868
- output.system.push(CHINESE_LANGUAGE_INSTRUCTION);
1952
+ try {
1953
+ if (output?.system && Array.isArray(output.system)) {
1954
+ output.system.push(CHINESE_LANGUAGE_INSTRUCTION);
1955
+ }
1956
+ } catch (err) {
1957
+ appendLog("system.transform", "hook 失败", err);
1958
+ }
1869
1959
  },
1870
1960
  dispose: async () => {
1871
1961
  clearInterval(cleanupTimer);
@@ -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.0",
3
+ "version": "1.10.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Mr-cjf/oh-my-opencode-cohub.git"
@@ -52,6 +52,9 @@
52
52
  "@types/node": "^26.1.1",
53
53
  "typescript": "^5.4.0"
54
54
  },
55
+ "overrides": {
56
+ "@babel/core": "7.29.6"
57
+ },
55
58
  "opencode": {
56
59
  "plugin": true
57
60
  }