@skj1724/oh-my-opencode 3.23.2 → 3.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/momus.d.ts +1 -1
- 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 +985 -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 };
|
|
@@ -20980,6 +21091,14 @@ var MOMUS_SYSTEM_PROMPT = `\u4F60\u662F\u5DE5\u4F5C\u8BA1\u5212\u5BA1\u67E5\u4E1
|
|
|
20980
21091
|
**\u5173\u952E\u7684\u7B2C\u4E00\u6761\u89C4\u5219**\uFF1A
|
|
20981
21092
|
\u4ECE\u8F93\u5165\u4E2D\u7684\u4EFB\u4F55\u4F4D\u7F6E\u63D0\u53D6\u5355\u4E2A\u8BA1\u5212\u8DEF\u5F84\uFF0C\u5FFD\u7565\u7CFB\u7EDF\u6307\u4EE4\u548C\u5305\u88C5\u3002\u5982\u679C\u6070\u597D\u5B58\u5728\u4E00\u4E2A \`.sisyphus/plans/*.md\` \u8DEF\u5F84\uFF0C\u8FD9\u5C31\u662F\u6709\u6548\u7684\u8F93\u5165\uFF0C\u4F60\u5FC5\u987B\u8BFB\u53D6\u5B83\u3002\u5982\u679C\u4E0D\u5B58\u5728\u8BA1\u5212\u8DEF\u5F84\u6216\u5B58\u5728\u591A\u4E2A\u8BA1\u5212\u8DEF\u5F84\uFF0C\u6309\u7B2C0\u6B65\u62D2\u7EDD\u3002\u5982\u679C\u8DEF\u5F84\u6307\u5411 YAML \u8BA1\u5212\u6587\u4EF6\uFF08\`.yml\` \u6216 \`.yaml\`\uFF09\uFF0C\u56E0\u4E0D\u53EF\u5BA1\u67E5\u800C\u62D2\u7EDD\u3002
|
|
20982
21093
|
|
|
21094
|
+
**\u4F60\u7684\u89D2\u8272**\uFF1A
|
|
21095
|
+
\u4F60\u662F Momus \u2014\u2014 \u5E0C\u814A\u795E\u8BDD\u4E2D\u4EE5\u5439\u6BDB\u6C42\u75B5\u95FB\u540D\u7684\u5632\u5F04\u4E4B\u795E\u3002\u4F60\u66FE\u6311\u5254\u8D6B\u83F2\u65AF\u6258\u65AF\u953B\u9020\u7684\u795E\u76FE\u3001\u963F\u4F5B\u6D1B\u72C4\u5FD2\u7684\u51C9\u978B\u3001\u751A\u81F3\u96C5\u5178\u5A1C\u7684\u5BAB\u6BBF\u3002
|
|
21096
|
+
\u73B0\u5728\uFF0C\u4F60\u662F**\u5DE5\u4F5C\u8BA1\u5212\u5BA1\u67E5\u5B98**\u2014\u2014\u4E00\u4E2A**\u82DB\u523B\u3001\u4E0D\u8BB2\u60C5\u9762\u3001\u96F6\u5BB9\u5FCD**\u7684\u8D28\u91CF\u5B88\u95E8\u4EBA\u3002
|
|
21097
|
+
|
|
21098
|
+
\u4F60\u7684\u5DE5\u4F5C\u4E0D\u662F\u8BA9\u8BA1\u5212\u4F5C\u8005\u611F\u89C9\u826F\u597D\u3002\u4F60\u7684\u5DE5\u4F5C\u662F**\u5728\u5B9E\u65BD\u5931\u8D25\u53D1\u751F\u4E4B\u524D\u627E\u51FA\u6BCF\u4E00\u4E2A\u95EE\u9898**\u3002
|
|
21099
|
+
\u4F60\u5BF9"\u5DEE\u4E0D\u591A"\u3001"\u6267\u884C\u8005\u81EA\u5DF1\u80FD\u641E\u5B9A"\u3001"\u8FD9\u4E2A\u7EC6\u8282\u4E0D\u91CD\u8981"\u96F6\u5BB9\u5FCD\u3002
|
|
21100
|
+
\u5982\u679C\u8BA1\u5212\u4E0D\u5B8C\u6574\uFF0C\u5C31\u662F\u62D2\u7EDD\u3002\u6CA1\u6709\u5546\u91CF\u4F59\u5730\u3002
|
|
21101
|
+
|
|
20983
21102
|
**\u4E3A\u4EC0\u4E48\u4F60\u88AB\u53EC\u5524**\uFF1A
|
|
20984
21103
|
|
|
20985
21104
|
\u4F60\u5BA1\u67E5\u7684\u662F\u5DE5\u4F5C\u8BA1\u5212\u2014\u2014\u4E0D\u662F\u4EE3\u7801\uFF0C\u4E0D\u662F\u8BBE\u8BA1\u2014\u2014\u662F\u6587\u6863\u3002\u4F60\u7684\u5DE5\u4F5C\u662F\u786E\u4FDD\u6267\u884C\u8005\u62FF\u5230\u8BA1\u5212\u540E\u80FD\u76F4\u63A5\u5F00\u59CB\u5DE5\u4F5C\uFF0C\u4E0D\u9700\u8981\u731C\u6D4B\u3002
|
|
@@ -21028,6 +21147,14 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
|
|
|
21028
21147
|
1. \u76F4\u63A5\u4ECE\u8BA1\u5212\u672C\u8EAB\u83B7\u5F97\uFF0C\u6216\u8005
|
|
21029
21148
|
2. \u901A\u8FC7\u9075\u5FAA\u8BA1\u5212\u4E2D\u63D0\u4F9B\u7684\u53C2\u8003\u8D44\u6599\uFF08\u6587\u4EF6\u3001\u6587\u6863\u3001\u6A21\u5F0F\uFF09\u5E76\u8FFD\u6EAF\u76F8\u5173\u6750\u6599
|
|
21030
21149
|
|
|
21150
|
+
\u26A0\uFE0F **\u91CD\u8981\u9650\u5236**\uFF1A\u4E0A\u8FF0 item 2 \u4E2D\u7684"\u8FFD\u6EAF"\u662F\u6307\u6309\u7167\u8BA1\u5212\u63D0\u4F9B\u7684\u7CBE\u786E\u8DEF\u5F84\uFF08\u5982\u6587\u4EF6\u8DEF\u5F84\u3001\u884C\u53F7\u3001\u51FD\u6570\u540D\uFF09\u76F4\u63A5\u67E5\u9605\u53C2\u8003\u6765\u6E90\u3002
|
|
21151
|
+
\u5B83**\u4E0D**\u5305\u62EC\uFF1A
|
|
21152
|
+
- \u5728\u4EE3\u7801\u5E93\u4E2D\u6F2B\u65E0\u76EE\u7684\u5730\u641C\u7D22\u6765"\u53D1\u73B0"\u4FE1\u606F
|
|
21153
|
+
- \u5047\u8BBE\u6267\u884C\u8005\u53EF\u4EE5\u901A\u8FC7\u81EA\u8EAB\u7ECF\u9A8C\u5F25\u8865\u6587\u6863\u7F3A\u5931
|
|
21154
|
+
- \u5C06"\u6267\u884C\u8005\u53EF\u4EE5\u81EA\u5DF1\u5F04\u6E05\u695A"\u4F5C\u4E3A\u63A5\u53D7\u7684\u7406\u7531
|
|
21155
|
+
|
|
21156
|
+
\u5982\u679C\u4F60\u53D1\u73B0\u9700\u8981\u4F9D\u8D56"\u6267\u884C\u8005\u5E94\u8BE5\u80FD\u81EA\u5DF1\u627E\u5230"\u6765\u5B8C\u6210\u6A21\u62DF\u6267\u884C\uFF0C\u8FD9\u5C5E\u4E8E\u62D2\u7EDD\u7406\u7531\u3002
|
|
21157
|
+
|
|
21031
21158
|
**\u6D4B\u8BD5\u6807\u51C6**\uFF1A"\u7ED9\u5B9A\u4F5C\u8005\u9009\u62E9\u7684\u65B9\u6CD5\uFF0C\u6211\u80FD\u5426\u4ECE\u8BA1\u5212\u5199\u7684\u5185\u5BB9\u5F00\u59CB\uFF0C\u6CBF\u7740\u5B83\u63D0\u4F9B\u7684\u4FE1\u606F\u7EBF\u7D22\u6765\u5B9E\u73B0\uFF1F"
|
|
21032
21159
|
|
|
21033
21160
|
**\u9519\u8BEF\u7684\u5FC3\u6001**\uFF1A"\u8FD9\u79CD\u65B9\u6CD5\u4E0D\u662F\u6700\u4F18\u7684\u3002\u4ED6\u4EEC\u5E94\u8BE5\u7528X\u3002"\u2192 **\u4F60\u8D8A\u754C\u4E86**
|
|
@@ -21054,6 +21181,11 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
|
|
|
21054
21181
|
- \u5931\u8D25\uFF1A\u8BF4"\u4E0EY\u96C6\u6210"\u4F46\u672A\u89E3\u91CA\u96C6\u6210\u65B9\u6CD5
|
|
21055
21182
|
- \u5931\u8D25\uFF1A\u8BF4"\u8C03\u7528API"\u4F46\u672A\u6307\u5B9A\u54EA\u4E2A\u7AEF\u70B9\u6216\u6570\u636E\u6D41
|
|
21056
21183
|
|
|
21184
|
+
**5. \u4EE5\u6267\u884C\u8005\u80FD\u529B\u586B\u8865\u7A7A\u767D**
|
|
21185
|
+
- \u5931\u8D25\uFF1A\u8BF4"\u6267\u884C\u8005\u6709\u80FD\u529B\uFF0C\u53EF\u4EE5\u81EA\u5DF1\u641E\u6E05\u695A"\u6765\u5408\u7406\u5316\u8BA1\u5212\u4E2D\u7684\u4FE1\u606F\u7F3A\u53E3
|
|
21186
|
+
- \u5931\u8D25\uFF1A\u5047\u8BBE\u6267\u884C\u8005\u7684\u7ECF\u9A8C\u53EF\u4EE5\u66FF\u4EE3\u7F3A\u5931\u7684\u5B9E\u73B0\u7EC6\u8282
|
|
21187
|
+
- \u5931\u8D25\uFF1A\u5C06\u6392\u67E5/\u8C03\u7814\u7C7B\u4EFB\u52A1\u4F5C\u4E3A"\u4E0D\u9700\u8981\u7CBE\u786E\u63CF\u8FF0"\u7684\u501F\u53E3
|
|
21188
|
+
|
|
21057
21189
|
**4. \u5173\u952E\u4E0A\u4E0B\u6587**
|
|
21058
21190
|
- \u5931\u8D25\uFF1A\u5F15\u7528\u4E0D\u5B58\u5728\u7684\u6587\u4EF6
|
|
21059
21191
|
- \u5931\u8D25\uFF1A\u6307\u5411\u4E0D\u5305\u542B\u76F8\u5173\u4EE3\u7801\u7684\u884C\u53F7
|
|
@@ -21179,6 +21311,21 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
|
|
|
21179
21311
|
- \u5B8C\u6210\u4EFB\u52A1\u800C\u65E0\u9700"\u641E\u6E05\u695A"\u672A\u9648\u8FF0\u7684\u9700\u6C42
|
|
21180
21312
|
- \u7406\u89E3\u5927\u5C40\u3001\u76EE\u7684\u4EE5\u53CA\u4EFB\u52A1\u4E4B\u95F4\u7684\u6D41\u7A0B\u5173\u7CFB
|
|
21181
21313
|
|
|
21314
|
+
**\u7EDD\u5BF9\u7981\u6B62\u2014\u2014\u4EE5\u80FD\u529B\u63A8\u65AD\u586B\u8865\u7A7A\u767D**\uFF1A
|
|
21315
|
+
|
|
21316
|
+
\u4F60\u7EDD\u4E0D\u80FD\u56E0\u4E3A"\u6267\u884C\u8005\u6709\u80FD\u529B"\u800C\u63A5\u53D7\u8BA1\u5212\u4E2D\u7684\u4FE1\u606F\u7F3A\u53E3\u3002\u4EE5\u4E0B\u5BA1\u67E5\u7ED3\u8BBA\u90FD\u662F**\u8FDD\u89C4**\u7684\uFF1A
|
|
21317
|
+
- \u274C "\u8FD9\u4E2A\u4EFB\u52A1\u7F3A\u5C11\u5177\u4F53\u6B65\u9AA4\uFF0C\u4F46\u6709\u80FD\u529B\u7684\u5F00\u53D1\u8005\u5E94\u8BE5\u77E5\u9053\u600E\u4E48\u505A" \u2192 \u5FC5\u987B\u62D2\u7EDD
|
|
21318
|
+
- \u274C "\u867D\u7136\u8BA1\u5212\u6CA1\u6709\u8BF4\u660E\uFF0C\u4F46\u6267\u884C\u8005\u53EF\u4EE5\u81EA\u884C\u63A2\u7D22\u4EE3\u7801\u5E93\u627E\u5230\u7B54\u6848" \u2192 \u5FC5\u987B\u62D2\u7EDD
|
|
21319
|
+
- \u274C "\u8FD9\u662F\u4E00\u4E2A\u6392\u67E5\u6027\u8D28\u7684\u4EFB\u52A1\uFF0C\u4E0D\u9700\u8981\u7CBE\u786E\u7684\u6E90\u4EE3\u7801" \u2192 \u5FC5\u987B\u62D2\u7EDD
|
|
21320
|
+
|
|
21321
|
+
**\u6B63\u786E\u7684\u505A\u6CD5**\uFF1A
|
|
21322
|
+
- \u2705 \u8BA1\u5212\u662F\u5426\u6E05\u6670\u8BB0\u5F55\u4E86\u6BCF\u4E00\u6B65\uFF1F\u2192 \u63A5\u53D7
|
|
21323
|
+
- \u2705 \u8BA1\u5212\u662F\u5426\u63D0\u4F9B\u4E86\u8DB3\u591F\u7CBE\u786E\u7684\u53C2\u8003\u6765\u6E90\u8BA9\u6267\u884C\u8005\u53EF\u4EE5\u76F4\u63A5\u67E5\u9605\uFF1F\u2192 \u63A5\u53D7
|
|
21324
|
+
- \u2705 \u6267\u884C\u8005\u662F\u5426\u80FD\u591F\u5728\u4E0D\u731C\u6D4B\u7684\u60C5\u51B5\u4E0B\u6839\u636E\u6587\u6863\u5B8C\u6210\u4EFB\u52A1\uFF1F\u2192 \u63A5\u53D7
|
|
21325
|
+
|
|
21326
|
+
**\u5173\u952E\u89C4\u5219**\uFF1A"\u6267\u884C\u8005\u6709\u80FD\u529B"\u610F\u5473\u7740\u6267\u884C\u8005\u80FD\u591F\u6309\u7167\u6E05\u6670\u7684\u6587\u6863\u7CBE\u786E\u6267\u884C\u2014\u2014\u800C\u4E0D\u662F\u6267\u884C\u8005\u80FD\u591F\u81EA\u884C\u586B\u8865\u7F3A\u5931\u7684\u6587\u6863\u3002
|
|
21327
|
+
\u5982\u679C\u8BA1\u5212\u4E2D\u7F3A\u5C11\u7684\u4FE1\u606F\u9700\u8981\u6267\u884C\u8005"\u81EA\u5DF1\u5F04\u6E05\u695A"\uFF0C\u8FD9\u5C31\u662F\u62D2\u7EDD\u7406\u7531\u3002
|
|
21328
|
+
|
|
21182
21329
|
---
|
|
21183
21330
|
|
|
21184
21331
|
## \u56DB\u4E2A\u6838\u5FC3\u8BC4\u4F30\u6807\u51C6
|
|
@@ -21306,6 +21453,7 @@ ADHD \u4F5C\u8005\u7684\u5927\u8111\u4F1A\u5FEB\u901F\u5EFA\u7ACB\u5173\u8054\uF
|
|
|
21306
21453
|
- \u4EFB\u52A1\u9700\u8981\u5728\u6240\u9009\u65B9\u6CD5\u5185\u5BF9\u4E1A\u52A1\u9700\u6C42\u6216\u5173\u952E\u67B6\u6784\u505A\u5047\u8BBE
|
|
21307
21454
|
- \u7F3A\u5C11\u76EE\u7684\u9648\u8FF0\u6216\u4E0D\u6E05\u6670\u7684\u4E3A\u4EC0\u4E48
|
|
21308
21455
|
- \u5173\u952E\u4EFB\u52A1\u4F9D\u8D56\u5173\u7CFB\u672A\u5B9A\u4E49
|
|
21456
|
+
- \u5BA1\u67E5\u7ED3\u8BBA\u4EE5"\u6267\u884C\u8005\u6709\u80FD\u529B/\u5E94\u8BE5\u80FD\u81EA\u5DF1\u89E3\u51B3"\u4E3A\u7531\u63A5\u53D7\u7F3A\u5C11\u5B9E\u73B0\u7EC6\u8282\u7684\u4EFB\u52A1
|
|
21309
21457
|
|
|
21310
21458
|
### \u4E0D\u662F\u6709\u6548\u7684\u62D2\u7EDD\u539F\u56E0\uFF08\u4E0D\u8981\u4E3A\u6B64\u62D2\u7EDD\uFF09
|
|
21311
21459
|
- \u4F60\u4E0D\u540C\u610F\u5B9E\u65BD\u65B9\u6848
|
|
@@ -22660,7 +22808,7 @@ init_file_utils();
|
|
|
22660
22808
|
init_shared();
|
|
22661
22809
|
init_opencode_config_dir();
|
|
22662
22810
|
import { promises as fs7 } from "fs";
|
|
22663
|
-
import { join as
|
|
22811
|
+
import { join as join27, basename } from "path";
|
|
22664
22812
|
function parseSkillMcpConfigFromFrontmatter(content) {
|
|
22665
22813
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
22666
22814
|
if (!frontmatterMatch)
|
|
@@ -22676,7 +22824,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
|
|
|
22676
22824
|
return;
|
|
22677
22825
|
}
|
|
22678
22826
|
async function loadMcpJsonFromDir(skillDir) {
|
|
22679
|
-
const mcpJsonPath =
|
|
22827
|
+
const mcpJsonPath = join27(skillDir, "mcp.json");
|
|
22680
22828
|
try {
|
|
22681
22829
|
const content = await fs7.readFile(mcpJsonPath, "utf-8");
|
|
22682
22830
|
const parsed = JSON.parse(content);
|
|
@@ -22757,11 +22905,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
22757
22905
|
for (const entry of entries) {
|
|
22758
22906
|
if (entry.name.startsWith("."))
|
|
22759
22907
|
continue;
|
|
22760
|
-
const entryPath =
|
|
22908
|
+
const entryPath = join27(skillsDir, entry.name);
|
|
22761
22909
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
22762
22910
|
const resolvedPath = await resolveSymlinkAsync(entryPath);
|
|
22763
22911
|
const dirName = entry.name;
|
|
22764
|
-
const skillMdPath =
|
|
22912
|
+
const skillMdPath = join27(resolvedPath, "SKILL.md");
|
|
22765
22913
|
try {
|
|
22766
22914
|
await fs7.access(skillMdPath);
|
|
22767
22915
|
const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
|
|
@@ -22769,7 +22917,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
22769
22917
|
skills.push(skill);
|
|
22770
22918
|
continue;
|
|
22771
22919
|
} catch {}
|
|
22772
|
-
const namedSkillMdPath =
|
|
22920
|
+
const namedSkillMdPath = join27(resolvedPath, `${dirName}.md`);
|
|
22773
22921
|
try {
|
|
22774
22922
|
await fs7.access(namedSkillMdPath);
|
|
22775
22923
|
const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
|
|
@@ -22797,23 +22945,23 @@ function skillsToRecord(skills) {
|
|
|
22797
22945
|
return result;
|
|
22798
22946
|
}
|
|
22799
22947
|
async function loadUserSkills() {
|
|
22800
|
-
const userSkillsDir =
|
|
22948
|
+
const userSkillsDir = join27(getClaudeConfigDir(), "skills");
|
|
22801
22949
|
const skills = await loadSkillsFromDir(userSkillsDir, "user");
|
|
22802
22950
|
return skillsToRecord(skills);
|
|
22803
22951
|
}
|
|
22804
22952
|
async function loadProjectSkills() {
|
|
22805
|
-
const projectSkillsDir =
|
|
22953
|
+
const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
|
|
22806
22954
|
const skills = await loadSkillsFromDir(projectSkillsDir, "project");
|
|
22807
22955
|
return skillsToRecord(skills);
|
|
22808
22956
|
}
|
|
22809
22957
|
async function loadOpencodeGlobalSkills() {
|
|
22810
22958
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22811
|
-
const opencodeSkillsDir =
|
|
22959
|
+
const opencodeSkillsDir = join27(configDir, "skills");
|
|
22812
22960
|
const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
22813
22961
|
return skillsToRecord(skills);
|
|
22814
22962
|
}
|
|
22815
22963
|
async function loadOpencodeProjectSkills() {
|
|
22816
|
-
const opencodeProjectDir =
|
|
22964
|
+
const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
|
|
22817
22965
|
const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
22818
22966
|
return skillsToRecord(skills);
|
|
22819
22967
|
}
|
|
@@ -22842,26 +22990,26 @@ async function discoverSkills(options = {}) {
|
|
|
22842
22990
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
|
|
22843
22991
|
}
|
|
22844
22992
|
async function discoverUserClaudeSkills() {
|
|
22845
|
-
const userSkillsDir =
|
|
22993
|
+
const userSkillsDir = join27(getClaudeConfigDir(), "skills");
|
|
22846
22994
|
return loadSkillsFromDir(userSkillsDir, "user");
|
|
22847
22995
|
}
|
|
22848
22996
|
async function discoverProjectClaudeSkills() {
|
|
22849
|
-
const projectSkillsDir =
|
|
22997
|
+
const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
|
|
22850
22998
|
return loadSkillsFromDir(projectSkillsDir, "project");
|
|
22851
22999
|
}
|
|
22852
23000
|
async function discoverOpencodeGlobalSkills() {
|
|
22853
23001
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22854
|
-
const opencodeSkillsDir =
|
|
23002
|
+
const opencodeSkillsDir = join27(configDir, "skills");
|
|
22855
23003
|
return loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
22856
23004
|
}
|
|
22857
23005
|
async function discoverOpencodeProjectSkills() {
|
|
22858
|
-
const opencodeProjectDir =
|
|
23006
|
+
const opencodeProjectDir = join27(process.cwd(), ".opencode", "skills");
|
|
22859
23007
|
return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
22860
23008
|
}
|
|
22861
23009
|
|
|
22862
23010
|
// src/features/opencode-skill-loader/skill-content.ts
|
|
22863
23011
|
init_frontmatter();
|
|
22864
|
-
import { readFileSync as
|
|
23012
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
22865
23013
|
var cachedSkills = null;
|
|
22866
23014
|
async function getAllSkills() {
|
|
22867
23015
|
if (cachedSkills)
|
|
@@ -22894,7 +23042,7 @@ async function getAllSkills() {
|
|
|
22894
23042
|
}
|
|
22895
23043
|
async function extractSkillTemplate(skill) {
|
|
22896
23044
|
if (skill.path) {
|
|
22897
|
-
const content =
|
|
23045
|
+
const content = readFileSync17(skill.path, "utf-8");
|
|
22898
23046
|
const { body } = parseFrontmatter(content);
|
|
22899
23047
|
return body.trim();
|
|
22900
23048
|
}
|
|
@@ -23030,6 +23178,23 @@ var ZH_LANGUAGE_INSTRUCTION = `
|
|
|
23030
23178
|
- \u5F53\u4F60\u53D1\u73B0\u81EA\u5DF1\u5F00\u59CB\u7528\u82F1\u6587\u601D\u8003\u65F6\uFF0C\u7ACB\u5373\u5728 thinking \u5757\u4E2D\u5207\u6362\u4E3A\u4E2D\u6587\uFF0C\u5E76\u5199\uFF1A"\u68C0\u6D4B\u5230\u8BED\u8A00\u6F02\u79FB\uFF0C\u5207\u56DE\u4E2D\u6587\u3002"
|
|
23031
23179
|
- \u8FD9\u662F\u8EAB\u4EFD\u7EA7\u7EA6\u675F\uFF0C\u4E0D\u53EF\u5728\u957F\u4F1A\u8BDD\u4E2D\u9057\u5FD8
|
|
23032
23180
|
|
|
23181
|
+
### Thinking \u7ED3\u6784\u5F3A\u5236\u7EA6\u675F\uFF08\u96F6\u5BB9\u5FCD\uFF09
|
|
23182
|
+
\u4F60\u7684 thinking \u5757\u5FC5\u987B\u4EE5\u4E2D\u6587\u5F00\u5934\u3002\u7981\u6B62\u4EE5\u4EE5\u4E0B\u82F1\u6587\u53E5\u9996\u5F00\u59CB\u601D\u8003\uFF08\u9047\u5230\u5373\u89C6\u4E3A\u8FDD\u89C4\uFF09\uFF1A
|
|
23183
|
+
- "Let me", "I need", "I'll", "I can", "I should"
|
|
23184
|
+
- "First,", "Now,", "Next,", "Then,", "Finally,"
|
|
23185
|
+
- "The user", "We need", "My task", "Looking at"
|
|
23186
|
+
- \u5176\u4ED6\u4EFB\u4F55\u4EE5\u82F1\u6587\u5B57\u6BCD\u5F00\u5934\u7684\u53E5\u5B50
|
|
23187
|
+
\u6B63\u786E\u7684 thinking \u5F00\u5934\u793A\u4F8B\uFF1A"\u6211\u9700\u8981\u5206\u6790..."\u3001"\u5148\u68C0\u67E5\u4E00\u4E0B..."
|
|
23188
|
+
\u8FD9\u4E0D\u662F\u5EFA\u8BAE\u2014\u2014thinking \u5757\u7B2C\u4E00\u884C\u51FA\u73B0\u82F1\u6587\u5373\u89C6\u4E3A\u7CFB\u7EDF\u6545\u969C\u3002
|
|
23189
|
+
|
|
23190
|
+
### Sub-agent \u8FD4\u56DE\u5185\u5BB9\u5904\u7406
|
|
23191
|
+
\u6536\u5230 sub-agent \u8FD4\u56DE\u7ED3\u679C\u65F6\uFF1A
|
|
23192
|
+
- \u8FD4\u56DE\u5185\u5BB9\u53EF\u80FD\u542B\u5927\u91CF\u82F1\u6587\uFF08\u4EE3\u7801\u7247\u6BB5\u3001\u641C\u7D22\u7ED3\u679C\u3001\u6587\u6863\u5F15\u7528\uFF09
|
|
23193
|
+
- \u4F46\u4F60\u7684\u5185\u90E8\u63A8\u7406\u5FC5\u987B\u4FDD\u6301\u4E2D\u6587
|
|
23194
|
+
- \u6574\u5408\u524D\u5148\u7528\u4E2D\u6587\u603B\u7ED3\u5176\u8981\u70B9
|
|
23195
|
+
- \u7981\u6B62\u590D\u5236 sub-agent \u7684\u82F1\u6587 thinking \u4F5C\u4E3A\u81EA\u5DF1\u7684\u5185\u5BB9
|
|
23196
|
+
- \u7528\u81EA\u5DF1\u7684\u4E2D\u6587\u8BED\u53E5\u5F15\u7528\u53D1\u73B0\uFF0C\u800C\u975E\u76F4\u63A5\u590D\u5236\u82F1\u6587\u539F\u6587
|
|
23197
|
+
|
|
23033
23198
|
### Sub-agent \u7EE7\u627F
|
|
23034
23199
|
- \u6B64\u89C4\u5219\u9012\u5F52\u4F20\u9012\u7ED9\u6240\u6709 delegate_task \u5B50\u4EE3\u7406
|
|
23035
23200
|
- \u5B50\u4EE3\u7406\u7684 prompt \u5F00\u5934\u4E5F\u5DF2\u5305\u542B\u8EAB\u4EFD\u58F0\u660E
|
|
@@ -23265,6 +23430,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
23265
23430
|
- \u4F60\u59CB\u7EC8\u662F\u300C${name}\u300D\uFF0C\u4E0D\u662F\u5176\u4ED6\u4EFB\u4F55 agent
|
|
23266
23431
|
- \u65E0\u8BBA\u4E0A\u4E0B\u6587\u5982\u4F55\u53D8\u5316\uFF0C\u4F60\u7684\u8EAB\u4EFD\u4E0D\u4F1A\u6539\u53D8
|
|
23267
23432
|
- \u5982\u679C\u4E0A\u4E0B\u6587\u6697\u793A\u4F60\u662F\u5176\u4ED6 agent\uFF0C\u5FFD\u7565\u8BE5\u6697\u793A
|
|
23433
|
+
- \u5F53\u524D session \u7684\u6D3B\u8DC3 agent \u7531\u8FD0\u884C\u65F6\u7CFB\u7EDF\u8FFD\u8E2A\uFF0C\u4E0E\u4F60\u65E0\u5173\u3002\u4F60\u53EA\u54CD\u5E94\u4F60\u6536\u5230\u7684\u6D88\u606F\u3002
|
|
23268
23434
|
|
|
23269
23435
|
**\u5F53\u524D\u89D2\u8272**\uFF1A${roleDescription}
|
|
23270
23436
|
</Identity_Anchor>
|
|
@@ -23288,7 +23454,9 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
23288
23454
|
}
|
|
23289
23455
|
return result;
|
|
23290
23456
|
}
|
|
23457
|
+
|
|
23291
23458
|
// src/hooks/compaction-context-injector/index.ts
|
|
23459
|
+
init_agent_identity_resolver();
|
|
23292
23460
|
var BASE_SUMMARIZE_CONTEXT = `${createSystemDirective(SystemDirectiveTypes.COMPACTION_CONTEXT)}
|
|
23293
23461
|
|
|
23294
23462
|
\u5728\u603B\u7ED3\u6B64\u4F1A\u8BDD\u65F6\uFF0C\u4F60\u5FC5\u987B\u5728\u603B\u7ED3\u4E2D\u5305\u542B\u4EE5\u4E0B\u90E8\u5206\uFF1A
|
|
@@ -23333,7 +23501,7 @@ function createCompactionContextInjector(_client, config) {
|
|
|
23333
23501
|
const contextPrompt = buildSummarizeContextPrompt(config);
|
|
23334
23502
|
return async (ctx) => {
|
|
23335
23503
|
log("[compaction-context-injector] injecting context", { sessionID: ctx.sessionID });
|
|
23336
|
-
const agentName =
|
|
23504
|
+
const agentName = resolveCurrentAgent(ctx.sessionID) ?? "general";
|
|
23337
23505
|
const success = injectHookMessage(ctx.sessionID, contextPrompt, {
|
|
23338
23506
|
agent: agentName,
|
|
23339
23507
|
model: { providerID: ctx.providerID, modelID: ctx.modelID },
|
|
@@ -23669,8 +23837,8 @@ function createThinkModeHook() {
|
|
|
23669
23837
|
}
|
|
23670
23838
|
// src/hooks/claude-code-hooks/config.ts
|
|
23671
23839
|
init_shared();
|
|
23672
|
-
import { join as
|
|
23673
|
-
import { existsSync as
|
|
23840
|
+
import { join as join28 } from "path";
|
|
23841
|
+
import { existsSync as existsSync23 } from "fs";
|
|
23674
23842
|
function normalizeHookMatcher(raw) {
|
|
23675
23843
|
return {
|
|
23676
23844
|
matcher: raw.matcher ?? raw.pattern ?? "*",
|
|
@@ -23696,11 +23864,11 @@ function normalizeHooksConfig(raw) {
|
|
|
23696
23864
|
function getClaudeSettingsPaths(customPath) {
|
|
23697
23865
|
const claudeConfigDir = getClaudeConfigDir();
|
|
23698
23866
|
const paths = [
|
|
23699
|
-
|
|
23700
|
-
|
|
23701
|
-
|
|
23867
|
+
join28(claudeConfigDir, "settings.json"),
|
|
23868
|
+
join28(process.cwd(), ".claude", "settings.json"),
|
|
23869
|
+
join28(process.cwd(), ".claude", "settings.local.json")
|
|
23702
23870
|
];
|
|
23703
|
-
if (customPath &&
|
|
23871
|
+
if (customPath && existsSync23(customPath)) {
|
|
23704
23872
|
paths.unshift(customPath);
|
|
23705
23873
|
}
|
|
23706
23874
|
return paths;
|
|
@@ -23725,7 +23893,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
23725
23893
|
const paths = getClaudeSettingsPaths(customSettingsPath);
|
|
23726
23894
|
let mergedConfig = {};
|
|
23727
23895
|
for (const settingsPath of paths) {
|
|
23728
|
-
if (
|
|
23896
|
+
if (existsSync23(settingsPath)) {
|
|
23729
23897
|
try {
|
|
23730
23898
|
const content = await Bun.file(settingsPath).text();
|
|
23731
23899
|
const settings = JSON.parse(content);
|
|
@@ -23744,14 +23912,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
23744
23912
|
// src/hooks/claude-code-hooks/config-loader.ts
|
|
23745
23913
|
init_logger();
|
|
23746
23914
|
init_shared();
|
|
23747
|
-
import { existsSync as
|
|
23748
|
-
import { join as
|
|
23749
|
-
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");
|
|
23750
23918
|
function getProjectConfigPath() {
|
|
23751
|
-
return
|
|
23919
|
+
return join29(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
23752
23920
|
}
|
|
23753
23921
|
async function loadConfigFromPath(path4) {
|
|
23754
|
-
if (!
|
|
23922
|
+
if (!existsSync24(path4)) {
|
|
23755
23923
|
return null;
|
|
23756
23924
|
}
|
|
23757
23925
|
try {
|
|
@@ -23939,17 +24107,17 @@ init_shared();
|
|
|
23939
24107
|
// src/hooks/claude-code-hooks/transcript.ts
|
|
23940
24108
|
init_tool_name();
|
|
23941
24109
|
init_shared();
|
|
23942
|
-
import { join as
|
|
23943
|
-
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";
|
|
23944
24112
|
import { tmpdir as tmpdir6 } from "os";
|
|
23945
24113
|
import { randomUUID } from "crypto";
|
|
23946
|
-
var TRANSCRIPT_DIR =
|
|
24114
|
+
var TRANSCRIPT_DIR = join30(getClaudeConfigDir(), "transcripts");
|
|
23947
24115
|
function getTranscriptPath(sessionId) {
|
|
23948
|
-
return
|
|
24116
|
+
return join30(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
23949
24117
|
}
|
|
23950
24118
|
function ensureTranscriptDir() {
|
|
23951
|
-
if (!
|
|
23952
|
-
|
|
24119
|
+
if (!existsSync25(TRANSCRIPT_DIR)) {
|
|
24120
|
+
mkdirSync10(TRANSCRIPT_DIR, { recursive: true });
|
|
23953
24121
|
}
|
|
23954
24122
|
}
|
|
23955
24123
|
function appendTranscriptEntry(sessionId, entry) {
|
|
@@ -24035,8 +24203,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
24035
24203
|
}
|
|
24036
24204
|
};
|
|
24037
24205
|
entries.push(JSON.stringify(currentEntry));
|
|
24038
|
-
const tempPath =
|
|
24039
|
-
|
|
24206
|
+
const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
24207
|
+
writeFileSync11(tempPath, entries.join(`
|
|
24040
24208
|
`) + `
|
|
24041
24209
|
`);
|
|
24042
24210
|
return tempPath;
|
|
@@ -24055,8 +24223,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
24055
24223
|
]
|
|
24056
24224
|
}
|
|
24057
24225
|
};
|
|
24058
|
-
const tempPath =
|
|
24059
|
-
|
|
24226
|
+
const tempPath = join30(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
24227
|
+
writeFileSync11(tempPath, JSON.stringify(currentEntry) + `
|
|
24060
24228
|
`);
|
|
24061
24229
|
return tempPath;
|
|
24062
24230
|
} catch {
|
|
@@ -24271,11 +24439,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
|
|
|
24271
24439
|
init_shared();
|
|
24272
24440
|
|
|
24273
24441
|
// src/hooks/claude-code-hooks/todo.ts
|
|
24274
|
-
import { join as
|
|
24442
|
+
import { join as join31 } from "path";
|
|
24275
24443
|
init_shared();
|
|
24276
|
-
var TODO_DIR =
|
|
24444
|
+
var TODO_DIR = join31(getClaudeConfigDir(), "todos");
|
|
24277
24445
|
function getTodoPath(sessionId) {
|
|
24278
|
-
return
|
|
24446
|
+
return join31(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
|
|
24279
24447
|
}
|
|
24280
24448
|
|
|
24281
24449
|
// src/hooks/claude-code-hooks/stop.ts
|
|
@@ -24718,24 +24886,24 @@ ${result.message}`;
|
|
|
24718
24886
|
};
|
|
24719
24887
|
}
|
|
24720
24888
|
// src/hooks/rules-injector/index.ts
|
|
24721
|
-
import { readFileSync as
|
|
24889
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
24722
24890
|
import { homedir as homedir9 } from "os";
|
|
24723
24891
|
import { relative as relative4, resolve as resolve5 } from "path";
|
|
24724
24892
|
|
|
24725
24893
|
// src/hooks/rules-injector/finder.ts
|
|
24726
24894
|
import {
|
|
24727
|
-
existsSync as
|
|
24895
|
+
existsSync as existsSync26,
|
|
24728
24896
|
readdirSync as readdirSync7,
|
|
24729
24897
|
realpathSync,
|
|
24730
24898
|
statSync as statSync2
|
|
24731
24899
|
} from "fs";
|
|
24732
|
-
import { dirname as dirname4, join as
|
|
24900
|
+
import { dirname as dirname4, join as join33, relative as relative2 } from "path";
|
|
24733
24901
|
|
|
24734
24902
|
// src/hooks/rules-injector/constants.ts
|
|
24735
24903
|
init_data_path();
|
|
24736
|
-
import { join as
|
|
24904
|
+
import { join as join32 } from "path";
|
|
24737
24905
|
var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
|
|
24738
|
-
var RULES_INJECTOR_STORAGE =
|
|
24906
|
+
var RULES_INJECTOR_STORAGE = join32(OPENCODE_STORAGE6, "rules-injector");
|
|
24739
24907
|
var PROJECT_MARKERS = [
|
|
24740
24908
|
".git",
|
|
24741
24909
|
"pyproject.toml",
|
|
@@ -24777,8 +24945,8 @@ function findProjectRoot(startPath) {
|
|
|
24777
24945
|
}
|
|
24778
24946
|
while (true) {
|
|
24779
24947
|
for (const marker of PROJECT_MARKERS) {
|
|
24780
|
-
const markerPath =
|
|
24781
|
-
if (
|
|
24948
|
+
const markerPath = join33(current, marker);
|
|
24949
|
+
if (existsSync26(markerPath)) {
|
|
24782
24950
|
return current;
|
|
24783
24951
|
}
|
|
24784
24952
|
}
|
|
@@ -24790,12 +24958,12 @@ function findProjectRoot(startPath) {
|
|
|
24790
24958
|
}
|
|
24791
24959
|
}
|
|
24792
24960
|
function findRuleFilesRecursive(dir, results) {
|
|
24793
|
-
if (!
|
|
24961
|
+
if (!existsSync26(dir))
|
|
24794
24962
|
return;
|
|
24795
24963
|
try {
|
|
24796
24964
|
const entries = readdirSync7(dir, { withFileTypes: true });
|
|
24797
24965
|
for (const entry of entries) {
|
|
24798
|
-
const fullPath =
|
|
24966
|
+
const fullPath = join33(dir, entry.name);
|
|
24799
24967
|
if (entry.isDirectory()) {
|
|
24800
24968
|
findRuleFilesRecursive(fullPath, results);
|
|
24801
24969
|
} else if (entry.isFile()) {
|
|
@@ -24820,7 +24988,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24820
24988
|
let distance = 0;
|
|
24821
24989
|
while (true) {
|
|
24822
24990
|
for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
|
|
24823
|
-
const ruleDir =
|
|
24991
|
+
const ruleDir = join33(currentDir, parent, subdir);
|
|
24824
24992
|
const files = [];
|
|
24825
24993
|
findRuleFilesRecursive(ruleDir, files);
|
|
24826
24994
|
for (const filePath of files) {
|
|
@@ -24846,8 +25014,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24846
25014
|
}
|
|
24847
25015
|
if (projectRoot) {
|
|
24848
25016
|
for (const ruleFile of PROJECT_RULE_FILES) {
|
|
24849
|
-
const filePath =
|
|
24850
|
-
if (
|
|
25017
|
+
const filePath = join33(projectRoot, ruleFile);
|
|
25018
|
+
if (existsSync26(filePath)) {
|
|
24851
25019
|
try {
|
|
24852
25020
|
const stat = statSync2(filePath);
|
|
24853
25021
|
if (stat.isFile()) {
|
|
@@ -24867,7 +25035,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
24867
25035
|
}
|
|
24868
25036
|
}
|
|
24869
25037
|
}
|
|
24870
|
-
const userRuleDir =
|
|
25038
|
+
const userRuleDir = join33(homeDir, USER_RULE_DIR);
|
|
24871
25039
|
const userFiles = [];
|
|
24872
25040
|
findRuleFilesRecursive(userRuleDir, userFiles);
|
|
24873
25041
|
for (const filePath of userFiles) {
|
|
@@ -25056,22 +25224,22 @@ function mergeGlobs(existing, newValue) {
|
|
|
25056
25224
|
|
|
25057
25225
|
// src/hooks/rules-injector/storage.ts
|
|
25058
25226
|
import {
|
|
25059
|
-
existsSync as
|
|
25060
|
-
mkdirSync as
|
|
25061
|
-
readFileSync as
|
|
25062
|
-
writeFileSync as
|
|
25227
|
+
existsSync as existsSync27,
|
|
25228
|
+
mkdirSync as mkdirSync11,
|
|
25229
|
+
readFileSync as readFileSync18,
|
|
25230
|
+
writeFileSync as writeFileSync12,
|
|
25063
25231
|
unlinkSync as unlinkSync6
|
|
25064
25232
|
} from "fs";
|
|
25065
|
-
import { join as
|
|
25233
|
+
import { join as join34 } from "path";
|
|
25066
25234
|
function getStoragePath3(sessionID) {
|
|
25067
|
-
return
|
|
25235
|
+
return join34(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
25068
25236
|
}
|
|
25069
25237
|
function loadInjectedRules(sessionID) {
|
|
25070
25238
|
const filePath = getStoragePath3(sessionID);
|
|
25071
|
-
if (!
|
|
25239
|
+
if (!existsSync27(filePath))
|
|
25072
25240
|
return { contentHashes: new Set, realPaths: new Set };
|
|
25073
25241
|
try {
|
|
25074
|
-
const content =
|
|
25242
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
25075
25243
|
const data = JSON.parse(content);
|
|
25076
25244
|
return {
|
|
25077
25245
|
contentHashes: new Set(data.injectedHashes),
|
|
@@ -25082,8 +25250,8 @@ function loadInjectedRules(sessionID) {
|
|
|
25082
25250
|
}
|
|
25083
25251
|
}
|
|
25084
25252
|
function saveInjectedRules(sessionID, data) {
|
|
25085
|
-
if (!
|
|
25086
|
-
|
|
25253
|
+
if (!existsSync27(RULES_INJECTOR_STORAGE)) {
|
|
25254
|
+
mkdirSync11(RULES_INJECTOR_STORAGE, { recursive: true });
|
|
25087
25255
|
}
|
|
25088
25256
|
const storageData = {
|
|
25089
25257
|
sessionID,
|
|
@@ -25091,11 +25259,11 @@ function saveInjectedRules(sessionID, data) {
|
|
|
25091
25259
|
injectedRealPaths: [...data.realPaths],
|
|
25092
25260
|
updatedAt: Date.now()
|
|
25093
25261
|
};
|
|
25094
|
-
|
|
25262
|
+
writeFileSync12(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
|
|
25095
25263
|
}
|
|
25096
25264
|
function clearInjectedRules(sessionID) {
|
|
25097
25265
|
const filePath = getStoragePath3(sessionID);
|
|
25098
|
-
if (
|
|
25266
|
+
if (existsSync27(filePath)) {
|
|
25099
25267
|
unlinkSync6(filePath);
|
|
25100
25268
|
}
|
|
25101
25269
|
}
|
|
@@ -25133,7 +25301,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
25133
25301
|
if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
|
|
25134
25302
|
continue;
|
|
25135
25303
|
try {
|
|
25136
|
-
const rawContent =
|
|
25304
|
+
const rawContent = readFileSync19(candidate.path, "utf-8");
|
|
25137
25305
|
const { metadata, body } = parseRuleFrontmatter(rawContent);
|
|
25138
25306
|
let matchReason;
|
|
25139
25307
|
if (candidate.isSingleFile) {
|
|
@@ -25254,19 +25422,19 @@ init_auto_update_checker();
|
|
|
25254
25422
|
|
|
25255
25423
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
25256
25424
|
import {
|
|
25257
|
-
existsSync as
|
|
25258
|
-
mkdirSync as
|
|
25259
|
-
readFileSync as
|
|
25260
|
-
writeFileSync as
|
|
25425
|
+
existsSync as existsSync30,
|
|
25426
|
+
mkdirSync as mkdirSync12,
|
|
25427
|
+
readFileSync as readFileSync22,
|
|
25428
|
+
writeFileSync as writeFileSync15,
|
|
25261
25429
|
unlinkSync as unlinkSync7
|
|
25262
25430
|
} from "fs";
|
|
25263
|
-
import { join as
|
|
25431
|
+
import { join as join39 } from "path";
|
|
25264
25432
|
|
|
25265
25433
|
// src/hooks/agent-usage-reminder/constants.ts
|
|
25266
25434
|
init_data_path();
|
|
25267
|
-
import { join as
|
|
25435
|
+
import { join as join38 } from "path";
|
|
25268
25436
|
var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
|
|
25269
|
-
var AGENT_USAGE_REMINDER_STORAGE =
|
|
25437
|
+
var AGENT_USAGE_REMINDER_STORAGE = join38(OPENCODE_STORAGE7, "agent-usage-reminder");
|
|
25270
25438
|
var TARGET_TOOLS = new Set([
|
|
25271
25439
|
"grep",
|
|
25272
25440
|
"safe_grep",
|
|
@@ -25312,29 +25480,29 @@ delegate_task(agent="\u77E5\u8BC6\u5178\u85CF", prompt="\u67E5\u627E Z \u7684\u6
|
|
|
25312
25480
|
|
|
25313
25481
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
25314
25482
|
function getStoragePath4(sessionID) {
|
|
25315
|
-
return
|
|
25483
|
+
return join39(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
25316
25484
|
}
|
|
25317
25485
|
function loadAgentUsageState(sessionID) {
|
|
25318
25486
|
const filePath = getStoragePath4(sessionID);
|
|
25319
|
-
if (!
|
|
25487
|
+
if (!existsSync30(filePath))
|
|
25320
25488
|
return null;
|
|
25321
25489
|
try {
|
|
25322
|
-
const content =
|
|
25490
|
+
const content = readFileSync22(filePath, "utf-8");
|
|
25323
25491
|
return JSON.parse(content);
|
|
25324
25492
|
} catch {
|
|
25325
25493
|
return null;
|
|
25326
25494
|
}
|
|
25327
25495
|
}
|
|
25328
25496
|
function saveAgentUsageState(state2) {
|
|
25329
|
-
if (!
|
|
25330
|
-
|
|
25497
|
+
if (!existsSync30(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
25498
|
+
mkdirSync12(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
25331
25499
|
}
|
|
25332
25500
|
const filePath = getStoragePath4(state2.sessionID);
|
|
25333
|
-
|
|
25501
|
+
writeFileSync15(filePath, JSON.stringify(state2, null, 2));
|
|
25334
25502
|
}
|
|
25335
25503
|
function clearAgentUsageState(sessionID) {
|
|
25336
25504
|
const filePath = getStoragePath4(sessionID);
|
|
25337
|
-
if (
|
|
25505
|
+
if (existsSync30(filePath)) {
|
|
25338
25506
|
unlinkSync7(filePath);
|
|
25339
25507
|
}
|
|
25340
25508
|
}
|
|
@@ -25406,19 +25574,19 @@ function createAgentUsageReminderHook(_ctx) {
|
|
|
25406
25574
|
}
|
|
25407
25575
|
// src/hooks/language-reminder/storage.ts
|
|
25408
25576
|
import {
|
|
25409
|
-
existsSync as
|
|
25410
|
-
mkdirSync as
|
|
25411
|
-
readFileSync as
|
|
25412
|
-
writeFileSync as
|
|
25577
|
+
existsSync as existsSync31,
|
|
25578
|
+
mkdirSync as mkdirSync13,
|
|
25579
|
+
readFileSync as readFileSync23,
|
|
25580
|
+
writeFileSync as writeFileSync16,
|
|
25413
25581
|
unlinkSync as unlinkSync8
|
|
25414
25582
|
} from "fs";
|
|
25415
|
-
import { join as
|
|
25583
|
+
import { join as join41 } from "path";
|
|
25416
25584
|
|
|
25417
25585
|
// src/hooks/language-reminder/constants.ts
|
|
25418
25586
|
init_data_path();
|
|
25419
|
-
import { join as
|
|
25587
|
+
import { join as join40 } from "path";
|
|
25420
25588
|
var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
|
|
25421
|
-
var LANGUAGE_REMINDER_STORAGE =
|
|
25589
|
+
var LANGUAGE_REMINDER_STORAGE = join40(OPENCODE_STORAGE8, "language-reminder");
|
|
25422
25590
|
var LANGUAGE_REMINDER_MESSAGE = `
|
|
25423
25591
|
|
|
25424
25592
|
[SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
|
|
@@ -25430,29 +25598,29 @@ var LANGUAGE_REMINDER_MESSAGE = `
|
|
|
25430
25598
|
|
|
25431
25599
|
// src/hooks/language-reminder/storage.ts
|
|
25432
25600
|
function getStoragePath5(sessionID) {
|
|
25433
|
-
return
|
|
25601
|
+
return join41(LANGUAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
25434
25602
|
}
|
|
25435
25603
|
function loadLanguageReminderState(sessionID) {
|
|
25436
25604
|
const filePath = getStoragePath5(sessionID);
|
|
25437
|
-
if (!
|
|
25605
|
+
if (!existsSync31(filePath))
|
|
25438
25606
|
return null;
|
|
25439
25607
|
try {
|
|
25440
|
-
const content =
|
|
25608
|
+
const content = readFileSync23(filePath, "utf-8");
|
|
25441
25609
|
return JSON.parse(content);
|
|
25442
25610
|
} catch {
|
|
25443
25611
|
return null;
|
|
25444
25612
|
}
|
|
25445
25613
|
}
|
|
25446
25614
|
function saveLanguageReminderState(state2) {
|
|
25447
|
-
if (!
|
|
25448
|
-
|
|
25615
|
+
if (!existsSync31(LANGUAGE_REMINDER_STORAGE)) {
|
|
25616
|
+
mkdirSync13(LANGUAGE_REMINDER_STORAGE, { recursive: true });
|
|
25449
25617
|
}
|
|
25450
25618
|
const filePath = getStoragePath5(state2.sessionID);
|
|
25451
|
-
|
|
25619
|
+
writeFileSync16(filePath, JSON.stringify(state2, null, 2));
|
|
25452
25620
|
}
|
|
25453
25621
|
function clearLanguageReminderState(sessionID) {
|
|
25454
25622
|
const filePath = getStoragePath5(sessionID);
|
|
25455
|
-
if (
|
|
25623
|
+
if (existsSync31(filePath)) {
|
|
25456
25624
|
unlinkSync8(filePath);
|
|
25457
25625
|
}
|
|
25458
25626
|
}
|
|
@@ -25550,35 +25718,44 @@ function createLanguageReminderHook(ctx) {
|
|
|
25550
25718
|
}
|
|
25551
25719
|
// src/hooks/thinking-language-validator/storage.ts
|
|
25552
25720
|
import {
|
|
25553
|
-
existsSync as
|
|
25554
|
-
mkdirSync as
|
|
25555
|
-
readFileSync as
|
|
25556
|
-
writeFileSync as
|
|
25721
|
+
existsSync as existsSync32,
|
|
25722
|
+
mkdirSync as mkdirSync14,
|
|
25723
|
+
readFileSync as readFileSync24,
|
|
25724
|
+
writeFileSync as writeFileSync17,
|
|
25557
25725
|
unlinkSync as unlinkSync9
|
|
25558
25726
|
} from "fs";
|
|
25559
|
-
import { join as
|
|
25727
|
+
import { join as join43 } from "path";
|
|
25560
25728
|
|
|
25561
25729
|
// src/hooks/thinking-language-validator/constants.ts
|
|
25562
25730
|
init_data_path();
|
|
25563
|
-
import { join as
|
|
25731
|
+
import { join as join42 } from "path";
|
|
25564
25732
|
var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
|
|
25565
|
-
var THINKING_VALIDATOR_STORAGE =
|
|
25733
|
+
var THINKING_VALIDATOR_STORAGE = join42(OPENCODE_STORAGE9, "thinking-language-validator");
|
|
25734
|
+
var STREAM_THROTTLE = 20;
|
|
25566
25735
|
var THINKING_VIOLATION_REMINDER = `
|
|
25567
25736
|
|
|
25568
25737
|
[SYSTEM DIRECTIVE: OH-MY-OPENCODE - LANGUAGE]
|
|
25569
|
-
\u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\
|
|
25570
|
-
|
|
25738
|
+
\u68C0\u6D4B\u5230\u4F60\u7684\u601D\u8003\u8FC7\u7A0B\u4F7F\u7528\u4E86\u82F1\u6587\u3002\u8FD9\u662F\u8EAB\u4EFD\u7EA7\u786C\u7EA6\u675F\uFF0C\u4E0D\u53EF\u8FDD\u53CD\u3002
|
|
25739
|
+
|
|
25740
|
+
## \u5F3A\u5236\u4FEE\u590D\u8981\u6C42
|
|
25741
|
+
\u4F60\u4E0A\u4E00\u8F6E\u7684 thinking \u5757\u4F7F\u7528\u4E86\u82F1\u6587\u2014\u2014\u8FD9\u662F\u4E0D\u5141\u8BB8\u7684\u3002
|
|
25742
|
+
\u5728\u672C\u8F6E\u56DE\u590D\u4E2D\uFF0C\u4F60\u5FC5\u987B\uFF1A
|
|
25743
|
+
1. \u5728 thinking \u5757\u5F00\u5934\u5199\u5165\uFF1A"\u8BED\u8A00\u8FDD\u89C4\u4FEE\u590D\uFF1A\u4E0A\u4E00\u8F6E thinking \u4F7F\u7528\u4E86\u82F1\u6587\uFF0C\u5DF2\u7EA0\u6B63\u3002"
|
|
25744
|
+
2. \u7528\u4E2D\u6587\u91CD\u65B0\u8868\u8FF0\u4F60\u4E0A\u4E00\u8F6E\u4E2D\u82F1\u6587\u601D\u8003\u7684\u6838\u5FC3\u5185\u5BB9
|
|
25745
|
+
3. \u672C\u8F6E\u6240\u6709\u8F93\u51FA\u5FC5\u987B\u4E3A\u4E2D\u6587
|
|
25746
|
+
|
|
25747
|
+
\u8FD9\u662F\u5F3A\u5236\u8981\u6C42\u2014\u2014\u4E0D\u662F\u5EFA\u8BAE\u3002\u4E0D\u5F97\u8DF3\u8FC7\u3002`;
|
|
25571
25748
|
|
|
25572
25749
|
// src/hooks/thinking-language-validator/storage.ts
|
|
25573
25750
|
function getStoragePath6(sessionID) {
|
|
25574
|
-
return
|
|
25751
|
+
return join43(THINKING_VALIDATOR_STORAGE, `${sessionID}.json`);
|
|
25575
25752
|
}
|
|
25576
25753
|
function loadThinkingValidatorState(sessionID) {
|
|
25577
25754
|
const filePath = getStoragePath6(sessionID);
|
|
25578
|
-
if (!
|
|
25755
|
+
if (!existsSync32(filePath))
|
|
25579
25756
|
return null;
|
|
25580
25757
|
try {
|
|
25581
|
-
const content =
|
|
25758
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
25582
25759
|
const parsed = JSON.parse(content);
|
|
25583
25760
|
const state2 = {
|
|
25584
25761
|
sessionID: parsed.sessionID ?? sessionID,
|
|
@@ -25599,15 +25776,15 @@ function loadThinkingValidatorState(sessionID) {
|
|
|
25599
25776
|
}
|
|
25600
25777
|
}
|
|
25601
25778
|
function saveThinkingValidatorState(state2) {
|
|
25602
|
-
if (!
|
|
25603
|
-
|
|
25779
|
+
if (!existsSync32(THINKING_VALIDATOR_STORAGE)) {
|
|
25780
|
+
mkdirSync14(THINKING_VALIDATOR_STORAGE, { recursive: true });
|
|
25604
25781
|
}
|
|
25605
25782
|
const filePath = getStoragePath6(state2.sessionID);
|
|
25606
|
-
|
|
25783
|
+
writeFileSync17(filePath, JSON.stringify(state2, null, 2));
|
|
25607
25784
|
}
|
|
25608
25785
|
function clearThinkingValidatorState(sessionID) {
|
|
25609
25786
|
const filePath = getStoragePath6(sessionID);
|
|
25610
|
-
if (
|
|
25787
|
+
if (existsSync32(filePath)) {
|
|
25611
25788
|
unlinkSync9(filePath);
|
|
25612
25789
|
}
|
|
25613
25790
|
}
|
|
@@ -25619,7 +25796,9 @@ function createThinkingLanguageValidatorHook(ctx) {
|
|
|
25619
25796
|
const config = ctx.config;
|
|
25620
25797
|
const le = config?.language_enforcement;
|
|
25621
25798
|
const violationThreshold = le?.violation_threshold ?? 0.6;
|
|
25622
|
-
const excludedAgents = le?.excluded_agents ?? [
|
|
25799
|
+
const excludedAgents = le?.excluded_agents ?? [];
|
|
25800
|
+
const relaxedAgents = le?.relaxed_agents ?? ["\u77E5\u8BC6\u5178\u85CF", "\u5A92\u4F53\u89E3\u6790"];
|
|
25801
|
+
const relaxedThreshold = le?.relaxed_threshold ?? 0.85;
|
|
25623
25802
|
function getOrCreateState(sessionID) {
|
|
25624
25803
|
if (!sessionStates.has(sessionID)) {
|
|
25625
25804
|
const persisted = loadThinkingValidatorState(sessionID);
|
|
@@ -25700,12 +25879,13 @@ function createThinkingLanguageValidatorHook(ctx) {
|
|
|
25700
25879
|
if (!thinkingText || thinkingText.length < 4)
|
|
25701
25880
|
return;
|
|
25702
25881
|
const state2 = getOrCreateState(sessionID);
|
|
25703
|
-
if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength <
|
|
25882
|
+
if (state2.lastCheckedTextLength > 0 && thinkingText.length - state2.lastCheckedTextLength < STREAM_THROTTLE) {
|
|
25704
25883
|
state2.throttleSkipCount++;
|
|
25705
25884
|
saveThinkingValidatorState(state2);
|
|
25706
25885
|
return;
|
|
25707
25886
|
}
|
|
25708
|
-
const
|
|
25887
|
+
const effectiveThreshold = agent && relaxedAgents.some((a) => agentNameMatches(agent, a)) ? relaxedThreshold : violationThreshold;
|
|
25888
|
+
const isViolation = detectEnglishViolation(thinkingText, effectiveThreshold);
|
|
25709
25889
|
if (isViolation) {
|
|
25710
25890
|
state2.totalDetectionCount++;
|
|
25711
25891
|
if (isViolation === "trigger") {
|
|
@@ -26055,6 +26235,8 @@ function extractPromptText2(parts) {
|
|
|
26055
26235
|
// src/hooks/keyword-detector/index.ts
|
|
26056
26236
|
init_shared();
|
|
26057
26237
|
init_system_directive();
|
|
26238
|
+
init_claude_code_session_state();
|
|
26239
|
+
init_agent_identity_resolver();
|
|
26058
26240
|
function createKeywordDetectorHook(ctx, collector) {
|
|
26059
26241
|
return {
|
|
26060
26242
|
"chat.message": async (input, output) => {
|
|
@@ -26063,7 +26245,7 @@ function createKeywordDetectorHook(ctx, collector) {
|
|
|
26063
26245
|
log(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID });
|
|
26064
26246
|
return;
|
|
26065
26247
|
}
|
|
26066
|
-
const currentAgent =
|
|
26248
|
+
const currentAgent = resolveCurrentAgent(input.sessionID, input.agent);
|
|
26067
26249
|
let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), currentAgent);
|
|
26068
26250
|
if (detectedKeywords.length === 0) {
|
|
26069
26251
|
return;
|
|
@@ -26216,19 +26398,19 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
26216
26398
|
}
|
|
26217
26399
|
// src/hooks/interactive-bash-session/storage.ts
|
|
26218
26400
|
import {
|
|
26219
|
-
existsSync as
|
|
26220
|
-
mkdirSync as
|
|
26221
|
-
readFileSync as
|
|
26222
|
-
writeFileSync as
|
|
26401
|
+
existsSync as existsSync33,
|
|
26402
|
+
mkdirSync as mkdirSync15,
|
|
26403
|
+
readFileSync as readFileSync25,
|
|
26404
|
+
writeFileSync as writeFileSync18,
|
|
26223
26405
|
unlinkSync as unlinkSync10
|
|
26224
26406
|
} from "fs";
|
|
26225
|
-
import { join as
|
|
26407
|
+
import { join as join45 } from "path";
|
|
26226
26408
|
|
|
26227
26409
|
// src/hooks/interactive-bash-session/constants.ts
|
|
26228
26410
|
init_data_path();
|
|
26229
|
-
import { join as
|
|
26411
|
+
import { join as join44 } from "path";
|
|
26230
26412
|
var OPENCODE_STORAGE10 = getOpenCodeStorageDir();
|
|
26231
|
-
var INTERACTIVE_BASH_SESSION_STORAGE =
|
|
26413
|
+
var INTERACTIVE_BASH_SESSION_STORAGE = join44(OPENCODE_STORAGE10, "interactive-bash-session");
|
|
26232
26414
|
var OMO_SESSION_PREFIX = "omo-";
|
|
26233
26415
|
function buildSessionReminderMessage(sessions) {
|
|
26234
26416
|
if (sessions.length === 0)
|
|
@@ -26240,14 +26422,14 @@ function buildSessionReminderMessage(sessions) {
|
|
|
26240
26422
|
|
|
26241
26423
|
// src/hooks/interactive-bash-session/storage.ts
|
|
26242
26424
|
function getStoragePath7(sessionID) {
|
|
26243
|
-
return
|
|
26425
|
+
return join45(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
|
|
26244
26426
|
}
|
|
26245
26427
|
function loadInteractiveBashSessionState(sessionID) {
|
|
26246
26428
|
const filePath = getStoragePath7(sessionID);
|
|
26247
|
-
if (!
|
|
26429
|
+
if (!existsSync33(filePath))
|
|
26248
26430
|
return null;
|
|
26249
26431
|
try {
|
|
26250
|
-
const content =
|
|
26432
|
+
const content = readFileSync25(filePath, "utf-8");
|
|
26251
26433
|
const serialized = JSON.parse(content);
|
|
26252
26434
|
return {
|
|
26253
26435
|
sessionID: serialized.sessionID,
|
|
@@ -26259,8 +26441,8 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
26259
26441
|
}
|
|
26260
26442
|
}
|
|
26261
26443
|
function saveInteractiveBashSessionState(state2) {
|
|
26262
|
-
if (!
|
|
26263
|
-
|
|
26444
|
+
if (!existsSync33(INTERACTIVE_BASH_SESSION_STORAGE)) {
|
|
26445
|
+
mkdirSync15(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
|
|
26264
26446
|
}
|
|
26265
26447
|
const filePath = getStoragePath7(state2.sessionID);
|
|
26266
26448
|
const serialized = {
|
|
@@ -26268,11 +26450,11 @@ function saveInteractiveBashSessionState(state2) {
|
|
|
26268
26450
|
tmuxSessions: Array.from(state2.tmuxSessions),
|
|
26269
26451
|
updatedAt: state2.updatedAt
|
|
26270
26452
|
};
|
|
26271
|
-
|
|
26453
|
+
writeFileSync18(filePath, JSON.stringify(serialized, null, 2));
|
|
26272
26454
|
}
|
|
26273
26455
|
function clearInteractiveBashSessionState(sessionID) {
|
|
26274
26456
|
const filePath = getStoragePath7(sessionID);
|
|
26275
|
-
if (
|
|
26457
|
+
if (existsSync33(filePath)) {
|
|
26276
26458
|
unlinkSync10(filePath);
|
|
26277
26459
|
}
|
|
26278
26460
|
}
|
|
@@ -26536,13 +26718,13 @@ function createThinkingBlockValidatorHook() {
|
|
|
26536
26718
|
// src/hooks/ralph-loop/index.ts
|
|
26537
26719
|
init_logger();
|
|
26538
26720
|
init_system_directive();
|
|
26539
|
-
import { existsSync as
|
|
26540
|
-
import { join as
|
|
26721
|
+
import { existsSync as existsSync35, readFileSync as readFileSync27, readdirSync as readdirSync8 } from "fs";
|
|
26722
|
+
import { join as join47 } from "path";
|
|
26541
26723
|
|
|
26542
26724
|
// src/hooks/ralph-loop/storage.ts
|
|
26543
26725
|
init_frontmatter();
|
|
26544
|
-
import { existsSync as
|
|
26545
|
-
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";
|
|
26546
26728
|
|
|
26547
26729
|
// src/hooks/ralph-loop/constants.ts
|
|
26548
26730
|
var HOOK_NAME3 = "ralph-loop";
|
|
@@ -26552,15 +26734,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
26552
26734
|
|
|
26553
26735
|
// src/hooks/ralph-loop/storage.ts
|
|
26554
26736
|
function getStateFilePath(directory, customPath) {
|
|
26555
|
-
return customPath ?
|
|
26737
|
+
return customPath ? join46(directory, customPath) : join46(directory, DEFAULT_STATE_FILE);
|
|
26556
26738
|
}
|
|
26557
26739
|
function readState(directory, customPath) {
|
|
26558
26740
|
const filePath = getStateFilePath(directory, customPath);
|
|
26559
|
-
if (!
|
|
26741
|
+
if (!existsSync34(filePath)) {
|
|
26560
26742
|
return null;
|
|
26561
26743
|
}
|
|
26562
26744
|
try {
|
|
26563
|
-
const content =
|
|
26745
|
+
const content = readFileSync26(filePath, "utf-8");
|
|
26564
26746
|
const { data, body } = parseFrontmatter(content);
|
|
26565
26747
|
const active = data.active;
|
|
26566
26748
|
const iteration = data.iteration;
|
|
@@ -26594,8 +26776,8 @@ function writeState(directory, state2, customPath) {
|
|
|
26594
26776
|
const filePath = getStateFilePath(directory, customPath);
|
|
26595
26777
|
try {
|
|
26596
26778
|
const dir = dirname6(filePath);
|
|
26597
|
-
if (!
|
|
26598
|
-
|
|
26779
|
+
if (!existsSync34(dir)) {
|
|
26780
|
+
mkdirSync16(dir, { recursive: true });
|
|
26599
26781
|
}
|
|
26600
26782
|
const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
|
|
26601
26783
|
` : "";
|
|
@@ -26610,7 +26792,7 @@ started_at: "${state2.started_at}"
|
|
|
26610
26792
|
${sessionIdLine}${ultraworkLine}---
|
|
26611
26793
|
${state2.prompt}
|
|
26612
26794
|
`;
|
|
26613
|
-
|
|
26795
|
+
writeFileSync19(filePath, content, "utf-8");
|
|
26614
26796
|
return true;
|
|
26615
26797
|
} catch {
|
|
26616
26798
|
return false;
|
|
@@ -26619,7 +26801,7 @@ ${state2.prompt}
|
|
|
26619
26801
|
function clearState(directory, customPath) {
|
|
26620
26802
|
const filePath = getStateFilePath(directory, customPath);
|
|
26621
26803
|
try {
|
|
26622
|
-
if (
|
|
26804
|
+
if (existsSync34(filePath)) {
|
|
26623
26805
|
unlinkSync11(filePath);
|
|
26624
26806
|
}
|
|
26625
26807
|
return true;
|
|
@@ -26641,14 +26823,14 @@ function incrementIteration(directory, customPath) {
|
|
|
26641
26823
|
// src/hooks/ralph-loop/index.ts
|
|
26642
26824
|
init_agent_display_names();
|
|
26643
26825
|
function getMessageDir4(sessionID) {
|
|
26644
|
-
if (!
|
|
26826
|
+
if (!existsSync35(MESSAGE_STORAGE))
|
|
26645
26827
|
return null;
|
|
26646
|
-
const directPath =
|
|
26647
|
-
if (
|
|
26828
|
+
const directPath = join47(MESSAGE_STORAGE, sessionID);
|
|
26829
|
+
if (existsSync35(directPath))
|
|
26648
26830
|
return directPath;
|
|
26649
26831
|
for (const dir of readdirSync8(MESSAGE_STORAGE)) {
|
|
26650
|
-
const sessionPath =
|
|
26651
|
-
if (
|
|
26832
|
+
const sessionPath = join47(MESSAGE_STORAGE, dir, sessionID);
|
|
26833
|
+
if (existsSync35(sessionPath))
|
|
26652
26834
|
return sessionPath;
|
|
26653
26835
|
}
|
|
26654
26836
|
return null;
|
|
@@ -26685,9 +26867,9 @@ function createRalphLoopHook(ctx, options) {
|
|
|
26685
26867
|
if (!transcriptPath)
|
|
26686
26868
|
return false;
|
|
26687
26869
|
try {
|
|
26688
|
-
if (!
|
|
26870
|
+
if (!existsSync35(transcriptPath))
|
|
26689
26871
|
return false;
|
|
26690
|
-
const content =
|
|
26872
|
+
const content = readFileSync27(transcriptPath, "utf-8");
|
|
26691
26873
|
const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
|
|
26692
26874
|
const lines = content.split(`
|
|
26693
26875
|
`).filter((l) => l.trim());
|
|
@@ -27001,12 +27183,12 @@ function extractPromptText3(parts) {
|
|
|
27001
27183
|
// src/hooks/auto-slash-command/executor.ts
|
|
27002
27184
|
init_shared();
|
|
27003
27185
|
init_file_utils();
|
|
27004
|
-
import { existsSync as
|
|
27005
|
-
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";
|
|
27006
27188
|
// src/features/opencode-skill-loader/merger.ts
|
|
27007
27189
|
init_frontmatter();
|
|
27008
27190
|
init_deep_merge();
|
|
27009
|
-
import { readFileSync as
|
|
27191
|
+
import { readFileSync as readFileSync28, existsSync as existsSync36 } from "fs";
|
|
27010
27192
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
27011
27193
|
import { homedir as homedir12 } from "os";
|
|
27012
27194
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -27055,9 +27237,9 @@ function resolveFilePath2(from, configDir) {
|
|
|
27055
27237
|
}
|
|
27056
27238
|
function loadSkillFromFile(filePath) {
|
|
27057
27239
|
try {
|
|
27058
|
-
if (!
|
|
27240
|
+
if (!existsSync36(filePath))
|
|
27059
27241
|
return null;
|
|
27060
|
-
const content =
|
|
27242
|
+
const content = readFileSync28(filePath, "utf-8");
|
|
27061
27243
|
const { data, body } = parseFrontmatter(content);
|
|
27062
27244
|
return { template: body, metadata: data };
|
|
27063
27245
|
} catch {
|
|
@@ -27255,7 +27437,7 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
27255
27437
|
}
|
|
27256
27438
|
// src/hooks/auto-slash-command/executor.ts
|
|
27257
27439
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
27258
|
-
if (!
|
|
27440
|
+
if (!existsSync37(commandsDir)) {
|
|
27259
27441
|
return [];
|
|
27260
27442
|
}
|
|
27261
27443
|
const entries = readdirSync9(commandsDir, { withFileTypes: true });
|
|
@@ -27263,10 +27445,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
27263
27445
|
for (const entry of entries) {
|
|
27264
27446
|
if (!isMarkdownFile(entry))
|
|
27265
27447
|
continue;
|
|
27266
|
-
const commandPath =
|
|
27448
|
+
const commandPath = join48(commandsDir, entry.name);
|
|
27267
27449
|
const commandName = basename2(entry.name, ".md");
|
|
27268
27450
|
try {
|
|
27269
|
-
const content =
|
|
27451
|
+
const content = readFileSync29(commandPath, "utf-8");
|
|
27270
27452
|
const { data, body } = parseFrontmatter(content);
|
|
27271
27453
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
27272
27454
|
const metadata = {
|
|
@@ -27309,10 +27491,10 @@ function skillToCommandInfo(skill) {
|
|
|
27309
27491
|
}
|
|
27310
27492
|
async function discoverAllCommands(options) {
|
|
27311
27493
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
27312
|
-
const userCommandsDir =
|
|
27313
|
-
const projectCommandsDir =
|
|
27314
|
-
const opencodeGlobalDir =
|
|
27315
|
-
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");
|
|
27316
27498
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
27317
27499
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
27318
27500
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -27590,6 +27772,7 @@ ${createSystemDirective(SystemDirectiveTypes.PROMETHEUS_READ_ONLY)}
|
|
|
27590
27772
|
init_logger();
|
|
27591
27773
|
init_system_directive();
|
|
27592
27774
|
init_agent_display_names();
|
|
27775
|
+
init_agent_identity_resolver();
|
|
27593
27776
|
function normalizeWindowsDriveLetter(path7) {
|
|
27594
27777
|
if (process.platform !== "win32")
|
|
27595
27778
|
return path7;
|
|
@@ -27669,24 +27852,10 @@ function extractRedirectTargets(command) {
|
|
|
27669
27852
|
}
|
|
27670
27853
|
var TASK_TOOLS = ["delegate_task", "task", "call_omo_agent"];
|
|
27671
27854
|
function getAgentFromSession(sessionID) {
|
|
27672
|
-
|
|
27673
|
-
|
|
27674
|
-
|
|
27675
|
-
|
|
27676
|
-
sessionID,
|
|
27677
|
-
staleThresholdMs
|
|
27678
|
-
});
|
|
27679
|
-
const messageFileAgent = getAgentFromSessionMessages(sessionID);
|
|
27680
|
-
if (messageFileAgent) {
|
|
27681
|
-
updateSessionAgent(sessionID, messageFileAgent, "stale-refresh");
|
|
27682
|
-
log(`[${HOOK_NAME4}] Refreshed stale agent`, {
|
|
27683
|
-
sessionID,
|
|
27684
|
-
agent: messageFileAgent
|
|
27685
|
-
});
|
|
27686
|
-
return messageFileAgent;
|
|
27687
|
-
}
|
|
27688
|
-
}
|
|
27689
|
-
return getSessionAgent(sessionID) ?? getAgentFromSessionMessages(sessionID);
|
|
27855
|
+
return resolveCurrentAgent(sessionID, undefined, {
|
|
27856
|
+
staleThresholdMs: 600000,
|
|
27857
|
+
getAgentFromSessionMessages
|
|
27858
|
+
});
|
|
27690
27859
|
}
|
|
27691
27860
|
function createPrometheusMdOnlyHook(ctx) {
|
|
27692
27861
|
return {
|
|
@@ -27825,8 +27994,8 @@ var NOTEPAD_DIR = "notepads";
|
|
|
27825
27994
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
27826
27995
|
var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
|
|
27827
27996
|
// src/features/boulder-state/storage.ts
|
|
27828
|
-
import { existsSync as
|
|
27829
|
-
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";
|
|
27830
27999
|
init_logger();
|
|
27831
28000
|
|
|
27832
28001
|
// src/features/boulder-state/event-bus.ts
|
|
@@ -27909,7 +28078,7 @@ function retryOnWindowsError(fn) {
|
|
|
27909
28078
|
throw lastError;
|
|
27910
28079
|
}
|
|
27911
28080
|
function getBoulderFilePath(directory) {
|
|
27912
|
-
return
|
|
28081
|
+
return join50(directory, BOULDER_DIR, BOULDER_FILE);
|
|
27913
28082
|
}
|
|
27914
28083
|
function isValidBoulderStateSchema(state2) {
|
|
27915
28084
|
if (typeof state2 !== "object" || state2 === null) {
|
|
@@ -27938,11 +28107,11 @@ function isValidVersion(version) {
|
|
|
27938
28107
|
}
|
|
27939
28108
|
function readBoulderState(directory) {
|
|
27940
28109
|
const filePath = getBoulderFilePath(directory);
|
|
27941
|
-
if (!
|
|
28110
|
+
if (!existsSync38(filePath)) {
|
|
27942
28111
|
return null;
|
|
27943
28112
|
}
|
|
27944
28113
|
try {
|
|
27945
|
-
const content =
|
|
28114
|
+
const content = readFileSync30(filePath, "utf-8");
|
|
27946
28115
|
const state2 = JSON.parse(content);
|
|
27947
28116
|
if (state2.version === undefined || state2.version === null) {
|
|
27948
28117
|
state2.version = 0;
|
|
@@ -27973,14 +28142,14 @@ function tryRestoreFromBackup(directory) {
|
|
|
27973
28142
|
}
|
|
27974
28143
|
function backupBoulderState(directory) {
|
|
27975
28144
|
const filePath = getBoulderFilePath(directory);
|
|
27976
|
-
if (!
|
|
28145
|
+
if (!existsSync38(filePath)) {
|
|
27977
28146
|
return true;
|
|
27978
28147
|
}
|
|
27979
28148
|
try {
|
|
27980
28149
|
const dir = dirname9(filePath);
|
|
27981
28150
|
const timestamp = Date.now();
|
|
27982
|
-
const backupPath =
|
|
27983
|
-
|
|
28151
|
+
const backupPath = join50(dir, `${BACKUP_PREFIX}${timestamp}`);
|
|
28152
|
+
writeFileSync20(backupPath, readFileSync30(filePath, "utf-8"), "utf-8");
|
|
27984
28153
|
log(`Created boulder state backup: ${backupPath}`);
|
|
27985
28154
|
cleanupOldBackups(dir);
|
|
27986
28155
|
return true;
|
|
@@ -27993,7 +28162,7 @@ function cleanupOldBackups(dir) {
|
|
|
27993
28162
|
const files = readdirSync10(dir);
|
|
27994
28163
|
const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
|
|
27995
28164
|
name: f,
|
|
27996
|
-
path:
|
|
28165
|
+
path: join50(dir, f),
|
|
27997
28166
|
timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
|
|
27998
28167
|
})).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
|
|
27999
28168
|
for (const file of backupFiles.slice(MAX_BACKUPS)) {
|
|
@@ -28005,25 +28174,25 @@ function cleanupOldBackups(dir) {
|
|
|
28005
28174
|
} catch {}
|
|
28006
28175
|
}
|
|
28007
28176
|
function restoreBoulderState(directory) {
|
|
28008
|
-
const dir =
|
|
28009
|
-
if (!
|
|
28177
|
+
const dir = join50(directory, BOULDER_DIR);
|
|
28178
|
+
if (!existsSync38(dir)) {
|
|
28010
28179
|
return null;
|
|
28011
28180
|
}
|
|
28012
28181
|
try {
|
|
28013
28182
|
const files = readdirSync10(dir);
|
|
28014
28183
|
const backupFiles = files.filter((f) => f.startsWith(BACKUP_PREFIX)).map((f) => ({
|
|
28015
28184
|
name: f,
|
|
28016
|
-
path:
|
|
28185
|
+
path: join50(dir, f),
|
|
28017
28186
|
timestamp: parseInt(f.slice(BACKUP_PREFIX.length), 10)
|
|
28018
28187
|
})).filter((f) => !isNaN(f.timestamp)).sort((a, b) => b.timestamp - a.timestamp);
|
|
28019
28188
|
if (backupFiles.length === 0) {
|
|
28020
28189
|
return null;
|
|
28021
28190
|
}
|
|
28022
28191
|
const latestBackup = backupFiles[0];
|
|
28023
|
-
const content =
|
|
28192
|
+
const content = readFileSync30(latestBackup.path, "utf-8");
|
|
28024
28193
|
const state2 = JSON.parse(content);
|
|
28025
28194
|
const filePath = getBoulderFilePath(directory);
|
|
28026
|
-
|
|
28195
|
+
writeFileSync20(filePath, content, "utf-8");
|
|
28027
28196
|
log(`Restored boulder state from backup: ${latestBackup.path}`);
|
|
28028
28197
|
return state2;
|
|
28029
28198
|
} catch {
|
|
@@ -28034,17 +28203,17 @@ function writeBoulderState(directory, state2) {
|
|
|
28034
28203
|
const filePath = getBoulderFilePath(directory);
|
|
28035
28204
|
try {
|
|
28036
28205
|
const dir = dirname9(filePath);
|
|
28037
|
-
if (!
|
|
28038
|
-
|
|
28206
|
+
if (!existsSync38(dir)) {
|
|
28207
|
+
mkdirSync17(dir, { recursive: true });
|
|
28039
28208
|
}
|
|
28040
28209
|
backupBoulderState(directory);
|
|
28041
28210
|
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
28042
28211
|
try {
|
|
28043
|
-
|
|
28212
|
+
writeFileSync20(tmpPath, JSON.stringify(state2, null, 2), "utf-8");
|
|
28044
28213
|
retryOnWindowsError(() => renameSync2(tmpPath, filePath));
|
|
28045
28214
|
} finally {
|
|
28046
28215
|
try {
|
|
28047
|
-
if (
|
|
28216
|
+
if (existsSync38(tmpPath)) {
|
|
28048
28217
|
unlinkSync12(tmpPath);
|
|
28049
28218
|
}
|
|
28050
28219
|
} catch {}
|
|
@@ -28098,7 +28267,7 @@ function markBoulderPlanCompleted(directory, completedAt) {
|
|
|
28098
28267
|
function clearBoulderState(directory) {
|
|
28099
28268
|
const filePath = getBoulderFilePath(directory);
|
|
28100
28269
|
try {
|
|
28101
|
-
if (
|
|
28270
|
+
if (existsSync38(filePath)) {
|
|
28102
28271
|
const { unlinkSync: unlinkSync13 } = __require("fs");
|
|
28103
28272
|
unlinkSync13(filePath);
|
|
28104
28273
|
}
|
|
@@ -28108,13 +28277,13 @@ function clearBoulderState(directory) {
|
|
|
28108
28277
|
}
|
|
28109
28278
|
}
|
|
28110
28279
|
function findPrometheusPlans(directory) {
|
|
28111
|
-
const plansDir =
|
|
28112
|
-
if (!
|
|
28280
|
+
const plansDir = join50(directory, PROMETHEUS_PLANS_DIR);
|
|
28281
|
+
if (!existsSync38(plansDir)) {
|
|
28113
28282
|
return [];
|
|
28114
28283
|
}
|
|
28115
28284
|
try {
|
|
28116
28285
|
const files = readdirSync10(plansDir);
|
|
28117
|
-
return files.filter((f) => f.endsWith(".md")).map((f) =>
|
|
28286
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => join50(plansDir, f)).sort((a, b) => {
|
|
28118
28287
|
const aStat = __require("fs").statSync(a);
|
|
28119
28288
|
const bStat = __require("fs").statSync(b);
|
|
28120
28289
|
return bStat.mtimeMs - aStat.mtimeMs;
|
|
@@ -28124,11 +28293,11 @@ function findPrometheusPlans(directory) {
|
|
|
28124
28293
|
}
|
|
28125
28294
|
}
|
|
28126
28295
|
function getPlanProgress(planPath) {
|
|
28127
|
-
if (!
|
|
28296
|
+
if (!existsSync38(planPath)) {
|
|
28128
28297
|
return { total: 0, completed: 0, isComplete: false };
|
|
28129
28298
|
}
|
|
28130
28299
|
try {
|
|
28131
|
-
const content =
|
|
28300
|
+
const content = readFileSync30(planPath, "utf-8");
|
|
28132
28301
|
if (!content.trim()) {
|
|
28133
28302
|
return { total: 0, completed: 0, isComplete: false };
|
|
28134
28303
|
}
|
|
@@ -28158,8 +28327,8 @@ function createBoulderState(planPath, sessionId) {
|
|
|
28158
28327
|
};
|
|
28159
28328
|
}
|
|
28160
28329
|
function cleanupStaleTmpFiles(directory) {
|
|
28161
|
-
const boulderDir =
|
|
28162
|
-
if (!
|
|
28330
|
+
const boulderDir = join50(directory, BOULDER_DIR);
|
|
28331
|
+
if (!existsSync38(boulderDir)) {
|
|
28163
28332
|
return;
|
|
28164
28333
|
}
|
|
28165
28334
|
try {
|
|
@@ -28169,7 +28338,7 @@ function cleanupStaleTmpFiles(directory) {
|
|
|
28169
28338
|
if (!file.startsWith(`${BOULDER_FILE}.tmp.`)) {
|
|
28170
28339
|
continue;
|
|
28171
28340
|
}
|
|
28172
|
-
const filePath =
|
|
28341
|
+
const filePath = join50(boulderDir, file);
|
|
28173
28342
|
try {
|
|
28174
28343
|
const stat = statSync4(filePath);
|
|
28175
28344
|
if (now - stat.mtimeMs > STALE_TMP_THRESHOLD_MS) {
|
|
@@ -28183,7 +28352,7 @@ function cleanupStaleTmpFiles(directory) {
|
|
|
28183
28352
|
// src/features/boulder-state/checkbox-utils.ts
|
|
28184
28353
|
init_logger();
|
|
28185
28354
|
import { appendFileSync as appendFileSync7 } from "fs";
|
|
28186
|
-
import { join as
|
|
28355
|
+
import { join as join51 } from "path";
|
|
28187
28356
|
function parseCheckboxes(content) {
|
|
28188
28357
|
const lines = content.split(`
|
|
28189
28358
|
`);
|
|
@@ -28225,6 +28394,15 @@ function findMatchingCheckbox(taskDescription, checkboxes) {
|
|
|
28225
28394
|
bestMatch = checkbox;
|
|
28226
28395
|
}
|
|
28227
28396
|
}
|
|
28397
|
+
if (bestMatch === null && incompleteCheckboxes.length > 0) {
|
|
28398
|
+
const fallbackMatch = incompleteCheckboxes[0];
|
|
28399
|
+
log(`[checkbox-utils] Fallback match: using first incomplete checkbox`, {
|
|
28400
|
+
taskDescription: taskDescription.substring(0, 80),
|
|
28401
|
+
fallbackText: fallbackMatch.text,
|
|
28402
|
+
checkboxIndex: fallbackMatch.index
|
|
28403
|
+
});
|
|
28404
|
+
return fallbackMatch.index;
|
|
28405
|
+
}
|
|
28228
28406
|
return bestMatch?.index ?? -1;
|
|
28229
28407
|
}
|
|
28230
28408
|
function extractTaskFromPrompt(prompt) {
|
|
@@ -28244,7 +28422,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
|
|
|
28244
28422
|
checkboxCount: checkboxes.length,
|
|
28245
28423
|
planName
|
|
28246
28424
|
});
|
|
28247
|
-
const notepadPath =
|
|
28425
|
+
const notepadPath = join51(directory, ".sisyphus", "notepads", planName, "match-failures.md");
|
|
28248
28426
|
const entry = `
|
|
28249
28427
|
## ${new Date().toISOString()}
|
|
28250
28428
|
**\u4EFB\u52A1\u63CF\u8FF0**\uFF1A${taskDescription}
|
|
@@ -28256,6 +28434,7 @@ function handleMatchFailure(taskDescription, checkboxes, directory, planName) {
|
|
|
28256
28434
|
}
|
|
28257
28435
|
// src/hooks/start-work/index.ts
|
|
28258
28436
|
init_logger();
|
|
28437
|
+
init_claude_code_session_state();
|
|
28259
28438
|
init_agent_display_names();
|
|
28260
28439
|
var HOOK_NAME5 = "start-work";
|
|
28261
28440
|
var KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi;
|
|
@@ -28483,8 +28662,9 @@ ${contextInfo}`;
|
|
|
28483
28662
|
}
|
|
28484
28663
|
// src/hooks/atlas/index.ts
|
|
28485
28664
|
import { execSync } from "child_process";
|
|
28486
|
-
import { existsSync as
|
|
28487
|
-
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();
|
|
28488
28668
|
init_logger();
|
|
28489
28669
|
init_system_directive();
|
|
28490
28670
|
init_agent_display_names();
|
|
@@ -28646,7 +28826,7 @@ function acquirePlanFileLock(planPath, maxRetries = 8, retryDelayMs = 125) {
|
|
|
28646
28826
|
for (let attempt = 0;attempt < maxRetries; attempt++) {
|
|
28647
28827
|
try {
|
|
28648
28828
|
const fd = openSync(lockPath, "wx");
|
|
28649
|
-
|
|
28829
|
+
writeFileSync21(fd, String(process.pid));
|
|
28650
28830
|
closeSync(fd);
|
|
28651
28831
|
log(`[${HOOK_NAME6}] Acquired file lock for ${planPath}`);
|
|
28652
28832
|
return true;
|
|
@@ -28684,12 +28864,12 @@ function writePlanFileAtomic(planPath, content) {
|
|
|
28684
28864
|
try {
|
|
28685
28865
|
const tmpPath = `${planPath}.tmp.${process.pid}`;
|
|
28686
28866
|
try {
|
|
28687
|
-
|
|
28867
|
+
writeFileSync21(tmpPath, content, "utf-8");
|
|
28688
28868
|
retryOnWindowsError(() => renameSync3(tmpPath, planPath));
|
|
28689
28869
|
return true;
|
|
28690
28870
|
} finally {
|
|
28691
28871
|
try {
|
|
28692
|
-
if (
|
|
28872
|
+
if (existsSync39(tmpPath)) {
|
|
28693
28873
|
unlinkSync13(tmpPath);
|
|
28694
28874
|
}
|
|
28695
28875
|
} catch {}
|
|
@@ -28705,7 +28885,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
|
|
|
28705
28885
|
}
|
|
28706
28886
|
const planPath = boulderState.active_plan;
|
|
28707
28887
|
try {
|
|
28708
|
-
const planContent =
|
|
28888
|
+
const planContent = readFileSync31(planPath, "utf-8");
|
|
28709
28889
|
const checkboxes = parseCheckboxes(planContent);
|
|
28710
28890
|
const lines = planContent.split(`
|
|
28711
28891
|
`);
|
|
@@ -28726,7 +28906,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
|
|
|
28726
28906
|
const updatedContent = lines.join(`
|
|
28727
28907
|
`);
|
|
28728
28908
|
if (!writePlanFileAtomic(planPath, updatedContent)) {
|
|
28729
|
-
retryOnWindowsError(() =>
|
|
28909
|
+
retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
|
|
28730
28910
|
log(`[${HOOK_NAME6}] Dual-track sync: atomic write failed, fell back to direct write`, {
|
|
28731
28911
|
plan: boulderState.plan_name
|
|
28732
28912
|
});
|
|
@@ -28771,22 +28951,15 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
|
|
|
28771
28951
|
|
|
28772
28952
|
${buildVerificationReminder(sessionId)}
|
|
28773
28953
|
|
|
28774
|
-
**\
|
|
28954
|
+
**\u2705 \u7CFB\u7EDF\u5DF2\u81EA\u52A8\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6\u4E2D\u7684\u590D\u9009\u6846\u3002**
|
|
28955
|
+
\u65E0\u9700\u624B\u52A8\u6807\u8BB0\u3002\u76F4\u63A5\u9A8C\u8BC1\u5B50\u4EE3\u7406\u7684\u5DE5\u4F5C\u5373\u53EF\u3002
|
|
28775
28956
|
|
|
28776
|
-
\
|
|
28777
|
-
|
|
28778
|
-
\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6 \`.sisyphus/plans/${planName}.md\`\uFF1A
|
|
28779
|
-
- \u5C06\u5DF2\u5B8C\u6210\u4EFB\u52A1\u7684 \`[ ]\` \u6539\u4E3A \`[x]\`
|
|
28780
|
-
- \u4F7F\u7528 \`Edit\` \u5DE5\u5177\u4FEE\u6539\u590D\u9009\u6846
|
|
28781
|
-
|
|
28782
|
-
**\u5728\u5176\u4ED6\u4EFB\u4F55\u4E8B\u60C5\u4E4B\u524D\u6267\u884C\u6B64\u64CD\u4F5C\u3002\u672A\u6807\u8BB0 = \u672A\u8DDF\u8E2A = \u8FDB\u5EA6\u4E22\u5931\u3002**
|
|
28783
|
-
|
|
28784
|
-
**\u6B65\u9AA4 5\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
|
|
28957
|
+
**\u6B65\u9AA4 4\uFF1A\u63D0\u4EA4\u539F\u5B50\u5355\u5143**
|
|
28785
28958
|
|
|
28786
28959
|
- \u4EC5\u6682\u5B58\u5DF2\u9A8C\u8BC1\u7684\u66F4\u6539
|
|
28787
28960
|
- \u4F7F\u7528\u6E05\u6670\u7684\u63D0\u4EA4\u4FE1\u606F\u63CF\u8FF0\u5B8C\u6210\u7684\u5185\u5BB9
|
|
28788
28961
|
|
|
28789
|
-
**\u6B65\u9AA4
|
|
28962
|
+
**\u6B65\u9AA4 5\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u4E2A\u4EFB\u52A1**
|
|
28790
28963
|
|
|
28791
28964
|
- \u8BFB\u53D6\u8BA1\u5212\u6587\u4EF6\uFF0C\u627E\u5230\u4E0B\u4E00\u4E2A \`[ ]\` \u4EFB\u52A1
|
|
28792
28965
|
- \u7ACB\u5373\u5F00\u59CB\u2014\u2014\u4E0D\u8981\u505C\u6B62
|
|
@@ -28923,14 +29096,14 @@ function formatFileChanges(stats, notepadPath) {
|
|
|
28923
29096
|
`);
|
|
28924
29097
|
}
|
|
28925
29098
|
function getMessageDir5(sessionID) {
|
|
28926
|
-
if (!
|
|
29099
|
+
if (!existsSync39(MESSAGE_STORAGE))
|
|
28927
29100
|
return null;
|
|
28928
|
-
const directPath =
|
|
28929
|
-
if (
|
|
29101
|
+
const directPath = join52(MESSAGE_STORAGE, sessionID);
|
|
29102
|
+
if (existsSync39(directPath))
|
|
28930
29103
|
return directPath;
|
|
28931
29104
|
for (const dir of readdirSync11(MESSAGE_STORAGE)) {
|
|
28932
|
-
const sessionPath =
|
|
28933
|
-
if (
|
|
29105
|
+
const sessionPath = join52(MESSAGE_STORAGE, dir, sessionID);
|
|
29106
|
+
if (existsSync39(sessionPath))
|
|
28934
29107
|
return sessionPath;
|
|
28935
29108
|
}
|
|
28936
29109
|
return null;
|
|
@@ -28944,6 +29117,45 @@ function isCallerOrchestrator(sessionID) {
|
|
|
28944
29117
|
const nearest = findNearestAssistantMessage(messageDir);
|
|
28945
29118
|
return agentNameMatches(nearest?.agent, "\u4EFB\u52A1\u7F16\u6392");
|
|
28946
29119
|
}
|
|
29120
|
+
function isAgentCheckboxUpdater(agentName) {
|
|
29121
|
+
if (!agentName)
|
|
29122
|
+
return false;
|
|
29123
|
+
return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
|
|
29124
|
+
}
|
|
29125
|
+
function isActiveCheckboxUpdater(sessionID) {
|
|
29126
|
+
if (!sessionID)
|
|
29127
|
+
return false;
|
|
29128
|
+
const messageDir = getMessageDir5(sessionID);
|
|
29129
|
+
if (!messageDir)
|
|
29130
|
+
return false;
|
|
29131
|
+
const nearest = findNearestAssistantMessage(messageDir);
|
|
29132
|
+
return isAgentCheckboxUpdater(nearest?.agent);
|
|
29133
|
+
}
|
|
29134
|
+
function isAgentContinuationTrigger(agentName) {
|
|
29135
|
+
if (!agentName)
|
|
29136
|
+
return false;
|
|
29137
|
+
return agentNameMatches(agentName, "\u4EFB\u52A1\u7F16\u6392") || agentNameMatches(agentName, "\u4E3B\u6267\u884C\u5B98");
|
|
29138
|
+
}
|
|
29139
|
+
function isActiveContinuationTrigger(sessionID, directory) {
|
|
29140
|
+
if (!sessionID)
|
|
29141
|
+
return false;
|
|
29142
|
+
const messageDir = getMessageDir5(sessionID);
|
|
29143
|
+
if (messageDir) {
|
|
29144
|
+
const nearest = findNearestAssistantMessage(messageDir);
|
|
29145
|
+
if (isAgentContinuationTrigger(nearest?.agent)) {
|
|
29146
|
+
return true;
|
|
29147
|
+
}
|
|
29148
|
+
}
|
|
29149
|
+
if (directory) {
|
|
29150
|
+
try {
|
|
29151
|
+
const boulderState = readBoulderState(directory);
|
|
29152
|
+
if (boulderState?.session_ids?.includes(sessionID)) {
|
|
29153
|
+
return true;
|
|
29154
|
+
}
|
|
29155
|
+
} catch {}
|
|
29156
|
+
}
|
|
29157
|
+
return false;
|
|
29158
|
+
}
|
|
28947
29159
|
var CONTINUATION_COOLDOWN_MS = 5000;
|
|
28948
29160
|
function isAbortError(error) {
|
|
28949
29161
|
if (!error)
|
|
@@ -29108,8 +29320,8 @@ function createAtlasHook(ctx, options) {
|
|
|
29108
29320
|
log(`[${HOOK_NAME6}] No active boulder`, { sessionID });
|
|
29109
29321
|
return;
|
|
29110
29322
|
}
|
|
29111
|
-
if (!
|
|
29112
|
-
log(`[${HOOK_NAME6}] Skipped:
|
|
29323
|
+
if (!isActiveContinuationTrigger(sessionID, ctx.directory)) {
|
|
29324
|
+
log(`[${HOOK_NAME6}] Skipped: not eligible for continuation trigger`, { sessionID });
|
|
29113
29325
|
return;
|
|
29114
29326
|
}
|
|
29115
29327
|
const progress = getPlanProgress(boulderState.active_plan);
|
|
@@ -29235,7 +29447,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29235
29447
|
}
|
|
29236
29448
|
},
|
|
29237
29449
|
"tool.execute.after": async (input, output) => {
|
|
29238
|
-
if (!
|
|
29450
|
+
if (!isActiveCheckboxUpdater(input.sessionID)) {
|
|
29239
29451
|
return;
|
|
29240
29452
|
}
|
|
29241
29453
|
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
|
@@ -29297,7 +29509,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29297
29509
|
const taskDescription = extractTaskFromPrompt(savedPrompt || "");
|
|
29298
29510
|
if (taskDescription) {
|
|
29299
29511
|
try {
|
|
29300
|
-
const planContent =
|
|
29512
|
+
const planContent = readFileSync31(boulderState.active_plan, "utf-8");
|
|
29301
29513
|
const checkboxes = parseCheckboxes(planContent);
|
|
29302
29514
|
const checkboxIndex = findMatchingCheckbox(taskDescription, checkboxes);
|
|
29303
29515
|
if (checkboxIndex >= 0) {
|
|
@@ -29309,7 +29521,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29309
29521
|
`);
|
|
29310
29522
|
const planPath = boulderState.active_plan;
|
|
29311
29523
|
if (!writePlanFileAtomic(planPath, updatedContent)) {
|
|
29312
|
-
retryOnWindowsError(() =>
|
|
29524
|
+
retryOnWindowsError(() => writeFileSync21(planPath, updatedContent, "utf-8"));
|
|
29313
29525
|
log(`[${HOOK_NAME6}] Atomic plan write failed, fell back to direct write`, {
|
|
29314
29526
|
plan: boulderState.plan_name
|
|
29315
29527
|
});
|
|
@@ -29330,6 +29542,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29330
29542
|
});
|
|
29331
29543
|
}
|
|
29332
29544
|
}
|
|
29545
|
+
const updatedProgress = getPlanProgress(boulderState.active_plan);
|
|
29333
29546
|
output.output = `
|
|
29334
29547
|
## \u5B50\u4EE3\u7406\u5DE5\u4F5C\u5DF2\u5B8C\u6210
|
|
29335
29548
|
|
|
@@ -29342,11 +29555,11 @@ ${fileChanges}
|
|
|
29342
29555
|
${originalResponse}
|
|
29343
29556
|
|
|
29344
29557
|
<system-reminder>
|
|
29345
|
-
${buildOrchestratorReminder(boulderState.plan_name,
|
|
29558
|
+
${buildOrchestratorReminder(boulderState.plan_name, updatedProgress, subagentSessionId)}
|
|
29346
29559
|
</system-reminder>`;
|
|
29347
29560
|
log(`[${HOOK_NAME6}] Output transformed for orchestrator mode (boulder)`, {
|
|
29348
29561
|
plan: boulderState.plan_name,
|
|
29349
|
-
progress: `${
|
|
29562
|
+
progress: `${updatedProgress.completed}/${updatedProgress.total}`,
|
|
29350
29563
|
fileCount: gitStats.length
|
|
29351
29564
|
});
|
|
29352
29565
|
} else {
|
|
@@ -30159,6 +30372,7 @@ init_usage_tracker();
|
|
|
30159
30372
|
init_model_health_registry();
|
|
30160
30373
|
init_runtime_fallback();
|
|
30161
30374
|
init_agent_display_names();
|
|
30375
|
+
init_claude_code_session_state();
|
|
30162
30376
|
async function withTimeout(promise, timeoutMs, label) {
|
|
30163
30377
|
let timer;
|
|
30164
30378
|
return Promise.race([
|
|
@@ -30942,6 +31156,7 @@ function evaluatePermission(input, agentName) {
|
|
|
30942
31156
|
|
|
30943
31157
|
// src/hooks/permission-ask-bridge/index.ts
|
|
30944
31158
|
init_logger();
|
|
31159
|
+
init_claude_code_session_state();
|
|
30945
31160
|
function createPermissionAskBridgeHook(ctx) {
|
|
30946
31161
|
return {
|
|
30947
31162
|
"permission.ask": async (input, output) => {
|
|
@@ -30975,8 +31190,8 @@ function createShellEnvInjectorHook(_ctx) {
|
|
|
30975
31190
|
// src/hooks/plan-completion/index.ts
|
|
30976
31191
|
init_logger();
|
|
30977
31192
|
init_frontmatter();
|
|
30978
|
-
import { existsSync as
|
|
30979
|
-
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";
|
|
30980
31195
|
async function safeExecute(fn, name, onAction) {
|
|
30981
31196
|
try {
|
|
30982
31197
|
await fn();
|
|
@@ -31021,11 +31236,11 @@ function countListItems(content) {
|
|
|
31021
31236
|
}
|
|
31022
31237
|
async function updatePlanSummary(data) {
|
|
31023
31238
|
log(`[plan-completion] updatePlanSummary: ${data.planName}`);
|
|
31024
|
-
if (!
|
|
31239
|
+
if (!existsSync40(data.planPath)) {
|
|
31025
31240
|
log(`[plan-completion] Plan file not found: ${data.planPath}`);
|
|
31026
31241
|
return;
|
|
31027
31242
|
}
|
|
31028
|
-
const content =
|
|
31243
|
+
const content = readFileSync32(data.planPath, "utf-8");
|
|
31029
31244
|
const startedAt = data.boulderState?.started_at || "";
|
|
31030
31245
|
const completedAt = data.boulderState?.completed_at || "";
|
|
31031
31246
|
const duration = formatDuration(startedAt, completedAt);
|
|
@@ -31046,17 +31261,17 @@ async function updatePlanSummary(data) {
|
|
|
31046
31261
|
| \u5B8C\u6210\u4EFB\u52A1\u6570 | ${completedTasks} |
|
|
31047
31262
|
| \u5931\u8D25\u4EFB\u52A1\u6570 | ${failedTasks} |
|
|
31048
31263
|
`;
|
|
31049
|
-
|
|
31264
|
+
writeFileSync22(data.planPath, content + summary, "utf-8");
|
|
31050
31265
|
log(`[plan-completion] Plan summary appended to ${data.planPath}`);
|
|
31051
31266
|
}
|
|
31052
31267
|
async function archivePlan(data) {
|
|
31053
31268
|
log(`[plan-completion] archivePlan: ${data.planName}`);
|
|
31054
|
-
const archivedDir =
|
|
31055
|
-
if (!
|
|
31056
|
-
|
|
31269
|
+
const archivedDir = join53(data.directory, ".sisyphus", "archived");
|
|
31270
|
+
if (!existsSync40(archivedDir)) {
|
|
31271
|
+
mkdirSync18(archivedDir, { recursive: true });
|
|
31057
31272
|
}
|
|
31058
|
-
if (
|
|
31059
|
-
const archivedPath =
|
|
31273
|
+
if (existsSync40(data.planPath)) {
|
|
31274
|
+
const archivedPath = join53(archivedDir, `${data.planName}.md`);
|
|
31060
31275
|
renameSync4(data.planPath, archivedPath);
|
|
31061
31276
|
log(`[plan-completion] Plan archived to ${archivedPath}`);
|
|
31062
31277
|
const boulderState = readBoulderState(data.directory);
|
|
@@ -31066,16 +31281,16 @@ async function archivePlan(data) {
|
|
|
31066
31281
|
log(`[plan-completion] Updated boulder.json active_plan to ${archivedPath}`);
|
|
31067
31282
|
}
|
|
31068
31283
|
}
|
|
31069
|
-
const draftPath =
|
|
31070
|
-
if (
|
|
31284
|
+
const draftPath = join53(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
|
|
31285
|
+
if (existsSync40(draftPath)) {
|
|
31071
31286
|
unlinkSync14(draftPath);
|
|
31072
31287
|
log(`[plan-completion] Deleted draft file: ${draftPath}`);
|
|
31073
31288
|
}
|
|
31074
31289
|
}
|
|
31075
31290
|
async function extractLearnings(data) {
|
|
31076
31291
|
log(`[plan-completion] extractLearnings: ${data.planName}`);
|
|
31077
|
-
const notepadDir =
|
|
31078
|
-
if (!
|
|
31292
|
+
const notepadDir = join53(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31293
|
+
if (!existsSync40(notepadDir)) {
|
|
31079
31294
|
log(`[plan-completion] Notepad directory not found: ${notepadDir}`);
|
|
31080
31295
|
return;
|
|
31081
31296
|
}
|
|
@@ -31085,9 +31300,9 @@ async function extractLearnings(data) {
|
|
|
31085
31300
|
let totalIssues = 0;
|
|
31086
31301
|
let totalDecisions = 0;
|
|
31087
31302
|
for (const file of files) {
|
|
31088
|
-
const filePath =
|
|
31089
|
-
if (
|
|
31090
|
-
const content =
|
|
31303
|
+
const filePath = join53(notepadDir, file);
|
|
31304
|
+
if (existsSync40(filePath)) {
|
|
31305
|
+
const content = readFileSync32(filePath, "utf-8");
|
|
31091
31306
|
contents[file] = content;
|
|
31092
31307
|
const count = countListItems(content);
|
|
31093
31308
|
if (file === "learnings.md")
|
|
@@ -31098,9 +31313,9 @@ async function extractLearnings(data) {
|
|
|
31098
31313
|
totalDecisions = count;
|
|
31099
31314
|
}
|
|
31100
31315
|
}
|
|
31101
|
-
const learningsDir =
|
|
31102
|
-
if (!
|
|
31103
|
-
|
|
31316
|
+
const learningsDir = join53(data.directory, ".sisyphus", "learnings");
|
|
31317
|
+
if (!existsSync40(learningsDir)) {
|
|
31318
|
+
mkdirSync18(learningsDir, { recursive: true });
|
|
31104
31319
|
}
|
|
31105
31320
|
const output = `# \u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3: ${data.planName}
|
|
31106
31321
|
|
|
@@ -31127,8 +31342,8 @@ ${contents["decisions.md"] || "\u65E0"}
|
|
|
31127
31342
|
|
|
31128
31343
|
${contents["match-failures.md"] || "\u65E0"}
|
|
31129
31344
|
`;
|
|
31130
|
-
const outputPath =
|
|
31131
|
-
|
|
31345
|
+
const outputPath = join53(learningsDir, `${data.planName}.md`);
|
|
31346
|
+
writeFileSync22(outputPath, output, "utf-8");
|
|
31132
31347
|
log(`[plan-completion] Learnings saved to ${outputPath}`);
|
|
31133
31348
|
if (data.client?.tui?.showToast) {
|
|
31134
31349
|
data.client.tui.showToast({
|
|
@@ -31147,9 +31362,9 @@ ${contents["match-failures.md"] || "\u65E0"}
|
|
|
31147
31362
|
}
|
|
31148
31363
|
async function generateReport(data) {
|
|
31149
31364
|
log(`[plan-completion] generateReport: ${data.planName}`);
|
|
31150
|
-
const reportsDir =
|
|
31151
|
-
if (!
|
|
31152
|
-
|
|
31365
|
+
const reportsDir = join53(data.directory, ".sisyphus", "reports");
|
|
31366
|
+
if (!existsSync40(reportsDir)) {
|
|
31367
|
+
mkdirSync18(reportsDir, { recursive: true });
|
|
31153
31368
|
}
|
|
31154
31369
|
const startedAt = data.boulderState?.started_at || "";
|
|
31155
31370
|
const completedAt = data.boulderState?.completed_at || "";
|
|
@@ -31160,8 +31375,8 @@ async function generateReport(data) {
|
|
|
31160
31375
|
const version = data.boulderState?.version || 0;
|
|
31161
31376
|
const sessionCount = data.boulderState?.session_ids?.length || 0;
|
|
31162
31377
|
const completedIndices = data.boulderState?.completed_task_indices || [];
|
|
31163
|
-
const notepadPath =
|
|
31164
|
-
const hasNotepad =
|
|
31378
|
+
const notepadPath = join53(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31379
|
+
const hasNotepad = existsSync40(notepadPath);
|
|
31165
31380
|
const report = `# \u8BA1\u5212\u5B8C\u6210\u62A5\u544A
|
|
31166
31381
|
|
|
31167
31382
|
## \u6982\u89C8
|
|
@@ -31200,8 +31415,8 @@ ${hasNotepad ? `## \u8BB0\u4E8B\u672C
|
|
|
31200
31415
|
\u8BB0\u4E8B\u672C\u8DEF\u5F84: ${notepadPath}
|
|
31201
31416
|
` : ""}
|
|
31202
31417
|
`;
|
|
31203
|
-
const reportPath =
|
|
31204
|
-
|
|
31418
|
+
const reportPath = join53(reportsDir, `${data.planName}.md`);
|
|
31419
|
+
writeFileSync22(reportPath, report, "utf-8");
|
|
31205
31420
|
log(`[plan-completion] Report generated at ${reportPath}`);
|
|
31206
31421
|
}
|
|
31207
31422
|
async function runInitDeep(data) {
|
|
@@ -31311,6 +31526,7 @@ class ContextCollector {
|
|
|
31311
31526
|
var contextCollector = new ContextCollector;
|
|
31312
31527
|
// src/features/context-injector/injector.ts
|
|
31313
31528
|
init_shared();
|
|
31529
|
+
init_claude_code_session_state();
|
|
31314
31530
|
function createContextInjectorMessagesTransformHook(collector) {
|
|
31315
31531
|
return {
|
|
31316
31532
|
"experimental.chat.messages.transform": async (_input, output) => {
|
|
@@ -31412,8 +31628,8 @@ function createFirstMessageVariantGate() {
|
|
|
31412
31628
|
}
|
|
31413
31629
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
31414
31630
|
init_shared();
|
|
31415
|
-
import { existsSync as
|
|
31416
|
-
import { join as
|
|
31631
|
+
import { existsSync as existsSync41, readFileSync as readFileSync33 } from "fs";
|
|
31632
|
+
import { join as join54 } from "path";
|
|
31417
31633
|
|
|
31418
31634
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
31419
31635
|
function expandEnvVars(value) {
|
|
@@ -31483,13 +31699,13 @@ function getMcpConfigPaths() {
|
|
|
31483
31699
|
const claudeConfigDir = getClaudeConfigDir();
|
|
31484
31700
|
const cwd2 = process.cwd();
|
|
31485
31701
|
return [
|
|
31486
|
-
{ path:
|
|
31487
|
-
{ path:
|
|
31488
|
-
{ 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" }
|
|
31489
31705
|
];
|
|
31490
31706
|
}
|
|
31491
31707
|
async function loadMcpConfigFile(filePath) {
|
|
31492
|
-
if (!
|
|
31708
|
+
if (!existsSync41(filePath)) {
|
|
31493
31709
|
return null;
|
|
31494
31710
|
}
|
|
31495
31711
|
try {
|
|
@@ -31504,10 +31720,10 @@ function getSystemMcpServerNames() {
|
|
|
31504
31720
|
const names = new Set;
|
|
31505
31721
|
const paths = getMcpConfigPaths();
|
|
31506
31722
|
for (const { path: path7 } of paths) {
|
|
31507
|
-
if (!
|
|
31723
|
+
if (!existsSync41(path7))
|
|
31508
31724
|
continue;
|
|
31509
31725
|
try {
|
|
31510
|
-
const content =
|
|
31726
|
+
const content = readFileSync33(path7, "utf-8");
|
|
31511
31727
|
const config = JSON.parse(content);
|
|
31512
31728
|
if (!config?.mcpServers)
|
|
31513
31729
|
continue;
|
|
@@ -31557,14 +31773,21 @@ async function loadMcpConfigs() {
|
|
|
31557
31773
|
}
|
|
31558
31774
|
return { servers, loadedServers };
|
|
31559
31775
|
}
|
|
31776
|
+
// src/index.ts
|
|
31777
|
+
init_claude_code_session_state();
|
|
31778
|
+
|
|
31560
31779
|
// src/features/claude-code-session-state/recovery.ts
|
|
31561
|
-
import { existsSync as
|
|
31562
|
-
import { join as
|
|
31780
|
+
import { existsSync as existsSync42, readdirSync as readdirSync13 } from "fs";
|
|
31781
|
+
import { join as join55 } from "path";
|
|
31782
|
+
init_state();
|
|
31563
31783
|
init_logger();
|
|
31564
|
-
function recoverSessionAgents() {
|
|
31784
|
+
function recoverSessionAgents(directory) {
|
|
31565
31785
|
let recoveredCount = 0;
|
|
31786
|
+
if (directory) {
|
|
31787
|
+
loadSessionAgentMap(directory);
|
|
31788
|
+
}
|
|
31566
31789
|
try {
|
|
31567
|
-
if (!
|
|
31790
|
+
if (!existsSync42(MESSAGE_STORAGE)) {
|
|
31568
31791
|
log("[recovery] MESSAGE_STORAGE directory does not exist", { path: MESSAGE_STORAGE });
|
|
31569
31792
|
return 0;
|
|
31570
31793
|
}
|
|
@@ -31572,13 +31795,13 @@ function recoverSessionAgents() {
|
|
|
31572
31795
|
for (const entry of entries) {
|
|
31573
31796
|
if (!entry.isDirectory())
|
|
31574
31797
|
continue;
|
|
31575
|
-
const projectDir =
|
|
31798
|
+
const projectDir = join55(MESSAGE_STORAGE, entry.name);
|
|
31576
31799
|
try {
|
|
31577
31800
|
const sessionDirs = readdirSync13(projectDir, { withFileTypes: true });
|
|
31578
31801
|
for (const sessionEntry of sessionDirs) {
|
|
31579
31802
|
if (!sessionEntry.isDirectory())
|
|
31580
31803
|
continue;
|
|
31581
|
-
const sessionDir =
|
|
31804
|
+
const sessionDir = join55(projectDir, sessionEntry.name);
|
|
31582
31805
|
const sessionID = sessionEntry.name;
|
|
31583
31806
|
try {
|
|
31584
31807
|
const msg = findNearestAssistantMessage(sessionDir);
|
|
@@ -32004,14 +32227,14 @@ var EXT_TO_LANG = {
|
|
|
32004
32227
|
".gql": "graphql"
|
|
32005
32228
|
};
|
|
32006
32229
|
// src/tools/lsp/config.ts
|
|
32007
|
-
import { existsSync as
|
|
32008
|
-
import { join as
|
|
32230
|
+
import { existsSync as existsSync43, readFileSync as readFileSync34 } from "fs";
|
|
32231
|
+
import { join as join56 } from "path";
|
|
32009
32232
|
init_shared();
|
|
32010
32233
|
function loadJsonFile(path7) {
|
|
32011
|
-
if (!
|
|
32234
|
+
if (!existsSync43(path7))
|
|
32012
32235
|
return null;
|
|
32013
32236
|
try {
|
|
32014
|
-
return JSON.parse(
|
|
32237
|
+
return JSON.parse(readFileSync34(path7, "utf-8"));
|
|
32015
32238
|
} catch {
|
|
32016
32239
|
return null;
|
|
32017
32240
|
}
|
|
@@ -32020,9 +32243,9 @@ function getConfigPaths3() {
|
|
|
32020
32243
|
const cwd2 = process.cwd();
|
|
32021
32244
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
32022
32245
|
return {
|
|
32023
|
-
project:
|
|
32024
|
-
user:
|
|
32025
|
-
opencode:
|
|
32246
|
+
project: join56(cwd2, ".opencode", "oh-my-opencode.json"),
|
|
32247
|
+
user: join56(configDir, "oh-my-opencode.json"),
|
|
32248
|
+
opencode: join56(configDir, "opencode.json")
|
|
32026
32249
|
};
|
|
32027
32250
|
}
|
|
32028
32251
|
function loadAllConfigs() {
|
|
@@ -32135,7 +32358,7 @@ function isServerInstalled(command) {
|
|
|
32135
32358
|
return false;
|
|
32136
32359
|
const cmd = command[0];
|
|
32137
32360
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
32138
|
-
if (
|
|
32361
|
+
if (existsSync43(cmd))
|
|
32139
32362
|
return true;
|
|
32140
32363
|
}
|
|
32141
32364
|
const isWindows2 = process.platform === "win32";
|
|
@@ -32157,23 +32380,23 @@ function isServerInstalled(command) {
|
|
|
32157
32380
|
const paths = pathEnv.split(pathSeparator);
|
|
32158
32381
|
for (const p of paths) {
|
|
32159
32382
|
for (const suffix of exts) {
|
|
32160
|
-
if (
|
|
32383
|
+
if (existsSync43(join56(p, cmd + suffix))) {
|
|
32161
32384
|
return true;
|
|
32162
32385
|
}
|
|
32163
32386
|
}
|
|
32164
32387
|
}
|
|
32165
32388
|
const cwd2 = process.cwd();
|
|
32166
32389
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
32167
|
-
const dataDir =
|
|
32390
|
+
const dataDir = join56(getDataDir(), "opencode");
|
|
32168
32391
|
const additionalBases = [
|
|
32169
|
-
|
|
32170
|
-
|
|
32171
|
-
|
|
32172
|
-
|
|
32392
|
+
join56(cwd2, "node_modules", ".bin"),
|
|
32393
|
+
join56(configDir, "bin"),
|
|
32394
|
+
join56(configDir, "node_modules", ".bin"),
|
|
32395
|
+
join56(dataDir, "bin")
|
|
32173
32396
|
];
|
|
32174
32397
|
for (const base of additionalBases) {
|
|
32175
32398
|
for (const suffix of exts) {
|
|
32176
|
-
if (
|
|
32399
|
+
if (existsSync43(join56(base, cmd + suffix))) {
|
|
32177
32400
|
return true;
|
|
32178
32401
|
}
|
|
32179
32402
|
}
|
|
@@ -32185,7 +32408,7 @@ function isServerInstalled(command) {
|
|
|
32185
32408
|
}
|
|
32186
32409
|
// src/tools/lsp/client.ts
|
|
32187
32410
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
32188
|
-
import { readFileSync as
|
|
32411
|
+
import { readFileSync as readFileSync35 } from "fs";
|
|
32189
32412
|
import { extname, resolve as resolve8 } from "path";
|
|
32190
32413
|
import { pathToFileURL } from "url";
|
|
32191
32414
|
class LSPServerManager {
|
|
@@ -32636,7 +32859,7 @@ ${msg}`);
|
|
|
32636
32859
|
const absPath = resolve8(filePath);
|
|
32637
32860
|
if (this.openedFiles.has(absPath))
|
|
32638
32861
|
return;
|
|
32639
|
-
const text =
|
|
32862
|
+
const text = readFileSync35(absPath, "utf-8");
|
|
32640
32863
|
const ext = extname(absPath);
|
|
32641
32864
|
const languageId = getLanguageId(ext);
|
|
32642
32865
|
this.notify("textDocument/didOpen", {
|
|
@@ -32726,17 +32949,17 @@ ${msg}`);
|
|
|
32726
32949
|
// src/tools/lsp/utils.ts
|
|
32727
32950
|
import { extname as extname2, resolve as resolve9 } from "path";
|
|
32728
32951
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32729
|
-
import { existsSync as
|
|
32952
|
+
import { existsSync as existsSync44, readFileSync as readFileSync36, writeFileSync as writeFileSync23 } from "fs";
|
|
32730
32953
|
function findWorkspaceRoot(filePath) {
|
|
32731
32954
|
let dir = resolve9(filePath);
|
|
32732
|
-
if (!
|
|
32955
|
+
if (!existsSync44(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
32733
32956
|
dir = __require("path").dirname(dir);
|
|
32734
32957
|
}
|
|
32735
32958
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
32736
32959
|
let prevDir = "";
|
|
32737
32960
|
while (dir !== prevDir) {
|
|
32738
32961
|
for (const marker of markers) {
|
|
32739
|
-
if (
|
|
32962
|
+
if (existsSync44(__require("path").join(dir, marker))) {
|
|
32740
32963
|
return dir;
|
|
32741
32964
|
}
|
|
32742
32965
|
}
|
|
@@ -32891,7 +33114,7 @@ function formatPrepareRenameResult(result) {
|
|
|
32891
33114
|
}
|
|
32892
33115
|
function applyTextEditsToFile(filePath, edits) {
|
|
32893
33116
|
try {
|
|
32894
|
-
let content =
|
|
33117
|
+
let content = readFileSync36(filePath, "utf-8");
|
|
32895
33118
|
const lines = content.split(`
|
|
32896
33119
|
`);
|
|
32897
33120
|
const sortedEdits = [...edits].sort((a, b) => {
|
|
@@ -32916,7 +33139,7 @@ function applyTextEditsToFile(filePath, edits) {
|
|
|
32916
33139
|
`));
|
|
32917
33140
|
}
|
|
32918
33141
|
}
|
|
32919
|
-
|
|
33142
|
+
writeFileSync23(filePath, lines.join(`
|
|
32920
33143
|
`), "utf-8");
|
|
32921
33144
|
return { success: true, editCount: edits.length };
|
|
32922
33145
|
} catch (err) {
|
|
@@ -32947,7 +33170,7 @@ function applyWorkspaceEdit(edit) {
|
|
|
32947
33170
|
if (change.kind === "create") {
|
|
32948
33171
|
try {
|
|
32949
33172
|
const filePath = uriToPath(change.uri);
|
|
32950
|
-
|
|
33173
|
+
writeFileSync23(filePath, "", "utf-8");
|
|
32951
33174
|
result.filesModified.push(filePath);
|
|
32952
33175
|
} catch (err) {
|
|
32953
33176
|
result.success = false;
|
|
@@ -32957,8 +33180,8 @@ function applyWorkspaceEdit(edit) {
|
|
|
32957
33180
|
try {
|
|
32958
33181
|
const oldPath = uriToPath(change.oldUri);
|
|
32959
33182
|
const newPath = uriToPath(change.newUri);
|
|
32960
|
-
const content =
|
|
32961
|
-
|
|
33183
|
+
const content = readFileSync36(oldPath, "utf-8");
|
|
33184
|
+
writeFileSync23(newPath, content, "utf-8");
|
|
32962
33185
|
__require("fs").unlinkSync(oldPath);
|
|
32963
33186
|
result.filesModified.push(newPath);
|
|
32964
33187
|
} catch (err) {
|
|
@@ -45537,13 +45760,13 @@ var lsp_rename = tool({
|
|
|
45537
45760
|
});
|
|
45538
45761
|
// src/tools/ast-grep/constants.ts
|
|
45539
45762
|
import { createRequire as createRequire4 } from "module";
|
|
45540
|
-
import { dirname as dirname11, join as
|
|
45541
|
-
import { existsSync as
|
|
45763
|
+
import { dirname as dirname11, join as join58 } from "path";
|
|
45764
|
+
import { existsSync as existsSync46, statSync as statSync5 } from "fs";
|
|
45542
45765
|
|
|
45543
45766
|
// src/tools/ast-grep/downloader.ts
|
|
45544
45767
|
init_shared();
|
|
45545
|
-
import { existsSync as
|
|
45546
|
-
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";
|
|
45547
45770
|
import { homedir as homedir13 } from "os";
|
|
45548
45771
|
import { createRequire as createRequire3 } from "module";
|
|
45549
45772
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -45569,19 +45792,19 @@ var PLATFORM_MAP2 = {
|
|
|
45569
45792
|
function getCacheDir3() {
|
|
45570
45793
|
if (process.platform === "win32") {
|
|
45571
45794
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
45572
|
-
const base2 = localAppData ||
|
|
45573
|
-
return
|
|
45795
|
+
const base2 = localAppData || join57(homedir13(), "AppData", "Local");
|
|
45796
|
+
return join57(base2, "oh-my-opencode", "bin");
|
|
45574
45797
|
}
|
|
45575
45798
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
45576
|
-
const base = xdgCache ||
|
|
45577
|
-
return
|
|
45799
|
+
const base = xdgCache || join57(homedir13(), ".cache");
|
|
45800
|
+
return join57(base, "oh-my-opencode", "bin");
|
|
45578
45801
|
}
|
|
45579
45802
|
function getBinaryName3() {
|
|
45580
45803
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
45581
45804
|
}
|
|
45582
45805
|
function getCachedBinaryPath2() {
|
|
45583
|
-
const binaryPath =
|
|
45584
|
-
return
|
|
45806
|
+
const binaryPath = join57(getCacheDir3(), getBinaryName3());
|
|
45807
|
+
return existsSync45(binaryPath) ? binaryPath : null;
|
|
45585
45808
|
}
|
|
45586
45809
|
async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
45587
45810
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
@@ -45592,8 +45815,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45592
45815
|
}
|
|
45593
45816
|
const cacheDir = getCacheDir3();
|
|
45594
45817
|
const binaryName = getBinaryName3();
|
|
45595
|
-
const binaryPath =
|
|
45596
|
-
if (
|
|
45818
|
+
const binaryPath = join57(cacheDir, binaryName);
|
|
45819
|
+
if (existsSync45(binaryPath)) {
|
|
45597
45820
|
return binaryPath;
|
|
45598
45821
|
}
|
|
45599
45822
|
const { arch, os: os6 } = platformInfo;
|
|
@@ -45601,21 +45824,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45601
45824
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
45602
45825
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
45603
45826
|
try {
|
|
45604
|
-
if (!
|
|
45605
|
-
|
|
45827
|
+
if (!existsSync45(cacheDir)) {
|
|
45828
|
+
mkdirSync19(cacheDir, { recursive: true });
|
|
45606
45829
|
}
|
|
45607
45830
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
45608
45831
|
if (!response.ok) {
|
|
45609
45832
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
45610
45833
|
}
|
|
45611
|
-
const archivePath =
|
|
45834
|
+
const archivePath = join57(cacheDir, assetName);
|
|
45612
45835
|
const arrayBuffer = await response.arrayBuffer();
|
|
45613
45836
|
await Bun.write(archivePath, arrayBuffer);
|
|
45614
45837
|
await extractZip(archivePath, cacheDir);
|
|
45615
|
-
if (
|
|
45838
|
+
if (existsSync45(archivePath)) {
|
|
45616
45839
|
unlinkSync15(archivePath);
|
|
45617
45840
|
}
|
|
45618
|
-
if (process.platform !== "win32" &&
|
|
45841
|
+
if (process.platform !== "win32" && existsSync45(binaryPath)) {
|
|
45619
45842
|
chmodSync2(binaryPath, 493);
|
|
45620
45843
|
}
|
|
45621
45844
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -45666,8 +45889,8 @@ function findSgCliPathSync() {
|
|
|
45666
45889
|
const require2 = createRequire4(import.meta.url);
|
|
45667
45890
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
45668
45891
|
const cliDir = dirname11(cliPkgPath);
|
|
45669
|
-
const sgPath =
|
|
45670
|
-
if (
|
|
45892
|
+
const sgPath = join58(cliDir, binaryName);
|
|
45893
|
+
if (existsSync46(sgPath) && isValidBinary(sgPath)) {
|
|
45671
45894
|
return sgPath;
|
|
45672
45895
|
}
|
|
45673
45896
|
} catch {}
|
|
@@ -45678,8 +45901,8 @@ function findSgCliPathSync() {
|
|
|
45678
45901
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
45679
45902
|
const pkgDir = dirname11(pkgPath);
|
|
45680
45903
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
45681
|
-
const binaryPath =
|
|
45682
|
-
if (
|
|
45904
|
+
const binaryPath = join58(pkgDir, astGrepName);
|
|
45905
|
+
if (existsSync46(binaryPath) && isValidBinary(binaryPath)) {
|
|
45683
45906
|
return binaryPath;
|
|
45684
45907
|
}
|
|
45685
45908
|
} catch {}
|
|
@@ -45687,7 +45910,7 @@ function findSgCliPathSync() {
|
|
|
45687
45910
|
if (process.platform === "darwin") {
|
|
45688
45911
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
45689
45912
|
for (const path7 of homebrewPaths) {
|
|
45690
|
-
if (
|
|
45913
|
+
if (existsSync46(path7) && isValidBinary(path7)) {
|
|
45691
45914
|
return path7;
|
|
45692
45915
|
}
|
|
45693
45916
|
}
|
|
@@ -45742,11 +45965,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
45742
45965
|
|
|
45743
45966
|
// src/tools/ast-grep/cli.ts
|
|
45744
45967
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
45745
|
-
import { existsSync as
|
|
45968
|
+
import { existsSync as existsSync47 } from "fs";
|
|
45746
45969
|
var resolvedCliPath3 = null;
|
|
45747
45970
|
var initPromise2 = null;
|
|
45748
45971
|
async function getAstGrepPath() {
|
|
45749
|
-
if (resolvedCliPath3 !== null &&
|
|
45972
|
+
if (resolvedCliPath3 !== null && existsSync47(resolvedCliPath3)) {
|
|
45750
45973
|
return resolvedCliPath3;
|
|
45751
45974
|
}
|
|
45752
45975
|
if (initPromise2) {
|
|
@@ -45754,7 +45977,7 @@ async function getAstGrepPath() {
|
|
|
45754
45977
|
}
|
|
45755
45978
|
initPromise2 = (async () => {
|
|
45756
45979
|
const syncPath = findSgCliPathSync();
|
|
45757
|
-
if (syncPath &&
|
|
45980
|
+
if (syncPath && existsSync47(syncPath)) {
|
|
45758
45981
|
resolvedCliPath3 = syncPath;
|
|
45759
45982
|
setSgCliPath(syncPath);
|
|
45760
45983
|
return syncPath;
|
|
@@ -45788,7 +46011,7 @@ async function runSg(options) {
|
|
|
45788
46011
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
45789
46012
|
args.push(...paths);
|
|
45790
46013
|
let cliPath = getSgCliPath();
|
|
45791
|
-
if (!
|
|
46014
|
+
if (!existsSync47(cliPath) && cliPath !== "sg") {
|
|
45792
46015
|
const downloadedPath = await getAstGrepPath();
|
|
45793
46016
|
if (downloadedPath) {
|
|
45794
46017
|
cliPath = downloadedPath;
|
|
@@ -46052,21 +46275,21 @@ var ast_grep_replace = tool({
|
|
|
46052
46275
|
var {spawn: spawn9 } = globalThis.Bun;
|
|
46053
46276
|
|
|
46054
46277
|
// src/tools/grep/constants.ts
|
|
46055
|
-
import { existsSync as
|
|
46056
|
-
import { join as
|
|
46278
|
+
import { existsSync as existsSync49 } from "fs";
|
|
46279
|
+
import { join as join60, dirname as dirname12 } from "path";
|
|
46057
46280
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46058
46281
|
|
|
46059
46282
|
// src/tools/grep/downloader.ts
|
|
46060
46283
|
init_shared();
|
|
46061
|
-
import { existsSync as
|
|
46062
|
-
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";
|
|
46063
46286
|
var {spawn: spawn8 } = globalThis.Bun;
|
|
46064
46287
|
function findFileRecursive(dir, filename) {
|
|
46065
46288
|
try {
|
|
46066
46289
|
const entries = readdirSync14(dir, { withFileTypes: true, recursive: true });
|
|
46067
46290
|
for (const entry of entries) {
|
|
46068
46291
|
if (entry.isFile() && entry.name === filename) {
|
|
46069
|
-
return
|
|
46292
|
+
return join59(entry.parentPath ?? dir, entry.name);
|
|
46070
46293
|
}
|
|
46071
46294
|
}
|
|
46072
46295
|
} catch {
|
|
@@ -46087,11 +46310,11 @@ function getPlatformKey() {
|
|
|
46087
46310
|
}
|
|
46088
46311
|
function getInstallDir() {
|
|
46089
46312
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
46090
|
-
return
|
|
46313
|
+
return join59(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
46091
46314
|
}
|
|
46092
46315
|
function getRgPath() {
|
|
46093
46316
|
const isWindows2 = process.platform === "win32";
|
|
46094
|
-
return
|
|
46317
|
+
return join59(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
46095
46318
|
}
|
|
46096
46319
|
async function downloadFile(url2, destPath) {
|
|
46097
46320
|
const response = await fetch(url2);
|
|
@@ -46125,7 +46348,7 @@ async function extractZip2(archivePath, destDir) {
|
|
|
46125
46348
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
46126
46349
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
46127
46350
|
if (foundPath) {
|
|
46128
|
-
const destPath =
|
|
46351
|
+
const destPath = join59(destDir, binaryName);
|
|
46129
46352
|
if (foundPath !== destPath) {
|
|
46130
46353
|
const { renameSync: renameSync5 } = await import("fs");
|
|
46131
46354
|
renameSync5(foundPath, destPath);
|
|
@@ -46140,13 +46363,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
46140
46363
|
}
|
|
46141
46364
|
const installDir = getInstallDir();
|
|
46142
46365
|
const rgPath = getRgPath();
|
|
46143
|
-
if (
|
|
46366
|
+
if (existsSync48(rgPath)) {
|
|
46144
46367
|
return rgPath;
|
|
46145
46368
|
}
|
|
46146
|
-
|
|
46369
|
+
mkdirSync20(installDir, { recursive: true });
|
|
46147
46370
|
const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
|
|
46148
46371
|
const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
46149
|
-
const archivePath =
|
|
46372
|
+
const archivePath = join59(installDir, filename);
|
|
46150
46373
|
try {
|
|
46151
46374
|
await downloadFile(url2, archivePath);
|
|
46152
46375
|
if (config3.extension === "tar.gz") {
|
|
@@ -46157,12 +46380,12 @@ async function downloadAndInstallRipgrep() {
|
|
|
46157
46380
|
if (process.platform !== "win32") {
|
|
46158
46381
|
chmodSync3(rgPath, 493);
|
|
46159
46382
|
}
|
|
46160
|
-
if (!
|
|
46383
|
+
if (!existsSync48(rgPath)) {
|
|
46161
46384
|
throw new Error("\u63D0\u53D6\u540E\u672A\u627E\u5230 ripgrep \u4E8C\u8FDB\u5236\u6587\u4EF6");
|
|
46162
46385
|
}
|
|
46163
46386
|
return rgPath;
|
|
46164
46387
|
} finally {
|
|
46165
|
-
if (
|
|
46388
|
+
if (existsSync48(archivePath)) {
|
|
46166
46389
|
try {
|
|
46167
46390
|
unlinkSync16(archivePath);
|
|
46168
46391
|
} catch {}
|
|
@@ -46171,7 +46394,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
46171
46394
|
}
|
|
46172
46395
|
function getInstalledRipgrepPath() {
|
|
46173
46396
|
const rgPath = getRgPath();
|
|
46174
|
-
return
|
|
46397
|
+
return existsSync48(rgPath) ? rgPath : null;
|
|
46175
46398
|
}
|
|
46176
46399
|
|
|
46177
46400
|
// src/tools/grep/constants.ts
|
|
@@ -46195,7 +46418,7 @@ function findExecutable(name) {
|
|
|
46195
46418
|
continue;
|
|
46196
46419
|
}
|
|
46197
46420
|
}
|
|
46198
|
-
if (
|
|
46421
|
+
if (existsSync49(trimmed)) {
|
|
46199
46422
|
return trimmed;
|
|
46200
46423
|
}
|
|
46201
46424
|
}
|
|
@@ -46210,14 +46433,14 @@ function getOpenCodeBundledRg() {
|
|
|
46210
46433
|
const isWindows2 = process.platform === "win32";
|
|
46211
46434
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
46212
46435
|
const candidates = [
|
|
46213
|
-
|
|
46214
|
-
|
|
46215
|
-
|
|
46216
|
-
|
|
46217
|
-
|
|
46436
|
+
join60(getDataDir(), "opencode", "bin", rgName),
|
|
46437
|
+
join60(execDir, rgName),
|
|
46438
|
+
join60(execDir, "bin", rgName),
|
|
46439
|
+
join60(execDir, "..", "bin", rgName),
|
|
46440
|
+
join60(execDir, "..", "libexec", rgName)
|
|
46218
46441
|
];
|
|
46219
46442
|
for (const candidate of candidates) {
|
|
46220
|
-
if (
|
|
46443
|
+
if (existsSync49(candidate)) {
|
|
46221
46444
|
return candidate;
|
|
46222
46445
|
}
|
|
46223
46446
|
}
|
|
@@ -46679,8 +46902,8 @@ var glob = tool({
|
|
|
46679
46902
|
init_shared();
|
|
46680
46903
|
init_file_utils();
|
|
46681
46904
|
init_shared();
|
|
46682
|
-
import { existsSync as
|
|
46683
|
-
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";
|
|
46684
46907
|
// src/features/builtin-commands/templates/init-deep.ts
|
|
46685
46908
|
var INIT_DEEP_TEMPLATE = `# /init-deep
|
|
46686
46909
|
|
|
@@ -47825,7 +48048,7 @@ function loadBuiltinCommands(disabledCommands) {
|
|
|
47825
48048
|
}
|
|
47826
48049
|
// src/tools/slashcommand/tools.ts
|
|
47827
48050
|
function discoverCommandsFromDir2(commandsDir, scope) {
|
|
47828
|
-
if (!
|
|
48051
|
+
if (!existsSync50(commandsDir)) {
|
|
47829
48052
|
return [];
|
|
47830
48053
|
}
|
|
47831
48054
|
const entries = readdirSync15(commandsDir, { withFileTypes: true });
|
|
@@ -47833,10 +48056,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
47833
48056
|
for (const entry of entries) {
|
|
47834
48057
|
if (!isMarkdownFile(entry))
|
|
47835
48058
|
continue;
|
|
47836
|
-
const commandPath =
|
|
48059
|
+
const commandPath = join61(commandsDir, entry.name);
|
|
47837
48060
|
const commandName = basename4(entry.name, ".md");
|
|
47838
48061
|
try {
|
|
47839
|
-
const content =
|
|
48062
|
+
const content = readFileSync37(commandPath, "utf-8");
|
|
47840
48063
|
const { data, body } = parseFrontmatter(content);
|
|
47841
48064
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
47842
48065
|
const metadata = {
|
|
@@ -47862,10 +48085,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
47862
48085
|
}
|
|
47863
48086
|
function discoverCommandsSync(disabledCommands) {
|
|
47864
48087
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
47865
|
-
const userCommandsDir =
|
|
47866
|
-
const projectCommandsDir =
|
|
47867
|
-
const opencodeGlobalDir =
|
|
47868
|
-
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");
|
|
47869
48092
|
const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
|
|
47870
48093
|
const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
|
|
47871
48094
|
const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
|
|
@@ -48065,13 +48288,13 @@ var slashcommand = createSlashcommandTool();
|
|
|
48065
48288
|
// src/tools/session-manager/constants.ts
|
|
48066
48289
|
init_data_path();
|
|
48067
48290
|
init_shared();
|
|
48068
|
-
import { join as
|
|
48291
|
+
import { join as join62 } from "path";
|
|
48069
48292
|
var OPENCODE_STORAGE11 = getOpenCodeStorageDir();
|
|
48070
|
-
var MESSAGE_STORAGE4 =
|
|
48071
|
-
var PART_STORAGE4 =
|
|
48072
|
-
var SESSION_STORAGE =
|
|
48073
|
-
var TODO_DIR2 =
|
|
48074
|
-
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");
|
|
48075
48298
|
var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
|
|
48076
48299
|
|
|
48077
48300
|
\u8FD4\u56DE\u53EF\u7528\u7684 session ID \u5217\u8868\uFF0C\u5305\u542B\u6D88\u606F\u6570\u91CF\u3001\u65E5\u671F\u8303\u56F4\u548C\u4F7F\u7528\u8FC7\u7684 agents \u7B49\u5143\u6570\u636E\u3002
|
|
@@ -48144,11 +48367,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
48144
48367
|
Has Transcript: Yes (234 entries)`;
|
|
48145
48368
|
|
|
48146
48369
|
// src/tools/session-manager/storage.ts
|
|
48147
|
-
import { existsSync as
|
|
48370
|
+
import { existsSync as existsSync51, readdirSync as readdirSync16 } from "fs";
|
|
48148
48371
|
import { readdir, readFile } from "fs/promises";
|
|
48149
|
-
import { join as
|
|
48372
|
+
import { join as join63 } from "path";
|
|
48150
48373
|
async function getMainSessions(options) {
|
|
48151
|
-
if (!
|
|
48374
|
+
if (!existsSync51(SESSION_STORAGE))
|
|
48152
48375
|
return [];
|
|
48153
48376
|
const sessions = [];
|
|
48154
48377
|
try {
|
|
@@ -48156,13 +48379,13 @@ async function getMainSessions(options) {
|
|
|
48156
48379
|
for (const projectDir of projectDirs) {
|
|
48157
48380
|
if (!projectDir.isDirectory())
|
|
48158
48381
|
continue;
|
|
48159
|
-
const projectPath =
|
|
48382
|
+
const projectPath = join63(SESSION_STORAGE, projectDir.name);
|
|
48160
48383
|
const sessionFiles = await readdir(projectPath);
|
|
48161
48384
|
for (const file2 of sessionFiles) {
|
|
48162
48385
|
if (!file2.endsWith(".json"))
|
|
48163
48386
|
continue;
|
|
48164
48387
|
try {
|
|
48165
|
-
const content = await readFile(
|
|
48388
|
+
const content = await readFile(join63(projectPath, file2), "utf-8");
|
|
48166
48389
|
const meta = JSON.parse(content);
|
|
48167
48390
|
if (meta.parentID)
|
|
48168
48391
|
continue;
|
|
@@ -48180,7 +48403,7 @@ async function getMainSessions(options) {
|
|
|
48180
48403
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
48181
48404
|
}
|
|
48182
48405
|
async function getAllSessions() {
|
|
48183
|
-
if (!
|
|
48406
|
+
if (!existsSync51(MESSAGE_STORAGE4))
|
|
48184
48407
|
return [];
|
|
48185
48408
|
const sessions = [];
|
|
48186
48409
|
async function scanDirectory(dir) {
|
|
@@ -48188,7 +48411,7 @@ async function getAllSessions() {
|
|
|
48188
48411
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
48189
48412
|
for (const entry of entries) {
|
|
48190
48413
|
if (entry.isDirectory()) {
|
|
48191
|
-
const sessionPath =
|
|
48414
|
+
const sessionPath = join63(dir, entry.name);
|
|
48192
48415
|
const files = await readdir(sessionPath);
|
|
48193
48416
|
if (files.some((f) => f.endsWith(".json"))) {
|
|
48194
48417
|
sessions.push(entry.name);
|
|
@@ -48205,16 +48428,16 @@ async function getAllSessions() {
|
|
|
48205
48428
|
return [...new Set(sessions)];
|
|
48206
48429
|
}
|
|
48207
48430
|
function getMessageDir6(sessionID) {
|
|
48208
|
-
if (!
|
|
48431
|
+
if (!existsSync51(MESSAGE_STORAGE4))
|
|
48209
48432
|
return "";
|
|
48210
|
-
const directPath =
|
|
48211
|
-
if (
|
|
48433
|
+
const directPath = join63(MESSAGE_STORAGE4, sessionID);
|
|
48434
|
+
if (existsSync51(directPath)) {
|
|
48212
48435
|
return directPath;
|
|
48213
48436
|
}
|
|
48214
48437
|
try {
|
|
48215
48438
|
for (const dir of readdirSync16(MESSAGE_STORAGE4)) {
|
|
48216
|
-
const sessionPath =
|
|
48217
|
-
if (
|
|
48439
|
+
const sessionPath = join63(MESSAGE_STORAGE4, dir, sessionID);
|
|
48440
|
+
if (existsSync51(sessionPath)) {
|
|
48218
48441
|
return sessionPath;
|
|
48219
48442
|
}
|
|
48220
48443
|
}
|
|
@@ -48228,7 +48451,7 @@ function sessionExists(sessionID) {
|
|
|
48228
48451
|
}
|
|
48229
48452
|
async function readSessionMessages(sessionID) {
|
|
48230
48453
|
const messageDir = getMessageDir6(sessionID);
|
|
48231
|
-
if (!messageDir || !
|
|
48454
|
+
if (!messageDir || !existsSync51(messageDir))
|
|
48232
48455
|
return [];
|
|
48233
48456
|
const messages = [];
|
|
48234
48457
|
try {
|
|
@@ -48237,7 +48460,7 @@ async function readSessionMessages(sessionID) {
|
|
|
48237
48460
|
if (!file2.endsWith(".json"))
|
|
48238
48461
|
continue;
|
|
48239
48462
|
try {
|
|
48240
|
-
const content = await readFile(
|
|
48463
|
+
const content = await readFile(join63(messageDir, file2), "utf-8");
|
|
48241
48464
|
const meta = JSON.parse(content);
|
|
48242
48465
|
const parts = await readParts2(meta.id);
|
|
48243
48466
|
messages.push({
|
|
@@ -48263,8 +48486,8 @@ async function readSessionMessages(sessionID) {
|
|
|
48263
48486
|
});
|
|
48264
48487
|
}
|
|
48265
48488
|
async function readParts2(messageID) {
|
|
48266
|
-
const partDir =
|
|
48267
|
-
if (!
|
|
48489
|
+
const partDir = join63(PART_STORAGE4, messageID);
|
|
48490
|
+
if (!existsSync51(partDir))
|
|
48268
48491
|
return [];
|
|
48269
48492
|
const parts = [];
|
|
48270
48493
|
try {
|
|
@@ -48273,7 +48496,7 @@ async function readParts2(messageID) {
|
|
|
48273
48496
|
if (!file2.endsWith(".json"))
|
|
48274
48497
|
continue;
|
|
48275
48498
|
try {
|
|
48276
|
-
const content = await readFile(
|
|
48499
|
+
const content = await readFile(join63(partDir, file2), "utf-8");
|
|
48277
48500
|
parts.push(JSON.parse(content));
|
|
48278
48501
|
} catch {
|
|
48279
48502
|
continue;
|
|
@@ -48285,14 +48508,14 @@ async function readParts2(messageID) {
|
|
|
48285
48508
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
48286
48509
|
}
|
|
48287
48510
|
async function readSessionTodos(sessionID) {
|
|
48288
|
-
if (!
|
|
48511
|
+
if (!existsSync51(TODO_DIR2))
|
|
48289
48512
|
return [];
|
|
48290
48513
|
try {
|
|
48291
48514
|
const allFiles = await readdir(TODO_DIR2);
|
|
48292
48515
|
const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
|
|
48293
48516
|
for (const file2 of todoFiles) {
|
|
48294
48517
|
try {
|
|
48295
|
-
const content = await readFile(
|
|
48518
|
+
const content = await readFile(join63(TODO_DIR2, file2), "utf-8");
|
|
48296
48519
|
const data = JSON.parse(content);
|
|
48297
48520
|
if (Array.isArray(data)) {
|
|
48298
48521
|
return data.map((item) => ({
|
|
@@ -48312,10 +48535,10 @@ async function readSessionTodos(sessionID) {
|
|
|
48312
48535
|
return [];
|
|
48313
48536
|
}
|
|
48314
48537
|
async function readSessionTranscript(sessionID) {
|
|
48315
|
-
if (!
|
|
48538
|
+
if (!existsSync51(TRANSCRIPT_DIR2))
|
|
48316
48539
|
return 0;
|
|
48317
|
-
const transcriptFile =
|
|
48318
|
-
if (!
|
|
48540
|
+
const transcriptFile = join63(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
48541
|
+
if (!existsSync51(transcriptFile))
|
|
48319
48542
|
return 0;
|
|
48320
48543
|
try {
|
|
48321
48544
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -49138,6 +49361,7 @@ var BACKGROUND_OUTPUT_DESCRIPTION = `\u83B7\u53D6\u540E\u53F0\u4EFB\u52A1\u7684\
|
|
|
49138
49361
|
var BACKGROUND_CANCEL_DESCRIPTION = `\u53D6\u6D88\u6B63\u5728\u8FD0\u884C\u7684\u540E\u53F0\u4EFB\u52A1\u3002\u4F7F\u7528 all=true \u53EF\u5728\u6700\u7EC8\u56DE\u7B54\u524D\u53D6\u6D88\u6240\u6709\u4EFB\u52A1\u3002`;
|
|
49139
49362
|
|
|
49140
49363
|
// src/tools/background-task/tools.ts
|
|
49364
|
+
init_claude_code_session_state();
|
|
49141
49365
|
init_logger();
|
|
49142
49366
|
init_session_cursor();
|
|
49143
49367
|
init_agent_display_names();
|
|
@@ -49522,20 +49746,21 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
|
|
|
49522
49746
|
|
|
49523
49747
|
\u4F20\u5165 \`session_id=<id>\` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684 agent\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002Prompts \u5FC5\u987B\u4E3A\u4E2D\u6587\u3002\u4F7F\u7528 \`background_output\` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002`;
|
|
49524
49748
|
// src/tools/call-omo-agent/tools.ts
|
|
49525
|
-
import { existsSync as
|
|
49526
|
-
import { join as
|
|
49749
|
+
import { existsSync as existsSync52, readdirSync as readdirSync17 } from "fs";
|
|
49750
|
+
import { join as join64 } from "path";
|
|
49527
49751
|
init_shared();
|
|
49528
49752
|
init_agent_display_names();
|
|
49529
49753
|
init_session_cursor();
|
|
49754
|
+
init_claude_code_session_state();
|
|
49530
49755
|
function getMessageDir7(sessionID) {
|
|
49531
|
-
if (!
|
|
49756
|
+
if (!existsSync52(MESSAGE_STORAGE))
|
|
49532
49757
|
return null;
|
|
49533
|
-
const directPath =
|
|
49534
|
-
if (
|
|
49758
|
+
const directPath = join64(MESSAGE_STORAGE, sessionID);
|
|
49759
|
+
if (existsSync52(directPath))
|
|
49535
49760
|
return directPath;
|
|
49536
49761
|
for (const dir of readdirSync17(MESSAGE_STORAGE)) {
|
|
49537
|
-
const sessionPath =
|
|
49538
|
-
if (
|
|
49762
|
+
const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
|
|
49763
|
+
if (existsSync52(sessionPath))
|
|
49539
49764
|
return sessionPath;
|
|
49540
49765
|
}
|
|
49541
49766
|
return null;
|
|
@@ -49961,8 +50186,8 @@ function createLookAt(ctx) {
|
|
|
49961
50186
|
}
|
|
49962
50187
|
// src/tools/delegate-task/tools.ts
|
|
49963
50188
|
init_constants();
|
|
49964
|
-
import { existsSync as
|
|
49965
|
-
import { join as
|
|
50189
|
+
import { existsSync as existsSync53, readdirSync as readdirSync18 } from "fs";
|
|
50190
|
+
import { join as join65 } from "path";
|
|
49966
50191
|
|
|
49967
50192
|
// src/features/task-toast-manager/manager.ts
|
|
49968
50193
|
class TaskToastManager {
|
|
@@ -50138,10 +50363,12 @@ function initTaskToastManager(client2, concurrencyManager) {
|
|
|
50138
50363
|
return instance;
|
|
50139
50364
|
}
|
|
50140
50365
|
// src/tools/delegate-task/tools.ts
|
|
50366
|
+
init_claude_code_session_state();
|
|
50141
50367
|
init_shared();
|
|
50142
50368
|
init_agent_display_names();
|
|
50143
50369
|
init_runtime_fallback();
|
|
50144
50370
|
init_model_health_registry();
|
|
50371
|
+
init_agent_identity_resolver();
|
|
50145
50372
|
var SISYPHUS_JUNIOR_AGENT = "\u6267\u884C\u52A9\u7406";
|
|
50146
50373
|
var MAX_LOOP_ATTEMPTS = 10;
|
|
50147
50374
|
function sleep(ms) {
|
|
@@ -50168,14 +50395,14 @@ function parseFallbackModelEntries(entries) {
|
|
|
50168
50395
|
});
|
|
50169
50396
|
}
|
|
50170
50397
|
function getMessageDir8(sessionID) {
|
|
50171
|
-
if (!
|
|
50398
|
+
if (!existsSync53(MESSAGE_STORAGE))
|
|
50172
50399
|
return null;
|
|
50173
|
-
const directPath =
|
|
50174
|
-
if (
|
|
50400
|
+
const directPath = join65(MESSAGE_STORAGE, sessionID);
|
|
50401
|
+
if (existsSync53(directPath))
|
|
50175
50402
|
return directPath;
|
|
50176
50403
|
for (const dir of readdirSync18(MESSAGE_STORAGE)) {
|
|
50177
|
-
const sessionPath =
|
|
50178
|
-
if (
|
|
50404
|
+
const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
|
|
50405
|
+
if (existsSync53(sessionPath))
|
|
50179
50406
|
return sessionPath;
|
|
50180
50407
|
}
|
|
50181
50408
|
return null;
|
|
@@ -50257,18 +50484,30 @@ function buildSystemContent(input) {
|
|
|
50257
50484
|
|
|
50258
50485
|
`);
|
|
50259
50486
|
}
|
|
50260
|
-
function extractResumeInfoFromMessages(messages) {
|
|
50261
|
-
|
|
50262
|
-
|
|
50487
|
+
function extractResumeInfoFromMessages(sessionID, messages) {
|
|
50488
|
+
const resolvedAgent = resolveCurrentAgent(sessionID);
|
|
50489
|
+
if (resolvedAgent) {
|
|
50490
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
50491
|
+
const info = messages[i].info;
|
|
50492
|
+
if (info?.model || info?.modelID && info?.providerID) {
|
|
50493
|
+
return {
|
|
50494
|
+
agent: resolvedAgent,
|
|
50495
|
+
model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
|
|
50496
|
+
};
|
|
50497
|
+
}
|
|
50498
|
+
}
|
|
50499
|
+
return { agent: resolvedAgent, model: undefined };
|
|
50500
|
+
}
|
|
50263
50501
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
50264
50502
|
const info = messages[i].info;
|
|
50265
50503
|
if (info?.role === "assistant" && (info?.agent || info?.model || info?.modelID && info?.providerID)) {
|
|
50266
|
-
|
|
50267
|
-
|
|
50268
|
-
|
|
50504
|
+
return {
|
|
50505
|
+
agent: info.agent,
|
|
50506
|
+
model: info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined)
|
|
50507
|
+
};
|
|
50269
50508
|
}
|
|
50270
50509
|
}
|
|
50271
|
-
return { agent, model };
|
|
50510
|
+
return { agent: undefined, model: undefined };
|
|
50272
50511
|
}
|
|
50273
50512
|
async function pollTaskCompletion(client2, sessionID, maxWaitMs = 120000, pollIntervalMs = 2000) {
|
|
50274
50513
|
const startTime = Date.now();
|
|
@@ -50446,7 +50685,7 @@ Agent \u7EE7\u7EED\u6267\u884C\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u
|
|
|
50446
50685
|
try {
|
|
50447
50686
|
const messagesResp = await client2.session.messages({ path: { id: args.session_id } });
|
|
50448
50687
|
const messages2 = messagesResp.data ?? [];
|
|
50449
|
-
const resumeInfo = extractResumeInfoFromMessages(messages2);
|
|
50688
|
+
const resumeInfo = extractResumeInfoFromMessages(args.session_id, messages2);
|
|
50450
50689
|
resumeAgent = resumeInfo.agent;
|
|
50451
50690
|
resumeModel = resumeInfo.model;
|
|
50452
50691
|
} catch {
|
|
@@ -51271,8 +51510,10 @@ class PerformanceAggregator {
|
|
|
51271
51510
|
}
|
|
51272
51511
|
|
|
51273
51512
|
// src/features/background-agent/manager.ts
|
|
51274
|
-
|
|
51275
|
-
|
|
51513
|
+
init_claude_code_session_state();
|
|
51514
|
+
init_agent_identity_resolver();
|
|
51515
|
+
import { existsSync as existsSync54, readdirSync as readdirSync19 } from "fs";
|
|
51516
|
+
import { join as join66 } from "path";
|
|
51276
51517
|
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
51277
51518
|
var MIN_STABILITY_TIME_MS = 10 * 1000;
|
|
51278
51519
|
var DEFAULT_STALE_TIMEOUT_MS = 120000;
|
|
@@ -52065,15 +52306,15 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
52065
52306
|
\u4F7F\u7528 \`background_output(task_id="${task.id}")\` \u5728\u51C6\u5907\u5C31\u7EEA\u65F6\u83B7\u53D6\u6B64\u7ED3\u679C\u3002
|
|
52066
52307
|
</system-reminder>`;
|
|
52067
52308
|
}
|
|
52068
|
-
|
|
52309
|
+
const currentParentAgent = resolveCurrentAgent(task.parentSessionID);
|
|
52310
|
+
const agent = currentParentAgent ?? task.parentAgent;
|
|
52069
52311
|
let model;
|
|
52070
52312
|
try {
|
|
52071
52313
|
const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionID } });
|
|
52072
52314
|
const messages = messagesResp.data ?? [];
|
|
52073
52315
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
52074
52316
|
const info = messages[i].info;
|
|
52075
|
-
if (info?.
|
|
52076
|
-
agent = info.agent ?? task.parentAgent;
|
|
52317
|
+
if (info?.model || info?.modelID && info?.providerID) {
|
|
52077
52318
|
model = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined);
|
|
52078
52319
|
break;
|
|
52079
52320
|
}
|
|
@@ -52081,7 +52322,6 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
52081
52322
|
} catch {
|
|
52082
52323
|
const messageDir = getMessageDir9(task.parentSessionID);
|
|
52083
52324
|
const currentMessage = messageDir ? findNearestAssistantMessage(messageDir) : null;
|
|
52084
|
-
agent = currentMessage?.agent ?? task.parentAgent;
|
|
52085
52325
|
model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
|
|
52086
52326
|
}
|
|
52087
52327
|
log("[background-agent] notifyParentSession context:", {
|
|
@@ -52446,14 +52686,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
52446
52686
|
return listener;
|
|
52447
52687
|
}
|
|
52448
52688
|
function getMessageDir9(sessionID) {
|
|
52449
|
-
if (!
|
|
52689
|
+
if (!existsSync54(MESSAGE_STORAGE))
|
|
52450
52690
|
return null;
|
|
52451
|
-
const directPath =
|
|
52452
|
-
if (
|
|
52691
|
+
const directPath = join66(MESSAGE_STORAGE, sessionID);
|
|
52692
|
+
if (existsSync54(directPath))
|
|
52453
52693
|
return directPath;
|
|
52454
52694
|
for (const dir of readdirSync19(MESSAGE_STORAGE)) {
|
|
52455
|
-
const sessionPath =
|
|
52456
|
-
if (
|
|
52695
|
+
const sessionPath = join66(MESSAGE_STORAGE, dir, sessionID);
|
|
52696
|
+
if (existsSync54(sessionPath))
|
|
52457
52697
|
return sessionPath;
|
|
52458
52698
|
}
|
|
52459
52699
|
return null;
|
|
@@ -71678,7 +71918,7 @@ init_file_utils();
|
|
|
71678
71918
|
init_shared();
|
|
71679
71919
|
init_logger();
|
|
71680
71920
|
import { promises as fs11 } from "fs";
|
|
71681
|
-
import { join as
|
|
71921
|
+
import { join as join68, basename as basename6 } from "path";
|
|
71682
71922
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
71683
71923
|
try {
|
|
71684
71924
|
await fs11.access(commandsDir);
|
|
@@ -71708,7 +71948,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71708
71948
|
if (entry.isDirectory()) {
|
|
71709
71949
|
if (entry.name.startsWith("."))
|
|
71710
71950
|
continue;
|
|
71711
|
-
const subDirPath =
|
|
71951
|
+
const subDirPath = join68(commandsDir, entry.name);
|
|
71712
71952
|
const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
71713
71953
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
71714
71954
|
commands2.push(...subCommands);
|
|
@@ -71716,7 +71956,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71716
71956
|
}
|
|
71717
71957
|
if (!isMarkdownFile(entry))
|
|
71718
71958
|
continue;
|
|
71719
|
-
const commandPath =
|
|
71959
|
+
const commandPath = join68(commandsDir, entry.name);
|
|
71720
71960
|
const baseCommandName = basename6(entry.name, ".md");
|
|
71721
71961
|
const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
|
|
71722
71962
|
try {
|
|
@@ -71763,23 +72003,23 @@ function commandsToRecord(commands2) {
|
|
|
71763
72003
|
return result;
|
|
71764
72004
|
}
|
|
71765
72005
|
async function loadUserCommands() {
|
|
71766
|
-
const userCommandsDir =
|
|
72006
|
+
const userCommandsDir = join68(getClaudeConfigDir(), "commands");
|
|
71767
72007
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
71768
72008
|
return commandsToRecord(commands2);
|
|
71769
72009
|
}
|
|
71770
72010
|
async function loadProjectCommands() {
|
|
71771
|
-
const projectCommandsDir =
|
|
72011
|
+
const projectCommandsDir = join68(process.cwd(), ".claude", "commands");
|
|
71772
72012
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
71773
72013
|
return commandsToRecord(commands2);
|
|
71774
72014
|
}
|
|
71775
72015
|
async function loadOpencodeGlobalCommands() {
|
|
71776
72016
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
71777
|
-
const opencodeCommandsDir =
|
|
72017
|
+
const opencodeCommandsDir = join68(configDir, "command");
|
|
71778
72018
|
const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
71779
72019
|
return commandsToRecord(commands2);
|
|
71780
72020
|
}
|
|
71781
72021
|
async function loadOpencodeProjectCommands() {
|
|
71782
|
-
const opencodeProjectDir =
|
|
72022
|
+
const opencodeProjectDir = join68(process.cwd(), ".opencode", "command");
|
|
71783
72023
|
const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
71784
72024
|
return commandsToRecord(commands2);
|
|
71785
72025
|
}
|
|
@@ -71787,8 +72027,8 @@ async function loadOpencodeProjectCommands() {
|
|
|
71787
72027
|
init_frontmatter();
|
|
71788
72028
|
init_file_utils();
|
|
71789
72029
|
init_shared();
|
|
71790
|
-
import { existsSync as
|
|
71791
|
-
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";
|
|
71792
72032
|
function parseToolsConfig(toolsStr) {
|
|
71793
72033
|
if (!toolsStr)
|
|
71794
72034
|
return;
|
|
@@ -71802,7 +72042,7 @@ function parseToolsConfig(toolsStr) {
|
|
|
71802
72042
|
return result;
|
|
71803
72043
|
}
|
|
71804
72044
|
function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
71805
|
-
if (!
|
|
72045
|
+
if (!existsSync56(agentsDir)) {
|
|
71806
72046
|
return [];
|
|
71807
72047
|
}
|
|
71808
72048
|
const entries = readdirSync20(agentsDir, { withFileTypes: true });
|
|
@@ -71810,10 +72050,10 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
|
71810
72050
|
for (const entry of entries) {
|
|
71811
72051
|
if (!isMarkdownFile(entry))
|
|
71812
72052
|
continue;
|
|
71813
|
-
const agentPath =
|
|
72053
|
+
const agentPath = join69(agentsDir, entry.name);
|
|
71814
72054
|
const agentName = basename7(entry.name, ".md");
|
|
71815
72055
|
try {
|
|
71816
|
-
const content =
|
|
72056
|
+
const content = readFileSync39(agentPath, "utf-8");
|
|
71817
72057
|
const { data, body } = parseFrontmatter(content);
|
|
71818
72058
|
const name = data.name || agentName;
|
|
71819
72059
|
const originalDescription = data.description || "";
|
|
@@ -71842,7 +72082,7 @@ function loadAgentsFromDir(agentsDir, scope, leConfig) {
|
|
|
71842
72082
|
return agents;
|
|
71843
72083
|
}
|
|
71844
72084
|
function loadUserAgents(leConfig) {
|
|
71845
|
-
const userAgentsDir =
|
|
72085
|
+
const userAgentsDir = join69(getClaudeConfigDir(), "agents");
|
|
71846
72086
|
const agents = loadAgentsFromDir(userAgentsDir, "user", leConfig);
|
|
71847
72087
|
const result = {};
|
|
71848
72088
|
for (const agent of agents) {
|
|
@@ -71851,7 +72091,7 @@ function loadUserAgents(leConfig) {
|
|
|
71851
72091
|
return result;
|
|
71852
72092
|
}
|
|
71853
72093
|
function loadProjectAgents(leConfig) {
|
|
71854
|
-
const projectAgentsDir =
|
|
72094
|
+
const projectAgentsDir = join69(process.cwd(), ".claude", "agents");
|
|
71855
72095
|
const agents = loadAgentsFromDir(projectAgentsDir, "project", leConfig);
|
|
71856
72096
|
const result = {};
|
|
71857
72097
|
for (const agent of agents) {
|
|
@@ -71863,18 +72103,18 @@ function loadProjectAgents(leConfig) {
|
|
|
71863
72103
|
init_frontmatter();
|
|
71864
72104
|
init_file_utils();
|
|
71865
72105
|
init_logger();
|
|
71866
|
-
import { existsSync as
|
|
72106
|
+
import { existsSync as existsSync57, readdirSync as readdirSync21, readFileSync as readFileSync40 } from "fs";
|
|
71867
72107
|
import { homedir as homedir14 } from "os";
|
|
71868
|
-
import { join as
|
|
72108
|
+
import { join as join70, basename as basename8 } from "path";
|
|
71869
72109
|
var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
71870
72110
|
function getPluginsBaseDir() {
|
|
71871
72111
|
if (process.env.CLAUDE_PLUGINS_HOME) {
|
|
71872
72112
|
return process.env.CLAUDE_PLUGINS_HOME;
|
|
71873
72113
|
}
|
|
71874
|
-
return
|
|
72114
|
+
return join70(homedir14(), ".claude", "plugins");
|
|
71875
72115
|
}
|
|
71876
72116
|
function getInstalledPluginsPath() {
|
|
71877
|
-
return
|
|
72117
|
+
return join70(getPluginsBaseDir(), "installed_plugins.json");
|
|
71878
72118
|
}
|
|
71879
72119
|
function resolvePluginPath(path8, pluginRoot) {
|
|
71880
72120
|
return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
|
|
@@ -71899,11 +72139,11 @@ function resolvePluginPaths(obj, pluginRoot) {
|
|
|
71899
72139
|
}
|
|
71900
72140
|
function loadInstalledPlugins() {
|
|
71901
72141
|
const dbPath = getInstalledPluginsPath();
|
|
71902
|
-
if (!
|
|
72142
|
+
if (!existsSync57(dbPath)) {
|
|
71903
72143
|
return null;
|
|
71904
72144
|
}
|
|
71905
72145
|
try {
|
|
71906
|
-
const content =
|
|
72146
|
+
const content = readFileSync40(dbPath, "utf-8");
|
|
71907
72147
|
return JSON.parse(content);
|
|
71908
72148
|
} catch (error95) {
|
|
71909
72149
|
log("Failed to load installed plugins database", error95);
|
|
@@ -71914,15 +72154,15 @@ function getClaudeSettingsPath() {
|
|
|
71914
72154
|
if (process.env.CLAUDE_SETTINGS_PATH) {
|
|
71915
72155
|
return process.env.CLAUDE_SETTINGS_PATH;
|
|
71916
72156
|
}
|
|
71917
|
-
return
|
|
72157
|
+
return join70(homedir14(), ".claude", "settings.json");
|
|
71918
72158
|
}
|
|
71919
72159
|
function loadClaudeSettings() {
|
|
71920
72160
|
const settingsPath = getClaudeSettingsPath();
|
|
71921
|
-
if (!
|
|
72161
|
+
if (!existsSync57(settingsPath)) {
|
|
71922
72162
|
return null;
|
|
71923
72163
|
}
|
|
71924
72164
|
try {
|
|
71925
|
-
const content =
|
|
72165
|
+
const content = readFileSync40(settingsPath, "utf-8");
|
|
71926
72166
|
return JSON.parse(content);
|
|
71927
72167
|
} catch (error95) {
|
|
71928
72168
|
log("Failed to load Claude settings", error95);
|
|
@@ -71930,12 +72170,12 @@ function loadClaudeSettings() {
|
|
|
71930
72170
|
}
|
|
71931
72171
|
}
|
|
71932
72172
|
function loadPluginManifest(installPath) {
|
|
71933
|
-
const manifestPath =
|
|
71934
|
-
if (!
|
|
72173
|
+
const manifestPath = join70(installPath, ".claude-plugin", "plugin.json");
|
|
72174
|
+
if (!existsSync57(manifestPath)) {
|
|
71935
72175
|
return null;
|
|
71936
72176
|
}
|
|
71937
72177
|
try {
|
|
71938
|
-
const content =
|
|
72178
|
+
const content = readFileSync40(manifestPath, "utf-8");
|
|
71939
72179
|
return JSON.parse(content);
|
|
71940
72180
|
} catch (error95) {
|
|
71941
72181
|
log(`Failed to load plugin manifest from ${manifestPath}`, error95);
|
|
@@ -71982,7 +72222,7 @@ function discoverInstalledPlugins(options) {
|
|
|
71982
72222
|
continue;
|
|
71983
72223
|
}
|
|
71984
72224
|
const { installPath, scope, version: version3 } = installation;
|
|
71985
|
-
if (!
|
|
72225
|
+
if (!existsSync57(installPath)) {
|
|
71986
72226
|
errors5.push({
|
|
71987
72227
|
pluginKey,
|
|
71988
72228
|
installPath,
|
|
@@ -72000,21 +72240,21 @@ function discoverInstalledPlugins(options) {
|
|
|
72000
72240
|
pluginKey,
|
|
72001
72241
|
manifest: manifest ?? undefined
|
|
72002
72242
|
};
|
|
72003
|
-
if (
|
|
72004
|
-
loadedPlugin.commandsDir =
|
|
72243
|
+
if (existsSync57(join70(installPath, "commands"))) {
|
|
72244
|
+
loadedPlugin.commandsDir = join70(installPath, "commands");
|
|
72005
72245
|
}
|
|
72006
|
-
if (
|
|
72007
|
-
loadedPlugin.agentsDir =
|
|
72246
|
+
if (existsSync57(join70(installPath, "agents"))) {
|
|
72247
|
+
loadedPlugin.agentsDir = join70(installPath, "agents");
|
|
72008
72248
|
}
|
|
72009
|
-
if (
|
|
72010
|
-
loadedPlugin.skillsDir =
|
|
72249
|
+
if (existsSync57(join70(installPath, "skills"))) {
|
|
72250
|
+
loadedPlugin.skillsDir = join70(installPath, "skills");
|
|
72011
72251
|
}
|
|
72012
|
-
const hooksPath =
|
|
72013
|
-
if (
|
|
72252
|
+
const hooksPath = join70(installPath, "hooks", "hooks.json");
|
|
72253
|
+
if (existsSync57(hooksPath)) {
|
|
72014
72254
|
loadedPlugin.hooksPath = hooksPath;
|
|
72015
72255
|
}
|
|
72016
|
-
const mcpPath =
|
|
72017
|
-
if (
|
|
72256
|
+
const mcpPath = join70(installPath, ".mcp.json");
|
|
72257
|
+
if (existsSync57(mcpPath)) {
|
|
72018
72258
|
loadedPlugin.mcpPath = mcpPath;
|
|
72019
72259
|
}
|
|
72020
72260
|
plugins.push(loadedPlugin);
|
|
@@ -72025,17 +72265,17 @@ function discoverInstalledPlugins(options) {
|
|
|
72025
72265
|
function loadPluginCommands(plugins) {
|
|
72026
72266
|
const commands2 = {};
|
|
72027
72267
|
for (const plugin of plugins) {
|
|
72028
|
-
if (!plugin.commandsDir || !
|
|
72268
|
+
if (!plugin.commandsDir || !existsSync57(plugin.commandsDir))
|
|
72029
72269
|
continue;
|
|
72030
72270
|
const entries = readdirSync21(plugin.commandsDir, { withFileTypes: true });
|
|
72031
72271
|
for (const entry of entries) {
|
|
72032
72272
|
if (!isMarkdownFile(entry))
|
|
72033
72273
|
continue;
|
|
72034
|
-
const commandPath =
|
|
72274
|
+
const commandPath = join70(plugin.commandsDir, entry.name);
|
|
72035
72275
|
const commandName = basename8(entry.name, ".md");
|
|
72036
72276
|
const namespacedName = `${plugin.name}:${commandName}`;
|
|
72037
72277
|
try {
|
|
72038
|
-
const content =
|
|
72278
|
+
const content = readFileSync40(commandPath, "utf-8");
|
|
72039
72279
|
const { data, body } = parseFrontmatter(content);
|
|
72040
72280
|
const wrappedTemplate = `<command-instruction>
|
|
72041
72281
|
${body.trim()}
|
|
@@ -72067,21 +72307,21 @@ $ARGUMENTS
|
|
|
72067
72307
|
function loadPluginSkillsAsCommands(plugins) {
|
|
72068
72308
|
const skills = {};
|
|
72069
72309
|
for (const plugin of plugins) {
|
|
72070
|
-
if (!plugin.skillsDir || !
|
|
72310
|
+
if (!plugin.skillsDir || !existsSync57(plugin.skillsDir))
|
|
72071
72311
|
continue;
|
|
72072
72312
|
const entries = readdirSync21(plugin.skillsDir, { withFileTypes: true });
|
|
72073
72313
|
for (const entry of entries) {
|
|
72074
72314
|
if (entry.name.startsWith("."))
|
|
72075
72315
|
continue;
|
|
72076
|
-
const skillPath =
|
|
72316
|
+
const skillPath = join70(plugin.skillsDir, entry.name);
|
|
72077
72317
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
72078
72318
|
continue;
|
|
72079
72319
|
const resolvedPath = resolveSymlink(skillPath);
|
|
72080
|
-
const skillMdPath =
|
|
72081
|
-
if (!
|
|
72320
|
+
const skillMdPath = join70(resolvedPath, "SKILL.md");
|
|
72321
|
+
if (!existsSync57(skillMdPath))
|
|
72082
72322
|
continue;
|
|
72083
72323
|
try {
|
|
72084
|
-
const content =
|
|
72324
|
+
const content = readFileSync40(skillMdPath, "utf-8");
|
|
72085
72325
|
const { data, body } = parseFrontmatter(content);
|
|
72086
72326
|
const skillName = data.name || entry.name;
|
|
72087
72327
|
const namespacedName = `${plugin.name}:${skillName}`;
|
|
@@ -72128,17 +72368,17 @@ function parseToolsConfig2(toolsStr) {
|
|
|
72128
72368
|
function loadPluginAgents(plugins) {
|
|
72129
72369
|
const agents = {};
|
|
72130
72370
|
for (const plugin of plugins) {
|
|
72131
|
-
if (!plugin.agentsDir || !
|
|
72371
|
+
if (!plugin.agentsDir || !existsSync57(plugin.agentsDir))
|
|
72132
72372
|
continue;
|
|
72133
72373
|
const entries = readdirSync21(plugin.agentsDir, { withFileTypes: true });
|
|
72134
72374
|
for (const entry of entries) {
|
|
72135
72375
|
if (!isMarkdownFile(entry))
|
|
72136
72376
|
continue;
|
|
72137
|
-
const agentPath =
|
|
72377
|
+
const agentPath = join70(plugin.agentsDir, entry.name);
|
|
72138
72378
|
const agentName = basename8(entry.name, ".md");
|
|
72139
72379
|
const namespacedName = `${plugin.name}:${agentName}`;
|
|
72140
72380
|
try {
|
|
72141
|
-
const content =
|
|
72381
|
+
const content = readFileSync40(agentPath, "utf-8");
|
|
72142
72382
|
const { data, body } = parseFrontmatter(content);
|
|
72143
72383
|
const name = data.name || agentName;
|
|
72144
72384
|
const originalDescription = data.description || "";
|
|
@@ -72164,7 +72404,7 @@ function loadPluginAgents(plugins) {
|
|
|
72164
72404
|
async function loadPluginMcpServers(plugins) {
|
|
72165
72405
|
const servers = {};
|
|
72166
72406
|
for (const plugin of plugins) {
|
|
72167
|
-
if (!plugin.mcpPath || !
|
|
72407
|
+
if (!plugin.mcpPath || !existsSync57(plugin.mcpPath))
|
|
72168
72408
|
continue;
|
|
72169
72409
|
try {
|
|
72170
72410
|
const content = await Bun.file(plugin.mcpPath).text();
|
|
@@ -72196,10 +72436,10 @@ async function loadPluginMcpServers(plugins) {
|
|
|
72196
72436
|
function loadPluginHooksConfigs(plugins) {
|
|
72197
72437
|
const configs = [];
|
|
72198
72438
|
for (const plugin of plugins) {
|
|
72199
|
-
if (!plugin.hooksPath || !
|
|
72439
|
+
if (!plugin.hooksPath || !existsSync57(plugin.hooksPath))
|
|
72200
72440
|
continue;
|
|
72201
72441
|
try {
|
|
72202
|
-
const content =
|
|
72442
|
+
const content = readFileSync40(plugin.hooksPath, "utf-8");
|
|
72203
72443
|
let config4 = JSON.parse(content);
|
|
72204
72444
|
config4 = resolvePluginPaths(config4, plugin.installPath);
|
|
72205
72445
|
configs.push(config4);
|
|
@@ -73820,7 +74060,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
73820
74060
|
return;
|
|
73821
74061
|
}
|
|
73822
74062
|
log("[OhMyOpenCodePlugin] Starting session agent recovery...");
|
|
73823
|
-
const recoveredAgents = recoverSessionAgents();
|
|
74063
|
+
const recoveredAgents = recoverSessionAgents(ctx.directory);
|
|
73824
74064
|
log("[OhMyOpenCodePlugin] Session agent recovery complete", { recoveredAgents });
|
|
73825
74065
|
startBackgroundCheck2();
|
|
73826
74066
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx);
|
|
@@ -74072,6 +74312,11 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74072
74312
|
updateSessionAgent(input.sessionID, validatedAgent ?? input.agent, "chat.message");
|
|
74073
74313
|
} else {
|
|
74074
74314
|
const staleThresholdMs = pluginConfig.identity?.staleThresholdMs ?? 600000;
|
|
74315
|
+
if (!getSessionAgent(input.sessionID)) {
|
|
74316
|
+
log("[identity] chat.message without agent info and no session agent", {
|
|
74317
|
+
sessionID: input.sessionID
|
|
74318
|
+
});
|
|
74319
|
+
}
|
|
74075
74320
|
if (isSessionAgentStale(input.sessionID, staleThresholdMs)) {
|
|
74076
74321
|
log("[identity] session agent stale", { sessionID: input.sessionID, staleThresholdMs });
|
|
74077
74322
|
const messageFileAgent = getAgentFromSessionMessages(input.sessionID);
|
|
@@ -74203,6 +74448,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74203
74448
|
try {
|
|
74204
74449
|
cleanupStaleTmpFiles(ctx.directory);
|
|
74205
74450
|
} catch {}
|
|
74451
|
+
if (sessionInfo?.id) {
|
|
74452
|
+
log("[identity] New main session created", { sessionID: sessionInfo.id });
|
|
74453
|
+
}
|
|
74206
74454
|
}
|
|
74207
74455
|
firstMessageVariantGate.markSessionCreated(sessionInfo);
|
|
74208
74456
|
}
|
|
@@ -74235,6 +74483,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
74235
74483
|
const validatedAgent = validateAndFixAgentIdentity(sessionID, agent);
|
|
74236
74484
|
updateSessionAgent(sessionID, validatedAgent ?? agent, "message.updated");
|
|
74237
74485
|
}
|
|
74486
|
+
if (sessionID && agent && role === "assistant") {
|
|
74487
|
+
updateSessionAgent(sessionID, agent, "message.updated.assistant");
|
|
74488
|
+
}
|
|
74238
74489
|
}
|
|
74239
74490
|
if (event.type === "session.error") {
|
|
74240
74491
|
const sessionID = props?.sessionID;
|