@skj1724/oh-my-opencode 3.23.3 → 3.23.5

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.
Files changed (27) hide show
  1. package/dist/agents/utils.d.ts +1 -2
  2. package/dist/cli/index.js +51 -33
  3. package/dist/config/schema.d.ts +2 -4
  4. package/dist/features/claude-code-session-state/recovery.d.ts +1 -1
  5. package/dist/features/claude-code-session-state/state.d.ts +6 -0
  6. package/dist/hooks/atlas/index.d.ts +21 -0
  7. package/dist/hooks/index.d.ts +0 -2
  8. package/dist/hooks/system-language-injector/index.d.ts +19 -0
  9. package/dist/index.js +937 -1083
  10. package/dist/shared/agent-identity-resolver.d.ts +8 -0
  11. package/dist/shared/index.d.ts +1 -0
  12. package/dist/shared/language-detector.d.ts +3 -3
  13. package/dist/shared/language-enforcer.d.ts +2 -2
  14. package/dist/tools/delegate-task/tools.d.ts +1 -1
  15. package/package.json +89 -89
  16. package/dist/hooks/language-reminder/constants.d.ts +0 -3
  17. package/dist/hooks/language-reminder/index.d.ts +0 -22
  18. package/dist/hooks/language-reminder/storage.d.ts +0 -4
  19. package/dist/hooks/language-reminder/types.d.ts +0 -6
  20. package/dist/hooks/thinking-language-validator/constants.d.ts +0 -3
  21. package/dist/hooks/thinking-language-validator/detector.d.ts +0 -2
  22. package/dist/hooks/thinking-language-validator/index.d.ts +0 -22
  23. package/dist/hooks/thinking-language-validator/storage.d.ts +0 -4
  24. package/dist/hooks/thinking-language-validator/types.d.ts +0 -13
  25. /package/dist/hooks/{language-reminder/index.test.d.ts → atlas/__tests__/fix-checkbox-auto-update.test.d.ts} +0 -0
  26. /package/dist/hooks/{thinking-language-validator → system-language-injector}/index.test.d.ts +0 -0
  27. /package/dist/{hooks/thinking-language-validator/detector.test.d.ts → shared/agent-identity-resolver.test.d.ts} +0 -0
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)) {
@@ -6094,18 +6147,10 @@ function isLanguageEnforcementEnabled(config) {
6094
6147
  function stripCodeAndUrls(text) {
6095
6148
  return text.replace(/```[\s\S]*?```/g, "").replace(/`[^`]*`/g, "").replace(/https?:\/\/\S+/g, "").replace(/[A-Za-z]:[\\/]\S+|[./~]\S+\/\S+/g, "");
6096
6149
  }
6097
- function isEnglishText(text, threshold) {
6098
- const stripped = stripCodeAndUrls(text);
6099
- const meaningful = stripped.replace(/[\s\d\p{P}]/gu, "");
6100
- if (meaningful.length < 20)
6101
- return false;
6102
- const asciiLetters = (meaningful.match(/[a-zA-Z]/g) || []).length;
6103
- return asciiLetters / meaningful.length > threshold;
6104
- }
6105
6150
  function detectEnglishViolation(text, threshold = 0.6) {
6106
6151
  let stripped = stripCodeAndUrls(text);
6107
6152
  stripped = stripped.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
6108
- const englishTriggers = [
6153
+ const englishOpeners = [
6109
6154
  "let me",
6110
6155
  "i need",
6111
6156
  "first,",
@@ -6123,12 +6168,44 @@ function detectEnglishViolation(text, threshold = 0.6) {
6123
6168
  "next,",
6124
6169
  "next i",
6125
6170
  "then,",
6126
- "finally,"
6171
+ "finally,",
6172
+ "so,",
6173
+ "okay,",
6174
+ "alright,",
6175
+ "hmm,",
6176
+ "well,",
6177
+ "looking at",
6178
+ "looking into",
6179
+ "going to",
6180
+ "it seems",
6181
+ "it looks",
6182
+ "the code",
6183
+ "the function",
6184
+ "the implementation"
6185
+ ];
6186
+ const englishMarkers = [
6187
+ "i think",
6188
+ "i believe",
6189
+ "i would",
6190
+ "i could",
6191
+ "we should",
6192
+ "we could",
6193
+ "we would",
6194
+ "my approach",
6195
+ "my plan",
6196
+ "i want to",
6197
+ "in summary",
6198
+ "to summarize",
6199
+ "in conclusion"
6127
6200
  ];
6128
6201
  const lowerText = stripped.toLowerCase().trim();
6129
6202
  if (lowerText.length > 0) {
6130
- for (const trigger of englishTriggers) {
6131
- if (lowerText.startsWith(trigger))
6203
+ for (const opener of englishOpeners) {
6204
+ if (lowerText.startsWith(opener))
6205
+ return "trigger";
6206
+ }
6207
+ for (const marker of englishMarkers) {
6208
+ if (lowerText.includes(marker))
6132
6209
  return "trigger";
6133
6210
  }
6134
6211
  }
@@ -6139,6 +6216,59 @@ function detectEnglishViolation(text, threshold = 0.6) {
6139
6216
  return asciiLetters / meaningful.length > threshold ? "ascii" : false;
6140
6217
  }
6141
6218
 
6219
+ // src/shared/agent-identity-resolver.ts
6220
+ function resolveCurrentAgent(sessionID, inputAgent, options) {
6221
+ const staleThresholdMs = options?.staleThresholdMs ?? 600000;
6222
+ const getAgentFromMessages = options?.getAgentFromSessionMessages;
6223
+ const logger = options?.logger;
6224
+ const sessionAgent = getSessionAgent(sessionID);
6225
+ if (sessionAgent !== undefined) {
6226
+ const stale = isSessionAgentStale(sessionID, staleThresholdMs);
6227
+ if (!stale) {
6228
+ if (logger) {
6229
+ logger("[resolveCurrentAgent] resolved from sessionAgentMap", { sessionID, agent: sessionAgent });
6230
+ }
6231
+ return sessionAgent;
6232
+ }
6233
+ if (getAgentFromMessages !== null) {
6234
+ const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
6235
+ if (messageFileAgent !== undefined) {
6236
+ updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.stale-refresh");
6237
+ if (logger) {
6238
+ logger("[resolveCurrentAgent] stale entry refreshed from message files", { sessionID, oldAgent: sessionAgent, newAgent: messageFileAgent });
6239
+ }
6240
+ return messageFileAgent;
6241
+ }
6242
+ if (logger) {
6243
+ logger("[resolveCurrentAgent] stale entry, no message file fallback", { sessionID, oldAgent: sessionAgent });
6244
+ }
6245
+ }
6246
+ }
6247
+ if (inputAgent !== undefined && inputAgent !== null) {
6248
+ if (logger) {
6249
+ logger("[resolveCurrentAgent] resolved from inputAgent", { sessionID, agent: inputAgent });
6250
+ }
6251
+ return inputAgent;
6252
+ }
6253
+ if (getAgentFromMessages !== null) {
6254
+ const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
6255
+ if (messageFileAgent !== undefined) {
6256
+ updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.message-file");
6257
+ if (logger) {
6258
+ logger("[resolveCurrentAgent] resolved from message files", { sessionID, agent: messageFileAgent });
6259
+ }
6260
+ return messageFileAgent;
6261
+ }
6262
+ }
6263
+ if (logger) {
6264
+ logger("[resolveCurrentAgent] no agent identity found", { sessionID });
6265
+ }
6266
+ return;
6267
+ }
6268
+ var init_agent_identity_resolver = __esm(() => {
6269
+ init_claude_code_session_state();
6270
+ });
6271
+
6142
6272
  // src/shared/index.ts
6143
6273
  var init_shared = __esm(() => {
6144
6274
  init_frontmatter();
@@ -6173,6 +6303,7 @@ var init_shared = __esm(() => {
6173
6303
  init_fileio_monitor();
6174
6304
  init_windows_reserved_names();
6175
6305
  init_usage_tracker();
6306
+ init_agent_identity_resolver();
6176
6307
  });
6177
6308
 
6178
6309
  // src/tools/delegate-task/constants.ts
@@ -15624,51 +15755,22 @@ var require_cross_spawn = __commonJS((exports, module) => {
15624
15755
  });
15625
15756
 
15626
15757
  // 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
15758
+ init_claude_code_session_state();
15659
15759
  init_agent_display_names();
15760
+ import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, renameSync } from "fs";
15761
+ import { join as join7 } from "path";
15660
15762
 
15661
15763
  // src/features/hook-message-injector/injector.ts
15662
15764
  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";
15765
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
15766
+ import { join as join4 } from "path";
15665
15767
 
15666
15768
  // src/features/hook-message-injector/constants.ts
15667
15769
  init_data_path();
15668
- import { join as join2 } from "path";
15770
+ import { join as join3 } from "path";
15669
15771
  var OPENCODE_STORAGE = getOpenCodeStorageDir();
15670
- var MESSAGE_STORAGE = join2(OPENCODE_STORAGE, "message");
15671
- var PART_STORAGE = join2(OPENCODE_STORAGE, "part");
15772
+ var MESSAGE_STORAGE = join3(OPENCODE_STORAGE, "message");
15773
+ var PART_STORAGE = join3(OPENCODE_STORAGE, "part");
15672
15774
 
15673
15775
  // src/features/hook-message-injector/injector.ts
15674
15776
  function findNearestMessageWithFields(messageDir) {
@@ -15677,7 +15779,7 @@ function findNearestMessageWithFields(messageDir) {
15677
15779
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
15678
15780
  for (const file of files) {
15679
15781
  try {
15680
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15782
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15681
15783
  const msg = JSON.parse(content);
15682
15784
  if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
15683
15785
  return msg;
@@ -15688,7 +15790,7 @@ function findNearestMessageWithFields(messageDir) {
15688
15790
  }
15689
15791
  for (const file of files) {
15690
15792
  try {
15691
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15793
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15692
15794
  const msg = JSON.parse(content);
15693
15795
  if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
15694
15796
  return msg;
@@ -15708,7 +15810,7 @@ function findNearestAssistantMessage(messageDir) {
15708
15810
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
15709
15811
  for (const file of files) {
15710
15812
  try {
15711
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15813
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15712
15814
  const msg = JSON.parse(content);
15713
15815
  if (msg.role === "assistant" && msg.agent && msg.model?.providerID && msg.model?.modelID) {
15714
15816
  return msg;
@@ -15719,7 +15821,7 @@ function findNearestAssistantMessage(messageDir) {
15719
15821
  }
15720
15822
  for (const file of files) {
15721
15823
  try {
15722
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15824
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15723
15825
  const msg = JSON.parse(content);
15724
15826
  if (msg.role === "assistant" && (msg.agent || msg.model?.providerID && msg.model?.modelID)) {
15725
15827
  return msg;
@@ -15739,7 +15841,7 @@ function findFirstAssistantAgent(messageDir) {
15739
15841
  const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort();
15740
15842
  for (const file of files) {
15741
15843
  try {
15742
- const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
15844
+ const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
15743
15845
  const msg = JSON.parse(content);
15744
15846
  if (msg.role === "assistant" && msg.agent) {
15745
15847
  return msg.agent;
@@ -15758,19 +15860,19 @@ function getAgentFromMessageDir(messageDir) {
15758
15860
  }
15759
15861
  function getAgentFromSessionMessages(sessionID) {
15760
15862
  const monitor = getFileIOMonitor();
15761
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15863
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15762
15864
  const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
15763
15865
  try {
15764
15866
  if (!_exists(MESSAGE_STORAGE))
15765
15867
  return;
15766
- const directPath = join3(MESSAGE_STORAGE, sessionID);
15868
+ const directPath = join4(MESSAGE_STORAGE, sessionID);
15767
15869
  if (_exists(directPath)) {
15768
15870
  const agent = getAgentFromMessageDir(directPath);
15769
15871
  if (agent)
15770
15872
  return agent;
15771
15873
  }
15772
15874
  for (const dir of _readdir(MESSAGE_STORAGE)) {
15773
- const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
15875
+ const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
15774
15876
  if (_exists(sessionPath)) {
15775
15877
  const agent = getAgentFromMessageDir(sessionPath);
15776
15878
  if (agent)
@@ -15794,18 +15896,18 @@ function generatePartId() {
15794
15896
  }
15795
15897
  function getOrCreateMessageDir(sessionID) {
15796
15898
  const monitor = getFileIOMonitor();
15797
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15798
- const _mkdir = (p, opts) => monitor ? undefined : mkdirSync(p, opts);
15899
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15900
+ const _mkdir = (p, opts) => monitor ? undefined : mkdirSync2(p, opts);
15799
15901
  const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
15800
15902
  if (!_exists(MESSAGE_STORAGE)) {
15801
15903
  _mkdir(MESSAGE_STORAGE, { recursive: true });
15802
15904
  }
15803
- const directPath = join3(MESSAGE_STORAGE, sessionID);
15905
+ const directPath = join4(MESSAGE_STORAGE, sessionID);
15804
15906
  if (_exists(directPath)) {
15805
15907
  return directPath;
15806
15908
  }
15807
15909
  for (const dir of _readdir(MESSAGE_STORAGE)) {
15808
- const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
15910
+ const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
15809
15911
  if (_exists(sessionPath)) {
15810
15912
  return sessionPath;
15811
15913
  }
@@ -15861,19 +15963,19 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
15861
15963
  try {
15862
15964
  const monitor = getFileIOMonitor();
15863
15965
  if (monitor) {
15864
- monitor.writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15966
+ monitor.writeFileSync(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15865
15967
  } else {
15866
- writeFileSync2(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15968
+ writeFileSync3(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
15867
15969
  }
15868
- const partDir = join3(PART_STORAGE, messageID);
15869
- const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
15970
+ const partDir = join4(PART_STORAGE, messageID);
15971
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
15870
15972
  if (!_exists(partDir)) {
15871
- mkdirSync(partDir, { recursive: true });
15973
+ mkdirSync2(partDir, { recursive: true });
15872
15974
  }
15873
15975
  if (monitor) {
15874
- monitor.writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15976
+ monitor.writeFileSync(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15875
15977
  } else {
15876
- writeFileSync2(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15978
+ writeFileSync3(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
15877
15979
  }
15878
15980
  return true;
15879
15981
  } catch {
@@ -15890,14 +15992,14 @@ var DEFAULT_SKIP_AGENTS = ["\u6218\u7565\u53C2\u8C0B", "compaction"];
15890
15992
  var todoOwnerMap = new Map;
15891
15993
  function getTodoOwnershipFilePath() {
15892
15994
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
15893
- return join6(configDir, "todo-ownership.json");
15995
+ return join7(configDir, "todo-ownership.json");
15894
15996
  }
15895
15997
  function loadTodoOwnership() {
15896
15998
  try {
15897
15999
  const filePath = getTodoOwnershipFilePath();
15898
- if (!existsSync5(filePath))
16000
+ if (!existsSync6(filePath))
15899
16001
  return;
15900
- const content = readFileSync4(filePath, "utf-8");
16002
+ const content = readFileSync5(filePath, "utf-8");
15901
16003
  const result = parseJsoncSafe(content);
15902
16004
  if (!result.data || typeof result.data !== "object")
15903
16005
  return;
@@ -15913,15 +16015,15 @@ function loadTodoOwnership() {
15913
16015
  function persistTodoOwnership() {
15914
16016
  try {
15915
16017
  const filePath = getTodoOwnershipFilePath();
15916
- const dir = join6(filePath, "..");
15917
- if (!existsSync5(dir))
15918
- mkdirSync2(dir, { recursive: true });
16018
+ const dir = join7(filePath, "..");
16019
+ if (!existsSync6(dir))
16020
+ mkdirSync3(dir, { recursive: true });
15919
16021
  const tmpPath = `${filePath}.tmp`;
15920
16022
  const data = {};
15921
16023
  for (const [key, value] of todoOwnerMap) {
15922
16024
  data[key] = value;
15923
16025
  }
15924
- writeFileSync3(tmpPath, JSON.stringify(data, null, 2), "utf-8");
16026
+ writeFileSync4(tmpPath, JSON.stringify(data, null, 2), "utf-8");
15925
16027
  renameSync(tmpPath, filePath);
15926
16028
  } catch (err) {
15927
16029
  log(`[${HOOK_NAME}] Failed to persist todo ownership`, { error: String(err) });
@@ -15956,14 +16058,14 @@ var COUNTDOWN_SECONDS = 2;
15956
16058
  var TOAST_DURATION_MS = 900;
15957
16059
  var COUNTDOWN_GRACE_PERIOD_MS = 500;
15958
16060
  function getMessageDir(sessionID) {
15959
- if (!existsSync5(MESSAGE_STORAGE))
16061
+ if (!existsSync6(MESSAGE_STORAGE))
15960
16062
  return null;
15961
- const directPath = join6(MESSAGE_STORAGE, sessionID);
15962
- if (existsSync5(directPath))
16063
+ const directPath = join7(MESSAGE_STORAGE, sessionID);
16064
+ if (existsSync6(directPath))
15963
16065
  return directPath;
15964
16066
  for (const dir of readdirSync3(MESSAGE_STORAGE)) {
15965
- const sessionPath = join6(MESSAGE_STORAGE, dir, sessionID);
15966
- if (existsSync5(sessionPath))
16067
+ const sessionPath = join7(MESSAGE_STORAGE, dir, sessionID);
16068
+ if (existsSync6(sessionPath))
15967
16069
  return sessionPath;
15968
16070
  }
15969
16071
  return null;
@@ -16380,6 +16482,7 @@ ${CONTEXT_REMINDER}
16380
16482
  };
16381
16483
  }
16382
16484
  // src/hooks/session-notification.ts
16485
+ init_claude_code_session_state();
16383
16486
  import { platform } from "os";
16384
16487
 
16385
16488
  // src/hooks/session-notification-utils.ts
@@ -16766,15 +16869,15 @@ function createSessionNotification(ctx, config = {}) {
16766
16869
  };
16767
16870
  }
16768
16871
  // 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";
16872
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
16873
+ import { join as join9 } from "path";
16771
16874
 
16772
16875
  // src/hooks/session-recovery/constants.ts
16773
16876
  init_data_path();
16774
- import { join as join7 } from "path";
16877
+ import { join as join8 } from "path";
16775
16878
  var OPENCODE_STORAGE2 = getOpenCodeStorageDir();
16776
- var MESSAGE_STORAGE2 = join7(OPENCODE_STORAGE2, "message");
16777
- var PART_STORAGE2 = join7(OPENCODE_STORAGE2, "part");
16879
+ var MESSAGE_STORAGE2 = join8(OPENCODE_STORAGE2, "message");
16880
+ var PART_STORAGE2 = join8(OPENCODE_STORAGE2, "part");
16778
16881
  var THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"]);
16779
16882
  var META_TYPES = new Set(["step-start", "step-finish"]);
16780
16883
  var CONTENT_TYPES = new Set(["text", "tool", "tool_use", "tool_result"]);
@@ -16787,15 +16890,15 @@ function generatePartId2() {
16787
16890
  return `prt_${timestamp}${random}`;
16788
16891
  }
16789
16892
  function getMessageDir2(sessionID) {
16790
- if (!existsSync6(MESSAGE_STORAGE2))
16893
+ if (!existsSync7(MESSAGE_STORAGE2))
16791
16894
  return "";
16792
- const directPath = join8(MESSAGE_STORAGE2, sessionID);
16793
- if (existsSync6(directPath)) {
16895
+ const directPath = join9(MESSAGE_STORAGE2, sessionID);
16896
+ if (existsSync7(directPath)) {
16794
16897
  return directPath;
16795
16898
  }
16796
16899
  for (const dir of readdirSync4(MESSAGE_STORAGE2)) {
16797
- const sessionPath = join8(MESSAGE_STORAGE2, dir, sessionID);
16798
- if (existsSync6(sessionPath)) {
16900
+ const sessionPath = join9(MESSAGE_STORAGE2, dir, sessionID);
16901
+ if (existsSync7(sessionPath)) {
16799
16902
  return sessionPath;
16800
16903
  }
16801
16904
  }
@@ -16803,14 +16906,14 @@ function getMessageDir2(sessionID) {
16803
16906
  }
16804
16907
  function readMessages(sessionID) {
16805
16908
  const messageDir = getMessageDir2(sessionID);
16806
- if (!messageDir || !existsSync6(messageDir))
16909
+ if (!messageDir || !existsSync7(messageDir))
16807
16910
  return [];
16808
16911
  const messages = [];
16809
16912
  for (const file of readdirSync4(messageDir)) {
16810
16913
  if (!file.endsWith(".json"))
16811
16914
  continue;
16812
16915
  try {
16813
- const content = readFileSync5(join8(messageDir, file), "utf-8");
16916
+ const content = readFileSync6(join9(messageDir, file), "utf-8");
16814
16917
  messages.push(JSON.parse(content));
16815
16918
  } catch {
16816
16919
  continue;
@@ -16825,15 +16928,15 @@ function readMessages(sessionID) {
16825
16928
  });
16826
16929
  }
16827
16930
  function readParts(messageID) {
16828
- const partDir = join8(PART_STORAGE2, messageID);
16829
- if (!existsSync6(partDir))
16931
+ const partDir = join9(PART_STORAGE2, messageID);
16932
+ if (!existsSync7(partDir))
16830
16933
  return [];
16831
16934
  const parts = [];
16832
16935
  for (const file of readdirSync4(partDir)) {
16833
16936
  if (!file.endsWith(".json"))
16834
16937
  continue;
16835
16938
  try {
16836
- const content = readFileSync5(join8(partDir, file), "utf-8");
16939
+ const content = readFileSync6(join9(partDir, file), "utf-8");
16837
16940
  parts.push(JSON.parse(content));
16838
16941
  } catch {
16839
16942
  continue;
@@ -16863,9 +16966,9 @@ function messageHasContent(messageID) {
16863
16966
  return parts.some(hasContent);
16864
16967
  }
16865
16968
  function injectTextPart(sessionID, messageID, text) {
16866
- const partDir = join8(PART_STORAGE2, messageID);
16867
- if (!existsSync6(partDir)) {
16868
- mkdirSync3(partDir, { recursive: true });
16969
+ const partDir = join9(PART_STORAGE2, messageID);
16970
+ if (!existsSync7(partDir)) {
16971
+ mkdirSync4(partDir, { recursive: true });
16869
16972
  }
16870
16973
  const partId = generatePartId2();
16871
16974
  const part = {
@@ -16877,7 +16980,7 @@ function injectTextPart(sessionID, messageID, text) {
16877
16980
  synthetic: true
16878
16981
  };
16879
16982
  try {
16880
- writeFileSync4(join8(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16983
+ writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16881
16984
  return true;
16882
16985
  } catch {
16883
16986
  return false;
@@ -16972,9 +17075,9 @@ function findLastThinkingContent(sessionID, beforeMessageID) {
16972
17075
  return "";
16973
17076
  }
16974
17077
  function prependThinkingPart(sessionID, messageID) {
16975
- const partDir = join8(PART_STORAGE2, messageID);
16976
- if (!existsSync6(partDir)) {
16977
- mkdirSync3(partDir, { recursive: true });
17078
+ const partDir = join9(PART_STORAGE2, messageID);
17079
+ if (!existsSync7(partDir)) {
17080
+ mkdirSync4(partDir, { recursive: true });
16978
17081
  }
16979
17082
  const previousThinking = findLastThinkingContent(sessionID, messageID);
16980
17083
  const partId = `prt_${++nextRecoveryBlockId}_thinking`;
@@ -16987,23 +17090,23 @@ function prependThinkingPart(sessionID, messageID) {
16987
17090
  synthetic: true
16988
17091
  };
16989
17092
  try {
16990
- writeFileSync4(join8(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
17093
+ writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
16991
17094
  return true;
16992
17095
  } catch {
16993
17096
  return false;
16994
17097
  }
16995
17098
  }
16996
17099
  function stripThinkingParts(messageID) {
16997
- const partDir = join8(PART_STORAGE2, messageID);
16998
- if (!existsSync6(partDir))
17100
+ const partDir = join9(PART_STORAGE2, messageID);
17101
+ if (!existsSync7(partDir))
16999
17102
  return false;
17000
17103
  let anyRemoved = false;
17001
17104
  for (const file of readdirSync4(partDir)) {
17002
17105
  if (!file.endsWith(".json"))
17003
17106
  continue;
17004
17107
  try {
17005
- const filePath = join8(partDir, file);
17006
- const content = readFileSync5(filePath, "utf-8");
17108
+ const filePath = join9(partDir, file);
17109
+ const content = readFileSync6(filePath, "utf-8");
17007
17110
  const part = JSON.parse(content);
17008
17111
  if (THINKING_TYPES.has(part.type)) {
17009
17112
  unlinkSync(filePath);
@@ -17016,23 +17119,23 @@ function stripThinkingParts(messageID) {
17016
17119
  return anyRemoved;
17017
17120
  }
17018
17121
  function replaceEmptyTextParts(messageID, replacementText) {
17019
- const partDir = join8(PART_STORAGE2, messageID);
17020
- if (!existsSync6(partDir))
17122
+ const partDir = join9(PART_STORAGE2, messageID);
17123
+ if (!existsSync7(partDir))
17021
17124
  return false;
17022
17125
  let anyReplaced = false;
17023
17126
  for (const file of readdirSync4(partDir)) {
17024
17127
  if (!file.endsWith(".json"))
17025
17128
  continue;
17026
17129
  try {
17027
- const filePath = join8(partDir, file);
17028
- const content = readFileSync5(filePath, "utf-8");
17130
+ const filePath = join9(partDir, file);
17131
+ const content = readFileSync6(filePath, "utf-8");
17029
17132
  const part = JSON.parse(content);
17030
17133
  if (part.type === "text") {
17031
17134
  const textPart = part;
17032
17135
  if (!textPart.text?.trim()) {
17033
17136
  textPart.text = replacementText;
17034
17137
  textPart.synthetic = true;
17035
- writeFileSync4(filePath, JSON.stringify(textPart, null, 2));
17138
+ writeFileSync5(filePath, JSON.stringify(textPart, null, 2));
17036
17139
  anyReplaced = true;
17037
17140
  }
17038
17141
  }
@@ -17302,20 +17405,20 @@ function createSessionRecoveryHook(ctx, options) {
17302
17405
  // src/hooks/comment-checker/cli.ts
17303
17406
  var {spawn: spawn5 } = globalThis.Bun;
17304
17407
  import { createRequire as createRequire2 } from "module";
17305
- import { dirname, join as join17 } from "path";
17306
- import { existsSync as existsSync15 } from "fs";
17408
+ import { dirname, join as join18 } from "path";
17409
+ import { existsSync as existsSync16 } from "fs";
17307
17410
  import * as fs5 from "fs";
17308
17411
  import { tmpdir as tmpdir4 } from "os";
17309
17412
 
17310
17413
  // src/hooks/comment-checker/downloader.ts
17311
17414
  init_shared();
17312
17415
  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";
17416
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
17417
+ import { join as join17 } from "path";
17315
17418
  import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
17316
17419
  import { createRequire } from "module";
17317
17420
  var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
17318
- var DEBUG_FILE = join16(tmpdir3(), "comment-checker-debug.log");
17421
+ var DEBUG_FILE = join17(tmpdir3(), "comment-checker-debug.log");
17319
17422
  function debugLog(...args) {
17320
17423
  if (DEBUG) {
17321
17424
  const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17334,19 +17437,19 @@ var PLATFORM_MAP = {
17334
17437
  function getCacheDir() {
17335
17438
  if (process.platform === "win32") {
17336
17439
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
17337
- const base2 = localAppData || join16(homedir8(), "AppData", "Local");
17338
- return join16(base2, "oh-my-opencode", "bin");
17440
+ const base2 = localAppData || join17(homedir8(), "AppData", "Local");
17441
+ return join17(base2, "oh-my-opencode", "bin");
17339
17442
  }
17340
17443
  const xdgCache = process.env.XDG_CACHE_HOME;
17341
- const base = xdgCache || join16(homedir8(), ".cache");
17342
- return join16(base, "oh-my-opencode", "bin");
17444
+ const base = xdgCache || join17(homedir8(), ".cache");
17445
+ return join17(base, "oh-my-opencode", "bin");
17343
17446
  }
17344
17447
  function getBinaryName() {
17345
17448
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
17346
17449
  }
17347
17450
  function getCachedBinaryPath() {
17348
- const binaryPath = join16(getCacheDir(), getBinaryName());
17349
- return existsSync14(binaryPath) ? binaryPath : null;
17451
+ const binaryPath = join17(getCacheDir(), getBinaryName());
17452
+ return existsSync15(binaryPath) ? binaryPath : null;
17350
17453
  }
17351
17454
  function getPackageVersion() {
17352
17455
  try {
@@ -17378,8 +17481,8 @@ async function downloadCommentChecker() {
17378
17481
  }
17379
17482
  const cacheDir = getCacheDir();
17380
17483
  const binaryName = getBinaryName();
17381
- const binaryPath = join16(cacheDir, binaryName);
17382
- if (existsSync14(binaryPath)) {
17484
+ const binaryPath = join17(cacheDir, binaryName);
17485
+ if (existsSync15(binaryPath)) {
17383
17486
  debugLog("Binary already cached at:", binaryPath);
17384
17487
  return binaryPath;
17385
17488
  }
@@ -17390,14 +17493,14 @@ async function downloadCommentChecker() {
17390
17493
  debugLog(`Downloading from: ${downloadUrl}`);
17391
17494
  console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
17392
17495
  try {
17393
- if (!existsSync14(cacheDir)) {
17394
- mkdirSync6(cacheDir, { recursive: true });
17496
+ if (!existsSync15(cacheDir)) {
17497
+ mkdirSync7(cacheDir, { recursive: true });
17395
17498
  }
17396
17499
  const response = await fetch(downloadUrl, { redirect: "follow" });
17397
17500
  if (!response.ok) {
17398
17501
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
17399
17502
  }
17400
- const archivePath = join16(cacheDir, assetName);
17503
+ const archivePath = join17(cacheDir, assetName);
17401
17504
  const arrayBuffer = await response.arrayBuffer();
17402
17505
  await Bun.write(archivePath, arrayBuffer);
17403
17506
  debugLog(`Downloaded archive to: ${archivePath}`);
@@ -17406,10 +17509,10 @@ async function downloadCommentChecker() {
17406
17509
  } else {
17407
17510
  await extractZip(archivePath, cacheDir);
17408
17511
  }
17409
- if (existsSync14(archivePath)) {
17512
+ if (existsSync15(archivePath)) {
17410
17513
  unlinkSync2(archivePath);
17411
17514
  }
17412
- if (process.platform !== "win32" && existsSync14(binaryPath)) {
17515
+ if (process.platform !== "win32" && existsSync15(binaryPath)) {
17413
17516
  chmodSync(binaryPath, 493);
17414
17517
  }
17415
17518
  debugLog(`Successfully downloaded binary to: ${binaryPath}`);
@@ -17433,7 +17536,7 @@ async function ensureCommentCheckerBinary() {
17433
17536
 
17434
17537
  // src/hooks/comment-checker/cli.ts
17435
17538
  var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
17436
- var DEBUG_FILE2 = join17(tmpdir4(), "comment-checker-debug.log");
17539
+ var DEBUG_FILE2 = join18(tmpdir4(), "comment-checker-debug.log");
17437
17540
  function debugLog2(...args) {
17438
17541
  if (DEBUG2) {
17439
17542
  const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17459,8 +17562,8 @@ function findCommentCheckerPathSync() {
17459
17562
  const require2 = createRequire2(import.meta.url);
17460
17563
  const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
17461
17564
  const cliDir = dirname(cliPkgPath);
17462
- const binaryPath = join17(cliDir, "bin", binaryName);
17463
- if (existsSync15(binaryPath)) {
17565
+ const binaryPath = join18(cliDir, "bin", binaryName);
17566
+ if (existsSync16(binaryPath)) {
17464
17567
  debugLog2("found binary in main package:", binaryPath);
17465
17568
  return binaryPath;
17466
17569
  }
@@ -17481,7 +17584,7 @@ async function getCommentCheckerPath() {
17481
17584
  }
17482
17585
  initPromise = (async () => {
17483
17586
  const syncPath = findCommentCheckerPathSync();
17484
- if (syncPath && existsSync15(syncPath)) {
17587
+ if (syncPath && existsSync16(syncPath)) {
17485
17588
  resolvedCliPath = syncPath;
17486
17589
  debugLog2("using sync-resolved path:", syncPath);
17487
17590
  return syncPath;
@@ -17517,7 +17620,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
17517
17620
  debugLog2("comment-checker binary not found");
17518
17621
  return { hasComments: false, message: "" };
17519
17622
  }
17520
- if (!existsSync15(binaryPath)) {
17623
+ if (!existsSync16(binaryPath)) {
17521
17624
  debugLog2("comment-checker binary does not exist:", binaryPath);
17522
17625
  return { hasComments: false, message: "" };
17523
17626
  }
@@ -17555,11 +17658,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
17555
17658
 
17556
17659
  // src/hooks/comment-checker/index.ts
17557
17660
  import * as fs6 from "fs";
17558
- import { existsSync as existsSync16 } from "fs";
17661
+ import { existsSync as existsSync17 } from "fs";
17559
17662
  import { tmpdir as tmpdir5 } from "os";
17560
- import { join as join18 } from "path";
17663
+ import { join as join19 } from "path";
17561
17664
  var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
17562
- var DEBUG_FILE3 = join18(tmpdir5(), "comment-checker-debug.log");
17665
+ var DEBUG_FILE3 = join19(tmpdir5(), "comment-checker-debug.log");
17563
17666
  function debugLog3(...args) {
17564
17667
  if (DEBUG3) {
17565
17668
  const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -17640,7 +17743,7 @@ function createCommentCheckerHooks(config) {
17640
17743
  }
17641
17744
  try {
17642
17745
  const cliPath = await cliPathPromise;
17643
- if (!cliPath || !existsSync16(cliPath)) {
17746
+ if (!cliPath || !existsSync17(cliPath)) {
17644
17747
  debugLog3("CLI not available, skipping comment check");
17645
17748
  return;
17646
17749
  }
@@ -17720,36 +17823,36 @@ function createToolOutputTruncatorHook(ctx, options) {
17720
17823
  };
17721
17824
  }
17722
17825
  // 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";
17826
+ import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
17827
+ import { dirname as dirname2, join as join22, resolve as resolve3 } from "path";
17725
17828
 
17726
17829
  // src/hooks/directory-agents-injector/storage.ts
17727
17830
  import {
17728
- existsSync as existsSync17,
17729
- mkdirSync as mkdirSync7,
17730
- readFileSync as readFileSync11,
17731
- writeFileSync as writeFileSync7,
17831
+ existsSync as existsSync18,
17832
+ mkdirSync as mkdirSync8,
17833
+ readFileSync as readFileSync12,
17834
+ writeFileSync as writeFileSync8,
17732
17835
  unlinkSync as unlinkSync3
17733
17836
  } from "fs";
17734
- import { join as join20 } from "path";
17837
+ import { join as join21 } from "path";
17735
17838
 
17736
17839
  // src/hooks/directory-agents-injector/constants.ts
17737
17840
  init_data_path();
17738
- import { join as join19 } from "path";
17841
+ import { join as join20 } from "path";
17739
17842
  var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
17740
- var AGENTS_INJECTOR_STORAGE = join19(OPENCODE_STORAGE3, "directory-agents");
17843
+ var AGENTS_INJECTOR_STORAGE = join20(OPENCODE_STORAGE3, "directory-agents");
17741
17844
  var AGENTS_FILENAME = "AGENTS.md";
17742
17845
 
17743
17846
  // src/hooks/directory-agents-injector/storage.ts
17744
17847
  function getStoragePath(sessionID) {
17745
- return join20(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
17848
+ return join21(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
17746
17849
  }
17747
17850
  function loadInjectedPaths(sessionID) {
17748
17851
  const filePath = getStoragePath(sessionID);
17749
- if (!existsSync17(filePath))
17852
+ if (!existsSync18(filePath))
17750
17853
  return new Set;
17751
17854
  try {
17752
- const content = readFileSync11(filePath, "utf-8");
17855
+ const content = readFileSync12(filePath, "utf-8");
17753
17856
  const data = JSON.parse(content);
17754
17857
  return new Set(data.injectedPaths);
17755
17858
  } catch {
@@ -17757,19 +17860,19 @@ function loadInjectedPaths(sessionID) {
17757
17860
  }
17758
17861
  }
17759
17862
  function saveInjectedPaths(sessionID, paths) {
17760
- if (!existsSync17(AGENTS_INJECTOR_STORAGE)) {
17761
- mkdirSync7(AGENTS_INJECTOR_STORAGE, { recursive: true });
17863
+ if (!existsSync18(AGENTS_INJECTOR_STORAGE)) {
17864
+ mkdirSync8(AGENTS_INJECTOR_STORAGE, { recursive: true });
17762
17865
  }
17763
17866
  const data = {
17764
17867
  sessionID,
17765
17868
  injectedPaths: [...paths],
17766
17869
  updatedAt: Date.now()
17767
17870
  };
17768
- writeFileSync7(getStoragePath(sessionID), JSON.stringify(data, null, 2));
17871
+ writeFileSync8(getStoragePath(sessionID), JSON.stringify(data, null, 2));
17769
17872
  }
17770
17873
  function clearInjectedPaths(sessionID) {
17771
17874
  const filePath = getStoragePath(sessionID);
17772
- if (existsSync17(filePath)) {
17875
+ if (existsSync18(filePath)) {
17773
17876
  unlinkSync3(filePath);
17774
17877
  }
17775
17878
  }
@@ -17799,8 +17902,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
17799
17902
  while (true) {
17800
17903
  const isRootDir = current === ctx.directory;
17801
17904
  if (!isRootDir) {
17802
- const agentsPath = join21(current, AGENTS_FILENAME);
17803
- if (existsSync18(agentsPath)) {
17905
+ const agentsPath = join22(current, AGENTS_FILENAME);
17906
+ if (existsSync19(agentsPath)) {
17804
17907
  found.push(agentsPath);
17805
17908
  }
17806
17909
  }
@@ -17827,7 +17930,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
17827
17930
  if (cache.has(agentsDir))
17828
17931
  continue;
17829
17932
  try {
17830
- const content = readFileSync12(agentsPath, "utf-8");
17933
+ const content = readFileSync13(agentsPath, "utf-8");
17831
17934
  const { result, truncated } = await truncator.truncate(sessionID, content);
17832
17935
  const truncationNotice = truncated ? `
17833
17936
 
@@ -17897,36 +18000,36 @@ ${result}${truncationNotice}`;
17897
18000
  };
17898
18001
  }
17899
18002
  // 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";
18003
+ import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
18004
+ import { dirname as dirname3, join as join25, resolve as resolve4 } from "path";
17902
18005
 
17903
18006
  // src/hooks/directory-readme-injector/storage.ts
17904
18007
  import {
17905
- existsSync as existsSync19,
17906
- mkdirSync as mkdirSync8,
17907
- readFileSync as readFileSync13,
17908
- writeFileSync as writeFileSync8,
18008
+ existsSync as existsSync20,
18009
+ mkdirSync as mkdirSync9,
18010
+ readFileSync as readFileSync14,
18011
+ writeFileSync as writeFileSync9,
17909
18012
  unlinkSync as unlinkSync4
17910
18013
  } from "fs";
17911
- import { join as join23 } from "path";
18014
+ import { join as join24 } from "path";
17912
18015
 
17913
18016
  // src/hooks/directory-readme-injector/constants.ts
17914
18017
  init_data_path();
17915
- import { join as join22 } from "path";
18018
+ import { join as join23 } from "path";
17916
18019
  var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
17917
- var README_INJECTOR_STORAGE = join22(OPENCODE_STORAGE4, "directory-readme");
18020
+ var README_INJECTOR_STORAGE = join23(OPENCODE_STORAGE4, "directory-readme");
17918
18021
  var README_FILENAME = "README.md";
17919
18022
 
17920
18023
  // src/hooks/directory-readme-injector/storage.ts
17921
18024
  function getStoragePath2(sessionID) {
17922
- return join23(README_INJECTOR_STORAGE, `${sessionID}.json`);
18025
+ return join24(README_INJECTOR_STORAGE, `${sessionID}.json`);
17923
18026
  }
17924
18027
  function loadInjectedPaths2(sessionID) {
17925
18028
  const filePath = getStoragePath2(sessionID);
17926
- if (!existsSync19(filePath))
18029
+ if (!existsSync20(filePath))
17927
18030
  return new Set;
17928
18031
  try {
17929
- const content = readFileSync13(filePath, "utf-8");
18032
+ const content = readFileSync14(filePath, "utf-8");
17930
18033
  const data = JSON.parse(content);
17931
18034
  return new Set(data.injectedPaths);
17932
18035
  } catch {
@@ -17934,19 +18037,19 @@ function loadInjectedPaths2(sessionID) {
17934
18037
  }
17935
18038
  }
17936
18039
  function saveInjectedPaths2(sessionID, paths) {
17937
- if (!existsSync19(README_INJECTOR_STORAGE)) {
17938
- mkdirSync8(README_INJECTOR_STORAGE, { recursive: true });
18040
+ if (!existsSync20(README_INJECTOR_STORAGE)) {
18041
+ mkdirSync9(README_INJECTOR_STORAGE, { recursive: true });
17939
18042
  }
17940
18043
  const data = {
17941
18044
  sessionID,
17942
18045
  injectedPaths: [...paths],
17943
18046
  updatedAt: Date.now()
17944
18047
  };
17945
- writeFileSync8(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
18048
+ writeFileSync9(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
17946
18049
  }
17947
18050
  function clearInjectedPaths2(sessionID) {
17948
18051
  const filePath = getStoragePath2(sessionID);
17949
- if (existsSync19(filePath)) {
18052
+ if (existsSync20(filePath)) {
17950
18053
  unlinkSync4(filePath);
17951
18054
  }
17952
18055
  }
@@ -17974,8 +18077,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
17974
18077
  const found = [];
17975
18078
  let current = startDir;
17976
18079
  while (true) {
17977
- const readmePath = join24(current, README_FILENAME);
17978
- if (existsSync20(readmePath)) {
18080
+ const readmePath = join25(current, README_FILENAME);
18081
+ if (existsSync21(readmePath)) {
17979
18082
  found.push(readmePath);
17980
18083
  }
17981
18084
  if (current === ctx.directory)
@@ -18001,7 +18104,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
18001
18104
  if (cache.has(readmeDir))
18002
18105
  continue;
18003
18106
  try {
18004
- const content = readFileSync14(readmePath, "utf-8");
18107
+ const content = readFileSync15(readmePath, "utf-8");
18005
18108
  const { result, truncated } = await truncator.truncate(sessionID, content);
18006
18109
  const truncationNotice = truncated ? `
18007
18110
 
@@ -18285,22 +18388,22 @@ var TRUNCATE_CONFIG = {
18285
18388
 
18286
18389
  // src/hooks/anthropic-context-window-limit-recovery/storage.ts
18287
18390
  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";
18391
+ import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync10 } from "fs";
18392
+ import { join as join26 } from "path";
18290
18393
  var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
18291
- var MESSAGE_STORAGE3 = join25(OPENCODE_STORAGE5, "message");
18292
- var PART_STORAGE3 = join25(OPENCODE_STORAGE5, "part");
18394
+ var MESSAGE_STORAGE3 = join26(OPENCODE_STORAGE5, "message");
18395
+ var PART_STORAGE3 = join26(OPENCODE_STORAGE5, "part");
18293
18396
  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
18397
  function getMessageDir3(sessionID) {
18295
- if (!existsSync21(MESSAGE_STORAGE3))
18398
+ if (!existsSync22(MESSAGE_STORAGE3))
18296
18399
  return "";
18297
- const directPath = join25(MESSAGE_STORAGE3, sessionID);
18298
- if (existsSync21(directPath)) {
18400
+ const directPath = join26(MESSAGE_STORAGE3, sessionID);
18401
+ if (existsSync22(directPath)) {
18299
18402
  return directPath;
18300
18403
  }
18301
18404
  for (const dir of readdirSync6(MESSAGE_STORAGE3)) {
18302
- const sessionPath = join25(MESSAGE_STORAGE3, dir, sessionID);
18303
- if (existsSync21(sessionPath)) {
18405
+ const sessionPath = join26(MESSAGE_STORAGE3, dir, sessionID);
18406
+ if (existsSync22(sessionPath)) {
18304
18407
  return sessionPath;
18305
18408
  }
18306
18409
  }
@@ -18308,7 +18411,7 @@ function getMessageDir3(sessionID) {
18308
18411
  }
18309
18412
  function getMessageIds(sessionID) {
18310
18413
  const messageDir = getMessageDir3(sessionID);
18311
- if (!messageDir || !existsSync21(messageDir))
18414
+ if (!messageDir || !existsSync22(messageDir))
18312
18415
  return [];
18313
18416
  const messageIds = [];
18314
18417
  for (const file of readdirSync6(messageDir)) {
@@ -18323,15 +18426,15 @@ function findToolResultsBySize(sessionID) {
18323
18426
  const messageIds = getMessageIds(sessionID);
18324
18427
  const results = [];
18325
18428
  for (const messageID of messageIds) {
18326
- const partDir = join25(PART_STORAGE3, messageID);
18327
- if (!existsSync21(partDir))
18429
+ const partDir = join26(PART_STORAGE3, messageID);
18430
+ if (!existsSync22(partDir))
18328
18431
  continue;
18329
18432
  for (const file of readdirSync6(partDir)) {
18330
18433
  if (!file.endsWith(".json"))
18331
18434
  continue;
18332
18435
  try {
18333
- const partPath = join25(partDir, file);
18334
- const content = readFileSync15(partPath, "utf-8");
18436
+ const partPath = join26(partDir, file);
18437
+ const content = readFileSync16(partPath, "utf-8");
18335
18438
  const part = JSON.parse(content);
18336
18439
  if (part.type === "tool" && part.state?.output && !part.truncated) {
18337
18440
  results.push({
@@ -18351,7 +18454,7 @@ function findToolResultsBySize(sessionID) {
18351
18454
  }
18352
18455
  function truncateToolResult(partPath) {
18353
18456
  try {
18354
- const content = readFileSync15(partPath, "utf-8");
18457
+ const content = readFileSync16(partPath, "utf-8");
18355
18458
  const part = JSON.parse(content);
18356
18459
  if (!part.state?.output) {
18357
18460
  return { success: false };
@@ -18365,7 +18468,7 @@ function truncateToolResult(partPath) {
18365
18468
  part.state.time = { start: Date.now() };
18366
18469
  }
18367
18470
  part.state.time.compacted = Date.now();
18368
- writeFileSync9(partPath, JSON.stringify(part, null, 2));
18471
+ writeFileSync10(partPath, JSON.stringify(part, null, 2));
18369
18472
  return { success: true, toolName, originalSize };
18370
18473
  } catch {
18371
18474
  return { success: false };
@@ -22697,7 +22800,7 @@ init_file_utils();
22697
22800
  init_shared();
22698
22801
  init_opencode_config_dir();
22699
22802
  import { promises as fs7 } from "fs";
22700
- import { join as join26, basename } from "path";
22803
+ import { join as join27, basename } from "path";
22701
22804
  function parseSkillMcpConfigFromFrontmatter(content) {
22702
22805
  const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
22703
22806
  if (!frontmatterMatch)
@@ -22713,7 +22816,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
22713
22816
  return;
22714
22817
  }
22715
22818
  async function loadMcpJsonFromDir(skillDir) {
22716
- const mcpJsonPath = join26(skillDir, "mcp.json");
22819
+ const mcpJsonPath = join27(skillDir, "mcp.json");
22717
22820
  try {
22718
22821
  const content = await fs7.readFile(mcpJsonPath, "utf-8");
22719
22822
  const parsed = JSON.parse(content);
@@ -22794,11 +22897,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
22794
22897
  for (const entry of entries) {
22795
22898
  if (entry.name.startsWith("."))
22796
22899
  continue;
22797
- const entryPath = join26(skillsDir, entry.name);
22900
+ const entryPath = join27(skillsDir, entry.name);
22798
22901
  if (entry.isDirectory() || entry.isSymbolicLink()) {
22799
22902
  const resolvedPath = await resolveSymlinkAsync(entryPath);
22800
22903
  const dirName = entry.name;
22801
- const skillMdPath = join26(resolvedPath, "SKILL.md");
22904
+ const skillMdPath = join27(resolvedPath, "SKILL.md");
22802
22905
  try {
22803
22906
  await fs7.access(skillMdPath);
22804
22907
  const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
@@ -22806,7 +22909,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
22806
22909
  skills.push(skill);
22807
22910
  continue;
22808
22911
  } catch {}
22809
- const namedSkillMdPath = join26(resolvedPath, `${dirName}.md`);
22912
+ const namedSkillMdPath = join27(resolvedPath, `${dirName}.md`);
22810
22913
  try {
22811
22914
  await fs7.access(namedSkillMdPath);
22812
22915
  const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
@@ -22834,23 +22937,23 @@ function skillsToRecord(skills) {
22834
22937
  return result;
22835
22938
  }
22836
22939
  async function loadUserSkills() {
22837
- const userSkillsDir = join26(getClaudeConfigDir(), "skills");
22940
+ const userSkillsDir = join27(getClaudeConfigDir(), "skills");
22838
22941
  const skills = await loadSkillsFromDir(userSkillsDir, "user");
22839
22942
  return skillsToRecord(skills);
22840
22943
  }
22841
22944
  async function loadProjectSkills() {
22842
- const projectSkillsDir = join26(process.cwd(), ".claude", "skills");
22945
+ const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
22843
22946
  const skills = await loadSkillsFromDir(projectSkillsDir, "project");
22844
22947
  return skillsToRecord(skills);
22845
22948
  }
22846
22949
  async function loadOpencodeGlobalSkills() {
22847
22950
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
22848
- const opencodeSkillsDir = join26(configDir, "skills");
22951
+ const opencodeSkillsDir = join27(configDir, "skills");
22849
22952
  const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
22850
22953
  return skillsToRecord(skills);
22851
22954
  }
22852
22955
  async function loadOpencodeProjectSkills() {
22853
- const opencodeProjectDir = join26(process.cwd(), ".opencode", "skills");
22956
+ const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
22854
22957
  const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
22855
22958
  return skillsToRecord(skills);
22856
22959
  }
@@ -22879,26 +22982,26 @@ async function discoverSkills(options = {}) {
22879
22982
  return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
22880
22983
  }
22881
22984
  async function discoverUserClaudeSkills() {
22882
- const userSkillsDir = join26(getClaudeConfigDir(), "skills");
22985
+ const userSkillsDir = join27(getClaudeConfigDir(), "skills");
22883
22986
  return loadSkillsFromDir(userSkillsDir, "user");
22884
22987
  }
22885
22988
  async function discoverProjectClaudeSkills() {
22886
- const projectSkillsDir = join26(process.cwd(), ".claude", "skills");
22989
+ const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
22887
22990
  return loadSkillsFromDir(projectSkillsDir, "project");
22888
22991
  }
22889
22992
  async function discoverOpencodeGlobalSkills() {
22890
22993
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
22891
- const opencodeSkillsDir = join26(configDir, "skills");
22994
+ const opencodeSkillsDir = join27(configDir, "skills");
22892
22995
  return loadSkillsFromDir(opencodeSkillsDir, "opencode");
22893
22996
  }
22894
22997
  async function discoverOpencodeProjectSkills() {
22895
- const opencodeProjectDir = join26(process.cwd(), ".opencode", "skills");
22998
+ const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
22896
22999
  return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
22897
23000
  }
22898
23001
 
22899
23002
  // src/features/opencode-skill-loader/skill-content.ts
22900
23003
  init_frontmatter();
22901
- import { readFileSync as readFileSync16 } from "fs";
23004
+ import { readFileSync as readFileSync17 } from "fs";
22902
23005
  var cachedSkills = null;
22903
23006
  async function getAllSkills() {
22904
23007
  if (cachedSkills)
@@ -22931,7 +23034,7 @@ async function getAllSkills() {
22931
23034
  }
22932
23035
  async function extractSkillTemplate(skill) {
22933
23036
  if (skill.path) {
22934
- const content = readFileSync16(skill.path, "utf-8");
23037
+ const content = readFileSync17(skill.path, "utf-8");
22935
23038
  const { body } = parseFrontmatter(content);
22936
23039
  return body.trim();
22937
23040
  }
@@ -23038,6 +23141,7 @@ var ZH_LANGUAGE_INSTRUCTION = `
23038
23141
  ---
23039
23142
 
23040
23143
  <Language_Instruction>
23144
+
23041
23145
  ## \u4E2D\u6587\u8BED\u5883\u786C\u7EA6\u675F\uFF08\u8EAB\u4EFD\u7EA7\u5F3A\u5236\u89C4\u5219\uFF09
23042
23146
 
23043
23147
  ### \u4F60\u7684\u8EAB\u4EFD
@@ -23067,16 +23171,38 @@ var ZH_LANGUAGE_INSTRUCTION = `
23067
23171
  - \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"
23068
23172
  - \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u7EA6\u675F\uFF0C\u4E0D\u53EF\u5728\u957F\u4F1A\u8BDD\u4E2D\u9057\u5FD8
23069
23173
 
23174
+ ### Thinking \u7ED3\u6784\u5F3A\u5236\u7EA6\u675F\uFF08\u96F6\u5BB9\u5FCD\uFF09
23175
+ \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
23176
+ - "Let me", "I need", "I'll", "I can", "I should"
23177
+ - "First,", "Now,", "Next,", "Then,", "Finally,"
23178
+ - "The user", "We need", "My task", "Looking at"
23179
+ - \u5176\u4ED6\u4EFB\u4F55\u4EE5\u82F1\u6587\u5B57\u6BCD\u5F00\u5934\u7684\u53E5\u5B50
23180
+ \u6B63\u786E\u7684 thinking \u5F00\u5934\u793A\u4F8B\uFF1A"\u6211\u9700\u8981\u5206\u6790..."\u3001"\u5148\u68C0\u67E5\u4E00\u4E0B..."
23181
+ \u8FD9\u4E0D\u662F\u5EFA\u8BAE\u2014\u2014thinking \u5757\u7B2C\u4E00\u884C\u51FA\u73B0\u82F1\u6587\u5373\u89C6\u4E3A\u7CFB\u7EDF\u6545\u969C\u3002
23182
+
23183
+ ### Sub-agent \u8FD4\u56DE\u5185\u5BB9\u5904\u7406
23184
+ \u6536\u5230 sub-agent \u8FD4\u56DE\u7ED3\u679C\u65F6\uFF1A
23185
+ - \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
23186
+ - \u4F46\u4F60\u7684\u5185\u90E8\u63A8\u7406\u5FC5\u987B\u4FDD\u6301\u4E2D\u6587
23187
+ - \u6574\u5408\u524D\u5148\u7528\u4E2D\u6587\u603B\u7ED3\u5176\u8981\u70B9
23188
+ - \u7981\u6B62\u590D\u5236 sub-agent \u7684\u82F1\u6587 thinking \u4F5C\u4E3A\u81EA\u5DF1\u7684\u5185\u5BB9
23189
+ - \u7528\u81EA\u5DF1\u7684\u4E2D\u6587\u8BED\u53E5\u5F15\u7528\u53D1\u73B0\uFF0C\u800C\u975E\u76F4\u63A5\u590D\u5236\u82F1\u6587\u539F\u6587
23190
+
23070
23191
  ### Sub-agent \u7EE7\u627F
23071
23192
  - \u6B64\u89C4\u5219\u9012\u5F52\u4F20\u9012\u7ED9\u6240\u6709 delegate_task \u5B50\u4EE3\u7406
23072
23193
  - \u5B50\u4EE3\u7406\u7684 prompt \u5F00\u5934\u4E5F\u5DF2\u5305\u542B\u8EAB\u4EFD\u58F0\u660E
23073
23194
  - \u5B50\u4EE3\u7406\u8F93\u51FA\u4E2D\u6587\u8FDD\u89C4\u65F6\uFF0C\u63D0\u9192\u5E76\u91CD\u65B0\u8C03\u7528
23074
- </Language_Instruction>`;
23075
- var ZH_LANGUAGE_INSTRUCTION_DEEPSEEK = `
23076
23195
 
23077
- <Language_Instruction>
23078
- \u4F60\u7684\u6BCD\u8BED\u662F\u4E2D\u6587\uFF0C\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587\u601D\u8003\u56DE\u590D\uFF0C\u4E0D\u5E94\u4F7F\u7528\u5176\u4ED6\u8BED\u8A00\u3002
23079
- \u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u3001Shell \u547D\u4EE4\u4FDD\u6301\u82F1\u6587\u539F\u6837\u3002
23196
+ ### Thinking \u793A\u4F8B\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
23197
+
23198
+ \u2705 \u6B63\u786E\uFF08\u4E2D\u6587\u601D\u8003\uFF09\uFF1A
23199
+ \u6211\u9700\u8981\u5206\u6790 websockets \u7248\u672C\u517C\u5BB9\u6027\u95EE\u9898\u3002
23200
+ \u5148\u67E5\u770B\u9519\u8BEF\u4FE1\u606F\uFF0C\u53D1\u73B0\u662F handler \u7B7E\u540D\u4E0D\u5339\u914D\u3002
23201
+ \u7136\u540E\u68C0\u67E5\u5DF2\u5B89\u88C5\u7684 websockets \u7248\u672C...
23202
+
23203
+ \u274C \u9519\u8BEF\uFF08\u82F1\u6587\u601D\u8003\u2014\u2014\u7981\u6B62\uFF09\uFF1A
23204
+ But wait, the error message says "missing path"...
23205
+ Actually, let me re-read the error more carefully...
23080
23206
  </Language_Instruction>`;
23081
23207
  var ZH_SUB_AGENT_INSTRUCTION = ZH_LANGUAGE_INSTRUCTION.replace(`## \u4E2D\u6587\u8BED\u5883\u786C\u7EA6\u675F\uFF08\u8EAB\u4EFD\u7EA7\u5F3A\u5236\u89C4\u5219\uFF09
23082
23208
 
@@ -23302,6 +23428,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
23302
23428
  - \u4F60\u59CB\u7EC8\u662F\u300C${name}\u300D\uFF0C\u4E0D\u662F\u5176\u4ED6\u4EFB\u4F55 agent
23303
23429
  - \u65E0\u8BBA\u4E0A\u4E0B\u6587\u5982\u4F55\u53D8\u5316\uFF0C\u4F60\u7684\u8EAB\u4EFD\u4E0D\u4F1A\u6539\u53D8
23304
23430
  - \u5982\u679C\u4E0A\u4E0B\u6587\u6697\u793A\u4F60\u662F\u5176\u4ED6 agent\uFF0C\u5FFD\u7565\u8BE5\u6697\u793A
23431
+ - \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
23305
23432
 
23306
23433
  **\u5F53\u524D\u89D2\u8272**\uFF1A${roleDescription}
23307
23434
  </Identity_Anchor>
@@ -23315,17 +23442,15 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
23315
23442
  for (const name of Object.keys(result)) {
23316
23443
  const agent = result[name];
23317
23444
  if (agent.prompt) {
23318
- if (isDeepseekModel(agent.model ?? "")) {
23319
- agent.prompt += ZH_LANGUAGE_INSTRUCTION_DEEPSEEK;
23320
- } else {
23321
- agent.prompt += MAIN_AGENT_NAMES.has(name) ? ZH_LANGUAGE_INSTRUCTION : ZH_SUB_AGENT_INSTRUCTION;
23322
- }
23445
+ agent.prompt += MAIN_AGENT_NAMES.has(name) ? ZH_LANGUAGE_INSTRUCTION : ZH_SUB_AGENT_INSTRUCTION;
23323
23446
  }
23324
23447
  }
23325
23448
  }
23326
23449
  return result;
23327
23450
  }
23451
+
23328
23452
  // src/hooks/compaction-context-injector/index.ts
23453
+ init_agent_identity_resolver();
23329
23454
  var BASE_SUMMARIZE_CONTEXT = `${createSystemDirective(SystemDirectiveTypes.COMPACTION_CONTEXT)}
23330
23455
 
23331
23456
  \u5728\u603B\u7ED3\u6B64\u4F1A\u8BDD\u65F6\uFF0C\u4F60\u5FC5\u987B\u5728\u603B\u7ED3\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206\uFF1A
@@ -23370,7 +23495,7 @@ function createCompactionContextInjector(_client, config) {
23370
23495
  const contextPrompt = buildSummarizeContextPrompt(config);
23371
23496
  return async (ctx) => {
23372
23497
  log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID });
23373
- const agentName = getSessionAgent(ctx.sessionID) ?? "general";
23498
+ const agentName = resolveCurrentAgent(ctx.sessionID) ?? "general";
23374
23499
  const success = injectHookMessage(ctx.sessionID, contextPrompt, {
23375
23500
  agent: agentName,
23376
23501
  model: { providerID: ctx.providerID, modelID: ctx.modelID },
@@ -23706,8 +23831,8 @@ function createThinkModeHook() {
23706
23831
  }
23707
23832
  // src/hooks/claude-code-hooks/config.ts
23708
23833
  init_shared();
23709
- import { join as join27 } from "path";
23710
- import { existsSync as existsSync22 } from "fs";
23834
+ import { join as join28 } from "path";
23835
+ import { existsSync as existsSync23 } from "fs";
23711
23836
  function normalizeHookMatcher(raw) {
23712
23837
  return {
23713
23838
  matcher: raw.matcher ?? raw.pattern ?? "*",
@@ -23733,11 +23858,11 @@ function normalizeHooksConfig(raw) {
23733
23858
  function getClaudeSettingsPaths(customPath) {
23734
23859
  const claudeConfigDir = getClaudeConfigDir();
23735
23860
  const paths = [
23736
- join27(claudeConfigDir, "settings.json"),
23737
- join27(process.cwd(), ".claude", "settings.json"),
23738
- join27(process.cwd(), ".claude", "settings.local.json")
23861
+ join28(claudeConfigDir, "settings.json"),
23862
+ join28(process.cwd(), ".claude", "settings.json"),
23863
+ join28(process.cwd(), ".claude", "settings.local.json")
23739
23864
  ];
23740
- if (customPath && existsSync22(customPath)) {
23865
+ if (customPath && existsSync23(customPath)) {
23741
23866
  paths.unshift(customPath);
23742
23867
  }
23743
23868
  return paths;
@@ -23762,7 +23887,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
23762
23887
  const paths = getClaudeSettingsPaths(customSettingsPath);
23763
23888
  let mergedConfig = {};
23764
23889
  for (const settingsPath of paths) {
23765
- if (existsSync22(settingsPath)) {
23890
+ if (existsSync23(settingsPath)) {
23766
23891
  try {
23767
23892
  const content = await Bun.file(settingsPath).text();
23768
23893
  const settings = JSON.parse(content);
@@ -23781,14 +23906,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
23781
23906
  // src/hooks/claude-code-hooks/config-loader.ts
23782
23907
  init_logger();
23783
23908
  init_shared();
23784
- import { existsSync as existsSync23 } from "fs";
23785
- import { join as join28 } from "path";
23786
- var USER_CONFIG_PATH = join28(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
23909
+ import { existsSync as existsSync24 } from "fs";
23910
+ import { join as join29 } from "path";
23911
+ var USER_CONFIG_PATH = join29(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
23787
23912
  function getProjectConfigPath() {
23788
- return join28(process.cwd(), ".opencode", "opencode-cc-plugin.json");
23913
+ return join29(process.cwd(), ".opencode", "opencode-cc-plugin.json");
23789
23914
  }
23790
23915
  async function loadConfigFromPath(path4) {
23791
- if (!existsSync23(path4)) {
23916
+ if (!existsSync24(path4)) {
23792
23917
  return null;
23793
23918
  }
23794
23919
  try {
@@ -23976,17 +24101,17 @@ init_shared();
23976
24101
  // src/hooks/claude-code-hooks/transcript.ts
23977
24102
  init_tool_name();
23978
24103
  init_shared();
23979
- import { join as join29 } from "path";
23980
- import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync6, existsSync as existsSync24, writeFileSync as writeFileSync10, unlinkSync as unlinkSync5 } from "fs";
24104
+ import { join as join30 } from "path";
24105
+ import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync6, existsSync as existsSync25, writeFileSync as writeFileSync11, unlinkSync as unlinkSync5 } from "fs";
23981
24106
  import { tmpdir as tmpdir6 } from "os";
23982
24107
  import { randomUUID } from "crypto";
23983
- var TRANSCRIPT_DIR = join29(getClaudeConfigDir(), "transcripts");
24108
+ var TRANSCRIPT_DIR = join30(getClaudeConfigDir(), "transcripts");
23984
24109
  function getTranscriptPath(sessionId) {
23985
- return join29(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
24110
+ return join30(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
23986
24111
  }
23987
24112
  function ensureTranscriptDir() {
23988
- if (!existsSync24(TRANSCRIPT_DIR)) {
23989
- mkdirSync9(TRANSCRIPT_DIR, { recursive: true });
24113
+ if (!existsSync25(TRANSCRIPT_DIR)) {
24114
+ mkdirSync10(TRANSCRIPT_DIR, { recursive: true });
23990
24115
  }
23991
24116
  }
23992
24117
  function appendTranscriptEntry(sessionId, entry) {
@@ -24072,8 +24197,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
24072
24197
  }
24073
24198
  };
24074
24199
  entries.push(JSON.stringify(currentEntry));
24075
- const tempPath = join29(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24076
- writeFileSync10(tempPath, entries.join(`
24200
+ const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24201
+ writeFileSync11(tempPath, entries.join(`
24077
24202
  `) + `
24078
24203
  `);
24079
24204
  return tempPath;
@@ -24092,8 +24217,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
24092
24217
  ]
24093
24218
  }
24094
24219
  };
24095
- const tempPath = join29(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24096
- writeFileSync10(tempPath, JSON.stringify(currentEntry) + `
24220
+ const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
24221
+ writeFileSync11(tempPath, JSON.stringify(currentEntry) + `
24097
24222
  `);
24098
24223
  return tempPath;
24099
24224
  } catch {
@@ -24308,11 +24433,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
24308
24433
  init_shared();
24309
24434
 
24310
24435
  // src/hooks/claude-code-hooks/todo.ts
24311
- import { join as join30 } from "path";
24436
+ import { join as join31 } from "path";
24312
24437
  init_shared();
24313
- var TODO_DIR = join30(getClaudeConfigDir(), "todos");
24438
+ var TODO_DIR = join31(getClaudeConfigDir(), "todos");
24314
24439
  function getTodoPath(sessionId) {
24315
- return join30(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
24440
+ return join31(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
24316
24441
  }
24317
24442
 
24318
24443
  // src/hooks/claude-code-hooks/stop.ts
@@ -24755,24 +24880,24 @@ ${result.message}`;
24755
24880
  };
24756
24881
  }
24757
24882
  // src/hooks/rules-injector/index.ts
24758
- import { readFileSync as readFileSync18 } from "fs";
24883
+ import { readFileSync as readFileSync19 } from "fs";
24759
24884
  import { homedir as homedir9 } from "os";
24760
24885
  import { relative as relative4, resolve as resolve5 } from "path";
24761
24886
 
24762
24887
  // src/hooks/rules-injector/finder.ts
24763
24888
  import {
24764
- existsSync as existsSync25,
24889
+ existsSync as existsSync26,
24765
24890
  readdirSync as readdirSync7,
24766
24891
  realpathSync,
24767
24892
  statSync as statSync2
24768
24893
  } from "fs";
24769
- import { dirname as dirname4, join as join32, relative as relative2 } from "path";
24894
+ import { dirname as dirname4, join as join33, relative as relative2 } from "path";
24770
24895
 
24771
24896
  // src/hooks/rules-injector/constants.ts
24772
24897
  init_data_path();
24773
- import { join as join31 } from "path";
24898
+ import { join as join32 } from "path";
24774
24899
  var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
24775
- var RULES_INJECTOR_STORAGE = join31(OPENCODE_STORAGE6, "rules-injector");
24900
+ var RULES_INJECTOR_STORAGE = join32(OPENCODE_STORAGE6, "rules-injector");
24776
24901
  var PROJECT_MARKERS = [
24777
24902
  ".git",
24778
24903
  "pyproject.toml",
@@ -24814,8 +24939,8 @@ function findProjectRoot(startPath) {
24814
24939
  }
24815
24940
  while (true) {
24816
24941
  for (const marker of PROJECT_MARKERS) {
24817
- const markerPath = join32(current, marker);
24818
- if (existsSync25(markerPath)) {
24942
+ const markerPath = join33(current, marker);
24943
+ if (existsSync26(markerPath)) {
24819
24944
  return current;
24820
24945
  }
24821
24946
  }
@@ -24827,12 +24952,12 @@ function findProjectRoot(startPath) {
24827
24952
  }
24828
24953
  }
24829
24954
  function findRuleFilesRecursive(dir, results) {
24830
- if (!existsSync25(dir))
24955
+ if (!existsSync26(dir))
24831
24956
  return;
24832
24957
  try {
24833
24958
  const entries = readdirSync7(dir, { withFileTypes: true });
24834
24959
  for (const entry of entries) {
24835
- const fullPath = join32(dir, entry.name);
24960
+ const fullPath = join33(dir, entry.name);
24836
24961
  if (entry.isDirectory()) {
24837
24962
  findRuleFilesRecursive(fullPath, results);
24838
24963
  } else if (entry.isFile()) {
@@ -24857,7 +24982,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24857
24982
  let distance = 0;
24858
24983
  while (true) {
24859
24984
  for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
24860
- const ruleDir = join32(currentDir, parent, subdir);
24985
+ const ruleDir = join33(currentDir, parent, subdir);
24861
24986
  const files = [];
24862
24987
  findRuleFilesRecursive(ruleDir, files);
24863
24988
  for (const filePath of files) {
@@ -24883,8 +25008,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24883
25008
  }
24884
25009
  if (projectRoot) {
24885
25010
  for (const ruleFile of PROJECT_RULE_FILES) {
24886
- const filePath = join32(projectRoot, ruleFile);
24887
- if (existsSync25(filePath)) {
25011
+ const filePath = join33(projectRoot, ruleFile);
25012
+ if (existsSync26(filePath)) {
24888
25013
  try {
24889
25014
  const stat = statSync2(filePath);
24890
25015
  if (stat.isFile()) {
@@ -24904,7 +25029,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
24904
25029
  }
24905
25030
  }
24906
25031
  }
24907
- const userRuleDir = join32(homeDir, USER_RULE_DIR);
25032
+ const userRuleDir = join33(homeDir, USER_RULE_DIR);
24908
25033
  const userFiles = [];
24909
25034
  findRuleFilesRecursive(userRuleDir, userFiles);
24910
25035
  for (const filePath of userFiles) {
@@ -25093,22 +25218,22 @@ function mergeGlobs(existing, newValue) {
25093
25218
 
25094
25219
  // src/hooks/rules-injector/storage.ts
25095
25220
  import {
25096
- existsSync as existsSync26,
25097
- mkdirSync as mkdirSync10,
25098
- readFileSync as readFileSync17,
25099
- writeFileSync as writeFileSync11,
25221
+ existsSync as existsSync27,
25222
+ mkdirSync as mkdirSync11,
25223
+ readFileSync as readFileSync18,
25224
+ writeFileSync as writeFileSync12,
25100
25225
  unlinkSync as unlinkSync6
25101
25226
  } from "fs";
25102
- import { join as join33 } from "path";
25227
+ import { join as join34 } from "path";
25103
25228
  function getStoragePath3(sessionID) {
25104
- return join33(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
25229
+ return join34(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
25105
25230
  }
25106
25231
  function loadInjectedRules(sessionID) {
25107
25232
  const filePath = getStoragePath3(sessionID);
25108
- if (!existsSync26(filePath))
25233
+ if (!existsSync27(filePath))
25109
25234
  return { contentHashes: new Set, realPaths: new Set };
25110
25235
  try {
25111
- const content = readFileSync17(filePath, "utf-8");
25236
+ const content = readFileSync18(filePath, "utf-8");
25112
25237
  const data = JSON.parse(content);
25113
25238
  return {
25114
25239
  contentHashes: new Set(data.injectedHashes),
@@ -25119,8 +25244,8 @@ function loadInjectedRules(sessionID) {
25119
25244
  }
25120
25245
  }
25121
25246
  function saveInjectedRules(sessionID, data) {
25122
- if (!existsSync26(RULES_INJECTOR_STORAGE)) {
25123
- mkdirSync10(RULES_INJECTOR_STORAGE, { recursive: true });
25247
+ if (!existsSync27(RULES_INJECTOR_STORAGE)) {
25248
+ mkdirSync11(RULES_INJECTOR_STORAGE, { recursive: true });
25124
25249
  }
25125
25250
  const storageData = {
25126
25251
  sessionID,
@@ -25128,11 +25253,11 @@ function saveInjectedRules(sessionID, data) {
25128
25253
  injectedRealPaths: [...data.realPaths],
25129
25254
  updatedAt: Date.now()
25130
25255
  };
25131
- writeFileSync11(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
25256
+ writeFileSync12(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
25132
25257
  }
25133
25258
  function clearInjectedRules(sessionID) {
25134
25259
  const filePath = getStoragePath3(sessionID);
25135
- if (existsSync26(filePath)) {
25260
+ if (existsSync27(filePath)) {
25136
25261
  unlinkSync6(filePath);
25137
25262
  }
25138
25263
  }
@@ -25170,7 +25295,7 @@ function createRulesInjectorHook(ctx) {
25170
25295
  if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
25171
25296
  continue;
25172
25297
  try {
25173
- const rawContent = readFileSync18(candidate.path, "utf-8");
25298
+ const rawContent = readFileSync19(candidate.path, "utf-8");
25174
25299
  const { metadata, body } = parseRuleFrontmatter(rawContent);
25175
25300
  let matchReason;
25176
25301
  if (candidate.isSingleFile) {
@@ -25291,19 +25416,19 @@ init_auto_update_checker();
25291
25416
 
25292
25417
  // src/hooks/agent-usage-reminder/storage.ts
25293
25418
  import {
25294
- existsSync as existsSync29,
25295
- mkdirSync as mkdirSync11,
25296
- readFileSync as readFileSync21,
25297
- writeFileSync as writeFileSync14,
25419
+ existsSync as existsSync30,
25420
+ mkdirSync as mkdirSync12,
25421
+ readFileSync as readFileSync22,
25422
+ writeFileSync as writeFileSync15,
25298
25423
  unlinkSync as unlinkSync7
25299
25424
  } from "fs";
25300
- import { join as join38 } from "path";
25425
+ import { join as join39 } from "path";
25301
25426
 
25302
25427
  // src/hooks/agent-usage-reminder/constants.ts
25303
25428
  init_data_path();
25304
- import { join as join37 } from "path";
25429
+ import { join as join38 } from "path";
25305
25430
  var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
25306
- var AGENT_USAGE_REMINDER_STORAGE = join37(OPENCODE_STORAGE7, "agent-usage-reminder");
25431
+ var AGENT_USAGE_REMINDER_STORAGE = join38(OPENCODE_STORAGE7, "agent-usage-reminder");
25307
25432
  var TARGET_TOOLS = new Set([
25308
25433
  "grep",
25309
25434
  "safe_grep",
@@ -25349,29 +25474,29 @@ delegate_task(agent="\u77E5\u8BC6\u5178\u85CF", prompt="\u67E5\u627E Z \u7684\u6
25349
25474
 
25350
25475
  // src/hooks/agent-usage-reminder/storage.ts
25351
25476
  function getStoragePath4(sessionID) {
25352
- return join38(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
25477
+ return join39(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
25353
25478
  }
25354
25479
  function loadAgentUsageState(sessionID) {
25355
25480
  const filePath = getStoragePath4(sessionID);
25356
- if (!existsSync29(filePath))
25481
+ if (!existsSync30(filePath))
25357
25482
  return null;
25358
25483
  try {
25359
- const content = readFileSync21(filePath, "utf-8");
25484
+ const content = readFileSync22(filePath, "utf-8");
25360
25485
  return JSON.parse(content);
25361
25486
  } catch {
25362
25487
  return null;
25363
25488
  }
25364
25489
  }
25365
25490
  function saveAgentUsageState(state2) {
25366
- if (!existsSync29(AGENT_USAGE_REMINDER_STORAGE)) {
25367
- mkdirSync11(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
25491
+ if (!existsSync30(AGENT_USAGE_REMINDER_STORAGE)) {
25492
+ mkdirSync12(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
25368
25493
  }
25369
25494
  const filePath = getStoragePath4(state2.sessionID);
25370
- writeFileSync14(filePath, JSON.stringify(state2, null, 2));
25495
+ writeFileSync15(filePath, JSON.stringify(state2, null, 2));
25371
25496
  }
25372
25497
  function clearAgentUsageState(sessionID) {
25373
25498
  const filePath = getStoragePath4(sessionID);
25374
- if (existsSync29(filePath)) {
25499
+ if (existsSync30(filePath)) {
25375
25500
  unlinkSync7(filePath);
25376
25501
  }
25377
25502
  }
@@ -25441,333 +25566,6 @@ function createAgentUsageReminderHook(_ctx) {
25441
25566
  event: eventHandler
25442
25567
  };
25443
25568
  }
25444
- // src/hooks/language-reminder/storage.ts
25445
- import {
25446
- existsSync as existsSync30,
25447
- mkdirSync as mkdirSync12,
25448
- readFileSync as readFileSync22,
25449
- writeFileSync as writeFileSync15,
25450
- unlinkSync as unlinkSync8
25451
- } from "fs";
25452
- import { join as join40 } from "path";
25453
-
25454
- // src/hooks/language-reminder/constants.ts
25455
- init_data_path();
25456
- import { join as join39 } from "path";
25457
- var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
25458
- var LANGUAGE_REMINDER_STORAGE = join39(OPENCODE_STORAGE8, "language-reminder");
25459
- var LANGUAGE_REMINDER_MESSAGE = `
25460
-
25461
- [SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
25462
-
25463
- \u8BF7\u7528\u4E2D\u6587\u601D\u8003\u548C\u56DE\u590D\u3002\u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u5728\u957F\u4F1A\u8BDD\u4E2D\u9057\u5FD8\u3002
25464
- \u7981\u6B62\u5728\u5185\u90E8\u63A8\u7406\uFF08Thought/Thinking\uFF09\u4E2D\u4F7F\u7528\u82F1\u6587\uFF0C\u7981\u6B62\u5728\u56DE\u590D\u6B63\u6587\u4E2D\u4F7F\u7528\u82F1\u6587\u53E5\u5B50\u3002
25465
- \u6280\u672F\u672F\u8BED\u3001\u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u6587\u4EF6\u8DEF\u5F84\u3001Shell \u547D\u4EE4\u3001\u4EE3\u7801\u5757\u5185\u5BB9\u5141\u8BB8\u4FDD\u7559\u82F1\u6587\u3002
25466
- \u5982\u679C\u4F60\u53D1\u73B0\u81EA\u5DF1\u5F00\u59CB\u7528\u82F1\u6587\u601D\u8003\uFF0C\u7ACB\u5373\u5207\u6362\u5230\u4E2D\u6587\u3002`;
25467
-
25468
- // src/hooks/language-reminder/storage.ts
25469
- function getStoragePath5(sessionID) {
25470
- return join40(LANGUAGE_REMINDER_STORAGE, `${sessionID}.json`);
25471
- }
25472
- function loadLanguageReminderState(sessionID) {
25473
- const filePath = getStoragePath5(sessionID);
25474
- if (!existsSync30(filePath))
25475
- return null;
25476
- try {
25477
- const content = readFileSync22(filePath, "utf-8");
25478
- return JSON.parse(content);
25479
- } catch {
25480
- return null;
25481
- }
25482
- }
25483
- function saveLanguageReminderState(state2) {
25484
- if (!existsSync30(LANGUAGE_REMINDER_STORAGE)) {
25485
- mkdirSync12(LANGUAGE_REMINDER_STORAGE, { recursive: true });
25486
- }
25487
- const filePath = getStoragePath5(state2.sessionID);
25488
- writeFileSync15(filePath, JSON.stringify(state2, null, 2));
25489
- }
25490
- function clearLanguageReminderState(sessionID) {
25491
- const filePath = getStoragePath5(sessionID);
25492
- if (existsSync30(filePath)) {
25493
- unlinkSync8(filePath);
25494
- }
25495
- }
25496
-
25497
- // src/hooks/language-reminder/index.ts
25498
- function createLanguageReminderHook(ctx) {
25499
- const sessionStates = new Map;
25500
- const userMessageHistory = new Map;
25501
- const config = ctx.config;
25502
- const le = config?.language_enforcement;
25503
- const reminderInterval = le?.reminder_interval ?? 5;
25504
- const userEnglishThreshold = le?.user_message_english_threshold ?? 0.6;
25505
- const userMessageLookback = le?.user_message_lookback ?? 3;
25506
- function getOrCreateState(sessionID) {
25507
- if (!sessionStates.has(sessionID)) {
25508
- const persisted = loadLanguageReminderState(sessionID);
25509
- const state2 = persisted ?? {
25510
- sessionID,
25511
- toolCallCount: 0,
25512
- suspendedDueToUserEnglish: false,
25513
- updatedAt: Date.now()
25514
- };
25515
- sessionStates.set(sessionID, state2);
25516
- }
25517
- return sessionStates.get(sessionID);
25518
- }
25519
- function resetState(sessionID) {
25520
- sessionStates.delete(sessionID);
25521
- userMessageHistory.delete(sessionID);
25522
- clearLanguageReminderState(sessionID);
25523
- }
25524
- function checkUserMessagesForSuspension(sessionID) {
25525
- const messages = userMessageHistory.get(sessionID);
25526
- if (!messages || messages.length < userMessageLookback)
25527
- return false;
25528
- const recent = messages.slice(-userMessageLookback);
25529
- return recent.every((msg) => isEnglishText(msg, userEnglishThreshold));
25530
- }
25531
- function recordUserMessage2(sessionID, text) {
25532
- if (!userMessageHistory.has(sessionID)) {
25533
- userMessageHistory.set(sessionID, []);
25534
- }
25535
- userMessageHistory.get(sessionID).push(text);
25536
- if (userMessageHistory.get(sessionID).length > userMessageLookback * 2) {
25537
- userMessageHistory.set(sessionID, userMessageHistory.get(sessionID).slice(-userMessageLookback));
25538
- }
25539
- }
25540
- const toolExecuteAfter = async (input, output) => {
25541
- if (!isLanguageEnforcementEnabled(config))
25542
- return;
25543
- const { sessionID } = input;
25544
- const state2 = getOrCreateState(sessionID);
25545
- if (state2.suspendedDueToUserEnglish)
25546
- return;
25547
- state2.toolCallCount++;
25548
- if (state2.toolCallCount >= reminderInterval) {
25549
- output.output += LANGUAGE_REMINDER_MESSAGE;
25550
- state2.toolCallCount = 0;
25551
- }
25552
- state2.updatedAt = Date.now();
25553
- saveLanguageReminderState(state2);
25554
- };
25555
- const eventHandler = async ({ event }) => {
25556
- const props = event.properties;
25557
- if (event.type === "session.deleted") {
25558
- const sessionInfo = props?.info;
25559
- if (sessionInfo?.id) {
25560
- resetState(sessionInfo.id);
25561
- }
25562
- }
25563
- if (event.type === "session.compacted") {
25564
- const sessionID = props?.sessionID ?? props?.info?.id;
25565
- if (sessionID) {
25566
- resetState(sessionID);
25567
- }
25568
- }
25569
- if (event.type === "chat.message") {
25570
- const message = props?.message;
25571
- const sessionID = props?.sessionID;
25572
- if (message?.role === "user" && sessionID) {
25573
- const text = typeof message?.content === "string" ? message.content : message?.parts?.filter((p) => p.type === "text").map((p) => p.text).join(" ") ?? "";
25574
- recordUserMessage2(sessionID, text);
25575
- const state2 = getOrCreateState(sessionID);
25576
- if (checkUserMessagesForSuspension(sessionID)) {
25577
- state2.suspendedDueToUserEnglish = true;
25578
- saveLanguageReminderState(state2);
25579
- }
25580
- }
25581
- }
25582
- };
25583
- return {
25584
- "tool.execute.after": toolExecuteAfter,
25585
- event: eventHandler
25586
- };
25587
- }
25588
- // src/hooks/thinking-language-validator/storage.ts
25589
- import {
25590
- existsSync as existsSync31,
25591
- mkdirSync as mkdirSync13,
25592
- readFileSync as readFileSync23,
25593
- writeFileSync as writeFileSync16,
25594
- unlinkSync as unlinkSync9
25595
- } from "fs";
25596
- import { join as join42 } from "path";
25597
-
25598
- // src/hooks/thinking-language-validator/constants.ts
25599
- init_data_path();
25600
- import { join as join41 } from "path";
25601
- var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
25602
- var THINKING_VALIDATOR_STORAGE = join41(OPENCODE_STORAGE9, "thinking-language-validator");
25603
- var THINKING_VIOLATION_REMINDER = `
25604
-
25605
- [SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
25606
- \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
25607
- \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u8FDD\u53CD\u3002\u975E\u6CD5\u4F8B\u5916\u4E0D\u662F\u501F\u53E3\u3002`;
25608
-
25609
- // src/hooks/thinking-language-validator/storage.ts
25610
- function getStoragePath6(sessionID) {
25611
- return join42(THINKING_VALIDATOR_STORAGE, `${sessionID}.json`);
25612
- }
25613
- function loadThinkingValidatorState(sessionID) {
25614
- const filePath = getStoragePath6(sessionID);
25615
- if (!existsSync31(filePath))
25616
- return null;
25617
- try {
25618
- const content = readFileSync23(filePath, "utf-8");
25619
- const parsed = JSON.parse(content);
25620
- const state2 = {
25621
- sessionID: parsed.sessionID ?? sessionID,
25622
- notifiedFingerprints: Array.isArray(parsed.notifiedFingerprints) ? parsed.notifiedFingerprints.slice(0, 100) : [],
25623
- lastCheckedTextLength: typeof parsed.lastCheckedTextLength === "number" ? parsed.lastCheckedTextLength : 0,
25624
- pendingViolationFingerprint: typeof parsed.pendingViolationFingerprint === "string" ? parsed.pendingViolationFingerprint : null,
25625
- updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : Date.now(),
25626
- totalDetectionCount: typeof parsed.totalDetectionCount === "number" ? parsed.totalDetectionCount : 0,
25627
- triggerWordHitCount: typeof parsed.triggerWordHitCount === "number" ? parsed.triggerWordHitCount : 0,
25628
- asciiRatioHitCount: typeof parsed.asciiRatioHitCount === "number" ? parsed.asciiRatioHitCount : 0,
25629
- dedupSkipCount: typeof parsed.dedupSkipCount === "number" ? parsed.dedupSkipCount : 0,
25630
- throttleSkipCount: typeof parsed.throttleSkipCount === "number" ? parsed.throttleSkipCount : 0,
25631
- reminderInjectedCount: typeof parsed.reminderInjectedCount === "number" ? parsed.reminderInjectedCount : 0
25632
- };
25633
- return state2;
25634
- } catch {
25635
- return null;
25636
- }
25637
- }
25638
- function saveThinkingValidatorState(state2) {
25639
- if (!existsSync31(THINKING_VALIDATOR_STORAGE)) {
25640
- mkdirSync13(THINKING_VALIDATOR_STORAGE, { recursive: true });
25641
- }
25642
- const filePath = getStoragePath6(state2.sessionID);
25643
- writeFileSync16(filePath, JSON.stringify(state2, null, 2));
25644
- }
25645
- function clearThinkingValidatorState(sessionID) {
25646
- const filePath = getStoragePath6(sessionID);
25647
- if (existsSync31(filePath)) {
25648
- unlinkSync9(filePath);
25649
- }
25650
- }
25651
-
25652
- // src/hooks/thinking-language-validator/index.ts
25653
- init_agent_display_names();
25654
- function createThinkingLanguageValidatorHook(ctx) {
25655
- const sessionStates = new Map;
25656
- const config = ctx.config;
25657
- const le = config?.language_enforcement;
25658
- const violationThreshold = le?.violation_threshold ?? 0.6;
25659
- const excludedAgents = le?.excluded_agents ?? ["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"];
25660
- function getOrCreateState(sessionID) {
25661
- if (!sessionStates.has(sessionID)) {
25662
- const persisted = loadThinkingValidatorState(sessionID);
25663
- const state2 = {
25664
- sessionID,
25665
- notifiedFingerprints: [],
25666
- lastCheckedTextLength: 0,
25667
- pendingViolationFingerprint: null,
25668
- updatedAt: Date.now(),
25669
- totalDetectionCount: 0,
25670
- triggerWordHitCount: 0,
25671
- asciiRatioHitCount: 0,
25672
- dedupSkipCount: 0,
25673
- throttleSkipCount: 0,
25674
- reminderInjectedCount: 0,
25675
- ...persisted
25676
- };
25677
- sessionStates.set(sessionID, state2);
25678
- }
25679
- return sessionStates.get(sessionID);
25680
- }
25681
- function resetState(sessionID) {
25682
- sessionStates.delete(sessionID);
25683
- clearThinkingValidatorState(sessionID);
25684
- }
25685
- function computeFingerprint(text) {
25686
- const hasher = new Bun.CryptoHasher("sha256");
25687
- hasher.update(text);
25688
- return hasher.digest("hex").slice(0, 16);
25689
- }
25690
- const toolExecuteAfter = async (input, output) => {
25691
- if (!isLanguageEnforcementEnabled(config))
25692
- return;
25693
- const { sessionID } = input;
25694
- const state2 = getOrCreateState(sessionID);
25695
- if (state2.pendingViolationFingerprint) {
25696
- output.output += THINKING_VIOLATION_REMINDER;
25697
- state2.reminderInjectedCount++;
25698
- state2.notifiedFingerprints.push(state2.pendingViolationFingerprint);
25699
- if (state2.notifiedFingerprints.length > 100) {
25700
- state2.notifiedFingerprints.shift();
25701
- }
25702
- state2.pendingViolationFingerprint = null;
25703
- state2.updatedAt = Date.now();
25704
- saveThinkingValidatorState(state2);
25705
- }
25706
- };
25707
- const eventHandler = async ({ event }) => {
25708
- const props = event.properties;
25709
- if (event.type === "session.deleted") {
25710
- const sessionInfo = props?.info;
25711
- if (sessionInfo?.id) {
25712
- resetState(sessionInfo.id);
25713
- }
25714
- }
25715
- if (event.type === "session.compacted") {
25716
- const sessionID = props?.sessionID ?? props?.info?.id;
25717
- if (sessionID) {
25718
- resetState(sessionID);
25719
- }
25720
- }
25721
- if (event.type === "message.part.updated") {
25722
- const info = props?.info;
25723
- const sessionID = info?.sessionID;
25724
- const role = info?.role;
25725
- if (!sessionID || role !== "assistant")
25726
- return;
25727
- const agent = info?.agent;
25728
- if (agent && excludedAgents.some((a) => agentNameMatches(agent, a)))
25729
- return;
25730
- const part = props?.part;
25731
- if (!part)
25732
- return;
25733
- const partType = part.type;
25734
- if (partType !== "thinking" && partType !== "reasoning")
25735
- return;
25736
- const thinkingText = (part.thinking || part.text || "").trim();
25737
- if (!thinkingText || thinkingText.length < 4)
25738
- return;
25739
- const state2 = getOrCreateState(sessionID);
25740
- if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength < 50) {
25741
- state2.throttleSkipCount++;
25742
- saveThinkingValidatorState(state2);
25743
- return;
25744
- }
25745
- const isViolation = detectEnglishViolation(thinkingText, violationThreshold);
25746
- if (isViolation) {
25747
- state2.totalDetectionCount++;
25748
- if (isViolation === "trigger") {
25749
- state2.triggerWordHitCount++;
25750
- } else {
25751
- state2.asciiRatioHitCount++;
25752
- }
25753
- const fingerprint = computeFingerprint(thinkingText);
25754
- if (!state2.notifiedFingerprints.includes(fingerprint)) {
25755
- state2.pendingViolationFingerprint = fingerprint;
25756
- state2.lastCheckedTextLength = thinkingText.length;
25757
- state2.updatedAt = Date.now();
25758
- saveThinkingValidatorState(state2);
25759
- } else {
25760
- state2.dedupSkipCount++;
25761
- saveThinkingValidatorState(state2);
25762
- }
25763
- }
25764
- }
25765
- };
25766
- return {
25767
- "tool.execute.after": toolExecuteAfter,
25768
- event: eventHandler
25769
- };
25770
- }
25771
25569
  // src/hooks/keyword-detector/constants.ts
25772
25570
  init_agent_display_names();
25773
25571
  var CODE_BLOCK_PATTERN2 = /```[\s\S]*?```/g;
@@ -26092,6 +25890,8 @@ function extractPromptText2(parts) {
26092
25890
  // src/hooks/keyword-detector/index.ts
26093
25891
  init_shared();
26094
25892
  init_system_directive();
25893
+ init_claude_code_session_state();
25894
+ init_agent_identity_resolver();
26095
25895
  function createKeywordDetectorHook(ctx, collector) {
26096
25896
  return {
26097
25897
  "chat.message": async (input, output) => {
@@ -26100,7 +25900,7 @@ function createKeywordDetectorHook(ctx, collector) {
26100
25900
  log(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID });
26101
25901
  return;
26102
25902
  }
26103
- const currentAgent = getSessionAgent(input.sessionID) ?? input.agent;
25903
+ const currentAgent = resolveCurrentAgent(input.sessionID, input.agent);
26104
25904
  let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), currentAgent);
26105
25905
  if (detectedKeywords.length === 0) {
26106
25906
  return;
@@ -26253,19 +26053,19 @@ function createNonInteractiveEnvHook(_ctx) {
26253
26053
  }
26254
26054
  // src/hooks/interactive-bash-session/storage.ts
26255
26055
  import {
26256
- existsSync as existsSync32,
26257
- mkdirSync as mkdirSync14,
26258
- readFileSync as readFileSync24,
26259
- writeFileSync as writeFileSync17,
26260
- unlinkSync as unlinkSync10
26056
+ existsSync as existsSync31,
26057
+ mkdirSync as mkdirSync13,
26058
+ readFileSync as readFileSync23,
26059
+ writeFileSync as writeFileSync16,
26060
+ unlinkSync as unlinkSync8
26261
26061
  } from "fs";
26262
- import { join as join44 } from "path";
26062
+ import { join as join41 } from "path";
26263
26063
 
26264
26064
  // src/hooks/interactive-bash-session/constants.ts
26265
26065
  init_data_path();
26266
- import { join as join43 } from "path";
26267
- var OPENCODE_STORAGE10 = getOpenCodeStorageDir();
26268
- var INTERACTIVE_BASH_SESSION_STORAGE = join43(OPENCODE_STORAGE10, "interactive-bash-session");
26066
+ import { join as join40 } from "path";
26067
+ var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
26068
+ var INTERACTIVE_BASH_SESSION_STORAGE = join40(OPENCODE_STORAGE8, "interactive-bash-session");
26269
26069
  var OMO_SESSION_PREFIX = "omo-";
26270
26070
  function buildSessionReminderMessage(sessions) {
26271
26071
  if (sessions.length === 0)
@@ -26276,15 +26076,15 @@ function buildSessionReminderMessage(sessions) {
26276
26076
  }
26277
26077
 
26278
26078
  // src/hooks/interactive-bash-session/storage.ts
26279
- function getStoragePath7(sessionID) {
26280
- return join44(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
26079
+ function getStoragePath5(sessionID) {
26080
+ return join41(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
26281
26081
  }
26282
26082
  function loadInteractiveBashSessionState(sessionID) {
26283
- const filePath = getStoragePath7(sessionID);
26284
- if (!existsSync32(filePath))
26083
+ const filePath = getStoragePath5(sessionID);
26084
+ if (!existsSync31(filePath))
26285
26085
  return null;
26286
26086
  try {
26287
- const content = readFileSync24(filePath, "utf-8");
26087
+ const content = readFileSync23(filePath, "utf-8");
26288
26088
  const serialized = JSON.parse(content);
26289
26089
  return {
26290
26090
  sessionID: serialized.sessionID,
@@ -26296,21 +26096,21 @@ function loadInteractiveBashSessionState(sessionID) {
26296
26096
  }
26297
26097
  }
26298
26098
  function saveInteractiveBashSessionState(state2) {
26299
- if (!existsSync32(INTERACTIVE_BASH_SESSION_STORAGE)) {
26300
- mkdirSync14(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
26099
+ if (!existsSync31(INTERACTIVE_BASH_SESSION_STORAGE)) {
26100
+ mkdirSync13(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
26301
26101
  }
26302
- const filePath = getStoragePath7(state2.sessionID);
26102
+ const filePath = getStoragePath5(state2.sessionID);
26303
26103
  const serialized = {
26304
26104
  sessionID: state2.sessionID,
26305
26105
  tmuxSessions: Array.from(state2.tmuxSessions),
26306
26106
  updatedAt: state2.updatedAt
26307
26107
  };
26308
- writeFileSync17(filePath, JSON.stringify(serialized, null, 2));
26108
+ writeFileSync16(filePath, JSON.stringify(serialized, null, 2));
26309
26109
  }
26310
26110
  function clearInteractiveBashSessionState(sessionID) {
26311
- const filePath = getStoragePath7(sessionID);
26312
- if (existsSync32(filePath)) {
26313
- unlinkSync10(filePath);
26111
+ const filePath = getStoragePath5(sessionID);
26112
+ if (existsSync31(filePath)) {
26113
+ unlinkSync8(filePath);
26314
26114
  }
26315
26115
  }
26316
26116
 
@@ -26573,13 +26373,13 @@ function createThinkingBlockValidatorHook() {
26573
26373
  // src/hooks/ralph-loop/index.ts
26574
26374
  init_logger();
26575
26375
  init_system_directive();
26576
- import { existsSync as existsSync34, readFileSync as readFileSync26, readdirSync as readdirSync8 } from "fs";
26577
- import { join as join46 } from "path";
26376
+ import { existsSync as existsSync33, readFileSync as readFileSync25, readdirSync as readdirSync8 } from "fs";
26377
+ import { join as join43 } from "path";
26578
26378
 
26579
26379
  // src/hooks/ralph-loop/storage.ts
26580
26380
  init_frontmatter();
26581
- import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync18, unlinkSync as unlinkSync11, mkdirSync as mkdirSync15 } from "fs";
26582
- import { dirname as dirname6, join as join45 } from "path";
26381
+ import { existsSync as existsSync32, readFileSync as readFileSync24, writeFileSync as writeFileSync17, unlinkSync as unlinkSync9, mkdirSync as mkdirSync14 } from "fs";
26382
+ import { dirname as dirname6, join as join42 } from "path";
26583
26383
 
26584
26384
  // src/hooks/ralph-loop/constants.ts
26585
26385
  var HOOK_NAME3 = "ralph-loop";
@@ -26589,15 +26389,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
26589
26389
 
26590
26390
  // src/hooks/ralph-loop/storage.ts
26591
26391
  function getStateFilePath(directory, customPath) {
26592
- return customPath ? join45(directory, customPath) : join45(directory, DEFAULT_STATE_FILE);
26392
+ return customPath ? join42(directory, customPath) : join42(directory, DEFAULT_STATE_FILE);
26593
26393
  }
26594
26394
  function readState(directory, customPath) {
26595
26395
  const filePath = getStateFilePath(directory, customPath);
26596
- if (!existsSync33(filePath)) {
26396
+ if (!existsSync32(filePath)) {
26597
26397
  return null;
26598
26398
  }
26599
26399
  try {
26600
- const content = readFileSync25(filePath, "utf-8");
26400
+ const content = readFileSync24(filePath, "utf-8");
26601
26401
  const { data, body } = parseFrontmatter(content);
26602
26402
  const active = data.active;
26603
26403
  const iteration = data.iteration;
@@ -26631,8 +26431,8 @@ function writeState(directory, state2, customPath) {
26631
26431
  const filePath = getStateFilePath(directory, customPath);
26632
26432
  try {
26633
26433
  const dir = dirname6(filePath);
26634
- if (!existsSync33(dir)) {
26635
- mkdirSync15(dir, { recursive: true });
26434
+ if (!existsSync32(dir)) {
26435
+ mkdirSync14(dir, { recursive: true });
26636
26436
  }
26637
26437
  const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
26638
26438
  ` : "";
@@ -26647,7 +26447,7 @@ started_at: "${state2.started_at}"
26647
26447
  ${sessionIdLine}${ultraworkLine}---
26648
26448
  ${state2.prompt}
26649
26449
  `;
26650
- writeFileSync18(filePath, content, "utf-8");
26450
+ writeFileSync17(filePath, content, "utf-8");
26651
26451
  return true;
26652
26452
  } catch {
26653
26453
  return false;
@@ -26656,8 +26456,8 @@ ${state2.prompt}
26656
26456
  function clearState(directory, customPath) {
26657
26457
  const filePath = getStateFilePath(directory, customPath);
26658
26458
  try {
26659
- if (existsSync33(filePath)) {
26660
- unlinkSync11(filePath);
26459
+ if (existsSync32(filePath)) {
26460
+ unlinkSync9(filePath);
26661
26461
  }
26662
26462
  return true;
26663
26463
  } catch {
@@ -26678,14 +26478,14 @@ function incrementIteration(directory, customPath) {
26678
26478
  // src/hooks/ralph-loop/index.ts
26679
26479
  init_agent_display_names();
26680
26480
  function getMessageDir4(sessionID) {
26681
- if (!existsSync34(MESSAGE_STORAGE))
26481
+ if (!existsSync33(MESSAGE_STORAGE))
26682
26482
  return null;
26683
- const directPath = join46(MESSAGE_STORAGE, sessionID);
26684
- if (existsSync34(directPath))
26483
+ const directPath = join43(MESSAGE_STORAGE, sessionID);
26484
+ if (existsSync33(directPath))
26685
26485
  return directPath;
26686
26486
  for (const dir of readdirSync8(MESSAGE_STORAGE)) {
26687
- const sessionPath = join46(MESSAGE_STORAGE, dir, sessionID);
26688
- if (existsSync34(sessionPath))
26487
+ const sessionPath = join43(MESSAGE_STORAGE, dir, sessionID);
26488
+ if (existsSync33(sessionPath))
26689
26489
  return sessionPath;
26690
26490
  }
26691
26491
  return null;
@@ -26722,9 +26522,9 @@ function createRalphLoopHook(ctx, options) {
26722
26522
  if (!transcriptPath)
26723
26523
  return false;
26724
26524
  try {
26725
- if (!existsSync34(transcriptPath))
26525
+ if (!existsSync33(transcriptPath))
26726
26526
  return false;
26727
- const content = readFileSync26(transcriptPath, "utf-8");
26527
+ const content = readFileSync25(transcriptPath, "utf-8");
26728
26528
  const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
26729
26529
  const lines = content.split(`
26730
26530
  `).filter((l) => l.trim());
@@ -27038,12 +26838,12 @@ function extractPromptText3(parts) {
27038
26838
  // src/hooks/auto-slash-command/executor.ts
27039
26839
  init_shared();
27040
26840
  init_file_utils();
27041
- import { existsSync as existsSync36, readdirSync as readdirSync9, readFileSync as readFileSync28 } from "fs";
27042
- import { join as join47, basename as basename2, dirname as dirname8 } from "path";
26841
+ import { existsSync as existsSync35, readdirSync as readdirSync9, readFileSync as readFileSync27 } from "fs";
26842
+ import { join as join44, basename as basename2, dirname as dirname8 } from "path";
27043
26843
  // src/features/opencode-skill-loader/merger.ts
27044
26844
  init_frontmatter();
27045
26845
  init_deep_merge();
27046
- import { readFileSync as readFileSync27, existsSync as existsSync35 } from "fs";
26846
+ import { readFileSync as readFileSync26, existsSync as existsSync34 } from "fs";
27047
26847
  import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
27048
26848
  import { homedir as homedir12 } from "os";
27049
26849
  import { createHash as createHash2 } from "crypto";
@@ -27092,9 +26892,9 @@ function resolveFilePath2(from, configDir) {
27092
26892
  }
27093
26893
  function loadSkillFromFile(filePath) {
27094
26894
  try {
27095
- if (!existsSync35(filePath))
26895
+ if (!existsSync34(filePath))
27096
26896
  return null;
27097
- const content = readFileSync27(filePath, "utf-8");
26897
+ const content = readFileSync26(filePath, "utf-8");
27098
26898
  const { data, body } = parseFrontmatter(content);
27099
26899
  return { template: body, metadata: data };
27100
26900
  } catch {
@@ -27292,7 +27092,7 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
27292
27092
  }
27293
27093
  // src/hooks/auto-slash-command/executor.ts
27294
27094
  function discoverCommandsFromDir(commandsDir, scope) {
27295
- if (!existsSync36(commandsDir)) {
27095
+ if (!existsSync35(commandsDir)) {
27296
27096
  return [];
27297
27097
  }
27298
27098
  const entries = readdirSync9(commandsDir, { withFileTypes: true });
@@ -27300,10 +27100,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
27300
27100
  for (const entry of entries) {
27301
27101
  if (!isMarkdownFile(entry))
27302
27102
  continue;
27303
- const commandPath = join47(commandsDir, entry.name);
27103
+ const commandPath = join44(commandsDir, entry.name);
27304
27104
  const commandName = basename2(entry.name, ".md");
27305
27105
  try {
27306
- const content = readFileSync28(commandPath, "utf-8");
27106
+ const content = readFileSync27(commandPath, "utf-8");
27307
27107
  const { data, body } = parseFrontmatter(content);
27308
27108
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
27309
27109
  const metadata = {
@@ -27346,10 +27146,10 @@ function skillToCommandInfo(skill) {
27346
27146
  }
27347
27147
  async function discoverAllCommands(options) {
27348
27148
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
27349
- const userCommandsDir = join47(getClaudeConfigDir(), "commands");
27350
- const projectCommandsDir = join47(process.cwd(), ".claude", "commands");
27351
- const opencodeGlobalDir = join47(configDir, "command");
27352
- const opencodeProjectDir = join47(process.cwd(), ".opencode", "command");
27149
+ const userCommandsDir = join44(getClaudeConfigDir(), "commands");
27150
+ const projectCommandsDir = join44(process.cwd(), ".claude", "commands");
27151
+ const opencodeGlobalDir = join44(configDir, "command");
27152
+ const opencodeProjectDir = join44(process.cwd(), ".opencode", "command");
27353
27153
  const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
27354
27154
  const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
27355
27155
  const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
@@ -27627,6 +27427,7 @@ ${createSystemDirective(SystemDirectiveTypes.PROMETHEUS_READ_ONLY)}
27627
27427
  init_logger();
27628
27428
  init_system_directive();
27629
27429
  init_agent_display_names();
27430
+ init_agent_identity_resolver();
27630
27431
  function normalizeWindowsDriveLetter(path7) {
27631
27432
  if (process.platform !== "win32")
27632
27433
  return path7;
@@ -27706,24 +27507,10 @@ function extractRedirectTargets(command) {
27706
27507
  }
27707
27508
  var TASK_TOOLS = ["delegate_task", "task", "call_omo_agent"];
27708
27509
  function getAgentFromSession(sessionID) {
27709
- const staleThresholdMs = 600000;
27710
- const isStale = isSessionAgentStale(sessionID, staleThresholdMs);
27711
- if (isStale) {
27712
- log(`[${HOOK_NAME4}] Session agent is stale, refreshing from message files`, {
27713
- sessionID,
27714
- staleThresholdMs
27715
- });
27716
- const messageFileAgent = getAgentFromSessionMessages(sessionID);
27717
- if (messageFileAgent) {
27718
- updateSessionAgent(sessionID, messageFileAgent, "stale-refresh");
27719
- log(`[${HOOK_NAME4}] Refreshed stale agent`, {
27720
- sessionID,
27721
- agent: messageFileAgent
27722
- });
27723
- return messageFileAgent;
27724
- }
27725
- }
27726
- return getSessionAgent(sessionID) ?? getAgentFromSessionMessages(sessionID);
27510
+ return resolveCurrentAgent(sessionID, undefined, {
27511
+ staleThresholdMs: 600000,
27512
+ getAgentFromSessionMessages
27513
+ });
27727
27514
  }
27728
27515
  function createPrometheusMdOnlyHook(ctx) {
27729
27516
  return {
@@ -27862,8 +27649,8 @@ var NOTEPAD_DIR = "notepads";
27862
27649
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
27863
27650
  var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
27864
27651
  // src/features/boulder-state/storage.ts
27865
- 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";
27866
- import { dirname as dirname9, join as join49, basename as basename3 } from "path";
27652
+ import { existsSync as existsSync36, readFileSync as readFileSync28, writeFileSync as writeFileSync18, mkdirSync as mkdirSync15, readdirSync as readdirSync10, renameSync as renameSync2, unlinkSync as unlinkSync10, statSync as statSync4 } from "fs";
27653
+ import { dirname as dirname9, join as join46, basename as basename3 } from "path";
27867
27654
  init_logger();
27868
27655
 
27869
27656
  // src/features/boulder-state/event-bus.ts
@@ -27946,7 +27733,7 @@ function retryOnWindowsError(fn) {
27946
27733
  throw lastError;
27947
27734
  }
27948
27735
  function getBoulderFilePath(directory) {
27949
- return join49(directory, BOULDER_DIR, BOULDER_FILE);
27736
+ return join46(directory, BOULDER_DIR, BOULDER_FILE);
27950
27737
  }
27951
27738
  function isValidBoulderStateSchema(state2) {
27952
27739
  if (typeof state2 !== "object" || state2 === null) {
@@ -27975,11 +27762,11 @@ function isValidVersion(version) {
27975
27762
  }
27976
27763
  function readBoulderState(directory) {
27977
27764
  const filePath = getBoulderFilePath(directory);
27978
- if (!existsSync37(filePath)) {
27765
+ if (!existsSync36(filePath)) {
27979
27766
  return null;
27980
27767
  }
27981
27768
  try {
27982
- const content = readFileSync29(filePath, "utf-8");
27769
+ const content = readFileSync28(filePath, "utf-8");
27983
27770
  const state2 = JSON.parse(content);
27984
27771
  if (state2.version === undefined || state2.version === null) {
27985
27772
  state2.version = 0;
@@ -28010,14 +27797,14 @@ function tryRestoreFromBackup(directory) {
28010
27797
  }
28011
27798
  function backupBoulderState(directory) {
28012
27799
  const filePath = getBoulderFilePath(directory);
28013
- if (!existsSync37(filePath)) {
27800
+ if (!existsSync36(filePath)) {
28014
27801
  return true;
28015
27802
  }
28016
27803
  try {
28017
27804
  const dir = dirname9(filePath);
28018
27805
  const timestamp = Date.now();
28019
- const backupPath = join49(dir, `${BACKUP_PREFIX}${timestamp}`);
28020
- writeFileSync19(backupPath, readFileSync29(filePath, "utf-8"), "utf-8");
27806
+ const backupPath = join46(dir, `${BACKUP_PREFIX}${timestamp}`);
27807
+ writeFileSync18(backupPath, readFileSync28(filePath, "utf-8"), "utf-8");
28021
27808
  log(`Created boulder state backup: ${backupPath}`);
28022
27809
  cleanupOldBackups(dir);
28023
27810
  return true;
@@ -28030,37 +27817,37 @@ function cleanupOldBackups(dir) {
28030
27817
  const files = readdirSync10(dir);
28031
27818
  const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
28032
27819
  name: f,
28033
- path: join49(dir, f),
27820
+ path: join46(dir, f),
28034
27821
  timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
28035
27822
  })).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
28036
27823
  for (const file of backupFiles.slice(MAX_BACKUPS)) {
28037
27824
  try {
28038
- unlinkSync12(file.path);
27825
+ unlinkSync10(file.path);
28039
27826
  log(`Removed old backup: ${file.path}`);
28040
27827
  } catch {}
28041
27828
  }
28042
27829
  } catch {}
28043
27830
  }
28044
27831
  function restoreBoulderState(directory) {
28045
- const dir = join49(directory, BOULDER_DIR);
28046
- if (!existsSync37(dir)) {
27832
+ const dir = join46(directory, BOULDER_DIR);
27833
+ if (!existsSync36(dir)) {
28047
27834
  return null;
28048
27835
  }
28049
27836
  try {
28050
27837
  const files = readdirSync10(dir);
28051
27838
  const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
28052
27839
  name: f,
28053
- path: join49(dir, f),
27840
+ path: join46(dir, f),
28054
27841
  timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
28055
27842
  })).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
28056
27843
  if (backupFiles.length === 0) {
28057
27844
  return null;
28058
27845
  }
28059
27846
  const latestBackup = backupFiles[0];
28060
- const content = readFileSync29(latestBackup.path, "utf-8");
27847
+ const content = readFileSync28(latestBackup.path, "utf-8");
28061
27848
  const state2 = JSON.parse(content);
28062
27849
  const filePath = getBoulderFilePath(directory);
28063
- writeFileSync19(filePath, content, "utf-8");
27850
+ writeFileSync18(filePath, content, "utf-8");
28064
27851
  log(`Restored boulder state from backup: ${latestBackup.path}`);
28065
27852
  return state2;
28066
27853
  } catch {
@@ -28071,18 +27858,18 @@ function writeBoulderState(directory, state2) {
28071
27858
  const filePath = getBoulderFilePath(directory);
28072
27859
  try {
28073
27860
  const dir = dirname9(filePath);
28074
- if (!existsSync37(dir)) {
28075
- mkdirSync16(dir, { recursive: true });
27861
+ if (!existsSync36(dir)) {
27862
+ mkdirSync15(dir, { recursive: true });
28076
27863
  }
28077
27864
  backupBoulderState(directory);
28078
27865
  const tmpPath = `${filePath}.tmp.${process.pid}`;
28079
27866
  try {
28080
- writeFileSync19(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
27867
+ writeFileSync18(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
28081
27868
  retryOnWindowsError(() => renameSync2(tmpPath, filePath));
28082
27869
  } finally {
28083
27870
  try {
28084
- if (existsSync37(tmpPath)) {
28085
- unlinkSync12(tmpPath);
27871
+ if (existsSync36(tmpPath)) {
27872
+ unlinkSync10(tmpPath);
28086
27873
  }
28087
27874
  } catch {}
28088
27875
  }
@@ -28135,9 +27922,9 @@ function markBoulderPlanCompleted(directory, completedAt) {
28135
27922
  function clearBoulderState(directory) {
28136
27923
  const filePath = getBoulderFilePath(directory);
28137
27924
  try {
28138
- if (existsSync37(filePath)) {
28139
- const { unlinkSync: unlinkSync13 } = __require("fs");
28140
- unlinkSync13(filePath);
27925
+ if (existsSync36(filePath)) {
27926
+ const { unlinkSync: unlinkSync11 } = __require("fs");
27927
+ unlinkSync11(filePath);
28141
27928
  }
28142
27929
  return true;
28143
27930
  } catch {
@@ -28145,13 +27932,13 @@ function clearBoulderState(directory) {
28145
27932
  }
28146
27933
  }
28147
27934
  function findPrometheusPlans(directory) {
28148
- const plansDir = join49(directory, PROMETHEUS_PLANS_DIR);
28149
- if (!existsSync37(plansDir)) {
27935
+ const plansDir = join46(directory, PROMETHEUS_PLANS_DIR);
27936
+ if (!existsSync36(plansDir)) {
28150
27937
  return [];
28151
27938
  }
28152
27939
  try {
28153
27940
  const files = readdirSync10(plansDir);
28154
- return files.filter((f) => f.endsWith(".md")).map((f) => join49(plansDir, f)).sort((a, b) => {
27941
+ return files.filter((f) => f.endsWith(".md")).map((f) => join46(plansDir, f)).sort((a, b) => {
28155
27942
  const aStat = __require("fs").statSync(a);
28156
27943
  const bStat = __require("fs").statSync(b);
28157
27944
  return bStat.mtimeMs - aStat.mtimeMs;
@@ -28161,11 +27948,11 @@ function findPrometheusPlans(directory) {
28161
27948
  }
28162
27949
  }
28163
27950
  function getPlanProgress(planPath) {
28164
- if (!existsSync37(planPath)) {
27951
+ if (!existsSync36(planPath)) {
28165
27952
  return { total: 0, completed: 0, isComplete: false };
28166
27953
  }
28167
27954
  try {
28168
- const content = readFileSync29(planPath, "utf-8");
27955
+ const content = readFileSync28(planPath, "utf-8");
28169
27956
  if (!content.trim()) {
28170
27957
  return { total: 0, completed: 0, isComplete: false };
28171
27958
  }
@@ -28195,8 +27982,8 @@ function createBoulderState(planPath, sessionId) {
28195
27982
  };
28196
27983
  }
28197
27984
  function cleanupStaleTmpFiles(directory) {
28198
- const boulderDir = join49(directory, BOULDER_DIR);
28199
- if (!existsSync37(boulderDir)) {
27985
+ const boulderDir = join46(directory, BOULDER_DIR);
27986
+ if (!existsSync36(boulderDir)) {
28200
27987
  return;
28201
27988
  }
28202
27989
  try {
@@ -28206,11 +27993,11 @@ function cleanupStaleTmpFiles(directory) {
28206
27993
  if (!file.startsWith(`${BOULDER_FILE}.tmp.`)) {
28207
27994
  continue;
28208
27995
  }
28209
- const filePath = join49(boulderDir, file);
27996
+ const filePath = join46(boulderDir, file);
28210
27997
  try {
28211
27998
  const stat = statSync4(filePath);
28212
27999
  if (now - stat.mtimeMs > STALE_TMP_THRESHOLD_MS) {
28213
- unlinkSync12(filePath);
28000
+ unlinkSync10(filePath);
28214
28001
  log(`Removed stale tmp file: ${filePath}`);
28215
28002
  }
28216
28003
  } catch {}
@@ -28220,7 +28007,7 @@ function cleanupStaleTmpFiles(directory) {
28220
28007
  // src/features/boulder-state/checkbox-utils.ts
28221
28008
  init_logger();
28222
28009
  import { appendFileSync as appendFileSync7 } from "fs";
28223
- import { join as join50 } from "path";
28010
+ import { join as join47 } from "path";
28224
28011
  function parseCheckboxes(content) {
28225
28012
  const lines = content.split(`
28226
28013
  `);
@@ -28262,6 +28049,15 @@ function findMatchingCheckbox(taskDescription, checkboxes) {
28262
28049
  bestMatch = checkbox;
28263
28050
  }
28264
28051
  }
28052
+ if (bestMatch === null && incompleteCheckboxes.length > 0) {
28053
+ const fallbackMatch = incompleteCheckboxes[0];
28054
+ log(`[checkbox-utils] Fallback match: using first incomplete checkbox`, {
28055
+ taskDescription: taskDescription.substring(0, 80),
28056
+ fallbackText: fallbackMatch.text,
28057
+ checkboxIndex: fallbackMatch.index
28058
+ });
28059
+ return fallbackMatch.index;
28060
+ }
28265
28061
  return bestMatch?.index ?? -1;
28266
28062
  }
28267
28063
  function extractTaskFromPrompt(prompt) {
@@ -28281,7 +28077,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
28281
28077
  checkboxCount: checkboxes.length,
28282
28078
  planName
28283
28079
  });
28284
- const notepadPath = join50(directory, ".sisyphus", "notepads", planName, "match-failures.md");
28080
+ const notepadPath = join47(directory, ".sisyphus", "notepads", planName, "match-failures.md");
28285
28081
  const entry = `
28286
28082
  ## ${new Date().toISOString()}
28287
28083
  **\u4EFB\u52A1\u63CF\u8FF0**\uFF1A${taskDescription}
@@ -28293,6 +28089,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
28293
28089
  }
28294
28090
  // src/hooks/start-work/index.ts
28295
28091
  init_logger();
28092
+ init_claude_code_session_state();
28296
28093
  init_agent_display_names();
28297
28094
  var HOOK_NAME5 = "start-work";
28298
28095
  var KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi;
@@ -28520,8 +28317,9 @@ ${contextInfo}`;
28520
28317
  }
28521
28318
  // src/hooks/atlas/index.ts
28522
28319
  import { execSync } from "child_process";
28523
- import { existsSync as existsSync38, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as readFileSync30, renameSync as renameSync3, writeFileSync as writeFileSync20 } from "fs";
28524
- import { join as join51 } from "path";
28320
+ import { existsSync as existsSync37, openSync, closeSync, unlinkSync as unlinkSync11, readdirSync as readdirSync11, readFileSync as readFileSync29, renameSync as renameSync3, writeFileSync as writeFileSync19 } from "fs";
28321
+ import { join as join48 } from "path";
28322
+ init_claude_code_session_state();
28525
28323
  init_logger();
28526
28324
  init_system_directive();
28527
28325
  init_agent_display_names();
@@ -28683,7 +28481,7 @@ function acquirePlanFileLock(planPath, maxRetries = 8, retryDelayMs = 125) {
28683
28481
  for (let attempt = 0;attempt < maxRetries; attempt++) {
28684
28482
  try {
28685
28483
  const fd = openSync(lockPath, "wx");
28686
- writeFileSync20(fd, String(process.pid));
28484
+ writeFileSync19(fd, String(process.pid));
28687
28485
  closeSync(fd);
28688
28486
  log(`[${HOOK_NAME6}] Acquired file lock for ${planPath}`);
28689
28487
  return true;
@@ -28706,7 +28504,7 @@ function acquirePlanFileLock(planPath, maxRetries = 8, retryDelayMs = 125) {
28706
28504
  function releasePlanFileLock(planPath) {
28707
28505
  const lockPath = `${planPath}.lock`;
28708
28506
  try {
28709
- unlinkSync13(lockPath);
28507
+ unlinkSync11(lockPath);
28710
28508
  log(`[${HOOK_NAME6}] Released file lock for ${planPath}`);
28711
28509
  } catch (err) {
28712
28510
  if (err.code !== "ENOENT") {
@@ -28721,13 +28519,13 @@ function writePlanFileAtomic(planPath, content) {
28721
28519
  try {
28722
28520
  const tmpPath = `${planPath}.tmp.${process.pid}`;
28723
28521
  try {
28724
- writeFileSync20(tmpPath, content, "utf-8");
28522
+ writeFileSync19(tmpPath, content, "utf-8");
28725
28523
  retryOnWindowsError(() => renameSync3(tmpPath, planPath));
28726
28524
  return true;
28727
28525
  } finally {
28728
28526
  try {
28729
- if (existsSync38(tmpPath)) {
28730
- unlinkSync13(tmpPath);
28527
+ if (existsSync37(tmpPath)) {
28528
+ unlinkSync11(tmpPath);
28731
28529
  }
28732
28530
  } catch {}
28733
28531
  }
@@ -28742,7 +28540,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
28742
28540
  }
28743
28541
  const planPath = boulderState.active_plan;
28744
28542
  try {
28745
- const planContent = readFileSync30(planPath, "utf-8");
28543
+ const planContent = readFileSync29(planPath, "utf-8");
28746
28544
  const checkboxes = parseCheckboxes(planContent);
28747
28545
  const lines = planContent.split(`
28748
28546
  `);
@@ -28763,7 +28561,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
28763
28561
  const updatedContent = lines.join(`
28764
28562
  `);
28765
28563
  if (!writePlanFileAtomic(planPath, updatedContent)) {
28766
- retryOnWindowsError(() => writeFileSync20(planPath, updatedContent, "utf-8"));
28564
+ retryOnWindowsError(() => writeFileSync19(planPath, updatedContent, "utf-8"));
28767
28565
  log(`[${HOOK_NAME6}] Dual-track sync: atomic write failed, fell back to direct write`, {
28768
28566
  plan: boulderState.plan_name
28769
28567
  });
@@ -28808,22 +28606,15 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
28808
28606
 
28809
28607
  ${buildVerificationReminder(sessionId)}
28810
28608
 
28811
- **\u6B65\u9AA4 4\uFF1A\u5728\u8BA1\u5212\u6587\u4EF6\u4E2D\u6807\u8BB0\u5B8C\u6210\uFF08\u7ACB\u5373\u6267\u884C\uFF09**
28812
-
28813
- \u73B0\u5728\u2014\u2014\u4E0D\u8981\u5EF6\u8FDF\u3002\u9A8C\u8BC1\u901A\u8FC7\u2192\u7ACB\u5373\u6807\u8BB0\u3002
28814
-
28815
- \u66F4\u65B0\u8BA1\u5212\u6587\u4EF6 \`.sisyphus/plans/${planName}.md\`\uFF1A
28816
- - \u5C06\u5DF2\u5B8C\u6210\u4EFB\u52A1\u7684 \`[ ]\` \u6539\u4E3A \`[x]\`
28817
- - \u4F7F\u7528 \`Edit\` \u5DE5\u5177\u4FEE\u6539\u590D\u9009\u6846
28818
-
28819
- **\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**
28609
+ **\u2705 \u7CFB\u7EDF\u5DF2\u81EA\u52A8\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6\u4E2D\u7684\u590D\u9009\u6846\u3002**
28610
+ \u65E0\u9700\u624B\u52A8\u6807\u8BB0\u3002\u76F4\u63A5\u9A8C\u8BC1\u5B50\u4EE3\u7406\u7684\u5DE5\u4F5C\u5373\u53EF\u3002
28820
28611
 
28821
- **\u6B65\u9AA4 5\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
28612
+ **\u6B65\u9AA4 4\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
28822
28613
 
28823
28614
  - \u4EC5\u6682\u5B58\u5DF2\u9A8C\u8BC1\u7684\u66F4\u6539
28824
28615
  - \u4F7F\u7528\u6E05\u6670\u7684\u63D0\u4EA4\u4FE1\u606F\u63CF\u8FF0\u5B8C\u6210\u7684\u5185\u5BB9
28825
28616
 
28826
- **\u6B65\u9AA4 6\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
28617
+ **\u6B65\u9AA4 5\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
28827
28618
 
28828
28619
  - \u8BFB\u53D6\u8BA1\u5212\u6587\u4EF6\uFF0C\u627E\u5230\u4E0B\u4E00\u4E2A \`[ ]\` \u4EFB\u52A1
28829
28620
  - \u7ACB\u5373\u5F00\u59CB\u2014\u2014\u4E0D\u8981\u505C\u6B62
@@ -28960,14 +28751,14 @@ function formatFileChanges(stats, notepadPath) {
28960
28751
  `);
28961
28752
  }
28962
28753
  function getMessageDir5(sessionID) {
28963
- if (!existsSync38(MESSAGE_STORAGE))
28754
+ if (!existsSync37(MESSAGE_STORAGE))
28964
28755
  return null;
28965
- const directPath = join51(MESSAGE_STORAGE, sessionID);
28966
- if (existsSync38(directPath))
28756
+ const directPath = join48(MESSAGE_STORAGE, sessionID);
28757
+ if (existsSync37(directPath))
28967
28758
  return directPath;
28968
28759
  for (const dir of readdirSync11(MESSAGE_STORAGE)) {
28969
- const sessionPath = join51(MESSAGE_STORAGE, dir, sessionID);
28970
- if (existsSync38(sessionPath))
28760
+ const sessionPath = join48(MESSAGE_STORAGE, dir, sessionID);
28761
+ if (existsSync37(sessionPath))
28971
28762
  return sessionPath;
28972
28763
  }
28973
28764
  return null;
@@ -28981,6 +28772,45 @@ function isCallerOrchestrator(sessionID) {
28981
28772
  const nearest = findNearestAssistantMessage(messageDir);
28982
28773
  return agentNameMatches(nearest?.agent, "\u4EFB\u52A1\u7F16\u6392");
28983
28774
  }
28775
+ function isAgentCheckboxUpdater(agentName) {
28776
+ if (!agentName)
28777
+ return false;
28778
+ return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
28779
+ }
28780
+ function isActiveCheckboxUpdater(sessionID) {
28781
+ if (!sessionID)
28782
+ return false;
28783
+ const messageDir = getMessageDir5(sessionID);
28784
+ if (!messageDir)
28785
+ return false;
28786
+ const nearest = findNearestAssistantMessage(messageDir);
28787
+ return isAgentCheckboxUpdater(nearest?.agent);
28788
+ }
28789
+ function isAgentContinuationTrigger(agentName) {
28790
+ if (!agentName)
28791
+ return false;
28792
+ return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
28793
+ }
28794
+ function isActiveContinuationTrigger(sessionID, directory) {
28795
+ if (!sessionID)
28796
+ return false;
28797
+ const messageDir = getMessageDir5(sessionID);
28798
+ if (messageDir) {
28799
+ const nearest = findNearestAssistantMessage(messageDir);
28800
+ if (isAgentContinuationTrigger(nearest?.agent)) {
28801
+ return true;
28802
+ }
28803
+ }
28804
+ if (directory) {
28805
+ try {
28806
+ const boulderState = readBoulderState(directory);
28807
+ if (boulderState?.session_ids?.includes(sessionID)) {
28808
+ return true;
28809
+ }
28810
+ } catch {}
28811
+ }
28812
+ return false;
28813
+ }
28984
28814
  var CONTINUATION_COOLDOWN_MS = 5000;
28985
28815
  function isAbortError(error) {
28986
28816
  if (!error)
@@ -29145,8 +28975,8 @@ function createAtlasHook(ctx, options) {
29145
28975
  log(`[${HOOK_NAME6}] No active boulder`, { sessionID });
29146
28976
  return;
29147
28977
  }
29148
- if (!isCallerOrchestrator(sessionID)) {
29149
- log(`[${HOOK_NAME6}] Skipped: last agent is not Atlas`, { sessionID });
28978
+ if (!isActiveContinuationTrigger(sessionID, ctx.directory)) {
28979
+ log(`[${HOOK_NAME6}] Skipped: not eligible for continuation trigger`, { sessionID });
29150
28980
  return;
29151
28981
  }
29152
28982
  const progress = getPlanProgress(boulderState.active_plan);
@@ -29272,7 +29102,7 @@ function createAtlasHook(ctx, options) {
29272
29102
  }
29273
29103
  },
29274
29104
  "tool.execute.after": async (input, output) => {
29275
- if (!isCallerOrchestrator(input.sessionID)) {
29105
+ if (!isActiveCheckboxUpdater(input.sessionID)) {
29276
29106
  return;
29277
29107
  }
29278
29108
  if (WRITE_EDIT_TOOLS.includes(input.tool)) {
@@ -29334,7 +29164,7 @@ function createAtlasHook(ctx, options) {
29334
29164
  const taskDescription = extractTaskFromPrompt(savedPrompt || "");
29335
29165
  if (taskDescription) {
29336
29166
  try {
29337
- const planContent = readFileSync30(boulderState.active_plan, "utf-8");
29167
+ const planContent = readFileSync29(boulderState.active_plan, "utf-8");
29338
29168
  const checkboxes = parseCheckboxes(planContent);
29339
29169
  const checkboxIndex = findMatchingCheckbox(taskDescription, checkboxes);
29340
29170
  if (checkboxIndex >= 0) {
@@ -29346,7 +29176,7 @@ function createAtlasHook(ctx, options) {
29346
29176
  `);
29347
29177
  const planPath = boulderState.active_plan;
29348
29178
  if (!writePlanFileAtomic(planPath, updatedContent)) {
29349
- retryOnWindowsError(() => writeFileSync20(planPath, updatedContent, "utf-8"));
29179
+ retryOnWindowsError(() => writeFileSync19(planPath, updatedContent, "utf-8"));
29350
29180
  log(`[${HOOK_NAME6}] Atomic plan write failed, fell back to direct write`, {
29351
29181
  plan: boulderState.plan_name
29352
29182
  });
@@ -29367,6 +29197,7 @@ function createAtlasHook(ctx, options) {
29367
29197
  });
29368
29198
  }
29369
29199
  }
29200
+ const updatedProgress = getPlanProgress(boulderState.active_plan);
29370
29201
  output.output = `
29371
29202
  ## \u5B50\u4EE3\u7406\u5DE5\u4F5C\u5DF2\u5B8C\u6210
29372
29203
 
@@ -29379,11 +29210,11 @@ ${fileChanges}
29379
29210
  ${originalResponse}
29380
29211
 
29381
29212
  <system-reminder>
29382
- ${buildOrchestratorReminder(boulderState.plan_name, progress, subagentSessionId)}
29213
+ ${buildOrchestratorReminder(boulderState.plan_name, updatedProgress, subagentSessionId)}
29383
29214
  </system-reminder>`;
29384
29215
  log(`[${HOOK_NAME6}] Output transformed for orchestrator mode (boulder)`, {
29385
29216
  plan: boulderState.plan_name,
29386
- progress: `${progress.completed}/${progress.total}`,
29217
+ progress: `${updatedProgress.completed}/${updatedProgress.total}`,
29387
29218
  fileCount: gitStats.length
29388
29219
  });
29389
29220
  } else {
@@ -30196,6 +30027,7 @@ init_usage_tracker();
30196
30027
  init_model_health_registry();
30197
30028
  init_runtime_fallback();
30198
30029
  init_agent_display_names();
30030
+ init_claude_code_session_state();
30199
30031
  async function withTimeout(promise, timeoutMs, label) {
30200
30032
  let timer;
30201
30033
  return Promise.race([
@@ -30979,6 +30811,7 @@ function evaluatePermission(input, agentName) {
30979
30811
 
30980
30812
  // src/hooks/permission-ask-bridge/index.ts
30981
30813
  init_logger();
30814
+ init_claude_code_session_state();
30982
30815
  function createPermissionAskBridgeHook(ctx) {
30983
30816
  return {
30984
30817
  "permission.ask": async (input, output) => {
@@ -31012,8 +30845,8 @@ function createShellEnvInjectorHook(_ctx) {
31012
30845
  // src/hooks/plan-completion/index.ts
31013
30846
  init_logger();
31014
30847
  init_frontmatter();
31015
- import { existsSync as existsSync39, readFileSync as readFileSync31, writeFileSync as writeFileSync21, mkdirSync as mkdirSync17, renameSync as renameSync4, unlinkSync as unlinkSync14 } from "fs";
31016
- import { join as join52 } from "path";
30848
+ import { existsSync as existsSync38, readFileSync as readFileSync30, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16, renameSync as renameSync4, unlinkSync as unlinkSync12 } from "fs";
30849
+ import { join as join49 } from "path";
31017
30850
  async function safeExecute(fn, name, onAction) {
31018
30851
  try {
31019
30852
  await fn();
@@ -31058,11 +30891,11 @@ function countListItems(content) {
31058
30891
  }
31059
30892
  async function updatePlanSummary(data) {
31060
30893
  log(`[plan-completion] updatePlanSummary: ${data.planName}`);
31061
- if (!existsSync39(data.planPath)) {
30894
+ if (!existsSync38(data.planPath)) {
31062
30895
  log(`[plan-completion] Plan file not found: ${data.planPath}`);
31063
30896
  return;
31064
30897
  }
31065
- const content = readFileSync31(data.planPath, "utf-8");
30898
+ const content = readFileSync30(data.planPath, "utf-8");
31066
30899
  const startedAt = data.boulderState?.started_at || "";
31067
30900
  const completedAt = data.boulderState?.completed_at || "";
31068
30901
  const duration = formatDuration(startedAt, completedAt);
@@ -31083,17 +30916,17 @@ async function updatePlanSummary(data) {
31083
30916
  | \u5B8C\u6210\u4EFB\u52A1\u6570 | ${completedTasks} |
31084
30917
  | \u5931\u8D25\u4EFB\u52A1\u6570 | ${failedTasks} |
31085
30918
  `;
31086
- writeFileSync21(data.planPath, content + summary, "utf-8");
30919
+ writeFileSync20(data.planPath, content + summary, "utf-8");
31087
30920
  log(`[plan-completion] Plan summary appended to ${data.planPath}`);
31088
30921
  }
31089
30922
  async function archivePlan(data) {
31090
30923
  log(`[plan-completion] archivePlan: ${data.planName}`);
31091
- const archivedDir = join52(data.directory, ".sisyphus", "archived");
31092
- if (!existsSync39(archivedDir)) {
31093
- mkdirSync17(archivedDir, { recursive: true });
30924
+ const archivedDir = join49(data.directory, ".sisyphus", "archived");
30925
+ if (!existsSync38(archivedDir)) {
30926
+ mkdirSync16(archivedDir, { recursive: true });
31094
30927
  }
31095
- if (existsSync39(data.planPath)) {
31096
- const archivedPath = join52(archivedDir, `${data.planName}.md`);
30928
+ if (existsSync38(data.planPath)) {
30929
+ const archivedPath = join49(archivedDir, `${data.planName}.md`);
31097
30930
  renameSync4(data.planPath, archivedPath);
31098
30931
  log(`[plan-completion] Plan archived to ${archivedPath}`);
31099
30932
  const boulderState = readBoulderState(data.directory);
@@ -31103,16 +30936,16 @@ async function archivePlan(data) {
31103
30936
  log(`[plan-completion] Updated boulder.json active_plan to ${archivedPath}`);
31104
30937
  }
31105
30938
  }
31106
- const draftPath = join52(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
31107
- if (existsSync39(draftPath)) {
31108
- unlinkSync14(draftPath);
30939
+ const draftPath = join49(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
30940
+ if (existsSync38(draftPath)) {
30941
+ unlinkSync12(draftPath);
31109
30942
  log(`[plan-completion] Deleted draft file: ${draftPath}`);
31110
30943
  }
31111
30944
  }
31112
30945
  async function extractLearnings(data) {
31113
30946
  log(`[plan-completion] extractLearnings: ${data.planName}`);
31114
- const notepadDir = join52(data.directory, ".sisyphus", "notepads", data.planName);
31115
- if (!existsSync39(notepadDir)) {
30947
+ const notepadDir = join49(data.directory, ".sisyphus", "notepads", data.planName);
30948
+ if (!existsSync38(notepadDir)) {
31116
30949
  log(`[plan-completion] Notepad directory not found: ${notepadDir}`);
31117
30950
  return;
31118
30951
  }
@@ -31122,9 +30955,9 @@ async function extractLearnings(data) {
31122
30955
  let totalIssues = 0;
31123
30956
  let totalDecisions = 0;
31124
30957
  for (const file of files) {
31125
- const filePath = join52(notepadDir, file);
31126
- if (existsSync39(filePath)) {
31127
- const content = readFileSync31(filePath, "utf-8");
30958
+ const filePath = join49(notepadDir, file);
30959
+ if (existsSync38(filePath)) {
30960
+ const content = readFileSync30(filePath, "utf-8");
31128
30961
  contents[file] = content;
31129
30962
  const count = countListItems(content);
31130
30963
  if (file === "learnings.md")
@@ -31135,9 +30968,9 @@ async function extractLearnings(data) {
31135
30968
  totalDecisions = count;
31136
30969
  }
31137
30970
  }
31138
- const learningsDir = join52(data.directory, ".sisyphus", "learnings");
31139
- if (!existsSync39(learningsDir)) {
31140
- mkdirSync17(learningsDir, { recursive: true });
30971
+ const learningsDir = join49(data.directory, ".sisyphus", "learnings");
30972
+ if (!existsSync38(learningsDir)) {
30973
+ mkdirSync16(learningsDir, { recursive: true });
31141
30974
  }
31142
30975
  const output = `# \u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3: ${data.planName}
31143
30976
 
@@ -31164,8 +30997,8 @@ ${contents["decisions.md"] || "\u65E0"}
31164
30997
 
31165
30998
  ${contents["match-failures.md"] || "\u65E0"}
31166
30999
  `;
31167
- const outputPath = join52(learningsDir, `${data.planName}.md`);
31168
- writeFileSync21(outputPath, output, "utf-8");
31000
+ const outputPath = join49(learningsDir, `${data.planName}.md`);
31001
+ writeFileSync20(outputPath, output, "utf-8");
31169
31002
  log(`[plan-completion] Learnings saved to ${outputPath}`);
31170
31003
  if (data.client?.tui?.showToast) {
31171
31004
  data.client.tui.showToast({
@@ -31184,9 +31017,9 @@ ${contents["match-failures.md"] || "\u65E0"}
31184
31017
  }
31185
31018
  async function generateReport(data) {
31186
31019
  log(`[plan-completion] generateReport: ${data.planName}`);
31187
- const reportsDir = join52(data.directory, ".sisyphus", "reports");
31188
- if (!existsSync39(reportsDir)) {
31189
- mkdirSync17(reportsDir, { recursive: true });
31020
+ const reportsDir = join49(data.directory, ".sisyphus", "reports");
31021
+ if (!existsSync38(reportsDir)) {
31022
+ mkdirSync16(reportsDir, { recursive: true });
31190
31023
  }
31191
31024
  const startedAt = data.boulderState?.started_at || "";
31192
31025
  const completedAt = data.boulderState?.completed_at || "";
@@ -31197,8 +31030,8 @@ async function generateReport(data) {
31197
31030
  const version = data.boulderState?.version || 0;
31198
31031
  const sessionCount = data.boulderState?.session_ids?.length || 0;
31199
31032
  const completedIndices = data.boulderState?.completed_task_indices || [];
31200
- const notepadPath = join52(data.directory, ".sisyphus", "notepads", data.planName);
31201
- const hasNotepad = existsSync39(notepadPath);
31033
+ const notepadPath = join49(data.directory, ".sisyphus", "notepads", data.planName);
31034
+ const hasNotepad = existsSync38(notepadPath);
31202
31035
  const report = `# \u8BA1\u5212\u5B8C\u6210\u62A5\u544A
31203
31036
 
31204
31037
  ## \u6982\u89C8
@@ -31237,8 +31070,8 @@ ${hasNotepad ? `## \u8BB0\u4E8B\u672C
31237
31070
  \u8BB0\u4E8B\u672C\u8DEF\u5F84: ${notepadPath}
31238
31071
  ` : ""}
31239
31072
  `;
31240
- const reportPath = join52(reportsDir, `${data.planName}.md`);
31241
- writeFileSync21(reportPath, report, "utf-8");
31073
+ const reportPath = join49(reportsDir, `${data.planName}.md`);
31074
+ writeFileSync20(reportPath, report, "utf-8");
31242
31075
  log(`[plan-completion] Report generated at ${reportPath}`);
31243
31076
  }
31244
31077
  async function runInitDeep(data) {
@@ -31348,6 +31181,7 @@ class ContextCollector {
31348
31181
  var contextCollector = new ContextCollector;
31349
31182
  // src/features/context-injector/injector.ts
31350
31183
  init_shared();
31184
+ init_claude_code_session_state();
31351
31185
  function createContextInjectorMessagesTransformHook(collector) {
31352
31186
  return {
31353
31187
  "experimental.chat.messages.transform": async (_input, output) => {
@@ -31449,8 +31283,8 @@ function createFirstMessageVariantGate() {
31449
31283
  }
31450
31284
  // src/features/claude-code-mcp-loader/loader.ts
31451
31285
  init_shared();
31452
- import { existsSync as existsSync40, readFileSync as readFileSync32 } from "fs";
31453
- import { join as join53 } from "path";
31286
+ import { existsSync as existsSync39, readFileSync as readFileSync31 } from "fs";
31287
+ import { join as join50 } from "path";
31454
31288
 
31455
31289
  // src/features/claude-code-mcp-loader/env-expander.ts
31456
31290
  function expandEnvVars(value) {
@@ -31520,13 +31354,13 @@ function getMcpConfigPaths() {
31520
31354
  const claudeConfigDir = getClaudeConfigDir();
31521
31355
  const cwd2 = process.cwd();
31522
31356
  return [
31523
- { path: join53(claudeConfigDir, ".mcp.json"), scope: "user" },
31524
- { path: join53(cwd2, ".mcp.json"), scope: "project" },
31525
- { path: join53(cwd2, ".claude", ".mcp.json"), scope: "local" }
31357
+ { path: join50(claudeConfigDir, ".mcp.json"), scope: "user" },
31358
+ { path: join50(cwd2, ".mcp.json"), scope: "project" },
31359
+ { path: join50(cwd2, ".claude", ".mcp.json"), scope: "local" }
31526
31360
  ];
31527
31361
  }
31528
31362
  async function loadMcpConfigFile(filePath) {
31529
- if (!existsSync40(filePath)) {
31363
+ if (!existsSync39(filePath)) {
31530
31364
  return null;
31531
31365
  }
31532
31366
  try {
@@ -31541,10 +31375,10 @@ function getSystemMcpServerNames() {
31541
31375
  const names = new Set;
31542
31376
  const paths = getMcpConfigPaths();
31543
31377
  for (const { path: path7 } of paths) {
31544
- if (!existsSync40(path7))
31378
+ if (!existsSync39(path7))
31545
31379
  continue;
31546
31380
  try {
31547
- const content = readFileSync32(path7, "utf-8");
31381
+ const content = readFileSync31(path7, "utf-8");
31548
31382
  const config = JSON.parse(content);
31549
31383
  if (!config?.mcpServers)
31550
31384
  continue;
@@ -31594,14 +31428,21 @@ async function loadMcpConfigs() {
31594
31428
  }
31595
31429
  return { servers, loadedServers };
31596
31430
  }
31431
+ // src/index.ts
31432
+ init_claude_code_session_state();
31433
+
31597
31434
  // src/features/claude-code-session-state/recovery.ts
31598
- import { existsSync as existsSync41, readdirSync as readdirSync13 } from "fs";
31599
- import { join as join54 } from "path";
31435
+ import { existsSync as existsSync40, readdirSync as readdirSync13 } from "fs";
31436
+ import { join as join51 } from "path";
31437
+ init_state();
31600
31438
  init_logger();
31601
- function recoverSessionAgents() {
31439
+ function recoverSessionAgents(directory) {
31602
31440
  let recoveredCount = 0;
31441
+ if (directory) {
31442
+ loadSessionAgentMap(directory);
31443
+ }
31603
31444
  try {
31604
- if (!existsSync41(MESSAGE_STORAGE)) {
31445
+ if (!existsSync40(MESSAGE_STORAGE)) {
31605
31446
  log("[recovery] MESSAGE_STORAGE directory does not exist", { path: MESSAGE_STORAGE });
31606
31447
  return 0;
31607
31448
  }
@@ -31609,13 +31450,13 @@ function recoverSessionAgents() {
31609
31450
  for (const entry of entries) {
31610
31451
  if (!entry.isDirectory())
31611
31452
  continue;
31612
- const projectDir = join54(MESSAGE_STORAGE, entry.name);
31453
+ const projectDir = join51(MESSAGE_STORAGE, entry.name);
31613
31454
  try {
31614
31455
  const sessionDirs = readdirSync13(projectDir, { withFileTypes: true });
31615
31456
  for (const sessionEntry of sessionDirs) {
31616
31457
  if (!sessionEntry.isDirectory())
31617
31458
  continue;
31618
- const sessionDir = join54(projectDir, sessionEntry.name);
31459
+ const sessionDir = join51(projectDir, sessionEntry.name);
31619
31460
  const sessionID = sessionEntry.name;
31620
31461
  try {
31621
31462
  const msg = findNearestAssistantMessage(sessionDir);
@@ -32041,14 +31882,14 @@ var EXT_TO_LANG = {
32041
31882
  ".gql": "graphql"
32042
31883
  };
32043
31884
  // src/tools/lsp/config.ts
32044
- import { existsSync as existsSync42, readFileSync as readFileSync33 } from "fs";
32045
- import { join as join55 } from "path";
31885
+ import { existsSync as existsSync41, readFileSync as readFileSync32 } from "fs";
31886
+ import { join as join52 } from "path";
32046
31887
  init_shared();
32047
31888
  function loadJsonFile(path7) {
32048
- if (!existsSync42(path7))
31889
+ if (!existsSync41(path7))
32049
31890
  return null;
32050
31891
  try {
32051
- return JSON.parse(readFileSync33(path7, "utf-8"));
31892
+ return JSON.parse(readFileSync32(path7, "utf-8"));
32052
31893
  } catch {
32053
31894
  return null;
32054
31895
  }
@@ -32057,9 +31898,9 @@ function getConfigPaths3() {
32057
31898
  const cwd2 = process.cwd();
32058
31899
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
32059
31900
  return {
32060
- project: join55(cwd2, ".opencode", "oh-my-opencode.json"),
32061
- user: join55(configDir, "oh-my-opencode.json"),
32062
- opencode: join55(configDir, "opencode.json")
31901
+ project: join52(cwd2, ".opencode", "oh-my-opencode.json"),
31902
+ user: join52(configDir, "oh-my-opencode.json"),
31903
+ opencode: join52(configDir, "opencode.json")
32063
31904
  };
32064
31905
  }
32065
31906
  function loadAllConfigs() {
@@ -32172,7 +32013,7 @@ function isServerInstalled(command) {
32172
32013
  return false;
32173
32014
  const cmd = command[0];
32174
32015
  if (cmd.includes("/") || cmd.includes("\\")) {
32175
- if (existsSync42(cmd))
32016
+ if (existsSync41(cmd))
32176
32017
  return true;
32177
32018
  }
32178
32019
  const isWindows2 = process.platform === "win32";
@@ -32194,23 +32035,23 @@ function isServerInstalled(command) {
32194
32035
  const paths = pathEnv.split(pathSeparator);
32195
32036
  for (const p of paths) {
32196
32037
  for (const suffix of exts) {
32197
- if (existsSync42(join55(p, cmd + suffix))) {
32038
+ if (existsSync41(join52(p, cmd + suffix))) {
32198
32039
  return true;
32199
32040
  }
32200
32041
  }
32201
32042
  }
32202
32043
  const cwd2 = process.cwd();
32203
32044
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
32204
- const dataDir = join55(getDataDir(), "opencode");
32045
+ const dataDir = join52(getDataDir(), "opencode");
32205
32046
  const additionalBases = [
32206
- join55(cwd2, "node_modules", ".bin"),
32207
- join55(configDir, "bin"),
32208
- join55(configDir, "node_modules", ".bin"),
32209
- join55(dataDir, "bin")
32047
+ join52(cwd2, "node_modules", ".bin"),
32048
+ join52(configDir, "bin"),
32049
+ join52(configDir, "node_modules", ".bin"),
32050
+ join52(dataDir, "bin")
32210
32051
  ];
32211
32052
  for (const base of additionalBases) {
32212
32053
  for (const suffix of exts) {
32213
- if (existsSync42(join55(base, cmd + suffix))) {
32054
+ if (existsSync41(join52(base, cmd + suffix))) {
32214
32055
  return true;
32215
32056
  }
32216
32057
  }
@@ -32222,7 +32063,7 @@ function isServerInstalled(command) {
32222
32063
  }
32223
32064
  // src/tools/lsp/client.ts
32224
32065
  var {spawn: spawn6 } = globalThis.Bun;
32225
- import { readFileSync as readFileSync34 } from "fs";
32066
+ import { readFileSync as readFileSync33 } from "fs";
32226
32067
  import { extname, resolve as resolve8 } from "path";
32227
32068
  import { pathToFileURL } from "url";
32228
32069
  class LSPServerManager {
@@ -32673,7 +32514,7 @@ ${msg}`);
32673
32514
  const absPath = resolve8(filePath);
32674
32515
  if (this.openedFiles.has(absPath))
32675
32516
  return;
32676
- const text = readFileSync34(absPath, "utf-8");
32517
+ const text = readFileSync33(absPath, "utf-8");
32677
32518
  const ext = extname(absPath);
32678
32519
  const languageId = getLanguageId(ext);
32679
32520
  this.notify("textDocument/didOpen", {
@@ -32763,17 +32604,17 @@ ${msg}`);
32763
32604
  // src/tools/lsp/utils.ts
32764
32605
  import { extname as extname2, resolve as resolve9 } from "path";
32765
32606
  import { fileURLToPath as fileURLToPath2 } from "url";
32766
- import { existsSync as existsSync43, readFileSync as readFileSync35, writeFileSync as writeFileSync22 } from "fs";
32607
+ import { existsSync as existsSync42, readFileSync as readFileSync34, writeFileSync as writeFileSync21 } from "fs";
32767
32608
  function findWorkspaceRoot(filePath) {
32768
32609
  let dir = resolve9(filePath);
32769
- if (!existsSync43(dir) || !__require("fs").statSync(dir).isDirectory()) {
32610
+ if (!existsSync42(dir) || !__require("fs").statSync(dir).isDirectory()) {
32770
32611
  dir = __require("path").dirname(dir);
32771
32612
  }
32772
32613
  const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
32773
32614
  let prevDir = "";
32774
32615
  while (dir !== prevDir) {
32775
32616
  for (const marker of markers) {
32776
- if (existsSync43(__require("path").join(dir, marker))) {
32617
+ if (existsSync42(__require("path").join(dir, marker))) {
32777
32618
  return dir;
32778
32619
  }
32779
32620
  }
@@ -32928,7 +32769,7 @@ function formatPrepareRenameResult(result) {
32928
32769
  }
32929
32770
  function applyTextEditsToFile(filePath, edits) {
32930
32771
  try {
32931
- let content = readFileSync35(filePath, "utf-8");
32772
+ let content = readFileSync34(filePath, "utf-8");
32932
32773
  const lines = content.split(`
32933
32774
  `);
32934
32775
  const sortedEdits = [...edits].sort((a, b) => {
@@ -32953,7 +32794,7 @@ function applyTextEditsToFile(filePath, edits) {
32953
32794
  `));
32954
32795
  }
32955
32796
  }
32956
- writeFileSync22(filePath, lines.join(`
32797
+ writeFileSync21(filePath, lines.join(`
32957
32798
  `), "utf-8");
32958
32799
  return { success: true, editCount: edits.length };
32959
32800
  } catch (err) {
@@ -32984,7 +32825,7 @@ function applyWorkspaceEdit(edit) {
32984
32825
  if (change.kind === "create") {
32985
32826
  try {
32986
32827
  const filePath = uriToPath(change.uri);
32987
- writeFileSync22(filePath, "", "utf-8");
32828
+ writeFileSync21(filePath, "", "utf-8");
32988
32829
  result.filesModified.push(filePath);
32989
32830
  } catch (err) {
32990
32831
  result.success = false;
@@ -32994,8 +32835,8 @@ function applyWorkspaceEdit(edit) {
32994
32835
  try {
32995
32836
  const oldPath = uriToPath(change.oldUri);
32996
32837
  const newPath = uriToPath(change.newUri);
32997
- const content = readFileSync35(oldPath, "utf-8");
32998
- writeFileSync22(newPath, content, "utf-8");
32838
+ const content = readFileSync34(oldPath, "utf-8");
32839
+ writeFileSync21(newPath, content, "utf-8");
32999
32840
  __require("fs").unlinkSync(oldPath);
33000
32841
  result.filesModified.push(newPath);
33001
32842
  } catch (err) {
@@ -45574,13 +45415,13 @@ var lsp_rename = tool({
45574
45415
  });
45575
45416
  // src/tools/ast-grep/constants.ts
45576
45417
  import { createRequire as createRequire4 } from "module";
45577
- import { dirname as dirname11, join as join57 } from "path";
45578
- import { existsSync as existsSync45, statSync as statSync5 } from "fs";
45418
+ import { dirname as dirname11, join as join54 } from "path";
45419
+ import { existsSync as existsSync44, statSync as statSync5 } from "fs";
45579
45420
 
45580
45421
  // src/tools/ast-grep/downloader.ts
45581
45422
  init_shared();
45582
- import { existsSync as existsSync44, mkdirSync as mkdirSync18, chmodSync as chmodSync2, unlinkSync as unlinkSync15 } from "fs";
45583
- import { join as join56 } from "path";
45423
+ import { existsSync as existsSync43, mkdirSync as mkdirSync17, chmodSync as chmodSync2, unlinkSync as unlinkSync13 } from "fs";
45424
+ import { join as join53 } from "path";
45584
45425
  import { homedir as homedir13 } from "os";
45585
45426
  import { createRequire as createRequire3 } from "module";
45586
45427
  var REPO2 = "ast-grep/ast-grep";
@@ -45606,19 +45447,19 @@ var PLATFORM_MAP2 = {
45606
45447
  function getCacheDir3() {
45607
45448
  if (process.platform === "win32") {
45608
45449
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
45609
- const base2 = localAppData || join56(homedir13(), "AppData", "Local");
45610
- return join56(base2, "oh-my-opencode", "bin");
45450
+ const base2 = localAppData || join53(homedir13(), "AppData", "Local");
45451
+ return join53(base2, "oh-my-opencode", "bin");
45611
45452
  }
45612
45453
  const xdgCache = process.env.XDG_CACHE_HOME;
45613
- const base = xdgCache || join56(homedir13(), ".cache");
45614
- return join56(base, "oh-my-opencode", "bin");
45454
+ const base = xdgCache || join53(homedir13(), ".cache");
45455
+ return join53(base, "oh-my-opencode", "bin");
45615
45456
  }
45616
45457
  function getBinaryName3() {
45617
45458
  return process.platform === "win32" ? "sg.exe" : "sg";
45618
45459
  }
45619
45460
  function getCachedBinaryPath2() {
45620
- const binaryPath = join56(getCacheDir3(), getBinaryName3());
45621
- return existsSync44(binaryPath) ? binaryPath : null;
45461
+ const binaryPath = join53(getCacheDir3(), getBinaryName3());
45462
+ return existsSync43(binaryPath) ? binaryPath : null;
45622
45463
  }
45623
45464
  async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45624
45465
  const platformKey = `${process.platform}-${process.arch}`;
@@ -45629,8 +45470,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45629
45470
  }
45630
45471
  const cacheDir = getCacheDir3();
45631
45472
  const binaryName = getBinaryName3();
45632
- const binaryPath = join56(cacheDir, binaryName);
45633
- if (existsSync44(binaryPath)) {
45473
+ const binaryPath = join53(cacheDir, binaryName);
45474
+ if (existsSync43(binaryPath)) {
45634
45475
  return binaryPath;
45635
45476
  }
45636
45477
  const { arch, os: os6 } = platformInfo;
@@ -45638,21 +45479,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
45638
45479
  const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
45639
45480
  console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
45640
45481
  try {
45641
- if (!existsSync44(cacheDir)) {
45642
- mkdirSync18(cacheDir, { recursive: true });
45482
+ if (!existsSync43(cacheDir)) {
45483
+ mkdirSync17(cacheDir, { recursive: true });
45643
45484
  }
45644
45485
  const response = await fetch(downloadUrl, { redirect: "follow" });
45645
45486
  if (!response.ok) {
45646
45487
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
45647
45488
  }
45648
- const archivePath = join56(cacheDir, assetName);
45489
+ const archivePath = join53(cacheDir, assetName);
45649
45490
  const arrayBuffer = await response.arrayBuffer();
45650
45491
  await Bun.write(archivePath, arrayBuffer);
45651
45492
  await extractZip(archivePath, cacheDir);
45652
- if (existsSync44(archivePath)) {
45653
- unlinkSync15(archivePath);
45493
+ if (existsSync43(archivePath)) {
45494
+ unlinkSync13(archivePath);
45654
45495
  }
45655
- if (process.platform !== "win32" && existsSync44(binaryPath)) {
45496
+ if (process.platform !== "win32" && existsSync43(binaryPath)) {
45656
45497
  chmodSync2(binaryPath, 493);
45657
45498
  }
45658
45499
  console.log(`[oh-my-opencode] ast-grep binary ready.`);
@@ -45703,8 +45544,8 @@ function findSgCliPathSync() {
45703
45544
  const require2 = createRequire4(import.meta.url);
45704
45545
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
45705
45546
  const cliDir = dirname11(cliPkgPath);
45706
- const sgPath = join57(cliDir, binaryName);
45707
- if (existsSync45(sgPath) && isValidBinary(sgPath)) {
45547
+ const sgPath = join54(cliDir, binaryName);
45548
+ if (existsSync44(sgPath) && isValidBinary(sgPath)) {
45708
45549
  return sgPath;
45709
45550
  }
45710
45551
  } catch {}
@@ -45715,8 +45556,8 @@ function findSgCliPathSync() {
45715
45556
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
45716
45557
  const pkgDir = dirname11(pkgPath);
45717
45558
  const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
45718
- const binaryPath = join57(pkgDir, astGrepName);
45719
- if (existsSync45(binaryPath) && isValidBinary(binaryPath)) {
45559
+ const binaryPath = join54(pkgDir, astGrepName);
45560
+ if (existsSync44(binaryPath) && isValidBinary(binaryPath)) {
45720
45561
  return binaryPath;
45721
45562
  }
45722
45563
  } catch {}
@@ -45724,7 +45565,7 @@ function findSgCliPathSync() {
45724
45565
  if (process.platform === "darwin") {
45725
45566
  const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
45726
45567
  for (const path7 of homebrewPaths) {
45727
- if (existsSync45(path7) && isValidBinary(path7)) {
45568
+ if (existsSync44(path7) && isValidBinary(path7)) {
45728
45569
  return path7;
45729
45570
  }
45730
45571
  }
@@ -45779,11 +45620,11 @@ var DEFAULT_MAX_MATCHES = 500;
45779
45620
 
45780
45621
  // src/tools/ast-grep/cli.ts
45781
45622
  var {spawn: spawn7 } = globalThis.Bun;
45782
- import { existsSync as existsSync46 } from "fs";
45623
+ import { existsSync as existsSync45 } from "fs";
45783
45624
  var resolvedCliPath3 = null;
45784
45625
  var initPromise2 = null;
45785
45626
  async function getAstGrepPath() {
45786
- if (resolvedCliPath3 !== null && existsSync46(resolvedCliPath3)) {
45627
+ if (resolvedCliPath3 !== null && existsSync45(resolvedCliPath3)) {
45787
45628
  return resolvedCliPath3;
45788
45629
  }
45789
45630
  if (initPromise2) {
@@ -45791,7 +45632,7 @@ async function getAstGrepPath() {
45791
45632
  }
45792
45633
  initPromise2 = (async () => {
45793
45634
  const syncPath = findSgCliPathSync();
45794
- if (syncPath && existsSync46(syncPath)) {
45635
+ if (syncPath && existsSync45(syncPath)) {
45795
45636
  resolvedCliPath3 = syncPath;
45796
45637
  setSgCliPath(syncPath);
45797
45638
  return syncPath;
@@ -45825,7 +45666,7 @@ async function runSg(options) {
45825
45666
  const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
45826
45667
  args.push(...paths);
45827
45668
  let cliPath = getSgCliPath();
45828
- if (!existsSync46(cliPath) && cliPath !== "sg") {
45669
+ if (!existsSync45(cliPath) && cliPath !== "sg") {
45829
45670
  const downloadedPath = await getAstGrepPath();
45830
45671
  if (downloadedPath) {
45831
45672
  cliPath = downloadedPath;
@@ -46089,21 +45930,21 @@ var ast_grep_replace = tool({
46089
45930
  var {spawn: spawn9 } = globalThis.Bun;
46090
45931
 
46091
45932
  // src/tools/grep/constants.ts
46092
- import { existsSync as existsSync48 } from "fs";
46093
- import { join as join59, dirname as dirname12 } from "path";
45933
+ import { existsSync as existsSync47 } from "fs";
45934
+ import { join as join56, dirname as dirname12 } from "path";
46094
45935
  import { spawnSync as spawnSync2 } from "child_process";
46095
45936
 
46096
45937
  // src/tools/grep/downloader.ts
46097
45938
  init_shared();
46098
- import { existsSync as existsSync47, mkdirSync as mkdirSync19, chmodSync as chmodSync3, unlinkSync as unlinkSync16, readdirSync as readdirSync14 } from "fs";
46099
- import { join as join58 } from "path";
45939
+ import { existsSync as existsSync46, mkdirSync as mkdirSync18, chmodSync as chmodSync3, unlinkSync as unlinkSync14, readdirSync as readdirSync14 } from "fs";
45940
+ import { join as join55 } from "path";
46100
45941
  var {spawn: spawn8 } = globalThis.Bun;
46101
45942
  function findFileRecursive(dir, filename) {
46102
45943
  try {
46103
45944
  const entries = readdirSync14(dir, { withFileTypes: true, recursive: true });
46104
45945
  for (const entry of entries) {
46105
45946
  if (entry.isFile() && entry.name === filename) {
46106
- return join58(entry.parentPath ?? dir, entry.name);
45947
+ return join55(entry.parentPath ?? dir, entry.name);
46107
45948
  }
46108
45949
  }
46109
45950
  } catch {
@@ -46124,11 +45965,11 @@ function getPlatformKey() {
46124
45965
  }
46125
45966
  function getInstallDir() {
46126
45967
  const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
46127
- return join58(homeDir, ".cache", "oh-my-opencode", "bin");
45968
+ return join55(homeDir, ".cache", "oh-my-opencode", "bin");
46128
45969
  }
46129
45970
  function getRgPath() {
46130
45971
  const isWindows2 = process.platform === "win32";
46131
- return join58(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
45972
+ return join55(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
46132
45973
  }
46133
45974
  async function downloadFile(url2, destPath) {
46134
45975
  const response = await fetch(url2);
@@ -46162,7 +46003,7 @@ async function extractZip2(archivePath, destDir) {
46162
46003
  const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
46163
46004
  const foundPath = findFileRecursive(destDir, binaryName);
46164
46005
  if (foundPath) {
46165
- const destPath = join58(destDir, binaryName);
46006
+ const destPath = join55(destDir, binaryName);
46166
46007
  if (foundPath !== destPath) {
46167
46008
  const { renameSync: renameSync5 } = await import("fs");
46168
46009
  renameSync5(foundPath, destPath);
@@ -46177,13 +46018,13 @@ async function downloadAndInstallRipgrep() {
46177
46018
  }
46178
46019
  const installDir = getInstallDir();
46179
46020
  const rgPath = getRgPath();
46180
- if (existsSync47(rgPath)) {
46021
+ if (existsSync46(rgPath)) {
46181
46022
  return rgPath;
46182
46023
  }
46183
- mkdirSync19(installDir, { recursive: true });
46024
+ mkdirSync18(installDir, { recursive: true });
46184
46025
  const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
46185
46026
  const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
46186
- const archivePath = join58(installDir, filename);
46027
+ const archivePath = join55(installDir, filename);
46187
46028
  try {
46188
46029
  await downloadFile(url2, archivePath);
46189
46030
  if (config3.extension === "tar.gz") {
@@ -46194,21 +46035,21 @@ async function downloadAndInstallRipgrep() {
46194
46035
  if (process.platform !== "win32") {
46195
46036
  chmodSync3(rgPath, 493);
46196
46037
  }
46197
- if (!existsSync47(rgPath)) {
46038
+ if (!existsSync46(rgPath)) {
46198
46039
  throw new Error("\u63D0\u53D6\u540E\u672A\u627E\u5230 ripgrep \u4E8C\u8FDB\u5236\u6587\u4EF6");
46199
46040
  }
46200
46041
  return rgPath;
46201
46042
  } finally {
46202
- if (existsSync47(archivePath)) {
46043
+ if (existsSync46(archivePath)) {
46203
46044
  try {
46204
- unlinkSync16(archivePath);
46045
+ unlinkSync14(archivePath);
46205
46046
  } catch {}
46206
46047
  }
46207
46048
  }
46208
46049
  }
46209
46050
  function getInstalledRipgrepPath() {
46210
46051
  const rgPath = getRgPath();
46211
- return existsSync47(rgPath) ? rgPath : null;
46052
+ return existsSync46(rgPath) ? rgPath : null;
46212
46053
  }
46213
46054
 
46214
46055
  // src/tools/grep/constants.ts
@@ -46232,7 +46073,7 @@ function findExecutable(name) {
46232
46073
  continue;
46233
46074
  }
46234
46075
  }
46235
- if (existsSync48(trimmed)) {
46076
+ if (existsSync47(trimmed)) {
46236
46077
  return trimmed;
46237
46078
  }
46238
46079
  }
@@ -46247,14 +46088,14 @@ function getOpenCodeBundledRg() {
46247
46088
  const isWindows2 = process.platform === "win32";
46248
46089
  const rgName = isWindows2 ? "rg.exe" : "rg";
46249
46090
  const candidates = [
46250
- join59(getDataDir(), "opencode", "bin", rgName),
46251
- join59(execDir, rgName),
46252
- join59(execDir, "bin", rgName),
46253
- join59(execDir, "..", "bin", rgName),
46254
- join59(execDir, "..", "libexec", rgName)
46091
+ join56(getDataDir(), "opencode", "bin", rgName),
46092
+ join56(execDir, rgName),
46093
+ join56(execDir, "bin", rgName),
46094
+ join56(execDir, "..", "bin", rgName),
46095
+ join56(execDir, "..", "libexec", rgName)
46255
46096
  ];
46256
46097
  for (const candidate of candidates) {
46257
- if (existsSync48(candidate)) {
46098
+ if (existsSync47(candidate)) {
46258
46099
  return candidate;
46259
46100
  }
46260
46101
  }
@@ -46716,8 +46557,8 @@ var glob = tool({
46716
46557
  init_shared();
46717
46558
  init_file_utils();
46718
46559
  init_shared();
46719
- import { existsSync as existsSync49, readdirSync as readdirSync15, readFileSync as readFileSync36 } from "fs";
46720
- import { join as join60, basename as basename4, dirname as dirname13 } from "path";
46560
+ import { existsSync as existsSync48, readdirSync as readdirSync15, readFileSync as readFileSync35 } from "fs";
46561
+ import { join as join57, basename as basename4, dirname as dirname13 } from "path";
46721
46562
  // src/features/builtin-commands/templates/init-deep.ts
46722
46563
  var INIT_DEEP_TEMPLATE = `# /init-deep
46723
46564
 
@@ -47862,7 +47703,7 @@ function loadBuiltinCommands(disabledCommands) {
47862
47703
  }
47863
47704
  // src/tools/slashcommand/tools.ts
47864
47705
  function discoverCommandsFromDir2(commandsDir, scope) {
47865
- if (!existsSync49(commandsDir)) {
47706
+ if (!existsSync48(commandsDir)) {
47866
47707
  return [];
47867
47708
  }
47868
47709
  const entries = readdirSync15(commandsDir, { withFileTypes: true });
@@ -47870,10 +47711,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
47870
47711
  for (const entry of entries) {
47871
47712
  if (!isMarkdownFile(entry))
47872
47713
  continue;
47873
- const commandPath = join60(commandsDir, entry.name);
47714
+ const commandPath = join57(commandsDir, entry.name);
47874
47715
  const commandName = basename4(entry.name, ".md");
47875
47716
  try {
47876
- const content = readFileSync36(commandPath, "utf-8");
47717
+ const content = readFileSync35(commandPath, "utf-8");
47877
47718
  const { data, body } = parseFrontmatter(content);
47878
47719
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
47879
47720
  const metadata = {
@@ -47899,10 +47740,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
47899
47740
  }
47900
47741
  function discoverCommandsSync(disabledCommands) {
47901
47742
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
47902
- const userCommandsDir = join60(getClaudeConfigDir(), "commands");
47903
- const projectCommandsDir = join60(process.cwd(), ".claude", "commands");
47904
- const opencodeGlobalDir = join60(configDir, "command");
47905
- const opencodeProjectDir = join60(process.cwd(), ".opencode", "command");
47743
+ const userCommandsDir = join57(getClaudeConfigDir(), "commands");
47744
+ const projectCommandsDir = join57(process.cwd(), ".claude", "commands");
47745
+ const opencodeGlobalDir = join57(configDir, "command");
47746
+ const opencodeProjectDir = join57(process.cwd(), ".opencode", "command");
47906
47747
  const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
47907
47748
  const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
47908
47749
  const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
@@ -48102,13 +47943,13 @@ var slashcommand = createSlashcommandTool();
48102
47943
  // src/tools/session-manager/constants.ts
48103
47944
  init_data_path();
48104
47945
  init_shared();
48105
- import { join as join61 } from "path";
48106
- var OPENCODE_STORAGE11 = getOpenCodeStorageDir();
48107
- var MESSAGE_STORAGE4 = join61(OPENCODE_STORAGE11, "message");
48108
- var PART_STORAGE4 = join61(OPENCODE_STORAGE11, "part");
48109
- var SESSION_STORAGE = join61(OPENCODE_STORAGE11, "session");
48110
- var TODO_DIR2 = join61(getClaudeConfigDir(), "todos");
48111
- var TRANSCRIPT_DIR2 = join61(getClaudeConfigDir(), "transcripts");
47946
+ import { join as join58 } from "path";
47947
+ var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
47948
+ var MESSAGE_STORAGE4 = join58(OPENCODE_STORAGE9, "message");
47949
+ var PART_STORAGE4 = join58(OPENCODE_STORAGE9, "part");
47950
+ var SESSION_STORAGE = join58(OPENCODE_STORAGE9, "session");
47951
+ var TODO_DIR2 = join58(getClaudeConfigDir(), "todos");
47952
+ var TRANSCRIPT_DIR2 = join58(getClaudeConfigDir(), "transcripts");
48112
47953
  var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
48113
47954
 
48114
47955
  \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
@@ -48181,11 +48022,11 @@ Has Todos: Yes (12 items, 8 completed)
48181
48022
  Has Transcript: Yes (234 entries)`;
48182
48023
 
48183
48024
  // src/tools/session-manager/storage.ts
48184
- import { existsSync as existsSync50, readdirSync as readdirSync16 } from "fs";
48025
+ import { existsSync as existsSync49, readdirSync as readdirSync16 } from "fs";
48185
48026
  import { readdir, readFile } from "fs/promises";
48186
- import { join as join62 } from "path";
48027
+ import { join as join59 } from "path";
48187
48028
  async function getMainSessions(options) {
48188
- if (!existsSync50(SESSION_STORAGE))
48029
+ if (!existsSync49(SESSION_STORAGE))
48189
48030
  return [];
48190
48031
  const sessions = [];
48191
48032
  try {
@@ -48193,13 +48034,13 @@ async function getMainSessions(options) {
48193
48034
  for (const projectDir of projectDirs) {
48194
48035
  if (!projectDir.isDirectory())
48195
48036
  continue;
48196
- const projectPath = join62(SESSION_STORAGE, projectDir.name);
48037
+ const projectPath = join59(SESSION_STORAGE, projectDir.name);
48197
48038
  const sessionFiles = await readdir(projectPath);
48198
48039
  for (const file2 of sessionFiles) {
48199
48040
  if (!file2.endsWith(".json"))
48200
48041
  continue;
48201
48042
  try {
48202
- const content = await readFile(join62(projectPath, file2), "utf-8");
48043
+ const content = await readFile(join59(projectPath, file2), "utf-8");
48203
48044
  const meta = JSON.parse(content);
48204
48045
  if (meta.parentID)
48205
48046
  continue;
@@ -48217,7 +48058,7 @@ async function getMainSessions(options) {
48217
48058
  return sessions.sort((a, b) => b.time.updated - a.time.updated);
48218
48059
  }
48219
48060
  async function getAllSessions() {
48220
- if (!existsSync50(MESSAGE_STORAGE4))
48061
+ if (!existsSync49(MESSAGE_STORAGE4))
48221
48062
  return [];
48222
48063
  const sessions = [];
48223
48064
  async function scanDirectory(dir) {
@@ -48225,7 +48066,7 @@ async function getAllSessions() {
48225
48066
  const entries = await readdir(dir, { withFileTypes: true });
48226
48067
  for (const entry of entries) {
48227
48068
  if (entry.isDirectory()) {
48228
- const sessionPath = join62(dir, entry.name);
48069
+ const sessionPath = join59(dir, entry.name);
48229
48070
  const files = await readdir(sessionPath);
48230
48071
  if (files.some((f) => f.endsWith(".json"))) {
48231
48072
  sessions.push(entry.name);
@@ -48242,16 +48083,16 @@ async function getAllSessions() {
48242
48083
  return [...new Set(sessions)];
48243
48084
  }
48244
48085
  function getMessageDir6(sessionID) {
48245
- if (!existsSync50(MESSAGE_STORAGE4))
48086
+ if (!existsSync49(MESSAGE_STORAGE4))
48246
48087
  return "";
48247
- const directPath = join62(MESSAGE_STORAGE4, sessionID);
48248
- if (existsSync50(directPath)) {
48088
+ const directPath = join59(MESSAGE_STORAGE4, sessionID);
48089
+ if (existsSync49(directPath)) {
48249
48090
  return directPath;
48250
48091
  }
48251
48092
  try {
48252
48093
  for (const dir of readdirSync16(MESSAGE_STORAGE4)) {
48253
- const sessionPath = join62(MESSAGE_STORAGE4, dir, sessionID);
48254
- if (existsSync50(sessionPath)) {
48094
+ const sessionPath = join59(MESSAGE_STORAGE4, dir, sessionID);
48095
+ if (existsSync49(sessionPath)) {
48255
48096
  return sessionPath;
48256
48097
  }
48257
48098
  }
@@ -48265,7 +48106,7 @@ function sessionExists(sessionID) {
48265
48106
  }
48266
48107
  async function readSessionMessages(sessionID) {
48267
48108
  const messageDir = getMessageDir6(sessionID);
48268
- if (!messageDir || !existsSync50(messageDir))
48109
+ if (!messageDir || !existsSync49(messageDir))
48269
48110
  return [];
48270
48111
  const messages = [];
48271
48112
  try {
@@ -48274,7 +48115,7 @@ async function readSessionMessages(sessionID) {
48274
48115
  if (!file2.endsWith(".json"))
48275
48116
  continue;
48276
48117
  try {
48277
- const content = await readFile(join62(messageDir, file2), "utf-8");
48118
+ const content = await readFile(join59(messageDir, file2), "utf-8");
48278
48119
  const meta = JSON.parse(content);
48279
48120
  const parts = await readParts2(meta.id);
48280
48121
  messages.push({
@@ -48300,8 +48141,8 @@ async function readSessionMessages(sessionID) {
48300
48141
  });
48301
48142
  }
48302
48143
  async function readParts2(messageID) {
48303
- const partDir = join62(PART_STORAGE4, messageID);
48304
- if (!existsSync50(partDir))
48144
+ const partDir = join59(PART_STORAGE4, messageID);
48145
+ if (!existsSync49(partDir))
48305
48146
  return [];
48306
48147
  const parts = [];
48307
48148
  try {
@@ -48310,7 +48151,7 @@ async function readParts2(messageID) {
48310
48151
  if (!file2.endsWith(".json"))
48311
48152
  continue;
48312
48153
  try {
48313
- const content = await readFile(join62(partDir, file2), "utf-8");
48154
+ const content = await readFile(join59(partDir, file2), "utf-8");
48314
48155
  parts.push(JSON.parse(content));
48315
48156
  } catch {
48316
48157
  continue;
@@ -48322,14 +48163,14 @@ async function readParts2(messageID) {
48322
48163
  return parts.sort((a, b) => a.id.localeCompare(b.id));
48323
48164
  }
48324
48165
  async function readSessionTodos(sessionID) {
48325
- if (!existsSync50(TODO_DIR2))
48166
+ if (!existsSync49(TODO_DIR2))
48326
48167
  return [];
48327
48168
  try {
48328
48169
  const allFiles = await readdir(TODO_DIR2);
48329
48170
  const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
48330
48171
  for (const file2 of todoFiles) {
48331
48172
  try {
48332
- const content = await readFile(join62(TODO_DIR2, file2), "utf-8");
48173
+ const content = await readFile(join59(TODO_DIR2, file2), "utf-8");
48333
48174
  const data = JSON.parse(content);
48334
48175
  if (Array.isArray(data)) {
48335
48176
  return data.map((item) => ({
@@ -48349,10 +48190,10 @@ async function readSessionTodos(sessionID) {
48349
48190
  return [];
48350
48191
  }
48351
48192
  async function readSessionTranscript(sessionID) {
48352
- if (!existsSync50(TRANSCRIPT_DIR2))
48193
+ if (!existsSync49(TRANSCRIPT_DIR2))
48353
48194
  return 0;
48354
- const transcriptFile = join62(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
48355
- if (!existsSync50(transcriptFile))
48195
+ const transcriptFile = join59(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
48196
+ if (!existsSync49(transcriptFile))
48356
48197
  return 0;
48357
48198
  try {
48358
48199
  const content = await readFile(transcriptFile, "utf-8");
@@ -49175,6 +49016,7 @@ var BACKGROUND_OUTPUT_DESCRIPTION = `\u83B7\u53D6\u540E\u53F0\u4EFB\u52A1\u7684\
49175
49016
  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`;
49176
49017
 
49177
49018
  // src/tools/background-task/tools.ts
49019
+ init_claude_code_session_state();
49178
49020
  init_logger();
49179
49021
  init_session_cursor();
49180
49022
  init_agent_display_names();
@@ -49559,20 +49401,21 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
49559
49401
 
49560
49402
  \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`;
49561
49403
  // src/tools/call-omo-agent/tools.ts
49562
- import { existsSync as existsSync51, readdirSync as readdirSync17 } from "fs";
49563
- import { join as join63 } from "path";
49404
+ import { existsSync as existsSync50, readdirSync as readdirSync17 } from "fs";
49405
+ import { join as join60 } from "path";
49564
49406
  init_shared();
49565
49407
  init_agent_display_names();
49566
49408
  init_session_cursor();
49409
+ init_claude_code_session_state();
49567
49410
  function getMessageDir7(sessionID) {
49568
- if (!existsSync51(MESSAGE_STORAGE))
49411
+ if (!existsSync50(MESSAGE_STORAGE))
49569
49412
  return null;
49570
- const directPath = join63(MESSAGE_STORAGE, sessionID);
49571
- if (existsSync51(directPath))
49413
+ const directPath = join60(MESSAGE_STORAGE, sessionID);
49414
+ if (existsSync50(directPath))
49572
49415
  return directPath;
49573
49416
  for (const dir of readdirSync17(MESSAGE_STORAGE)) {
49574
- const sessionPath = join63(MESSAGE_STORAGE, dir, sessionID);
49575
- if (existsSync51(sessionPath))
49417
+ const sessionPath = join60(MESSAGE_STORAGE, dir, sessionID);
49418
+ if (existsSync50(sessionPath))
49576
49419
  return sessionPath;
49577
49420
  }
49578
49421
  return null;
@@ -49998,8 +49841,8 @@ function createLookAt(ctx) {
49998
49841
  }
49999
49842
  // src/tools/delegate-task/tools.ts
50000
49843
  init_constants();
50001
- import { existsSync as existsSync52, readdirSync as readdirSync18 } from "fs";
50002
- import { join as join64 } from "path";
49844
+ import { existsSync as existsSync51, readdirSync as readdirSync18 } from "fs";
49845
+ import { join as join61 } from "path";
50003
49846
 
50004
49847
  // src/features/task-toast-manager/manager.ts
50005
49848
  class TaskToastManager {
@@ -50175,10 +50018,12 @@ function initTaskToastManager(client2, concurrencyManager) {
50175
50018
  return instance;
50176
50019
  }
50177
50020
  // src/tools/delegate-task/tools.ts
50021
+ init_claude_code_session_state();
50178
50022
  init_shared();
50179
50023
  init_agent_display_names();
50180
50024
  init_runtime_fallback();
50181
50025
  init_model_health_registry();
50026
+ init_agent_identity_resolver();
50182
50027
  var SISYPHUS_JUNIOR_AGENT = "\u6267\u884C\u52A9\u7406";
50183
50028
  var MAX_LOOP_ATTEMPTS = 10;
50184
50029
  function sleep(ms) {
@@ -50205,14 +50050,14 @@ function parseFallbackModelEntries(entries) {
50205
50050
  });
50206
50051
  }
50207
50052
  function getMessageDir8(sessionID) {
50208
- if (!existsSync52(MESSAGE_STORAGE))
50053
+ if (!existsSync51(MESSAGE_STORAGE))
50209
50054
  return null;
50210
- const directPath = join64(MESSAGE_STORAGE, sessionID);
50211
- if (existsSync52(directPath))
50055
+ const directPath = join61(MESSAGE_STORAGE, sessionID);
50056
+ if (existsSync51(directPath))
50212
50057
  return directPath;
50213
50058
  for (const dir of readdirSync18(MESSAGE_STORAGE)) {
50214
- const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
50215
- if (existsSync52(sessionPath))
50059
+ const sessionPath = join61(MESSAGE_STORAGE, dir, sessionID);
50060
+ if (existsSync51(sessionPath))
50216
50061
  return sessionPath;
50217
50062
  }
50218
50063
  return null;
@@ -50294,18 +50139,30 @@ function buildSystemContent(input) {
50294
50139
 
50295
50140
  `);
50296
50141
  }
50297
- function extractResumeInfoFromMessages(messages) {
50298
- let agent;
50299
- let model;
50142
+ function extractResumeInfoFromMessages(sessionID, messages) {
50143
+ const resolvedAgent = resolveCurrentAgent(sessionID);
50144
+ if (resolvedAgent) {
50145
+ for (let i = messages.length - 1;i >= 0; i--) {
50146
+ const info = messages[i].info;
50147
+ if (info?.model || info?.modelID && info?.providerID) {
50148
+ return {
50149
+ agent: resolvedAgent,
50150
+ model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
50151
+ };
50152
+ }
50153
+ }
50154
+ return { agent: resolvedAgent, model: undefined };
50155
+ }
50300
50156
  for (let i = messages.length - 1;i >= 0; i--) {
50301
50157
  const info = messages[i].info;
50302
50158
  if (info?.role === "assistant" && (info?.agent || info?.model || info?.modelID && info?.providerID)) {
50303
- agent = info.agent;
50304
- model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
50305
- break;
50159
+ return {
50160
+ agent: info.agent,
50161
+ model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
50162
+ };
50306
50163
  }
50307
50164
  }
50308
- return { agent, model };
50165
+ return { agent: undefined, model: undefined };
50309
50166
  }
50310
50167
  async function pollTaskCompletion(client2, sessionID, maxWaitMs = 120000, pollIntervalMs = 2000) {
50311
50168
  const startTime = Date.now();
@@ -50483,7 +50340,7 @@ Agent \u7EE7\u7EED\u6267\u884C\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u
50483
50340
  try {
50484
50341
  const messagesResp = await client2.session.messages({ path: { id: args.session_id } });
50485
50342
  const messages2 = messagesResp.data ?? [];
50486
- const resumeInfo = extractResumeInfoFromMessages(messages2);
50343
+ const resumeInfo = extractResumeInfoFromMessages(args.session_id, messages2);
50487
50344
  resumeAgent = resumeInfo.agent;
50488
50345
  resumeModel = resumeInfo.model;
50489
50346
  } catch {
@@ -51308,8 +51165,10 @@ class PerformanceAggregator {
51308
51165
  }
51309
51166
 
51310
51167
  // src/features/background-agent/manager.ts
51311
- import { existsSync as existsSync53, readdirSync as readdirSync19 } from "fs";
51312
- import { join as join65 } from "path";
51168
+ init_claude_code_session_state();
51169
+ init_agent_identity_resolver();
51170
+ import { existsSync as existsSync52, readdirSync as readdirSync19 } from "fs";
51171
+ import { join as join62 } from "path";
51313
51172
  var TASK_TTL_MS = 30 * 60 * 1000;
51314
51173
  var MIN_STABILITY_TIME_MS = 10 * 1000;
51315
51174
  var DEFAULT_STALE_TIMEOUT_MS = 120000;
@@ -52102,15 +51961,15 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
52102
51961
  \u4F7F\u7528 \`background_output(task_id="${task.id}")\` \u5728\u51C6\u5907\u5C31\u7EEA\u65F6\u83B7\u53D6\u6B64\u7ED3\u679C\u3002
52103
51962
  </system-reminder>`;
52104
51963
  }
52105
- let agent = task.parentAgent;
51964
+ const currentParentAgent = resolveCurrentAgent(task.parentSessionID);
51965
+ const agent = currentParentAgent ?? task.parentAgent;
52106
51966
  let model;
52107
51967
  try {
52108
51968
  const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionID } });
52109
51969
  const messages = messagesResp.data ?? [];
52110
51970
  for (let i = messages.length - 1;i >= 0; i--) {
52111
51971
  const info = messages[i].info;
52112
- if (info?.agent || info?.model || info?.modelID && info?.providerID) {
52113
- agent = info.agent ?? task.parentAgent;
51972
+ if (info?.model || info?.modelID && info?.providerID) {
52114
51973
  model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
52115
51974
  break;
52116
51975
  }
@@ -52118,7 +51977,6 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
52118
51977
  } catch {
52119
51978
  const messageDir = getMessageDir9(task.parentSessionID);
52120
51979
  const currentMessage = messageDir ? findNearestAssistantMessage(messageDir) : null;
52121
- agent = currentMessage?.agent ?? task.parentAgent;
52122
51980
  model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
52123
51981
  }
52124
51982
  log("[background-agent] notifyParentSession context:", {
@@ -52483,14 +52341,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
52483
52341
  return listener;
52484
52342
  }
52485
52343
  function getMessageDir9(sessionID) {
52486
- if (!existsSync53(MESSAGE_STORAGE))
52344
+ if (!existsSync52(MESSAGE_STORAGE))
52487
52345
  return null;
52488
- const directPath = join65(MESSAGE_STORAGE, sessionID);
52489
- if (existsSync53(directPath))
52346
+ const directPath = join62(MESSAGE_STORAGE, sessionID);
52347
+ if (existsSync52(directPath))
52490
52348
  return directPath;
52491
52349
  for (const dir of readdirSync19(MESSAGE_STORAGE)) {
52492
- const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
52493
- if (existsSync53(sessionPath))
52350
+ const sessionPath = join62(MESSAGE_STORAGE, dir, sessionID);
52351
+ if (existsSync52(sessionPath))
52494
52352
  return sessionPath;
52495
52353
  }
52496
52354
  return null;
@@ -71221,8 +71079,7 @@ var HookNameSchema = exports_external2.enum([
71221
71079
  "prometheus-md-only",
71222
71080
  "perf-profiler",
71223
71081
  "start-work",
71224
- "language-reminder",
71225
- "thinking-language-validator",
71082
+ "system-language-injector",
71226
71083
  "atlas",
71227
71084
  "tool-definition-optimizer",
71228
71085
  "permission-ask-bridge",
@@ -71453,7 +71310,7 @@ var LanguageEnforcementConfigSchema = exports_external2.object({
71453
71310
  enabled: exports_external2.boolean().default(true),
71454
71311
  reminder_interval: exports_external2.number().int().positive().default(5),
71455
71312
  violation_threshold: exports_external2.number().min(0).max(1).default(0.6),
71456
- excluded_agents: exports_external2.array(exports_external2.string()).default(["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"]),
71313
+ excluded_agents: exports_external2.array(exports_external2.string()).default([]),
71457
71314
  user_message_english_threshold: exports_external2.number().min(0).max(1).default(0.6),
71458
71315
  user_message_lookback: exports_external2.number().int().positive().default(3)
71459
71316
  }).optional();
@@ -71715,7 +71572,7 @@ init_file_utils();
71715
71572
  init_shared();
71716
71573
  init_logger();
71717
71574
  import { promises as fs11 } from "fs";
71718
- import { join as join67, basename as basename6 } from "path";
71575
+ import { join as join64, basename as basename6 } from "path";
71719
71576
  async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
71720
71577
  try {
71721
71578
  await fs11.access(commandsDir);
@@ -71745,7 +71602,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
71745
71602
  if (entry.isDirectory()) {
71746
71603
  if (entry.name.startsWith("."))
71747
71604
  continue;
71748
- const subDirPath = join67(commandsDir, entry.name);
71605
+ const subDirPath = join64(commandsDir, entry.name);
71749
71606
  const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
71750
71607
  const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
71751
71608
  commands2.push(...subCommands);
@@ -71753,7 +71610,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
71753
71610
  }
71754
71611
  if (!isMarkdownFile(entry))
71755
71612
  continue;
71756
- const commandPath = join67(commandsDir, entry.name);
71613
+ const commandPath = join64(commandsDir, entry.name);
71757
71614
  const baseCommandName = basename6(entry.name, ".md");
71758
71615
  const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
71759
71616
  try {
@@ -71800,23 +71657,23 @@ function commandsToRecord(commands2) {
71800
71657
  return result;
71801
71658
  }
71802
71659
  async function loadUserCommands() {
71803
- const userCommandsDir = join67(getClaudeConfigDir(), "commands");
71660
+ const userCommandsDir = join64(getClaudeConfigDir(), "commands");
71804
71661
  const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
71805
71662
  return commandsToRecord(commands2);
71806
71663
  }
71807
71664
  async function loadProjectCommands() {
71808
- const projectCommandsDir = join67(process.cwd(), ".claude", "commands");
71665
+ const projectCommandsDir = join64(process.cwd(), ".claude", "commands");
71809
71666
  const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
71810
71667
  return commandsToRecord(commands2);
71811
71668
  }
71812
71669
  async function loadOpencodeGlobalCommands() {
71813
71670
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
71814
- const opencodeCommandsDir = join67(configDir, "command");
71671
+ const opencodeCommandsDir = join64(configDir, "command");
71815
71672
  const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
71816
71673
  return commandsToRecord(commands2);
71817
71674
  }
71818
71675
  async function loadOpencodeProjectCommands() {
71819
- const opencodeProjectDir = join67(process.cwd(), ".opencode", "command");
71676
+ const opencodeProjectDir = join64(process.cwd(), ".opencode", "command");
71820
71677
  const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
71821
71678
  return commandsToRecord(commands2);
71822
71679
  }
@@ -71824,8 +71681,8 @@ async function loadOpencodeProjectCommands() {
71824
71681
  init_frontmatter();
71825
71682
  init_file_utils();
71826
71683
  init_shared();
71827
- import { existsSync as existsSync55, readdirSync as readdirSync20, readFileSync as readFileSync38 } from "fs";
71828
- import { join as join68, basename as basename7 } from "path";
71684
+ import { existsSync as existsSync54, readdirSync as readdirSync20, readFileSync as readFileSync37 } from "fs";
71685
+ import { join as join65, basename as basename7 } from "path";
71829
71686
  function parseToolsConfig(toolsStr) {
71830
71687
  if (!toolsStr)
71831
71688
  return;
@@ -71839,7 +71696,7 @@ function parseToolsConfig(toolsStr) {
71839
71696
  return result;
71840
71697
  }
71841
71698
  function loadAgentsFromDir(agentsDir, scope, leConfig) {
71842
- if (!existsSync55(agentsDir)) {
71699
+ if (!existsSync54(agentsDir)) {
71843
71700
  return [];
71844
71701
  }
71845
71702
  const entries = readdirSync20(agentsDir, { withFileTypes: true });
@@ -71847,10 +71704,10 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
71847
71704
  for (const entry of entries) {
71848
71705
  if (!isMarkdownFile(entry))
71849
71706
  continue;
71850
- const agentPath = join68(agentsDir, entry.name);
71707
+ const agentPath = join65(agentsDir, entry.name);
71851
71708
  const agentName = basename7(entry.name, ".md");
71852
71709
  try {
71853
- const content = readFileSync38(agentPath, "utf-8");
71710
+ const content = readFileSync37(agentPath, "utf-8");
71854
71711
  const { data, body } = parseFrontmatter(content);
71855
71712
  const name = data.name || agentName;
71856
71713
  const originalDescription = data.description || "";
@@ -71879,7 +71736,7 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
71879
71736
  return agents;
71880
71737
  }
71881
71738
  function loadUserAgents(leConfig) {
71882
- const userAgentsDir = join68(getClaudeConfigDir(), "agents");
71739
+ const userAgentsDir = join65(getClaudeConfigDir(), "agents");
71883
71740
  const agents = loadAgentsFromDir(userAgentsDir, "user", leConfig);
71884
71741
  const result = {};
71885
71742
  for (const agent of agents) {
@@ -71888,7 +71745,7 @@ function loadUserAgents(leConfig) {
71888
71745
  return result;
71889
71746
  }
71890
71747
  function loadProjectAgents(leConfig) {
71891
- const projectAgentsDir = join68(process.cwd(), ".claude", "agents");
71748
+ const projectAgentsDir = join65(process.cwd(), ".claude", "agents");
71892
71749
  const agents = loadAgentsFromDir(projectAgentsDir, "project", leConfig);
71893
71750
  const result = {};
71894
71751
  for (const agent of agents) {
@@ -71900,18 +71757,18 @@ function loadProjectAgents(leConfig) {
71900
71757
  init_frontmatter();
71901
71758
  init_file_utils();
71902
71759
  init_logger();
71903
- import { existsSync as existsSync56, readdirSync as readdirSync21, readFileSync as readFileSync39 } from "fs";
71760
+ import { existsSync as existsSync55, readdirSync as readdirSync21, readFileSync as readFileSync38 } from "fs";
71904
71761
  import { homedir as homedir14 } from "os";
71905
- import { join as join69, basename as basename8 } from "path";
71762
+ import { join as join66, basename as basename8 } from "path";
71906
71763
  var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
71907
71764
  function getPluginsBaseDir() {
71908
71765
  if (process.env.CLAUDE_PLUGINS_HOME) {
71909
71766
  return process.env.CLAUDE_PLUGINS_HOME;
71910
71767
  }
71911
- return join69(homedir14(), ".claude", "plugins");
71768
+ return join66(homedir14(), ".claude", "plugins");
71912
71769
  }
71913
71770
  function getInstalledPluginsPath() {
71914
- return join69(getPluginsBaseDir(), "installed_plugins.json");
71771
+ return join66(getPluginsBaseDir(), "installed_plugins.json");
71915
71772
  }
71916
71773
  function resolvePluginPath(path8, pluginRoot) {
71917
71774
  return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
@@ -71936,11 +71793,11 @@ function resolvePluginPaths(obj, pluginRoot) {
71936
71793
  }
71937
71794
  function loadInstalledPlugins() {
71938
71795
  const dbPath = getInstalledPluginsPath();
71939
- if (!existsSync56(dbPath)) {
71796
+ if (!existsSync55(dbPath)) {
71940
71797
  return null;
71941
71798
  }
71942
71799
  try {
71943
- const content = readFileSync39(dbPath, "utf-8");
71800
+ const content = readFileSync38(dbPath, "utf-8");
71944
71801
  return JSON.parse(content);
71945
71802
  } catch (error95) {
71946
71803
  log("Failed to load installed plugins database", error95);
@@ -71951,15 +71808,15 @@ function getClaudeSettingsPath() {
71951
71808
  if (process.env.CLAUDE_SETTINGS_PATH) {
71952
71809
  return process.env.CLAUDE_SETTINGS_PATH;
71953
71810
  }
71954
- return join69(homedir14(), ".claude", "settings.json");
71811
+ return join66(homedir14(), ".claude", "settings.json");
71955
71812
  }
71956
71813
  function loadClaudeSettings() {
71957
71814
  const settingsPath = getClaudeSettingsPath();
71958
- if (!existsSync56(settingsPath)) {
71815
+ if (!existsSync55(settingsPath)) {
71959
71816
  return null;
71960
71817
  }
71961
71818
  try {
71962
- const content = readFileSync39(settingsPath, "utf-8");
71819
+ const content = readFileSync38(settingsPath, "utf-8");
71963
71820
  return JSON.parse(content);
71964
71821
  } catch (error95) {
71965
71822
  log("Failed to load Claude settings", error95);
@@ -71967,12 +71824,12 @@ function loadClaudeSettings() {
71967
71824
  }
71968
71825
  }
71969
71826
  function loadPluginManifest(installPath) {
71970
- const manifestPath = join69(installPath, ".claude-plugin", "plugin.json");
71971
- if (!existsSync56(manifestPath)) {
71827
+ const manifestPath = join66(installPath, ".claude-plugin", "plugin.json");
71828
+ if (!existsSync55(manifestPath)) {
71972
71829
  return null;
71973
71830
  }
71974
71831
  try {
71975
- const content = readFileSync39(manifestPath, "utf-8");
71832
+ const content = readFileSync38(manifestPath, "utf-8");
71976
71833
  return JSON.parse(content);
71977
71834
  } catch (error95) {
71978
71835
  log(`Failed to load plugin manifest from ${manifestPath}`, error95);
@@ -72019,7 +71876,7 @@ function discoverInstalledPlugins(options) {
72019
71876
  continue;
72020
71877
  }
72021
71878
  const { installPath, scope, version: version3 } = installation;
72022
- if (!existsSync56(installPath)) {
71879
+ if (!existsSync55(installPath)) {
72023
71880
  errors5.push({
72024
71881
  pluginKey,
72025
71882
  installPath,
@@ -72037,21 +71894,21 @@ function discoverInstalledPlugins(options) {
72037
71894
  pluginKey,
72038
71895
  manifest: manifest ?? undefined
72039
71896
  };
72040
- if (existsSync56(join69(installPath, "commands"))) {
72041
- loadedPlugin.commandsDir = join69(installPath, "commands");
71897
+ if (existsSync55(join66(installPath, "commands"))) {
71898
+ loadedPlugin.commandsDir = join66(installPath, "commands");
72042
71899
  }
72043
- if (existsSync56(join69(installPath, "agents"))) {
72044
- loadedPlugin.agentsDir = join69(installPath, "agents");
71900
+ if (existsSync55(join66(installPath, "agents"))) {
71901
+ loadedPlugin.agentsDir = join66(installPath, "agents");
72045
71902
  }
72046
- if (existsSync56(join69(installPath, "skills"))) {
72047
- loadedPlugin.skillsDir = join69(installPath, "skills");
71903
+ if (existsSync55(join66(installPath, "skills"))) {
71904
+ loadedPlugin.skillsDir = join66(installPath, "skills");
72048
71905
  }
72049
- const hooksPath = join69(installPath, "hooks", "hooks.json");
72050
- if (existsSync56(hooksPath)) {
71906
+ const hooksPath = join66(installPath, "hooks", "hooks.json");
71907
+ if (existsSync55(hooksPath)) {
72051
71908
  loadedPlugin.hooksPath = hooksPath;
72052
71909
  }
72053
- const mcpPath = join69(installPath, ".mcp.json");
72054
- if (existsSync56(mcpPath)) {
71910
+ const mcpPath = join66(installPath, ".mcp.json");
71911
+ if (existsSync55(mcpPath)) {
72055
71912
  loadedPlugin.mcpPath = mcpPath;
72056
71913
  }
72057
71914
  plugins.push(loadedPlugin);
@@ -72062,17 +71919,17 @@ function discoverInstalledPlugins(options) {
72062
71919
  function loadPluginCommands(plugins) {
72063
71920
  const commands2 = {};
72064
71921
  for (const plugin of plugins) {
72065
- if (!plugin.commandsDir || !existsSync56(plugin.commandsDir))
71922
+ if (!plugin.commandsDir || !existsSync55(plugin.commandsDir))
72066
71923
  continue;
72067
71924
  const entries = readdirSync21(plugin.commandsDir, { withFileTypes: true });
72068
71925
  for (const entry of entries) {
72069
71926
  if (!isMarkdownFile(entry))
72070
71927
  continue;
72071
- const commandPath = join69(plugin.commandsDir, entry.name);
71928
+ const commandPath = join66(plugin.commandsDir, entry.name);
72072
71929
  const commandName = basename8(entry.name, ".md");
72073
71930
  const namespacedName = `${plugin.name}:${commandName}`;
72074
71931
  try {
72075
- const content = readFileSync39(commandPath, "utf-8");
71932
+ const content = readFileSync38(commandPath, "utf-8");
72076
71933
  const { data, body } = parseFrontmatter(content);
72077
71934
  const wrappedTemplate = `<command-instruction>
72078
71935
  ${body.trim()}
@@ -72104,21 +71961,21 @@ $ARGUMENTS
72104
71961
  function loadPluginSkillsAsCommands(plugins) {
72105
71962
  const skills = {};
72106
71963
  for (const plugin of plugins) {
72107
- if (!plugin.skillsDir || !existsSync56(plugin.skillsDir))
71964
+ if (!plugin.skillsDir || !existsSync55(plugin.skillsDir))
72108
71965
  continue;
72109
71966
  const entries = readdirSync21(plugin.skillsDir, { withFileTypes: true });
72110
71967
  for (const entry of entries) {
72111
71968
  if (entry.name.startsWith("."))
72112
71969
  continue;
72113
- const skillPath = join69(plugin.skillsDir, entry.name);
71970
+ const skillPath = join66(plugin.skillsDir, entry.name);
72114
71971
  if (!entry.isDirectory() && !entry.isSymbolicLink())
72115
71972
  continue;
72116
71973
  const resolvedPath = resolveSymlink(skillPath);
72117
- const skillMdPath = join69(resolvedPath, "SKILL.md");
72118
- if (!existsSync56(skillMdPath))
71974
+ const skillMdPath = join66(resolvedPath, "SKILL.md");
71975
+ if (!existsSync55(skillMdPath))
72119
71976
  continue;
72120
71977
  try {
72121
- const content = readFileSync39(skillMdPath, "utf-8");
71978
+ const content = readFileSync38(skillMdPath, "utf-8");
72122
71979
  const { data, body } = parseFrontmatter(content);
72123
71980
  const skillName = data.name || entry.name;
72124
71981
  const namespacedName = `${plugin.name}:${skillName}`;
@@ -72165,17 +72022,17 @@ function parseToolsConfig2(toolsStr) {
72165
72022
  function loadPluginAgents(plugins) {
72166
72023
  const agents = {};
72167
72024
  for (const plugin of plugins) {
72168
- if (!plugin.agentsDir || !existsSync56(plugin.agentsDir))
72025
+ if (!plugin.agentsDir || !existsSync55(plugin.agentsDir))
72169
72026
  continue;
72170
72027
  const entries = readdirSync21(plugin.agentsDir, { withFileTypes: true });
72171
72028
  for (const entry of entries) {
72172
72029
  if (!isMarkdownFile(entry))
72173
72030
  continue;
72174
- const agentPath = join69(plugin.agentsDir, entry.name);
72031
+ const agentPath = join66(plugin.agentsDir, entry.name);
72175
72032
  const agentName = basename8(entry.name, ".md");
72176
72033
  const namespacedName = `${plugin.name}:${agentName}`;
72177
72034
  try {
72178
- const content = readFileSync39(agentPath, "utf-8");
72035
+ const content = readFileSync38(agentPath, "utf-8");
72179
72036
  const { data, body } = parseFrontmatter(content);
72180
72037
  const name = data.name || agentName;
72181
72038
  const originalDescription = data.description || "";
@@ -72201,7 +72058,7 @@ function loadPluginAgents(plugins) {
72201
72058
  async function loadPluginMcpServers(plugins) {
72202
72059
  const servers = {};
72203
72060
  for (const plugin of plugins) {
72204
- if (!plugin.mcpPath || !existsSync56(plugin.mcpPath))
72061
+ if (!plugin.mcpPath || !existsSync55(plugin.mcpPath))
72205
72062
  continue;
72206
72063
  try {
72207
72064
  const content = await Bun.file(plugin.mcpPath).text();
@@ -72233,10 +72090,10 @@ async function loadPluginMcpServers(plugins) {
72233
72090
  function loadPluginHooksConfigs(plugins) {
72234
72091
  const configs = [];
72235
72092
  for (const plugin of plugins) {
72236
- if (!plugin.hooksPath || !existsSync56(plugin.hooksPath))
72093
+ if (!plugin.hooksPath || !existsSync55(plugin.hooksPath))
72237
72094
  continue;
72238
72095
  try {
72239
- const content = readFileSync39(plugin.hooksPath, "utf-8");
72096
+ const content = readFileSync38(plugin.hooksPath, "utf-8");
72240
72097
  let config4 = JSON.parse(content);
72241
72098
  config4 = resolvePluginPaths(config4, plugin.installPath);
72242
72099
  configs.push(config4);
@@ -73654,11 +73511,7 @@ function createConfigHandler(deps) {
73654
73511
  if (isLanguageEnforcementEnabled(pluginConfig)) {
73655
73512
  const prometheusAgent = agentConfig["\u6218\u7565\u53C2\u8C0B"];
73656
73513
  if (prometheusAgent?.prompt && !prometheusAgent.prompt.includes("<Language_Instruction>")) {
73657
- if (isDeepseekModel(prometheusAgent.model ?? "")) {
73658
- prometheusAgent.prompt += ZH_LANGUAGE_INSTRUCTION_DEEPSEEK;
73659
- } else {
73660
- prometheusAgent.prompt += ZH_LANGUAGE_INSTRUCTION;
73661
- }
73514
+ prometheusAgent.prompt += ZH_LANGUAGE_INSTRUCTION;
73662
73515
  }
73663
73516
  }
73664
73517
  if (isLanguageEnforcementEnabled(pluginConfig)) {
@@ -73857,7 +73710,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
73857
73710
  return;
73858
73711
  }
73859
73712
  log("[OhMyOpenCodePlugin] Starting session agent recovery...");
73860
- const recoveredAgents = recoverSessionAgents();
73713
+ const recoveredAgents = recoverSessionAgents(ctx.directory);
73861
73714
  log("[OhMyOpenCodePlugin] Session agent recovery complete", { recoveredAgents });
73862
73715
  startBackgroundCheck2();
73863
73716
  const pluginConfig = loadPluginConfig(ctx.directory, ctx);
@@ -73936,8 +73789,6 @@ var OhMyOpenCodePlugin = async (ctx) => {
73936
73789
  const keywordDetector = isHookEnabled("keyword-detector") ? createKeywordDetectorHook(ctx, contextCollector) : null;
73937
73790
  const contextInjectorMessagesTransform = createContextInjectorMessagesTransformHook(contextCollector);
73938
73791
  const agentUsageReminder = isHookEnabled("agent-usage-reminder") ? createAgentUsageReminderHook(ctx) : null;
73939
- const languageReminder = isHookEnabled("language-reminder") && isLanguageEnforcementEnabled(pluginConfig) ? createLanguageReminderHook(ctx) : null;
73940
- const thinkingLanguageValidator = isHookEnabled("thinking-language-validator") && isLanguageEnforcementEnabled(pluginConfig) ? createThinkingLanguageValidatorHook(ctx) : null;
73941
73792
  const nonInteractiveEnv = isHookEnabled("non-interactive-env") ? createNonInteractiveEnvHook(ctx) : null;
73942
73793
  const interactiveBashSession = isHookEnabled("interactive-bash-session") ? createInteractiveBashSessionHook(ctx) : null;
73943
73794
  const thinkingBlockValidator = isHookEnabled("thinking-block-validator") ? createThinkingBlockValidatorHook() : null;
@@ -74109,6 +73960,11 @@ var OhMyOpenCodePlugin = async (ctx) => {
74109
73960
  updateSessionAgent(input.sessionID, validatedAgent ?? input.agent, "chat.message");
74110
73961
  } else {
74111
73962
  const staleThresholdMs = pluginConfig.identity?.staleThresholdMs ?? 600000;
73963
+ if (!getSessionAgent(input.sessionID)) {
73964
+ log("[identity] chat.message without agent info and no session agent", {
73965
+ sessionID: input.sessionID
73966
+ });
73967
+ }
74112
73968
  if (isSessionAgentStale(input.sessionID, staleThresholdMs)) {
74113
73969
  log("[identity] session agent stale", { sessionID: input.sessionID, staleThresholdMs });
74114
73970
  const messageFileAgent = getAgentFromSessionMessages(input.sessionID);
@@ -74221,10 +74077,6 @@ var OhMyOpenCodePlugin = async (ctx) => {
74221
74077
  hookCount++;
74222
74078
  await wrapWithTiming(perfTracer, "event", "agentUsageReminder", () => agentUsageReminder?.event(input), evtSessionID);
74223
74079
  hookCount++;
74224
- await wrapWithTiming(perfTracer, "event", "languageReminder", () => languageReminder?.event(input), evtSessionID);
74225
- hookCount++;
74226
- await wrapWithTiming(perfTracer, "event", "thinkingLanguageValidator", () => thinkingLanguageValidator?.event(input), evtSessionID);
74227
- hookCount++;
74228
74080
  await wrapWithTiming(perfTracer, "event", "interactiveBashSession", () => interactiveBashSession?.event(input), evtSessionID);
74229
74081
  hookCount++;
74230
74082
  await wrapWithTiming(perfTracer, "event", "ralphLoop", () => ralphLoop?.event(input), evtSessionID);
@@ -74240,6 +74092,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
74240
74092
  try {
74241
74093
  cleanupStaleTmpFiles(ctx.directory);
74242
74094
  } catch {}
74095
+ if (sessionInfo?.id) {
74096
+ log("[identity] New main session created", { sessionID: sessionInfo.id });
74097
+ }
74243
74098
  }
74244
74099
  firstMessageVariantGate.markSessionCreated(sessionInfo);
74245
74100
  }
@@ -74272,6 +74127,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
74272
74127
  const validatedAgent = validateAndFixAgentIdentity(sessionID, agent);
74273
74128
  updateSessionAgent(sessionID, validatedAgent ?? agent, "message.updated");
74274
74129
  }
74130
+ if (sessionID && agent && role === "assistant") {
74131
+ updateSessionAgent(sessionID, agent, "message.updated.assistant");
74132
+ }
74275
74133
  }
74276
74134
  if (event.type === "session.error") {
74277
74135
  const sessionID = props?.sessionID;
@@ -74384,10 +74242,6 @@ var OhMyOpenCodePlugin = async (ctx) => {
74384
74242
  hookCount++;
74385
74243
  await wrapWithTiming(perfTracer, "tool.execute.after", "agentUsageReminder", () => agentUsageReminder?.["tool.execute.after"](input, output), input.sessionID, input.tool);
74386
74244
  hookCount++;
74387
- await wrapWithTiming(perfTracer, "tool.execute.after", "languageReminder", () => languageReminder?.["tool.execute.after"](input, output), input.sessionID, input.tool);
74388
- hookCount++;
74389
- await wrapWithTiming(perfTracer, "tool.execute.after", "thinkingLanguageValidator", () => thinkingLanguageValidator?.["tool.execute.after"](input, output), input.sessionID, input.tool);
74390
- hookCount++;
74391
74245
  await wrapWithTiming(perfTracer, "tool.execute.after", "interactiveBashSession", () => interactiveBashSession?.["tool.execute.after"](input, output), input.sessionID, input.tool);
74392
74246
  hookCount++;
74393
74247
  await wrapWithTiming(perfTracer, "tool.execute.after", "editErrorRecovery", () => editErrorRecovery?.["tool.execute.after"](input, output), input.sessionID, input.tool);