@skj1724/oh-my-opencode 3.19.4 → 3.19.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.
package/dist/index.js CHANGED
@@ -46,6 +46,84 @@ 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/shared/fileio-monitor.ts
50
+ import { readdirSync, readFileSync, writeFileSync, existsSync } from "fs";
51
+ import { relative } from "path";
52
+ import { cwd } from "process";
53
+ function summarize(path) {
54
+ let result;
55
+ try {
56
+ result = relative(cwd(), path);
57
+ } catch {
58
+ result = path;
59
+ }
60
+ if (result.length > MAX_PATH_LENGTH) {
61
+ return result.slice(0, MAX_PATH_LENGTH - 3) + "...";
62
+ }
63
+ return result;
64
+ }
65
+ function setFileIOMonitor(monitor) {
66
+ globalMonitor = monitor;
67
+ }
68
+ function getFileIOMonitor() {
69
+ return globalMonitor;
70
+ }
71
+ function createFileIOMonitor(tracer) {
72
+ return {
73
+ readdirSync(path) {
74
+ if (!tracer.isEnabled()) {
75
+ return readdirSync(path);
76
+ }
77
+ const start = performance.now();
78
+ try {
79
+ return readdirSync(path);
80
+ } finally {
81
+ const durationMs = performance.now() - start;
82
+ tracer.recordFileIO("readdirSync", summarize(path), durationMs);
83
+ }
84
+ },
85
+ readFileSync(path, options) {
86
+ if (!tracer.isEnabled()) {
87
+ return readFileSync(path, options);
88
+ }
89
+ const start = performance.now();
90
+ try {
91
+ return readFileSync(path, options);
92
+ } finally {
93
+ const durationMs = performance.now() - start;
94
+ tracer.recordFileIO("readFileSync", summarize(path), durationMs);
95
+ }
96
+ },
97
+ writeFileSync(path, data, options) {
98
+ if (!tracer.isEnabled()) {
99
+ writeFileSync(path, data, options);
100
+ return;
101
+ }
102
+ const start = performance.now();
103
+ try {
104
+ writeFileSync(path, data, options);
105
+ } finally {
106
+ const durationMs = performance.now() - start;
107
+ tracer.recordFileIO("writeFileSync", summarize(path), durationMs);
108
+ }
109
+ },
110
+ existsSync(path) {
111
+ if (!tracer.isEnabled()) {
112
+ return existsSync(path);
113
+ }
114
+ const start = performance.now();
115
+ try {
116
+ return existsSync(path);
117
+ } finally {
118
+ const durationMs = performance.now() - start;
119
+ tracer.recordFileIO("existsSync", summarize(path), durationMs);
120
+ }
121
+ }
122
+ };
123
+ }
124
+ var MAX_PATH_LENGTH = 120, globalMonitor = null;
125
+ var init_fileio_monitor = () => {};
126
+
49
127
  // src/shared/data-path.ts
50
128
  import * as path from "path";
51
129
  import * as os from "os";
@@ -2767,17 +2845,17 @@ var init_frontmatter = __esm(() => {
2767
2845
  import { spawn as spawn2 } from "child_process";
2768
2846
  import { exec } from "child_process";
2769
2847
  import { promisify } from "util";
2770
- import { existsSync as existsSync4 } from "fs";
2848
+ import { existsSync as existsSync5 } from "fs";
2771
2849
  import { homedir as homedir2 } from "os";
2772
2850
  function getHomeDir() {
2773
2851
  return process.env.HOME || process.env.USERPROFILE || homedir2();
2774
2852
  }
2775
2853
  function findShellPath(defaultPaths, customPath) {
2776
- if (customPath && existsSync4(customPath)) {
2854
+ if (customPath && existsSync5(customPath)) {
2777
2855
  return customPath;
2778
2856
  }
2779
2857
  for (const path3 of defaultPaths) {
2780
- if (existsSync4(path3)) {
2858
+ if (existsSync5(path3)) {
2781
2859
  return path3;
2782
2860
  }
2783
2861
  }
@@ -2789,9 +2867,9 @@ function findZshPath(customZshPath) {
2789
2867
  function findBashPath() {
2790
2868
  return findShellPath(DEFAULT_BASH_PATHS);
2791
2869
  }
2792
- async function executeHookCommand(command, stdin, cwd, options) {
2870
+ async function executeHookCommand(command, stdin, cwd2, options) {
2793
2871
  const home = getHomeDir();
2794
- let expandedCommand = command.replace(/^~(?=\/|$)/g, home).replace(/\s~(?=\/)/g, ` ${home}`).replace(/\$CLAUDE_PROJECT_DIR/g, cwd).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, cwd);
2872
+ let expandedCommand = command.replace(/^~(?=\/|$)/g, home).replace(/\s~(?=\/)/g, ` ${home}`).replace(/\$CLAUDE_PROJECT_DIR/g, cwd2).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, cwd2);
2795
2873
  let finalCommand = expandedCommand;
2796
2874
  if (options?.forceZsh) {
2797
2875
  const zshPath = findZshPath(options.zshPath);
@@ -2807,9 +2885,9 @@ async function executeHookCommand(command, stdin, cwd, options) {
2807
2885
  }
2808
2886
  return new Promise((resolve) => {
2809
2887
  const proc = spawn2(finalCommand, {
2810
- cwd,
2888
+ cwd: cwd2,
2811
2889
  shell: true,
2812
- env: { ...process.env, HOME: home, CLAUDE_PROJECT_DIR: cwd }
2890
+ env: { ...process.env, HOME: home, CLAUDE_PROJECT_DIR: cwd2 }
2813
2891
  });
2814
2892
  let stdout = "";
2815
2893
  let stderr = "";
@@ -2912,7 +2990,7 @@ var init_command_executor = __esm(() => {
2912
2990
  });
2913
2991
 
2914
2992
  // src/shared/file-reference-resolver.ts
2915
- import { existsSync as existsSync5, readFileSync as readFileSync3, statSync } from "fs";
2993
+ import { existsSync as existsSync6, readFileSync as readFileSync4, statSync } from "fs";
2916
2994
  import { join as join8, isAbsolute } from "path";
2917
2995
  function findFileReferences(text) {
2918
2996
  const matches = [];
@@ -2928,24 +3006,24 @@ function findFileReferences(text) {
2928
3006
  }
2929
3007
  return matches;
2930
3008
  }
2931
- function resolveFilePath(filePath, cwd) {
3009
+ function resolveFilePath(filePath, cwd2) {
2932
3010
  if (isAbsolute(filePath)) {
2933
3011
  return filePath;
2934
3012
  }
2935
- return join8(cwd, filePath);
3013
+ return join8(cwd2, filePath);
2936
3014
  }
2937
3015
  function readFileContent(resolvedPath) {
2938
- if (!existsSync5(resolvedPath)) {
3016
+ if (!existsSync6(resolvedPath)) {
2939
3017
  return `[file not found: ${resolvedPath}]`;
2940
3018
  }
2941
3019
  const stat = statSync(resolvedPath);
2942
3020
  if (stat.isDirectory()) {
2943
3021
  return `[cannot read directory: ${resolvedPath}]`;
2944
3022
  }
2945
- const content = readFileSync3(resolvedPath, "utf-8");
3023
+ const content = readFileSync4(resolvedPath, "utf-8");
2946
3024
  return content;
2947
3025
  }
2948
- async function resolveFileReferencesInText(text, cwd = process.cwd(), depth = 0, maxDepth = 3) {
3026
+ async function resolveFileReferencesInText(text, cwd2 = process.cwd(), depth = 0, maxDepth = 3) {
2949
3027
  if (depth >= maxDepth) {
2950
3028
  return text;
2951
3029
  }
@@ -2955,7 +3033,7 @@ async function resolveFileReferencesInText(text, cwd = process.cwd(), depth = 0,
2955
3033
  }
2956
3034
  const replacements = new Map;
2957
3035
  for (const match of matches) {
2958
- const resolvedPath = resolveFilePath(match.filePath, cwd);
3036
+ const resolvedPath = resolveFilePath(match.filePath, cwd2);
2959
3037
  const content = readFileContent(resolvedPath);
2960
3038
  replacements.set(match.fullMatch, content);
2961
3039
  }
@@ -2964,7 +3042,7 @@ async function resolveFileReferencesInText(text, cwd = process.cwd(), depth = 0,
2964
3042
  resolved = resolved.split(pattern).join(replacement);
2965
3043
  }
2966
3044
  if (findFileReferences(resolved).length > 0 && depth + 1 < maxDepth) {
2967
- return resolveFileReferencesInText(resolved, cwd, depth + 1, maxDepth);
3045
+ return resolveFileReferencesInText(resolved, cwd2, depth + 1, maxDepth);
2968
3046
  }
2969
3047
  return resolved;
2970
3048
  }
@@ -4138,7 +4216,7 @@ var init_main = __esm(() => {
4138
4216
  });
4139
4217
 
4140
4218
  // src/shared/jsonc-parser.ts
4141
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
4219
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
4142
4220
  function parseJsonc(content) {
4143
4221
  const errors = [];
4144
4222
  const result = parse2(content, errors, {
@@ -4169,10 +4247,10 @@ function parseJsoncSafe(content) {
4169
4247
  function detectConfigFile(basePath) {
4170
4248
  const jsoncPath = `${basePath}.jsonc`;
4171
4249
  const jsonPath = `${basePath}.json`;
4172
- if (existsSync6(jsoncPath)) {
4250
+ if (existsSync7(jsoncPath)) {
4173
4251
  return { format: "jsonc", path: jsoncPath };
4174
4252
  }
4175
- if (existsSync6(jsonPath)) {
4253
+ if (existsSync7(jsonPath)) {
4176
4254
  return { format: "json", path: jsonPath };
4177
4255
  }
4178
4256
  return { format: "none", path: jsonPath };
@@ -4318,7 +4396,7 @@ var init_migration = __esm(() => {
4318
4396
  });
4319
4397
 
4320
4398
  // src/shared/opencode-config-dir.ts
4321
- import { existsSync as existsSync7 } from "fs";
4399
+ import { existsSync as existsSync8 } from "fs";
4322
4400
  import { homedir as homedir4 } from "os";
4323
4401
  import { join as join10, resolve as resolve2 } from "path";
4324
4402
  function isDevBuild(version) {
@@ -4350,13 +4428,13 @@ function getCliConfigDir() {
4350
4428
  if (process.platform === "win32") {
4351
4429
  const crossPlatformDir = join10(homedir4(), ".config", "opencode");
4352
4430
  const crossPlatformConfig = join10(crossPlatformDir, "opencode.json");
4353
- if (existsSync7(crossPlatformConfig)) {
4431
+ if (existsSync8(crossPlatformConfig)) {
4354
4432
  return crossPlatformDir;
4355
4433
  }
4356
4434
  const appData = process.env.APPDATA || join10(homedir4(), "AppData", "Roaming");
4357
4435
  const appdataDir = join10(appData, "opencode");
4358
4436
  const appdataConfig = join10(appdataDir, "opencode.json");
4359
- if (existsSync7(appdataConfig)) {
4437
+ if (existsSync8(appdataConfig)) {
4360
4438
  return appdataDir;
4361
4439
  }
4362
4440
  return crossPlatformDir;
@@ -4375,7 +4453,7 @@ function getOpenCodeConfigDir(options) {
4375
4453
  const legacyDir = getCliConfigDir();
4376
4454
  const legacyConfig = join10(legacyDir, "opencode.json");
4377
4455
  const legacyConfigC = join10(legacyDir, "opencode.jsonc");
4378
- if (existsSync7(legacyConfig) || existsSync7(legacyConfigC)) {
4456
+ if (existsSync8(legacyConfig) || existsSync8(legacyConfigC)) {
4379
4457
  return legacyDir;
4380
4458
  }
4381
4459
  }
@@ -4853,7 +4931,7 @@ var init_model_requirements = __esm(() => {
4853
4931
  });
4854
4932
 
4855
4933
  // src/shared/model-availability.ts
4856
- import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
4934
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
4857
4935
  import { homedir as homedir6 } from "os";
4858
4936
  import { join as join12 } from "path";
4859
4937
  function normalizeModelName(name) {
@@ -4908,12 +4986,12 @@ async function fetchAvailableModels(_client) {
4908
4986
  const modelSet = new Set;
4909
4987
  const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
4910
4988
  log("[fetchAvailableModels] reading cache file", { cacheFile });
4911
- if (!existsSync9(cacheFile)) {
4989
+ if (!existsSync10(cacheFile)) {
4912
4990
  log("[fetchAvailableModels] cache file not found, returning empty set");
4913
4991
  return modelSet;
4914
4992
  }
4915
4993
  try {
4916
- const content = readFileSync6(cacheFile, "utf-8");
4994
+ const content = readFileSync7(cacheFile, "utf-8");
4917
4995
  const data = JSON.parse(content);
4918
4996
  const providerIds = Object.keys(data);
4919
4997
  log("[fetchAvailableModels] providers found", { count: providerIds.length, providers: providerIds.slice(0, 10) });
@@ -4936,7 +5014,7 @@ async function fetchAvailableModels(_client) {
4936
5014
  }
4937
5015
  function isModelCacheAvailable() {
4938
5016
  const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
4939
- return existsSync9(cacheFile);
5017
+ return existsSync10(cacheFile);
4940
5018
  }
4941
5019
  var cachedModels = null;
4942
5020
  var init_model_availability = __esm(() => {
@@ -5033,6 +5111,136 @@ class PerfTimer {
5033
5111
  }
5034
5112
  }
5035
5113
 
5114
+ // src/shared/perf-tracer.ts
5115
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync11 } from "fs";
5116
+ import { tmpdir as tmpdir2 } from "os";
5117
+ import { join as join13 } from "path";
5118
+
5119
+ class PerfTracer {
5120
+ buffer = [];
5121
+ enabled;
5122
+ outputDir;
5123
+ slowThreshold;
5124
+ eventCount = 0;
5125
+ memorySnapshotInterval;
5126
+ constructor(config) {
5127
+ this.enabled = config.enabled;
5128
+ this.outputDir = config.outputDir ?? join13(tmpdir2(), "oh-my-opencode-perf");
5129
+ this.slowThreshold = config.slowThreshold ?? 100;
5130
+ this.memorySnapshotInterval = config.memorySnapshotInterval ?? 5;
5131
+ }
5132
+ isEnabled() {
5133
+ return this.enabled;
5134
+ }
5135
+ isSlowHook(durationMs) {
5136
+ return durationMs > this.slowThreshold;
5137
+ }
5138
+ recordHook(pipeline, hook, durationMs, sessionID, tool, error) {
5139
+ if (!this.enabled)
5140
+ return;
5141
+ const span = {
5142
+ t: new Date().toISOString(),
5143
+ type: "hook",
5144
+ pipeline,
5145
+ hook,
5146
+ durationMs,
5147
+ sessionID
5148
+ };
5149
+ if (tool !== undefined)
5150
+ span.tool = tool;
5151
+ if (error !== undefined)
5152
+ span.error = error;
5153
+ this.buffer.push(span);
5154
+ }
5155
+ recordPipeline(name, totalDurationMs, hookCount, sessionID) {
5156
+ if (!this.enabled)
5157
+ return;
5158
+ this.buffer.push({
5159
+ t: new Date().toISOString(),
5160
+ type: "pipeline",
5161
+ name,
5162
+ totalDurationMs,
5163
+ hookCount,
5164
+ sessionID
5165
+ });
5166
+ }
5167
+ recordApiCall(method, durationMs, sessionID, messageCount, error) {
5168
+ if (!this.enabled)
5169
+ return;
5170
+ const span = {
5171
+ t: new Date().toISOString(),
5172
+ type: "api",
5173
+ method,
5174
+ durationMs,
5175
+ sessionID
5176
+ };
5177
+ if (messageCount !== undefined)
5178
+ span.messageCount = messageCount;
5179
+ if (error !== undefined)
5180
+ span.error = error;
5181
+ this.buffer.push(span);
5182
+ }
5183
+ recordFileIO(operation, path4, durationMs, fileCount) {
5184
+ if (!this.enabled)
5185
+ return;
5186
+ const span = {
5187
+ t: new Date().toISOString(),
5188
+ type: "fileio",
5189
+ operation,
5190
+ path: path4,
5191
+ durationMs
5192
+ };
5193
+ if (fileCount !== undefined)
5194
+ span.fileCount = fileCount;
5195
+ this.buffer.push(span);
5196
+ }
5197
+ recordPolling(durationMs, taskCount, sessionCount) {
5198
+ if (!this.enabled)
5199
+ return;
5200
+ this.buffer.push({
5201
+ t: new Date().toISOString(),
5202
+ type: "polling",
5203
+ durationMs,
5204
+ taskCount,
5205
+ sessionCount
5206
+ });
5207
+ }
5208
+ snapshotMemory(trigger, mapSizes) {
5209
+ if (!this.enabled)
5210
+ return;
5211
+ this.eventCount++;
5212
+ if (this.eventCount % this.memorySnapshotInterval !== 0)
5213
+ return;
5214
+ this.buffer.push({
5215
+ t: new Date().toISOString(),
5216
+ type: "memory",
5217
+ trigger,
5218
+ mapSizes
5219
+ });
5220
+ }
5221
+ flush() {
5222
+ if (this.buffer.length === 0)
5223
+ return;
5224
+ if (!existsSync11(this.outputDir)) {
5225
+ mkdirSync3(this.outputDir, { recursive: true });
5226
+ }
5227
+ const date = new Date().toISOString().slice(0, 10);
5228
+ const filePath = join13(this.outputDir, `${date}.jsonl`);
5229
+ let output = "";
5230
+ for (const span of this.buffer) {
5231
+ output += JSON.stringify(span) + `
5232
+ `;
5233
+ }
5234
+ appendFileSync2(filePath, output);
5235
+ this.buffer = [];
5236
+ }
5237
+ reset() {
5238
+ this.buffer = [];
5239
+ this.eventCount = 0;
5240
+ }
5241
+ }
5242
+ var init_perf_tracer = () => {};
5243
+
5036
5244
  // src/shared/index.ts
5037
5245
  var init_shared = __esm(() => {
5038
5246
  init_frontmatter();
@@ -5060,6 +5268,8 @@ var init_shared = __esm(() => {
5060
5268
  init_model_requirements();
5061
5269
  init_model_resolver();
5062
5270
  init_model_availability();
5271
+ init_perf_tracer();
5272
+ init_fileio_monitor();
5063
5273
  });
5064
5274
 
5065
5275
  // node_modules/picomatch/lib/constants.js
@@ -10944,49 +11154,49 @@ var require_fast_uri = __commonJS((exports, module) => {
10944
11154
  schemelessOptions.skipEscape = true;
10945
11155
  return serialize(resolved, schemelessOptions);
10946
11156
  }
10947
- function resolveComponent(base, relative5, options, skipNormalization) {
11157
+ function resolveComponent(base, relative6, options, skipNormalization) {
10948
11158
  const target = {};
10949
11159
  if (!skipNormalization) {
10950
11160
  base = parse11(serialize(base, options), options);
10951
- relative5 = parse11(serialize(relative5, options), options);
11161
+ relative6 = parse11(serialize(relative6, options), options);
10952
11162
  }
10953
11163
  options = options || {};
10954
- if (!options.tolerant && relative5.scheme) {
10955
- target.scheme = relative5.scheme;
10956
- target.userinfo = relative5.userinfo;
10957
- target.host = relative5.host;
10958
- target.port = relative5.port;
10959
- target.path = removeDotSegments(relative5.path || "");
10960
- target.query = relative5.query;
11164
+ if (!options.tolerant && relative6.scheme) {
11165
+ target.scheme = relative6.scheme;
11166
+ target.userinfo = relative6.userinfo;
11167
+ target.host = relative6.host;
11168
+ target.port = relative6.port;
11169
+ target.path = removeDotSegments(relative6.path || "");
11170
+ target.query = relative6.query;
10961
11171
  } else {
10962
- if (relative5.userinfo !== undefined || relative5.host !== undefined || relative5.port !== undefined) {
10963
- target.userinfo = relative5.userinfo;
10964
- target.host = relative5.host;
10965
- target.port = relative5.port;
10966
- target.path = removeDotSegments(relative5.path || "");
10967
- target.query = relative5.query;
11172
+ if (relative6.userinfo !== undefined || relative6.host !== undefined || relative6.port !== undefined) {
11173
+ target.userinfo = relative6.userinfo;
11174
+ target.host = relative6.host;
11175
+ target.port = relative6.port;
11176
+ target.path = removeDotSegments(relative6.path || "");
11177
+ target.query = relative6.query;
10968
11178
  } else {
10969
- if (!relative5.path) {
11179
+ if (!relative6.path) {
10970
11180
  target.path = base.path;
10971
- if (relative5.query !== undefined) {
10972
- target.query = relative5.query;
11181
+ if (relative6.query !== undefined) {
11182
+ target.query = relative6.query;
10973
11183
  } else {
10974
11184
  target.query = base.query;
10975
11185
  }
10976
11186
  } else {
10977
- if (relative5.path[0] === "/") {
10978
- target.path = removeDotSegments(relative5.path);
11187
+ if (relative6.path[0] === "/") {
11188
+ target.path = removeDotSegments(relative6.path);
10979
11189
  } else {
10980
11190
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
10981
- target.path = "/" + relative5.path;
11191
+ target.path = "/" + relative6.path;
10982
11192
  } else if (!base.path) {
10983
- target.path = relative5.path;
11193
+ target.path = relative6.path;
10984
11194
  } else {
10985
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative5.path;
11195
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative6.path;
10986
11196
  }
10987
11197
  target.path = removeDotSegments(target.path);
10988
11198
  }
10989
- target.query = relative5.query;
11199
+ target.query = relative6.query;
10990
11200
  }
10991
11201
  target.userinfo = base.userinfo;
10992
11202
  target.host = base.host;
@@ -10994,7 +11204,7 @@ var require_fast_uri = __commonJS((exports, module) => {
10994
11204
  }
10995
11205
  target.scheme = base.scheme;
10996
11206
  }
10997
- target.fragment = relative5.fragment;
11207
+ target.fragment = relative6.fragment;
10998
11208
  return target;
10999
11209
  }
11000
11210
  function equal(uriA, uriB, options) {
@@ -14201,7 +14411,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
14201
14411
  var getPathKey = require_path_key();
14202
14412
  function resolveCommandAttempt(parsed, withoutPathExt) {
14203
14413
  const env = parsed.options.env || process.env;
14204
- const cwd = process.cwd();
14414
+ const cwd2 = process.cwd();
14205
14415
  const hasCustomCwd = parsed.options.cwd != null;
14206
14416
  const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
14207
14417
  if (shouldSwitchCwd) {
@@ -14217,7 +14427,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
14217
14427
  });
14218
14428
  } catch (e) {} finally {
14219
14429
  if (shouldSwitchCwd) {
14220
- process.chdir(cwd);
14430
+ process.chdir(cwd2);
14221
14431
  }
14222
14432
  }
14223
14433
  if (resolved) {
@@ -14424,7 +14634,7 @@ var require_cross_spawn = __commonJS((exports, module) => {
14424
14634
  });
14425
14635
 
14426
14636
  // src/hooks/todo-continuation-enforcer.ts
14427
- import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
14637
+ import { existsSync as existsSync3, readdirSync as readdirSync3 } from "fs";
14428
14638
  import { join as join5 } from "path";
14429
14639
 
14430
14640
  // src/features/claude-code-session-state/state.ts
@@ -14452,7 +14662,8 @@ function clearSessionAgent(sessionID) {
14452
14662
  sessionAgentMap.delete(sessionID);
14453
14663
  }
14454
14664
  // src/features/hook-message-injector/injector.ts
14455
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
14665
+ init_fileio_monitor();
14666
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
14456
14667
  import { join as join3 } from "path";
14457
14668
 
14458
14669
  // src/features/hook-message-injector/constants.ts
@@ -14464,11 +14675,12 @@ var PART_STORAGE = join2(OPENCODE_STORAGE, "part");
14464
14675
 
14465
14676
  // src/features/hook-message-injector/injector.ts
14466
14677
  function findNearestMessageWithFields(messageDir) {
14678
+ const monitor = getFileIOMonitor();
14467
14679
  try {
14468
- const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort().reverse();
14680
+ const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
14469
14681
  for (const file of files) {
14470
14682
  try {
14471
- const content = readFileSync(join3(messageDir, file), "utf-8");
14683
+ const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
14472
14684
  const msg = JSON.parse(content);
14473
14685
  if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
14474
14686
  return msg;
@@ -14479,7 +14691,7 @@ function findNearestMessageWithFields(messageDir) {
14479
14691
  }
14480
14692
  for (const file of files) {
14481
14693
  try {
14482
- const content = readFileSync(join3(messageDir, file), "utf-8");
14694
+ const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
14483
14695
  const msg = JSON.parse(content);
14484
14696
  if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
14485
14697
  return msg;
@@ -14494,11 +14706,12 @@ function findNearestMessageWithFields(messageDir) {
14494
14706
  return null;
14495
14707
  }
14496
14708
  function findFirstMessageWithAgent(messageDir) {
14709
+ const monitor = getFileIOMonitor();
14497
14710
  try {
14498
- const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort();
14711
+ const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort();
14499
14712
  for (const file of files) {
14500
14713
  try {
14501
- const content = readFileSync(join3(messageDir, file), "utf-8");
14714
+ const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
14502
14715
  const msg = JSON.parse(content);
14503
14716
  if (msg.agent) {
14504
14717
  return msg.agent;
@@ -14523,20 +14736,24 @@ function generatePartId() {
14523
14736
  return `prt_${timestamp}${random}`;
14524
14737
  }
14525
14738
  function getOrCreateMessageDir(sessionID) {
14526
- if (!existsSync(MESSAGE_STORAGE)) {
14527
- mkdirSync(MESSAGE_STORAGE, { recursive: true });
14739
+ const monitor = getFileIOMonitor();
14740
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
14741
+ const _mkdir = (p, opts) => monitor ? undefined : mkdirSync(p, opts);
14742
+ const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
14743
+ if (!_exists(MESSAGE_STORAGE)) {
14744
+ _mkdir(MESSAGE_STORAGE, { recursive: true });
14528
14745
  }
14529
14746
  const directPath = join3(MESSAGE_STORAGE, sessionID);
14530
- if (existsSync(directPath)) {
14747
+ if (_exists(directPath)) {
14531
14748
  return directPath;
14532
14749
  }
14533
- for (const dir of readdirSync(MESSAGE_STORAGE)) {
14750
+ for (const dir of _readdir(MESSAGE_STORAGE)) {
14534
14751
  const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
14535
- if (existsSync(sessionPath)) {
14752
+ if (_exists(sessionPath)) {
14536
14753
  return sessionPath;
14537
14754
  }
14538
14755
  }
14539
- mkdirSync(directPath, { recursive: true });
14756
+ _mkdir(directPath, { recursive: true });
14540
14757
  return directPath;
14541
14758
  }
14542
14759
  function injectHookMessage(sessionID, hookContent, originalMessage) {
@@ -14585,12 +14802,22 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
14585
14802
  sessionID
14586
14803
  };
14587
14804
  try {
14588
- writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
14805
+ const monitor = getFileIOMonitor();
14806
+ if (monitor) {
14807
+ monitor.writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
14808
+ } else {
14809
+ writeFileSync2(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
14810
+ }
14589
14811
  const partDir = join3(PART_STORAGE, messageID);
14590
- if (!existsSync(partDir)) {
14812
+ const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
14813
+ if (!_exists(partDir)) {
14591
14814
  mkdirSync(partDir, { recursive: true });
14592
14815
  }
14593
- writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
14816
+ if (monitor) {
14817
+ monitor.writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
14818
+ } else {
14819
+ writeFileSync2(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
14820
+ }
14594
14821
  return true;
14595
14822
  } catch {
14596
14823
  return false;
@@ -14612,14 +14839,14 @@ var COUNTDOWN_SECONDS = 2;
14612
14839
  var TOAST_DURATION_MS = 900;
14613
14840
  var COUNTDOWN_GRACE_PERIOD_MS = 500;
14614
14841
  function getMessageDir(sessionID) {
14615
- if (!existsSync2(MESSAGE_STORAGE))
14842
+ if (!existsSync3(MESSAGE_STORAGE))
14616
14843
  return null;
14617
14844
  const directPath = join5(MESSAGE_STORAGE, sessionID);
14618
- if (existsSync2(directPath))
14845
+ if (existsSync3(directPath))
14619
14846
  return directPath;
14620
- for (const dir of readdirSync2(MESSAGE_STORAGE)) {
14847
+ for (const dir of readdirSync3(MESSAGE_STORAGE)) {
14621
14848
  const sessionPath = join5(MESSAGE_STORAGE, dir, sessionID);
14622
- if (existsSync2(sessionPath))
14849
+ if (existsSync3(sessionPath))
14623
14850
  return sessionPath;
14624
14851
  }
14625
14852
  return null;
@@ -15397,7 +15624,7 @@ function createSessionNotification(ctx, config = {}) {
15397
15624
  };
15398
15625
  }
15399
15626
  // src/hooks/session-recovery/storage.ts
15400
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
15627
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync4, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
15401
15628
  import { join as join7 } from "path";
15402
15629
 
15403
15630
  // src/hooks/session-recovery/constants.ts
@@ -15418,15 +15645,15 @@ function generatePartId2() {
15418
15645
  return `prt_${timestamp}${random}`;
15419
15646
  }
15420
15647
  function getMessageDir2(sessionID) {
15421
- if (!existsSync3(MESSAGE_STORAGE2))
15648
+ if (!existsSync4(MESSAGE_STORAGE2))
15422
15649
  return "";
15423
15650
  const directPath = join7(MESSAGE_STORAGE2, sessionID);
15424
- if (existsSync3(directPath)) {
15651
+ if (existsSync4(directPath)) {
15425
15652
  return directPath;
15426
15653
  }
15427
- for (const dir of readdirSync3(MESSAGE_STORAGE2)) {
15654
+ for (const dir of readdirSync4(MESSAGE_STORAGE2)) {
15428
15655
  const sessionPath = join7(MESSAGE_STORAGE2, dir, sessionID);
15429
- if (existsSync3(sessionPath)) {
15656
+ if (existsSync4(sessionPath)) {
15430
15657
  return sessionPath;
15431
15658
  }
15432
15659
  }
@@ -15434,14 +15661,14 @@ function getMessageDir2(sessionID) {
15434
15661
  }
15435
15662
  function readMessages(sessionID) {
15436
15663
  const messageDir = getMessageDir2(sessionID);
15437
- if (!messageDir || !existsSync3(messageDir))
15664
+ if (!messageDir || !existsSync4(messageDir))
15438
15665
  return [];
15439
15666
  const messages = [];
15440
- for (const file of readdirSync3(messageDir)) {
15667
+ for (const file of readdirSync4(messageDir)) {
15441
15668
  if (!file.endsWith(".json"))
15442
15669
  continue;
15443
15670
  try {
15444
- const content = readFileSync2(join7(messageDir, file), "utf-8");
15671
+ const content = readFileSync3(join7(messageDir, file), "utf-8");
15445
15672
  messages.push(JSON.parse(content));
15446
15673
  } catch {
15447
15674
  continue;
@@ -15457,14 +15684,14 @@ function readMessages(sessionID) {
15457
15684
  }
15458
15685
  function readParts(messageID) {
15459
15686
  const partDir = join7(PART_STORAGE2, messageID);
15460
- if (!existsSync3(partDir))
15687
+ if (!existsSync4(partDir))
15461
15688
  return [];
15462
15689
  const parts = [];
15463
- for (const file of readdirSync3(partDir)) {
15690
+ for (const file of readdirSync4(partDir)) {
15464
15691
  if (!file.endsWith(".json"))
15465
15692
  continue;
15466
15693
  try {
15467
- const content = readFileSync2(join7(partDir, file), "utf-8");
15694
+ const content = readFileSync3(join7(partDir, file), "utf-8");
15468
15695
  parts.push(JSON.parse(content));
15469
15696
  } catch {
15470
15697
  continue;
@@ -15495,7 +15722,7 @@ function messageHasContent(messageID) {
15495
15722
  }
15496
15723
  function injectTextPart(sessionID, messageID, text) {
15497
15724
  const partDir = join7(PART_STORAGE2, messageID);
15498
- if (!existsSync3(partDir)) {
15725
+ if (!existsSync4(partDir)) {
15499
15726
  mkdirSync2(partDir, { recursive: true });
15500
15727
  }
15501
15728
  const partId = generatePartId2();
@@ -15508,7 +15735,7 @@ function injectTextPart(sessionID, messageID, text) {
15508
15735
  synthetic: true
15509
15736
  };
15510
15737
  try {
15511
- writeFileSync2(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
15738
+ writeFileSync3(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
15512
15739
  return true;
15513
15740
  } catch {
15514
15741
  return false;
@@ -15604,7 +15831,7 @@ function findLastThinkingContent(sessionID, beforeMessageID) {
15604
15831
  }
15605
15832
  function prependThinkingPart(sessionID, messageID) {
15606
15833
  const partDir = join7(PART_STORAGE2, messageID);
15607
- if (!existsSync3(partDir)) {
15834
+ if (!existsSync4(partDir)) {
15608
15835
  mkdirSync2(partDir, { recursive: true });
15609
15836
  }
15610
15837
  const previousThinking = findLastThinkingContent(sessionID, messageID);
@@ -15614,11 +15841,11 @@ function prependThinkingPart(sessionID, messageID) {
15614
15841
  sessionID,
15615
15842
  messageID,
15616
15843
  type: "thinking",
15617
- thinking: previousThinking || "[Continuing from previous reasoning]",
15844
+ thinking: previousThinking || "[\u63A5\u7EED\u4E4B\u524D\u7684\u63A8\u7406]",
15618
15845
  synthetic: true
15619
15846
  };
15620
15847
  try {
15621
- writeFileSync2(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
15848
+ writeFileSync3(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
15622
15849
  return true;
15623
15850
  } catch {
15624
15851
  return false;
@@ -15626,15 +15853,15 @@ function prependThinkingPart(sessionID, messageID) {
15626
15853
  }
15627
15854
  function stripThinkingParts(messageID) {
15628
15855
  const partDir = join7(PART_STORAGE2, messageID);
15629
- if (!existsSync3(partDir))
15856
+ if (!existsSync4(partDir))
15630
15857
  return false;
15631
15858
  let anyRemoved = false;
15632
- for (const file of readdirSync3(partDir)) {
15859
+ for (const file of readdirSync4(partDir)) {
15633
15860
  if (!file.endsWith(".json"))
15634
15861
  continue;
15635
15862
  try {
15636
15863
  const filePath = join7(partDir, file);
15637
- const content = readFileSync2(filePath, "utf-8");
15864
+ const content = readFileSync3(filePath, "utf-8");
15638
15865
  const part = JSON.parse(content);
15639
15866
  if (THINKING_TYPES.has(part.type)) {
15640
15867
  unlinkSync(filePath);
@@ -15648,22 +15875,22 @@ function stripThinkingParts(messageID) {
15648
15875
  }
15649
15876
  function replaceEmptyTextParts(messageID, replacementText) {
15650
15877
  const partDir = join7(PART_STORAGE2, messageID);
15651
- if (!existsSync3(partDir))
15878
+ if (!existsSync4(partDir))
15652
15879
  return false;
15653
15880
  let anyReplaced = false;
15654
- for (const file of readdirSync3(partDir)) {
15881
+ for (const file of readdirSync4(partDir)) {
15655
15882
  if (!file.endsWith(".json"))
15656
15883
  continue;
15657
15884
  try {
15658
15885
  const filePath = join7(partDir, file);
15659
- const content = readFileSync2(filePath, "utf-8");
15886
+ const content = readFileSync3(filePath, "utf-8");
15660
15887
  const part = JSON.parse(content);
15661
15888
  if (part.type === "text") {
15662
15889
  const textPart = part;
15663
15890
  if (!textPart.text?.trim()) {
15664
15891
  textPart.text = replacementText;
15665
15892
  textPart.synthetic = true;
15666
- writeFileSync2(filePath, JSON.stringify(textPart, null, 2));
15893
+ writeFileSync3(filePath, JSON.stringify(textPart, null, 2));
15667
15894
  anyReplaced = true;
15668
15895
  }
15669
15896
  }
@@ -15932,25 +16159,25 @@ function createSessionRecoveryHook(ctx, options) {
15932
16159
  // src/hooks/comment-checker/cli.ts
15933
16160
  var {spawn: spawn5 } = globalThis.Bun;
15934
16161
  import { createRequire as createRequire2 } from "module";
15935
- import { dirname, join as join14 } from "path";
15936
- import { existsSync as existsSync11 } from "fs";
16162
+ import { dirname, join as join15 } from "path";
16163
+ import { existsSync as existsSync13 } from "fs";
15937
16164
  import * as fs5 from "fs";
15938
- import { tmpdir as tmpdir3 } from "os";
16165
+ import { tmpdir as tmpdir4 } from "os";
15939
16166
 
15940
16167
  // src/hooks/comment-checker/downloader.ts
15941
16168
  init_shared();
15942
16169
  var {spawn: spawn4 } = globalThis.Bun;
15943
- import { existsSync as existsSync10, mkdirSync as mkdirSync3, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync2 } from "fs";
15944
- import { join as join13 } from "path";
15945
- import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
16170
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
16171
+ import { join as join14 } from "path";
16172
+ import { homedir as homedir7, tmpdir as tmpdir3 } from "os";
15946
16173
  import { createRequire } from "module";
15947
16174
  var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
15948
- var DEBUG_FILE = join13(tmpdir2(), "comment-checker-debug.log");
16175
+ var DEBUG_FILE = join14(tmpdir3(), "comment-checker-debug.log");
15949
16176
  function debugLog(...args) {
15950
16177
  if (DEBUG) {
15951
16178
  const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
15952
16179
  `;
15953
- appendFileSync2(DEBUG_FILE, msg);
16180
+ appendFileSync3(DEBUG_FILE, msg);
15954
16181
  }
15955
16182
  }
15956
16183
  var REPO = "code-yeongyu/go-claude-code-comment-checker";
@@ -15964,19 +16191,19 @@ var PLATFORM_MAP = {
15964
16191
  function getCacheDir() {
15965
16192
  if (process.platform === "win32") {
15966
16193
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
15967
- const base2 = localAppData || join13(homedir7(), "AppData", "Local");
15968
- return join13(base2, "oh-my-opencode", "bin");
16194
+ const base2 = localAppData || join14(homedir7(), "AppData", "Local");
16195
+ return join14(base2, "oh-my-opencode", "bin");
15969
16196
  }
15970
16197
  const xdgCache = process.env.XDG_CACHE_HOME;
15971
- const base = xdgCache || join13(homedir7(), ".cache");
15972
- return join13(base, "oh-my-opencode", "bin");
16198
+ const base = xdgCache || join14(homedir7(), ".cache");
16199
+ return join14(base, "oh-my-opencode", "bin");
15973
16200
  }
15974
16201
  function getBinaryName() {
15975
16202
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
15976
16203
  }
15977
16204
  function getCachedBinaryPath() {
15978
- const binaryPath = join13(getCacheDir(), getBinaryName());
15979
- return existsSync10(binaryPath) ? binaryPath : null;
16205
+ const binaryPath = join14(getCacheDir(), getBinaryName());
16206
+ return existsSync12(binaryPath) ? binaryPath : null;
15980
16207
  }
15981
16208
  function getPackageVersion() {
15982
16209
  try {
@@ -16008,8 +16235,8 @@ async function downloadCommentChecker() {
16008
16235
  }
16009
16236
  const cacheDir = getCacheDir();
16010
16237
  const binaryName = getBinaryName();
16011
- const binaryPath = join13(cacheDir, binaryName);
16012
- if (existsSync10(binaryPath)) {
16238
+ const binaryPath = join14(cacheDir, binaryName);
16239
+ if (existsSync12(binaryPath)) {
16013
16240
  debugLog("Binary already cached at:", binaryPath);
16014
16241
  return binaryPath;
16015
16242
  }
@@ -16020,14 +16247,14 @@ async function downloadCommentChecker() {
16020
16247
  debugLog(`Downloading from: ${downloadUrl}`);
16021
16248
  console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
16022
16249
  try {
16023
- if (!existsSync10(cacheDir)) {
16024
- mkdirSync3(cacheDir, { recursive: true });
16250
+ if (!existsSync12(cacheDir)) {
16251
+ mkdirSync4(cacheDir, { recursive: true });
16025
16252
  }
16026
16253
  const response = await fetch(downloadUrl, { redirect: "follow" });
16027
16254
  if (!response.ok) {
16028
16255
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
16029
16256
  }
16030
- const archivePath = join13(cacheDir, assetName);
16257
+ const archivePath = join14(cacheDir, assetName);
16031
16258
  const arrayBuffer = await response.arrayBuffer();
16032
16259
  await Bun.write(archivePath, arrayBuffer);
16033
16260
  debugLog(`Downloaded archive to: ${archivePath}`);
@@ -16036,10 +16263,10 @@ async function downloadCommentChecker() {
16036
16263
  } else {
16037
16264
  await extractZip(archivePath, cacheDir);
16038
16265
  }
16039
- if (existsSync10(archivePath)) {
16266
+ if (existsSync12(archivePath)) {
16040
16267
  unlinkSync2(archivePath);
16041
16268
  }
16042
- if (process.platform !== "win32" && existsSync10(binaryPath)) {
16269
+ if (process.platform !== "win32" && existsSync12(binaryPath)) {
16043
16270
  chmodSync(binaryPath, 493);
16044
16271
  }
16045
16272
  debugLog(`Successfully downloaded binary to: ${binaryPath}`);
@@ -16063,7 +16290,7 @@ async function ensureCommentCheckerBinary() {
16063
16290
 
16064
16291
  // src/hooks/comment-checker/cli.ts
16065
16292
  var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
16066
- var DEBUG_FILE2 = join14(tmpdir3(), "comment-checker-debug.log");
16293
+ var DEBUG_FILE2 = join15(tmpdir4(), "comment-checker-debug.log");
16067
16294
  function debugLog2(...args) {
16068
16295
  if (DEBUG2) {
16069
16296
  const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -16089,8 +16316,8 @@ function findCommentCheckerPathSync() {
16089
16316
  const require2 = createRequire2(import.meta.url);
16090
16317
  const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
16091
16318
  const cliDir = dirname(cliPkgPath);
16092
- const binaryPath = join14(cliDir, "bin", binaryName);
16093
- if (existsSync11(binaryPath)) {
16319
+ const binaryPath = join15(cliDir, "bin", binaryName);
16320
+ if (existsSync13(binaryPath)) {
16094
16321
  debugLog2("found binary in main package:", binaryPath);
16095
16322
  return binaryPath;
16096
16323
  }
@@ -16111,7 +16338,7 @@ async function getCommentCheckerPath() {
16111
16338
  }
16112
16339
  initPromise = (async () => {
16113
16340
  const syncPath = findCommentCheckerPathSync();
16114
- if (syncPath && existsSync11(syncPath)) {
16341
+ if (syncPath && existsSync13(syncPath)) {
16115
16342
  resolvedCliPath = syncPath;
16116
16343
  debugLog2("using sync-resolved path:", syncPath);
16117
16344
  return syncPath;
@@ -16147,7 +16374,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
16147
16374
  debugLog2("comment-checker binary not found");
16148
16375
  return { hasComments: false, message: "" };
16149
16376
  }
16150
- if (!existsSync11(binaryPath)) {
16377
+ if (!existsSync13(binaryPath)) {
16151
16378
  debugLog2("comment-checker binary does not exist:", binaryPath);
16152
16379
  return { hasComments: false, message: "" };
16153
16380
  }
@@ -16185,11 +16412,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
16185
16412
 
16186
16413
  // src/hooks/comment-checker/index.ts
16187
16414
  import * as fs6 from "fs";
16188
- import { existsSync as existsSync12 } from "fs";
16189
- import { tmpdir as tmpdir4 } from "os";
16190
- import { join as join15 } from "path";
16415
+ import { existsSync as existsSync14 } from "fs";
16416
+ import { tmpdir as tmpdir5 } from "os";
16417
+ import { join as join16 } from "path";
16191
16418
  var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
16192
- var DEBUG_FILE3 = join15(tmpdir4(), "comment-checker-debug.log");
16419
+ var DEBUG_FILE3 = join16(tmpdir5(), "comment-checker-debug.log");
16193
16420
  function debugLog3(...args) {
16194
16421
  if (DEBUG3) {
16195
16422
  const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
@@ -16269,7 +16496,7 @@ function createCommentCheckerHooks(config) {
16269
16496
  }
16270
16497
  try {
16271
16498
  const cliPath = await cliPathPromise;
16272
- if (!cliPath || !existsSync12(cliPath)) {
16499
+ if (!cliPath || !existsSync14(cliPath)) {
16273
16500
  debugLog3("CLI not available, skipping comment check");
16274
16501
  return;
16275
16502
  }
@@ -16349,36 +16576,36 @@ function createToolOutputTruncatorHook(ctx, options) {
16349
16576
  };
16350
16577
  }
16351
16578
  // src/hooks/directory-agents-injector/index.ts
16352
- import { existsSync as existsSync14, readFileSync as readFileSync8 } from "fs";
16353
- import { dirname as dirname2, join as join18, resolve as resolve3 } from "path";
16579
+ import { existsSync as existsSync16, readFileSync as readFileSync9 } from "fs";
16580
+ import { dirname as dirname2, join as join19, resolve as resolve3 } from "path";
16354
16581
 
16355
16582
  // src/hooks/directory-agents-injector/storage.ts
16356
16583
  import {
16357
- existsSync as existsSync13,
16358
- mkdirSync as mkdirSync4,
16359
- readFileSync as readFileSync7,
16360
- writeFileSync as writeFileSync4,
16584
+ existsSync as existsSync15,
16585
+ mkdirSync as mkdirSync5,
16586
+ readFileSync as readFileSync8,
16587
+ writeFileSync as writeFileSync5,
16361
16588
  unlinkSync as unlinkSync3
16362
16589
  } from "fs";
16363
- import { join as join17 } from "path";
16590
+ import { join as join18 } from "path";
16364
16591
 
16365
16592
  // src/hooks/directory-agents-injector/constants.ts
16366
16593
  init_data_path();
16367
- import { join as join16 } from "path";
16594
+ import { join as join17 } from "path";
16368
16595
  var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
16369
- var AGENTS_INJECTOR_STORAGE = join16(OPENCODE_STORAGE3, "directory-agents");
16596
+ var AGENTS_INJECTOR_STORAGE = join17(OPENCODE_STORAGE3, "directory-agents");
16370
16597
  var AGENTS_FILENAME = "AGENTS.md";
16371
16598
 
16372
16599
  // src/hooks/directory-agents-injector/storage.ts
16373
16600
  function getStoragePath(sessionID) {
16374
- return join17(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
16601
+ return join18(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
16375
16602
  }
16376
16603
  function loadInjectedPaths(sessionID) {
16377
16604
  const filePath = getStoragePath(sessionID);
16378
- if (!existsSync13(filePath))
16605
+ if (!existsSync15(filePath))
16379
16606
  return new Set;
16380
16607
  try {
16381
- const content = readFileSync7(filePath, "utf-8");
16608
+ const content = readFileSync8(filePath, "utf-8");
16382
16609
  const data = JSON.parse(content);
16383
16610
  return new Set(data.injectedPaths);
16384
16611
  } catch {
@@ -16386,19 +16613,19 @@ function loadInjectedPaths(sessionID) {
16386
16613
  }
16387
16614
  }
16388
16615
  function saveInjectedPaths(sessionID, paths) {
16389
- if (!existsSync13(AGENTS_INJECTOR_STORAGE)) {
16390
- mkdirSync4(AGENTS_INJECTOR_STORAGE, { recursive: true });
16616
+ if (!existsSync15(AGENTS_INJECTOR_STORAGE)) {
16617
+ mkdirSync5(AGENTS_INJECTOR_STORAGE, { recursive: true });
16391
16618
  }
16392
16619
  const data = {
16393
16620
  sessionID,
16394
16621
  injectedPaths: [...paths],
16395
16622
  updatedAt: Date.now()
16396
16623
  };
16397
- writeFileSync4(getStoragePath(sessionID), JSON.stringify(data, null, 2));
16624
+ writeFileSync5(getStoragePath(sessionID), JSON.stringify(data, null, 2));
16398
16625
  }
16399
16626
  function clearInjectedPaths(sessionID) {
16400
16627
  const filePath = getStoragePath(sessionID);
16401
- if (existsSync13(filePath)) {
16628
+ if (existsSync15(filePath)) {
16402
16629
  unlinkSync3(filePath);
16403
16630
  }
16404
16631
  }
@@ -16428,8 +16655,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
16428
16655
  while (true) {
16429
16656
  const isRootDir = current === ctx.directory;
16430
16657
  if (!isRootDir) {
16431
- const agentsPath = join18(current, AGENTS_FILENAME);
16432
- if (existsSync14(agentsPath)) {
16658
+ const agentsPath = join19(current, AGENTS_FILENAME);
16659
+ if (existsSync16(agentsPath)) {
16433
16660
  found.push(agentsPath);
16434
16661
  }
16435
16662
  }
@@ -16456,7 +16683,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
16456
16683
  if (cache.has(agentsDir))
16457
16684
  continue;
16458
16685
  try {
16459
- const content = readFileSync8(agentsPath, "utf-8");
16686
+ const content = readFileSync9(agentsPath, "utf-8");
16460
16687
  const { result, truncated } = await truncator.truncate(sessionID, content);
16461
16688
  const truncationNotice = truncated ? `
16462
16689
 
@@ -16526,36 +16753,36 @@ ${result}${truncationNotice}`;
16526
16753
  };
16527
16754
  }
16528
16755
  // src/hooks/directory-readme-injector/index.ts
16529
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "fs";
16530
- import { dirname as dirname3, join as join21, resolve as resolve4 } from "path";
16756
+ import { existsSync as existsSync18, readFileSync as readFileSync11 } from "fs";
16757
+ import { dirname as dirname3, join as join22, resolve as resolve4 } from "path";
16531
16758
 
16532
16759
  // src/hooks/directory-readme-injector/storage.ts
16533
16760
  import {
16534
- existsSync as existsSync15,
16535
- mkdirSync as mkdirSync5,
16536
- readFileSync as readFileSync9,
16537
- writeFileSync as writeFileSync5,
16761
+ existsSync as existsSync17,
16762
+ mkdirSync as mkdirSync6,
16763
+ readFileSync as readFileSync10,
16764
+ writeFileSync as writeFileSync6,
16538
16765
  unlinkSync as unlinkSync4
16539
16766
  } from "fs";
16540
- import { join as join20 } from "path";
16767
+ import { join as join21 } from "path";
16541
16768
 
16542
16769
  // src/hooks/directory-readme-injector/constants.ts
16543
16770
  init_data_path();
16544
- import { join as join19 } from "path";
16771
+ import { join as join20 } from "path";
16545
16772
  var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
16546
- var README_INJECTOR_STORAGE = join19(OPENCODE_STORAGE4, "directory-readme");
16773
+ var README_INJECTOR_STORAGE = join20(OPENCODE_STORAGE4, "directory-readme");
16547
16774
  var README_FILENAME = "README.md";
16548
16775
 
16549
16776
  // src/hooks/directory-readme-injector/storage.ts
16550
16777
  function getStoragePath2(sessionID) {
16551
- return join20(README_INJECTOR_STORAGE, `${sessionID}.json`);
16778
+ return join21(README_INJECTOR_STORAGE, `${sessionID}.json`);
16552
16779
  }
16553
16780
  function loadInjectedPaths2(sessionID) {
16554
16781
  const filePath = getStoragePath2(sessionID);
16555
- if (!existsSync15(filePath))
16782
+ if (!existsSync17(filePath))
16556
16783
  return new Set;
16557
16784
  try {
16558
- const content = readFileSync9(filePath, "utf-8");
16785
+ const content = readFileSync10(filePath, "utf-8");
16559
16786
  const data = JSON.parse(content);
16560
16787
  return new Set(data.injectedPaths);
16561
16788
  } catch {
@@ -16563,19 +16790,19 @@ function loadInjectedPaths2(sessionID) {
16563
16790
  }
16564
16791
  }
16565
16792
  function saveInjectedPaths2(sessionID, paths) {
16566
- if (!existsSync15(README_INJECTOR_STORAGE)) {
16567
- mkdirSync5(README_INJECTOR_STORAGE, { recursive: true });
16793
+ if (!existsSync17(README_INJECTOR_STORAGE)) {
16794
+ mkdirSync6(README_INJECTOR_STORAGE, { recursive: true });
16568
16795
  }
16569
16796
  const data = {
16570
16797
  sessionID,
16571
16798
  injectedPaths: [...paths],
16572
16799
  updatedAt: Date.now()
16573
16800
  };
16574
- writeFileSync5(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
16801
+ writeFileSync6(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
16575
16802
  }
16576
16803
  function clearInjectedPaths2(sessionID) {
16577
16804
  const filePath = getStoragePath2(sessionID);
16578
- if (existsSync15(filePath)) {
16805
+ if (existsSync17(filePath)) {
16579
16806
  unlinkSync4(filePath);
16580
16807
  }
16581
16808
  }
@@ -16603,8 +16830,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
16603
16830
  const found = [];
16604
16831
  let current = startDir;
16605
16832
  while (true) {
16606
- const readmePath = join21(current, README_FILENAME);
16607
- if (existsSync16(readmePath)) {
16833
+ const readmePath = join22(current, README_FILENAME);
16834
+ if (existsSync18(readmePath)) {
16608
16835
  found.push(readmePath);
16609
16836
  }
16610
16837
  if (current === ctx.directory)
@@ -16630,7 +16857,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
16630
16857
  if (cache.has(readmeDir))
16631
16858
  continue;
16632
16859
  try {
16633
- const content = readFileSync10(readmePath, "utf-8");
16860
+ const content = readFileSync11(readmePath, "utf-8");
16634
16861
  const { result, truncated } = await truncator.truncate(sessionID, content);
16635
16862
  const truncationNotice = truncated ? `
16636
16863
 
@@ -16914,22 +17141,22 @@ var TRUNCATE_CONFIG = {
16914
17141
 
16915
17142
  // src/hooks/anthropic-context-window-limit-recovery/storage.ts
16916
17143
  init_data_path();
16917
- import { existsSync as existsSync17, readdirSync as readdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
16918
- import { join as join22 } from "path";
17144
+ import { existsSync as existsSync19, readdirSync as readdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
17145
+ import { join as join23 } from "path";
16919
17146
  var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
16920
- var MESSAGE_STORAGE3 = join22(OPENCODE_STORAGE5, "message");
16921
- var PART_STORAGE3 = join22(OPENCODE_STORAGE5, "part");
17147
+ var MESSAGE_STORAGE3 = join23(OPENCODE_STORAGE5, "message");
17148
+ var PART_STORAGE3 = join23(OPENCODE_STORAGE5, "part");
16922
17149
  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.]";
16923
17150
  function getMessageDir3(sessionID) {
16924
- if (!existsSync17(MESSAGE_STORAGE3))
17151
+ if (!existsSync19(MESSAGE_STORAGE3))
16925
17152
  return "";
16926
- const directPath = join22(MESSAGE_STORAGE3, sessionID);
16927
- if (existsSync17(directPath)) {
17153
+ const directPath = join23(MESSAGE_STORAGE3, sessionID);
17154
+ if (existsSync19(directPath)) {
16928
17155
  return directPath;
16929
17156
  }
16930
- for (const dir of readdirSync4(MESSAGE_STORAGE3)) {
16931
- const sessionPath = join22(MESSAGE_STORAGE3, dir, sessionID);
16932
- if (existsSync17(sessionPath)) {
17157
+ for (const dir of readdirSync5(MESSAGE_STORAGE3)) {
17158
+ const sessionPath = join23(MESSAGE_STORAGE3, dir, sessionID);
17159
+ if (existsSync19(sessionPath)) {
16933
17160
  return sessionPath;
16934
17161
  }
16935
17162
  }
@@ -16937,10 +17164,10 @@ function getMessageDir3(sessionID) {
16937
17164
  }
16938
17165
  function getMessageIds(sessionID) {
16939
17166
  const messageDir = getMessageDir3(sessionID);
16940
- if (!messageDir || !existsSync17(messageDir))
17167
+ if (!messageDir || !existsSync19(messageDir))
16941
17168
  return [];
16942
17169
  const messageIds = [];
16943
- for (const file of readdirSync4(messageDir)) {
17170
+ for (const file of readdirSync5(messageDir)) {
16944
17171
  if (!file.endsWith(".json"))
16945
17172
  continue;
16946
17173
  const messageId = file.replace(".json", "");
@@ -16952,15 +17179,15 @@ function findToolResultsBySize(sessionID) {
16952
17179
  const messageIds = getMessageIds(sessionID);
16953
17180
  const results = [];
16954
17181
  for (const messageID of messageIds) {
16955
- const partDir = join22(PART_STORAGE3, messageID);
16956
- if (!existsSync17(partDir))
17182
+ const partDir = join23(PART_STORAGE3, messageID);
17183
+ if (!existsSync19(partDir))
16957
17184
  continue;
16958
- for (const file of readdirSync4(partDir)) {
17185
+ for (const file of readdirSync5(partDir)) {
16959
17186
  if (!file.endsWith(".json"))
16960
17187
  continue;
16961
17188
  try {
16962
- const partPath = join22(partDir, file);
16963
- const content = readFileSync11(partPath, "utf-8");
17189
+ const partPath = join23(partDir, file);
17190
+ const content = readFileSync12(partPath, "utf-8");
16964
17191
  const part = JSON.parse(content);
16965
17192
  if (part.type === "tool" && part.state?.output && !part.truncated) {
16966
17193
  results.push({
@@ -16980,7 +17207,7 @@ function findToolResultsBySize(sessionID) {
16980
17207
  }
16981
17208
  function truncateToolResult(partPath) {
16982
17209
  try {
16983
- const content = readFileSync11(partPath, "utf-8");
17210
+ const content = readFileSync12(partPath, "utf-8");
16984
17211
  const part = JSON.parse(content);
16985
17212
  if (!part.state?.output) {
16986
17213
  return { success: false };
@@ -16994,7 +17221,7 @@ function truncateToolResult(partPath) {
16994
17221
  part.state.time = { start: Date.now() };
16995
17222
  }
16996
17223
  part.state.time.compacted = Date.now();
16997
- writeFileSync6(partPath, JSON.stringify(part, null, 2));
17224
+ writeFileSync7(partPath, JSON.stringify(part, null, 2));
16998
17225
  return { success: true, toolName, originalSize };
16999
17226
  } catch {
17000
17227
  return { success: false };
@@ -17494,15 +17721,29 @@ function createCompactionContextInjector() {
17494
17721
  }
17495
17722
  // src/hooks/think-mode/detector.ts
17496
17723
  var ENGLISH_PATTERNS = [/\bultrathink\b/i, /\bthink\b/i];
17497
- var MULTILINGUAL_KEYWORDS = [
17724
+ var CHINESE_KEYWORDS = [
17725
+ "\u601D\u8003",
17726
+ "\u8003\u8651",
17727
+ "\u8003\u616E",
17728
+ "\u6DF1\u5165\u601D\u8003",
17729
+ "\u4ED4\u7EC6\u60F3\u60F3",
17730
+ "\u4ED4\u7EC6\u601D\u8003",
17731
+ "\u8BA4\u771F\u601D\u8003",
17732
+ "\u597D\u597D\u60F3\u60F3",
17733
+ "\u597D\u597D\u8003\u8651",
17734
+ "\u7422\u78E8",
17735
+ "\u5206\u6790\u4E00\u4E0B",
17736
+ "\u53CD\u601D",
17737
+ "\u63A8\u6572",
17738
+ "\u659F\u914C",
17739
+ "\u6DF1\u601D\u719F\u8651",
17740
+ "\u60F3\u4E00\u60F3"
17741
+ ];
17742
+ var OTHER_MULTILINGUAL_KEYWORDS = [
17498
17743
  "\uC0DD\uAC01",
17499
17744
  "\uACE0\uBBFC",
17500
17745
  "\uAC80\uD1A0",
17501
17746
  "\uC81C\uB300\uB85C",
17502
- "\u601D\u8003",
17503
- "\u8003\u8651",
17504
- "\u8003\u616E",
17505
- "\u601D\u8003",
17506
17747
  "\u8003\u3048",
17507
17748
  "\u719F\u8003",
17508
17749
  "\u0938\u094B\u091A",
@@ -17580,8 +17821,9 @@ var MULTILINGUAL_KEYWORDS = [
17580
17821
  "fikir",
17581
17822
  "berfikir"
17582
17823
  ];
17583
- var MULTILINGUAL_PATTERNS = MULTILINGUAL_KEYWORDS.map((kw) => new RegExp(kw, "i"));
17584
- var THINK_PATTERNS = [...ENGLISH_PATTERNS, ...MULTILINGUAL_PATTERNS];
17824
+ var CHINESE_PATTERNS = CHINESE_KEYWORDS.map((kw) => new RegExp(kw, "i"));
17825
+ var MULTILINGUAL_PATTERNS = OTHER_MULTILINGUAL_KEYWORDS.map((kw) => new RegExp(kw, "i"));
17826
+ var THINK_PATTERNS = [...ENGLISH_PATTERNS, ...CHINESE_PATTERNS, ...MULTILINGUAL_PATTERNS];
17585
17827
  var CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
17586
17828
  var INLINE_CODE_PATTERN = /`[^`]+`/g;
17587
17829
  function removeCodeBlocks(text) {
@@ -17729,53 +17971,55 @@ init_shared();
17729
17971
  var thinkModeState = new Map;
17730
17972
  function createThinkModeHook() {
17731
17973
  return {
17732
- "chat.params": async (output, sessionID) => {
17733
- const promptText = extractPromptText(output.parts);
17974
+ "chat.params": async (input, output) => {
17975
+ const promptText = extractPromptText(input.message.parts ?? []);
17734
17976
  const state2 = {
17735
17977
  requested: false,
17736
17978
  modelSwitched: false,
17737
17979
  thinkingConfigInjected: false
17738
17980
  };
17739
17981
  if (!detectThinkKeyword(promptText)) {
17740
- thinkModeState.set(sessionID, state2);
17982
+ thinkModeState.set(input.sessionID, state2);
17741
17983
  return;
17742
17984
  }
17743
17985
  state2.requested = true;
17744
- const currentModel = output.message.model;
17745
- if (!currentModel) {
17746
- thinkModeState.set(sessionID, state2);
17986
+ const modelID = input.model.id;
17987
+ const providerID = input.model.providerID;
17988
+ if (!modelID) {
17989
+ thinkModeState.set(input.sessionID, state2);
17747
17990
  return;
17748
17991
  }
17749
- state2.providerID = currentModel.providerID;
17750
- state2.modelID = currentModel.modelID;
17751
- if (isAlreadyHighVariant(currentModel.modelID)) {
17752
- thinkModeState.set(sessionID, state2);
17992
+ state2.providerID = providerID;
17993
+ state2.modelID = modelID;
17994
+ if (isAlreadyHighVariant(modelID)) {
17995
+ thinkModeState.set(input.sessionID, state2);
17753
17996
  return;
17754
17997
  }
17755
- const highVariant = getHighVariant(currentModel.modelID);
17756
- const thinkingConfig = getThinkingConfig(currentModel.providerID, currentModel.modelID);
17998
+ const highVariant = getHighVariant(modelID);
17999
+ const thinkingConfig = getThinkingConfig(providerID, modelID);
17757
18000
  if (highVariant) {
17758
- output.message.model = {
17759
- providerID: currentModel.providerID,
17760
- modelID: highVariant
17761
- };
18001
+ input.model.id = highVariant;
17762
18002
  state2.modelSwitched = true;
17763
18003
  log("Think mode: model switched to high variant", {
17764
- sessionID,
17765
- from: currentModel.modelID,
18004
+ sessionID: input.sessionID,
18005
+ from: modelID,
17766
18006
  to: highVariant
17767
18007
  });
17768
18008
  }
17769
18009
  if (thinkingConfig) {
17770
- Object.assign(output.message, thinkingConfig);
18010
+ const { maxTokens, ...thinkingOptions } = thinkingConfig;
18011
+ if (typeof maxTokens === "number") {
18012
+ output.maxOutputTokens = maxTokens;
18013
+ }
18014
+ Object.assign(output.options, thinkingOptions);
17771
18015
  state2.thinkingConfigInjected = true;
17772
18016
  log("Think mode: thinking config injected", {
17773
- sessionID,
17774
- provider: currentModel.providerID,
18017
+ sessionID: input.sessionID,
18018
+ provider: providerID,
17775
18019
  config: thinkingConfig
17776
18020
  });
17777
18021
  }
17778
- thinkModeState.set(sessionID, state2);
18022
+ thinkModeState.set(input.sessionID, state2);
17779
18023
  },
17780
18024
  event: async ({ event }) => {
17781
18025
  if (event.type === "session.deleted") {
@@ -17789,8 +18033,8 @@ function createThinkModeHook() {
17789
18033
  }
17790
18034
  // src/hooks/claude-code-hooks/config.ts
17791
18035
  init_shared();
17792
- import { join as join23 } from "path";
17793
- import { existsSync as existsSync18 } from "fs";
18036
+ import { join as join24 } from "path";
18037
+ import { existsSync as existsSync20 } from "fs";
17794
18038
  function normalizeHookMatcher(raw) {
17795
18039
  return {
17796
18040
  matcher: raw.matcher ?? raw.pattern ?? "*",
@@ -17816,11 +18060,11 @@ function normalizeHooksConfig(raw) {
17816
18060
  function getClaudeSettingsPaths(customPath) {
17817
18061
  const claudeConfigDir = getClaudeConfigDir();
17818
18062
  const paths = [
17819
- join23(claudeConfigDir, "settings.json"),
17820
- join23(process.cwd(), ".claude", "settings.json"),
17821
- join23(process.cwd(), ".claude", "settings.local.json")
18063
+ join24(claudeConfigDir, "settings.json"),
18064
+ join24(process.cwd(), ".claude", "settings.json"),
18065
+ join24(process.cwd(), ".claude", "settings.local.json")
17822
18066
  ];
17823
- if (customPath && existsSync18(customPath)) {
18067
+ if (customPath && existsSync20(customPath)) {
17824
18068
  paths.unshift(customPath);
17825
18069
  }
17826
18070
  return paths;
@@ -17845,7 +18089,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
17845
18089
  const paths = getClaudeSettingsPaths(customSettingsPath);
17846
18090
  let mergedConfig = {};
17847
18091
  for (const settingsPath of paths) {
17848
- if (existsSync18(settingsPath)) {
18092
+ if (existsSync20(settingsPath)) {
17849
18093
  try {
17850
18094
  const content = await Bun.file(settingsPath).text();
17851
18095
  const settings = JSON.parse(content);
@@ -17864,14 +18108,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
17864
18108
  // src/hooks/claude-code-hooks/config-loader.ts
17865
18109
  init_logger();
17866
18110
  init_shared();
17867
- import { existsSync as existsSync19 } from "fs";
17868
- import { join as join24 } from "path";
17869
- var USER_CONFIG_PATH = join24(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
18111
+ import { existsSync as existsSync21 } from "fs";
18112
+ import { join as join25 } from "path";
18113
+ var USER_CONFIG_PATH = join25(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
17870
18114
  function getProjectConfigPath() {
17871
- return join24(process.cwd(), ".opencode", "opencode-cc-plugin.json");
18115
+ return join25(process.cwd(), ".opencode", "opencode-cc-plugin.json");
17872
18116
  }
17873
18117
  async function loadConfigFromPath(path4) {
17874
- if (!existsSync19(path4)) {
18118
+ if (!existsSync21(path4)) {
17875
18119
  return null;
17876
18120
  }
17877
18121
  try {
@@ -18059,17 +18303,17 @@ init_shared();
18059
18303
  // src/hooks/claude-code-hooks/transcript.ts
18060
18304
  init_tool_name();
18061
18305
  init_shared();
18062
- import { join as join25 } from "path";
18063
- import { mkdirSync as mkdirSync6, appendFileSync as appendFileSync5, existsSync as existsSync20, writeFileSync as writeFileSync7, unlinkSync as unlinkSync5 } from "fs";
18064
- import { tmpdir as tmpdir5 } from "os";
18306
+ import { join as join26 } from "path";
18307
+ import { mkdirSync as mkdirSync7, appendFileSync as appendFileSync6, existsSync as existsSync22, writeFileSync as writeFileSync8, unlinkSync as unlinkSync5 } from "fs";
18308
+ import { tmpdir as tmpdir6 } from "os";
18065
18309
  import { randomUUID } from "crypto";
18066
- var TRANSCRIPT_DIR = join25(getClaudeConfigDir(), "transcripts");
18310
+ var TRANSCRIPT_DIR = join26(getClaudeConfigDir(), "transcripts");
18067
18311
  function getTranscriptPath(sessionId) {
18068
- return join25(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
18312
+ return join26(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
18069
18313
  }
18070
18314
  function ensureTranscriptDir() {
18071
- if (!existsSync20(TRANSCRIPT_DIR)) {
18072
- mkdirSync6(TRANSCRIPT_DIR, { recursive: true });
18315
+ if (!existsSync22(TRANSCRIPT_DIR)) {
18316
+ mkdirSync7(TRANSCRIPT_DIR, { recursive: true });
18073
18317
  }
18074
18318
  }
18075
18319
  function appendTranscriptEntry(sessionId, entry) {
@@ -18077,7 +18321,7 @@ function appendTranscriptEntry(sessionId, entry) {
18077
18321
  const path4 = getTranscriptPath(sessionId);
18078
18322
  const line = JSON.stringify(entry) + `
18079
18323
  `;
18080
- appendFileSync5(path4, line);
18324
+ appendFileSync6(path4, line);
18081
18325
  }
18082
18326
  function recordToolUse(sessionId, toolName, toolInput) {
18083
18327
  appendTranscriptEntry(sessionId, {
@@ -18155,8 +18399,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
18155
18399
  }
18156
18400
  };
18157
18401
  entries.push(JSON.stringify(currentEntry));
18158
- const tempPath = join25(tmpdir5(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
18159
- writeFileSync7(tempPath, entries.join(`
18402
+ const tempPath = join26(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
18403
+ writeFileSync8(tempPath, entries.join(`
18160
18404
  `) + `
18161
18405
  `);
18162
18406
  return tempPath;
@@ -18175,8 +18419,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
18175
18419
  ]
18176
18420
  }
18177
18421
  };
18178
- const tempPath = join25(tmpdir5(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
18179
- writeFileSync7(tempPath, JSON.stringify(currentEntry) + `
18422
+ const tempPath = join26(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
18423
+ writeFileSync8(tempPath, JSON.stringify(currentEntry) + `
18180
18424
  `);
18181
18425
  return tempPath;
18182
18426
  } catch {
@@ -18391,11 +18635,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
18391
18635
  init_shared();
18392
18636
 
18393
18637
  // src/hooks/claude-code-hooks/todo.ts
18394
- import { join as join26 } from "path";
18638
+ import { join as join27 } from "path";
18395
18639
  init_shared();
18396
- var TODO_DIR = join26(getClaudeConfigDir(), "todos");
18640
+ var TODO_DIR = join27(getClaudeConfigDir(), "todos");
18397
18641
  function getTodoPath(sessionId) {
18398
- return join26(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
18642
+ return join27(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
18399
18643
  }
18400
18644
 
18401
18645
  // src/hooks/claude-code-hooks/stop.ts
@@ -18837,24 +19081,24 @@ ${result.message}`;
18837
19081
  };
18838
19082
  }
18839
19083
  // src/hooks/rules-injector/index.ts
18840
- import { readFileSync as readFileSync13 } from "fs";
19084
+ import { readFileSync as readFileSync14 } from "fs";
18841
19085
  import { homedir as homedir8 } from "os";
18842
- import { relative as relative3, resolve as resolve5 } from "path";
19086
+ import { relative as relative4, resolve as resolve5 } from "path";
18843
19087
 
18844
19088
  // src/hooks/rules-injector/finder.ts
18845
19089
  import {
18846
- existsSync as existsSync21,
18847
- readdirSync as readdirSync5,
19090
+ existsSync as existsSync23,
19091
+ readdirSync as readdirSync6,
18848
19092
  realpathSync,
18849
19093
  statSync as statSync2
18850
19094
  } from "fs";
18851
- import { dirname as dirname4, join as join28, relative } from "path";
19095
+ import { dirname as dirname4, join as join29, relative as relative2 } from "path";
18852
19096
 
18853
19097
  // src/hooks/rules-injector/constants.ts
18854
19098
  init_data_path();
18855
- import { join as join27 } from "path";
19099
+ import { join as join28 } from "path";
18856
19100
  var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
18857
- var RULES_INJECTOR_STORAGE = join27(OPENCODE_STORAGE6, "rules-injector");
19101
+ var RULES_INJECTOR_STORAGE = join28(OPENCODE_STORAGE6, "rules-injector");
18858
19102
  var PROJECT_MARKERS = [
18859
19103
  ".git",
18860
19104
  "pyproject.toml",
@@ -18895,8 +19139,8 @@ function findProjectRoot(startPath) {
18895
19139
  }
18896
19140
  while (true) {
18897
19141
  for (const marker of PROJECT_MARKERS) {
18898
- const markerPath = join28(current, marker);
18899
- if (existsSync21(markerPath)) {
19142
+ const markerPath = join29(current, marker);
19143
+ if (existsSync23(markerPath)) {
18900
19144
  return current;
18901
19145
  }
18902
19146
  }
@@ -18908,12 +19152,12 @@ function findProjectRoot(startPath) {
18908
19152
  }
18909
19153
  }
18910
19154
  function findRuleFilesRecursive(dir, results) {
18911
- if (!existsSync21(dir))
19155
+ if (!existsSync23(dir))
18912
19156
  return;
18913
19157
  try {
18914
- const entries = readdirSync5(dir, { withFileTypes: true });
19158
+ const entries = readdirSync6(dir, { withFileTypes: true });
18915
19159
  for (const entry of entries) {
18916
- const fullPath = join28(dir, entry.name);
19160
+ const fullPath = join29(dir, entry.name);
18917
19161
  if (entry.isDirectory()) {
18918
19162
  findRuleFilesRecursive(fullPath, results);
18919
19163
  } else if (entry.isFile()) {
@@ -18938,7 +19182,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
18938
19182
  let distance = 0;
18939
19183
  while (true) {
18940
19184
  for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
18941
- const ruleDir = join28(currentDir, parent, subdir);
19185
+ const ruleDir = join29(currentDir, parent, subdir);
18942
19186
  const files = [];
18943
19187
  findRuleFilesRecursive(ruleDir, files);
18944
19188
  for (const filePath of files) {
@@ -18964,8 +19208,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
18964
19208
  }
18965
19209
  if (projectRoot) {
18966
19210
  for (const ruleFile of PROJECT_RULE_FILES) {
18967
- const filePath = join28(projectRoot, ruleFile);
18968
- if (existsSync21(filePath)) {
19211
+ const filePath = join29(projectRoot, ruleFile);
19212
+ if (existsSync23(filePath)) {
18969
19213
  try {
18970
19214
  const stat = statSync2(filePath);
18971
19215
  if (stat.isFile()) {
@@ -18985,7 +19229,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
18985
19229
  }
18986
19230
  }
18987
19231
  }
18988
- const userRuleDir = join28(homeDir, USER_RULE_DIR);
19232
+ const userRuleDir = join29(homeDir, USER_RULE_DIR);
18989
19233
  const userFiles = [];
18990
19234
  findRuleFilesRecursive(userRuleDir, userFiles);
18991
19235
  for (const filePath of userFiles) {
@@ -19012,7 +19256,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
19012
19256
  // src/hooks/rules-injector/matcher.ts
19013
19257
  var import_picomatch = __toESM(require_picomatch2(), 1);
19014
19258
  import { createHash } from "crypto";
19015
- import { relative as relative2 } from "path";
19259
+ import { relative as relative3 } from "path";
19016
19260
  function shouldApplyRule(metadata, currentFilePath, projectRoot) {
19017
19261
  if (metadata.alwaysApply === true) {
19018
19262
  return { applies: true, reason: "alwaysApply" };
@@ -19025,7 +19269,7 @@ function shouldApplyRule(metadata, currentFilePath, projectRoot) {
19025
19269
  if (patterns.length === 0) {
19026
19270
  return { applies: false };
19027
19271
  }
19028
- const relativePath = projectRoot ? relative2(projectRoot, currentFilePath) : currentFilePath;
19272
+ const relativePath = projectRoot ? relative3(projectRoot, currentFilePath) : currentFilePath;
19029
19273
  for (const pattern of patterns) {
19030
19274
  if (import_picomatch.default.isMatch(relativePath, pattern, { dot: true, bash: true })) {
19031
19275
  return { applies: true, reason: `glob: ${pattern}` };
@@ -19174,22 +19418,22 @@ function mergeGlobs(existing, newValue) {
19174
19418
 
19175
19419
  // src/hooks/rules-injector/storage.ts
19176
19420
  import {
19177
- existsSync as existsSync22,
19178
- mkdirSync as mkdirSync7,
19179
- readFileSync as readFileSync12,
19180
- writeFileSync as writeFileSync8,
19421
+ existsSync as existsSync24,
19422
+ mkdirSync as mkdirSync8,
19423
+ readFileSync as readFileSync13,
19424
+ writeFileSync as writeFileSync9,
19181
19425
  unlinkSync as unlinkSync6
19182
19426
  } from "fs";
19183
- import { join as join29 } from "path";
19427
+ import { join as join30 } from "path";
19184
19428
  function getStoragePath3(sessionID) {
19185
- return join29(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
19429
+ return join30(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
19186
19430
  }
19187
19431
  function loadInjectedRules(sessionID) {
19188
19432
  const filePath = getStoragePath3(sessionID);
19189
- if (!existsSync22(filePath))
19433
+ if (!existsSync24(filePath))
19190
19434
  return { contentHashes: new Set, realPaths: new Set };
19191
19435
  try {
19192
- const content = readFileSync12(filePath, "utf-8");
19436
+ const content = readFileSync13(filePath, "utf-8");
19193
19437
  const data = JSON.parse(content);
19194
19438
  return {
19195
19439
  contentHashes: new Set(data.injectedHashes),
@@ -19200,8 +19444,8 @@ function loadInjectedRules(sessionID) {
19200
19444
  }
19201
19445
  }
19202
19446
  function saveInjectedRules(sessionID, data) {
19203
- if (!existsSync22(RULES_INJECTOR_STORAGE)) {
19204
- mkdirSync7(RULES_INJECTOR_STORAGE, { recursive: true });
19447
+ if (!existsSync24(RULES_INJECTOR_STORAGE)) {
19448
+ mkdirSync8(RULES_INJECTOR_STORAGE, { recursive: true });
19205
19449
  }
19206
19450
  const storageData = {
19207
19451
  sessionID,
@@ -19209,11 +19453,11 @@ function saveInjectedRules(sessionID, data) {
19209
19453
  injectedRealPaths: [...data.realPaths],
19210
19454
  updatedAt: Date.now()
19211
19455
  };
19212
- writeFileSync8(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
19456
+ writeFileSync9(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
19213
19457
  }
19214
19458
  function clearInjectedRules(sessionID) {
19215
19459
  const filePath = getStoragePath3(sessionID);
19216
- if (existsSync22(filePath)) {
19460
+ if (existsSync24(filePath)) {
19217
19461
  unlinkSync6(filePath);
19218
19462
  }
19219
19463
  }
@@ -19251,7 +19495,7 @@ function createRulesInjectorHook(ctx) {
19251
19495
  if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
19252
19496
  continue;
19253
19497
  try {
19254
- const rawContent = readFileSync13(candidate.path, "utf-8");
19498
+ const rawContent = readFileSync14(candidate.path, "utf-8");
19255
19499
  const { metadata, body } = parseRuleFrontmatter(rawContent);
19256
19500
  let matchReason;
19257
19501
  if (candidate.isSingleFile) {
@@ -19265,7 +19509,7 @@ function createRulesInjectorHook(ctx) {
19265
19509
  const contentHash = createContentHash(body);
19266
19510
  if (isDuplicateByContentHash(contentHash, cache2.contentHashes))
19267
19511
  continue;
19268
- const relativePath = projectRoot ? relative3(projectRoot, candidate.path) : candidate.path;
19512
+ const relativePath = projectRoot ? relative4(projectRoot, candidate.path) : candidate.path;
19269
19513
  toInject.push({
19270
19514
  relativePath,
19271
19515
  matchReason,
@@ -19369,19 +19613,19 @@ init_auto_update_checker();
19369
19613
 
19370
19614
  // src/hooks/agent-usage-reminder/storage.ts
19371
19615
  import {
19372
- existsSync as existsSync25,
19373
- mkdirSync as mkdirSync8,
19374
- readFileSync as readFileSync16,
19375
- writeFileSync as writeFileSync11,
19616
+ existsSync as existsSync27,
19617
+ mkdirSync as mkdirSync9,
19618
+ readFileSync as readFileSync17,
19619
+ writeFileSync as writeFileSync12,
19376
19620
  unlinkSync as unlinkSync7
19377
19621
  } from "fs";
19378
- import { join as join34 } from "path";
19622
+ import { join as join35 } from "path";
19379
19623
 
19380
19624
  // src/hooks/agent-usage-reminder/constants.ts
19381
19625
  init_data_path();
19382
- import { join as join33 } from "path";
19626
+ import { join as join34 } from "path";
19383
19627
  var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
19384
- var AGENT_USAGE_REMINDER_STORAGE = join33(OPENCODE_STORAGE7, "agent-usage-reminder");
19628
+ var AGENT_USAGE_REMINDER_STORAGE = join34(OPENCODE_STORAGE7, "agent-usage-reminder");
19385
19629
  var TARGET_TOOLS = new Set([
19386
19630
  "grep",
19387
19631
  "safe_grep",
@@ -19427,29 +19671,29 @@ delegate_task(agent="librarian", prompt="\u67E5\u627E Z \u7684\u6587\u6863")
19427
19671
 
19428
19672
  // src/hooks/agent-usage-reminder/storage.ts
19429
19673
  function getStoragePath4(sessionID) {
19430
- return join34(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
19674
+ return join35(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
19431
19675
  }
19432
19676
  function loadAgentUsageState(sessionID) {
19433
19677
  const filePath = getStoragePath4(sessionID);
19434
- if (!existsSync25(filePath))
19678
+ if (!existsSync27(filePath))
19435
19679
  return null;
19436
19680
  try {
19437
- const content = readFileSync16(filePath, "utf-8");
19681
+ const content = readFileSync17(filePath, "utf-8");
19438
19682
  return JSON.parse(content);
19439
19683
  } catch {
19440
19684
  return null;
19441
19685
  }
19442
19686
  }
19443
19687
  function saveAgentUsageState(state2) {
19444
- if (!existsSync25(AGENT_USAGE_REMINDER_STORAGE)) {
19445
- mkdirSync8(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
19688
+ if (!existsSync27(AGENT_USAGE_REMINDER_STORAGE)) {
19689
+ mkdirSync9(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
19446
19690
  }
19447
19691
  const filePath = getStoragePath4(state2.sessionID);
19448
- writeFileSync11(filePath, JSON.stringify(state2, null, 2));
19692
+ writeFileSync12(filePath, JSON.stringify(state2, null, 2));
19449
19693
  }
19450
19694
  function clearAgentUsageState(sessionID) {
19451
19695
  const filePath = getStoragePath4(sessionID);
19452
- if (existsSync25(filePath)) {
19696
+ if (existsSync27(filePath)) {
19453
19697
  unlinkSync7(filePath);
19454
19698
  }
19455
19699
  }
@@ -20032,19 +20276,19 @@ function createNonInteractiveEnvHook(_ctx) {
20032
20276
  }
20033
20277
  // src/hooks/interactive-bash-session/storage.ts
20034
20278
  import {
20035
- existsSync as existsSync26,
20036
- mkdirSync as mkdirSync9,
20037
- readFileSync as readFileSync17,
20038
- writeFileSync as writeFileSync12,
20279
+ existsSync as existsSync28,
20280
+ mkdirSync as mkdirSync10,
20281
+ readFileSync as readFileSync18,
20282
+ writeFileSync as writeFileSync13,
20039
20283
  unlinkSync as unlinkSync8
20040
20284
  } from "fs";
20041
- import { join as join36 } from "path";
20285
+ import { join as join37 } from "path";
20042
20286
 
20043
20287
  // src/hooks/interactive-bash-session/constants.ts
20044
20288
  init_data_path();
20045
- import { join as join35 } from "path";
20289
+ import { join as join36 } from "path";
20046
20290
  var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
20047
- var INTERACTIVE_BASH_SESSION_STORAGE = join35(OPENCODE_STORAGE8, "interactive-bash-session");
20291
+ var INTERACTIVE_BASH_SESSION_STORAGE = join36(OPENCODE_STORAGE8, "interactive-bash-session");
20048
20292
  var OMO_SESSION_PREFIX = "omo-";
20049
20293
  function buildSessionReminderMessage(sessions) {
20050
20294
  if (sessions.length === 0)
@@ -20056,14 +20300,14 @@ function buildSessionReminderMessage(sessions) {
20056
20300
 
20057
20301
  // src/hooks/interactive-bash-session/storage.ts
20058
20302
  function getStoragePath5(sessionID) {
20059
- return join36(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
20303
+ return join37(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
20060
20304
  }
20061
20305
  function loadInteractiveBashSessionState(sessionID) {
20062
20306
  const filePath = getStoragePath5(sessionID);
20063
- if (!existsSync26(filePath))
20307
+ if (!existsSync28(filePath))
20064
20308
  return null;
20065
20309
  try {
20066
- const content = readFileSync17(filePath, "utf-8");
20310
+ const content = readFileSync18(filePath, "utf-8");
20067
20311
  const serialized = JSON.parse(content);
20068
20312
  return {
20069
20313
  sessionID: serialized.sessionID,
@@ -20075,8 +20319,8 @@ function loadInteractiveBashSessionState(sessionID) {
20075
20319
  }
20076
20320
  }
20077
20321
  function saveInteractiveBashSessionState(state2) {
20078
- if (!existsSync26(INTERACTIVE_BASH_SESSION_STORAGE)) {
20079
- mkdirSync9(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
20322
+ if (!existsSync28(INTERACTIVE_BASH_SESSION_STORAGE)) {
20323
+ mkdirSync10(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
20080
20324
  }
20081
20325
  const filePath = getStoragePath5(state2.sessionID);
20082
20326
  const serialized = {
@@ -20084,11 +20328,11 @@ function saveInteractiveBashSessionState(state2) {
20084
20328
  tmuxSessions: Array.from(state2.tmuxSessions),
20085
20329
  updatedAt: state2.updatedAt
20086
20330
  };
20087
- writeFileSync12(filePath, JSON.stringify(serialized, null, 2));
20331
+ writeFileSync13(filePath, JSON.stringify(serialized, null, 2));
20088
20332
  }
20089
20333
  function clearInteractiveBashSessionState(sessionID) {
20090
20334
  const filePath = getStoragePath5(sessionID);
20091
- if (existsSync26(filePath)) {
20335
+ if (existsSync28(filePath)) {
20092
20336
  unlinkSync8(filePath);
20093
20337
  }
20094
20338
  }
@@ -20342,7 +20586,7 @@ function createThinkingBlockValidatorHook() {
20342
20586
  continue;
20343
20587
  if (hasContentParts(msg.parts) && !startsWithThinkingBlock(msg.parts)) {
20344
20588
  const previousThinking = findPreviousThinkingContent(messages, i2);
20345
- const thinkingContent = previousThinking || "[Continuing from previous reasoning]";
20589
+ const thinkingContent = previousThinking || "[\u63A5\u7EED\u4E4B\u524D\u7684\u63A8\u7406]";
20346
20590
  prependThinkingBlock(msg, thinkingContent);
20347
20591
  }
20348
20592
  }
@@ -20352,13 +20596,13 @@ function createThinkingBlockValidatorHook() {
20352
20596
  // src/hooks/ralph-loop/index.ts
20353
20597
  init_logger();
20354
20598
  init_system_directive();
20355
- import { existsSync as existsSync28, readFileSync as readFileSync19, readdirSync as readdirSync6 } from "fs";
20356
- import { join as join38 } from "path";
20599
+ import { existsSync as existsSync30, readFileSync as readFileSync20, readdirSync as readdirSync7 } from "fs";
20600
+ import { join as join39 } from "path";
20357
20601
 
20358
20602
  // src/hooks/ralph-loop/storage.ts
20359
20603
  init_frontmatter();
20360
- import { existsSync as existsSync27, readFileSync as readFileSync18, writeFileSync as writeFileSync13, unlinkSync as unlinkSync9, mkdirSync as mkdirSync10 } from "fs";
20361
- import { dirname as dirname6, join as join37 } from "path";
20604
+ import { existsSync as existsSync29, readFileSync as readFileSync19, writeFileSync as writeFileSync14, unlinkSync as unlinkSync9, mkdirSync as mkdirSync11 } from "fs";
20605
+ import { dirname as dirname6, join as join38 } from "path";
20362
20606
 
20363
20607
  // src/hooks/ralph-loop/constants.ts
20364
20608
  var HOOK_NAME3 = "ralph-loop";
@@ -20368,15 +20612,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
20368
20612
 
20369
20613
  // src/hooks/ralph-loop/storage.ts
20370
20614
  function getStateFilePath(directory, customPath) {
20371
- return customPath ? join37(directory, customPath) : join37(directory, DEFAULT_STATE_FILE);
20615
+ return customPath ? join38(directory, customPath) : join38(directory, DEFAULT_STATE_FILE);
20372
20616
  }
20373
20617
  function readState(directory, customPath) {
20374
20618
  const filePath = getStateFilePath(directory, customPath);
20375
- if (!existsSync27(filePath)) {
20619
+ if (!existsSync29(filePath)) {
20376
20620
  return null;
20377
20621
  }
20378
20622
  try {
20379
- const content = readFileSync18(filePath, "utf-8");
20623
+ const content = readFileSync19(filePath, "utf-8");
20380
20624
  const { data, body } = parseFrontmatter(content);
20381
20625
  const active = data.active;
20382
20626
  const iteration = data.iteration;
@@ -20410,8 +20654,8 @@ function writeState(directory, state2, customPath) {
20410
20654
  const filePath = getStateFilePath(directory, customPath);
20411
20655
  try {
20412
20656
  const dir = dirname6(filePath);
20413
- if (!existsSync27(dir)) {
20414
- mkdirSync10(dir, { recursive: true });
20657
+ if (!existsSync29(dir)) {
20658
+ mkdirSync11(dir, { recursive: true });
20415
20659
  }
20416
20660
  const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
20417
20661
  ` : "";
@@ -20426,7 +20670,7 @@ started_at: "${state2.started_at}"
20426
20670
  ${sessionIdLine}${ultraworkLine}---
20427
20671
  ${state2.prompt}
20428
20672
  `;
20429
- writeFileSync13(filePath, content, "utf-8");
20673
+ writeFileSync14(filePath, content, "utf-8");
20430
20674
  return true;
20431
20675
  } catch {
20432
20676
  return false;
@@ -20435,7 +20679,7 @@ ${state2.prompt}
20435
20679
  function clearState(directory, customPath) {
20436
20680
  const filePath = getStateFilePath(directory, customPath);
20437
20681
  try {
20438
- if (existsSync27(filePath)) {
20682
+ if (existsSync29(filePath)) {
20439
20683
  unlinkSync9(filePath);
20440
20684
  }
20441
20685
  return true;
@@ -20456,14 +20700,14 @@ function incrementIteration(directory, customPath) {
20456
20700
 
20457
20701
  // src/hooks/ralph-loop/index.ts
20458
20702
  function getMessageDir4(sessionID) {
20459
- if (!existsSync28(MESSAGE_STORAGE))
20703
+ if (!existsSync30(MESSAGE_STORAGE))
20460
20704
  return null;
20461
- const directPath = join38(MESSAGE_STORAGE, sessionID);
20462
- if (existsSync28(directPath))
20705
+ const directPath = join39(MESSAGE_STORAGE, sessionID);
20706
+ if (existsSync30(directPath))
20463
20707
  return directPath;
20464
- for (const dir of readdirSync6(MESSAGE_STORAGE)) {
20465
- const sessionPath = join38(MESSAGE_STORAGE, dir, sessionID);
20466
- if (existsSync28(sessionPath))
20708
+ for (const dir of readdirSync7(MESSAGE_STORAGE)) {
20709
+ const sessionPath = join39(MESSAGE_STORAGE, dir, sessionID);
20710
+ if (existsSync30(sessionPath))
20467
20711
  return sessionPath;
20468
20712
  }
20469
20713
  return null;
@@ -20500,9 +20744,9 @@ function createRalphLoopHook(ctx, options) {
20500
20744
  if (!transcriptPath)
20501
20745
  return false;
20502
20746
  try {
20503
- if (!existsSync28(transcriptPath))
20747
+ if (!existsSync30(transcriptPath))
20504
20748
  return false;
20505
- const content = readFileSync19(transcriptPath, "utf-8");
20749
+ const content = readFileSync20(transcriptPath, "utf-8");
20506
20750
  const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
20507
20751
  const lines = content.split(`
20508
20752
  `).filter((l) => l.trim());
@@ -20816,8 +21060,8 @@ function extractPromptText3(parts) {
20816
21060
  // src/hooks/auto-slash-command/executor.ts
20817
21061
  init_shared();
20818
21062
  init_file_utils();
20819
- import { existsSync as existsSync30, readdirSync as readdirSync7, readFileSync as readFileSync22 } from "fs";
20820
- import { join as join40, basename as basename2, dirname as dirname8 } from "path";
21063
+ import { existsSync as existsSync32, readdirSync as readdirSync8, readFileSync as readFileSync23 } from "fs";
21064
+ import { join as join41, basename as basename2, dirname as dirname8 } from "path";
20821
21065
  // src/features/opencode-skill-loader/loader.ts
20822
21066
  init_js_yaml();
20823
21067
  init_frontmatter();
@@ -20825,7 +21069,7 @@ init_file_utils();
20825
21069
  init_shared();
20826
21070
  init_opencode_config_dir();
20827
21071
  import { promises as fs9 } from "fs";
20828
- import { join as join39, basename } from "path";
21072
+ import { join as join40, basename } from "path";
20829
21073
  function parseSkillMcpConfigFromFrontmatter(content) {
20830
21074
  const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
20831
21075
  if (!frontmatterMatch)
@@ -20841,7 +21085,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
20841
21085
  return;
20842
21086
  }
20843
21087
  async function loadMcpJsonFromDir(skillDir) {
20844
- const mcpJsonPath = join39(skillDir, "mcp.json");
21088
+ const mcpJsonPath = join40(skillDir, "mcp.json");
20845
21089
  try {
20846
21090
  const content = await fs9.readFile(mcpJsonPath, "utf-8");
20847
21091
  const parsed = JSON.parse(content);
@@ -20922,11 +21166,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
20922
21166
  for (const entry of entries) {
20923
21167
  if (entry.name.startsWith("."))
20924
21168
  continue;
20925
- const entryPath = join39(skillsDir, entry.name);
21169
+ const entryPath = join40(skillsDir, entry.name);
20926
21170
  if (entry.isDirectory() || entry.isSymbolicLink()) {
20927
21171
  const resolvedPath = await resolveSymlinkAsync(entryPath);
20928
21172
  const dirName = entry.name;
20929
- const skillMdPath = join39(resolvedPath, "SKILL.md");
21173
+ const skillMdPath = join40(resolvedPath, "SKILL.md");
20930
21174
  try {
20931
21175
  await fs9.access(skillMdPath);
20932
21176
  const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
@@ -20934,7 +21178,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
20934
21178
  skills.push(skill);
20935
21179
  continue;
20936
21180
  } catch {}
20937
- const namedSkillMdPath = join39(resolvedPath, `${dirName}.md`);
21181
+ const namedSkillMdPath = join40(resolvedPath, `${dirName}.md`);
20938
21182
  try {
20939
21183
  await fs9.access(namedSkillMdPath);
20940
21184
  const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
@@ -20962,23 +21206,23 @@ function skillsToRecord(skills) {
20962
21206
  return result;
20963
21207
  }
20964
21208
  async function loadUserSkills() {
20965
- const userSkillsDir = join39(getClaudeConfigDir(), "skills");
21209
+ const userSkillsDir = join40(getClaudeConfigDir(), "skills");
20966
21210
  const skills = await loadSkillsFromDir(userSkillsDir, "user");
20967
21211
  return skillsToRecord(skills);
20968
21212
  }
20969
21213
  async function loadProjectSkills() {
20970
- const projectSkillsDir = join39(process.cwd(), ".claude", "skills");
21214
+ const projectSkillsDir = join40(process.cwd(), ".claude", "skills");
20971
21215
  const skills = await loadSkillsFromDir(projectSkillsDir, "project");
20972
21216
  return skillsToRecord(skills);
20973
21217
  }
20974
21218
  async function loadOpencodeGlobalSkills() {
20975
21219
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
20976
- const opencodeSkillsDir = join39(configDir, "skills");
21220
+ const opencodeSkillsDir = join40(configDir, "skills");
20977
21221
  const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
20978
21222
  return skillsToRecord(skills);
20979
21223
  }
20980
21224
  async function loadOpencodeProjectSkills() {
20981
- const opencodeProjectDir = join39(process.cwd(), ".opencode", "skills");
21225
+ const opencodeProjectDir = join40(process.cwd(), ".opencode", "skills");
20982
21226
  const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
20983
21227
  return skillsToRecord(skills);
20984
21228
  }
@@ -21007,26 +21251,26 @@ async function discoverSkills(options = {}) {
21007
21251
  return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
21008
21252
  }
21009
21253
  async function discoverUserClaudeSkills() {
21010
- const userSkillsDir = join39(getClaudeConfigDir(), "skills");
21254
+ const userSkillsDir = join40(getClaudeConfigDir(), "skills");
21011
21255
  return loadSkillsFromDir(userSkillsDir, "user");
21012
21256
  }
21013
21257
  async function discoverProjectClaudeSkills() {
21014
- const projectSkillsDir = join39(process.cwd(), ".claude", "skills");
21258
+ const projectSkillsDir = join40(process.cwd(), ".claude", "skills");
21015
21259
  return loadSkillsFromDir(projectSkillsDir, "project");
21016
21260
  }
21017
21261
  async function discoverOpencodeGlobalSkills() {
21018
21262
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
21019
- const opencodeSkillsDir = join39(configDir, "skills");
21263
+ const opencodeSkillsDir = join40(configDir, "skills");
21020
21264
  return loadSkillsFromDir(opencodeSkillsDir, "opencode");
21021
21265
  }
21022
21266
  async function discoverOpencodeProjectSkills() {
21023
- const opencodeProjectDir = join39(process.cwd(), ".opencode", "skills");
21267
+ const opencodeProjectDir = join40(process.cwd(), ".opencode", "skills");
21024
21268
  return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
21025
21269
  }
21026
21270
  // src/features/opencode-skill-loader/merger.ts
21027
21271
  init_frontmatter();
21028
21272
  init_deep_merge();
21029
- import { readFileSync as readFileSync20, existsSync as existsSync29 } from "fs";
21273
+ import { readFileSync as readFileSync21, existsSync as existsSync31 } from "fs";
21030
21274
  import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
21031
21275
  import { homedir as homedir11 } from "os";
21032
21276
  var SCOPE_PRIORITY = {
@@ -21074,9 +21318,9 @@ function resolveFilePath2(from, configDir) {
21074
21318
  }
21075
21319
  function loadSkillFromFile(filePath) {
21076
21320
  try {
21077
- if (!existsSync29(filePath))
21321
+ if (!existsSync31(filePath))
21078
21322
  return null;
21079
- const content = readFileSync20(filePath, "utf-8");
21323
+ const content = readFileSync21(filePath, "utf-8");
21080
21324
  const { data, body } = parseFrontmatter(content);
21081
21325
  return { template: body, metadata: data };
21082
21326
  } catch {
@@ -22423,7 +22667,7 @@ function createBuiltinSkills() {
22423
22667
 
22424
22668
  // src/features/opencode-skill-loader/skill-content.ts
22425
22669
  init_frontmatter();
22426
- import { readFileSync as readFileSync21 } from "fs";
22670
+ import { readFileSync as readFileSync22 } from "fs";
22427
22671
  var cachedSkills = null;
22428
22672
  async function getAllSkills() {
22429
22673
  if (cachedSkills)
@@ -22456,7 +22700,7 @@ async function getAllSkills() {
22456
22700
  }
22457
22701
  async function extractSkillTemplate(skill) {
22458
22702
  if (skill.path) {
22459
- const content = readFileSync21(skill.path, "utf-8");
22703
+ const content = readFileSync22(skill.path, "utf-8");
22460
22704
  const { body } = parseFrontmatter(content);
22461
22705
  return body.trim();
22462
22706
  }
@@ -22558,18 +22802,18 @@ async function resolveMultipleSkillsAsync(skillNames, options) {
22558
22802
  }
22559
22803
  // src/hooks/auto-slash-command/executor.ts
22560
22804
  function discoverCommandsFromDir(commandsDir, scope) {
22561
- if (!existsSync30(commandsDir)) {
22805
+ if (!existsSync32(commandsDir)) {
22562
22806
  return [];
22563
22807
  }
22564
- const entries = readdirSync7(commandsDir, { withFileTypes: true });
22808
+ const entries = readdirSync8(commandsDir, { withFileTypes: true });
22565
22809
  const commands = [];
22566
22810
  for (const entry of entries) {
22567
22811
  if (!isMarkdownFile(entry))
22568
22812
  continue;
22569
- const commandPath = join40(commandsDir, entry.name);
22813
+ const commandPath = join41(commandsDir, entry.name);
22570
22814
  const commandName = basename2(entry.name, ".md");
22571
22815
  try {
22572
- const content = readFileSync22(commandPath, "utf-8");
22816
+ const content = readFileSync23(commandPath, "utf-8");
22573
22817
  const { data, body } = parseFrontmatter(content);
22574
22818
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
22575
22819
  const metadata = {
@@ -22612,10 +22856,10 @@ function skillToCommandInfo(skill) {
22612
22856
  }
22613
22857
  async function discoverAllCommands(options) {
22614
22858
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
22615
- const userCommandsDir = join40(getClaudeConfigDir(), "commands");
22616
- const projectCommandsDir = join40(process.cwd(), ".claude", "commands");
22617
- const opencodeGlobalDir = join40(configDir, "command");
22618
- const opencodeProjectDir = join40(process.cwd(), ".opencode", "command");
22859
+ const userCommandsDir = join41(getClaudeConfigDir(), "commands");
22860
+ const projectCommandsDir = join41(process.cwd(), ".claude", "commands");
22861
+ const opencodeGlobalDir = join41(configDir, "command");
22862
+ const opencodeProjectDir = join41(process.cwd(), ".opencode", "command");
22619
22863
  const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
22620
22864
  const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
22621
22865
  const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
@@ -22785,8 +23029,8 @@ ${EDIT_ERROR_REMINDER}`;
22785
23029
  };
22786
23030
  }
22787
23031
  // src/hooks/prometheus-md-only/index.ts
22788
- import { existsSync as existsSync31, readdirSync as readdirSync8 } from "fs";
22789
- import { join as join41, resolve as resolve7, relative as relative4, isAbsolute as isAbsolute3 } from "path";
23032
+ import { existsSync as existsSync33, readdirSync as readdirSync9 } from "fs";
23033
+ import { join as join42, resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3 } from "path";
22790
23034
 
22791
23035
  // src/hooks/prometheus-md-only/constants.ts
22792
23036
  init_system_directive();
@@ -22891,7 +23135,7 @@ init_logger();
22891
23135
  init_system_directive();
22892
23136
  function isAllowedFile(filePath, workspaceRoot) {
22893
23137
  const resolved = resolve7(workspaceRoot, filePath);
22894
- const rel = relative4(workspaceRoot, resolved);
23138
+ const rel = relative5(workspaceRoot, resolved);
22895
23139
  if (rel.startsWith("..") || isAbsolute3(rel)) {
22896
23140
  return false;
22897
23141
  }
@@ -22905,14 +23149,14 @@ function isAllowedFile(filePath, workspaceRoot) {
22905
23149
  return true;
22906
23150
  }
22907
23151
  function getMessageDir5(sessionID) {
22908
- if (!existsSync31(MESSAGE_STORAGE))
23152
+ if (!existsSync33(MESSAGE_STORAGE))
22909
23153
  return null;
22910
- const directPath = join41(MESSAGE_STORAGE, sessionID);
22911
- if (existsSync31(directPath))
23154
+ const directPath = join42(MESSAGE_STORAGE, sessionID);
23155
+ if (existsSync33(directPath))
22912
23156
  return directPath;
22913
- for (const dir of readdirSync8(MESSAGE_STORAGE)) {
22914
- const sessionPath = join41(MESSAGE_STORAGE, dir, sessionID);
22915
- if (existsSync31(sessionPath))
23157
+ for (const dir of readdirSync9(MESSAGE_STORAGE)) {
23158
+ const sessionPath = join42(MESSAGE_STORAGE, dir, sessionID);
23159
+ if (existsSync33(sessionPath))
22916
23160
  return sessionPath;
22917
23161
  }
22918
23162
  return null;
@@ -23026,18 +23270,18 @@ var NOTEPAD_DIR = "notepads";
23026
23270
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
23027
23271
  var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
23028
23272
  // src/features/boulder-state/storage.ts
23029
- import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync14, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "fs";
23030
- import { dirname as dirname9, join as join42, basename as basename3 } from "path";
23273
+ import { existsSync as existsSync34, readFileSync as readFileSync24, writeFileSync as writeFileSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync10 } from "fs";
23274
+ import { dirname as dirname9, join as join43, basename as basename3 } from "path";
23031
23275
  function getBoulderFilePath(directory) {
23032
- return join42(directory, BOULDER_DIR, BOULDER_FILE);
23276
+ return join43(directory, BOULDER_DIR, BOULDER_FILE);
23033
23277
  }
23034
23278
  function readBoulderState(directory) {
23035
23279
  const filePath = getBoulderFilePath(directory);
23036
- if (!existsSync32(filePath)) {
23280
+ if (!existsSync34(filePath)) {
23037
23281
  return null;
23038
23282
  }
23039
23283
  try {
23040
- const content = readFileSync23(filePath, "utf-8");
23284
+ const content = readFileSync24(filePath, "utf-8");
23041
23285
  return JSON.parse(content);
23042
23286
  } catch {
23043
23287
  return null;
@@ -23047,10 +23291,10 @@ function writeBoulderState(directory, state2) {
23047
23291
  const filePath = getBoulderFilePath(directory);
23048
23292
  try {
23049
23293
  const dir = dirname9(filePath);
23050
- if (!existsSync32(dir)) {
23051
- mkdirSync11(dir, { recursive: true });
23294
+ if (!existsSync34(dir)) {
23295
+ mkdirSync12(dir, { recursive: true });
23052
23296
  }
23053
- writeFileSync14(filePath, JSON.stringify(state2, null, 2), "utf-8");
23297
+ writeFileSync15(filePath, JSON.stringify(state2, null, 2), "utf-8");
23054
23298
  return true;
23055
23299
  } catch {
23056
23300
  return false;
@@ -23071,7 +23315,7 @@ function appendSessionId(directory, sessionId) {
23071
23315
  function clearBoulderState(directory) {
23072
23316
  const filePath = getBoulderFilePath(directory);
23073
23317
  try {
23074
- if (existsSync32(filePath)) {
23318
+ if (existsSync34(filePath)) {
23075
23319
  const { unlinkSync: unlinkSync10 } = __require("fs");
23076
23320
  unlinkSync10(filePath);
23077
23321
  }
@@ -23081,13 +23325,13 @@ function clearBoulderState(directory) {
23081
23325
  }
23082
23326
  }
23083
23327
  function findPrometheusPlans(directory) {
23084
- const plansDir = join42(directory, PROMETHEUS_PLANS_DIR);
23085
- if (!existsSync32(plansDir)) {
23328
+ const plansDir = join43(directory, PROMETHEUS_PLANS_DIR);
23329
+ if (!existsSync34(plansDir)) {
23086
23330
  return [];
23087
23331
  }
23088
23332
  try {
23089
- const files = readdirSync9(plansDir);
23090
- return files.filter((f) => f.endsWith(".md")).map((f) => join42(plansDir, f)).sort((a, b) => {
23333
+ const files = readdirSync10(plansDir);
23334
+ return files.filter((f) => f.endsWith(".md")).map((f) => join43(plansDir, f)).sort((a, b) => {
23091
23335
  const aStat = __require("fs").statSync(a);
23092
23336
  const bStat = __require("fs").statSync(b);
23093
23337
  return bStat.mtimeMs - aStat.mtimeMs;
@@ -23097,11 +23341,11 @@ function findPrometheusPlans(directory) {
23097
23341
  }
23098
23342
  }
23099
23343
  function getPlanProgress(planPath) {
23100
- if (!existsSync32(planPath)) {
23344
+ if (!existsSync34(planPath)) {
23101
23345
  return { total: 0, completed: 0, isComplete: true };
23102
23346
  }
23103
23347
  try {
23104
- const content = readFileSync23(planPath, "utf-8");
23348
+ const content = readFileSync24(planPath, "utf-8");
23105
23349
  const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
23106
23350
  const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
23107
23351
  const total = uncheckedMatches.length + checkedMatches.length;
@@ -23318,8 +23562,8 @@ ${contextInfo}`;
23318
23562
  }
23319
23563
  // src/hooks/atlas/index.ts
23320
23564
  import { execSync } from "child_process";
23321
- import { existsSync as existsSync33, readdirSync as readdirSync10 } from "fs";
23322
- import { join as join43 } from "path";
23565
+ import { existsSync as existsSync35, readdirSync as readdirSync11 } from "fs";
23566
+ import { join as join44 } from "path";
23323
23567
  init_logger();
23324
23568
  init_system_directive();
23325
23569
  var HOOK_NAME6 = "atlas";
@@ -23648,14 +23892,14 @@ function formatFileChanges(stats, notepadPath) {
23648
23892
  `);
23649
23893
  }
23650
23894
  function getMessageDir6(sessionID) {
23651
- if (!existsSync33(MESSAGE_STORAGE))
23895
+ if (!existsSync35(MESSAGE_STORAGE))
23652
23896
  return null;
23653
- const directPath = join43(MESSAGE_STORAGE, sessionID);
23654
- if (existsSync33(directPath))
23897
+ const directPath = join44(MESSAGE_STORAGE, sessionID);
23898
+ if (existsSync35(directPath))
23655
23899
  return directPath;
23656
- for (const dir of readdirSync10(MESSAGE_STORAGE)) {
23657
- const sessionPath = join43(MESSAGE_STORAGE, dir, sessionID);
23658
- if (existsSync33(sessionPath))
23900
+ for (const dir of readdirSync11(MESSAGE_STORAGE)) {
23901
+ const sessionPath = join44(MESSAGE_STORAGE, dir, sessionID);
23902
+ if (existsSync35(sessionPath))
23659
23903
  return sessionPath;
23660
23904
  }
23661
23905
  return null;
@@ -24109,6 +24353,28 @@ function createQuestionLabelTruncatorHook() {
24109
24353
  }
24110
24354
  };
24111
24355
  }
24356
+ // src/hooks/perf-profiler/index.ts
24357
+ function createPerfProfilerHook(options) {
24358
+ return {
24359
+ event: async (input) => {
24360
+ if (input.event.type === "message.part.updated")
24361
+ return;
24362
+ const tracer = options.tracer;
24363
+ if (!tracer.isEnabled())
24364
+ return;
24365
+ const mapSizes = {};
24366
+ for (const [name, fn] of Object.entries(options.memoryProbes ?? {})) {
24367
+ try {
24368
+ mapSizes[name] = fn();
24369
+ } catch {}
24370
+ }
24371
+ tracer.snapshotMemory(input.event.type, mapSizes);
24372
+ },
24373
+ "tool.execute.before": async () => {},
24374
+ "tool.execute.after": async () => {},
24375
+ "chat.message": async () => {}
24376
+ };
24377
+ }
24112
24378
  // src/features/context-injector/collector.ts
24113
24379
  var PRIORITY_ORDER = {
24114
24380
  critical: 0,
@@ -24282,8 +24548,8 @@ function createFirstMessageVariantGate() {
24282
24548
  }
24283
24549
  // src/features/claude-code-mcp-loader/loader.ts
24284
24550
  init_shared();
24285
- import { existsSync as existsSync34, readFileSync as readFileSync24 } from "fs";
24286
- import { join as join44 } from "path";
24551
+ import { existsSync as existsSync36, readFileSync as readFileSync25 } from "fs";
24552
+ import { join as join45 } from "path";
24287
24553
 
24288
24554
  // src/features/claude-code-mcp-loader/env-expander.ts
24289
24555
  function expandEnvVars(value) {
@@ -24351,15 +24617,15 @@ function transformMcpServer(name, server) {
24351
24617
  init_logger();
24352
24618
  function getMcpConfigPaths() {
24353
24619
  const claudeConfigDir = getClaudeConfigDir();
24354
- const cwd = process.cwd();
24620
+ const cwd2 = process.cwd();
24355
24621
  return [
24356
- { path: join44(claudeConfigDir, ".mcp.json"), scope: "user" },
24357
- { path: join44(cwd, ".mcp.json"), scope: "project" },
24358
- { path: join44(cwd, ".claude", ".mcp.json"), scope: "local" }
24622
+ { path: join45(claudeConfigDir, ".mcp.json"), scope: "user" },
24623
+ { path: join45(cwd2, ".mcp.json"), scope: "project" },
24624
+ { path: join45(cwd2, ".claude", ".mcp.json"), scope: "local" }
24359
24625
  ];
24360
24626
  }
24361
24627
  async function loadMcpConfigFile(filePath) {
24362
- if (!existsSync34(filePath)) {
24628
+ if (!existsSync36(filePath)) {
24363
24629
  return null;
24364
24630
  }
24365
24631
  try {
@@ -24374,10 +24640,10 @@ function getSystemMcpServerNames() {
24374
24640
  const names = new Set;
24375
24641
  const paths = getMcpConfigPaths();
24376
24642
  for (const { path: path7 } of paths) {
24377
- if (!existsSync34(path7))
24643
+ if (!existsSync36(path7))
24378
24644
  continue;
24379
24645
  try {
24380
- const content = readFileSync24(path7, "utf-8");
24646
+ const content = readFileSync25(path7, "utf-8");
24381
24647
  const config = JSON.parse(content);
24382
24648
  if (!config?.mcpServers)
24383
24649
  continue;
@@ -24820,25 +25086,25 @@ var EXT_TO_LANG = {
24820
25086
  ".gql": "graphql"
24821
25087
  };
24822
25088
  // src/tools/lsp/config.ts
24823
- import { existsSync as existsSync35, readFileSync as readFileSync25 } from "fs";
24824
- import { join as join45 } from "path";
25089
+ import { existsSync as existsSync37, readFileSync as readFileSync26 } from "fs";
25090
+ import { join as join46 } from "path";
24825
25091
  init_shared();
24826
25092
  function loadJsonFile(path7) {
24827
- if (!existsSync35(path7))
25093
+ if (!existsSync37(path7))
24828
25094
  return null;
24829
25095
  try {
24830
- return JSON.parse(readFileSync25(path7, "utf-8"));
25096
+ return JSON.parse(readFileSync26(path7, "utf-8"));
24831
25097
  } catch {
24832
25098
  return null;
24833
25099
  }
24834
25100
  }
24835
25101
  function getConfigPaths3() {
24836
- const cwd = process.cwd();
25102
+ const cwd2 = process.cwd();
24837
25103
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
24838
25104
  return {
24839
- project: join45(cwd, ".opencode", "oh-my-opencode.json"),
24840
- user: join45(configDir, "oh-my-opencode.json"),
24841
- opencode: join45(configDir, "opencode.json")
25105
+ project: join46(cwd2, ".opencode", "oh-my-opencode.json"),
25106
+ user: join46(configDir, "oh-my-opencode.json"),
25107
+ opencode: join46(configDir, "opencode.json")
24842
25108
  };
24843
25109
  }
24844
25110
  function loadAllConfigs() {
@@ -24951,7 +25217,7 @@ function isServerInstalled(command) {
24951
25217
  return false;
24952
25218
  const cmd = command[0];
24953
25219
  if (cmd.includes("/") || cmd.includes("\\")) {
24954
- if (existsSync35(cmd))
25220
+ if (existsSync37(cmd))
24955
25221
  return true;
24956
25222
  }
24957
25223
  const isWindows2 = process.platform === "win32";
@@ -24973,23 +25239,23 @@ function isServerInstalled(command) {
24973
25239
  const paths = pathEnv.split(pathSeparator);
24974
25240
  for (const p of paths) {
24975
25241
  for (const suffix of exts) {
24976
- if (existsSync35(join45(p, cmd + suffix))) {
25242
+ if (existsSync37(join46(p, cmd + suffix))) {
24977
25243
  return true;
24978
25244
  }
24979
25245
  }
24980
25246
  }
24981
- const cwd = process.cwd();
25247
+ const cwd2 = process.cwd();
24982
25248
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
24983
- const dataDir = join45(getDataDir(), "opencode");
25249
+ const dataDir = join46(getDataDir(), "opencode");
24984
25250
  const additionalBases = [
24985
- join45(cwd, "node_modules", ".bin"),
24986
- join45(configDir, "bin"),
24987
- join45(configDir, "node_modules", ".bin"),
24988
- join45(dataDir, "bin")
25251
+ join46(cwd2, "node_modules", ".bin"),
25252
+ join46(configDir, "bin"),
25253
+ join46(configDir, "node_modules", ".bin"),
25254
+ join46(dataDir, "bin")
24989
25255
  ];
24990
25256
  for (const base of additionalBases) {
24991
25257
  for (const suffix of exts) {
24992
- if (existsSync35(join45(base, cmd + suffix))) {
25258
+ if (existsSync37(join46(base, cmd + suffix))) {
24993
25259
  return true;
24994
25260
  }
24995
25261
  }
@@ -25001,7 +25267,7 @@ function isServerInstalled(command) {
25001
25267
  }
25002
25268
  // src/tools/lsp/client.ts
25003
25269
  var {spawn: spawn6 } = globalThis.Bun;
25004
- import { readFileSync as readFileSync26 } from "fs";
25270
+ import { readFileSync as readFileSync27 } from "fs";
25005
25271
  import { extname, resolve as resolve8 } from "path";
25006
25272
  import { pathToFileURL } from "url";
25007
25273
  class LSPServerManager {
@@ -25451,7 +25717,7 @@ ${msg}`);
25451
25717
  const absPath = resolve8(filePath);
25452
25718
  if (this.openedFiles.has(absPath))
25453
25719
  return;
25454
- const text = readFileSync26(absPath, "utf-8");
25720
+ const text = readFileSync27(absPath, "utf-8");
25455
25721
  const ext = extname(absPath);
25456
25722
  const languageId = getLanguageId(ext);
25457
25723
  this.notify("textDocument/didOpen", {
@@ -25541,17 +25807,17 @@ ${msg}`);
25541
25807
  // src/tools/lsp/utils.ts
25542
25808
  import { extname as extname2, resolve as resolve9 } from "path";
25543
25809
  import { fileURLToPath as fileURLToPath2 } from "url";
25544
- import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15 } from "fs";
25810
+ import { existsSync as existsSync38, readFileSync as readFileSync28, writeFileSync as writeFileSync16 } from "fs";
25545
25811
  function findWorkspaceRoot(filePath) {
25546
25812
  let dir = resolve9(filePath);
25547
- if (!existsSync36(dir) || !__require("fs").statSync(dir).isDirectory()) {
25813
+ if (!existsSync38(dir) || !__require("fs").statSync(dir).isDirectory()) {
25548
25814
  dir = __require("path").dirname(dir);
25549
25815
  }
25550
25816
  const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
25551
25817
  let prevDir = "";
25552
25818
  while (dir !== prevDir) {
25553
25819
  for (const marker of markers) {
25554
- if (existsSync36(__require("path").join(dir, marker))) {
25820
+ if (existsSync38(__require("path").join(dir, marker))) {
25555
25821
  return dir;
25556
25822
  }
25557
25823
  }
@@ -25706,7 +25972,7 @@ function formatPrepareRenameResult(result) {
25706
25972
  }
25707
25973
  function applyTextEditsToFile(filePath, edits) {
25708
25974
  try {
25709
- let content = readFileSync27(filePath, "utf-8");
25975
+ let content = readFileSync28(filePath, "utf-8");
25710
25976
  const lines = content.split(`
25711
25977
  `);
25712
25978
  const sortedEdits = [...edits].sort((a, b) => {
@@ -25731,7 +25997,7 @@ function applyTextEditsToFile(filePath, edits) {
25731
25997
  `));
25732
25998
  }
25733
25999
  }
25734
- writeFileSync15(filePath, lines.join(`
26000
+ writeFileSync16(filePath, lines.join(`
25735
26001
  `), "utf-8");
25736
26002
  return { success: true, editCount: edits.length };
25737
26003
  } catch (err) {
@@ -25762,7 +26028,7 @@ function applyWorkspaceEdit(edit) {
25762
26028
  if (change.kind === "create") {
25763
26029
  try {
25764
26030
  const filePath = uriToPath(change.uri);
25765
- writeFileSync15(filePath, "", "utf-8");
26031
+ writeFileSync16(filePath, "", "utf-8");
25766
26032
  result.filesModified.push(filePath);
25767
26033
  } catch (err) {
25768
26034
  result.success = false;
@@ -25772,8 +26038,8 @@ function applyWorkspaceEdit(edit) {
25772
26038
  try {
25773
26039
  const oldPath = uriToPath(change.oldUri);
25774
26040
  const newPath = uriToPath(change.newUri);
25775
- const content = readFileSync27(oldPath, "utf-8");
25776
- writeFileSync15(newPath, content, "utf-8");
26041
+ const content = readFileSync28(oldPath, "utf-8");
26042
+ writeFileSync16(newPath, content, "utf-8");
25777
26043
  __require("fs").unlinkSync(oldPath);
25778
26044
  result.filesModified.push(newPath);
25779
26045
  } catch (err) {
@@ -38352,13 +38618,13 @@ var lsp_rename = tool({
38352
38618
  });
38353
38619
  // src/tools/ast-grep/constants.ts
38354
38620
  import { createRequire as createRequire4 } from "module";
38355
- import { dirname as dirname10, join as join47 } from "path";
38356
- import { existsSync as existsSync38, statSync as statSync4 } from "fs";
38621
+ import { dirname as dirname10, join as join48 } from "path";
38622
+ import { existsSync as existsSync40, statSync as statSync4 } from "fs";
38357
38623
 
38358
38624
  // src/tools/ast-grep/downloader.ts
38359
38625
  init_shared();
38360
- import { existsSync as existsSync37, mkdirSync as mkdirSync12, chmodSync as chmodSync2, unlinkSync as unlinkSync10 } from "fs";
38361
- import { join as join46 } from "path";
38626
+ import { existsSync as existsSync39, mkdirSync as mkdirSync13, chmodSync as chmodSync2, unlinkSync as unlinkSync10 } from "fs";
38627
+ import { join as join47 } from "path";
38362
38628
  import { homedir as homedir12 } from "os";
38363
38629
  import { createRequire as createRequire3 } from "module";
38364
38630
  var REPO2 = "ast-grep/ast-grep";
@@ -38384,19 +38650,19 @@ var PLATFORM_MAP2 = {
38384
38650
  function getCacheDir3() {
38385
38651
  if (process.platform === "win32") {
38386
38652
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
38387
- const base2 = localAppData || join46(homedir12(), "AppData", "Local");
38388
- return join46(base2, "oh-my-opencode", "bin");
38653
+ const base2 = localAppData || join47(homedir12(), "AppData", "Local");
38654
+ return join47(base2, "oh-my-opencode", "bin");
38389
38655
  }
38390
38656
  const xdgCache = process.env.XDG_CACHE_HOME;
38391
- const base = xdgCache || join46(homedir12(), ".cache");
38392
- return join46(base, "oh-my-opencode", "bin");
38657
+ const base = xdgCache || join47(homedir12(), ".cache");
38658
+ return join47(base, "oh-my-opencode", "bin");
38393
38659
  }
38394
38660
  function getBinaryName3() {
38395
38661
  return process.platform === "win32" ? "sg.exe" : "sg";
38396
38662
  }
38397
38663
  function getCachedBinaryPath2() {
38398
- const binaryPath = join46(getCacheDir3(), getBinaryName3());
38399
- return existsSync37(binaryPath) ? binaryPath : null;
38664
+ const binaryPath = join47(getCacheDir3(), getBinaryName3());
38665
+ return existsSync39(binaryPath) ? binaryPath : null;
38400
38666
  }
38401
38667
  async function downloadAstGrep(version2 = DEFAULT_VERSION) {
38402
38668
  const platformKey = `${process.platform}-${process.arch}`;
@@ -38407,8 +38673,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
38407
38673
  }
38408
38674
  const cacheDir = getCacheDir3();
38409
38675
  const binaryName = getBinaryName3();
38410
- const binaryPath = join46(cacheDir, binaryName);
38411
- if (existsSync37(binaryPath)) {
38676
+ const binaryPath = join47(cacheDir, binaryName);
38677
+ if (existsSync39(binaryPath)) {
38412
38678
  return binaryPath;
38413
38679
  }
38414
38680
  const { arch, os: os6 } = platformInfo;
@@ -38416,21 +38682,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
38416
38682
  const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
38417
38683
  console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
38418
38684
  try {
38419
- if (!existsSync37(cacheDir)) {
38420
- mkdirSync12(cacheDir, { recursive: true });
38685
+ if (!existsSync39(cacheDir)) {
38686
+ mkdirSync13(cacheDir, { recursive: true });
38421
38687
  }
38422
38688
  const response = await fetch(downloadUrl, { redirect: "follow" });
38423
38689
  if (!response.ok) {
38424
38690
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
38425
38691
  }
38426
- const archivePath = join46(cacheDir, assetName);
38692
+ const archivePath = join47(cacheDir, assetName);
38427
38693
  const arrayBuffer = await response.arrayBuffer();
38428
38694
  await Bun.write(archivePath, arrayBuffer);
38429
38695
  await extractZip(archivePath, cacheDir);
38430
- if (existsSync37(archivePath)) {
38696
+ if (existsSync39(archivePath)) {
38431
38697
  unlinkSync10(archivePath);
38432
38698
  }
38433
- if (process.platform !== "win32" && existsSync37(binaryPath)) {
38699
+ if (process.platform !== "win32" && existsSync39(binaryPath)) {
38434
38700
  chmodSync2(binaryPath, 493);
38435
38701
  }
38436
38702
  console.log(`[oh-my-opencode] ast-grep binary ready.`);
@@ -38481,8 +38747,8 @@ function findSgCliPathSync() {
38481
38747
  const require2 = createRequire4(import.meta.url);
38482
38748
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
38483
38749
  const cliDir = dirname10(cliPkgPath);
38484
- const sgPath = join47(cliDir, binaryName);
38485
- if (existsSync38(sgPath) && isValidBinary(sgPath)) {
38750
+ const sgPath = join48(cliDir, binaryName);
38751
+ if (existsSync40(sgPath) && isValidBinary(sgPath)) {
38486
38752
  return sgPath;
38487
38753
  }
38488
38754
  } catch {}
@@ -38493,8 +38759,8 @@ function findSgCliPathSync() {
38493
38759
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
38494
38760
  const pkgDir = dirname10(pkgPath);
38495
38761
  const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
38496
- const binaryPath = join47(pkgDir, astGrepName);
38497
- if (existsSync38(binaryPath) && isValidBinary(binaryPath)) {
38762
+ const binaryPath = join48(pkgDir, astGrepName);
38763
+ if (existsSync40(binaryPath) && isValidBinary(binaryPath)) {
38498
38764
  return binaryPath;
38499
38765
  }
38500
38766
  } catch {}
@@ -38502,7 +38768,7 @@ function findSgCliPathSync() {
38502
38768
  if (process.platform === "darwin") {
38503
38769
  const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
38504
38770
  for (const path7 of homebrewPaths) {
38505
- if (existsSync38(path7) && isValidBinary(path7)) {
38771
+ if (existsSync40(path7) && isValidBinary(path7)) {
38506
38772
  return path7;
38507
38773
  }
38508
38774
  }
@@ -38557,11 +38823,11 @@ var DEFAULT_MAX_MATCHES = 500;
38557
38823
 
38558
38824
  // src/tools/ast-grep/cli.ts
38559
38825
  var {spawn: spawn7 } = globalThis.Bun;
38560
- import { existsSync as existsSync39 } from "fs";
38826
+ import { existsSync as existsSync41 } from "fs";
38561
38827
  var resolvedCliPath3 = null;
38562
38828
  var initPromise2 = null;
38563
38829
  async function getAstGrepPath() {
38564
- if (resolvedCliPath3 !== null && existsSync39(resolvedCliPath3)) {
38830
+ if (resolvedCliPath3 !== null && existsSync41(resolvedCliPath3)) {
38565
38831
  return resolvedCliPath3;
38566
38832
  }
38567
38833
  if (initPromise2) {
@@ -38569,7 +38835,7 @@ async function getAstGrepPath() {
38569
38835
  }
38570
38836
  initPromise2 = (async () => {
38571
38837
  const syncPath = findSgCliPathSync();
38572
- if (syncPath && existsSync39(syncPath)) {
38838
+ if (syncPath && existsSync41(syncPath)) {
38573
38839
  resolvedCliPath3 = syncPath;
38574
38840
  setSgCliPath(syncPath);
38575
38841
  return syncPath;
@@ -38603,7 +38869,7 @@ async function runSg(options) {
38603
38869
  const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
38604
38870
  args.push(...paths);
38605
38871
  let cliPath = getSgCliPath();
38606
- if (!existsSync39(cliPath) && cliPath !== "sg") {
38872
+ if (!existsSync41(cliPath) && cliPath !== "sg") {
38607
38873
  const downloadedPath = await getAstGrepPath();
38608
38874
  if (downloadedPath) {
38609
38875
  cliPath = downloadedPath;
@@ -38867,21 +39133,21 @@ var ast_grep_replace = tool({
38867
39133
  var {spawn: spawn9 } = globalThis.Bun;
38868
39134
 
38869
39135
  // src/tools/grep/constants.ts
38870
- import { existsSync as existsSync41 } from "fs";
38871
- import { join as join49, dirname as dirname11 } from "path";
39136
+ import { existsSync as existsSync43 } from "fs";
39137
+ import { join as join50, dirname as dirname11 } from "path";
38872
39138
  import { spawnSync as spawnSync2 } from "child_process";
38873
39139
 
38874
39140
  // src/tools/grep/downloader.ts
38875
39141
  init_shared();
38876
- import { existsSync as existsSync40, mkdirSync as mkdirSync13, chmodSync as chmodSync3, unlinkSync as unlinkSync11, readdirSync as readdirSync11 } from "fs";
38877
- import { join as join48 } from "path";
39142
+ import { existsSync as existsSync42, mkdirSync as mkdirSync14, chmodSync as chmodSync3, unlinkSync as unlinkSync11, readdirSync as readdirSync12 } from "fs";
39143
+ import { join as join49 } from "path";
38878
39144
  var {spawn: spawn8 } = globalThis.Bun;
38879
39145
  function findFileRecursive(dir, filename) {
38880
39146
  try {
38881
- const entries = readdirSync11(dir, { withFileTypes: true, recursive: true });
39147
+ const entries = readdirSync12(dir, { withFileTypes: true, recursive: true });
38882
39148
  for (const entry of entries) {
38883
39149
  if (entry.isFile() && entry.name === filename) {
38884
- return join48(entry.parentPath ?? dir, entry.name);
39150
+ return join49(entry.parentPath ?? dir, entry.name);
38885
39151
  }
38886
39152
  }
38887
39153
  } catch {
@@ -38902,11 +39168,11 @@ function getPlatformKey() {
38902
39168
  }
38903
39169
  function getInstallDir() {
38904
39170
  const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
38905
- return join48(homeDir, ".cache", "oh-my-opencode", "bin");
39171
+ return join49(homeDir, ".cache", "oh-my-opencode", "bin");
38906
39172
  }
38907
39173
  function getRgPath() {
38908
39174
  const isWindows2 = process.platform === "win32";
38909
- return join48(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
39175
+ return join49(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
38910
39176
  }
38911
39177
  async function downloadFile(url2, destPath) {
38912
39178
  const response = await fetch(url2);
@@ -38940,7 +39206,7 @@ async function extractZip2(archivePath, destDir) {
38940
39206
  const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
38941
39207
  const foundPath = findFileRecursive(destDir, binaryName);
38942
39208
  if (foundPath) {
38943
- const destPath = join48(destDir, binaryName);
39209
+ const destPath = join49(destDir, binaryName);
38944
39210
  if (foundPath !== destPath) {
38945
39211
  const { renameSync } = await import("fs");
38946
39212
  renameSync(foundPath, destPath);
@@ -38955,13 +39221,13 @@ async function downloadAndInstallRipgrep() {
38955
39221
  }
38956
39222
  const installDir = getInstallDir();
38957
39223
  const rgPath = getRgPath();
38958
- if (existsSync40(rgPath)) {
39224
+ if (existsSync42(rgPath)) {
38959
39225
  return rgPath;
38960
39226
  }
38961
- mkdirSync13(installDir, { recursive: true });
39227
+ mkdirSync14(installDir, { recursive: true });
38962
39228
  const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
38963
39229
  const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
38964
- const archivePath = join48(installDir, filename);
39230
+ const archivePath = join49(installDir, filename);
38965
39231
  try {
38966
39232
  await downloadFile(url2, archivePath);
38967
39233
  if (config3.extension === "tar.gz") {
@@ -38972,12 +39238,12 @@ async function downloadAndInstallRipgrep() {
38972
39238
  if (process.platform !== "win32") {
38973
39239
  chmodSync3(rgPath, 493);
38974
39240
  }
38975
- if (!existsSync40(rgPath)) {
39241
+ if (!existsSync42(rgPath)) {
38976
39242
  throw new Error("ripgrep binary not found after extraction");
38977
39243
  }
38978
39244
  return rgPath;
38979
39245
  } finally {
38980
- if (existsSync40(archivePath)) {
39246
+ if (existsSync42(archivePath)) {
38981
39247
  try {
38982
39248
  unlinkSync11(archivePath);
38983
39249
  } catch {}
@@ -38986,7 +39252,7 @@ async function downloadAndInstallRipgrep() {
38986
39252
  }
38987
39253
  function getInstalledRipgrepPath() {
38988
39254
  const rgPath = getRgPath();
38989
- return existsSync40(rgPath) ? rgPath : null;
39255
+ return existsSync42(rgPath) ? rgPath : null;
38990
39256
  }
38991
39257
 
38992
39258
  // src/tools/grep/constants.ts
@@ -39011,14 +39277,14 @@ function getOpenCodeBundledRg() {
39011
39277
  const isWindows2 = process.platform === "win32";
39012
39278
  const rgName = isWindows2 ? "rg.exe" : "rg";
39013
39279
  const candidates = [
39014
- join49(getDataDir(), "opencode", "bin", rgName),
39015
- join49(execDir, rgName),
39016
- join49(execDir, "bin", rgName),
39017
- join49(execDir, "..", "bin", rgName),
39018
- join49(execDir, "..", "libexec", rgName)
39280
+ join50(getDataDir(), "opencode", "bin", rgName),
39281
+ join50(execDir, rgName),
39282
+ join50(execDir, "bin", rgName),
39283
+ join50(execDir, "..", "bin", rgName),
39284
+ join50(execDir, "..", "libexec", rgName)
39019
39285
  ];
39020
39286
  for (const candidate of candidates) {
39021
- if (existsSync41(candidate)) {
39287
+ if (existsSync43(candidate)) {
39022
39288
  return candidate;
39023
39289
  }
39024
39290
  }
@@ -39355,26 +39621,26 @@ async function runRgFiles(options, resolvedCli) {
39355
39621
  const isRg = cli.backend === "rg";
39356
39622
  const isWindows2 = process.platform === "win32";
39357
39623
  let command;
39358
- let cwd;
39624
+ let cwd2;
39359
39625
  if (isRg) {
39360
39626
  const args = buildRgArgs2(options);
39361
39627
  const paths = options.paths?.length ? options.paths : ["."];
39362
39628
  args.push(...paths);
39363
39629
  command = [cli.path, ...args];
39364
- cwd = undefined;
39630
+ cwd2 = undefined;
39365
39631
  } else if (isWindows2) {
39366
39632
  command = buildPowerShellCommand(options);
39367
- cwd = undefined;
39633
+ cwd2 = undefined;
39368
39634
  } else {
39369
39635
  const args = buildFindArgs(options);
39370
39636
  const paths = options.paths?.length ? options.paths : ["."];
39371
- cwd = paths[0] || ".";
39637
+ cwd2 = paths[0] || ".";
39372
39638
  command = [cli.path, ...args];
39373
39639
  }
39374
39640
  const proc = spawn10(command, {
39375
39641
  stdout: "pipe",
39376
39642
  stderr: "pipe",
39377
- cwd
39643
+ cwd: cwd2
39378
39644
  });
39379
39645
  const timeoutPromise = new Promise((_, reject) => {
39380
39646
  const id = setTimeout(() => {
@@ -39412,7 +39678,7 @@ async function runRgFiles(options, resolvedCli) {
39412
39678
  } else if (isWindows2) {
39413
39679
  filePath = line.trim();
39414
39680
  } else {
39415
- filePath = `${cwd}/${line}`;
39681
+ filePath = `${cwd2}/${line}`;
39416
39682
  }
39417
39683
  const mtime = await getFileMtime(filePath);
39418
39684
  files.push({ path: filePath, mtime });
@@ -39480,8 +39746,8 @@ var glob = tool({
39480
39746
  init_shared();
39481
39747
  init_file_utils();
39482
39748
  init_shared();
39483
- import { existsSync as existsSync42, readdirSync as readdirSync12, readFileSync as readFileSync28 } from "fs";
39484
- import { join as join50, basename as basename4, dirname as dirname12 } from "path";
39749
+ import { existsSync as existsSync44, readdirSync as readdirSync13, readFileSync as readFileSync29 } from "fs";
39750
+ import { join as join51, basename as basename4, dirname as dirname12 } from "path";
39485
39751
  // src/features/builtin-commands/templates/init-deep.ts
39486
39752
  var INIT_DEEP_TEMPLATE = `# /init-deep
39487
39753
 
@@ -40597,18 +40863,18 @@ function loadBuiltinCommands(disabledCommands) {
40597
40863
  }
40598
40864
  // src/tools/slashcommand/tools.ts
40599
40865
  function discoverCommandsFromDir2(commandsDir, scope) {
40600
- if (!existsSync42(commandsDir)) {
40866
+ if (!existsSync44(commandsDir)) {
40601
40867
  return [];
40602
40868
  }
40603
- const entries = readdirSync12(commandsDir, { withFileTypes: true });
40869
+ const entries = readdirSync13(commandsDir, { withFileTypes: true });
40604
40870
  const commands2 = [];
40605
40871
  for (const entry of entries) {
40606
40872
  if (!isMarkdownFile(entry))
40607
40873
  continue;
40608
- const commandPath = join50(commandsDir, entry.name);
40874
+ const commandPath = join51(commandsDir, entry.name);
40609
40875
  const commandName = basename4(entry.name, ".md");
40610
40876
  try {
40611
- const content = readFileSync28(commandPath, "utf-8");
40877
+ const content = readFileSync29(commandPath, "utf-8");
40612
40878
  const { data, body } = parseFrontmatter(content);
40613
40879
  const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
40614
40880
  const metadata = {
@@ -40634,10 +40900,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
40634
40900
  }
40635
40901
  function discoverCommandsSync() {
40636
40902
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
40637
- const userCommandsDir = join50(getClaudeConfigDir(), "commands");
40638
- const projectCommandsDir = join50(process.cwd(), ".claude", "commands");
40639
- const opencodeGlobalDir = join50(configDir, "command");
40640
- const opencodeProjectDir = join50(process.cwd(), ".opencode", "command");
40903
+ const userCommandsDir = join51(getClaudeConfigDir(), "commands");
40904
+ const projectCommandsDir = join51(process.cwd(), ".claude", "commands");
40905
+ const opencodeGlobalDir = join51(configDir, "command");
40906
+ const opencodeProjectDir = join51(process.cwd(), ".opencode", "command");
40641
40907
  const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
40642
40908
  const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
40643
40909
  const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
@@ -40814,13 +41080,13 @@ var slashcommand = createSlashcommandTool();
40814
41080
  // src/tools/session-manager/constants.ts
40815
41081
  init_data_path();
40816
41082
  init_shared();
40817
- import { join as join51 } from "path";
41083
+ import { join as join52 } from "path";
40818
41084
  var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
40819
- var MESSAGE_STORAGE4 = join51(OPENCODE_STORAGE9, "message");
40820
- var PART_STORAGE4 = join51(OPENCODE_STORAGE9, "part");
40821
- var SESSION_STORAGE = join51(OPENCODE_STORAGE9, "session");
40822
- var TODO_DIR2 = join51(getClaudeConfigDir(), "todos");
40823
- var TRANSCRIPT_DIR2 = join51(getClaudeConfigDir(), "transcripts");
41085
+ var MESSAGE_STORAGE4 = join52(OPENCODE_STORAGE9, "message");
41086
+ var PART_STORAGE4 = join52(OPENCODE_STORAGE9, "part");
41087
+ var SESSION_STORAGE = join52(OPENCODE_STORAGE9, "session");
41088
+ var TODO_DIR2 = join52(getClaudeConfigDir(), "todos");
41089
+ var TRANSCRIPT_DIR2 = join52(getClaudeConfigDir(), "transcripts");
40824
41090
  var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
40825
41091
 
40826
41092
  \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
@@ -40893,11 +41159,11 @@ Has Todos: Yes (12 items, 8 completed)
40893
41159
  Has Transcript: Yes (234 entries)`;
40894
41160
 
40895
41161
  // src/tools/session-manager/storage.ts
40896
- import { existsSync as existsSync43, readdirSync as readdirSync13 } from "fs";
41162
+ import { existsSync as existsSync45, readdirSync as readdirSync14 } from "fs";
40897
41163
  import { readdir, readFile } from "fs/promises";
40898
- import { join as join52 } from "path";
41164
+ import { join as join53 } from "path";
40899
41165
  async function getMainSessions(options) {
40900
- if (!existsSync43(SESSION_STORAGE))
41166
+ if (!existsSync45(SESSION_STORAGE))
40901
41167
  return [];
40902
41168
  const sessions = [];
40903
41169
  try {
@@ -40905,13 +41171,13 @@ async function getMainSessions(options) {
40905
41171
  for (const projectDir of projectDirs) {
40906
41172
  if (!projectDir.isDirectory())
40907
41173
  continue;
40908
- const projectPath = join52(SESSION_STORAGE, projectDir.name);
41174
+ const projectPath = join53(SESSION_STORAGE, projectDir.name);
40909
41175
  const sessionFiles = await readdir(projectPath);
40910
41176
  for (const file2 of sessionFiles) {
40911
41177
  if (!file2.endsWith(".json"))
40912
41178
  continue;
40913
41179
  try {
40914
- const content = await readFile(join52(projectPath, file2), "utf-8");
41180
+ const content = await readFile(join53(projectPath, file2), "utf-8");
40915
41181
  const meta = JSON.parse(content);
40916
41182
  if (meta.parentID)
40917
41183
  continue;
@@ -40929,7 +41195,7 @@ async function getMainSessions(options) {
40929
41195
  return sessions.sort((a, b) => b.time.updated - a.time.updated);
40930
41196
  }
40931
41197
  async function getAllSessions() {
40932
- if (!existsSync43(MESSAGE_STORAGE4))
41198
+ if (!existsSync45(MESSAGE_STORAGE4))
40933
41199
  return [];
40934
41200
  const sessions = [];
40935
41201
  async function scanDirectory(dir) {
@@ -40937,7 +41203,7 @@ async function getAllSessions() {
40937
41203
  const entries = await readdir(dir, { withFileTypes: true });
40938
41204
  for (const entry of entries) {
40939
41205
  if (entry.isDirectory()) {
40940
- const sessionPath = join52(dir, entry.name);
41206
+ const sessionPath = join53(dir, entry.name);
40941
41207
  const files = await readdir(sessionPath);
40942
41208
  if (files.some((f) => f.endsWith(".json"))) {
40943
41209
  sessions.push(entry.name);
@@ -40954,16 +41220,16 @@ async function getAllSessions() {
40954
41220
  return [...new Set(sessions)];
40955
41221
  }
40956
41222
  function getMessageDir7(sessionID) {
40957
- if (!existsSync43(MESSAGE_STORAGE4))
41223
+ if (!existsSync45(MESSAGE_STORAGE4))
40958
41224
  return "";
40959
- const directPath = join52(MESSAGE_STORAGE4, sessionID);
40960
- if (existsSync43(directPath)) {
41225
+ const directPath = join53(MESSAGE_STORAGE4, sessionID);
41226
+ if (existsSync45(directPath)) {
40961
41227
  return directPath;
40962
41228
  }
40963
41229
  try {
40964
- for (const dir of readdirSync13(MESSAGE_STORAGE4)) {
40965
- const sessionPath = join52(MESSAGE_STORAGE4, dir, sessionID);
40966
- if (existsSync43(sessionPath)) {
41230
+ for (const dir of readdirSync14(MESSAGE_STORAGE4)) {
41231
+ const sessionPath = join53(MESSAGE_STORAGE4, dir, sessionID);
41232
+ if (existsSync45(sessionPath)) {
40967
41233
  return sessionPath;
40968
41234
  }
40969
41235
  }
@@ -40977,7 +41243,7 @@ function sessionExists(sessionID) {
40977
41243
  }
40978
41244
  async function readSessionMessages(sessionID) {
40979
41245
  const messageDir = getMessageDir7(sessionID);
40980
- if (!messageDir || !existsSync43(messageDir))
41246
+ if (!messageDir || !existsSync45(messageDir))
40981
41247
  return [];
40982
41248
  const messages = [];
40983
41249
  try {
@@ -40986,7 +41252,7 @@ async function readSessionMessages(sessionID) {
40986
41252
  if (!file2.endsWith(".json"))
40987
41253
  continue;
40988
41254
  try {
40989
- const content = await readFile(join52(messageDir, file2), "utf-8");
41255
+ const content = await readFile(join53(messageDir, file2), "utf-8");
40990
41256
  const meta = JSON.parse(content);
40991
41257
  const parts = await readParts2(meta.id);
40992
41258
  messages.push({
@@ -41012,8 +41278,8 @@ async function readSessionMessages(sessionID) {
41012
41278
  });
41013
41279
  }
41014
41280
  async function readParts2(messageID) {
41015
- const partDir = join52(PART_STORAGE4, messageID);
41016
- if (!existsSync43(partDir))
41281
+ const partDir = join53(PART_STORAGE4, messageID);
41282
+ if (!existsSync45(partDir))
41017
41283
  return [];
41018
41284
  const parts = [];
41019
41285
  try {
@@ -41022,7 +41288,7 @@ async function readParts2(messageID) {
41022
41288
  if (!file2.endsWith(".json"))
41023
41289
  continue;
41024
41290
  try {
41025
- const content = await readFile(join52(partDir, file2), "utf-8");
41291
+ const content = await readFile(join53(partDir, file2), "utf-8");
41026
41292
  parts.push(JSON.parse(content));
41027
41293
  } catch {
41028
41294
  continue;
@@ -41034,14 +41300,14 @@ async function readParts2(messageID) {
41034
41300
  return parts.sort((a, b) => a.id.localeCompare(b.id));
41035
41301
  }
41036
41302
  async function readSessionTodos(sessionID) {
41037
- if (!existsSync43(TODO_DIR2))
41303
+ if (!existsSync45(TODO_DIR2))
41038
41304
  return [];
41039
41305
  try {
41040
41306
  const allFiles = await readdir(TODO_DIR2);
41041
41307
  const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
41042
41308
  for (const file2 of todoFiles) {
41043
41309
  try {
41044
- const content = await readFile(join52(TODO_DIR2, file2), "utf-8");
41310
+ const content = await readFile(join53(TODO_DIR2, file2), "utf-8");
41045
41311
  const data = JSON.parse(content);
41046
41312
  if (Array.isArray(data)) {
41047
41313
  return data.map((item) => ({
@@ -41061,10 +41327,10 @@ async function readSessionTodos(sessionID) {
41061
41327
  return [];
41062
41328
  }
41063
41329
  async function readSessionTranscript(sessionID) {
41064
- if (!existsSync43(TRANSCRIPT_DIR2))
41330
+ if (!existsSync45(TRANSCRIPT_DIR2))
41065
41331
  return 0;
41066
- const transcriptFile = join52(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
41067
- if (!existsSync43(transcriptFile))
41332
+ const transcriptFile = join53(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
41333
+ if (!existsSync45(transcriptFile))
41068
41334
  return 0;
41069
41335
  try {
41070
41336
  const content = await readFile(transcriptFile, "utf-8");
@@ -42266,19 +42532,19 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8 explore/librarian agent\u3002run_
42266
42532
 
42267
42533
  \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`;
42268
42534
  // src/tools/call-omo-agent/tools.ts
42269
- import { existsSync as existsSync44, readdirSync as readdirSync14 } from "fs";
42270
- import { join as join53 } from "path";
42535
+ import { existsSync as existsSync46, readdirSync as readdirSync15 } from "fs";
42536
+ import { join as join54 } from "path";
42271
42537
  init_shared();
42272
42538
  init_session_cursor();
42273
42539
  function getMessageDir8(sessionID) {
42274
- if (!existsSync44(MESSAGE_STORAGE))
42540
+ if (!existsSync46(MESSAGE_STORAGE))
42275
42541
  return null;
42276
- const directPath = join53(MESSAGE_STORAGE, sessionID);
42277
- if (existsSync44(directPath))
42542
+ const directPath = join54(MESSAGE_STORAGE, sessionID);
42543
+ if (existsSync46(directPath))
42278
42544
  return directPath;
42279
- for (const dir of readdirSync14(MESSAGE_STORAGE)) {
42280
- const sessionPath = join53(MESSAGE_STORAGE, dir, sessionID);
42281
- if (existsSync44(sessionPath))
42545
+ for (const dir of readdirSync15(MESSAGE_STORAGE)) {
42546
+ const sessionPath = join54(MESSAGE_STORAGE, dir, sessionID);
42547
+ if (existsSync46(sessionPath))
42282
42548
  return sessionPath;
42283
42549
  }
42284
42550
  return null;
@@ -42687,8 +42953,8 @@ If the requested information is not found, clearly state what is missing.`;
42687
42953
  }
42688
42954
  // src/tools/delegate-task/tools.ts
42689
42955
  init_constants2();
42690
- import { existsSync as existsSync45, readdirSync as readdirSync15 } from "fs";
42691
- import { join as join54 } from "path";
42956
+ import { existsSync as existsSync47, readdirSync as readdirSync16 } from "fs";
42957
+ import { join as join55 } from "path";
42692
42958
 
42693
42959
  // src/features/task-toast-manager/manager.ts
42694
42960
  class TaskToastManager {
@@ -42847,14 +43113,14 @@ function parseModelString(model) {
42847
43113
  return;
42848
43114
  }
42849
43115
  function getMessageDir9(sessionID) {
42850
- if (!existsSync45(MESSAGE_STORAGE))
43116
+ if (!existsSync47(MESSAGE_STORAGE))
42851
43117
  return null;
42852
- const directPath = join54(MESSAGE_STORAGE, sessionID);
42853
- if (existsSync45(directPath))
43118
+ const directPath = join55(MESSAGE_STORAGE, sessionID);
43119
+ if (existsSync47(directPath))
42854
43120
  return directPath;
42855
- for (const dir of readdirSync15(MESSAGE_STORAGE)) {
42856
- const sessionPath = join54(MESSAGE_STORAGE, dir, sessionID);
42857
- if (existsSync45(sessionPath))
43121
+ for (const dir of readdirSync16(MESSAGE_STORAGE)) {
43122
+ const sessionPath = join55(MESSAGE_STORAGE, dir, sessionID);
43123
+ if (existsSync47(sessionPath))
42858
43124
  return sessionPath;
42859
43125
  }
42860
43126
  return null;
@@ -43682,8 +43948,8 @@ class PerformanceAggregator {
43682
43948
  }
43683
43949
 
43684
43950
  // src/features/background-agent/manager.ts
43685
- import { existsSync as existsSync46, readdirSync as readdirSync16 } from "fs";
43686
- import { join as join55 } from "path";
43951
+ import { existsSync as existsSync48, readdirSync as readdirSync17 } from "fs";
43952
+ import { join as join56 } from "path";
43687
43953
  var TASK_TTL_MS = 30 * 60 * 1000;
43688
43954
  var MIN_STABILITY_TIME_MS = 10 * 1000;
43689
43955
  var DEFAULT_STALE_TIMEOUT_MS = 180000;
@@ -43703,6 +43969,7 @@ class BackgroundManager {
43703
43969
  shutdownTriggered = false;
43704
43970
  config;
43705
43971
  perfAggregator = new PerformanceAggregator;
43972
+ perfTracer;
43706
43973
  queuesByKey = new Map;
43707
43974
  processingKeys = new Set;
43708
43975
  constructor(ctx, config3) {
@@ -43715,6 +43982,9 @@ class BackgroundManager {
43715
43982
  this.config = config3;
43716
43983
  this.registerProcessCleanup();
43717
43984
  }
43985
+ setPerfTracer(tracer) {
43986
+ this.perfTracer = tracer;
43987
+ }
43718
43988
  async launch(input) {
43719
43989
  log("[background-agent] launch() called with:", {
43720
43990
  agent: input.agent,
@@ -44531,124 +44801,132 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
44531
44801
  }
44532
44802
  }
44533
44803
  async pollRunningTasks() {
44534
- this.pruneStaleTasksAndNotifications();
44535
- await this.checkAndInterruptStaleTasks();
44536
- const statusResult = await this.client.session.status();
44537
- const allStatuses = statusResult.data ?? {};
44538
- for (const task of this.tasks.values()) {
44539
- if (task.status !== "running")
44540
- continue;
44541
- const sessionID = task.sessionID;
44542
- if (!sessionID)
44543
- continue;
44544
- try {
44545
- const sessionStatus = allStatuses[sessionID];
44546
- if (sessionStatus?.type === "idle") {
44547
- const hasValidOutput = await this.validateSessionHasOutput(sessionID);
44548
- if (!hasValidOutput) {
44549
- log("[background-agent] Polling idle but no valid output yet, waiting:", task.id);
44550
- continue;
44551
- }
44552
- if (task.status !== "running")
44553
- continue;
44554
- const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
44555
- if (hasIncompleteTodos2) {
44556
- log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
44557
- continue;
44558
- }
44559
- await this.tryCompleteTask(task, "polling (idle status)");
44804
+ const start = this.perfTracer?.isEnabled() ? performance.now() : undefined;
44805
+ try {
44806
+ this.pruneStaleTasksAndNotifications();
44807
+ await this.checkAndInterruptStaleTasks();
44808
+ const statusResult = await this.client.session.status();
44809
+ const allStatuses = statusResult.data ?? {};
44810
+ for (const task of this.tasks.values()) {
44811
+ if (task.status !== "running")
44560
44812
  continue;
44561
- }
44562
- const messagesResult = await this.client.session.messages({
44563
- path: { id: sessionID }
44564
- });
44565
- if (!messagesResult.error && messagesResult.data) {
44566
- const messages = messagesResult.data;
44567
- const assistantMsgs = messages.filter((m) => m.info?.role === "assistant");
44568
- let toolCalls = 0;
44569
- let lastTool;
44570
- let lastMessage;
44571
- for (const msg of assistantMsgs) {
44572
- const parts = msg.parts ?? [];
44573
- for (const part of parts) {
44574
- if (part.type === "tool_use" || part.tool) {
44575
- toolCalls++;
44576
- lastTool = part.tool || part.name || "unknown";
44577
- }
44578
- if (part.type === "text" && part.text) {
44579
- lastMessage = part.text;
44580
- }
44813
+ const sessionID = task.sessionID;
44814
+ if (!sessionID)
44815
+ continue;
44816
+ try {
44817
+ const sessionStatus = allStatuses[sessionID];
44818
+ if (sessionStatus?.type === "idle") {
44819
+ const hasValidOutput = await this.validateSessionHasOutput(sessionID);
44820
+ if (!hasValidOutput) {
44821
+ log("[background-agent] Polling idle but no valid output yet, waiting:", task.id);
44822
+ continue;
44581
44823
  }
44582
- }
44583
- if (!task.progress) {
44584
- task.progress = { toolCalls: 0, lastUpdate: new Date };
44585
- }
44586
- if (task.startedAt && !task.progress.phaseTiming) {
44587
- const now = Date.now();
44588
- task.progress.phaseTiming = {
44589
- queueWaitMs: task.queuedAt ? now - task.queuedAt.getTime() : 0,
44590
- totalRunMs: now - task.startedAt.getTime(),
44591
- toolCallCount: 0
44592
- };
44593
- }
44594
- if (task.progress.phaseTiming && task.progress.phaseTiming.firstResponseMs === undefined && assistantMsgs.length > 0) {
44595
- task.progress.phaseTiming.firstResponseMs = Date.now() - task.startedAt.getTime();
44596
- }
44597
- task.progress.toolCalls = toolCalls;
44598
- task.progress.lastTool = lastTool;
44599
- task.progress.lastUpdate = new Date;
44600
- if (lastMessage) {
44601
- task.progress.lastMessage = lastMessage;
44602
- task.progress.lastMessageAt = new Date;
44603
- }
44604
- const currentMsgCount = messages.length;
44605
- const startedAt = task.startedAt;
44606
- if (!startedAt)
44824
+ if (task.status !== "running")
44825
+ continue;
44826
+ const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
44827
+ if (hasIncompleteTodos2) {
44828
+ log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
44829
+ continue;
44830
+ }
44831
+ await this.tryCompleteTask(task, "polling (idle status)");
44607
44832
  continue;
44608
- const elapsedMs = Date.now() - startedAt.getTime();
44609
- if (elapsedMs >= MIN_STABILITY_TIME_MS) {
44610
- if (task.lastMsgCount === currentMsgCount) {
44611
- task.stablePolls = (task.stablePolls ?? 0) + 1;
44612
- if (task.stablePolls >= 3) {
44613
- const recheckStatus = await this.client.session.status();
44614
- const recheckData = recheckStatus.data ?? {};
44615
- const currentStatus = recheckData[sessionID];
44616
- if (currentStatus?.type !== "idle") {
44617
- log("[background-agent] Stability reached but session not idle, resetting:", {
44618
- taskId: task.id,
44619
- sessionStatus: currentStatus?.type ?? "not_in_status"
44620
- });
44621
- task.stablePolls = 0;
44622
- continue;
44833
+ }
44834
+ const messagesResult = await this.client.session.messages({
44835
+ path: { id: sessionID }
44836
+ });
44837
+ if (!messagesResult.error && messagesResult.data) {
44838
+ const messages = messagesResult.data;
44839
+ const assistantMsgs = messages.filter((m) => m.info?.role === "assistant");
44840
+ let toolCalls = 0;
44841
+ let lastTool;
44842
+ let lastMessage;
44843
+ for (const msg of assistantMsgs) {
44844
+ const parts = msg.parts ?? [];
44845
+ for (const part of parts) {
44846
+ if (part.type === "tool_use" || part.tool) {
44847
+ toolCalls++;
44848
+ lastTool = part.tool || part.name || "unknown";
44623
44849
  }
44624
- const hasValidOutput = await this.validateSessionHasOutput(sessionID);
44625
- if (!hasValidOutput) {
44626
- log("[background-agent] Stability reached but no valid output, waiting:", task.id);
44627
- continue;
44850
+ if (part.type === "text" && part.text) {
44851
+ lastMessage = part.text;
44628
44852
  }
44629
- if (task.status !== "running")
44630
- continue;
44631
- const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
44632
- if (!hasIncompleteTodos2) {
44633
- await this.tryCompleteTask(task, "stability detection");
44634
- continue;
44853
+ }
44854
+ }
44855
+ if (!task.progress) {
44856
+ task.progress = { toolCalls: 0, lastUpdate: new Date };
44857
+ }
44858
+ if (task.startedAt && !task.progress.phaseTiming) {
44859
+ const now = Date.now();
44860
+ task.progress.phaseTiming = {
44861
+ queueWaitMs: task.queuedAt ? now - task.queuedAt.getTime() : 0,
44862
+ totalRunMs: now - task.startedAt.getTime(),
44863
+ toolCallCount: 0
44864
+ };
44865
+ }
44866
+ if (task.progress.phaseTiming && task.progress.phaseTiming.firstResponseMs === undefined && assistantMsgs.length > 0) {
44867
+ task.progress.phaseTiming.firstResponseMs = Date.now() - task.startedAt.getTime();
44868
+ }
44869
+ task.progress.toolCalls = toolCalls;
44870
+ task.progress.lastTool = lastTool;
44871
+ task.progress.lastUpdate = new Date;
44872
+ if (lastMessage) {
44873
+ task.progress.lastMessage = lastMessage;
44874
+ task.progress.lastMessageAt = new Date;
44875
+ }
44876
+ const currentMsgCount = messages.length;
44877
+ const startedAt = task.startedAt;
44878
+ if (!startedAt)
44879
+ continue;
44880
+ const elapsedMs = Date.now() - startedAt.getTime();
44881
+ if (elapsedMs >= MIN_STABILITY_TIME_MS) {
44882
+ if (task.lastMsgCount === currentMsgCount) {
44883
+ task.stablePolls = (task.stablePolls ?? 0) + 1;
44884
+ if (task.stablePolls >= 3) {
44885
+ const recheckStatus = await this.client.session.status();
44886
+ const recheckData = recheckStatus.data ?? {};
44887
+ const currentStatus = recheckData[sessionID];
44888
+ if (currentStatus?.type !== "idle") {
44889
+ log("[background-agent] Stability reached but session not idle, resetting:", {
44890
+ taskId: task.id,
44891
+ sessionStatus: currentStatus?.type ?? "not_in_status"
44892
+ });
44893
+ task.stablePolls = 0;
44894
+ continue;
44895
+ }
44896
+ const hasValidOutput = await this.validateSessionHasOutput(sessionID);
44897
+ if (!hasValidOutput) {
44898
+ log("[background-agent] Stability reached but no valid output, waiting:", task.id);
44899
+ continue;
44900
+ }
44901
+ if (task.status !== "running")
44902
+ continue;
44903
+ const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
44904
+ if (!hasIncompleteTodos2) {
44905
+ await this.tryCompleteTask(task, "stability detection");
44906
+ continue;
44907
+ }
44635
44908
  }
44909
+ } else {
44910
+ task.stablePolls = 0;
44636
44911
  }
44637
- } else {
44638
- task.stablePolls = 0;
44639
44912
  }
44913
+ task.lastMsgCount = currentMsgCount;
44640
44914
  }
44641
- task.lastMsgCount = currentMsgCount;
44915
+ } catch (error45) {
44916
+ log("[background-agent] Poll error for task:", { taskId: task.id, error: error45 });
44642
44917
  }
44643
- } catch (error45) {
44644
- log("[background-agent] Poll error for task:", { taskId: task.id, error: error45 });
44645
44918
  }
44646
- }
44647
- if (!this.hasRunningTasks()) {
44648
- this.stopPolling();
44649
- if (this.perfAggregator.taskCount >= 2) {
44650
- const report = this.perfAggregator.getReport();
44651
- log("[perf] Session report:", report);
44919
+ if (!this.hasRunningTasks()) {
44920
+ this.stopPolling();
44921
+ if (this.perfAggregator.taskCount >= 2) {
44922
+ const report = this.perfAggregator.getReport();
44923
+ log("[perf] Session report:", report);
44924
+ }
44925
+ }
44926
+ } finally {
44927
+ if (start !== undefined) {
44928
+ const duration3 = performance.now() - start;
44929
+ this.perfTracer.recordPolling(duration3, this.getRunningTasks().length, new Set(...this.tasks.values().map((t) => t.parentSessionID).filter(Boolean)).size);
44652
44930
  }
44653
44931
  }
44654
44932
  }
@@ -44686,14 +44964,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
44686
44964
  return listener;
44687
44965
  }
44688
44966
  function getMessageDir10(sessionID) {
44689
- if (!existsSync46(MESSAGE_STORAGE))
44967
+ if (!existsSync48(MESSAGE_STORAGE))
44690
44968
  return null;
44691
- const directPath = join55(MESSAGE_STORAGE, sessionID);
44692
- if (existsSync46(directPath))
44969
+ const directPath = join56(MESSAGE_STORAGE, sessionID);
44970
+ if (existsSync48(directPath))
44693
44971
  return directPath;
44694
- for (const dir of readdirSync16(MESSAGE_STORAGE)) {
44695
- const sessionPath = join55(MESSAGE_STORAGE, dir, sessionID);
44696
- if (existsSync46(sessionPath))
44972
+ for (const dir of readdirSync17(MESSAGE_STORAGE)) {
44973
+ const sessionPath = join56(MESSAGE_STORAGE, dir, sessionID);
44974
+ if (existsSync48(sessionPath))
44697
44975
  return sessionPath;
44698
44976
  }
44699
44977
  return null;
@@ -62607,6 +62885,7 @@ var HookNameSchema = exports_external2.enum([
62607
62885
  "edit-error-recovery",
62608
62886
  "delegate-task-retry",
62609
62887
  "prometheus-md-only",
62888
+ "perf-profiler",
62610
62889
  "start-work",
62611
62890
  "atlas"
62612
62891
  ]);
@@ -62720,11 +62999,21 @@ var DynamicContextPruningConfigSchema = exports_external2.object({
62720
62999
  }).optional()
62721
63000
  }).optional()
62722
63001
  });
63002
+ var ProfilingConfigSchema = exports_external2.object({
63003
+ enabled: exports_external2.boolean().default(false),
63004
+ output_dir: exports_external2.string().optional(),
63005
+ slow_threshold_ms: exports_external2.number().default(100),
63006
+ memory_snapshot_interval: exports_external2.number().default(5),
63007
+ trace_api: exports_external2.boolean().default(true),
63008
+ trace_fileio: exports_external2.boolean().default(true),
63009
+ trace_polling: exports_external2.boolean().default(true)
63010
+ });
62723
63011
  var ExperimentalConfigSchema = exports_external2.object({
62724
63012
  aggressive_truncation: exports_external2.boolean().optional(),
62725
63013
  auto_resume: exports_external2.boolean().optional(),
62726
63014
  truncate_all_tool_outputs: exports_external2.boolean().optional(),
62727
- dynamic_context_pruning: DynamicContextPruningConfigSchema.optional()
63015
+ dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
63016
+ profiling: ProfilingConfigSchema.optional()
62728
63017
  });
62729
63018
  var SkillSourceSchema = exports_external2.union([
62730
63019
  exports_external2.string(),
@@ -65753,7 +66042,7 @@ init_file_utils();
65753
66042
  init_shared();
65754
66043
  init_logger();
65755
66044
  import { promises as fs11 } from "fs";
65756
- import { join as join57, basename as basename6 } from "path";
66045
+ import { join as join58, basename as basename6 } from "path";
65757
66046
  async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
65758
66047
  try {
65759
66048
  await fs11.access(commandsDir);
@@ -65783,7 +66072,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
65783
66072
  if (entry.isDirectory()) {
65784
66073
  if (entry.name.startsWith("."))
65785
66074
  continue;
65786
- const subDirPath = join57(commandsDir, entry.name);
66075
+ const subDirPath = join58(commandsDir, entry.name);
65787
66076
  const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
65788
66077
  const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
65789
66078
  commands2.push(...subCommands);
@@ -65791,7 +66080,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
65791
66080
  }
65792
66081
  if (!isMarkdownFile(entry))
65793
66082
  continue;
65794
- const commandPath = join57(commandsDir, entry.name);
66083
+ const commandPath = join58(commandsDir, entry.name);
65795
66084
  const baseCommandName = basename6(entry.name, ".md");
65796
66085
  const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
65797
66086
  try {
@@ -65838,23 +66127,23 @@ function commandsToRecord(commands2) {
65838
66127
  return result;
65839
66128
  }
65840
66129
  async function loadUserCommands() {
65841
- const userCommandsDir = join57(getClaudeConfigDir(), "commands");
66130
+ const userCommandsDir = join58(getClaudeConfigDir(), "commands");
65842
66131
  const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
65843
66132
  return commandsToRecord(commands2);
65844
66133
  }
65845
66134
  async function loadProjectCommands() {
65846
- const projectCommandsDir = join57(process.cwd(), ".claude", "commands");
66135
+ const projectCommandsDir = join58(process.cwd(), ".claude", "commands");
65847
66136
  const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
65848
66137
  return commandsToRecord(commands2);
65849
66138
  }
65850
66139
  async function loadOpencodeGlobalCommands() {
65851
66140
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
65852
- const opencodeCommandsDir = join57(configDir, "command");
66141
+ const opencodeCommandsDir = join58(configDir, "command");
65853
66142
  const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
65854
66143
  return commandsToRecord(commands2);
65855
66144
  }
65856
66145
  async function loadOpencodeProjectCommands() {
65857
- const opencodeProjectDir = join57(process.cwd(), ".opencode", "command");
66146
+ const opencodeProjectDir = join58(process.cwd(), ".opencode", "command");
65858
66147
  const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
65859
66148
  return commandsToRecord(commands2);
65860
66149
  }
@@ -65862,8 +66151,8 @@ async function loadOpencodeProjectCommands() {
65862
66151
  init_frontmatter();
65863
66152
  init_file_utils();
65864
66153
  init_shared();
65865
- import { existsSync as existsSync48, readdirSync as readdirSync17, readFileSync as readFileSync30 } from "fs";
65866
- import { join as join58, basename as basename7 } from "path";
66154
+ import { existsSync as existsSync50, readdirSync as readdirSync18, readFileSync as readFileSync31 } from "fs";
66155
+ import { join as join59, basename as basename7 } from "path";
65867
66156
  function parseToolsConfig(toolsStr) {
65868
66157
  if (!toolsStr)
65869
66158
  return;
@@ -65877,18 +66166,18 @@ function parseToolsConfig(toolsStr) {
65877
66166
  return result;
65878
66167
  }
65879
66168
  function loadAgentsFromDir(agentsDir, scope) {
65880
- if (!existsSync48(agentsDir)) {
66169
+ if (!existsSync50(agentsDir)) {
65881
66170
  return [];
65882
66171
  }
65883
- const entries = readdirSync17(agentsDir, { withFileTypes: true });
66172
+ const entries = readdirSync18(agentsDir, { withFileTypes: true });
65884
66173
  const agents = [];
65885
66174
  for (const entry of entries) {
65886
66175
  if (!isMarkdownFile(entry))
65887
66176
  continue;
65888
- const agentPath = join58(agentsDir, entry.name);
66177
+ const agentPath = join59(agentsDir, entry.name);
65889
66178
  const agentName = basename7(entry.name, ".md");
65890
66179
  try {
65891
- const content = readFileSync30(agentPath, "utf-8");
66180
+ const content = readFileSync31(agentPath, "utf-8");
65892
66181
  const { data, body } = parseFrontmatter(content);
65893
66182
  const name = data.name || agentName;
65894
66183
  const originalDescription = data.description || "";
@@ -65915,7 +66204,7 @@ function loadAgentsFromDir(agentsDir, scope) {
65915
66204
  return agents;
65916
66205
  }
65917
66206
  function loadUserAgents() {
65918
- const userAgentsDir = join58(getClaudeConfigDir(), "agents");
66207
+ const userAgentsDir = join59(getClaudeConfigDir(), "agents");
65919
66208
  const agents = loadAgentsFromDir(userAgentsDir, "user");
65920
66209
  const result = {};
65921
66210
  for (const agent of agents) {
@@ -65924,7 +66213,7 @@ function loadUserAgents() {
65924
66213
  return result;
65925
66214
  }
65926
66215
  function loadProjectAgents() {
65927
- const projectAgentsDir = join58(process.cwd(), ".claude", "agents");
66216
+ const projectAgentsDir = join59(process.cwd(), ".claude", "agents");
65928
66217
  const agents = loadAgentsFromDir(projectAgentsDir, "project");
65929
66218
  const result = {};
65930
66219
  for (const agent of agents) {
@@ -65936,18 +66225,18 @@ function loadProjectAgents() {
65936
66225
  init_frontmatter();
65937
66226
  init_file_utils();
65938
66227
  init_logger();
65939
- import { existsSync as existsSync49, readdirSync as readdirSync18, readFileSync as readFileSync31 } from "fs";
66228
+ import { existsSync as existsSync51, readdirSync as readdirSync19, readFileSync as readFileSync32 } from "fs";
65940
66229
  import { homedir as homedir13 } from "os";
65941
- import { join as join59, basename as basename8 } from "path";
66230
+ import { join as join60, basename as basename8 } from "path";
65942
66231
  var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
65943
66232
  function getPluginsBaseDir() {
65944
66233
  if (process.env.CLAUDE_PLUGINS_HOME) {
65945
66234
  return process.env.CLAUDE_PLUGINS_HOME;
65946
66235
  }
65947
- return join59(homedir13(), ".claude", "plugins");
66236
+ return join60(homedir13(), ".claude", "plugins");
65948
66237
  }
65949
66238
  function getInstalledPluginsPath() {
65950
- return join59(getPluginsBaseDir(), "installed_plugins.json");
66239
+ return join60(getPluginsBaseDir(), "installed_plugins.json");
65951
66240
  }
65952
66241
  function resolvePluginPath(path8, pluginRoot) {
65953
66242
  return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
@@ -65972,11 +66261,11 @@ function resolvePluginPaths(obj, pluginRoot) {
65972
66261
  }
65973
66262
  function loadInstalledPlugins() {
65974
66263
  const dbPath = getInstalledPluginsPath();
65975
- if (!existsSync49(dbPath)) {
66264
+ if (!existsSync51(dbPath)) {
65976
66265
  return null;
65977
66266
  }
65978
66267
  try {
65979
- const content = readFileSync31(dbPath, "utf-8");
66268
+ const content = readFileSync32(dbPath, "utf-8");
65980
66269
  return JSON.parse(content);
65981
66270
  } catch (error92) {
65982
66271
  log("Failed to load installed plugins database", error92);
@@ -65987,15 +66276,15 @@ function getClaudeSettingsPath() {
65987
66276
  if (process.env.CLAUDE_SETTINGS_PATH) {
65988
66277
  return process.env.CLAUDE_SETTINGS_PATH;
65989
66278
  }
65990
- return join59(homedir13(), ".claude", "settings.json");
66279
+ return join60(homedir13(), ".claude", "settings.json");
65991
66280
  }
65992
66281
  function loadClaudeSettings() {
65993
66282
  const settingsPath = getClaudeSettingsPath();
65994
- if (!existsSync49(settingsPath)) {
66283
+ if (!existsSync51(settingsPath)) {
65995
66284
  return null;
65996
66285
  }
65997
66286
  try {
65998
- const content = readFileSync31(settingsPath, "utf-8");
66287
+ const content = readFileSync32(settingsPath, "utf-8");
65999
66288
  return JSON.parse(content);
66000
66289
  } catch (error92) {
66001
66290
  log("Failed to load Claude settings", error92);
@@ -66003,12 +66292,12 @@ function loadClaudeSettings() {
66003
66292
  }
66004
66293
  }
66005
66294
  function loadPluginManifest(installPath) {
66006
- const manifestPath = join59(installPath, ".claude-plugin", "plugin.json");
66007
- if (!existsSync49(manifestPath)) {
66295
+ const manifestPath = join60(installPath, ".claude-plugin", "plugin.json");
66296
+ if (!existsSync51(manifestPath)) {
66008
66297
  return null;
66009
66298
  }
66010
66299
  try {
66011
- const content = readFileSync31(manifestPath, "utf-8");
66300
+ const content = readFileSync32(manifestPath, "utf-8");
66012
66301
  return JSON.parse(content);
66013
66302
  } catch (error92) {
66014
66303
  log(`Failed to load plugin manifest from ${manifestPath}`, error92);
@@ -66055,7 +66344,7 @@ function discoverInstalledPlugins(options) {
66055
66344
  continue;
66056
66345
  }
66057
66346
  const { installPath, scope, version: version3 } = installation;
66058
- if (!existsSync49(installPath)) {
66347
+ if (!existsSync51(installPath)) {
66059
66348
  errors5.push({
66060
66349
  pluginKey,
66061
66350
  installPath,
@@ -66073,21 +66362,21 @@ function discoverInstalledPlugins(options) {
66073
66362
  pluginKey,
66074
66363
  manifest: manifest ?? undefined
66075
66364
  };
66076
- if (existsSync49(join59(installPath, "commands"))) {
66077
- loadedPlugin.commandsDir = join59(installPath, "commands");
66365
+ if (existsSync51(join60(installPath, "commands"))) {
66366
+ loadedPlugin.commandsDir = join60(installPath, "commands");
66078
66367
  }
66079
- if (existsSync49(join59(installPath, "agents"))) {
66080
- loadedPlugin.agentsDir = join59(installPath, "agents");
66368
+ if (existsSync51(join60(installPath, "agents"))) {
66369
+ loadedPlugin.agentsDir = join60(installPath, "agents");
66081
66370
  }
66082
- if (existsSync49(join59(installPath, "skills"))) {
66083
- loadedPlugin.skillsDir = join59(installPath, "skills");
66371
+ if (existsSync51(join60(installPath, "skills"))) {
66372
+ loadedPlugin.skillsDir = join60(installPath, "skills");
66084
66373
  }
66085
- const hooksPath = join59(installPath, "hooks", "hooks.json");
66086
- if (existsSync49(hooksPath)) {
66374
+ const hooksPath = join60(installPath, "hooks", "hooks.json");
66375
+ if (existsSync51(hooksPath)) {
66087
66376
  loadedPlugin.hooksPath = hooksPath;
66088
66377
  }
66089
- const mcpPath = join59(installPath, ".mcp.json");
66090
- if (existsSync49(mcpPath)) {
66378
+ const mcpPath = join60(installPath, ".mcp.json");
66379
+ if (existsSync51(mcpPath)) {
66091
66380
  loadedPlugin.mcpPath = mcpPath;
66092
66381
  }
66093
66382
  plugins.push(loadedPlugin);
@@ -66098,17 +66387,17 @@ function discoverInstalledPlugins(options) {
66098
66387
  function loadPluginCommands(plugins) {
66099
66388
  const commands2 = {};
66100
66389
  for (const plugin of plugins) {
66101
- if (!plugin.commandsDir || !existsSync49(plugin.commandsDir))
66390
+ if (!plugin.commandsDir || !existsSync51(plugin.commandsDir))
66102
66391
  continue;
66103
- const entries = readdirSync18(plugin.commandsDir, { withFileTypes: true });
66392
+ const entries = readdirSync19(plugin.commandsDir, { withFileTypes: true });
66104
66393
  for (const entry of entries) {
66105
66394
  if (!isMarkdownFile(entry))
66106
66395
  continue;
66107
- const commandPath = join59(plugin.commandsDir, entry.name);
66396
+ const commandPath = join60(plugin.commandsDir, entry.name);
66108
66397
  const commandName = basename8(entry.name, ".md");
66109
66398
  const namespacedName = `${plugin.name}:${commandName}`;
66110
66399
  try {
66111
- const content = readFileSync31(commandPath, "utf-8");
66400
+ const content = readFileSync32(commandPath, "utf-8");
66112
66401
  const { data, body } = parseFrontmatter(content);
66113
66402
  const wrappedTemplate = `<command-instruction>
66114
66403
  ${body.trim()}
@@ -66140,21 +66429,21 @@ $ARGUMENTS
66140
66429
  function loadPluginSkillsAsCommands(plugins) {
66141
66430
  const skills = {};
66142
66431
  for (const plugin of plugins) {
66143
- if (!plugin.skillsDir || !existsSync49(plugin.skillsDir))
66432
+ if (!plugin.skillsDir || !existsSync51(plugin.skillsDir))
66144
66433
  continue;
66145
- const entries = readdirSync18(plugin.skillsDir, { withFileTypes: true });
66434
+ const entries = readdirSync19(plugin.skillsDir, { withFileTypes: true });
66146
66435
  for (const entry of entries) {
66147
66436
  if (entry.name.startsWith("."))
66148
66437
  continue;
66149
- const skillPath = join59(plugin.skillsDir, entry.name);
66438
+ const skillPath = join60(plugin.skillsDir, entry.name);
66150
66439
  if (!entry.isDirectory() && !entry.isSymbolicLink())
66151
66440
  continue;
66152
66441
  const resolvedPath = resolveSymlink(skillPath);
66153
- const skillMdPath = join59(resolvedPath, "SKILL.md");
66154
- if (!existsSync49(skillMdPath))
66442
+ const skillMdPath = join60(resolvedPath, "SKILL.md");
66443
+ if (!existsSync51(skillMdPath))
66155
66444
  continue;
66156
66445
  try {
66157
- const content = readFileSync31(skillMdPath, "utf-8");
66446
+ const content = readFileSync32(skillMdPath, "utf-8");
66158
66447
  const { data, body } = parseFrontmatter(content);
66159
66448
  const skillName = data.name || entry.name;
66160
66449
  const namespacedName = `${plugin.name}:${skillName}`;
@@ -66201,17 +66490,17 @@ function parseToolsConfig2(toolsStr) {
66201
66490
  function loadPluginAgents(plugins) {
66202
66491
  const agents = {};
66203
66492
  for (const plugin of plugins) {
66204
- if (!plugin.agentsDir || !existsSync49(plugin.agentsDir))
66493
+ if (!plugin.agentsDir || !existsSync51(plugin.agentsDir))
66205
66494
  continue;
66206
- const entries = readdirSync18(plugin.agentsDir, { withFileTypes: true });
66495
+ const entries = readdirSync19(plugin.agentsDir, { withFileTypes: true });
66207
66496
  for (const entry of entries) {
66208
66497
  if (!isMarkdownFile(entry))
66209
66498
  continue;
66210
- const agentPath = join59(plugin.agentsDir, entry.name);
66499
+ const agentPath = join60(plugin.agentsDir, entry.name);
66211
66500
  const agentName = basename8(entry.name, ".md");
66212
66501
  const namespacedName = `${plugin.name}:${agentName}`;
66213
66502
  try {
66214
- const content = readFileSync31(agentPath, "utf-8");
66503
+ const content = readFileSync32(agentPath, "utf-8");
66215
66504
  const { data, body } = parseFrontmatter(content);
66216
66505
  const name = data.name || agentName;
66217
66506
  const originalDescription = data.description || "";
@@ -66237,7 +66526,7 @@ function loadPluginAgents(plugins) {
66237
66526
  async function loadPluginMcpServers(plugins) {
66238
66527
  const servers = {};
66239
66528
  for (const plugin of plugins) {
66240
- if (!plugin.mcpPath || !existsSync49(plugin.mcpPath))
66529
+ if (!plugin.mcpPath || !existsSync51(plugin.mcpPath))
66241
66530
  continue;
66242
66531
  try {
66243
66532
  const content = await Bun.file(plugin.mcpPath).text();
@@ -66269,10 +66558,10 @@ async function loadPluginMcpServers(plugins) {
66269
66558
  function loadPluginHooksConfigs(plugins) {
66270
66559
  const configs = [];
66271
66560
  for (const plugin of plugins) {
66272
- if (!plugin.hooksPath || !existsSync49(plugin.hooksPath))
66561
+ if (!plugin.hooksPath || !existsSync51(plugin.hooksPath))
66273
66562
  continue;
66274
66563
  try {
66275
- const content = readFileSync31(plugin.hooksPath, "utf-8");
66564
+ const content = readFileSync32(plugin.hooksPath, "utf-8");
66276
66565
  let config4 = JSON.parse(content);
66277
66566
  config4 = resolvePluginPaths(config4, plugin.installPath);
66278
66567
  configs.push(config4);
@@ -67798,6 +68087,44 @@ function createConfigHandler(deps) {
67798
68087
  };
67799
68088
  };
67800
68089
  }
68090
+ // src/index.ts
68091
+ init_perf_tracer();
68092
+ init_fileio_monitor();
68093
+
68094
+ // src/tools/perf-profiler/client-patch.ts
68095
+ function patchSessionClient(client2, tracer) {
68096
+ if (!tracer.isEnabled())
68097
+ return;
68098
+ const session = client2.session;
68099
+ if (!session || typeof session !== "object")
68100
+ return;
68101
+ function wrap(methodName, extractMessageCount) {
68102
+ const original = session[methodName];
68103
+ if (typeof original !== "function")
68104
+ return;
68105
+ session[methodName] = async function(opts) {
68106
+ const start = performance.now();
68107
+ let error92;
68108
+ try {
68109
+ const result = await original.call(session, opts);
68110
+ const durationMs = performance.now() - start;
68111
+ tracer.recordApiCall(methodName, durationMs, opts?.path?.id ?? "", extractMessageCount ? extractMessageCount(result) : undefined);
68112
+ return result;
68113
+ } catch (err) {
68114
+ const durationMs = performance.now() - start;
68115
+ error92 = err instanceof Error ? err.message : String(err);
68116
+ tracer.recordApiCall(methodName, durationMs, opts?.path?.id ?? "", undefined, error92);
68117
+ throw err;
68118
+ }
68119
+ };
68120
+ }
68121
+ wrap("messages", (r) => r?.data?.length ?? undefined);
68122
+ wrap("prompt", (r) => r?.data ? 1 : undefined);
68123
+ wrap("todo", (r) => r?.data?.length ?? undefined);
68124
+ wrap("status", (r) => r?.data ? Object.keys(r.data).length : undefined);
68125
+ wrap("summarize");
68126
+ }
68127
+
67801
68128
  // src/index.ts
67802
68129
  var OhMyOpenCodePlugin = async (ctx) => {
67803
68130
  log("[OhMyOpenCodePlugin] ENTRY - plugin loading", { directory: ctx.directory });
@@ -67863,6 +68190,34 @@ var OhMyOpenCodePlugin = async (ctx) => {
67863
68190
  const taskResumeInfo = createTaskResumeInfoHook();
67864
68191
  const backgroundManager = new BackgroundManager(ctx, pluginConfig.background_task);
67865
68192
  const atlasHook = isHookEnabled("atlas") ? createAtlasHook(ctx, { directory: ctx.directory, backgroundManager }) : null;
68193
+ const perfTracer = pluginConfig.experimental?.profiling?.enabled ? new PerfTracer({
68194
+ enabled: true,
68195
+ outputDir: pluginConfig.experimental.profiling.output_dir,
68196
+ slowThreshold: pluginConfig.experimental.profiling.slow_threshold_ms,
68197
+ memorySnapshotInterval: pluginConfig.experimental.profiling.memory_snapshot_interval
68198
+ }) : new PerfTracer({ enabled: false });
68199
+ const memoryProbes = {};
68200
+ if (perfTracer.isEnabled()) {
68201
+ memoryProbes.subagentSessions = () => subagentSessions.size;
68202
+ memoryProbes.backgroundRunningTasks = () => backgroundManager.getRunningTasks().length;
68203
+ memoryProbes.backgroundCompletedTasks = () => backgroundManager.getCompletedTasks().length;
68204
+ }
68205
+ const perfProfiler = isHookEnabled("perf-profiler") ? createPerfProfilerHook({
68206
+ config: pluginConfig.experimental?.profiling ?? { enabled: false, slow_threshold_ms: 100, memory_snapshot_interval: 5, trace_api: true, trace_fileio: true, trace_polling: true },
68207
+ tracer: perfTracer,
68208
+ memoryProbes
68209
+ }) : null;
68210
+ if (perfTracer.isEnabled()) {
68211
+ try {
68212
+ patchSessionClient(ctx.client, perfTracer);
68213
+ } catch {}
68214
+ try {
68215
+ setFileIOMonitor(createFileIOMonitor(perfTracer));
68216
+ } catch {}
68217
+ try {
68218
+ backgroundManager.setPerfTracer(perfTracer);
68219
+ } catch {}
68220
+ }
67866
68221
  initTaskToastManager(ctx.client);
67867
68222
  const todoContinuationEnforcer = isHookEnabled("todo-continuation-enforcer") ? createTodoContinuationEnforcer(ctx, { backgroundManager }) : null;
67868
68223
  if (sessionRecovery && todoContinuationEnforcer) {
@@ -67927,6 +68282,27 @@ var OhMyOpenCodePlugin = async (ctx) => {
67927
68282
  pluginConfig,
67928
68283
  modelCacheState
67929
68284
  });
68285
+ async function wrapWithTiming(tracer, pipeline2, hookName, fn, sessionID, tool3) {
68286
+ const start = performance.now();
68287
+ let error92;
68288
+ try {
68289
+ await fn();
68290
+ } catch (e) {
68291
+ error92 = String(e);
68292
+ throw e;
68293
+ } finally {
68294
+ tracer.recordHook(pipeline2, hookName, performance.now() - start, sessionID ?? "", tool3, error92);
68295
+ }
68296
+ }
68297
+ function getEventSessionID(input) {
68298
+ const props = input.event.properties;
68299
+ if (!props)
68300
+ return "";
68301
+ const info = props.info;
68302
+ if (input.event.type === "session.deleted" || input.event.type === "session.created")
68303
+ return info?.id ?? "";
68304
+ return props.sessionID ?? "";
68305
+ }
67930
68306
  return {
67931
68307
  tool: {
67932
68308
  ...builtinTools,
@@ -67953,10 +68329,17 @@ var OhMyOpenCodePlugin = async (ctx) => {
67953
68329
  } else {
67954
68330
  applyAgentVariant(pluginConfig, input.agent, message);
67955
68331
  }
67956
- await keywordDetector?.["chat.message"]?.(input, output);
67957
- await claudeCodeHooks["chat.message"]?.(input, output);
67958
- await autoSlashCommand?.["chat.message"]?.(input, output);
67959
- await startWork?.["chat.message"]?.(input, output);
68332
+ const pipelineStart = performance.now();
68333
+ let hookCount = 0;
68334
+ await wrapWithTiming(perfTracer, "chat.message", "keywordDetector", () => keywordDetector?.["chat.message"]?.(input, output), input.sessionID);
68335
+ hookCount++;
68336
+ await wrapWithTiming(perfTracer, "chat.message", "claudeCodeHooks", () => claudeCodeHooks["chat.message"]?.(input, output), input.sessionID);
68337
+ hookCount++;
68338
+ await wrapWithTiming(perfTracer, "chat.message", "autoSlashCommand", () => autoSlashCommand?.["chat.message"]?.(input, output), input.sessionID);
68339
+ hookCount++;
68340
+ await wrapWithTiming(perfTracer, "chat.message", "startWork", () => startWork?.["chat.message"]?.(input, output), input.sessionID);
68341
+ hookCount++;
68342
+ perfTracer.recordPipeline("chat.message", performance.now() - pipelineStart, hookCount, input.sessionID);
67960
68343
  if (ralphLoop) {
67961
68344
  const parts = output.parts;
67962
68345
  const promptText = parts?.filter((p) => p.type === "text" && p.text).map((p) => p.text).join(`
@@ -67986,27 +68369,49 @@ var OhMyOpenCodePlugin = async (ctx) => {
67986
68369
  }
67987
68370
  }
67988
68371
  },
68372
+ "chat.params": async (input, output) => {
68373
+ await thinkMode?.["chat.params"]?.(input, output);
68374
+ },
67989
68375
  "experimental.chat.messages.transform": async (input, output) => {
67990
68376
  await contextInjectorMessagesTransform?.["experimental.chat.messages.transform"]?.(input, output);
67991
68377
  await thinkingBlockValidator?.["experimental.chat.messages.transform"]?.(input, output);
67992
68378
  },
67993
68379
  config: configHandler,
67994
68380
  event: async (input) => {
67995
- await autoUpdateChecker?.event(input);
67996
- await claudeCodeHooks.event(input);
67997
- await backgroundNotificationHook?.event(input);
67998
- await sessionNotification?.(input);
67999
- await todoContinuationEnforcer?.handler(input);
68000
- await contextWindowMonitor?.event(input);
68001
- await directoryAgentsInjector?.event(input);
68002
- await directoryReadmeInjector?.event(input);
68003
- await rulesInjector?.event(input);
68004
- await thinkMode?.event(input);
68005
- await anthropicContextWindowLimitRecovery?.event(input);
68006
- await agentUsageReminder?.event(input);
68007
- await interactiveBashSession?.event(input);
68008
- await ralphLoop?.event(input);
68009
- await atlasHook?.handler(input);
68381
+ const pipelineStart = performance.now();
68382
+ let hookCount = 0;
68383
+ await perfProfiler?.event?.(input);
68384
+ const evtSessionID = getEventSessionID(input);
68385
+ await wrapWithTiming(perfTracer, "event", "autoUpdateChecker", () => autoUpdateChecker?.event(input), evtSessionID);
68386
+ hookCount++;
68387
+ await wrapWithTiming(perfTracer, "event", "claudeCodeHooks", () => claudeCodeHooks.event(input), evtSessionID);
68388
+ hookCount++;
68389
+ await wrapWithTiming(perfTracer, "event", "backgroundNotificationHook", () => backgroundNotificationHook?.event(input), evtSessionID);
68390
+ hookCount++;
68391
+ await wrapWithTiming(perfTracer, "event", "sessionNotification", () => sessionNotification?.(input), evtSessionID);
68392
+ hookCount++;
68393
+ await wrapWithTiming(perfTracer, "event", "todoContinuationEnforcer", () => todoContinuationEnforcer?.handler(input), evtSessionID);
68394
+ hookCount++;
68395
+ await wrapWithTiming(perfTracer, "event", "contextWindowMonitor", () => contextWindowMonitor?.event(input), evtSessionID);
68396
+ hookCount++;
68397
+ await wrapWithTiming(perfTracer, "event", "directoryAgentsInjector", () => directoryAgentsInjector?.event(input), evtSessionID);
68398
+ hookCount++;
68399
+ await wrapWithTiming(perfTracer, "event", "directoryReadmeInjector", () => directoryReadmeInjector?.event(input), evtSessionID);
68400
+ hookCount++;
68401
+ await wrapWithTiming(perfTracer, "event", "rulesInjector", () => rulesInjector?.event(input), evtSessionID);
68402
+ hookCount++;
68403
+ await wrapWithTiming(perfTracer, "event", "thinkMode", () => thinkMode?.event(input), evtSessionID);
68404
+ hookCount++;
68405
+ await wrapWithTiming(perfTracer, "event", "anthropicContextWindowLimitRecovery", () => anthropicContextWindowLimitRecovery?.event(input), evtSessionID);
68406
+ hookCount++;
68407
+ await wrapWithTiming(perfTracer, "event", "agentUsageReminder", () => agentUsageReminder?.event(input), evtSessionID);
68408
+ hookCount++;
68409
+ await wrapWithTiming(perfTracer, "event", "interactiveBashSession", () => interactiveBashSession?.event(input), evtSessionID);
68410
+ hookCount++;
68411
+ await wrapWithTiming(perfTracer, "event", "ralphLoop", () => ralphLoop?.event(input), evtSessionID);
68412
+ hookCount++;
68413
+ await wrapWithTiming(perfTracer, "event", "atlasHook", () => atlasHook?.handler(input), evtSessionID);
68414
+ hookCount++;
68010
68415
  const { event } = input;
68011
68416
  const props = event.properties;
68012
68417
  if (event.type === "session.created") {
@@ -68059,17 +68464,30 @@ var OhMyOpenCodePlugin = async (ctx) => {
68059
68464
  }
68060
68465
  }
68061
68466
  }
68467
+ perfTracer.recordPipeline("event", performance.now() - pipelineStart, hookCount, evtSessionID);
68468
+ perfTracer.flush();
68062
68469
  },
68063
68470
  "tool.execute.before": async (input, output) => {
68064
- await questionLabelTruncator["tool.execute.before"]?.(input, output);
68065
- await claudeCodeHooks["tool.execute.before"](input, output);
68066
- await nonInteractiveEnv?.["tool.execute.before"](input, output);
68067
- await commentChecker?.["tool.execute.before"](input, output);
68068
- await directoryAgentsInjector?.["tool.execute.before"]?.(input, output);
68069
- await directoryReadmeInjector?.["tool.execute.before"]?.(input, output);
68070
- await rulesInjector?.["tool.execute.before"]?.(input, output);
68071
- await prometheusMdOnly?.["tool.execute.before"]?.(input, output);
68072
- await atlasHook?.["tool.execute.before"]?.(input, output);
68471
+ const pipelineStart = performance.now();
68472
+ let hookCount = 0;
68473
+ await wrapWithTiming(perfTracer, "tool.execute.before", "questionLabelTruncator", () => questionLabelTruncator["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68474
+ hookCount++;
68475
+ await wrapWithTiming(perfTracer, "tool.execute.before", "claudeCodeHooks", () => claudeCodeHooks["tool.execute.before"](input, output), input.sessionID, input.tool);
68476
+ hookCount++;
68477
+ await wrapWithTiming(perfTracer, "tool.execute.before", "nonInteractiveEnv", () => nonInteractiveEnv?.["tool.execute.before"](input, output), input.sessionID, input.tool);
68478
+ hookCount++;
68479
+ await wrapWithTiming(perfTracer, "tool.execute.before", "commentChecker", () => commentChecker?.["tool.execute.before"](input, output), input.sessionID, input.tool);
68480
+ hookCount++;
68481
+ await wrapWithTiming(perfTracer, "tool.execute.before", "directoryAgentsInjector", () => directoryAgentsInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68482
+ hookCount++;
68483
+ await wrapWithTiming(perfTracer, "tool.execute.before", "directoryReadmeInjector", () => directoryReadmeInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68484
+ hookCount++;
68485
+ await wrapWithTiming(perfTracer, "tool.execute.before", "rulesInjector", () => rulesInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68486
+ hookCount++;
68487
+ await wrapWithTiming(perfTracer, "tool.execute.before", "prometheusMdOnly", () => prometheusMdOnly?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68488
+ hookCount++;
68489
+ await wrapWithTiming(perfTracer, "tool.execute.before", "atlasHook", () => atlasHook?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
68490
+ hookCount++;
68073
68491
  if (input.tool === "task") {
68074
68492
  const args = output.args;
68075
68493
  const subagentType = args.subagent_type;
@@ -68109,22 +68527,40 @@ var OhMyOpenCodePlugin = async (ctx) => {
68109
68527
  });
68110
68528
  }
68111
68529
  }
68530
+ perfTracer.recordPipeline("tool.execute.before", performance.now() - pipelineStart, hookCount, input.sessionID);
68112
68531
  },
68113
68532
  "tool.execute.after": async (input, output) => {
68114
- await claudeCodeHooks["tool.execute.after"](input, output);
68115
- await toolOutputTruncator?.["tool.execute.after"](input, output);
68116
- await contextWindowMonitor?.["tool.execute.after"](input, output);
68117
- await commentChecker?.["tool.execute.after"](input, output);
68118
- await directoryAgentsInjector?.["tool.execute.after"](input, output);
68119
- await directoryReadmeInjector?.["tool.execute.after"](input, output);
68120
- await rulesInjector?.["tool.execute.after"](input, output);
68121
- await emptyTaskResponseDetector?.["tool.execute.after"](input, output);
68122
- await agentUsageReminder?.["tool.execute.after"](input, output);
68123
- await interactiveBashSession?.["tool.execute.after"](input, output);
68124
- await editErrorRecovery?.["tool.execute.after"](input, output);
68125
- await delegateTaskRetry?.["tool.execute.after"](input, output);
68126
- await atlasHook?.["tool.execute.after"]?.(input, output);
68127
- await taskResumeInfo["tool.execute.after"](input, output);
68533
+ const pipelineStart = performance.now();
68534
+ let hookCount = 0;
68535
+ await wrapWithTiming(perfTracer, "tool.execute.after", "claudeCodeHooks", () => claudeCodeHooks["tool.execute.after"](input, output), input.sessionID, input.tool);
68536
+ hookCount++;
68537
+ await wrapWithTiming(perfTracer, "tool.execute.after", "toolOutputTruncator", () => toolOutputTruncator?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68538
+ hookCount++;
68539
+ await wrapWithTiming(perfTracer, "tool.execute.after", "contextWindowMonitor", () => contextWindowMonitor?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68540
+ hookCount++;
68541
+ await wrapWithTiming(perfTracer, "tool.execute.after", "commentChecker", () => commentChecker?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68542
+ hookCount++;
68543
+ await wrapWithTiming(perfTracer, "tool.execute.after", "directoryAgentsInjector", () => directoryAgentsInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68544
+ hookCount++;
68545
+ await wrapWithTiming(perfTracer, "tool.execute.after", "directoryReadmeInjector", () => directoryReadmeInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68546
+ hookCount++;
68547
+ await wrapWithTiming(perfTracer, "tool.execute.after", "rulesInjector", () => rulesInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68548
+ hookCount++;
68549
+ await wrapWithTiming(perfTracer, "tool.execute.after", "emptyTaskResponseDetector", () => emptyTaskResponseDetector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68550
+ hookCount++;
68551
+ await wrapWithTiming(perfTracer, "tool.execute.after", "agentUsageReminder", () => agentUsageReminder?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68552
+ hookCount++;
68553
+ await wrapWithTiming(perfTracer, "tool.execute.after", "interactiveBashSession", () => interactiveBashSession?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68554
+ hookCount++;
68555
+ await wrapWithTiming(perfTracer, "tool.execute.after", "editErrorRecovery", () => editErrorRecovery?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68556
+ hookCount++;
68557
+ await wrapWithTiming(perfTracer, "tool.execute.after", "delegateTaskRetry", () => delegateTaskRetry?.["tool.execute.after"](input, output), input.sessionID, input.tool);
68558
+ hookCount++;
68559
+ await wrapWithTiming(perfTracer, "tool.execute.after", "atlasHook", () => atlasHook?.["tool.execute.after"]?.(input, output), input.sessionID, input.tool);
68560
+ hookCount++;
68561
+ await wrapWithTiming(perfTracer, "tool.execute.after", "taskResumeInfo", () => taskResumeInfo["tool.execute.after"](input, output), input.sessionID, input.tool);
68562
+ hookCount++;
68563
+ perfTracer.recordPipeline("tool.execute.after", performance.now() - pipelineStart, hookCount, input.sessionID);
68128
68564
  }
68129
68565
  };
68130
68566
  };