@skj1724/oh-my-opencode 3.23.3 → 3.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/utils.d.ts +1 -1
- package/dist/cli/index.js +49 -30
- 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/__tests__/fix-checkbox-auto-update.test.d.ts +1 -0
- package/dist/hooks/atlas/index.d.ts +21 -0
- package/dist/hooks/thinking-language-validator/constants.d.ts +7 -1
- package/dist/index.js +948 -734
- package/dist/shared/agent-identity-resolver.d.ts +8 -0
- package/dist/shared/agent-identity-resolver.test.d.ts +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/language-detector.d.ts +1 -1
- package/dist/tools/delegate-task/tools.d.ts +1 -1
- package/package.json +89 -89
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)) {
|
|
@@ -6105,7 +6158,7 @@ function isEnglishText(text, threshold) {
|
|
|
6105
6158
|
function detectEnglishViolation(text, threshold = 0.6) {
|
|
6106
6159
|
let stripped = stripCodeAndUrls(text);
|
|
6107
6160
|
stripped = stripped.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
|
|
6108
|
-
const
|
|
6161
|
+
const englishOpeners = [
|
|
6109
6162
|
"let me",
|
|
6110
6163
|
"i need",
|
|
6111
6164
|
"first,",
|
|
@@ -6123,12 +6176,44 @@ function detectEnglishViolation(text, threshold = 0.6) {
|
|
|
6123
6176
|
"next,",
|
|
6124
6177
|
"next i",
|
|
6125
6178
|
"then,",
|
|
6126
|
-
"finally,"
|
|
6179
|
+
"finally,",
|
|
6180
|
+
"so,",
|
|
6181
|
+
"okay,",
|
|
6182
|
+
"alright,",
|
|
6183
|
+
"hmm,",
|
|
6184
|
+
"well,",
|
|
6185
|
+
"looking at",
|
|
6186
|
+
"looking into",
|
|
6187
|
+
"going to",
|
|
6188
|
+
"it seems",
|
|
6189
|
+
"it looks",
|
|
6190
|
+
"the code",
|
|
6191
|
+
"the function",
|
|
6192
|
+
"the implementation"
|
|
6193
|
+
];
|
|
6194
|
+
const englishMarkers = [
|
|
6195
|
+
"i think",
|
|
6196
|
+
"i believe",
|
|
6197
|
+
"i would",
|
|
6198
|
+
"i could",
|
|
6199
|
+
"we should",
|
|
6200
|
+
"we could",
|
|
6201
|
+
"we would",
|
|
6202
|
+
"my approach",
|
|
6203
|
+
"my plan",
|
|
6204
|
+
"i want to",
|
|
6205
|
+
"in summary",
|
|
6206
|
+
"to summarize",
|
|
6207
|
+
"in conclusion"
|
|
6127
6208
|
];
|
|
6128
6209
|
const lowerText = stripped.toLowerCase().trim();
|
|
6129
6210
|
if (lowerText.length > 0) {
|
|
6130
|
-
for (const
|
|
6131
|
-
if (lowerText.startsWith(
|
|
6211
|
+
for (const opener of englishOpeners) {
|
|
6212
|
+
if (lowerText.startsWith(opener))
|
|
6213
|
+
return "trigger";
|
|
6214
|
+
}
|
|
6215
|
+
for (const marker of englishMarkers) {
|
|
6216
|
+
if (lowerText.includes(marker))
|
|
6132
6217
|
return "trigger";
|
|
6133
6218
|
}
|
|
6134
6219
|
}
|
|
@@ -6139,6 +6224,59 @@ function detectEnglishViolation(text, threshold = 0.6) {
|
|
|
6139
6224
|
return asciiLetters / meaningful.length > threshold ? "ascii" : false;
|
|
6140
6225
|
}
|
|
6141
6226
|
|
|
6227
|
+
// src/shared/agent-identity-resolver.ts
|
|
6228
|
+
function resolveCurrentAgent(sessionID, inputAgent, options) {
|
|
6229
|
+
const staleThresholdMs = options?.staleThresholdMs ?? 600000;
|
|
6230
|
+
const getAgentFromMessages = options?.getAgentFromSessionMessages;
|
|
6231
|
+
const logger = options?.logger;
|
|
6232
|
+
const sessionAgent = getSessionAgent(sessionID);
|
|
6233
|
+
if (sessionAgent !== undefined) {
|
|
6234
|
+
const stale = isSessionAgentStale(sessionID, staleThresholdMs);
|
|
6235
|
+
if (!stale) {
|
|
6236
|
+
if (logger) {
|
|
6237
|
+
logger("[resolveCurrentAgent] resolved from sessionAgentMap", { sessionID, agent: sessionAgent });
|
|
6238
|
+
}
|
|
6239
|
+
return sessionAgent;
|
|
6240
|
+
}
|
|
6241
|
+
if (getAgentFromMessages !== null) {
|
|
6242
|
+
const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
|
|
6243
|
+
if (messageFileAgent !== undefined) {
|
|
6244
|
+
updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.stale-refresh");
|
|
6245
|
+
if (logger) {
|
|
6246
|
+
logger("[resolveCurrentAgent] stale entry refreshed from message files", { sessionID, oldAgent: sessionAgent, newAgent: messageFileAgent });
|
|
6247
|
+
}
|
|
6248
|
+
return messageFileAgent;
|
|
6249
|
+
}
|
|
6250
|
+
if (logger) {
|
|
6251
|
+
logger("[resolveCurrentAgent] stale entry, no message file fallback", { sessionID, oldAgent: sessionAgent });
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
if (inputAgent !== undefined && inputAgent !== null) {
|
|
6256
|
+
if (logger) {
|
|
6257
|
+
logger("[resolveCurrentAgent] resolved from inputAgent", { sessionID, agent: inputAgent });
|
|
6258
|
+
}
|
|
6259
|
+
return inputAgent;
|
|
6260
|
+
}
|
|
6261
|
+
if (getAgentFromMessages !== null) {
|
|
6262
|
+
const messageFileAgent = getAgentFromMessages ? getAgentFromMessages(sessionID) : undefined;
|
|
6263
|
+
if (messageFileAgent !== undefined) {
|
|
6264
|
+
updateSessionAgent(sessionID, messageFileAgent, "resolveCurrentAgent.message-file");
|
|
6265
|
+
if (logger) {
|
|
6266
|
+
logger("[resolveCurrentAgent] resolved from message files", { sessionID, agent: messageFileAgent });
|
|
6267
|
+
}
|
|
6268
|
+
return messageFileAgent;
|
|
6269
|
+
}
|
|
6270
|
+
}
|
|
6271
|
+
if (logger) {
|
|
6272
|
+
logger("[resolveCurrentAgent] no agent identity found", { sessionID });
|
|
6273
|
+
}
|
|
6274
|
+
return;
|
|
6275
|
+
}
|
|
6276
|
+
var init_agent_identity_resolver = __esm(() => {
|
|
6277
|
+
init_claude_code_session_state();
|
|
6278
|
+
});
|
|
6279
|
+
|
|
6142
6280
|
// src/shared/index.ts
|
|
6143
6281
|
var init_shared = __esm(() => {
|
|
6144
6282
|
init_frontmatter();
|
|
@@ -6173,6 +6311,7 @@ var init_shared = __esm(() => {
|
|
|
6173
6311
|
init_fileio_monitor();
|
|
6174
6312
|
init_windows_reserved_names();
|
|
6175
6313
|
init_usage_tracker();
|
|
6314
|
+
init_agent_identity_resolver();
|
|
6176
6315
|
});
|
|
6177
6316
|
|
|
6178
6317
|
// src/tools/delegate-task/constants.ts
|
|
@@ -15624,51 +15763,22 @@ var require_cross_spawn = __commonJS((exports, module) => {
|
|
|
15624
15763
|
});
|
|
15625
15764
|
|
|
15626
15765
|
// src/hooks/todo-continuation-enforcer.ts
|
|
15627
|
-
|
|
15628
|
-
import { join as join6 } from "path";
|
|
15629
|
-
|
|
15630
|
-
// src/features/claude-code-session-state/state.ts
|
|
15631
|
-
var subagentSessions = new Set;
|
|
15632
|
-
var _mainSessionID;
|
|
15633
|
-
function setMainSession(id) {
|
|
15634
|
-
_mainSessionID = id;
|
|
15635
|
-
}
|
|
15636
|
-
function getMainSessionID() {
|
|
15637
|
-
return _mainSessionID;
|
|
15638
|
-
}
|
|
15639
|
-
var sessionAgentMap = new Map;
|
|
15640
|
-
var sessionAgentMetaMap = new Map;
|
|
15641
|
-
function updateSessionAgent(sessionID, agent, source = "unknown") {
|
|
15642
|
-
sessionAgentMap.set(sessionID, agent);
|
|
15643
|
-
sessionAgentMetaMap.set(sessionID, { updatedAt: Date.now(), source });
|
|
15644
|
-
}
|
|
15645
|
-
function getSessionAgent(sessionID) {
|
|
15646
|
-
return sessionAgentMap.get(sessionID);
|
|
15647
|
-
}
|
|
15648
|
-
function isSessionAgentStale(sessionID, staleThresholdMs) {
|
|
15649
|
-
const meta = sessionAgentMetaMap.get(sessionID);
|
|
15650
|
-
if (!meta)
|
|
15651
|
-
return false;
|
|
15652
|
-
return Date.now() - meta.updatedAt > staleThresholdMs;
|
|
15653
|
-
}
|
|
15654
|
-
function clearSessionAgent(sessionID) {
|
|
15655
|
-
sessionAgentMap.delete(sessionID);
|
|
15656
|
-
sessionAgentMetaMap.delete(sessionID);
|
|
15657
|
-
}
|
|
15658
|
-
// src/hooks/todo-continuation-enforcer.ts
|
|
15766
|
+
init_claude_code_session_state();
|
|
15659
15767
|
init_agent_display_names();
|
|
15768
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, renameSync } from "fs";
|
|
15769
|
+
import { join as join7 } from "path";
|
|
15660
15770
|
|
|
15661
15771
|
// src/features/hook-message-injector/injector.ts
|
|
15662
15772
|
init_fileio_monitor();
|
|
15663
|
-
import { existsSync as
|
|
15664
|
-
import { join as
|
|
15773
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
15774
|
+
import { join as join4 } from "path";
|
|
15665
15775
|
|
|
15666
15776
|
// src/features/hook-message-injector/constants.ts
|
|
15667
15777
|
init_data_path();
|
|
15668
|
-
import { join as
|
|
15778
|
+
import { join as join3 } from "path";
|
|
15669
15779
|
var OPENCODE_STORAGE = getOpenCodeStorageDir();
|
|
15670
|
-
var MESSAGE_STORAGE =
|
|
15671
|
-
var PART_STORAGE =
|
|
15780
|
+
var MESSAGE_STORAGE = join3(OPENCODE_STORAGE, "message");
|
|
15781
|
+
var PART_STORAGE = join3(OPENCODE_STORAGE, "part");
|
|
15672
15782
|
|
|
15673
15783
|
// src/features/hook-message-injector/injector.ts
|
|
15674
15784
|
function findNearestMessageWithFields(messageDir) {
|
|
@@ -15677,7 +15787,7 @@ function findNearestMessageWithFields(messageDir) {
|
|
|
15677
15787
|
const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
15678
15788
|
for (const file of files) {
|
|
15679
15789
|
try {
|
|
15680
|
-
const content = monitor?.readFileSync(
|
|
15790
|
+
const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
|
|
15681
15791
|
const msg = JSON.parse(content);
|
|
15682
15792
|
if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
|
|
15683
15793
|
return msg;
|
|
@@ -15688,7 +15798,7 @@ function findNearestMessageWithFields(messageDir) {
|
|
|
15688
15798
|
}
|
|
15689
15799
|
for (const file of files) {
|
|
15690
15800
|
try {
|
|
15691
|
-
const content = monitor?.readFileSync(
|
|
15801
|
+
const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
|
|
15692
15802
|
const msg = JSON.parse(content);
|
|
15693
15803
|
if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
|
|
15694
15804
|
return msg;
|
|
@@ -15708,7 +15818,7 @@ function findNearestAssistantMessage(messageDir) {
|
|
|
15708
15818
|
const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
15709
15819
|
for (const file of files) {
|
|
15710
15820
|
try {
|
|
15711
|
-
const content = monitor?.readFileSync(
|
|
15821
|
+
const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
|
|
15712
15822
|
const msg = JSON.parse(content);
|
|
15713
15823
|
if (msg.role === "assistant" && msg.agent && msg.model?.providerID && msg.model?.modelID) {
|
|
15714
15824
|
return msg;
|
|
@@ -15719,7 +15829,7 @@ function findNearestAssistantMessage(messageDir) {
|
|
|
15719
15829
|
}
|
|
15720
15830
|
for (const file of files) {
|
|
15721
15831
|
try {
|
|
15722
|
-
const content = monitor?.readFileSync(
|
|
15832
|
+
const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
|
|
15723
15833
|
const msg = JSON.parse(content);
|
|
15724
15834
|
if (msg.role === "assistant" && (msg.agent || msg.model?.providerID && msg.model?.modelID)) {
|
|
15725
15835
|
return msg;
|
|
@@ -15739,7 +15849,7 @@ function findFirstAssistantAgent(messageDir) {
|
|
|
15739
15849
|
const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort();
|
|
15740
15850
|
for (const file of files) {
|
|
15741
15851
|
try {
|
|
15742
|
-
const content = monitor?.readFileSync(
|
|
15852
|
+
const content = monitor?.readFileSync(join4(messageDir, file), "utf-8") ?? readFileSync3(join4(messageDir, file), "utf-8");
|
|
15743
15853
|
const msg = JSON.parse(content);
|
|
15744
15854
|
if (msg.role === "assistant" && msg.agent) {
|
|
15745
15855
|
return msg.agent;
|
|
@@ -15758,19 +15868,19 @@ function getAgentFromMessageDir(messageDir) {
|
|
|
15758
15868
|
}
|
|
15759
15869
|
function getAgentFromSessionMessages(sessionID) {
|
|
15760
15870
|
const monitor = getFileIOMonitor();
|
|
15761
|
-
const _exists = (p) => monitor?.existsSync(p) ??
|
|
15871
|
+
const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
|
|
15762
15872
|
const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
|
|
15763
15873
|
try {
|
|
15764
15874
|
if (!_exists(MESSAGE_STORAGE))
|
|
15765
15875
|
return;
|
|
15766
|
-
const directPath =
|
|
15876
|
+
const directPath = join4(MESSAGE_STORAGE, sessionID);
|
|
15767
15877
|
if (_exists(directPath)) {
|
|
15768
15878
|
const agent = getAgentFromMessageDir(directPath);
|
|
15769
15879
|
if (agent)
|
|
15770
15880
|
return agent;
|
|
15771
15881
|
}
|
|
15772
15882
|
for (const dir of _readdir(MESSAGE_STORAGE)) {
|
|
15773
|
-
const sessionPath =
|
|
15883
|
+
const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
|
|
15774
15884
|
if (_exists(sessionPath)) {
|
|
15775
15885
|
const agent = getAgentFromMessageDir(sessionPath);
|
|
15776
15886
|
if (agent)
|
|
@@ -15794,18 +15904,18 @@ function generatePartId() {
|
|
|
15794
15904
|
}
|
|
15795
15905
|
function getOrCreateMessageDir(sessionID) {
|
|
15796
15906
|
const monitor = getFileIOMonitor();
|
|
15797
|
-
const _exists = (p) => monitor?.existsSync(p) ??
|
|
15798
|
-
const _mkdir = (p, opts) => monitor ? undefined :
|
|
15907
|
+
const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
|
|
15908
|
+
const _mkdir = (p, opts) => monitor ? undefined : mkdirSync2(p, opts);
|
|
15799
15909
|
const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
|
|
15800
15910
|
if (!_exists(MESSAGE_STORAGE)) {
|
|
15801
15911
|
_mkdir(MESSAGE_STORAGE, { recursive: true });
|
|
15802
15912
|
}
|
|
15803
|
-
const directPath =
|
|
15913
|
+
const directPath = join4(MESSAGE_STORAGE, sessionID);
|
|
15804
15914
|
if (_exists(directPath)) {
|
|
15805
15915
|
return directPath;
|
|
15806
15916
|
}
|
|
15807
15917
|
for (const dir of _readdir(MESSAGE_STORAGE)) {
|
|
15808
|
-
const sessionPath =
|
|
15918
|
+
const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
|
|
15809
15919
|
if (_exists(sessionPath)) {
|
|
15810
15920
|
return sessionPath;
|
|
15811
15921
|
}
|
|
@@ -15861,19 +15971,19 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
|
|
|
15861
15971
|
try {
|
|
15862
15972
|
const monitor = getFileIOMonitor();
|
|
15863
15973
|
if (monitor) {
|
|
15864
|
-
monitor.writeFileSync(
|
|
15974
|
+
monitor.writeFileSync(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
|
|
15865
15975
|
} else {
|
|
15866
|
-
|
|
15976
|
+
writeFileSync3(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
|
|
15867
15977
|
}
|
|
15868
|
-
const partDir =
|
|
15869
|
-
const _exists = (p) => monitor?.existsSync(p) ??
|
|
15978
|
+
const partDir = join4(PART_STORAGE, messageID);
|
|
15979
|
+
const _exists = (p) => monitor?.existsSync(p) ?? existsSync3(p);
|
|
15870
15980
|
if (!_exists(partDir)) {
|
|
15871
|
-
|
|
15981
|
+
mkdirSync2(partDir, { recursive: true });
|
|
15872
15982
|
}
|
|
15873
15983
|
if (monitor) {
|
|
15874
|
-
monitor.writeFileSync(
|
|
15984
|
+
monitor.writeFileSync(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
|
|
15875
15985
|
} else {
|
|
15876
|
-
|
|
15986
|
+
writeFileSync3(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
|
|
15877
15987
|
}
|
|
15878
15988
|
return true;
|
|
15879
15989
|
} catch {
|
|
@@ -15890,14 +16000,14 @@ var DEFAULT_SKIP_AGENTS = ["\u6218\u7565\u53C2\u8C0B", "compaction"];
|
|
|
15890
16000
|
var todoOwnerMap = new Map;
|
|
15891
16001
|
function getTodoOwnershipFilePath() {
|
|
15892
16002
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
15893
|
-
return
|
|
16003
|
+
return join7(configDir, "todo-ownership.json");
|
|
15894
16004
|
}
|
|
15895
16005
|
function loadTodoOwnership() {
|
|
15896
16006
|
try {
|
|
15897
16007
|
const filePath = getTodoOwnershipFilePath();
|
|
15898
|
-
if (!
|
|
16008
|
+
if (!existsSync6(filePath))
|
|
15899
16009
|
return;
|
|
15900
|
-
const content =
|
|
16010
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
15901
16011
|
const result = parseJsoncSafe(content);
|
|
15902
16012
|
if (!result.data || typeof result.data !== "object")
|
|
15903
16013
|
return;
|
|
@@ -15913,15 +16023,15 @@ function loadTodoOwnership() {
|
|
|
15913
16023
|
function persistTodoOwnership() {
|
|
15914
16024
|
try {
|
|
15915
16025
|
const filePath = getTodoOwnershipFilePath();
|
|
15916
|
-
const dir =
|
|
15917
|
-
if (!
|
|
15918
|
-
|
|
16026
|
+
const dir = join7(filePath, "..");
|
|
16027
|
+
if (!existsSync6(dir))
|
|
16028
|
+
mkdirSync3(dir, { recursive: true });
|
|
15919
16029
|
const tmpPath = `${filePath}.tmp`;
|
|
15920
16030
|
const data = {};
|
|
15921
16031
|
for (const [key, value] of todoOwnerMap) {
|
|
15922
16032
|
data[key] = value;
|
|
15923
16033
|
}
|
|
15924
|
-
|
|
16034
|
+
writeFileSync4(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
15925
16035
|
renameSync(tmpPath, filePath);
|
|
15926
16036
|
} catch (err) {
|
|
15927
16037
|
log(`[${HOOK_NAME}] Failed to persist todo ownership`, { error: String(err) });
|
|
@@ -15956,14 +16066,14 @@ var COUNTDOWN_SECONDS = 2;
|
|
|
15956
16066
|
var TOAST_DURATION_MS = 900;
|
|
15957
16067
|
var COUNTDOWN_GRACE_PERIOD_MS = 500;
|
|
15958
16068
|
function getMessageDir(sessionID) {
|
|
15959
|
-
if (!
|
|
16069
|
+
if (!existsSync6(MESSAGE_STORAGE))
|
|
15960
16070
|
return null;
|
|
15961
|
-
const directPath =
|
|
15962
|
-
if (
|
|
16071
|
+
const directPath = join7(MESSAGE_STORAGE, sessionID);
|
|
16072
|
+
if (existsSync6(directPath))
|
|
15963
16073
|
return directPath;
|
|
15964
16074
|
for (const dir of readdirSync3(MESSAGE_STORAGE)) {
|
|
15965
|
-
const sessionPath =
|
|
15966
|
-
if (
|
|
16075
|
+
const sessionPath = join7(MESSAGE_STORAGE, dir, sessionID);
|
|
16076
|
+
if (existsSync6(sessionPath))
|
|
15967
16077
|
return sessionPath;
|
|
15968
16078
|
}
|
|
15969
16079
|
return null;
|
|
@@ -16380,6 +16490,7 @@ ${CONTEXT_REMINDER}
|
|
|
16380
16490
|
};
|
|
16381
16491
|
}
|
|
16382
16492
|
// src/hooks/session-notification.ts
|
|
16493
|
+
init_claude_code_session_state();
|
|
16383
16494
|
import { platform } from "os";
|
|
16384
16495
|
|
|
16385
16496
|
// src/hooks/session-notification-utils.ts
|
|
@@ -16766,15 +16877,15 @@ function createSessionNotification(ctx, config = {}) {
|
|
|
16766
16877
|
};
|
|
16767
16878
|
}
|
|
16768
16879
|
// src/hooks/session-recovery/storage.ts
|
|
16769
|
-
import { existsSync as
|
|
16770
|
-
import { join as
|
|
16880
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
|
|
16881
|
+
import { join as join9 } from "path";
|
|
16771
16882
|
|
|
16772
16883
|
// src/hooks/session-recovery/constants.ts
|
|
16773
16884
|
init_data_path();
|
|
16774
|
-
import { join as
|
|
16885
|
+
import { join as join8 } from "path";
|
|
16775
16886
|
var OPENCODE_STORAGE2 = getOpenCodeStorageDir();
|
|
16776
|
-
var MESSAGE_STORAGE2 =
|
|
16777
|
-
var PART_STORAGE2 =
|
|
16887
|
+
var MESSAGE_STORAGE2 = join8(OPENCODE_STORAGE2, "message");
|
|
16888
|
+
var PART_STORAGE2 = join8(OPENCODE_STORAGE2, "part");
|
|
16778
16889
|
var THINKING_TYPES = new Set(["thinking", "redacted_thinking", "reasoning"]);
|
|
16779
16890
|
var META_TYPES = new Set(["step-start", "step-finish"]);
|
|
16780
16891
|
var CONTENT_TYPES = new Set(["text", "tool", "tool_use", "tool_result"]);
|
|
@@ -16787,15 +16898,15 @@ function generatePartId2() {
|
|
|
16787
16898
|
return `prt_${timestamp}${random}`;
|
|
16788
16899
|
}
|
|
16789
16900
|
function getMessageDir2(sessionID) {
|
|
16790
|
-
if (!
|
|
16901
|
+
if (!existsSync7(MESSAGE_STORAGE2))
|
|
16791
16902
|
return "";
|
|
16792
|
-
const directPath =
|
|
16793
|
-
if (
|
|
16903
|
+
const directPath = join9(MESSAGE_STORAGE2, sessionID);
|
|
16904
|
+
if (existsSync7(directPath)) {
|
|
16794
16905
|
return directPath;
|
|
16795
16906
|
}
|
|
16796
16907
|
for (const dir of readdirSync4(MESSAGE_STORAGE2)) {
|
|
16797
|
-
const sessionPath =
|
|
16798
|
-
if (
|
|
16908
|
+
const sessionPath = join9(MESSAGE_STORAGE2, dir, sessionID);
|
|
16909
|
+
if (existsSync7(sessionPath)) {
|
|
16799
16910
|
return sessionPath;
|
|
16800
16911
|
}
|
|
16801
16912
|
}
|
|
@@ -16803,14 +16914,14 @@ function getMessageDir2(sessionID) {
|
|
|
16803
16914
|
}
|
|
16804
16915
|
function readMessages(sessionID) {
|
|
16805
16916
|
const messageDir = getMessageDir2(sessionID);
|
|
16806
|
-
if (!messageDir || !
|
|
16917
|
+
if (!messageDir || !existsSync7(messageDir))
|
|
16807
16918
|
return [];
|
|
16808
16919
|
const messages = [];
|
|
16809
16920
|
for (const file of readdirSync4(messageDir)) {
|
|
16810
16921
|
if (!file.endsWith(".json"))
|
|
16811
16922
|
continue;
|
|
16812
16923
|
try {
|
|
16813
|
-
const content =
|
|
16924
|
+
const content = readFileSync6(join9(messageDir, file), "utf-8");
|
|
16814
16925
|
messages.push(JSON.parse(content));
|
|
16815
16926
|
} catch {
|
|
16816
16927
|
continue;
|
|
@@ -16825,15 +16936,15 @@ function readMessages(sessionID) {
|
|
|
16825
16936
|
});
|
|
16826
16937
|
}
|
|
16827
16938
|
function readParts(messageID) {
|
|
16828
|
-
const partDir =
|
|
16829
|
-
if (!
|
|
16939
|
+
const partDir = join9(PART_STORAGE2, messageID);
|
|
16940
|
+
if (!existsSync7(partDir))
|
|
16830
16941
|
return [];
|
|
16831
16942
|
const parts = [];
|
|
16832
16943
|
for (const file of readdirSync4(partDir)) {
|
|
16833
16944
|
if (!file.endsWith(".json"))
|
|
16834
16945
|
continue;
|
|
16835
16946
|
try {
|
|
16836
|
-
const content =
|
|
16947
|
+
const content = readFileSync6(join9(partDir, file), "utf-8");
|
|
16837
16948
|
parts.push(JSON.parse(content));
|
|
16838
16949
|
} catch {
|
|
16839
16950
|
continue;
|
|
@@ -16863,9 +16974,9 @@ function messageHasContent(messageID) {
|
|
|
16863
16974
|
return parts.some(hasContent);
|
|
16864
16975
|
}
|
|
16865
16976
|
function injectTextPart(sessionID, messageID, text) {
|
|
16866
|
-
const partDir =
|
|
16867
|
-
if (!
|
|
16868
|
-
|
|
16977
|
+
const partDir = join9(PART_STORAGE2, messageID);
|
|
16978
|
+
if (!existsSync7(partDir)) {
|
|
16979
|
+
mkdirSync4(partDir, { recursive: true });
|
|
16869
16980
|
}
|
|
16870
16981
|
const partId = generatePartId2();
|
|
16871
16982
|
const part = {
|
|
@@ -16877,7 +16988,7 @@ function injectTextPart(sessionID, messageID, text) {
|
|
|
16877
16988
|
synthetic: true
|
|
16878
16989
|
};
|
|
16879
16990
|
try {
|
|
16880
|
-
|
|
16991
|
+
writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
|
|
16881
16992
|
return true;
|
|
16882
16993
|
} catch {
|
|
16883
16994
|
return false;
|
|
@@ -16972,9 +17083,9 @@ function findLastThinkingContent(sessionID, beforeMessageID) {
|
|
|
16972
17083
|
return "";
|
|
16973
17084
|
}
|
|
16974
17085
|
function prependThinkingPart(sessionID, messageID) {
|
|
16975
|
-
const partDir =
|
|
16976
|
-
if (!
|
|
16977
|
-
|
|
17086
|
+
const partDir = join9(PART_STORAGE2, messageID);
|
|
17087
|
+
if (!existsSync7(partDir)) {
|
|
17088
|
+
mkdirSync4(partDir, { recursive: true });
|
|
16978
17089
|
}
|
|
16979
17090
|
const previousThinking = findLastThinkingContent(sessionID, messageID);
|
|
16980
17091
|
const partId = `prt_${++nextRecoveryBlockId}_thinking`;
|
|
@@ -16987,23 +17098,23 @@ function prependThinkingPart(sessionID, messageID) {
|
|
|
16987
17098
|
synthetic: true
|
|
16988
17099
|
};
|
|
16989
17100
|
try {
|
|
16990
|
-
|
|
17101
|
+
writeFileSync5(join9(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
|
|
16991
17102
|
return true;
|
|
16992
17103
|
} catch {
|
|
16993
17104
|
return false;
|
|
16994
17105
|
}
|
|
16995
17106
|
}
|
|
16996
17107
|
function stripThinkingParts(messageID) {
|
|
16997
|
-
const partDir =
|
|
16998
|
-
if (!
|
|
17108
|
+
const partDir = join9(PART_STORAGE2, messageID);
|
|
17109
|
+
if (!existsSync7(partDir))
|
|
16999
17110
|
return false;
|
|
17000
17111
|
let anyRemoved = false;
|
|
17001
17112
|
for (const file of readdirSync4(partDir)) {
|
|
17002
17113
|
if (!file.endsWith(".json"))
|
|
17003
17114
|
continue;
|
|
17004
17115
|
try {
|
|
17005
|
-
const filePath =
|
|
17006
|
-
const content =
|
|
17116
|
+
const filePath = join9(partDir, file);
|
|
17117
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
17007
17118
|
const part = JSON.parse(content);
|
|
17008
17119
|
if (THINKING_TYPES.has(part.type)) {
|
|
17009
17120
|
unlinkSync(filePath);
|
|
@@ -17016,23 +17127,23 @@ function stripThinkingParts(messageID) {
|
|
|
17016
17127
|
return anyRemoved;
|
|
17017
17128
|
}
|
|
17018
17129
|
function replaceEmptyTextParts(messageID, replacementText) {
|
|
17019
|
-
const partDir =
|
|
17020
|
-
if (!
|
|
17130
|
+
const partDir = join9(PART_STORAGE2, messageID);
|
|
17131
|
+
if (!existsSync7(partDir))
|
|
17021
17132
|
return false;
|
|
17022
17133
|
let anyReplaced = false;
|
|
17023
17134
|
for (const file of readdirSync4(partDir)) {
|
|
17024
17135
|
if (!file.endsWith(".json"))
|
|
17025
17136
|
continue;
|
|
17026
17137
|
try {
|
|
17027
|
-
const filePath =
|
|
17028
|
-
const content =
|
|
17138
|
+
const filePath = join9(partDir, file);
|
|
17139
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
17029
17140
|
const part = JSON.parse(content);
|
|
17030
17141
|
if (part.type === "text") {
|
|
17031
17142
|
const textPart = part;
|
|
17032
17143
|
if (!textPart.text?.trim()) {
|
|
17033
17144
|
textPart.text = replacementText;
|
|
17034
17145
|
textPart.synthetic = true;
|
|
17035
|
-
|
|
17146
|
+
writeFileSync5(filePath, JSON.stringify(textPart, null, 2));
|
|
17036
17147
|
anyReplaced = true;
|
|
17037
17148
|
}
|
|
17038
17149
|
}
|
|
@@ -17302,20 +17413,20 @@ function createSessionRecoveryHook(ctx, options) {
|
|
|
17302
17413
|
// src/hooks/comment-checker/cli.ts
|
|
17303
17414
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
17304
17415
|
import { createRequire as createRequire2 } from "module";
|
|
17305
|
-
import { dirname, join as
|
|
17306
|
-
import { existsSync as
|
|
17416
|
+
import { dirname, join as join18 } from "path";
|
|
17417
|
+
import { existsSync as existsSync16 } from "fs";
|
|
17307
17418
|
import * as fs5 from "fs";
|
|
17308
17419
|
import { tmpdir as tmpdir4 } from "os";
|
|
17309
17420
|
|
|
17310
17421
|
// src/hooks/comment-checker/downloader.ts
|
|
17311
17422
|
init_shared();
|
|
17312
17423
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
17313
|
-
import { existsSync as
|
|
17314
|
-
import { join as
|
|
17424
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync7, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
|
|
17425
|
+
import { join as join17 } from "path";
|
|
17315
17426
|
import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
|
|
17316
17427
|
import { createRequire } from "module";
|
|
17317
17428
|
var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
17318
|
-
var DEBUG_FILE =
|
|
17429
|
+
var DEBUG_FILE = join17(tmpdir3(), "comment-checker-debug.log");
|
|
17319
17430
|
function debugLog(...args) {
|
|
17320
17431
|
if (DEBUG) {
|
|
17321
17432
|
const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -17334,19 +17445,19 @@ var PLATFORM_MAP = {
|
|
|
17334
17445
|
function getCacheDir() {
|
|
17335
17446
|
if (process.platform === "win32") {
|
|
17336
17447
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
17337
|
-
const base2 = localAppData ||
|
|
17338
|
-
return
|
|
17448
|
+
const base2 = localAppData || join17(homedir8(), "AppData", "Local");
|
|
17449
|
+
return join17(base2, "oh-my-opencode", "bin");
|
|
17339
17450
|
}
|
|
17340
17451
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
17341
|
-
const base = xdgCache ||
|
|
17342
|
-
return
|
|
17452
|
+
const base = xdgCache || join17(homedir8(), ".cache");
|
|
17453
|
+
return join17(base, "oh-my-opencode", "bin");
|
|
17343
17454
|
}
|
|
17344
17455
|
function getBinaryName() {
|
|
17345
17456
|
return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
17346
17457
|
}
|
|
17347
17458
|
function getCachedBinaryPath() {
|
|
17348
|
-
const binaryPath =
|
|
17349
|
-
return
|
|
17459
|
+
const binaryPath = join17(getCacheDir(), getBinaryName());
|
|
17460
|
+
return existsSync15(binaryPath) ? binaryPath : null;
|
|
17350
17461
|
}
|
|
17351
17462
|
function getPackageVersion() {
|
|
17352
17463
|
try {
|
|
@@ -17378,8 +17489,8 @@ async function downloadCommentChecker() {
|
|
|
17378
17489
|
}
|
|
17379
17490
|
const cacheDir = getCacheDir();
|
|
17380
17491
|
const binaryName = getBinaryName();
|
|
17381
|
-
const binaryPath =
|
|
17382
|
-
if (
|
|
17492
|
+
const binaryPath = join17(cacheDir, binaryName);
|
|
17493
|
+
if (existsSync15(binaryPath)) {
|
|
17383
17494
|
debugLog("Binary already cached at:", binaryPath);
|
|
17384
17495
|
return binaryPath;
|
|
17385
17496
|
}
|
|
@@ -17390,14 +17501,14 @@ async function downloadCommentChecker() {
|
|
|
17390
17501
|
debugLog(`Downloading from: ${downloadUrl}`);
|
|
17391
17502
|
console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
|
|
17392
17503
|
try {
|
|
17393
|
-
if (!
|
|
17394
|
-
|
|
17504
|
+
if (!existsSync15(cacheDir)) {
|
|
17505
|
+
mkdirSync7(cacheDir, { recursive: true });
|
|
17395
17506
|
}
|
|
17396
17507
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
17397
17508
|
if (!response.ok) {
|
|
17398
17509
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
17399
17510
|
}
|
|
17400
|
-
const archivePath =
|
|
17511
|
+
const archivePath = join17(cacheDir, assetName);
|
|
17401
17512
|
const arrayBuffer = await response.arrayBuffer();
|
|
17402
17513
|
await Bun.write(archivePath, arrayBuffer);
|
|
17403
17514
|
debugLog(`Downloaded archive to: ${archivePath}`);
|
|
@@ -17406,10 +17517,10 @@ async function downloadCommentChecker() {
|
|
|
17406
17517
|
} else {
|
|
17407
17518
|
await extractZip(archivePath, cacheDir);
|
|
17408
17519
|
}
|
|
17409
|
-
if (
|
|
17520
|
+
if (existsSync15(archivePath)) {
|
|
17410
17521
|
unlinkSync2(archivePath);
|
|
17411
17522
|
}
|
|
17412
|
-
if (process.platform !== "win32" &&
|
|
17523
|
+
if (process.platform !== "win32" && existsSync15(binaryPath)) {
|
|
17413
17524
|
chmodSync(binaryPath, 493);
|
|
17414
17525
|
}
|
|
17415
17526
|
debugLog(`Successfully downloaded binary to: ${binaryPath}`);
|
|
@@ -17433,7 +17544,7 @@ async function ensureCommentCheckerBinary() {
|
|
|
17433
17544
|
|
|
17434
17545
|
// src/hooks/comment-checker/cli.ts
|
|
17435
17546
|
var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
17436
|
-
var DEBUG_FILE2 =
|
|
17547
|
+
var DEBUG_FILE2 = join18(tmpdir4(), "comment-checker-debug.log");
|
|
17437
17548
|
function debugLog2(...args) {
|
|
17438
17549
|
if (DEBUG2) {
|
|
17439
17550
|
const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -17459,8 +17570,8 @@ function findCommentCheckerPathSync() {
|
|
|
17459
17570
|
const require2 = createRequire2(import.meta.url);
|
|
17460
17571
|
const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
17461
17572
|
const cliDir = dirname(cliPkgPath);
|
|
17462
|
-
const binaryPath =
|
|
17463
|
-
if (
|
|
17573
|
+
const binaryPath = join18(cliDir, "bin", binaryName);
|
|
17574
|
+
if (existsSync16(binaryPath)) {
|
|
17464
17575
|
debugLog2("found binary in main package:", binaryPath);
|
|
17465
17576
|
return binaryPath;
|
|
17466
17577
|
}
|
|
@@ -17481,7 +17592,7 @@ async function getCommentCheckerPath() {
|
|
|
17481
17592
|
}
|
|
17482
17593
|
initPromise = (async () => {
|
|
17483
17594
|
const syncPath = findCommentCheckerPathSync();
|
|
17484
|
-
if (syncPath &&
|
|
17595
|
+
if (syncPath && existsSync16(syncPath)) {
|
|
17485
17596
|
resolvedCliPath = syncPath;
|
|
17486
17597
|
debugLog2("using sync-resolved path:", syncPath);
|
|
17487
17598
|
return syncPath;
|
|
@@ -17517,7 +17628,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
17517
17628
|
debugLog2("comment-checker binary not found");
|
|
17518
17629
|
return { hasComments: false, message: "" };
|
|
17519
17630
|
}
|
|
17520
|
-
if (!
|
|
17631
|
+
if (!existsSync16(binaryPath)) {
|
|
17521
17632
|
debugLog2("comment-checker binary does not exist:", binaryPath);
|
|
17522
17633
|
return { hasComments: false, message: "" };
|
|
17523
17634
|
}
|
|
@@ -17555,11 +17666,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
17555
17666
|
|
|
17556
17667
|
// src/hooks/comment-checker/index.ts
|
|
17557
17668
|
import * as fs6 from "fs";
|
|
17558
|
-
import { existsSync as
|
|
17669
|
+
import { existsSync as existsSync17 } from "fs";
|
|
17559
17670
|
import { tmpdir as tmpdir5 } from "os";
|
|
17560
|
-
import { join as
|
|
17671
|
+
import { join as join19 } from "path";
|
|
17561
17672
|
var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
17562
|
-
var DEBUG_FILE3 =
|
|
17673
|
+
var DEBUG_FILE3 = join19(tmpdir5(), "comment-checker-debug.log");
|
|
17563
17674
|
function debugLog3(...args) {
|
|
17564
17675
|
if (DEBUG3) {
|
|
17565
17676
|
const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -17640,7 +17751,7 @@ function createCommentCheckerHooks(config) {
|
|
|
17640
17751
|
}
|
|
17641
17752
|
try {
|
|
17642
17753
|
const cliPath = await cliPathPromise;
|
|
17643
|
-
if (!cliPath || !
|
|
17754
|
+
if (!cliPath || !existsSync17(cliPath)) {
|
|
17644
17755
|
debugLog3("CLI not available, skipping comment check");
|
|
17645
17756
|
return;
|
|
17646
17757
|
}
|
|
@@ -17720,36 +17831,36 @@ function createToolOutputTruncatorHook(ctx, options) {
|
|
|
17720
17831
|
};
|
|
17721
17832
|
}
|
|
17722
17833
|
// src/hooks/directory-agents-injector/index.ts
|
|
17723
|
-
import { existsSync as
|
|
17724
|
-
import { dirname as dirname2, join as
|
|
17834
|
+
import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
17835
|
+
import { dirname as dirname2, join as join22, resolve as resolve3 } from "path";
|
|
17725
17836
|
|
|
17726
17837
|
// src/hooks/directory-agents-injector/storage.ts
|
|
17727
17838
|
import {
|
|
17728
|
-
existsSync as
|
|
17729
|
-
mkdirSync as
|
|
17730
|
-
readFileSync as
|
|
17731
|
-
writeFileSync as
|
|
17839
|
+
existsSync as existsSync18,
|
|
17840
|
+
mkdirSync as mkdirSync8,
|
|
17841
|
+
readFileSync as readFileSync12,
|
|
17842
|
+
writeFileSync as writeFileSync8,
|
|
17732
17843
|
unlinkSync as unlinkSync3
|
|
17733
17844
|
} from "fs";
|
|
17734
|
-
import { join as
|
|
17845
|
+
import { join as join21 } from "path";
|
|
17735
17846
|
|
|
17736
17847
|
// src/hooks/directory-agents-injector/constants.ts
|
|
17737
17848
|
init_data_path();
|
|
17738
|
-
import { join as
|
|
17849
|
+
import { join as join20 } from "path";
|
|
17739
17850
|
var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
|
|
17740
|
-
var AGENTS_INJECTOR_STORAGE =
|
|
17851
|
+
var AGENTS_INJECTOR_STORAGE = join20(OPENCODE_STORAGE3, "directory-agents");
|
|
17741
17852
|
var AGENTS_FILENAME = "AGENTS.md";
|
|
17742
17853
|
|
|
17743
17854
|
// src/hooks/directory-agents-injector/storage.ts
|
|
17744
17855
|
function getStoragePath(sessionID) {
|
|
17745
|
-
return
|
|
17856
|
+
return join21(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
17746
17857
|
}
|
|
17747
17858
|
function loadInjectedPaths(sessionID) {
|
|
17748
17859
|
const filePath = getStoragePath(sessionID);
|
|
17749
|
-
if (!
|
|
17860
|
+
if (!existsSync18(filePath))
|
|
17750
17861
|
return new Set;
|
|
17751
17862
|
try {
|
|
17752
|
-
const content =
|
|
17863
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
17753
17864
|
const data = JSON.parse(content);
|
|
17754
17865
|
return new Set(data.injectedPaths);
|
|
17755
17866
|
} catch {
|
|
@@ -17757,19 +17868,19 @@ function loadInjectedPaths(sessionID) {
|
|
|
17757
17868
|
}
|
|
17758
17869
|
}
|
|
17759
17870
|
function saveInjectedPaths(sessionID, paths) {
|
|
17760
|
-
if (!
|
|
17761
|
-
|
|
17871
|
+
if (!existsSync18(AGENTS_INJECTOR_STORAGE)) {
|
|
17872
|
+
mkdirSync8(AGENTS_INJECTOR_STORAGE, { recursive: true });
|
|
17762
17873
|
}
|
|
17763
17874
|
const data = {
|
|
17764
17875
|
sessionID,
|
|
17765
17876
|
injectedPaths: [...paths],
|
|
17766
17877
|
updatedAt: Date.now()
|
|
17767
17878
|
};
|
|
17768
|
-
|
|
17879
|
+
writeFileSync8(getStoragePath(sessionID), JSON.stringify(data, null, 2));
|
|
17769
17880
|
}
|
|
17770
17881
|
function clearInjectedPaths(sessionID) {
|
|
17771
17882
|
const filePath = getStoragePath(sessionID);
|
|
17772
|
-
if (
|
|
17883
|
+
if (existsSync18(filePath)) {
|
|
17773
17884
|
unlinkSync3(filePath);
|
|
17774
17885
|
}
|
|
17775
17886
|
}
|
|
@@ -17799,8 +17910,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
17799
17910
|
while (true) {
|
|
17800
17911
|
const isRootDir = current === ctx.directory;
|
|
17801
17912
|
if (!isRootDir) {
|
|
17802
|
-
const agentsPath =
|
|
17803
|
-
if (
|
|
17913
|
+
const agentsPath = join22(current, AGENTS_FILENAME);
|
|
17914
|
+
if (existsSync19(agentsPath)) {
|
|
17804
17915
|
found.push(agentsPath);
|
|
17805
17916
|
}
|
|
17806
17917
|
}
|
|
@@ -17827,7 +17938,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
17827
17938
|
if (cache.has(agentsDir))
|
|
17828
17939
|
continue;
|
|
17829
17940
|
try {
|
|
17830
|
-
const content =
|
|
17941
|
+
const content = readFileSync13(agentsPath, "utf-8");
|
|
17831
17942
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
17832
17943
|
const truncationNotice = truncated ? `
|
|
17833
17944
|
|
|
@@ -17897,36 +18008,36 @@ ${result}${truncationNotice}`;
|
|
|
17897
18008
|
};
|
|
17898
18009
|
}
|
|
17899
18010
|
// src/hooks/directory-readme-injector/index.ts
|
|
17900
|
-
import { existsSync as
|
|
17901
|
-
import { dirname as dirname3, join as
|
|
18011
|
+
import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
|
|
18012
|
+
import { dirname as dirname3, join as join25, resolve as resolve4 } from "path";
|
|
17902
18013
|
|
|
17903
18014
|
// src/hooks/directory-readme-injector/storage.ts
|
|
17904
18015
|
import {
|
|
17905
|
-
existsSync as
|
|
17906
|
-
mkdirSync as
|
|
17907
|
-
readFileSync as
|
|
17908
|
-
writeFileSync as
|
|
18016
|
+
existsSync as existsSync20,
|
|
18017
|
+
mkdirSync as mkdirSync9,
|
|
18018
|
+
readFileSync as readFileSync14,
|
|
18019
|
+
writeFileSync as writeFileSync9,
|
|
17909
18020
|
unlinkSync as unlinkSync4
|
|
17910
18021
|
} from "fs";
|
|
17911
|
-
import { join as
|
|
18022
|
+
import { join as join24 } from "path";
|
|
17912
18023
|
|
|
17913
18024
|
// src/hooks/directory-readme-injector/constants.ts
|
|
17914
18025
|
init_data_path();
|
|
17915
|
-
import { join as
|
|
18026
|
+
import { join as join23 } from "path";
|
|
17916
18027
|
var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
|
|
17917
|
-
var README_INJECTOR_STORAGE =
|
|
18028
|
+
var README_INJECTOR_STORAGE = join23(OPENCODE_STORAGE4, "directory-readme");
|
|
17918
18029
|
var README_FILENAME = "README.md";
|
|
17919
18030
|
|
|
17920
18031
|
// src/hooks/directory-readme-injector/storage.ts
|
|
17921
18032
|
function getStoragePath2(sessionID) {
|
|
17922
|
-
return
|
|
18033
|
+
return join24(README_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
17923
18034
|
}
|
|
17924
18035
|
function loadInjectedPaths2(sessionID) {
|
|
17925
18036
|
const filePath = getStoragePath2(sessionID);
|
|
17926
|
-
if (!
|
|
18037
|
+
if (!existsSync20(filePath))
|
|
17927
18038
|
return new Set;
|
|
17928
18039
|
try {
|
|
17929
|
-
const content =
|
|
18040
|
+
const content = readFileSync14(filePath, "utf-8");
|
|
17930
18041
|
const data = JSON.parse(content);
|
|
17931
18042
|
return new Set(data.injectedPaths);
|
|
17932
18043
|
} catch {
|
|
@@ -17934,19 +18045,19 @@ function loadInjectedPaths2(sessionID) {
|
|
|
17934
18045
|
}
|
|
17935
18046
|
}
|
|
17936
18047
|
function saveInjectedPaths2(sessionID, paths) {
|
|
17937
|
-
if (!
|
|
17938
|
-
|
|
18048
|
+
if (!existsSync20(README_INJECTOR_STORAGE)) {
|
|
18049
|
+
mkdirSync9(README_INJECTOR_STORAGE, { recursive: true });
|
|
17939
18050
|
}
|
|
17940
18051
|
const data = {
|
|
17941
18052
|
sessionID,
|
|
17942
18053
|
injectedPaths: [...paths],
|
|
17943
18054
|
updatedAt: Date.now()
|
|
17944
18055
|
};
|
|
17945
|
-
|
|
18056
|
+
writeFileSync9(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
|
|
17946
18057
|
}
|
|
17947
18058
|
function clearInjectedPaths2(sessionID) {
|
|
17948
18059
|
const filePath = getStoragePath2(sessionID);
|
|
17949
|
-
if (
|
|
18060
|
+
if (existsSync20(filePath)) {
|
|
17950
18061
|
unlinkSync4(filePath);
|
|
17951
18062
|
}
|
|
17952
18063
|
}
|
|
@@ -17974,8 +18085,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
17974
18085
|
const found = [];
|
|
17975
18086
|
let current = startDir;
|
|
17976
18087
|
while (true) {
|
|
17977
|
-
const readmePath =
|
|
17978
|
-
if (
|
|
18088
|
+
const readmePath = join25(current, README_FILENAME);
|
|
18089
|
+
if (existsSync21(readmePath)) {
|
|
17979
18090
|
found.push(readmePath);
|
|
17980
18091
|
}
|
|
17981
18092
|
if (current === ctx.directory)
|
|
@@ -18001,7 +18112,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
18001
18112
|
if (cache.has(readmeDir))
|
|
18002
18113
|
continue;
|
|
18003
18114
|
try {
|
|
18004
|
-
const content =
|
|
18115
|
+
const content = readFileSync15(readmePath, "utf-8");
|
|
18005
18116
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
18006
18117
|
const truncationNotice = truncated ? `
|
|
18007
18118
|
|
|
@@ -18285,22 +18396,22 @@ var TRUNCATE_CONFIG = {
|
|
|
18285
18396
|
|
|
18286
18397
|
// src/hooks/anthropic-context-window-limit-recovery/storage.ts
|
|
18287
18398
|
init_data_path();
|
|
18288
|
-
import { existsSync as
|
|
18289
|
-
import { join as
|
|
18399
|
+
import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync10 } from "fs";
|
|
18400
|
+
import { join as join26 } from "path";
|
|
18290
18401
|
var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
|
|
18291
|
-
var MESSAGE_STORAGE3 =
|
|
18292
|
-
var PART_STORAGE3 =
|
|
18402
|
+
var MESSAGE_STORAGE3 = join26(OPENCODE_STORAGE5, "message");
|
|
18403
|
+
var PART_STORAGE3 = join26(OPENCODE_STORAGE5, "part");
|
|
18293
18404
|
var TRUNCATION_MESSAGE = "[TOOL RESULT TRUNCATED - Context limit exceeded. Original output was too large and has been truncated to recover the session. Please re-run this tool if you need the full output.]";
|
|
18294
18405
|
function getMessageDir3(sessionID) {
|
|
18295
|
-
if (!
|
|
18406
|
+
if (!existsSync22(MESSAGE_STORAGE3))
|
|
18296
18407
|
return "";
|
|
18297
|
-
const directPath =
|
|
18298
|
-
if (
|
|
18408
|
+
const directPath = join26(MESSAGE_STORAGE3, sessionID);
|
|
18409
|
+
if (existsSync22(directPath)) {
|
|
18299
18410
|
return directPath;
|
|
18300
18411
|
}
|
|
18301
18412
|
for (const dir of readdirSync6(MESSAGE_STORAGE3)) {
|
|
18302
|
-
const sessionPath =
|
|
18303
|
-
if (
|
|
18413
|
+
const sessionPath = join26(MESSAGE_STORAGE3, dir, sessionID);
|
|
18414
|
+
if (existsSync22(sessionPath)) {
|
|
18304
18415
|
return sessionPath;
|
|
18305
18416
|
}
|
|
18306
18417
|
}
|
|
@@ -18308,7 +18419,7 @@ function getMessageDir3(sessionID) {
|
|
|
18308
18419
|
}
|
|
18309
18420
|
function getMessageIds(sessionID) {
|
|
18310
18421
|
const messageDir = getMessageDir3(sessionID);
|
|
18311
|
-
if (!messageDir || !
|
|
18422
|
+
if (!messageDir || !existsSync22(messageDir))
|
|
18312
18423
|
return [];
|
|
18313
18424
|
const messageIds = [];
|
|
18314
18425
|
for (const file of readdirSync6(messageDir)) {
|
|
@@ -18323,15 +18434,15 @@ function findToolResultsBySize(sessionID) {
|
|
|
18323
18434
|
const messageIds = getMessageIds(sessionID);
|
|
18324
18435
|
const results = [];
|
|
18325
18436
|
for (const messageID of messageIds) {
|
|
18326
|
-
const partDir =
|
|
18327
|
-
if (!
|
|
18437
|
+
const partDir = join26(PART_STORAGE3, messageID);
|
|
18438
|
+
if (!existsSync22(partDir))
|
|
18328
18439
|
continue;
|
|
18329
18440
|
for (const file of readdirSync6(partDir)) {
|
|
18330
18441
|
if (!file.endsWith(".json"))
|
|
18331
18442
|
continue;
|
|
18332
18443
|
try {
|
|
18333
|
-
const partPath =
|
|
18334
|
-
const content =
|
|
18444
|
+
const partPath = join26(partDir, file);
|
|
18445
|
+
const content = readFileSync16(partPath, "utf-8");
|
|
18335
18446
|
const part = JSON.parse(content);
|
|
18336
18447
|
if (part.type === "tool" && part.state?.output && !part.truncated) {
|
|
18337
18448
|
results.push({
|
|
@@ -18351,7 +18462,7 @@ function findToolResultsBySize(sessionID) {
|
|
|
18351
18462
|
}
|
|
18352
18463
|
function truncateToolResult(partPath) {
|
|
18353
18464
|
try {
|
|
18354
|
-
const content =
|
|
18465
|
+
const content = readFileSync16(partPath, "utf-8");
|
|
18355
18466
|
const part = JSON.parse(content);
|
|
18356
18467
|
if (!part.state?.output) {
|
|
18357
18468
|
return { success: false };
|
|
@@ -18365,7 +18476,7 @@ function truncateToolResult(partPath) {
|
|
|
18365
18476
|
part.state.time = { start: Date.now() };
|
|
18366
18477
|
}
|
|
18367
18478
|
part.state.time.compacted = Date.now();
|
|
18368
|
-
|
|
18479
|
+
writeFileSync10(partPath, JSON.stringify(part, null, 2));
|
|
18369
18480
|
return { success: true, toolName, originalSize };
|
|
18370
18481
|
} catch {
|
|
18371
18482
|
return { success: false };
|
|
@@ -22697,7 +22808,7 @@ init_file_utils();
|
|
|
22697
22808
|
init_shared();
|
|
22698
22809
|
init_opencode_config_dir();
|
|
22699
22810
|
import { promises as fs7 } from "fs";
|
|
22700
|
-
import { join as
|
|
22811
|
+
import { join as join27, basename } from "path";
|
|
22701
22812
|
function parseSkillMcpConfigFromFrontmatter(content) {
|
|
22702
22813
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
22703
22814
|
if (!frontmatterMatch)
|
|
@@ -22713,7 +22824,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
|
|
|
22713
22824
|
return;
|
|
22714
22825
|
}
|
|
22715
22826
|
async function loadMcpJsonFromDir(skillDir) {
|
|
22716
|
-
const mcpJsonPath =
|
|
22827
|
+
const mcpJsonPath = join27(skillDir, "mcp.json");
|
|
22717
22828
|
try {
|
|
22718
22829
|
const content = await fs7.readFile(mcpJsonPath, "utf-8");
|
|
22719
22830
|
const parsed = JSON.parse(content);
|
|
@@ -22794,11 +22905,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
22794
22905
|
for (const entry of entries) {
|
|
22795
22906
|
if (entry.name.startsWith("."))
|
|
22796
22907
|
continue;
|
|
22797
|
-
const entryPath =
|
|
22908
|
+
const entryPath = join27(skillsDir, entry.name);
|
|
22798
22909
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
22799
22910
|
const resolvedPath = await resolveSymlinkAsync(entryPath);
|
|
22800
22911
|
const dirName = entry.name;
|
|
22801
|
-
const skillMdPath =
|
|
22912
|
+
const skillMdPath = join27(resolvedPath, "SKILL.md");
|
|
22802
22913
|
try {
|
|
22803
22914
|
await fs7.access(skillMdPath);
|
|
22804
22915
|
const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
|
|
@@ -22806,7 +22917,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
22806
22917
|
skills.push(skill);
|
|
22807
22918
|
continue;
|
|
22808
22919
|
} catch {}
|
|
22809
|
-
const namedSkillMdPath =
|
|
22920
|
+
const namedSkillMdPath = join27(resolvedPath, `${dirName}.md`);
|
|
22810
22921
|
try {
|
|
22811
22922
|
await fs7.access(namedSkillMdPath);
|
|
22812
22923
|
const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
|
|
@@ -22834,23 +22945,23 @@ function skillsToRecord(skills) {
|
|
|
22834
22945
|
return result;
|
|
22835
22946
|
}
|
|
22836
22947
|
async function loadUserSkills() {
|
|
22837
|
-
const userSkillsDir =
|
|
22948
|
+
const userSkillsDir = join27(getClaudeConfigDir(), "skills");
|
|
22838
22949
|
const skills = await loadSkillsFromDir(userSkillsDir, "user");
|
|
22839
22950
|
return skillsToRecord(skills);
|
|
22840
22951
|
}
|
|
22841
22952
|
async function loadProjectSkills() {
|
|
22842
|
-
const projectSkillsDir =
|
|
22953
|
+
const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
|
|
22843
22954
|
const skills = await loadSkillsFromDir(projectSkillsDir, "project");
|
|
22844
22955
|
return skillsToRecord(skills);
|
|
22845
22956
|
}
|
|
22846
22957
|
async function loadOpencodeGlobalSkills() {
|
|
22847
22958
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22848
|
-
const opencodeSkillsDir =
|
|
22959
|
+
const opencodeSkillsDir = join27(configDir, "skills");
|
|
22849
22960
|
const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
22850
22961
|
return skillsToRecord(skills);
|
|
22851
22962
|
}
|
|
22852
22963
|
async function loadOpencodeProjectSkills() {
|
|
22853
|
-
const opencodeProjectDir =
|
|
22964
|
+
const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
|
|
22854
22965
|
const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
22855
22966
|
return skillsToRecord(skills);
|
|
22856
22967
|
}
|
|
@@ -22879,26 +22990,26 @@ async function discoverSkills(options = {}) {
|
|
|
22879
22990
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
|
|
22880
22991
|
}
|
|
22881
22992
|
async function discoverUserClaudeSkills() {
|
|
22882
|
-
const userSkillsDir =
|
|
22993
|
+
const userSkillsDir = join27(getClaudeConfigDir(), "skills");
|
|
22883
22994
|
return loadSkillsFromDir(userSkillsDir, "user");
|
|
22884
22995
|
}
|
|
22885
22996
|
async function discoverProjectClaudeSkills() {
|
|
22886
|
-
const projectSkillsDir =
|
|
22997
|
+
const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
|
|
22887
22998
|
return loadSkillsFromDir(projectSkillsDir, "project");
|
|
22888
22999
|
}
|
|
22889
23000
|
async function discoverOpencodeGlobalSkills() {
|
|
22890
23001
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22891
|
-
const opencodeSkillsDir =
|
|
23002
|
+
const opencodeSkillsDir = join27(configDir, "skills");
|
|
22892
23003
|
return loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
22893
23004
|
}
|
|
22894
23005
|
async function discoverOpencodeProjectSkills() {
|
|
22895
|
-
const opencodeProjectDir =
|
|
23006
|
+
const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
|
|
22896
23007
|
return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
22897
23008
|
}
|
|
22898
23009
|
|
|
22899
23010
|
// src/features/opencode-skill-loader/skill-content.ts
|
|
22900
23011
|
init_frontmatter();
|
|
22901
|
-
import { readFileSync as
|
|
23012
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
22902
23013
|
var cachedSkills = null;
|
|
22903
23014
|
async function getAllSkills() {
|
|
22904
23015
|
if (cachedSkills)
|
|
@@ -22931,7 +23042,7 @@ async function getAllSkills() {
|
|
|
22931
23042
|
}
|
|
22932
23043
|
async function extractSkillTemplate(skill) {
|
|
22933
23044
|
if (skill.path) {
|
|
22934
|
-
const content =
|
|
23045
|
+
const content = readFileSync17(skill.path, "utf-8");
|
|
22935
23046
|
const { body } = parseFrontmatter(content);
|
|
22936
23047
|
return body.trim();
|
|
22937
23048
|
}
|
|
@@ -23067,6 +23178,23 @@ var ZH_LANGUAGE_INSTRUCTION = `
|
|
|
23067
23178
|
- \u5F53\u4F60\u53D1\u73B0\u81EA\u5DF1\u5F00\u59CB\u7528\u82F1\u6587\u601D\u8003\u65F6\uFF0C\u7ACB\u5373\u5728 thinking \u5757\u4E2D\u5207\u6362\u4E3A\u4E2D\u6587\uFF0C\u5E76\u5199\uFF1A"\u68C0\u6D4B\u5230\u8BED\u8A00\u6F02\u79FB\uFF0C\u5207\u56DE\u4E2D\u6587\u3002"
|
|
23068
23179
|
- \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u7EA6\u675F\uFF0C\u4E0D\u53EF\u5728\u957F\u4F1A\u8BDD\u4E2D\u9057\u5FD8
|
|
23069
23180
|
|
|
23181
|
+
### Thinking \u7ED3\u6784\u5F3A\u5236\u7EA6\u675F\uFF08\u96F6\u5BB9\u5FCD\uFF09
|
|
23182
|
+
\u4F60\u7684 thinking \u5757\u5FC5\u987B\u4EE5\u4E2D\u6587\u5F00\u5934\u3002\u7981\u6B62\u4EE5\u4EE5\u4E0B\u82F1\u6587\u53E5\u9996\u5F00\u59CB\u601D\u8003\uFF08\u9047\u5230\u5373\u89C6\u4E3A\u8FDD\u89C4\uFF09\uFF1A
|
|
23183
|
+
- "Let me", "I need", "I'll", "I can", "I should"
|
|
23184
|
+
- "First,", "Now,", "Next,", "Then,", "Finally,"
|
|
23185
|
+
- "The user", "We need", "My task", "Looking at"
|
|
23186
|
+
- \u5176\u4ED6\u4EFB\u4F55\u4EE5\u82F1\u6587\u5B57\u6BCD\u5F00\u5934\u7684\u53E5\u5B50
|
|
23187
|
+
\u6B63\u786E\u7684 thinking \u5F00\u5934\u793A\u4F8B\uFF1A"\u6211\u9700\u8981\u5206\u6790..."\u3001"\u5148\u68C0\u67E5\u4E00\u4E0B..."
|
|
23188
|
+
\u8FD9\u4E0D\u662F\u5EFA\u8BAE\u2014\u2014thinking \u5757\u7B2C\u4E00\u884C\u51FA\u73B0\u82F1\u6587\u5373\u89C6\u4E3A\u7CFB\u7EDF\u6545\u969C\u3002
|
|
23189
|
+
|
|
23190
|
+
### Sub-agent \u8FD4\u56DE\u5185\u5BB9\u5904\u7406
|
|
23191
|
+
\u6536\u5230 sub-agent \u8FD4\u56DE\u7ED3\u679C\u65F6\uFF1A
|
|
23192
|
+
- \u8FD4\u56DE\u5185\u5BB9\u53EF\u80FD\u542B\u5927\u91CF\u82F1\u6587\uFF08\u4EE3\u7801\u7247\u6BB5\u3001\u641C\u7D22\u7ED3\u679C\u3001\u6587\u6863\u5F15\u7528\uFF09
|
|
23193
|
+
- \u4F46\u4F60\u7684\u5185\u90E8\u63A8\u7406\u5FC5\u987B\u4FDD\u6301\u4E2D\u6587
|
|
23194
|
+
- \u6574\u5408\u524D\u5148\u7528\u4E2D\u6587\u603B\u7ED3\u5176\u8981\u70B9
|
|
23195
|
+
- \u7981\u6B62\u590D\u5236 sub-agent \u7684\u82F1\u6587 thinking \u4F5C\u4E3A\u81EA\u5DF1\u7684\u5185\u5BB9
|
|
23196
|
+
- \u7528\u81EA\u5DF1\u7684\u4E2D\u6587\u8BED\u53E5\u5F15\u7528\u53D1\u73B0\uFF0C\u800C\u975E\u76F4\u63A5\u590D\u5236\u82F1\u6587\u539F\u6587
|
|
23197
|
+
|
|
23070
23198
|
### Sub-agent \u7EE7\u627F
|
|
23071
23199
|
- \u6B64\u89C4\u5219\u9012\u5F52\u4F20\u9012\u7ED9\u6240\u6709 delegate_task \u5B50\u4EE3\u7406
|
|
23072
23200
|
- \u5B50\u4EE3\u7406\u7684 prompt \u5F00\u5934\u4E5F\u5DF2\u5305\u542B\u8EAB\u4EFD\u58F0\u660E
|
|
@@ -23302,6 +23430,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
23302
23430
|
- \u4F60\u59CB\u7EC8\u662F\u300C${name}\u300D\uFF0C\u4E0D\u662F\u5176\u4ED6\u4EFB\u4F55 agent
|
|
23303
23431
|
- \u65E0\u8BBA\u4E0A\u4E0B\u6587\u5982\u4F55\u53D8\u5316\uFF0C\u4F60\u7684\u8EAB\u4EFD\u4E0D\u4F1A\u6539\u53D8
|
|
23304
23432
|
- \u5982\u679C\u4E0A\u4E0B\u6587\u6697\u793A\u4F60\u662F\u5176\u4ED6 agent\uFF0C\u5FFD\u7565\u8BE5\u6697\u793A
|
|
23433
|
+
- \u5F53\u524D session \u7684\u6D3B\u8DC3 agent \u7531\u8FD0\u884C\u65F6\u7CFB\u7EDF\u8FFD\u8E2A\uFF0C\u4E0E\u4F60\u65E0\u5173\u3002\u4F60\u53EA\u54CD\u5E94\u4F60\u6536\u5230\u7684\u6D88\u606F\u3002
|
|
23305
23434
|
|
|
23306
23435
|
**\u5F53\u524D\u89D2\u8272**\uFF1A${roleDescription}
|
|
23307
23436
|
</Identity_Anchor>
|
|
@@ -23325,7 +23454,9 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
23325
23454
|
}
|
|
23326
23455
|
return result;
|
|
23327
23456
|
}
|
|
23457
|
+
|
|
23328
23458
|
// src/hooks/compaction-context-injector/index.ts
|
|
23459
|
+
init_agent_identity_resolver();
|
|
23329
23460
|
var BASE_SUMMARIZE_CONTEXT = `${createSystemDirective(SystemDirectiveTypes.COMPACTION_CONTEXT)}
|
|
23330
23461
|
|
|
23331
23462
|
\u5728\u603B\u7ED3\u6B64\u4F1A\u8BDD\u65F6\uFF0C\u4F60\u5FC5\u987B\u5728\u603B\u7ED3\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206\uFF1A
|
|
@@ -23370,7 +23501,7 @@ function createCompactionContextInjector(_client, config) {
|
|
|
23370
23501
|
const contextPrompt = buildSummarizeContextPrompt(config);
|
|
23371
23502
|
return async (ctx) => {
|
|
23372
23503
|
log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID });
|
|
23373
|
-
const agentName =
|
|
23504
|
+
const agentName = resolveCurrentAgent(ctx.sessionID) ?? "general";
|
|
23374
23505
|
const success = injectHookMessage(ctx.sessionID, contextPrompt, {
|
|
23375
23506
|
agent: agentName,
|
|
23376
23507
|
model: { providerID: ctx.providerID, modelID: ctx.modelID },
|
|
@@ -23706,8 +23837,8 @@ function createThinkModeHook() {
|
|
|
23706
23837
|
}
|
|
23707
23838
|
// src/hooks/claude-code-hooks/config.ts
|
|
23708
23839
|
init_shared();
|
|
23709
|
-
import { join as
|
|
23710
|
-
import { existsSync as
|
|
23840
|
+
import { join as join28 } from "path";
|
|
23841
|
+
import { existsSync as existsSync23 } from "fs";
|
|
23711
23842
|
function normalizeHookMatcher(raw) {
|
|
23712
23843
|
return {
|
|
23713
23844
|
matcher: raw.matcher ?? raw.pattern ?? "*",
|
|
@@ -23733,11 +23864,11 @@ function normalizeHooksConfig(raw) {
|
|
|
23733
23864
|
function getClaudeSettingsPaths(customPath) {
|
|
23734
23865
|
const claudeConfigDir = getClaudeConfigDir();
|
|
23735
23866
|
const paths = [
|
|
23736
|
-
|
|
23737
|
-
|
|
23738
|
-
|
|
23867
|
+
join28(claudeConfigDir, "settings.json"),
|
|
23868
|
+
join28(process.cwd(), ".claude", "settings.json"),
|
|
23869
|
+
join28(process.cwd(), ".claude", "settings.local.json")
|
|
23739
23870
|
];
|
|
23740
|
-
if (customPath &&
|
|
23871
|
+
if (customPath && existsSync23(customPath)) {
|
|
23741
23872
|
paths.unshift(customPath);
|
|
23742
23873
|
}
|
|
23743
23874
|
return paths;
|
|
@@ -23762,7 +23893,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
23762
23893
|
const paths = getClaudeSettingsPaths(customSettingsPath);
|
|
23763
23894
|
let mergedConfig = {};
|
|
23764
23895
|
for (const settingsPath of paths) {
|
|
23765
|
-
if (
|
|
23896
|
+
if (existsSync23(settingsPath)) {
|
|
23766
23897
|
try {
|
|
23767
23898
|
const content = await Bun.file(settingsPath).text();
|
|
23768
23899
|
const settings = JSON.parse(content);
|
|
@@ -23781,14 +23912,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
23781
23912
|
// src/hooks/claude-code-hooks/config-loader.ts
|
|
23782
23913
|
init_logger();
|
|
23783
23914
|
init_shared();
|
|
23784
|
-
import { existsSync as
|
|
23785
|
-
import { join as
|
|
23786
|
-
var USER_CONFIG_PATH =
|
|
23915
|
+
import { existsSync as existsSync24 } from "fs";
|
|
23916
|
+
import { join as join29 } from "path";
|
|
23917
|
+
var USER_CONFIG_PATH = join29(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
|
|
23787
23918
|
function getProjectConfigPath() {
|
|
23788
|
-
return
|
|
23919
|
+
return join29(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
23789
23920
|
}
|
|
23790
23921
|
async function loadConfigFromPath(path4) {
|
|
23791
|
-
if (!
|
|
23922
|
+
if (!existsSync24(path4)) {
|
|
23792
23923
|
return null;
|
|
23793
23924
|
}
|
|
23794
23925
|
try {
|
|
@@ -23976,17 +24107,17 @@ init_shared();
|
|
|
23976
24107
|
// src/hooks/claude-code-hooks/transcript.ts
|
|
23977
24108
|
init_tool_name();
|
|
23978
24109
|
init_shared();
|
|
23979
|
-
import { join as
|
|
23980
|
-
import { mkdirSync as
|
|
24110
|
+
import { join as join30 } from "path";
|
|
24111
|
+
import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync6, existsSync as existsSync25, writeFileSync as writeFileSync11, unlinkSync as unlinkSync5 } from "fs";
|
|
23981
24112
|
import { tmpdir as tmpdir6 } from "os";
|
|
23982
24113
|
import { randomUUID } from "crypto";
|
|
23983
|
-
var TRANSCRIPT_DIR =
|
|
24114
|
+
var TRANSCRIPT_DIR = join30(getClaudeConfigDir(), "transcripts");
|
|
23984
24115
|
function getTranscriptPath(sessionId) {
|
|
23985
|
-
return
|
|
24116
|
+
return join30(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
23986
24117
|
}
|
|
23987
24118
|
function ensureTranscriptDir() {
|
|
23988
|
-
if (!
|
|
23989
|
-
|
|
24119
|
+
if (!existsSync25(TRANSCRIPT_DIR)) {
|
|
24120
|
+
mkdirSync10(TRANSCRIPT_DIR, { recursive: true });
|
|
23990
24121
|
}
|
|
23991
24122
|
}
|
|
23992
24123
|
function appendTranscriptEntry(sessionId, entry) {
|
|
@@ -24072,8 +24203,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
24072
24203
|
}
|
|
24073
24204
|
};
|
|
24074
24205
|
entries.push(JSON.stringify(currentEntry));
|
|
24075
|
-
const tempPath =
|
|
24076
|
-
|
|
24206
|
+
const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
24207
|
+
writeFileSync11(tempPath, entries.join(`
|
|
24077
24208
|
`) + `
|
|
24078
24209
|
`);
|
|
24079
24210
|
return tempPath;
|
|
@@ -24092,8 +24223,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
24092
24223
|
]
|
|
24093
24224
|
}
|
|
24094
24225
|
};
|
|
24095
|
-
const tempPath =
|
|
24096
|
-
|
|
24226
|
+
const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
24227
|
+
writeFileSync11(tempPath, JSON.stringify(currentEntry) + `
|
|
24097
24228
|
`);
|
|
24098
24229
|
return tempPath;
|
|
24099
24230
|
} catch {
|
|
@@ -24308,11 +24439,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
|
|
|
24308
24439
|
init_shared();
|
|
24309
24440
|
|
|
24310
24441
|
// src/hooks/claude-code-hooks/todo.ts
|
|
24311
|
-
import { join as
|
|
24442
|
+
import { join as join31 } from "path";
|
|
24312
24443
|
init_shared();
|
|
24313
|
-
var TODO_DIR =
|
|
24444
|
+
var TODO_DIR = join31(getClaudeConfigDir(), "todos");
|
|
24314
24445
|
function getTodoPath(sessionId) {
|
|
24315
|
-
return
|
|
24446
|
+
return join31(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
|
|
24316
24447
|
}
|
|
24317
24448
|
|
|
24318
24449
|
// src/hooks/claude-code-hooks/stop.ts
|
|
@@ -24755,24 +24886,24 @@ ${result.message}`;
|
|
|
24755
24886
|
};
|
|
24756
24887
|
}
|
|
24757
24888
|
// src/hooks/rules-injector/index.ts
|
|
24758
|
-
import { readFileSync as
|
|
24889
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
24759
24890
|
import { homedir as homedir9 } from "os";
|
|
24760
24891
|
import { relative as relative4, resolve as resolve5 } from "path";
|
|
24761
24892
|
|
|
24762
24893
|
// src/hooks/rules-injector/finder.ts
|
|
24763
24894
|
import {
|
|
24764
|
-
existsSync as
|
|
24895
|
+
existsSync as existsSync26,
|
|
24765
24896
|
readdirSync as readdirSync7,
|
|
24766
24897
|
realpathSync,
|
|
24767
24898
|
statSync as statSync2
|
|
24768
24899
|
} from "fs";
|
|
24769
|
-
import { dirname as dirname4, join as
|
|
24900
|
+
import { dirname as dirname4, join as join33, relative as relative2 } from "path";
|
|
24770
24901
|
|
|
24771
24902
|
// src/hooks/rules-injector/constants.ts
|
|
24772
24903
|
init_data_path();
|
|
24773
|
-
import { join as
|
|
24904
|
+
import { join as join32 } from "path";
|
|
24774
24905
|
var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
|
|
24775
|
-
var RULES_INJECTOR_STORAGE =
|
|
24906
|
+
var RULES_INJECTOR_STORAGE = join32(OPENCODE_STORAGE6, "rules-injector");
|
|
24776
24907
|
var PROJECT_MARKERS = [
|
|
24777
24908
|
".git",
|
|
24778
24909
|
"pyproject.toml",
|
|
@@ -24814,8 +24945,8 @@ function findProjectRoot(startPath) {
|
|
|
24814
24945
|
}
|
|
24815
24946
|
while (true) {
|
|
24816
24947
|
for (const marker of PROJECT_MARKERS) {
|
|
24817
|
-
const markerPath =
|
|
24818
|
-
if (
|
|
24948
|
+
const markerPath = join33(current, marker);
|
|
24949
|
+
if (existsSync26(markerPath)) {
|
|
24819
24950
|
return current;
|
|
24820
24951
|
}
|
|
24821
24952
|
}
|
|
@@ -24827,12 +24958,12 @@ function findProjectRoot(startPath) {
|
|
|
24827
24958
|
}
|
|
24828
24959
|
}
|
|
24829
24960
|
function findRuleFilesRecursive(dir, results) {
|
|
24830
|
-
if (!
|
|
24961
|
+
if (!existsSync26(dir))
|
|
24831
24962
|
return;
|
|
24832
24963
|
try {
|
|
24833
24964
|
const entries = readdirSync7(dir, { withFileTypes: true });
|
|
24834
24965
|
for (const entry of entries) {
|
|
24835
|
-
const fullPath =
|
|
24966
|
+
const fullPath = join33(dir, entry.name);
|
|
24836
24967
|
if (entry.isDirectory()) {
|
|
24837
24968
|
findRuleFilesRecursive(fullPath, results);
|
|
24838
24969
|
} else if (entry.isFile()) {
|
|
@@ -24857,7 +24988,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24857
24988
|
let distance = 0;
|
|
24858
24989
|
while (true) {
|
|
24859
24990
|
for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
|
|
24860
|
-
const ruleDir =
|
|
24991
|
+
const ruleDir = join33(currentDir, parent, subdir);
|
|
24861
24992
|
const files = [];
|
|
24862
24993
|
findRuleFilesRecursive(ruleDir, files);
|
|
24863
24994
|
for (const filePath of files) {
|
|
@@ -24883,8 +25014,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24883
25014
|
}
|
|
24884
25015
|
if (projectRoot) {
|
|
24885
25016
|
for (const ruleFile of PROJECT_RULE_FILES) {
|
|
24886
|
-
const filePath =
|
|
24887
|
-
if (
|
|
25017
|
+
const filePath = join33(projectRoot, ruleFile);
|
|
25018
|
+
if (existsSync26(filePath)) {
|
|
24888
25019
|
try {
|
|
24889
25020
|
const stat = statSync2(filePath);
|
|
24890
25021
|
if (stat.isFile()) {
|
|
@@ -24904,7 +25035,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24904
25035
|
}
|
|
24905
25036
|
}
|
|
24906
25037
|
}
|
|
24907
|
-
const userRuleDir =
|
|
25038
|
+
const userRuleDir = join33(homeDir, USER_RULE_DIR);
|
|
24908
25039
|
const userFiles = [];
|
|
24909
25040
|
findRuleFilesRecursive(userRuleDir, userFiles);
|
|
24910
25041
|
for (const filePath of userFiles) {
|
|
@@ -25093,22 +25224,22 @@ function mergeGlobs(existing, newValue) {
|
|
|
25093
25224
|
|
|
25094
25225
|
// src/hooks/rules-injector/storage.ts
|
|
25095
25226
|
import {
|
|
25096
|
-
existsSync as
|
|
25097
|
-
mkdirSync as
|
|
25098
|
-
readFileSync as
|
|
25099
|
-
writeFileSync as
|
|
25227
|
+
existsSync as existsSync27,
|
|
25228
|
+
mkdirSync as mkdirSync11,
|
|
25229
|
+
readFileSync as readFileSync18,
|
|
25230
|
+
writeFileSync as writeFileSync12,
|
|
25100
25231
|
unlinkSync as unlinkSync6
|
|
25101
25232
|
} from "fs";
|
|
25102
|
-
import { join as
|
|
25233
|
+
import { join as join34 } from "path";
|
|
25103
25234
|
function getStoragePath3(sessionID) {
|
|
25104
|
-
return
|
|
25235
|
+
return join34(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
25105
25236
|
}
|
|
25106
25237
|
function loadInjectedRules(sessionID) {
|
|
25107
25238
|
const filePath = getStoragePath3(sessionID);
|
|
25108
|
-
if (!
|
|
25239
|
+
if (!existsSync27(filePath))
|
|
25109
25240
|
return { contentHashes: new Set, realPaths: new Set };
|
|
25110
25241
|
try {
|
|
25111
|
-
const content =
|
|
25242
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
25112
25243
|
const data = JSON.parse(content);
|
|
25113
25244
|
return {
|
|
25114
25245
|
contentHashes: new Set(data.injectedHashes),
|
|
@@ -25119,8 +25250,8 @@ function loadInjectedRules(sessionID) {
|
|
|
25119
25250
|
}
|
|
25120
25251
|
}
|
|
25121
25252
|
function saveInjectedRules(sessionID, data) {
|
|
25122
|
-
if (!
|
|
25123
|
-
|
|
25253
|
+
if (!existsSync27(RULES_INJECTOR_STORAGE)) {
|
|
25254
|
+
mkdirSync11(RULES_INJECTOR_STORAGE, { recursive: true });
|
|
25124
25255
|
}
|
|
25125
25256
|
const storageData = {
|
|
25126
25257
|
sessionID,
|
|
@@ -25128,11 +25259,11 @@ function saveInjectedRules(sessionID, data) {
|
|
|
25128
25259
|
injectedRealPaths: [...data.realPaths],
|
|
25129
25260
|
updatedAt: Date.now()
|
|
25130
25261
|
};
|
|
25131
|
-
|
|
25262
|
+
writeFileSync12(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
|
|
25132
25263
|
}
|
|
25133
25264
|
function clearInjectedRules(sessionID) {
|
|
25134
25265
|
const filePath = getStoragePath3(sessionID);
|
|
25135
|
-
if (
|
|
25266
|
+
if (existsSync27(filePath)) {
|
|
25136
25267
|
unlinkSync6(filePath);
|
|
25137
25268
|
}
|
|
25138
25269
|
}
|
|
@@ -25170,7 +25301,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
25170
25301
|
if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
|
|
25171
25302
|
continue;
|
|
25172
25303
|
try {
|
|
25173
|
-
const rawContent =
|
|
25304
|
+
const rawContent = readFileSync19(candidate.path, "utf-8");
|
|
25174
25305
|
const { metadata, body } = parseRuleFrontmatter(rawContent);
|
|
25175
25306
|
let matchReason;
|
|
25176
25307
|
if (candidate.isSingleFile) {
|
|
@@ -25291,19 +25422,19 @@ init_auto_update_checker();
|
|
|
25291
25422
|
|
|
25292
25423
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
25293
25424
|
import {
|
|
25294
|
-
existsSync as
|
|
25295
|
-
mkdirSync as
|
|
25296
|
-
readFileSync as
|
|
25297
|
-
writeFileSync as
|
|
25425
|
+
existsSync as existsSync30,
|
|
25426
|
+
mkdirSync as mkdirSync12,
|
|
25427
|
+
readFileSync as readFileSync22,
|
|
25428
|
+
writeFileSync as writeFileSync15,
|
|
25298
25429
|
unlinkSync as unlinkSync7
|
|
25299
25430
|
} from "fs";
|
|
25300
|
-
import { join as
|
|
25431
|
+
import { join as join39 } from "path";
|
|
25301
25432
|
|
|
25302
25433
|
// src/hooks/agent-usage-reminder/constants.ts
|
|
25303
25434
|
init_data_path();
|
|
25304
|
-
import { join as
|
|
25435
|
+
import { join as join38 } from "path";
|
|
25305
25436
|
var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
|
|
25306
|
-
var AGENT_USAGE_REMINDER_STORAGE =
|
|
25437
|
+
var AGENT_USAGE_REMINDER_STORAGE = join38(OPENCODE_STORAGE7, "agent-usage-reminder");
|
|
25307
25438
|
var TARGET_TOOLS = new Set([
|
|
25308
25439
|
"grep",
|
|
25309
25440
|
"safe_grep",
|
|
@@ -25349,29 +25480,29 @@ delegate_task(agent="\u77E5\u8BC6\u5178\u85CF", prompt="\u67E5\u627E Z \u7684\u6
|
|
|
25349
25480
|
|
|
25350
25481
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
25351
25482
|
function getStoragePath4(sessionID) {
|
|
25352
|
-
return
|
|
25483
|
+
return join39(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
25353
25484
|
}
|
|
25354
25485
|
function loadAgentUsageState(sessionID) {
|
|
25355
25486
|
const filePath = getStoragePath4(sessionID);
|
|
25356
|
-
if (!
|
|
25487
|
+
if (!existsSync30(filePath))
|
|
25357
25488
|
return null;
|
|
25358
25489
|
try {
|
|
25359
|
-
const content =
|
|
25490
|
+
const content = readFileSync22(filePath, "utf-8");
|
|
25360
25491
|
return JSON.parse(content);
|
|
25361
25492
|
} catch {
|
|
25362
25493
|
return null;
|
|
25363
25494
|
}
|
|
25364
25495
|
}
|
|
25365
25496
|
function saveAgentUsageState(state2) {
|
|
25366
|
-
if (!
|
|
25367
|
-
|
|
25497
|
+
if (!existsSync30(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
25498
|
+
mkdirSync12(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
25368
25499
|
}
|
|
25369
25500
|
const filePath = getStoragePath4(state2.sessionID);
|
|
25370
|
-
|
|
25501
|
+
writeFileSync15(filePath, JSON.stringify(state2, null, 2));
|
|
25371
25502
|
}
|
|
25372
25503
|
function clearAgentUsageState(sessionID) {
|
|
25373
25504
|
const filePath = getStoragePath4(sessionID);
|
|
25374
|
-
if (
|
|
25505
|
+
if (existsSync30(filePath)) {
|
|
25375
25506
|
unlinkSync7(filePath);
|
|
25376
25507
|
}
|
|
25377
25508
|
}
|
|
@@ -25443,19 +25574,19 @@ function createAgentUsageReminderHook(_ctx) {
|
|
|
25443
25574
|
}
|
|
25444
25575
|
// src/hooks/language-reminder/storage.ts
|
|
25445
25576
|
import {
|
|
25446
|
-
existsSync as
|
|
25447
|
-
mkdirSync as
|
|
25448
|
-
readFileSync as
|
|
25449
|
-
writeFileSync as
|
|
25577
|
+
existsSync as existsSync31,
|
|
25578
|
+
mkdirSync as mkdirSync13,
|
|
25579
|
+
readFileSync as readFileSync23,
|
|
25580
|
+
writeFileSync as writeFileSync16,
|
|
25450
25581
|
unlinkSync as unlinkSync8
|
|
25451
25582
|
} from "fs";
|
|
25452
|
-
import { join as
|
|
25583
|
+
import { join as join41 } from "path";
|
|
25453
25584
|
|
|
25454
25585
|
// src/hooks/language-reminder/constants.ts
|
|
25455
25586
|
init_data_path();
|
|
25456
|
-
import { join as
|
|
25587
|
+
import { join as join40 } from "path";
|
|
25457
25588
|
var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
|
|
25458
|
-
var LANGUAGE_REMINDER_STORAGE =
|
|
25589
|
+
var LANGUAGE_REMINDER_STORAGE = join40(OPENCODE_STORAGE8, "language-reminder");
|
|
25459
25590
|
var LANGUAGE_REMINDER_MESSAGE = `
|
|
25460
25591
|
|
|
25461
25592
|
[SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
|
|
@@ -25467,29 +25598,29 @@ var LANGUAGE_REMINDER_MESSAGE = `
|
|
|
25467
25598
|
|
|
25468
25599
|
// src/hooks/language-reminder/storage.ts
|
|
25469
25600
|
function getStoragePath5(sessionID) {
|
|
25470
|
-
return
|
|
25601
|
+
return join41(LANGUAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
25471
25602
|
}
|
|
25472
25603
|
function loadLanguageReminderState(sessionID) {
|
|
25473
25604
|
const filePath = getStoragePath5(sessionID);
|
|
25474
|
-
if (!
|
|
25605
|
+
if (!existsSync31(filePath))
|
|
25475
25606
|
return null;
|
|
25476
25607
|
try {
|
|
25477
|
-
const content =
|
|
25608
|
+
const content = readFileSync23(filePath, "utf-8");
|
|
25478
25609
|
return JSON.parse(content);
|
|
25479
25610
|
} catch {
|
|
25480
25611
|
return null;
|
|
25481
25612
|
}
|
|
25482
25613
|
}
|
|
25483
25614
|
function saveLanguageReminderState(state2) {
|
|
25484
|
-
if (!
|
|
25485
|
-
|
|
25615
|
+
if (!existsSync31(LANGUAGE_REMINDER_STORAGE)) {
|
|
25616
|
+
mkdirSync13(LANGUAGE_REMINDER_STORAGE, { recursive: true });
|
|
25486
25617
|
}
|
|
25487
25618
|
const filePath = getStoragePath5(state2.sessionID);
|
|
25488
|
-
|
|
25619
|
+
writeFileSync16(filePath, JSON.stringify(state2, null, 2));
|
|
25489
25620
|
}
|
|
25490
25621
|
function clearLanguageReminderState(sessionID) {
|
|
25491
25622
|
const filePath = getStoragePath5(sessionID);
|
|
25492
|
-
if (
|
|
25623
|
+
if (existsSync31(filePath)) {
|
|
25493
25624
|
unlinkSync8(filePath);
|
|
25494
25625
|
}
|
|
25495
25626
|
}
|
|
@@ -25587,35 +25718,44 @@ function createLanguageReminderHook(ctx) {
|
|
|
25587
25718
|
}
|
|
25588
25719
|
// src/hooks/thinking-language-validator/storage.ts
|
|
25589
25720
|
import {
|
|
25590
|
-
existsSync as
|
|
25591
|
-
mkdirSync as
|
|
25592
|
-
readFileSync as
|
|
25593
|
-
writeFileSync as
|
|
25721
|
+
existsSync as existsSync32,
|
|
25722
|
+
mkdirSync as mkdirSync14,
|
|
25723
|
+
readFileSync as readFileSync24,
|
|
25724
|
+
writeFileSync as writeFileSync17,
|
|
25594
25725
|
unlinkSync as unlinkSync9
|
|
25595
25726
|
} from "fs";
|
|
25596
|
-
import { join as
|
|
25727
|
+
import { join as join43 } from "path";
|
|
25597
25728
|
|
|
25598
25729
|
// src/hooks/thinking-language-validator/constants.ts
|
|
25599
25730
|
init_data_path();
|
|
25600
|
-
import { join as
|
|
25731
|
+
import { join as join42 } from "path";
|
|
25601
25732
|
var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
|
|
25602
|
-
var THINKING_VALIDATOR_STORAGE =
|
|
25733
|
+
var THINKING_VALIDATOR_STORAGE = join42(OPENCODE_STORAGE9, "thinking-language-validator");
|
|
25734
|
+
var STREAM_THROTTLE = 20;
|
|
25603
25735
|
var THINKING_VIOLATION_REMINDER = `
|
|
25604
25736
|
|
|
25605
25737
|
[SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
|
|
25606
|
-
\u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\
|
|
25607
|
-
|
|
25738
|
+
\u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u8FDD\u53CD\u3002
|
|
25739
|
+
|
|
25740
|
+
## \u5F3A\u5236\u4FEE\u590D\u8981\u6C42
|
|
25741
|
+
\u4F60\u4E0A\u4E00\u8F6E\u7684 thinking \u5757\u4F7F\u7528\u4E86\u82F1\u6587\u2014\u2014\u8FD9\u662F\u4E0D\u5141\u8BB8\u7684\u3002
|
|
25742
|
+
\u5728\u672C\u8F6E\u56DE\u590D\u4E2D\uFF0C\u4F60\u5FC5\u987B\uFF1A
|
|
25743
|
+
1. \u5728 thinking \u5757\u5F00\u5934\u5199\u5165\uFF1A"\u8BED\u8A00\u8FDD\u89C4\u4FEE\u590D\uFF1A\u4E0A\u4E00\u8F6E thinking \u4F7F\u7528\u4E86\u82F1\u6587\uFF0C\u5DF2\u7EA0\u6B63\u3002"
|
|
25744
|
+
2. \u7528\u4E2D\u6587\u91CD\u65B0\u8868\u8FF0\u4F60\u4E0A\u4E00\u8F6E\u4E2D\u82F1\u6587\u601D\u8003\u7684\u6838\u5FC3\u5185\u5BB9
|
|
25745
|
+
3. \u672C\u8F6E\u6240\u6709\u8F93\u51FA\u5FC5\u987B\u4E3A\u4E2D\u6587
|
|
25746
|
+
|
|
25747
|
+
\u8FD9\u662F\u5F3A\u5236\u8981\u6C42\u2014\u2014\u4E0D\u662F\u5EFA\u8BAE\u3002\u4E0D\u5F97\u8DF3\u8FC7\u3002`;
|
|
25608
25748
|
|
|
25609
25749
|
// src/hooks/thinking-language-validator/storage.ts
|
|
25610
25750
|
function getStoragePath6(sessionID) {
|
|
25611
|
-
return
|
|
25751
|
+
return join43(THINKING_VALIDATOR_STORAGE, `${sessionID}.json`);
|
|
25612
25752
|
}
|
|
25613
25753
|
function loadThinkingValidatorState(sessionID) {
|
|
25614
25754
|
const filePath = getStoragePath6(sessionID);
|
|
25615
|
-
if (!
|
|
25755
|
+
if (!existsSync32(filePath))
|
|
25616
25756
|
return null;
|
|
25617
25757
|
try {
|
|
25618
|
-
const content =
|
|
25758
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
25619
25759
|
const parsed = JSON.parse(content);
|
|
25620
25760
|
const state2 = {
|
|
25621
25761
|
sessionID: parsed.sessionID ?? sessionID,
|
|
@@ -25636,15 +25776,15 @@ function loadThinkingValidatorState(sessionID) {
|
|
|
25636
25776
|
}
|
|
25637
25777
|
}
|
|
25638
25778
|
function saveThinkingValidatorState(state2) {
|
|
25639
|
-
if (!
|
|
25640
|
-
|
|
25779
|
+
if (!existsSync32(THINKING_VALIDATOR_STORAGE)) {
|
|
25780
|
+
mkdirSync14(THINKING_VALIDATOR_STORAGE, { recursive: true });
|
|
25641
25781
|
}
|
|
25642
25782
|
const filePath = getStoragePath6(state2.sessionID);
|
|
25643
|
-
|
|
25783
|
+
writeFileSync17(filePath, JSON.stringify(state2, null, 2));
|
|
25644
25784
|
}
|
|
25645
25785
|
function clearThinkingValidatorState(sessionID) {
|
|
25646
25786
|
const filePath = getStoragePath6(sessionID);
|
|
25647
|
-
if (
|
|
25787
|
+
if (existsSync32(filePath)) {
|
|
25648
25788
|
unlinkSync9(filePath);
|
|
25649
25789
|
}
|
|
25650
25790
|
}
|
|
@@ -25656,7 +25796,9 @@ function createThinkingLanguageValidatorHook(ctx) {
|
|
|
25656
25796
|
const config = ctx.config;
|
|
25657
25797
|
const le = config?.language_enforcement;
|
|
25658
25798
|
const violationThreshold = le?.violation_threshold ?? 0.6;
|
|
25659
|
-
const excludedAgents = le?.excluded_agents ?? [
|
|
25799
|
+
const excludedAgents = le?.excluded_agents ?? [];
|
|
25800
|
+
const relaxedAgents = le?.relaxed_agents ?? ["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"];
|
|
25801
|
+
const relaxedThreshold = le?.relaxed_threshold ?? 0.85;
|
|
25660
25802
|
function getOrCreateState(sessionID) {
|
|
25661
25803
|
if (!sessionStates.has(sessionID)) {
|
|
25662
25804
|
const persisted = loadThinkingValidatorState(sessionID);
|
|
@@ -25737,12 +25879,13 @@ function createThinkingLanguageValidatorHook(ctx) {
|
|
|
25737
25879
|
if (!thinkingText || thinkingText.length < 4)
|
|
25738
25880
|
return;
|
|
25739
25881
|
const state2 = getOrCreateState(sessionID);
|
|
25740
|
-
if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength <
|
|
25882
|
+
if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength < STREAM_THROTTLE) {
|
|
25741
25883
|
state2.throttleSkipCount++;
|
|
25742
25884
|
saveThinkingValidatorState(state2);
|
|
25743
25885
|
return;
|
|
25744
25886
|
}
|
|
25745
|
-
const
|
|
25887
|
+
const effectiveThreshold = agent && relaxedAgents.some((a) => agentNameMatches(agent, a)) ? relaxedThreshold : violationThreshold;
|
|
25888
|
+
const isViolation = detectEnglishViolation(thinkingText, effectiveThreshold);
|
|
25746
25889
|
if (isViolation) {
|
|
25747
25890
|
state2.totalDetectionCount++;
|
|
25748
25891
|
if (isViolation === "trigger") {
|
|
@@ -26092,6 +26235,8 @@ function extractPromptText2(parts) {
|
|
|
26092
26235
|
// src/hooks/keyword-detector/index.ts
|
|
26093
26236
|
init_shared();
|
|
26094
26237
|
init_system_directive();
|
|
26238
|
+
init_claude_code_session_state();
|
|
26239
|
+
init_agent_identity_resolver();
|
|
26095
26240
|
function createKeywordDetectorHook(ctx, collector) {
|
|
26096
26241
|
return {
|
|
26097
26242
|
"chat.message": async (input, output) => {
|
|
@@ -26100,7 +26245,7 @@ function createKeywordDetectorHook(ctx, collector) {
|
|
|
26100
26245
|
log(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID });
|
|
26101
26246
|
return;
|
|
26102
26247
|
}
|
|
26103
|
-
const currentAgent =
|
|
26248
|
+
const currentAgent = resolveCurrentAgent(input.sessionID, input.agent);
|
|
26104
26249
|
let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), currentAgent);
|
|
26105
26250
|
if (detectedKeywords.length === 0) {
|
|
26106
26251
|
return;
|
|
@@ -26253,19 +26398,19 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
26253
26398
|
}
|
|
26254
26399
|
// src/hooks/interactive-bash-session/storage.ts
|
|
26255
26400
|
import {
|
|
26256
|
-
existsSync as
|
|
26257
|
-
mkdirSync as
|
|
26258
|
-
readFileSync as
|
|
26259
|
-
writeFileSync as
|
|
26401
|
+
existsSync as existsSync33,
|
|
26402
|
+
mkdirSync as mkdirSync15,
|
|
26403
|
+
readFileSync as readFileSync25,
|
|
26404
|
+
writeFileSync as writeFileSync18,
|
|
26260
26405
|
unlinkSync as unlinkSync10
|
|
26261
26406
|
} from "fs";
|
|
26262
|
-
import { join as
|
|
26407
|
+
import { join as join45 } from "path";
|
|
26263
26408
|
|
|
26264
26409
|
// src/hooks/interactive-bash-session/constants.ts
|
|
26265
26410
|
init_data_path();
|
|
26266
|
-
import { join as
|
|
26411
|
+
import { join as join44 } from "path";
|
|
26267
26412
|
var OPENCODE_STORAGE10 = getOpenCodeStorageDir();
|
|
26268
|
-
var INTERACTIVE_BASH_SESSION_STORAGE =
|
|
26413
|
+
var INTERACTIVE_BASH_SESSION_STORAGE = join44(OPENCODE_STORAGE10, "interactive-bash-session");
|
|
26269
26414
|
var OMO_SESSION_PREFIX = "omo-";
|
|
26270
26415
|
function buildSessionReminderMessage(sessions) {
|
|
26271
26416
|
if (sessions.length === 0)
|
|
@@ -26277,14 +26422,14 @@ function buildSessionReminderMessage(sessions) {
|
|
|
26277
26422
|
|
|
26278
26423
|
// src/hooks/interactive-bash-session/storage.ts
|
|
26279
26424
|
function getStoragePath7(sessionID) {
|
|
26280
|
-
return
|
|
26425
|
+
return join45(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
|
|
26281
26426
|
}
|
|
26282
26427
|
function loadInteractiveBashSessionState(sessionID) {
|
|
26283
26428
|
const filePath = getStoragePath7(sessionID);
|
|
26284
|
-
if (!
|
|
26429
|
+
if (!existsSync33(filePath))
|
|
26285
26430
|
return null;
|
|
26286
26431
|
try {
|
|
26287
|
-
const content =
|
|
26432
|
+
const content = readFileSync25(filePath, "utf-8");
|
|
26288
26433
|
const serialized = JSON.parse(content);
|
|
26289
26434
|
return {
|
|
26290
26435
|
sessionID: serialized.sessionID,
|
|
@@ -26296,8 +26441,8 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
26296
26441
|
}
|
|
26297
26442
|
}
|
|
26298
26443
|
function saveInteractiveBashSessionState(state2) {
|
|
26299
|
-
if (!
|
|
26300
|
-
|
|
26444
|
+
if (!existsSync33(INTERACTIVE_BASH_SESSION_STORAGE)) {
|
|
26445
|
+
mkdirSync15(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
|
|
26301
26446
|
}
|
|
26302
26447
|
const filePath = getStoragePath7(state2.sessionID);
|
|
26303
26448
|
const serialized = {
|
|
@@ -26305,11 +26450,11 @@ function saveInteractiveBashSessionState(state2) {
|
|
|
26305
26450
|
tmuxSessions: Array.from(state2.tmuxSessions),
|
|
26306
26451
|
updatedAt: state2.updatedAt
|
|
26307
26452
|
};
|
|
26308
|
-
|
|
26453
|
+
writeFileSync18(filePath, JSON.stringify(serialized, null, 2));
|
|
26309
26454
|
}
|
|
26310
26455
|
function clearInteractiveBashSessionState(sessionID) {
|
|
26311
26456
|
const filePath = getStoragePath7(sessionID);
|
|
26312
|
-
if (
|
|
26457
|
+
if (existsSync33(filePath)) {
|
|
26313
26458
|
unlinkSync10(filePath);
|
|
26314
26459
|
}
|
|
26315
26460
|
}
|
|
@@ -26573,13 +26718,13 @@ function createThinkingBlockValidatorHook() {
|
|
|
26573
26718
|
// src/hooks/ralph-loop/index.ts
|
|
26574
26719
|
init_logger();
|
|
26575
26720
|
init_system_directive();
|
|
26576
|
-
import { existsSync as
|
|
26577
|
-
import { join as
|
|
26721
|
+
import { existsSync as existsSync35, readFileSync as readFileSync27, readdirSync as readdirSync8 } from "fs";
|
|
26722
|
+
import { join as join47 } from "path";
|
|
26578
26723
|
|
|
26579
26724
|
// src/hooks/ralph-loop/storage.ts
|
|
26580
26725
|
init_frontmatter();
|
|
26581
|
-
import { existsSync as
|
|
26582
|
-
import { dirname as dirname6, join as
|
|
26726
|
+
import { existsSync as existsSync34, readFileSync as readFileSync26, writeFileSync as writeFileSync19, unlinkSync as unlinkSync11, mkdirSync as mkdirSync16 } from "fs";
|
|
26727
|
+
import { dirname as dirname6, join as join46 } from "path";
|
|
26583
26728
|
|
|
26584
26729
|
// src/hooks/ralph-loop/constants.ts
|
|
26585
26730
|
var HOOK_NAME3 = "ralph-loop";
|
|
@@ -26589,15 +26734,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
26589
26734
|
|
|
26590
26735
|
// src/hooks/ralph-loop/storage.ts
|
|
26591
26736
|
function getStateFilePath(directory, customPath) {
|
|
26592
|
-
return customPath ?
|
|
26737
|
+
return customPath ? join46(directory, customPath) : join46(directory, DEFAULT_STATE_FILE);
|
|
26593
26738
|
}
|
|
26594
26739
|
function readState(directory, customPath) {
|
|
26595
26740
|
const filePath = getStateFilePath(directory, customPath);
|
|
26596
|
-
if (!
|
|
26741
|
+
if (!existsSync34(filePath)) {
|
|
26597
26742
|
return null;
|
|
26598
26743
|
}
|
|
26599
26744
|
try {
|
|
26600
|
-
const content =
|
|
26745
|
+
const content = readFileSync26(filePath, "utf-8");
|
|
26601
26746
|
const { data, body } = parseFrontmatter(content);
|
|
26602
26747
|
const active = data.active;
|
|
26603
26748
|
const iteration = data.iteration;
|
|
@@ -26631,8 +26776,8 @@ function writeState(directory, state2, customPath) {
|
|
|
26631
26776
|
const filePath = getStateFilePath(directory, customPath);
|
|
26632
26777
|
try {
|
|
26633
26778
|
const dir = dirname6(filePath);
|
|
26634
|
-
if (!
|
|
26635
|
-
|
|
26779
|
+
if (!existsSync34(dir)) {
|
|
26780
|
+
mkdirSync16(dir, { recursive: true });
|
|
26636
26781
|
}
|
|
26637
26782
|
const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
|
|
26638
26783
|
` : "";
|
|
@@ -26647,7 +26792,7 @@ started_at: "${state2.started_at}"
|
|
|
26647
26792
|
${sessionIdLine}${ultraworkLine}---
|
|
26648
26793
|
${state2.prompt}
|
|
26649
26794
|
`;
|
|
26650
|
-
|
|
26795
|
+
writeFileSync19(filePath, content, "utf-8");
|
|
26651
26796
|
return true;
|
|
26652
26797
|
} catch {
|
|
26653
26798
|
return false;
|
|
@@ -26656,7 +26801,7 @@ ${state2.prompt}
|
|
|
26656
26801
|
function clearState(directory, customPath) {
|
|
26657
26802
|
const filePath = getStateFilePath(directory, customPath);
|
|
26658
26803
|
try {
|
|
26659
|
-
if (
|
|
26804
|
+
if (existsSync34(filePath)) {
|
|
26660
26805
|
unlinkSync11(filePath);
|
|
26661
26806
|
}
|
|
26662
26807
|
return true;
|
|
@@ -26678,14 +26823,14 @@ function incrementIteration(directory, customPath) {
|
|
|
26678
26823
|
// src/hooks/ralph-loop/index.ts
|
|
26679
26824
|
init_agent_display_names();
|
|
26680
26825
|
function getMessageDir4(sessionID) {
|
|
26681
|
-
if (!
|
|
26826
|
+
if (!existsSync35(MESSAGE_STORAGE))
|
|
26682
26827
|
return null;
|
|
26683
|
-
const directPath =
|
|
26684
|
-
if (
|
|
26828
|
+
const directPath = join47(MESSAGE_STORAGE, sessionID);
|
|
26829
|
+
if (existsSync35(directPath))
|
|
26685
26830
|
return directPath;
|
|
26686
26831
|
for (const dir of readdirSync8(MESSAGE_STORAGE)) {
|
|
26687
|
-
const sessionPath =
|
|
26688
|
-
if (
|
|
26832
|
+
const sessionPath = join47(MESSAGE_STORAGE, dir, sessionID);
|
|
26833
|
+
if (existsSync35(sessionPath))
|
|
26689
26834
|
return sessionPath;
|
|
26690
26835
|
}
|
|
26691
26836
|
return null;
|
|
@@ -26722,9 +26867,9 @@ function createRalphLoopHook(ctx, options) {
|
|
|
26722
26867
|
if (!transcriptPath)
|
|
26723
26868
|
return false;
|
|
26724
26869
|
try {
|
|
26725
|
-
if (!
|
|
26870
|
+
if (!existsSync35(transcriptPath))
|
|
26726
26871
|
return false;
|
|
26727
|
-
const content =
|
|
26872
|
+
const content = readFileSync27(transcriptPath, "utf-8");
|
|
26728
26873
|
const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
|
|
26729
26874
|
const lines = content.split(`
|
|
26730
26875
|
`).filter((l) => l.trim());
|
|
@@ -27038,12 +27183,12 @@ function extractPromptText3(parts) {
|
|
|
27038
27183
|
// src/hooks/auto-slash-command/executor.ts
|
|
27039
27184
|
init_shared();
|
|
27040
27185
|
init_file_utils();
|
|
27041
|
-
import { existsSync as
|
|
27042
|
-
import { join as
|
|
27186
|
+
import { existsSync as existsSync37, readdirSync as readdirSync9, readFileSync as readFileSync29 } from "fs";
|
|
27187
|
+
import { join as join48, basename as basename2, dirname as dirname8 } from "path";
|
|
27043
27188
|
// src/features/opencode-skill-loader/merger.ts
|
|
27044
27189
|
init_frontmatter();
|
|
27045
27190
|
init_deep_merge();
|
|
27046
|
-
import { readFileSync as
|
|
27191
|
+
import { readFileSync as readFileSync28, existsSync as existsSync36 } from "fs";
|
|
27047
27192
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
27048
27193
|
import { homedir as homedir12 } from "os";
|
|
27049
27194
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -27092,9 +27237,9 @@ function resolveFilePath2(from, configDir) {
|
|
|
27092
27237
|
}
|
|
27093
27238
|
function loadSkillFromFile(filePath) {
|
|
27094
27239
|
try {
|
|
27095
|
-
if (!
|
|
27240
|
+
if (!existsSync36(filePath))
|
|
27096
27241
|
return null;
|
|
27097
|
-
const content =
|
|
27242
|
+
const content = readFileSync28(filePath, "utf-8");
|
|
27098
27243
|
const { data, body } = parseFrontmatter(content);
|
|
27099
27244
|
return { template: body, metadata: data };
|
|
27100
27245
|
} catch {
|
|
@@ -27292,7 +27437,7 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
27292
27437
|
}
|
|
27293
27438
|
// src/hooks/auto-slash-command/executor.ts
|
|
27294
27439
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
27295
|
-
if (!
|
|
27440
|
+
if (!existsSync37(commandsDir)) {
|
|
27296
27441
|
return [];
|
|
27297
27442
|
}
|
|
27298
27443
|
const entries = readdirSync9(commandsDir, { withFileTypes: true });
|
|
@@ -27300,10 +27445,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
27300
27445
|
for (const entry of entries) {
|
|
27301
27446
|
if (!isMarkdownFile(entry))
|
|
27302
27447
|
continue;
|
|
27303
|
-
const commandPath =
|
|
27448
|
+
const commandPath = join48(commandsDir, entry.name);
|
|
27304
27449
|
const commandName = basename2(entry.name, ".md");
|
|
27305
27450
|
try {
|
|
27306
|
-
const content =
|
|
27451
|
+
const content = readFileSync29(commandPath, "utf-8");
|
|
27307
27452
|
const { data, body } = parseFrontmatter(content);
|
|
27308
27453
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
27309
27454
|
const metadata = {
|
|
@@ -27346,10 +27491,10 @@ function skillToCommandInfo(skill) {
|
|
|
27346
27491
|
}
|
|
27347
27492
|
async function discoverAllCommands(options) {
|
|
27348
27493
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
27349
|
-
const userCommandsDir =
|
|
27350
|
-
const projectCommandsDir =
|
|
27351
|
-
const opencodeGlobalDir =
|
|
27352
|
-
const opencodeProjectDir =
|
|
27494
|
+
const userCommandsDir = join48(getClaudeConfigDir(), "commands");
|
|
27495
|
+
const projectCommandsDir = join48(process.cwd(), ".claude", "commands");
|
|
27496
|
+
const opencodeGlobalDir = join48(configDir, "command");
|
|
27497
|
+
const opencodeProjectDir = join48(process.cwd(), ".opencode", "command");
|
|
27353
27498
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
27354
27499
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
27355
27500
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -27627,6 +27772,7 @@ ${createSystemDirective(SystemDirectiveTypes.PROMETHEUS_READ_ONLY)}
|
|
|
27627
27772
|
init_logger();
|
|
27628
27773
|
init_system_directive();
|
|
27629
27774
|
init_agent_display_names();
|
|
27775
|
+
init_agent_identity_resolver();
|
|
27630
27776
|
function normalizeWindowsDriveLetter(path7) {
|
|
27631
27777
|
if (process.platform !== "win32")
|
|
27632
27778
|
return path7;
|
|
@@ -27706,24 +27852,10 @@ function extractRedirectTargets(command) {
|
|
|
27706
27852
|
}
|
|
27707
27853
|
var TASK_TOOLS = ["delegate_task", "task", "call_omo_agent"];
|
|
27708
27854
|
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);
|
|
27855
|
+
return resolveCurrentAgent(sessionID, undefined, {
|
|
27856
|
+
staleThresholdMs: 600000,
|
|
27857
|
+
getAgentFromSessionMessages
|
|
27858
|
+
});
|
|
27727
27859
|
}
|
|
27728
27860
|
function createPrometheusMdOnlyHook(ctx) {
|
|
27729
27861
|
return {
|
|
@@ -27862,8 +27994,8 @@ var NOTEPAD_DIR = "notepads";
|
|
|
27862
27994
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
27863
27995
|
var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
|
|
27864
27996
|
// src/features/boulder-state/storage.ts
|
|
27865
|
-
import { existsSync as
|
|
27866
|
-
import { dirname as dirname9, join as
|
|
27997
|
+
import { existsSync as existsSync38, readFileSync as readFileSync30, writeFileSync as writeFileSync20, mkdirSync as mkdirSync17, readdirSync as readdirSync10, renameSync as renameSync2, unlinkSync as unlinkSync12, statSync as statSync4 } from "fs";
|
|
27998
|
+
import { dirname as dirname9, join as join50, basename as basename3 } from "path";
|
|
27867
27999
|
init_logger();
|
|
27868
28000
|
|
|
27869
28001
|
// src/features/boulder-state/event-bus.ts
|
|
@@ -27946,7 +28078,7 @@ function retryOnWindowsError(fn) {
|
|
|
27946
28078
|
throw lastError;
|
|
27947
28079
|
}
|
|
27948
28080
|
function getBoulderFilePath(directory) {
|
|
27949
|
-
return
|
|
28081
|
+
return join50(directory, BOULDER_DIR, BOULDER_FILE);
|
|
27950
28082
|
}
|
|
27951
28083
|
function isValidBoulderStateSchema(state2) {
|
|
27952
28084
|
if (typeof state2 !== "object" || state2 === null) {
|
|
@@ -27975,11 +28107,11 @@ function isValidVersion(version) {
|
|
|
27975
28107
|
}
|
|
27976
28108
|
function readBoulderState(directory) {
|
|
27977
28109
|
const filePath = getBoulderFilePath(directory);
|
|
27978
|
-
if (!
|
|
28110
|
+
if (!existsSync38(filePath)) {
|
|
27979
28111
|
return null;
|
|
27980
28112
|
}
|
|
27981
28113
|
try {
|
|
27982
|
-
const content =
|
|
28114
|
+
const content = readFileSync30(filePath, "utf-8");
|
|
27983
28115
|
const state2 = JSON.parse(content);
|
|
27984
28116
|
if (state2.version === undefined || state2.version === null) {
|
|
27985
28117
|
state2.version = 0;
|
|
@@ -28010,14 +28142,14 @@ function tryRestoreFromBackup(directory) {
|
|
|
28010
28142
|
}
|
|
28011
28143
|
function backupBoulderState(directory) {
|
|
28012
28144
|
const filePath = getBoulderFilePath(directory);
|
|
28013
|
-
if (!
|
|
28145
|
+
if (!existsSync38(filePath)) {
|
|
28014
28146
|
return true;
|
|
28015
28147
|
}
|
|
28016
28148
|
try {
|
|
28017
28149
|
const dir = dirname9(filePath);
|
|
28018
28150
|
const timestamp = Date.now();
|
|
28019
|
-
const backupPath =
|
|
28020
|
-
|
|
28151
|
+
const backupPath = join50(dir, `${BACKUP_PREFIX}${timestamp}`);
|
|
28152
|
+
writeFileSync20(backupPath, readFileSync30(filePath, "utf-8"), "utf-8");
|
|
28021
28153
|
log(`Created boulder state backup: ${backupPath}`);
|
|
28022
28154
|
cleanupOldBackups(dir);
|
|
28023
28155
|
return true;
|
|
@@ -28030,7 +28162,7 @@ function cleanupOldBackups(dir) {
|
|
|
28030
28162
|
const files = readdirSync10(dir);
|
|
28031
28163
|
const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
|
|
28032
28164
|
name: f,
|
|
28033
|
-
path:
|
|
28165
|
+
path: join50(dir, f),
|
|
28034
28166
|
timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
|
|
28035
28167
|
})).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
|
|
28036
28168
|
for (const file of backupFiles.slice(MAX_BACKUPS)) {
|
|
@@ -28042,25 +28174,25 @@ function cleanupOldBackups(dir) {
|
|
|
28042
28174
|
} catch {}
|
|
28043
28175
|
}
|
|
28044
28176
|
function restoreBoulderState(directory) {
|
|
28045
|
-
const dir =
|
|
28046
|
-
if (!
|
|
28177
|
+
const dir = join50(directory, BOULDER_DIR);
|
|
28178
|
+
if (!existsSync38(dir)) {
|
|
28047
28179
|
return null;
|
|
28048
28180
|
}
|
|
28049
28181
|
try {
|
|
28050
28182
|
const files = readdirSync10(dir);
|
|
28051
28183
|
const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
|
|
28052
28184
|
name: f,
|
|
28053
|
-
path:
|
|
28185
|
+
path: join50(dir, f),
|
|
28054
28186
|
timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
|
|
28055
28187
|
})).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
|
|
28056
28188
|
if (backupFiles.length === 0) {
|
|
28057
28189
|
return null;
|
|
28058
28190
|
}
|
|
28059
28191
|
const latestBackup = backupFiles[0];
|
|
28060
|
-
const content =
|
|
28192
|
+
const content = readFileSync30(latestBackup.path, "utf-8");
|
|
28061
28193
|
const state2 = JSON.parse(content);
|
|
28062
28194
|
const filePath = getBoulderFilePath(directory);
|
|
28063
|
-
|
|
28195
|
+
writeFileSync20(filePath, content, "utf-8");
|
|
28064
28196
|
log(`Restored boulder state from backup: ${latestBackup.path}`);
|
|
28065
28197
|
return state2;
|
|
28066
28198
|
} catch {
|
|
@@ -28071,17 +28203,17 @@ function writeBoulderState(directory, state2) {
|
|
|
28071
28203
|
const filePath = getBoulderFilePath(directory);
|
|
28072
28204
|
try {
|
|
28073
28205
|
const dir = dirname9(filePath);
|
|
28074
|
-
if (!
|
|
28075
|
-
|
|
28206
|
+
if (!existsSync38(dir)) {
|
|
28207
|
+
mkdirSync17(dir, { recursive: true });
|
|
28076
28208
|
}
|
|
28077
28209
|
backupBoulderState(directory);
|
|
28078
28210
|
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
28079
28211
|
try {
|
|
28080
|
-
|
|
28212
|
+
writeFileSync20(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
|
|
28081
28213
|
retryOnWindowsError(() => renameSync2(tmpPath, filePath));
|
|
28082
28214
|
} finally {
|
|
28083
28215
|
try {
|
|
28084
|
-
if (
|
|
28216
|
+
if (existsSync38(tmpPath)) {
|
|
28085
28217
|
unlinkSync12(tmpPath);
|
|
28086
28218
|
}
|
|
28087
28219
|
} catch {}
|
|
@@ -28135,7 +28267,7 @@ function markBoulderPlanCompleted(directory, completedAt) {
|
|
|
28135
28267
|
function clearBoulderState(directory) {
|
|
28136
28268
|
const filePath = getBoulderFilePath(directory);
|
|
28137
28269
|
try {
|
|
28138
|
-
if (
|
|
28270
|
+
if (existsSync38(filePath)) {
|
|
28139
28271
|
const { unlinkSync: unlinkSync13 } = __require("fs");
|
|
28140
28272
|
unlinkSync13(filePath);
|
|
28141
28273
|
}
|
|
@@ -28145,13 +28277,13 @@ function clearBoulderState(directory) {
|
|
|
28145
28277
|
}
|
|
28146
28278
|
}
|
|
28147
28279
|
function findPrometheusPlans(directory) {
|
|
28148
|
-
const plansDir =
|
|
28149
|
-
if (!
|
|
28280
|
+
const plansDir = join50(directory, PROMETHEUS_PLANS_DIR);
|
|
28281
|
+
if (!existsSync38(plansDir)) {
|
|
28150
28282
|
return [];
|
|
28151
28283
|
}
|
|
28152
28284
|
try {
|
|
28153
28285
|
const files = readdirSync10(plansDir);
|
|
28154
|
-
return files.filter((f) => f.endsWith(".md")).map((f) =>
|
|
28286
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => join50(plansDir, f)).sort((a, b) => {
|
|
28155
28287
|
const aStat = __require("fs").statSync(a);
|
|
28156
28288
|
const bStat = __require("fs").statSync(b);
|
|
28157
28289
|
return bStat.mtimeMs - aStat.mtimeMs;
|
|
@@ -28161,11 +28293,11 @@ function findPrometheusPlans(directory) {
|
|
|
28161
28293
|
}
|
|
28162
28294
|
}
|
|
28163
28295
|
function getPlanProgress(planPath) {
|
|
28164
|
-
if (!
|
|
28296
|
+
if (!existsSync38(planPath)) {
|
|
28165
28297
|
return { total: 0, completed: 0, isComplete: false };
|
|
28166
28298
|
}
|
|
28167
28299
|
try {
|
|
28168
|
-
const content =
|
|
28300
|
+
const content = readFileSync30(planPath, "utf-8");
|
|
28169
28301
|
if (!content.trim()) {
|
|
28170
28302
|
return { total: 0, completed: 0, isComplete: false };
|
|
28171
28303
|
}
|
|
@@ -28195,8 +28327,8 @@ function createBoulderState(planPath, sessionId) {
|
|
|
28195
28327
|
};
|
|
28196
28328
|
}
|
|
28197
28329
|
function cleanupStaleTmpFiles(directory) {
|
|
28198
|
-
const boulderDir =
|
|
28199
|
-
if (!
|
|
28330
|
+
const boulderDir = join50(directory, BOULDER_DIR);
|
|
28331
|
+
if (!existsSync38(boulderDir)) {
|
|
28200
28332
|
return;
|
|
28201
28333
|
}
|
|
28202
28334
|
try {
|
|
@@ -28206,7 +28338,7 @@ function cleanupStaleTmpFiles(directory) {
|
|
|
28206
28338
|
if (!file.startsWith(`${BOULDER_FILE}.tmp.`)) {
|
|
28207
28339
|
continue;
|
|
28208
28340
|
}
|
|
28209
|
-
const filePath =
|
|
28341
|
+
const filePath = join50(boulderDir, file);
|
|
28210
28342
|
try {
|
|
28211
28343
|
const stat = statSync4(filePath);
|
|
28212
28344
|
if (now - stat.mtimeMs > STALE_TMP_THRESHOLD_MS) {
|
|
@@ -28220,7 +28352,7 @@ function cleanupStaleTmpFiles(directory) {
|
|
|
28220
28352
|
// src/features/boulder-state/checkbox-utils.ts
|
|
28221
28353
|
init_logger();
|
|
28222
28354
|
import { appendFileSync as appendFileSync7 } from "fs";
|
|
28223
|
-
import { join as
|
|
28355
|
+
import { join as join51 } from "path";
|
|
28224
28356
|
function parseCheckboxes(content) {
|
|
28225
28357
|
const lines = content.split(`
|
|
28226
28358
|
`);
|
|
@@ -28262,6 +28394,15 @@ function findMatchingCheckbox(taskDescription, checkboxes) {
|
|
|
28262
28394
|
bestMatch = checkbox;
|
|
28263
28395
|
}
|
|
28264
28396
|
}
|
|
28397
|
+
if (bestMatch === null && incompleteCheckboxes.length > 0) {
|
|
28398
|
+
const fallbackMatch = incompleteCheckboxes[0];
|
|
28399
|
+
log(`[checkbox-utils] Fallback match: using first incomplete checkbox`, {
|
|
28400
|
+
taskDescription: taskDescription.substring(0, 80),
|
|
28401
|
+
fallbackText: fallbackMatch.text,
|
|
28402
|
+
checkboxIndex: fallbackMatch.index
|
|
28403
|
+
});
|
|
28404
|
+
return fallbackMatch.index;
|
|
28405
|
+
}
|
|
28265
28406
|
return bestMatch?.index ?? -1;
|
|
28266
28407
|
}
|
|
28267
28408
|
function extractTaskFromPrompt(prompt) {
|
|
@@ -28281,7 +28422,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
|
|
|
28281
28422
|
checkboxCount: checkboxes.length,
|
|
28282
28423
|
planName
|
|
28283
28424
|
});
|
|
28284
|
-
const notepadPath =
|
|
28425
|
+
const notepadPath = join51(directory, ".sisyphus", "notepads", planName, "match-failures.md");
|
|
28285
28426
|
const entry = `
|
|
28286
28427
|
## ${new Date().toISOString()}
|
|
28287
28428
|
**\u4EFB\u52A1\u63CF\u8FF0**\uFF1A${taskDescription}
|
|
@@ -28293,6 +28434,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
|
|
|
28293
28434
|
}
|
|
28294
28435
|
// src/hooks/start-work/index.ts
|
|
28295
28436
|
init_logger();
|
|
28437
|
+
init_claude_code_session_state();
|
|
28296
28438
|
init_agent_display_names();
|
|
28297
28439
|
var HOOK_NAME5 = "start-work";
|
|
28298
28440
|
var KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi;
|
|
@@ -28520,8 +28662,9 @@ ${contextInfo}`;
|
|
|
28520
28662
|
}
|
|
28521
28663
|
// src/hooks/atlas/index.ts
|
|
28522
28664
|
import { execSync } from "child_process";
|
|
28523
|
-
import { existsSync as
|
|
28524
|
-
import { join as
|
|
28665
|
+
import { existsSync as existsSync39, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as readFileSync31, renameSync as renameSync3, writeFileSync as writeFileSync21 } from "fs";
|
|
28666
|
+
import { join as join52 } from "path";
|
|
28667
|
+
init_claude_code_session_state();
|
|
28525
28668
|
init_logger();
|
|
28526
28669
|
init_system_directive();
|
|
28527
28670
|
init_agent_display_names();
|
|
@@ -28683,7 +28826,7 @@ function acquirePlanFileLock(planPath, maxRetries = 8, retryDelayMs = 125) {
|
|
|
28683
28826
|
for (let attempt = 0;attempt < maxRetries; attempt++) {
|
|
28684
28827
|
try {
|
|
28685
28828
|
const fd = openSync(lockPath, "wx");
|
|
28686
|
-
|
|
28829
|
+
writeFileSync21(fd, String(process.pid));
|
|
28687
28830
|
closeSync(fd);
|
|
28688
28831
|
log(`[${HOOK_NAME6}] Acquired file lock for ${planPath}`);
|
|
28689
28832
|
return true;
|
|
@@ -28721,12 +28864,12 @@ function writePlanFileAtomic(planPath, content) {
|
|
|
28721
28864
|
try {
|
|
28722
28865
|
const tmpPath = `${planPath}.tmp.${process.pid}`;
|
|
28723
28866
|
try {
|
|
28724
|
-
|
|
28867
|
+
writeFileSync21(tmpPath, content, "utf-8");
|
|
28725
28868
|
retryOnWindowsError(() => renameSync3(tmpPath, planPath));
|
|
28726
28869
|
return true;
|
|
28727
28870
|
} finally {
|
|
28728
28871
|
try {
|
|
28729
|
-
if (
|
|
28872
|
+
if (existsSync39(tmpPath)) {
|
|
28730
28873
|
unlinkSync13(tmpPath);
|
|
28731
28874
|
}
|
|
28732
28875
|
} catch {}
|
|
@@ -28742,7 +28885,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
|
|
|
28742
28885
|
}
|
|
28743
28886
|
const planPath = boulderState.active_plan;
|
|
28744
28887
|
try {
|
|
28745
|
-
const planContent =
|
|
28888
|
+
const planContent = readFileSync31(planPath, "utf-8");
|
|
28746
28889
|
const checkboxes = parseCheckboxes(planContent);
|
|
28747
28890
|
const lines = planContent.split(`
|
|
28748
28891
|
`);
|
|
@@ -28763,7 +28906,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
|
|
|
28763
28906
|
const updatedContent = lines.join(`
|
|
28764
28907
|
`);
|
|
28765
28908
|
if (!writePlanFileAtomic(planPath, updatedContent)) {
|
|
28766
|
-
retryOnWindowsError(() =>
|
|
28909
|
+
retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
|
|
28767
28910
|
log(`[${HOOK_NAME6}] Dual-track sync: atomic write failed, fell back to direct write`, {
|
|
28768
28911
|
plan: boulderState.plan_name
|
|
28769
28912
|
});
|
|
@@ -28808,22 +28951,15 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
|
|
|
28808
28951
|
|
|
28809
28952
|
${buildVerificationReminder(sessionId)}
|
|
28810
28953
|
|
|
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
|
|
28954
|
+
**\u2705 \u7CFB\u7EDF\u5DF2\u81EA\u52A8\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6\u4E2D\u7684\u590D\u9009\u6846\u3002**
|
|
28955
|
+
\u65E0\u9700\u624B\u52A8\u6807\u8BB0\u3002\u76F4\u63A5\u9A8C\u8BC1\u5B50\u4EE3\u7406\u7684\u5DE5\u4F5C\u5373\u53EF\u3002
|
|
28818
28956
|
|
|
28819
|
-
**\
|
|
28820
|
-
|
|
28821
|
-
**\u6B65\u9AA4 5\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
|
|
28957
|
+
**\u6B65\u9AA4 4\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
|
|
28822
28958
|
|
|
28823
28959
|
- \u4EC5\u6682\u5B58\u5DF2\u9A8C\u8BC1\u7684\u66F4\u6539
|
|
28824
28960
|
- \u4F7F\u7528\u6E05\u6670\u7684\u63D0\u4EA4\u4FE1\u606F\u63CF\u8FF0\u5B8C\u6210\u7684\u5185\u5BB9
|
|
28825
28961
|
|
|
28826
|
-
**\u6B65\u9AA4
|
|
28962
|
+
**\u6B65\u9AA4 5\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
|
|
28827
28963
|
|
|
28828
28964
|
- \u8BFB\u53D6\u8BA1\u5212\u6587\u4EF6\uFF0C\u627E\u5230\u4E0B\u4E00\u4E2A \`[ ]\` \u4EFB\u52A1
|
|
28829
28965
|
- \u7ACB\u5373\u5F00\u59CB\u2014\u2014\u4E0D\u8981\u505C\u6B62
|
|
@@ -28960,14 +29096,14 @@ function formatFileChanges(stats, notepadPath) {
|
|
|
28960
29096
|
`);
|
|
28961
29097
|
}
|
|
28962
29098
|
function getMessageDir5(sessionID) {
|
|
28963
|
-
if (!
|
|
29099
|
+
if (!existsSync39(MESSAGE_STORAGE))
|
|
28964
29100
|
return null;
|
|
28965
|
-
const directPath =
|
|
28966
|
-
if (
|
|
29101
|
+
const directPath = join52(MESSAGE_STORAGE, sessionID);
|
|
29102
|
+
if (existsSync39(directPath))
|
|
28967
29103
|
return directPath;
|
|
28968
29104
|
for (const dir of readdirSync11(MESSAGE_STORAGE)) {
|
|
28969
|
-
const sessionPath =
|
|
28970
|
-
if (
|
|
29105
|
+
const sessionPath = join52(MESSAGE_STORAGE, dir, sessionID);
|
|
29106
|
+
if (existsSync39(sessionPath))
|
|
28971
29107
|
return sessionPath;
|
|
28972
29108
|
}
|
|
28973
29109
|
return null;
|
|
@@ -28981,6 +29117,45 @@ function isCallerOrchestrator(sessionID) {
|
|
|
28981
29117
|
const nearest = findNearestAssistantMessage(messageDir);
|
|
28982
29118
|
return agentNameMatches(nearest?.agent, "\u4EFB\u52A1\u7F16\u6392");
|
|
28983
29119
|
}
|
|
29120
|
+
function isAgentCheckboxUpdater(agentName) {
|
|
29121
|
+
if (!agentName)
|
|
29122
|
+
return false;
|
|
29123
|
+
return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
|
|
29124
|
+
}
|
|
29125
|
+
function isActiveCheckboxUpdater(sessionID) {
|
|
29126
|
+
if (!sessionID)
|
|
29127
|
+
return false;
|
|
29128
|
+
const messageDir = getMessageDir5(sessionID);
|
|
29129
|
+
if (!messageDir)
|
|
29130
|
+
return false;
|
|
29131
|
+
const nearest = findNearestAssistantMessage(messageDir);
|
|
29132
|
+
return isAgentCheckboxUpdater(nearest?.agent);
|
|
29133
|
+
}
|
|
29134
|
+
function isAgentContinuationTrigger(agentName) {
|
|
29135
|
+
if (!agentName)
|
|
29136
|
+
return false;
|
|
29137
|
+
return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
|
|
29138
|
+
}
|
|
29139
|
+
function isActiveContinuationTrigger(sessionID, directory) {
|
|
29140
|
+
if (!sessionID)
|
|
29141
|
+
return false;
|
|
29142
|
+
const messageDir = getMessageDir5(sessionID);
|
|
29143
|
+
if (messageDir) {
|
|
29144
|
+
const nearest = findNearestAssistantMessage(messageDir);
|
|
29145
|
+
if (isAgentContinuationTrigger(nearest?.agent)) {
|
|
29146
|
+
return true;
|
|
29147
|
+
}
|
|
29148
|
+
}
|
|
29149
|
+
if (directory) {
|
|
29150
|
+
try {
|
|
29151
|
+
const boulderState = readBoulderState(directory);
|
|
29152
|
+
if (boulderState?.session_ids?.includes(sessionID)) {
|
|
29153
|
+
return true;
|
|
29154
|
+
}
|
|
29155
|
+
} catch {}
|
|
29156
|
+
}
|
|
29157
|
+
return false;
|
|
29158
|
+
}
|
|
28984
29159
|
var CONTINUATION_COOLDOWN_MS = 5000;
|
|
28985
29160
|
function isAbortError(error) {
|
|
28986
29161
|
if (!error)
|
|
@@ -29145,8 +29320,8 @@ function createAtlasHook(ctx, options) {
|
|
|
29145
29320
|
log(`[${HOOK_NAME6}] No active boulder`, { sessionID });
|
|
29146
29321
|
return;
|
|
29147
29322
|
}
|
|
29148
|
-
if (!
|
|
29149
|
-
log(`[${HOOK_NAME6}] Skipped:
|
|
29323
|
+
if (!isActiveContinuationTrigger(sessionID, ctx.directory)) {
|
|
29324
|
+
log(`[${HOOK_NAME6}] Skipped: not eligible for continuation trigger`, { sessionID });
|
|
29150
29325
|
return;
|
|
29151
29326
|
}
|
|
29152
29327
|
const progress = getPlanProgress(boulderState.active_plan);
|
|
@@ -29272,7 +29447,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29272
29447
|
}
|
|
29273
29448
|
},
|
|
29274
29449
|
"tool.execute.after": async (input, output) => {
|
|
29275
|
-
if (!
|
|
29450
|
+
if (!isActiveCheckboxUpdater(input.sessionID)) {
|
|
29276
29451
|
return;
|
|
29277
29452
|
}
|
|
29278
29453
|
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
|
@@ -29334,7 +29509,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29334
29509
|
const taskDescription = extractTaskFromPrompt(savedPrompt || "");
|
|
29335
29510
|
if (taskDescription) {
|
|
29336
29511
|
try {
|
|
29337
|
-
const planContent =
|
|
29512
|
+
const planContent = readFileSync31(boulderState.active_plan, "utf-8");
|
|
29338
29513
|
const checkboxes = parseCheckboxes(planContent);
|
|
29339
29514
|
const checkboxIndex = findMatchingCheckbox(taskDescription, checkboxes);
|
|
29340
29515
|
if (checkboxIndex >= 0) {
|
|
@@ -29346,7 +29521,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29346
29521
|
`);
|
|
29347
29522
|
const planPath = boulderState.active_plan;
|
|
29348
29523
|
if (!writePlanFileAtomic(planPath, updatedContent)) {
|
|
29349
|
-
retryOnWindowsError(() =>
|
|
29524
|
+
retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
|
|
29350
29525
|
log(`[${HOOK_NAME6}] Atomic plan write failed, fell back to direct write`, {
|
|
29351
29526
|
plan: boulderState.plan_name
|
|
29352
29527
|
});
|
|
@@ -29367,6 +29542,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29367
29542
|
});
|
|
29368
29543
|
}
|
|
29369
29544
|
}
|
|
29545
|
+
const updatedProgress = getPlanProgress(boulderState.active_plan);
|
|
29370
29546
|
output.output = `
|
|
29371
29547
|
## \u5B50\u4EE3\u7406\u5DE5\u4F5C\u5DF2\u5B8C\u6210
|
|
29372
29548
|
|
|
@@ -29379,11 +29555,11 @@ ${fileChanges}
|
|
|
29379
29555
|
${originalResponse}
|
|
29380
29556
|
|
|
29381
29557
|
<system-reminder>
|
|
29382
|
-
${buildOrchestratorReminder(boulderState.plan_name,
|
|
29558
|
+
${buildOrchestratorReminder(boulderState.plan_name, updatedProgress, subagentSessionId)}
|
|
29383
29559
|
</system-reminder>`;
|
|
29384
29560
|
log(`[${HOOK_NAME6}] Output transformed for orchestrator mode (boulder)`, {
|
|
29385
29561
|
plan: boulderState.plan_name,
|
|
29386
|
-
progress: `${
|
|
29562
|
+
progress: `${updatedProgress.completed}/${updatedProgress.total}`,
|
|
29387
29563
|
fileCount: gitStats.length
|
|
29388
29564
|
});
|
|
29389
29565
|
} else {
|
|
@@ -30196,6 +30372,7 @@ init_usage_tracker();
|
|
|
30196
30372
|
init_model_health_registry();
|
|
30197
30373
|
init_runtime_fallback();
|
|
30198
30374
|
init_agent_display_names();
|
|
30375
|
+
init_claude_code_session_state();
|
|
30199
30376
|
async function withTimeout(promise, timeoutMs, label) {
|
|
30200
30377
|
let timer;
|
|
30201
30378
|
return Promise.race([
|
|
@@ -30979,6 +31156,7 @@ function evaluatePermission(input, agentName) {
|
|
|
30979
31156
|
|
|
30980
31157
|
// src/hooks/permission-ask-bridge/index.ts
|
|
30981
31158
|
init_logger();
|
|
31159
|
+
init_claude_code_session_state();
|
|
30982
31160
|
function createPermissionAskBridgeHook(ctx) {
|
|
30983
31161
|
return {
|
|
30984
31162
|
"permission.ask": async (input, output) => {
|
|
@@ -31012,8 +31190,8 @@ function createShellEnvInjectorHook(_ctx) {
|
|
|
31012
31190
|
// src/hooks/plan-completion/index.ts
|
|
31013
31191
|
init_logger();
|
|
31014
31192
|
init_frontmatter();
|
|
31015
|
-
import { existsSync as
|
|
31016
|
-
import { join as
|
|
31193
|
+
import { existsSync as existsSync40, readFileSync as readFileSync32, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18, renameSync as renameSync4, unlinkSync as unlinkSync14 } from "fs";
|
|
31194
|
+
import { join as join53 } from "path";
|
|
31017
31195
|
async function safeExecute(fn, name, onAction) {
|
|
31018
31196
|
try {
|
|
31019
31197
|
await fn();
|
|
@@ -31058,11 +31236,11 @@ function countListItems(content) {
|
|
|
31058
31236
|
}
|
|
31059
31237
|
async function updatePlanSummary(data) {
|
|
31060
31238
|
log(`[plan-completion] updatePlanSummary: ${data.planName}`);
|
|
31061
|
-
if (!
|
|
31239
|
+
if (!existsSync40(data.planPath)) {
|
|
31062
31240
|
log(`[plan-completion] Plan file not found: ${data.planPath}`);
|
|
31063
31241
|
return;
|
|
31064
31242
|
}
|
|
31065
|
-
const content =
|
|
31243
|
+
const content = readFileSync32(data.planPath, "utf-8");
|
|
31066
31244
|
const startedAt = data.boulderState?.started_at || "";
|
|
31067
31245
|
const completedAt = data.boulderState?.completed_at || "";
|
|
31068
31246
|
const duration = formatDuration(startedAt, completedAt);
|
|
@@ -31083,17 +31261,17 @@ async function updatePlanSummary(data) {
|
|
|
31083
31261
|
| \u5B8C\u6210\u4EFB\u52A1\u6570 | ${completedTasks} |
|
|
31084
31262
|
| \u5931\u8D25\u4EFB\u52A1\u6570 | ${failedTasks} |
|
|
31085
31263
|
`;
|
|
31086
|
-
|
|
31264
|
+
writeFileSync22(data.planPath, content + summary, "utf-8");
|
|
31087
31265
|
log(`[plan-completion] Plan summary appended to ${data.planPath}`);
|
|
31088
31266
|
}
|
|
31089
31267
|
async function archivePlan(data) {
|
|
31090
31268
|
log(`[plan-completion] archivePlan: ${data.planName}`);
|
|
31091
|
-
const archivedDir =
|
|
31092
|
-
if (!
|
|
31093
|
-
|
|
31269
|
+
const archivedDir = join53(data.directory, ".sisyphus", "archived");
|
|
31270
|
+
if (!existsSync40(archivedDir)) {
|
|
31271
|
+
mkdirSync18(archivedDir, { recursive: true });
|
|
31094
31272
|
}
|
|
31095
|
-
if (
|
|
31096
|
-
const archivedPath =
|
|
31273
|
+
if (existsSync40(data.planPath)) {
|
|
31274
|
+
const archivedPath = join53(archivedDir, `${data.planName}.md`);
|
|
31097
31275
|
renameSync4(data.planPath, archivedPath);
|
|
31098
31276
|
log(`[plan-completion] Plan archived to ${archivedPath}`);
|
|
31099
31277
|
const boulderState = readBoulderState(data.directory);
|
|
@@ -31103,16 +31281,16 @@ async function archivePlan(data) {
|
|
|
31103
31281
|
log(`[plan-completion] Updated boulder.json active_plan to ${archivedPath}`);
|
|
31104
31282
|
}
|
|
31105
31283
|
}
|
|
31106
|
-
const draftPath =
|
|
31107
|
-
if (
|
|
31284
|
+
const draftPath = join53(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
|
|
31285
|
+
if (existsSync40(draftPath)) {
|
|
31108
31286
|
unlinkSync14(draftPath);
|
|
31109
31287
|
log(`[plan-completion] Deleted draft file: ${draftPath}`);
|
|
31110
31288
|
}
|
|
31111
31289
|
}
|
|
31112
31290
|
async function extractLearnings(data) {
|
|
31113
31291
|
log(`[plan-completion] extractLearnings: ${data.planName}`);
|
|
31114
|
-
const notepadDir =
|
|
31115
|
-
if (!
|
|
31292
|
+
const notepadDir = join53(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31293
|
+
if (!existsSync40(notepadDir)) {
|
|
31116
31294
|
log(`[plan-completion] Notepad directory not found: ${notepadDir}`);
|
|
31117
31295
|
return;
|
|
31118
31296
|
}
|
|
@@ -31122,9 +31300,9 @@ async function extractLearnings(data) {
|
|
|
31122
31300
|
let totalIssues = 0;
|
|
31123
31301
|
let totalDecisions = 0;
|
|
31124
31302
|
for (const file of files) {
|
|
31125
|
-
const filePath =
|
|
31126
|
-
if (
|
|
31127
|
-
const content =
|
|
31303
|
+
const filePath = join53(notepadDir, file);
|
|
31304
|
+
if (existsSync40(filePath)) {
|
|
31305
|
+
const content = readFileSync32(filePath, "utf-8");
|
|
31128
31306
|
contents[file] = content;
|
|
31129
31307
|
const count = countListItems(content);
|
|
31130
31308
|
if (file === "learnings.md")
|
|
@@ -31135,9 +31313,9 @@ async function extractLearnings(data) {
|
|
|
31135
31313
|
totalDecisions = count;
|
|
31136
31314
|
}
|
|
31137
31315
|
}
|
|
31138
|
-
const learningsDir =
|
|
31139
|
-
if (!
|
|
31140
|
-
|
|
31316
|
+
const learningsDir = join53(data.directory, ".sisyphus", "learnings");
|
|
31317
|
+
if (!existsSync40(learningsDir)) {
|
|
31318
|
+
mkdirSync18(learningsDir, { recursive: true });
|
|
31141
31319
|
}
|
|
31142
31320
|
const output = `# \u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3: ${data.planName}
|
|
31143
31321
|
|
|
@@ -31164,8 +31342,8 @@ ${contents["decisions.md"] || "\u65E0"}
|
|
|
31164
31342
|
|
|
31165
31343
|
${contents["match-failures.md"] || "\u65E0"}
|
|
31166
31344
|
`;
|
|
31167
|
-
const outputPath =
|
|
31168
|
-
|
|
31345
|
+
const outputPath = join53(learningsDir, `${data.planName}.md`);
|
|
31346
|
+
writeFileSync22(outputPath, output, "utf-8");
|
|
31169
31347
|
log(`[plan-completion] Learnings saved to ${outputPath}`);
|
|
31170
31348
|
if (data.client?.tui?.showToast) {
|
|
31171
31349
|
data.client.tui.showToast({
|
|
@@ -31184,9 +31362,9 @@ ${contents["match-failures.md"] || "\u65E0"}
|
|
|
31184
31362
|
}
|
|
31185
31363
|
async function generateReport(data) {
|
|
31186
31364
|
log(`[plan-completion] generateReport: ${data.planName}`);
|
|
31187
|
-
const reportsDir =
|
|
31188
|
-
if (!
|
|
31189
|
-
|
|
31365
|
+
const reportsDir = join53(data.directory, ".sisyphus", "reports");
|
|
31366
|
+
if (!existsSync40(reportsDir)) {
|
|
31367
|
+
mkdirSync18(reportsDir, { recursive: true });
|
|
31190
31368
|
}
|
|
31191
31369
|
const startedAt = data.boulderState?.started_at || "";
|
|
31192
31370
|
const completedAt = data.boulderState?.completed_at || "";
|
|
@@ -31197,8 +31375,8 @@ async function generateReport(data) {
|
|
|
31197
31375
|
const version = data.boulderState?.version || 0;
|
|
31198
31376
|
const sessionCount = data.boulderState?.session_ids?.length || 0;
|
|
31199
31377
|
const completedIndices = data.boulderState?.completed_task_indices || [];
|
|
31200
|
-
const notepadPath =
|
|
31201
|
-
const hasNotepad =
|
|
31378
|
+
const notepadPath = join53(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31379
|
+
const hasNotepad = existsSync40(notepadPath);
|
|
31202
31380
|
const report = `# \u8BA1\u5212\u5B8C\u6210\u62A5\u544A
|
|
31203
31381
|
|
|
31204
31382
|
## \u6982\u89C8
|
|
@@ -31237,8 +31415,8 @@ ${hasNotepad ? `## \u8BB0\u4E8B\u672C
|
|
|
31237
31415
|
\u8BB0\u4E8B\u672C\u8DEF\u5F84: ${notepadPath}
|
|
31238
31416
|
` : ""}
|
|
31239
31417
|
`;
|
|
31240
|
-
const reportPath =
|
|
31241
|
-
|
|
31418
|
+
const reportPath = join53(reportsDir, `${data.planName}.md`);
|
|
31419
|
+
writeFileSync22(reportPath, report, "utf-8");
|
|
31242
31420
|
log(`[plan-completion] Report generated at ${reportPath}`);
|
|
31243
31421
|
}
|
|
31244
31422
|
async function runInitDeep(data) {
|
|
@@ -31348,6 +31526,7 @@ class ContextCollector {
|
|
|
31348
31526
|
var contextCollector = new ContextCollector;
|
|
31349
31527
|
// src/features/context-injector/injector.ts
|
|
31350
31528
|
init_shared();
|
|
31529
|
+
init_claude_code_session_state();
|
|
31351
31530
|
function createContextInjectorMessagesTransformHook(collector) {
|
|
31352
31531
|
return {
|
|
31353
31532
|
"experimental.chat.messages.transform": async (_input, output) => {
|
|
@@ -31449,8 +31628,8 @@ function createFirstMessageVariantGate() {
|
|
|
31449
31628
|
}
|
|
31450
31629
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
31451
31630
|
init_shared();
|
|
31452
|
-
import { existsSync as
|
|
31453
|
-
import { join as
|
|
31631
|
+
import { existsSync as existsSync41, readFileSync as readFileSync33 } from "fs";
|
|
31632
|
+
import { join as join54 } from "path";
|
|
31454
31633
|
|
|
31455
31634
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
31456
31635
|
function expandEnvVars(value) {
|
|
@@ -31520,13 +31699,13 @@ function getMcpConfigPaths() {
|
|
|
31520
31699
|
const claudeConfigDir = getClaudeConfigDir();
|
|
31521
31700
|
const cwd2 = process.cwd();
|
|
31522
31701
|
return [
|
|
31523
|
-
{ path:
|
|
31524
|
-
{ path:
|
|
31525
|
-
{ path:
|
|
31702
|
+
{ path: join54(claudeConfigDir, ".mcp.json"), scope: "user" },
|
|
31703
|
+
{ path: join54(cwd2, ".mcp.json"), scope: "project" },
|
|
31704
|
+
{ path: join54(cwd2, ".claude", ".mcp.json"), scope: "local" }
|
|
31526
31705
|
];
|
|
31527
31706
|
}
|
|
31528
31707
|
async function loadMcpConfigFile(filePath) {
|
|
31529
|
-
if (!
|
|
31708
|
+
if (!existsSync41(filePath)) {
|
|
31530
31709
|
return null;
|
|
31531
31710
|
}
|
|
31532
31711
|
try {
|
|
@@ -31541,10 +31720,10 @@ function getSystemMcpServerNames() {
|
|
|
31541
31720
|
const names = new Set;
|
|
31542
31721
|
const paths = getMcpConfigPaths();
|
|
31543
31722
|
for (const { path: path7 } of paths) {
|
|
31544
|
-
if (!
|
|
31723
|
+
if (!existsSync41(path7))
|
|
31545
31724
|
continue;
|
|
31546
31725
|
try {
|
|
31547
|
-
const content =
|
|
31726
|
+
const content = readFileSync33(path7, "utf-8");
|
|
31548
31727
|
const config = JSON.parse(content);
|
|
31549
31728
|
if (!config?.mcpServers)
|
|
31550
31729
|
continue;
|
|
@@ -31594,14 +31773,21 @@ async function loadMcpConfigs() {
|
|
|
31594
31773
|
}
|
|
31595
31774
|
return { servers, loadedServers };
|
|
31596
31775
|
}
|
|
31776
|
+
// src/index.ts
|
|
31777
|
+
init_claude_code_session_state();
|
|
31778
|
+
|
|
31597
31779
|
// src/features/claude-code-session-state/recovery.ts
|
|
31598
|
-
import { existsSync as
|
|
31599
|
-
import { join as
|
|
31780
|
+
import { existsSync as existsSync42, readdirSync as readdirSync13 } from "fs";
|
|
31781
|
+
import { join as join55 } from "path";
|
|
31782
|
+
init_state();
|
|
31600
31783
|
init_logger();
|
|
31601
|
-
function recoverSessionAgents() {
|
|
31784
|
+
function recoverSessionAgents(directory) {
|
|
31602
31785
|
let recoveredCount = 0;
|
|
31786
|
+
if (directory) {
|
|
31787
|
+
loadSessionAgentMap(directory);
|
|
31788
|
+
}
|
|
31603
31789
|
try {
|
|
31604
|
-
if (!
|
|
31790
|
+
if (!existsSync42(MESSAGE_STORAGE)) {
|
|
31605
31791
|
log("[recovery] MESSAGE_STORAGE directory does not exist", { path: MESSAGE_STORAGE });
|
|
31606
31792
|
return 0;
|
|
31607
31793
|
}
|
|
@@ -31609,13 +31795,13 @@ function recoverSessionAgents() {
|
|
|
31609
31795
|
for (const entry of entries) {
|
|
31610
31796
|
if (!entry.isDirectory())
|
|
31611
31797
|
continue;
|
|
31612
|
-
const projectDir =
|
|
31798
|
+
const projectDir = join55(MESSAGE_STORAGE, entry.name);
|
|
31613
31799
|
try {
|
|
31614
31800
|
const sessionDirs = readdirSync13(projectDir, { withFileTypes: true });
|
|
31615
31801
|
for (const sessionEntry of sessionDirs) {
|
|
31616
31802
|
if (!sessionEntry.isDirectory())
|
|
31617
31803
|
continue;
|
|
31618
|
-
const sessionDir =
|
|
31804
|
+
const sessionDir = join55(projectDir, sessionEntry.name);
|
|
31619
31805
|
const sessionID = sessionEntry.name;
|
|
31620
31806
|
try {
|
|
31621
31807
|
const msg = findNearestAssistantMessage(sessionDir);
|
|
@@ -32041,14 +32227,14 @@ var EXT_TO_LANG = {
|
|
|
32041
32227
|
".gql": "graphql"
|
|
32042
32228
|
};
|
|
32043
32229
|
// src/tools/lsp/config.ts
|
|
32044
|
-
import { existsSync as
|
|
32045
|
-
import { join as
|
|
32230
|
+
import { existsSync as existsSync43, readFileSync as readFileSync34 } from "fs";
|
|
32231
|
+
import { join as join56 } from "path";
|
|
32046
32232
|
init_shared();
|
|
32047
32233
|
function loadJsonFile(path7) {
|
|
32048
|
-
if (!
|
|
32234
|
+
if (!existsSync43(path7))
|
|
32049
32235
|
return null;
|
|
32050
32236
|
try {
|
|
32051
|
-
return JSON.parse(
|
|
32237
|
+
return JSON.parse(readFileSync34(path7, "utf-8"));
|
|
32052
32238
|
} catch {
|
|
32053
32239
|
return null;
|
|
32054
32240
|
}
|
|
@@ -32057,9 +32243,9 @@ function getConfigPaths3() {
|
|
|
32057
32243
|
const cwd2 = process.cwd();
|
|
32058
32244
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
32059
32245
|
return {
|
|
32060
|
-
project:
|
|
32061
|
-
user:
|
|
32062
|
-
opencode:
|
|
32246
|
+
project: join56(cwd2, ".opencode", "oh-my-opencode.json"),
|
|
32247
|
+
user: join56(configDir, "oh-my-opencode.json"),
|
|
32248
|
+
opencode: join56(configDir, "opencode.json")
|
|
32063
32249
|
};
|
|
32064
32250
|
}
|
|
32065
32251
|
function loadAllConfigs() {
|
|
@@ -32172,7 +32358,7 @@ function isServerInstalled(command) {
|
|
|
32172
32358
|
return false;
|
|
32173
32359
|
const cmd = command[0];
|
|
32174
32360
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
32175
|
-
if (
|
|
32361
|
+
if (existsSync43(cmd))
|
|
32176
32362
|
return true;
|
|
32177
32363
|
}
|
|
32178
32364
|
const isWindows2 = process.platform === "win32";
|
|
@@ -32194,23 +32380,23 @@ function isServerInstalled(command) {
|
|
|
32194
32380
|
const paths = pathEnv.split(pathSeparator);
|
|
32195
32381
|
for (const p of paths) {
|
|
32196
32382
|
for (const suffix of exts) {
|
|
32197
|
-
if (
|
|
32383
|
+
if (existsSync43(join56(p, cmd + suffix))) {
|
|
32198
32384
|
return true;
|
|
32199
32385
|
}
|
|
32200
32386
|
}
|
|
32201
32387
|
}
|
|
32202
32388
|
const cwd2 = process.cwd();
|
|
32203
32389
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
32204
|
-
const dataDir =
|
|
32390
|
+
const dataDir = join56(getDataDir(), "opencode");
|
|
32205
32391
|
const additionalBases = [
|
|
32206
|
-
|
|
32207
|
-
|
|
32208
|
-
|
|
32209
|
-
|
|
32392
|
+
join56(cwd2, "node_modules", ".bin"),
|
|
32393
|
+
join56(configDir, "bin"),
|
|
32394
|
+
join56(configDir, "node_modules", ".bin"),
|
|
32395
|
+
join56(dataDir, "bin")
|
|
32210
32396
|
];
|
|
32211
32397
|
for (const base of additionalBases) {
|
|
32212
32398
|
for (const suffix of exts) {
|
|
32213
|
-
if (
|
|
32399
|
+
if (existsSync43(join56(base, cmd + suffix))) {
|
|
32214
32400
|
return true;
|
|
32215
32401
|
}
|
|
32216
32402
|
}
|
|
@@ -32222,7 +32408,7 @@ function isServerInstalled(command) {
|
|
|
32222
32408
|
}
|
|
32223
32409
|
// src/tools/lsp/client.ts
|
|
32224
32410
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
32225
|
-
import { readFileSync as
|
|
32411
|
+
import { readFileSync as readFileSync35 } from "fs";
|
|
32226
32412
|
import { extname, resolve as resolve8 } from "path";
|
|
32227
32413
|
import { pathToFileURL } from "url";
|
|
32228
32414
|
class LSPServerManager {
|
|
@@ -32673,7 +32859,7 @@ ${msg}`);
|
|
|
32673
32859
|
const absPath = resolve8(filePath);
|
|
32674
32860
|
if (this.openedFiles.has(absPath))
|
|
32675
32861
|
return;
|
|
32676
|
-
const text =
|
|
32862
|
+
const text = readFileSync35(absPath, "utf-8");
|
|
32677
32863
|
const ext = extname(absPath);
|
|
32678
32864
|
const languageId = getLanguageId(ext);
|
|
32679
32865
|
this.notify("textDocument/didOpen", {
|
|
@@ -32763,17 +32949,17 @@ ${msg}`);
|
|
|
32763
32949
|
// src/tools/lsp/utils.ts
|
|
32764
32950
|
import { extname as extname2, resolve as resolve9 } from "path";
|
|
32765
32951
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32766
|
-
import { existsSync as
|
|
32952
|
+
import { existsSync as existsSync44, readFileSync as readFileSync36, writeFileSync as writeFileSync23 } from "fs";
|
|
32767
32953
|
function findWorkspaceRoot(filePath) {
|
|
32768
32954
|
let dir = resolve9(filePath);
|
|
32769
|
-
if (!
|
|
32955
|
+
if (!existsSync44(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
32770
32956
|
dir = __require("path").dirname(dir);
|
|
32771
32957
|
}
|
|
32772
32958
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
32773
32959
|
let prevDir = "";
|
|
32774
32960
|
while (dir !== prevDir) {
|
|
32775
32961
|
for (const marker of markers) {
|
|
32776
|
-
if (
|
|
32962
|
+
if (existsSync44(__require("path").join(dir, marker))) {
|
|
32777
32963
|
return dir;
|
|
32778
32964
|
}
|
|
32779
32965
|
}
|
|
@@ -32928,7 +33114,7 @@ function formatPrepareRenameResult(result) {
|
|
|
32928
33114
|
}
|
|
32929
33115
|
function applyTextEditsToFile(filePath, edits) {
|
|
32930
33116
|
try {
|
|
32931
|
-
let content =
|
|
33117
|
+
let content = readFileSync36(filePath, "utf-8");
|
|
32932
33118
|
const lines = content.split(`
|
|
32933
33119
|
`);
|
|
32934
33120
|
const sortedEdits = [...edits].sort((a, b) => {
|
|
@@ -32953,7 +33139,7 @@ function applyTextEditsToFile(filePath, edits) {
|
|
|
32953
33139
|
`));
|
|
32954
33140
|
}
|
|
32955
33141
|
}
|
|
32956
|
-
|
|
33142
|
+
writeFileSync23(filePath, lines.join(`
|
|
32957
33143
|
`), "utf-8");
|
|
32958
33144
|
return { success: true, editCount: edits.length };
|
|
32959
33145
|
} catch (err) {
|
|
@@ -32984,7 +33170,7 @@ function applyWorkspaceEdit(edit) {
|
|
|
32984
33170
|
if (change.kind === "create") {
|
|
32985
33171
|
try {
|
|
32986
33172
|
const filePath = uriToPath(change.uri);
|
|
32987
|
-
|
|
33173
|
+
writeFileSync23(filePath, "", "utf-8");
|
|
32988
33174
|
result.filesModified.push(filePath);
|
|
32989
33175
|
} catch (err) {
|
|
32990
33176
|
result.success = false;
|
|
@@ -32994,8 +33180,8 @@ function applyWorkspaceEdit(edit) {
|
|
|
32994
33180
|
try {
|
|
32995
33181
|
const oldPath = uriToPath(change.oldUri);
|
|
32996
33182
|
const newPath = uriToPath(change.newUri);
|
|
32997
|
-
const content =
|
|
32998
|
-
|
|
33183
|
+
const content = readFileSync36(oldPath, "utf-8");
|
|
33184
|
+
writeFileSync23(newPath, content, "utf-8");
|
|
32999
33185
|
__require("fs").unlinkSync(oldPath);
|
|
33000
33186
|
result.filesModified.push(newPath);
|
|
33001
33187
|
} catch (err) {
|
|
@@ -45574,13 +45760,13 @@ var lsp_rename = tool({
|
|
|
45574
45760
|
});
|
|
45575
45761
|
// src/tools/ast-grep/constants.ts
|
|
45576
45762
|
import { createRequire as createRequire4 } from "module";
|
|
45577
|
-
import { dirname as dirname11, join as
|
|
45578
|
-
import { existsSync as
|
|
45763
|
+
import { dirname as dirname11, join as join58 } from "path";
|
|
45764
|
+
import { existsSync as existsSync46, statSync as statSync5 } from "fs";
|
|
45579
45765
|
|
|
45580
45766
|
// src/tools/ast-grep/downloader.ts
|
|
45581
45767
|
init_shared();
|
|
45582
|
-
import { existsSync as
|
|
45583
|
-
import { join as
|
|
45768
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync19, chmodSync as chmodSync2, unlinkSync as unlinkSync15 } from "fs";
|
|
45769
|
+
import { join as join57 } from "path";
|
|
45584
45770
|
import { homedir as homedir13 } from "os";
|
|
45585
45771
|
import { createRequire as createRequire3 } from "module";
|
|
45586
45772
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -45606,19 +45792,19 @@ var PLATFORM_MAP2 = {
|
|
|
45606
45792
|
function getCacheDir3() {
|
|
45607
45793
|
if (process.platform === "win32") {
|
|
45608
45794
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
45609
|
-
const base2 = localAppData ||
|
|
45610
|
-
return
|
|
45795
|
+
const base2 = localAppData || join57(homedir13(), "AppData", "Local");
|
|
45796
|
+
return join57(base2, "oh-my-opencode", "bin");
|
|
45611
45797
|
}
|
|
45612
45798
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
45613
|
-
const base = xdgCache ||
|
|
45614
|
-
return
|
|
45799
|
+
const base = xdgCache || join57(homedir13(), ".cache");
|
|
45800
|
+
return join57(base, "oh-my-opencode", "bin");
|
|
45615
45801
|
}
|
|
45616
45802
|
function getBinaryName3() {
|
|
45617
45803
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
45618
45804
|
}
|
|
45619
45805
|
function getCachedBinaryPath2() {
|
|
45620
|
-
const binaryPath =
|
|
45621
|
-
return
|
|
45806
|
+
const binaryPath = join57(getCacheDir3(), getBinaryName3());
|
|
45807
|
+
return existsSync45(binaryPath) ? binaryPath : null;
|
|
45622
45808
|
}
|
|
45623
45809
|
async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
45624
45810
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
@@ -45629,8 +45815,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45629
45815
|
}
|
|
45630
45816
|
const cacheDir = getCacheDir3();
|
|
45631
45817
|
const binaryName = getBinaryName3();
|
|
45632
|
-
const binaryPath =
|
|
45633
|
-
if (
|
|
45818
|
+
const binaryPath = join57(cacheDir, binaryName);
|
|
45819
|
+
if (existsSync45(binaryPath)) {
|
|
45634
45820
|
return binaryPath;
|
|
45635
45821
|
}
|
|
45636
45822
|
const { arch, os: os6 } = platformInfo;
|
|
@@ -45638,21 +45824,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45638
45824
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
45639
45825
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
45640
45826
|
try {
|
|
45641
|
-
if (!
|
|
45642
|
-
|
|
45827
|
+
if (!existsSync45(cacheDir)) {
|
|
45828
|
+
mkdirSync19(cacheDir, { recursive: true });
|
|
45643
45829
|
}
|
|
45644
45830
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
45645
45831
|
if (!response.ok) {
|
|
45646
45832
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
45647
45833
|
}
|
|
45648
|
-
const archivePath =
|
|
45834
|
+
const archivePath = join57(cacheDir, assetName);
|
|
45649
45835
|
const arrayBuffer = await response.arrayBuffer();
|
|
45650
45836
|
await Bun.write(archivePath, arrayBuffer);
|
|
45651
45837
|
await extractZip(archivePath, cacheDir);
|
|
45652
|
-
if (
|
|
45838
|
+
if (existsSync45(archivePath)) {
|
|
45653
45839
|
unlinkSync15(archivePath);
|
|
45654
45840
|
}
|
|
45655
|
-
if (process.platform !== "win32" &&
|
|
45841
|
+
if (process.platform !== "win32" && existsSync45(binaryPath)) {
|
|
45656
45842
|
chmodSync2(binaryPath, 493);
|
|
45657
45843
|
}
|
|
45658
45844
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -45703,8 +45889,8 @@ function findSgCliPathSync() {
|
|
|
45703
45889
|
const require2 = createRequire4(import.meta.url);
|
|
45704
45890
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
45705
45891
|
const cliDir = dirname11(cliPkgPath);
|
|
45706
|
-
const sgPath =
|
|
45707
|
-
if (
|
|
45892
|
+
const sgPath = join58(cliDir, binaryName);
|
|
45893
|
+
if (existsSync46(sgPath) && isValidBinary(sgPath)) {
|
|
45708
45894
|
return sgPath;
|
|
45709
45895
|
}
|
|
45710
45896
|
} catch {}
|
|
@@ -45715,8 +45901,8 @@ function findSgCliPathSync() {
|
|
|
45715
45901
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
45716
45902
|
const pkgDir = dirname11(pkgPath);
|
|
45717
45903
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
45718
|
-
const binaryPath =
|
|
45719
|
-
if (
|
|
45904
|
+
const binaryPath = join58(pkgDir, astGrepName);
|
|
45905
|
+
if (existsSync46(binaryPath) && isValidBinary(binaryPath)) {
|
|
45720
45906
|
return binaryPath;
|
|
45721
45907
|
}
|
|
45722
45908
|
} catch {}
|
|
@@ -45724,7 +45910,7 @@ function findSgCliPathSync() {
|
|
|
45724
45910
|
if (process.platform === "darwin") {
|
|
45725
45911
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
45726
45912
|
for (const path7 of homebrewPaths) {
|
|
45727
|
-
if (
|
|
45913
|
+
if (existsSync46(path7) && isValidBinary(path7)) {
|
|
45728
45914
|
return path7;
|
|
45729
45915
|
}
|
|
45730
45916
|
}
|
|
@@ -45779,11 +45965,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
45779
45965
|
|
|
45780
45966
|
// src/tools/ast-grep/cli.ts
|
|
45781
45967
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
45782
|
-
import { existsSync as
|
|
45968
|
+
import { existsSync as existsSync47 } from "fs";
|
|
45783
45969
|
var resolvedCliPath3 = null;
|
|
45784
45970
|
var initPromise2 = null;
|
|
45785
45971
|
async function getAstGrepPath() {
|
|
45786
|
-
if (resolvedCliPath3 !== null &&
|
|
45972
|
+
if (resolvedCliPath3 !== null && existsSync47(resolvedCliPath3)) {
|
|
45787
45973
|
return resolvedCliPath3;
|
|
45788
45974
|
}
|
|
45789
45975
|
if (initPromise2) {
|
|
@@ -45791,7 +45977,7 @@ async function getAstGrepPath() {
|
|
|
45791
45977
|
}
|
|
45792
45978
|
initPromise2 = (async () => {
|
|
45793
45979
|
const syncPath = findSgCliPathSync();
|
|
45794
|
-
if (syncPath &&
|
|
45980
|
+
if (syncPath && existsSync47(syncPath)) {
|
|
45795
45981
|
resolvedCliPath3 = syncPath;
|
|
45796
45982
|
setSgCliPath(syncPath);
|
|
45797
45983
|
return syncPath;
|
|
@@ -45825,7 +46011,7 @@ async function runSg(options) {
|
|
|
45825
46011
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
45826
46012
|
args.push(...paths);
|
|
45827
46013
|
let cliPath = getSgCliPath();
|
|
45828
|
-
if (!
|
|
46014
|
+
if (!existsSync47(cliPath) && cliPath !== "sg") {
|
|
45829
46015
|
const downloadedPath = await getAstGrepPath();
|
|
45830
46016
|
if (downloadedPath) {
|
|
45831
46017
|
cliPath = downloadedPath;
|
|
@@ -46089,21 +46275,21 @@ var ast_grep_replace = tool({
|
|
|
46089
46275
|
var {spawn: spawn9 } = globalThis.Bun;
|
|
46090
46276
|
|
|
46091
46277
|
// src/tools/grep/constants.ts
|
|
46092
|
-
import { existsSync as
|
|
46093
|
-
import { join as
|
|
46278
|
+
import { existsSync as existsSync49 } from "fs";
|
|
46279
|
+
import { join as join60, dirname as dirname12 } from "path";
|
|
46094
46280
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46095
46281
|
|
|
46096
46282
|
// src/tools/grep/downloader.ts
|
|
46097
46283
|
init_shared();
|
|
46098
|
-
import { existsSync as
|
|
46099
|
-
import { join as
|
|
46284
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync20, chmodSync as chmodSync3, unlinkSync as unlinkSync16, readdirSync as readdirSync14 } from "fs";
|
|
46285
|
+
import { join as join59 } from "path";
|
|
46100
46286
|
var {spawn: spawn8 } = globalThis.Bun;
|
|
46101
46287
|
function findFileRecursive(dir, filename) {
|
|
46102
46288
|
try {
|
|
46103
46289
|
const entries = readdirSync14(dir, { withFileTypes: true, recursive: true });
|
|
46104
46290
|
for (const entry of entries) {
|
|
46105
46291
|
if (entry.isFile() && entry.name === filename) {
|
|
46106
|
-
return
|
|
46292
|
+
return join59(entry.parentPath ?? dir, entry.name);
|
|
46107
46293
|
}
|
|
46108
46294
|
}
|
|
46109
46295
|
} catch {
|
|
@@ -46124,11 +46310,11 @@ function getPlatformKey() {
|
|
|
46124
46310
|
}
|
|
46125
46311
|
function getInstallDir() {
|
|
46126
46312
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
46127
|
-
return
|
|
46313
|
+
return join59(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
46128
46314
|
}
|
|
46129
46315
|
function getRgPath() {
|
|
46130
46316
|
const isWindows2 = process.platform === "win32";
|
|
46131
|
-
return
|
|
46317
|
+
return join59(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
46132
46318
|
}
|
|
46133
46319
|
async function downloadFile(url2, destPath) {
|
|
46134
46320
|
const response = await fetch(url2);
|
|
@@ -46162,7 +46348,7 @@ async function extractZip2(archivePath, destDir) {
|
|
|
46162
46348
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
46163
46349
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
46164
46350
|
if (foundPath) {
|
|
46165
|
-
const destPath =
|
|
46351
|
+
const destPath = join59(destDir, binaryName);
|
|
46166
46352
|
if (foundPath !== destPath) {
|
|
46167
46353
|
const { renameSync: renameSync5 } = await import("fs");
|
|
46168
46354
|
renameSync5(foundPath, destPath);
|
|
@@ -46177,13 +46363,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
46177
46363
|
}
|
|
46178
46364
|
const installDir = getInstallDir();
|
|
46179
46365
|
const rgPath = getRgPath();
|
|
46180
|
-
if (
|
|
46366
|
+
if (existsSync48(rgPath)) {
|
|
46181
46367
|
return rgPath;
|
|
46182
46368
|
}
|
|
46183
|
-
|
|
46369
|
+
mkdirSync20(installDir, { recursive: true });
|
|
46184
46370
|
const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
|
|
46185
46371
|
const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
46186
|
-
const archivePath =
|
|
46372
|
+
const archivePath = join59(installDir, filename);
|
|
46187
46373
|
try {
|
|
46188
46374
|
await downloadFile(url2, archivePath);
|
|
46189
46375
|
if (config3.extension === "tar.gz") {
|
|
@@ -46194,12 +46380,12 @@ async function downloadAndInstallRipgrep() {
|
|
|
46194
46380
|
if (process.platform !== "win32") {
|
|
46195
46381
|
chmodSync3(rgPath, 493);
|
|
46196
46382
|
}
|
|
46197
|
-
if (!
|
|
46383
|
+
if (!existsSync48(rgPath)) {
|
|
46198
46384
|
throw new Error("\u63D0\u53D6\u540E\u672A\u627E\u5230 ripgrep \u4E8C\u8FDB\u5236\u6587\u4EF6");
|
|
46199
46385
|
}
|
|
46200
46386
|
return rgPath;
|
|
46201
46387
|
} finally {
|
|
46202
|
-
if (
|
|
46388
|
+
if (existsSync48(archivePath)) {
|
|
46203
46389
|
try {
|
|
46204
46390
|
unlinkSync16(archivePath);
|
|
46205
46391
|
} catch {}
|
|
@@ -46208,7 +46394,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
46208
46394
|
}
|
|
46209
46395
|
function getInstalledRipgrepPath() {
|
|
46210
46396
|
const rgPath = getRgPath();
|
|
46211
|
-
return
|
|
46397
|
+
return existsSync48(rgPath) ? rgPath : null;
|
|
46212
46398
|
}
|
|
46213
46399
|
|
|
46214
46400
|
// src/tools/grep/constants.ts
|
|
@@ -46232,7 +46418,7 @@ function findExecutable(name) {
|
|
|
46232
46418
|
continue;
|
|
46233
46419
|
}
|
|
46234
46420
|
}
|
|
46235
|
-
if (
|
|
46421
|
+
if (existsSync49(trimmed)) {
|
|
46236
46422
|
return trimmed;
|
|
46237
46423
|
}
|
|
46238
46424
|
}
|
|
@@ -46247,14 +46433,14 @@ function getOpenCodeBundledRg() {
|
|
|
46247
46433
|
const isWindows2 = process.platform === "win32";
|
|
46248
46434
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
46249
46435
|
const candidates = [
|
|
46250
|
-
|
|
46251
|
-
|
|
46252
|
-
|
|
46253
|
-
|
|
46254
|
-
|
|
46436
|
+
join60(getDataDir(), "opencode", "bin", rgName),
|
|
46437
|
+
join60(execDir, rgName),
|
|
46438
|
+
join60(execDir, "bin", rgName),
|
|
46439
|
+
join60(execDir, "..", "bin", rgName),
|
|
46440
|
+
join60(execDir, "..", "libexec", rgName)
|
|
46255
46441
|
];
|
|
46256
46442
|
for (const candidate of candidates) {
|
|
46257
|
-
if (
|
|
46443
|
+
if (existsSync49(candidate)) {
|
|
46258
46444
|
return candidate;
|
|
46259
46445
|
}
|
|
46260
46446
|
}
|
|
@@ -46716,8 +46902,8 @@ var glob = tool({
|
|
|
46716
46902
|
init_shared();
|
|
46717
46903
|
init_file_utils();
|
|
46718
46904
|
init_shared();
|
|
46719
|
-
import { existsSync as
|
|
46720
|
-
import { join as
|
|
46905
|
+
import { existsSync as existsSync50, readdirSync as readdirSync15, readFileSync as readFileSync37 } from "fs";
|
|
46906
|
+
import { join as join61, basename as basename4, dirname as dirname13 } from "path";
|
|
46721
46907
|
// src/features/builtin-commands/templates/init-deep.ts
|
|
46722
46908
|
var INIT_DEEP_TEMPLATE = `# /init-deep
|
|
46723
46909
|
|
|
@@ -47862,7 +48048,7 @@ function loadBuiltinCommands(disabledCommands) {
|
|
|
47862
48048
|
}
|
|
47863
48049
|
// src/tools/slashcommand/tools.ts
|
|
47864
48050
|
function discoverCommandsFromDir2(commandsDir, scope) {
|
|
47865
|
-
if (!
|
|
48051
|
+
if (!existsSync50(commandsDir)) {
|
|
47866
48052
|
return [];
|
|
47867
48053
|
}
|
|
47868
48054
|
const entries = readdirSync15(commandsDir, { withFileTypes: true });
|
|
@@ -47870,10 +48056,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
47870
48056
|
for (const entry of entries) {
|
|
47871
48057
|
if (!isMarkdownFile(entry))
|
|
47872
48058
|
continue;
|
|
47873
|
-
const commandPath =
|
|
48059
|
+
const commandPath = join61(commandsDir, entry.name);
|
|
47874
48060
|
const commandName = basename4(entry.name, ".md");
|
|
47875
48061
|
try {
|
|
47876
|
-
const content =
|
|
48062
|
+
const content = readFileSync37(commandPath, "utf-8");
|
|
47877
48063
|
const { data, body } = parseFrontmatter(content);
|
|
47878
48064
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
47879
48065
|
const metadata = {
|
|
@@ -47899,10 +48085,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
47899
48085
|
}
|
|
47900
48086
|
function discoverCommandsSync(disabledCommands) {
|
|
47901
48087
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
47902
|
-
const userCommandsDir =
|
|
47903
|
-
const projectCommandsDir =
|
|
47904
|
-
const opencodeGlobalDir =
|
|
47905
|
-
const opencodeProjectDir =
|
|
48088
|
+
const userCommandsDir = join61(getClaudeConfigDir(), "commands");
|
|
48089
|
+
const projectCommandsDir = join61(process.cwd(), ".claude", "commands");
|
|
48090
|
+
const opencodeGlobalDir = join61(configDir, "command");
|
|
48091
|
+
const opencodeProjectDir = join61(process.cwd(), ".opencode", "command");
|
|
47906
48092
|
const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
|
|
47907
48093
|
const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
|
|
47908
48094
|
const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
|
|
@@ -48102,13 +48288,13 @@ var slashcommand = createSlashcommandTool();
|
|
|
48102
48288
|
// src/tools/session-manager/constants.ts
|
|
48103
48289
|
init_data_path();
|
|
48104
48290
|
init_shared();
|
|
48105
|
-
import { join as
|
|
48291
|
+
import { join as join62 } from "path";
|
|
48106
48292
|
var OPENCODE_STORAGE11 = getOpenCodeStorageDir();
|
|
48107
|
-
var MESSAGE_STORAGE4 =
|
|
48108
|
-
var PART_STORAGE4 =
|
|
48109
|
-
var SESSION_STORAGE =
|
|
48110
|
-
var TODO_DIR2 =
|
|
48111
|
-
var TRANSCRIPT_DIR2 =
|
|
48293
|
+
var MESSAGE_STORAGE4 = join62(OPENCODE_STORAGE11, "message");
|
|
48294
|
+
var PART_STORAGE4 = join62(OPENCODE_STORAGE11, "part");
|
|
48295
|
+
var SESSION_STORAGE = join62(OPENCODE_STORAGE11, "session");
|
|
48296
|
+
var TODO_DIR2 = join62(getClaudeConfigDir(), "todos");
|
|
48297
|
+
var TRANSCRIPT_DIR2 = join62(getClaudeConfigDir(), "transcripts");
|
|
48112
48298
|
var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
|
|
48113
48299
|
|
|
48114
48300
|
\u8FD4\u56DE\u53EF\u7528\u7684 session ID \u5217\u8868\uFF0C\u5305\u542B\u6D88\u606F\u6570\u91CF\u3001\u65E5\u671F\u8303\u56F4\u548C\u4F7F\u7528\u8FC7\u7684 agents \u7B49\u5143\u6570\u636E\u3002
|
|
@@ -48181,11 +48367,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
48181
48367
|
Has Transcript: Yes (234 entries)`;
|
|
48182
48368
|
|
|
48183
48369
|
// src/tools/session-manager/storage.ts
|
|
48184
|
-
import { existsSync as
|
|
48370
|
+
import { existsSync as existsSync51, readdirSync as readdirSync16 } from "fs";
|
|
48185
48371
|
import { readdir, readFile } from "fs/promises";
|
|
48186
|
-
import { join as
|
|
48372
|
+
import { join as join63 } from "path";
|
|
48187
48373
|
async function getMainSessions(options) {
|
|
48188
|
-
if (!
|
|
48374
|
+
if (!existsSync51(SESSION_STORAGE))
|
|
48189
48375
|
return [];
|
|
48190
48376
|
const sessions = [];
|
|
48191
48377
|
try {
|
|
@@ -48193,13 +48379,13 @@ async function getMainSessions(options) {
|
|
|
48193
48379
|
for (const projectDir of projectDirs) {
|
|
48194
48380
|
if (!projectDir.isDirectory())
|
|
48195
48381
|
continue;
|
|
48196
|
-
const projectPath =
|
|
48382
|
+
const projectPath = join63(SESSION_STORAGE, projectDir.name);
|
|
48197
48383
|
const sessionFiles = await readdir(projectPath);
|
|
48198
48384
|
for (const file2 of sessionFiles) {
|
|
48199
48385
|
if (!file2.endsWith(".json"))
|
|
48200
48386
|
continue;
|
|
48201
48387
|
try {
|
|
48202
|
-
const content = await readFile(
|
|
48388
|
+
const content = await readFile(join63(projectPath, file2), "utf-8");
|
|
48203
48389
|
const meta = JSON.parse(content);
|
|
48204
48390
|
if (meta.parentID)
|
|
48205
48391
|
continue;
|
|
@@ -48217,7 +48403,7 @@ async function getMainSessions(options) {
|
|
|
48217
48403
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
48218
48404
|
}
|
|
48219
48405
|
async function getAllSessions() {
|
|
48220
|
-
if (!
|
|
48406
|
+
if (!existsSync51(MESSAGE_STORAGE4))
|
|
48221
48407
|
return [];
|
|
48222
48408
|
const sessions = [];
|
|
48223
48409
|
async function scanDirectory(dir) {
|
|
@@ -48225,7 +48411,7 @@ async function getAllSessions() {
|
|
|
48225
48411
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
48226
48412
|
for (const entry of entries) {
|
|
48227
48413
|
if (entry.isDirectory()) {
|
|
48228
|
-
const sessionPath =
|
|
48414
|
+
const sessionPath = join63(dir, entry.name);
|
|
48229
48415
|
const files = await readdir(sessionPath);
|
|
48230
48416
|
if (files.some((f) => f.endsWith(".json"))) {
|
|
48231
48417
|
sessions.push(entry.name);
|
|
@@ -48242,16 +48428,16 @@ async function getAllSessions() {
|
|
|
48242
48428
|
return [...new Set(sessions)];
|
|
48243
48429
|
}
|
|
48244
48430
|
function getMessageDir6(sessionID) {
|
|
48245
|
-
if (!
|
|
48431
|
+
if (!existsSync51(MESSAGE_STORAGE4))
|
|
48246
48432
|
return "";
|
|
48247
|
-
const directPath =
|
|
48248
|
-
if (
|
|
48433
|
+
const directPath = join63(MESSAGE_STORAGE4, sessionID);
|
|
48434
|
+
if (existsSync51(directPath)) {
|
|
48249
48435
|
return directPath;
|
|
48250
48436
|
}
|
|
48251
48437
|
try {
|
|
48252
48438
|
for (const dir of readdirSync16(MESSAGE_STORAGE4)) {
|
|
48253
|
-
const sessionPath =
|
|
48254
|
-
if (
|
|
48439
|
+
const sessionPath = join63(MESSAGE_STORAGE4, dir, sessionID);
|
|
48440
|
+
if (existsSync51(sessionPath)) {
|
|
48255
48441
|
return sessionPath;
|
|
48256
48442
|
}
|
|
48257
48443
|
}
|
|
@@ -48265,7 +48451,7 @@ function sessionExists(sessionID) {
|
|
|
48265
48451
|
}
|
|
48266
48452
|
async function readSessionMessages(sessionID) {
|
|
48267
48453
|
const messageDir = getMessageDir6(sessionID);
|
|
48268
|
-
if (!messageDir || !
|
|
48454
|
+
if (!messageDir || !existsSync51(messageDir))
|
|
48269
48455
|
return [];
|
|
48270
48456
|
const messages = [];
|
|
48271
48457
|
try {
|
|
@@ -48274,7 +48460,7 @@ async function readSessionMessages(sessionID) {
|
|
|
48274
48460
|
if (!file2.endsWith(".json"))
|
|
48275
48461
|
continue;
|
|
48276
48462
|
try {
|
|
48277
|
-
const content = await readFile(
|
|
48463
|
+
const content = await readFile(join63(messageDir, file2), "utf-8");
|
|
48278
48464
|
const meta = JSON.parse(content);
|
|
48279
48465
|
const parts = await readParts2(meta.id);
|
|
48280
48466
|
messages.push({
|
|
@@ -48300,8 +48486,8 @@ async function readSessionMessages(sessionID) {
|
|
|
48300
48486
|
});
|
|
48301
48487
|
}
|
|
48302
48488
|
async function readParts2(messageID) {
|
|
48303
|
-
const partDir =
|
|
48304
|
-
if (!
|
|
48489
|
+
const partDir = join63(PART_STORAGE4, messageID);
|
|
48490
|
+
if (!existsSync51(partDir))
|
|
48305
48491
|
return [];
|
|
48306
48492
|
const parts = [];
|
|
48307
48493
|
try {
|
|
@@ -48310,7 +48496,7 @@ async function readParts2(messageID) {
|
|
|
48310
48496
|
if (!file2.endsWith(".json"))
|
|
48311
48497
|
continue;
|
|
48312
48498
|
try {
|
|
48313
|
-
const content = await readFile(
|
|
48499
|
+
const content = await readFile(join63(partDir, file2), "utf-8");
|
|
48314
48500
|
parts.push(JSON.parse(content));
|
|
48315
48501
|
} catch {
|
|
48316
48502
|
continue;
|
|
@@ -48322,14 +48508,14 @@ async function readParts2(messageID) {
|
|
|
48322
48508
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
48323
48509
|
}
|
|
48324
48510
|
async function readSessionTodos(sessionID) {
|
|
48325
|
-
if (!
|
|
48511
|
+
if (!existsSync51(TODO_DIR2))
|
|
48326
48512
|
return [];
|
|
48327
48513
|
try {
|
|
48328
48514
|
const allFiles = await readdir(TODO_DIR2);
|
|
48329
48515
|
const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
|
|
48330
48516
|
for (const file2 of todoFiles) {
|
|
48331
48517
|
try {
|
|
48332
|
-
const content = await readFile(
|
|
48518
|
+
const content = await readFile(join63(TODO_DIR2, file2), "utf-8");
|
|
48333
48519
|
const data = JSON.parse(content);
|
|
48334
48520
|
if (Array.isArray(data)) {
|
|
48335
48521
|
return data.map((item) => ({
|
|
@@ -48349,10 +48535,10 @@ async function readSessionTodos(sessionID) {
|
|
|
48349
48535
|
return [];
|
|
48350
48536
|
}
|
|
48351
48537
|
async function readSessionTranscript(sessionID) {
|
|
48352
|
-
if (!
|
|
48538
|
+
if (!existsSync51(TRANSCRIPT_DIR2))
|
|
48353
48539
|
return 0;
|
|
48354
|
-
const transcriptFile =
|
|
48355
|
-
if (!
|
|
48540
|
+
const transcriptFile = join63(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
48541
|
+
if (!existsSync51(transcriptFile))
|
|
48356
48542
|
return 0;
|
|
48357
48543
|
try {
|
|
48358
48544
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -49175,6 +49361,7 @@ var BACKGROUND_OUTPUT_DESCRIPTION = `\u83B7\u53D6\u540E\u53F0\u4EFB\u52A1\u7684\
|
|
|
49175
49361
|
var BACKGROUND_CANCEL_DESCRIPTION = `\u53D6\u6D88\u6B63\u5728\u8FD0\u884C\u7684\u540E\u53F0\u4EFB\u52A1\u3002\u4F7F\u7528 all=true \u53EF\u5728\u6700\u7EC8\u56DE\u7B54\u524D\u53D6\u6D88\u6240\u6709\u4EFB\u52A1\u3002`;
|
|
49176
49362
|
|
|
49177
49363
|
// src/tools/background-task/tools.ts
|
|
49364
|
+
init_claude_code_session_state();
|
|
49178
49365
|
init_logger();
|
|
49179
49366
|
init_session_cursor();
|
|
49180
49367
|
init_agent_display_names();
|
|
@@ -49559,20 +49746,21 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
|
|
|
49559
49746
|
|
|
49560
49747
|
\u4F20\u5165 \`session_id=<id>\` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684 agent\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002Prompts \u5FC5\u987B\u4E3A\u4E2D\u6587\u3002\u4F7F\u7528 \`background_output\` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002`;
|
|
49561
49748
|
// src/tools/call-omo-agent/tools.ts
|
|
49562
|
-
import { existsSync as
|
|
49563
|
-
import { join as
|
|
49749
|
+
import { existsSync as existsSync52, readdirSync as readdirSync17 } from "fs";
|
|
49750
|
+
import { join as join64 } from "path";
|
|
49564
49751
|
init_shared();
|
|
49565
49752
|
init_agent_display_names();
|
|
49566
49753
|
init_session_cursor();
|
|
49754
|
+
init_claude_code_session_state();
|
|
49567
49755
|
function getMessageDir7(sessionID) {
|
|
49568
|
-
if (!
|
|
49756
|
+
if (!existsSync52(MESSAGE_STORAGE))
|
|
49569
49757
|
return null;
|
|
49570
|
-
const directPath =
|
|
49571
|
-
if (
|
|
49758
|
+
const directPath = join64(MESSAGE_STORAGE, sessionID);
|
|
49759
|
+
if (existsSync52(directPath))
|
|
49572
49760
|
return directPath;
|
|
49573
49761
|
for (const dir of readdirSync17(MESSAGE_STORAGE)) {
|
|
49574
|
-
const sessionPath =
|
|
49575
|
-
if (
|
|
49762
|
+
const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
|
|
49763
|
+
if (existsSync52(sessionPath))
|
|
49576
49764
|
return sessionPath;
|
|
49577
49765
|
}
|
|
49578
49766
|
return null;
|
|
@@ -49998,8 +50186,8 @@ function createLookAt(ctx) {
|
|
|
49998
50186
|
}
|
|
49999
50187
|
// src/tools/delegate-task/tools.ts
|
|
50000
50188
|
init_constants();
|
|
50001
|
-
import { existsSync as
|
|
50002
|
-
import { join as
|
|
50189
|
+
import { existsSync as existsSync53, readdirSync as readdirSync18 } from "fs";
|
|
50190
|
+
import { join as join65 } from "path";
|
|
50003
50191
|
|
|
50004
50192
|
// src/features/task-toast-manager/manager.ts
|
|
50005
50193
|
class TaskToastManager {
|
|
@@ -50175,10 +50363,12 @@ function initTaskToastManager(client2, concurrencyManager) {
|
|
|
50175
50363
|
return instance;
|
|
50176
50364
|
}
|
|
50177
50365
|
// src/tools/delegate-task/tools.ts
|
|
50366
|
+
init_claude_code_session_state();
|
|
50178
50367
|
init_shared();
|
|
50179
50368
|
init_agent_display_names();
|
|
50180
50369
|
init_runtime_fallback();
|
|
50181
50370
|
init_model_health_registry();
|
|
50371
|
+
init_agent_identity_resolver();
|
|
50182
50372
|
var SISYPHUS_JUNIOR_AGENT = "\u6267\u884C\u52A9\u7406";
|
|
50183
50373
|
var MAX_LOOP_ATTEMPTS = 10;
|
|
50184
50374
|
function sleep(ms) {
|
|
@@ -50205,14 +50395,14 @@ function parseFallbackModelEntries(entries) {
|
|
|
50205
50395
|
});
|
|
50206
50396
|
}
|
|
50207
50397
|
function getMessageDir8(sessionID) {
|
|
50208
|
-
if (!
|
|
50398
|
+
if (!existsSync53(MESSAGE_STORAGE))
|
|
50209
50399
|
return null;
|
|
50210
|
-
const directPath =
|
|
50211
|
-
if (
|
|
50400
|
+
const directPath = join65(MESSAGE_STORAGE, sessionID);
|
|
50401
|
+
if (existsSync53(directPath))
|
|
50212
50402
|
return directPath;
|
|
50213
50403
|
for (const dir of readdirSync18(MESSAGE_STORAGE)) {
|
|
50214
|
-
const sessionPath =
|
|
50215
|
-
if (
|
|
50404
|
+
const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
|
|
50405
|
+
if (existsSync53(sessionPath))
|
|
50216
50406
|
return sessionPath;
|
|
50217
50407
|
}
|
|
50218
50408
|
return null;
|
|
@@ -50294,18 +50484,30 @@ function buildSystemContent(input) {
|
|
|
50294
50484
|
|
|
50295
50485
|
`);
|
|
50296
50486
|
}
|
|
50297
|
-
function extractResumeInfoFromMessages(messages) {
|
|
50298
|
-
|
|
50299
|
-
|
|
50487
|
+
function extractResumeInfoFromMessages(sessionID, messages) {
|
|
50488
|
+
const resolvedAgent = resolveCurrentAgent(sessionID);
|
|
50489
|
+
if (resolvedAgent) {
|
|
50490
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
50491
|
+
const info = messages[i].info;
|
|
50492
|
+
if (info?.model || info?.modelID && info?.providerID) {
|
|
50493
|
+
return {
|
|
50494
|
+
agent: resolvedAgent,
|
|
50495
|
+
model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
|
|
50496
|
+
};
|
|
50497
|
+
}
|
|
50498
|
+
}
|
|
50499
|
+
return { agent: resolvedAgent, model: undefined };
|
|
50500
|
+
}
|
|
50300
50501
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
50301
50502
|
const info = messages[i].info;
|
|
50302
50503
|
if (info?.role === "assistant" && (info?.agent || info?.model || info?.modelID && info?.providerID)) {
|
|
50303
|
-
|
|
50304
|
-
|
|
50305
|
-
|
|
50504
|
+
return {
|
|
50505
|
+
agent: info.agent,
|
|
50506
|
+
model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
|
|
50507
|
+
};
|
|
50306
50508
|
}
|
|
50307
50509
|
}
|
|
50308
|
-
return { agent, model };
|
|
50510
|
+
return { agent: undefined, model: undefined };
|
|
50309
50511
|
}
|
|
50310
50512
|
async function pollTaskCompletion(client2, sessionID, maxWaitMs = 120000, pollIntervalMs = 2000) {
|
|
50311
50513
|
const startTime = Date.now();
|
|
@@ -50483,7 +50685,7 @@ Agent \u7EE7\u7EED\u6267\u884C\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u
|
|
|
50483
50685
|
try {
|
|
50484
50686
|
const messagesResp = await client2.session.messages({ path: { id: args.session_id } });
|
|
50485
50687
|
const messages2 = messagesResp.data ?? [];
|
|
50486
|
-
const resumeInfo = extractResumeInfoFromMessages(messages2);
|
|
50688
|
+
const resumeInfo = extractResumeInfoFromMessages(args.session_id, messages2);
|
|
50487
50689
|
resumeAgent = resumeInfo.agent;
|
|
50488
50690
|
resumeModel = resumeInfo.model;
|
|
50489
50691
|
} catch {
|
|
@@ -51308,8 +51510,10 @@ class PerformanceAggregator {
|
|
|
51308
51510
|
}
|
|
51309
51511
|
|
|
51310
51512
|
// src/features/background-agent/manager.ts
|
|
51311
|
-
|
|
51312
|
-
|
|
51513
|
+
init_claude_code_session_state();
|
|
51514
|
+
init_agent_identity_resolver();
|
|
51515
|
+
import { existsSync as existsSync54, readdirSync as readdirSync19 } from "fs";
|
|
51516
|
+
import { join as join66 } from "path";
|
|
51313
51517
|
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
51314
51518
|
var MIN_STABILITY_TIME_MS = 10 * 1000;
|
|
51315
51519
|
var DEFAULT_STALE_TIMEOUT_MS = 120000;
|
|
@@ -52102,15 +52306,15 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
52102
52306
|
\u4F7F\u7528 \`background_output(task_id="${task.id}")\` \u5728\u51C6\u5907\u5C31\u7EEA\u65F6\u83B7\u53D6\u6B64\u7ED3\u679C\u3002
|
|
52103
52307
|
</system-reminder>`;
|
|
52104
52308
|
}
|
|
52105
|
-
|
|
52309
|
+
const currentParentAgent = resolveCurrentAgent(task.parentSessionID);
|
|
52310
|
+
const agent = currentParentAgent ?? task.parentAgent;
|
|
52106
52311
|
let model;
|
|
52107
52312
|
try {
|
|
52108
52313
|
const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionID } });
|
|
52109
52314
|
const messages = messagesResp.data ?? [];
|
|
52110
52315
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
52111
52316
|
const info = messages[i].info;
|
|
52112
|
-
if (info?.
|
|
52113
|
-
agent = info.agent ?? task.parentAgent;
|
|
52317
|
+
if (info?.model || info?.modelID && info?.providerID) {
|
|
52114
52318
|
model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
|
|
52115
52319
|
break;
|
|
52116
52320
|
}
|
|
@@ -52118,7 +52322,6 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
52118
52322
|
} catch {
|
|
52119
52323
|
const messageDir = getMessageDir9(task.parentSessionID);
|
|
52120
52324
|
const currentMessage = messageDir ? findNearestAssistantMessage(messageDir) : null;
|
|
52121
|
-
agent = currentMessage?.agent ?? task.parentAgent;
|
|
52122
52325
|
model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
|
|
52123
52326
|
}
|
|
52124
52327
|
log("[background-agent] notifyParentSession context:", {
|
|
@@ -52483,14 +52686,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
52483
52686
|
return listener;
|
|
52484
52687
|
}
|
|
52485
52688
|
function getMessageDir9(sessionID) {
|
|
52486
|
-
if (!
|
|
52689
|
+
if (!existsSync54(MESSAGE_STORAGE))
|
|
52487
52690
|
return null;
|
|
52488
|
-
const directPath =
|
|
52489
|
-
if (
|
|
52691
|
+
const directPath = join66(MESSAGE_STORAGE, sessionID);
|
|
52692
|
+
if (existsSync54(directPath))
|
|
52490
52693
|
return directPath;
|
|
52491
52694
|
for (const dir of readdirSync19(MESSAGE_STORAGE)) {
|
|
52492
|
-
const sessionPath =
|
|
52493
|
-
if (
|
|
52695
|
+
const sessionPath = join66(MESSAGE_STORAGE, dir, sessionID);
|
|
52696
|
+
if (existsSync54(sessionPath))
|
|
52494
52697
|
return sessionPath;
|
|
52495
52698
|
}
|
|
52496
52699
|
return null;
|
|
@@ -71715,7 +71918,7 @@ init_file_utils();
|
|
|
71715
71918
|
init_shared();
|
|
71716
71919
|
init_logger();
|
|
71717
71920
|
import { promises as fs11 } from "fs";
|
|
71718
|
-
import { join as
|
|
71921
|
+
import { join as join68, basename as basename6 } from "path";
|
|
71719
71922
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
71720
71923
|
try {
|
|
71721
71924
|
await fs11.access(commandsDir);
|
|
@@ -71745,7 +71948,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71745
71948
|
if (entry.isDirectory()) {
|
|
71746
71949
|
if (entry.name.startsWith("."))
|
|
71747
71950
|
continue;
|
|
71748
|
-
const subDirPath =
|
|
71951
|
+
const subDirPath = join68(commandsDir, entry.name);
|
|
71749
71952
|
const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
71750
71953
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
71751
71954
|
commands2.push(...subCommands);
|
|
@@ -71753,7 +71956,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71753
71956
|
}
|
|
71754
71957
|
if (!isMarkdownFile(entry))
|
|
71755
71958
|
continue;
|
|
71756
|
-
const commandPath =
|
|
71959
|
+
const commandPath = join68(commandsDir, entry.name);
|
|
71757
71960
|
const baseCommandName = basename6(entry.name, ".md");
|
|
71758
71961
|
const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
|
|
71759
71962
|
try {
|
|
@@ -71800,23 +72003,23 @@ function commandsToRecord(commands2) {
|
|
|
71800
72003
|
return result;
|
|
71801
72004
|
}
|
|
71802
72005
|
async function loadUserCommands() {
|
|
71803
|
-
const userCommandsDir =
|
|
72006
|
+
const userCommandsDir = join68(getClaudeConfigDir(), "commands");
|
|
71804
72007
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
71805
72008
|
return commandsToRecord(commands2);
|
|
71806
72009
|
}
|
|
71807
72010
|
async function loadProjectCommands() {
|
|
71808
|
-
const projectCommandsDir =
|
|
72011
|
+
const projectCommandsDir = join68(process.cwd(), ".claude", "commands");
|
|
71809
72012
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
71810
72013
|
return commandsToRecord(commands2);
|
|
71811
72014
|
}
|
|
71812
72015
|
async function loadOpencodeGlobalCommands() {
|
|
71813
72016
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
71814
|
-
const opencodeCommandsDir =
|
|
72017
|
+
const opencodeCommandsDir = join68(configDir, "command");
|
|
71815
72018
|
const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
71816
72019
|
return commandsToRecord(commands2);
|
|
71817
72020
|
}
|
|
71818
72021
|
async function loadOpencodeProjectCommands() {
|
|
71819
|
-
const opencodeProjectDir =
|
|
72022
|
+
const opencodeProjectDir = join68(process.cwd(), ".opencode", "command");
|
|
71820
72023
|
const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
71821
72024
|
return commandsToRecord(commands2);
|
|
71822
72025
|
}
|
|
@@ -71824,8 +72027,8 @@ async function loadOpencodeProjectCommands() {
|
|
|
71824
72027
|
init_frontmatter();
|
|
71825
72028
|
init_file_utils();
|
|
71826
72029
|
init_shared();
|
|
71827
|
-
import { existsSync as
|
|
71828
|
-
import { join as
|
|
72030
|
+
import { existsSync as existsSync56, readdirSync as readdirSync20, readFileSync as readFileSync39 } from "fs";
|
|
72031
|
+
import { join as join69, basename as basename7 } from "path";
|
|
71829
72032
|
function parseToolsConfig(toolsStr) {
|
|
71830
72033
|
if (!toolsStr)
|
|
71831
72034
|
return;
|
|
@@ -71839,7 +72042,7 @@ function parseToolsConfig(toolsStr) {
|
|
|
71839
72042
|
return result;
|
|
71840
72043
|
}
|
|
71841
72044
|
function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
71842
|
-
if (!
|
|
72045
|
+
if (!existsSync56(agentsDir)) {
|
|
71843
72046
|
return [];
|
|
71844
72047
|
}
|
|
71845
72048
|
const entries = readdirSync20(agentsDir, { withFileTypes: true });
|
|
@@ -71847,10 +72050,10 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
|
71847
72050
|
for (const entry of entries) {
|
|
71848
72051
|
if (!isMarkdownFile(entry))
|
|
71849
72052
|
continue;
|
|
71850
|
-
const agentPath =
|
|
72053
|
+
const agentPath = join69(agentsDir, entry.name);
|
|
71851
72054
|
const agentName = basename7(entry.name, ".md");
|
|
71852
72055
|
try {
|
|
71853
|
-
const content =
|
|
72056
|
+
const content = readFileSync39(agentPath, "utf-8");
|
|
71854
72057
|
const { data, body } = parseFrontmatter(content);
|
|
71855
72058
|
const name = data.name || agentName;
|
|
71856
72059
|
const originalDescription = data.description || "";
|
|
@@ -71879,7 +72082,7 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
|
71879
72082
|
return agents;
|
|
71880
72083
|
}
|
|
71881
72084
|
function loadUserAgents(leConfig) {
|
|
71882
|
-
const userAgentsDir =
|
|
72085
|
+
const userAgentsDir = join69(getClaudeConfigDir(), "agents");
|
|
71883
72086
|
const agents = loadAgentsFromDir(userAgentsDir, "user", leConfig);
|
|
71884
72087
|
const result = {};
|
|
71885
72088
|
for (const agent of agents) {
|
|
@@ -71888,7 +72091,7 @@ function loadUserAgents(leConfig) {
|
|
|
71888
72091
|
return result;
|
|
71889
72092
|
}
|
|
71890
72093
|
function loadProjectAgents(leConfig) {
|
|
71891
|
-
const projectAgentsDir =
|
|
72094
|
+
const projectAgentsDir = join69(process.cwd(), ".claude", "agents");
|
|
71892
72095
|
const agents = loadAgentsFromDir(projectAgentsDir, "project", leConfig);
|
|
71893
72096
|
const result = {};
|
|
71894
72097
|
for (const agent of agents) {
|
|
@@ -71900,18 +72103,18 @@ function loadProjectAgents(leConfig) {
|
|
|
71900
72103
|
init_frontmatter();
|
|
71901
72104
|
init_file_utils();
|
|
71902
72105
|
init_logger();
|
|
71903
|
-
import { existsSync as
|
|
72106
|
+
import { existsSync as existsSync57, readdirSync as readdirSync21, readFileSync as readFileSync40 } from "fs";
|
|
71904
72107
|
import { homedir as homedir14 } from "os";
|
|
71905
|
-
import { join as
|
|
72108
|
+
import { join as join70, basename as basename8 } from "path";
|
|
71906
72109
|
var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
71907
72110
|
function getPluginsBaseDir() {
|
|
71908
72111
|
if (process.env.CLAUDE_PLUGINS_HOME) {
|
|
71909
72112
|
return process.env.CLAUDE_PLUGINS_HOME;
|
|
71910
72113
|
}
|
|
71911
|
-
return
|
|
72114
|
+
return join70(homedir14(), ".claude", "plugins");
|
|
71912
72115
|
}
|
|
71913
72116
|
function getInstalledPluginsPath() {
|
|
71914
|
-
return
|
|
72117
|
+
return join70(getPluginsBaseDir(), "installed_plugins.json");
|
|
71915
72118
|
}
|
|
71916
72119
|
function resolvePluginPath(path8, pluginRoot) {
|
|
71917
72120
|
return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
|
|
@@ -71936,11 +72139,11 @@ function resolvePluginPaths(obj, pluginRoot) {
|
|
|
71936
72139
|
}
|
|
71937
72140
|
function loadInstalledPlugins() {
|
|
71938
72141
|
const dbPath = getInstalledPluginsPath();
|
|
71939
|
-
if (!
|
|
72142
|
+
if (!existsSync57(dbPath)) {
|
|
71940
72143
|
return null;
|
|
71941
72144
|
}
|
|
71942
72145
|
try {
|
|
71943
|
-
const content =
|
|
72146
|
+
const content = readFileSync40(dbPath, "utf-8");
|
|
71944
72147
|
return JSON.parse(content);
|
|
71945
72148
|
} catch (error95) {
|
|
71946
72149
|
log("Failed to load installed plugins database", error95);
|
|
@@ -71951,15 +72154,15 @@ function getClaudeSettingsPath() {
|
|
|
71951
72154
|
if (process.env.CLAUDE_SETTINGS_PATH) {
|
|
71952
72155
|
return process.env.CLAUDE_SETTINGS_PATH;
|
|
71953
72156
|
}
|
|
71954
|
-
return
|
|
72157
|
+
return join70(homedir14(), ".claude", "settings.json");
|
|
71955
72158
|
}
|
|
71956
72159
|
function loadClaudeSettings() {
|
|
71957
72160
|
const settingsPath = getClaudeSettingsPath();
|
|
71958
|
-
if (!
|
|
72161
|
+
if (!existsSync57(settingsPath)) {
|
|
71959
72162
|
return null;
|
|
71960
72163
|
}
|
|
71961
72164
|
try {
|
|
71962
|
-
const content =
|
|
72165
|
+
const content = readFileSync40(settingsPath, "utf-8");
|
|
71963
72166
|
return JSON.parse(content);
|
|
71964
72167
|
} catch (error95) {
|
|
71965
72168
|
log("Failed to load Claude settings", error95);
|
|
@@ -71967,12 +72170,12 @@ function loadClaudeSettings() {
|
|
|
71967
72170
|
}
|
|
71968
72171
|
}
|
|
71969
72172
|
function loadPluginManifest(installPath) {
|
|
71970
|
-
const manifestPath =
|
|
71971
|
-
if (!
|
|
72173
|
+
const manifestPath = join70(installPath, ".claude-plugin", "plugin.json");
|
|
72174
|
+
if (!existsSync57(manifestPath)) {
|
|
71972
72175
|
return null;
|
|
71973
72176
|
}
|
|
71974
72177
|
try {
|
|
71975
|
-
const content =
|
|
72178
|
+
const content = readFileSync40(manifestPath, "utf-8");
|
|
71976
72179
|
return JSON.parse(content);
|
|
71977
72180
|
} catch (error95) {
|
|
71978
72181
|
log(`Failed to load plugin manifest from ${manifestPath}`, error95);
|
|
@@ -72019,7 +72222,7 @@ function discoverInstalledPlugins(options) {
|
|
|
72019
72222
|
continue;
|
|
72020
72223
|
}
|
|
72021
72224
|
const { installPath, scope, version: version3 } = installation;
|
|
72022
|
-
if (!
|
|
72225
|
+
if (!existsSync57(installPath)) {
|
|
72023
72226
|
errors5.push({
|
|
72024
72227
|
pluginKey,
|
|
72025
72228
|
installPath,
|
|
@@ -72037,21 +72240,21 @@ function discoverInstalledPlugins(options) {
|
|
|
72037
72240
|
pluginKey,
|
|
72038
72241
|
manifest: manifest ?? undefined
|
|
72039
72242
|
};
|
|
72040
|
-
if (
|
|
72041
|
-
loadedPlugin.commandsDir =
|
|
72243
|
+
if (existsSync57(join70(installPath, "commands"))) {
|
|
72244
|
+
loadedPlugin.commandsDir = join70(installPath, "commands");
|
|
72042
72245
|
}
|
|
72043
|
-
if (
|
|
72044
|
-
loadedPlugin.agentsDir =
|
|
72246
|
+
if (existsSync57(join70(installPath, "agents"))) {
|
|
72247
|
+
loadedPlugin.agentsDir = join70(installPath, "agents");
|
|
72045
72248
|
}
|
|
72046
|
-
if (
|
|
72047
|
-
loadedPlugin.skillsDir =
|
|
72249
|
+
if (existsSync57(join70(installPath, "skills"))) {
|
|
72250
|
+
loadedPlugin.skillsDir = join70(installPath, "skills");
|
|
72048
72251
|
}
|
|
72049
|
-
const hooksPath =
|
|
72050
|
-
if (
|
|
72252
|
+
const hooksPath = join70(installPath, "hooks", "hooks.json");
|
|
72253
|
+
if (existsSync57(hooksPath)) {
|
|
72051
72254
|
loadedPlugin.hooksPath = hooksPath;
|
|
72052
72255
|
}
|
|
72053
|
-
const mcpPath =
|
|
72054
|
-
if (
|
|
72256
|
+
const mcpPath = join70(installPath, ".mcp.json");
|
|
72257
|
+
if (existsSync57(mcpPath)) {
|
|
72055
72258
|
loadedPlugin.mcpPath = mcpPath;
|
|
72056
72259
|
}
|
|
72057
72260
|
plugins.push(loadedPlugin);
|
|
@@ -72062,17 +72265,17 @@ function discoverInstalledPlugins(options) {
|
|
|
72062
72265
|
function loadPluginCommands(plugins) {
|
|
72063
72266
|
const commands2 = {};
|
|
72064
72267
|
for (const plugin of plugins) {
|
|
72065
|
-
if (!plugin.commandsDir || !
|
|
72268
|
+
if (!plugin.commandsDir || !existsSync57(plugin.commandsDir))
|
|
72066
72269
|
continue;
|
|
72067
72270
|
const entries = readdirSync21(plugin.commandsDir, { withFileTypes: true });
|
|
72068
72271
|
for (const entry of entries) {
|
|
72069
72272
|
if (!isMarkdownFile(entry))
|
|
72070
72273
|
continue;
|
|
72071
|
-
const commandPath =
|
|
72274
|
+
const commandPath = join70(plugin.commandsDir, entry.name);
|
|
72072
72275
|
const commandName = basename8(entry.name, ".md");
|
|
72073
72276
|
const namespacedName = `${plugin.name}:${commandName}`;
|
|
72074
72277
|
try {
|
|
72075
|
-
const content =
|
|
72278
|
+
const content = readFileSync40(commandPath, "utf-8");
|
|
72076
72279
|
const { data, body } = parseFrontmatter(content);
|
|
72077
72280
|
const wrappedTemplate = `<command-instruction>
|
|
72078
72281
|
${body.trim()}
|
|
@@ -72104,21 +72307,21 @@ $ARGUMENTS
|
|
|
72104
72307
|
function loadPluginSkillsAsCommands(plugins) {
|
|
72105
72308
|
const skills = {};
|
|
72106
72309
|
for (const plugin of plugins) {
|
|
72107
|
-
if (!plugin.skillsDir || !
|
|
72310
|
+
if (!plugin.skillsDir || !existsSync57(plugin.skillsDir))
|
|
72108
72311
|
continue;
|
|
72109
72312
|
const entries = readdirSync21(plugin.skillsDir, { withFileTypes: true });
|
|
72110
72313
|
for (const entry of entries) {
|
|
72111
72314
|
if (entry.name.startsWith("."))
|
|
72112
72315
|
continue;
|
|
72113
|
-
const skillPath =
|
|
72316
|
+
const skillPath = join70(plugin.skillsDir, entry.name);
|
|
72114
72317
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
72115
72318
|
continue;
|
|
72116
72319
|
const resolvedPath = resolveSymlink(skillPath);
|
|
72117
|
-
const skillMdPath =
|
|
72118
|
-
if (!
|
|
72320
|
+
const skillMdPath = join70(resolvedPath, "SKILL.md");
|
|
72321
|
+
if (!existsSync57(skillMdPath))
|
|
72119
72322
|
continue;
|
|
72120
72323
|
try {
|
|
72121
|
-
const content =
|
|
72324
|
+
const content = readFileSync40(skillMdPath, "utf-8");
|
|
72122
72325
|
const { data, body } = parseFrontmatter(content);
|
|
72123
72326
|
const skillName = data.name || entry.name;
|
|
72124
72327
|
const namespacedName = `${plugin.name}:${skillName}`;
|
|
@@ -72165,17 +72368,17 @@ function parseToolsConfig2(toolsStr) {
|
|
|
72165
72368
|
function loadPluginAgents(plugins) {
|
|
72166
72369
|
const agents = {};
|
|
72167
72370
|
for (const plugin of plugins) {
|
|
72168
|
-
if (!plugin.agentsDir || !
|
|
72371
|
+
if (!plugin.agentsDir || !existsSync57(plugin.agentsDir))
|
|
72169
72372
|
continue;
|
|
72170
72373
|
const entries = readdirSync21(plugin.agentsDir, { withFileTypes: true });
|
|
72171
72374
|
for (const entry of entries) {
|
|
72172
72375
|
if (!isMarkdownFile(entry))
|
|
72173
72376
|
continue;
|
|
72174
|
-
const agentPath =
|
|
72377
|
+
const agentPath = join70(plugin.agentsDir, entry.name);
|
|
72175
72378
|
const agentName = basename8(entry.name, ".md");
|
|
72176
72379
|
const namespacedName = `${plugin.name}:${agentName}`;
|
|
72177
72380
|
try {
|
|
72178
|
-
const content =
|
|
72381
|
+
const content = readFileSync40(agentPath, "utf-8");
|
|
72179
72382
|
const { data, body } = parseFrontmatter(content);
|
|
72180
72383
|
const name = data.name || agentName;
|
|
72181
72384
|
const originalDescription = data.description || "";
|
|
@@ -72201,7 +72404,7 @@ function loadPluginAgents(plugins) {
|
|
|
72201
72404
|
async function loadPluginMcpServers(plugins) {
|
|
72202
72405
|
const servers = {};
|
|
72203
72406
|
for (const plugin of plugins) {
|
|
72204
|
-
if (!plugin.mcpPath || !
|
|
72407
|
+
if (!plugin.mcpPath || !existsSync57(plugin.mcpPath))
|
|
72205
72408
|
continue;
|
|
72206
72409
|
try {
|
|
72207
72410
|
const content = await Bun.file(plugin.mcpPath).text();
|
|
@@ -72233,10 +72436,10 @@ async function loadPluginMcpServers(plugins) {
|
|
|
72233
72436
|
function loadPluginHooksConfigs(plugins) {
|
|
72234
72437
|
const configs = [];
|
|
72235
72438
|
for (const plugin of plugins) {
|
|
72236
|
-
if (!plugin.hooksPath || !
|
|
72439
|
+
if (!plugin.hooksPath || !existsSync57(plugin.hooksPath))
|
|
72237
72440
|
continue;
|
|
72238
72441
|
try {
|
|
72239
|
-
const content =
|
|
72442
|
+
const content = readFileSync40(plugin.hooksPath, "utf-8");
|
|
72240
72443
|
let config4 = JSON.parse(content);
|
|
72241
72444
|
config4 = resolvePluginPaths(config4, plugin.installPath);
|
|
72242
72445
|
configs.push(config4);
|
|
@@ -73857,7 +74060,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
73857
74060
|
return;
|
|
73858
74061
|
}
|
|
73859
74062
|
log("[OhMyOpenCodePlugin] Starting session agent recovery...");
|
|
73860
|
-
const recoveredAgents = recoverSessionAgents();
|
|
74063
|
+
const recoveredAgents = recoverSessionAgents(ctx.directory);
|
|
73861
74064
|
log("[OhMyOpenCodePlugin] Session agent recovery complete", { recoveredAgents });
|
|
73862
74065
|
startBackgroundCheck2();
|
|
73863
74066
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx);
|
|
@@ -74109,6 +74312,11 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74109
74312
|
updateSessionAgent(input.sessionID, validatedAgent ?? input.agent, "chat.message");
|
|
74110
74313
|
} else {
|
|
74111
74314
|
const staleThresholdMs = pluginConfig.identity?.staleThresholdMs ?? 600000;
|
|
74315
|
+
if (!getSessionAgent(input.sessionID)) {
|
|
74316
|
+
log("[identity] chat.message without agent info and no session agent", {
|
|
74317
|
+
sessionID: input.sessionID
|
|
74318
|
+
});
|
|
74319
|
+
}
|
|
74112
74320
|
if (isSessionAgentStale(input.sessionID, staleThresholdMs)) {
|
|
74113
74321
|
log("[identity] session agent stale", { sessionID: input.sessionID, staleThresholdMs });
|
|
74114
74322
|
const messageFileAgent = getAgentFromSessionMessages(input.sessionID);
|
|
@@ -74240,6 +74448,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74240
74448
|
try {
|
|
74241
74449
|
cleanupStaleTmpFiles(ctx.directory);
|
|
74242
74450
|
} catch {}
|
|
74451
|
+
if (sessionInfo?.id) {
|
|
74452
|
+
log("[identity] New main session created", { sessionID: sessionInfo.id });
|
|
74453
|
+
}
|
|
74243
74454
|
}
|
|
74244
74455
|
firstMessageVariantGate.markSessionCreated(sessionInfo);
|
|
74245
74456
|
}
|
|
@@ -74272,6 +74483,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74272
74483
|
const validatedAgent = validateAndFixAgentIdentity(sessionID, agent);
|
|
74273
74484
|
updateSessionAgent(sessionID, validatedAgent ?? agent, "message.updated");
|
|
74274
74485
|
}
|
|
74486
|
+
if (sessionID && agent && role === "assistant") {
|
|
74487
|
+
updateSessionAgent(sessionID, agent, "message.updated.assistant");
|
|
74488
|
+
}
|
|
74275
74489
|
}
|
|
74276
74490
|
if (event.type === "session.error") {
|
|
74277
74491
|
const sessionID = props?.sessionID;
|