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