@skj1724/oh-my-opencode 3.23.2 → 3.23.4

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/index.js CHANGED
@@ -46,6 +46,59 @@ var __export = (target, all) => {
46
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
47
  var __require = import.meta.require;
48
48
 
49
+ // src/features/claude-code-session-state/state.ts
50
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
51
+ import { join } from "path";
52
+ function setMainSession(id) {
53
+ _mainSessionID = id;
54
+ }
55
+ function getMainSessionID() {
56
+ return _mainSessionID;
57
+ }
58
+ function updateSessionAgent(sessionID, agent, source = "unknown") {
59
+ sessionAgentMap.set(sessionID, agent);
60
+ sessionAgentMetaMap.set(sessionID, { updatedAt: Date.now(), source });
61
+ }
62
+ function getSessionAgent(sessionID) {
63
+ return sessionAgentMap.get(sessionID);
64
+ }
65
+ function isSessionAgentStale(sessionID, staleThresholdMs) {
66
+ const meta = sessionAgentMetaMap.get(sessionID);
67
+ if (!meta)
68
+ return false;
69
+ return Date.now() - meta.updatedAt > staleThresholdMs;
70
+ }
71
+ function clearSessionAgent(sessionID) {
72
+ sessionAgentMap.delete(sessionID);
73
+ sessionAgentMetaMap.delete(sessionID);
74
+ }
75
+ function loadSessionAgentMap(directory) {
76
+ try {
77
+ const persistPath = join(directory, ".opencode", "session-agent-map.json");
78
+ if (!existsSync(persistPath))
79
+ return;
80
+ const content = readFileSync(persistPath, "utf-8");
81
+ const data = JSON.parse(content);
82
+ for (const [sessionID, entry] of Object.entries(data)) {
83
+ if (!sessionAgentMap.has(sessionID)) {
84
+ sessionAgentMap.set(sessionID, entry.agent);
85
+ sessionAgentMetaMap.set(sessionID, { updatedAt: entry.updatedAt, source: entry.source });
86
+ }
87
+ }
88
+ } catch {}
89
+ }
90
+ var subagentSessions, _mainSessionID, sessionAgentMap, sessionAgentMetaMap;
91
+ var init_state = __esm(() => {
92
+ subagentSessions = new Set;
93
+ sessionAgentMap = new Map;
94
+ sessionAgentMetaMap = new Map;
95
+ });
96
+
97
+ // src/features/claude-code-session-state/index.ts
98
+ var init_claude_code_session_state = __esm(() => {
99
+ init_state();
100
+ });
101
+
49
102
  // src/shared/agent-display-names.ts
50
103
  function getAgentDisplayName(configKey) {
51
104
  const exactMatch = AGENT_DISPLAY_TO_KEY[configKey];
@@ -135,7 +188,7 @@ var init_agent_display_names = __esm(() => {
135
188
  });
136
189
 
137
190
  // src/shared/fileio-monitor.ts
138
- import { readdirSync, readFileSync, writeFileSync, existsSync } from "fs";
191
+ import { readdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
139
192
  import { relative } from "path";
140
193
  import { cwd } from "process";
141
194
  function summarize(path) {
@@ -172,11 +225,11 @@ function createFileIOMonitor(tracer) {
172
225
  },
173
226
  readFileSync(path, options) {
174
227
  if (!tracer.isEnabled()) {
175
- return readFileSync(path, options);
228
+ return readFileSync2(path, options);
176
229
  }
177
230
  const start = performance.now();
178
231
  try {
179
- return readFileSync(path, options);
232
+ return readFileSync2(path, options);
180
233
  } finally {
181
234
  const durationMs = performance.now() - start;
182
235
  tracer.recordFileIO("readFileSync", summarize(path), durationMs);
@@ -184,12 +237,12 @@ function createFileIOMonitor(tracer) {
184
237
  },
185
238
  writeFileSync(path, data, options) {
186
239
  if (!tracer.isEnabled()) {
187
- writeFileSync(path, data, options);
240
+ writeFileSync2(path, data, options);
188
241
  return;
189
242
  }
190
243
  const start = performance.now();
191
244
  try {
192
- writeFileSync(path, data, options);
245
+ writeFileSync2(path, data, options);
193
246
  } finally {
194
247
  const durationMs = performance.now() - start;
195
248
  tracer.recordFileIO("writeFileSync", summarize(path), durationMs);
@@ -197,11 +250,11 @@ function createFileIOMonitor(tracer) {
197
250
  },
198
251
  existsSync(path) {
199
252
  if (!tracer.isEnabled()) {
200
- return existsSync(path);
253
+ return existsSync2(path);
201
254
  }
202
255
  const start = performance.now();
203
256
  try {
204
- return existsSync(path);
257
+ return existsSync2(path);
205
258
  } finally {
206
259
  const durationMs = performance.now() - start;
207
260
  tracer.recordFileIO("existsSync", summarize(path), durationMs);
@@ -262,9 +315,9 @@ var init_system_directive = __esm(() => {
262
315
  });
263
316
 
264
317
  // src/shared/opencode-config-dir.ts
265
- import { existsSync as existsSync3 } from "fs";
318
+ import { existsSync as existsSync4 } from "fs";
266
319
  import { homedir as homedir2 } from "os";
267
- import { join as join5, resolve } from "path";
320
+ import { join as join6, resolve } from "path";
268
321
  function isDevBuild(version) {
269
322
  if (!version)
270
323
  return false;
@@ -274,15 +327,15 @@ function getTauriConfigDir(identifier) {
274
327
  const platform = process.platform;
275
328
  switch (platform) {
276
329
  case "darwin":
277
- return join5(homedir2(), "Library", "Application Support", identifier);
330
+ return join6(homedir2(), "Library", "Application Support", identifier);
278
331
  case "win32": {
279
- const appData = process.env.APPDATA || join5(homedir2(), "AppData", "Roaming");
280
- return join5(appData, identifier);
332
+ const appData = process.env.APPDATA || join6(homedir2(), "AppData", "Roaming");
333
+ return join6(appData, identifier);
281
334
  }
282
335
  case "linux":
283
336
  default: {
284
- const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
285
- return join5(xdgConfig, identifier);
337
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config");
338
+ return join6(xdgConfig, identifier);
286
339
  }
287
340
  }
288
341
  }
@@ -292,21 +345,21 @@ function getCliConfigDir() {
292
345
  return resolve(envConfigDir);
293
346
  }
294
347
  if (process.platform === "win32") {
295
- const crossPlatformDir = join5(homedir2(), ".config", "opencode");
296
- const crossPlatformConfig = join5(crossPlatformDir, "opencode.json");
297
- if (existsSync3(crossPlatformConfig)) {
348
+ const crossPlatformDir = join6(homedir2(), ".config", "opencode");
349
+ const crossPlatformConfig = join6(crossPlatformDir, "opencode.json");
350
+ if (existsSync4(crossPlatformConfig)) {
298
351
  return crossPlatformDir;
299
352
  }
300
- const appData = process.env.APPDATA || join5(homedir2(), "AppData", "Roaming");
301
- const appdataDir = join5(appData, "opencode");
302
- const appdataConfig = join5(appdataDir, "opencode.json");
303
- if (existsSync3(appdataConfig)) {
353
+ const appData = process.env.APPDATA || join6(homedir2(), "AppData", "Roaming");
354
+ const appdataDir = join6(appData, "opencode");
355
+ const appdataConfig = join6(appdataDir, "opencode.json");
356
+ if (existsSync4(appdataConfig)) {
304
357
  return appdataDir;
305
358
  }
306
359
  return crossPlatformDir;
307
360
  }
308
- const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
309
- return join5(xdgConfig, "opencode");
361
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config");
362
+ return join6(xdgConfig, "opencode");
310
363
  }
311
364
  function getOpenCodeConfigDir(options) {
312
365
  const { binary, version, checkExisting = true } = options;
@@ -317,9 +370,9 @@ function getOpenCodeConfigDir(options) {
317
370
  const tauriDir = getTauriConfigDir(identifier);
318
371
  if (checkExisting) {
319
372
  const legacyDir = getCliConfigDir();
320
- const legacyConfig = join5(legacyDir, "opencode.json");
321
- const legacyConfigC = join5(legacyDir, "opencode.jsonc");
322
- if (existsSync3(legacyConfig) || existsSync3(legacyConfigC)) {
373
+ const legacyConfig = join6(legacyDir, "opencode.json");
374
+ const legacyConfigC = join6(legacyDir, "opencode.jsonc");
375
+ if (existsSync4(legacyConfig) || existsSync4(legacyConfigC)) {
323
376
  return legacyDir;
324
377
  }
325
378
  }
@@ -329,10 +382,10 @@ function getOpenCodeConfigPaths(options) {
329
382
  const configDir = getOpenCodeConfigDir(options);
330
383
  return {
331
384
  configDir,
332
- configJson: join5(configDir, "opencode.json"),
333
- configJsonc: join5(configDir, "opencode.jsonc"),
334
- packageJson: join5(configDir, "package.json"),
335
- omoConfig: join5(configDir, "oh-my-opencode.json")
385
+ configJson: join6(configDir, "opencode.json"),
386
+ configJsonc: join6(configDir, "opencode.jsonc"),
387
+ packageJson: join6(configDir, "package.json"),
388
+ omoConfig: join6(configDir, "oh-my-opencode.json")
336
389
  };
337
390
  }
338
391
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
@@ -1203,7 +1256,7 @@ var init_main = __esm(() => {
1203
1256
  });
1204
1257
 
1205
1258
  // src/shared/jsonc-parser.ts
1206
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1259
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
1207
1260
  function parseJsonc(content) {
1208
1261
  const errors = [];
1209
1262
  const result = parse2(content, errors, {
@@ -1234,10 +1287,10 @@ function parseJsoncSafe(content) {
1234
1287
  function detectConfigFile(basePath) {
1235
1288
  const jsoncPath = `${basePath}.jsonc`;
1236
1289
  const jsonPath = `${basePath}.json`;
1237
- if (existsSync4(jsoncPath)) {
1290
+ if (existsSync5(jsoncPath)) {
1238
1291
  return { format: "jsonc", path: jsoncPath };
1239
1292
  }
1240
- if (existsSync4(jsonPath)) {
1293
+ if (existsSync5(jsonPath)) {
1241
1294
  return { format: "json", path: jsonPath };
1242
1295
  }
1243
1296
  return { format: "none", path: jsonPath };
@@ -3999,7 +4052,7 @@ var init_js_yaml = __esm(() => {
3999
4052
  });
4000
4053
 
4001
4054
  // src/shared/frontmatter.ts
4002
- import { readFileSync as readFileSync6 } from "fs";
4055
+ import { readFileSync as readFileSync7 } from "fs";
4003
4056
  function parseFrontmatter(content) {
4004
4057
  const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n?---\r?\n([\s\S]*)$/;
4005
4058
  const match = content.match(frontmatterRegex);
@@ -4018,7 +4071,7 @@ function parseFrontmatter(content) {
4018
4071
  }
4019
4072
  function parseCompletionActions(planPath) {
4020
4073
  try {
4021
- const content = readFileSync6(planPath, "utf-8");
4074
+ const content = readFileSync7(planPath, "utf-8");
4022
4075
  const result = parseFrontmatter(content);
4023
4076
  if (!result.hadFrontmatter || result.parseError) {
4024
4077
  return [];
@@ -4046,17 +4099,17 @@ var init_frontmatter = __esm(() => {
4046
4099
  import { spawn as spawn2 } from "child_process";
4047
4100
  import { exec } from "child_process";
4048
4101
  import { promisify } from "util";
4049
- import { existsSync as existsSync7 } from "fs";
4102
+ import { existsSync as existsSync8 } from "fs";
4050
4103
  import { homedir as homedir3 } from "os";
4051
4104
  function getHomeDir() {
4052
4105
  return process.env.HOME || process.env.USERPROFILE || homedir3();
4053
4106
  }
4054
4107
  function findShellPath(defaultPaths, customPath) {
4055
- if (customPath && existsSync7(customPath)) {
4108
+ if (customPath && existsSync8(customPath)) {
4056
4109
  return customPath;
4057
4110
  }
4058
4111
  for (const path3 of defaultPaths) {
4059
- if (existsSync7(path3)) {
4112
+ if (existsSync8(path3)) {
4060
4113
  return path3;
4061
4114
  }
4062
4115
  }
@@ -4191,8 +4244,8 @@ var init_command_executor = __esm(() => {
4191
4244
  });
4192
4245
 
4193
4246
  // src/shared/file-reference-resolver.ts
4194
- import { existsSync as existsSync8, readFileSync as readFileSync7, statSync } from "fs";
4195
- import { join as join9, isAbsolute } from "path";
4247
+ import { existsSync as existsSync9, readFileSync as readFileSync8, statSync } from "fs";
4248
+ import { join as join10, isAbsolute } from "path";
4196
4249
  function findFileReferences(text) {
4197
4250
  const matches = [];
4198
4251
  let match;
@@ -4211,17 +4264,17 @@ function resolveFilePath(filePath, cwd2) {
4211
4264
  if (isAbsolute(filePath)) {
4212
4265
  return filePath;
4213
4266
  }
4214
- return join9(cwd2, filePath);
4267
+ return join10(cwd2, filePath);
4215
4268
  }
4216
4269
  function readFileContent(resolvedPath) {
4217
- if (!existsSync8(resolvedPath)) {
4270
+ if (!existsSync9(resolvedPath)) {
4218
4271
  return `[file not found: ${resolvedPath}]`;
4219
4272
  }
4220
4273
  const stat = statSync(resolvedPath);
4221
4274
  if (stat.isDirectory()) {
4222
4275
  return `[cannot read directory: ${resolvedPath}]`;
4223
4276
  }
4224
- const content = readFileSync7(resolvedPath, "utf-8");
4277
+ const content = readFileSync8(resolvedPath, "utf-8");
4225
4278
  return content;
4226
4279
  }
4227
4280
  async function resolveFileReferencesInText(text, cwd2 = process.cwd(), depth = 0, maxDepth = 3) {
@@ -4542,13 +4595,13 @@ var init_config_errors = __esm(() => {
4542
4595
 
4543
4596
  // src/shared/claude-config-dir.ts
4544
4597
  import { homedir as homedir4 } from "os";
4545
- import { join as join10 } from "path";
4598
+ import { join as join11 } from "path";
4546
4599
  function getClaudeConfigDir() {
4547
4600
  const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
4548
4601
  if (envConfigDir) {
4549
4602
  return envConfigDir;
4550
4603
  }
4551
- return join10(homedir4(), ".claude");
4604
+ return join11(homedir4(), ".claude");
4552
4605
  }
4553
4606
  var init_claude_config_dir = () => {};
4554
4607
 
@@ -5214,9 +5267,9 @@ var init_model_requirements = __esm(() => {
5214
5267
  });
5215
5268
 
5216
5269
  // src/shared/model-availability.ts
5217
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
5270
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
5218
5271
  import { homedir as homedir6 } from "os";
5219
- import { join as join12 } from "path";
5272
+ import { join as join13 } from "path";
5220
5273
  function normalizeModelName(name) {
5221
5274
  return name.toLowerCase().replace(/claude-(opus|sonnet|haiku)-4-5/g, "claude-$1-4.5").replace(/claude-(opus|sonnet|haiku)-4\.5/g, "claude-$1-4.5");
5222
5275
  }
@@ -5257,8 +5310,8 @@ function fuzzyMatchModel(target, available, providers) {
5257
5310
  function getOpenCodeCacheDir() {
5258
5311
  const xdgCache = process.env.XDG_CACHE_HOME;
5259
5312
  if (xdgCache)
5260
- return join12(xdgCache, "opencode");
5261
- return join12(homedir6(), ".cache", "opencode");
5313
+ return join13(xdgCache, "opencode");
5314
+ return join13(homedir6(), ".cache", "opencode");
5262
5315
  }
5263
5316
  async function fetchAvailableModels(_client) {
5264
5317
  log("[fetchAvailableModels] CALLED");
@@ -5267,14 +5320,14 @@ async function fetchAvailableModels(_client) {
5267
5320
  return cachedModels;
5268
5321
  }
5269
5322
  const modelSet = new Set;
5270
- const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
5323
+ const cacheFile = join13(getOpenCodeCacheDir(), "models.json");
5271
5324
  log("[fetchAvailableModels] reading cache file", { cacheFile });
5272
- if (!existsSync10(cacheFile)) {
5325
+ if (!existsSync11(cacheFile)) {
5273
5326
  log("[fetchAvailableModels] cache file not found, returning empty set");
5274
5327
  return modelSet;
5275
5328
  }
5276
5329
  try {
5277
- const content = readFileSync9(cacheFile, "utf-8");
5330
+ const content = readFileSync10(cacheFile, "utf-8");
5278
5331
  const data = JSON.parse(content);
5279
5332
  const providerIds = Object.keys(data);
5280
5333
  log("[fetchAvailableModels] providers found", { count: providerIds.length, providers: providerIds.slice(0, 10) });
@@ -5296,8 +5349,8 @@ async function fetchAvailableModels(_client) {
5296
5349
  }
5297
5350
  }
5298
5351
  function isModelCacheAvailable() {
5299
- const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
5300
- return existsSync10(cacheFile);
5352
+ const cacheFile = join13(getOpenCodeCacheDir(), "models.json");
5353
+ return existsSync11(cacheFile);
5301
5354
  }
5302
5355
  var cachedModels = null;
5303
5356
  var init_model_availability = __esm(() => {
@@ -5651,9 +5704,9 @@ class PerfTimer {
5651
5704
  }
5652
5705
 
5653
5706
  // src/shared/perf-tracer.ts
5654
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, existsSync as existsSync11 } from "fs";
5707
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5, existsSync as existsSync12 } from "fs";
5655
5708
  import { tmpdir as tmpdir2 } from "os";
5656
- import { join as join13 } from "path";
5709
+ import { join as join14 } from "path";
5657
5710
 
5658
5711
  class PerfTracer {
5659
5712
  buffer = [];
@@ -5664,7 +5717,7 @@ class PerfTracer {
5664
5717
  memorySnapshotInterval;
5665
5718
  constructor(config) {
5666
5719
  this.enabled = config.enabled;
5667
- this.outputDir = config.outputDir ?? join13(tmpdir2(), "oh-my-opencode-perf");
5720
+ this.outputDir = config.outputDir ?? join14(tmpdir2(), "oh-my-opencode-perf");
5668
5721
  this.slowThreshold = config.slowThreshold ?? 100;
5669
5722
  this.memorySnapshotInterval = config.memorySnapshotInterval ?? 5;
5670
5723
  }
@@ -5760,11 +5813,11 @@ class PerfTracer {
5760
5813
  flush() {
5761
5814
  if (this.buffer.length === 0)
5762
5815
  return;
5763
- if (!existsSync11(this.outputDir)) {
5764
- mkdirSync4(this.outputDir, { recursive: true });
5816
+ if (!existsSync12(this.outputDir)) {
5817
+ mkdirSync5(this.outputDir, { recursive: true });
5765
5818
  }
5766
5819
  const date = new Date().toISOString().slice(0, 10);
5767
- const filePath = join13(this.outputDir, `${date}.jsonl`);
5820
+ const filePath = join14(this.outputDir, `${date}.jsonl`);
5768
5821
  let output = "";
5769
5822
  for (const span of this.buffer) {
5770
5823
  output += JSON.stringify(span) + `
@@ -5781,10 +5834,10 @@ class PerfTracer {
5781
5834
  var init_perf_tracer = () => {};
5782
5835
 
5783
5836
  // src/shared/windows-reserved-names.ts
5784
- import { existsSync as existsSync12, readdirSync as readdirSync5 } from "fs";
5785
- import { join as join14 } from "path";
5837
+ import { existsSync as existsSync13, readdirSync as readdirSync5 } from "fs";
5838
+ import { join as join15 } from "path";
5786
5839
  function scanForReservedNames(directory, maxDepth = 2) {
5787
- if (!existsSync12(directory))
5840
+ if (!existsSync13(directory))
5788
5841
  return [];
5789
5842
  const found = [];
5790
5843
  _scan(directory, 0, maxDepth, found);
@@ -5803,11 +5856,11 @@ function _scan(dir, depth, maxDepth, found) {
5803
5856
  const upper = name.toUpperCase();
5804
5857
  const baseName = upper.split(".")[0] ?? "";
5805
5858
  if (WIN_RESERVED_NAMES.has(upper) || WIN_RESERVED_NAMES.has(baseName)) {
5806
- found.push(join14(dir, name));
5859
+ found.push(join15(dir, name));
5807
5860
  }
5808
- const fullPath = join14(dir, name);
5861
+ const fullPath = join15(dir, name);
5809
5862
  try {
5810
- const stat = existsSync12(fullPath);
5863
+ const stat = existsSync13(fullPath);
5811
5864
  if (stat && depth < maxDepth) {
5812
5865
  _scan(fullPath, depth + 1, maxDepth, found);
5813
5866
  }
@@ -5861,12 +5914,12 @@ var init_windows_reserved_names = __esm(() => {
5861
5914
  });
5862
5915
 
5863
5916
  // src/shared/usage-tracker.ts
5864
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
5917
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
5865
5918
  import { homedir as homedir7 } from "os";
5866
- import { join as join15 } from "path";
5919
+ import { join as join16 } from "path";
5867
5920
  function getStatsFilePath() {
5868
- const configDir = join15(homedir7(), ".config", "opencode");
5869
- return join15(configDir, "usage-stats.json");
5921
+ const configDir = join16(homedir7(), ".config", "opencode");
5922
+ return join16(configDir, "usage-stats.json");
5870
5923
  }
5871
5924
 
5872
5925
  class UsageTracker {
@@ -5967,9 +6020,9 @@ class UsageTracker {
5967
6020
  persistToFile() {
5968
6021
  try {
5969
6022
  const filePath = getStatsFilePath();
5970
- const dir = join15(filePath, "..");
5971
- if (!existsSync13(dir)) {
5972
- mkdirSync5(dir, { recursive: true });
6023
+ const dir = join16(filePath, "..");
6024
+ if (!existsSync14(dir)) {
6025
+ mkdirSync6(dir, { recursive: true });
5973
6026
  }
5974
6027
  const sessions = {};
5975
6028
  for (const [sessionID, records] of this.sessionData) {
@@ -5984,7 +6037,7 @@ class UsageTracker {
5984
6037
  sessions,
5985
6038
  lastUpdated: Date.now()
5986
6039
  };
5987
- writeFileSync6(filePath, JSON.stringify(data, null, 2), "utf-8");
6040
+ writeFileSync7(filePath, JSON.stringify(data, null, 2), "utf-8");
5988
6041
  } catch (error) {
5989
6042
  log("UsageTracker: \u6301\u4E45\u5316\u5931\u8D25", error);
5990
6043
  }
@@ -5992,9 +6045,9 @@ class UsageTracker {
5992
6045
  loadFromDisk() {
5993
6046
  try {
5994
6047
  const filePath = getStatsFilePath();
5995
- if (!existsSync13(filePath))
6048
+ if (!existsSync14(filePath))
5996
6049
  return;
5997
- const content = readFileSync10(filePath, "utf-8");
6050
+ const content = readFileSync11(filePath, "utf-8");
5998
6051
  const data = JSON.parse(content);
5999
6052
  if (data.sessions) {
6000
6053
  for (const [sessionID, sessionData] of Object.entries(data.sessions)) {
@@ -6105,7 +6158,7 @@ function isEnglishText(text, threshold) {
6105
6158
  function detectEnglishViolation(text, threshold = 0.6) {
6106
6159
  let stripped = stripCodeAndUrls(text);
6107
6160
  stripped = stripped.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
6108
- const englishTriggers = [
6161
+ const englishOpeners = [
6109
6162
  "let me",
6110
6163
  "i need",
6111
6164
  "first,",
@@ -6123,12 +6176,44 @@ function detectEnglishViolation(text, threshold = 0.6) {
6123
6176
  "next,",
6124
6177
  "next i",
6125
6178
  "then,",
6126
- "finally,"
6179
+ "finally,",
6180
+ "so,",
6181
+ "okay,",
6182
+ "alright,",
6183
+ "hmm,",
6184
+ "well,",
6185
+ "looking at",
6186
+ "looking into",
6187
+ "going to",
6188
+ "it seems",
6189
+ "it looks",
6190
+ "the code",
6191
+ "the function",
6192
+ "the implementation"
6193
+ ];
6194
+ const englishMarkers = [
6195
+ "i think",
6196
+ "i believe",
6197
+ "i would",
6198
+ "i could",
6199
+ "we should",
6200
+ "we could",
6201
+ "we would",
6202
+ "my approach",
6203
+ "my plan",
6204
+ "i want to",
6205
+ "in summary",
6206
+ "to summarize",
6207
+ "in conclusion"
6127
6208
  ];
6128
6209
  const lowerText = stripped.toLowerCase().trim();
6129
6210
  if (lowerText.length > 0) {
6130
- for (const trigger of englishTriggers) {
6131
- if (lowerText.startsWith(trigger))
6211
+ for (const opener of englishOpeners) {
6212
+ if (lowerText.startsWith(opener))
6213
+ return "trigger";
6214
+ }
6215
+ for (const marker of englishMarkers) {
6216
+ if (lowerText.includes(marker))
6132
6217
  return "trigger";
6133
6218
  }
6134
6219
  }
@@ -6139,6 +6224,59 @@ function detectEnglishViolation(text, threshold = 0.6) {
6139
6224
  return asciiLetters / meaningful.length > threshold ? "ascii" : false;
6140
6225
  }
6141
6226
 
6227
+ // src/shared/agent-identity-resolver.ts
6228
+ function resolveCurrentAgent(sessionID, inputAgent, options) {
6229
+ const staleThresholdMs = options?.staleThresholdMs ?? 600000;
6230
+ const getAgentFromMessages = options?.getAgentFromSessionMessages;
6231
+ const logger = options?.logger;
6232
+ const sessionAgent = getSessionAgent(sessionID);
6233
+ if (sessionAgent !== undefined) {
6234
+ const stale = isSessionAgentStale(sessionID, staleThresholdMs);
6235
+ if (!stale) {
6236
+ if (logger) {
6237
+ logger("[resolveCurrentAgent] resolved from sessionAgentMap", { sessionID, agent: sessionAgent });
6238
+ }
6239
+ return sessionAgent;
6240
+ }
6241
+ if (getAgentFromMessages !== null) {
6242
+ const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
6243
+ if (messageFileAgent !== undefined) {
6244
+ updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.stale-refresh");
6245
+ if (logger) {
6246
+ logger("[resolveCurrentAgent] stale entry refreshed from message files", { sessionID, oldAgent: sessionAgent, newAgent: messageFileAgent });
6247
+ }
6248
+ return messageFileAgent;
6249
+ }
6250
+ if (logger) {
6251
+ logger("[resolveCurrentAgent] stale entry, no message file fallback", { sessionID, oldAgent: sessionAgent });
6252
+ }
6253
+ }
6254
+ }
6255
+ if (inputAgent !== undefined && inputAgent !== null) {
6256
+ if (logger) {
6257
+ logger("[resolveCurrentAgent] resolved from inputAgent", { sessionID, agent: inputAgent });
6258
+ }
6259
+ return inputAgent;
6260
+ }
6261
+ if (getAgentFromMessages !== null) {
6262
+ const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
6263
+ if (messageFileAgent !== undefined) {
6264
+ updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.message-file");
6265
+ if (logger) {
6266
+ logger("[resolveCurrentAgent] resolved from message files", { sessionID, agent: messageFileAgent });
6267
+ }
6268
+ return messageFileAgent;
6269
+ }
6270
+ }
6271
+ if (logger) {
6272
+ logger("[resolveCurrentAgent] no agent identity found", { sessionID });
6273
+ }
6274
+ return;
6275
+ }
6276
+ var init_agent_identity_resolver = __esm(() => {
6277
+ init_claude_code_session_state();
6278
+ });
6279
+
6142
6280
  // src/shared/index.ts
6143
6281
  var init_shared = __esm(() => {
6144
6282
  init_frontmatter();
@@ -6173,6 +6311,7 @@ var init_shared = __esm(() => {
6173
6311
  init_fileio_monitor();
6174
6312
  init_windows_reserved_names();
6175
6313
  init_usage_tracker();
6314
+ init_agent_identity_resolver();
6176
6315
  });
6177
6316
 
6178
6317
  // src/tools/delegate-task/constants.ts
@@ -15624,51 +15763,22 @@ var require_cross_spawn = __commonJS((exports, module) => {
15624
15763
  });
15625
15764
 
15626
15765
  // src/hooks/todo-continuation-enforcer.ts
15627
- import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, renameSync } from "fs";
15628
- import { join as join6 } from "path";
15629
-
15630
- // src/features/claude-code-session-state/state.ts
15631
- var subagentSessions = new Set;
15632
- var _mainSessionID;
15633
- function setMainSession(id) {
15634
- _mainSessionID = id;
15635
- }
15636
- function getMainSessionID() {
15637
- return _mainSessionID;
15638
- }
15639
- var sessionAgentMap = new Map;
15640
- var sessionAgentMetaMap = new Map;
15641
- function updateSessionAgent(sessionID, agent, source = "unknown") {
15642
- sessionAgentMap.set(sessionID, agent);
15643
- sessionAgentMetaMap.set(sessionID, { updatedAt: Date.now(), source });
15644
- }
15645
- function getSessionAgent(sessionID) {
15646
- return sessionAgentMap.get(sessionID);
15647
- }
15648
- function isSessionAgentStale(sessionID, staleThresholdMs) {
15649
- const meta = sessionAgentMetaMap.get(sessionID);
15650
- if (!meta)
15651
- return false;
15652
- return Date.now() - meta.updatedAt > staleThresholdMs;
15653
- }
15654
- function clearSessionAgent(sessionID) {
15655
- sessionAgentMap.delete(sessionID);
15656
- sessionAgentMetaMap.delete(sessionID);
15657
- }
15658
- // src/hooks/todo-continuation-enforcer.ts
15766
+ init_claude_code_session_state();
15659
15767
  init_agent_display_names();
15768
+ import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, renameSync } from "fs";
15769
+ import { join as join7 } from "path";
15660
15770
 
15661
15771
  // src/features/hook-message-injector/injector.ts
15662
15772
  init_fileio_monitor();
15663
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
15664
- import { join as join3 } from "path";
15773
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
15774
+ import { join as join4 } from "path";
15665
15775
 
15666
15776
  // src/features/hook-message-injector/constants.ts
15667
15777
  init_data_path();
15668
- import { join as join2 } from "path";
15778
+ import { join as join3 } from "path";
15669
15779
  var OPENCODE_STORAGE = getOpenCodeStorageDir();
15670
- var MESSAGE_STORAGE = join2(OPENCODE_STORAGE, "message");
15671
- var PART_STORAGE = join2(OPENCODE_STORAGE, "part");
15780
+ var MESSAGE_STORAGE = join3(OPENCODE_STORAGE, "message");
15781
+ var PART_STORAGE = join3(OPENCODE_STORAGE, "part");
15672
15782
 
15673
15783
  // src/features/hook-message-injector/injector.ts
15674
15784
  function findNearestMessageWithFields(messageDir) {
@@ -15677,7 +15787,7 @@ function findNearestMessageWithFields(messageDir) {
15677
15787
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
15678
15788
  for (const file of files) {
15679
15789
  try {
15680
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15790
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15681
15791
  const msg = JSON.parse(content);
15682
15792
  if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
15683
15793
  return msg;
@@ -15688,7 +15798,7 @@ function findNearestMessageWithFields(messageDir) {
15688
15798
  }
15689
15799
  for (const file of files) {
15690
15800
  try {
15691
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15801
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15692
15802
  const msg = JSON.parse(content);
15693
15803
  if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
15694
15804
  return msg;
@@ -15708,7 +15818,7 @@ function findNearestAssistantMessage(messageDir) {
15708
15818
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
15709
15819
  for (const file of files) {
15710
15820
  try {
15711
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15821
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15712
15822
  const msg = JSON.parse(content);
15713
15823
  if (msg.role === "assistant" && msg.agent && msg.model?.providerID && msg.model?.modelID) {
15714
15824
  return msg;
@@ -15719,7 +15829,7 @@ function findNearestAssistantMessage(messageDir) {
15719
15829
  }
15720
15830
  for (const file of files) {
15721
15831
  try {
15722
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15832
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15723
15833
  const msg = JSON.parse(content);
15724
15834
  if (msg.role === "assistant" && (msg.agent || msg.model?.providerID && msg.model?.modelID)) {
15725
15835
  return msg;
@@ -15739,7 +15849,7 @@ function findFirstAssistantAgent(messageDir) {
15739
15849
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort();
15740
15850
  for (const file of files) {
15741
15851
  try {
15742
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15852
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15743
15853
  const msg = JSON.parse(content);
15744
15854
  if (msg.role === "assistant" && msg.agent) {
15745
15855
  return msg.agent;
@@ -15758,19 +15868,19 @@ function getAgentFromMessageDir(messageDir) {
15758
15868
  }
15759
15869
  function getAgentFromSessionMessages(sessionID) {
15760
15870
  const monitor = getFileIOMonitor();
15761
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15871
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15762
15872
  const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
15763
15873
  try {
15764
15874
  if (!_exists(MESSAGE_STORAGE))
15765
15875
  return;
15766
- const directPath = join3(MESSAGE_STORAGE, sessionID);
15876
+ const directPath = join4(MESSAGE_STORAGE, sessionID);
15767
15877
  if (_exists(directPath)) {
15768
15878
  const agent = getAgentFromMessageDir(directPath);
15769
15879
  if (agent)
15770
15880
  return agent;
15771
15881
  }
15772
15882
  for (const dir of _readdir(MESSAGE_STORAGE)) {
15773
- const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
15883
+ const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
15774
15884
  if (_exists(sessionPath)) {
15775
15885
  const agent = getAgentFromMessageDir(sessionPath);
15776
15886
  if (agent)
@@ -15794,18 +15904,18 @@ function generatePartId() {
15794
15904
  }
15795
15905
  function getOrCreateMessageDir(sessionID) {
15796
15906
  const monitor = getFileIOMonitor();
15797
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15798
- const _mkdir = (p, opts) => monitor ? undefined : mkdirSync(p, opts);
15907
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15908
+ const _mkdir = (p, opts) => monitor ? undefined : mkdirSync2(p, opts);
15799
15909
  const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
15800
15910
  if (!_exists(MESSAGE_STORAGE)) {
15801
15911
  _mkdir(MESSAGE_STORAGE, { recursive: true });
15802
15912
  }
15803
- const directPath = join3(MESSAGE_STORAGE, sessionID);
15913
+ const directPath = join4(MESSAGE_STORAGE, sessionID);
15804
15914
  if (_exists(directPath)) {
15805
15915
  return directPath;
15806
15916
  }
15807
15917
  for (const dir of _readdir(MESSAGE_STORAGE)) {
15808
- const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
15918
+ const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
15809
15919
  if (_exists(sessionPath)) {
15810
15920
  return sessionPath;
15811
15921
  }
@@ -15861,19 +15971,19 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
15861
15971
  try {
15862
15972
  const monitor = getFileIOMonitor();
15863
15973
  if (monitor) {
15864
- monitor.writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15974
+ monitor.writeFileSync(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15865
15975
  } else {
15866
- writeFileSync2(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15976
+ writeFileSync3(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15867
15977
  }
15868
- const partDir = join3(PART_STORAGE, messageID);
15869
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15978
+ const partDir = join4(PART_STORAGE, messageID);
15979
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15870
15980
  if (!_exists(partDir)) {
15871
- mkdirSync(partDir, { recursive: true });
15981
+ mkdirSync2(partDir, { recursive: true });
15872
15982
  }
15873
15983
  if (monitor) {
15874
- monitor.writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15984
+ monitor.writeFileSync(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15875
15985
  } else {
15876
- writeFileSync2(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15986
+ writeFileSync3(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15877
15987
  }
15878
15988
  return true;
15879
15989
  } catch {
@@ -15890,14 +16000,14 @@ var DEFAULT_SKIP_AGENTS = ["\u6218\u7565\u53C2\u8C0B", "compaction"];
15890
16000
  var todoOwnerMap = new Map;
15891
16001
  function getTodoOwnershipFilePath() {
15892
16002
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
15893
- return join6(configDir, "todo-ownership.json");
16003
+ return join7(configDir, "todo-ownership.json");
15894
16004
  }
15895
16005
  function loadTodoOwnership() {
15896
16006
  try {
15897
16007
  const filePath = getTodoOwnershipFilePath();
15898
- if (!existsSync5(filePath))
16008
+ if (!existsSync6(filePath))
15899
16009
  return;
15900
- const content = readFileSync4(filePath, "utf-8");
16010
+ const content = readFileSync5(filePath, "utf-8");
15901
16011
  const result = parseJsoncSafe(content);
15902
16012
  if (!result.data || typeof result.data !== "object")
15903
16013
  return;
@@ -15913,15 +16023,15 @@ function loadTodoOwnership() {
15913
16023
  function persistTodoOwnership() {
15914
16024
  try {
15915
16025
  const filePath = getTodoOwnershipFilePath();
15916
- const dir = join6(filePath, "..");
15917
- if (!existsSync5(dir))
15918
- mkdirSync2(dir, { recursive: true });
16026
+ const dir = join7(filePath, "..");
16027
+ if (!existsSync6(dir))
16028
+ mkdirSync3(dir, { recursive: true });
15919
16029
  const tmpPath = `${filePath}.tmp`;
15920
16030
  const data = {};
15921
16031
  for (const [key, value] of todoOwnerMap) {
15922
16032
  data[key] = value;
15923
16033
  }
15924
- writeFileSync3(tmpPath, JSON.stringify(data, null, 2), "utf-8");
16034
+ writeFileSync4(tmpPath, JSON.stringify(data, null, 2), "utf-8");
15925
16035
  renameSync(tmpPath, filePath);
15926
16036
  } catch (err) {
15927
16037
  log(`[${HOOK_NAME}] Failed to persist todo ownership`, { error: String(err) });
@@ -15956,14 +16066,14 @@ var COUNTDOWN_SECONDS = 2;
15956
16066
  var TOAST_DURATION_MS = 900;
15957
16067
  var COUNTDOWN_GRACE_PERIOD_MS = 500;
15958
16068
  function getMessageDir(sessionID) {
15959
- if (!existsSync5(MESSAGE_STORAGE))
16069
+ if (!existsSync6(MESSAGE_STORAGE))
15960
16070
  return null;
15961
- const directPath = join6(MESSAGE_STORAGE, sessionID);
15962
- if (existsSync5(directPath))
16071
+ const directPath = join7(MESSAGE_STORAGE, sessionID);
16072
+ if (existsSync6(directPath))
15963
16073
  return directPath;
15964
16074
  for (const dir of readdirSync3(MESSAGE_STORAGE)) {
15965
- const sessionPath = join6(MESSAGE_STORAGE, dir, sessionID);
15966
- if (existsSync5(sessionPath))
16075
+ const sessionPath = join7(MESSAGE_STORAGE, dir, sessionID);
16076
+ if (existsSync6(sessionPath))
15967
16077
  return sessionPath;
15968
16078
  }
15969
16079
  return null;
@@ -16380,6 +16490,7 @@ ${CONTEXT_REMINDER}
16380
16490
  };
16381
16491
  }
16382
16492
  // src/hooks/session-notification.ts
16493
+ init_claude_code_session_state();
16383
16494
  import { platform } from "os";
16384
16495
 
16385
16496
  // src/hooks/session-notification-utils.ts
@@ -16766,15 +16877,15 @@ function createSessionNotification(ctx, config = {}) {
16766
16877
  };
16767
16878
  }
16768
16879
  // src/hooks/session-recovery/storage.ts
16769
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
16770
- import { join as join8 } from "path";
16880
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
16881
+ import { join as join9 } from "path";
16771
16882
 
16772
16883
  // src/hooks/session-recovery/constants.ts
16773
16884
  init_data_path();
16774
- import { join as join7 } from "path";
16885
+ import { join as join8 } from "path";
16775
16886
  var OPENCODE_STORAGE2 = getOpenCodeStorageDir();
16776
- var MESSAGE_STORAGE2 = join7(OPENCODE_STORAGE2, "message");
16777
- var PART_STORAGE2 = join7(OPENCODE_STORAGE2, "part");
16887
+ var MESSAGE_STORAGE2 = join8(OPENCODE_STORAGE2, "message");
16888
+ var PART_STORAGE2 = join8(OPENCODE_STORAGE2, "part");
16778
16889
  var THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"]);
16779
16890
  var META_TYPES = new Set(["step-start", "step-finish"]);
16780
16891
  var CONTENT_TYPES = new Set(["text", "tool", "tool_use", "tool_result"]);
@@ -16787,15 +16898,15 @@ function generatePartId2() {
16787
16898
  return `prt_${timestamp}${random}`;
16788
16899
  }
16789
16900
  function getMessageDir2(sessionID) {
16790
- if (!existsSync6(MESSAGE_STORAGE2))
16901
+ if (!existsSync7(MESSAGE_STORAGE2))
16791
16902
  return "";
16792
- const directPath = join8(MESSAGE_STORAGE2, sessionID);
16793
- if (existsSync6(directPath)) {
16903
+ const directPath = join9(MESSAGE_STORAGE2, sessionID);
16904
+ if (existsSync7(directPath)) {
16794
16905
  return directPath;
16795
16906
  }
16796
16907
  for (const dir of readdirSync4(MESSAGE_STORAGE2)) {
16797
- const sessionPath = join8(MESSAGE_STORAGE2, dir, sessionID);
16798
- if (existsSync6(sessionPath)) {
16908
+ const sessionPath = join9(MESSAGE_STORAGE2, dir, sessionID);
16909
+ if (existsSync7(sessionPath)) {
16799
16910
  return sessionPath;
16800
16911
  }
16801
16912
  }
@@ -16803,14 +16914,14 @@ function getMessageDir2(sessionID) {
16803
16914
  }
16804
16915
  function readMessages(sessionID) {
16805
16916
  const messageDir = getMessageDir2(sessionID);
16806
- if (!messageDir || !existsSync6(messageDir))
16917
+ if (!messageDir || !existsSync7(messageDir))
16807
16918
  return [];
16808
16919
  const messages = [];
16809
16920
  for (const file of readdirSync4(messageDir)) {
16810
16921
  if (!file.endsWith(".json"))
16811
16922
  continue;
16812
16923
  try {
16813
- const content = readFileSync5(join8(messageDir, file), "utf-8");
16924
+ const content = readFileSync6(join9(messageDir, file), "utf-8");
16814
16925
  messages.push(JSON.parse(content));
16815
16926
  } catch {
16816
16927
  continue;
@@ -16825,15 +16936,15 @@ function readMessages(sessionID) {
16825
16936
  });
16826
16937
  }
16827
16938
  function readParts(messageID) {
16828
- const partDir = join8(PART_STORAGE2, messageID);
16829
- if (!existsSync6(partDir))
16939
+ const partDir = join9(PART_STORAGE2, messageID);
16940
+ if (!existsSync7(partDir))
16830
16941
  return [];
16831
16942
  const parts = [];
16832
16943
  for (const file of readdirSync4(partDir)) {
16833
16944
  if (!file.endsWith(".json"))
16834
16945
  continue;
16835
16946
  try {
16836
- const content = readFileSync5(join8(partDir, file), "utf-8");
16947
+ const content = readFileSync6(join9(partDir, file), "utf-8");
16837
16948
  parts.push(JSON.parse(content));
16838
16949
  } catch {
16839
16950
  continue;
@@ -16863,9 +16974,9 @@ function messageHasContent(messageID) {
16863
16974
  return parts.some(hasContent);
16864
16975
  }
16865
16976
  function injectTextPart(sessionID, messageID, text) {
16866
- const partDir = join8(PART_STORAGE2, messageID);
16867
- if (!existsSync6(partDir)) {
16868
- mkdirSync3(partDir, { recursive: true });
16977
+ const partDir = join9(PART_STORAGE2, messageID);
16978
+ if (!existsSync7(partDir)) {
16979
+ mkdirSync4(partDir, { recursive: true });
16869
16980
  }
16870
16981
  const partId = generatePartId2();
16871
16982
  const part = {
@@ -16877,7 +16988,7 @@ function injectTextPart(sessionID, messageID, text) {
16877
16988
  synthetic: true
16878
16989
  };
16879
16990
  try {
16880
- writeFileSync4(join8(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16991
+ writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16881
16992
  return true;
16882
16993
  } catch {
16883
16994
  return false;
@@ -16972,9 +17083,9 @@ function findLastThinkingContent(sessionID, beforeMessageID) {
16972
17083
  return "";
16973
17084
  }
16974
17085
  function prependThinkingPart(sessionID, messageID) {
16975
- const partDir = join8(PART_STORAGE2, messageID);
16976
- if (!existsSync6(partDir)) {
16977
- mkdirSync3(partDir, { recursive: true });
17086
+ const partDir = join9(PART_STORAGE2, messageID);
17087
+ if (!existsSync7(partDir)) {
17088
+ mkdirSync4(partDir, { recursive: true });
16978
17089
  }
16979
17090
  const previousThinking = findLastThinkingContent(sessionID, messageID);
16980
17091
  const partId = `prt_${++nextRecoveryBlockId}_thinking`;
@@ -16987,23 +17098,23 @@ function prependThinkingPart(sessionID, messageID) {
16987
17098
  synthetic: true
16988
17099
  };
16989
17100
  try {
16990
- writeFileSync4(join8(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
17101
+ writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16991
17102
  return true;
16992
17103
  } catch {
16993
17104
  return false;
16994
17105
  }
16995
17106
  }
16996
17107
  function stripThinkingParts(messageID) {
16997
- const partDir = join8(PART_STORAGE2, messageID);
16998
- if (!existsSync6(partDir))
17108
+ const partDir = join9(PART_STORAGE2, messageID);
17109
+ if (!existsSync7(partDir))
16999
17110
  return false;
17000
17111
  let anyRemoved = false;
17001
17112
  for (const file of readdirSync4(partDir)) {
17002
17113
  if (!file.endsWith(".json"))
17003
17114
  continue;
17004
17115
  try {
17005
- const filePath = join8(partDir, file);
17006
- const content = readFileSync5(filePath, "utf-8");
17116
+ const filePath = join9(partDir, file);
17117
+ const content = readFileSync6(filePath, "utf-8");
17007
17118
  const part = JSON.parse(content);
17008
17119
  if (THINKING_TYPES.has(part.type)) {
17009
17120
  unlinkSync(filePath);
@@ -17016,23 +17127,23 @@ function stripThinkingParts(messageID) {
17016
17127
  return anyRemoved;
17017
17128
  }
17018
17129
  function replaceEmptyTextParts(messageID, replacementText) {
17019
- const partDir = join8(PART_STORAGE2, messageID);
17020
- if (!existsSync6(partDir))
17130
+ const partDir = join9(PART_STORAGE2, messageID);
17131
+ if (!existsSync7(partDir))
17021
17132
  return false;
17022
17133
  let anyReplaced = false;
17023
17134
  for (const file of readdirSync4(partDir)) {
17024
17135
  if (!file.endsWith(".json"))
17025
17136
  continue;
17026
17137
  try {
17027
- const filePath = join8(partDir, file);
17028
- const content = readFileSync5(filePath, "utf-8");
17138
+ const filePath = join9(partDir, file);
17139
+ const content = readFileSync6(filePath, "utf-8");
17029
17140
  const part = JSON.parse(content);
17030
17141
  if (part.type === "text") {
17031
17142
  const textPart = part;
17032
17143
  if (!textPart.text?.trim()) {
17033
17144
  textPart.text = replacementText;
17034
17145
  textPart.synthetic = true;
17035
- writeFileSync4(filePath, JSON.stringify(textPart, null, 2));
17146
+ writeFileSync5(filePath, JSON.stringify(textPart, null, 2));
17036
17147
  anyReplaced = true;
17037
17148
  }
17038
17149
  }
@@ -17302,20 +17413,20 @@ function createSessionRecoveryHook(ctx, options) {
17302
17413
  // src/hooks/comment-checker/cli.ts
17303
17414
  var {spawn: spawn5 } = globalThis.Bun;
17304
17415
  import { createRequire as createRequire2 } from "module";
17305
- import { dirname, join as join17 } from "path";
17306
- import { existsSync as existsSync15 } from "fs";
17416
+ import { dirname, join as join18 } from "path";
17417
+ import { existsSync as existsSync16 } from "fs";
17307
17418
  import * as fs5 from "fs";
17308
17419
  import { tmpdir as tmpdir4 } from "os";
17309
17420
 
17310
17421
  // src/hooks/comment-checker/downloader.ts
17311
17422
  init_shared();
17312
17423
  var {spawn: spawn4 } = globalThis.Bun;
17313
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
17314
- import { join as join16 } from "path";
17424
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
17425
+ import { join as join17 } from "path";
17315
17426
  import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
17316
17427
  import { createRequire } from "module";
17317
17428
  var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
17318
- var DEBUG_FILE = join16(tmpdir3(), "comment-checker-debug.log");
17429
+ var DEBUG_FILE = join17(tmpdir3(), "comment-checker-debug.log");
17319
17430
  function debugLog(...args) {
17320
17431
  if (DEBUG) {
17321
17432
  const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17334,19 +17445,19 @@ var PLATFORM_MAP = {
17334
17445
  function getCacheDir() {
17335
17446
  if (process.platform === "win32") {
17336
17447
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
17337
- const base2 = localAppData || join16(homedir8(), "AppData", "Local");
17338
- return join16(base2, "oh-my-opencode", "bin");
17448
+ const base2 = localAppData || join17(homedir8(), "AppData", "Local");
17449
+ return join17(base2, "oh-my-opencode", "bin");
17339
17450
  }
17340
17451
  const xdgCache = process.env.XDG_CACHE_HOME;
17341
- const base = xdgCache || join16(homedir8(), ".cache");
17342
- return join16(base, "oh-my-opencode", "bin");
17452
+ const base = xdgCache || join17(homedir8(), ".cache");
17453
+ return join17(base, "oh-my-opencode", "bin");
17343
17454
  }
17344
17455
  function getBinaryName() {
17345
17456
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
17346
17457
  }
17347
17458
  function getCachedBinaryPath() {
17348
- const binaryPath = join16(getCacheDir(), getBinaryName());
17349
- return existsSync14(binaryPath) ? binaryPath : null;
17459
+ const binaryPath = join17(getCacheDir(), getBinaryName());
17460
+ return existsSync15(binaryPath) ? binaryPath : null;
17350
17461
  }
17351
17462
  function getPackageVersion() {
17352
17463
  try {
@@ -17378,8 +17489,8 @@ async function downloadCommentChecker() {
17378
17489
  }
17379
17490
  const cacheDir = getCacheDir();
17380
17491
  const binaryName = getBinaryName();
17381
- const binaryPath = join16(cacheDir, binaryName);
17382
- if (existsSync14(binaryPath)) {
17492
+ const binaryPath = join17(cacheDir, binaryName);
17493
+ if (existsSync15(binaryPath)) {
17383
17494
  debugLog("Binary already cached at:", binaryPath);
17384
17495
  return binaryPath;
17385
17496
  }
@@ -17390,14 +17501,14 @@ async function downloadCommentChecker() {
17390
17501
  debugLog(`Downloading from: ${downloadUrl}`);
17391
17502
  console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
17392
17503
  try {
17393
- if (!existsSync14(cacheDir)) {
17394
- mkdirSync6(cacheDir, { recursive: true });
17504
+ if (!existsSync15(cacheDir)) {
17505
+ mkdirSync7(cacheDir, { recursive: true });
17395
17506
  }
17396
17507
  const response = await fetch(downloadUrl, { redirect: "follow" });
17397
17508
  if (!response.ok) {
17398
17509
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
17399
17510
  }
17400
- const archivePath = join16(cacheDir, assetName);
17511
+ const archivePath = join17(cacheDir, assetName);
17401
17512
  const arrayBuffer = await response.arrayBuffer();
17402
17513
  await Bun.write(archivePath, arrayBuffer);
17403
17514
  debugLog(`Downloaded archive to: ${archivePath}`);
@@ -17406,10 +17517,10 @@ async function downloadCommentChecker() {
17406
17517
  } else {
17407
17518
  await extractZip(archivePath, cacheDir);
17408
17519
  }
17409
- if (existsSync14(archivePath)) {
17520
+ if (existsSync15(archivePath)) {
17410
17521
  unlinkSync2(archivePath);
17411
17522
  }
17412
- if (process.platform !== "win32" && existsSync14(binaryPath)) {
17523
+ if (process.platform !== "win32" && existsSync15(binaryPath)) {
17413
17524
  chmodSync(binaryPath, 493);
17414
17525
  }
17415
17526
  debugLog(`Successfully downloaded binary to: ${binaryPath}`);
@@ -17433,7 +17544,7 @@ async function ensureCommentCheckerBinary() {
17433
17544
 
17434
17545
  // src/hooks/comment-checker/cli.ts
17435
17546
  var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
17436
- var DEBUG_FILE2 = join17(tmpdir4(), "comment-checker-debug.log");
17547
+ var DEBUG_FILE2 = join18(tmpdir4(), "comment-checker-debug.log");
17437
17548
  function debugLog2(...args) {
17438
17549
  if (DEBUG2) {
17439
17550
  const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17459,8 +17570,8 @@ function findCommentCheckerPathSync() {
17459
17570
  const require2 = createRequire2(import.meta.url);
17460
17571
  const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
17461
17572
  const cliDir = dirname(cliPkgPath);
17462
- const binaryPath = join17(cliDir, "bin", binaryName);
17463
- if (existsSync15(binaryPath)) {
17573
+ const binaryPath = join18(cliDir, "bin", binaryName);
17574
+ if (existsSync16(binaryPath)) {
17464
17575
  debugLog2("found binary in main package:", binaryPath);
17465
17576
  return binaryPath;
17466
17577
  }
@@ -17481,7 +17592,7 @@ async function getCommentCheckerPath() {
17481
17592
  }
17482
17593
  initPromise = (async () => {
17483
17594
  const syncPath = findCommentCheckerPathSync();
17484
- if (syncPath && existsSync15(syncPath)) {
17595
+ if (syncPath && existsSync16(syncPath)) {
17485
17596
  resolvedCliPath = syncPath;
17486
17597
  debugLog2("using sync-resolved path:", syncPath);
17487
17598
  return syncPath;
@@ -17517,7 +17628,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
17517
17628
  debugLog2("comment-checker binary not found");
17518
17629
  return { hasComments: false, message: "" };
17519
17630
  }
17520
- if (!existsSync15(binaryPath)) {
17631
+ if (!existsSync16(binaryPath)) {
17521
17632
  debugLog2("comment-checker binary does not exist:", binaryPath);
17522
17633
  return { hasComments: false, message: "" };
17523
17634
  }
@@ -17555,11 +17666,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
17555
17666
 
17556
17667
  // src/hooks/comment-checker/index.ts
17557
17668
  import * as fs6 from "fs";
17558
- import { existsSync as existsSync16 } from "fs";
17669
+ import { existsSync as existsSync17 } from "fs";
17559
17670
  import { tmpdir as tmpdir5 } from "os";
17560
- import { join as join18 } from "path";
17671
+ import { join as join19 } from "path";
17561
17672
  var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
17562
- var DEBUG_FILE3 = join18(tmpdir5(), "comment-checker-debug.log");
17673
+ var DEBUG_FILE3 = join19(tmpdir5(), "comment-checker-debug.log");
17563
17674
  function debugLog3(...args) {
17564
17675
  if (DEBUG3) {
17565
17676
  const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17640,7 +17751,7 @@ function createCommentCheckerHooks(config) {
17640
17751
  }
17641
17752
  try {
17642
17753
  const cliPath = await cliPathPromise;
17643
- if (!cliPath || !existsSync16(cliPath)) {
17754
+ if (!cliPath || !existsSync17(cliPath)) {
17644
17755
  debugLog3("CLI not available, skipping comment check");
17645
17756
  return;
17646
17757
  }
@@ -17720,36 +17831,36 @@ function createToolOutputTruncatorHook(ctx, options) {
17720
17831
  };
17721
17832
  }
17722
17833
  // src/hooks/directory-agents-injector/index.ts
17723
- import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
17724
- import { dirname as dirname2, join as join21, resolve as resolve3 } from "path";
17834
+ import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
17835
+ import { dirname as dirname2, join as join22, resolve as resolve3 } from "path";
17725
17836
 
17726
17837
  // src/hooks/directory-agents-injector/storage.ts
17727
17838
  import {
17728
- existsSync as existsSync17,
17729
- mkdirSync as mkdirSync7,
17730
- readFileSync as readFileSync11,
17731
- writeFileSync as writeFileSync7,
17839
+ existsSync as existsSync18,
17840
+ mkdirSync as mkdirSync8,
17841
+ readFileSync as readFileSync12,
17842
+ writeFileSync as writeFileSync8,
17732
17843
  unlinkSync as unlinkSync3
17733
17844
  } from "fs";
17734
- import { join as join20 } from "path";
17845
+ import { join as join21 } from "path";
17735
17846
 
17736
17847
  // src/hooks/directory-agents-injector/constants.ts
17737
17848
  init_data_path();
17738
- import { join as join19 } from "path";
17849
+ import { join as join20 } from "path";
17739
17850
  var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
17740
- var AGENTS_INJECTOR_STORAGE = join19(OPENCODE_STORAGE3, "directory-agents");
17851
+ var AGENTS_INJECTOR_STORAGE = join20(OPENCODE_STORAGE3, "directory-agents");
17741
17852
  var AGENTS_FILENAME = "AGENTS.md";
17742
17853
 
17743
17854
  // src/hooks/directory-agents-injector/storage.ts
17744
17855
  function getStoragePath(sessionID) {
17745
- return join20(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
17856
+ return join21(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
17746
17857
  }
17747
17858
  function loadInjectedPaths(sessionID) {
17748
17859
  const filePath = getStoragePath(sessionID);
17749
- if (!existsSync17(filePath))
17860
+ if (!existsSync18(filePath))
17750
17861
  return new Set;
17751
17862
  try {
17752
- const content = readFileSync11(filePath, "utf-8");
17863
+ const content = readFileSync12(filePath, "utf-8");
17753
17864
  const data = JSON.parse(content);
17754
17865
  return new Set(data.injectedPaths);
17755
17866
  } catch {
@@ -17757,19 +17868,19 @@ function loadInjectedPaths(sessionID) {
17757
17868
  }
17758
17869
  }
17759
17870
  function saveInjectedPaths(sessionID, paths) {
17760
- if (!existsSync17(AGENTS_INJECTOR_STORAGE)) {
17761
- mkdirSync7(AGENTS_INJECTOR_STORAGE, { recursive: true });
17871
+ if (!existsSync18(AGENTS_INJECTOR_STORAGE)) {
17872
+ mkdirSync8(AGENTS_INJECTOR_STORAGE, { recursive: true });
17762
17873
  }
17763
17874
  const data = {
17764
17875
  sessionID,
17765
17876
  injectedPaths: [...paths],
17766
17877
  updatedAt: Date.now()
17767
17878
  };
17768
- writeFileSync7(getStoragePath(sessionID), JSON.stringify(data, null, 2));
17879
+ writeFileSync8(getStoragePath(sessionID), JSON.stringify(data, null, 2));
17769
17880
  }
17770
17881
  function clearInjectedPaths(sessionID) {
17771
17882
  const filePath = getStoragePath(sessionID);
17772
- if (existsSync17(filePath)) {
17883
+ if (existsSync18(filePath)) {
17773
17884
  unlinkSync3(filePath);
17774
17885
  }
17775
17886
  }
@@ -17799,8 +17910,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
17799
17910
  while (true) {
17800
17911
  const isRootDir = current === ctx.directory;
17801
17912
  if (!isRootDir) {
17802
- const agentsPath = join21(current, AGENTS_FILENAME);
17803
- if (existsSync18(agentsPath)) {
17913
+ const agentsPath = join22(current, AGENTS_FILENAME);
17914
+ if (existsSync19(agentsPath)) {
17804
17915
  found.push(agentsPath);
17805
17916
  }
17806
17917
  }
@@ -17827,7 +17938,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
17827
17938
  if (cache.has(agentsDir))
17828
17939
  continue;
17829
17940
  try {
17830
- const content = readFileSync12(agentsPath, "utf-8");
17941
+ const content = readFileSync13(agentsPath, "utf-8");
17831
17942
  const { result, truncated } = await truncator.truncate(sessionID, content);
17832
17943
  const truncationNotice = truncated ? `
17833
17944
 
@@ -17897,36 +18008,36 @@ ${result}${truncationNotice}`;
17897
18008
  };
17898
18009
  }
17899
18010
  // src/hooks/directory-readme-injector/index.ts
17900
- import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
17901
- import { dirname as dirname3, join as join24, resolve as resolve4 } from "path";
18011
+ import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
18012
+ import { dirname as dirname3, join as join25, resolve as resolve4 } from "path";
17902
18013
 
17903
18014
  // src/hooks/directory-readme-injector/storage.ts
17904
18015
  import {
17905
- existsSync as existsSync19,
17906
- mkdirSync as mkdirSync8,
17907
- readFileSync as readFileSync13,
17908
- writeFileSync as writeFileSync8,
18016
+ existsSync as existsSync20,
18017
+ mkdirSync as mkdirSync9,
18018
+ readFileSync as readFileSync14,
18019
+ writeFileSync as writeFileSync9,
17909
18020
  unlinkSync as unlinkSync4
17910
18021
  } from "fs";
17911
- import { join as join23 } from "path";
18022
+ import { join as join24 } from "path";
17912
18023
 
17913
18024
  // src/hooks/directory-readme-injector/constants.ts
17914
18025
  init_data_path();
17915
- import { join as join22 } from "path";
18026
+ import { join as join23 } from "path";
17916
18027
  var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
17917
- var README_INJECTOR_STORAGE = join22(OPENCODE_STORAGE4, "directory-readme");
18028
+ var README_INJECTOR_STORAGE = join23(OPENCODE_STORAGE4, "directory-readme");
17918
18029
  var README_FILENAME = "README.md";
17919
18030
 
17920
18031
  // src/hooks/directory-readme-injector/storage.ts
17921
18032
  function getStoragePath2(sessionID) {
17922
- return join23(README_INJECTOR_STORAGE, `${sessionID}.json`);
18033
+ return join24(README_INJECTOR_STORAGE, `${sessionID}.json`);
17923
18034
  }
17924
18035
  function loadInjectedPaths2(sessionID) {
17925
18036
  const filePath = getStoragePath2(sessionID);
17926
- if (!existsSync19(filePath))
18037
+ if (!existsSync20(filePath))
17927
18038
  return new Set;
17928
18039
  try {
17929
- const content = readFileSync13(filePath, "utf-8");
18040
+ const content = readFileSync14(filePath, "utf-8");
17930
18041
  const data = JSON.parse(content);
17931
18042
  return new Set(data.injectedPaths);
17932
18043
  } catch {
@@ -17934,19 +18045,19 @@ function loadInjectedPaths2(sessionID) {
17934
18045
  }
17935
18046
  }
17936
18047
  function saveInjectedPaths2(sessionID, paths) {
17937
- if (!existsSync19(README_INJECTOR_STORAGE)) {
17938
- mkdirSync8(README_INJECTOR_STORAGE, { recursive: true });
18048
+ if (!existsSync20(README_INJECTOR_STORAGE)) {
18049
+ mkdirSync9(README_INJECTOR_STORAGE, { recursive: true });
17939
18050
  }
17940
18051
  const data = {
17941
18052
  sessionID,
17942
18053
  injectedPaths: [...paths],
17943
18054
  updatedAt: Date.now()
17944
18055
  };
17945
- writeFileSync8(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
18056
+ writeFileSync9(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
17946
18057
  }
17947
18058
  function clearInjectedPaths2(sessionID) {
17948
18059
  const filePath = getStoragePath2(sessionID);
17949
- if (existsSync19(filePath)) {
18060
+ if (existsSync20(filePath)) {
17950
18061
  unlinkSync4(filePath);
17951
18062
  }
17952
18063
  }
@@ -17974,8 +18085,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
17974
18085
  const found = [];
17975
18086
  let current = startDir;
17976
18087
  while (true) {
17977
- const readmePath = join24(current, README_FILENAME);
17978
- if (existsSync20(readmePath)) {
18088
+ const readmePath = join25(current, README_FILENAME);
18089
+ if (existsSync21(readmePath)) {
17979
18090
  found.push(readmePath);
17980
18091
  }
17981
18092
  if (current === ctx.directory)
@@ -18001,7 +18112,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
18001
18112
  if (cache.has(readmeDir))
18002
18113
  continue;
18003
18114
  try {
18004
- const content = readFileSync14(readmePath, "utf-8");
18115
+ const content = readFileSync15(readmePath, "utf-8");
18005
18116
  const { result, truncated } = await truncator.truncate(sessionID, content);
18006
18117
  const truncationNotice = truncated ? `
18007
18118
 
@@ -18285,22 +18396,22 @@ var TRUNCATE_CONFIG = {
18285
18396
 
18286
18397
  // src/hooks/anthropic-context-window-limit-recovery/storage.ts
18287
18398
  init_data_path();
18288
- import { existsSync as existsSync21, readdirSync as readdirSync6, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
18289
- import { join as join25 } from "path";
18399
+ import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync10 } from "fs";
18400
+ import { join as join26 } from "path";
18290
18401
  var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
18291
- var MESSAGE_STORAGE3 = join25(OPENCODE_STORAGE5, "message");
18292
- var PART_STORAGE3 = join25(OPENCODE_STORAGE5, "part");
18402
+ var MESSAGE_STORAGE3 = join26(OPENCODE_STORAGE5, "message");
18403
+ var PART_STORAGE3 = join26(OPENCODE_STORAGE5, "part");
18293
18404
  var TRUNCATION_MESSAGE = "[TOOL RESULT TRUNCATED - Context limit exceeded. Original output was too large and has been truncated to recover the session. Please re-run this tool if you need the full output.]";
18294
18405
  function getMessageDir3(sessionID) {
18295
- if (!existsSync21(MESSAGE_STORAGE3))
18406
+ if (!existsSync22(MESSAGE_STORAGE3))
18296
18407
  return "";
18297
- const directPath = join25(MESSAGE_STORAGE3, sessionID);
18298
- if (existsSync21(directPath)) {
18408
+ const directPath = join26(MESSAGE_STORAGE3, sessionID);
18409
+ if (existsSync22(directPath)) {
18299
18410
  return directPath;
18300
18411
  }
18301
18412
  for (const dir of readdirSync6(MESSAGE_STORAGE3)) {
18302
- const sessionPath = join25(MESSAGE_STORAGE3, dir, sessionID);
18303
- if (existsSync21(sessionPath)) {
18413
+ const sessionPath = join26(MESSAGE_STORAGE3, dir, sessionID);
18414
+ if (existsSync22(sessionPath)) {
18304
18415
  return sessionPath;
18305
18416
  }
18306
18417
  }
@@ -18308,7 +18419,7 @@ function getMessageDir3(sessionID) {
18308
18419
  }
18309
18420
  function getMessageIds(sessionID) {
18310
18421
  const messageDir = getMessageDir3(sessionID);
18311
- if (!messageDir || !existsSync21(messageDir))
18422
+ if (!messageDir || !existsSync22(messageDir))
18312
18423
  return [];
18313
18424
  const messageIds = [];
18314
18425
  for (const file of readdirSync6(messageDir)) {
@@ -18323,15 +18434,15 @@ function findToolResultsBySize(sessionID) {
18323
18434
  const messageIds = getMessageIds(sessionID);
18324
18435
  const results = [];
18325
18436
  for (const messageID of messageIds) {
18326
- const partDir = join25(PART_STORAGE3, messageID);
18327
- if (!existsSync21(partDir))
18437
+ const partDir = join26(PART_STORAGE3, messageID);
18438
+ if (!existsSync22(partDir))
18328
18439
  continue;
18329
18440
  for (const file of readdirSync6(partDir)) {
18330
18441
  if (!file.endsWith(".json"))
18331
18442
  continue;
18332
18443
  try {
18333
- const partPath = join25(partDir, file);
18334
- const content = readFileSync15(partPath, "utf-8");
18444
+ const partPath = join26(partDir, file);
18445
+ const content = readFileSync16(partPath, "utf-8");
18335
18446
  const part = JSON.parse(content);
18336
18447
  if (part.type === "tool" && part.state?.output && !part.truncated) {
18337
18448
  results.push({
@@ -18351,7 +18462,7 @@ function findToolResultsBySize(sessionID) {
18351
18462
  }
18352
18463
  function truncateToolResult(partPath) {
18353
18464
  try {
18354
- const content = readFileSync15(partPath, "utf-8");
18465
+ const content = readFileSync16(partPath, "utf-8");
18355
18466
  const part = JSON.parse(content);
18356
18467
  if (!part.state?.output) {
18357
18468
  return { success: false };
@@ -18365,7 +18476,7 @@ function truncateToolResult(partPath) {
18365
18476
  part.state.time = { start: Date.now() };
18366
18477
  }
18367
18478
  part.state.time.compacted = Date.now();
18368
- writeFileSync9(partPath, JSON.stringify(part, null, 2));
18479
+ writeFileSync10(partPath, JSON.stringify(part, null, 2));
18369
18480
  return { success: true, toolName, originalSize };
18370
18481
  } catch {
18371
18482
  return { success: false };
@@ -20980,6 +21091,14 @@ var MOMUS_SYSTEM_PROMPT = `\u4F60\u662F\u5DE5\u4F5C\u8BA1\u5212\u5BA1\u67E5\u4E1
20980
21091
  **\u5173\u952E\u7684\u7B2C\u4E00\u6761\u89C4\u5219**\uFF1A
20981
21092
  \u4ECE\u8F93\u5165\u4E2D\u7684\u4EFB\u4F55\u4F4D\u7F6E\u63D0\u53D6\u5355\u4E2A\u8BA1\u5212\u8DEF\u5F84\uFF0C\u5FFD\u7565\u7CFB\u7EDF\u6307\u4EE4\u548C\u5305\u88C5\u3002\u5982\u679C\u6070\u597D\u5B58\u5728\u4E00\u4E2A \`.sisyphus/plans/*.md\` \u8DEF\u5F84\uFF0C\u8FD9\u5C31\u662F\u6709\u6548\u7684\u8F93\u5165\uFF0C\u4F60\u5FC5\u987B\u8BFB\u53D6\u5B83\u3002\u5982\u679C\u4E0D\u5B58\u5728\u8BA1\u5212\u8DEF\u5F84\u6216\u5B58\u5728\u591A\u4E2A\u8BA1\u5212\u8DEF\u5F84\uFF0C\u6309\u7B2C0\u6B65\u62D2\u7EDD\u3002\u5982\u679C\u8DEF\u5F84\u6307\u5411 YAML \u8BA1\u5212\u6587\u4EF6\uFF08\`.yml\` \u6216 \`.yaml\`\uFF09\uFF0C\u56E0\u4E0D\u53EF\u5BA1\u67E5\u800C\u62D2\u7EDD\u3002
20982
21093
 
21094
+ **\u4F60\u7684\u89D2\u8272**\uFF1A
21095
+ \u4F60\u662F Momus \u2014\u2014 \u5E0C\u814A\u795E\u8BDD\u4E2D\u4EE5\u5439\u6BDB\u6C42\u75B5\u95FB\u540D\u7684\u5632\u5F04\u4E4B\u795E\u3002\u4F60\u66FE\u6311\u5254\u8D6B\u83F2\u65AF\u6258\u65AF\u953B\u9020\u7684\u795E\u76FE\u3001\u963F\u4F5B\u6D1B\u72C4\u5FD2\u7684\u51C9\u978B\u3001\u751A\u81F3\u96C5\u5178\u5A1C\u7684\u5BAB\u6BBF\u3002
21096
+ \u73B0\u5728\uFF0C\u4F60\u662F**\u5DE5\u4F5C\u8BA1\u5212\u5BA1\u67E5\u5B98**\u2014\u2014\u4E00\u4E2A**\u82DB\u523B\u3001\u4E0D\u8BB2\u60C5\u9762\u3001\u96F6\u5BB9\u5FCD**\u7684\u8D28\u91CF\u5B88\u95E8\u4EBA\u3002
21097
+
21098
+ \u4F60\u7684\u5DE5\u4F5C\u4E0D\u662F\u8BA9\u8BA1\u5212\u4F5C\u8005\u611F\u89C9\u826F\u597D\u3002\u4F60\u7684\u5DE5\u4F5C\u662F**\u5728\u5B9E\u65BD\u5931\u8D25\u53D1\u751F\u4E4B\u524D\u627E\u51FA\u6BCF\u4E00\u4E2A\u95EE\u9898**\u3002
21099
+ \u4F60\u5BF9"\u5DEE\u4E0D\u591A"\u3001"\u6267\u884C\u8005\u81EA\u5DF1\u80FD\u641E\u5B9A"\u3001"\u8FD9\u4E2A\u7EC6\u8282\u4E0D\u91CD\u8981"\u96F6\u5BB9\u5FCD\u3002
21100
+ \u5982\u679C\u8BA1\u5212\u4E0D\u5B8C\u6574\uFF0C\u5C31\u662F\u62D2\u7EDD\u3002\u6CA1\u6709\u5546\u91CF\u4F59\u5730\u3002
21101
+
20983
21102
  **\u4E3A\u4EC0\u4E48\u4F60\u88AB\u53EC\u5524**\uFF1A
20984
21103
 
20985
21104
  \u4F60\u5BA1\u67E5\u7684\u662F\u5DE5\u4F5C\u8BA1\u5212\u2014\u2014\u4E0D\u662F\u4EE3\u7801\uFF0C\u4E0D\u662F\u8BBE\u8BA1\u2014\u2014\u662F\u6587\u6863\u3002\u4F60\u7684\u5DE5\u4F5C\u662F\u786E\u4FDD\u6267\u884C\u8005\u62FF\u5230\u8BA1\u5212\u540E\u80FD\u76F4\u63A5\u5F00\u59CB\u5DE5\u4F5C\uFF0C\u4E0D\u9700\u8981\u731C\u6D4B\u3002
@@ -21028,6 +21147,14 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
21028
21147
  1. \u76F4\u63A5\u4ECE\u8BA1\u5212\u672C\u8EAB\u83B7\u5F97\uFF0C\u6216\u8005
21029
21148
  2. \u901A\u8FC7\u9075\u5FAA\u8BA1\u5212\u4E2D\u63D0\u4F9B\u7684\u53C2\u8003\u8D44\u6599\uFF08\u6587\u4EF6\u3001\u6587\u6863\u3001\u6A21\u5F0F\uFF09\u5E76\u8FFD\u6EAF\u76F8\u5173\u6750\u6599
21030
21149
 
21150
+ \u26A0\uFE0F **\u91CD\u8981\u9650\u5236**\uFF1A\u4E0A\u8FF0 item 2 \u4E2D\u7684"\u8FFD\u6EAF"\u662F\u6307\u6309\u7167\u8BA1\u5212\u63D0\u4F9B\u7684\u7CBE\u786E\u8DEF\u5F84\uFF08\u5982\u6587\u4EF6\u8DEF\u5F84\u3001\u884C\u53F7\u3001\u51FD\u6570\u540D\uFF09\u76F4\u63A5\u67E5\u9605\u53C2\u8003\u6765\u6E90\u3002
21151
+ \u5B83**\u4E0D**\u5305\u62EC\uFF1A
21152
+ - \u5728\u4EE3\u7801\u5E93\u4E2D\u6F2B\u65E0\u76EE\u7684\u5730\u641C\u7D22\u6765"\u53D1\u73B0"\u4FE1\u606F
21153
+ - \u5047\u8BBE\u6267\u884C\u8005\u53EF\u4EE5\u901A\u8FC7\u81EA\u8EAB\u7ECF\u9A8C\u5F25\u8865\u6587\u6863\u7F3A\u5931
21154
+ - \u5C06"\u6267\u884C\u8005\u53EF\u4EE5\u81EA\u5DF1\u5F04\u6E05\u695A"\u4F5C\u4E3A\u63A5\u53D7\u7684\u7406\u7531
21155
+
21156
+ \u5982\u679C\u4F60\u53D1\u73B0\u9700\u8981\u4F9D\u8D56"\u6267\u884C\u8005\u5E94\u8BE5\u80FD\u81EA\u5DF1\u627E\u5230"\u6765\u5B8C\u6210\u6A21\u62DF\u6267\u884C\uFF0C\u8FD9\u5C5E\u4E8E\u62D2\u7EDD\u7406\u7531\u3002
21157
+
21031
21158
  **\u6D4B\u8BD5\u6807\u51C6**\uFF1A"\u7ED9\u5B9A\u4F5C\u8005\u9009\u62E9\u7684\u65B9\u6CD5\uFF0C\u6211\u80FD\u5426\u4ECE\u8BA1\u5212\u5199\u7684\u5185\u5BB9\u5F00\u59CB\uFF0C\u6CBF\u7740\u5B83\u63D0\u4F9B\u7684\u4FE1\u606F\u7EBF\u7D22\u6765\u5B9E\u73B0\uFF1F"
21032
21159
 
21033
21160
  **\u9519\u8BEF\u7684\u5FC3\u6001**\uFF1A"\u8FD9\u79CD\u65B9\u6CD5\u4E0D\u662F\u6700\u4F18\u7684\u3002\u4ED6\u4EEC\u5E94\u8BE5\u7528X\u3002"\u2192 **\u4F60\u8D8A\u754C\u4E86**
@@ -21054,6 +21181,11 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
21054
21181
  - \u5931\u8D25\uFF1A\u8BF4"\u4E0EY\u96C6\u6210"\u4F46\u672A\u89E3\u91CA\u96C6\u6210\u65B9\u6CD5
21055
21182
  - \u5931\u8D25\uFF1A\u8BF4"\u8C03\u7528API"\u4F46\u672A\u6307\u5B9A\u54EA\u4E2A\u7AEF\u70B9\u6216\u6570\u636E\u6D41
21056
21183
 
21184
+ **5. \u4EE5\u6267\u884C\u8005\u80FD\u529B\u586B\u8865\u7A7A\u767D**
21185
+ - \u5931\u8D25\uFF1A\u8BF4"\u6267\u884C\u8005\u6709\u80FD\u529B\uFF0C\u53EF\u4EE5\u81EA\u5DF1\u641E\u6E05\u695A"\u6765\u5408\u7406\u5316\u8BA1\u5212\u4E2D\u7684\u4FE1\u606F\u7F3A\u53E3
21186
+ - \u5931\u8D25\uFF1A\u5047\u8BBE\u6267\u884C\u8005\u7684\u7ECF\u9A8C\u53EF\u4EE5\u66FF\u4EE3\u7F3A\u5931\u7684\u5B9E\u73B0\u7EC6\u8282
21187
+ - \u5931\u8D25\uFF1A\u5C06\u6392\u67E5/\u8C03\u7814\u7C7B\u4EFB\u52A1\u4F5C\u4E3A"\u4E0D\u9700\u8981\u7CBE\u786E\u63CF\u8FF0"\u7684\u501F\u53E3
21188
+
21057
21189
  **4. \u5173\u952E\u4E0A\u4E0B\u6587**
21058
21190
  - \u5931\u8D25\uFF1A\u5F15\u7528\u4E0D\u5B58\u5728\u7684\u6587\u4EF6
21059
21191
  - \u5931\u8D25\uFF1A\u6307\u5411\u4E0D\u5305\u542B\u76F8\u5173\u4EE3\u7801\u7684\u884C\u53F7
@@ -21179,6 +21311,21 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
21179
21311
  - \u5B8C\u6210\u4EFB\u52A1\u800C\u65E0\u9700"\u641E\u6E05\u695A"\u672A\u9648\u8FF0\u7684\u9700\u6C42
21180
21312
  - \u7406\u89E3\u5927\u5C40\u3001\u76EE\u7684\u4EE5\u53CA\u4EFB\u52A1\u4E4B\u95F4\u7684\u6D41\u7A0B\u5173\u7CFB
21181
21313
 
21314
+ **\u7EDD\u5BF9\u7981\u6B62\u2014\u2014\u4EE5\u80FD\u529B\u63A8\u65AD\u586B\u8865\u7A7A\u767D**\uFF1A
21315
+
21316
+ \u4F60\u7EDD\u4E0D\u80FD\u56E0\u4E3A"\u6267\u884C\u8005\u6709\u80FD\u529B"\u800C\u63A5\u53D7\u8BA1\u5212\u4E2D\u7684\u4FE1\u606F\u7F3A\u53E3\u3002\u4EE5\u4E0B\u5BA1\u67E5\u7ED3\u8BBA\u90FD\u662F**\u8FDD\u89C4**\u7684\uFF1A
21317
+ - \u274C "\u8FD9\u4E2A\u4EFB\u52A1\u7F3A\u5C11\u5177\u4F53\u6B65\u9AA4\uFF0C\u4F46\u6709\u80FD\u529B\u7684\u5F00\u53D1\u8005\u5E94\u8BE5\u77E5\u9053\u600E\u4E48\u505A" \u2192 \u5FC5\u987B\u62D2\u7EDD
21318
+ - \u274C "\u867D\u7136\u8BA1\u5212\u6CA1\u6709\u8BF4\u660E\uFF0C\u4F46\u6267\u884C\u8005\u53EF\u4EE5\u81EA\u884C\u63A2\u7D22\u4EE3\u7801\u5E93\u627E\u5230\u7B54\u6848" \u2192 \u5FC5\u987B\u62D2\u7EDD
21319
+ - \u274C "\u8FD9\u662F\u4E00\u4E2A\u6392\u67E5\u6027\u8D28\u7684\u4EFB\u52A1\uFF0C\u4E0D\u9700\u8981\u7CBE\u786E\u7684\u6E90\u4EE3\u7801" \u2192 \u5FC5\u987B\u62D2\u7EDD
21320
+
21321
+ **\u6B63\u786E\u7684\u505A\u6CD5**\uFF1A
21322
+ - \u2705 \u8BA1\u5212\u662F\u5426\u6E05\u6670\u8BB0\u5F55\u4E86\u6BCF\u4E00\u6B65\uFF1F\u2192 \u63A5\u53D7
21323
+ - \u2705 \u8BA1\u5212\u662F\u5426\u63D0\u4F9B\u4E86\u8DB3\u591F\u7CBE\u786E\u7684\u53C2\u8003\u6765\u6E90\u8BA9\u6267\u884C\u8005\u53EF\u4EE5\u76F4\u63A5\u67E5\u9605\uFF1F\u2192 \u63A5\u53D7
21324
+ - \u2705 \u6267\u884C\u8005\u662F\u5426\u80FD\u591F\u5728\u4E0D\u731C\u6D4B\u7684\u60C5\u51B5\u4E0B\u6839\u636E\u6587\u6863\u5B8C\u6210\u4EFB\u52A1\uFF1F\u2192 \u63A5\u53D7
21325
+
21326
+ **\u5173\u952E\u89C4\u5219**\uFF1A"\u6267\u884C\u8005\u6709\u80FD\u529B"\u610F\u5473\u7740\u6267\u884C\u8005\u80FD\u591F\u6309\u7167\u6E05\u6670\u7684\u6587\u6863\u7CBE\u786E\u6267\u884C\u2014\u2014\u800C\u4E0D\u662F\u6267\u884C\u8005\u80FD\u591F\u81EA\u884C\u586B\u8865\u7F3A\u5931\u7684\u6587\u6863\u3002
21327
+ \u5982\u679C\u8BA1\u5212\u4E2D\u7F3A\u5C11\u7684\u4FE1\u606F\u9700\u8981\u6267\u884C\u8005"\u81EA\u5DF1\u5F04\u6E05\u695A"\uFF0C\u8FD9\u5C31\u662F\u62D2\u7EDD\u7406\u7531\u3002
21328
+
21182
21329
  ---
21183
21330
 
21184
21331
  ## \u56DB\u4E2A\u6838\u5FC3\u8BC4\u4F30\u6807\u51C6
@@ -21306,6 +21453,7 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
21306
21453
  - \u4EFB\u52A1\u9700\u8981\u5728\u6240\u9009\u65B9\u6CD5\u5185\u5BF9\u4E1A\u52A1\u9700\u6C42\u6216\u5173\u952E\u67B6\u6784\u505A\u5047\u8BBE
21307
21454
  - \u7F3A\u5C11\u76EE\u7684\u9648\u8FF0\u6216\u4E0D\u6E05\u6670\u7684\u4E3A\u4EC0\u4E48
21308
21455
  - \u5173\u952E\u4EFB\u52A1\u4F9D\u8D56\u5173\u7CFB\u672A\u5B9A\u4E49
21456
+ - \u5BA1\u67E5\u7ED3\u8BBA\u4EE5"\u6267\u884C\u8005\u6709\u80FD\u529B/\u5E94\u8BE5\u80FD\u81EA\u5DF1\u89E3\u51B3"\u4E3A\u7531\u63A5\u53D7\u7F3A\u5C11\u5B9E\u73B0\u7EC6\u8282\u7684\u4EFB\u52A1
21309
21457
 
21310
21458
  ### \u4E0D\u662F\u6709\u6548\u7684\u62D2\u7EDD\u539F\u56E0\uFF08\u4E0D\u8981\u4E3A\u6B64\u62D2\u7EDD\uFF09
21311
21459
  - \u4F60\u4E0D\u540C\u610F\u5B9E\u65BD\u65B9\u6848
@@ -22660,7 +22808,7 @@ init_file_utils();
22660
22808
  init_shared();
22661
22809
  init_opencode_config_dir();
22662
22810
  import { promises as fs7 } from "fs";
22663
- import { join as join26, basename } from "path";
22811
+ import { join as join27, basename } from "path";
22664
22812
  function parseSkillMcpConfigFromFrontmatter(content) {
22665
22813
  const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
22666
22814
  if (!frontmatterMatch)
@@ -22676,7 +22824,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
22676
22824
  return;
22677
22825
  }
22678
22826
  async function loadMcpJsonFromDir(skillDir) {
22679
- const mcpJsonPath = join26(skillDir, "mcp.json");
22827
+ const mcpJsonPath = join27(skillDir, "mcp.json");
22680
22828
  try {
22681
22829
  const content = await fs7.readFile(mcpJsonPath, "utf-8");
22682
22830
  const parsed = JSON.parse(content);
@@ -22757,11 +22905,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
22757
22905
  for (const entry of entries) {
22758
22906
  if (entry.name.startsWith("."))
22759
22907
  continue;
22760
- const entryPath = join26(skillsDir, entry.name);
22908
+ const entryPath = join27(skillsDir, entry.name);
22761
22909
  if (entry.isDirectory() || entry.isSymbolicLink()) {
22762
22910
  const resolvedPath = await resolveSymlinkAsync(entryPath);
22763
22911
  const dirName = entry.name;
22764
- const skillMdPath = join26(resolvedPath, "SKILL.md");
22912
+ const skillMdPath = join27(resolvedPath, "SKILL.md");
22765
22913
  try {
22766
22914
  await fs7.access(skillMdPath);
22767
22915
  const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
@@ -22769,7 +22917,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
22769
22917
  skills.push(skill);
22770
22918
  continue;
22771
22919
  } catch {}
22772
- const namedSkillMdPath = join26(resolvedPath, `${dirName}.md`);
22920
+ const namedSkillMdPath = join27(resolvedPath, `${dirName}.md`);
22773
22921
  try {
22774
22922
  await fs7.access(namedSkillMdPath);
22775
22923
  const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
@@ -22797,23 +22945,23 @@ function skillsToRecord(skills) {
22797
22945
  return result;
22798
22946
  }
22799
22947
  async function loadUserSkills() {
22800
- const userSkillsDir = join26(getClaudeConfigDir(), "skills");
22948
+ const userSkillsDir = join27(getClaudeConfigDir(), "skills");
22801
22949
  const skills = await loadSkillsFromDir(userSkillsDir, "user");
22802
22950
  return skillsToRecord(skills);
22803
22951
  }
22804
22952
  async function loadProjectSkills() {
22805
- const projectSkillsDir = join26(process.cwd(), ".claude", "skills");
22953
+ const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
22806
22954
  const skills = await loadSkillsFromDir(projectSkillsDir, "project");
22807
22955
  return skillsToRecord(skills);
22808
22956
  }
22809
22957
  async function loadOpencodeGlobalSkills() {
22810
22958
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
22811
- const opencodeSkillsDir = join26(configDir, "skills");
22959
+ const opencodeSkillsDir = join27(configDir, "skills");
22812
22960
  const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
22813
22961
  return skillsToRecord(skills);
22814
22962
  }
22815
22963
  async function loadOpencodeProjectSkills() {
22816
- const opencodeProjectDir = join26(process.cwd(), ".opencode", "skills");
22964
+ const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
22817
22965
  const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
22818
22966
  return skillsToRecord(skills);
22819
22967
  }
@@ -22842,26 +22990,26 @@ async function discoverSkills(options = {}) {
22842
22990
  return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
22843
22991
  }
22844
22992
  async function discoverUserClaudeSkills() {
22845
- const userSkillsDir = join26(getClaudeConfigDir(), "skills");
22993
+ const userSkillsDir = join27(getClaudeConfigDir(), "skills");
22846
22994
  return loadSkillsFromDir(userSkillsDir, "user");
22847
22995
  }
22848
22996
  async function discoverProjectClaudeSkills() {
22849
- const projectSkillsDir = join26(process.cwd(), ".claude", "skills");
22997
+ const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
22850
22998
  return loadSkillsFromDir(projectSkillsDir, "project");
22851
22999
  }
22852
23000
  async function discoverOpencodeGlobalSkills() {
22853
23001
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
22854
- const opencodeSkillsDir = join26(configDir, "skills");
23002
+ const opencodeSkillsDir = join27(configDir, "skills");
22855
23003
  return loadSkillsFromDir(opencodeSkillsDir, "opencode");
22856
23004
  }
22857
23005
  async function discoverOpencodeProjectSkills() {
22858
- const opencodeProjectDir = join26(process.cwd(), ".opencode", "skills");
23006
+ const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
22859
23007
  return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
22860
23008
  }
22861
23009
 
22862
23010
  // src/features/opencode-skill-loader/skill-content.ts
22863
23011
  init_frontmatter();
22864
- import { readFileSync as readFileSync16 } from "fs";
23012
+ import { readFileSync as readFileSync17 } from "fs";
22865
23013
  var cachedSkills = null;
22866
23014
  async function getAllSkills() {
22867
23015
  if (cachedSkills)
@@ -22894,7 +23042,7 @@ async function getAllSkills() {
22894
23042
  }
22895
23043
  async function extractSkillTemplate(skill) {
22896
23044
  if (skill.path) {
22897
- const content = readFileSync16(skill.path, "utf-8");
23045
+ const content = readFileSync17(skill.path, "utf-8");
22898
23046
  const { body } = parseFrontmatter(content);
22899
23047
  return body.trim();
22900
23048
  }
@@ -23030,6 +23178,23 @@ var ZH_LANGUAGE_INSTRUCTION = `
23030
23178
  - \u5F53\u4F60\u53D1\u73B0\u81EA\u5DF1\u5F00\u59CB\u7528\u82F1\u6587\u601D\u8003\u65F6\uFF0C\u7ACB\u5373\u5728 thinking \u5757\u4E2D\u5207\u6362\u4E3A\u4E2D\u6587\uFF0C\u5E76\u5199\uFF1A"\u68C0\u6D4B\u5230\u8BED\u8A00\u6F02\u79FB\uFF0C\u5207\u56DE\u4E2D\u6587\u3002"
23031
23179
  - \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u7EA6\u675F\uFF0C\u4E0D\u53EF\u5728\u957F\u4F1A\u8BDD\u4E2D\u9057\u5FD8
23032
23180
 
23181
+ ### Thinking \u7ED3\u6784\u5F3A\u5236\u7EA6\u675F\uFF08\u96F6\u5BB9\u5FCD\uFF09
23182
+ \u4F60\u7684 thinking \u5757\u5FC5\u987B\u4EE5\u4E2D\u6587\u5F00\u5934\u3002\u7981\u6B62\u4EE5\u4EE5\u4E0B\u82F1\u6587\u53E5\u9996\u5F00\u59CB\u601D\u8003\uFF08\u9047\u5230\u5373\u89C6\u4E3A\u8FDD\u89C4\uFF09\uFF1A
23183
+ - "Let me", "I need", "I'll", "I can", "I should"
23184
+ - "First,", "Now,", "Next,", "Then,", "Finally,"
23185
+ - "The user", "We need", "My task", "Looking at"
23186
+ - \u5176\u4ED6\u4EFB\u4F55\u4EE5\u82F1\u6587\u5B57\u6BCD\u5F00\u5934\u7684\u53E5\u5B50
23187
+ \u6B63\u786E\u7684 thinking \u5F00\u5934\u793A\u4F8B\uFF1A"\u6211\u9700\u8981\u5206\u6790..."\u3001"\u5148\u68C0\u67E5\u4E00\u4E0B..."
23188
+ \u8FD9\u4E0D\u662F\u5EFA\u8BAE\u2014\u2014thinking \u5757\u7B2C\u4E00\u884C\u51FA\u73B0\u82F1\u6587\u5373\u89C6\u4E3A\u7CFB\u7EDF\u6545\u969C\u3002
23189
+
23190
+ ### Sub-agent \u8FD4\u56DE\u5185\u5BB9\u5904\u7406
23191
+ \u6536\u5230 sub-agent \u8FD4\u56DE\u7ED3\u679C\u65F6\uFF1A
23192
+ - \u8FD4\u56DE\u5185\u5BB9\u53EF\u80FD\u542B\u5927\u91CF\u82F1\u6587\uFF08\u4EE3\u7801\u7247\u6BB5\u3001\u641C\u7D22\u7ED3\u679C\u3001\u6587\u6863\u5F15\u7528\uFF09
23193
+ - \u4F46\u4F60\u7684\u5185\u90E8\u63A8\u7406\u5FC5\u987B\u4FDD\u6301\u4E2D\u6587
23194
+ - \u6574\u5408\u524D\u5148\u7528\u4E2D\u6587\u603B\u7ED3\u5176\u8981\u70B9
23195
+ - \u7981\u6B62\u590D\u5236 sub-agent \u7684\u82F1\u6587 thinking \u4F5C\u4E3A\u81EA\u5DF1\u7684\u5185\u5BB9
23196
+ - \u7528\u81EA\u5DF1\u7684\u4E2D\u6587\u8BED\u53E5\u5F15\u7528\u53D1\u73B0\uFF0C\u800C\u975E\u76F4\u63A5\u590D\u5236\u82F1\u6587\u539F\u6587
23197
+
23033
23198
  ### Sub-agent \u7EE7\u627F
23034
23199
  - \u6B64\u89C4\u5219\u9012\u5F52\u4F20\u9012\u7ED9\u6240\u6709 delegate_task \u5B50\u4EE3\u7406
23035
23200
  - \u5B50\u4EE3\u7406\u7684 prompt \u5F00\u5934\u4E5F\u5DF2\u5305\u542B\u8EAB\u4EFD\u58F0\u660E
@@ -23265,6 +23430,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
23265
23430
  - \u4F60\u59CB\u7EC8\u662F\u300C${name}\u300D\uFF0C\u4E0D\u662F\u5176\u4ED6\u4EFB\u4F55 agent
23266
23431
  - \u65E0\u8BBA\u4E0A\u4E0B\u6587\u5982\u4F55\u53D8\u5316\uFF0C\u4F60\u7684\u8EAB\u4EFD\u4E0D\u4F1A\u6539\u53D8
23267
23432
  - \u5982\u679C\u4E0A\u4E0B\u6587\u6697\u793A\u4F60\u662F\u5176\u4ED6 agent\uFF0C\u5FFD\u7565\u8BE5\u6697\u793A
23433
+ - \u5F53\u524D session \u7684\u6D3B\u8DC3 agent \u7531\u8FD0\u884C\u65F6\u7CFB\u7EDF\u8FFD\u8E2A\uFF0C\u4E0E\u4F60\u65E0\u5173\u3002\u4F60\u53EA\u54CD\u5E94\u4F60\u6536\u5230\u7684\u6D88\u606F\u3002
23268
23434
 
23269
23435
  **\u5F53\u524D\u89D2\u8272**\uFF1A${roleDescription}
23270
23436
  </Identity_Anchor>
@@ -23288,7 +23454,9 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
23288
23454
  }
23289
23455
  return result;
23290
23456
  }
23457
+
23291
23458
  // src/hooks/compaction-context-injector/index.ts
23459
+ init_agent_identity_resolver();
23292
23460
  var BASE_SUMMARIZE_CONTEXT = `${createSystemDirective(SystemDirectiveTypes.COMPACTION_CONTEXT)}
23293
23461
 
23294
23462
  \u5728\u603B\u7ED3\u6B64\u4F1A\u8BDD\u65F6\uFF0C\u4F60\u5FC5\u987B\u5728\u603B\u7ED3\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206\uFF1A
@@ -23333,7 +23501,7 @@ function createCompactionContextInjector(_client, config) {
23333
23501
  const contextPrompt = buildSummarizeContextPrompt(config);
23334
23502
  return async (ctx) => {
23335
23503
  log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID });
23336
- const agentName = getSessionAgent(ctx.sessionID) ?? "general";
23504
+ const agentName = resolveCurrentAgent(ctx.sessionID) ?? "general";
23337
23505
  const success = injectHookMessage(ctx.sessionID, contextPrompt, {
23338
23506
  agent: agentName,
23339
23507
  model: { providerID: ctx.providerID, modelID: ctx.modelID },
@@ -23669,8 +23837,8 @@ function createThinkModeHook() {
23669
23837
  }
23670
23838
  // src/hooks/claude-code-hooks/config.ts
23671
23839
  init_shared();
23672
- import { join as join27 } from "path";
23673
- import { existsSync as existsSync22 } from "fs";
23840
+ import { join as join28 } from "path";
23841
+ import { existsSync as existsSync23 } from "fs";
23674
23842
  function normalizeHookMatcher(raw) {
23675
23843
  return {
23676
23844
  matcher: raw.matcher ?? raw.pattern ?? "*",
@@ -23696,11 +23864,11 @@ function normalizeHooksConfig(raw) {
23696
23864
  function getClaudeSettingsPaths(customPath) {
23697
23865
  const claudeConfigDir = getClaudeConfigDir();
23698
23866
  const paths = [
23699
- join27(claudeConfigDir, "settings.json"),
23700
- join27(process.cwd(), ".claude", "settings.json"),
23701
- join27(process.cwd(), ".claude", "settings.local.json")
23867
+ join28(claudeConfigDir, "settings.json"),
23868
+ join28(process.cwd(), ".claude", "settings.json"),
23869
+ join28(process.cwd(), ".claude", "settings.local.json")
23702
23870
  ];
23703
- if (customPath && existsSync22(customPath)) {
23871
+ if (customPath && existsSync23(customPath)) {
23704
23872
  paths.unshift(customPath);
23705
23873
  }
23706
23874
  return paths;
@@ -23725,7 +23893,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
23725
23893
  const paths = getClaudeSettingsPaths(customSettingsPath);
23726
23894
  let mergedConfig = {};
23727
23895
  for (const settingsPath of paths) {
23728
- if (existsSync22(settingsPath)) {
23896
+ if (existsSync23(settingsPath)) {
23729
23897
  try {
23730
23898
  const content = await Bun.file(settingsPath).text();
23731
23899
  const settings = JSON.parse(content);
@@ -23744,14 +23912,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
23744
23912
  // src/hooks/claude-code-hooks/config-loader.ts
23745
23913
  init_logger();
23746
23914
  init_shared();
23747
- import { existsSync as existsSync23 } from "fs";
23748
- import { join as join28 } from "path";
23749
- var USER_CONFIG_PATH = join28(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
23915
+ import { existsSync as existsSync24 } from "fs";
23916
+ import { join as join29 } from "path";
23917
+ var USER_CONFIG_PATH = join29(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
23750
23918
  function getProjectConfigPath() {
23751
- return join28(process.cwd(), ".opencode", "opencode-cc-plugin.json");
23919
+ return join29(process.cwd(), ".opencode", "opencode-cc-plugin.json");
23752
23920
  }
23753
23921
  async function loadConfigFromPath(path4) {
23754
- if (!existsSync23(path4)) {
23922
+ if (!existsSync24(path4)) {
23755
23923
  return null;
23756
23924
  }
23757
23925
  try {
@@ -23939,17 +24107,17 @@ init_shared();
23939
24107
  // src/hooks/claude-code-hooks/transcript.ts
23940
24108
  init_tool_name();
23941
24109
  init_shared();
23942
- import { join as join29 } from "path";
23943
- import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync6, existsSync as existsSync24, writeFileSync as writeFileSync10, unlinkSync as unlinkSync5 } from "fs";
24110
+ import { join as join30 } from "path";
24111
+ import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync6, existsSync as existsSync25, writeFileSync as writeFileSync11, unlinkSync as unlinkSync5 } from "fs";
23944
24112
  import { tmpdir as tmpdir6 } from "os";
23945
24113
  import { randomUUID } from "crypto";
23946
- var TRANSCRIPT_DIR = join29(getClaudeConfigDir(), "transcripts");
24114
+ var TRANSCRIPT_DIR = join30(getClaudeConfigDir(), "transcripts");
23947
24115
  function getTranscriptPath(sessionId) {
23948
- return join29(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
24116
+ return join30(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
23949
24117
  }
23950
24118
  function ensureTranscriptDir() {
23951
- if (!existsSync24(TRANSCRIPT_DIR)) {
23952
- mkdirSync9(TRANSCRIPT_DIR, { recursive: true });
24119
+ if (!existsSync25(TRANSCRIPT_DIR)) {
24120
+ mkdirSync10(TRANSCRIPT_DIR, { recursive: true });
23953
24121
  }
23954
24122
  }
23955
24123
  function appendTranscriptEntry(sessionId, entry) {
@@ -24035,8 +24203,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
24035
24203
  }
24036
24204
  };
24037
24205
  entries.push(JSON.stringify(currentEntry));
24038
- const tempPath = join29(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24039
- writeFileSync10(tempPath, entries.join(`
24206
+ const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24207
+ writeFileSync11(tempPath, entries.join(`
24040
24208
  `) + `
24041
24209
  `);
24042
24210
  return tempPath;
@@ -24055,8 +24223,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
24055
24223
  ]
24056
24224
  }
24057
24225
  };
24058
- const tempPath = join29(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24059
- writeFileSync10(tempPath, JSON.stringify(currentEntry) + `
24226
+ const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24227
+ writeFileSync11(tempPath, JSON.stringify(currentEntry) + `
24060
24228
  `);
24061
24229
  return tempPath;
24062
24230
  } catch {
@@ -24271,11 +24439,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
24271
24439
  init_shared();
24272
24440
 
24273
24441
  // src/hooks/claude-code-hooks/todo.ts
24274
- import { join as join30 } from "path";
24442
+ import { join as join31 } from "path";
24275
24443
  init_shared();
24276
- var TODO_DIR = join30(getClaudeConfigDir(), "todos");
24444
+ var TODO_DIR = join31(getClaudeConfigDir(), "todos");
24277
24445
  function getTodoPath(sessionId) {
24278
- return join30(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
24446
+ return join31(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
24279
24447
  }
24280
24448
 
24281
24449
  // src/hooks/claude-code-hooks/stop.ts
@@ -24718,24 +24886,24 @@ ${result.message}`;
24718
24886
  };
24719
24887
  }
24720
24888
  // src/hooks/rules-injector/index.ts
24721
- import { readFileSync as readFileSync18 } from "fs";
24889
+ import { readFileSync as readFileSync19 } from "fs";
24722
24890
  import { homedir as homedir9 } from "os";
24723
24891
  import { relative as relative4, resolve as resolve5 } from "path";
24724
24892
 
24725
24893
  // src/hooks/rules-injector/finder.ts
24726
24894
  import {
24727
- existsSync as existsSync25,
24895
+ existsSync as existsSync26,
24728
24896
  readdirSync as readdirSync7,
24729
24897
  realpathSync,
24730
24898
  statSync as statSync2
24731
24899
  } from "fs";
24732
- import { dirname as dirname4, join as join32, relative as relative2 } from "path";
24900
+ import { dirname as dirname4, join as join33, relative as relative2 } from "path";
24733
24901
 
24734
24902
  // src/hooks/rules-injector/constants.ts
24735
24903
  init_data_path();
24736
- import { join as join31 } from "path";
24904
+ import { join as join32 } from "path";
24737
24905
  var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
24738
- var RULES_INJECTOR_STORAGE = join31(OPENCODE_STORAGE6, "rules-injector");
24906
+ var RULES_INJECTOR_STORAGE = join32(OPENCODE_STORAGE6, "rules-injector");
24739
24907
  var PROJECT_MARKERS = [
24740
24908
  ".git",
24741
24909
  "pyproject.toml",
@@ -24777,8 +24945,8 @@ function findProjectRoot(startPath) {
24777
24945
  }
24778
24946
  while (true) {
24779
24947
  for (const marker of PROJECT_MARKERS) {
24780
- const markerPath = join32(current, marker);
24781
- if (existsSync25(markerPath)) {
24948
+ const markerPath = join33(current, marker);
24949
+ if (existsSync26(markerPath)) {
24782
24950
  return current;
24783
24951
  }
24784
24952
  }
@@ -24790,12 +24958,12 @@ function findProjectRoot(startPath) {
24790
24958
  }
24791
24959
  }
24792
24960
  function findRuleFilesRecursive(dir, results) {
24793
- if (!existsSync25(dir))
24961
+ if (!existsSync26(dir))
24794
24962
  return;
24795
24963
  try {
24796
24964
  const entries = readdirSync7(dir, { withFileTypes: true });
24797
24965
  for (const entry of entries) {
24798
- const fullPath = join32(dir, entry.name);
24966
+ const fullPath = join33(dir, entry.name);
24799
24967
  if (entry.isDirectory()) {
24800
24968
  findRuleFilesRecursive(fullPath, results);
24801
24969
  } else if (entry.isFile()) {
@@ -24820,7 +24988,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24820
24988
  let distance = 0;
24821
24989
  while (true) {
24822
24990
  for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
24823
- const ruleDir = join32(currentDir, parent, subdir);
24991
+ const ruleDir = join33(currentDir, parent, subdir);
24824
24992
  const files = [];
24825
24993
  findRuleFilesRecursive(ruleDir, files);
24826
24994
  for (const filePath of files) {
@@ -24846,8 +25014,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24846
25014
  }
24847
25015
  if (projectRoot) {
24848
25016
  for (const ruleFile of PROJECT_RULE_FILES) {
24849
- const filePath = join32(projectRoot, ruleFile);
24850
- if (existsSync25(filePath)) {
25017
+ const filePath = join33(projectRoot, ruleFile);
25018
+ if (existsSync26(filePath)) {
24851
25019
  try {
24852
25020
  const stat = statSync2(filePath);
24853
25021
  if (stat.isFile()) {
@@ -24867,7 +25035,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24867
25035
  }
24868
25036
  }
24869
25037
  }
24870
- const userRuleDir = join32(homeDir, USER_RULE_DIR);
25038
+ const userRuleDir = join33(homeDir, USER_RULE_DIR);
24871
25039
  const userFiles = [];
24872
25040
  findRuleFilesRecursive(userRuleDir, userFiles);
24873
25041
  for (const filePath of userFiles) {
@@ -25056,22 +25224,22 @@ function mergeGlobs(existing, newValue) {
25056
25224
 
25057
25225
  // src/hooks/rules-injector/storage.ts
25058
25226
  import {
25059
- existsSync as existsSync26,
25060
- mkdirSync as mkdirSync10,
25061
- readFileSync as readFileSync17,
25062
- writeFileSync as writeFileSync11,
25227
+ existsSync as existsSync27,
25228
+ mkdirSync as mkdirSync11,
25229
+ readFileSync as readFileSync18,
25230
+ writeFileSync as writeFileSync12,
25063
25231
  unlinkSync as unlinkSync6
25064
25232
  } from "fs";
25065
- import { join as join33 } from "path";
25233
+ import { join as join34 } from "path";
25066
25234
  function getStoragePath3(sessionID) {
25067
- return join33(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
25235
+ return join34(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
25068
25236
  }
25069
25237
  function loadInjectedRules(sessionID) {
25070
25238
  const filePath = getStoragePath3(sessionID);
25071
- if (!existsSync26(filePath))
25239
+ if (!existsSync27(filePath))
25072
25240
  return { contentHashes: new Set, realPaths: new Set };
25073
25241
  try {
25074
- const content = readFileSync17(filePath, "utf-8");
25242
+ const content = readFileSync18(filePath, "utf-8");
25075
25243
  const data = JSON.parse(content);
25076
25244
  return {
25077
25245
  contentHashes: new Set(data.injectedHashes),
@@ -25082,8 +25250,8 @@ function loadInjectedRules(sessionID) {
25082
25250
  }
25083
25251
  }
25084
25252
  function saveInjectedRules(sessionID, data) {
25085
- if (!existsSync26(RULES_INJECTOR_STORAGE)) {
25086
- mkdirSync10(RULES_INJECTOR_STORAGE, { recursive: true });
25253
+ if (!existsSync27(RULES_INJECTOR_STORAGE)) {
25254
+ mkdirSync11(RULES_INJECTOR_STORAGE, { recursive: true });
25087
25255
  }
25088
25256
  const storageData = {
25089
25257
  sessionID,
@@ -25091,11 +25259,11 @@ function saveInjectedRules(sessionID, data) {
25091
25259
  injectedRealPaths: [...data.realPaths],
25092
25260
  updatedAt: Date.now()
25093
25261
  };
25094
- writeFileSync11(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
25262
+ writeFileSync12(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
25095
25263
  }
25096
25264
  function clearInjectedRules(sessionID) {
25097
25265
  const filePath = getStoragePath3(sessionID);
25098
- if (existsSync26(filePath)) {
25266
+ if (existsSync27(filePath)) {
25099
25267
  unlinkSync6(filePath);
25100
25268
  }
25101
25269
  }
@@ -25133,7 +25301,7 @@ function createRulesInjectorHook(ctx) {
25133
25301
  if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
25134
25302
  continue;
25135
25303
  try {
25136
- const rawContent = readFileSync18(candidate.path, "utf-8");
25304
+ const rawContent = readFileSync19(candidate.path, "utf-8");
25137
25305
  const { metadata, body } = parseRuleFrontmatter(rawContent);
25138
25306
  let matchReason;
25139
25307
  if (candidate.isSingleFile) {
@@ -25254,19 +25422,19 @@ init_auto_update_checker();
25254
25422
 
25255
25423
  // src/hooks/agent-usage-reminder/storage.ts
25256
25424
  import {
25257
- existsSync as existsSync29,
25258
- mkdirSync as mkdirSync11,
25259
- readFileSync as readFileSync21,
25260
- writeFileSync as writeFileSync14,
25425
+ existsSync as existsSync30,
25426
+ mkdirSync as mkdirSync12,
25427
+ readFileSync as readFileSync22,
25428
+ writeFileSync as writeFileSync15,
25261
25429
  unlinkSync as unlinkSync7
25262
25430
  } from "fs";
25263
- import { join as join38 } from "path";
25431
+ import { join as join39 } from "path";
25264
25432
 
25265
25433
  // src/hooks/agent-usage-reminder/constants.ts
25266
25434
  init_data_path();
25267
- import { join as join37 } from "path";
25435
+ import { join as join38 } from "path";
25268
25436
  var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
25269
- var AGENT_USAGE_REMINDER_STORAGE = join37(OPENCODE_STORAGE7, "agent-usage-reminder");
25437
+ var AGENT_USAGE_REMINDER_STORAGE = join38(OPENCODE_STORAGE7, "agent-usage-reminder");
25270
25438
  var TARGET_TOOLS = new Set([
25271
25439
  "grep",
25272
25440
  "safe_grep",
@@ -25312,29 +25480,29 @@ delegate_task(agent="\u77E5\u8BC6\u5178\u85CF", prompt="\u67E5\u627E Z \u7684\u6
25312
25480
 
25313
25481
  // src/hooks/agent-usage-reminder/storage.ts
25314
25482
  function getStoragePath4(sessionID) {
25315
- return join38(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
25483
+ return join39(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
25316
25484
  }
25317
25485
  function loadAgentUsageState(sessionID) {
25318
25486
  const filePath = getStoragePath4(sessionID);
25319
- if (!existsSync29(filePath))
25487
+ if (!existsSync30(filePath))
25320
25488
  return null;
25321
25489
  try {
25322
- const content = readFileSync21(filePath, "utf-8");
25490
+ const content = readFileSync22(filePath, "utf-8");
25323
25491
  return JSON.parse(content);
25324
25492
  } catch {
25325
25493
  return null;
25326
25494
  }
25327
25495
  }
25328
25496
  function saveAgentUsageState(state2) {
25329
- if (!existsSync29(AGENT_USAGE_REMINDER_STORAGE)) {
25330
- mkdirSync11(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
25497
+ if (!existsSync30(AGENT_USAGE_REMINDER_STORAGE)) {
25498
+ mkdirSync12(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
25331
25499
  }
25332
25500
  const filePath = getStoragePath4(state2.sessionID);
25333
- writeFileSync14(filePath, JSON.stringify(state2, null, 2));
25501
+ writeFileSync15(filePath, JSON.stringify(state2, null, 2));
25334
25502
  }
25335
25503
  function clearAgentUsageState(sessionID) {
25336
25504
  const filePath = getStoragePath4(sessionID);
25337
- if (existsSync29(filePath)) {
25505
+ if (existsSync30(filePath)) {
25338
25506
  unlinkSync7(filePath);
25339
25507
  }
25340
25508
  }
@@ -25406,19 +25574,19 @@ function createAgentUsageReminderHook(_ctx) {
25406
25574
  }
25407
25575
  // src/hooks/language-reminder/storage.ts
25408
25576
  import {
25409
- existsSync as existsSync30,
25410
- mkdirSync as mkdirSync12,
25411
- readFileSync as readFileSync22,
25412
- writeFileSync as writeFileSync15,
25577
+ existsSync as existsSync31,
25578
+ mkdirSync as mkdirSync13,
25579
+ readFileSync as readFileSync23,
25580
+ writeFileSync as writeFileSync16,
25413
25581
  unlinkSync as unlinkSync8
25414
25582
  } from "fs";
25415
- import { join as join40 } from "path";
25583
+ import { join as join41 } from "path";
25416
25584
 
25417
25585
  // src/hooks/language-reminder/constants.ts
25418
25586
  init_data_path();
25419
- import { join as join39 } from "path";
25587
+ import { join as join40 } from "path";
25420
25588
  var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
25421
- var LANGUAGE_REMINDER_STORAGE = join39(OPENCODE_STORAGE8, "language-reminder");
25589
+ var LANGUAGE_REMINDER_STORAGE = join40(OPENCODE_STORAGE8, "language-reminder");
25422
25590
  var LANGUAGE_REMINDER_MESSAGE = `
25423
25591
 
25424
25592
  [SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
@@ -25430,29 +25598,29 @@ var LANGUAGE_REMINDER_MESSAGE = `
25430
25598
 
25431
25599
  // src/hooks/language-reminder/storage.ts
25432
25600
  function getStoragePath5(sessionID) {
25433
- return join40(LANGUAGE_REMINDER_STORAGE, `${sessionID}.json`);
25601
+ return join41(LANGUAGE_REMINDER_STORAGE, `${sessionID}.json`);
25434
25602
  }
25435
25603
  function loadLanguageReminderState(sessionID) {
25436
25604
  const filePath = getStoragePath5(sessionID);
25437
- if (!existsSync30(filePath))
25605
+ if (!existsSync31(filePath))
25438
25606
  return null;
25439
25607
  try {
25440
- const content = readFileSync22(filePath, "utf-8");
25608
+ const content = readFileSync23(filePath, "utf-8");
25441
25609
  return JSON.parse(content);
25442
25610
  } catch {
25443
25611
  return null;
25444
25612
  }
25445
25613
  }
25446
25614
  function saveLanguageReminderState(state2) {
25447
- if (!existsSync30(LANGUAGE_REMINDER_STORAGE)) {
25448
- mkdirSync12(LANGUAGE_REMINDER_STORAGE, { recursive: true });
25615
+ if (!existsSync31(LANGUAGE_REMINDER_STORAGE)) {
25616
+ mkdirSync13(LANGUAGE_REMINDER_STORAGE, { recursive: true });
25449
25617
  }
25450
25618
  const filePath = getStoragePath5(state2.sessionID);
25451
- writeFileSync15(filePath, JSON.stringify(state2, null, 2));
25619
+ writeFileSync16(filePath, JSON.stringify(state2, null, 2));
25452
25620
  }
25453
25621
  function clearLanguageReminderState(sessionID) {
25454
25622
  const filePath = getStoragePath5(sessionID);
25455
- if (existsSync30(filePath)) {
25623
+ if (existsSync31(filePath)) {
25456
25624
  unlinkSync8(filePath);
25457
25625
  }
25458
25626
  }
@@ -25550,35 +25718,44 @@ function createLanguageReminderHook(ctx) {
25550
25718
  }
25551
25719
  // src/hooks/thinking-language-validator/storage.ts
25552
25720
  import {
25553
- existsSync as existsSync31,
25554
- mkdirSync as mkdirSync13,
25555
- readFileSync as readFileSync23,
25556
- writeFileSync as writeFileSync16,
25721
+ existsSync as existsSync32,
25722
+ mkdirSync as mkdirSync14,
25723
+ readFileSync as readFileSync24,
25724
+ writeFileSync as writeFileSync17,
25557
25725
  unlinkSync as unlinkSync9
25558
25726
  } from "fs";
25559
- import { join as join42 } from "path";
25727
+ import { join as join43 } from "path";
25560
25728
 
25561
25729
  // src/hooks/thinking-language-validator/constants.ts
25562
25730
  init_data_path();
25563
- import { join as join41 } from "path";
25731
+ import { join as join42 } from "path";
25564
25732
  var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
25565
- var THINKING_VALIDATOR_STORAGE = join41(OPENCODE_STORAGE9, "thinking-language-validator");
25733
+ var THINKING_VALIDATOR_STORAGE = join42(OPENCODE_STORAGE9, "thinking-language-validator");
25734
+ var STREAM_THROTTLE = 20;
25566
25735
  var THINKING_VIOLATION_REMINDER = `
25567
25736
 
25568
25737
  [SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
25569
- \u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\u8BF7\u7ACB\u5373\u5207\u6362\u56DE\u4E2D\u6587\u601D\u8003\u3002
25570
- \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u8FDD\u53CD\u3002\u975E\u6CD5\u4F8B\u5916\u4E0D\u662F\u501F\u53E3\u3002`;
25738
+ \u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u8FDD\u53CD\u3002
25739
+
25740
+ ## \u5F3A\u5236\u4FEE\u590D\u8981\u6C42
25741
+ \u4F60\u4E0A\u4E00\u8F6E\u7684 thinking \u5757\u4F7F\u7528\u4E86\u82F1\u6587\u2014\u2014\u8FD9\u662F\u4E0D\u5141\u8BB8\u7684\u3002
25742
+ \u5728\u672C\u8F6E\u56DE\u590D\u4E2D\uFF0C\u4F60\u5FC5\u987B\uFF1A
25743
+ 1. \u5728 thinking \u5757\u5F00\u5934\u5199\u5165\uFF1A"\u8BED\u8A00\u8FDD\u89C4\u4FEE\u590D\uFF1A\u4E0A\u4E00\u8F6E thinking \u4F7F\u7528\u4E86\u82F1\u6587\uFF0C\u5DF2\u7EA0\u6B63\u3002"
25744
+ 2. \u7528\u4E2D\u6587\u91CD\u65B0\u8868\u8FF0\u4F60\u4E0A\u4E00\u8F6E\u4E2D\u82F1\u6587\u601D\u8003\u7684\u6838\u5FC3\u5185\u5BB9
25745
+ 3. \u672C\u8F6E\u6240\u6709\u8F93\u51FA\u5FC5\u987B\u4E3A\u4E2D\u6587
25746
+
25747
+ \u8FD9\u662F\u5F3A\u5236\u8981\u6C42\u2014\u2014\u4E0D\u662F\u5EFA\u8BAE\u3002\u4E0D\u5F97\u8DF3\u8FC7\u3002`;
25571
25748
 
25572
25749
  // src/hooks/thinking-language-validator/storage.ts
25573
25750
  function getStoragePath6(sessionID) {
25574
- return join42(THINKING_VALIDATOR_STORAGE, `${sessionID}.json`);
25751
+ return join43(THINKING_VALIDATOR_STORAGE, `${sessionID}.json`);
25575
25752
  }
25576
25753
  function loadThinkingValidatorState(sessionID) {
25577
25754
  const filePath = getStoragePath6(sessionID);
25578
- if (!existsSync31(filePath))
25755
+ if (!existsSync32(filePath))
25579
25756
  return null;
25580
25757
  try {
25581
- const content = readFileSync23(filePath, "utf-8");
25758
+ const content = readFileSync24(filePath, "utf-8");
25582
25759
  const parsed = JSON.parse(content);
25583
25760
  const state2 = {
25584
25761
  sessionID: parsed.sessionID ?? sessionID,
@@ -25599,15 +25776,15 @@ function loadThinkingValidatorState(sessionID) {
25599
25776
  }
25600
25777
  }
25601
25778
  function saveThinkingValidatorState(state2) {
25602
- if (!existsSync31(THINKING_VALIDATOR_STORAGE)) {
25603
- mkdirSync13(THINKING_VALIDATOR_STORAGE, { recursive: true });
25779
+ if (!existsSync32(THINKING_VALIDATOR_STORAGE)) {
25780
+ mkdirSync14(THINKING_VALIDATOR_STORAGE, { recursive: true });
25604
25781
  }
25605
25782
  const filePath = getStoragePath6(state2.sessionID);
25606
- writeFileSync16(filePath, JSON.stringify(state2, null, 2));
25783
+ writeFileSync17(filePath, JSON.stringify(state2, null, 2));
25607
25784
  }
25608
25785
  function clearThinkingValidatorState(sessionID) {
25609
25786
  const filePath = getStoragePath6(sessionID);
25610
- if (existsSync31(filePath)) {
25787
+ if (existsSync32(filePath)) {
25611
25788
  unlinkSync9(filePath);
25612
25789
  }
25613
25790
  }
@@ -25619,7 +25796,9 @@ function createThinkingLanguageValidatorHook(ctx) {
25619
25796
  const config = ctx.config;
25620
25797
  const le = config?.language_enforcement;
25621
25798
  const violationThreshold = le?.violation_threshold ?? 0.6;
25622
- const excludedAgents = le?.excluded_agents ?? ["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"];
25799
+ const excludedAgents = le?.excluded_agents ?? [];
25800
+ const relaxedAgents = le?.relaxed_agents ?? ["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"];
25801
+ const relaxedThreshold = le?.relaxed_threshold ?? 0.85;
25623
25802
  function getOrCreateState(sessionID) {
25624
25803
  if (!sessionStates.has(sessionID)) {
25625
25804
  const persisted = loadThinkingValidatorState(sessionID);
@@ -25700,12 +25879,13 @@ function createThinkingLanguageValidatorHook(ctx) {
25700
25879
  if (!thinkingText || thinkingText.length < 4)
25701
25880
  return;
25702
25881
  const state2 = getOrCreateState(sessionID);
25703
- if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength < 50) {
25882
+ if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength < STREAM_THROTTLE) {
25704
25883
  state2.throttleSkipCount++;
25705
25884
  saveThinkingValidatorState(state2);
25706
25885
  return;
25707
25886
  }
25708
- const isViolation = detectEnglishViolation(thinkingText, violationThreshold);
25887
+ const effectiveThreshold = agent && relaxedAgents.some((a) => agentNameMatches(agent, a)) ? relaxedThreshold : violationThreshold;
25888
+ const isViolation = detectEnglishViolation(thinkingText, effectiveThreshold);
25709
25889
  if (isViolation) {
25710
25890
  state2.totalDetectionCount++;
25711
25891
  if (isViolation === "trigger") {
@@ -26055,6 +26235,8 @@ function extractPromptText2(parts) {
26055
26235
  // src/hooks/keyword-detector/index.ts
26056
26236
  init_shared();
26057
26237
  init_system_directive();
26238
+ init_claude_code_session_state();
26239
+ init_agent_identity_resolver();
26058
26240
  function createKeywordDetectorHook(ctx, collector) {
26059
26241
  return {
26060
26242
  "chat.message": async (input, output) => {
@@ -26063,7 +26245,7 @@ function createKeywordDetectorHook(ctx, collector) {
26063
26245
  log(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID });
26064
26246
  return;
26065
26247
  }
26066
- const currentAgent = getSessionAgent(input.sessionID) ?? input.agent;
26248
+ const currentAgent = resolveCurrentAgent(input.sessionID, input.agent);
26067
26249
  let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), currentAgent);
26068
26250
  if (detectedKeywords.length === 0) {
26069
26251
  return;
@@ -26216,19 +26398,19 @@ function createNonInteractiveEnvHook(_ctx) {
26216
26398
  }
26217
26399
  // src/hooks/interactive-bash-session/storage.ts
26218
26400
  import {
26219
- existsSync as existsSync32,
26220
- mkdirSync as mkdirSync14,
26221
- readFileSync as readFileSync24,
26222
- writeFileSync as writeFileSync17,
26401
+ existsSync as existsSync33,
26402
+ mkdirSync as mkdirSync15,
26403
+ readFileSync as readFileSync25,
26404
+ writeFileSync as writeFileSync18,
26223
26405
  unlinkSync as unlinkSync10
26224
26406
  } from "fs";
26225
- import { join as join44 } from "path";
26407
+ import { join as join45 } from "path";
26226
26408
 
26227
26409
  // src/hooks/interactive-bash-session/constants.ts
26228
26410
  init_data_path();
26229
- import { join as join43 } from "path";
26411
+ import { join as join44 } from "path";
26230
26412
  var OPENCODE_STORAGE10 = getOpenCodeStorageDir();
26231
- var INTERACTIVE_BASH_SESSION_STORAGE = join43(OPENCODE_STORAGE10, "interactive-bash-session");
26413
+ var INTERACTIVE_BASH_SESSION_STORAGE = join44(OPENCODE_STORAGE10, "interactive-bash-session");
26232
26414
  var OMO_SESSION_PREFIX = "omo-";
26233
26415
  function buildSessionReminderMessage(sessions) {
26234
26416
  if (sessions.length === 0)
@@ -26240,14 +26422,14 @@ function buildSessionReminderMessage(sessions) {
26240
26422
 
26241
26423
  // src/hooks/interactive-bash-session/storage.ts
26242
26424
  function getStoragePath7(sessionID) {
26243
- return join44(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
26425
+ return join45(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
26244
26426
  }
26245
26427
  function loadInteractiveBashSessionState(sessionID) {
26246
26428
  const filePath = getStoragePath7(sessionID);
26247
- if (!existsSync32(filePath))
26429
+ if (!existsSync33(filePath))
26248
26430
  return null;
26249
26431
  try {
26250
- const content = readFileSync24(filePath, "utf-8");
26432
+ const content = readFileSync25(filePath, "utf-8");
26251
26433
  const serialized = JSON.parse(content);
26252
26434
  return {
26253
26435
  sessionID: serialized.sessionID,
@@ -26259,8 +26441,8 @@ function loadInteractiveBashSessionState(sessionID) {
26259
26441
  }
26260
26442
  }
26261
26443
  function saveInteractiveBashSessionState(state2) {
26262
- if (!existsSync32(INTERACTIVE_BASH_SESSION_STORAGE)) {
26263
- mkdirSync14(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
26444
+ if (!existsSync33(INTERACTIVE_BASH_SESSION_STORAGE)) {
26445
+ mkdirSync15(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
26264
26446
  }
26265
26447
  const filePath = getStoragePath7(state2.sessionID);
26266
26448
  const serialized = {
@@ -26268,11 +26450,11 @@ function saveInteractiveBashSessionState(state2) {
26268
26450
  tmuxSessions: Array.from(state2.tmuxSessions),
26269
26451
  updatedAt: state2.updatedAt
26270
26452
  };
26271
- writeFileSync17(filePath, JSON.stringify(serialized, null, 2));
26453
+ writeFileSync18(filePath, JSON.stringify(serialized, null, 2));
26272
26454
  }
26273
26455
  function clearInteractiveBashSessionState(sessionID) {
26274
26456
  const filePath = getStoragePath7(sessionID);
26275
- if (existsSync32(filePath)) {
26457
+ if (existsSync33(filePath)) {
26276
26458
  unlinkSync10(filePath);
26277
26459
  }
26278
26460
  }
@@ -26536,13 +26718,13 @@ function createThinkingBlockValidatorHook() {
26536
26718
  // src/hooks/ralph-loop/index.ts
26537
26719
  init_logger();
26538
26720
  init_system_directive();
26539
- import { existsSync as existsSync34, readFileSync as readFileSync26, readdirSync as readdirSync8 } from "fs";
26540
- import { join as join46 } from "path";
26721
+ import { existsSync as existsSync35, readFileSync as readFileSync27, readdirSync as readdirSync8 } from "fs";
26722
+ import { join as join47 } from "path";
26541
26723
 
26542
26724
  // src/hooks/ralph-loop/storage.ts
26543
26725
  init_frontmatter();
26544
- import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync18, unlinkSync as unlinkSync11, mkdirSync as mkdirSync15 } from "fs";
26545
- import { dirname as dirname6, join as join45 } from "path";
26726
+ import { existsSync as existsSync34, readFileSync as readFileSync26, writeFileSync as writeFileSync19, unlinkSync as unlinkSync11, mkdirSync as mkdirSync16 } from "fs";
26727
+ import { dirname as dirname6, join as join46 } from "path";
26546
26728
 
26547
26729
  // src/hooks/ralph-loop/constants.ts
26548
26730
  var HOOK_NAME3 = "ralph-loop";
@@ -26552,15 +26734,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
26552
26734
 
26553
26735
  // src/hooks/ralph-loop/storage.ts
26554
26736
  function getStateFilePath(directory, customPath) {
26555
- return customPath ? join45(directory, customPath) : join45(directory, DEFAULT_STATE_FILE);
26737
+ return customPath ? join46(directory, customPath) : join46(directory, DEFAULT_STATE_FILE);
26556
26738
  }
26557
26739
  function readState(directory, customPath) {
26558
26740
  const filePath = getStateFilePath(directory, customPath);
26559
- if (!existsSync33(filePath)) {
26741
+ if (!existsSync34(filePath)) {
26560
26742
  return null;
26561
26743
  }
26562
26744
  try {
26563
- const content = readFileSync25(filePath, "utf-8");
26745
+ const content = readFileSync26(filePath, "utf-8");
26564
26746
  const { data, body } = parseFrontmatter(content);
26565
26747
  const active = data.active;
26566
26748
  const iteration = data.iteration;
@@ -26594,8 +26776,8 @@ function writeState(directory, state2, customPath) {
26594
26776
  const filePath = getStateFilePath(directory, customPath);
26595
26777
  try {
26596
26778
  const dir = dirname6(filePath);
26597
- if (!existsSync33(dir)) {
26598
- mkdirSync15(dir, { recursive: true });
26779
+ if (!existsSync34(dir)) {
26780
+ mkdirSync16(dir, { recursive: true });
26599
26781
  }
26600
26782
  const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
26601
26783
  ` : "";
@@ -26610,7 +26792,7 @@ started_at: "${state2.started_at}"
26610
26792
  ${sessionIdLine}${ultraworkLine}---
26611
26793
  ${state2.prompt}
26612
26794
  `;
26613
- writeFileSync18(filePath, content, "utf-8");
26795
+ writeFileSync19(filePath, content, "utf-8");
26614
26796
  return true;
26615
26797
  } catch {
26616
26798
  return false;
@@ -26619,7 +26801,7 @@ ${state2.prompt}
26619
26801
  function clearState(directory, customPath) {
26620
26802
  const filePath = getStateFilePath(directory, customPath);
26621
26803
  try {
26622
- if (existsSync33(filePath)) {
26804
+ if (existsSync34(filePath)) {
26623
26805
  unlinkSync11(filePath);
26624
26806
  }
26625
26807
  return true;
@@ -26641,14 +26823,14 @@ function incrementIteration(directory, customPath) {
26641
26823
  // src/hooks/ralph-loop/index.ts
26642
26824
  init_agent_display_names();
26643
26825
  function getMessageDir4(sessionID) {
26644
- if (!existsSync34(MESSAGE_STORAGE))
26826
+ if (!existsSync35(MESSAGE_STORAGE))
26645
26827
  return null;
26646
- const directPath = join46(MESSAGE_STORAGE, sessionID);
26647
- if (existsSync34(directPath))
26828
+ const directPath = join47(MESSAGE_STORAGE, sessionID);
26829
+ if (existsSync35(directPath))
26648
26830
  return directPath;
26649
26831
  for (const dir of readdirSync8(MESSAGE_STORAGE)) {
26650
- const sessionPath = join46(MESSAGE_STORAGE, dir, sessionID);
26651
- if (existsSync34(sessionPath))
26832
+ const sessionPath = join47(MESSAGE_STORAGE, dir, sessionID);
26833
+ if (existsSync35(sessionPath))
26652
26834
  return sessionPath;
26653
26835
  }
26654
26836
  return null;
@@ -26685,9 +26867,9 @@ function createRalphLoopHook(ctx, options) {
26685
26867
  if (!transcriptPath)
26686
26868
  return false;
26687
26869
  try {
26688
- if (!existsSync34(transcriptPath))
26870
+ if (!existsSync35(transcriptPath))
26689
26871
  return false;
26690
- const content = readFileSync26(transcriptPath, "utf-8");
26872
+ const content = readFileSync27(transcriptPath, "utf-8");
26691
26873
  const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
26692
26874
  const lines = content.split(`
26693
26875
  `).filter((l) => l.trim());
@@ -27001,12 +27183,12 @@ function extractPromptText3(parts) {
27001
27183
  // src/hooks/auto-slash-command/executor.ts
27002
27184
  init_shared();
27003
27185
  init_file_utils();
27004
- import { existsSync as existsSync36, readdirSync as readdirSync9, readFileSync as readFileSync28 } from "fs";
27005
- import { join as join47, basename as basename2, dirname as dirname8 } from "path";
27186
+ import { existsSync as existsSync37, readdirSync as readdirSync9, readFileSync as readFileSync29 } from "fs";
27187
+ import { join as join48, basename as basename2, dirname as dirname8 } from "path";
27006
27188
  // src/features/opencode-skill-loader/merger.ts
27007
27189
  init_frontmatter();
27008
27190
  init_deep_merge();
27009
- import { readFileSync as readFileSync27, existsSync as existsSync35 } from "fs";
27191
+ import { readFileSync as readFileSync28, existsSync as existsSync36 } from "fs";
27010
27192
  import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
27011
27193
  import { homedir as homedir12 } from "os";
27012
27194
  import { createHash as createHash2 } from "crypto";
@@ -27055,9 +27237,9 @@ function resolveFilePath2(from, configDir) {
27055
27237
  }
27056
27238
  function loadSkillFromFile(filePath) {
27057
27239
  try {
27058
- if (!existsSync35(filePath))
27240
+ if (!existsSync36(filePath))
27059
27241
  return null;
27060
- const content = readFileSync27(filePath, "utf-8");
27242
+ const content = readFileSync28(filePath, "utf-8");
27061
27243
  const { data, body } = parseFrontmatter(content);
27062
27244
  return { template: body, metadata: data };
27063
27245
  } catch {
@@ -27255,7 +27437,7 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
27255
27437
  }
27256
27438
  // src/hooks/auto-slash-command/executor.ts
27257
27439
  function discoverCommandsFromDir(commandsDir, scope) {
27258
- if (!existsSync36(commandsDir)) {
27440
+ if (!existsSync37(commandsDir)) {
27259
27441
  return [];
27260
27442
  }
27261
27443
  const entries = readdirSync9(commandsDir, { withFileTypes: true });
@@ -27263,10 +27445,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
27263
27445
  for (const entry of entries) {
27264
27446
  if (!isMarkdownFile(entry))
27265
27447
  continue;
27266
- const commandPath = join47(commandsDir, entry.name);
27448
+ const commandPath = join48(commandsDir, entry.name);
27267
27449
  const commandName = basename2(entry.name, ".md");
27268
27450
  try {
27269
- const content = readFileSync28(commandPath, "utf-8");
27451
+ const content = readFileSync29(commandPath, "utf-8");
27270
27452
  const { data, body } = parseFrontmatter(content);
27271
27453
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
27272
27454
  const metadata = {
@@ -27309,10 +27491,10 @@ function skillToCommandInfo(skill) {
27309
27491
  }
27310
27492
  async function discoverAllCommands(options) {
27311
27493
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
27312
- const userCommandsDir = join47(getClaudeConfigDir(), "commands");
27313
- const projectCommandsDir = join47(process.cwd(), ".claude", "commands");
27314
- const opencodeGlobalDir = join47(configDir, "command");
27315
- const opencodeProjectDir = join47(process.cwd(), ".opencode", "command");
27494
+ const userCommandsDir = join48(getClaudeConfigDir(), "commands");
27495
+ const projectCommandsDir = join48(process.cwd(), ".claude", "commands");
27496
+ const opencodeGlobalDir = join48(configDir, "command");
27497
+ const opencodeProjectDir = join48(process.cwd(), ".opencode", "command");
27316
27498
  const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
27317
27499
  const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
27318
27500
  const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
@@ -27590,6 +27772,7 @@ ${createSystemDirective(SystemDirectiveTypes.PROMETHEUS_READ_ONLY)}
27590
27772
  init_logger();
27591
27773
  init_system_directive();
27592
27774
  init_agent_display_names();
27775
+ init_agent_identity_resolver();
27593
27776
  function normalizeWindowsDriveLetter(path7) {
27594
27777
  if (process.platform !== "win32")
27595
27778
  return path7;
@@ -27669,24 +27852,10 @@ function extractRedirectTargets(command) {
27669
27852
  }
27670
27853
  var TASK_TOOLS = ["delegate_task", "task", "call_omo_agent"];
27671
27854
  function getAgentFromSession(sessionID) {
27672
- const staleThresholdMs = 600000;
27673
- const isStale = isSessionAgentStale(sessionID, staleThresholdMs);
27674
- if (isStale) {
27675
- log(`[${HOOK_NAME4}] Session agent is stale, refreshing from message files`, {
27676
- sessionID,
27677
- staleThresholdMs
27678
- });
27679
- const messageFileAgent = getAgentFromSessionMessages(sessionID);
27680
- if (messageFileAgent) {
27681
- updateSessionAgent(sessionID, messageFileAgent, "stale-refresh");
27682
- log(`[${HOOK_NAME4}] Refreshed stale agent`, {
27683
- sessionID,
27684
- agent: messageFileAgent
27685
- });
27686
- return messageFileAgent;
27687
- }
27688
- }
27689
- return getSessionAgent(sessionID) ?? getAgentFromSessionMessages(sessionID);
27855
+ return resolveCurrentAgent(sessionID, undefined, {
27856
+ staleThresholdMs: 600000,
27857
+ getAgentFromSessionMessages
27858
+ });
27690
27859
  }
27691
27860
  function createPrometheusMdOnlyHook(ctx) {
27692
27861
  return {
@@ -27825,8 +27994,8 @@ var NOTEPAD_DIR = "notepads";
27825
27994
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
27826
27995
  var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
27827
27996
  // src/features/boulder-state/storage.ts
27828
- import { existsSync as existsSync37, readFileSync as readFileSync29, writeFileSync as writeFileSync19, mkdirSync as mkdirSync16, readdirSync as readdirSync10, renameSync as renameSync2, unlinkSync as unlinkSync12, statSync as statSync4 } from "fs";
27829
- import { dirname as dirname9, join as join49, basename as basename3 } from "path";
27997
+ import { existsSync as existsSync38, readFileSync as readFileSync30, writeFileSync as writeFileSync20, mkdirSync as mkdirSync17, readdirSync as readdirSync10, renameSync as renameSync2, unlinkSync as unlinkSync12, statSync as statSync4 } from "fs";
27998
+ import { dirname as dirname9, join as join50, basename as basename3 } from "path";
27830
27999
  init_logger();
27831
28000
 
27832
28001
  // src/features/boulder-state/event-bus.ts
@@ -27909,7 +28078,7 @@ function retryOnWindowsError(fn) {
27909
28078
  throw lastError;
27910
28079
  }
27911
28080
  function getBoulderFilePath(directory) {
27912
- return join49(directory, BOULDER_DIR, BOULDER_FILE);
28081
+ return join50(directory, BOULDER_DIR, BOULDER_FILE);
27913
28082
  }
27914
28083
  function isValidBoulderStateSchema(state2) {
27915
28084
  if (typeof state2 !== "object" || state2 === null) {
@@ -27938,11 +28107,11 @@ function isValidVersion(version) {
27938
28107
  }
27939
28108
  function readBoulderState(directory) {
27940
28109
  const filePath = getBoulderFilePath(directory);
27941
- if (!existsSync37(filePath)) {
28110
+ if (!existsSync38(filePath)) {
27942
28111
  return null;
27943
28112
  }
27944
28113
  try {
27945
- const content = readFileSync29(filePath, "utf-8");
28114
+ const content = readFileSync30(filePath, "utf-8");
27946
28115
  const state2 = JSON.parse(content);
27947
28116
  if (state2.version === undefined || state2.version === null) {
27948
28117
  state2.version = 0;
@@ -27973,14 +28142,14 @@ function tryRestoreFromBackup(directory) {
27973
28142
  }
27974
28143
  function backupBoulderState(directory) {
27975
28144
  const filePath = getBoulderFilePath(directory);
27976
- if (!existsSync37(filePath)) {
28145
+ if (!existsSync38(filePath)) {
27977
28146
  return true;
27978
28147
  }
27979
28148
  try {
27980
28149
  const dir = dirname9(filePath);
27981
28150
  const timestamp = Date.now();
27982
- const backupPath = join49(dir, `${BACKUP_PREFIX}${timestamp}`);
27983
- writeFileSync19(backupPath, readFileSync29(filePath, "utf-8"), "utf-8");
28151
+ const backupPath = join50(dir, `${BACKUP_PREFIX}${timestamp}`);
28152
+ writeFileSync20(backupPath, readFileSync30(filePath, "utf-8"), "utf-8");
27984
28153
  log(`Created boulder state backup: ${backupPath}`);
27985
28154
  cleanupOldBackups(dir);
27986
28155
  return true;
@@ -27993,7 +28162,7 @@ function cleanupOldBackups(dir) {
27993
28162
  const files = readdirSync10(dir);
27994
28163
  const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
27995
28164
  name: f,
27996
- path: join49(dir, f),
28165
+ path: join50(dir, f),
27997
28166
  timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
27998
28167
  })).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
27999
28168
  for (const file of backupFiles.slice(MAX_BACKUPS)) {
@@ -28005,25 +28174,25 @@ function cleanupOldBackups(dir) {
28005
28174
  } catch {}
28006
28175
  }
28007
28176
  function restoreBoulderState(directory) {
28008
- const dir = join49(directory, BOULDER_DIR);
28009
- if (!existsSync37(dir)) {
28177
+ const dir = join50(directory, BOULDER_DIR);
28178
+ if (!existsSync38(dir)) {
28010
28179
  return null;
28011
28180
  }
28012
28181
  try {
28013
28182
  const files = readdirSync10(dir);
28014
28183
  const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
28015
28184
  name: f,
28016
- path: join49(dir, f),
28185
+ path: join50(dir, f),
28017
28186
  timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
28018
28187
  })).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
28019
28188
  if (backupFiles.length === 0) {
28020
28189
  return null;
28021
28190
  }
28022
28191
  const latestBackup = backupFiles[0];
28023
- const content = readFileSync29(latestBackup.path, "utf-8");
28192
+ const content = readFileSync30(latestBackup.path, "utf-8");
28024
28193
  const state2 = JSON.parse(content);
28025
28194
  const filePath = getBoulderFilePath(directory);
28026
- writeFileSync19(filePath, content, "utf-8");
28195
+ writeFileSync20(filePath, content, "utf-8");
28027
28196
  log(`Restored boulder state from backup: ${latestBackup.path}`);
28028
28197
  return state2;
28029
28198
  } catch {
@@ -28034,17 +28203,17 @@ function writeBoulderState(directory, state2) {
28034
28203
  const filePath = getBoulderFilePath(directory);
28035
28204
  try {
28036
28205
  const dir = dirname9(filePath);
28037
- if (!existsSync37(dir)) {
28038
- mkdirSync16(dir, { recursive: true });
28206
+ if (!existsSync38(dir)) {
28207
+ mkdirSync17(dir, { recursive: true });
28039
28208
  }
28040
28209
  backupBoulderState(directory);
28041
28210
  const tmpPath = `${filePath}.tmp.${process.pid}`;
28042
28211
  try {
28043
- writeFileSync19(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
28212
+ writeFileSync20(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
28044
28213
  retryOnWindowsError(() => renameSync2(tmpPath, filePath));
28045
28214
  } finally {
28046
28215
  try {
28047
- if (existsSync37(tmpPath)) {
28216
+ if (existsSync38(tmpPath)) {
28048
28217
  unlinkSync12(tmpPath);
28049
28218
  }
28050
28219
  } catch {}
@@ -28098,7 +28267,7 @@ function markBoulderPlanCompleted(directory, completedAt) {
28098
28267
  function clearBoulderState(directory) {
28099
28268
  const filePath = getBoulderFilePath(directory);
28100
28269
  try {
28101
- if (existsSync37(filePath)) {
28270
+ if (existsSync38(filePath)) {
28102
28271
  const { unlinkSync: unlinkSync13 } = __require("fs");
28103
28272
  unlinkSync13(filePath);
28104
28273
  }
@@ -28108,13 +28277,13 @@ function clearBoulderState(directory) {
28108
28277
  }
28109
28278
  }
28110
28279
  function findPrometheusPlans(directory) {
28111
- const plansDir = join49(directory, PROMETHEUS_PLANS_DIR);
28112
- if (!existsSync37(plansDir)) {
28280
+ const plansDir = join50(directory, PROMETHEUS_PLANS_DIR);
28281
+ if (!existsSync38(plansDir)) {
28113
28282
  return [];
28114
28283
  }
28115
28284
  try {
28116
28285
  const files = readdirSync10(plansDir);
28117
- return files.filter((f) => f.endsWith(".md")).map((f) => join49(plansDir, f)).sort((a, b) => {
28286
+ return files.filter((f) => f.endsWith(".md")).map((f) => join50(plansDir, f)).sort((a, b) => {
28118
28287
  const aStat = __require("fs").statSync(a);
28119
28288
  const bStat = __require("fs").statSync(b);
28120
28289
  return bStat.mtimeMs - aStat.mtimeMs;
@@ -28124,11 +28293,11 @@ function findPrometheusPlans(directory) {
28124
28293
  }
28125
28294
  }
28126
28295
  function getPlanProgress(planPath) {
28127
- if (!existsSync37(planPath)) {
28296
+ if (!existsSync38(planPath)) {
28128
28297
  return { total: 0, completed: 0, isComplete: false };
28129
28298
  }
28130
28299
  try {
28131
- const content = readFileSync29(planPath, "utf-8");
28300
+ const content = readFileSync30(planPath, "utf-8");
28132
28301
  if (!content.trim()) {
28133
28302
  return { total: 0, completed: 0, isComplete: false };
28134
28303
  }
@@ -28158,8 +28327,8 @@ function createBoulderState(planPath, sessionId) {
28158
28327
  };
28159
28328
  }
28160
28329
  function cleanupStaleTmpFiles(directory) {
28161
- const boulderDir = join49(directory, BOULDER_DIR);
28162
- if (!existsSync37(boulderDir)) {
28330
+ const boulderDir = join50(directory, BOULDER_DIR);
28331
+ if (!existsSync38(boulderDir)) {
28163
28332
  return;
28164
28333
  }
28165
28334
  try {
@@ -28169,7 +28338,7 @@ function cleanupStaleTmpFiles(directory) {
28169
28338
  if (!file.startsWith(`${BOULDER_FILE}.tmp.`)) {
28170
28339
  continue;
28171
28340
  }
28172
- const filePath = join49(boulderDir, file);
28341
+ const filePath = join50(boulderDir, file);
28173
28342
  try {
28174
28343
  const stat = statSync4(filePath);
28175
28344
  if (now - stat.mtimeMs > STALE_TMP_THRESHOLD_MS) {
@@ -28183,7 +28352,7 @@ function cleanupStaleTmpFiles(directory) {
28183
28352
  // src/features/boulder-state/checkbox-utils.ts
28184
28353
  init_logger();
28185
28354
  import { appendFileSync as appendFileSync7 } from "fs";
28186
- import { join as join50 } from "path";
28355
+ import { join as join51 } from "path";
28187
28356
  function parseCheckboxes(content) {
28188
28357
  const lines = content.split(`
28189
28358
  `);
@@ -28225,6 +28394,15 @@ function findMatchingCheckbox(taskDescription, checkboxes) {
28225
28394
  bestMatch = checkbox;
28226
28395
  }
28227
28396
  }
28397
+ if (bestMatch === null && incompleteCheckboxes.length > 0) {
28398
+ const fallbackMatch = incompleteCheckboxes[0];
28399
+ log(`[checkbox-utils] Fallback match: using first incomplete checkbox`, {
28400
+ taskDescription: taskDescription.substring(0, 80),
28401
+ fallbackText: fallbackMatch.text,
28402
+ checkboxIndex: fallbackMatch.index
28403
+ });
28404
+ return fallbackMatch.index;
28405
+ }
28228
28406
  return bestMatch?.index ?? -1;
28229
28407
  }
28230
28408
  function extractTaskFromPrompt(prompt) {
@@ -28244,7 +28422,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
28244
28422
  checkboxCount: checkboxes.length,
28245
28423
  planName
28246
28424
  });
28247
- const notepadPath = join50(directory, ".sisyphus", "notepads", planName, "match-failures.md");
28425
+ const notepadPath = join51(directory, ".sisyphus", "notepads", planName, "match-failures.md");
28248
28426
  const entry = `
28249
28427
  ## ${new Date().toISOString()}
28250
28428
  **\u4EFB\u52A1\u63CF\u8FF0**\uFF1A${taskDescription}
@@ -28256,6 +28434,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
28256
28434
  }
28257
28435
  // src/hooks/start-work/index.ts
28258
28436
  init_logger();
28437
+ init_claude_code_session_state();
28259
28438
  init_agent_display_names();
28260
28439
  var HOOK_NAME5 = "start-work";
28261
28440
  var KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi;
@@ -28483,8 +28662,9 @@ ${contextInfo}`;
28483
28662
  }
28484
28663
  // src/hooks/atlas/index.ts
28485
28664
  import { execSync } from "child_process";
28486
- import { existsSync as existsSync38, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as readFileSync30, renameSync as renameSync3, writeFileSync as writeFileSync20 } from "fs";
28487
- import { join as join51 } from "path";
28665
+ import { existsSync as existsSync39, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as readFileSync31, renameSync as renameSync3, writeFileSync as writeFileSync21 } from "fs";
28666
+ import { join as join52 } from "path";
28667
+ init_claude_code_session_state();
28488
28668
  init_logger();
28489
28669
  init_system_directive();
28490
28670
  init_agent_display_names();
@@ -28646,7 +28826,7 @@ function acquirePlanFileLock(planPath, maxRetries = 8, retryDelayMs = 125) {
28646
28826
  for (let attempt = 0;attempt < maxRetries; attempt++) {
28647
28827
  try {
28648
28828
  const fd = openSync(lockPath, "wx");
28649
- writeFileSync20(fd, String(process.pid));
28829
+ writeFileSync21(fd, String(process.pid));
28650
28830
  closeSync(fd);
28651
28831
  log(`[${HOOK_NAME6}] Acquired file lock for ${planPath}`);
28652
28832
  return true;
@@ -28684,12 +28864,12 @@ function writePlanFileAtomic(planPath, content) {
28684
28864
  try {
28685
28865
  const tmpPath = `${planPath}.tmp.${process.pid}`;
28686
28866
  try {
28687
- writeFileSync20(tmpPath, content, "utf-8");
28867
+ writeFileSync21(tmpPath, content, "utf-8");
28688
28868
  retryOnWindowsError(() => renameSync3(tmpPath, planPath));
28689
28869
  return true;
28690
28870
  } finally {
28691
28871
  try {
28692
- if (existsSync38(tmpPath)) {
28872
+ if (existsSync39(tmpPath)) {
28693
28873
  unlinkSync13(tmpPath);
28694
28874
  }
28695
28875
  } catch {}
@@ -28705,7 +28885,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
28705
28885
  }
28706
28886
  const planPath = boulderState.active_plan;
28707
28887
  try {
28708
- const planContent = readFileSync30(planPath, "utf-8");
28888
+ const planContent = readFileSync31(planPath, "utf-8");
28709
28889
  const checkboxes = parseCheckboxes(planContent);
28710
28890
  const lines = planContent.split(`
28711
28891
  `);
@@ -28726,7 +28906,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
28726
28906
  const updatedContent = lines.join(`
28727
28907
  `);
28728
28908
  if (!writePlanFileAtomic(planPath, updatedContent)) {
28729
- retryOnWindowsError(() => writeFileSync20(planPath, updatedContent, "utf-8"));
28909
+ retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
28730
28910
  log(`[${HOOK_NAME6}] Dual-track sync: atomic write failed, fell back to direct write`, {
28731
28911
  plan: boulderState.plan_name
28732
28912
  });
@@ -28771,22 +28951,15 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
28771
28951
 
28772
28952
  ${buildVerificationReminder(sessionId)}
28773
28953
 
28774
- **\u6B65\u9AA4 4\uFF1A\u5728\u8BA1\u5212\u6587\u4EF6\u4E2D\u6807\u8BB0\u5B8C\u6210\uFF08\u7ACB\u5373\u6267\u884C\uFF09**
28954
+ **\u2705 \u7CFB\u7EDF\u5DF2\u81EA\u52A8\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6\u4E2D\u7684\u590D\u9009\u6846\u3002**
28955
+ \u65E0\u9700\u624B\u52A8\u6807\u8BB0\u3002\u76F4\u63A5\u9A8C\u8BC1\u5B50\u4EE3\u7406\u7684\u5DE5\u4F5C\u5373\u53EF\u3002
28775
28956
 
28776
- \u73B0\u5728\u2014\u2014\u4E0D\u8981\u5EF6\u8FDF\u3002\u9A8C\u8BC1\u901A\u8FC7\u2192\u7ACB\u5373\u6807\u8BB0\u3002
28777
-
28778
- \u66F4\u65B0\u8BA1\u5212\u6587\u4EF6 \`.sisyphus/plans/${planName}.md\`\uFF1A
28779
- - \u5C06\u5DF2\u5B8C\u6210\u4EFB\u52A1\u7684 \`[ ]\` \u6539\u4E3A \`[x]\`
28780
- - \u4F7F\u7528 \`Edit\` \u5DE5\u5177\u4FEE\u6539\u590D\u9009\u6846
28781
-
28782
- **\u5728\u5176\u4ED6\u4EFB\u4F55\u4E8B\u60C5\u4E4B\u524D\u6267\u884C\u6B64\u64CD\u4F5C\u3002\u672A\u6807\u8BB0 = \u672A\u8DDF\u8E2A = \u8FDB\u5EA6\u4E22\u5931\u3002**
28783
-
28784
- **\u6B65\u9AA4 5\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
28957
+ **\u6B65\u9AA4 4\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
28785
28958
 
28786
28959
  - \u4EC5\u6682\u5B58\u5DF2\u9A8C\u8BC1\u7684\u66F4\u6539
28787
28960
  - \u4F7F\u7528\u6E05\u6670\u7684\u63D0\u4EA4\u4FE1\u606F\u63CF\u8FF0\u5B8C\u6210\u7684\u5185\u5BB9
28788
28961
 
28789
- **\u6B65\u9AA4 6\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
28962
+ **\u6B65\u9AA4 5\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
28790
28963
 
28791
28964
  - \u8BFB\u53D6\u8BA1\u5212\u6587\u4EF6\uFF0C\u627E\u5230\u4E0B\u4E00\u4E2A \`[ ]\` \u4EFB\u52A1
28792
28965
  - \u7ACB\u5373\u5F00\u59CB\u2014\u2014\u4E0D\u8981\u505C\u6B62
@@ -28923,14 +29096,14 @@ function formatFileChanges(stats, notepadPath) {
28923
29096
  `);
28924
29097
  }
28925
29098
  function getMessageDir5(sessionID) {
28926
- if (!existsSync38(MESSAGE_STORAGE))
29099
+ if (!existsSync39(MESSAGE_STORAGE))
28927
29100
  return null;
28928
- const directPath = join51(MESSAGE_STORAGE, sessionID);
28929
- if (existsSync38(directPath))
29101
+ const directPath = join52(MESSAGE_STORAGE, sessionID);
29102
+ if (existsSync39(directPath))
28930
29103
  return directPath;
28931
29104
  for (const dir of readdirSync11(MESSAGE_STORAGE)) {
28932
- const sessionPath = join51(MESSAGE_STORAGE, dir, sessionID);
28933
- if (existsSync38(sessionPath))
29105
+ const sessionPath = join52(MESSAGE_STORAGE, dir, sessionID);
29106
+ if (existsSync39(sessionPath))
28934
29107
  return sessionPath;
28935
29108
  }
28936
29109
  return null;
@@ -28944,6 +29117,45 @@ function isCallerOrchestrator(sessionID) {
28944
29117
  const nearest = findNearestAssistantMessage(messageDir);
28945
29118
  return agentNameMatches(nearest?.agent, "\u4EFB\u52A1\u7F16\u6392");
28946
29119
  }
29120
+ function isAgentCheckboxUpdater(agentName) {
29121
+ if (!agentName)
29122
+ return false;
29123
+ return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
29124
+ }
29125
+ function isActiveCheckboxUpdater(sessionID) {
29126
+ if (!sessionID)
29127
+ return false;
29128
+ const messageDir = getMessageDir5(sessionID);
29129
+ if (!messageDir)
29130
+ return false;
29131
+ const nearest = findNearestAssistantMessage(messageDir);
29132
+ return isAgentCheckboxUpdater(nearest?.agent);
29133
+ }
29134
+ function isAgentContinuationTrigger(agentName) {
29135
+ if (!agentName)
29136
+ return false;
29137
+ return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
29138
+ }
29139
+ function isActiveContinuationTrigger(sessionID, directory) {
29140
+ if (!sessionID)
29141
+ return false;
29142
+ const messageDir = getMessageDir5(sessionID);
29143
+ if (messageDir) {
29144
+ const nearest = findNearestAssistantMessage(messageDir);
29145
+ if (isAgentContinuationTrigger(nearest?.agent)) {
29146
+ return true;
29147
+ }
29148
+ }
29149
+ if (directory) {
29150
+ try {
29151
+ const boulderState = readBoulderState(directory);
29152
+ if (boulderState?.session_ids?.includes(sessionID)) {
29153
+ return true;
29154
+ }
29155
+ } catch {}
29156
+ }
29157
+ return false;
29158
+ }
28947
29159
  var CONTINUATION_COOLDOWN_MS = 5000;
28948
29160
  function isAbortError(error) {
28949
29161
  if (!error)
@@ -29108,8 +29320,8 @@ function createAtlasHook(ctx, options) {
29108
29320
  log(`[${HOOK_NAME6}] No active boulder`, { sessionID });
29109
29321
  return;
29110
29322
  }
29111
- if (!isCallerOrchestrator(sessionID)) {
29112
- log(`[${HOOK_NAME6}] Skipped: last agent is not Atlas`, { sessionID });
29323
+ if (!isActiveContinuationTrigger(sessionID, ctx.directory)) {
29324
+ log(`[${HOOK_NAME6}] Skipped: not eligible for continuation trigger`, { sessionID });
29113
29325
  return;
29114
29326
  }
29115
29327
  const progress = getPlanProgress(boulderState.active_plan);
@@ -29235,7 +29447,7 @@ function createAtlasHook(ctx, options) {
29235
29447
  }
29236
29448
  },
29237
29449
  "tool.execute.after": async (input, output) => {
29238
- if (!isCallerOrchestrator(input.sessionID)) {
29450
+ if (!isActiveCheckboxUpdater(input.sessionID)) {
29239
29451
  return;
29240
29452
  }
29241
29453
  if (WRITE_EDIT_TOOLS.includes(input.tool)) {
@@ -29297,7 +29509,7 @@ function createAtlasHook(ctx, options) {
29297
29509
  const taskDescription = extractTaskFromPrompt(savedPrompt || "");
29298
29510
  if (taskDescription) {
29299
29511
  try {
29300
- const planContent = readFileSync30(boulderState.active_plan, "utf-8");
29512
+ const planContent = readFileSync31(boulderState.active_plan, "utf-8");
29301
29513
  const checkboxes = parseCheckboxes(planContent);
29302
29514
  const checkboxIndex = findMatchingCheckbox(taskDescription, checkboxes);
29303
29515
  if (checkboxIndex >= 0) {
@@ -29309,7 +29521,7 @@ function createAtlasHook(ctx, options) {
29309
29521
  `);
29310
29522
  const planPath = boulderState.active_plan;
29311
29523
  if (!writePlanFileAtomic(planPath, updatedContent)) {
29312
- retryOnWindowsError(() => writeFileSync20(planPath, updatedContent, "utf-8"));
29524
+ retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
29313
29525
  log(`[${HOOK_NAME6}] Atomic plan write failed, fell back to direct write`, {
29314
29526
  plan: boulderState.plan_name
29315
29527
  });
@@ -29330,6 +29542,7 @@ function createAtlasHook(ctx, options) {
29330
29542
  });
29331
29543
  }
29332
29544
  }
29545
+ const updatedProgress = getPlanProgress(boulderState.active_plan);
29333
29546
  output.output = `
29334
29547
  ## \u5B50\u4EE3\u7406\u5DE5\u4F5C\u5DF2\u5B8C\u6210
29335
29548
 
@@ -29342,11 +29555,11 @@ ${fileChanges}
29342
29555
  ${originalResponse}
29343
29556
 
29344
29557
  <system-reminder>
29345
- ${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId)}
29558
+ ${buildOrchestratorReminder(boulderState.plan_name, updatedProgress, subagentSessionId)}
29346
29559
  </system-reminder>`;
29347
29560
  log(`[${HOOK_NAME6}] Output transformed for orchestrator mode (boulder)`, {
29348
29561
  plan: boulderState.plan_name,
29349
- progress: `${progress.completed}/${progress.total}`,
29562
+ progress: `${updatedProgress.completed}/${updatedProgress.total}`,
29350
29563
  fileCount: gitStats.length
29351
29564
  });
29352
29565
  } else {
@@ -30159,6 +30372,7 @@ init_usage_tracker();
30159
30372
  init_model_health_registry();
30160
30373
  init_runtime_fallback();
30161
30374
  init_agent_display_names();
30375
+ init_claude_code_session_state();
30162
30376
  async function withTimeout(promise, timeoutMs, label) {
30163
30377
  let timer;
30164
30378
  return Promise.race([
@@ -30942,6 +31156,7 @@ function evaluatePermission(input, agentName) {
30942
31156
 
30943
31157
  // src/hooks/permission-ask-bridge/index.ts
30944
31158
  init_logger();
31159
+ init_claude_code_session_state();
30945
31160
  function createPermissionAskBridgeHook(ctx) {
30946
31161
  return {
30947
31162
  "permission.ask": async (input, output) => {
@@ -30975,8 +31190,8 @@ function createShellEnvInjectorHook(_ctx) {
30975
31190
  // src/hooks/plan-completion/index.ts
30976
31191
  init_logger();
30977
31192
  init_frontmatter();
30978
- import { existsSync as existsSync39, readFileSync as readFileSync31, writeFileSync as writeFileSync21, mkdirSync as mkdirSync17, renameSync as renameSync4, unlinkSync as unlinkSync14 } from "fs";
30979
- import { join as join52 } from "path";
31193
+ import { existsSync as existsSync40, readFileSync as readFileSync32, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18, renameSync as renameSync4, unlinkSync as unlinkSync14 } from "fs";
31194
+ import { join as join53 } from "path";
30980
31195
  async function safeExecute(fn, name, onAction) {
30981
31196
  try {
30982
31197
  await fn();
@@ -31021,11 +31236,11 @@ function countListItems(content) {
31021
31236
  }
31022
31237
  async function updatePlanSummary(data) {
31023
31238
  log(`[plan-completion] updatePlanSummary: ${data.planName}`);
31024
- if (!existsSync39(data.planPath)) {
31239
+ if (!existsSync40(data.planPath)) {
31025
31240
  log(`[plan-completion] Plan file not found: ${data.planPath}`);
31026
31241
  return;
31027
31242
  }
31028
- const content = readFileSync31(data.planPath, "utf-8");
31243
+ const content = readFileSync32(data.planPath, "utf-8");
31029
31244
  const startedAt = data.boulderState?.started_at || "";
31030
31245
  const completedAt = data.boulderState?.completed_at || "";
31031
31246
  const duration = formatDuration(startedAt, completedAt);
@@ -31046,17 +31261,17 @@ async function updatePlanSummary(data) {
31046
31261
  | \u5B8C\u6210\u4EFB\u52A1\u6570 | ${completedTasks} |
31047
31262
  | \u5931\u8D25\u4EFB\u52A1\u6570 | ${failedTasks} |
31048
31263
  `;
31049
- writeFileSync21(data.planPath, content + summary, "utf-8");
31264
+ writeFileSync22(data.planPath, content + summary, "utf-8");
31050
31265
  log(`[plan-completion] Plan summary appended to ${data.planPath}`);
31051
31266
  }
31052
31267
  async function archivePlan(data) {
31053
31268
  log(`[plan-completion] archivePlan: ${data.planName}`);
31054
- const archivedDir = join52(data.directory, ".sisyphus", "archived");
31055
- if (!existsSync39(archivedDir)) {
31056
- mkdirSync17(archivedDir, { recursive: true });
31269
+ const archivedDir = join53(data.directory, ".sisyphus", "archived");
31270
+ if (!existsSync40(archivedDir)) {
31271
+ mkdirSync18(archivedDir, { recursive: true });
31057
31272
  }
31058
- if (existsSync39(data.planPath)) {
31059
- const archivedPath = join52(archivedDir, `${data.planName}.md`);
31273
+ if (existsSync40(data.planPath)) {
31274
+ const archivedPath = join53(archivedDir, `${data.planName}.md`);
31060
31275
  renameSync4(data.planPath, archivedPath);
31061
31276
  log(`[plan-completion] Plan archived to ${archivedPath}`);
31062
31277
  const boulderState = readBoulderState(data.directory);
@@ -31066,16 +31281,16 @@ async function archivePlan(data) {
31066
31281
  log(`[plan-completion] Updated boulder.json active_plan to ${archivedPath}`);
31067
31282
  }
31068
31283
  }
31069
- const draftPath = join52(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
31070
- if (existsSync39(draftPath)) {
31284
+ const draftPath = join53(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
31285
+ if (existsSync40(draftPath)) {
31071
31286
  unlinkSync14(draftPath);
31072
31287
  log(`[plan-completion] Deleted draft file: ${draftPath}`);
31073
31288
  }
31074
31289
  }
31075
31290
  async function extractLearnings(data) {
31076
31291
  log(`[plan-completion] extractLearnings: ${data.planName}`);
31077
- const notepadDir = join52(data.directory, ".sisyphus", "notepads", data.planName);
31078
- if (!existsSync39(notepadDir)) {
31292
+ const notepadDir = join53(data.directory, ".sisyphus", "notepads", data.planName);
31293
+ if (!existsSync40(notepadDir)) {
31079
31294
  log(`[plan-completion] Notepad directory not found: ${notepadDir}`);
31080
31295
  return;
31081
31296
  }
@@ -31085,9 +31300,9 @@ async function extractLearnings(data) {
31085
31300
  let totalIssues = 0;
31086
31301
  let totalDecisions = 0;
31087
31302
  for (const file of files) {
31088
- const filePath = join52(notepadDir, file);
31089
- if (existsSync39(filePath)) {
31090
- const content = readFileSync31(filePath, "utf-8");
31303
+ const filePath = join53(notepadDir, file);
31304
+ if (existsSync40(filePath)) {
31305
+ const content = readFileSync32(filePath, "utf-8");
31091
31306
  contents[file] = content;
31092
31307
  const count = countListItems(content);
31093
31308
  if (file === "learnings.md")
@@ -31098,9 +31313,9 @@ async function extractLearnings(data) {
31098
31313
  totalDecisions = count;
31099
31314
  }
31100
31315
  }
31101
- const learningsDir = join52(data.directory, ".sisyphus", "learnings");
31102
- if (!existsSync39(learningsDir)) {
31103
- mkdirSync17(learningsDir, { recursive: true });
31316
+ const learningsDir = join53(data.directory, ".sisyphus", "learnings");
31317
+ if (!existsSync40(learningsDir)) {
31318
+ mkdirSync18(learningsDir, { recursive: true });
31104
31319
  }
31105
31320
  const output = `# \u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3: ${data.planName}
31106
31321
 
@@ -31127,8 +31342,8 @@ ${contents["decisions.md"] || "\u65E0"}
31127
31342
 
31128
31343
  ${contents["match-failures.md"] || "\u65E0"}
31129
31344
  `;
31130
- const outputPath = join52(learningsDir, `${data.planName}.md`);
31131
- writeFileSync21(outputPath, output, "utf-8");
31345
+ const outputPath = join53(learningsDir, `${data.planName}.md`);
31346
+ writeFileSync22(outputPath, output, "utf-8");
31132
31347
  log(`[plan-completion] Learnings saved to ${outputPath}`);
31133
31348
  if (data.client?.tui?.showToast) {
31134
31349
  data.client.tui.showToast({
@@ -31147,9 +31362,9 @@ ${contents["match-failures.md"] || "\u65E0"}
31147
31362
  }
31148
31363
  async function generateReport(data) {
31149
31364
  log(`[plan-completion] generateReport: ${data.planName}`);
31150
- const reportsDir = join52(data.directory, ".sisyphus", "reports");
31151
- if (!existsSync39(reportsDir)) {
31152
- mkdirSync17(reportsDir, { recursive: true });
31365
+ const reportsDir = join53(data.directory, ".sisyphus", "reports");
31366
+ if (!existsSync40(reportsDir)) {
31367
+ mkdirSync18(reportsDir, { recursive: true });
31153
31368
  }
31154
31369
  const startedAt = data.boulderState?.started_at || "";
31155
31370
  const completedAt = data.boulderState?.completed_at || "";
@@ -31160,8 +31375,8 @@ async function generateReport(data) {
31160
31375
  const version = data.boulderState?.version || 0;
31161
31376
  const sessionCount = data.boulderState?.session_ids?.length || 0;
31162
31377
  const completedIndices = data.boulderState?.completed_task_indices || [];
31163
- const notepadPath = join52(data.directory, ".sisyphus", "notepads", data.planName);
31164
- const hasNotepad = existsSync39(notepadPath);
31378
+ const notepadPath = join53(data.directory, ".sisyphus", "notepads", data.planName);
31379
+ const hasNotepad = existsSync40(notepadPath);
31165
31380
  const report = `# \u8BA1\u5212\u5B8C\u6210\u62A5\u544A
31166
31381
 
31167
31382
  ## \u6982\u89C8
@@ -31200,8 +31415,8 @@ ${hasNotepad ? `## \u8BB0\u4E8B\u672C
31200
31415
  \u8BB0\u4E8B\u672C\u8DEF\u5F84: ${notepadPath}
31201
31416
  ` : ""}
31202
31417
  `;
31203
- const reportPath = join52(reportsDir, `${data.planName}.md`);
31204
- writeFileSync21(reportPath, report, "utf-8");
31418
+ const reportPath = join53(reportsDir, `${data.planName}.md`);
31419
+ writeFileSync22(reportPath, report, "utf-8");
31205
31420
  log(`[plan-completion] Report generated at ${reportPath}`);
31206
31421
  }
31207
31422
  async function runInitDeep(data) {
@@ -31311,6 +31526,7 @@ class ContextCollector {
31311
31526
  var contextCollector = new ContextCollector;
31312
31527
  // src/features/context-injector/injector.ts
31313
31528
  init_shared();
31529
+ init_claude_code_session_state();
31314
31530
  function createContextInjectorMessagesTransformHook(collector) {
31315
31531
  return {
31316
31532
  "experimental.chat.messages.transform": async (_input, output) => {
@@ -31412,8 +31628,8 @@ function createFirstMessageVariantGate() {
31412
31628
  }
31413
31629
  // src/features/claude-code-mcp-loader/loader.ts
31414
31630
  init_shared();
31415
- import { existsSync as existsSync40, readFileSync as readFileSync32 } from "fs";
31416
- import { join as join53 } from "path";
31631
+ import { existsSync as existsSync41, readFileSync as readFileSync33 } from "fs";
31632
+ import { join as join54 } from "path";
31417
31633
 
31418
31634
  // src/features/claude-code-mcp-loader/env-expander.ts
31419
31635
  function expandEnvVars(value) {
@@ -31483,13 +31699,13 @@ function getMcpConfigPaths() {
31483
31699
  const claudeConfigDir = getClaudeConfigDir();
31484
31700
  const cwd2 = process.cwd();
31485
31701
  return [
31486
- { path: join53(claudeConfigDir, ".mcp.json"), scope: "user" },
31487
- { path: join53(cwd2, ".mcp.json"), scope: "project" },
31488
- { path: join53(cwd2, ".claude", ".mcp.json"), scope: "local" }
31702
+ { path: join54(claudeConfigDir, ".mcp.json"), scope: "user" },
31703
+ { path: join54(cwd2, ".mcp.json"), scope: "project" },
31704
+ { path: join54(cwd2, ".claude", ".mcp.json"), scope: "local" }
31489
31705
  ];
31490
31706
  }
31491
31707
  async function loadMcpConfigFile(filePath) {
31492
- if (!existsSync40(filePath)) {
31708
+ if (!existsSync41(filePath)) {
31493
31709
  return null;
31494
31710
  }
31495
31711
  try {
@@ -31504,10 +31720,10 @@ function getSystemMcpServerNames() {
31504
31720
  const names = new Set;
31505
31721
  const paths = getMcpConfigPaths();
31506
31722
  for (const { path: path7 } of paths) {
31507
- if (!existsSync40(path7))
31723
+ if (!existsSync41(path7))
31508
31724
  continue;
31509
31725
  try {
31510
- const content = readFileSync32(path7, "utf-8");
31726
+ const content = readFileSync33(path7, "utf-8");
31511
31727
  const config = JSON.parse(content);
31512
31728
  if (!config?.mcpServers)
31513
31729
  continue;
@@ -31557,14 +31773,21 @@ async function loadMcpConfigs() {
31557
31773
  }
31558
31774
  return { servers, loadedServers };
31559
31775
  }
31776
+ // src/index.ts
31777
+ init_claude_code_session_state();
31778
+
31560
31779
  // src/features/claude-code-session-state/recovery.ts
31561
- import { existsSync as existsSync41, readdirSync as readdirSync13 } from "fs";
31562
- import { join as join54 } from "path";
31780
+ import { existsSync as existsSync42, readdirSync as readdirSync13 } from "fs";
31781
+ import { join as join55 } from "path";
31782
+ init_state();
31563
31783
  init_logger();
31564
- function recoverSessionAgents() {
31784
+ function recoverSessionAgents(directory) {
31565
31785
  let recoveredCount = 0;
31786
+ if (directory) {
31787
+ loadSessionAgentMap(directory);
31788
+ }
31566
31789
  try {
31567
- if (!existsSync41(MESSAGE_STORAGE)) {
31790
+ if (!existsSync42(MESSAGE_STORAGE)) {
31568
31791
  log("[recovery] MESSAGE_STORAGE directory does not exist", { path: MESSAGE_STORAGE });
31569
31792
  return 0;
31570
31793
  }
@@ -31572,13 +31795,13 @@ function recoverSessionAgents() {
31572
31795
  for (const entry of entries) {
31573
31796
  if (!entry.isDirectory())
31574
31797
  continue;
31575
- const projectDir = join54(MESSAGE_STORAGE, entry.name);
31798
+ const projectDir = join55(MESSAGE_STORAGE, entry.name);
31576
31799
  try {
31577
31800
  const sessionDirs = readdirSync13(projectDir, { withFileTypes: true });
31578
31801
  for (const sessionEntry of sessionDirs) {
31579
31802
  if (!sessionEntry.isDirectory())
31580
31803
  continue;
31581
- const sessionDir = join54(projectDir, sessionEntry.name);
31804
+ const sessionDir = join55(projectDir, sessionEntry.name);
31582
31805
  const sessionID = sessionEntry.name;
31583
31806
  try {
31584
31807
  const msg = findNearestAssistantMessage(sessionDir);
@@ -32004,14 +32227,14 @@ var EXT_TO_LANG = {
32004
32227
  ".gql": "graphql"
32005
32228
  };
32006
32229
  // src/tools/lsp/config.ts
32007
- import { existsSync as existsSync42, readFileSync as readFileSync33 } from "fs";
32008
- import { join as join55 } from "path";
32230
+ import { existsSync as existsSync43, readFileSync as readFileSync34 } from "fs";
32231
+ import { join as join56 } from "path";
32009
32232
  init_shared();
32010
32233
  function loadJsonFile(path7) {
32011
- if (!existsSync42(path7))
32234
+ if (!existsSync43(path7))
32012
32235
  return null;
32013
32236
  try {
32014
- return JSON.parse(readFileSync33(path7, "utf-8"));
32237
+ return JSON.parse(readFileSync34(path7, "utf-8"));
32015
32238
  } catch {
32016
32239
  return null;
32017
32240
  }
@@ -32020,9 +32243,9 @@ function getConfigPaths3() {
32020
32243
  const cwd2 = process.cwd();
32021
32244
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
32022
32245
  return {
32023
- project: join55(cwd2, ".opencode", "oh-my-opencode.json"),
32024
- user: join55(configDir, "oh-my-opencode.json"),
32025
- opencode: join55(configDir, "opencode.json")
32246
+ project: join56(cwd2, ".opencode", "oh-my-opencode.json"),
32247
+ user: join56(configDir, "oh-my-opencode.json"),
32248
+ opencode: join56(configDir, "opencode.json")
32026
32249
  };
32027
32250
  }
32028
32251
  function loadAllConfigs() {
@@ -32135,7 +32358,7 @@ function isServerInstalled(command) {
32135
32358
  return false;
32136
32359
  const cmd = command[0];
32137
32360
  if (cmd.includes("/") || cmd.includes("\\")) {
32138
- if (existsSync42(cmd))
32361
+ if (existsSync43(cmd))
32139
32362
  return true;
32140
32363
  }
32141
32364
  const isWindows2 = process.platform === "win32";
@@ -32157,23 +32380,23 @@ function isServerInstalled(command) {
32157
32380
  const paths = pathEnv.split(pathSeparator);
32158
32381
  for (const p of paths) {
32159
32382
  for (const suffix of exts) {
32160
- if (existsSync42(join55(p, cmd + suffix))) {
32383
+ if (existsSync43(join56(p, cmd + suffix))) {
32161
32384
  return true;
32162
32385
  }
32163
32386
  }
32164
32387
  }
32165
32388
  const cwd2 = process.cwd();
32166
32389
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
32167
- const dataDir = join55(getDataDir(), "opencode");
32390
+ const dataDir = join56(getDataDir(), "opencode");
32168
32391
  const additionalBases = [
32169
- join55(cwd2, "node_modules", ".bin"),
32170
- join55(configDir, "bin"),
32171
- join55(configDir, "node_modules", ".bin"),
32172
- join55(dataDir, "bin")
32392
+ join56(cwd2, "node_modules", ".bin"),
32393
+ join56(configDir, "bin"),
32394
+ join56(configDir, "node_modules", ".bin"),
32395
+ join56(dataDir, "bin")
32173
32396
  ];
32174
32397
  for (const base of additionalBases) {
32175
32398
  for (const suffix of exts) {
32176
- if (existsSync42(join55(base, cmd + suffix))) {
32399
+ if (existsSync43(join56(base, cmd + suffix))) {
32177
32400
  return true;
32178
32401
  }
32179
32402
  }
@@ -32185,7 +32408,7 @@ function isServerInstalled(command) {
32185
32408
  }
32186
32409
  // src/tools/lsp/client.ts
32187
32410
  var {spawn: spawn6 } = globalThis.Bun;
32188
- import { readFileSync as readFileSync34 } from "fs";
32411
+ import { readFileSync as readFileSync35 } from "fs";
32189
32412
  import { extname, resolve as resolve8 } from "path";
32190
32413
  import { pathToFileURL } from "url";
32191
32414
  class LSPServerManager {
@@ -32636,7 +32859,7 @@ ${msg}`);
32636
32859
  const absPath = resolve8(filePath);
32637
32860
  if (this.openedFiles.has(absPath))
32638
32861
  return;
32639
- const text = readFileSync34(absPath, "utf-8");
32862
+ const text = readFileSync35(absPath, "utf-8");
32640
32863
  const ext = extname(absPath);
32641
32864
  const languageId = getLanguageId(ext);
32642
32865
  this.notify("textDocument/didOpen", {
@@ -32726,17 +32949,17 @@ ${msg}`);
32726
32949
  // src/tools/lsp/utils.ts
32727
32950
  import { extname as extname2, resolve as resolve9 } from "path";
32728
32951
  import { fileURLToPath as fileURLToPath2 } from "url";
32729
- import { existsSync as existsSync43, readFileSync as readFileSync35, writeFileSync as writeFileSync22 } from "fs";
32952
+ import { existsSync as existsSync44, readFileSync as readFileSync36, writeFileSync as writeFileSync23 } from "fs";
32730
32953
  function findWorkspaceRoot(filePath) {
32731
32954
  let dir = resolve9(filePath);
32732
- if (!existsSync43(dir) || !__require("fs").statSync(dir).isDirectory()) {
32955
+ if (!existsSync44(dir) || !__require("fs").statSync(dir).isDirectory()) {
32733
32956
  dir = __require("path").dirname(dir);
32734
32957
  }
32735
32958
  const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
32736
32959
  let prevDir = "";
32737
32960
  while (dir !== prevDir) {
32738
32961
  for (const marker of markers) {
32739
- if (existsSync43(__require("path").join(dir, marker))) {
32962
+ if (existsSync44(__require("path").join(dir, marker))) {
32740
32963
  return dir;
32741
32964
  }
32742
32965
  }
@@ -32891,7 +33114,7 @@ function formatPrepareRenameResult(result) {
32891
33114
  }
32892
33115
  function applyTextEditsToFile(filePath, edits) {
32893
33116
  try {
32894
- let content = readFileSync35(filePath, "utf-8");
33117
+ let content = readFileSync36(filePath, "utf-8");
32895
33118
  const lines = content.split(`
32896
33119
  `);
32897
33120
  const sortedEdits = [...edits].sort((a, b) => {
@@ -32916,7 +33139,7 @@ function applyTextEditsToFile(filePath, edits) {
32916
33139
  `));
32917
33140
  }
32918
33141
  }
32919
- writeFileSync22(filePath, lines.join(`
33142
+ writeFileSync23(filePath, lines.join(`
32920
33143
  `), "utf-8");
32921
33144
  return { success: true, editCount: edits.length };
32922
33145
  } catch (err) {
@@ -32947,7 +33170,7 @@ function applyWorkspaceEdit(edit) {
32947
33170
  if (change.kind === "create") {
32948
33171
  try {
32949
33172
  const filePath = uriToPath(change.uri);
32950
- writeFileSync22(filePath, "", "utf-8");
33173
+ writeFileSync23(filePath, "", "utf-8");
32951
33174
  result.filesModified.push(filePath);
32952
33175
  } catch (err) {
32953
33176
  result.success = false;
@@ -32957,8 +33180,8 @@ function applyWorkspaceEdit(edit) {
32957
33180
  try {
32958
33181
  const oldPath = uriToPath(change.oldUri);
32959
33182
  const newPath = uriToPath(change.newUri);
32960
- const content = readFileSync35(oldPath, "utf-8");
32961
- writeFileSync22(newPath, content, "utf-8");
33183
+ const content = readFileSync36(oldPath, "utf-8");
33184
+ writeFileSync23(newPath, content, "utf-8");
32962
33185
  __require("fs").unlinkSync(oldPath);
32963
33186
  result.filesModified.push(newPath);
32964
33187
  } catch (err) {
@@ -45537,13 +45760,13 @@ var lsp_rename = tool({
45537
45760
  });
45538
45761
  // src/tools/ast-grep/constants.ts
45539
45762
  import { createRequire as createRequire4 } from "module";
45540
- import { dirname as dirname11, join as join57 } from "path";
45541
- import { existsSync as existsSync45, statSync as statSync5 } from "fs";
45763
+ import { dirname as dirname11, join as join58 } from "path";
45764
+ import { existsSync as existsSync46, statSync as statSync5 } from "fs";
45542
45765
 
45543
45766
  // src/tools/ast-grep/downloader.ts
45544
45767
  init_shared();
45545
- import { existsSync as existsSync44, mkdirSync as mkdirSync18, chmodSync as chmodSync2, unlinkSync as unlinkSync15 } from "fs";
45546
- import { join as join56 } from "path";
45768
+ import { existsSync as existsSync45, mkdirSync as mkdirSync19, chmodSync as chmodSync2, unlinkSync as unlinkSync15 } from "fs";
45769
+ import { join as join57 } from "path";
45547
45770
  import { homedir as homedir13 } from "os";
45548
45771
  import { createRequire as createRequire3 } from "module";
45549
45772
  var REPO2 = "ast-grep/ast-grep";
@@ -45569,19 +45792,19 @@ var PLATFORM_MAP2 = {
45569
45792
  function getCacheDir3() {
45570
45793
  if (process.platform === "win32") {
45571
45794
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
45572
- const base2 = localAppData || join56(homedir13(), "AppData", "Local");
45573
- return join56(base2, "oh-my-opencode", "bin");
45795
+ const base2 = localAppData || join57(homedir13(), "AppData", "Local");
45796
+ return join57(base2, "oh-my-opencode", "bin");
45574
45797
  }
45575
45798
  const xdgCache = process.env.XDG_CACHE_HOME;
45576
- const base = xdgCache || join56(homedir13(), ".cache");
45577
- return join56(base, "oh-my-opencode", "bin");
45799
+ const base = xdgCache || join57(homedir13(), ".cache");
45800
+ return join57(base, "oh-my-opencode", "bin");
45578
45801
  }
45579
45802
  function getBinaryName3() {
45580
45803
  return process.platform === "win32" ? "sg.exe" : "sg";
45581
45804
  }
45582
45805
  function getCachedBinaryPath2() {
45583
- const binaryPath = join56(getCacheDir3(), getBinaryName3());
45584
- return existsSync44(binaryPath) ? binaryPath : null;
45806
+ const binaryPath = join57(getCacheDir3(), getBinaryName3());
45807
+ return existsSync45(binaryPath) ? binaryPath : null;
45585
45808
  }
45586
45809
  async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45587
45810
  const platformKey = `${process.platform}-${process.arch}`;
@@ -45592,8 +45815,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45592
45815
  }
45593
45816
  const cacheDir = getCacheDir3();
45594
45817
  const binaryName = getBinaryName3();
45595
- const binaryPath = join56(cacheDir, binaryName);
45596
- if (existsSync44(binaryPath)) {
45818
+ const binaryPath = join57(cacheDir, binaryName);
45819
+ if (existsSync45(binaryPath)) {
45597
45820
  return binaryPath;
45598
45821
  }
45599
45822
  const { arch, os: os6 } = platformInfo;
@@ -45601,21 +45824,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45601
45824
  const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
45602
45825
  console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
45603
45826
  try {
45604
- if (!existsSync44(cacheDir)) {
45605
- mkdirSync18(cacheDir, { recursive: true });
45827
+ if (!existsSync45(cacheDir)) {
45828
+ mkdirSync19(cacheDir, { recursive: true });
45606
45829
  }
45607
45830
  const response = await fetch(downloadUrl, { redirect: "follow" });
45608
45831
  if (!response.ok) {
45609
45832
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
45610
45833
  }
45611
- const archivePath = join56(cacheDir, assetName);
45834
+ const archivePath = join57(cacheDir, assetName);
45612
45835
  const arrayBuffer = await response.arrayBuffer();
45613
45836
  await Bun.write(archivePath, arrayBuffer);
45614
45837
  await extractZip(archivePath, cacheDir);
45615
- if (existsSync44(archivePath)) {
45838
+ if (existsSync45(archivePath)) {
45616
45839
  unlinkSync15(archivePath);
45617
45840
  }
45618
- if (process.platform !== "win32" && existsSync44(binaryPath)) {
45841
+ if (process.platform !== "win32" && existsSync45(binaryPath)) {
45619
45842
  chmodSync2(binaryPath, 493);
45620
45843
  }
45621
45844
  console.log(`[oh-my-opencode] ast-grep binary ready.`);
@@ -45666,8 +45889,8 @@ function findSgCliPathSync() {
45666
45889
  const require2 = createRequire4(import.meta.url);
45667
45890
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
45668
45891
  const cliDir = dirname11(cliPkgPath);
45669
- const sgPath = join57(cliDir, binaryName);
45670
- if (existsSync45(sgPath) && isValidBinary(sgPath)) {
45892
+ const sgPath = join58(cliDir, binaryName);
45893
+ if (existsSync46(sgPath) && isValidBinary(sgPath)) {
45671
45894
  return sgPath;
45672
45895
  }
45673
45896
  } catch {}
@@ -45678,8 +45901,8 @@ function findSgCliPathSync() {
45678
45901
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
45679
45902
  const pkgDir = dirname11(pkgPath);
45680
45903
  const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
45681
- const binaryPath = join57(pkgDir, astGrepName);
45682
- if (existsSync45(binaryPath) && isValidBinary(binaryPath)) {
45904
+ const binaryPath = join58(pkgDir, astGrepName);
45905
+ if (existsSync46(binaryPath) && isValidBinary(binaryPath)) {
45683
45906
  return binaryPath;
45684
45907
  }
45685
45908
  } catch {}
@@ -45687,7 +45910,7 @@ function findSgCliPathSync() {
45687
45910
  if (process.platform === "darwin") {
45688
45911
  const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
45689
45912
  for (const path7 of homebrewPaths) {
45690
- if (existsSync45(path7) && isValidBinary(path7)) {
45913
+ if (existsSync46(path7) && isValidBinary(path7)) {
45691
45914
  return path7;
45692
45915
  }
45693
45916
  }
@@ -45742,11 +45965,11 @@ var DEFAULT_MAX_MATCHES = 500;
45742
45965
 
45743
45966
  // src/tools/ast-grep/cli.ts
45744
45967
  var {spawn: spawn7 } = globalThis.Bun;
45745
- import { existsSync as existsSync46 } from "fs";
45968
+ import { existsSync as existsSync47 } from "fs";
45746
45969
  var resolvedCliPath3 = null;
45747
45970
  var initPromise2 = null;
45748
45971
  async function getAstGrepPath() {
45749
- if (resolvedCliPath3 !== null && existsSync46(resolvedCliPath3)) {
45972
+ if (resolvedCliPath3 !== null && existsSync47(resolvedCliPath3)) {
45750
45973
  return resolvedCliPath3;
45751
45974
  }
45752
45975
  if (initPromise2) {
@@ -45754,7 +45977,7 @@ async function getAstGrepPath() {
45754
45977
  }
45755
45978
  initPromise2 = (async () => {
45756
45979
  const syncPath = findSgCliPathSync();
45757
- if (syncPath && existsSync46(syncPath)) {
45980
+ if (syncPath && existsSync47(syncPath)) {
45758
45981
  resolvedCliPath3 = syncPath;
45759
45982
  setSgCliPath(syncPath);
45760
45983
  return syncPath;
@@ -45788,7 +46011,7 @@ async function runSg(options) {
45788
46011
  const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
45789
46012
  args.push(...paths);
45790
46013
  let cliPath = getSgCliPath();
45791
- if (!existsSync46(cliPath) && cliPath !== "sg") {
46014
+ if (!existsSync47(cliPath) && cliPath !== "sg") {
45792
46015
  const downloadedPath = await getAstGrepPath();
45793
46016
  if (downloadedPath) {
45794
46017
  cliPath = downloadedPath;
@@ -46052,21 +46275,21 @@ var ast_grep_replace = tool({
46052
46275
  var {spawn: spawn9 } = globalThis.Bun;
46053
46276
 
46054
46277
  // src/tools/grep/constants.ts
46055
- import { existsSync as existsSync48 } from "fs";
46056
- import { join as join59, dirname as dirname12 } from "path";
46278
+ import { existsSync as existsSync49 } from "fs";
46279
+ import { join as join60, dirname as dirname12 } from "path";
46057
46280
  import { spawnSync as spawnSync2 } from "child_process";
46058
46281
 
46059
46282
  // src/tools/grep/downloader.ts
46060
46283
  init_shared();
46061
- import { existsSync as existsSync47, mkdirSync as mkdirSync19, chmodSync as chmodSync3, unlinkSync as unlinkSync16, readdirSync as readdirSync14 } from "fs";
46062
- import { join as join58 } from "path";
46284
+ import { existsSync as existsSync48, mkdirSync as mkdirSync20, chmodSync as chmodSync3, unlinkSync as unlinkSync16, readdirSync as readdirSync14 } from "fs";
46285
+ import { join as join59 } from "path";
46063
46286
  var {spawn: spawn8 } = globalThis.Bun;
46064
46287
  function findFileRecursive(dir, filename) {
46065
46288
  try {
46066
46289
  const entries = readdirSync14(dir, { withFileTypes: true, recursive: true });
46067
46290
  for (const entry of entries) {
46068
46291
  if (entry.isFile() && entry.name === filename) {
46069
- return join58(entry.parentPath ?? dir, entry.name);
46292
+ return join59(entry.parentPath ?? dir, entry.name);
46070
46293
  }
46071
46294
  }
46072
46295
  } catch {
@@ -46087,11 +46310,11 @@ function getPlatformKey() {
46087
46310
  }
46088
46311
  function getInstallDir() {
46089
46312
  const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
46090
- return join58(homeDir, ".cache", "oh-my-opencode", "bin");
46313
+ return join59(homeDir, ".cache", "oh-my-opencode", "bin");
46091
46314
  }
46092
46315
  function getRgPath() {
46093
46316
  const isWindows2 = process.platform === "win32";
46094
- return join58(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
46317
+ return join59(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
46095
46318
  }
46096
46319
  async function downloadFile(url2, destPath) {
46097
46320
  const response = await fetch(url2);
@@ -46125,7 +46348,7 @@ async function extractZip2(archivePath, destDir) {
46125
46348
  const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
46126
46349
  const foundPath = findFileRecursive(destDir, binaryName);
46127
46350
  if (foundPath) {
46128
- const destPath = join58(destDir, binaryName);
46351
+ const destPath = join59(destDir, binaryName);
46129
46352
  if (foundPath !== destPath) {
46130
46353
  const { renameSync: renameSync5 } = await import("fs");
46131
46354
  renameSync5(foundPath, destPath);
@@ -46140,13 +46363,13 @@ async function downloadAndInstallRipgrep() {
46140
46363
  }
46141
46364
  const installDir = getInstallDir();
46142
46365
  const rgPath = getRgPath();
46143
- if (existsSync47(rgPath)) {
46366
+ if (existsSync48(rgPath)) {
46144
46367
  return rgPath;
46145
46368
  }
46146
- mkdirSync19(installDir, { recursive: true });
46369
+ mkdirSync20(installDir, { recursive: true });
46147
46370
  const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
46148
46371
  const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
46149
- const archivePath = join58(installDir, filename);
46372
+ const archivePath = join59(installDir, filename);
46150
46373
  try {
46151
46374
  await downloadFile(url2, archivePath);
46152
46375
  if (config3.extension === "tar.gz") {
@@ -46157,12 +46380,12 @@ async function downloadAndInstallRipgrep() {
46157
46380
  if (process.platform !== "win32") {
46158
46381
  chmodSync3(rgPath, 493);
46159
46382
  }
46160
- if (!existsSync47(rgPath)) {
46383
+ if (!existsSync48(rgPath)) {
46161
46384
  throw new Error("\u63D0\u53D6\u540E\u672A\u627E\u5230 ripgrep \u4E8C\u8FDB\u5236\u6587\u4EF6");
46162
46385
  }
46163
46386
  return rgPath;
46164
46387
  } finally {
46165
- if (existsSync47(archivePath)) {
46388
+ if (existsSync48(archivePath)) {
46166
46389
  try {
46167
46390
  unlinkSync16(archivePath);
46168
46391
  } catch {}
@@ -46171,7 +46394,7 @@ async function downloadAndInstallRipgrep() {
46171
46394
  }
46172
46395
  function getInstalledRipgrepPath() {
46173
46396
  const rgPath = getRgPath();
46174
- return existsSync47(rgPath) ? rgPath : null;
46397
+ return existsSync48(rgPath) ? rgPath : null;
46175
46398
  }
46176
46399
 
46177
46400
  // src/tools/grep/constants.ts
@@ -46195,7 +46418,7 @@ function findExecutable(name) {
46195
46418
  continue;
46196
46419
  }
46197
46420
  }
46198
- if (existsSync48(trimmed)) {
46421
+ if (existsSync49(trimmed)) {
46199
46422
  return trimmed;
46200
46423
  }
46201
46424
  }
@@ -46210,14 +46433,14 @@ function getOpenCodeBundledRg() {
46210
46433
  const isWindows2 = process.platform === "win32";
46211
46434
  const rgName = isWindows2 ? "rg.exe" : "rg";
46212
46435
  const candidates = [
46213
- join59(getDataDir(), "opencode", "bin", rgName),
46214
- join59(execDir, rgName),
46215
- join59(execDir, "bin", rgName),
46216
- join59(execDir, "..", "bin", rgName),
46217
- join59(execDir, "..", "libexec", rgName)
46436
+ join60(getDataDir(), "opencode", "bin", rgName),
46437
+ join60(execDir, rgName),
46438
+ join60(execDir, "bin", rgName),
46439
+ join60(execDir, "..", "bin", rgName),
46440
+ join60(execDir, "..", "libexec", rgName)
46218
46441
  ];
46219
46442
  for (const candidate of candidates) {
46220
- if (existsSync48(candidate)) {
46443
+ if (existsSync49(candidate)) {
46221
46444
  return candidate;
46222
46445
  }
46223
46446
  }
@@ -46679,8 +46902,8 @@ var glob = tool({
46679
46902
  init_shared();
46680
46903
  init_file_utils();
46681
46904
  init_shared();
46682
- import { existsSync as existsSync49, readdirSync as readdirSync15, readFileSync as readFileSync36 } from "fs";
46683
- import { join as join60, basename as basename4, dirname as dirname13 } from "path";
46905
+ import { existsSync as existsSync50, readdirSync as readdirSync15, readFileSync as readFileSync37 } from "fs";
46906
+ import { join as join61, basename as basename4, dirname as dirname13 } from "path";
46684
46907
  // src/features/builtin-commands/templates/init-deep.ts
46685
46908
  var INIT_DEEP_TEMPLATE = `# /init-deep
46686
46909
 
@@ -47825,7 +48048,7 @@ function loadBuiltinCommands(disabledCommands) {
47825
48048
  }
47826
48049
  // src/tools/slashcommand/tools.ts
47827
48050
  function discoverCommandsFromDir2(commandsDir, scope) {
47828
- if (!existsSync49(commandsDir)) {
48051
+ if (!existsSync50(commandsDir)) {
47829
48052
  return [];
47830
48053
  }
47831
48054
  const entries = readdirSync15(commandsDir, { withFileTypes: true });
@@ -47833,10 +48056,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
47833
48056
  for (const entry of entries) {
47834
48057
  if (!isMarkdownFile(entry))
47835
48058
  continue;
47836
- const commandPath = join60(commandsDir, entry.name);
48059
+ const commandPath = join61(commandsDir, entry.name);
47837
48060
  const commandName = basename4(entry.name, ".md");
47838
48061
  try {
47839
- const content = readFileSync36(commandPath, "utf-8");
48062
+ const content = readFileSync37(commandPath, "utf-8");
47840
48063
  const { data, body } = parseFrontmatter(content);
47841
48064
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
47842
48065
  const metadata = {
@@ -47862,10 +48085,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
47862
48085
  }
47863
48086
  function discoverCommandsSync(disabledCommands) {
47864
48087
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
47865
- const userCommandsDir = join60(getClaudeConfigDir(), "commands");
47866
- const projectCommandsDir = join60(process.cwd(), ".claude", "commands");
47867
- const opencodeGlobalDir = join60(configDir, "command");
47868
- const opencodeProjectDir = join60(process.cwd(), ".opencode", "command");
48088
+ const userCommandsDir = join61(getClaudeConfigDir(), "commands");
48089
+ const projectCommandsDir = join61(process.cwd(), ".claude", "commands");
48090
+ const opencodeGlobalDir = join61(configDir, "command");
48091
+ const opencodeProjectDir = join61(process.cwd(), ".opencode", "command");
47869
48092
  const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
47870
48093
  const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
47871
48094
  const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
@@ -48065,13 +48288,13 @@ var slashcommand = createSlashcommandTool();
48065
48288
  // src/tools/session-manager/constants.ts
48066
48289
  init_data_path();
48067
48290
  init_shared();
48068
- import { join as join61 } from "path";
48291
+ import { join as join62 } from "path";
48069
48292
  var OPENCODE_STORAGE11 = getOpenCodeStorageDir();
48070
- var MESSAGE_STORAGE4 = join61(OPENCODE_STORAGE11, "message");
48071
- var PART_STORAGE4 = join61(OPENCODE_STORAGE11, "part");
48072
- var SESSION_STORAGE = join61(OPENCODE_STORAGE11, "session");
48073
- var TODO_DIR2 = join61(getClaudeConfigDir(), "todos");
48074
- var TRANSCRIPT_DIR2 = join61(getClaudeConfigDir(), "transcripts");
48293
+ var MESSAGE_STORAGE4 = join62(OPENCODE_STORAGE11, "message");
48294
+ var PART_STORAGE4 = join62(OPENCODE_STORAGE11, "part");
48295
+ var SESSION_STORAGE = join62(OPENCODE_STORAGE11, "session");
48296
+ var TODO_DIR2 = join62(getClaudeConfigDir(), "todos");
48297
+ var TRANSCRIPT_DIR2 = join62(getClaudeConfigDir(), "transcripts");
48075
48298
  var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
48076
48299
 
48077
48300
  \u8FD4\u56DE\u53EF\u7528\u7684 session ID \u5217\u8868\uFF0C\u5305\u542B\u6D88\u606F\u6570\u91CF\u3001\u65E5\u671F\u8303\u56F4\u548C\u4F7F\u7528\u8FC7\u7684 agents \u7B49\u5143\u6570\u636E\u3002
@@ -48144,11 +48367,11 @@ Has Todos: Yes (12 items, 8 completed)
48144
48367
  Has Transcript: Yes (234 entries)`;
48145
48368
 
48146
48369
  // src/tools/session-manager/storage.ts
48147
- import { existsSync as existsSync50, readdirSync as readdirSync16 } from "fs";
48370
+ import { existsSync as existsSync51, readdirSync as readdirSync16 } from "fs";
48148
48371
  import { readdir, readFile } from "fs/promises";
48149
- import { join as join62 } from "path";
48372
+ import { join as join63 } from "path";
48150
48373
  async function getMainSessions(options) {
48151
- if (!existsSync50(SESSION_STORAGE))
48374
+ if (!existsSync51(SESSION_STORAGE))
48152
48375
  return [];
48153
48376
  const sessions = [];
48154
48377
  try {
@@ -48156,13 +48379,13 @@ async function getMainSessions(options) {
48156
48379
  for (const projectDir of projectDirs) {
48157
48380
  if (!projectDir.isDirectory())
48158
48381
  continue;
48159
- const projectPath = join62(SESSION_STORAGE, projectDir.name);
48382
+ const projectPath = join63(SESSION_STORAGE, projectDir.name);
48160
48383
  const sessionFiles = await readdir(projectPath);
48161
48384
  for (const file2 of sessionFiles) {
48162
48385
  if (!file2.endsWith(".json"))
48163
48386
  continue;
48164
48387
  try {
48165
- const content = await readFile(join62(projectPath, file2), "utf-8");
48388
+ const content = await readFile(join63(projectPath, file2), "utf-8");
48166
48389
  const meta = JSON.parse(content);
48167
48390
  if (meta.parentID)
48168
48391
  continue;
@@ -48180,7 +48403,7 @@ async function getMainSessions(options) {
48180
48403
  return sessions.sort((a, b) => b.time.updated - a.time.updated);
48181
48404
  }
48182
48405
  async function getAllSessions() {
48183
- if (!existsSync50(MESSAGE_STORAGE4))
48406
+ if (!existsSync51(MESSAGE_STORAGE4))
48184
48407
  return [];
48185
48408
  const sessions = [];
48186
48409
  async function scanDirectory(dir) {
@@ -48188,7 +48411,7 @@ async function getAllSessions() {
48188
48411
  const entries = await readdir(dir, { withFileTypes: true });
48189
48412
  for (const entry of entries) {
48190
48413
  if (entry.isDirectory()) {
48191
- const sessionPath = join62(dir, entry.name);
48414
+ const sessionPath = join63(dir, entry.name);
48192
48415
  const files = await readdir(sessionPath);
48193
48416
  if (files.some((f) => f.endsWith(".json"))) {
48194
48417
  sessions.push(entry.name);
@@ -48205,16 +48428,16 @@ async function getAllSessions() {
48205
48428
  return [...new Set(sessions)];
48206
48429
  }
48207
48430
  function getMessageDir6(sessionID) {
48208
- if (!existsSync50(MESSAGE_STORAGE4))
48431
+ if (!existsSync51(MESSAGE_STORAGE4))
48209
48432
  return "";
48210
- const directPath = join62(MESSAGE_STORAGE4, sessionID);
48211
- if (existsSync50(directPath)) {
48433
+ const directPath = join63(MESSAGE_STORAGE4, sessionID);
48434
+ if (existsSync51(directPath)) {
48212
48435
  return directPath;
48213
48436
  }
48214
48437
  try {
48215
48438
  for (const dir of readdirSync16(MESSAGE_STORAGE4)) {
48216
- const sessionPath = join62(MESSAGE_STORAGE4, dir, sessionID);
48217
- if (existsSync50(sessionPath)) {
48439
+ const sessionPath = join63(MESSAGE_STORAGE4, dir, sessionID);
48440
+ if (existsSync51(sessionPath)) {
48218
48441
  return sessionPath;
48219
48442
  }
48220
48443
  }
@@ -48228,7 +48451,7 @@ function sessionExists(sessionID) {
48228
48451
  }
48229
48452
  async function readSessionMessages(sessionID) {
48230
48453
  const messageDir = getMessageDir6(sessionID);
48231
- if (!messageDir || !existsSync50(messageDir))
48454
+ if (!messageDir || !existsSync51(messageDir))
48232
48455
  return [];
48233
48456
  const messages = [];
48234
48457
  try {
@@ -48237,7 +48460,7 @@ async function readSessionMessages(sessionID) {
48237
48460
  if (!file2.endsWith(".json"))
48238
48461
  continue;
48239
48462
  try {
48240
- const content = await readFile(join62(messageDir, file2), "utf-8");
48463
+ const content = await readFile(join63(messageDir, file2), "utf-8");
48241
48464
  const meta = JSON.parse(content);
48242
48465
  const parts = await readParts2(meta.id);
48243
48466
  messages.push({
@@ -48263,8 +48486,8 @@ async function readSessionMessages(sessionID) {
48263
48486
  });
48264
48487
  }
48265
48488
  async function readParts2(messageID) {
48266
- const partDir = join62(PART_STORAGE4, messageID);
48267
- if (!existsSync50(partDir))
48489
+ const partDir = join63(PART_STORAGE4, messageID);
48490
+ if (!existsSync51(partDir))
48268
48491
  return [];
48269
48492
  const parts = [];
48270
48493
  try {
@@ -48273,7 +48496,7 @@ async function readParts2(messageID) {
48273
48496
  if (!file2.endsWith(".json"))
48274
48497
  continue;
48275
48498
  try {
48276
- const content = await readFile(join62(partDir, file2), "utf-8");
48499
+ const content = await readFile(join63(partDir, file2), "utf-8");
48277
48500
  parts.push(JSON.parse(content));
48278
48501
  } catch {
48279
48502
  continue;
@@ -48285,14 +48508,14 @@ async function readParts2(messageID) {
48285
48508
  return parts.sort((a, b) => a.id.localeCompare(b.id));
48286
48509
  }
48287
48510
  async function readSessionTodos(sessionID) {
48288
- if (!existsSync50(TODO_DIR2))
48511
+ if (!existsSync51(TODO_DIR2))
48289
48512
  return [];
48290
48513
  try {
48291
48514
  const allFiles = await readdir(TODO_DIR2);
48292
48515
  const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
48293
48516
  for (const file2 of todoFiles) {
48294
48517
  try {
48295
- const content = await readFile(join62(TODO_DIR2, file2), "utf-8");
48518
+ const content = await readFile(join63(TODO_DIR2, file2), "utf-8");
48296
48519
  const data = JSON.parse(content);
48297
48520
  if (Array.isArray(data)) {
48298
48521
  return data.map((item) => ({
@@ -48312,10 +48535,10 @@ async function readSessionTodos(sessionID) {
48312
48535
  return [];
48313
48536
  }
48314
48537
  async function readSessionTranscript(sessionID) {
48315
- if (!existsSync50(TRANSCRIPT_DIR2))
48538
+ if (!existsSync51(TRANSCRIPT_DIR2))
48316
48539
  return 0;
48317
- const transcriptFile = join62(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
48318
- if (!existsSync50(transcriptFile))
48540
+ const transcriptFile = join63(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
48541
+ if (!existsSync51(transcriptFile))
48319
48542
  return 0;
48320
48543
  try {
48321
48544
  const content = await readFile(transcriptFile, "utf-8");
@@ -49138,6 +49361,7 @@ var BACKGROUND_OUTPUT_DESCRIPTION = `\u83B7\u53D6\u540E\u53F0\u4EFB\u52A1\u7684\
49138
49361
  var BACKGROUND_CANCEL_DESCRIPTION = `\u53D6\u6D88\u6B63\u5728\u8FD0\u884C\u7684\u540E\u53F0\u4EFB\u52A1\u3002\u4F7F\u7528 all=true \u53EF\u5728\u6700\u7EC8\u56DE\u7B54\u524D\u53D6\u6D88\u6240\u6709\u4EFB\u52A1\u3002`;
49139
49362
 
49140
49363
  // src/tools/background-task/tools.ts
49364
+ init_claude_code_session_state();
49141
49365
  init_logger();
49142
49366
  init_session_cursor();
49143
49367
  init_agent_display_names();
@@ -49522,20 +49746,21 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
49522
49746
 
49523
49747
  \u4F20\u5165 \`session_id=<id>\` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684 agent\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002Prompts \u5FC5\u987B\u4E3A\u4E2D\u6587\u3002\u4F7F\u7528 \`background_output\` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002`;
49524
49748
  // src/tools/call-omo-agent/tools.ts
49525
- import { existsSync as existsSync51, readdirSync as readdirSync17 } from "fs";
49526
- import { join as join63 } from "path";
49749
+ import { existsSync as existsSync52, readdirSync as readdirSync17 } from "fs";
49750
+ import { join as join64 } from "path";
49527
49751
  init_shared();
49528
49752
  init_agent_display_names();
49529
49753
  init_session_cursor();
49754
+ init_claude_code_session_state();
49530
49755
  function getMessageDir7(sessionID) {
49531
- if (!existsSync51(MESSAGE_STORAGE))
49756
+ if (!existsSync52(MESSAGE_STORAGE))
49532
49757
  return null;
49533
- const directPath = join63(MESSAGE_STORAGE, sessionID);
49534
- if (existsSync51(directPath))
49758
+ const directPath = join64(MESSAGE_STORAGE, sessionID);
49759
+ if (existsSync52(directPath))
49535
49760
  return directPath;
49536
49761
  for (const dir of readdirSync17(MESSAGE_STORAGE)) {
49537
- const sessionPath = join63(MESSAGE_STORAGE, dir, sessionID);
49538
- if (existsSync51(sessionPath))
49762
+ const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
49763
+ if (existsSync52(sessionPath))
49539
49764
  return sessionPath;
49540
49765
  }
49541
49766
  return null;
@@ -49961,8 +50186,8 @@ function createLookAt(ctx) {
49961
50186
  }
49962
50187
  // src/tools/delegate-task/tools.ts
49963
50188
  init_constants();
49964
- import { existsSync as existsSync52, readdirSync as readdirSync18 } from "fs";
49965
- import { join as join64 } from "path";
50189
+ import { existsSync as existsSync53, readdirSync as readdirSync18 } from "fs";
50190
+ import { join as join65 } from "path";
49966
50191
 
49967
50192
  // src/features/task-toast-manager/manager.ts
49968
50193
  class TaskToastManager {
@@ -50138,10 +50363,12 @@ function initTaskToastManager(client2, concurrencyManager) {
50138
50363
  return instance;
50139
50364
  }
50140
50365
  // src/tools/delegate-task/tools.ts
50366
+ init_claude_code_session_state();
50141
50367
  init_shared();
50142
50368
  init_agent_display_names();
50143
50369
  init_runtime_fallback();
50144
50370
  init_model_health_registry();
50371
+ init_agent_identity_resolver();
50145
50372
  var SISYPHUS_JUNIOR_AGENT = "\u6267\u884C\u52A9\u7406";
50146
50373
  var MAX_LOOP_ATTEMPTS = 10;
50147
50374
  function sleep(ms) {
@@ -50168,14 +50395,14 @@ function parseFallbackModelEntries(entries) {
50168
50395
  });
50169
50396
  }
50170
50397
  function getMessageDir8(sessionID) {
50171
- if (!existsSync52(MESSAGE_STORAGE))
50398
+ if (!existsSync53(MESSAGE_STORAGE))
50172
50399
  return null;
50173
- const directPath = join64(MESSAGE_STORAGE, sessionID);
50174
- if (existsSync52(directPath))
50400
+ const directPath = join65(MESSAGE_STORAGE, sessionID);
50401
+ if (existsSync53(directPath))
50175
50402
  return directPath;
50176
50403
  for (const dir of readdirSync18(MESSAGE_STORAGE)) {
50177
- const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
50178
- if (existsSync52(sessionPath))
50404
+ const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
50405
+ if (existsSync53(sessionPath))
50179
50406
  return sessionPath;
50180
50407
  }
50181
50408
  return null;
@@ -50257,18 +50484,30 @@ function buildSystemContent(input) {
50257
50484
 
50258
50485
  `);
50259
50486
  }
50260
- function extractResumeInfoFromMessages(messages) {
50261
- let agent;
50262
- let model;
50487
+ function extractResumeInfoFromMessages(sessionID, messages) {
50488
+ const resolvedAgent = resolveCurrentAgent(sessionID);
50489
+ if (resolvedAgent) {
50490
+ for (let i = messages.length - 1;i >= 0; i--) {
50491
+ const info = messages[i].info;
50492
+ if (info?.model || info?.modelID && info?.providerID) {
50493
+ return {
50494
+ agent: resolvedAgent,
50495
+ model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
50496
+ };
50497
+ }
50498
+ }
50499
+ return { agent: resolvedAgent, model: undefined };
50500
+ }
50263
50501
  for (let i = messages.length - 1;i >= 0; i--) {
50264
50502
  const info = messages[i].info;
50265
50503
  if (info?.role === "assistant" && (info?.agent || info?.model || info?.modelID && info?.providerID)) {
50266
- agent = info.agent;
50267
- model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
50268
- break;
50504
+ return {
50505
+ agent: info.agent,
50506
+ model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
50507
+ };
50269
50508
  }
50270
50509
  }
50271
- return { agent, model };
50510
+ return { agent: undefined, model: undefined };
50272
50511
  }
50273
50512
  async function pollTaskCompletion(client2, sessionID, maxWaitMs = 120000, pollIntervalMs = 2000) {
50274
50513
  const startTime = Date.now();
@@ -50446,7 +50685,7 @@ Agent \u7EE7\u7EED\u6267\u884C\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u
50446
50685
  try {
50447
50686
  const messagesResp = await client2.session.messages({ path: { id: args.session_id } });
50448
50687
  const messages2 = messagesResp.data ?? [];
50449
- const resumeInfo = extractResumeInfoFromMessages(messages2);
50688
+ const resumeInfo = extractResumeInfoFromMessages(args.session_id, messages2);
50450
50689
  resumeAgent = resumeInfo.agent;
50451
50690
  resumeModel = resumeInfo.model;
50452
50691
  } catch {
@@ -51271,8 +51510,10 @@ class PerformanceAggregator {
51271
51510
  }
51272
51511
 
51273
51512
  // src/features/background-agent/manager.ts
51274
- import { existsSync as existsSync53, readdirSync as readdirSync19 } from "fs";
51275
- import { join as join65 } from "path";
51513
+ init_claude_code_session_state();
51514
+ init_agent_identity_resolver();
51515
+ import { existsSync as existsSync54, readdirSync as readdirSync19 } from "fs";
51516
+ import { join as join66 } from "path";
51276
51517
  var TASK_TTL_MS = 30 * 60 * 1000;
51277
51518
  var MIN_STABILITY_TIME_MS = 10 * 1000;
51278
51519
  var DEFAULT_STALE_TIMEOUT_MS = 120000;
@@ -52065,15 +52306,15 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
52065
52306
  \u4F7F\u7528 \`background_output(task_id="${task.id}")\` \u5728\u51C6\u5907\u5C31\u7EEA\u65F6\u83B7\u53D6\u6B64\u7ED3\u679C\u3002
52066
52307
  </system-reminder>`;
52067
52308
  }
52068
- let agent = task.parentAgent;
52309
+ const currentParentAgent = resolveCurrentAgent(task.parentSessionID);
52310
+ const agent = currentParentAgent ?? task.parentAgent;
52069
52311
  let model;
52070
52312
  try {
52071
52313
  const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionID } });
52072
52314
  const messages = messagesResp.data ?? [];
52073
52315
  for (let i = messages.length - 1;i >= 0; i--) {
52074
52316
  const info = messages[i].info;
52075
- if (info?.agent || info?.model || info?.modelID && info?.providerID) {
52076
- agent = info.agent ?? task.parentAgent;
52317
+ if (info?.model || info?.modelID && info?.providerID) {
52077
52318
  model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
52078
52319
  break;
52079
52320
  }
@@ -52081,7 +52322,6 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
52081
52322
  } catch {
52082
52323
  const messageDir = getMessageDir9(task.parentSessionID);
52083
52324
  const currentMessage = messageDir ? findNearestAssistantMessage(messageDir) : null;
52084
- agent = currentMessage?.agent ?? task.parentAgent;
52085
52325
  model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
52086
52326
  }
52087
52327
  log("[background-agent] notifyParentSession context:", {
@@ -52446,14 +52686,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
52446
52686
  return listener;
52447
52687
  }
52448
52688
  function getMessageDir9(sessionID) {
52449
- if (!existsSync53(MESSAGE_STORAGE))
52689
+ if (!existsSync54(MESSAGE_STORAGE))
52450
52690
  return null;
52451
- const directPath = join65(MESSAGE_STORAGE, sessionID);
52452
- if (existsSync53(directPath))
52691
+ const directPath = join66(MESSAGE_STORAGE, sessionID);
52692
+ if (existsSync54(directPath))
52453
52693
  return directPath;
52454
52694
  for (const dir of readdirSync19(MESSAGE_STORAGE)) {
52455
- const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
52456
- if (existsSync53(sessionPath))
52695
+ const sessionPath = join66(MESSAGE_STORAGE, dir, sessionID);
52696
+ if (existsSync54(sessionPath))
52457
52697
  return sessionPath;
52458
52698
  }
52459
52699
  return null;
@@ -71678,7 +71918,7 @@ init_file_utils();
71678
71918
  init_shared();
71679
71919
  init_logger();
71680
71920
  import { promises as fs11 } from "fs";
71681
- import { join as join67, basename as basename6 } from "path";
71921
+ import { join as join68, basename as basename6 } from "path";
71682
71922
  async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
71683
71923
  try {
71684
71924
  await fs11.access(commandsDir);
@@ -71708,7 +71948,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
71708
71948
  if (entry.isDirectory()) {
71709
71949
  if (entry.name.startsWith("."))
71710
71950
  continue;
71711
- const subDirPath = join67(commandsDir, entry.name);
71951
+ const subDirPath = join68(commandsDir, entry.name);
71712
71952
  const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
71713
71953
  const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
71714
71954
  commands2.push(...subCommands);
@@ -71716,7 +71956,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
71716
71956
  }
71717
71957
  if (!isMarkdownFile(entry))
71718
71958
  continue;
71719
- const commandPath = join67(commandsDir, entry.name);
71959
+ const commandPath = join68(commandsDir, entry.name);
71720
71960
  const baseCommandName = basename6(entry.name, ".md");
71721
71961
  const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
71722
71962
  try {
@@ -71763,23 +72003,23 @@ function commandsToRecord(commands2) {
71763
72003
  return result;
71764
72004
  }
71765
72005
  async function loadUserCommands() {
71766
- const userCommandsDir = join67(getClaudeConfigDir(), "commands");
72006
+ const userCommandsDir = join68(getClaudeConfigDir(), "commands");
71767
72007
  const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
71768
72008
  return commandsToRecord(commands2);
71769
72009
  }
71770
72010
  async function loadProjectCommands() {
71771
- const projectCommandsDir = join67(process.cwd(), ".claude", "commands");
72011
+ const projectCommandsDir = join68(process.cwd(), ".claude", "commands");
71772
72012
  const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
71773
72013
  return commandsToRecord(commands2);
71774
72014
  }
71775
72015
  async function loadOpencodeGlobalCommands() {
71776
72016
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
71777
- const opencodeCommandsDir = join67(configDir, "command");
72017
+ const opencodeCommandsDir = join68(configDir, "command");
71778
72018
  const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
71779
72019
  return commandsToRecord(commands2);
71780
72020
  }
71781
72021
  async function loadOpencodeProjectCommands() {
71782
- const opencodeProjectDir = join67(process.cwd(), ".opencode", "command");
72022
+ const opencodeProjectDir = join68(process.cwd(), ".opencode", "command");
71783
72023
  const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
71784
72024
  return commandsToRecord(commands2);
71785
72025
  }
@@ -71787,8 +72027,8 @@ async function loadOpencodeProjectCommands() {
71787
72027
  init_frontmatter();
71788
72028
  init_file_utils();
71789
72029
  init_shared();
71790
- import { existsSync as existsSync55, readdirSync as readdirSync20, readFileSync as readFileSync38 } from "fs";
71791
- import { join as join68, basename as basename7 } from "path";
72030
+ import { existsSync as existsSync56, readdirSync as readdirSync20, readFileSync as readFileSync39 } from "fs";
72031
+ import { join as join69, basename as basename7 } from "path";
71792
72032
  function parseToolsConfig(toolsStr) {
71793
72033
  if (!toolsStr)
71794
72034
  return;
@@ -71802,7 +72042,7 @@ function parseToolsConfig(toolsStr) {
71802
72042
  return result;
71803
72043
  }
71804
72044
  function loadAgentsFromDir(agentsDir, scope, leConfig) {
71805
- if (!existsSync55(agentsDir)) {
72045
+ if (!existsSync56(agentsDir)) {
71806
72046
  return [];
71807
72047
  }
71808
72048
  const entries = readdirSync20(agentsDir, { withFileTypes: true });
@@ -71810,10 +72050,10 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
71810
72050
  for (const entry of entries) {
71811
72051
  if (!isMarkdownFile(entry))
71812
72052
  continue;
71813
- const agentPath = join68(agentsDir, entry.name);
72053
+ const agentPath = join69(agentsDir, entry.name);
71814
72054
  const agentName = basename7(entry.name, ".md");
71815
72055
  try {
71816
- const content = readFileSync38(agentPath, "utf-8");
72056
+ const content = readFileSync39(agentPath, "utf-8");
71817
72057
  const { data, body } = parseFrontmatter(content);
71818
72058
  const name = data.name || agentName;
71819
72059
  const originalDescription = data.description || "";
@@ -71842,7 +72082,7 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
71842
72082
  return agents;
71843
72083
  }
71844
72084
  function loadUserAgents(leConfig) {
71845
- const userAgentsDir = join68(getClaudeConfigDir(), "agents");
72085
+ const userAgentsDir = join69(getClaudeConfigDir(), "agents");
71846
72086
  const agents = loadAgentsFromDir(userAgentsDir, "user", leConfig);
71847
72087
  const result = {};
71848
72088
  for (const agent of agents) {
@@ -71851,7 +72091,7 @@ function loadUserAgents(leConfig) {
71851
72091
  return result;
71852
72092
  }
71853
72093
  function loadProjectAgents(leConfig) {
71854
- const projectAgentsDir = join68(process.cwd(), ".claude", "agents");
72094
+ const projectAgentsDir = join69(process.cwd(), ".claude", "agents");
71855
72095
  const agents = loadAgentsFromDir(projectAgentsDir, "project", leConfig);
71856
72096
  const result = {};
71857
72097
  for (const agent of agents) {
@@ -71863,18 +72103,18 @@ function loadProjectAgents(leConfig) {
71863
72103
  init_frontmatter();
71864
72104
  init_file_utils();
71865
72105
  init_logger();
71866
- import { existsSync as existsSync56, readdirSync as readdirSync21, readFileSync as readFileSync39 } from "fs";
72106
+ import { existsSync as existsSync57, readdirSync as readdirSync21, readFileSync as readFileSync40 } from "fs";
71867
72107
  import { homedir as homedir14 } from "os";
71868
- import { join as join69, basename as basename8 } from "path";
72108
+ import { join as join70, basename as basename8 } from "path";
71869
72109
  var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
71870
72110
  function getPluginsBaseDir() {
71871
72111
  if (process.env.CLAUDE_PLUGINS_HOME) {
71872
72112
  return process.env.CLAUDE_PLUGINS_HOME;
71873
72113
  }
71874
- return join69(homedir14(), ".claude", "plugins");
72114
+ return join70(homedir14(), ".claude", "plugins");
71875
72115
  }
71876
72116
  function getInstalledPluginsPath() {
71877
- return join69(getPluginsBaseDir(), "installed_plugins.json");
72117
+ return join70(getPluginsBaseDir(), "installed_plugins.json");
71878
72118
  }
71879
72119
  function resolvePluginPath(path8, pluginRoot) {
71880
72120
  return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
@@ -71899,11 +72139,11 @@ function resolvePluginPaths(obj, pluginRoot) {
71899
72139
  }
71900
72140
  function loadInstalledPlugins() {
71901
72141
  const dbPath = getInstalledPluginsPath();
71902
- if (!existsSync56(dbPath)) {
72142
+ if (!existsSync57(dbPath)) {
71903
72143
  return null;
71904
72144
  }
71905
72145
  try {
71906
- const content = readFileSync39(dbPath, "utf-8");
72146
+ const content = readFileSync40(dbPath, "utf-8");
71907
72147
  return JSON.parse(content);
71908
72148
  } catch (error95) {
71909
72149
  log("Failed to load installed plugins database", error95);
@@ -71914,15 +72154,15 @@ function getClaudeSettingsPath() {
71914
72154
  if (process.env.CLAUDE_SETTINGS_PATH) {
71915
72155
  return process.env.CLAUDE_SETTINGS_PATH;
71916
72156
  }
71917
- return join69(homedir14(), ".claude", "settings.json");
72157
+ return join70(homedir14(), ".claude", "settings.json");
71918
72158
  }
71919
72159
  function loadClaudeSettings() {
71920
72160
  const settingsPath = getClaudeSettingsPath();
71921
- if (!existsSync56(settingsPath)) {
72161
+ if (!existsSync57(settingsPath)) {
71922
72162
  return null;
71923
72163
  }
71924
72164
  try {
71925
- const content = readFileSync39(settingsPath, "utf-8");
72165
+ const content = readFileSync40(settingsPath, "utf-8");
71926
72166
  return JSON.parse(content);
71927
72167
  } catch (error95) {
71928
72168
  log("Failed to load Claude settings", error95);
@@ -71930,12 +72170,12 @@ function loadClaudeSettings() {
71930
72170
  }
71931
72171
  }
71932
72172
  function loadPluginManifest(installPath) {
71933
- const manifestPath = join69(installPath, ".claude-plugin", "plugin.json");
71934
- if (!existsSync56(manifestPath)) {
72173
+ const manifestPath = join70(installPath, ".claude-plugin", "plugin.json");
72174
+ if (!existsSync57(manifestPath)) {
71935
72175
  return null;
71936
72176
  }
71937
72177
  try {
71938
- const content = readFileSync39(manifestPath, "utf-8");
72178
+ const content = readFileSync40(manifestPath, "utf-8");
71939
72179
  return JSON.parse(content);
71940
72180
  } catch (error95) {
71941
72181
  log(`Failed to load plugin manifest from ${manifestPath}`, error95);
@@ -71982,7 +72222,7 @@ function discoverInstalledPlugins(options) {
71982
72222
  continue;
71983
72223
  }
71984
72224
  const { installPath, scope, version: version3 } = installation;
71985
- if (!existsSync56(installPath)) {
72225
+ if (!existsSync57(installPath)) {
71986
72226
  errors5.push({
71987
72227
  pluginKey,
71988
72228
  installPath,
@@ -72000,21 +72240,21 @@ function discoverInstalledPlugins(options) {
72000
72240
  pluginKey,
72001
72241
  manifest: manifest ?? undefined
72002
72242
  };
72003
- if (existsSync56(join69(installPath, "commands"))) {
72004
- loadedPlugin.commandsDir = join69(installPath, "commands");
72243
+ if (existsSync57(join70(installPath, "commands"))) {
72244
+ loadedPlugin.commandsDir = join70(installPath, "commands");
72005
72245
  }
72006
- if (existsSync56(join69(installPath, "agents"))) {
72007
- loadedPlugin.agentsDir = join69(installPath, "agents");
72246
+ if (existsSync57(join70(installPath, "agents"))) {
72247
+ loadedPlugin.agentsDir = join70(installPath, "agents");
72008
72248
  }
72009
- if (existsSync56(join69(installPath, "skills"))) {
72010
- loadedPlugin.skillsDir = join69(installPath, "skills");
72249
+ if (existsSync57(join70(installPath, "skills"))) {
72250
+ loadedPlugin.skillsDir = join70(installPath, "skills");
72011
72251
  }
72012
- const hooksPath = join69(installPath, "hooks", "hooks.json");
72013
- if (existsSync56(hooksPath)) {
72252
+ const hooksPath = join70(installPath, "hooks", "hooks.json");
72253
+ if (existsSync57(hooksPath)) {
72014
72254
  loadedPlugin.hooksPath = hooksPath;
72015
72255
  }
72016
- const mcpPath = join69(installPath, ".mcp.json");
72017
- if (existsSync56(mcpPath)) {
72256
+ const mcpPath = join70(installPath, ".mcp.json");
72257
+ if (existsSync57(mcpPath)) {
72018
72258
  loadedPlugin.mcpPath = mcpPath;
72019
72259
  }
72020
72260
  plugins.push(loadedPlugin);
@@ -72025,17 +72265,17 @@ function discoverInstalledPlugins(options) {
72025
72265
  function loadPluginCommands(plugins) {
72026
72266
  const commands2 = {};
72027
72267
  for (const plugin of plugins) {
72028
- if (!plugin.commandsDir || !existsSync56(plugin.commandsDir))
72268
+ if (!plugin.commandsDir || !existsSync57(plugin.commandsDir))
72029
72269
  continue;
72030
72270
  const entries = readdirSync21(plugin.commandsDir, { withFileTypes: true });
72031
72271
  for (const entry of entries) {
72032
72272
  if (!isMarkdownFile(entry))
72033
72273
  continue;
72034
- const commandPath = join69(plugin.commandsDir, entry.name);
72274
+ const commandPath = join70(plugin.commandsDir, entry.name);
72035
72275
  const commandName = basename8(entry.name, ".md");
72036
72276
  const namespacedName = `${plugin.name}:${commandName}`;
72037
72277
  try {
72038
- const content = readFileSync39(commandPath, "utf-8");
72278
+ const content = readFileSync40(commandPath, "utf-8");
72039
72279
  const { data, body } = parseFrontmatter(content);
72040
72280
  const wrappedTemplate = `<command-instruction>
72041
72281
  ${body.trim()}
@@ -72067,21 +72307,21 @@ $ARGUMENTS
72067
72307
  function loadPluginSkillsAsCommands(plugins) {
72068
72308
  const skills = {};
72069
72309
  for (const plugin of plugins) {
72070
- if (!plugin.skillsDir || !existsSync56(plugin.skillsDir))
72310
+ if (!plugin.skillsDir || !existsSync57(plugin.skillsDir))
72071
72311
  continue;
72072
72312
  const entries = readdirSync21(plugin.skillsDir, { withFileTypes: true });
72073
72313
  for (const entry of entries) {
72074
72314
  if (entry.name.startsWith("."))
72075
72315
  continue;
72076
- const skillPath = join69(plugin.skillsDir, entry.name);
72316
+ const skillPath = join70(plugin.skillsDir, entry.name);
72077
72317
  if (!entry.isDirectory() && !entry.isSymbolicLink())
72078
72318
  continue;
72079
72319
  const resolvedPath = resolveSymlink(skillPath);
72080
- const skillMdPath = join69(resolvedPath, "SKILL.md");
72081
- if (!existsSync56(skillMdPath))
72320
+ const skillMdPath = join70(resolvedPath, "SKILL.md");
72321
+ if (!existsSync57(skillMdPath))
72082
72322
  continue;
72083
72323
  try {
72084
- const content = readFileSync39(skillMdPath, "utf-8");
72324
+ const content = readFileSync40(skillMdPath, "utf-8");
72085
72325
  const { data, body } = parseFrontmatter(content);
72086
72326
  const skillName = data.name || entry.name;
72087
72327
  const namespacedName = `${plugin.name}:${skillName}`;
@@ -72128,17 +72368,17 @@ function parseToolsConfig2(toolsStr) {
72128
72368
  function loadPluginAgents(plugins) {
72129
72369
  const agents = {};
72130
72370
  for (const plugin of plugins) {
72131
- if (!plugin.agentsDir || !existsSync56(plugin.agentsDir))
72371
+ if (!plugin.agentsDir || !existsSync57(plugin.agentsDir))
72132
72372
  continue;
72133
72373
  const entries = readdirSync21(plugin.agentsDir, { withFileTypes: true });
72134
72374
  for (const entry of entries) {
72135
72375
  if (!isMarkdownFile(entry))
72136
72376
  continue;
72137
- const agentPath = join69(plugin.agentsDir, entry.name);
72377
+ const agentPath = join70(plugin.agentsDir, entry.name);
72138
72378
  const agentName = basename8(entry.name, ".md");
72139
72379
  const namespacedName = `${plugin.name}:${agentName}`;
72140
72380
  try {
72141
- const content = readFileSync39(agentPath, "utf-8");
72381
+ const content = readFileSync40(agentPath, "utf-8");
72142
72382
  const { data, body } = parseFrontmatter(content);
72143
72383
  const name = data.name || agentName;
72144
72384
  const originalDescription = data.description || "";
@@ -72164,7 +72404,7 @@ function loadPluginAgents(plugins) {
72164
72404
  async function loadPluginMcpServers(plugins) {
72165
72405
  const servers = {};
72166
72406
  for (const plugin of plugins) {
72167
- if (!plugin.mcpPath || !existsSync56(plugin.mcpPath))
72407
+ if (!plugin.mcpPath || !existsSync57(plugin.mcpPath))
72168
72408
  continue;
72169
72409
  try {
72170
72410
  const content = await Bun.file(plugin.mcpPath).text();
@@ -72196,10 +72436,10 @@ async function loadPluginMcpServers(plugins) {
72196
72436
  function loadPluginHooksConfigs(plugins) {
72197
72437
  const configs = [];
72198
72438
  for (const plugin of plugins) {
72199
- if (!plugin.hooksPath || !existsSync56(plugin.hooksPath))
72439
+ if (!plugin.hooksPath || !existsSync57(plugin.hooksPath))
72200
72440
  continue;
72201
72441
  try {
72202
- const content = readFileSync39(plugin.hooksPath, "utf-8");
72442
+ const content = readFileSync40(plugin.hooksPath, "utf-8");
72203
72443
  let config4 = JSON.parse(content);
72204
72444
  config4 = resolvePluginPaths(config4, plugin.installPath);
72205
72445
  configs.push(config4);
@@ -73820,7 +74060,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
73820
74060
  return;
73821
74061
  }
73822
74062
  log("[OhMyOpenCodePlugin] Starting session agent recovery...");
73823
- const recoveredAgents = recoverSessionAgents();
74063
+ const recoveredAgents = recoverSessionAgents(ctx.directory);
73824
74064
  log("[OhMyOpenCodePlugin] Session agent recovery complete", { recoveredAgents });
73825
74065
  startBackgroundCheck2();
73826
74066
  const pluginConfig = loadPluginConfig(ctx.directory, ctx);
@@ -74072,6 +74312,11 @@ var OhMyOpenCodePlugin = async (ctx) => {
74072
74312
  updateSessionAgent(input.sessionID, validatedAgent ?? input.agent, "chat.message");
74073
74313
  } else {
74074
74314
  const staleThresholdMs = pluginConfig.identity?.staleThresholdMs ?? 600000;
74315
+ if (!getSessionAgent(input.sessionID)) {
74316
+ log("[identity] chat.message without agent info and no session agent", {
74317
+ sessionID: input.sessionID
74318
+ });
74319
+ }
74075
74320
  if (isSessionAgentStale(input.sessionID, staleThresholdMs)) {
74076
74321
  log("[identity] session agent stale", { sessionID: input.sessionID, staleThresholdMs });
74077
74322
  const messageFileAgent = getAgentFromSessionMessages(input.sessionID);
@@ -74203,6 +74448,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
74203
74448
  try {
74204
74449
  cleanupStaleTmpFiles(ctx.directory);
74205
74450
  } catch {}
74451
+ if (sessionInfo?.id) {
74452
+ log("[identity] New main session created", { sessionID: sessionInfo.id });
74453
+ }
74206
74454
  }
74207
74455
  firstMessageVariantGate.markSessionCreated(sessionInfo);
74208
74456
  }
@@ -74235,6 +74483,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
74235
74483
  const validatedAgent = validateAndFixAgentIdentity(sessionID, agent);
74236
74484
  updateSessionAgent(sessionID, validatedAgent ?? agent, "message.updated");
74237
74485
  }
74486
+ if (sessionID && agent && role === "assistant") {
74487
+ updateSessionAgent(sessionID, agent, "message.updated.assistant");
74488
+ }
74238
74489
  }
74239
74490
  if (event.type === "session.error") {
74240
74491
  const sessionID = props?.sessionID;