@skj1724/oh-my-opencode 3.19.4 → 3.19.6
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/bin/oh-my-opencode.js +39 -32
- package/dist/agents/atlas.d.ts +1 -1
- package/dist/agents/prometheus-prompt.d.ts +1 -1
- package/dist/cli/index.js +55 -3
- package/dist/config/schema.d.ts +36 -0
- package/dist/features/background-agent/manager.d.ts +6 -0
- package/dist/features/background-agent/types.d.ts +10 -0
- package/dist/features/hook-message-injector/injector.d.ts +0 -6
- package/dist/features/task-toast-manager/manager.d.ts +5 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/perf-profiler/index.d.ts +2 -0
- package/dist/hooks/perf-profiler/index.test.d.ts +1 -0
- package/dist/hooks/perf-profiler/types.d.ts +42 -0
- package/dist/hooks/think-mode/index.d.ts +26 -2
- package/dist/hooks/think-mode/types.d.ts +14 -12
- package/dist/index.js +1463 -774
- package/dist/shared/fileio-monitor.d.ts +10 -0
- package/dist/shared/fileio-monitor.test.d.ts +1 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/perf-tracer.d.ts +73 -0
- package/dist/shared/perf-tracer.test.d.ts +1 -0
- package/dist/shared/windows-reserved-names.d.ts +8 -0
- package/dist/tools/perf-profiler/client-patch.d.ts +2 -0
- package/package.json +1 -1
- package/postinstall.mjs +20 -0
package/dist/index.js
CHANGED
|
@@ -46,6 +46,84 @@ var __export = (target, all) => {
|
|
|
46
46
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
47
|
var __require = import.meta.require;
|
|
48
48
|
|
|
49
|
+
// src/shared/fileio-monitor.ts
|
|
50
|
+
import { readdirSync, readFileSync, writeFileSync, existsSync } from "fs";
|
|
51
|
+
import { relative } from "path";
|
|
52
|
+
import { cwd } from "process";
|
|
53
|
+
function summarize(path) {
|
|
54
|
+
let result;
|
|
55
|
+
try {
|
|
56
|
+
result = relative(cwd(), path);
|
|
57
|
+
} catch {
|
|
58
|
+
result = path;
|
|
59
|
+
}
|
|
60
|
+
if (result.length > MAX_PATH_LENGTH) {
|
|
61
|
+
return result.slice(0, MAX_PATH_LENGTH - 3) + "...";
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function setFileIOMonitor(monitor) {
|
|
66
|
+
globalMonitor = monitor;
|
|
67
|
+
}
|
|
68
|
+
function getFileIOMonitor() {
|
|
69
|
+
return globalMonitor;
|
|
70
|
+
}
|
|
71
|
+
function createFileIOMonitor(tracer) {
|
|
72
|
+
return {
|
|
73
|
+
readdirSync(path) {
|
|
74
|
+
if (!tracer.isEnabled()) {
|
|
75
|
+
return readdirSync(path);
|
|
76
|
+
}
|
|
77
|
+
const start = performance.now();
|
|
78
|
+
try {
|
|
79
|
+
return readdirSync(path);
|
|
80
|
+
} finally {
|
|
81
|
+
const durationMs = performance.now() - start;
|
|
82
|
+
tracer.recordFileIO("readdirSync", summarize(path), durationMs);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
readFileSync(path, options) {
|
|
86
|
+
if (!tracer.isEnabled()) {
|
|
87
|
+
return readFileSync(path, options);
|
|
88
|
+
}
|
|
89
|
+
const start = performance.now();
|
|
90
|
+
try {
|
|
91
|
+
return readFileSync(path, options);
|
|
92
|
+
} finally {
|
|
93
|
+
const durationMs = performance.now() - start;
|
|
94
|
+
tracer.recordFileIO("readFileSync", summarize(path), durationMs);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
writeFileSync(path, data, options) {
|
|
98
|
+
if (!tracer.isEnabled()) {
|
|
99
|
+
writeFileSync(path, data, options);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const start = performance.now();
|
|
103
|
+
try {
|
|
104
|
+
writeFileSync(path, data, options);
|
|
105
|
+
} finally {
|
|
106
|
+
const durationMs = performance.now() - start;
|
|
107
|
+
tracer.recordFileIO("writeFileSync", summarize(path), durationMs);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
existsSync(path) {
|
|
111
|
+
if (!tracer.isEnabled()) {
|
|
112
|
+
return existsSync(path);
|
|
113
|
+
}
|
|
114
|
+
const start = performance.now();
|
|
115
|
+
try {
|
|
116
|
+
return existsSync(path);
|
|
117
|
+
} finally {
|
|
118
|
+
const durationMs = performance.now() - start;
|
|
119
|
+
tracer.recordFileIO("existsSync", summarize(path), durationMs);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
var MAX_PATH_LENGTH = 120, globalMonitor = null;
|
|
125
|
+
var init_fileio_monitor = () => {};
|
|
126
|
+
|
|
49
127
|
// src/shared/data-path.ts
|
|
50
128
|
import * as path from "path";
|
|
51
129
|
import * as os from "os";
|
|
@@ -2767,17 +2845,17 @@ var init_frontmatter = __esm(() => {
|
|
|
2767
2845
|
import { spawn as spawn2 } from "child_process";
|
|
2768
2846
|
import { exec } from "child_process";
|
|
2769
2847
|
import { promisify } from "util";
|
|
2770
|
-
import { existsSync as
|
|
2848
|
+
import { existsSync as existsSync5 } from "fs";
|
|
2771
2849
|
import { homedir as homedir2 } from "os";
|
|
2772
2850
|
function getHomeDir() {
|
|
2773
2851
|
return process.env.HOME || process.env.USERPROFILE || homedir2();
|
|
2774
2852
|
}
|
|
2775
2853
|
function findShellPath(defaultPaths, customPath) {
|
|
2776
|
-
if (customPath &&
|
|
2854
|
+
if (customPath && existsSync5(customPath)) {
|
|
2777
2855
|
return customPath;
|
|
2778
2856
|
}
|
|
2779
2857
|
for (const path3 of defaultPaths) {
|
|
2780
|
-
if (
|
|
2858
|
+
if (existsSync5(path3)) {
|
|
2781
2859
|
return path3;
|
|
2782
2860
|
}
|
|
2783
2861
|
}
|
|
@@ -2789,9 +2867,9 @@ function findZshPath(customZshPath) {
|
|
|
2789
2867
|
function findBashPath() {
|
|
2790
2868
|
return findShellPath(DEFAULT_BASH_PATHS);
|
|
2791
2869
|
}
|
|
2792
|
-
async function executeHookCommand(command, stdin,
|
|
2870
|
+
async function executeHookCommand(command, stdin, cwd2, options) {
|
|
2793
2871
|
const home = getHomeDir();
|
|
2794
|
-
let expandedCommand = command.replace(/^~(?=\/|$)/g, home).replace(/\s~(?=\/)/g, ` ${home}`).replace(/\$CLAUDE_PROJECT_DIR/g,
|
|
2872
|
+
let expandedCommand = command.replace(/^~(?=\/|$)/g, home).replace(/\s~(?=\/)/g, ` ${home}`).replace(/\$CLAUDE_PROJECT_DIR/g, cwd2).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, cwd2);
|
|
2795
2873
|
let finalCommand = expandedCommand;
|
|
2796
2874
|
if (options?.forceZsh) {
|
|
2797
2875
|
const zshPath = findZshPath(options.zshPath);
|
|
@@ -2807,9 +2885,9 @@ async function executeHookCommand(command, stdin, cwd, options) {
|
|
|
2807
2885
|
}
|
|
2808
2886
|
return new Promise((resolve) => {
|
|
2809
2887
|
const proc = spawn2(finalCommand, {
|
|
2810
|
-
cwd,
|
|
2888
|
+
cwd: cwd2,
|
|
2811
2889
|
shell: true,
|
|
2812
|
-
env: { ...process.env, HOME: home, CLAUDE_PROJECT_DIR:
|
|
2890
|
+
env: { ...process.env, HOME: home, CLAUDE_PROJECT_DIR: cwd2 }
|
|
2813
2891
|
});
|
|
2814
2892
|
let stdout = "";
|
|
2815
2893
|
let stderr = "";
|
|
@@ -2912,7 +2990,7 @@ var init_command_executor = __esm(() => {
|
|
|
2912
2990
|
});
|
|
2913
2991
|
|
|
2914
2992
|
// src/shared/file-reference-resolver.ts
|
|
2915
|
-
import { existsSync as
|
|
2993
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, statSync } from "fs";
|
|
2916
2994
|
import { join as join8, isAbsolute } from "path";
|
|
2917
2995
|
function findFileReferences(text) {
|
|
2918
2996
|
const matches = [];
|
|
@@ -2928,24 +3006,24 @@ function findFileReferences(text) {
|
|
|
2928
3006
|
}
|
|
2929
3007
|
return matches;
|
|
2930
3008
|
}
|
|
2931
|
-
function resolveFilePath(filePath,
|
|
3009
|
+
function resolveFilePath(filePath, cwd2) {
|
|
2932
3010
|
if (isAbsolute(filePath)) {
|
|
2933
3011
|
return filePath;
|
|
2934
3012
|
}
|
|
2935
|
-
return join8(
|
|
3013
|
+
return join8(cwd2, filePath);
|
|
2936
3014
|
}
|
|
2937
3015
|
function readFileContent(resolvedPath) {
|
|
2938
|
-
if (!
|
|
3016
|
+
if (!existsSync6(resolvedPath)) {
|
|
2939
3017
|
return `[file not found: ${resolvedPath}]`;
|
|
2940
3018
|
}
|
|
2941
3019
|
const stat = statSync(resolvedPath);
|
|
2942
3020
|
if (stat.isDirectory()) {
|
|
2943
3021
|
return `[cannot read directory: ${resolvedPath}]`;
|
|
2944
3022
|
}
|
|
2945
|
-
const content =
|
|
3023
|
+
const content = readFileSync4(resolvedPath, "utf-8");
|
|
2946
3024
|
return content;
|
|
2947
3025
|
}
|
|
2948
|
-
async function resolveFileReferencesInText(text,
|
|
3026
|
+
async function resolveFileReferencesInText(text, cwd2 = process.cwd(), depth = 0, maxDepth = 3) {
|
|
2949
3027
|
if (depth >= maxDepth) {
|
|
2950
3028
|
return text;
|
|
2951
3029
|
}
|
|
@@ -2955,7 +3033,7 @@ async function resolveFileReferencesInText(text, cwd = process.cwd(), depth = 0,
|
|
|
2955
3033
|
}
|
|
2956
3034
|
const replacements = new Map;
|
|
2957
3035
|
for (const match of matches) {
|
|
2958
|
-
const resolvedPath = resolveFilePath(match.filePath,
|
|
3036
|
+
const resolvedPath = resolveFilePath(match.filePath, cwd2);
|
|
2959
3037
|
const content = readFileContent(resolvedPath);
|
|
2960
3038
|
replacements.set(match.fullMatch, content);
|
|
2961
3039
|
}
|
|
@@ -2964,7 +3042,7 @@ async function resolveFileReferencesInText(text, cwd = process.cwd(), depth = 0,
|
|
|
2964
3042
|
resolved = resolved.split(pattern).join(replacement);
|
|
2965
3043
|
}
|
|
2966
3044
|
if (findFileReferences(resolved).length > 0 && depth + 1 < maxDepth) {
|
|
2967
|
-
return resolveFileReferencesInText(resolved,
|
|
3045
|
+
return resolveFileReferencesInText(resolved, cwd2, depth + 1, maxDepth);
|
|
2968
3046
|
}
|
|
2969
3047
|
return resolved;
|
|
2970
3048
|
}
|
|
@@ -4138,7 +4216,7 @@ var init_main = __esm(() => {
|
|
|
4138
4216
|
});
|
|
4139
4217
|
|
|
4140
4218
|
// src/shared/jsonc-parser.ts
|
|
4141
|
-
import { existsSync as
|
|
4219
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
4142
4220
|
function parseJsonc(content) {
|
|
4143
4221
|
const errors = [];
|
|
4144
4222
|
const result = parse2(content, errors, {
|
|
@@ -4169,10 +4247,10 @@ function parseJsoncSafe(content) {
|
|
|
4169
4247
|
function detectConfigFile(basePath) {
|
|
4170
4248
|
const jsoncPath = `${basePath}.jsonc`;
|
|
4171
4249
|
const jsonPath = `${basePath}.json`;
|
|
4172
|
-
if (
|
|
4250
|
+
if (existsSync7(jsoncPath)) {
|
|
4173
4251
|
return { format: "jsonc", path: jsoncPath };
|
|
4174
4252
|
}
|
|
4175
|
-
if (
|
|
4253
|
+
if (existsSync7(jsonPath)) {
|
|
4176
4254
|
return { format: "json", path: jsonPath };
|
|
4177
4255
|
}
|
|
4178
4256
|
return { format: "none", path: jsonPath };
|
|
@@ -4318,7 +4396,7 @@ var init_migration = __esm(() => {
|
|
|
4318
4396
|
});
|
|
4319
4397
|
|
|
4320
4398
|
// src/shared/opencode-config-dir.ts
|
|
4321
|
-
import { existsSync as
|
|
4399
|
+
import { existsSync as existsSync8 } from "fs";
|
|
4322
4400
|
import { homedir as homedir4 } from "os";
|
|
4323
4401
|
import { join as join10, resolve as resolve2 } from "path";
|
|
4324
4402
|
function isDevBuild(version) {
|
|
@@ -4350,13 +4428,13 @@ function getCliConfigDir() {
|
|
|
4350
4428
|
if (process.platform === "win32") {
|
|
4351
4429
|
const crossPlatformDir = join10(homedir4(), ".config", "opencode");
|
|
4352
4430
|
const crossPlatformConfig = join10(crossPlatformDir, "opencode.json");
|
|
4353
|
-
if (
|
|
4431
|
+
if (existsSync8(crossPlatformConfig)) {
|
|
4354
4432
|
return crossPlatformDir;
|
|
4355
4433
|
}
|
|
4356
4434
|
const appData = process.env.APPDATA || join10(homedir4(), "AppData", "Roaming");
|
|
4357
4435
|
const appdataDir = join10(appData, "opencode");
|
|
4358
4436
|
const appdataConfig = join10(appdataDir, "opencode.json");
|
|
4359
|
-
if (
|
|
4437
|
+
if (existsSync8(appdataConfig)) {
|
|
4360
4438
|
return appdataDir;
|
|
4361
4439
|
}
|
|
4362
4440
|
return crossPlatformDir;
|
|
@@ -4375,7 +4453,7 @@ function getOpenCodeConfigDir(options) {
|
|
|
4375
4453
|
const legacyDir = getCliConfigDir();
|
|
4376
4454
|
const legacyConfig = join10(legacyDir, "opencode.json");
|
|
4377
4455
|
const legacyConfigC = join10(legacyDir, "opencode.jsonc");
|
|
4378
|
-
if (
|
|
4456
|
+
if (existsSync8(legacyConfig) || existsSync8(legacyConfigC)) {
|
|
4379
4457
|
return legacyDir;
|
|
4380
4458
|
}
|
|
4381
4459
|
}
|
|
@@ -4853,7 +4931,7 @@ var init_model_requirements = __esm(() => {
|
|
|
4853
4931
|
});
|
|
4854
4932
|
|
|
4855
4933
|
// src/shared/model-availability.ts
|
|
4856
|
-
import { existsSync as
|
|
4934
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
4857
4935
|
import { homedir as homedir6 } from "os";
|
|
4858
4936
|
import { join as join12 } from "path";
|
|
4859
4937
|
function normalizeModelName(name) {
|
|
@@ -4908,12 +4986,12 @@ async function fetchAvailableModels(_client) {
|
|
|
4908
4986
|
const modelSet = new Set;
|
|
4909
4987
|
const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
|
|
4910
4988
|
log("[fetchAvailableModels] reading cache file", { cacheFile });
|
|
4911
|
-
if (!
|
|
4989
|
+
if (!existsSync10(cacheFile)) {
|
|
4912
4990
|
log("[fetchAvailableModels] cache file not found, returning empty set");
|
|
4913
4991
|
return modelSet;
|
|
4914
4992
|
}
|
|
4915
4993
|
try {
|
|
4916
|
-
const content =
|
|
4994
|
+
const content = readFileSync7(cacheFile, "utf-8");
|
|
4917
4995
|
const data = JSON.parse(content);
|
|
4918
4996
|
const providerIds = Object.keys(data);
|
|
4919
4997
|
log("[fetchAvailableModels] providers found", { count: providerIds.length, providers: providerIds.slice(0, 10) });
|
|
@@ -4936,7 +5014,7 @@ async function fetchAvailableModels(_client) {
|
|
|
4936
5014
|
}
|
|
4937
5015
|
function isModelCacheAvailable() {
|
|
4938
5016
|
const cacheFile = join12(getOpenCodeCacheDir(), "models.json");
|
|
4939
|
-
return
|
|
5017
|
+
return existsSync10(cacheFile);
|
|
4940
5018
|
}
|
|
4941
5019
|
var cachedModels = null;
|
|
4942
5020
|
var init_model_availability = __esm(() => {
|
|
@@ -5033,6 +5111,216 @@ class PerfTimer {
|
|
|
5033
5111
|
}
|
|
5034
5112
|
}
|
|
5035
5113
|
|
|
5114
|
+
// src/shared/perf-tracer.ts
|
|
5115
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync11 } from "fs";
|
|
5116
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
5117
|
+
import { join as join13 } from "path";
|
|
5118
|
+
|
|
5119
|
+
class PerfTracer {
|
|
5120
|
+
buffer = [];
|
|
5121
|
+
enabled;
|
|
5122
|
+
outputDir;
|
|
5123
|
+
slowThreshold;
|
|
5124
|
+
eventCount = 0;
|
|
5125
|
+
memorySnapshotInterval;
|
|
5126
|
+
constructor(config) {
|
|
5127
|
+
this.enabled = config.enabled;
|
|
5128
|
+
this.outputDir = config.outputDir ?? join13(tmpdir2(), "oh-my-opencode-perf");
|
|
5129
|
+
this.slowThreshold = config.slowThreshold ?? 100;
|
|
5130
|
+
this.memorySnapshotInterval = config.memorySnapshotInterval ?? 5;
|
|
5131
|
+
}
|
|
5132
|
+
isEnabled() {
|
|
5133
|
+
return this.enabled;
|
|
5134
|
+
}
|
|
5135
|
+
isSlowHook(durationMs) {
|
|
5136
|
+
return durationMs > this.slowThreshold;
|
|
5137
|
+
}
|
|
5138
|
+
recordHook(pipeline, hook, durationMs, sessionID, tool, error) {
|
|
5139
|
+
if (!this.enabled)
|
|
5140
|
+
return;
|
|
5141
|
+
const span = {
|
|
5142
|
+
t: new Date().toISOString(),
|
|
5143
|
+
type: "hook",
|
|
5144
|
+
pipeline,
|
|
5145
|
+
hook,
|
|
5146
|
+
durationMs,
|
|
5147
|
+
sessionID
|
|
5148
|
+
};
|
|
5149
|
+
if (tool !== undefined)
|
|
5150
|
+
span.tool = tool;
|
|
5151
|
+
if (error !== undefined)
|
|
5152
|
+
span.error = error;
|
|
5153
|
+
this.buffer.push(span);
|
|
5154
|
+
}
|
|
5155
|
+
recordPipeline(name, totalDurationMs, hookCount, sessionID) {
|
|
5156
|
+
if (!this.enabled)
|
|
5157
|
+
return;
|
|
5158
|
+
this.buffer.push({
|
|
5159
|
+
t: new Date().toISOString(),
|
|
5160
|
+
type: "pipeline",
|
|
5161
|
+
name,
|
|
5162
|
+
totalDurationMs,
|
|
5163
|
+
hookCount,
|
|
5164
|
+
sessionID
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
5167
|
+
recordApiCall(method, durationMs, sessionID, messageCount, error) {
|
|
5168
|
+
if (!this.enabled)
|
|
5169
|
+
return;
|
|
5170
|
+
const span = {
|
|
5171
|
+
t: new Date().toISOString(),
|
|
5172
|
+
type: "api",
|
|
5173
|
+
method,
|
|
5174
|
+
durationMs,
|
|
5175
|
+
sessionID
|
|
5176
|
+
};
|
|
5177
|
+
if (messageCount !== undefined)
|
|
5178
|
+
span.messageCount = messageCount;
|
|
5179
|
+
if (error !== undefined)
|
|
5180
|
+
span.error = error;
|
|
5181
|
+
this.buffer.push(span);
|
|
5182
|
+
}
|
|
5183
|
+
recordFileIO(operation, path4, durationMs, fileCount) {
|
|
5184
|
+
if (!this.enabled)
|
|
5185
|
+
return;
|
|
5186
|
+
const span = {
|
|
5187
|
+
t: new Date().toISOString(),
|
|
5188
|
+
type: "fileio",
|
|
5189
|
+
operation,
|
|
5190
|
+
path: path4,
|
|
5191
|
+
durationMs
|
|
5192
|
+
};
|
|
5193
|
+
if (fileCount !== undefined)
|
|
5194
|
+
span.fileCount = fileCount;
|
|
5195
|
+
this.buffer.push(span);
|
|
5196
|
+
}
|
|
5197
|
+
recordPolling(durationMs, taskCount, sessionCount) {
|
|
5198
|
+
if (!this.enabled)
|
|
5199
|
+
return;
|
|
5200
|
+
this.buffer.push({
|
|
5201
|
+
t: new Date().toISOString(),
|
|
5202
|
+
type: "polling",
|
|
5203
|
+
durationMs,
|
|
5204
|
+
taskCount,
|
|
5205
|
+
sessionCount
|
|
5206
|
+
});
|
|
5207
|
+
}
|
|
5208
|
+
snapshotMemory(trigger, mapSizes) {
|
|
5209
|
+
if (!this.enabled)
|
|
5210
|
+
return;
|
|
5211
|
+
this.eventCount++;
|
|
5212
|
+
if (this.eventCount % this.memorySnapshotInterval !== 0)
|
|
5213
|
+
return;
|
|
5214
|
+
this.buffer.push({
|
|
5215
|
+
t: new Date().toISOString(),
|
|
5216
|
+
type: "memory",
|
|
5217
|
+
trigger,
|
|
5218
|
+
mapSizes
|
|
5219
|
+
});
|
|
5220
|
+
}
|
|
5221
|
+
flush() {
|
|
5222
|
+
if (this.buffer.length === 0)
|
|
5223
|
+
return;
|
|
5224
|
+
if (!existsSync11(this.outputDir)) {
|
|
5225
|
+
mkdirSync3(this.outputDir, { recursive: true });
|
|
5226
|
+
}
|
|
5227
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
5228
|
+
const filePath = join13(this.outputDir, `${date}.jsonl`);
|
|
5229
|
+
let output = "";
|
|
5230
|
+
for (const span of this.buffer) {
|
|
5231
|
+
output += JSON.stringify(span) + `
|
|
5232
|
+
`;
|
|
5233
|
+
}
|
|
5234
|
+
appendFileSync2(filePath, output);
|
|
5235
|
+
this.buffer = [];
|
|
5236
|
+
}
|
|
5237
|
+
reset() {
|
|
5238
|
+
this.buffer = [];
|
|
5239
|
+
this.eventCount = 0;
|
|
5240
|
+
}
|
|
5241
|
+
}
|
|
5242
|
+
var init_perf_tracer = () => {};
|
|
5243
|
+
|
|
5244
|
+
// src/shared/windows-reserved-names.ts
|
|
5245
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5 } from "fs";
|
|
5246
|
+
import { join as join14 } from "path";
|
|
5247
|
+
function scanForReservedNames(directory, maxDepth = 2) {
|
|
5248
|
+
if (!existsSync12(directory))
|
|
5249
|
+
return [];
|
|
5250
|
+
const found = [];
|
|
5251
|
+
_scan(directory, 0, maxDepth, found);
|
|
5252
|
+
return found;
|
|
5253
|
+
}
|
|
5254
|
+
function _scan(dir, depth, maxDepth, found) {
|
|
5255
|
+
if (depth > maxDepth)
|
|
5256
|
+
return;
|
|
5257
|
+
let entries;
|
|
5258
|
+
try {
|
|
5259
|
+
entries = readdirSync5(dir);
|
|
5260
|
+
} catch {
|
|
5261
|
+
return;
|
|
5262
|
+
}
|
|
5263
|
+
for (const name of entries) {
|
|
5264
|
+
const upper = name.toUpperCase();
|
|
5265
|
+
const baseName = upper.split(".")[0] ?? "";
|
|
5266
|
+
if (WIN_RESERVED_NAMES.has(upper) || WIN_RESERVED_NAMES.has(baseName)) {
|
|
5267
|
+
found.push(join14(dir, name));
|
|
5268
|
+
}
|
|
5269
|
+
const fullPath = join14(dir, name);
|
|
5270
|
+
try {
|
|
5271
|
+
const stat = existsSync12(fullPath);
|
|
5272
|
+
if (stat && depth < maxDepth) {
|
|
5273
|
+
_scan(fullPath, depth + 1, maxDepth, found);
|
|
5274
|
+
}
|
|
5275
|
+
} catch {}
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
function formatReservedNamesWarning(found) {
|
|
5279
|
+
const lines = [
|
|
5280
|
+
"",
|
|
5281
|
+
"\u26A0\uFE0F WINDOWS RESERVED DEVICE NAMES DETECTED",
|
|
5282
|
+
" The following paths match Windows reserved device names (NUL, CON, AUX, etc.):",
|
|
5283
|
+
"",
|
|
5284
|
+
...found.map((p) => ` - ${p}`),
|
|
5285
|
+
"",
|
|
5286
|
+
" These will cause 'error: short read while indexing' git failures on Windows.",
|
|
5287
|
+
" This can make OpenCode's snapshot system extremely slow (30+ minutes).",
|
|
5288
|
+
"",
|
|
5289
|
+
" Fix: Rename these files/directories to avoid reserved names.",
|
|
5290
|
+
" e.g., rename 'nul' \u2192 'null-device', 'con' \u2192 'console-util'",
|
|
5291
|
+
""
|
|
5292
|
+
];
|
|
5293
|
+
return lines.join(`
|
|
5294
|
+
`);
|
|
5295
|
+
}
|
|
5296
|
+
var WIN_RESERVED_NAMES;
|
|
5297
|
+
var init_windows_reserved_names = __esm(() => {
|
|
5298
|
+
WIN_RESERVED_NAMES = new Set([
|
|
5299
|
+
"CON",
|
|
5300
|
+
"PRN",
|
|
5301
|
+
"AUX",
|
|
5302
|
+
"NUL",
|
|
5303
|
+
"COM1",
|
|
5304
|
+
"COM2",
|
|
5305
|
+
"COM3",
|
|
5306
|
+
"COM4",
|
|
5307
|
+
"COM5",
|
|
5308
|
+
"COM6",
|
|
5309
|
+
"COM7",
|
|
5310
|
+
"COM8",
|
|
5311
|
+
"COM9",
|
|
5312
|
+
"LPT1",
|
|
5313
|
+
"LPT2",
|
|
5314
|
+
"LPT3",
|
|
5315
|
+
"LPT4",
|
|
5316
|
+
"LPT5",
|
|
5317
|
+
"LPT6",
|
|
5318
|
+
"LPT7",
|
|
5319
|
+
"LPT8",
|
|
5320
|
+
"LPT9"
|
|
5321
|
+
]);
|
|
5322
|
+
});
|
|
5323
|
+
|
|
5036
5324
|
// src/shared/index.ts
|
|
5037
5325
|
var init_shared = __esm(() => {
|
|
5038
5326
|
init_frontmatter();
|
|
@@ -5060,6 +5348,9 @@ var init_shared = __esm(() => {
|
|
|
5060
5348
|
init_model_requirements();
|
|
5061
5349
|
init_model_resolver();
|
|
5062
5350
|
init_model_availability();
|
|
5351
|
+
init_perf_tracer();
|
|
5352
|
+
init_fileio_monitor();
|
|
5353
|
+
init_windows_reserved_names();
|
|
5063
5354
|
});
|
|
5064
5355
|
|
|
5065
5356
|
// node_modules/picomatch/lib/constants.js
|
|
@@ -10944,49 +11235,49 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
10944
11235
|
schemelessOptions.skipEscape = true;
|
|
10945
11236
|
return serialize(resolved, schemelessOptions);
|
|
10946
11237
|
}
|
|
10947
|
-
function resolveComponent(base,
|
|
11238
|
+
function resolveComponent(base, relative6, options, skipNormalization) {
|
|
10948
11239
|
const target = {};
|
|
10949
11240
|
if (!skipNormalization) {
|
|
10950
11241
|
base = parse11(serialize(base, options), options);
|
|
10951
|
-
|
|
11242
|
+
relative6 = parse11(serialize(relative6, options), options);
|
|
10952
11243
|
}
|
|
10953
11244
|
options = options || {};
|
|
10954
|
-
if (!options.tolerant &&
|
|
10955
|
-
target.scheme =
|
|
10956
|
-
target.userinfo =
|
|
10957
|
-
target.host =
|
|
10958
|
-
target.port =
|
|
10959
|
-
target.path = removeDotSegments(
|
|
10960
|
-
target.query =
|
|
11245
|
+
if (!options.tolerant && relative6.scheme) {
|
|
11246
|
+
target.scheme = relative6.scheme;
|
|
11247
|
+
target.userinfo = relative6.userinfo;
|
|
11248
|
+
target.host = relative6.host;
|
|
11249
|
+
target.port = relative6.port;
|
|
11250
|
+
target.path = removeDotSegments(relative6.path || "");
|
|
11251
|
+
target.query = relative6.query;
|
|
10961
11252
|
} else {
|
|
10962
|
-
if (
|
|
10963
|
-
target.userinfo =
|
|
10964
|
-
target.host =
|
|
10965
|
-
target.port =
|
|
10966
|
-
target.path = removeDotSegments(
|
|
10967
|
-
target.query =
|
|
11253
|
+
if (relative6.userinfo !== undefined || relative6.host !== undefined || relative6.port !== undefined) {
|
|
11254
|
+
target.userinfo = relative6.userinfo;
|
|
11255
|
+
target.host = relative6.host;
|
|
11256
|
+
target.port = relative6.port;
|
|
11257
|
+
target.path = removeDotSegments(relative6.path || "");
|
|
11258
|
+
target.query = relative6.query;
|
|
10968
11259
|
} else {
|
|
10969
|
-
if (!
|
|
11260
|
+
if (!relative6.path) {
|
|
10970
11261
|
target.path = base.path;
|
|
10971
|
-
if (
|
|
10972
|
-
target.query =
|
|
11262
|
+
if (relative6.query !== undefined) {
|
|
11263
|
+
target.query = relative6.query;
|
|
10973
11264
|
} else {
|
|
10974
11265
|
target.query = base.query;
|
|
10975
11266
|
}
|
|
10976
11267
|
} else {
|
|
10977
|
-
if (
|
|
10978
|
-
target.path = removeDotSegments(
|
|
11268
|
+
if (relative6.path[0] === "/") {
|
|
11269
|
+
target.path = removeDotSegments(relative6.path);
|
|
10979
11270
|
} else {
|
|
10980
11271
|
if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
|
|
10981
|
-
target.path = "/" +
|
|
11272
|
+
target.path = "/" + relative6.path;
|
|
10982
11273
|
} else if (!base.path) {
|
|
10983
|
-
target.path =
|
|
11274
|
+
target.path = relative6.path;
|
|
10984
11275
|
} else {
|
|
10985
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
11276
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative6.path;
|
|
10986
11277
|
}
|
|
10987
11278
|
target.path = removeDotSegments(target.path);
|
|
10988
11279
|
}
|
|
10989
|
-
target.query =
|
|
11280
|
+
target.query = relative6.query;
|
|
10990
11281
|
}
|
|
10991
11282
|
target.userinfo = base.userinfo;
|
|
10992
11283
|
target.host = base.host;
|
|
@@ -10994,7 +11285,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
10994
11285
|
}
|
|
10995
11286
|
target.scheme = base.scheme;
|
|
10996
11287
|
}
|
|
10997
|
-
target.fragment =
|
|
11288
|
+
target.fragment = relative6.fragment;
|
|
10998
11289
|
return target;
|
|
10999
11290
|
}
|
|
11000
11291
|
function equal(uriA, uriB, options) {
|
|
@@ -14201,7 +14492,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
|
|
|
14201
14492
|
var getPathKey = require_path_key();
|
|
14202
14493
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
14203
14494
|
const env = parsed.options.env || process.env;
|
|
14204
|
-
const
|
|
14495
|
+
const cwd2 = process.cwd();
|
|
14205
14496
|
const hasCustomCwd = parsed.options.cwd != null;
|
|
14206
14497
|
const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
|
|
14207
14498
|
if (shouldSwitchCwd) {
|
|
@@ -14217,7 +14508,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
|
|
|
14217
14508
|
});
|
|
14218
14509
|
} catch (e) {} finally {
|
|
14219
14510
|
if (shouldSwitchCwd) {
|
|
14220
|
-
process.chdir(
|
|
14511
|
+
process.chdir(cwd2);
|
|
14221
14512
|
}
|
|
14222
14513
|
}
|
|
14223
14514
|
if (resolved) {
|
|
@@ -14424,7 +14715,7 @@ var require_cross_spawn = __commonJS((exports, module) => {
|
|
|
14424
14715
|
});
|
|
14425
14716
|
|
|
14426
14717
|
// src/hooks/todo-continuation-enforcer.ts
|
|
14427
|
-
import { existsSync as
|
|
14718
|
+
import { existsSync as existsSync3, readdirSync as readdirSync3 } from "fs";
|
|
14428
14719
|
import { join as join5 } from "path";
|
|
14429
14720
|
|
|
14430
14721
|
// src/features/claude-code-session-state/state.ts
|
|
@@ -14452,7 +14743,8 @@ function clearSessionAgent(sessionID) {
|
|
|
14452
14743
|
sessionAgentMap.delete(sessionID);
|
|
14453
14744
|
}
|
|
14454
14745
|
// src/features/hook-message-injector/injector.ts
|
|
14455
|
-
|
|
14746
|
+
init_fileio_monitor();
|
|
14747
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
14456
14748
|
import { join as join3 } from "path";
|
|
14457
14749
|
|
|
14458
14750
|
// src/features/hook-message-injector/constants.ts
|
|
@@ -14464,11 +14756,12 @@ var PART_STORAGE = join2(OPENCODE_STORAGE, "part");
|
|
|
14464
14756
|
|
|
14465
14757
|
// src/features/hook-message-injector/injector.ts
|
|
14466
14758
|
function findNearestMessageWithFields(messageDir) {
|
|
14759
|
+
const monitor = getFileIOMonitor();
|
|
14467
14760
|
try {
|
|
14468
|
-
const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
14761
|
+
const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
14469
14762
|
for (const file of files) {
|
|
14470
14763
|
try {
|
|
14471
|
-
const content = readFileSync(join3(messageDir, file), "utf-8");
|
|
14764
|
+
const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
|
|
14472
14765
|
const msg = JSON.parse(content);
|
|
14473
14766
|
if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
|
|
14474
14767
|
return msg;
|
|
@@ -14479,7 +14772,7 @@ function findNearestMessageWithFields(messageDir) {
|
|
|
14479
14772
|
}
|
|
14480
14773
|
for (const file of files) {
|
|
14481
14774
|
try {
|
|
14482
|
-
const content = readFileSync(join3(messageDir, file), "utf-8");
|
|
14775
|
+
const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
|
|
14483
14776
|
const msg = JSON.parse(content);
|
|
14484
14777
|
if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
|
|
14485
14778
|
return msg;
|
|
@@ -14494,11 +14787,12 @@ function findNearestMessageWithFields(messageDir) {
|
|
|
14494
14787
|
return null;
|
|
14495
14788
|
}
|
|
14496
14789
|
function findFirstMessageWithAgent(messageDir) {
|
|
14790
|
+
const monitor = getFileIOMonitor();
|
|
14497
14791
|
try {
|
|
14498
|
-
const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort();
|
|
14792
|
+
const files = (monitor?.readdirSync(messageDir) ?? readdirSync2(messageDir)).filter((f) => f.endsWith(".json")).sort();
|
|
14499
14793
|
for (const file of files) {
|
|
14500
14794
|
try {
|
|
14501
|
-
const content = readFileSync(join3(messageDir, file), "utf-8");
|
|
14795
|
+
const content = monitor?.readFileSync(join3(messageDir, file), "utf-8") ?? readFileSync2(join3(messageDir, file), "utf-8");
|
|
14502
14796
|
const msg = JSON.parse(content);
|
|
14503
14797
|
if (msg.agent) {
|
|
14504
14798
|
return msg.agent;
|
|
@@ -14523,20 +14817,24 @@ function generatePartId() {
|
|
|
14523
14817
|
return `prt_${timestamp}${random}`;
|
|
14524
14818
|
}
|
|
14525
14819
|
function getOrCreateMessageDir(sessionID) {
|
|
14526
|
-
|
|
14527
|
-
|
|
14820
|
+
const monitor = getFileIOMonitor();
|
|
14821
|
+
const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
|
|
14822
|
+
const _mkdir = (p, opts) => monitor ? undefined : mkdirSync(p, opts);
|
|
14823
|
+
const _readdir = (p) => monitor?.readdirSync(p) ?? readdirSync2(p);
|
|
14824
|
+
if (!_exists(MESSAGE_STORAGE)) {
|
|
14825
|
+
_mkdir(MESSAGE_STORAGE, { recursive: true });
|
|
14528
14826
|
}
|
|
14529
14827
|
const directPath = join3(MESSAGE_STORAGE, sessionID);
|
|
14530
|
-
if (
|
|
14828
|
+
if (_exists(directPath)) {
|
|
14531
14829
|
return directPath;
|
|
14532
14830
|
}
|
|
14533
|
-
for (const dir of
|
|
14831
|
+
for (const dir of _readdir(MESSAGE_STORAGE)) {
|
|
14534
14832
|
const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
|
|
14535
|
-
if (
|
|
14833
|
+
if (_exists(sessionPath)) {
|
|
14536
14834
|
return sessionPath;
|
|
14537
14835
|
}
|
|
14538
14836
|
}
|
|
14539
|
-
|
|
14837
|
+
_mkdir(directPath, { recursive: true });
|
|
14540
14838
|
return directPath;
|
|
14541
14839
|
}
|
|
14542
14840
|
function injectHookMessage(sessionID, hookContent, originalMessage) {
|
|
@@ -14585,12 +14883,22 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
|
|
|
14585
14883
|
sessionID
|
|
14586
14884
|
};
|
|
14587
14885
|
try {
|
|
14588
|
-
|
|
14886
|
+
const monitor = getFileIOMonitor();
|
|
14887
|
+
if (monitor) {
|
|
14888
|
+
monitor.writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
|
|
14889
|
+
} else {
|
|
14890
|
+
writeFileSync2(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
|
|
14891
|
+
}
|
|
14589
14892
|
const partDir = join3(PART_STORAGE, messageID);
|
|
14590
|
-
|
|
14893
|
+
const _exists = (p) => monitor?.existsSync(p) ?? existsSync2(p);
|
|
14894
|
+
if (!_exists(partDir)) {
|
|
14591
14895
|
mkdirSync(partDir, { recursive: true });
|
|
14592
14896
|
}
|
|
14593
|
-
|
|
14897
|
+
if (monitor) {
|
|
14898
|
+
monitor.writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
|
|
14899
|
+
} else {
|
|
14900
|
+
writeFileSync2(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
|
|
14901
|
+
}
|
|
14594
14902
|
return true;
|
|
14595
14903
|
} catch {
|
|
14596
14904
|
return false;
|
|
@@ -14612,14 +14920,14 @@ var COUNTDOWN_SECONDS = 2;
|
|
|
14612
14920
|
var TOAST_DURATION_MS = 900;
|
|
14613
14921
|
var COUNTDOWN_GRACE_PERIOD_MS = 500;
|
|
14614
14922
|
function getMessageDir(sessionID) {
|
|
14615
|
-
if (!
|
|
14923
|
+
if (!existsSync3(MESSAGE_STORAGE))
|
|
14616
14924
|
return null;
|
|
14617
14925
|
const directPath = join5(MESSAGE_STORAGE, sessionID);
|
|
14618
|
-
if (
|
|
14926
|
+
if (existsSync3(directPath))
|
|
14619
14927
|
return directPath;
|
|
14620
|
-
for (const dir of
|
|
14928
|
+
for (const dir of readdirSync3(MESSAGE_STORAGE)) {
|
|
14621
14929
|
const sessionPath = join5(MESSAGE_STORAGE, dir, sessionID);
|
|
14622
|
-
if (
|
|
14930
|
+
if (existsSync3(sessionPath))
|
|
14623
14931
|
return sessionPath;
|
|
14624
14932
|
}
|
|
14625
14933
|
return null;
|
|
@@ -15397,7 +15705,7 @@ function createSessionNotification(ctx, config = {}) {
|
|
|
15397
15705
|
};
|
|
15398
15706
|
}
|
|
15399
15707
|
// src/hooks/session-recovery/storage.ts
|
|
15400
|
-
import { existsSync as
|
|
15708
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync4, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
15401
15709
|
import { join as join7 } from "path";
|
|
15402
15710
|
|
|
15403
15711
|
// src/hooks/session-recovery/constants.ts
|
|
@@ -15418,15 +15726,15 @@ function generatePartId2() {
|
|
|
15418
15726
|
return `prt_${timestamp}${random}`;
|
|
15419
15727
|
}
|
|
15420
15728
|
function getMessageDir2(sessionID) {
|
|
15421
|
-
if (!
|
|
15729
|
+
if (!existsSync4(MESSAGE_STORAGE2))
|
|
15422
15730
|
return "";
|
|
15423
15731
|
const directPath = join7(MESSAGE_STORAGE2, sessionID);
|
|
15424
|
-
if (
|
|
15732
|
+
if (existsSync4(directPath)) {
|
|
15425
15733
|
return directPath;
|
|
15426
15734
|
}
|
|
15427
|
-
for (const dir of
|
|
15735
|
+
for (const dir of readdirSync4(MESSAGE_STORAGE2)) {
|
|
15428
15736
|
const sessionPath = join7(MESSAGE_STORAGE2, dir, sessionID);
|
|
15429
|
-
if (
|
|
15737
|
+
if (existsSync4(sessionPath)) {
|
|
15430
15738
|
return sessionPath;
|
|
15431
15739
|
}
|
|
15432
15740
|
}
|
|
@@ -15434,14 +15742,14 @@ function getMessageDir2(sessionID) {
|
|
|
15434
15742
|
}
|
|
15435
15743
|
function readMessages(sessionID) {
|
|
15436
15744
|
const messageDir = getMessageDir2(sessionID);
|
|
15437
|
-
if (!messageDir || !
|
|
15745
|
+
if (!messageDir || !existsSync4(messageDir))
|
|
15438
15746
|
return [];
|
|
15439
15747
|
const messages = [];
|
|
15440
|
-
for (const file of
|
|
15748
|
+
for (const file of readdirSync4(messageDir)) {
|
|
15441
15749
|
if (!file.endsWith(".json"))
|
|
15442
15750
|
continue;
|
|
15443
15751
|
try {
|
|
15444
|
-
const content =
|
|
15752
|
+
const content = readFileSync3(join7(messageDir, file), "utf-8");
|
|
15445
15753
|
messages.push(JSON.parse(content));
|
|
15446
15754
|
} catch {
|
|
15447
15755
|
continue;
|
|
@@ -15457,14 +15765,14 @@ function readMessages(sessionID) {
|
|
|
15457
15765
|
}
|
|
15458
15766
|
function readParts(messageID) {
|
|
15459
15767
|
const partDir = join7(PART_STORAGE2, messageID);
|
|
15460
|
-
if (!
|
|
15768
|
+
if (!existsSync4(partDir))
|
|
15461
15769
|
return [];
|
|
15462
15770
|
const parts = [];
|
|
15463
|
-
for (const file of
|
|
15771
|
+
for (const file of readdirSync4(partDir)) {
|
|
15464
15772
|
if (!file.endsWith(".json"))
|
|
15465
15773
|
continue;
|
|
15466
15774
|
try {
|
|
15467
|
-
const content =
|
|
15775
|
+
const content = readFileSync3(join7(partDir, file), "utf-8");
|
|
15468
15776
|
parts.push(JSON.parse(content));
|
|
15469
15777
|
} catch {
|
|
15470
15778
|
continue;
|
|
@@ -15495,7 +15803,7 @@ function messageHasContent(messageID) {
|
|
|
15495
15803
|
}
|
|
15496
15804
|
function injectTextPart(sessionID, messageID, text) {
|
|
15497
15805
|
const partDir = join7(PART_STORAGE2, messageID);
|
|
15498
|
-
if (!
|
|
15806
|
+
if (!existsSync4(partDir)) {
|
|
15499
15807
|
mkdirSync2(partDir, { recursive: true });
|
|
15500
15808
|
}
|
|
15501
15809
|
const partId = generatePartId2();
|
|
@@ -15508,7 +15816,7 @@ function injectTextPart(sessionID, messageID, text) {
|
|
|
15508
15816
|
synthetic: true
|
|
15509
15817
|
};
|
|
15510
15818
|
try {
|
|
15511
|
-
|
|
15819
|
+
writeFileSync3(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
|
|
15512
15820
|
return true;
|
|
15513
15821
|
} catch {
|
|
15514
15822
|
return false;
|
|
@@ -15604,7 +15912,7 @@ function findLastThinkingContent(sessionID, beforeMessageID) {
|
|
|
15604
15912
|
}
|
|
15605
15913
|
function prependThinkingPart(sessionID, messageID) {
|
|
15606
15914
|
const partDir = join7(PART_STORAGE2, messageID);
|
|
15607
|
-
if (!
|
|
15915
|
+
if (!existsSync4(partDir)) {
|
|
15608
15916
|
mkdirSync2(partDir, { recursive: true });
|
|
15609
15917
|
}
|
|
15610
15918
|
const previousThinking = findLastThinkingContent(sessionID, messageID);
|
|
@@ -15614,11 +15922,11 @@ function prependThinkingPart(sessionID, messageID) {
|
|
|
15614
15922
|
sessionID,
|
|
15615
15923
|
messageID,
|
|
15616
15924
|
type: "thinking",
|
|
15617
|
-
thinking: previousThinking || "[
|
|
15925
|
+
thinking: previousThinking || "[\u63A5\u7EED\u4E4B\u524D\u7684\u63A8\u7406]",
|
|
15618
15926
|
synthetic: true
|
|
15619
15927
|
};
|
|
15620
15928
|
try {
|
|
15621
|
-
|
|
15929
|
+
writeFileSync3(join7(partDir, `${partId}.json`), JSON.stringify(part, null, 2));
|
|
15622
15930
|
return true;
|
|
15623
15931
|
} catch {
|
|
15624
15932
|
return false;
|
|
@@ -15626,15 +15934,15 @@ function prependThinkingPart(sessionID, messageID) {
|
|
|
15626
15934
|
}
|
|
15627
15935
|
function stripThinkingParts(messageID) {
|
|
15628
15936
|
const partDir = join7(PART_STORAGE2, messageID);
|
|
15629
|
-
if (!
|
|
15937
|
+
if (!existsSync4(partDir))
|
|
15630
15938
|
return false;
|
|
15631
15939
|
let anyRemoved = false;
|
|
15632
|
-
for (const file of
|
|
15940
|
+
for (const file of readdirSync4(partDir)) {
|
|
15633
15941
|
if (!file.endsWith(".json"))
|
|
15634
15942
|
continue;
|
|
15635
15943
|
try {
|
|
15636
15944
|
const filePath = join7(partDir, file);
|
|
15637
|
-
const content =
|
|
15945
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
15638
15946
|
const part = JSON.parse(content);
|
|
15639
15947
|
if (THINKING_TYPES.has(part.type)) {
|
|
15640
15948
|
unlinkSync(filePath);
|
|
@@ -15648,22 +15956,22 @@ function stripThinkingParts(messageID) {
|
|
|
15648
15956
|
}
|
|
15649
15957
|
function replaceEmptyTextParts(messageID, replacementText) {
|
|
15650
15958
|
const partDir = join7(PART_STORAGE2, messageID);
|
|
15651
|
-
if (!
|
|
15959
|
+
if (!existsSync4(partDir))
|
|
15652
15960
|
return false;
|
|
15653
15961
|
let anyReplaced = false;
|
|
15654
|
-
for (const file of
|
|
15962
|
+
for (const file of readdirSync4(partDir)) {
|
|
15655
15963
|
if (!file.endsWith(".json"))
|
|
15656
15964
|
continue;
|
|
15657
15965
|
try {
|
|
15658
15966
|
const filePath = join7(partDir, file);
|
|
15659
|
-
const content =
|
|
15967
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
15660
15968
|
const part = JSON.parse(content);
|
|
15661
15969
|
if (part.type === "text") {
|
|
15662
15970
|
const textPart = part;
|
|
15663
15971
|
if (!textPart.text?.trim()) {
|
|
15664
15972
|
textPart.text = replacementText;
|
|
15665
15973
|
textPart.synthetic = true;
|
|
15666
|
-
|
|
15974
|
+
writeFileSync3(filePath, JSON.stringify(textPart, null, 2));
|
|
15667
15975
|
anyReplaced = true;
|
|
15668
15976
|
}
|
|
15669
15977
|
}
|
|
@@ -15932,25 +16240,25 @@ function createSessionRecoveryHook(ctx, options) {
|
|
|
15932
16240
|
// src/hooks/comment-checker/cli.ts
|
|
15933
16241
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
15934
16242
|
import { createRequire as createRequire2 } from "module";
|
|
15935
|
-
import { dirname, join as
|
|
15936
|
-
import { existsSync as
|
|
16243
|
+
import { dirname, join as join16 } from "path";
|
|
16244
|
+
import { existsSync as existsSync14 } from "fs";
|
|
15937
16245
|
import * as fs5 from "fs";
|
|
15938
|
-
import { tmpdir as
|
|
16246
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
15939
16247
|
|
|
15940
16248
|
// src/hooks/comment-checker/downloader.ts
|
|
15941
16249
|
init_shared();
|
|
15942
16250
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
15943
|
-
import { existsSync as
|
|
15944
|
-
import { join as
|
|
15945
|
-
import { homedir as homedir7, tmpdir as
|
|
16251
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
|
|
16252
|
+
import { join as join15 } from "path";
|
|
16253
|
+
import { homedir as homedir7, tmpdir as tmpdir3 } from "os";
|
|
15946
16254
|
import { createRequire } from "module";
|
|
15947
16255
|
var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
15948
|
-
var DEBUG_FILE =
|
|
16256
|
+
var DEBUG_FILE = join15(tmpdir3(), "comment-checker-debug.log");
|
|
15949
16257
|
function debugLog(...args) {
|
|
15950
16258
|
if (DEBUG) {
|
|
15951
16259
|
const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
15952
16260
|
`;
|
|
15953
|
-
|
|
16261
|
+
appendFileSync3(DEBUG_FILE, msg);
|
|
15954
16262
|
}
|
|
15955
16263
|
}
|
|
15956
16264
|
var REPO = "code-yeongyu/go-claude-code-comment-checker";
|
|
@@ -15964,19 +16272,19 @@ var PLATFORM_MAP = {
|
|
|
15964
16272
|
function getCacheDir() {
|
|
15965
16273
|
if (process.platform === "win32") {
|
|
15966
16274
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
15967
|
-
const base2 = localAppData ||
|
|
15968
|
-
return
|
|
16275
|
+
const base2 = localAppData || join15(homedir7(), "AppData", "Local");
|
|
16276
|
+
return join15(base2, "oh-my-opencode", "bin");
|
|
15969
16277
|
}
|
|
15970
16278
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
15971
|
-
const base = xdgCache ||
|
|
15972
|
-
return
|
|
16279
|
+
const base = xdgCache || join15(homedir7(), ".cache");
|
|
16280
|
+
return join15(base, "oh-my-opencode", "bin");
|
|
15973
16281
|
}
|
|
15974
16282
|
function getBinaryName() {
|
|
15975
16283
|
return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
15976
16284
|
}
|
|
15977
16285
|
function getCachedBinaryPath() {
|
|
15978
|
-
const binaryPath =
|
|
15979
|
-
return
|
|
16286
|
+
const binaryPath = join15(getCacheDir(), getBinaryName());
|
|
16287
|
+
return existsSync13(binaryPath) ? binaryPath : null;
|
|
15980
16288
|
}
|
|
15981
16289
|
function getPackageVersion() {
|
|
15982
16290
|
try {
|
|
@@ -16008,8 +16316,8 @@ async function downloadCommentChecker() {
|
|
|
16008
16316
|
}
|
|
16009
16317
|
const cacheDir = getCacheDir();
|
|
16010
16318
|
const binaryName = getBinaryName();
|
|
16011
|
-
const binaryPath =
|
|
16012
|
-
if (
|
|
16319
|
+
const binaryPath = join15(cacheDir, binaryName);
|
|
16320
|
+
if (existsSync13(binaryPath)) {
|
|
16013
16321
|
debugLog("Binary already cached at:", binaryPath);
|
|
16014
16322
|
return binaryPath;
|
|
16015
16323
|
}
|
|
@@ -16020,14 +16328,14 @@ async function downloadCommentChecker() {
|
|
|
16020
16328
|
debugLog(`Downloading from: ${downloadUrl}`);
|
|
16021
16329
|
console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
|
|
16022
16330
|
try {
|
|
16023
|
-
if (!
|
|
16024
|
-
|
|
16331
|
+
if (!existsSync13(cacheDir)) {
|
|
16332
|
+
mkdirSync4(cacheDir, { recursive: true });
|
|
16025
16333
|
}
|
|
16026
16334
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
16027
16335
|
if (!response.ok) {
|
|
16028
16336
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
16029
16337
|
}
|
|
16030
|
-
const archivePath =
|
|
16338
|
+
const archivePath = join15(cacheDir, assetName);
|
|
16031
16339
|
const arrayBuffer = await response.arrayBuffer();
|
|
16032
16340
|
await Bun.write(archivePath, arrayBuffer);
|
|
16033
16341
|
debugLog(`Downloaded archive to: ${archivePath}`);
|
|
@@ -16036,10 +16344,10 @@ async function downloadCommentChecker() {
|
|
|
16036
16344
|
} else {
|
|
16037
16345
|
await extractZip(archivePath, cacheDir);
|
|
16038
16346
|
}
|
|
16039
|
-
if (
|
|
16347
|
+
if (existsSync13(archivePath)) {
|
|
16040
16348
|
unlinkSync2(archivePath);
|
|
16041
16349
|
}
|
|
16042
|
-
if (process.platform !== "win32" &&
|
|
16350
|
+
if (process.platform !== "win32" && existsSync13(binaryPath)) {
|
|
16043
16351
|
chmodSync(binaryPath, 493);
|
|
16044
16352
|
}
|
|
16045
16353
|
debugLog(`Successfully downloaded binary to: ${binaryPath}`);
|
|
@@ -16063,7 +16371,7 @@ async function ensureCommentCheckerBinary() {
|
|
|
16063
16371
|
|
|
16064
16372
|
// src/hooks/comment-checker/cli.ts
|
|
16065
16373
|
var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
16066
|
-
var DEBUG_FILE2 =
|
|
16374
|
+
var DEBUG_FILE2 = join16(tmpdir4(), "comment-checker-debug.log");
|
|
16067
16375
|
function debugLog2(...args) {
|
|
16068
16376
|
if (DEBUG2) {
|
|
16069
16377
|
const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -16089,8 +16397,8 @@ function findCommentCheckerPathSync() {
|
|
|
16089
16397
|
const require2 = createRequire2(import.meta.url);
|
|
16090
16398
|
const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
16091
16399
|
const cliDir = dirname(cliPkgPath);
|
|
16092
|
-
const binaryPath =
|
|
16093
|
-
if (
|
|
16400
|
+
const binaryPath = join16(cliDir, "bin", binaryName);
|
|
16401
|
+
if (existsSync14(binaryPath)) {
|
|
16094
16402
|
debugLog2("found binary in main package:", binaryPath);
|
|
16095
16403
|
return binaryPath;
|
|
16096
16404
|
}
|
|
@@ -16111,7 +16419,7 @@ async function getCommentCheckerPath() {
|
|
|
16111
16419
|
}
|
|
16112
16420
|
initPromise = (async () => {
|
|
16113
16421
|
const syncPath = findCommentCheckerPathSync();
|
|
16114
|
-
if (syncPath &&
|
|
16422
|
+
if (syncPath && existsSync14(syncPath)) {
|
|
16115
16423
|
resolvedCliPath = syncPath;
|
|
16116
16424
|
debugLog2("using sync-resolved path:", syncPath);
|
|
16117
16425
|
return syncPath;
|
|
@@ -16147,7 +16455,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
16147
16455
|
debugLog2("comment-checker binary not found");
|
|
16148
16456
|
return { hasComments: false, message: "" };
|
|
16149
16457
|
}
|
|
16150
|
-
if (!
|
|
16458
|
+
if (!existsSync14(binaryPath)) {
|
|
16151
16459
|
debugLog2("comment-checker binary does not exist:", binaryPath);
|
|
16152
16460
|
return { hasComments: false, message: "" };
|
|
16153
16461
|
}
|
|
@@ -16185,11 +16493,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
16185
16493
|
|
|
16186
16494
|
// src/hooks/comment-checker/index.ts
|
|
16187
16495
|
import * as fs6 from "fs";
|
|
16188
|
-
import { existsSync as
|
|
16189
|
-
import { tmpdir as
|
|
16190
|
-
import { join as
|
|
16496
|
+
import { existsSync as existsSync15 } from "fs";
|
|
16497
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
16498
|
+
import { join as join17 } from "path";
|
|
16191
16499
|
var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
16192
|
-
var DEBUG_FILE3 =
|
|
16500
|
+
var DEBUG_FILE3 = join17(tmpdir5(), "comment-checker-debug.log");
|
|
16193
16501
|
function debugLog3(...args) {
|
|
16194
16502
|
if (DEBUG3) {
|
|
16195
16503
|
const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -16269,7 +16577,7 @@ function createCommentCheckerHooks(config) {
|
|
|
16269
16577
|
}
|
|
16270
16578
|
try {
|
|
16271
16579
|
const cliPath = await cliPathPromise;
|
|
16272
|
-
if (!cliPath || !
|
|
16580
|
+
if (!cliPath || !existsSync15(cliPath)) {
|
|
16273
16581
|
debugLog3("CLI not available, skipping comment check");
|
|
16274
16582
|
return;
|
|
16275
16583
|
}
|
|
@@ -16349,36 +16657,36 @@ function createToolOutputTruncatorHook(ctx, options) {
|
|
|
16349
16657
|
};
|
|
16350
16658
|
}
|
|
16351
16659
|
// src/hooks/directory-agents-injector/index.ts
|
|
16352
|
-
import { existsSync as
|
|
16353
|
-
import { dirname as dirname2, join as
|
|
16660
|
+
import { existsSync as existsSync17, readFileSync as readFileSync9 } from "fs";
|
|
16661
|
+
import { dirname as dirname2, join as join20, resolve as resolve3 } from "path";
|
|
16354
16662
|
|
|
16355
16663
|
// src/hooks/directory-agents-injector/storage.ts
|
|
16356
16664
|
import {
|
|
16357
|
-
existsSync as
|
|
16358
|
-
mkdirSync as
|
|
16359
|
-
readFileSync as
|
|
16360
|
-
writeFileSync as
|
|
16665
|
+
existsSync as existsSync16,
|
|
16666
|
+
mkdirSync as mkdirSync5,
|
|
16667
|
+
readFileSync as readFileSync8,
|
|
16668
|
+
writeFileSync as writeFileSync5,
|
|
16361
16669
|
unlinkSync as unlinkSync3
|
|
16362
16670
|
} from "fs";
|
|
16363
|
-
import { join as
|
|
16671
|
+
import { join as join19 } from "path";
|
|
16364
16672
|
|
|
16365
16673
|
// src/hooks/directory-agents-injector/constants.ts
|
|
16366
16674
|
init_data_path();
|
|
16367
|
-
import { join as
|
|
16675
|
+
import { join as join18 } from "path";
|
|
16368
16676
|
var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
|
|
16369
|
-
var AGENTS_INJECTOR_STORAGE =
|
|
16677
|
+
var AGENTS_INJECTOR_STORAGE = join18(OPENCODE_STORAGE3, "directory-agents");
|
|
16370
16678
|
var AGENTS_FILENAME = "AGENTS.md";
|
|
16371
16679
|
|
|
16372
16680
|
// src/hooks/directory-agents-injector/storage.ts
|
|
16373
16681
|
function getStoragePath(sessionID) {
|
|
16374
|
-
return
|
|
16682
|
+
return join19(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
16375
16683
|
}
|
|
16376
16684
|
function loadInjectedPaths(sessionID) {
|
|
16377
16685
|
const filePath = getStoragePath(sessionID);
|
|
16378
|
-
if (!
|
|
16686
|
+
if (!existsSync16(filePath))
|
|
16379
16687
|
return new Set;
|
|
16380
16688
|
try {
|
|
16381
|
-
const content =
|
|
16689
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
16382
16690
|
const data = JSON.parse(content);
|
|
16383
16691
|
return new Set(data.injectedPaths);
|
|
16384
16692
|
} catch {
|
|
@@ -16386,19 +16694,19 @@ function loadInjectedPaths(sessionID) {
|
|
|
16386
16694
|
}
|
|
16387
16695
|
}
|
|
16388
16696
|
function saveInjectedPaths(sessionID, paths) {
|
|
16389
|
-
if (!
|
|
16390
|
-
|
|
16697
|
+
if (!existsSync16(AGENTS_INJECTOR_STORAGE)) {
|
|
16698
|
+
mkdirSync5(AGENTS_INJECTOR_STORAGE, { recursive: true });
|
|
16391
16699
|
}
|
|
16392
16700
|
const data = {
|
|
16393
16701
|
sessionID,
|
|
16394
16702
|
injectedPaths: [...paths],
|
|
16395
16703
|
updatedAt: Date.now()
|
|
16396
16704
|
};
|
|
16397
|
-
|
|
16705
|
+
writeFileSync5(getStoragePath(sessionID), JSON.stringify(data, null, 2));
|
|
16398
16706
|
}
|
|
16399
16707
|
function clearInjectedPaths(sessionID) {
|
|
16400
16708
|
const filePath = getStoragePath(sessionID);
|
|
16401
|
-
if (
|
|
16709
|
+
if (existsSync16(filePath)) {
|
|
16402
16710
|
unlinkSync3(filePath);
|
|
16403
16711
|
}
|
|
16404
16712
|
}
|
|
@@ -16428,8 +16736,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
16428
16736
|
while (true) {
|
|
16429
16737
|
const isRootDir = current === ctx.directory;
|
|
16430
16738
|
if (!isRootDir) {
|
|
16431
|
-
const agentsPath =
|
|
16432
|
-
if (
|
|
16739
|
+
const agentsPath = join20(current, AGENTS_FILENAME);
|
|
16740
|
+
if (existsSync17(agentsPath)) {
|
|
16433
16741
|
found.push(agentsPath);
|
|
16434
16742
|
}
|
|
16435
16743
|
}
|
|
@@ -16456,7 +16764,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
16456
16764
|
if (cache.has(agentsDir))
|
|
16457
16765
|
continue;
|
|
16458
16766
|
try {
|
|
16459
|
-
const content =
|
|
16767
|
+
const content = readFileSync9(agentsPath, "utf-8");
|
|
16460
16768
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
16461
16769
|
const truncationNotice = truncated ? `
|
|
16462
16770
|
|
|
@@ -16526,36 +16834,36 @@ ${result}${truncationNotice}`;
|
|
|
16526
16834
|
};
|
|
16527
16835
|
}
|
|
16528
16836
|
// src/hooks/directory-readme-injector/index.ts
|
|
16529
|
-
import { existsSync as
|
|
16530
|
-
import { dirname as dirname3, join as
|
|
16837
|
+
import { existsSync as existsSync19, readFileSync as readFileSync11 } from "fs";
|
|
16838
|
+
import { dirname as dirname3, join as join23, resolve as resolve4 } from "path";
|
|
16531
16839
|
|
|
16532
16840
|
// src/hooks/directory-readme-injector/storage.ts
|
|
16533
16841
|
import {
|
|
16534
|
-
existsSync as
|
|
16535
|
-
mkdirSync as
|
|
16536
|
-
readFileSync as
|
|
16537
|
-
writeFileSync as
|
|
16842
|
+
existsSync as existsSync18,
|
|
16843
|
+
mkdirSync as mkdirSync6,
|
|
16844
|
+
readFileSync as readFileSync10,
|
|
16845
|
+
writeFileSync as writeFileSync6,
|
|
16538
16846
|
unlinkSync as unlinkSync4
|
|
16539
16847
|
} from "fs";
|
|
16540
|
-
import { join as
|
|
16848
|
+
import { join as join22 } from "path";
|
|
16541
16849
|
|
|
16542
16850
|
// src/hooks/directory-readme-injector/constants.ts
|
|
16543
16851
|
init_data_path();
|
|
16544
|
-
import { join as
|
|
16852
|
+
import { join as join21 } from "path";
|
|
16545
16853
|
var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
|
|
16546
|
-
var README_INJECTOR_STORAGE =
|
|
16854
|
+
var README_INJECTOR_STORAGE = join21(OPENCODE_STORAGE4, "directory-readme");
|
|
16547
16855
|
var README_FILENAME = "README.md";
|
|
16548
16856
|
|
|
16549
16857
|
// src/hooks/directory-readme-injector/storage.ts
|
|
16550
16858
|
function getStoragePath2(sessionID) {
|
|
16551
|
-
return
|
|
16859
|
+
return join22(README_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
16552
16860
|
}
|
|
16553
16861
|
function loadInjectedPaths2(sessionID) {
|
|
16554
16862
|
const filePath = getStoragePath2(sessionID);
|
|
16555
|
-
if (!
|
|
16863
|
+
if (!existsSync18(filePath))
|
|
16556
16864
|
return new Set;
|
|
16557
16865
|
try {
|
|
16558
|
-
const content =
|
|
16866
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
16559
16867
|
const data = JSON.parse(content);
|
|
16560
16868
|
return new Set(data.injectedPaths);
|
|
16561
16869
|
} catch {
|
|
@@ -16563,19 +16871,19 @@ function loadInjectedPaths2(sessionID) {
|
|
|
16563
16871
|
}
|
|
16564
16872
|
}
|
|
16565
16873
|
function saveInjectedPaths2(sessionID, paths) {
|
|
16566
|
-
if (!
|
|
16567
|
-
|
|
16874
|
+
if (!existsSync18(README_INJECTOR_STORAGE)) {
|
|
16875
|
+
mkdirSync6(README_INJECTOR_STORAGE, { recursive: true });
|
|
16568
16876
|
}
|
|
16569
16877
|
const data = {
|
|
16570
16878
|
sessionID,
|
|
16571
16879
|
injectedPaths: [...paths],
|
|
16572
16880
|
updatedAt: Date.now()
|
|
16573
16881
|
};
|
|
16574
|
-
|
|
16882
|
+
writeFileSync6(getStoragePath2(sessionID), JSON.stringify(data, null, 2));
|
|
16575
16883
|
}
|
|
16576
16884
|
function clearInjectedPaths2(sessionID) {
|
|
16577
16885
|
const filePath = getStoragePath2(sessionID);
|
|
16578
|
-
if (
|
|
16886
|
+
if (existsSync18(filePath)) {
|
|
16579
16887
|
unlinkSync4(filePath);
|
|
16580
16888
|
}
|
|
16581
16889
|
}
|
|
@@ -16603,8 +16911,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
16603
16911
|
const found = [];
|
|
16604
16912
|
let current = startDir;
|
|
16605
16913
|
while (true) {
|
|
16606
|
-
const readmePath =
|
|
16607
|
-
if (
|
|
16914
|
+
const readmePath = join23(current, README_FILENAME);
|
|
16915
|
+
if (existsSync19(readmePath)) {
|
|
16608
16916
|
found.push(readmePath);
|
|
16609
16917
|
}
|
|
16610
16918
|
if (current === ctx.directory)
|
|
@@ -16630,7 +16938,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
16630
16938
|
if (cache.has(readmeDir))
|
|
16631
16939
|
continue;
|
|
16632
16940
|
try {
|
|
16633
|
-
const content =
|
|
16941
|
+
const content = readFileSync11(readmePath, "utf-8");
|
|
16634
16942
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
16635
16943
|
const truncationNotice = truncated ? `
|
|
16636
16944
|
|
|
@@ -16914,22 +17222,22 @@ var TRUNCATE_CONFIG = {
|
|
|
16914
17222
|
|
|
16915
17223
|
// src/hooks/anthropic-context-window-limit-recovery/storage.ts
|
|
16916
17224
|
init_data_path();
|
|
16917
|
-
import { existsSync as
|
|
16918
|
-
import { join as
|
|
17225
|
+
import { existsSync as existsSync20, readdirSync as readdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
17226
|
+
import { join as join24 } from "path";
|
|
16919
17227
|
var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
|
|
16920
|
-
var MESSAGE_STORAGE3 =
|
|
16921
|
-
var PART_STORAGE3 =
|
|
17228
|
+
var MESSAGE_STORAGE3 = join24(OPENCODE_STORAGE5, "message");
|
|
17229
|
+
var PART_STORAGE3 = join24(OPENCODE_STORAGE5, "part");
|
|
16922
17230
|
var TRUNCATION_MESSAGE = "[TOOL RESULT TRUNCATED - Context limit exceeded. Original output was too large and has been truncated to recover the session. Please re-run this tool if you need the full output.]";
|
|
16923
17231
|
function getMessageDir3(sessionID) {
|
|
16924
|
-
if (!
|
|
17232
|
+
if (!existsSync20(MESSAGE_STORAGE3))
|
|
16925
17233
|
return "";
|
|
16926
|
-
const directPath =
|
|
16927
|
-
if (
|
|
17234
|
+
const directPath = join24(MESSAGE_STORAGE3, sessionID);
|
|
17235
|
+
if (existsSync20(directPath)) {
|
|
16928
17236
|
return directPath;
|
|
16929
17237
|
}
|
|
16930
|
-
for (const dir of
|
|
16931
|
-
const sessionPath =
|
|
16932
|
-
if (
|
|
17238
|
+
for (const dir of readdirSync6(MESSAGE_STORAGE3)) {
|
|
17239
|
+
const sessionPath = join24(MESSAGE_STORAGE3, dir, sessionID);
|
|
17240
|
+
if (existsSync20(sessionPath)) {
|
|
16933
17241
|
return sessionPath;
|
|
16934
17242
|
}
|
|
16935
17243
|
}
|
|
@@ -16937,10 +17245,10 @@ function getMessageDir3(sessionID) {
|
|
|
16937
17245
|
}
|
|
16938
17246
|
function getMessageIds(sessionID) {
|
|
16939
17247
|
const messageDir = getMessageDir3(sessionID);
|
|
16940
|
-
if (!messageDir || !
|
|
17248
|
+
if (!messageDir || !existsSync20(messageDir))
|
|
16941
17249
|
return [];
|
|
16942
17250
|
const messageIds = [];
|
|
16943
|
-
for (const file of
|
|
17251
|
+
for (const file of readdirSync6(messageDir)) {
|
|
16944
17252
|
if (!file.endsWith(".json"))
|
|
16945
17253
|
continue;
|
|
16946
17254
|
const messageId = file.replace(".json", "");
|
|
@@ -16952,15 +17260,15 @@ function findToolResultsBySize(sessionID) {
|
|
|
16952
17260
|
const messageIds = getMessageIds(sessionID);
|
|
16953
17261
|
const results = [];
|
|
16954
17262
|
for (const messageID of messageIds) {
|
|
16955
|
-
const partDir =
|
|
16956
|
-
if (!
|
|
17263
|
+
const partDir = join24(PART_STORAGE3, messageID);
|
|
17264
|
+
if (!existsSync20(partDir))
|
|
16957
17265
|
continue;
|
|
16958
|
-
for (const file of
|
|
17266
|
+
for (const file of readdirSync6(partDir)) {
|
|
16959
17267
|
if (!file.endsWith(".json"))
|
|
16960
17268
|
continue;
|
|
16961
17269
|
try {
|
|
16962
|
-
const partPath =
|
|
16963
|
-
const content =
|
|
17270
|
+
const partPath = join24(partDir, file);
|
|
17271
|
+
const content = readFileSync12(partPath, "utf-8");
|
|
16964
17272
|
const part = JSON.parse(content);
|
|
16965
17273
|
if (part.type === "tool" && part.state?.output && !part.truncated) {
|
|
16966
17274
|
results.push({
|
|
@@ -16980,7 +17288,7 @@ function findToolResultsBySize(sessionID) {
|
|
|
16980
17288
|
}
|
|
16981
17289
|
function truncateToolResult(partPath) {
|
|
16982
17290
|
try {
|
|
16983
|
-
const content =
|
|
17291
|
+
const content = readFileSync12(partPath, "utf-8");
|
|
16984
17292
|
const part = JSON.parse(content);
|
|
16985
17293
|
if (!part.state?.output) {
|
|
16986
17294
|
return { success: false };
|
|
@@ -16994,7 +17302,7 @@ function truncateToolResult(partPath) {
|
|
|
16994
17302
|
part.state.time = { start: Date.now() };
|
|
16995
17303
|
}
|
|
16996
17304
|
part.state.time.compacted = Date.now();
|
|
16997
|
-
|
|
17305
|
+
writeFileSync7(partPath, JSON.stringify(part, null, 2));
|
|
16998
17306
|
return { success: true, toolName, originalSize };
|
|
16999
17307
|
} catch {
|
|
17000
17308
|
return { success: false };
|
|
@@ -17494,15 +17802,29 @@ function createCompactionContextInjector() {
|
|
|
17494
17802
|
}
|
|
17495
17803
|
// src/hooks/think-mode/detector.ts
|
|
17496
17804
|
var ENGLISH_PATTERNS = [/\bultrathink\b/i, /\bthink\b/i];
|
|
17497
|
-
var
|
|
17805
|
+
var CHINESE_KEYWORDS = [
|
|
17806
|
+
"\u601D\u8003",
|
|
17807
|
+
"\u8003\u8651",
|
|
17808
|
+
"\u8003\u616E",
|
|
17809
|
+
"\u6DF1\u5165\u601D\u8003",
|
|
17810
|
+
"\u4ED4\u7EC6\u60F3\u60F3",
|
|
17811
|
+
"\u4ED4\u7EC6\u601D\u8003",
|
|
17812
|
+
"\u8BA4\u771F\u601D\u8003",
|
|
17813
|
+
"\u597D\u597D\u60F3\u60F3",
|
|
17814
|
+
"\u597D\u597D\u8003\u8651",
|
|
17815
|
+
"\u7422\u78E8",
|
|
17816
|
+
"\u5206\u6790\u4E00\u4E0B",
|
|
17817
|
+
"\u53CD\u601D",
|
|
17818
|
+
"\u63A8\u6572",
|
|
17819
|
+
"\u659F\u914C",
|
|
17820
|
+
"\u6DF1\u601D\u719F\u8651",
|
|
17821
|
+
"\u60F3\u4E00\u60F3"
|
|
17822
|
+
];
|
|
17823
|
+
var OTHER_MULTILINGUAL_KEYWORDS = [
|
|
17498
17824
|
"\uC0DD\uAC01",
|
|
17499
17825
|
"\uACE0\uBBFC",
|
|
17500
17826
|
"\uAC80\uD1A0",
|
|
17501
17827
|
"\uC81C\uB300\uB85C",
|
|
17502
|
-
"\u601D\u8003",
|
|
17503
|
-
"\u8003\u8651",
|
|
17504
|
-
"\u8003\u616E",
|
|
17505
|
-
"\u601D\u8003",
|
|
17506
17828
|
"\u8003\u3048",
|
|
17507
17829
|
"\u719F\u8003",
|
|
17508
17830
|
"\u0938\u094B\u091A",
|
|
@@ -17580,8 +17902,9 @@ var MULTILINGUAL_KEYWORDS = [
|
|
|
17580
17902
|
"fikir",
|
|
17581
17903
|
"berfikir"
|
|
17582
17904
|
];
|
|
17583
|
-
var
|
|
17584
|
-
var
|
|
17905
|
+
var CHINESE_PATTERNS = CHINESE_KEYWORDS.map((kw) => new RegExp(kw, "i"));
|
|
17906
|
+
var MULTILINGUAL_PATTERNS = OTHER_MULTILINGUAL_KEYWORDS.map((kw) => new RegExp(kw, "i"));
|
|
17907
|
+
var THINK_PATTERNS = [...ENGLISH_PATTERNS, ...CHINESE_PATTERNS, ...MULTILINGUAL_PATTERNS];
|
|
17585
17908
|
var CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
|
|
17586
17909
|
var INLINE_CODE_PATTERN = /`[^`]+`/g;
|
|
17587
17910
|
function removeCodeBlocks(text) {
|
|
@@ -17729,53 +18052,55 @@ init_shared();
|
|
|
17729
18052
|
var thinkModeState = new Map;
|
|
17730
18053
|
function createThinkModeHook() {
|
|
17731
18054
|
return {
|
|
17732
|
-
"chat.params": async (
|
|
17733
|
-
const promptText = extractPromptText(
|
|
18055
|
+
"chat.params": async (input, output) => {
|
|
18056
|
+
const promptText = extractPromptText(input.message.parts ?? []);
|
|
17734
18057
|
const state2 = {
|
|
17735
18058
|
requested: false,
|
|
17736
18059
|
modelSwitched: false,
|
|
17737
18060
|
thinkingConfigInjected: false
|
|
17738
18061
|
};
|
|
17739
18062
|
if (!detectThinkKeyword(promptText)) {
|
|
17740
|
-
thinkModeState.set(sessionID, state2);
|
|
18063
|
+
thinkModeState.set(input.sessionID, state2);
|
|
17741
18064
|
return;
|
|
17742
18065
|
}
|
|
17743
18066
|
state2.requested = true;
|
|
17744
|
-
const
|
|
17745
|
-
|
|
17746
|
-
|
|
18067
|
+
const modelID = input.model.id;
|
|
18068
|
+
const providerID = input.model.providerID;
|
|
18069
|
+
if (!modelID) {
|
|
18070
|
+
thinkModeState.set(input.sessionID, state2);
|
|
17747
18071
|
return;
|
|
17748
18072
|
}
|
|
17749
|
-
state2.providerID =
|
|
17750
|
-
state2.modelID =
|
|
17751
|
-
if (isAlreadyHighVariant(
|
|
17752
|
-
thinkModeState.set(sessionID, state2);
|
|
18073
|
+
state2.providerID = providerID;
|
|
18074
|
+
state2.modelID = modelID;
|
|
18075
|
+
if (isAlreadyHighVariant(modelID)) {
|
|
18076
|
+
thinkModeState.set(input.sessionID, state2);
|
|
17753
18077
|
return;
|
|
17754
18078
|
}
|
|
17755
|
-
const highVariant = getHighVariant(
|
|
17756
|
-
const thinkingConfig = getThinkingConfig(
|
|
18079
|
+
const highVariant = getHighVariant(modelID);
|
|
18080
|
+
const thinkingConfig = getThinkingConfig(providerID, modelID);
|
|
17757
18081
|
if (highVariant) {
|
|
17758
|
-
|
|
17759
|
-
providerID: currentModel.providerID,
|
|
17760
|
-
modelID: highVariant
|
|
17761
|
-
};
|
|
18082
|
+
input.model.id = highVariant;
|
|
17762
18083
|
state2.modelSwitched = true;
|
|
17763
18084
|
log("Think mode: model switched to high variant", {
|
|
17764
|
-
sessionID,
|
|
17765
|
-
from:
|
|
18085
|
+
sessionID: input.sessionID,
|
|
18086
|
+
from: modelID,
|
|
17766
18087
|
to: highVariant
|
|
17767
18088
|
});
|
|
17768
18089
|
}
|
|
17769
18090
|
if (thinkingConfig) {
|
|
17770
|
-
|
|
18091
|
+
const { maxTokens, ...thinkingOptions } = thinkingConfig;
|
|
18092
|
+
if (typeof maxTokens === "number") {
|
|
18093
|
+
output.maxOutputTokens = maxTokens;
|
|
18094
|
+
}
|
|
18095
|
+
Object.assign(output.options, thinkingOptions);
|
|
17771
18096
|
state2.thinkingConfigInjected = true;
|
|
17772
18097
|
log("Think mode: thinking config injected", {
|
|
17773
|
-
sessionID,
|
|
17774
|
-
provider:
|
|
18098
|
+
sessionID: input.sessionID,
|
|
18099
|
+
provider: providerID,
|
|
17775
18100
|
config: thinkingConfig
|
|
17776
18101
|
});
|
|
17777
18102
|
}
|
|
17778
|
-
thinkModeState.set(sessionID, state2);
|
|
18103
|
+
thinkModeState.set(input.sessionID, state2);
|
|
17779
18104
|
},
|
|
17780
18105
|
event: async ({ event }) => {
|
|
17781
18106
|
if (event.type === "session.deleted") {
|
|
@@ -17789,8 +18114,8 @@ function createThinkModeHook() {
|
|
|
17789
18114
|
}
|
|
17790
18115
|
// src/hooks/claude-code-hooks/config.ts
|
|
17791
18116
|
init_shared();
|
|
17792
|
-
import { join as
|
|
17793
|
-
import { existsSync as
|
|
18117
|
+
import { join as join25 } from "path";
|
|
18118
|
+
import { existsSync as existsSync21 } from "fs";
|
|
17794
18119
|
function normalizeHookMatcher(raw) {
|
|
17795
18120
|
return {
|
|
17796
18121
|
matcher: raw.matcher ?? raw.pattern ?? "*",
|
|
@@ -17816,11 +18141,11 @@ function normalizeHooksConfig(raw) {
|
|
|
17816
18141
|
function getClaudeSettingsPaths(customPath) {
|
|
17817
18142
|
const claudeConfigDir = getClaudeConfigDir();
|
|
17818
18143
|
const paths = [
|
|
17819
|
-
|
|
17820
|
-
|
|
17821
|
-
|
|
18144
|
+
join25(claudeConfigDir, "settings.json"),
|
|
18145
|
+
join25(process.cwd(), ".claude", "settings.json"),
|
|
18146
|
+
join25(process.cwd(), ".claude", "settings.local.json")
|
|
17822
18147
|
];
|
|
17823
|
-
if (customPath &&
|
|
18148
|
+
if (customPath && existsSync21(customPath)) {
|
|
17824
18149
|
paths.unshift(customPath);
|
|
17825
18150
|
}
|
|
17826
18151
|
return paths;
|
|
@@ -17845,7 +18170,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
17845
18170
|
const paths = getClaudeSettingsPaths(customSettingsPath);
|
|
17846
18171
|
let mergedConfig = {};
|
|
17847
18172
|
for (const settingsPath of paths) {
|
|
17848
|
-
if (
|
|
18173
|
+
if (existsSync21(settingsPath)) {
|
|
17849
18174
|
try {
|
|
17850
18175
|
const content = await Bun.file(settingsPath).text();
|
|
17851
18176
|
const settings = JSON.parse(content);
|
|
@@ -17864,14 +18189,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
17864
18189
|
// src/hooks/claude-code-hooks/config-loader.ts
|
|
17865
18190
|
init_logger();
|
|
17866
18191
|
init_shared();
|
|
17867
|
-
import { existsSync as
|
|
17868
|
-
import { join as
|
|
17869
|
-
var USER_CONFIG_PATH =
|
|
18192
|
+
import { existsSync as existsSync22 } from "fs";
|
|
18193
|
+
import { join as join26 } from "path";
|
|
18194
|
+
var USER_CONFIG_PATH = join26(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
|
|
17870
18195
|
function getProjectConfigPath() {
|
|
17871
|
-
return
|
|
18196
|
+
return join26(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
17872
18197
|
}
|
|
17873
18198
|
async function loadConfigFromPath(path4) {
|
|
17874
|
-
if (!
|
|
18199
|
+
if (!existsSync22(path4)) {
|
|
17875
18200
|
return null;
|
|
17876
18201
|
}
|
|
17877
18202
|
try {
|
|
@@ -18059,17 +18384,17 @@ init_shared();
|
|
|
18059
18384
|
// src/hooks/claude-code-hooks/transcript.ts
|
|
18060
18385
|
init_tool_name();
|
|
18061
18386
|
init_shared();
|
|
18062
|
-
import { join as
|
|
18063
|
-
import { mkdirSync as
|
|
18064
|
-
import { tmpdir as
|
|
18387
|
+
import { join as join27 } from "path";
|
|
18388
|
+
import { mkdirSync as mkdirSync7, appendFileSync as appendFileSync6, existsSync as existsSync23, writeFileSync as writeFileSync8, unlinkSync as unlinkSync5 } from "fs";
|
|
18389
|
+
import { tmpdir as tmpdir6 } from "os";
|
|
18065
18390
|
import { randomUUID } from "crypto";
|
|
18066
|
-
var TRANSCRIPT_DIR =
|
|
18391
|
+
var TRANSCRIPT_DIR = join27(getClaudeConfigDir(), "transcripts");
|
|
18067
18392
|
function getTranscriptPath(sessionId) {
|
|
18068
|
-
return
|
|
18393
|
+
return join27(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
18069
18394
|
}
|
|
18070
18395
|
function ensureTranscriptDir() {
|
|
18071
|
-
if (!
|
|
18072
|
-
|
|
18396
|
+
if (!existsSync23(TRANSCRIPT_DIR)) {
|
|
18397
|
+
mkdirSync7(TRANSCRIPT_DIR, { recursive: true });
|
|
18073
18398
|
}
|
|
18074
18399
|
}
|
|
18075
18400
|
function appendTranscriptEntry(sessionId, entry) {
|
|
@@ -18077,7 +18402,7 @@ function appendTranscriptEntry(sessionId, entry) {
|
|
|
18077
18402
|
const path4 = getTranscriptPath(sessionId);
|
|
18078
18403
|
const line = JSON.stringify(entry) + `
|
|
18079
18404
|
`;
|
|
18080
|
-
|
|
18405
|
+
appendFileSync6(path4, line);
|
|
18081
18406
|
}
|
|
18082
18407
|
function recordToolUse(sessionId, toolName, toolInput) {
|
|
18083
18408
|
appendTranscriptEntry(sessionId, {
|
|
@@ -18155,8 +18480,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
18155
18480
|
}
|
|
18156
18481
|
};
|
|
18157
18482
|
entries.push(JSON.stringify(currentEntry));
|
|
18158
|
-
const tempPath =
|
|
18159
|
-
|
|
18483
|
+
const tempPath = join27(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
18484
|
+
writeFileSync8(tempPath, entries.join(`
|
|
18160
18485
|
`) + `
|
|
18161
18486
|
`);
|
|
18162
18487
|
return tempPath;
|
|
@@ -18175,8 +18500,8 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
18175
18500
|
]
|
|
18176
18501
|
}
|
|
18177
18502
|
};
|
|
18178
|
-
const tempPath =
|
|
18179
|
-
|
|
18503
|
+
const tempPath = join27(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
18504
|
+
writeFileSync8(tempPath, JSON.stringify(currentEntry) + `
|
|
18180
18505
|
`);
|
|
18181
18506
|
return tempPath;
|
|
18182
18507
|
} catch {
|
|
@@ -18391,11 +18716,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
|
|
|
18391
18716
|
init_shared();
|
|
18392
18717
|
|
|
18393
18718
|
// src/hooks/claude-code-hooks/todo.ts
|
|
18394
|
-
import { join as
|
|
18719
|
+
import { join as join28 } from "path";
|
|
18395
18720
|
init_shared();
|
|
18396
|
-
var TODO_DIR =
|
|
18721
|
+
var TODO_DIR = join28(getClaudeConfigDir(), "todos");
|
|
18397
18722
|
function getTodoPath(sessionId) {
|
|
18398
|
-
return
|
|
18723
|
+
return join28(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
|
|
18399
18724
|
}
|
|
18400
18725
|
|
|
18401
18726
|
// src/hooks/claude-code-hooks/stop.ts
|
|
@@ -18837,24 +19162,24 @@ ${result.message}`;
|
|
|
18837
19162
|
};
|
|
18838
19163
|
}
|
|
18839
19164
|
// src/hooks/rules-injector/index.ts
|
|
18840
|
-
import { readFileSync as
|
|
19165
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
18841
19166
|
import { homedir as homedir8 } from "os";
|
|
18842
|
-
import { relative as
|
|
19167
|
+
import { relative as relative4, resolve as resolve5 } from "path";
|
|
18843
19168
|
|
|
18844
19169
|
// src/hooks/rules-injector/finder.ts
|
|
18845
19170
|
import {
|
|
18846
|
-
existsSync as
|
|
18847
|
-
readdirSync as
|
|
19171
|
+
existsSync as existsSync24,
|
|
19172
|
+
readdirSync as readdirSync7,
|
|
18848
19173
|
realpathSync,
|
|
18849
19174
|
statSync as statSync2
|
|
18850
19175
|
} from "fs";
|
|
18851
|
-
import { dirname as dirname4, join as
|
|
19176
|
+
import { dirname as dirname4, join as join30, relative as relative2 } from "path";
|
|
18852
19177
|
|
|
18853
19178
|
// src/hooks/rules-injector/constants.ts
|
|
18854
19179
|
init_data_path();
|
|
18855
|
-
import { join as
|
|
19180
|
+
import { join as join29 } from "path";
|
|
18856
19181
|
var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
|
|
18857
|
-
var RULES_INJECTOR_STORAGE =
|
|
19182
|
+
var RULES_INJECTOR_STORAGE = join29(OPENCODE_STORAGE6, "rules-injector");
|
|
18858
19183
|
var PROJECT_MARKERS = [
|
|
18859
19184
|
".git",
|
|
18860
19185
|
"pyproject.toml",
|
|
@@ -18895,8 +19220,8 @@ function findProjectRoot(startPath) {
|
|
|
18895
19220
|
}
|
|
18896
19221
|
while (true) {
|
|
18897
19222
|
for (const marker of PROJECT_MARKERS) {
|
|
18898
|
-
const markerPath =
|
|
18899
|
-
if (
|
|
19223
|
+
const markerPath = join30(current, marker);
|
|
19224
|
+
if (existsSync24(markerPath)) {
|
|
18900
19225
|
return current;
|
|
18901
19226
|
}
|
|
18902
19227
|
}
|
|
@@ -18908,12 +19233,12 @@ function findProjectRoot(startPath) {
|
|
|
18908
19233
|
}
|
|
18909
19234
|
}
|
|
18910
19235
|
function findRuleFilesRecursive(dir, results) {
|
|
18911
|
-
if (!
|
|
19236
|
+
if (!existsSync24(dir))
|
|
18912
19237
|
return;
|
|
18913
19238
|
try {
|
|
18914
|
-
const entries =
|
|
19239
|
+
const entries = readdirSync7(dir, { withFileTypes: true });
|
|
18915
19240
|
for (const entry of entries) {
|
|
18916
|
-
const fullPath =
|
|
19241
|
+
const fullPath = join30(dir, entry.name);
|
|
18917
19242
|
if (entry.isDirectory()) {
|
|
18918
19243
|
findRuleFilesRecursive(fullPath, results);
|
|
18919
19244
|
} else if (entry.isFile()) {
|
|
@@ -18938,7 +19263,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
18938
19263
|
let distance = 0;
|
|
18939
19264
|
while (true) {
|
|
18940
19265
|
for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
|
|
18941
|
-
const ruleDir =
|
|
19266
|
+
const ruleDir = join30(currentDir, parent, subdir);
|
|
18942
19267
|
const files = [];
|
|
18943
19268
|
findRuleFilesRecursive(ruleDir, files);
|
|
18944
19269
|
for (const filePath of files) {
|
|
@@ -18964,8 +19289,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
18964
19289
|
}
|
|
18965
19290
|
if (projectRoot) {
|
|
18966
19291
|
for (const ruleFile of PROJECT_RULE_FILES) {
|
|
18967
|
-
const filePath =
|
|
18968
|
-
if (
|
|
19292
|
+
const filePath = join30(projectRoot, ruleFile);
|
|
19293
|
+
if (existsSync24(filePath)) {
|
|
18969
19294
|
try {
|
|
18970
19295
|
const stat = statSync2(filePath);
|
|
18971
19296
|
if (stat.isFile()) {
|
|
@@ -18985,7 +19310,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
18985
19310
|
}
|
|
18986
19311
|
}
|
|
18987
19312
|
}
|
|
18988
|
-
const userRuleDir =
|
|
19313
|
+
const userRuleDir = join30(homeDir, USER_RULE_DIR);
|
|
18989
19314
|
const userFiles = [];
|
|
18990
19315
|
findRuleFilesRecursive(userRuleDir, userFiles);
|
|
18991
19316
|
for (const filePath of userFiles) {
|
|
@@ -19012,7 +19337,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
19012
19337
|
// src/hooks/rules-injector/matcher.ts
|
|
19013
19338
|
var import_picomatch = __toESM(require_picomatch2(), 1);
|
|
19014
19339
|
import { createHash } from "crypto";
|
|
19015
|
-
import { relative as
|
|
19340
|
+
import { relative as relative3 } from "path";
|
|
19016
19341
|
function shouldApplyRule(metadata, currentFilePath, projectRoot) {
|
|
19017
19342
|
if (metadata.alwaysApply === true) {
|
|
19018
19343
|
return { applies: true, reason: "alwaysApply" };
|
|
@@ -19025,7 +19350,7 @@ function shouldApplyRule(metadata, currentFilePath, projectRoot) {
|
|
|
19025
19350
|
if (patterns.length === 0) {
|
|
19026
19351
|
return { applies: false };
|
|
19027
19352
|
}
|
|
19028
|
-
const relativePath = projectRoot ?
|
|
19353
|
+
const relativePath = projectRoot ? relative3(projectRoot, currentFilePath) : currentFilePath;
|
|
19029
19354
|
for (const pattern of patterns) {
|
|
19030
19355
|
if (import_picomatch.default.isMatch(relativePath, pattern, { dot: true, bash: true })) {
|
|
19031
19356
|
return { applies: true, reason: `glob: ${pattern}` };
|
|
@@ -19174,22 +19499,22 @@ function mergeGlobs(existing, newValue) {
|
|
|
19174
19499
|
|
|
19175
19500
|
// src/hooks/rules-injector/storage.ts
|
|
19176
19501
|
import {
|
|
19177
|
-
existsSync as
|
|
19178
|
-
mkdirSync as
|
|
19179
|
-
readFileSync as
|
|
19180
|
-
writeFileSync as
|
|
19502
|
+
existsSync as existsSync25,
|
|
19503
|
+
mkdirSync as mkdirSync8,
|
|
19504
|
+
readFileSync as readFileSync13,
|
|
19505
|
+
writeFileSync as writeFileSync9,
|
|
19181
19506
|
unlinkSync as unlinkSync6
|
|
19182
19507
|
} from "fs";
|
|
19183
|
-
import { join as
|
|
19508
|
+
import { join as join31 } from "path";
|
|
19184
19509
|
function getStoragePath3(sessionID) {
|
|
19185
|
-
return
|
|
19510
|
+
return join31(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
19186
19511
|
}
|
|
19187
19512
|
function loadInjectedRules(sessionID) {
|
|
19188
19513
|
const filePath = getStoragePath3(sessionID);
|
|
19189
|
-
if (!
|
|
19514
|
+
if (!existsSync25(filePath))
|
|
19190
19515
|
return { contentHashes: new Set, realPaths: new Set };
|
|
19191
19516
|
try {
|
|
19192
|
-
const content =
|
|
19517
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
19193
19518
|
const data = JSON.parse(content);
|
|
19194
19519
|
return {
|
|
19195
19520
|
contentHashes: new Set(data.injectedHashes),
|
|
@@ -19200,8 +19525,8 @@ function loadInjectedRules(sessionID) {
|
|
|
19200
19525
|
}
|
|
19201
19526
|
}
|
|
19202
19527
|
function saveInjectedRules(sessionID, data) {
|
|
19203
|
-
if (!
|
|
19204
|
-
|
|
19528
|
+
if (!existsSync25(RULES_INJECTOR_STORAGE)) {
|
|
19529
|
+
mkdirSync8(RULES_INJECTOR_STORAGE, { recursive: true });
|
|
19205
19530
|
}
|
|
19206
19531
|
const storageData = {
|
|
19207
19532
|
sessionID,
|
|
@@ -19209,11 +19534,11 @@ function saveInjectedRules(sessionID, data) {
|
|
|
19209
19534
|
injectedRealPaths: [...data.realPaths],
|
|
19210
19535
|
updatedAt: Date.now()
|
|
19211
19536
|
};
|
|
19212
|
-
|
|
19537
|
+
writeFileSync9(getStoragePath3(sessionID), JSON.stringify(storageData, null, 2));
|
|
19213
19538
|
}
|
|
19214
19539
|
function clearInjectedRules(sessionID) {
|
|
19215
19540
|
const filePath = getStoragePath3(sessionID);
|
|
19216
|
-
if (
|
|
19541
|
+
if (existsSync25(filePath)) {
|
|
19217
19542
|
unlinkSync6(filePath);
|
|
19218
19543
|
}
|
|
19219
19544
|
}
|
|
@@ -19251,7 +19576,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
19251
19576
|
if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
|
|
19252
19577
|
continue;
|
|
19253
19578
|
try {
|
|
19254
|
-
const rawContent =
|
|
19579
|
+
const rawContent = readFileSync14(candidate.path, "utf-8");
|
|
19255
19580
|
const { metadata, body } = parseRuleFrontmatter(rawContent);
|
|
19256
19581
|
let matchReason;
|
|
19257
19582
|
if (candidate.isSingleFile) {
|
|
@@ -19265,7 +19590,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
19265
19590
|
const contentHash = createContentHash(body);
|
|
19266
19591
|
if (isDuplicateByContentHash(contentHash, cache2.contentHashes))
|
|
19267
19592
|
continue;
|
|
19268
|
-
const relativePath = projectRoot ?
|
|
19593
|
+
const relativePath = projectRoot ? relative4(projectRoot, candidate.path) : candidate.path;
|
|
19269
19594
|
toInject.push({
|
|
19270
19595
|
relativePath,
|
|
19271
19596
|
matchReason,
|
|
@@ -19369,19 +19694,19 @@ init_auto_update_checker();
|
|
|
19369
19694
|
|
|
19370
19695
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
19371
19696
|
import {
|
|
19372
|
-
existsSync as
|
|
19373
|
-
mkdirSync as
|
|
19374
|
-
readFileSync as
|
|
19375
|
-
writeFileSync as
|
|
19697
|
+
existsSync as existsSync28,
|
|
19698
|
+
mkdirSync as mkdirSync9,
|
|
19699
|
+
readFileSync as readFileSync17,
|
|
19700
|
+
writeFileSync as writeFileSync12,
|
|
19376
19701
|
unlinkSync as unlinkSync7
|
|
19377
19702
|
} from "fs";
|
|
19378
|
-
import { join as
|
|
19703
|
+
import { join as join36 } from "path";
|
|
19379
19704
|
|
|
19380
19705
|
// src/hooks/agent-usage-reminder/constants.ts
|
|
19381
19706
|
init_data_path();
|
|
19382
|
-
import { join as
|
|
19707
|
+
import { join as join35 } from "path";
|
|
19383
19708
|
var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
|
|
19384
|
-
var AGENT_USAGE_REMINDER_STORAGE =
|
|
19709
|
+
var AGENT_USAGE_REMINDER_STORAGE = join35(OPENCODE_STORAGE7, "agent-usage-reminder");
|
|
19385
19710
|
var TARGET_TOOLS = new Set([
|
|
19386
19711
|
"grep",
|
|
19387
19712
|
"safe_grep",
|
|
@@ -19427,29 +19752,29 @@ delegate_task(agent="librarian", prompt="\u67E5\u627E Z \u7684\u6587\u6863")
|
|
|
19427
19752
|
|
|
19428
19753
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
19429
19754
|
function getStoragePath4(sessionID) {
|
|
19430
|
-
return
|
|
19755
|
+
return join36(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
19431
19756
|
}
|
|
19432
19757
|
function loadAgentUsageState(sessionID) {
|
|
19433
19758
|
const filePath = getStoragePath4(sessionID);
|
|
19434
|
-
if (!
|
|
19759
|
+
if (!existsSync28(filePath))
|
|
19435
19760
|
return null;
|
|
19436
19761
|
try {
|
|
19437
|
-
const content =
|
|
19762
|
+
const content = readFileSync17(filePath, "utf-8");
|
|
19438
19763
|
return JSON.parse(content);
|
|
19439
19764
|
} catch {
|
|
19440
19765
|
return null;
|
|
19441
19766
|
}
|
|
19442
19767
|
}
|
|
19443
19768
|
function saveAgentUsageState(state2) {
|
|
19444
|
-
if (!
|
|
19445
|
-
|
|
19769
|
+
if (!existsSync28(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
19770
|
+
mkdirSync9(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
19446
19771
|
}
|
|
19447
19772
|
const filePath = getStoragePath4(state2.sessionID);
|
|
19448
|
-
|
|
19773
|
+
writeFileSync12(filePath, JSON.stringify(state2, null, 2));
|
|
19449
19774
|
}
|
|
19450
19775
|
function clearAgentUsageState(sessionID) {
|
|
19451
19776
|
const filePath = getStoragePath4(sessionID);
|
|
19452
|
-
if (
|
|
19777
|
+
if (existsSync28(filePath)) {
|
|
19453
19778
|
unlinkSync7(filePath);
|
|
19454
19779
|
}
|
|
19455
19780
|
}
|
|
@@ -20032,19 +20357,19 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
20032
20357
|
}
|
|
20033
20358
|
// src/hooks/interactive-bash-session/storage.ts
|
|
20034
20359
|
import {
|
|
20035
|
-
existsSync as
|
|
20036
|
-
mkdirSync as
|
|
20037
|
-
readFileSync as
|
|
20038
|
-
writeFileSync as
|
|
20360
|
+
existsSync as existsSync29,
|
|
20361
|
+
mkdirSync as mkdirSync10,
|
|
20362
|
+
readFileSync as readFileSync18,
|
|
20363
|
+
writeFileSync as writeFileSync13,
|
|
20039
20364
|
unlinkSync as unlinkSync8
|
|
20040
20365
|
} from "fs";
|
|
20041
|
-
import { join as
|
|
20366
|
+
import { join as join38 } from "path";
|
|
20042
20367
|
|
|
20043
20368
|
// src/hooks/interactive-bash-session/constants.ts
|
|
20044
20369
|
init_data_path();
|
|
20045
|
-
import { join as
|
|
20370
|
+
import { join as join37 } from "path";
|
|
20046
20371
|
var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
|
|
20047
|
-
var INTERACTIVE_BASH_SESSION_STORAGE =
|
|
20372
|
+
var INTERACTIVE_BASH_SESSION_STORAGE = join37(OPENCODE_STORAGE8, "interactive-bash-session");
|
|
20048
20373
|
var OMO_SESSION_PREFIX = "omo-";
|
|
20049
20374
|
function buildSessionReminderMessage(sessions) {
|
|
20050
20375
|
if (sessions.length === 0)
|
|
@@ -20056,14 +20381,14 @@ function buildSessionReminderMessage(sessions) {
|
|
|
20056
20381
|
|
|
20057
20382
|
// src/hooks/interactive-bash-session/storage.ts
|
|
20058
20383
|
function getStoragePath5(sessionID) {
|
|
20059
|
-
return
|
|
20384
|
+
return join38(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
|
|
20060
20385
|
}
|
|
20061
20386
|
function loadInteractiveBashSessionState(sessionID) {
|
|
20062
20387
|
const filePath = getStoragePath5(sessionID);
|
|
20063
|
-
if (!
|
|
20388
|
+
if (!existsSync29(filePath))
|
|
20064
20389
|
return null;
|
|
20065
20390
|
try {
|
|
20066
|
-
const content =
|
|
20391
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
20067
20392
|
const serialized = JSON.parse(content);
|
|
20068
20393
|
return {
|
|
20069
20394
|
sessionID: serialized.sessionID,
|
|
@@ -20075,8 +20400,8 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
20075
20400
|
}
|
|
20076
20401
|
}
|
|
20077
20402
|
function saveInteractiveBashSessionState(state2) {
|
|
20078
|
-
if (!
|
|
20079
|
-
|
|
20403
|
+
if (!existsSync29(INTERACTIVE_BASH_SESSION_STORAGE)) {
|
|
20404
|
+
mkdirSync10(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
|
|
20080
20405
|
}
|
|
20081
20406
|
const filePath = getStoragePath5(state2.sessionID);
|
|
20082
20407
|
const serialized = {
|
|
@@ -20084,11 +20409,11 @@ function saveInteractiveBashSessionState(state2) {
|
|
|
20084
20409
|
tmuxSessions: Array.from(state2.tmuxSessions),
|
|
20085
20410
|
updatedAt: state2.updatedAt
|
|
20086
20411
|
};
|
|
20087
|
-
|
|
20412
|
+
writeFileSync13(filePath, JSON.stringify(serialized, null, 2));
|
|
20088
20413
|
}
|
|
20089
20414
|
function clearInteractiveBashSessionState(sessionID) {
|
|
20090
20415
|
const filePath = getStoragePath5(sessionID);
|
|
20091
|
-
if (
|
|
20416
|
+
if (existsSync29(filePath)) {
|
|
20092
20417
|
unlinkSync8(filePath);
|
|
20093
20418
|
}
|
|
20094
20419
|
}
|
|
@@ -20342,7 +20667,7 @@ function createThinkingBlockValidatorHook() {
|
|
|
20342
20667
|
continue;
|
|
20343
20668
|
if (hasContentParts(msg.parts) && !startsWithThinkingBlock(msg.parts)) {
|
|
20344
20669
|
const previousThinking = findPreviousThinkingContent(messages, i2);
|
|
20345
|
-
const thinkingContent = previousThinking || "[
|
|
20670
|
+
const thinkingContent = previousThinking || "[\u63A5\u7EED\u4E4B\u524D\u7684\u63A8\u7406]";
|
|
20346
20671
|
prependThinkingBlock(msg, thinkingContent);
|
|
20347
20672
|
}
|
|
20348
20673
|
}
|
|
@@ -20352,13 +20677,13 @@ function createThinkingBlockValidatorHook() {
|
|
|
20352
20677
|
// src/hooks/ralph-loop/index.ts
|
|
20353
20678
|
init_logger();
|
|
20354
20679
|
init_system_directive();
|
|
20355
|
-
import { existsSync as
|
|
20356
|
-
import { join as
|
|
20680
|
+
import { existsSync as existsSync31, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "fs";
|
|
20681
|
+
import { join as join40 } from "path";
|
|
20357
20682
|
|
|
20358
20683
|
// src/hooks/ralph-loop/storage.ts
|
|
20359
20684
|
init_frontmatter();
|
|
20360
|
-
import { existsSync as
|
|
20361
|
-
import { dirname as dirname6, join as
|
|
20685
|
+
import { existsSync as existsSync30, readFileSync as readFileSync19, writeFileSync as writeFileSync14, unlinkSync as unlinkSync9, mkdirSync as mkdirSync11 } from "fs";
|
|
20686
|
+
import { dirname as dirname6, join as join39 } from "path";
|
|
20362
20687
|
|
|
20363
20688
|
// src/hooks/ralph-loop/constants.ts
|
|
20364
20689
|
var HOOK_NAME3 = "ralph-loop";
|
|
@@ -20368,15 +20693,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
20368
20693
|
|
|
20369
20694
|
// src/hooks/ralph-loop/storage.ts
|
|
20370
20695
|
function getStateFilePath(directory, customPath) {
|
|
20371
|
-
return customPath ?
|
|
20696
|
+
return customPath ? join39(directory, customPath) : join39(directory, DEFAULT_STATE_FILE);
|
|
20372
20697
|
}
|
|
20373
20698
|
function readState(directory, customPath) {
|
|
20374
20699
|
const filePath = getStateFilePath(directory, customPath);
|
|
20375
|
-
if (!
|
|
20700
|
+
if (!existsSync30(filePath)) {
|
|
20376
20701
|
return null;
|
|
20377
20702
|
}
|
|
20378
20703
|
try {
|
|
20379
|
-
const content =
|
|
20704
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
20380
20705
|
const { data, body } = parseFrontmatter(content);
|
|
20381
20706
|
const active = data.active;
|
|
20382
20707
|
const iteration = data.iteration;
|
|
@@ -20410,8 +20735,8 @@ function writeState(directory, state2, customPath) {
|
|
|
20410
20735
|
const filePath = getStateFilePath(directory, customPath);
|
|
20411
20736
|
try {
|
|
20412
20737
|
const dir = dirname6(filePath);
|
|
20413
|
-
if (!
|
|
20414
|
-
|
|
20738
|
+
if (!existsSync30(dir)) {
|
|
20739
|
+
mkdirSync11(dir, { recursive: true });
|
|
20415
20740
|
}
|
|
20416
20741
|
const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
|
|
20417
20742
|
` : "";
|
|
@@ -20426,7 +20751,7 @@ started_at: "${state2.started_at}"
|
|
|
20426
20751
|
${sessionIdLine}${ultraworkLine}---
|
|
20427
20752
|
${state2.prompt}
|
|
20428
20753
|
`;
|
|
20429
|
-
|
|
20754
|
+
writeFileSync14(filePath, content, "utf-8");
|
|
20430
20755
|
return true;
|
|
20431
20756
|
} catch {
|
|
20432
20757
|
return false;
|
|
@@ -20435,7 +20760,7 @@ ${state2.prompt}
|
|
|
20435
20760
|
function clearState(directory, customPath) {
|
|
20436
20761
|
const filePath = getStateFilePath(directory, customPath);
|
|
20437
20762
|
try {
|
|
20438
|
-
if (
|
|
20763
|
+
if (existsSync30(filePath)) {
|
|
20439
20764
|
unlinkSync9(filePath);
|
|
20440
20765
|
}
|
|
20441
20766
|
return true;
|
|
@@ -20456,14 +20781,14 @@ function incrementIteration(directory, customPath) {
|
|
|
20456
20781
|
|
|
20457
20782
|
// src/hooks/ralph-loop/index.ts
|
|
20458
20783
|
function getMessageDir4(sessionID) {
|
|
20459
|
-
if (!
|
|
20784
|
+
if (!existsSync31(MESSAGE_STORAGE))
|
|
20460
20785
|
return null;
|
|
20461
|
-
const directPath =
|
|
20462
|
-
if (
|
|
20786
|
+
const directPath = join40(MESSAGE_STORAGE, sessionID);
|
|
20787
|
+
if (existsSync31(directPath))
|
|
20463
20788
|
return directPath;
|
|
20464
|
-
for (const dir of
|
|
20465
|
-
const sessionPath =
|
|
20466
|
-
if (
|
|
20789
|
+
for (const dir of readdirSync8(MESSAGE_STORAGE)) {
|
|
20790
|
+
const sessionPath = join40(MESSAGE_STORAGE, dir, sessionID);
|
|
20791
|
+
if (existsSync31(sessionPath))
|
|
20467
20792
|
return sessionPath;
|
|
20468
20793
|
}
|
|
20469
20794
|
return null;
|
|
@@ -20500,9 +20825,9 @@ function createRalphLoopHook(ctx, options) {
|
|
|
20500
20825
|
if (!transcriptPath)
|
|
20501
20826
|
return false;
|
|
20502
20827
|
try {
|
|
20503
|
-
if (!
|
|
20828
|
+
if (!existsSync31(transcriptPath))
|
|
20504
20829
|
return false;
|
|
20505
|
-
const content =
|
|
20830
|
+
const content = readFileSync20(transcriptPath, "utf-8");
|
|
20506
20831
|
const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
|
|
20507
20832
|
const lines = content.split(`
|
|
20508
20833
|
`).filter((l) => l.trim());
|
|
@@ -20816,8 +21141,8 @@ function extractPromptText3(parts) {
|
|
|
20816
21141
|
// src/hooks/auto-slash-command/executor.ts
|
|
20817
21142
|
init_shared();
|
|
20818
21143
|
init_file_utils();
|
|
20819
|
-
import { existsSync as
|
|
20820
|
-
import { join as
|
|
21144
|
+
import { existsSync as existsSync33, readdirSync as readdirSync9, readFileSync as readFileSync23 } from "fs";
|
|
21145
|
+
import { join as join42, basename as basename2, dirname as dirname8 } from "path";
|
|
20821
21146
|
// src/features/opencode-skill-loader/loader.ts
|
|
20822
21147
|
init_js_yaml();
|
|
20823
21148
|
init_frontmatter();
|
|
@@ -20825,7 +21150,7 @@ init_file_utils();
|
|
|
20825
21150
|
init_shared();
|
|
20826
21151
|
init_opencode_config_dir();
|
|
20827
21152
|
import { promises as fs9 } from "fs";
|
|
20828
|
-
import { join as
|
|
21153
|
+
import { join as join41, basename } from "path";
|
|
20829
21154
|
function parseSkillMcpConfigFromFrontmatter(content) {
|
|
20830
21155
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
20831
21156
|
if (!frontmatterMatch)
|
|
@@ -20841,7 +21166,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
|
|
|
20841
21166
|
return;
|
|
20842
21167
|
}
|
|
20843
21168
|
async function loadMcpJsonFromDir(skillDir) {
|
|
20844
|
-
const mcpJsonPath =
|
|
21169
|
+
const mcpJsonPath = join41(skillDir, "mcp.json");
|
|
20845
21170
|
try {
|
|
20846
21171
|
const content = await fs9.readFile(mcpJsonPath, "utf-8");
|
|
20847
21172
|
const parsed = JSON.parse(content);
|
|
@@ -20922,11 +21247,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
20922
21247
|
for (const entry of entries) {
|
|
20923
21248
|
if (entry.name.startsWith("."))
|
|
20924
21249
|
continue;
|
|
20925
|
-
const entryPath =
|
|
21250
|
+
const entryPath = join41(skillsDir, entry.name);
|
|
20926
21251
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
20927
21252
|
const resolvedPath = await resolveSymlinkAsync(entryPath);
|
|
20928
21253
|
const dirName = entry.name;
|
|
20929
|
-
const skillMdPath =
|
|
21254
|
+
const skillMdPath = join41(resolvedPath, "SKILL.md");
|
|
20930
21255
|
try {
|
|
20931
21256
|
await fs9.access(skillMdPath);
|
|
20932
21257
|
const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
|
|
@@ -20934,7 +21259,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
20934
21259
|
skills.push(skill);
|
|
20935
21260
|
continue;
|
|
20936
21261
|
} catch {}
|
|
20937
|
-
const namedSkillMdPath =
|
|
21262
|
+
const namedSkillMdPath = join41(resolvedPath, `${dirName}.md`);
|
|
20938
21263
|
try {
|
|
20939
21264
|
await fs9.access(namedSkillMdPath);
|
|
20940
21265
|
const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
|
|
@@ -20962,23 +21287,23 @@ function skillsToRecord(skills) {
|
|
|
20962
21287
|
return result;
|
|
20963
21288
|
}
|
|
20964
21289
|
async function loadUserSkills() {
|
|
20965
|
-
const userSkillsDir =
|
|
21290
|
+
const userSkillsDir = join41(getClaudeConfigDir(), "skills");
|
|
20966
21291
|
const skills = await loadSkillsFromDir(userSkillsDir, "user");
|
|
20967
21292
|
return skillsToRecord(skills);
|
|
20968
21293
|
}
|
|
20969
21294
|
async function loadProjectSkills() {
|
|
20970
|
-
const projectSkillsDir =
|
|
21295
|
+
const projectSkillsDir = join41(process.cwd(), ".claude", "skills");
|
|
20971
21296
|
const skills = await loadSkillsFromDir(projectSkillsDir, "project");
|
|
20972
21297
|
return skillsToRecord(skills);
|
|
20973
21298
|
}
|
|
20974
21299
|
async function loadOpencodeGlobalSkills() {
|
|
20975
21300
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
20976
|
-
const opencodeSkillsDir =
|
|
21301
|
+
const opencodeSkillsDir = join41(configDir, "skills");
|
|
20977
21302
|
const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
20978
21303
|
return skillsToRecord(skills);
|
|
20979
21304
|
}
|
|
20980
21305
|
async function loadOpencodeProjectSkills() {
|
|
20981
|
-
const opencodeProjectDir =
|
|
21306
|
+
const opencodeProjectDir = join41(process.cwd(), ".opencode", "skills");
|
|
20982
21307
|
const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
20983
21308
|
return skillsToRecord(skills);
|
|
20984
21309
|
}
|
|
@@ -21007,28 +21332,29 @@ async function discoverSkills(options = {}) {
|
|
|
21007
21332
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
|
|
21008
21333
|
}
|
|
21009
21334
|
async function discoverUserClaudeSkills() {
|
|
21010
|
-
const userSkillsDir =
|
|
21335
|
+
const userSkillsDir = join41(getClaudeConfigDir(), "skills");
|
|
21011
21336
|
return loadSkillsFromDir(userSkillsDir, "user");
|
|
21012
21337
|
}
|
|
21013
21338
|
async function discoverProjectClaudeSkills() {
|
|
21014
|
-
const projectSkillsDir =
|
|
21339
|
+
const projectSkillsDir = join41(process.cwd(), ".claude", "skills");
|
|
21015
21340
|
return loadSkillsFromDir(projectSkillsDir, "project");
|
|
21016
21341
|
}
|
|
21017
21342
|
async function discoverOpencodeGlobalSkills() {
|
|
21018
21343
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
21019
|
-
const opencodeSkillsDir =
|
|
21344
|
+
const opencodeSkillsDir = join41(configDir, "skills");
|
|
21020
21345
|
return loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
21021
21346
|
}
|
|
21022
21347
|
async function discoverOpencodeProjectSkills() {
|
|
21023
|
-
const opencodeProjectDir =
|
|
21348
|
+
const opencodeProjectDir = join41(process.cwd(), ".opencode", "skills");
|
|
21024
21349
|
return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
21025
21350
|
}
|
|
21026
21351
|
// src/features/opencode-skill-loader/merger.ts
|
|
21027
21352
|
init_frontmatter();
|
|
21028
21353
|
init_deep_merge();
|
|
21029
|
-
import { readFileSync as
|
|
21354
|
+
import { readFileSync as readFileSync21, existsSync as existsSync32 } from "fs";
|
|
21030
21355
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
21031
21356
|
import { homedir as homedir11 } from "os";
|
|
21357
|
+
import { createHash as createHash2 } from "crypto";
|
|
21032
21358
|
var SCOPE_PRIORITY = {
|
|
21033
21359
|
builtin: 1,
|
|
21034
21360
|
config: 2,
|
|
@@ -21074,9 +21400,9 @@ function resolveFilePath2(from, configDir) {
|
|
|
21074
21400
|
}
|
|
21075
21401
|
function loadSkillFromFile(filePath) {
|
|
21076
21402
|
try {
|
|
21077
|
-
if (!
|
|
21403
|
+
if (!existsSync32(filePath))
|
|
21078
21404
|
return null;
|
|
21079
|
-
const content =
|
|
21405
|
+
const content = readFileSync21(filePath, "utf-8");
|
|
21080
21406
|
const { data, body } = parseFrontmatter(content);
|
|
21081
21407
|
return { template: body, metadata: data };
|
|
21082
21408
|
} catch {
|
|
@@ -21163,13 +21489,28 @@ function mergeSkillDefinitions(base, patch) {
|
|
|
21163
21489
|
allowedTools: mergedTools ? [...new Set(mergedTools)] : undefined
|
|
21164
21490
|
};
|
|
21165
21491
|
}
|
|
21492
|
+
function contentHash(content) {
|
|
21493
|
+
return createHash2("md5").update(content).digest("hex").slice(0, 8);
|
|
21494
|
+
}
|
|
21495
|
+
function emptyDedupStats() {
|
|
21496
|
+
return { totalScanned: 0, unique: 0, skippedByScope: 0, skippedByContent: 0, byScope: {} };
|
|
21497
|
+
}
|
|
21166
21498
|
function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills, projectClaudeSkills, projectOpencodeSkills, options = {}) {
|
|
21167
21499
|
const skillMap = new Map;
|
|
21500
|
+
const contentHashes = new Map;
|
|
21501
|
+
const stats = emptyDedupStats();
|
|
21168
21502
|
for (const builtin of builtinSkills) {
|
|
21169
21503
|
const loaded = builtinToLoaded(builtin);
|
|
21170
21504
|
skillMap.set(loaded.name, loaded);
|
|
21505
|
+
stats.byScope["builtin"] = (stats.byScope["builtin"] ?? 0) + 1;
|
|
21506
|
+
stats.unique++;
|
|
21507
|
+
if (loaded.definition.template) {
|
|
21508
|
+
contentHashes.set(loaded.name, contentHash(loaded.definition.template));
|
|
21509
|
+
}
|
|
21171
21510
|
}
|
|
21511
|
+
stats.totalScanned += builtinSkills.length;
|
|
21172
21512
|
const normalizedConfig = normalizeConfig(config);
|
|
21513
|
+
let configLoaded = 0;
|
|
21173
21514
|
for (const [name, entry] of Object.entries(normalizedConfig.entries)) {
|
|
21174
21515
|
if (entry === false)
|
|
21175
21516
|
continue;
|
|
@@ -21184,9 +21525,18 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
21184
21525
|
skillMap.set(name, mergeSkillDefinitions(existing, entry));
|
|
21185
21526
|
} else {
|
|
21186
21527
|
skillMap.set(name, loaded);
|
|
21528
|
+
configLoaded++;
|
|
21529
|
+
stats.unique++;
|
|
21530
|
+
if (loaded.definition.template) {
|
|
21531
|
+
contentHashes.set(name, contentHash(loaded.definition.template));
|
|
21532
|
+
}
|
|
21187
21533
|
}
|
|
21188
21534
|
}
|
|
21189
21535
|
}
|
|
21536
|
+
if (configLoaded > 0) {
|
|
21537
|
+
stats.byScope["config"] = configLoaded;
|
|
21538
|
+
stats.totalScanned += configLoaded;
|
|
21539
|
+
}
|
|
21190
21540
|
const fileSystemSkills = [
|
|
21191
21541
|
...userClaudeSkills,
|
|
21192
21542
|
...userOpencodeSkills,
|
|
@@ -21194,10 +21544,30 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
21194
21544
|
...projectOpencodeSkills
|
|
21195
21545
|
];
|
|
21196
21546
|
for (const skill of fileSystemSkills) {
|
|
21547
|
+
stats.totalScanned++;
|
|
21548
|
+
stats.byScope[skill.scope] = (stats.byScope[skill.scope] ?? 0) + 1;
|
|
21197
21549
|
const existing = skillMap.get(skill.name);
|
|
21198
|
-
|
|
21199
|
-
|
|
21550
|
+
const hash = skill.definition.template ? contentHash(skill.definition.template) : undefined;
|
|
21551
|
+
if (existing) {
|
|
21552
|
+
const existingHash = contentHashes.get(skill.name);
|
|
21553
|
+
if (hash && existingHash && hash === existingHash) {
|
|
21554
|
+
stats.skippedByContent++;
|
|
21555
|
+
continue;
|
|
21556
|
+
}
|
|
21557
|
+
if (SCOPE_PRIORITY[skill.scope] <= SCOPE_PRIORITY[existing.scope]) {
|
|
21558
|
+
stats.skippedByScope++;
|
|
21559
|
+
continue;
|
|
21560
|
+
}
|
|
21200
21561
|
}
|
|
21562
|
+
skillMap.set(skill.name, skill);
|
|
21563
|
+
if (hash) {
|
|
21564
|
+
contentHashes.set(skill.name, hash);
|
|
21565
|
+
}
|
|
21566
|
+
stats.unique++;
|
|
21567
|
+
}
|
|
21568
|
+
if (stats.skippedByContent > 0 || stats.skippedByScope > 1) {
|
|
21569
|
+
const scopeSummary = Object.entries(stats.byScope).map(([scope, count]) => `${scope}:${count}`).join(", ");
|
|
21570
|
+
console.debug(`[skill-loader] Scanned ${stats.totalScanned} skills (${scopeSummary}), ` + `${stats.unique} loaded, ` + `${stats.skippedByContent} skipped (identical content), ` + `${stats.skippedByScope} skipped (lower priority scope)`);
|
|
21201
21571
|
}
|
|
21202
21572
|
for (const [name, entry] of Object.entries(normalizedConfig.entries)) {
|
|
21203
21573
|
if (entry === true)
|
|
@@ -22423,7 +22793,7 @@ function createBuiltinSkills() {
|
|
|
22423
22793
|
|
|
22424
22794
|
// src/features/opencode-skill-loader/skill-content.ts
|
|
22425
22795
|
init_frontmatter();
|
|
22426
|
-
import { readFileSync as
|
|
22796
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
22427
22797
|
var cachedSkills = null;
|
|
22428
22798
|
async function getAllSkills() {
|
|
22429
22799
|
if (cachedSkills)
|
|
@@ -22456,7 +22826,7 @@ async function getAllSkills() {
|
|
|
22456
22826
|
}
|
|
22457
22827
|
async function extractSkillTemplate(skill) {
|
|
22458
22828
|
if (skill.path) {
|
|
22459
|
-
const content =
|
|
22829
|
+
const content = readFileSync22(skill.path, "utf-8");
|
|
22460
22830
|
const { body } = parseFrontmatter(content);
|
|
22461
22831
|
return body.trim();
|
|
22462
22832
|
}
|
|
@@ -22558,18 +22928,18 @@ async function resolveMultipleSkillsAsync(skillNames, options) {
|
|
|
22558
22928
|
}
|
|
22559
22929
|
// src/hooks/auto-slash-command/executor.ts
|
|
22560
22930
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
22561
|
-
if (!
|
|
22931
|
+
if (!existsSync33(commandsDir)) {
|
|
22562
22932
|
return [];
|
|
22563
22933
|
}
|
|
22564
|
-
const entries =
|
|
22934
|
+
const entries = readdirSync9(commandsDir, { withFileTypes: true });
|
|
22565
22935
|
const commands = [];
|
|
22566
22936
|
for (const entry of entries) {
|
|
22567
22937
|
if (!isMarkdownFile(entry))
|
|
22568
22938
|
continue;
|
|
22569
|
-
const commandPath =
|
|
22939
|
+
const commandPath = join42(commandsDir, entry.name);
|
|
22570
22940
|
const commandName = basename2(entry.name, ".md");
|
|
22571
22941
|
try {
|
|
22572
|
-
const content =
|
|
22942
|
+
const content = readFileSync23(commandPath, "utf-8");
|
|
22573
22943
|
const { data, body } = parseFrontmatter(content);
|
|
22574
22944
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
22575
22945
|
const metadata = {
|
|
@@ -22612,10 +22982,10 @@ function skillToCommandInfo(skill) {
|
|
|
22612
22982
|
}
|
|
22613
22983
|
async function discoverAllCommands(options) {
|
|
22614
22984
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22615
|
-
const userCommandsDir =
|
|
22616
|
-
const projectCommandsDir =
|
|
22617
|
-
const opencodeGlobalDir =
|
|
22618
|
-
const opencodeProjectDir =
|
|
22985
|
+
const userCommandsDir = join42(getClaudeConfigDir(), "commands");
|
|
22986
|
+
const projectCommandsDir = join42(process.cwd(), ".claude", "commands");
|
|
22987
|
+
const opencodeGlobalDir = join42(configDir, "command");
|
|
22988
|
+
const opencodeProjectDir = join42(process.cwd(), ".opencode", "command");
|
|
22619
22989
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
22620
22990
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
22621
22991
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -22785,8 +23155,8 @@ ${EDIT_ERROR_REMINDER}`;
|
|
|
22785
23155
|
};
|
|
22786
23156
|
}
|
|
22787
23157
|
// src/hooks/prometheus-md-only/index.ts
|
|
22788
|
-
import { existsSync as
|
|
22789
|
-
import { join as
|
|
23158
|
+
import { existsSync as existsSync34, readdirSync as readdirSync10 } from "fs";
|
|
23159
|
+
import { join as join43, resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3 } from "path";
|
|
22790
23160
|
|
|
22791
23161
|
// src/hooks/prometheus-md-only/constants.ts
|
|
22792
23162
|
init_system_directive();
|
|
@@ -22891,7 +23261,7 @@ init_logger();
|
|
|
22891
23261
|
init_system_directive();
|
|
22892
23262
|
function isAllowedFile(filePath, workspaceRoot) {
|
|
22893
23263
|
const resolved = resolve7(workspaceRoot, filePath);
|
|
22894
|
-
const rel =
|
|
23264
|
+
const rel = relative5(workspaceRoot, resolved);
|
|
22895
23265
|
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
22896
23266
|
return false;
|
|
22897
23267
|
}
|
|
@@ -22905,14 +23275,14 @@ function isAllowedFile(filePath, workspaceRoot) {
|
|
|
22905
23275
|
return true;
|
|
22906
23276
|
}
|
|
22907
23277
|
function getMessageDir5(sessionID) {
|
|
22908
|
-
if (!
|
|
23278
|
+
if (!existsSync34(MESSAGE_STORAGE))
|
|
22909
23279
|
return null;
|
|
22910
|
-
const directPath =
|
|
22911
|
-
if (
|
|
23280
|
+
const directPath = join43(MESSAGE_STORAGE, sessionID);
|
|
23281
|
+
if (existsSync34(directPath))
|
|
22912
23282
|
return directPath;
|
|
22913
|
-
for (const dir of
|
|
22914
|
-
const sessionPath =
|
|
22915
|
-
if (
|
|
23283
|
+
for (const dir of readdirSync10(MESSAGE_STORAGE)) {
|
|
23284
|
+
const sessionPath = join43(MESSAGE_STORAGE, dir, sessionID);
|
|
23285
|
+
if (existsSync34(sessionPath))
|
|
22916
23286
|
return sessionPath;
|
|
22917
23287
|
}
|
|
22918
23288
|
return null;
|
|
@@ -23026,18 +23396,18 @@ var NOTEPAD_DIR = "notepads";
|
|
|
23026
23396
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
23027
23397
|
var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
|
|
23028
23398
|
// src/features/boulder-state/storage.ts
|
|
23029
|
-
import { existsSync as
|
|
23030
|
-
import { dirname as dirname9, join as
|
|
23399
|
+
import { existsSync as existsSync35, readFileSync as readFileSync24, writeFileSync as writeFileSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync11 } from "fs";
|
|
23400
|
+
import { dirname as dirname9, join as join44, basename as basename3 } from "path";
|
|
23031
23401
|
function getBoulderFilePath(directory) {
|
|
23032
|
-
return
|
|
23402
|
+
return join44(directory, BOULDER_DIR, BOULDER_FILE);
|
|
23033
23403
|
}
|
|
23034
23404
|
function readBoulderState(directory) {
|
|
23035
23405
|
const filePath = getBoulderFilePath(directory);
|
|
23036
|
-
if (!
|
|
23406
|
+
if (!existsSync35(filePath)) {
|
|
23037
23407
|
return null;
|
|
23038
23408
|
}
|
|
23039
23409
|
try {
|
|
23040
|
-
const content =
|
|
23410
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
23041
23411
|
return JSON.parse(content);
|
|
23042
23412
|
} catch {
|
|
23043
23413
|
return null;
|
|
@@ -23047,10 +23417,10 @@ function writeBoulderState(directory, state2) {
|
|
|
23047
23417
|
const filePath = getBoulderFilePath(directory);
|
|
23048
23418
|
try {
|
|
23049
23419
|
const dir = dirname9(filePath);
|
|
23050
|
-
if (!
|
|
23051
|
-
|
|
23420
|
+
if (!existsSync35(dir)) {
|
|
23421
|
+
mkdirSync12(dir, { recursive: true });
|
|
23052
23422
|
}
|
|
23053
|
-
|
|
23423
|
+
writeFileSync15(filePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
23054
23424
|
return true;
|
|
23055
23425
|
} catch {
|
|
23056
23426
|
return false;
|
|
@@ -23071,7 +23441,7 @@ function appendSessionId(directory, sessionId) {
|
|
|
23071
23441
|
function clearBoulderState(directory) {
|
|
23072
23442
|
const filePath = getBoulderFilePath(directory);
|
|
23073
23443
|
try {
|
|
23074
|
-
if (
|
|
23444
|
+
if (existsSync35(filePath)) {
|
|
23075
23445
|
const { unlinkSync: unlinkSync10 } = __require("fs");
|
|
23076
23446
|
unlinkSync10(filePath);
|
|
23077
23447
|
}
|
|
@@ -23081,13 +23451,13 @@ function clearBoulderState(directory) {
|
|
|
23081
23451
|
}
|
|
23082
23452
|
}
|
|
23083
23453
|
function findPrometheusPlans(directory) {
|
|
23084
|
-
const plansDir =
|
|
23085
|
-
if (!
|
|
23454
|
+
const plansDir = join44(directory, PROMETHEUS_PLANS_DIR);
|
|
23455
|
+
if (!existsSync35(plansDir)) {
|
|
23086
23456
|
return [];
|
|
23087
23457
|
}
|
|
23088
23458
|
try {
|
|
23089
|
-
const files =
|
|
23090
|
-
return files.filter((f) => f.endsWith(".md")).map((f) =>
|
|
23459
|
+
const files = readdirSync11(plansDir);
|
|
23460
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => join44(plansDir, f)).sort((a, b) => {
|
|
23091
23461
|
const aStat = __require("fs").statSync(a);
|
|
23092
23462
|
const bStat = __require("fs").statSync(b);
|
|
23093
23463
|
return bStat.mtimeMs - aStat.mtimeMs;
|
|
@@ -23097,11 +23467,11 @@ function findPrometheusPlans(directory) {
|
|
|
23097
23467
|
}
|
|
23098
23468
|
}
|
|
23099
23469
|
function getPlanProgress(planPath) {
|
|
23100
|
-
if (!
|
|
23470
|
+
if (!existsSync35(planPath)) {
|
|
23101
23471
|
return { total: 0, completed: 0, isComplete: true };
|
|
23102
23472
|
}
|
|
23103
23473
|
try {
|
|
23104
|
-
const content =
|
|
23474
|
+
const content = readFileSync24(planPath, "utf-8");
|
|
23105
23475
|
const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
|
|
23106
23476
|
const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
|
|
23107
23477
|
const total = uncheckedMatches.length + checkedMatches.length;
|
|
@@ -23318,8 +23688,8 @@ ${contextInfo}`;
|
|
|
23318
23688
|
}
|
|
23319
23689
|
// src/hooks/atlas/index.ts
|
|
23320
23690
|
import { execSync } from "child_process";
|
|
23321
|
-
import { existsSync as
|
|
23322
|
-
import { join as
|
|
23691
|
+
import { existsSync as existsSync36, readdirSync as readdirSync12 } from "fs";
|
|
23692
|
+
import { join as join45 } from "path";
|
|
23323
23693
|
init_logger();
|
|
23324
23694
|
init_system_directive();
|
|
23325
23695
|
var HOOK_NAME6 = "atlas";
|
|
@@ -23648,14 +24018,14 @@ function formatFileChanges(stats, notepadPath) {
|
|
|
23648
24018
|
`);
|
|
23649
24019
|
}
|
|
23650
24020
|
function getMessageDir6(sessionID) {
|
|
23651
|
-
if (!
|
|
24021
|
+
if (!existsSync36(MESSAGE_STORAGE))
|
|
23652
24022
|
return null;
|
|
23653
|
-
const directPath =
|
|
23654
|
-
if (
|
|
24023
|
+
const directPath = join45(MESSAGE_STORAGE, sessionID);
|
|
24024
|
+
if (existsSync36(directPath))
|
|
23655
24025
|
return directPath;
|
|
23656
|
-
for (const dir of
|
|
23657
|
-
const sessionPath =
|
|
23658
|
-
if (
|
|
24026
|
+
for (const dir of readdirSync12(MESSAGE_STORAGE)) {
|
|
24027
|
+
const sessionPath = join45(MESSAGE_STORAGE, dir, sessionID);
|
|
24028
|
+
if (existsSync36(sessionPath))
|
|
23659
24029
|
return sessionPath;
|
|
23660
24030
|
}
|
|
23661
24031
|
return null;
|
|
@@ -24009,7 +24379,7 @@ var DELEGATE_TASK_ERROR_PATTERNS = [
|
|
|
24009
24379
|
}
|
|
24010
24380
|
];
|
|
24011
24381
|
function detectDelegateTaskError(output) {
|
|
24012
|
-
if (!output.includes("[ERROR]") && !output.includes("Invalid arguments"))
|
|
24382
|
+
if (!output.includes("[ERROR]") && !output.includes("Invalid arguments") && !output.includes("\u53C2\u6570\u9519\u8BEF\uFF1A"))
|
|
24013
24383
|
return null;
|
|
24014
24384
|
for (const errorPattern of DELEGATE_TASK_ERROR_PATTERNS) {
|
|
24015
24385
|
if (output.includes(errorPattern.pattern)) {
|
|
@@ -24109,6 +24479,28 @@ function createQuestionLabelTruncatorHook() {
|
|
|
24109
24479
|
}
|
|
24110
24480
|
};
|
|
24111
24481
|
}
|
|
24482
|
+
// src/hooks/perf-profiler/index.ts
|
|
24483
|
+
function createPerfProfilerHook(options) {
|
|
24484
|
+
return {
|
|
24485
|
+
event: async (input) => {
|
|
24486
|
+
if (input.event.type === "message.part.updated")
|
|
24487
|
+
return;
|
|
24488
|
+
const tracer = options.tracer;
|
|
24489
|
+
if (!tracer.isEnabled())
|
|
24490
|
+
return;
|
|
24491
|
+
const mapSizes = {};
|
|
24492
|
+
for (const [name, fn] of Object.entries(options.memoryProbes ?? {})) {
|
|
24493
|
+
try {
|
|
24494
|
+
mapSizes[name] = fn();
|
|
24495
|
+
} catch {}
|
|
24496
|
+
}
|
|
24497
|
+
tracer.snapshotMemory(input.event.type, mapSizes);
|
|
24498
|
+
},
|
|
24499
|
+
"tool.execute.before": async () => {},
|
|
24500
|
+
"tool.execute.after": async () => {},
|
|
24501
|
+
"chat.message": async () => {}
|
|
24502
|
+
};
|
|
24503
|
+
}
|
|
24112
24504
|
// src/features/context-injector/collector.ts
|
|
24113
24505
|
var PRIORITY_ORDER = {
|
|
24114
24506
|
critical: 0,
|
|
@@ -24282,8 +24674,8 @@ function createFirstMessageVariantGate() {
|
|
|
24282
24674
|
}
|
|
24283
24675
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
24284
24676
|
init_shared();
|
|
24285
|
-
import { existsSync as
|
|
24286
|
-
import { join as
|
|
24677
|
+
import { existsSync as existsSync37, readFileSync as readFileSync25 } from "fs";
|
|
24678
|
+
import { join as join46 } from "path";
|
|
24287
24679
|
|
|
24288
24680
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
24289
24681
|
function expandEnvVars(value) {
|
|
@@ -24351,15 +24743,15 @@ function transformMcpServer(name, server) {
|
|
|
24351
24743
|
init_logger();
|
|
24352
24744
|
function getMcpConfigPaths() {
|
|
24353
24745
|
const claudeConfigDir = getClaudeConfigDir();
|
|
24354
|
-
const
|
|
24746
|
+
const cwd2 = process.cwd();
|
|
24355
24747
|
return [
|
|
24356
|
-
{ path:
|
|
24357
|
-
{ path:
|
|
24358
|
-
{ path:
|
|
24748
|
+
{ path: join46(claudeConfigDir, ".mcp.json"), scope: "user" },
|
|
24749
|
+
{ path: join46(cwd2, ".mcp.json"), scope: "project" },
|
|
24750
|
+
{ path: join46(cwd2, ".claude", ".mcp.json"), scope: "local" }
|
|
24359
24751
|
];
|
|
24360
24752
|
}
|
|
24361
24753
|
async function loadMcpConfigFile(filePath) {
|
|
24362
|
-
if (!
|
|
24754
|
+
if (!existsSync37(filePath)) {
|
|
24363
24755
|
return null;
|
|
24364
24756
|
}
|
|
24365
24757
|
try {
|
|
@@ -24374,10 +24766,10 @@ function getSystemMcpServerNames() {
|
|
|
24374
24766
|
const names = new Set;
|
|
24375
24767
|
const paths = getMcpConfigPaths();
|
|
24376
24768
|
for (const { path: path7 } of paths) {
|
|
24377
|
-
if (!
|
|
24769
|
+
if (!existsSync37(path7))
|
|
24378
24770
|
continue;
|
|
24379
24771
|
try {
|
|
24380
|
-
const content =
|
|
24772
|
+
const content = readFileSync25(path7, "utf-8");
|
|
24381
24773
|
const config = JSON.parse(content);
|
|
24382
24774
|
if (!config?.mcpServers)
|
|
24383
24775
|
continue;
|
|
@@ -24820,25 +25212,25 @@ var EXT_TO_LANG = {
|
|
|
24820
25212
|
".gql": "graphql"
|
|
24821
25213
|
};
|
|
24822
25214
|
// src/tools/lsp/config.ts
|
|
24823
|
-
import { existsSync as
|
|
24824
|
-
import { join as
|
|
25215
|
+
import { existsSync as existsSync38, readFileSync as readFileSync26 } from "fs";
|
|
25216
|
+
import { join as join47 } from "path";
|
|
24825
25217
|
init_shared();
|
|
24826
25218
|
function loadJsonFile(path7) {
|
|
24827
|
-
if (!
|
|
25219
|
+
if (!existsSync38(path7))
|
|
24828
25220
|
return null;
|
|
24829
25221
|
try {
|
|
24830
|
-
return JSON.parse(
|
|
25222
|
+
return JSON.parse(readFileSync26(path7, "utf-8"));
|
|
24831
25223
|
} catch {
|
|
24832
25224
|
return null;
|
|
24833
25225
|
}
|
|
24834
25226
|
}
|
|
24835
25227
|
function getConfigPaths3() {
|
|
24836
|
-
const
|
|
25228
|
+
const cwd2 = process.cwd();
|
|
24837
25229
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
24838
25230
|
return {
|
|
24839
|
-
project:
|
|
24840
|
-
user:
|
|
24841
|
-
opencode:
|
|
25231
|
+
project: join47(cwd2, ".opencode", "oh-my-opencode.json"),
|
|
25232
|
+
user: join47(configDir, "oh-my-opencode.json"),
|
|
25233
|
+
opencode: join47(configDir, "opencode.json")
|
|
24842
25234
|
};
|
|
24843
25235
|
}
|
|
24844
25236
|
function loadAllConfigs() {
|
|
@@ -24951,7 +25343,7 @@ function isServerInstalled(command) {
|
|
|
24951
25343
|
return false;
|
|
24952
25344
|
const cmd = command[0];
|
|
24953
25345
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
24954
|
-
if (
|
|
25346
|
+
if (existsSync38(cmd))
|
|
24955
25347
|
return true;
|
|
24956
25348
|
}
|
|
24957
25349
|
const isWindows2 = process.platform === "win32";
|
|
@@ -24973,23 +25365,23 @@ function isServerInstalled(command) {
|
|
|
24973
25365
|
const paths = pathEnv.split(pathSeparator);
|
|
24974
25366
|
for (const p of paths) {
|
|
24975
25367
|
for (const suffix of exts) {
|
|
24976
|
-
if (
|
|
25368
|
+
if (existsSync38(join47(p, cmd + suffix))) {
|
|
24977
25369
|
return true;
|
|
24978
25370
|
}
|
|
24979
25371
|
}
|
|
24980
25372
|
}
|
|
24981
|
-
const
|
|
25373
|
+
const cwd2 = process.cwd();
|
|
24982
25374
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
24983
|
-
const dataDir =
|
|
25375
|
+
const dataDir = join47(getDataDir(), "opencode");
|
|
24984
25376
|
const additionalBases = [
|
|
24985
|
-
|
|
24986
|
-
|
|
24987
|
-
|
|
24988
|
-
|
|
25377
|
+
join47(cwd2, "node_modules", ".bin"),
|
|
25378
|
+
join47(configDir, "bin"),
|
|
25379
|
+
join47(configDir, "node_modules", ".bin"),
|
|
25380
|
+
join47(dataDir, "bin")
|
|
24989
25381
|
];
|
|
24990
25382
|
for (const base of additionalBases) {
|
|
24991
25383
|
for (const suffix of exts) {
|
|
24992
|
-
if (
|
|
25384
|
+
if (existsSync38(join47(base, cmd + suffix))) {
|
|
24993
25385
|
return true;
|
|
24994
25386
|
}
|
|
24995
25387
|
}
|
|
@@ -25001,7 +25393,7 @@ function isServerInstalled(command) {
|
|
|
25001
25393
|
}
|
|
25002
25394
|
// src/tools/lsp/client.ts
|
|
25003
25395
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
25004
|
-
import { readFileSync as
|
|
25396
|
+
import { readFileSync as readFileSync27 } from "fs";
|
|
25005
25397
|
import { extname, resolve as resolve8 } from "path";
|
|
25006
25398
|
import { pathToFileURL } from "url";
|
|
25007
25399
|
class LSPServerManager {
|
|
@@ -25451,7 +25843,7 @@ ${msg}`);
|
|
|
25451
25843
|
const absPath = resolve8(filePath);
|
|
25452
25844
|
if (this.openedFiles.has(absPath))
|
|
25453
25845
|
return;
|
|
25454
|
-
const text =
|
|
25846
|
+
const text = readFileSync27(absPath, "utf-8");
|
|
25455
25847
|
const ext = extname(absPath);
|
|
25456
25848
|
const languageId = getLanguageId(ext);
|
|
25457
25849
|
this.notify("textDocument/didOpen", {
|
|
@@ -25541,17 +25933,17 @@ ${msg}`);
|
|
|
25541
25933
|
// src/tools/lsp/utils.ts
|
|
25542
25934
|
import { extname as extname2, resolve as resolve9 } from "path";
|
|
25543
25935
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25544
|
-
import { existsSync as
|
|
25936
|
+
import { existsSync as existsSync39, readFileSync as readFileSync28, writeFileSync as writeFileSync16 } from "fs";
|
|
25545
25937
|
function findWorkspaceRoot(filePath) {
|
|
25546
25938
|
let dir = resolve9(filePath);
|
|
25547
|
-
if (!
|
|
25939
|
+
if (!existsSync39(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
25548
25940
|
dir = __require("path").dirname(dir);
|
|
25549
25941
|
}
|
|
25550
25942
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
25551
25943
|
let prevDir = "";
|
|
25552
25944
|
while (dir !== prevDir) {
|
|
25553
25945
|
for (const marker of markers) {
|
|
25554
|
-
if (
|
|
25946
|
+
if (existsSync39(__require("path").join(dir, marker))) {
|
|
25555
25947
|
return dir;
|
|
25556
25948
|
}
|
|
25557
25949
|
}
|
|
@@ -25706,7 +26098,7 @@ function formatPrepareRenameResult(result) {
|
|
|
25706
26098
|
}
|
|
25707
26099
|
function applyTextEditsToFile(filePath, edits) {
|
|
25708
26100
|
try {
|
|
25709
|
-
let content =
|
|
26101
|
+
let content = readFileSync28(filePath, "utf-8");
|
|
25710
26102
|
const lines = content.split(`
|
|
25711
26103
|
`);
|
|
25712
26104
|
const sortedEdits = [...edits].sort((a, b) => {
|
|
@@ -25731,7 +26123,7 @@ function applyTextEditsToFile(filePath, edits) {
|
|
|
25731
26123
|
`));
|
|
25732
26124
|
}
|
|
25733
26125
|
}
|
|
25734
|
-
|
|
26126
|
+
writeFileSync16(filePath, lines.join(`
|
|
25735
26127
|
`), "utf-8");
|
|
25736
26128
|
return { success: true, editCount: edits.length };
|
|
25737
26129
|
} catch (err) {
|
|
@@ -25762,7 +26154,7 @@ function applyWorkspaceEdit(edit) {
|
|
|
25762
26154
|
if (change.kind === "create") {
|
|
25763
26155
|
try {
|
|
25764
26156
|
const filePath = uriToPath(change.uri);
|
|
25765
|
-
|
|
26157
|
+
writeFileSync16(filePath, "", "utf-8");
|
|
25766
26158
|
result.filesModified.push(filePath);
|
|
25767
26159
|
} catch (err) {
|
|
25768
26160
|
result.success = false;
|
|
@@ -25772,8 +26164,8 @@ function applyWorkspaceEdit(edit) {
|
|
|
25772
26164
|
try {
|
|
25773
26165
|
const oldPath = uriToPath(change.oldUri);
|
|
25774
26166
|
const newPath = uriToPath(change.newUri);
|
|
25775
|
-
const content =
|
|
25776
|
-
|
|
26167
|
+
const content = readFileSync28(oldPath, "utf-8");
|
|
26168
|
+
writeFileSync16(newPath, content, "utf-8");
|
|
25777
26169
|
__require("fs").unlinkSync(oldPath);
|
|
25778
26170
|
result.filesModified.push(newPath);
|
|
25779
26171
|
} catch (err) {
|
|
@@ -38352,13 +38744,13 @@ var lsp_rename = tool({
|
|
|
38352
38744
|
});
|
|
38353
38745
|
// src/tools/ast-grep/constants.ts
|
|
38354
38746
|
import { createRequire as createRequire4 } from "module";
|
|
38355
|
-
import { dirname as dirname10, join as
|
|
38356
|
-
import { existsSync as
|
|
38747
|
+
import { dirname as dirname10, join as join49 } from "path";
|
|
38748
|
+
import { existsSync as existsSync41, statSync as statSync4 } from "fs";
|
|
38357
38749
|
|
|
38358
38750
|
// src/tools/ast-grep/downloader.ts
|
|
38359
38751
|
init_shared();
|
|
38360
|
-
import { existsSync as
|
|
38361
|
-
import { join as
|
|
38752
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync13, chmodSync as chmodSync2, unlinkSync as unlinkSync10 } from "fs";
|
|
38753
|
+
import { join as join48 } from "path";
|
|
38362
38754
|
import { homedir as homedir12 } from "os";
|
|
38363
38755
|
import { createRequire as createRequire3 } from "module";
|
|
38364
38756
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -38384,19 +38776,19 @@ var PLATFORM_MAP2 = {
|
|
|
38384
38776
|
function getCacheDir3() {
|
|
38385
38777
|
if (process.platform === "win32") {
|
|
38386
38778
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
38387
|
-
const base2 = localAppData ||
|
|
38388
|
-
return
|
|
38779
|
+
const base2 = localAppData || join48(homedir12(), "AppData", "Local");
|
|
38780
|
+
return join48(base2, "oh-my-opencode", "bin");
|
|
38389
38781
|
}
|
|
38390
38782
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
38391
|
-
const base = xdgCache ||
|
|
38392
|
-
return
|
|
38783
|
+
const base = xdgCache || join48(homedir12(), ".cache");
|
|
38784
|
+
return join48(base, "oh-my-opencode", "bin");
|
|
38393
38785
|
}
|
|
38394
38786
|
function getBinaryName3() {
|
|
38395
38787
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
38396
38788
|
}
|
|
38397
38789
|
function getCachedBinaryPath2() {
|
|
38398
|
-
const binaryPath =
|
|
38399
|
-
return
|
|
38790
|
+
const binaryPath = join48(getCacheDir3(), getBinaryName3());
|
|
38791
|
+
return existsSync40(binaryPath) ? binaryPath : null;
|
|
38400
38792
|
}
|
|
38401
38793
|
async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
38402
38794
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
@@ -38407,8 +38799,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
38407
38799
|
}
|
|
38408
38800
|
const cacheDir = getCacheDir3();
|
|
38409
38801
|
const binaryName = getBinaryName3();
|
|
38410
|
-
const binaryPath =
|
|
38411
|
-
if (
|
|
38802
|
+
const binaryPath = join48(cacheDir, binaryName);
|
|
38803
|
+
if (existsSync40(binaryPath)) {
|
|
38412
38804
|
return binaryPath;
|
|
38413
38805
|
}
|
|
38414
38806
|
const { arch, os: os6 } = platformInfo;
|
|
@@ -38416,21 +38808,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
38416
38808
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
38417
38809
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
38418
38810
|
try {
|
|
38419
|
-
if (!
|
|
38420
|
-
|
|
38811
|
+
if (!existsSync40(cacheDir)) {
|
|
38812
|
+
mkdirSync13(cacheDir, { recursive: true });
|
|
38421
38813
|
}
|
|
38422
38814
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
38423
38815
|
if (!response.ok) {
|
|
38424
38816
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
38425
38817
|
}
|
|
38426
|
-
const archivePath =
|
|
38818
|
+
const archivePath = join48(cacheDir, assetName);
|
|
38427
38819
|
const arrayBuffer = await response.arrayBuffer();
|
|
38428
38820
|
await Bun.write(archivePath, arrayBuffer);
|
|
38429
38821
|
await extractZip(archivePath, cacheDir);
|
|
38430
|
-
if (
|
|
38822
|
+
if (existsSync40(archivePath)) {
|
|
38431
38823
|
unlinkSync10(archivePath);
|
|
38432
38824
|
}
|
|
38433
|
-
if (process.platform !== "win32" &&
|
|
38825
|
+
if (process.platform !== "win32" && existsSync40(binaryPath)) {
|
|
38434
38826
|
chmodSync2(binaryPath, 493);
|
|
38435
38827
|
}
|
|
38436
38828
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -38481,8 +38873,8 @@ function findSgCliPathSync() {
|
|
|
38481
38873
|
const require2 = createRequire4(import.meta.url);
|
|
38482
38874
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
38483
38875
|
const cliDir = dirname10(cliPkgPath);
|
|
38484
|
-
const sgPath =
|
|
38485
|
-
if (
|
|
38876
|
+
const sgPath = join49(cliDir, binaryName);
|
|
38877
|
+
if (existsSync41(sgPath) && isValidBinary(sgPath)) {
|
|
38486
38878
|
return sgPath;
|
|
38487
38879
|
}
|
|
38488
38880
|
} catch {}
|
|
@@ -38493,8 +38885,8 @@ function findSgCliPathSync() {
|
|
|
38493
38885
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
38494
38886
|
const pkgDir = dirname10(pkgPath);
|
|
38495
38887
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
38496
|
-
const binaryPath =
|
|
38497
|
-
if (
|
|
38888
|
+
const binaryPath = join49(pkgDir, astGrepName);
|
|
38889
|
+
if (existsSync41(binaryPath) && isValidBinary(binaryPath)) {
|
|
38498
38890
|
return binaryPath;
|
|
38499
38891
|
}
|
|
38500
38892
|
} catch {}
|
|
@@ -38502,7 +38894,7 @@ function findSgCliPathSync() {
|
|
|
38502
38894
|
if (process.platform === "darwin") {
|
|
38503
38895
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
38504
38896
|
for (const path7 of homebrewPaths) {
|
|
38505
|
-
if (
|
|
38897
|
+
if (existsSync41(path7) && isValidBinary(path7)) {
|
|
38506
38898
|
return path7;
|
|
38507
38899
|
}
|
|
38508
38900
|
}
|
|
@@ -38557,11 +38949,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
38557
38949
|
|
|
38558
38950
|
// src/tools/ast-grep/cli.ts
|
|
38559
38951
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
38560
|
-
import { existsSync as
|
|
38952
|
+
import { existsSync as existsSync42 } from "fs";
|
|
38561
38953
|
var resolvedCliPath3 = null;
|
|
38562
38954
|
var initPromise2 = null;
|
|
38563
38955
|
async function getAstGrepPath() {
|
|
38564
|
-
if (resolvedCliPath3 !== null &&
|
|
38956
|
+
if (resolvedCliPath3 !== null && existsSync42(resolvedCliPath3)) {
|
|
38565
38957
|
return resolvedCliPath3;
|
|
38566
38958
|
}
|
|
38567
38959
|
if (initPromise2) {
|
|
@@ -38569,7 +38961,7 @@ async function getAstGrepPath() {
|
|
|
38569
38961
|
}
|
|
38570
38962
|
initPromise2 = (async () => {
|
|
38571
38963
|
const syncPath = findSgCliPathSync();
|
|
38572
|
-
if (syncPath &&
|
|
38964
|
+
if (syncPath && existsSync42(syncPath)) {
|
|
38573
38965
|
resolvedCliPath3 = syncPath;
|
|
38574
38966
|
setSgCliPath(syncPath);
|
|
38575
38967
|
return syncPath;
|
|
@@ -38603,7 +38995,7 @@ async function runSg(options) {
|
|
|
38603
38995
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
38604
38996
|
args.push(...paths);
|
|
38605
38997
|
let cliPath = getSgCliPath();
|
|
38606
|
-
if (!
|
|
38998
|
+
if (!existsSync42(cliPath) && cliPath !== "sg") {
|
|
38607
38999
|
const downloadedPath = await getAstGrepPath();
|
|
38608
39000
|
if (downloadedPath) {
|
|
38609
39001
|
cliPath = downloadedPath;
|
|
@@ -38867,21 +39259,21 @@ var ast_grep_replace = tool({
|
|
|
38867
39259
|
var {spawn: spawn9 } = globalThis.Bun;
|
|
38868
39260
|
|
|
38869
39261
|
// src/tools/grep/constants.ts
|
|
38870
|
-
import { existsSync as
|
|
38871
|
-
import { join as
|
|
39262
|
+
import { existsSync as existsSync44 } from "fs";
|
|
39263
|
+
import { join as join51, dirname as dirname11 } from "path";
|
|
38872
39264
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
38873
39265
|
|
|
38874
39266
|
// src/tools/grep/downloader.ts
|
|
38875
39267
|
init_shared();
|
|
38876
|
-
import { existsSync as
|
|
38877
|
-
import { join as
|
|
39268
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync14, chmodSync as chmodSync3, unlinkSync as unlinkSync11, readdirSync as readdirSync13 } from "fs";
|
|
39269
|
+
import { join as join50 } from "path";
|
|
38878
39270
|
var {spawn: spawn8 } = globalThis.Bun;
|
|
38879
39271
|
function findFileRecursive(dir, filename) {
|
|
38880
39272
|
try {
|
|
38881
|
-
const entries =
|
|
39273
|
+
const entries = readdirSync13(dir, { withFileTypes: true, recursive: true });
|
|
38882
39274
|
for (const entry of entries) {
|
|
38883
39275
|
if (entry.isFile() && entry.name === filename) {
|
|
38884
|
-
return
|
|
39276
|
+
return join50(entry.parentPath ?? dir, entry.name);
|
|
38885
39277
|
}
|
|
38886
39278
|
}
|
|
38887
39279
|
} catch {
|
|
@@ -38902,11 +39294,11 @@ function getPlatformKey() {
|
|
|
38902
39294
|
}
|
|
38903
39295
|
function getInstallDir() {
|
|
38904
39296
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
38905
|
-
return
|
|
39297
|
+
return join50(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
38906
39298
|
}
|
|
38907
39299
|
function getRgPath() {
|
|
38908
39300
|
const isWindows2 = process.platform === "win32";
|
|
38909
|
-
return
|
|
39301
|
+
return join50(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
38910
39302
|
}
|
|
38911
39303
|
async function downloadFile(url2, destPath) {
|
|
38912
39304
|
const response = await fetch(url2);
|
|
@@ -38940,7 +39332,7 @@ async function extractZip2(archivePath, destDir) {
|
|
|
38940
39332
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
38941
39333
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
38942
39334
|
if (foundPath) {
|
|
38943
|
-
const destPath =
|
|
39335
|
+
const destPath = join50(destDir, binaryName);
|
|
38944
39336
|
if (foundPath !== destPath) {
|
|
38945
39337
|
const { renameSync } = await import("fs");
|
|
38946
39338
|
renameSync(foundPath, destPath);
|
|
@@ -38955,13 +39347,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
38955
39347
|
}
|
|
38956
39348
|
const installDir = getInstallDir();
|
|
38957
39349
|
const rgPath = getRgPath();
|
|
38958
|
-
if (
|
|
39350
|
+
if (existsSync43(rgPath)) {
|
|
38959
39351
|
return rgPath;
|
|
38960
39352
|
}
|
|
38961
|
-
|
|
39353
|
+
mkdirSync14(installDir, { recursive: true });
|
|
38962
39354
|
const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
|
|
38963
39355
|
const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
38964
|
-
const archivePath =
|
|
39356
|
+
const archivePath = join50(installDir, filename);
|
|
38965
39357
|
try {
|
|
38966
39358
|
await downloadFile(url2, archivePath);
|
|
38967
39359
|
if (config3.extension === "tar.gz") {
|
|
@@ -38972,12 +39364,12 @@ async function downloadAndInstallRipgrep() {
|
|
|
38972
39364
|
if (process.platform !== "win32") {
|
|
38973
39365
|
chmodSync3(rgPath, 493);
|
|
38974
39366
|
}
|
|
38975
|
-
if (!
|
|
39367
|
+
if (!existsSync43(rgPath)) {
|
|
38976
39368
|
throw new Error("ripgrep binary not found after extraction");
|
|
38977
39369
|
}
|
|
38978
39370
|
return rgPath;
|
|
38979
39371
|
} finally {
|
|
38980
|
-
if (
|
|
39372
|
+
if (existsSync43(archivePath)) {
|
|
38981
39373
|
try {
|
|
38982
39374
|
unlinkSync11(archivePath);
|
|
38983
39375
|
} catch {}
|
|
@@ -38986,7 +39378,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
38986
39378
|
}
|
|
38987
39379
|
function getInstalledRipgrepPath() {
|
|
38988
39380
|
const rgPath = getRgPath();
|
|
38989
|
-
return
|
|
39381
|
+
return existsSync43(rgPath) ? rgPath : null;
|
|
38990
39382
|
}
|
|
38991
39383
|
|
|
38992
39384
|
// src/tools/grep/constants.ts
|
|
@@ -39011,14 +39403,14 @@ function getOpenCodeBundledRg() {
|
|
|
39011
39403
|
const isWindows2 = process.platform === "win32";
|
|
39012
39404
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
39013
39405
|
const candidates = [
|
|
39014
|
-
|
|
39015
|
-
|
|
39016
|
-
|
|
39017
|
-
|
|
39018
|
-
|
|
39406
|
+
join51(getDataDir(), "opencode", "bin", rgName),
|
|
39407
|
+
join51(execDir, rgName),
|
|
39408
|
+
join51(execDir, "bin", rgName),
|
|
39409
|
+
join51(execDir, "..", "bin", rgName),
|
|
39410
|
+
join51(execDir, "..", "libexec", rgName)
|
|
39019
39411
|
];
|
|
39020
39412
|
for (const candidate of candidates) {
|
|
39021
|
-
if (
|
|
39413
|
+
if (existsSync44(candidate)) {
|
|
39022
39414
|
return candidate;
|
|
39023
39415
|
}
|
|
39024
39416
|
}
|
|
@@ -39355,26 +39747,26 @@ async function runRgFiles(options, resolvedCli) {
|
|
|
39355
39747
|
const isRg = cli.backend === "rg";
|
|
39356
39748
|
const isWindows2 = process.platform === "win32";
|
|
39357
39749
|
let command;
|
|
39358
|
-
let
|
|
39750
|
+
let cwd2;
|
|
39359
39751
|
if (isRg) {
|
|
39360
39752
|
const args = buildRgArgs2(options);
|
|
39361
39753
|
const paths = options.paths?.length ? options.paths : ["."];
|
|
39362
39754
|
args.push(...paths);
|
|
39363
39755
|
command = [cli.path, ...args];
|
|
39364
|
-
|
|
39756
|
+
cwd2 = undefined;
|
|
39365
39757
|
} else if (isWindows2) {
|
|
39366
39758
|
command = buildPowerShellCommand(options);
|
|
39367
|
-
|
|
39759
|
+
cwd2 = undefined;
|
|
39368
39760
|
} else {
|
|
39369
39761
|
const args = buildFindArgs(options);
|
|
39370
39762
|
const paths = options.paths?.length ? options.paths : ["."];
|
|
39371
|
-
|
|
39763
|
+
cwd2 = paths[0] || ".";
|
|
39372
39764
|
command = [cli.path, ...args];
|
|
39373
39765
|
}
|
|
39374
39766
|
const proc = spawn10(command, {
|
|
39375
39767
|
stdout: "pipe",
|
|
39376
39768
|
stderr: "pipe",
|
|
39377
|
-
cwd
|
|
39769
|
+
cwd: cwd2
|
|
39378
39770
|
});
|
|
39379
39771
|
const timeoutPromise = new Promise((_, reject) => {
|
|
39380
39772
|
const id = setTimeout(() => {
|
|
@@ -39412,7 +39804,7 @@ async function runRgFiles(options, resolvedCli) {
|
|
|
39412
39804
|
} else if (isWindows2) {
|
|
39413
39805
|
filePath = line.trim();
|
|
39414
39806
|
} else {
|
|
39415
|
-
filePath = `${
|
|
39807
|
+
filePath = `${cwd2}/${line}`;
|
|
39416
39808
|
}
|
|
39417
39809
|
const mtime = await getFileMtime(filePath);
|
|
39418
39810
|
files.push({ path: filePath, mtime });
|
|
@@ -39480,8 +39872,8 @@ var glob = tool({
|
|
|
39480
39872
|
init_shared();
|
|
39481
39873
|
init_file_utils();
|
|
39482
39874
|
init_shared();
|
|
39483
|
-
import { existsSync as
|
|
39484
|
-
import { join as
|
|
39875
|
+
import { existsSync as existsSync45, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "fs";
|
|
39876
|
+
import { join as join52, basename as basename4, dirname as dirname12 } from "path";
|
|
39485
39877
|
// src/features/builtin-commands/templates/init-deep.ts
|
|
39486
39878
|
var INIT_DEEP_TEMPLATE = `# /init-deep
|
|
39487
39879
|
|
|
@@ -40597,18 +40989,18 @@ function loadBuiltinCommands(disabledCommands) {
|
|
|
40597
40989
|
}
|
|
40598
40990
|
// src/tools/slashcommand/tools.ts
|
|
40599
40991
|
function discoverCommandsFromDir2(commandsDir, scope) {
|
|
40600
|
-
if (!
|
|
40992
|
+
if (!existsSync45(commandsDir)) {
|
|
40601
40993
|
return [];
|
|
40602
40994
|
}
|
|
40603
|
-
const entries =
|
|
40995
|
+
const entries = readdirSync14(commandsDir, { withFileTypes: true });
|
|
40604
40996
|
const commands2 = [];
|
|
40605
40997
|
for (const entry of entries) {
|
|
40606
40998
|
if (!isMarkdownFile(entry))
|
|
40607
40999
|
continue;
|
|
40608
|
-
const commandPath =
|
|
41000
|
+
const commandPath = join52(commandsDir, entry.name);
|
|
40609
41001
|
const commandName = basename4(entry.name, ".md");
|
|
40610
41002
|
try {
|
|
40611
|
-
const content =
|
|
41003
|
+
const content = readFileSync29(commandPath, "utf-8");
|
|
40612
41004
|
const { data, body } = parseFrontmatter(content);
|
|
40613
41005
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
40614
41006
|
const metadata = {
|
|
@@ -40634,10 +41026,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
40634
41026
|
}
|
|
40635
41027
|
function discoverCommandsSync() {
|
|
40636
41028
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
40637
|
-
const userCommandsDir =
|
|
40638
|
-
const projectCommandsDir =
|
|
40639
|
-
const opencodeGlobalDir =
|
|
40640
|
-
const opencodeProjectDir =
|
|
41029
|
+
const userCommandsDir = join52(getClaudeConfigDir(), "commands");
|
|
41030
|
+
const projectCommandsDir = join52(process.cwd(), ".claude", "commands");
|
|
41031
|
+
const opencodeGlobalDir = join52(configDir, "command");
|
|
41032
|
+
const opencodeProjectDir = join52(process.cwd(), ".opencode", "command");
|
|
40641
41033
|
const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
|
|
40642
41034
|
const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
|
|
40643
41035
|
const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
|
|
@@ -40814,13 +41206,13 @@ var slashcommand = createSlashcommandTool();
|
|
|
40814
41206
|
// src/tools/session-manager/constants.ts
|
|
40815
41207
|
init_data_path();
|
|
40816
41208
|
init_shared();
|
|
40817
|
-
import { join as
|
|
41209
|
+
import { join as join53 } from "path";
|
|
40818
41210
|
var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
|
|
40819
|
-
var MESSAGE_STORAGE4 =
|
|
40820
|
-
var PART_STORAGE4 =
|
|
40821
|
-
var SESSION_STORAGE =
|
|
40822
|
-
var TODO_DIR2 =
|
|
40823
|
-
var TRANSCRIPT_DIR2 =
|
|
41211
|
+
var MESSAGE_STORAGE4 = join53(OPENCODE_STORAGE9, "message");
|
|
41212
|
+
var PART_STORAGE4 = join53(OPENCODE_STORAGE9, "part");
|
|
41213
|
+
var SESSION_STORAGE = join53(OPENCODE_STORAGE9, "session");
|
|
41214
|
+
var TODO_DIR2 = join53(getClaudeConfigDir(), "todos");
|
|
41215
|
+
var TRANSCRIPT_DIR2 = join53(getClaudeConfigDir(), "transcripts");
|
|
40824
41216
|
var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
|
|
40825
41217
|
|
|
40826
41218
|
\u8FD4\u56DE\u53EF\u7528\u7684 session ID \u5217\u8868\uFF0C\u5305\u542B\u6D88\u606F\u6570\u91CF\u3001\u65E5\u671F\u8303\u56F4\u548C\u4F7F\u7528\u8FC7\u7684 agents \u7B49\u5143\u6570\u636E\u3002
|
|
@@ -40893,11 +41285,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
40893
41285
|
Has Transcript: Yes (234 entries)`;
|
|
40894
41286
|
|
|
40895
41287
|
// src/tools/session-manager/storage.ts
|
|
40896
|
-
import { existsSync as
|
|
41288
|
+
import { existsSync as existsSync46, readdirSync as readdirSync15 } from "fs";
|
|
40897
41289
|
import { readdir, readFile } from "fs/promises";
|
|
40898
|
-
import { join as
|
|
41290
|
+
import { join as join54 } from "path";
|
|
40899
41291
|
async function getMainSessions(options) {
|
|
40900
|
-
if (!
|
|
41292
|
+
if (!existsSync46(SESSION_STORAGE))
|
|
40901
41293
|
return [];
|
|
40902
41294
|
const sessions = [];
|
|
40903
41295
|
try {
|
|
@@ -40905,13 +41297,13 @@ async function getMainSessions(options) {
|
|
|
40905
41297
|
for (const projectDir of projectDirs) {
|
|
40906
41298
|
if (!projectDir.isDirectory())
|
|
40907
41299
|
continue;
|
|
40908
|
-
const projectPath =
|
|
41300
|
+
const projectPath = join54(SESSION_STORAGE, projectDir.name);
|
|
40909
41301
|
const sessionFiles = await readdir(projectPath);
|
|
40910
41302
|
for (const file2 of sessionFiles) {
|
|
40911
41303
|
if (!file2.endsWith(".json"))
|
|
40912
41304
|
continue;
|
|
40913
41305
|
try {
|
|
40914
|
-
const content = await readFile(
|
|
41306
|
+
const content = await readFile(join54(projectPath, file2), "utf-8");
|
|
40915
41307
|
const meta = JSON.parse(content);
|
|
40916
41308
|
if (meta.parentID)
|
|
40917
41309
|
continue;
|
|
@@ -40929,7 +41321,7 @@ async function getMainSessions(options) {
|
|
|
40929
41321
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
40930
41322
|
}
|
|
40931
41323
|
async function getAllSessions() {
|
|
40932
|
-
if (!
|
|
41324
|
+
if (!existsSync46(MESSAGE_STORAGE4))
|
|
40933
41325
|
return [];
|
|
40934
41326
|
const sessions = [];
|
|
40935
41327
|
async function scanDirectory(dir) {
|
|
@@ -40937,7 +41329,7 @@ async function getAllSessions() {
|
|
|
40937
41329
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
40938
41330
|
for (const entry of entries) {
|
|
40939
41331
|
if (entry.isDirectory()) {
|
|
40940
|
-
const sessionPath =
|
|
41332
|
+
const sessionPath = join54(dir, entry.name);
|
|
40941
41333
|
const files = await readdir(sessionPath);
|
|
40942
41334
|
if (files.some((f) => f.endsWith(".json"))) {
|
|
40943
41335
|
sessions.push(entry.name);
|
|
@@ -40954,16 +41346,16 @@ async function getAllSessions() {
|
|
|
40954
41346
|
return [...new Set(sessions)];
|
|
40955
41347
|
}
|
|
40956
41348
|
function getMessageDir7(sessionID) {
|
|
40957
|
-
if (!
|
|
41349
|
+
if (!existsSync46(MESSAGE_STORAGE4))
|
|
40958
41350
|
return "";
|
|
40959
|
-
const directPath =
|
|
40960
|
-
if (
|
|
41351
|
+
const directPath = join54(MESSAGE_STORAGE4, sessionID);
|
|
41352
|
+
if (existsSync46(directPath)) {
|
|
40961
41353
|
return directPath;
|
|
40962
41354
|
}
|
|
40963
41355
|
try {
|
|
40964
|
-
for (const dir of
|
|
40965
|
-
const sessionPath =
|
|
40966
|
-
if (
|
|
41356
|
+
for (const dir of readdirSync15(MESSAGE_STORAGE4)) {
|
|
41357
|
+
const sessionPath = join54(MESSAGE_STORAGE4, dir, sessionID);
|
|
41358
|
+
if (existsSync46(sessionPath)) {
|
|
40967
41359
|
return sessionPath;
|
|
40968
41360
|
}
|
|
40969
41361
|
}
|
|
@@ -40977,7 +41369,7 @@ function sessionExists(sessionID) {
|
|
|
40977
41369
|
}
|
|
40978
41370
|
async function readSessionMessages(sessionID) {
|
|
40979
41371
|
const messageDir = getMessageDir7(sessionID);
|
|
40980
|
-
if (!messageDir || !
|
|
41372
|
+
if (!messageDir || !existsSync46(messageDir))
|
|
40981
41373
|
return [];
|
|
40982
41374
|
const messages = [];
|
|
40983
41375
|
try {
|
|
@@ -40986,7 +41378,7 @@ async function readSessionMessages(sessionID) {
|
|
|
40986
41378
|
if (!file2.endsWith(".json"))
|
|
40987
41379
|
continue;
|
|
40988
41380
|
try {
|
|
40989
|
-
const content = await readFile(
|
|
41381
|
+
const content = await readFile(join54(messageDir, file2), "utf-8");
|
|
40990
41382
|
const meta = JSON.parse(content);
|
|
40991
41383
|
const parts = await readParts2(meta.id);
|
|
40992
41384
|
messages.push({
|
|
@@ -41012,8 +41404,8 @@ async function readSessionMessages(sessionID) {
|
|
|
41012
41404
|
});
|
|
41013
41405
|
}
|
|
41014
41406
|
async function readParts2(messageID) {
|
|
41015
|
-
const partDir =
|
|
41016
|
-
if (!
|
|
41407
|
+
const partDir = join54(PART_STORAGE4, messageID);
|
|
41408
|
+
if (!existsSync46(partDir))
|
|
41017
41409
|
return [];
|
|
41018
41410
|
const parts = [];
|
|
41019
41411
|
try {
|
|
@@ -41022,7 +41414,7 @@ async function readParts2(messageID) {
|
|
|
41022
41414
|
if (!file2.endsWith(".json"))
|
|
41023
41415
|
continue;
|
|
41024
41416
|
try {
|
|
41025
|
-
const content = await readFile(
|
|
41417
|
+
const content = await readFile(join54(partDir, file2), "utf-8");
|
|
41026
41418
|
parts.push(JSON.parse(content));
|
|
41027
41419
|
} catch {
|
|
41028
41420
|
continue;
|
|
@@ -41034,14 +41426,14 @@ async function readParts2(messageID) {
|
|
|
41034
41426
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
41035
41427
|
}
|
|
41036
41428
|
async function readSessionTodos(sessionID) {
|
|
41037
|
-
if (!
|
|
41429
|
+
if (!existsSync46(TODO_DIR2))
|
|
41038
41430
|
return [];
|
|
41039
41431
|
try {
|
|
41040
41432
|
const allFiles = await readdir(TODO_DIR2);
|
|
41041
41433
|
const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
|
|
41042
41434
|
for (const file2 of todoFiles) {
|
|
41043
41435
|
try {
|
|
41044
|
-
const content = await readFile(
|
|
41436
|
+
const content = await readFile(join54(TODO_DIR2, file2), "utf-8");
|
|
41045
41437
|
const data = JSON.parse(content);
|
|
41046
41438
|
if (Array.isArray(data)) {
|
|
41047
41439
|
return data.map((item) => ({
|
|
@@ -41061,10 +41453,10 @@ async function readSessionTodos(sessionID) {
|
|
|
41061
41453
|
return [];
|
|
41062
41454
|
}
|
|
41063
41455
|
async function readSessionTranscript(sessionID) {
|
|
41064
|
-
if (!
|
|
41456
|
+
if (!existsSync46(TRANSCRIPT_DIR2))
|
|
41065
41457
|
return 0;
|
|
41066
|
-
const transcriptFile =
|
|
41067
|
-
if (!
|
|
41458
|
+
const transcriptFile = join54(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
41459
|
+
if (!existsSync46(transcriptFile))
|
|
41068
41460
|
return 0;
|
|
41069
41461
|
try {
|
|
41070
41462
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -42266,19 +42658,19 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8 explore/librarian agent\u3002run_
|
|
|
42266
42658
|
|
|
42267
42659
|
\u4F20\u5165 \`session_id=<id>\` \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684 agent\uFF0C\u4FDD\u7559\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002Prompts \u5FC5\u987B\u4E3A\u4E2D\u6587\u3002\u4F7F\u7528 \`background_output\` \u83B7\u53D6\u5F02\u6B65\u7ED3\u679C\u3002`;
|
|
42268
42660
|
// src/tools/call-omo-agent/tools.ts
|
|
42269
|
-
import { existsSync as
|
|
42270
|
-
import { join as
|
|
42661
|
+
import { existsSync as existsSync47, readdirSync as readdirSync16 } from "fs";
|
|
42662
|
+
import { join as join55 } from "path";
|
|
42271
42663
|
init_shared();
|
|
42272
42664
|
init_session_cursor();
|
|
42273
42665
|
function getMessageDir8(sessionID) {
|
|
42274
|
-
if (!
|
|
42666
|
+
if (!existsSync47(MESSAGE_STORAGE))
|
|
42275
42667
|
return null;
|
|
42276
|
-
const directPath =
|
|
42277
|
-
if (
|
|
42668
|
+
const directPath = join55(MESSAGE_STORAGE, sessionID);
|
|
42669
|
+
if (existsSync47(directPath))
|
|
42278
42670
|
return directPath;
|
|
42279
|
-
for (const dir of
|
|
42280
|
-
const sessionPath =
|
|
42281
|
-
if (
|
|
42671
|
+
for (const dir of readdirSync16(MESSAGE_STORAGE)) {
|
|
42672
|
+
const sessionPath = join55(MESSAGE_STORAGE, dir, sessionID);
|
|
42673
|
+
if (existsSync47(sessionPath))
|
|
42282
42674
|
return sessionPath;
|
|
42283
42675
|
}
|
|
42284
42676
|
return null;
|
|
@@ -42687,14 +43079,17 @@ If the requested information is not found, clearly state what is missing.`;
|
|
|
42687
43079
|
}
|
|
42688
43080
|
// src/tools/delegate-task/tools.ts
|
|
42689
43081
|
init_constants2();
|
|
42690
|
-
import { existsSync as
|
|
42691
|
-
import { join as
|
|
43082
|
+
import { existsSync as existsSync48, readdirSync as readdirSync17 } from "fs";
|
|
43083
|
+
import { join as join56 } from "path";
|
|
42692
43084
|
|
|
42693
43085
|
// src/features/task-toast-manager/manager.ts
|
|
42694
43086
|
class TaskToastManager {
|
|
42695
43087
|
tasks = new Map;
|
|
42696
43088
|
client;
|
|
42697
43089
|
concurrencyManager;
|
|
43090
|
+
completionBatch = [];
|
|
43091
|
+
completionDebounceTimer;
|
|
43092
|
+
static COMPLETION_DEBOUNCE_MS = 800;
|
|
42698
43093
|
constructor(client2, concurrencyManager) {
|
|
42699
43094
|
this.client = client2;
|
|
42700
43095
|
this.concurrencyManager = concurrencyManager;
|
|
@@ -42806,13 +43201,36 @@ class TaskToastManager {
|
|
|
42806
43201
|
}).catch(() => {});
|
|
42807
43202
|
}
|
|
42808
43203
|
showCompletionToast(task) {
|
|
43204
|
+
this.removeTask(task.id);
|
|
43205
|
+
this.completionBatch.push(task);
|
|
43206
|
+
if (this.completionDebounceTimer) {
|
|
43207
|
+
clearTimeout(this.completionDebounceTimer);
|
|
43208
|
+
}
|
|
43209
|
+
this.completionDebounceTimer = setTimeout(() => {
|
|
43210
|
+
this.flushCompletionBatch();
|
|
43211
|
+
}, TaskToastManager.COMPLETION_DEBOUNCE_MS);
|
|
43212
|
+
}
|
|
43213
|
+
flushCompletionBatch() {
|
|
42809
43214
|
const tuiClient = this.client;
|
|
42810
|
-
if (!tuiClient.tui?.showToast)
|
|
43215
|
+
if (!tuiClient.tui?.showToast) {
|
|
43216
|
+
this.completionBatch = [];
|
|
43217
|
+
return;
|
|
43218
|
+
}
|
|
43219
|
+
const batch = [...this.completionBatch];
|
|
43220
|
+
this.completionBatch = [];
|
|
43221
|
+
if (batch.length === 0)
|
|
42811
43222
|
return;
|
|
42812
|
-
this.removeTask(task.id);
|
|
42813
43223
|
const remaining = this.getRunningTasks();
|
|
42814
43224
|
const queued = this.getQueuedTasks();
|
|
42815
|
-
let message
|
|
43225
|
+
let message;
|
|
43226
|
+
if (batch.length === 1) {
|
|
43227
|
+
message = `"${batch[0].description}" finished in ${batch[0].duration}`;
|
|
43228
|
+
} else {
|
|
43229
|
+
const lines = batch.map((t) => ` \u2713 "${t.description}" (${t.duration})`);
|
|
43230
|
+
message = `${batch.length} tasks completed:
|
|
43231
|
+
${lines.join(`
|
|
43232
|
+
`)}`;
|
|
43233
|
+
}
|
|
42816
43234
|
if (remaining.length > 0 || queued.length > 0) {
|
|
42817
43235
|
message += `
|
|
42818
43236
|
|
|
@@ -42820,12 +43238,13 @@ Still running: ${remaining.length} | Queued: ${queued.length}`;
|
|
|
42820
43238
|
}
|
|
42821
43239
|
tuiClient.tui.showToast({
|
|
42822
43240
|
body: {
|
|
42823
|
-
title: "Task Completed"
|
|
43241
|
+
title: batch.length === 1 ? "Task Completed" : `${batch.length} Tasks Completed`,
|
|
42824
43242
|
message,
|
|
42825
43243
|
variant: "success",
|
|
42826
|
-
duration: 5000
|
|
43244
|
+
duration: batch.length > 1 ? 7000 : 5000
|
|
42827
43245
|
}
|
|
42828
43246
|
}).catch(() => {});
|
|
43247
|
+
this.completionDebounceTimer = undefined;
|
|
42829
43248
|
}
|
|
42830
43249
|
}
|
|
42831
43250
|
var instance = null;
|
|
@@ -42847,14 +43266,14 @@ function parseModelString(model) {
|
|
|
42847
43266
|
return;
|
|
42848
43267
|
}
|
|
42849
43268
|
function getMessageDir9(sessionID) {
|
|
42850
|
-
if (!
|
|
43269
|
+
if (!existsSync48(MESSAGE_STORAGE))
|
|
42851
43270
|
return null;
|
|
42852
|
-
const directPath =
|
|
42853
|
-
if (
|
|
43271
|
+
const directPath = join56(MESSAGE_STORAGE, sessionID);
|
|
43272
|
+
if (existsSync48(directPath))
|
|
42854
43273
|
return directPath;
|
|
42855
|
-
for (const dir of
|
|
42856
|
-
const sessionPath =
|
|
42857
|
-
if (
|
|
43274
|
+
for (const dir of readdirSync17(MESSAGE_STORAGE)) {
|
|
43275
|
+
const sessionPath = join56(MESSAGE_STORAGE, dir, sessionID);
|
|
43276
|
+
if (existsSync48(sessionPath))
|
|
42858
43277
|
return sessionPath;
|
|
42859
43278
|
}
|
|
42860
43279
|
return null;
|
|
@@ -43682,12 +44101,14 @@ class PerformanceAggregator {
|
|
|
43682
44101
|
}
|
|
43683
44102
|
|
|
43684
44103
|
// src/features/background-agent/manager.ts
|
|
43685
|
-
import { existsSync as
|
|
43686
|
-
import { join as
|
|
44104
|
+
import { existsSync as existsSync49, readdirSync as readdirSync18 } from "fs";
|
|
44105
|
+
import { join as join57 } from "path";
|
|
43687
44106
|
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
43688
44107
|
var MIN_STABILITY_TIME_MS = 10 * 1000;
|
|
43689
|
-
var DEFAULT_STALE_TIMEOUT_MS =
|
|
44108
|
+
var DEFAULT_STALE_TIMEOUT_MS = 120000;
|
|
43690
44109
|
var MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
44110
|
+
var STEP_TIMEOUT_MS = 600000;
|
|
44111
|
+
var MIN_IDLE_TIME_MS = 15000;
|
|
43691
44112
|
|
|
43692
44113
|
class BackgroundManager {
|
|
43693
44114
|
static cleanupManagers = new Set;
|
|
@@ -43703,6 +44124,7 @@ class BackgroundManager {
|
|
|
43703
44124
|
shutdownTriggered = false;
|
|
43704
44125
|
config;
|
|
43705
44126
|
perfAggregator = new PerformanceAggregator;
|
|
44127
|
+
perfTracer;
|
|
43706
44128
|
queuesByKey = new Map;
|
|
43707
44129
|
processingKeys = new Set;
|
|
43708
44130
|
constructor(ctx, config3) {
|
|
@@ -43715,6 +44137,9 @@ class BackgroundManager {
|
|
|
43715
44137
|
this.config = config3;
|
|
43716
44138
|
this.registerProcessCleanup();
|
|
43717
44139
|
}
|
|
44140
|
+
setPerfTracer(tracer) {
|
|
44141
|
+
this.perfTracer = tracer;
|
|
44142
|
+
}
|
|
43718
44143
|
async launch(input) {
|
|
43719
44144
|
log("[background-agent] launch() called with:", {
|
|
43720
44145
|
agent: input.agent,
|
|
@@ -43736,7 +44161,11 @@ class BackgroundManager {
|
|
|
43736
44161
|
parentMessageID: input.parentMessageID,
|
|
43737
44162
|
parentModel: input.parentModel,
|
|
43738
44163
|
parentAgent: input.parentAgent,
|
|
43739
|
-
model: input.model
|
|
44164
|
+
model: input.model,
|
|
44165
|
+
maxSteps: this.config?.maxSteps,
|
|
44166
|
+
maxRuntimeMs: this.config?.maxRuntimeMs,
|
|
44167
|
+
stepTimeoutMs: this.config?.stepTimeoutMs ?? STEP_TIMEOUT_MS,
|
|
44168
|
+
stepCount: 0
|
|
43740
44169
|
};
|
|
43741
44170
|
this.tasks.set(task.id, task);
|
|
43742
44171
|
if (input.parentSessionID) {
|
|
@@ -43828,7 +44257,8 @@ class BackgroundManager {
|
|
|
43828
44257
|
task.sessionID = sessionID;
|
|
43829
44258
|
task.progress = {
|
|
43830
44259
|
toolCalls: 0,
|
|
43831
|
-
lastUpdate: new Date
|
|
44260
|
+
lastUpdate: new Date,
|
|
44261
|
+
stepStartedAt: Date.now()
|
|
43832
44262
|
};
|
|
43833
44263
|
task.concurrencyKey = concurrencyKey;
|
|
43834
44264
|
task.concurrencyGroup = concurrencyKey;
|
|
@@ -43968,7 +44398,11 @@ class BackgroundManager {
|
|
|
43968
44398
|
},
|
|
43969
44399
|
parentAgent: input.parentAgent,
|
|
43970
44400
|
concurrencyKey: input.concurrencyKey,
|
|
43971
|
-
concurrencyGroup
|
|
44401
|
+
concurrencyGroup,
|
|
44402
|
+
maxSteps: this.config?.maxSteps,
|
|
44403
|
+
maxRuntimeMs: this.config?.maxRuntimeMs,
|
|
44404
|
+
stepTimeoutMs: this.config?.stepTimeoutMs ?? STEP_TIMEOUT_MS,
|
|
44405
|
+
stepCount: 0
|
|
43972
44406
|
};
|
|
43973
44407
|
this.tasks.set(task.id, task);
|
|
43974
44408
|
subagentSessions.add(input.sessionID);
|
|
@@ -44008,12 +44442,14 @@ class BackgroundManager {
|
|
|
44008
44442
|
existingTask.parentModel = input.parentModel;
|
|
44009
44443
|
existingTask.parentAgent = input.parentAgent;
|
|
44010
44444
|
existingTask.startedAt = new Date;
|
|
44445
|
+
existingTask.stepCount = 0;
|
|
44011
44446
|
if (existingTask.progress) {
|
|
44012
44447
|
existingTask.progress.phaseTiming = undefined;
|
|
44013
44448
|
}
|
|
44014
44449
|
existingTask.progress = {
|
|
44015
44450
|
toolCalls: existingTask.progress?.toolCalls ?? 0,
|
|
44016
|
-
lastUpdate: new Date
|
|
44451
|
+
lastUpdate: new Date,
|
|
44452
|
+
stepStartedAt: Date.now()
|
|
44017
44453
|
};
|
|
44018
44454
|
this.startPolling();
|
|
44019
44455
|
if (existingTask.sessionID) {
|
|
@@ -44115,11 +44551,20 @@ class BackgroundManager {
|
|
|
44115
44551
|
const task = this.findBySession(sessionID);
|
|
44116
44552
|
if (!task || task.status !== "running")
|
|
44117
44553
|
return;
|
|
44554
|
+
task.stepCount = (task.stepCount ?? 0) + 1;
|
|
44555
|
+
if (task.progress) {
|
|
44556
|
+
task.progress.stepStartedAt = Date.now();
|
|
44557
|
+
}
|
|
44558
|
+
if (this.isStepLimitExceeded(task)) {
|
|
44559
|
+
this.tryCompleteTask(task, `step limit (${task.maxSteps} steps)`).catch((err) => {
|
|
44560
|
+
log("[background-agent] Error completing task on step limit:", err);
|
|
44561
|
+
});
|
|
44562
|
+
return;
|
|
44563
|
+
}
|
|
44118
44564
|
const startedAt = task.startedAt;
|
|
44119
44565
|
if (!startedAt)
|
|
44120
44566
|
return;
|
|
44121
44567
|
const elapsedMs = Date.now() - startedAt.getTime();
|
|
44122
|
-
const MIN_IDLE_TIME_MS = 5000;
|
|
44123
44568
|
if (elapsedMs < MIN_IDLE_TIME_MS) {
|
|
44124
44569
|
log("[background-agent] Ignoring early session.idle, elapsed:", { elapsedMs, taskId: task.id });
|
|
44125
44570
|
return;
|
|
@@ -44506,6 +44951,41 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44506
44951
|
const runtime = now - startedAt.getTime();
|
|
44507
44952
|
if (runtime < MIN_RUNTIME_BEFORE_STALE_MS)
|
|
44508
44953
|
continue;
|
|
44954
|
+
if (this.isRuntimeLimitExceeded(task)) {
|
|
44955
|
+
task.status = "cancelled";
|
|
44956
|
+
task.error = `Runtime limit exceeded (${Math.round(runtime / 60000)}min)`;
|
|
44957
|
+
task.completedAt = new Date;
|
|
44958
|
+
if (task.concurrencyKey) {
|
|
44959
|
+
this.concurrencyManager.release(task.concurrencyKey);
|
|
44960
|
+
task.concurrencyKey = undefined;
|
|
44961
|
+
}
|
|
44962
|
+
this.client.session.abort({ path: { id: sessionID } }).catch(() => {});
|
|
44963
|
+
log(`[background-agent] Task ${task.id} interrupted: runtime limit`);
|
|
44964
|
+
try {
|
|
44965
|
+
await this.notifyParentSession(task);
|
|
44966
|
+
} catch (err) {
|
|
44967
|
+
log("[background-agent] Error in notifyParentSession for runtime-limit task:", { taskId: task.id, error: err });
|
|
44968
|
+
}
|
|
44969
|
+
continue;
|
|
44970
|
+
}
|
|
44971
|
+
if (this.isStepTimeoutExceeded(task)) {
|
|
44972
|
+
const stepTimeoutMs = task.stepTimeoutMs ?? STEP_TIMEOUT_MS;
|
|
44973
|
+
task.status = "cancelled";
|
|
44974
|
+
task.error = `Step timeout exceeded (single step > ${Math.round(stepTimeoutMs / 60000)}min)`;
|
|
44975
|
+
task.completedAt = new Date;
|
|
44976
|
+
if (task.concurrencyKey) {
|
|
44977
|
+
this.concurrencyManager.release(task.concurrencyKey);
|
|
44978
|
+
task.concurrencyKey = undefined;
|
|
44979
|
+
}
|
|
44980
|
+
this.client.session.abort({ path: { id: sessionID } }).catch(() => {});
|
|
44981
|
+
log(`[background-agent] Task ${task.id} interrupted: step timeout`);
|
|
44982
|
+
try {
|
|
44983
|
+
await this.notifyParentSession(task);
|
|
44984
|
+
} catch (err) {
|
|
44985
|
+
log("[background-agent] Error in notifyParentSession for step-timeout task:", { taskId: task.id, error: err });
|
|
44986
|
+
}
|
|
44987
|
+
continue;
|
|
44988
|
+
}
|
|
44509
44989
|
const timeSinceLastUpdate = now - task.progress.lastUpdate.getTime();
|
|
44510
44990
|
if (timeSinceLastUpdate <= staleTimeoutMs)
|
|
44511
44991
|
continue;
|
|
@@ -44530,125 +45010,165 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44530
45010
|
}
|
|
44531
45011
|
}
|
|
44532
45012
|
}
|
|
45013
|
+
isStepLimitExceeded(task) {
|
|
45014
|
+
const maxSteps = task.maxSteps;
|
|
45015
|
+
if (!maxSteps || maxSteps <= 0)
|
|
45016
|
+
return false;
|
|
45017
|
+
return (task.stepCount ?? 0) >= maxSteps;
|
|
45018
|
+
}
|
|
45019
|
+
isRuntimeLimitExceeded(task) {
|
|
45020
|
+
const maxRuntimeMs = task.maxRuntimeMs;
|
|
45021
|
+
if (!maxRuntimeMs || maxRuntimeMs <= 0)
|
|
45022
|
+
return false;
|
|
45023
|
+
if (!task.startedAt)
|
|
45024
|
+
return false;
|
|
45025
|
+
const runtime = Date.now() - task.startedAt.getTime();
|
|
45026
|
+
return runtime >= maxRuntimeMs;
|
|
45027
|
+
}
|
|
45028
|
+
isStepTimeoutExceeded(task) {
|
|
45029
|
+
const stepTimeoutMs = task.stepTimeoutMs;
|
|
45030
|
+
if (!stepTimeoutMs || stepTimeoutMs <= 0)
|
|
45031
|
+
return false;
|
|
45032
|
+
if (!task.progress?.stepStartedAt)
|
|
45033
|
+
return false;
|
|
45034
|
+
const stepDuration = Date.now() - task.progress.stepStartedAt;
|
|
45035
|
+
return stepDuration >= stepTimeoutMs;
|
|
45036
|
+
}
|
|
44533
45037
|
async pollRunningTasks() {
|
|
44534
|
-
this.
|
|
44535
|
-
|
|
44536
|
-
|
|
44537
|
-
|
|
44538
|
-
|
|
44539
|
-
|
|
44540
|
-
|
|
44541
|
-
|
|
44542
|
-
if (!sessionID)
|
|
44543
|
-
continue;
|
|
44544
|
-
try {
|
|
44545
|
-
const sessionStatus = allStatuses[sessionID];
|
|
44546
|
-
if (sessionStatus?.type === "idle") {
|
|
44547
|
-
const hasValidOutput = await this.validateSessionHasOutput(sessionID);
|
|
44548
|
-
if (!hasValidOutput) {
|
|
44549
|
-
log("[background-agent] Polling idle but no valid output yet, waiting:", task.id);
|
|
44550
|
-
continue;
|
|
44551
|
-
}
|
|
44552
|
-
if (task.status !== "running")
|
|
44553
|
-
continue;
|
|
44554
|
-
const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
|
|
44555
|
-
if (hasIncompleteTodos2) {
|
|
44556
|
-
log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
|
|
44557
|
-
continue;
|
|
44558
|
-
}
|
|
44559
|
-
await this.tryCompleteTask(task, "polling (idle status)");
|
|
45038
|
+
const start = this.perfTracer?.isEnabled() ? performance.now() : undefined;
|
|
45039
|
+
try {
|
|
45040
|
+
this.pruneStaleTasksAndNotifications();
|
|
45041
|
+
await this.checkAndInterruptStaleTasks();
|
|
45042
|
+
const statusResult = await this.client.session.status();
|
|
45043
|
+
const allStatuses = statusResult.data ?? {};
|
|
45044
|
+
for (const task of this.tasks.values()) {
|
|
45045
|
+
if (task.status !== "running")
|
|
44560
45046
|
continue;
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44564
|
-
|
|
44565
|
-
|
|
44566
|
-
|
|
44567
|
-
|
|
44568
|
-
|
|
44569
|
-
|
|
44570
|
-
|
|
44571
|
-
for (const msg of assistantMsgs) {
|
|
44572
|
-
const parts = msg.parts ?? [];
|
|
44573
|
-
for (const part of parts) {
|
|
44574
|
-
if (part.type === "tool_use" || part.tool) {
|
|
44575
|
-
toolCalls++;
|
|
44576
|
-
lastTool = part.tool || part.name || "unknown";
|
|
44577
|
-
}
|
|
44578
|
-
if (part.type === "text" && part.text) {
|
|
44579
|
-
lastMessage = part.text;
|
|
44580
|
-
}
|
|
45047
|
+
const sessionID = task.sessionID;
|
|
45048
|
+
if (!sessionID)
|
|
45049
|
+
continue;
|
|
45050
|
+
try {
|
|
45051
|
+
const sessionStatus = allStatuses[sessionID];
|
|
45052
|
+
if (sessionStatus?.type === "idle") {
|
|
45053
|
+
const hasValidOutput = await this.validateSessionHasOutput(sessionID);
|
|
45054
|
+
if (!hasValidOutput) {
|
|
45055
|
+
log("[background-agent] Polling idle but no valid output yet, waiting:", task.id);
|
|
45056
|
+
continue;
|
|
44581
45057
|
}
|
|
44582
|
-
|
|
44583
|
-
|
|
44584
|
-
|
|
44585
|
-
|
|
44586
|
-
|
|
44587
|
-
|
|
44588
|
-
|
|
44589
|
-
|
|
44590
|
-
|
|
44591
|
-
|
|
44592
|
-
}
|
|
44593
|
-
|
|
44594
|
-
if (task.progress.phaseTiming && task.progress.phaseTiming.firstResponseMs === undefined && assistantMsgs.length > 0) {
|
|
44595
|
-
task.progress.phaseTiming.firstResponseMs = Date.now() - task.startedAt.getTime();
|
|
44596
|
-
}
|
|
44597
|
-
task.progress.toolCalls = toolCalls;
|
|
44598
|
-
task.progress.lastTool = lastTool;
|
|
44599
|
-
task.progress.lastUpdate = new Date;
|
|
44600
|
-
if (lastMessage) {
|
|
44601
|
-
task.progress.lastMessage = lastMessage;
|
|
44602
|
-
task.progress.lastMessageAt = new Date;
|
|
44603
|
-
}
|
|
44604
|
-
const currentMsgCount = messages.length;
|
|
44605
|
-
const startedAt = task.startedAt;
|
|
44606
|
-
if (!startedAt)
|
|
45058
|
+
if (task.status !== "running")
|
|
45059
|
+
continue;
|
|
45060
|
+
const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
|
|
45061
|
+
if (hasIncompleteTodos2) {
|
|
45062
|
+
log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
|
|
45063
|
+
continue;
|
|
45064
|
+
}
|
|
45065
|
+
if (this.isStepLimitExceeded(task)) {
|
|
45066
|
+
await this.tryCompleteTask(task, `step limit via polling (${task.maxSteps} steps)`);
|
|
45067
|
+
continue;
|
|
45068
|
+
}
|
|
45069
|
+
await this.tryCompleteTask(task, "polling (idle status)");
|
|
44607
45070
|
continue;
|
|
44608
|
-
|
|
44609
|
-
|
|
44610
|
-
|
|
44611
|
-
|
|
44612
|
-
|
|
44613
|
-
|
|
44614
|
-
|
|
44615
|
-
|
|
44616
|
-
|
|
44617
|
-
|
|
44618
|
-
|
|
44619
|
-
|
|
44620
|
-
|
|
44621
|
-
|
|
44622
|
-
|
|
45071
|
+
}
|
|
45072
|
+
const messagesResult = await this.client.session.messages({
|
|
45073
|
+
path: { id: sessionID }
|
|
45074
|
+
});
|
|
45075
|
+
if (!messagesResult.error && messagesResult.data) {
|
|
45076
|
+
const messages = messagesResult.data;
|
|
45077
|
+
const assistantMsgs = messages.filter((m) => m.info?.role === "assistant");
|
|
45078
|
+
let toolCalls = 0;
|
|
45079
|
+
let lastTool;
|
|
45080
|
+
let lastMessage;
|
|
45081
|
+
for (const msg of assistantMsgs) {
|
|
45082
|
+
const parts = msg.parts ?? [];
|
|
45083
|
+
for (const part of parts) {
|
|
45084
|
+
if (part.type === "tool_use" || part.tool) {
|
|
45085
|
+
toolCalls++;
|
|
45086
|
+
lastTool = part.tool || part.name || "unknown";
|
|
44623
45087
|
}
|
|
44624
|
-
|
|
44625
|
-
|
|
44626
|
-
log("[background-agent] Stability reached but no valid output, waiting:", task.id);
|
|
44627
|
-
continue;
|
|
45088
|
+
if (part.type === "text" && part.text) {
|
|
45089
|
+
lastMessage = part.text;
|
|
44628
45090
|
}
|
|
44629
|
-
|
|
44630
|
-
|
|
44631
|
-
|
|
44632
|
-
|
|
44633
|
-
|
|
44634
|
-
|
|
45091
|
+
}
|
|
45092
|
+
}
|
|
45093
|
+
if (!task.progress) {
|
|
45094
|
+
task.progress = { toolCalls: 0, lastUpdate: new Date };
|
|
45095
|
+
}
|
|
45096
|
+
if (task.startedAt && !task.progress.phaseTiming) {
|
|
45097
|
+
const now = Date.now();
|
|
45098
|
+
task.progress.phaseTiming = {
|
|
45099
|
+
queueWaitMs: task.queuedAt ? now - task.queuedAt.getTime() : 0,
|
|
45100
|
+
totalRunMs: now - task.startedAt.getTime(),
|
|
45101
|
+
toolCallCount: 0
|
|
45102
|
+
};
|
|
45103
|
+
}
|
|
45104
|
+
if (task.progress.phaseTiming && task.progress.phaseTiming.firstResponseMs === undefined && assistantMsgs.length > 0) {
|
|
45105
|
+
task.progress.phaseTiming.firstResponseMs = Date.now() - task.startedAt.getTime();
|
|
45106
|
+
}
|
|
45107
|
+
task.progress.toolCalls = toolCalls;
|
|
45108
|
+
task.progress.lastTool = lastTool;
|
|
45109
|
+
task.progress.lastUpdate = new Date;
|
|
45110
|
+
if (lastMessage) {
|
|
45111
|
+
task.progress.lastMessage = lastMessage;
|
|
45112
|
+
task.progress.lastMessageAt = new Date;
|
|
45113
|
+
}
|
|
45114
|
+
const currentMsgCount = messages.length;
|
|
45115
|
+
const startedAt = task.startedAt;
|
|
45116
|
+
if (!startedAt)
|
|
45117
|
+
continue;
|
|
45118
|
+
const elapsedMs = Date.now() - startedAt.getTime();
|
|
45119
|
+
if (elapsedMs >= MIN_STABILITY_TIME_MS) {
|
|
45120
|
+
if (task.lastMsgCount === currentMsgCount) {
|
|
45121
|
+
task.stablePolls = (task.stablePolls ?? 0) + 1;
|
|
45122
|
+
if (task.stablePolls >= 3) {
|
|
45123
|
+
const recheckStatus = await this.client.session.status();
|
|
45124
|
+
const recheckData = recheckStatus.data ?? {};
|
|
45125
|
+
const currentStatus = recheckData[sessionID];
|
|
45126
|
+
if (currentStatus?.type !== "idle") {
|
|
45127
|
+
log("[background-agent] Stability reached but session not idle, resetting:", {
|
|
45128
|
+
taskId: task.id,
|
|
45129
|
+
sessionStatus: currentStatus?.type ?? "not_in_status"
|
|
45130
|
+
});
|
|
45131
|
+
task.stablePolls = 0;
|
|
45132
|
+
continue;
|
|
45133
|
+
}
|
|
45134
|
+
const hasValidOutput = await this.validateSessionHasOutput(sessionID);
|
|
45135
|
+
if (!hasValidOutput) {
|
|
45136
|
+
log("[background-agent] Stability reached but no valid output, waiting:", task.id);
|
|
45137
|
+
continue;
|
|
45138
|
+
}
|
|
45139
|
+
if (task.status !== "running")
|
|
45140
|
+
continue;
|
|
45141
|
+
if (this.isStepLimitExceeded(task)) {
|
|
45142
|
+
await this.tryCompleteTask(task, `step limit via stability (${task.maxSteps} steps)`);
|
|
45143
|
+
continue;
|
|
45144
|
+
}
|
|
45145
|
+
const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
|
|
45146
|
+
if (!hasIncompleteTodos2) {
|
|
45147
|
+
await this.tryCompleteTask(task, "stability detection");
|
|
45148
|
+
continue;
|
|
45149
|
+
}
|
|
44635
45150
|
}
|
|
45151
|
+
} else {
|
|
45152
|
+
task.stablePolls = 0;
|
|
44636
45153
|
}
|
|
44637
|
-
} else {
|
|
44638
|
-
task.stablePolls = 0;
|
|
44639
45154
|
}
|
|
45155
|
+
task.lastMsgCount = currentMsgCount;
|
|
44640
45156
|
}
|
|
44641
|
-
|
|
45157
|
+
} catch (error45) {
|
|
45158
|
+
log("[background-agent] Poll error for task:", { taskId: task.id, error: error45 });
|
|
44642
45159
|
}
|
|
44643
|
-
} catch (error45) {
|
|
44644
|
-
log("[background-agent] Poll error for task:", { taskId: task.id, error: error45 });
|
|
44645
45160
|
}
|
|
44646
|
-
|
|
44647
|
-
|
|
44648
|
-
|
|
44649
|
-
|
|
44650
|
-
|
|
44651
|
-
|
|
45161
|
+
if (!this.hasRunningTasks()) {
|
|
45162
|
+
this.stopPolling();
|
|
45163
|
+
if (this.perfAggregator.taskCount >= 2) {
|
|
45164
|
+
const report = this.perfAggregator.getReport();
|
|
45165
|
+
log("[perf] Session report:", report);
|
|
45166
|
+
}
|
|
45167
|
+
}
|
|
45168
|
+
} finally {
|
|
45169
|
+
if (start !== undefined) {
|
|
45170
|
+
const duration3 = performance.now() - start;
|
|
45171
|
+
this.perfTracer.recordPolling(duration3, this.getRunningTasks().length, new Set(...this.tasks.values().map((t) => t.parentSessionID).filter(Boolean)).size);
|
|
44652
45172
|
}
|
|
44653
45173
|
}
|
|
44654
45174
|
}
|
|
@@ -44686,14 +45206,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
44686
45206
|
return listener;
|
|
44687
45207
|
}
|
|
44688
45208
|
function getMessageDir10(sessionID) {
|
|
44689
|
-
if (!
|
|
45209
|
+
if (!existsSync49(MESSAGE_STORAGE))
|
|
44690
45210
|
return null;
|
|
44691
|
-
const directPath =
|
|
44692
|
-
if (
|
|
45211
|
+
const directPath = join57(MESSAGE_STORAGE, sessionID);
|
|
45212
|
+
if (existsSync49(directPath))
|
|
44693
45213
|
return directPath;
|
|
44694
|
-
for (const dir of
|
|
44695
|
-
const sessionPath =
|
|
44696
|
-
if (
|
|
45214
|
+
for (const dir of readdirSync18(MESSAGE_STORAGE)) {
|
|
45215
|
+
const sessionPath = join57(MESSAGE_STORAGE, dir, sessionID);
|
|
45216
|
+
if (existsSync49(sessionPath))
|
|
44697
45217
|
return sessionPath;
|
|
44698
45218
|
}
|
|
44699
45219
|
return null;
|
|
@@ -62607,6 +63127,7 @@ var HookNameSchema = exports_external2.enum([
|
|
|
62607
63127
|
"edit-error-recovery",
|
|
62608
63128
|
"delegate-task-retry",
|
|
62609
63129
|
"prometheus-md-only",
|
|
63130
|
+
"perf-profiler",
|
|
62610
63131
|
"start-work",
|
|
62611
63132
|
"atlas"
|
|
62612
63133
|
]);
|
|
@@ -62720,11 +63241,21 @@ var DynamicContextPruningConfigSchema = exports_external2.object({
|
|
|
62720
63241
|
}).optional()
|
|
62721
63242
|
}).optional()
|
|
62722
63243
|
});
|
|
63244
|
+
var ProfilingConfigSchema = exports_external2.object({
|
|
63245
|
+
enabled: exports_external2.boolean().default(false),
|
|
63246
|
+
output_dir: exports_external2.string().optional(),
|
|
63247
|
+
slow_threshold_ms: exports_external2.number().default(100),
|
|
63248
|
+
memory_snapshot_interval: exports_external2.number().default(5),
|
|
63249
|
+
trace_api: exports_external2.boolean().default(true),
|
|
63250
|
+
trace_fileio: exports_external2.boolean().default(true),
|
|
63251
|
+
trace_polling: exports_external2.boolean().default(true)
|
|
63252
|
+
});
|
|
62723
63253
|
var ExperimentalConfigSchema = exports_external2.object({
|
|
62724
63254
|
aggressive_truncation: exports_external2.boolean().optional(),
|
|
62725
63255
|
auto_resume: exports_external2.boolean().optional(),
|
|
62726
63256
|
truncate_all_tool_outputs: exports_external2.boolean().optional(),
|
|
62727
|
-
dynamic_context_pruning: DynamicContextPruningConfigSchema.optional()
|
|
63257
|
+
dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
|
|
63258
|
+
profiling: ProfilingConfigSchema.optional()
|
|
62728
63259
|
});
|
|
62729
63260
|
var SkillSourceSchema = exports_external2.union([
|
|
62730
63261
|
exports_external2.string(),
|
|
@@ -62769,7 +63300,10 @@ var BackgroundTaskConfigSchema = exports_external2.object({
|
|
|
62769
63300
|
defaultConcurrency: exports_external2.number().min(1).optional(),
|
|
62770
63301
|
providerConcurrency: exports_external2.record(exports_external2.string(), exports_external2.number().min(0)).optional(),
|
|
62771
63302
|
modelConcurrency: exports_external2.record(exports_external2.string(), exports_external2.number().min(0)).optional(),
|
|
62772
|
-
staleTimeoutMs: exports_external2.number().min(60000).optional()
|
|
63303
|
+
staleTimeoutMs: exports_external2.number().min(60000).optional(),
|
|
63304
|
+
maxSteps: exports_external2.number().min(0).optional(),
|
|
63305
|
+
maxRuntimeMs: exports_external2.number().min(0).optional(),
|
|
63306
|
+
stepTimeoutMs: exports_external2.number().min(0).optional()
|
|
62773
63307
|
});
|
|
62774
63308
|
var NotificationConfigSchema = exports_external2.object({
|
|
62775
63309
|
force_enable: exports_external2.boolean().optional()
|
|
@@ -64864,21 +65398,21 @@ TODO \u5217\u8868\uFF1A[\u8DEF\u5F84]
|
|
|
64864
65398
|
|
|
64865
65399
|
**\u5BF9\u4E8E\u63A2\u7D22\uFF08explore/librarian\uFF09**\uFF1A\u59CB\u7EC8\u540E\u53F0\u8FD0\u884C
|
|
64866
65400
|
\`\`\`typescript
|
|
64867
|
-
delegate_task(subagent_type="explore", run_in_background=true, ...)
|
|
64868
|
-
delegate_task(subagent_type="librarian", run_in_background=true, ...)
|
|
65401
|
+
delegate_task(subagent_type="explore", run_in_background=true, load_skills=[], ...)
|
|
65402
|
+
delegate_task(subagent_type="librarian", run_in_background=true, load_skills=[], ...)
|
|
64869
65403
|
\`\`\`
|
|
64870
65404
|
|
|
64871
65405
|
**\u5BF9\u4E8E\u4EFB\u52A1\u6267\u884C**\uFF1A\u7EDD\u4E0D\u7528\u540E\u53F0\u8FD0\u884C
|
|
64872
65406
|
\`\`\`typescript
|
|
64873
|
-
delegate_task(category="...", run_in_background=false, ...)
|
|
65407
|
+
delegate_task(category="...", run_in_background=false, load_skills=[], ...)
|
|
64874
65408
|
\`\`\`
|
|
64875
65409
|
|
|
64876
65410
|
**\u5E76\u884C\u4EFB\u52A1\u7EC4**\uFF1A\u5728\u4E00\u6761\u6D88\u606F\u4E2D\u591A\u6B21\u8C03\u7528
|
|
64877
65411
|
\`\`\`typescript
|
|
64878
65412
|
// \u4EFB\u52A12\u30013\u30014\u662F\u72EC\u7ACB\u7684\u2014\u2014\u4E00\u8D77\u8C03\u7528
|
|
64879
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A12...")
|
|
64880
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A13...")
|
|
64881
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A14...")
|
|
65413
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A12...", load_skills=[])
|
|
65414
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A13...", load_skills=[])
|
|
65415
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A14...", load_skills=[])
|
|
64882
65416
|
\`\`\`
|
|
64883
65417
|
|
|
64884
65418
|
**\u540E\u53F0\u7BA1\u7406**\uFF1A
|
|
@@ -65753,7 +66287,7 @@ init_file_utils();
|
|
|
65753
66287
|
init_shared();
|
|
65754
66288
|
init_logger();
|
|
65755
66289
|
import { promises as fs11 } from "fs";
|
|
65756
|
-
import { join as
|
|
66290
|
+
import { join as join59, basename as basename6 } from "path";
|
|
65757
66291
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
65758
66292
|
try {
|
|
65759
66293
|
await fs11.access(commandsDir);
|
|
@@ -65783,7 +66317,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
65783
66317
|
if (entry.isDirectory()) {
|
|
65784
66318
|
if (entry.name.startsWith("."))
|
|
65785
66319
|
continue;
|
|
65786
|
-
const subDirPath =
|
|
66320
|
+
const subDirPath = join59(commandsDir, entry.name);
|
|
65787
66321
|
const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
65788
66322
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
65789
66323
|
commands2.push(...subCommands);
|
|
@@ -65791,7 +66325,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
65791
66325
|
}
|
|
65792
66326
|
if (!isMarkdownFile(entry))
|
|
65793
66327
|
continue;
|
|
65794
|
-
const commandPath =
|
|
66328
|
+
const commandPath = join59(commandsDir, entry.name);
|
|
65795
66329
|
const baseCommandName = basename6(entry.name, ".md");
|
|
65796
66330
|
const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
|
|
65797
66331
|
try {
|
|
@@ -65838,23 +66372,23 @@ function commandsToRecord(commands2) {
|
|
|
65838
66372
|
return result;
|
|
65839
66373
|
}
|
|
65840
66374
|
async function loadUserCommands() {
|
|
65841
|
-
const userCommandsDir =
|
|
66375
|
+
const userCommandsDir = join59(getClaudeConfigDir(), "commands");
|
|
65842
66376
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
65843
66377
|
return commandsToRecord(commands2);
|
|
65844
66378
|
}
|
|
65845
66379
|
async function loadProjectCommands() {
|
|
65846
|
-
const projectCommandsDir =
|
|
66380
|
+
const projectCommandsDir = join59(process.cwd(), ".claude", "commands");
|
|
65847
66381
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
65848
66382
|
return commandsToRecord(commands2);
|
|
65849
66383
|
}
|
|
65850
66384
|
async function loadOpencodeGlobalCommands() {
|
|
65851
66385
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
65852
|
-
const opencodeCommandsDir =
|
|
66386
|
+
const opencodeCommandsDir = join59(configDir, "command");
|
|
65853
66387
|
const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
65854
66388
|
return commandsToRecord(commands2);
|
|
65855
66389
|
}
|
|
65856
66390
|
async function loadOpencodeProjectCommands() {
|
|
65857
|
-
const opencodeProjectDir =
|
|
66391
|
+
const opencodeProjectDir = join59(process.cwd(), ".opencode", "command");
|
|
65858
66392
|
const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
65859
66393
|
return commandsToRecord(commands2);
|
|
65860
66394
|
}
|
|
@@ -65862,8 +66396,8 @@ async function loadOpencodeProjectCommands() {
|
|
|
65862
66396
|
init_frontmatter();
|
|
65863
66397
|
init_file_utils();
|
|
65864
66398
|
init_shared();
|
|
65865
|
-
import { existsSync as
|
|
65866
|
-
import { join as
|
|
66399
|
+
import { existsSync as existsSync51, readdirSync as readdirSync19, readFileSync as readFileSync31 } from "fs";
|
|
66400
|
+
import { join as join60, basename as basename7 } from "path";
|
|
65867
66401
|
function parseToolsConfig(toolsStr) {
|
|
65868
66402
|
if (!toolsStr)
|
|
65869
66403
|
return;
|
|
@@ -65877,18 +66411,18 @@ function parseToolsConfig(toolsStr) {
|
|
|
65877
66411
|
return result;
|
|
65878
66412
|
}
|
|
65879
66413
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
65880
|
-
if (!
|
|
66414
|
+
if (!existsSync51(agentsDir)) {
|
|
65881
66415
|
return [];
|
|
65882
66416
|
}
|
|
65883
|
-
const entries =
|
|
66417
|
+
const entries = readdirSync19(agentsDir, { withFileTypes: true });
|
|
65884
66418
|
const agents = [];
|
|
65885
66419
|
for (const entry of entries) {
|
|
65886
66420
|
if (!isMarkdownFile(entry))
|
|
65887
66421
|
continue;
|
|
65888
|
-
const agentPath =
|
|
66422
|
+
const agentPath = join60(agentsDir, entry.name);
|
|
65889
66423
|
const agentName = basename7(entry.name, ".md");
|
|
65890
66424
|
try {
|
|
65891
|
-
const content =
|
|
66425
|
+
const content = readFileSync31(agentPath, "utf-8");
|
|
65892
66426
|
const { data, body } = parseFrontmatter(content);
|
|
65893
66427
|
const name = data.name || agentName;
|
|
65894
66428
|
const originalDescription = data.description || "";
|
|
@@ -65915,7 +66449,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
65915
66449
|
return agents;
|
|
65916
66450
|
}
|
|
65917
66451
|
function loadUserAgents() {
|
|
65918
|
-
const userAgentsDir =
|
|
66452
|
+
const userAgentsDir = join60(getClaudeConfigDir(), "agents");
|
|
65919
66453
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
65920
66454
|
const result = {};
|
|
65921
66455
|
for (const agent of agents) {
|
|
@@ -65924,7 +66458,7 @@ function loadUserAgents() {
|
|
|
65924
66458
|
return result;
|
|
65925
66459
|
}
|
|
65926
66460
|
function loadProjectAgents() {
|
|
65927
|
-
const projectAgentsDir =
|
|
66461
|
+
const projectAgentsDir = join60(process.cwd(), ".claude", "agents");
|
|
65928
66462
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
65929
66463
|
const result = {};
|
|
65930
66464
|
for (const agent of agents) {
|
|
@@ -65936,18 +66470,18 @@ function loadProjectAgents() {
|
|
|
65936
66470
|
init_frontmatter();
|
|
65937
66471
|
init_file_utils();
|
|
65938
66472
|
init_logger();
|
|
65939
|
-
import { existsSync as
|
|
66473
|
+
import { existsSync as existsSync52, readdirSync as readdirSync20, readFileSync as readFileSync32 } from "fs";
|
|
65940
66474
|
import { homedir as homedir13 } from "os";
|
|
65941
|
-
import { join as
|
|
66475
|
+
import { join as join61, basename as basename8 } from "path";
|
|
65942
66476
|
var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
65943
66477
|
function getPluginsBaseDir() {
|
|
65944
66478
|
if (process.env.CLAUDE_PLUGINS_HOME) {
|
|
65945
66479
|
return process.env.CLAUDE_PLUGINS_HOME;
|
|
65946
66480
|
}
|
|
65947
|
-
return
|
|
66481
|
+
return join61(homedir13(), ".claude", "plugins");
|
|
65948
66482
|
}
|
|
65949
66483
|
function getInstalledPluginsPath() {
|
|
65950
|
-
return
|
|
66484
|
+
return join61(getPluginsBaseDir(), "installed_plugins.json");
|
|
65951
66485
|
}
|
|
65952
66486
|
function resolvePluginPath(path8, pluginRoot) {
|
|
65953
66487
|
return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
|
|
@@ -65972,11 +66506,11 @@ function resolvePluginPaths(obj, pluginRoot) {
|
|
|
65972
66506
|
}
|
|
65973
66507
|
function loadInstalledPlugins() {
|
|
65974
66508
|
const dbPath = getInstalledPluginsPath();
|
|
65975
|
-
if (!
|
|
66509
|
+
if (!existsSync52(dbPath)) {
|
|
65976
66510
|
return null;
|
|
65977
66511
|
}
|
|
65978
66512
|
try {
|
|
65979
|
-
const content =
|
|
66513
|
+
const content = readFileSync32(dbPath, "utf-8");
|
|
65980
66514
|
return JSON.parse(content);
|
|
65981
66515
|
} catch (error92) {
|
|
65982
66516
|
log("Failed to load installed plugins database", error92);
|
|
@@ -65987,15 +66521,15 @@ function getClaudeSettingsPath() {
|
|
|
65987
66521
|
if (process.env.CLAUDE_SETTINGS_PATH) {
|
|
65988
66522
|
return process.env.CLAUDE_SETTINGS_PATH;
|
|
65989
66523
|
}
|
|
65990
|
-
return
|
|
66524
|
+
return join61(homedir13(), ".claude", "settings.json");
|
|
65991
66525
|
}
|
|
65992
66526
|
function loadClaudeSettings() {
|
|
65993
66527
|
const settingsPath = getClaudeSettingsPath();
|
|
65994
|
-
if (!
|
|
66528
|
+
if (!existsSync52(settingsPath)) {
|
|
65995
66529
|
return null;
|
|
65996
66530
|
}
|
|
65997
66531
|
try {
|
|
65998
|
-
const content =
|
|
66532
|
+
const content = readFileSync32(settingsPath, "utf-8");
|
|
65999
66533
|
return JSON.parse(content);
|
|
66000
66534
|
} catch (error92) {
|
|
66001
66535
|
log("Failed to load Claude settings", error92);
|
|
@@ -66003,12 +66537,12 @@ function loadClaudeSettings() {
|
|
|
66003
66537
|
}
|
|
66004
66538
|
}
|
|
66005
66539
|
function loadPluginManifest(installPath) {
|
|
66006
|
-
const manifestPath =
|
|
66007
|
-
if (!
|
|
66540
|
+
const manifestPath = join61(installPath, ".claude-plugin", "plugin.json");
|
|
66541
|
+
if (!existsSync52(manifestPath)) {
|
|
66008
66542
|
return null;
|
|
66009
66543
|
}
|
|
66010
66544
|
try {
|
|
66011
|
-
const content =
|
|
66545
|
+
const content = readFileSync32(manifestPath, "utf-8");
|
|
66012
66546
|
return JSON.parse(content);
|
|
66013
66547
|
} catch (error92) {
|
|
66014
66548
|
log(`Failed to load plugin manifest from ${manifestPath}`, error92);
|
|
@@ -66055,7 +66589,7 @@ function discoverInstalledPlugins(options) {
|
|
|
66055
66589
|
continue;
|
|
66056
66590
|
}
|
|
66057
66591
|
const { installPath, scope, version: version3 } = installation;
|
|
66058
|
-
if (!
|
|
66592
|
+
if (!existsSync52(installPath)) {
|
|
66059
66593
|
errors5.push({
|
|
66060
66594
|
pluginKey,
|
|
66061
66595
|
installPath,
|
|
@@ -66073,21 +66607,21 @@ function discoverInstalledPlugins(options) {
|
|
|
66073
66607
|
pluginKey,
|
|
66074
66608
|
manifest: manifest ?? undefined
|
|
66075
66609
|
};
|
|
66076
|
-
if (
|
|
66077
|
-
loadedPlugin.commandsDir =
|
|
66610
|
+
if (existsSync52(join61(installPath, "commands"))) {
|
|
66611
|
+
loadedPlugin.commandsDir = join61(installPath, "commands");
|
|
66078
66612
|
}
|
|
66079
|
-
if (
|
|
66080
|
-
loadedPlugin.agentsDir =
|
|
66613
|
+
if (existsSync52(join61(installPath, "agents"))) {
|
|
66614
|
+
loadedPlugin.agentsDir = join61(installPath, "agents");
|
|
66081
66615
|
}
|
|
66082
|
-
if (
|
|
66083
|
-
loadedPlugin.skillsDir =
|
|
66616
|
+
if (existsSync52(join61(installPath, "skills"))) {
|
|
66617
|
+
loadedPlugin.skillsDir = join61(installPath, "skills");
|
|
66084
66618
|
}
|
|
66085
|
-
const hooksPath =
|
|
66086
|
-
if (
|
|
66619
|
+
const hooksPath = join61(installPath, "hooks", "hooks.json");
|
|
66620
|
+
if (existsSync52(hooksPath)) {
|
|
66087
66621
|
loadedPlugin.hooksPath = hooksPath;
|
|
66088
66622
|
}
|
|
66089
|
-
const mcpPath =
|
|
66090
|
-
if (
|
|
66623
|
+
const mcpPath = join61(installPath, ".mcp.json");
|
|
66624
|
+
if (existsSync52(mcpPath)) {
|
|
66091
66625
|
loadedPlugin.mcpPath = mcpPath;
|
|
66092
66626
|
}
|
|
66093
66627
|
plugins.push(loadedPlugin);
|
|
@@ -66098,17 +66632,17 @@ function discoverInstalledPlugins(options) {
|
|
|
66098
66632
|
function loadPluginCommands(plugins) {
|
|
66099
66633
|
const commands2 = {};
|
|
66100
66634
|
for (const plugin of plugins) {
|
|
66101
|
-
if (!plugin.commandsDir || !
|
|
66635
|
+
if (!plugin.commandsDir || !existsSync52(plugin.commandsDir))
|
|
66102
66636
|
continue;
|
|
66103
|
-
const entries =
|
|
66637
|
+
const entries = readdirSync20(plugin.commandsDir, { withFileTypes: true });
|
|
66104
66638
|
for (const entry of entries) {
|
|
66105
66639
|
if (!isMarkdownFile(entry))
|
|
66106
66640
|
continue;
|
|
66107
|
-
const commandPath =
|
|
66641
|
+
const commandPath = join61(plugin.commandsDir, entry.name);
|
|
66108
66642
|
const commandName = basename8(entry.name, ".md");
|
|
66109
66643
|
const namespacedName = `${plugin.name}:${commandName}`;
|
|
66110
66644
|
try {
|
|
66111
|
-
const content =
|
|
66645
|
+
const content = readFileSync32(commandPath, "utf-8");
|
|
66112
66646
|
const { data, body } = parseFrontmatter(content);
|
|
66113
66647
|
const wrappedTemplate = `<command-instruction>
|
|
66114
66648
|
${body.trim()}
|
|
@@ -66140,21 +66674,21 @@ $ARGUMENTS
|
|
|
66140
66674
|
function loadPluginSkillsAsCommands(plugins) {
|
|
66141
66675
|
const skills = {};
|
|
66142
66676
|
for (const plugin of plugins) {
|
|
66143
|
-
if (!plugin.skillsDir || !
|
|
66677
|
+
if (!plugin.skillsDir || !existsSync52(plugin.skillsDir))
|
|
66144
66678
|
continue;
|
|
66145
|
-
const entries =
|
|
66679
|
+
const entries = readdirSync20(plugin.skillsDir, { withFileTypes: true });
|
|
66146
66680
|
for (const entry of entries) {
|
|
66147
66681
|
if (entry.name.startsWith("."))
|
|
66148
66682
|
continue;
|
|
66149
|
-
const skillPath =
|
|
66683
|
+
const skillPath = join61(plugin.skillsDir, entry.name);
|
|
66150
66684
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
66151
66685
|
continue;
|
|
66152
66686
|
const resolvedPath = resolveSymlink(skillPath);
|
|
66153
|
-
const skillMdPath =
|
|
66154
|
-
if (!
|
|
66687
|
+
const skillMdPath = join61(resolvedPath, "SKILL.md");
|
|
66688
|
+
if (!existsSync52(skillMdPath))
|
|
66155
66689
|
continue;
|
|
66156
66690
|
try {
|
|
66157
|
-
const content =
|
|
66691
|
+
const content = readFileSync32(skillMdPath, "utf-8");
|
|
66158
66692
|
const { data, body } = parseFrontmatter(content);
|
|
66159
66693
|
const skillName = data.name || entry.name;
|
|
66160
66694
|
const namespacedName = `${plugin.name}:${skillName}`;
|
|
@@ -66201,17 +66735,17 @@ function parseToolsConfig2(toolsStr) {
|
|
|
66201
66735
|
function loadPluginAgents(plugins) {
|
|
66202
66736
|
const agents = {};
|
|
66203
66737
|
for (const plugin of plugins) {
|
|
66204
|
-
if (!plugin.agentsDir || !
|
|
66738
|
+
if (!plugin.agentsDir || !existsSync52(plugin.agentsDir))
|
|
66205
66739
|
continue;
|
|
66206
|
-
const entries =
|
|
66740
|
+
const entries = readdirSync20(plugin.agentsDir, { withFileTypes: true });
|
|
66207
66741
|
for (const entry of entries) {
|
|
66208
66742
|
if (!isMarkdownFile(entry))
|
|
66209
66743
|
continue;
|
|
66210
|
-
const agentPath =
|
|
66744
|
+
const agentPath = join61(plugin.agentsDir, entry.name);
|
|
66211
66745
|
const agentName = basename8(entry.name, ".md");
|
|
66212
66746
|
const namespacedName = `${plugin.name}:${agentName}`;
|
|
66213
66747
|
try {
|
|
66214
|
-
const content =
|
|
66748
|
+
const content = readFileSync32(agentPath, "utf-8");
|
|
66215
66749
|
const { data, body } = parseFrontmatter(content);
|
|
66216
66750
|
const name = data.name || agentName;
|
|
66217
66751
|
const originalDescription = data.description || "";
|
|
@@ -66237,7 +66771,7 @@ function loadPluginAgents(plugins) {
|
|
|
66237
66771
|
async function loadPluginMcpServers(plugins) {
|
|
66238
66772
|
const servers = {};
|
|
66239
66773
|
for (const plugin of plugins) {
|
|
66240
|
-
if (!plugin.mcpPath || !
|
|
66774
|
+
if (!plugin.mcpPath || !existsSync52(plugin.mcpPath))
|
|
66241
66775
|
continue;
|
|
66242
66776
|
try {
|
|
66243
66777
|
const content = await Bun.file(plugin.mcpPath).text();
|
|
@@ -66269,10 +66803,10 @@ async function loadPluginMcpServers(plugins) {
|
|
|
66269
66803
|
function loadPluginHooksConfigs(plugins) {
|
|
66270
66804
|
const configs = [];
|
|
66271
66805
|
for (const plugin of plugins) {
|
|
66272
|
-
if (!plugin.hooksPath || !
|
|
66806
|
+
if (!plugin.hooksPath || !existsSync52(plugin.hooksPath))
|
|
66273
66807
|
continue;
|
|
66274
66808
|
try {
|
|
66275
|
-
const content =
|
|
66809
|
+
const content = readFileSync32(plugin.hooksPath, "utf-8");
|
|
66276
66810
|
let config4 = JSON.parse(content);
|
|
66277
66811
|
config4 = resolvePluginPaths(config4, plugin.installPath);
|
|
66278
66812
|
configs.push(config4);
|
|
@@ -66658,8 +67192,8 @@ Prometheus\uFF1A"\u5FEB\u901F\u4FEE\u590D\u2014\u2014\u6211\u770B\u5230\u62FC\u5
|
|
|
66658
67192
|
|
|
66659
67193
|
**\u5148\u505A\u7814\u7A76\uFF1A**
|
|
66660
67194
|
\`\`\`typescript
|
|
66661
|
-
delegate_task(subagent_type="explore", prompt="\u4F7F\u7528 lsp_find_references \u6A21\u5F0F\u67E5\u627E [\u76EE\u6807] \u7684\u6240\u6709\u4F7F\u7528\u4F4D\u7F6E...", run_in_background=true)
|
|
66662
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u53D7\u5F71\u54CD\u4EE3\u7801] \u7684\u6D4B\u8BD5\u8986\u76D6\u7387...", run_in_background=true)
|
|
67195
|
+
delegate_task(subagent_type="explore", prompt="\u4F7F\u7528 lsp_find_references \u6A21\u5F0F\u67E5\u627E [\u76EE\u6807] \u7684\u6240\u6709\u4F7F\u7528\u4F4D\u7F6E...", run_in_background=true, load_skills=[])
|
|
67196
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u53D7\u5F71\u54CD\u4EE3\u7801] \u7684\u6D4B\u8BD5\u8986\u76D6\u7387...", run_in_background=true, load_skills=[])
|
|
66663
67197
|
\`\`\`
|
|
66664
67198
|
|
|
66665
67199
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -66682,9 +67216,9 @@ delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u53D7\u5F71\u54CD\
|
|
|
66682
67216
|
**\u8BBF\u8C08\u524D\u7814\u7A76\uFF08\u5F3A\u5236\u8981\u6C42\uFF09\uFF1A**
|
|
66683
67217
|
\`\`\`typescript
|
|
66684
67218
|
// \u5728\u5411\u7528\u6237\u63D0\u95EE\u4E4B\u524D\u542F\u52A8
|
|
66685
|
-
delegate_task(subagent_type="explore", prompt="\u5728\u4EE3\u7801\u5E93\u4E2D\u67E5\u627E\u7C7B\u4F3C\u5B9E\u73B0...", run_in_background=true)
|
|
66686
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u529F\u80FD\u7C7B\u578B] \u7684\u9879\u76EE\u6A21\u5F0F...", run_in_background=true)
|
|
66687
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u6280\u672F] \u7684\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true)
|
|
67219
|
+
delegate_task(subagent_type="explore", prompt="\u5728\u4EE3\u7801\u5E93\u4E2D\u67E5\u627E\u7C7B\u4F3C\u5B9E\u73B0...", run_in_background=true, load_skills=[])
|
|
67220
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u529F\u80FD\u7C7B\u578B] \u7684\u9879\u76EE\u6A21\u5F0F...", run_in_background=true, load_skills=[])
|
|
67221
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u6280\u672F] \u7684\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true, load_skills=[])
|
|
66688
67222
|
\`\`\`
|
|
66689
67223
|
|
|
66690
67224
|
**\u8BBF\u8C08\u91CD\u70B9**\uFF08\u7814\u7A76\u4E4B\u540E\uFF09\uFF1A
|
|
@@ -66723,7 +67257,7 @@ Prometheus\uFF1A"\u6211\u53D1\u73B0\u4E86\u4E00\u4E9B\u60C5\u51B5\uFF1A
|
|
|
66723
67257
|
|
|
66724
67258
|
\u8FD0\u884C\u6B64\u68C0\u67E5\uFF1A
|
|
66725
67259
|
\`\`\`typescript
|
|
66726
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u6D4B\u8BD5\u57FA\u7840\u8BBE\u65BD\uFF1Apackage.json \u4E2D\u7684\u6D4B\u8BD5\u811A\u672C\u3001\u6D4B\u8BD5\u914D\u7F6E\u6587\u4EF6\uFF08jest.config\u3001vitest.config\u3001pytest.ini \u7B49\uFF09\u3001\u73B0\u6709\u6D4B\u8BD5\u6587\u4EF6\uFF08*.test.*\u3001*.spec.*\u3001test_*\uFF09\u3002\u62A5\u544A\uFF1A1\uFF09\u662F\u5426\u5B58\u5728\u6D4B\u8BD5\u57FA\u7840\u8BBE\u65BD\uFF1F2\uFF09\u4F7F\u7528\u4EC0\u4E48\u6846\u67B6\uFF1F3\uFF09\u793A\u4F8B\u6D4B\u8BD5\u6587\u4EF6\u6A21\u5F0F\u3002", run_in_background=true)
|
|
67260
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u6D4B\u8BD5\u57FA\u7840\u8BBE\u65BD\uFF1Apackage.json \u4E2D\u7684\u6D4B\u8BD5\u811A\u672C\u3001\u6D4B\u8BD5\u914D\u7F6E\u6587\u4EF6\uFF08jest.config\u3001vitest.config\u3001pytest.ini \u7B49\uFF09\u3001\u73B0\u6709\u6D4B\u8BD5\u6587\u4EF6\uFF08*.test.*\u3001*.spec.*\u3001test_*\uFF09\u3002\u62A5\u544A\uFF1A1\uFF09\u662F\u5426\u5B58\u5728\u6D4B\u8BD5\u57FA\u7840\u8BBE\u65BD\uFF1F2\uFF09\u4F7F\u7528\u4EC0\u4E48\u6846\u67B6\uFF1F3\uFF09\u793A\u4F8B\u6D4B\u8BD5\u6587\u4EF6\u6A21\u5F0F\u3002", run_in_background=true, load_skills=[])
|
|
66727
67261
|
\`\`\`
|
|
66728
67262
|
|
|
66729
67263
|
#### \u7B2C2\u6B65\uFF1A\u8BE2\u95EE\u6D4B\u8BD5\u95EE\u9898\uFF08\u5F3A\u5236\u8981\u6C42\uFF09
|
|
@@ -66812,13 +67346,13 @@ delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u6D4B\u8BD5\u57FA\u7
|
|
|
66812
67346
|
|
|
66813
67347
|
**\u5148\u505A\u7814\u7A76\uFF1A**
|
|
66814
67348
|
\`\`\`typescript
|
|
66815
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u5F53\u524D\u7CFB\u7EDF\u67B6\u6784\u548C\u6A21\u5F0F...", run_in_background=true)
|
|
66816
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u9886\u57DF] \u7684\u67B6\u6784\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true)
|
|
67349
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u5F53\u524D\u7CFB\u7EDF\u67B6\u6784\u548C\u6A21\u5F0F...", run_in_background=true, load_skills=[])
|
|
67350
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u9886\u57DF] \u7684\u67B6\u6784\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true, load_skills=[])
|
|
66817
67351
|
\`\`\`
|
|
66818
67352
|
|
|
66819
67353
|
**Oracle \u54A8\u8BE2**\uFF08\u5F53\u98CE\u9669\u8F83\u9AD8\u65F6\u63A8\u8350\uFF09\uFF1A
|
|
66820
67354
|
\`\`\`typescript
|
|
66821
|
-
delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8BE2\uFF1A[\u4E0A\u4E0B\u6587]...", run_in_background=false)
|
|
67355
|
+
delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8BE2\uFF1A[\u4E0A\u4E0B\u6587]...", run_in_background=false, load_skills=[])
|
|
66822
67356
|
\`\`\`
|
|
66823
67357
|
|
|
66824
67358
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -66835,9 +67369,9 @@ delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8B
|
|
|
66835
67369
|
|
|
66836
67370
|
**\u5E76\u884C\u8C03\u7814\uFF1A**
|
|
66837
67371
|
\`\`\`typescript
|
|
66838
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E X \u5F53\u524D\u662F\u5982\u4F55\u5904\u7406\u7684...", run_in_background=true)
|
|
66839
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Y \u7684\u5B98\u65B9\u6587\u6863...", run_in_background=true)
|
|
66840
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E90\u5B9E\u73B0...", run_in_background=true)
|
|
67372
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E X \u5F53\u524D\u662F\u5982\u4F55\u5904\u7406\u7684...", run_in_background=true, load_skills=[])
|
|
67373
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Y \u7684\u5B98\u65B9\u6587\u6863...", run_in_background=true, load_skills=[])
|
|
67374
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E90\u5B9E\u73B0...", run_in_background=true, load_skills=[])
|
|
66841
67375
|
\`\`\`
|
|
66842
67376
|
|
|
66843
67377
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -66863,17 +67397,17 @@ delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E
|
|
|
66863
67397
|
|
|
66864
67398
|
**\u7528\u4E8E\u7406\u89E3\u4EE3\u7801\u5E93\uFF1A**
|
|
66865
67399
|
\`\`\`typescript
|
|
66866
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u4E0E [\u4E3B\u9898] \u76F8\u5173\u7684\u6240\u6709\u6587\u4EF6\u3002\u5C55\u793A\u6A21\u5F0F\u3001\u7EA6\u5B9A\u548C\u7ED3\u6784\u3002", run_in_background=true)
|
|
67400
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u4E0E [\u4E3B\u9898] \u76F8\u5173\u7684\u6240\u6709\u6587\u4EF6\u3002\u5C55\u793A\u6A21\u5F0F\u3001\u7EA6\u5B9A\u548C\u7ED3\u6784\u3002", run_in_background=true, load_skills=[])
|
|
66867
67401
|
\`\`\`
|
|
66868
67402
|
|
|
66869
67403
|
**\u7528\u4E8E\u5916\u90E8\u77E5\u8BC6\uFF1A**
|
|
66870
67404
|
\`\`\`typescript
|
|
66871
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u5E93] \u7684\u5B98\u65B9\u6587\u6863\u3002\u91CD\u70B9\u5173\u6CE8 [\u7279\u5B9A\u529F\u80FD] \u548C\u6700\u4F73\u5B9E\u8DF5\u3002", run_in_background=true)
|
|
67405
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u5E93] \u7684\u5B98\u65B9\u6587\u6863\u3002\u91CD\u70B9\u5173\u6CE8 [\u7279\u5B9A\u529F\u80FD] \u548C\u6700\u4F73\u5B9E\u8DF5\u3002", run_in_background=true, load_skills=[])
|
|
66872
67406
|
\`\`\`
|
|
66873
67407
|
|
|
66874
67408
|
**\u7528\u4E8E\u5B9E\u73B0\u793A\u4F8B\uFF1A**
|
|
66875
67409
|
\`\`\`typescript
|
|
66876
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u529F\u80FD] \u7684\u5F00\u6E90\u5B9E\u73B0\u3002\u5BFB\u627E\u751F\u4EA7\u8D28\u91CF\u7684\u793A\u4F8B\u3002", run_in_background=true)
|
|
67410
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u529F\u80FD] \u7684\u5F00\u6E90\u5B9E\u73B0\u3002\u5BFB\u627E\u751F\u4EA7\u8D28\u91CF\u7684\u793A\u4F8B\u3002", run_in_background=true, load_skills=[])
|
|
66877
67411
|
\`\`\`
|
|
66878
67412
|
|
|
66879
67413
|
## \u8BBF\u8C08\u6A21\u5F0F\u53CD\u6A21\u5F0F
|
|
@@ -66971,6 +67505,7 @@ todoWrite([
|
|
|
66971
67505
|
\`\`\`typescript
|
|
66972
67506
|
delegate_task(
|
|
66973
67507
|
subagent_type="metis",
|
|
67508
|
+
load_skills=[],
|
|
66974
67509
|
prompt=\`\u5728\u6211\u751F\u6210\u5DE5\u4F5C\u8BA1\u5212\u4E4B\u524D\uFF0C\u5BA1\u67E5\u8FD9\u6B21\u89C4\u5212\u4F1A\u8BDD\uFF1A
|
|
66975
67510
|
|
|
66976
67511
|
**\u7528\u6237\u76EE\u6807**\uFF1A{\u603B\u7ED3\u7528\u6237\u60F3\u8981\u4EC0\u4E48}
|
|
@@ -67138,7 +67673,7 @@ while (true) {
|
|
|
67138
67673
|
const result = delegate_task(
|
|
67139
67674
|
subagent_type="momus",
|
|
67140
67675
|
prompt=".sisyphus/plans/{name}.md",
|
|
67141
|
-
run_in_background=false
|
|
67676
|
+
run_in_background=false, load_skills=[]
|
|
67142
67677
|
)
|
|
67143
67678
|
|
|
67144
67679
|
if (result.verdict === "OKAY") {
|
|
@@ -67798,11 +68333,56 @@ function createConfigHandler(deps) {
|
|
|
67798
68333
|
};
|
|
67799
68334
|
};
|
|
67800
68335
|
}
|
|
68336
|
+
// src/index.ts
|
|
68337
|
+
init_perf_tracer();
|
|
68338
|
+
init_fileio_monitor();
|
|
68339
|
+
|
|
68340
|
+
// src/tools/perf-profiler/client-patch.ts
|
|
68341
|
+
function patchSessionClient(client2, tracer) {
|
|
68342
|
+
if (!tracer.isEnabled())
|
|
68343
|
+
return;
|
|
68344
|
+
const session = client2.session;
|
|
68345
|
+
if (!session || typeof session !== "object")
|
|
68346
|
+
return;
|
|
68347
|
+
function wrap(methodName, extractMessageCount) {
|
|
68348
|
+
const original = session[methodName];
|
|
68349
|
+
if (typeof original !== "function")
|
|
68350
|
+
return;
|
|
68351
|
+
session[methodName] = async function(opts) {
|
|
68352
|
+
const start = performance.now();
|
|
68353
|
+
let error92;
|
|
68354
|
+
try {
|
|
68355
|
+
const result = await original.call(session, opts);
|
|
68356
|
+
const durationMs = performance.now() - start;
|
|
68357
|
+
tracer.recordApiCall(methodName, durationMs, opts?.path?.id ?? "", extractMessageCount ? extractMessageCount(result) : undefined);
|
|
68358
|
+
return result;
|
|
68359
|
+
} catch (err) {
|
|
68360
|
+
const durationMs = performance.now() - start;
|
|
68361
|
+
error92 = err instanceof Error ? err.message : String(err);
|
|
68362
|
+
tracer.recordApiCall(methodName, durationMs, opts?.path?.id ?? "", undefined, error92);
|
|
68363
|
+
throw err;
|
|
68364
|
+
}
|
|
68365
|
+
};
|
|
68366
|
+
}
|
|
68367
|
+
wrap("messages", (r) => r?.data?.length ?? undefined);
|
|
68368
|
+
wrap("prompt", (r) => r?.data ? 1 : undefined);
|
|
68369
|
+
wrap("todo", (r) => r?.data?.length ?? undefined);
|
|
68370
|
+
wrap("status", (r) => r?.data ? Object.keys(r.data).length : undefined);
|
|
68371
|
+
wrap("summarize");
|
|
68372
|
+
}
|
|
68373
|
+
|
|
67801
68374
|
// src/index.ts
|
|
67802
68375
|
var OhMyOpenCodePlugin = async (ctx) => {
|
|
67803
68376
|
log("[OhMyOpenCodePlugin] ENTRY - plugin loading", { directory: ctx.directory });
|
|
67804
68377
|
startBackgroundCheck2();
|
|
67805
68378
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx);
|
|
68379
|
+
if (process.platform === "win32") {
|
|
68380
|
+
const reservedNames = scanForReservedNames(ctx.directory, 3);
|
|
68381
|
+
if (reservedNames.length > 0) {
|
|
68382
|
+
console.warn(formatReservedNamesWarning(reservedNames));
|
|
68383
|
+
log("[oh-my-opencode] Windows reserved device names detected:", reservedNames);
|
|
68384
|
+
}
|
|
68385
|
+
}
|
|
67806
68386
|
const disabledHooks = new Set(pluginConfig.disabled_hooks ?? []);
|
|
67807
68387
|
const firstMessageVariantGate = createFirstMessageVariantGate();
|
|
67808
68388
|
const isHookEnabled = (hookName) => !disabledHooks.has(hookName);
|
|
@@ -67863,6 +68443,34 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
67863
68443
|
const taskResumeInfo = createTaskResumeInfoHook();
|
|
67864
68444
|
const backgroundManager = new BackgroundManager(ctx, pluginConfig.background_task);
|
|
67865
68445
|
const atlasHook = isHookEnabled("atlas") ? createAtlasHook(ctx, { directory: ctx.directory, backgroundManager }) : null;
|
|
68446
|
+
const perfTracer = pluginConfig.experimental?.profiling?.enabled ? new PerfTracer({
|
|
68447
|
+
enabled: true,
|
|
68448
|
+
outputDir: pluginConfig.experimental.profiling.output_dir,
|
|
68449
|
+
slowThreshold: pluginConfig.experimental.profiling.slow_threshold_ms,
|
|
68450
|
+
memorySnapshotInterval: pluginConfig.experimental.profiling.memory_snapshot_interval
|
|
68451
|
+
}) : new PerfTracer({ enabled: false });
|
|
68452
|
+
const memoryProbes = {};
|
|
68453
|
+
if (perfTracer.isEnabled()) {
|
|
68454
|
+
memoryProbes.subagentSessions = () => subagentSessions.size;
|
|
68455
|
+
memoryProbes.backgroundRunningTasks = () => backgroundManager.getRunningTasks().length;
|
|
68456
|
+
memoryProbes.backgroundCompletedTasks = () => backgroundManager.getCompletedTasks().length;
|
|
68457
|
+
}
|
|
68458
|
+
const perfProfiler = isHookEnabled("perf-profiler") ? createPerfProfilerHook({
|
|
68459
|
+
config: pluginConfig.experimental?.profiling ?? { enabled: false, slow_threshold_ms: 100, memory_snapshot_interval: 5, trace_api: true, trace_fileio: true, trace_polling: true },
|
|
68460
|
+
tracer: perfTracer,
|
|
68461
|
+
memoryProbes
|
|
68462
|
+
}) : null;
|
|
68463
|
+
if (perfTracer.isEnabled()) {
|
|
68464
|
+
try {
|
|
68465
|
+
patchSessionClient(ctx.client, perfTracer);
|
|
68466
|
+
} catch {}
|
|
68467
|
+
try {
|
|
68468
|
+
setFileIOMonitor(createFileIOMonitor(perfTracer));
|
|
68469
|
+
} catch {}
|
|
68470
|
+
try {
|
|
68471
|
+
backgroundManager.setPerfTracer(perfTracer);
|
|
68472
|
+
} catch {}
|
|
68473
|
+
}
|
|
67866
68474
|
initTaskToastManager(ctx.client);
|
|
67867
68475
|
const todoContinuationEnforcer = isHookEnabled("todo-continuation-enforcer") ? createTodoContinuationEnforcer(ctx, { backgroundManager }) : null;
|
|
67868
68476
|
if (sessionRecovery && todoContinuationEnforcer) {
|
|
@@ -67927,6 +68535,27 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
67927
68535
|
pluginConfig,
|
|
67928
68536
|
modelCacheState
|
|
67929
68537
|
});
|
|
68538
|
+
async function wrapWithTiming(tracer, pipeline2, hookName, fn, sessionID, tool3) {
|
|
68539
|
+
const start = performance.now();
|
|
68540
|
+
let error92;
|
|
68541
|
+
try {
|
|
68542
|
+
await fn();
|
|
68543
|
+
} catch (e) {
|
|
68544
|
+
error92 = String(e);
|
|
68545
|
+
throw e;
|
|
68546
|
+
} finally {
|
|
68547
|
+
tracer.recordHook(pipeline2, hookName, performance.now() - start, sessionID ?? "", tool3, error92);
|
|
68548
|
+
}
|
|
68549
|
+
}
|
|
68550
|
+
function getEventSessionID(input) {
|
|
68551
|
+
const props = input.event.properties;
|
|
68552
|
+
if (!props)
|
|
68553
|
+
return "";
|
|
68554
|
+
const info = props.info;
|
|
68555
|
+
if (input.event.type === "session.deleted" || input.event.type === "session.created")
|
|
68556
|
+
return info?.id ?? "";
|
|
68557
|
+
return props.sessionID ?? "";
|
|
68558
|
+
}
|
|
67930
68559
|
return {
|
|
67931
68560
|
tool: {
|
|
67932
68561
|
...builtinTools,
|
|
@@ -67953,10 +68582,17 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
67953
68582
|
} else {
|
|
67954
68583
|
applyAgentVariant(pluginConfig, input.agent, message);
|
|
67955
68584
|
}
|
|
67956
|
-
|
|
67957
|
-
|
|
67958
|
-
await
|
|
67959
|
-
|
|
68585
|
+
const pipelineStart = performance.now();
|
|
68586
|
+
let hookCount = 0;
|
|
68587
|
+
await wrapWithTiming(perfTracer, "chat.message", "keywordDetector", () => keywordDetector?.["chat.message"]?.(input, output), input.sessionID);
|
|
68588
|
+
hookCount++;
|
|
68589
|
+
await wrapWithTiming(perfTracer, "chat.message", "claudeCodeHooks", () => claudeCodeHooks["chat.message"]?.(input, output), input.sessionID);
|
|
68590
|
+
hookCount++;
|
|
68591
|
+
await wrapWithTiming(perfTracer, "chat.message", "autoSlashCommand", () => autoSlashCommand?.["chat.message"]?.(input, output), input.sessionID);
|
|
68592
|
+
hookCount++;
|
|
68593
|
+
await wrapWithTiming(perfTracer, "chat.message", "startWork", () => startWork?.["chat.message"]?.(input, output), input.sessionID);
|
|
68594
|
+
hookCount++;
|
|
68595
|
+
perfTracer.recordPipeline("chat.message", performance.now() - pipelineStart, hookCount, input.sessionID);
|
|
67960
68596
|
if (ralphLoop) {
|
|
67961
68597
|
const parts = output.parts;
|
|
67962
68598
|
const promptText = parts?.filter((p) => p.type === "text" && p.text).map((p) => p.text).join(`
|
|
@@ -67986,27 +68622,49 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
67986
68622
|
}
|
|
67987
68623
|
}
|
|
67988
68624
|
},
|
|
68625
|
+
"chat.params": async (input, output) => {
|
|
68626
|
+
await thinkMode?.["chat.params"]?.(input, output);
|
|
68627
|
+
},
|
|
67989
68628
|
"experimental.chat.messages.transform": async (input, output) => {
|
|
67990
68629
|
await contextInjectorMessagesTransform?.["experimental.chat.messages.transform"]?.(input, output);
|
|
67991
68630
|
await thinkingBlockValidator?.["experimental.chat.messages.transform"]?.(input, output);
|
|
67992
68631
|
},
|
|
67993
68632
|
config: configHandler,
|
|
67994
68633
|
event: async (input) => {
|
|
67995
|
-
|
|
67996
|
-
|
|
67997
|
-
await
|
|
67998
|
-
|
|
67999
|
-
await
|
|
68000
|
-
|
|
68001
|
-
await
|
|
68002
|
-
|
|
68003
|
-
await
|
|
68004
|
-
|
|
68005
|
-
await
|
|
68006
|
-
|
|
68007
|
-
await
|
|
68008
|
-
|
|
68009
|
-
await
|
|
68634
|
+
const pipelineStart = performance.now();
|
|
68635
|
+
let hookCount = 0;
|
|
68636
|
+
await perfProfiler?.event?.(input);
|
|
68637
|
+
const evtSessionID = getEventSessionID(input);
|
|
68638
|
+
await wrapWithTiming(perfTracer, "event", "autoUpdateChecker", () => autoUpdateChecker?.event(input), evtSessionID);
|
|
68639
|
+
hookCount++;
|
|
68640
|
+
await wrapWithTiming(perfTracer, "event", "claudeCodeHooks", () => claudeCodeHooks.event(input), evtSessionID);
|
|
68641
|
+
hookCount++;
|
|
68642
|
+
await wrapWithTiming(perfTracer, "event", "backgroundNotificationHook", () => backgroundNotificationHook?.event(input), evtSessionID);
|
|
68643
|
+
hookCount++;
|
|
68644
|
+
await wrapWithTiming(perfTracer, "event", "sessionNotification", () => sessionNotification?.(input), evtSessionID);
|
|
68645
|
+
hookCount++;
|
|
68646
|
+
await wrapWithTiming(perfTracer, "event", "todoContinuationEnforcer", () => todoContinuationEnforcer?.handler(input), evtSessionID);
|
|
68647
|
+
hookCount++;
|
|
68648
|
+
await wrapWithTiming(perfTracer, "event", "contextWindowMonitor", () => contextWindowMonitor?.event(input), evtSessionID);
|
|
68649
|
+
hookCount++;
|
|
68650
|
+
await wrapWithTiming(perfTracer, "event", "directoryAgentsInjector", () => directoryAgentsInjector?.event(input), evtSessionID);
|
|
68651
|
+
hookCount++;
|
|
68652
|
+
await wrapWithTiming(perfTracer, "event", "directoryReadmeInjector", () => directoryReadmeInjector?.event(input), evtSessionID);
|
|
68653
|
+
hookCount++;
|
|
68654
|
+
await wrapWithTiming(perfTracer, "event", "rulesInjector", () => rulesInjector?.event(input), evtSessionID);
|
|
68655
|
+
hookCount++;
|
|
68656
|
+
await wrapWithTiming(perfTracer, "event", "thinkMode", () => thinkMode?.event(input), evtSessionID);
|
|
68657
|
+
hookCount++;
|
|
68658
|
+
await wrapWithTiming(perfTracer, "event", "anthropicContextWindowLimitRecovery", () => anthropicContextWindowLimitRecovery?.event(input), evtSessionID);
|
|
68659
|
+
hookCount++;
|
|
68660
|
+
await wrapWithTiming(perfTracer, "event", "agentUsageReminder", () => agentUsageReminder?.event(input), evtSessionID);
|
|
68661
|
+
hookCount++;
|
|
68662
|
+
await wrapWithTiming(perfTracer, "event", "interactiveBashSession", () => interactiveBashSession?.event(input), evtSessionID);
|
|
68663
|
+
hookCount++;
|
|
68664
|
+
await wrapWithTiming(perfTracer, "event", "ralphLoop", () => ralphLoop?.event(input), evtSessionID);
|
|
68665
|
+
hookCount++;
|
|
68666
|
+
await wrapWithTiming(perfTracer, "event", "atlasHook", () => atlasHook?.handler(input), evtSessionID);
|
|
68667
|
+
hookCount++;
|
|
68010
68668
|
const { event } = input;
|
|
68011
68669
|
const props = event.properties;
|
|
68012
68670
|
if (event.type === "session.created") {
|
|
@@ -68059,17 +68717,30 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
68059
68717
|
}
|
|
68060
68718
|
}
|
|
68061
68719
|
}
|
|
68720
|
+
perfTracer.recordPipeline("event", performance.now() - pipelineStart, hookCount, evtSessionID);
|
|
68721
|
+
perfTracer.flush();
|
|
68062
68722
|
},
|
|
68063
68723
|
"tool.execute.before": async (input, output) => {
|
|
68064
|
-
|
|
68065
|
-
|
|
68066
|
-
await
|
|
68067
|
-
|
|
68068
|
-
await
|
|
68069
|
-
|
|
68070
|
-
await
|
|
68071
|
-
|
|
68072
|
-
await
|
|
68724
|
+
const pipelineStart = performance.now();
|
|
68725
|
+
let hookCount = 0;
|
|
68726
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "questionLabelTruncator", () => questionLabelTruncator["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68727
|
+
hookCount++;
|
|
68728
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "claudeCodeHooks", () => claudeCodeHooks["tool.execute.before"](input, output), input.sessionID, input.tool);
|
|
68729
|
+
hookCount++;
|
|
68730
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "nonInteractiveEnv", () => nonInteractiveEnv?.["tool.execute.before"](input, output), input.sessionID, input.tool);
|
|
68731
|
+
hookCount++;
|
|
68732
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "commentChecker", () => commentChecker?.["tool.execute.before"](input, output), input.sessionID, input.tool);
|
|
68733
|
+
hookCount++;
|
|
68734
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "directoryAgentsInjector", () => directoryAgentsInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68735
|
+
hookCount++;
|
|
68736
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "directoryReadmeInjector", () => directoryReadmeInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68737
|
+
hookCount++;
|
|
68738
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "rulesInjector", () => rulesInjector?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68739
|
+
hookCount++;
|
|
68740
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "prometheusMdOnly", () => prometheusMdOnly?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68741
|
+
hookCount++;
|
|
68742
|
+
await wrapWithTiming(perfTracer, "tool.execute.before", "atlasHook", () => atlasHook?.["tool.execute.before"]?.(input, output), input.sessionID, input.tool);
|
|
68743
|
+
hookCount++;
|
|
68073
68744
|
if (input.tool === "task") {
|
|
68074
68745
|
const args = output.args;
|
|
68075
68746
|
const subagentType = args.subagent_type;
|
|
@@ -68109,22 +68780,40 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
68109
68780
|
});
|
|
68110
68781
|
}
|
|
68111
68782
|
}
|
|
68783
|
+
perfTracer.recordPipeline("tool.execute.before", performance.now() - pipelineStart, hookCount, input.sessionID);
|
|
68112
68784
|
},
|
|
68113
68785
|
"tool.execute.after": async (input, output) => {
|
|
68114
|
-
|
|
68115
|
-
|
|
68116
|
-
await
|
|
68117
|
-
|
|
68118
|
-
await
|
|
68119
|
-
|
|
68120
|
-
await
|
|
68121
|
-
|
|
68122
|
-
await
|
|
68123
|
-
|
|
68124
|
-
await
|
|
68125
|
-
|
|
68126
|
-
await
|
|
68127
|
-
|
|
68786
|
+
const pipelineStart = performance.now();
|
|
68787
|
+
let hookCount = 0;
|
|
68788
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "claudeCodeHooks", () => claudeCodeHooks["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68789
|
+
hookCount++;
|
|
68790
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "toolOutputTruncator", () => toolOutputTruncator?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68791
|
+
hookCount++;
|
|
68792
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "contextWindowMonitor", () => contextWindowMonitor?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68793
|
+
hookCount++;
|
|
68794
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "commentChecker", () => commentChecker?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68795
|
+
hookCount++;
|
|
68796
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "directoryAgentsInjector", () => directoryAgentsInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68797
|
+
hookCount++;
|
|
68798
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "directoryReadmeInjector", () => directoryReadmeInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68799
|
+
hookCount++;
|
|
68800
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "rulesInjector", () => rulesInjector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68801
|
+
hookCount++;
|
|
68802
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "emptyTaskResponseDetector", () => emptyTaskResponseDetector?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68803
|
+
hookCount++;
|
|
68804
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "agentUsageReminder", () => agentUsageReminder?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68805
|
+
hookCount++;
|
|
68806
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "interactiveBashSession", () => interactiveBashSession?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68807
|
+
hookCount++;
|
|
68808
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "editErrorRecovery", () => editErrorRecovery?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68809
|
+
hookCount++;
|
|
68810
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "delegateTaskRetry", () => delegateTaskRetry?.["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68811
|
+
hookCount++;
|
|
68812
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "atlasHook", () => atlasHook?.["tool.execute.after"]?.(input, output), input.sessionID, input.tool);
|
|
68813
|
+
hookCount++;
|
|
68814
|
+
await wrapWithTiming(perfTracer, "tool.execute.after", "taskResumeInfo", () => taskResumeInfo["tool.execute.after"](input, output), input.sessionID, input.tool);
|
|
68815
|
+
hookCount++;
|
|
68816
|
+
perfTracer.recordPipeline("tool.execute.after", performance.now() - pipelineStart, hookCount, input.sessionID);
|
|
68128
68817
|
}
|
|
68129
68818
|
};
|
|
68130
68819
|
};
|