@skj1724/oh-my-opencode 3.19.5 → 3.19.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/atlas.d.ts +1 -1
- package/dist/agents/prometheus-prompt.d.ts +1 -1
- package/dist/cli/index.js +54 -3
- package/dist/config/schema.d.ts +27 -0
- package/dist/features/background-agent/manager.d.ts +3 -0
- package/dist/features/background-agent/types.d.ts +14 -0
- package/dist/features/task-toast-manager/manager.d.ts +5 -1
- package/dist/hooks/runtime-fallback/index.d.ts +23 -0
- package/dist/hooks/runtime-fallback/index.test.d.ts +1 -0
- package/dist/index.js +1116 -420
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/provider-error-classifier.d.ts +23 -0
- package/dist/shared/provider-error-classifier.test.d.ts +1 -0
- package/dist/shared/retry-strategy.d.ts +39 -0
- package/dist/shared/retry-strategy.test.d.ts +1 -0
- package/dist/shared/runtime-fallback.d.ts +46 -0
- package/dist/shared/runtime-fallback.test.d.ts +1 -0
- package/dist/shared/windows-reserved-names.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4859,7 +4859,7 @@ var init_agent_tool_restrictions = __esm(() => {
|
|
|
4859
4859
|
});
|
|
4860
4860
|
|
|
4861
4861
|
// src/shared/model-requirements.ts
|
|
4862
|
-
var AGENT_MODEL_REQUIREMENTS;
|
|
4862
|
+
var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
|
|
4863
4863
|
var init_model_requirements = __esm(() => {
|
|
4864
4864
|
AGENT_MODEL_REQUIREMENTS = {
|
|
4865
4865
|
sisyphus: {
|
|
@@ -4928,6 +4928,58 @@ var init_model_requirements = __esm(() => {
|
|
|
4928
4928
|
]
|
|
4929
4929
|
}
|
|
4930
4930
|
};
|
|
4931
|
+
CATEGORY_MODEL_REQUIREMENTS = {
|
|
4932
|
+
"visual-engineering": {
|
|
4933
|
+
fallbackChain: [
|
|
4934
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
|
|
4935
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4936
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
|
|
4937
|
+
]
|
|
4938
|
+
},
|
|
4939
|
+
ultrabrain: {
|
|
4940
|
+
fallbackChain: [
|
|
4941
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
|
|
4942
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4943
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4944
|
+
]
|
|
4945
|
+
},
|
|
4946
|
+
artistry: {
|
|
4947
|
+
fallbackChain: [
|
|
4948
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
|
|
4949
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4950
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
4951
|
+
]
|
|
4952
|
+
},
|
|
4953
|
+
quick: {
|
|
4954
|
+
fallbackChain: [
|
|
4955
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
4956
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4957
|
+
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4958
|
+
]
|
|
4959
|
+
},
|
|
4960
|
+
"unspecified-low": {
|
|
4961
|
+
fallbackChain: [
|
|
4962
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
4963
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
|
|
4964
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
|
|
4965
|
+
]
|
|
4966
|
+
},
|
|
4967
|
+
"unspecified-high": {
|
|
4968
|
+
fallbackChain: [
|
|
4969
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4970
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4971
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4972
|
+
]
|
|
4973
|
+
},
|
|
4974
|
+
writing: {
|
|
4975
|
+
fallbackChain: [
|
|
4976
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4977
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
4978
|
+
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4979
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
4980
|
+
]
|
|
4981
|
+
}
|
|
4982
|
+
};
|
|
4931
4983
|
});
|
|
4932
4984
|
|
|
4933
4985
|
// src/shared/model-availability.ts
|
|
@@ -5064,6 +5116,81 @@ var init_model_resolver = __esm(() => {
|
|
|
5064
5116
|
init_model_availability();
|
|
5065
5117
|
});
|
|
5066
5118
|
|
|
5119
|
+
// src/shared/runtime-fallback.ts
|
|
5120
|
+
function expandChain(chain) {
|
|
5121
|
+
const candidates = [];
|
|
5122
|
+
for (const entry of chain) {
|
|
5123
|
+
for (const provider of entry.providers) {
|
|
5124
|
+
candidates.push({
|
|
5125
|
+
providerID: provider,
|
|
5126
|
+
modelID: entry.model,
|
|
5127
|
+
variant: entry.variant
|
|
5128
|
+
});
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
return candidates;
|
|
5132
|
+
}
|
|
5133
|
+
function modelKey(m) {
|
|
5134
|
+
return `${m.providerID}/${m.modelID}`;
|
|
5135
|
+
}
|
|
5136
|
+
function getChain(agent, category) {
|
|
5137
|
+
if (agent && AGENT_MODEL_REQUIREMENTS[agent]) {
|
|
5138
|
+
return AGENT_MODEL_REQUIREMENTS[agent].fallbackChain;
|
|
5139
|
+
}
|
|
5140
|
+
if (category && CATEGORY_MODEL_REQUIREMENTS[category]) {
|
|
5141
|
+
return CATEGORY_MODEL_REQUIREMENTS[category].fallbackChain;
|
|
5142
|
+
}
|
|
5143
|
+
throw new Error(`No fallback chain found for agent="${agent ?? ""}" category="${category ?? ""}"`);
|
|
5144
|
+
}
|
|
5145
|
+
function resolveNextFallbackModel(input) {
|
|
5146
|
+
const {
|
|
5147
|
+
agent,
|
|
5148
|
+
category,
|
|
5149
|
+
currentModel,
|
|
5150
|
+
attempts,
|
|
5151
|
+
availableModels,
|
|
5152
|
+
lastErrorClassification
|
|
5153
|
+
} = input;
|
|
5154
|
+
const chain = getChain(agent, category);
|
|
5155
|
+
const candidates = expandChain(chain);
|
|
5156
|
+
const skipKeys = new Set;
|
|
5157
|
+
skipKeys.add(modelKey(currentModel));
|
|
5158
|
+
for (const a of attempts) {
|
|
5159
|
+
skipKeys.add(modelKey(a.model));
|
|
5160
|
+
}
|
|
5161
|
+
const resultAttempts = [...attempts];
|
|
5162
|
+
const currentKey = modelKey(currentModel);
|
|
5163
|
+
const isInAttempts = attempts.some((a) => modelKey(a.model) === currentKey);
|
|
5164
|
+
if (!isInAttempts) {
|
|
5165
|
+
resultAttempts.push({ model: currentModel });
|
|
5166
|
+
}
|
|
5167
|
+
const hasAvailabilityFilter = availableModels != null && availableModels.size > 0;
|
|
5168
|
+
for (const candidate of candidates) {
|
|
5169
|
+
const key = modelKey(candidate);
|
|
5170
|
+
if (skipKeys.has(key))
|
|
5171
|
+
continue;
|
|
5172
|
+
if (hasAvailabilityFilter) {
|
|
5173
|
+
const match = fuzzyMatchModel(key, availableModels, [candidate.providerID]);
|
|
5174
|
+
if (!match)
|
|
5175
|
+
continue;
|
|
5176
|
+
}
|
|
5177
|
+
return {
|
|
5178
|
+
kind: "next",
|
|
5179
|
+
model: candidate,
|
|
5180
|
+
attempts: resultAttempts
|
|
5181
|
+
};
|
|
5182
|
+
}
|
|
5183
|
+
return {
|
|
5184
|
+
kind: "exhausted",
|
|
5185
|
+
attempts: resultAttempts,
|
|
5186
|
+
lastErrorClassification
|
|
5187
|
+
};
|
|
5188
|
+
}
|
|
5189
|
+
var init_runtime_fallback = __esm(() => {
|
|
5190
|
+
init_model_availability();
|
|
5191
|
+
init_model_requirements();
|
|
5192
|
+
});
|
|
5193
|
+
|
|
5067
5194
|
// src/shared/perf-timer.ts
|
|
5068
5195
|
class PerfTimer {
|
|
5069
5196
|
marks = new Map;
|
|
@@ -5241,6 +5368,86 @@ class PerfTracer {
|
|
|
5241
5368
|
}
|
|
5242
5369
|
var init_perf_tracer = () => {};
|
|
5243
5370
|
|
|
5371
|
+
// src/shared/windows-reserved-names.ts
|
|
5372
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5 } from "fs";
|
|
5373
|
+
import { join as join14 } from "path";
|
|
5374
|
+
function scanForReservedNames(directory, maxDepth = 2) {
|
|
5375
|
+
if (!existsSync12(directory))
|
|
5376
|
+
return [];
|
|
5377
|
+
const found = [];
|
|
5378
|
+
_scan(directory, 0, maxDepth, found);
|
|
5379
|
+
return found;
|
|
5380
|
+
}
|
|
5381
|
+
function _scan(dir, depth, maxDepth, found) {
|
|
5382
|
+
if (depth > maxDepth)
|
|
5383
|
+
return;
|
|
5384
|
+
let entries;
|
|
5385
|
+
try {
|
|
5386
|
+
entries = readdirSync5(dir);
|
|
5387
|
+
} catch {
|
|
5388
|
+
return;
|
|
5389
|
+
}
|
|
5390
|
+
for (const name of entries) {
|
|
5391
|
+
const upper = name.toUpperCase();
|
|
5392
|
+
const baseName = upper.split(".")[0] ?? "";
|
|
5393
|
+
if (WIN_RESERVED_NAMES.has(upper) || WIN_RESERVED_NAMES.has(baseName)) {
|
|
5394
|
+
found.push(join14(dir, name));
|
|
5395
|
+
}
|
|
5396
|
+
const fullPath = join14(dir, name);
|
|
5397
|
+
try {
|
|
5398
|
+
const stat = existsSync12(fullPath);
|
|
5399
|
+
if (stat && depth < maxDepth) {
|
|
5400
|
+
_scan(fullPath, depth + 1, maxDepth, found);
|
|
5401
|
+
}
|
|
5402
|
+
} catch {}
|
|
5403
|
+
}
|
|
5404
|
+
}
|
|
5405
|
+
function formatReservedNamesWarning(found) {
|
|
5406
|
+
const lines = [
|
|
5407
|
+
"",
|
|
5408
|
+
"\u26A0\uFE0F WINDOWS RESERVED DEVICE NAMES DETECTED",
|
|
5409
|
+
" The following paths match Windows reserved device names (NUL, CON, AUX, etc.):",
|
|
5410
|
+
"",
|
|
5411
|
+
...found.map((p) => ` - ${p}`),
|
|
5412
|
+
"",
|
|
5413
|
+
" These will cause 'error: short read while indexing' git failures on Windows.",
|
|
5414
|
+
" This can make OpenCode's snapshot system extremely slow (30+ minutes).",
|
|
5415
|
+
"",
|
|
5416
|
+
" Fix: Rename these files/directories to avoid reserved names.",
|
|
5417
|
+
" e.g., rename 'nul' \u2192 'null-device', 'con' \u2192 'console-util'",
|
|
5418
|
+
""
|
|
5419
|
+
];
|
|
5420
|
+
return lines.join(`
|
|
5421
|
+
`);
|
|
5422
|
+
}
|
|
5423
|
+
var WIN_RESERVED_NAMES;
|
|
5424
|
+
var init_windows_reserved_names = __esm(() => {
|
|
5425
|
+
WIN_RESERVED_NAMES = new Set([
|
|
5426
|
+
"CON",
|
|
5427
|
+
"PRN",
|
|
5428
|
+
"AUX",
|
|
5429
|
+
"NUL",
|
|
5430
|
+
"COM1",
|
|
5431
|
+
"COM2",
|
|
5432
|
+
"COM3",
|
|
5433
|
+
"COM4",
|
|
5434
|
+
"COM5",
|
|
5435
|
+
"COM6",
|
|
5436
|
+
"COM7",
|
|
5437
|
+
"COM8",
|
|
5438
|
+
"COM9",
|
|
5439
|
+
"LPT1",
|
|
5440
|
+
"LPT2",
|
|
5441
|
+
"LPT3",
|
|
5442
|
+
"LPT4",
|
|
5443
|
+
"LPT5",
|
|
5444
|
+
"LPT6",
|
|
5445
|
+
"LPT7",
|
|
5446
|
+
"LPT8",
|
|
5447
|
+
"LPT9"
|
|
5448
|
+
]);
|
|
5449
|
+
});
|
|
5450
|
+
|
|
5244
5451
|
// src/shared/index.ts
|
|
5245
5452
|
var init_shared = __esm(() => {
|
|
5246
5453
|
init_frontmatter();
|
|
@@ -5268,8 +5475,10 @@ var init_shared = __esm(() => {
|
|
|
5268
5475
|
init_model_requirements();
|
|
5269
5476
|
init_model_resolver();
|
|
5270
5477
|
init_model_availability();
|
|
5478
|
+
init_runtime_fallback();
|
|
5271
5479
|
init_perf_tracer();
|
|
5272
5480
|
init_fileio_monitor();
|
|
5481
|
+
init_windows_reserved_names();
|
|
5273
5482
|
});
|
|
5274
5483
|
|
|
5275
5484
|
// node_modules/picomatch/lib/constants.js
|
|
@@ -16159,20 +16368,20 @@ function createSessionRecoveryHook(ctx, options) {
|
|
|
16159
16368
|
// src/hooks/comment-checker/cli.ts
|
|
16160
16369
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
16161
16370
|
import { createRequire as createRequire2 } from "module";
|
|
16162
|
-
import { dirname, join as
|
|
16163
|
-
import { existsSync as
|
|
16371
|
+
import { dirname, join as join16 } from "path";
|
|
16372
|
+
import { existsSync as existsSync14 } from "fs";
|
|
16164
16373
|
import * as fs5 from "fs";
|
|
16165
16374
|
import { tmpdir as tmpdir4 } from "os";
|
|
16166
16375
|
|
|
16167
16376
|
// src/hooks/comment-checker/downloader.ts
|
|
16168
16377
|
init_shared();
|
|
16169
16378
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
16170
|
-
import { existsSync as
|
|
16171
|
-
import { join as
|
|
16379
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync3 } from "fs";
|
|
16380
|
+
import { join as join15 } from "path";
|
|
16172
16381
|
import { homedir as homedir7, tmpdir as tmpdir3 } from "os";
|
|
16173
16382
|
import { createRequire } from "module";
|
|
16174
16383
|
var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
16175
|
-
var DEBUG_FILE =
|
|
16384
|
+
var DEBUG_FILE = join15(tmpdir3(), "comment-checker-debug.log");
|
|
16176
16385
|
function debugLog(...args) {
|
|
16177
16386
|
if (DEBUG) {
|
|
16178
16387
|
const msg = `[${new Date().toISOString()}] [comment-checker:downloader] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -16191,19 +16400,19 @@ var PLATFORM_MAP = {
|
|
|
16191
16400
|
function getCacheDir() {
|
|
16192
16401
|
if (process.platform === "win32") {
|
|
16193
16402
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
16194
|
-
const base2 = localAppData ||
|
|
16195
|
-
return
|
|
16403
|
+
const base2 = localAppData || join15(homedir7(), "AppData", "Local");
|
|
16404
|
+
return join15(base2, "oh-my-opencode", "bin");
|
|
16196
16405
|
}
|
|
16197
16406
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
16198
|
-
const base = xdgCache ||
|
|
16199
|
-
return
|
|
16407
|
+
const base = xdgCache || join15(homedir7(), ".cache");
|
|
16408
|
+
return join15(base, "oh-my-opencode", "bin");
|
|
16200
16409
|
}
|
|
16201
16410
|
function getBinaryName() {
|
|
16202
16411
|
return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
16203
16412
|
}
|
|
16204
16413
|
function getCachedBinaryPath() {
|
|
16205
|
-
const binaryPath =
|
|
16206
|
-
return
|
|
16414
|
+
const binaryPath = join15(getCacheDir(), getBinaryName());
|
|
16415
|
+
return existsSync13(binaryPath) ? binaryPath : null;
|
|
16207
16416
|
}
|
|
16208
16417
|
function getPackageVersion() {
|
|
16209
16418
|
try {
|
|
@@ -16235,8 +16444,8 @@ async function downloadCommentChecker() {
|
|
|
16235
16444
|
}
|
|
16236
16445
|
const cacheDir = getCacheDir();
|
|
16237
16446
|
const binaryName = getBinaryName();
|
|
16238
|
-
const binaryPath =
|
|
16239
|
-
if (
|
|
16447
|
+
const binaryPath = join15(cacheDir, binaryName);
|
|
16448
|
+
if (existsSync13(binaryPath)) {
|
|
16240
16449
|
debugLog("Binary already cached at:", binaryPath);
|
|
16241
16450
|
return binaryPath;
|
|
16242
16451
|
}
|
|
@@ -16247,14 +16456,14 @@ async function downloadCommentChecker() {
|
|
|
16247
16456
|
debugLog(`Downloading from: ${downloadUrl}`);
|
|
16248
16457
|
console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
|
|
16249
16458
|
try {
|
|
16250
|
-
if (!
|
|
16459
|
+
if (!existsSync13(cacheDir)) {
|
|
16251
16460
|
mkdirSync4(cacheDir, { recursive: true });
|
|
16252
16461
|
}
|
|
16253
16462
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
16254
16463
|
if (!response.ok) {
|
|
16255
16464
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
16256
16465
|
}
|
|
16257
|
-
const archivePath =
|
|
16466
|
+
const archivePath = join15(cacheDir, assetName);
|
|
16258
16467
|
const arrayBuffer = await response.arrayBuffer();
|
|
16259
16468
|
await Bun.write(archivePath, arrayBuffer);
|
|
16260
16469
|
debugLog(`Downloaded archive to: ${archivePath}`);
|
|
@@ -16263,10 +16472,10 @@ async function downloadCommentChecker() {
|
|
|
16263
16472
|
} else {
|
|
16264
16473
|
await extractZip(archivePath, cacheDir);
|
|
16265
16474
|
}
|
|
16266
|
-
if (
|
|
16475
|
+
if (existsSync13(archivePath)) {
|
|
16267
16476
|
unlinkSync2(archivePath);
|
|
16268
16477
|
}
|
|
16269
|
-
if (process.platform !== "win32" &&
|
|
16478
|
+
if (process.platform !== "win32" && existsSync13(binaryPath)) {
|
|
16270
16479
|
chmodSync(binaryPath, 493);
|
|
16271
16480
|
}
|
|
16272
16481
|
debugLog(`Successfully downloaded binary to: ${binaryPath}`);
|
|
@@ -16290,7 +16499,7 @@ async function ensureCommentCheckerBinary() {
|
|
|
16290
16499
|
|
|
16291
16500
|
// src/hooks/comment-checker/cli.ts
|
|
16292
16501
|
var DEBUG2 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
16293
|
-
var DEBUG_FILE2 =
|
|
16502
|
+
var DEBUG_FILE2 = join16(tmpdir4(), "comment-checker-debug.log");
|
|
16294
16503
|
function debugLog2(...args) {
|
|
16295
16504
|
if (DEBUG2) {
|
|
16296
16505
|
const msg = `[${new Date().toISOString()}] [comment-checker:cli] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -16316,8 +16525,8 @@ function findCommentCheckerPathSync() {
|
|
|
16316
16525
|
const require2 = createRequire2(import.meta.url);
|
|
16317
16526
|
const cliPkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
16318
16527
|
const cliDir = dirname(cliPkgPath);
|
|
16319
|
-
const binaryPath =
|
|
16320
|
-
if (
|
|
16528
|
+
const binaryPath = join16(cliDir, "bin", binaryName);
|
|
16529
|
+
if (existsSync14(binaryPath)) {
|
|
16321
16530
|
debugLog2("found binary in main package:", binaryPath);
|
|
16322
16531
|
return binaryPath;
|
|
16323
16532
|
}
|
|
@@ -16338,7 +16547,7 @@ async function getCommentCheckerPath() {
|
|
|
16338
16547
|
}
|
|
16339
16548
|
initPromise = (async () => {
|
|
16340
16549
|
const syncPath = findCommentCheckerPathSync();
|
|
16341
|
-
if (syncPath &&
|
|
16550
|
+
if (syncPath && existsSync14(syncPath)) {
|
|
16342
16551
|
resolvedCliPath = syncPath;
|
|
16343
16552
|
debugLog2("using sync-resolved path:", syncPath);
|
|
16344
16553
|
return syncPath;
|
|
@@ -16374,7 +16583,7 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
16374
16583
|
debugLog2("comment-checker binary not found");
|
|
16375
16584
|
return { hasComments: false, message: "" };
|
|
16376
16585
|
}
|
|
16377
|
-
if (!
|
|
16586
|
+
if (!existsSync14(binaryPath)) {
|
|
16378
16587
|
debugLog2("comment-checker binary does not exist:", binaryPath);
|
|
16379
16588
|
return { hasComments: false, message: "" };
|
|
16380
16589
|
}
|
|
@@ -16412,11 +16621,11 @@ async function runCommentChecker(input, cliPath, customPrompt) {
|
|
|
16412
16621
|
|
|
16413
16622
|
// src/hooks/comment-checker/index.ts
|
|
16414
16623
|
import * as fs6 from "fs";
|
|
16415
|
-
import { existsSync as
|
|
16624
|
+
import { existsSync as existsSync15 } from "fs";
|
|
16416
16625
|
import { tmpdir as tmpdir5 } from "os";
|
|
16417
|
-
import { join as
|
|
16626
|
+
import { join as join17 } from "path";
|
|
16418
16627
|
var DEBUG3 = process.env.COMMENT_CHECKER_DEBUG === "1";
|
|
16419
|
-
var DEBUG_FILE3 =
|
|
16628
|
+
var DEBUG_FILE3 = join17(tmpdir5(), "comment-checker-debug.log");
|
|
16420
16629
|
function debugLog3(...args) {
|
|
16421
16630
|
if (DEBUG3) {
|
|
16422
16631
|
const msg = `[${new Date().toISOString()}] [comment-checker:hook] ${args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ")}
|
|
@@ -16496,7 +16705,7 @@ function createCommentCheckerHooks(config) {
|
|
|
16496
16705
|
}
|
|
16497
16706
|
try {
|
|
16498
16707
|
const cliPath = await cliPathPromise;
|
|
16499
|
-
if (!cliPath || !
|
|
16708
|
+
if (!cliPath || !existsSync15(cliPath)) {
|
|
16500
16709
|
debugLog3("CLI not available, skipping comment check");
|
|
16501
16710
|
return;
|
|
16502
16711
|
}
|
|
@@ -16576,33 +16785,33 @@ function createToolOutputTruncatorHook(ctx, options) {
|
|
|
16576
16785
|
};
|
|
16577
16786
|
}
|
|
16578
16787
|
// src/hooks/directory-agents-injector/index.ts
|
|
16579
|
-
import { existsSync as
|
|
16580
|
-
import { dirname as dirname2, join as
|
|
16788
|
+
import { existsSync as existsSync17, readFileSync as readFileSync9 } from "fs";
|
|
16789
|
+
import { dirname as dirname2, join as join20, resolve as resolve3 } from "path";
|
|
16581
16790
|
|
|
16582
16791
|
// src/hooks/directory-agents-injector/storage.ts
|
|
16583
16792
|
import {
|
|
16584
|
-
existsSync as
|
|
16793
|
+
existsSync as existsSync16,
|
|
16585
16794
|
mkdirSync as mkdirSync5,
|
|
16586
16795
|
readFileSync as readFileSync8,
|
|
16587
16796
|
writeFileSync as writeFileSync5,
|
|
16588
16797
|
unlinkSync as unlinkSync3
|
|
16589
16798
|
} from "fs";
|
|
16590
|
-
import { join as
|
|
16799
|
+
import { join as join19 } from "path";
|
|
16591
16800
|
|
|
16592
16801
|
// src/hooks/directory-agents-injector/constants.ts
|
|
16593
16802
|
init_data_path();
|
|
16594
|
-
import { join as
|
|
16803
|
+
import { join as join18 } from "path";
|
|
16595
16804
|
var OPENCODE_STORAGE3 = getOpenCodeStorageDir();
|
|
16596
|
-
var AGENTS_INJECTOR_STORAGE =
|
|
16805
|
+
var AGENTS_INJECTOR_STORAGE = join18(OPENCODE_STORAGE3, "directory-agents");
|
|
16597
16806
|
var AGENTS_FILENAME = "AGENTS.md";
|
|
16598
16807
|
|
|
16599
16808
|
// src/hooks/directory-agents-injector/storage.ts
|
|
16600
16809
|
function getStoragePath(sessionID) {
|
|
16601
|
-
return
|
|
16810
|
+
return join19(AGENTS_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
16602
16811
|
}
|
|
16603
16812
|
function loadInjectedPaths(sessionID) {
|
|
16604
16813
|
const filePath = getStoragePath(sessionID);
|
|
16605
|
-
if (!
|
|
16814
|
+
if (!existsSync16(filePath))
|
|
16606
16815
|
return new Set;
|
|
16607
16816
|
try {
|
|
16608
16817
|
const content = readFileSync8(filePath, "utf-8");
|
|
@@ -16613,7 +16822,7 @@ function loadInjectedPaths(sessionID) {
|
|
|
16613
16822
|
}
|
|
16614
16823
|
}
|
|
16615
16824
|
function saveInjectedPaths(sessionID, paths) {
|
|
16616
|
-
if (!
|
|
16825
|
+
if (!existsSync16(AGENTS_INJECTOR_STORAGE)) {
|
|
16617
16826
|
mkdirSync5(AGENTS_INJECTOR_STORAGE, { recursive: true });
|
|
16618
16827
|
}
|
|
16619
16828
|
const data = {
|
|
@@ -16625,7 +16834,7 @@ function saveInjectedPaths(sessionID, paths) {
|
|
|
16625
16834
|
}
|
|
16626
16835
|
function clearInjectedPaths(sessionID) {
|
|
16627
16836
|
const filePath = getStoragePath(sessionID);
|
|
16628
|
-
if (
|
|
16837
|
+
if (existsSync16(filePath)) {
|
|
16629
16838
|
unlinkSync3(filePath);
|
|
16630
16839
|
}
|
|
16631
16840
|
}
|
|
@@ -16655,8 +16864,8 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
16655
16864
|
while (true) {
|
|
16656
16865
|
const isRootDir = current === ctx.directory;
|
|
16657
16866
|
if (!isRootDir) {
|
|
16658
|
-
const agentsPath =
|
|
16659
|
-
if (
|
|
16867
|
+
const agentsPath = join20(current, AGENTS_FILENAME);
|
|
16868
|
+
if (existsSync17(agentsPath)) {
|
|
16660
16869
|
found.push(agentsPath);
|
|
16661
16870
|
}
|
|
16662
16871
|
}
|
|
@@ -16753,33 +16962,33 @@ ${result}${truncationNotice}`;
|
|
|
16753
16962
|
};
|
|
16754
16963
|
}
|
|
16755
16964
|
// src/hooks/directory-readme-injector/index.ts
|
|
16756
|
-
import { existsSync as
|
|
16757
|
-
import { dirname as dirname3, join as
|
|
16965
|
+
import { existsSync as existsSync19, readFileSync as readFileSync11 } from "fs";
|
|
16966
|
+
import { dirname as dirname3, join as join23, resolve as resolve4 } from "path";
|
|
16758
16967
|
|
|
16759
16968
|
// src/hooks/directory-readme-injector/storage.ts
|
|
16760
16969
|
import {
|
|
16761
|
-
existsSync as
|
|
16970
|
+
existsSync as existsSync18,
|
|
16762
16971
|
mkdirSync as mkdirSync6,
|
|
16763
16972
|
readFileSync as readFileSync10,
|
|
16764
16973
|
writeFileSync as writeFileSync6,
|
|
16765
16974
|
unlinkSync as unlinkSync4
|
|
16766
16975
|
} from "fs";
|
|
16767
|
-
import { join as
|
|
16976
|
+
import { join as join22 } from "path";
|
|
16768
16977
|
|
|
16769
16978
|
// src/hooks/directory-readme-injector/constants.ts
|
|
16770
16979
|
init_data_path();
|
|
16771
|
-
import { join as
|
|
16980
|
+
import { join as join21 } from "path";
|
|
16772
16981
|
var OPENCODE_STORAGE4 = getOpenCodeStorageDir();
|
|
16773
|
-
var README_INJECTOR_STORAGE =
|
|
16982
|
+
var README_INJECTOR_STORAGE = join21(OPENCODE_STORAGE4, "directory-readme");
|
|
16774
16983
|
var README_FILENAME = "README.md";
|
|
16775
16984
|
|
|
16776
16985
|
// src/hooks/directory-readme-injector/storage.ts
|
|
16777
16986
|
function getStoragePath2(sessionID) {
|
|
16778
|
-
return
|
|
16987
|
+
return join22(README_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
16779
16988
|
}
|
|
16780
16989
|
function loadInjectedPaths2(sessionID) {
|
|
16781
16990
|
const filePath = getStoragePath2(sessionID);
|
|
16782
|
-
if (!
|
|
16991
|
+
if (!existsSync18(filePath))
|
|
16783
16992
|
return new Set;
|
|
16784
16993
|
try {
|
|
16785
16994
|
const content = readFileSync10(filePath, "utf-8");
|
|
@@ -16790,7 +16999,7 @@ function loadInjectedPaths2(sessionID) {
|
|
|
16790
16999
|
}
|
|
16791
17000
|
}
|
|
16792
17001
|
function saveInjectedPaths2(sessionID, paths) {
|
|
16793
|
-
if (!
|
|
17002
|
+
if (!existsSync18(README_INJECTOR_STORAGE)) {
|
|
16794
17003
|
mkdirSync6(README_INJECTOR_STORAGE, { recursive: true });
|
|
16795
17004
|
}
|
|
16796
17005
|
const data = {
|
|
@@ -16802,7 +17011,7 @@ function saveInjectedPaths2(sessionID, paths) {
|
|
|
16802
17011
|
}
|
|
16803
17012
|
function clearInjectedPaths2(sessionID) {
|
|
16804
17013
|
const filePath = getStoragePath2(sessionID);
|
|
16805
|
-
if (
|
|
17014
|
+
if (existsSync18(filePath)) {
|
|
16806
17015
|
unlinkSync4(filePath);
|
|
16807
17016
|
}
|
|
16808
17017
|
}
|
|
@@ -16830,8 +17039,8 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
16830
17039
|
const found = [];
|
|
16831
17040
|
let current = startDir;
|
|
16832
17041
|
while (true) {
|
|
16833
|
-
const readmePath =
|
|
16834
|
-
if (
|
|
17042
|
+
const readmePath = join23(current, README_FILENAME);
|
|
17043
|
+
if (existsSync19(readmePath)) {
|
|
16835
17044
|
found.push(readmePath);
|
|
16836
17045
|
}
|
|
16837
17046
|
if (current === ctx.directory)
|
|
@@ -17141,22 +17350,22 @@ var TRUNCATE_CONFIG = {
|
|
|
17141
17350
|
|
|
17142
17351
|
// src/hooks/anthropic-context-window-limit-recovery/storage.ts
|
|
17143
17352
|
init_data_path();
|
|
17144
|
-
import { existsSync as
|
|
17145
|
-
import { join as
|
|
17353
|
+
import { existsSync as existsSync20, readdirSync as readdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
17354
|
+
import { join as join24 } from "path";
|
|
17146
17355
|
var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
|
|
17147
|
-
var MESSAGE_STORAGE3 =
|
|
17148
|
-
var PART_STORAGE3 =
|
|
17356
|
+
var MESSAGE_STORAGE3 = join24(OPENCODE_STORAGE5, "message");
|
|
17357
|
+
var PART_STORAGE3 = join24(OPENCODE_STORAGE5, "part");
|
|
17149
17358
|
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.]";
|
|
17150
17359
|
function getMessageDir3(sessionID) {
|
|
17151
|
-
if (!
|
|
17360
|
+
if (!existsSync20(MESSAGE_STORAGE3))
|
|
17152
17361
|
return "";
|
|
17153
|
-
const directPath =
|
|
17154
|
-
if (
|
|
17362
|
+
const directPath = join24(MESSAGE_STORAGE3, sessionID);
|
|
17363
|
+
if (existsSync20(directPath)) {
|
|
17155
17364
|
return directPath;
|
|
17156
17365
|
}
|
|
17157
|
-
for (const dir of
|
|
17158
|
-
const sessionPath =
|
|
17159
|
-
if (
|
|
17366
|
+
for (const dir of readdirSync6(MESSAGE_STORAGE3)) {
|
|
17367
|
+
const sessionPath = join24(MESSAGE_STORAGE3, dir, sessionID);
|
|
17368
|
+
if (existsSync20(sessionPath)) {
|
|
17160
17369
|
return sessionPath;
|
|
17161
17370
|
}
|
|
17162
17371
|
}
|
|
@@ -17164,10 +17373,10 @@ function getMessageDir3(sessionID) {
|
|
|
17164
17373
|
}
|
|
17165
17374
|
function getMessageIds(sessionID) {
|
|
17166
17375
|
const messageDir = getMessageDir3(sessionID);
|
|
17167
|
-
if (!messageDir || !
|
|
17376
|
+
if (!messageDir || !existsSync20(messageDir))
|
|
17168
17377
|
return [];
|
|
17169
17378
|
const messageIds = [];
|
|
17170
|
-
for (const file of
|
|
17379
|
+
for (const file of readdirSync6(messageDir)) {
|
|
17171
17380
|
if (!file.endsWith(".json"))
|
|
17172
17381
|
continue;
|
|
17173
17382
|
const messageId = file.replace(".json", "");
|
|
@@ -17179,14 +17388,14 @@ function findToolResultsBySize(sessionID) {
|
|
|
17179
17388
|
const messageIds = getMessageIds(sessionID);
|
|
17180
17389
|
const results = [];
|
|
17181
17390
|
for (const messageID of messageIds) {
|
|
17182
|
-
const partDir =
|
|
17183
|
-
if (!
|
|
17391
|
+
const partDir = join24(PART_STORAGE3, messageID);
|
|
17392
|
+
if (!existsSync20(partDir))
|
|
17184
17393
|
continue;
|
|
17185
|
-
for (const file of
|
|
17394
|
+
for (const file of readdirSync6(partDir)) {
|
|
17186
17395
|
if (!file.endsWith(".json"))
|
|
17187
17396
|
continue;
|
|
17188
17397
|
try {
|
|
17189
|
-
const partPath =
|
|
17398
|
+
const partPath = join24(partDir, file);
|
|
17190
17399
|
const content = readFileSync12(partPath, "utf-8");
|
|
17191
17400
|
const part = JSON.parse(content);
|
|
17192
17401
|
if (part.type === "tool" && part.state?.output && !part.truncated) {
|
|
@@ -18033,8 +18242,8 @@ function createThinkModeHook() {
|
|
|
18033
18242
|
}
|
|
18034
18243
|
// src/hooks/claude-code-hooks/config.ts
|
|
18035
18244
|
init_shared();
|
|
18036
|
-
import { join as
|
|
18037
|
-
import { existsSync as
|
|
18245
|
+
import { join as join25 } from "path";
|
|
18246
|
+
import { existsSync as existsSync21 } from "fs";
|
|
18038
18247
|
function normalizeHookMatcher(raw) {
|
|
18039
18248
|
return {
|
|
18040
18249
|
matcher: raw.matcher ?? raw.pattern ?? "*",
|
|
@@ -18060,11 +18269,11 @@ function normalizeHooksConfig(raw) {
|
|
|
18060
18269
|
function getClaudeSettingsPaths(customPath) {
|
|
18061
18270
|
const claudeConfigDir = getClaudeConfigDir();
|
|
18062
18271
|
const paths = [
|
|
18063
|
-
|
|
18064
|
-
|
|
18065
|
-
|
|
18272
|
+
join25(claudeConfigDir, "settings.json"),
|
|
18273
|
+
join25(process.cwd(), ".claude", "settings.json"),
|
|
18274
|
+
join25(process.cwd(), ".claude", "settings.local.json")
|
|
18066
18275
|
];
|
|
18067
|
-
if (customPath &&
|
|
18276
|
+
if (customPath && existsSync21(customPath)) {
|
|
18068
18277
|
paths.unshift(customPath);
|
|
18069
18278
|
}
|
|
18070
18279
|
return paths;
|
|
@@ -18089,7 +18298,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
18089
18298
|
const paths = getClaudeSettingsPaths(customSettingsPath);
|
|
18090
18299
|
let mergedConfig = {};
|
|
18091
18300
|
for (const settingsPath of paths) {
|
|
18092
|
-
if (
|
|
18301
|
+
if (existsSync21(settingsPath)) {
|
|
18093
18302
|
try {
|
|
18094
18303
|
const content = await Bun.file(settingsPath).text();
|
|
18095
18304
|
const settings = JSON.parse(content);
|
|
@@ -18108,14 +18317,14 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
18108
18317
|
// src/hooks/claude-code-hooks/config-loader.ts
|
|
18109
18318
|
init_logger();
|
|
18110
18319
|
init_shared();
|
|
18111
|
-
import { existsSync as
|
|
18112
|
-
import { join as
|
|
18113
|
-
var USER_CONFIG_PATH =
|
|
18320
|
+
import { existsSync as existsSync22 } from "fs";
|
|
18321
|
+
import { join as join26 } from "path";
|
|
18322
|
+
var USER_CONFIG_PATH = join26(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
|
|
18114
18323
|
function getProjectConfigPath() {
|
|
18115
|
-
return
|
|
18324
|
+
return join26(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
18116
18325
|
}
|
|
18117
18326
|
async function loadConfigFromPath(path4) {
|
|
18118
|
-
if (!
|
|
18327
|
+
if (!existsSync22(path4)) {
|
|
18119
18328
|
return null;
|
|
18120
18329
|
}
|
|
18121
18330
|
try {
|
|
@@ -18303,16 +18512,16 @@ init_shared();
|
|
|
18303
18512
|
// src/hooks/claude-code-hooks/transcript.ts
|
|
18304
18513
|
init_tool_name();
|
|
18305
18514
|
init_shared();
|
|
18306
|
-
import { join as
|
|
18307
|
-
import { mkdirSync as mkdirSync7, appendFileSync as appendFileSync6, existsSync as
|
|
18515
|
+
import { join as join27 } from "path";
|
|
18516
|
+
import { mkdirSync as mkdirSync7, appendFileSync as appendFileSync6, existsSync as existsSync23, writeFileSync as writeFileSync8, unlinkSync as unlinkSync5 } from "fs";
|
|
18308
18517
|
import { tmpdir as tmpdir6 } from "os";
|
|
18309
18518
|
import { randomUUID } from "crypto";
|
|
18310
|
-
var TRANSCRIPT_DIR =
|
|
18519
|
+
var TRANSCRIPT_DIR = join27(getClaudeConfigDir(), "transcripts");
|
|
18311
18520
|
function getTranscriptPath(sessionId) {
|
|
18312
|
-
return
|
|
18521
|
+
return join27(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
18313
18522
|
}
|
|
18314
18523
|
function ensureTranscriptDir() {
|
|
18315
|
-
if (!
|
|
18524
|
+
if (!existsSync23(TRANSCRIPT_DIR)) {
|
|
18316
18525
|
mkdirSync7(TRANSCRIPT_DIR, { recursive: true });
|
|
18317
18526
|
}
|
|
18318
18527
|
}
|
|
@@ -18399,7 +18608,7 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
18399
18608
|
}
|
|
18400
18609
|
};
|
|
18401
18610
|
entries.push(JSON.stringify(currentEntry));
|
|
18402
|
-
const tempPath =
|
|
18611
|
+
const tempPath = join27(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
18403
18612
|
writeFileSync8(tempPath, entries.join(`
|
|
18404
18613
|
`) + `
|
|
18405
18614
|
`);
|
|
@@ -18419,7 +18628,7 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
18419
18628
|
]
|
|
18420
18629
|
}
|
|
18421
18630
|
};
|
|
18422
|
-
const tempPath =
|
|
18631
|
+
const tempPath = join27(tmpdir6(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
18423
18632
|
writeFileSync8(tempPath, JSON.stringify(currentEntry) + `
|
|
18424
18633
|
`);
|
|
18425
18634
|
return tempPath;
|
|
@@ -18635,11 +18844,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
|
|
|
18635
18844
|
init_shared();
|
|
18636
18845
|
|
|
18637
18846
|
// src/hooks/claude-code-hooks/todo.ts
|
|
18638
|
-
import { join as
|
|
18847
|
+
import { join as join28 } from "path";
|
|
18639
18848
|
init_shared();
|
|
18640
|
-
var TODO_DIR =
|
|
18849
|
+
var TODO_DIR = join28(getClaudeConfigDir(), "todos");
|
|
18641
18850
|
function getTodoPath(sessionId) {
|
|
18642
|
-
return
|
|
18851
|
+
return join28(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
|
|
18643
18852
|
}
|
|
18644
18853
|
|
|
18645
18854
|
// src/hooks/claude-code-hooks/stop.ts
|
|
@@ -19087,18 +19296,18 @@ import { relative as relative4, resolve as resolve5 } from "path";
|
|
|
19087
19296
|
|
|
19088
19297
|
// src/hooks/rules-injector/finder.ts
|
|
19089
19298
|
import {
|
|
19090
|
-
existsSync as
|
|
19091
|
-
readdirSync as
|
|
19299
|
+
existsSync as existsSync24,
|
|
19300
|
+
readdirSync as readdirSync7,
|
|
19092
19301
|
realpathSync,
|
|
19093
19302
|
statSync as statSync2
|
|
19094
19303
|
} from "fs";
|
|
19095
|
-
import { dirname as dirname4, join as
|
|
19304
|
+
import { dirname as dirname4, join as join30, relative as relative2 } from "path";
|
|
19096
19305
|
|
|
19097
19306
|
// src/hooks/rules-injector/constants.ts
|
|
19098
19307
|
init_data_path();
|
|
19099
|
-
import { join as
|
|
19308
|
+
import { join as join29 } from "path";
|
|
19100
19309
|
var OPENCODE_STORAGE6 = getOpenCodeStorageDir();
|
|
19101
|
-
var RULES_INJECTOR_STORAGE =
|
|
19310
|
+
var RULES_INJECTOR_STORAGE = join29(OPENCODE_STORAGE6, "rules-injector");
|
|
19102
19311
|
var PROJECT_MARKERS = [
|
|
19103
19312
|
".git",
|
|
19104
19313
|
"pyproject.toml",
|
|
@@ -19139,8 +19348,8 @@ function findProjectRoot(startPath) {
|
|
|
19139
19348
|
}
|
|
19140
19349
|
while (true) {
|
|
19141
19350
|
for (const marker of PROJECT_MARKERS) {
|
|
19142
|
-
const markerPath =
|
|
19143
|
-
if (
|
|
19351
|
+
const markerPath = join30(current, marker);
|
|
19352
|
+
if (existsSync24(markerPath)) {
|
|
19144
19353
|
return current;
|
|
19145
19354
|
}
|
|
19146
19355
|
}
|
|
@@ -19152,12 +19361,12 @@ function findProjectRoot(startPath) {
|
|
|
19152
19361
|
}
|
|
19153
19362
|
}
|
|
19154
19363
|
function findRuleFilesRecursive(dir, results) {
|
|
19155
|
-
if (!
|
|
19364
|
+
if (!existsSync24(dir))
|
|
19156
19365
|
return;
|
|
19157
19366
|
try {
|
|
19158
|
-
const entries =
|
|
19367
|
+
const entries = readdirSync7(dir, { withFileTypes: true });
|
|
19159
19368
|
for (const entry of entries) {
|
|
19160
|
-
const fullPath =
|
|
19369
|
+
const fullPath = join30(dir, entry.name);
|
|
19161
19370
|
if (entry.isDirectory()) {
|
|
19162
19371
|
findRuleFilesRecursive(fullPath, results);
|
|
19163
19372
|
} else if (entry.isFile()) {
|
|
@@ -19182,7 +19391,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
19182
19391
|
let distance = 0;
|
|
19183
19392
|
while (true) {
|
|
19184
19393
|
for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
|
|
19185
|
-
const ruleDir =
|
|
19394
|
+
const ruleDir = join30(currentDir, parent, subdir);
|
|
19186
19395
|
const files = [];
|
|
19187
19396
|
findRuleFilesRecursive(ruleDir, files);
|
|
19188
19397
|
for (const filePath of files) {
|
|
@@ -19208,8 +19417,8 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
19208
19417
|
}
|
|
19209
19418
|
if (projectRoot) {
|
|
19210
19419
|
for (const ruleFile of PROJECT_RULE_FILES) {
|
|
19211
|
-
const filePath =
|
|
19212
|
-
if (
|
|
19420
|
+
const filePath = join30(projectRoot, ruleFile);
|
|
19421
|
+
if (existsSync24(filePath)) {
|
|
19213
19422
|
try {
|
|
19214
19423
|
const stat = statSync2(filePath);
|
|
19215
19424
|
if (stat.isFile()) {
|
|
@@ -19229,7 +19438,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
19229
19438
|
}
|
|
19230
19439
|
}
|
|
19231
19440
|
}
|
|
19232
|
-
const userRuleDir =
|
|
19441
|
+
const userRuleDir = join30(homeDir, USER_RULE_DIR);
|
|
19233
19442
|
const userFiles = [];
|
|
19234
19443
|
findRuleFilesRecursive(userRuleDir, userFiles);
|
|
19235
19444
|
for (const filePath of userFiles) {
|
|
@@ -19418,19 +19627,19 @@ function mergeGlobs(existing, newValue) {
|
|
|
19418
19627
|
|
|
19419
19628
|
// src/hooks/rules-injector/storage.ts
|
|
19420
19629
|
import {
|
|
19421
|
-
existsSync as
|
|
19630
|
+
existsSync as existsSync25,
|
|
19422
19631
|
mkdirSync as mkdirSync8,
|
|
19423
19632
|
readFileSync as readFileSync13,
|
|
19424
19633
|
writeFileSync as writeFileSync9,
|
|
19425
19634
|
unlinkSync as unlinkSync6
|
|
19426
19635
|
} from "fs";
|
|
19427
|
-
import { join as
|
|
19636
|
+
import { join as join31 } from "path";
|
|
19428
19637
|
function getStoragePath3(sessionID) {
|
|
19429
|
-
return
|
|
19638
|
+
return join31(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
19430
19639
|
}
|
|
19431
19640
|
function loadInjectedRules(sessionID) {
|
|
19432
19641
|
const filePath = getStoragePath3(sessionID);
|
|
19433
|
-
if (!
|
|
19642
|
+
if (!existsSync25(filePath))
|
|
19434
19643
|
return { contentHashes: new Set, realPaths: new Set };
|
|
19435
19644
|
try {
|
|
19436
19645
|
const content = readFileSync13(filePath, "utf-8");
|
|
@@ -19444,7 +19653,7 @@ function loadInjectedRules(sessionID) {
|
|
|
19444
19653
|
}
|
|
19445
19654
|
}
|
|
19446
19655
|
function saveInjectedRules(sessionID, data) {
|
|
19447
|
-
if (!
|
|
19656
|
+
if (!existsSync25(RULES_INJECTOR_STORAGE)) {
|
|
19448
19657
|
mkdirSync8(RULES_INJECTOR_STORAGE, { recursive: true });
|
|
19449
19658
|
}
|
|
19450
19659
|
const storageData = {
|
|
@@ -19457,7 +19666,7 @@ function saveInjectedRules(sessionID, data) {
|
|
|
19457
19666
|
}
|
|
19458
19667
|
function clearInjectedRules(sessionID) {
|
|
19459
19668
|
const filePath = getStoragePath3(sessionID);
|
|
19460
|
-
if (
|
|
19669
|
+
if (existsSync25(filePath)) {
|
|
19461
19670
|
unlinkSync6(filePath);
|
|
19462
19671
|
}
|
|
19463
19672
|
}
|
|
@@ -19613,19 +19822,19 @@ init_auto_update_checker();
|
|
|
19613
19822
|
|
|
19614
19823
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
19615
19824
|
import {
|
|
19616
|
-
existsSync as
|
|
19825
|
+
existsSync as existsSync28,
|
|
19617
19826
|
mkdirSync as mkdirSync9,
|
|
19618
19827
|
readFileSync as readFileSync17,
|
|
19619
19828
|
writeFileSync as writeFileSync12,
|
|
19620
19829
|
unlinkSync as unlinkSync7
|
|
19621
19830
|
} from "fs";
|
|
19622
|
-
import { join as
|
|
19831
|
+
import { join as join36 } from "path";
|
|
19623
19832
|
|
|
19624
19833
|
// src/hooks/agent-usage-reminder/constants.ts
|
|
19625
19834
|
init_data_path();
|
|
19626
|
-
import { join as
|
|
19835
|
+
import { join as join35 } from "path";
|
|
19627
19836
|
var OPENCODE_STORAGE7 = getOpenCodeStorageDir();
|
|
19628
|
-
var AGENT_USAGE_REMINDER_STORAGE =
|
|
19837
|
+
var AGENT_USAGE_REMINDER_STORAGE = join35(OPENCODE_STORAGE7, "agent-usage-reminder");
|
|
19629
19838
|
var TARGET_TOOLS = new Set([
|
|
19630
19839
|
"grep",
|
|
19631
19840
|
"safe_grep",
|
|
@@ -19671,11 +19880,11 @@ delegate_task(agent="librarian", prompt="\u67E5\u627E Z \u7684\u6587\u6863")
|
|
|
19671
19880
|
|
|
19672
19881
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
19673
19882
|
function getStoragePath4(sessionID) {
|
|
19674
|
-
return
|
|
19883
|
+
return join36(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
19675
19884
|
}
|
|
19676
19885
|
function loadAgentUsageState(sessionID) {
|
|
19677
19886
|
const filePath = getStoragePath4(sessionID);
|
|
19678
|
-
if (!
|
|
19887
|
+
if (!existsSync28(filePath))
|
|
19679
19888
|
return null;
|
|
19680
19889
|
try {
|
|
19681
19890
|
const content = readFileSync17(filePath, "utf-8");
|
|
@@ -19685,7 +19894,7 @@ function loadAgentUsageState(sessionID) {
|
|
|
19685
19894
|
}
|
|
19686
19895
|
}
|
|
19687
19896
|
function saveAgentUsageState(state2) {
|
|
19688
|
-
if (!
|
|
19897
|
+
if (!existsSync28(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
19689
19898
|
mkdirSync9(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
19690
19899
|
}
|
|
19691
19900
|
const filePath = getStoragePath4(state2.sessionID);
|
|
@@ -19693,7 +19902,7 @@ function saveAgentUsageState(state2) {
|
|
|
19693
19902
|
}
|
|
19694
19903
|
function clearAgentUsageState(sessionID) {
|
|
19695
19904
|
const filePath = getStoragePath4(sessionID);
|
|
19696
|
-
if (
|
|
19905
|
+
if (existsSync28(filePath)) {
|
|
19697
19906
|
unlinkSync7(filePath);
|
|
19698
19907
|
}
|
|
19699
19908
|
}
|
|
@@ -20276,19 +20485,19 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
20276
20485
|
}
|
|
20277
20486
|
// src/hooks/interactive-bash-session/storage.ts
|
|
20278
20487
|
import {
|
|
20279
|
-
existsSync as
|
|
20488
|
+
existsSync as existsSync29,
|
|
20280
20489
|
mkdirSync as mkdirSync10,
|
|
20281
20490
|
readFileSync as readFileSync18,
|
|
20282
20491
|
writeFileSync as writeFileSync13,
|
|
20283
20492
|
unlinkSync as unlinkSync8
|
|
20284
20493
|
} from "fs";
|
|
20285
|
-
import { join as
|
|
20494
|
+
import { join as join38 } from "path";
|
|
20286
20495
|
|
|
20287
20496
|
// src/hooks/interactive-bash-session/constants.ts
|
|
20288
20497
|
init_data_path();
|
|
20289
|
-
import { join as
|
|
20498
|
+
import { join as join37 } from "path";
|
|
20290
20499
|
var OPENCODE_STORAGE8 = getOpenCodeStorageDir();
|
|
20291
|
-
var INTERACTIVE_BASH_SESSION_STORAGE =
|
|
20500
|
+
var INTERACTIVE_BASH_SESSION_STORAGE = join37(OPENCODE_STORAGE8, "interactive-bash-session");
|
|
20292
20501
|
var OMO_SESSION_PREFIX = "omo-";
|
|
20293
20502
|
function buildSessionReminderMessage(sessions) {
|
|
20294
20503
|
if (sessions.length === 0)
|
|
@@ -20300,11 +20509,11 @@ function buildSessionReminderMessage(sessions) {
|
|
|
20300
20509
|
|
|
20301
20510
|
// src/hooks/interactive-bash-session/storage.ts
|
|
20302
20511
|
function getStoragePath5(sessionID) {
|
|
20303
|
-
return
|
|
20512
|
+
return join38(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
|
|
20304
20513
|
}
|
|
20305
20514
|
function loadInteractiveBashSessionState(sessionID) {
|
|
20306
20515
|
const filePath = getStoragePath5(sessionID);
|
|
20307
|
-
if (!
|
|
20516
|
+
if (!existsSync29(filePath))
|
|
20308
20517
|
return null;
|
|
20309
20518
|
try {
|
|
20310
20519
|
const content = readFileSync18(filePath, "utf-8");
|
|
@@ -20319,7 +20528,7 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
20319
20528
|
}
|
|
20320
20529
|
}
|
|
20321
20530
|
function saveInteractiveBashSessionState(state2) {
|
|
20322
|
-
if (!
|
|
20531
|
+
if (!existsSync29(INTERACTIVE_BASH_SESSION_STORAGE)) {
|
|
20323
20532
|
mkdirSync10(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
|
|
20324
20533
|
}
|
|
20325
20534
|
const filePath = getStoragePath5(state2.sessionID);
|
|
@@ -20332,7 +20541,7 @@ function saveInteractiveBashSessionState(state2) {
|
|
|
20332
20541
|
}
|
|
20333
20542
|
function clearInteractiveBashSessionState(sessionID) {
|
|
20334
20543
|
const filePath = getStoragePath5(sessionID);
|
|
20335
|
-
if (
|
|
20544
|
+
if (existsSync29(filePath)) {
|
|
20336
20545
|
unlinkSync8(filePath);
|
|
20337
20546
|
}
|
|
20338
20547
|
}
|
|
@@ -20596,13 +20805,13 @@ function createThinkingBlockValidatorHook() {
|
|
|
20596
20805
|
// src/hooks/ralph-loop/index.ts
|
|
20597
20806
|
init_logger();
|
|
20598
20807
|
init_system_directive();
|
|
20599
|
-
import { existsSync as
|
|
20600
|
-
import { join as
|
|
20808
|
+
import { existsSync as existsSync31, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "fs";
|
|
20809
|
+
import { join as join40 } from "path";
|
|
20601
20810
|
|
|
20602
20811
|
// src/hooks/ralph-loop/storage.ts
|
|
20603
20812
|
init_frontmatter();
|
|
20604
|
-
import { existsSync as
|
|
20605
|
-
import { dirname as dirname6, join as
|
|
20813
|
+
import { existsSync as existsSync30, readFileSync as readFileSync19, writeFileSync as writeFileSync14, unlinkSync as unlinkSync9, mkdirSync as mkdirSync11 } from "fs";
|
|
20814
|
+
import { dirname as dirname6, join as join39 } from "path";
|
|
20606
20815
|
|
|
20607
20816
|
// src/hooks/ralph-loop/constants.ts
|
|
20608
20817
|
var HOOK_NAME3 = "ralph-loop";
|
|
@@ -20612,11 +20821,11 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
20612
20821
|
|
|
20613
20822
|
// src/hooks/ralph-loop/storage.ts
|
|
20614
20823
|
function getStateFilePath(directory, customPath) {
|
|
20615
|
-
return customPath ?
|
|
20824
|
+
return customPath ? join39(directory, customPath) : join39(directory, DEFAULT_STATE_FILE);
|
|
20616
20825
|
}
|
|
20617
20826
|
function readState(directory, customPath) {
|
|
20618
20827
|
const filePath = getStateFilePath(directory, customPath);
|
|
20619
|
-
if (!
|
|
20828
|
+
if (!existsSync30(filePath)) {
|
|
20620
20829
|
return null;
|
|
20621
20830
|
}
|
|
20622
20831
|
try {
|
|
@@ -20654,7 +20863,7 @@ function writeState(directory, state2, customPath) {
|
|
|
20654
20863
|
const filePath = getStateFilePath(directory, customPath);
|
|
20655
20864
|
try {
|
|
20656
20865
|
const dir = dirname6(filePath);
|
|
20657
|
-
if (!
|
|
20866
|
+
if (!existsSync30(dir)) {
|
|
20658
20867
|
mkdirSync11(dir, { recursive: true });
|
|
20659
20868
|
}
|
|
20660
20869
|
const sessionIdLine = state2.session_id ? `session_id: "${state2.session_id}"
|
|
@@ -20679,7 +20888,7 @@ ${state2.prompt}
|
|
|
20679
20888
|
function clearState(directory, customPath) {
|
|
20680
20889
|
const filePath = getStateFilePath(directory, customPath);
|
|
20681
20890
|
try {
|
|
20682
|
-
if (
|
|
20891
|
+
if (existsSync30(filePath)) {
|
|
20683
20892
|
unlinkSync9(filePath);
|
|
20684
20893
|
}
|
|
20685
20894
|
return true;
|
|
@@ -20700,14 +20909,14 @@ function incrementIteration(directory, customPath) {
|
|
|
20700
20909
|
|
|
20701
20910
|
// src/hooks/ralph-loop/index.ts
|
|
20702
20911
|
function getMessageDir4(sessionID) {
|
|
20703
|
-
if (!
|
|
20912
|
+
if (!existsSync31(MESSAGE_STORAGE))
|
|
20704
20913
|
return null;
|
|
20705
|
-
const directPath =
|
|
20706
|
-
if (
|
|
20914
|
+
const directPath = join40(MESSAGE_STORAGE, sessionID);
|
|
20915
|
+
if (existsSync31(directPath))
|
|
20707
20916
|
return directPath;
|
|
20708
|
-
for (const dir of
|
|
20709
|
-
const sessionPath =
|
|
20710
|
-
if (
|
|
20917
|
+
for (const dir of readdirSync8(MESSAGE_STORAGE)) {
|
|
20918
|
+
const sessionPath = join40(MESSAGE_STORAGE, dir, sessionID);
|
|
20919
|
+
if (existsSync31(sessionPath))
|
|
20711
20920
|
return sessionPath;
|
|
20712
20921
|
}
|
|
20713
20922
|
return null;
|
|
@@ -20744,7 +20953,7 @@ function createRalphLoopHook(ctx, options) {
|
|
|
20744
20953
|
if (!transcriptPath)
|
|
20745
20954
|
return false;
|
|
20746
20955
|
try {
|
|
20747
|
-
if (!
|
|
20956
|
+
if (!existsSync31(transcriptPath))
|
|
20748
20957
|
return false;
|
|
20749
20958
|
const content = readFileSync20(transcriptPath, "utf-8");
|
|
20750
20959
|
const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
|
|
@@ -21060,8 +21269,8 @@ function extractPromptText3(parts) {
|
|
|
21060
21269
|
// src/hooks/auto-slash-command/executor.ts
|
|
21061
21270
|
init_shared();
|
|
21062
21271
|
init_file_utils();
|
|
21063
|
-
import { existsSync as
|
|
21064
|
-
import { join as
|
|
21272
|
+
import { existsSync as existsSync33, readdirSync as readdirSync9, readFileSync as readFileSync23 } from "fs";
|
|
21273
|
+
import { join as join42, basename as basename2, dirname as dirname8 } from "path";
|
|
21065
21274
|
// src/features/opencode-skill-loader/loader.ts
|
|
21066
21275
|
init_js_yaml();
|
|
21067
21276
|
init_frontmatter();
|
|
@@ -21069,7 +21278,7 @@ init_file_utils();
|
|
|
21069
21278
|
init_shared();
|
|
21070
21279
|
init_opencode_config_dir();
|
|
21071
21280
|
import { promises as fs9 } from "fs";
|
|
21072
|
-
import { join as
|
|
21281
|
+
import { join as join41, basename } from "path";
|
|
21073
21282
|
function parseSkillMcpConfigFromFrontmatter(content) {
|
|
21074
21283
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
21075
21284
|
if (!frontmatterMatch)
|
|
@@ -21085,7 +21294,7 @@ function parseSkillMcpConfigFromFrontmatter(content) {
|
|
|
21085
21294
|
return;
|
|
21086
21295
|
}
|
|
21087
21296
|
async function loadMcpJsonFromDir(skillDir) {
|
|
21088
|
-
const mcpJsonPath =
|
|
21297
|
+
const mcpJsonPath = join41(skillDir, "mcp.json");
|
|
21089
21298
|
try {
|
|
21090
21299
|
const content = await fs9.readFile(mcpJsonPath, "utf-8");
|
|
21091
21300
|
const parsed = JSON.parse(content);
|
|
@@ -21166,11 +21375,11 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
21166
21375
|
for (const entry of entries) {
|
|
21167
21376
|
if (entry.name.startsWith("."))
|
|
21168
21377
|
continue;
|
|
21169
|
-
const entryPath =
|
|
21378
|
+
const entryPath = join41(skillsDir, entry.name);
|
|
21170
21379
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
21171
21380
|
const resolvedPath = await resolveSymlinkAsync(entryPath);
|
|
21172
21381
|
const dirName = entry.name;
|
|
21173
|
-
const skillMdPath =
|
|
21382
|
+
const skillMdPath = join41(resolvedPath, "SKILL.md");
|
|
21174
21383
|
try {
|
|
21175
21384
|
await fs9.access(skillMdPath);
|
|
21176
21385
|
const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
|
|
@@ -21178,7 +21387,7 @@ async function loadSkillsFromDir(skillsDir, scope) {
|
|
|
21178
21387
|
skills.push(skill);
|
|
21179
21388
|
continue;
|
|
21180
21389
|
} catch {}
|
|
21181
|
-
const namedSkillMdPath =
|
|
21390
|
+
const namedSkillMdPath = join41(resolvedPath, `${dirName}.md`);
|
|
21182
21391
|
try {
|
|
21183
21392
|
await fs9.access(namedSkillMdPath);
|
|
21184
21393
|
const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
|
|
@@ -21206,23 +21415,23 @@ function skillsToRecord(skills) {
|
|
|
21206
21415
|
return result;
|
|
21207
21416
|
}
|
|
21208
21417
|
async function loadUserSkills() {
|
|
21209
|
-
const userSkillsDir =
|
|
21418
|
+
const userSkillsDir = join41(getClaudeConfigDir(), "skills");
|
|
21210
21419
|
const skills = await loadSkillsFromDir(userSkillsDir, "user");
|
|
21211
21420
|
return skillsToRecord(skills);
|
|
21212
21421
|
}
|
|
21213
21422
|
async function loadProjectSkills() {
|
|
21214
|
-
const projectSkillsDir =
|
|
21423
|
+
const projectSkillsDir = join41(process.cwd(), ".claude", "skills");
|
|
21215
21424
|
const skills = await loadSkillsFromDir(projectSkillsDir, "project");
|
|
21216
21425
|
return skillsToRecord(skills);
|
|
21217
21426
|
}
|
|
21218
21427
|
async function loadOpencodeGlobalSkills() {
|
|
21219
21428
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
21220
|
-
const opencodeSkillsDir =
|
|
21429
|
+
const opencodeSkillsDir = join41(configDir, "skills");
|
|
21221
21430
|
const skills = await loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
21222
21431
|
return skillsToRecord(skills);
|
|
21223
21432
|
}
|
|
21224
21433
|
async function loadOpencodeProjectSkills() {
|
|
21225
|
-
const opencodeProjectDir =
|
|
21434
|
+
const opencodeProjectDir = join41(process.cwd(), ".opencode", "skills");
|
|
21226
21435
|
const skills = await loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
21227
21436
|
return skillsToRecord(skills);
|
|
21228
21437
|
}
|
|
@@ -21251,28 +21460,29 @@ async function discoverSkills(options = {}) {
|
|
|
21251
21460
|
return [...opencodeProjectSkills, ...projectSkills, ...opencodeGlobalSkills, ...userSkills];
|
|
21252
21461
|
}
|
|
21253
21462
|
async function discoverUserClaudeSkills() {
|
|
21254
|
-
const userSkillsDir =
|
|
21463
|
+
const userSkillsDir = join41(getClaudeConfigDir(), "skills");
|
|
21255
21464
|
return loadSkillsFromDir(userSkillsDir, "user");
|
|
21256
21465
|
}
|
|
21257
21466
|
async function discoverProjectClaudeSkills() {
|
|
21258
|
-
const projectSkillsDir =
|
|
21467
|
+
const projectSkillsDir = join41(process.cwd(), ".claude", "skills");
|
|
21259
21468
|
return loadSkillsFromDir(projectSkillsDir, "project");
|
|
21260
21469
|
}
|
|
21261
21470
|
async function discoverOpencodeGlobalSkills() {
|
|
21262
21471
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
21263
|
-
const opencodeSkillsDir =
|
|
21472
|
+
const opencodeSkillsDir = join41(configDir, "skills");
|
|
21264
21473
|
return loadSkillsFromDir(opencodeSkillsDir, "opencode");
|
|
21265
21474
|
}
|
|
21266
21475
|
async function discoverOpencodeProjectSkills() {
|
|
21267
|
-
const opencodeProjectDir =
|
|
21476
|
+
const opencodeProjectDir = join41(process.cwd(), ".opencode", "skills");
|
|
21268
21477
|
return loadSkillsFromDir(opencodeProjectDir, "opencode-project");
|
|
21269
21478
|
}
|
|
21270
21479
|
// src/features/opencode-skill-loader/merger.ts
|
|
21271
21480
|
init_frontmatter();
|
|
21272
21481
|
init_deep_merge();
|
|
21273
|
-
import { readFileSync as readFileSync21, existsSync as
|
|
21482
|
+
import { readFileSync as readFileSync21, existsSync as existsSync32 } from "fs";
|
|
21274
21483
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
21275
21484
|
import { homedir as homedir11 } from "os";
|
|
21485
|
+
import { createHash as createHash2 } from "crypto";
|
|
21276
21486
|
var SCOPE_PRIORITY = {
|
|
21277
21487
|
builtin: 1,
|
|
21278
21488
|
config: 2,
|
|
@@ -21318,7 +21528,7 @@ function resolveFilePath2(from, configDir) {
|
|
|
21318
21528
|
}
|
|
21319
21529
|
function loadSkillFromFile(filePath) {
|
|
21320
21530
|
try {
|
|
21321
|
-
if (!
|
|
21531
|
+
if (!existsSync32(filePath))
|
|
21322
21532
|
return null;
|
|
21323
21533
|
const content = readFileSync21(filePath, "utf-8");
|
|
21324
21534
|
const { data, body } = parseFrontmatter(content);
|
|
@@ -21407,13 +21617,28 @@ function mergeSkillDefinitions(base, patch) {
|
|
|
21407
21617
|
allowedTools: mergedTools ? [...new Set(mergedTools)] : undefined
|
|
21408
21618
|
};
|
|
21409
21619
|
}
|
|
21620
|
+
function contentHash(content) {
|
|
21621
|
+
return createHash2("md5").update(content).digest("hex").slice(0, 8);
|
|
21622
|
+
}
|
|
21623
|
+
function emptyDedupStats() {
|
|
21624
|
+
return { totalScanned: 0, unique: 0, skippedByScope: 0, skippedByContent: 0, byScope: {} };
|
|
21625
|
+
}
|
|
21410
21626
|
function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills, projectClaudeSkills, projectOpencodeSkills, options = {}) {
|
|
21411
21627
|
const skillMap = new Map;
|
|
21628
|
+
const contentHashes = new Map;
|
|
21629
|
+
const stats = emptyDedupStats();
|
|
21412
21630
|
for (const builtin of builtinSkills) {
|
|
21413
21631
|
const loaded = builtinToLoaded(builtin);
|
|
21414
21632
|
skillMap.set(loaded.name, loaded);
|
|
21633
|
+
stats.byScope["builtin"] = (stats.byScope["builtin"] ?? 0) + 1;
|
|
21634
|
+
stats.unique++;
|
|
21635
|
+
if (loaded.definition.template) {
|
|
21636
|
+
contentHashes.set(loaded.name, contentHash(loaded.definition.template));
|
|
21637
|
+
}
|
|
21415
21638
|
}
|
|
21639
|
+
stats.totalScanned += builtinSkills.length;
|
|
21416
21640
|
const normalizedConfig = normalizeConfig(config);
|
|
21641
|
+
let configLoaded = 0;
|
|
21417
21642
|
for (const [name, entry] of Object.entries(normalizedConfig.entries)) {
|
|
21418
21643
|
if (entry === false)
|
|
21419
21644
|
continue;
|
|
@@ -21428,9 +21653,18 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
21428
21653
|
skillMap.set(name, mergeSkillDefinitions(existing, entry));
|
|
21429
21654
|
} else {
|
|
21430
21655
|
skillMap.set(name, loaded);
|
|
21656
|
+
configLoaded++;
|
|
21657
|
+
stats.unique++;
|
|
21658
|
+
if (loaded.definition.template) {
|
|
21659
|
+
contentHashes.set(name, contentHash(loaded.definition.template));
|
|
21660
|
+
}
|
|
21431
21661
|
}
|
|
21432
21662
|
}
|
|
21433
21663
|
}
|
|
21664
|
+
if (configLoaded > 0) {
|
|
21665
|
+
stats.byScope["config"] = configLoaded;
|
|
21666
|
+
stats.totalScanned += configLoaded;
|
|
21667
|
+
}
|
|
21434
21668
|
const fileSystemSkills = [
|
|
21435
21669
|
...userClaudeSkills,
|
|
21436
21670
|
...userOpencodeSkills,
|
|
@@ -21438,10 +21672,30 @@ function mergeSkills(builtinSkills, config, userClaudeSkills, userOpencodeSkills
|
|
|
21438
21672
|
...projectOpencodeSkills
|
|
21439
21673
|
];
|
|
21440
21674
|
for (const skill of fileSystemSkills) {
|
|
21675
|
+
stats.totalScanned++;
|
|
21676
|
+
stats.byScope[skill.scope] = (stats.byScope[skill.scope] ?? 0) + 1;
|
|
21441
21677
|
const existing = skillMap.get(skill.name);
|
|
21442
|
-
|
|
21443
|
-
|
|
21678
|
+
const hash = skill.definition.template ? contentHash(skill.definition.template) : undefined;
|
|
21679
|
+
if (existing) {
|
|
21680
|
+
const existingHash = contentHashes.get(skill.name);
|
|
21681
|
+
if (hash && existingHash && hash === existingHash) {
|
|
21682
|
+
stats.skippedByContent++;
|
|
21683
|
+
continue;
|
|
21684
|
+
}
|
|
21685
|
+
if (SCOPE_PRIORITY[skill.scope] <= SCOPE_PRIORITY[existing.scope]) {
|
|
21686
|
+
stats.skippedByScope++;
|
|
21687
|
+
continue;
|
|
21688
|
+
}
|
|
21689
|
+
}
|
|
21690
|
+
skillMap.set(skill.name, skill);
|
|
21691
|
+
if (hash) {
|
|
21692
|
+
contentHashes.set(skill.name, hash);
|
|
21444
21693
|
}
|
|
21694
|
+
stats.unique++;
|
|
21695
|
+
}
|
|
21696
|
+
if (stats.skippedByContent > 0 || stats.skippedByScope > 1) {
|
|
21697
|
+
const scopeSummary = Object.entries(stats.byScope).map(([scope, count]) => `${scope}:${count}`).join(", ");
|
|
21698
|
+
console.debug(`[skill-loader] Scanned ${stats.totalScanned} skills (${scopeSummary}), ` + `${stats.unique} loaded, ` + `${stats.skippedByContent} skipped (identical content), ` + `${stats.skippedByScope} skipped (lower priority scope)`);
|
|
21445
21699
|
}
|
|
21446
21700
|
for (const [name, entry] of Object.entries(normalizedConfig.entries)) {
|
|
21447
21701
|
if (entry === true)
|
|
@@ -22802,15 +23056,15 @@ async function resolveMultipleSkillsAsync(skillNames, options) {
|
|
|
22802
23056
|
}
|
|
22803
23057
|
// src/hooks/auto-slash-command/executor.ts
|
|
22804
23058
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
22805
|
-
if (!
|
|
23059
|
+
if (!existsSync33(commandsDir)) {
|
|
22806
23060
|
return [];
|
|
22807
23061
|
}
|
|
22808
|
-
const entries =
|
|
23062
|
+
const entries = readdirSync9(commandsDir, { withFileTypes: true });
|
|
22809
23063
|
const commands = [];
|
|
22810
23064
|
for (const entry of entries) {
|
|
22811
23065
|
if (!isMarkdownFile(entry))
|
|
22812
23066
|
continue;
|
|
22813
|
-
const commandPath =
|
|
23067
|
+
const commandPath = join42(commandsDir, entry.name);
|
|
22814
23068
|
const commandName = basename2(entry.name, ".md");
|
|
22815
23069
|
try {
|
|
22816
23070
|
const content = readFileSync23(commandPath, "utf-8");
|
|
@@ -22856,10 +23110,10 @@ function skillToCommandInfo(skill) {
|
|
|
22856
23110
|
}
|
|
22857
23111
|
async function discoverAllCommands(options) {
|
|
22858
23112
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
22859
|
-
const userCommandsDir =
|
|
22860
|
-
const projectCommandsDir =
|
|
22861
|
-
const opencodeGlobalDir =
|
|
22862
|
-
const opencodeProjectDir =
|
|
23113
|
+
const userCommandsDir = join42(getClaudeConfigDir(), "commands");
|
|
23114
|
+
const projectCommandsDir = join42(process.cwd(), ".claude", "commands");
|
|
23115
|
+
const opencodeGlobalDir = join42(configDir, "command");
|
|
23116
|
+
const opencodeProjectDir = join42(process.cwd(), ".opencode", "command");
|
|
22863
23117
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
22864
23118
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
22865
23119
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -23029,8 +23283,8 @@ ${EDIT_ERROR_REMINDER}`;
|
|
|
23029
23283
|
};
|
|
23030
23284
|
}
|
|
23031
23285
|
// src/hooks/prometheus-md-only/index.ts
|
|
23032
|
-
import { existsSync as
|
|
23033
|
-
import { join as
|
|
23286
|
+
import { existsSync as existsSync34, readdirSync as readdirSync10 } from "fs";
|
|
23287
|
+
import { join as join43, resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3 } from "path";
|
|
23034
23288
|
|
|
23035
23289
|
// src/hooks/prometheus-md-only/constants.ts
|
|
23036
23290
|
init_system_directive();
|
|
@@ -23149,14 +23403,14 @@ function isAllowedFile(filePath, workspaceRoot) {
|
|
|
23149
23403
|
return true;
|
|
23150
23404
|
}
|
|
23151
23405
|
function getMessageDir5(sessionID) {
|
|
23152
|
-
if (!
|
|
23406
|
+
if (!existsSync34(MESSAGE_STORAGE))
|
|
23153
23407
|
return null;
|
|
23154
|
-
const directPath =
|
|
23155
|
-
if (
|
|
23408
|
+
const directPath = join43(MESSAGE_STORAGE, sessionID);
|
|
23409
|
+
if (existsSync34(directPath))
|
|
23156
23410
|
return directPath;
|
|
23157
|
-
for (const dir of
|
|
23158
|
-
const sessionPath =
|
|
23159
|
-
if (
|
|
23411
|
+
for (const dir of readdirSync10(MESSAGE_STORAGE)) {
|
|
23412
|
+
const sessionPath = join43(MESSAGE_STORAGE, dir, sessionID);
|
|
23413
|
+
if (existsSync34(sessionPath))
|
|
23160
23414
|
return sessionPath;
|
|
23161
23415
|
}
|
|
23162
23416
|
return null;
|
|
@@ -23270,14 +23524,14 @@ var NOTEPAD_DIR = "notepads";
|
|
|
23270
23524
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
23271
23525
|
var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
|
|
23272
23526
|
// src/features/boulder-state/storage.ts
|
|
23273
|
-
import { existsSync as
|
|
23274
|
-
import { dirname as dirname9, join as
|
|
23527
|
+
import { existsSync as existsSync35, readFileSync as readFileSync24, writeFileSync as writeFileSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync11 } from "fs";
|
|
23528
|
+
import { dirname as dirname9, join as join44, basename as basename3 } from "path";
|
|
23275
23529
|
function getBoulderFilePath(directory) {
|
|
23276
|
-
return
|
|
23530
|
+
return join44(directory, BOULDER_DIR, BOULDER_FILE);
|
|
23277
23531
|
}
|
|
23278
23532
|
function readBoulderState(directory) {
|
|
23279
23533
|
const filePath = getBoulderFilePath(directory);
|
|
23280
|
-
if (!
|
|
23534
|
+
if (!existsSync35(filePath)) {
|
|
23281
23535
|
return null;
|
|
23282
23536
|
}
|
|
23283
23537
|
try {
|
|
@@ -23291,7 +23545,7 @@ function writeBoulderState(directory, state2) {
|
|
|
23291
23545
|
const filePath = getBoulderFilePath(directory);
|
|
23292
23546
|
try {
|
|
23293
23547
|
const dir = dirname9(filePath);
|
|
23294
|
-
if (!
|
|
23548
|
+
if (!existsSync35(dir)) {
|
|
23295
23549
|
mkdirSync12(dir, { recursive: true });
|
|
23296
23550
|
}
|
|
23297
23551
|
writeFileSync15(filePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
@@ -23315,7 +23569,7 @@ function appendSessionId(directory, sessionId) {
|
|
|
23315
23569
|
function clearBoulderState(directory) {
|
|
23316
23570
|
const filePath = getBoulderFilePath(directory);
|
|
23317
23571
|
try {
|
|
23318
|
-
if (
|
|
23572
|
+
if (existsSync35(filePath)) {
|
|
23319
23573
|
const { unlinkSync: unlinkSync10 } = __require("fs");
|
|
23320
23574
|
unlinkSync10(filePath);
|
|
23321
23575
|
}
|
|
@@ -23325,13 +23579,13 @@ function clearBoulderState(directory) {
|
|
|
23325
23579
|
}
|
|
23326
23580
|
}
|
|
23327
23581
|
function findPrometheusPlans(directory) {
|
|
23328
|
-
const plansDir =
|
|
23329
|
-
if (!
|
|
23582
|
+
const plansDir = join44(directory, PROMETHEUS_PLANS_DIR);
|
|
23583
|
+
if (!existsSync35(plansDir)) {
|
|
23330
23584
|
return [];
|
|
23331
23585
|
}
|
|
23332
23586
|
try {
|
|
23333
|
-
const files =
|
|
23334
|
-
return files.filter((f) => f.endsWith(".md")).map((f) =>
|
|
23587
|
+
const files = readdirSync11(plansDir);
|
|
23588
|
+
return files.filter((f) => f.endsWith(".md")).map((f) => join44(plansDir, f)).sort((a, b) => {
|
|
23335
23589
|
const aStat = __require("fs").statSync(a);
|
|
23336
23590
|
const bStat = __require("fs").statSync(b);
|
|
23337
23591
|
return bStat.mtimeMs - aStat.mtimeMs;
|
|
@@ -23341,7 +23595,7 @@ function findPrometheusPlans(directory) {
|
|
|
23341
23595
|
}
|
|
23342
23596
|
}
|
|
23343
23597
|
function getPlanProgress(planPath) {
|
|
23344
|
-
if (!
|
|
23598
|
+
if (!existsSync35(planPath)) {
|
|
23345
23599
|
return { total: 0, completed: 0, isComplete: true };
|
|
23346
23600
|
}
|
|
23347
23601
|
try {
|
|
@@ -23562,8 +23816,8 @@ ${contextInfo}`;
|
|
|
23562
23816
|
}
|
|
23563
23817
|
// src/hooks/atlas/index.ts
|
|
23564
23818
|
import { execSync } from "child_process";
|
|
23565
|
-
import { existsSync as
|
|
23566
|
-
import { join as
|
|
23819
|
+
import { existsSync as existsSync36, readdirSync as readdirSync12 } from "fs";
|
|
23820
|
+
import { join as join45 } from "path";
|
|
23567
23821
|
init_logger();
|
|
23568
23822
|
init_system_directive();
|
|
23569
23823
|
var HOOK_NAME6 = "atlas";
|
|
@@ -23892,14 +24146,14 @@ function formatFileChanges(stats, notepadPath) {
|
|
|
23892
24146
|
`);
|
|
23893
24147
|
}
|
|
23894
24148
|
function getMessageDir6(sessionID) {
|
|
23895
|
-
if (!
|
|
24149
|
+
if (!existsSync36(MESSAGE_STORAGE))
|
|
23896
24150
|
return null;
|
|
23897
|
-
const directPath =
|
|
23898
|
-
if (
|
|
24151
|
+
const directPath = join45(MESSAGE_STORAGE, sessionID);
|
|
24152
|
+
if (existsSync36(directPath))
|
|
23899
24153
|
return directPath;
|
|
23900
|
-
for (const dir of
|
|
23901
|
-
const sessionPath =
|
|
23902
|
-
if (
|
|
24154
|
+
for (const dir of readdirSync12(MESSAGE_STORAGE)) {
|
|
24155
|
+
const sessionPath = join45(MESSAGE_STORAGE, dir, sessionID);
|
|
24156
|
+
if (existsSync36(sessionPath))
|
|
23903
24157
|
return sessionPath;
|
|
23904
24158
|
}
|
|
23905
24159
|
return null;
|
|
@@ -24253,7 +24507,7 @@ var DELEGATE_TASK_ERROR_PATTERNS = [
|
|
|
24253
24507
|
}
|
|
24254
24508
|
];
|
|
24255
24509
|
function detectDelegateTaskError(output) {
|
|
24256
|
-
if (!output.includes("[ERROR]") && !output.includes("Invalid arguments"))
|
|
24510
|
+
if (!output.includes("[ERROR]") && !output.includes("Invalid arguments") && !output.includes("\u53C2\u6570\u9519\u8BEF\uFF1A"))
|
|
24257
24511
|
return null;
|
|
24258
24512
|
for (const errorPattern of DELEGATE_TASK_ERROR_PATTERNS) {
|
|
24259
24513
|
if (output.includes(errorPattern.pattern)) {
|
|
@@ -24548,8 +24802,8 @@ function createFirstMessageVariantGate() {
|
|
|
24548
24802
|
}
|
|
24549
24803
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
24550
24804
|
init_shared();
|
|
24551
|
-
import { existsSync as
|
|
24552
|
-
import { join as
|
|
24805
|
+
import { existsSync as existsSync37, readFileSync as readFileSync25 } from "fs";
|
|
24806
|
+
import { join as join46 } from "path";
|
|
24553
24807
|
|
|
24554
24808
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
24555
24809
|
function expandEnvVars(value) {
|
|
@@ -24619,13 +24873,13 @@ function getMcpConfigPaths() {
|
|
|
24619
24873
|
const claudeConfigDir = getClaudeConfigDir();
|
|
24620
24874
|
const cwd2 = process.cwd();
|
|
24621
24875
|
return [
|
|
24622
|
-
{ path:
|
|
24623
|
-
{ path:
|
|
24624
|
-
{ path:
|
|
24876
|
+
{ path: join46(claudeConfigDir, ".mcp.json"), scope: "user" },
|
|
24877
|
+
{ path: join46(cwd2, ".mcp.json"), scope: "project" },
|
|
24878
|
+
{ path: join46(cwd2, ".claude", ".mcp.json"), scope: "local" }
|
|
24625
24879
|
];
|
|
24626
24880
|
}
|
|
24627
24881
|
async function loadMcpConfigFile(filePath) {
|
|
24628
|
-
if (!
|
|
24882
|
+
if (!existsSync37(filePath)) {
|
|
24629
24883
|
return null;
|
|
24630
24884
|
}
|
|
24631
24885
|
try {
|
|
@@ -24640,7 +24894,7 @@ function getSystemMcpServerNames() {
|
|
|
24640
24894
|
const names = new Set;
|
|
24641
24895
|
const paths = getMcpConfigPaths();
|
|
24642
24896
|
for (const { path: path7 } of paths) {
|
|
24643
|
-
if (!
|
|
24897
|
+
if (!existsSync37(path7))
|
|
24644
24898
|
continue;
|
|
24645
24899
|
try {
|
|
24646
24900
|
const content = readFileSync25(path7, "utf-8");
|
|
@@ -25086,11 +25340,11 @@ var EXT_TO_LANG = {
|
|
|
25086
25340
|
".gql": "graphql"
|
|
25087
25341
|
};
|
|
25088
25342
|
// src/tools/lsp/config.ts
|
|
25089
|
-
import { existsSync as
|
|
25090
|
-
import { join as
|
|
25343
|
+
import { existsSync as existsSync38, readFileSync as readFileSync26 } from "fs";
|
|
25344
|
+
import { join as join47 } from "path";
|
|
25091
25345
|
init_shared();
|
|
25092
25346
|
function loadJsonFile(path7) {
|
|
25093
|
-
if (!
|
|
25347
|
+
if (!existsSync38(path7))
|
|
25094
25348
|
return null;
|
|
25095
25349
|
try {
|
|
25096
25350
|
return JSON.parse(readFileSync26(path7, "utf-8"));
|
|
@@ -25102,9 +25356,9 @@ function getConfigPaths3() {
|
|
|
25102
25356
|
const cwd2 = process.cwd();
|
|
25103
25357
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
25104
25358
|
return {
|
|
25105
|
-
project:
|
|
25106
|
-
user:
|
|
25107
|
-
opencode:
|
|
25359
|
+
project: join47(cwd2, ".opencode", "oh-my-opencode.json"),
|
|
25360
|
+
user: join47(configDir, "oh-my-opencode.json"),
|
|
25361
|
+
opencode: join47(configDir, "opencode.json")
|
|
25108
25362
|
};
|
|
25109
25363
|
}
|
|
25110
25364
|
function loadAllConfigs() {
|
|
@@ -25217,7 +25471,7 @@ function isServerInstalled(command) {
|
|
|
25217
25471
|
return false;
|
|
25218
25472
|
const cmd = command[0];
|
|
25219
25473
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
25220
|
-
if (
|
|
25474
|
+
if (existsSync38(cmd))
|
|
25221
25475
|
return true;
|
|
25222
25476
|
}
|
|
25223
25477
|
const isWindows2 = process.platform === "win32";
|
|
@@ -25239,23 +25493,23 @@ function isServerInstalled(command) {
|
|
|
25239
25493
|
const paths = pathEnv.split(pathSeparator);
|
|
25240
25494
|
for (const p of paths) {
|
|
25241
25495
|
for (const suffix of exts) {
|
|
25242
|
-
if (
|
|
25496
|
+
if (existsSync38(join47(p, cmd + suffix))) {
|
|
25243
25497
|
return true;
|
|
25244
25498
|
}
|
|
25245
25499
|
}
|
|
25246
25500
|
}
|
|
25247
25501
|
const cwd2 = process.cwd();
|
|
25248
25502
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
25249
|
-
const dataDir =
|
|
25503
|
+
const dataDir = join47(getDataDir(), "opencode");
|
|
25250
25504
|
const additionalBases = [
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25254
|
-
|
|
25505
|
+
join47(cwd2, "node_modules", ".bin"),
|
|
25506
|
+
join47(configDir, "bin"),
|
|
25507
|
+
join47(configDir, "node_modules", ".bin"),
|
|
25508
|
+
join47(dataDir, "bin")
|
|
25255
25509
|
];
|
|
25256
25510
|
for (const base of additionalBases) {
|
|
25257
25511
|
for (const suffix of exts) {
|
|
25258
|
-
if (
|
|
25512
|
+
if (existsSync38(join47(base, cmd + suffix))) {
|
|
25259
25513
|
return true;
|
|
25260
25514
|
}
|
|
25261
25515
|
}
|
|
@@ -25807,17 +26061,17 @@ ${msg}`);
|
|
|
25807
26061
|
// src/tools/lsp/utils.ts
|
|
25808
26062
|
import { extname as extname2, resolve as resolve9 } from "path";
|
|
25809
26063
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25810
|
-
import { existsSync as
|
|
26064
|
+
import { existsSync as existsSync39, readFileSync as readFileSync28, writeFileSync as writeFileSync16 } from "fs";
|
|
25811
26065
|
function findWorkspaceRoot(filePath) {
|
|
25812
26066
|
let dir = resolve9(filePath);
|
|
25813
|
-
if (!
|
|
26067
|
+
if (!existsSync39(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
25814
26068
|
dir = __require("path").dirname(dir);
|
|
25815
26069
|
}
|
|
25816
26070
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
25817
26071
|
let prevDir = "";
|
|
25818
26072
|
while (dir !== prevDir) {
|
|
25819
26073
|
for (const marker of markers) {
|
|
25820
|
-
if (
|
|
26074
|
+
if (existsSync39(__require("path").join(dir, marker))) {
|
|
25821
26075
|
return dir;
|
|
25822
26076
|
}
|
|
25823
26077
|
}
|
|
@@ -38618,13 +38872,13 @@ var lsp_rename = tool({
|
|
|
38618
38872
|
});
|
|
38619
38873
|
// src/tools/ast-grep/constants.ts
|
|
38620
38874
|
import { createRequire as createRequire4 } from "module";
|
|
38621
|
-
import { dirname as dirname10, join as
|
|
38622
|
-
import { existsSync as
|
|
38875
|
+
import { dirname as dirname10, join as join49 } from "path";
|
|
38876
|
+
import { existsSync as existsSync41, statSync as statSync4 } from "fs";
|
|
38623
38877
|
|
|
38624
38878
|
// src/tools/ast-grep/downloader.ts
|
|
38625
38879
|
init_shared();
|
|
38626
|
-
import { existsSync as
|
|
38627
|
-
import { join as
|
|
38880
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync13, chmodSync as chmodSync2, unlinkSync as unlinkSync10 } from "fs";
|
|
38881
|
+
import { join as join48 } from "path";
|
|
38628
38882
|
import { homedir as homedir12 } from "os";
|
|
38629
38883
|
import { createRequire as createRequire3 } from "module";
|
|
38630
38884
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -38650,19 +38904,19 @@ var PLATFORM_MAP2 = {
|
|
|
38650
38904
|
function getCacheDir3() {
|
|
38651
38905
|
if (process.platform === "win32") {
|
|
38652
38906
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
38653
|
-
const base2 = localAppData ||
|
|
38654
|
-
return
|
|
38907
|
+
const base2 = localAppData || join48(homedir12(), "AppData", "Local");
|
|
38908
|
+
return join48(base2, "oh-my-opencode", "bin");
|
|
38655
38909
|
}
|
|
38656
38910
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
38657
|
-
const base = xdgCache ||
|
|
38658
|
-
return
|
|
38911
|
+
const base = xdgCache || join48(homedir12(), ".cache");
|
|
38912
|
+
return join48(base, "oh-my-opencode", "bin");
|
|
38659
38913
|
}
|
|
38660
38914
|
function getBinaryName3() {
|
|
38661
38915
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
38662
38916
|
}
|
|
38663
38917
|
function getCachedBinaryPath2() {
|
|
38664
|
-
const binaryPath =
|
|
38665
|
-
return
|
|
38918
|
+
const binaryPath = join48(getCacheDir3(), getBinaryName3());
|
|
38919
|
+
return existsSync40(binaryPath) ? binaryPath : null;
|
|
38666
38920
|
}
|
|
38667
38921
|
async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
38668
38922
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
@@ -38673,8 +38927,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
38673
38927
|
}
|
|
38674
38928
|
const cacheDir = getCacheDir3();
|
|
38675
38929
|
const binaryName = getBinaryName3();
|
|
38676
|
-
const binaryPath =
|
|
38677
|
-
if (
|
|
38930
|
+
const binaryPath = join48(cacheDir, binaryName);
|
|
38931
|
+
if (existsSync40(binaryPath)) {
|
|
38678
38932
|
return binaryPath;
|
|
38679
38933
|
}
|
|
38680
38934
|
const { arch, os: os6 } = platformInfo;
|
|
@@ -38682,21 +38936,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
38682
38936
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
38683
38937
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
38684
38938
|
try {
|
|
38685
|
-
if (!
|
|
38939
|
+
if (!existsSync40(cacheDir)) {
|
|
38686
38940
|
mkdirSync13(cacheDir, { recursive: true });
|
|
38687
38941
|
}
|
|
38688
38942
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
38689
38943
|
if (!response.ok) {
|
|
38690
38944
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
38691
38945
|
}
|
|
38692
|
-
const archivePath =
|
|
38946
|
+
const archivePath = join48(cacheDir, assetName);
|
|
38693
38947
|
const arrayBuffer = await response.arrayBuffer();
|
|
38694
38948
|
await Bun.write(archivePath, arrayBuffer);
|
|
38695
38949
|
await extractZip(archivePath, cacheDir);
|
|
38696
|
-
if (
|
|
38950
|
+
if (existsSync40(archivePath)) {
|
|
38697
38951
|
unlinkSync10(archivePath);
|
|
38698
38952
|
}
|
|
38699
|
-
if (process.platform !== "win32" &&
|
|
38953
|
+
if (process.platform !== "win32" && existsSync40(binaryPath)) {
|
|
38700
38954
|
chmodSync2(binaryPath, 493);
|
|
38701
38955
|
}
|
|
38702
38956
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -38747,8 +39001,8 @@ function findSgCliPathSync() {
|
|
|
38747
39001
|
const require2 = createRequire4(import.meta.url);
|
|
38748
39002
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
38749
39003
|
const cliDir = dirname10(cliPkgPath);
|
|
38750
|
-
const sgPath =
|
|
38751
|
-
if (
|
|
39004
|
+
const sgPath = join49(cliDir, binaryName);
|
|
39005
|
+
if (existsSync41(sgPath) && isValidBinary(sgPath)) {
|
|
38752
39006
|
return sgPath;
|
|
38753
39007
|
}
|
|
38754
39008
|
} catch {}
|
|
@@ -38759,8 +39013,8 @@ function findSgCliPathSync() {
|
|
|
38759
39013
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
38760
39014
|
const pkgDir = dirname10(pkgPath);
|
|
38761
39015
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
38762
|
-
const binaryPath =
|
|
38763
|
-
if (
|
|
39016
|
+
const binaryPath = join49(pkgDir, astGrepName);
|
|
39017
|
+
if (existsSync41(binaryPath) && isValidBinary(binaryPath)) {
|
|
38764
39018
|
return binaryPath;
|
|
38765
39019
|
}
|
|
38766
39020
|
} catch {}
|
|
@@ -38768,7 +39022,7 @@ function findSgCliPathSync() {
|
|
|
38768
39022
|
if (process.platform === "darwin") {
|
|
38769
39023
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
38770
39024
|
for (const path7 of homebrewPaths) {
|
|
38771
|
-
if (
|
|
39025
|
+
if (existsSync41(path7) && isValidBinary(path7)) {
|
|
38772
39026
|
return path7;
|
|
38773
39027
|
}
|
|
38774
39028
|
}
|
|
@@ -38823,11 +39077,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
38823
39077
|
|
|
38824
39078
|
// src/tools/ast-grep/cli.ts
|
|
38825
39079
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
38826
|
-
import { existsSync as
|
|
39080
|
+
import { existsSync as existsSync42 } from "fs";
|
|
38827
39081
|
var resolvedCliPath3 = null;
|
|
38828
39082
|
var initPromise2 = null;
|
|
38829
39083
|
async function getAstGrepPath() {
|
|
38830
|
-
if (resolvedCliPath3 !== null &&
|
|
39084
|
+
if (resolvedCliPath3 !== null && existsSync42(resolvedCliPath3)) {
|
|
38831
39085
|
return resolvedCliPath3;
|
|
38832
39086
|
}
|
|
38833
39087
|
if (initPromise2) {
|
|
@@ -38835,7 +39089,7 @@ async function getAstGrepPath() {
|
|
|
38835
39089
|
}
|
|
38836
39090
|
initPromise2 = (async () => {
|
|
38837
39091
|
const syncPath = findSgCliPathSync();
|
|
38838
|
-
if (syncPath &&
|
|
39092
|
+
if (syncPath && existsSync42(syncPath)) {
|
|
38839
39093
|
resolvedCliPath3 = syncPath;
|
|
38840
39094
|
setSgCliPath(syncPath);
|
|
38841
39095
|
return syncPath;
|
|
@@ -38869,7 +39123,7 @@ async function runSg(options) {
|
|
|
38869
39123
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
38870
39124
|
args.push(...paths);
|
|
38871
39125
|
let cliPath = getSgCliPath();
|
|
38872
|
-
if (!
|
|
39126
|
+
if (!existsSync42(cliPath) && cliPath !== "sg") {
|
|
38873
39127
|
const downloadedPath = await getAstGrepPath();
|
|
38874
39128
|
if (downloadedPath) {
|
|
38875
39129
|
cliPath = downloadedPath;
|
|
@@ -39133,21 +39387,21 @@ var ast_grep_replace = tool({
|
|
|
39133
39387
|
var {spawn: spawn9 } = globalThis.Bun;
|
|
39134
39388
|
|
|
39135
39389
|
// src/tools/grep/constants.ts
|
|
39136
|
-
import { existsSync as
|
|
39137
|
-
import { join as
|
|
39390
|
+
import { existsSync as existsSync44 } from "fs";
|
|
39391
|
+
import { join as join51, dirname as dirname11 } from "path";
|
|
39138
39392
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
39139
39393
|
|
|
39140
39394
|
// src/tools/grep/downloader.ts
|
|
39141
39395
|
init_shared();
|
|
39142
|
-
import { existsSync as
|
|
39143
|
-
import { join as
|
|
39396
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync14, chmodSync as chmodSync3, unlinkSync as unlinkSync11, readdirSync as readdirSync13 } from "fs";
|
|
39397
|
+
import { join as join50 } from "path";
|
|
39144
39398
|
var {spawn: spawn8 } = globalThis.Bun;
|
|
39145
39399
|
function findFileRecursive(dir, filename) {
|
|
39146
39400
|
try {
|
|
39147
|
-
const entries =
|
|
39401
|
+
const entries = readdirSync13(dir, { withFileTypes: true, recursive: true });
|
|
39148
39402
|
for (const entry of entries) {
|
|
39149
39403
|
if (entry.isFile() && entry.name === filename) {
|
|
39150
|
-
return
|
|
39404
|
+
return join50(entry.parentPath ?? dir, entry.name);
|
|
39151
39405
|
}
|
|
39152
39406
|
}
|
|
39153
39407
|
} catch {
|
|
@@ -39168,11 +39422,11 @@ function getPlatformKey() {
|
|
|
39168
39422
|
}
|
|
39169
39423
|
function getInstallDir() {
|
|
39170
39424
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
39171
|
-
return
|
|
39425
|
+
return join50(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
39172
39426
|
}
|
|
39173
39427
|
function getRgPath() {
|
|
39174
39428
|
const isWindows2 = process.platform === "win32";
|
|
39175
|
-
return
|
|
39429
|
+
return join50(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
39176
39430
|
}
|
|
39177
39431
|
async function downloadFile(url2, destPath) {
|
|
39178
39432
|
const response = await fetch(url2);
|
|
@@ -39206,7 +39460,7 @@ async function extractZip2(archivePath, destDir) {
|
|
|
39206
39460
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
39207
39461
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
39208
39462
|
if (foundPath) {
|
|
39209
|
-
const destPath =
|
|
39463
|
+
const destPath = join50(destDir, binaryName);
|
|
39210
39464
|
if (foundPath !== destPath) {
|
|
39211
39465
|
const { renameSync } = await import("fs");
|
|
39212
39466
|
renameSync(foundPath, destPath);
|
|
@@ -39221,13 +39475,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
39221
39475
|
}
|
|
39222
39476
|
const installDir = getInstallDir();
|
|
39223
39477
|
const rgPath = getRgPath();
|
|
39224
|
-
if (
|
|
39478
|
+
if (existsSync43(rgPath)) {
|
|
39225
39479
|
return rgPath;
|
|
39226
39480
|
}
|
|
39227
39481
|
mkdirSync14(installDir, { recursive: true });
|
|
39228
39482
|
const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
|
|
39229
39483
|
const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
39230
|
-
const archivePath =
|
|
39484
|
+
const archivePath = join50(installDir, filename);
|
|
39231
39485
|
try {
|
|
39232
39486
|
await downloadFile(url2, archivePath);
|
|
39233
39487
|
if (config3.extension === "tar.gz") {
|
|
@@ -39238,12 +39492,12 @@ async function downloadAndInstallRipgrep() {
|
|
|
39238
39492
|
if (process.platform !== "win32") {
|
|
39239
39493
|
chmodSync3(rgPath, 493);
|
|
39240
39494
|
}
|
|
39241
|
-
if (!
|
|
39495
|
+
if (!existsSync43(rgPath)) {
|
|
39242
39496
|
throw new Error("ripgrep binary not found after extraction");
|
|
39243
39497
|
}
|
|
39244
39498
|
return rgPath;
|
|
39245
39499
|
} finally {
|
|
39246
|
-
if (
|
|
39500
|
+
if (existsSync43(archivePath)) {
|
|
39247
39501
|
try {
|
|
39248
39502
|
unlinkSync11(archivePath);
|
|
39249
39503
|
} catch {}
|
|
@@ -39252,7 +39506,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
39252
39506
|
}
|
|
39253
39507
|
function getInstalledRipgrepPath() {
|
|
39254
39508
|
const rgPath = getRgPath();
|
|
39255
|
-
return
|
|
39509
|
+
return existsSync43(rgPath) ? rgPath : null;
|
|
39256
39510
|
}
|
|
39257
39511
|
|
|
39258
39512
|
// src/tools/grep/constants.ts
|
|
@@ -39277,14 +39531,14 @@ function getOpenCodeBundledRg() {
|
|
|
39277
39531
|
const isWindows2 = process.platform === "win32";
|
|
39278
39532
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
39279
39533
|
const candidates = [
|
|
39280
|
-
|
|
39281
|
-
|
|
39282
|
-
|
|
39283
|
-
|
|
39284
|
-
|
|
39534
|
+
join51(getDataDir(), "opencode", "bin", rgName),
|
|
39535
|
+
join51(execDir, rgName),
|
|
39536
|
+
join51(execDir, "bin", rgName),
|
|
39537
|
+
join51(execDir, "..", "bin", rgName),
|
|
39538
|
+
join51(execDir, "..", "libexec", rgName)
|
|
39285
39539
|
];
|
|
39286
39540
|
for (const candidate of candidates) {
|
|
39287
|
-
if (
|
|
39541
|
+
if (existsSync44(candidate)) {
|
|
39288
39542
|
return candidate;
|
|
39289
39543
|
}
|
|
39290
39544
|
}
|
|
@@ -39746,8 +40000,8 @@ var glob = tool({
|
|
|
39746
40000
|
init_shared();
|
|
39747
40001
|
init_file_utils();
|
|
39748
40002
|
init_shared();
|
|
39749
|
-
import { existsSync as
|
|
39750
|
-
import { join as
|
|
40003
|
+
import { existsSync as existsSync45, readdirSync as readdirSync14, readFileSync as readFileSync29 } from "fs";
|
|
40004
|
+
import { join as join52, basename as basename4, dirname as dirname12 } from "path";
|
|
39751
40005
|
// src/features/builtin-commands/templates/init-deep.ts
|
|
39752
40006
|
var INIT_DEEP_TEMPLATE = `# /init-deep
|
|
39753
40007
|
|
|
@@ -40863,15 +41117,15 @@ function loadBuiltinCommands(disabledCommands) {
|
|
|
40863
41117
|
}
|
|
40864
41118
|
// src/tools/slashcommand/tools.ts
|
|
40865
41119
|
function discoverCommandsFromDir2(commandsDir, scope) {
|
|
40866
|
-
if (!
|
|
41120
|
+
if (!existsSync45(commandsDir)) {
|
|
40867
41121
|
return [];
|
|
40868
41122
|
}
|
|
40869
|
-
const entries =
|
|
41123
|
+
const entries = readdirSync14(commandsDir, { withFileTypes: true });
|
|
40870
41124
|
const commands2 = [];
|
|
40871
41125
|
for (const entry of entries) {
|
|
40872
41126
|
if (!isMarkdownFile(entry))
|
|
40873
41127
|
continue;
|
|
40874
|
-
const commandPath =
|
|
41128
|
+
const commandPath = join52(commandsDir, entry.name);
|
|
40875
41129
|
const commandName = basename4(entry.name, ".md");
|
|
40876
41130
|
try {
|
|
40877
41131
|
const content = readFileSync29(commandPath, "utf-8");
|
|
@@ -40900,10 +41154,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
40900
41154
|
}
|
|
40901
41155
|
function discoverCommandsSync() {
|
|
40902
41156
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
40903
|
-
const userCommandsDir =
|
|
40904
|
-
const projectCommandsDir =
|
|
40905
|
-
const opencodeGlobalDir =
|
|
40906
|
-
const opencodeProjectDir =
|
|
41157
|
+
const userCommandsDir = join52(getClaudeConfigDir(), "commands");
|
|
41158
|
+
const projectCommandsDir = join52(process.cwd(), ".claude", "commands");
|
|
41159
|
+
const opencodeGlobalDir = join52(configDir, "command");
|
|
41160
|
+
const opencodeProjectDir = join52(process.cwd(), ".opencode", "command");
|
|
40907
41161
|
const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
|
|
40908
41162
|
const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
|
|
40909
41163
|
const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
|
|
@@ -41080,13 +41334,13 @@ var slashcommand = createSlashcommandTool();
|
|
|
41080
41334
|
// src/tools/session-manager/constants.ts
|
|
41081
41335
|
init_data_path();
|
|
41082
41336
|
init_shared();
|
|
41083
|
-
import { join as
|
|
41337
|
+
import { join as join53 } from "path";
|
|
41084
41338
|
var OPENCODE_STORAGE9 = getOpenCodeStorageDir();
|
|
41085
|
-
var MESSAGE_STORAGE4 =
|
|
41086
|
-
var PART_STORAGE4 =
|
|
41087
|
-
var SESSION_STORAGE =
|
|
41088
|
-
var TODO_DIR2 =
|
|
41089
|
-
var TRANSCRIPT_DIR2 =
|
|
41339
|
+
var MESSAGE_STORAGE4 = join53(OPENCODE_STORAGE9, "message");
|
|
41340
|
+
var PART_STORAGE4 = join53(OPENCODE_STORAGE9, "part");
|
|
41341
|
+
var SESSION_STORAGE = join53(OPENCODE_STORAGE9, "session");
|
|
41342
|
+
var TODO_DIR2 = join53(getClaudeConfigDir(), "todos");
|
|
41343
|
+
var TRANSCRIPT_DIR2 = join53(getClaudeConfigDir(), "transcripts");
|
|
41090
41344
|
var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
|
|
41091
41345
|
|
|
41092
41346
|
\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
|
|
@@ -41159,11 +41413,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
41159
41413
|
Has Transcript: Yes (234 entries)`;
|
|
41160
41414
|
|
|
41161
41415
|
// src/tools/session-manager/storage.ts
|
|
41162
|
-
import { existsSync as
|
|
41416
|
+
import { existsSync as existsSync46, readdirSync as readdirSync15 } from "fs";
|
|
41163
41417
|
import { readdir, readFile } from "fs/promises";
|
|
41164
|
-
import { join as
|
|
41418
|
+
import { join as join54 } from "path";
|
|
41165
41419
|
async function getMainSessions(options) {
|
|
41166
|
-
if (!
|
|
41420
|
+
if (!existsSync46(SESSION_STORAGE))
|
|
41167
41421
|
return [];
|
|
41168
41422
|
const sessions = [];
|
|
41169
41423
|
try {
|
|
@@ -41171,13 +41425,13 @@ async function getMainSessions(options) {
|
|
|
41171
41425
|
for (const projectDir of projectDirs) {
|
|
41172
41426
|
if (!projectDir.isDirectory())
|
|
41173
41427
|
continue;
|
|
41174
|
-
const projectPath =
|
|
41428
|
+
const projectPath = join54(SESSION_STORAGE, projectDir.name);
|
|
41175
41429
|
const sessionFiles = await readdir(projectPath);
|
|
41176
41430
|
for (const file2 of sessionFiles) {
|
|
41177
41431
|
if (!file2.endsWith(".json"))
|
|
41178
41432
|
continue;
|
|
41179
41433
|
try {
|
|
41180
|
-
const content = await readFile(
|
|
41434
|
+
const content = await readFile(join54(projectPath, file2), "utf-8");
|
|
41181
41435
|
const meta = JSON.parse(content);
|
|
41182
41436
|
if (meta.parentID)
|
|
41183
41437
|
continue;
|
|
@@ -41195,7 +41449,7 @@ async function getMainSessions(options) {
|
|
|
41195
41449
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
41196
41450
|
}
|
|
41197
41451
|
async function getAllSessions() {
|
|
41198
|
-
if (!
|
|
41452
|
+
if (!existsSync46(MESSAGE_STORAGE4))
|
|
41199
41453
|
return [];
|
|
41200
41454
|
const sessions = [];
|
|
41201
41455
|
async function scanDirectory(dir) {
|
|
@@ -41203,7 +41457,7 @@ async function getAllSessions() {
|
|
|
41203
41457
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
41204
41458
|
for (const entry of entries) {
|
|
41205
41459
|
if (entry.isDirectory()) {
|
|
41206
|
-
const sessionPath =
|
|
41460
|
+
const sessionPath = join54(dir, entry.name);
|
|
41207
41461
|
const files = await readdir(sessionPath);
|
|
41208
41462
|
if (files.some((f) => f.endsWith(".json"))) {
|
|
41209
41463
|
sessions.push(entry.name);
|
|
@@ -41220,16 +41474,16 @@ async function getAllSessions() {
|
|
|
41220
41474
|
return [...new Set(sessions)];
|
|
41221
41475
|
}
|
|
41222
41476
|
function getMessageDir7(sessionID) {
|
|
41223
|
-
if (!
|
|
41477
|
+
if (!existsSync46(MESSAGE_STORAGE4))
|
|
41224
41478
|
return "";
|
|
41225
|
-
const directPath =
|
|
41226
|
-
if (
|
|
41479
|
+
const directPath = join54(MESSAGE_STORAGE4, sessionID);
|
|
41480
|
+
if (existsSync46(directPath)) {
|
|
41227
41481
|
return directPath;
|
|
41228
41482
|
}
|
|
41229
41483
|
try {
|
|
41230
|
-
for (const dir of
|
|
41231
|
-
const sessionPath =
|
|
41232
|
-
if (
|
|
41484
|
+
for (const dir of readdirSync15(MESSAGE_STORAGE4)) {
|
|
41485
|
+
const sessionPath = join54(MESSAGE_STORAGE4, dir, sessionID);
|
|
41486
|
+
if (existsSync46(sessionPath)) {
|
|
41233
41487
|
return sessionPath;
|
|
41234
41488
|
}
|
|
41235
41489
|
}
|
|
@@ -41243,7 +41497,7 @@ function sessionExists(sessionID) {
|
|
|
41243
41497
|
}
|
|
41244
41498
|
async function readSessionMessages(sessionID) {
|
|
41245
41499
|
const messageDir = getMessageDir7(sessionID);
|
|
41246
|
-
if (!messageDir || !
|
|
41500
|
+
if (!messageDir || !existsSync46(messageDir))
|
|
41247
41501
|
return [];
|
|
41248
41502
|
const messages = [];
|
|
41249
41503
|
try {
|
|
@@ -41252,7 +41506,7 @@ async function readSessionMessages(sessionID) {
|
|
|
41252
41506
|
if (!file2.endsWith(".json"))
|
|
41253
41507
|
continue;
|
|
41254
41508
|
try {
|
|
41255
|
-
const content = await readFile(
|
|
41509
|
+
const content = await readFile(join54(messageDir, file2), "utf-8");
|
|
41256
41510
|
const meta = JSON.parse(content);
|
|
41257
41511
|
const parts = await readParts2(meta.id);
|
|
41258
41512
|
messages.push({
|
|
@@ -41278,8 +41532,8 @@ async function readSessionMessages(sessionID) {
|
|
|
41278
41532
|
});
|
|
41279
41533
|
}
|
|
41280
41534
|
async function readParts2(messageID) {
|
|
41281
|
-
const partDir =
|
|
41282
|
-
if (!
|
|
41535
|
+
const partDir = join54(PART_STORAGE4, messageID);
|
|
41536
|
+
if (!existsSync46(partDir))
|
|
41283
41537
|
return [];
|
|
41284
41538
|
const parts = [];
|
|
41285
41539
|
try {
|
|
@@ -41288,7 +41542,7 @@ async function readParts2(messageID) {
|
|
|
41288
41542
|
if (!file2.endsWith(".json"))
|
|
41289
41543
|
continue;
|
|
41290
41544
|
try {
|
|
41291
|
-
const content = await readFile(
|
|
41545
|
+
const content = await readFile(join54(partDir, file2), "utf-8");
|
|
41292
41546
|
parts.push(JSON.parse(content));
|
|
41293
41547
|
} catch {
|
|
41294
41548
|
continue;
|
|
@@ -41300,14 +41554,14 @@ async function readParts2(messageID) {
|
|
|
41300
41554
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
41301
41555
|
}
|
|
41302
41556
|
async function readSessionTodos(sessionID) {
|
|
41303
|
-
if (!
|
|
41557
|
+
if (!existsSync46(TODO_DIR2))
|
|
41304
41558
|
return [];
|
|
41305
41559
|
try {
|
|
41306
41560
|
const allFiles = await readdir(TODO_DIR2);
|
|
41307
41561
|
const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
|
|
41308
41562
|
for (const file2 of todoFiles) {
|
|
41309
41563
|
try {
|
|
41310
|
-
const content = await readFile(
|
|
41564
|
+
const content = await readFile(join54(TODO_DIR2, file2), "utf-8");
|
|
41311
41565
|
const data = JSON.parse(content);
|
|
41312
41566
|
if (Array.isArray(data)) {
|
|
41313
41567
|
return data.map((item) => ({
|
|
@@ -41327,10 +41581,10 @@ async function readSessionTodos(sessionID) {
|
|
|
41327
41581
|
return [];
|
|
41328
41582
|
}
|
|
41329
41583
|
async function readSessionTranscript(sessionID) {
|
|
41330
|
-
if (!
|
|
41584
|
+
if (!existsSync46(TRANSCRIPT_DIR2))
|
|
41331
41585
|
return 0;
|
|
41332
|
-
const transcriptFile =
|
|
41333
|
-
if (!
|
|
41586
|
+
const transcriptFile = join54(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
41587
|
+
if (!existsSync46(transcriptFile))
|
|
41334
41588
|
return 0;
|
|
41335
41589
|
try {
|
|
41336
41590
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -42532,19 +42786,19 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8 explore/librarian agent\u3002run_
|
|
|
42532
42786
|
|
|
42533
42787
|
\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`;
|
|
42534
42788
|
// src/tools/call-omo-agent/tools.ts
|
|
42535
|
-
import { existsSync as
|
|
42536
|
-
import { join as
|
|
42789
|
+
import { existsSync as existsSync47, readdirSync as readdirSync16 } from "fs";
|
|
42790
|
+
import { join as join55 } from "path";
|
|
42537
42791
|
init_shared();
|
|
42538
42792
|
init_session_cursor();
|
|
42539
42793
|
function getMessageDir8(sessionID) {
|
|
42540
|
-
if (!
|
|
42794
|
+
if (!existsSync47(MESSAGE_STORAGE))
|
|
42541
42795
|
return null;
|
|
42542
|
-
const directPath =
|
|
42543
|
-
if (
|
|
42796
|
+
const directPath = join55(MESSAGE_STORAGE, sessionID);
|
|
42797
|
+
if (existsSync47(directPath))
|
|
42544
42798
|
return directPath;
|
|
42545
|
-
for (const dir of
|
|
42546
|
-
const sessionPath =
|
|
42547
|
-
if (
|
|
42799
|
+
for (const dir of readdirSync16(MESSAGE_STORAGE)) {
|
|
42800
|
+
const sessionPath = join55(MESSAGE_STORAGE, dir, sessionID);
|
|
42801
|
+
if (existsSync47(sessionPath))
|
|
42548
42802
|
return sessionPath;
|
|
42549
42803
|
}
|
|
42550
42804
|
return null;
|
|
@@ -42953,14 +43207,17 @@ If the requested information is not found, clearly state what is missing.`;
|
|
|
42953
43207
|
}
|
|
42954
43208
|
// src/tools/delegate-task/tools.ts
|
|
42955
43209
|
init_constants2();
|
|
42956
|
-
import { existsSync as
|
|
42957
|
-
import { join as
|
|
43210
|
+
import { existsSync as existsSync48, readdirSync as readdirSync17 } from "fs";
|
|
43211
|
+
import { join as join56 } from "path";
|
|
42958
43212
|
|
|
42959
43213
|
// src/features/task-toast-manager/manager.ts
|
|
42960
43214
|
class TaskToastManager {
|
|
42961
43215
|
tasks = new Map;
|
|
42962
43216
|
client;
|
|
42963
43217
|
concurrencyManager;
|
|
43218
|
+
completionBatch = [];
|
|
43219
|
+
completionDebounceTimer;
|
|
43220
|
+
static COMPLETION_DEBOUNCE_MS = 800;
|
|
42964
43221
|
constructor(client2, concurrencyManager) {
|
|
42965
43222
|
this.client = client2;
|
|
42966
43223
|
this.concurrencyManager = concurrencyManager;
|
|
@@ -43072,13 +43329,36 @@ class TaskToastManager {
|
|
|
43072
43329
|
}).catch(() => {});
|
|
43073
43330
|
}
|
|
43074
43331
|
showCompletionToast(task) {
|
|
43332
|
+
this.removeTask(task.id);
|
|
43333
|
+
this.completionBatch.push(task);
|
|
43334
|
+
if (this.completionDebounceTimer) {
|
|
43335
|
+
clearTimeout(this.completionDebounceTimer);
|
|
43336
|
+
}
|
|
43337
|
+
this.completionDebounceTimer = setTimeout(() => {
|
|
43338
|
+
this.flushCompletionBatch();
|
|
43339
|
+
}, TaskToastManager.COMPLETION_DEBOUNCE_MS);
|
|
43340
|
+
}
|
|
43341
|
+
flushCompletionBatch() {
|
|
43075
43342
|
const tuiClient = this.client;
|
|
43076
|
-
if (!tuiClient.tui?.showToast)
|
|
43343
|
+
if (!tuiClient.tui?.showToast) {
|
|
43344
|
+
this.completionBatch = [];
|
|
43345
|
+
return;
|
|
43346
|
+
}
|
|
43347
|
+
const batch = [...this.completionBatch];
|
|
43348
|
+
this.completionBatch = [];
|
|
43349
|
+
if (batch.length === 0)
|
|
43077
43350
|
return;
|
|
43078
|
-
this.removeTask(task.id);
|
|
43079
43351
|
const remaining = this.getRunningTasks();
|
|
43080
43352
|
const queued = this.getQueuedTasks();
|
|
43081
|
-
let message
|
|
43353
|
+
let message;
|
|
43354
|
+
if (batch.length === 1) {
|
|
43355
|
+
message = `"${batch[0].description}" finished in ${batch[0].duration}`;
|
|
43356
|
+
} else {
|
|
43357
|
+
const lines = batch.map((t) => ` \u2713 "${t.description}" (${t.duration})`);
|
|
43358
|
+
message = `${batch.length} tasks completed:
|
|
43359
|
+
${lines.join(`
|
|
43360
|
+
`)}`;
|
|
43361
|
+
}
|
|
43082
43362
|
if (remaining.length > 0 || queued.length > 0) {
|
|
43083
43363
|
message += `
|
|
43084
43364
|
|
|
@@ -43086,12 +43366,13 @@ Still running: ${remaining.length} | Queued: ${queued.length}`;
|
|
|
43086
43366
|
}
|
|
43087
43367
|
tuiClient.tui.showToast({
|
|
43088
43368
|
body: {
|
|
43089
|
-
title: "Task Completed"
|
|
43369
|
+
title: batch.length === 1 ? "Task Completed" : `${batch.length} Tasks Completed`,
|
|
43090
43370
|
message,
|
|
43091
43371
|
variant: "success",
|
|
43092
|
-
duration: 5000
|
|
43372
|
+
duration: batch.length > 1 ? 7000 : 5000
|
|
43093
43373
|
}
|
|
43094
43374
|
}).catch(() => {});
|
|
43375
|
+
this.completionDebounceTimer = undefined;
|
|
43095
43376
|
}
|
|
43096
43377
|
}
|
|
43097
43378
|
var instance = null;
|
|
@@ -43104,6 +43385,256 @@ function initTaskToastManager(client2, concurrencyManager) {
|
|
|
43104
43385
|
}
|
|
43105
43386
|
// src/tools/delegate-task/tools.ts
|
|
43106
43387
|
init_shared();
|
|
43388
|
+
|
|
43389
|
+
// src/shared/provider-error-classifier.ts
|
|
43390
|
+
function extractErrorInfo(error45) {
|
|
43391
|
+
if (typeof error45 === "string") {
|
|
43392
|
+
return { message: error45 };
|
|
43393
|
+
}
|
|
43394
|
+
if (error45 instanceof Error) {
|
|
43395
|
+
const anyErr = error45;
|
|
43396
|
+
return {
|
|
43397
|
+
statusCode: anyErr.status ?? anyErr.statusCode ?? anyErr.httpStatus,
|
|
43398
|
+
code: anyErr.code ?? anyErr.error?.code,
|
|
43399
|
+
type: anyErr.type ?? anyErr.error?.type,
|
|
43400
|
+
message: error45.message,
|
|
43401
|
+
status: anyErr.status ?? anyErr.error?.status,
|
|
43402
|
+
headers: anyErr.headers
|
|
43403
|
+
};
|
|
43404
|
+
}
|
|
43405
|
+
if (typeof error45 === "object" && error45 !== null) {
|
|
43406
|
+
const obj = error45;
|
|
43407
|
+
const inner = obj.error ?? {};
|
|
43408
|
+
return {
|
|
43409
|
+
statusCode: obj.status ?? obj.statusCode ?? inner.status,
|
|
43410
|
+
code: inner.code ?? obj.code,
|
|
43411
|
+
type: inner.type ?? obj.type,
|
|
43412
|
+
message: inner.message ?? obj.message ?? String(error45),
|
|
43413
|
+
status: inner.status ?? obj.status,
|
|
43414
|
+
headers: obj.headers
|
|
43415
|
+
};
|
|
43416
|
+
}
|
|
43417
|
+
return { message: String(error45) };
|
|
43418
|
+
}
|
|
43419
|
+
function parseRetryAfterMs(headers) {
|
|
43420
|
+
if (!headers)
|
|
43421
|
+
return;
|
|
43422
|
+
const retryAfter = headers["retry-after"] ?? headers["Retry-After"];
|
|
43423
|
+
if (retryAfter) {
|
|
43424
|
+
const seconds = Number(retryAfter);
|
|
43425
|
+
if (!isNaN(seconds) && seconds > 0) {
|
|
43426
|
+
return seconds * 1000;
|
|
43427
|
+
}
|
|
43428
|
+
}
|
|
43429
|
+
const reset = headers["x-ratelimit-reset"] ?? headers["X-Ratelimit-Reset"];
|
|
43430
|
+
if (reset) {
|
|
43431
|
+
const resetTimestamp = Number(reset);
|
|
43432
|
+
if (!isNaN(resetTimestamp)) {
|
|
43433
|
+
const resetMs = resetTimestamp > 1000000000000 ? resetTimestamp : resetTimestamp * 1000;
|
|
43434
|
+
const delayMs = resetMs - Date.now();
|
|
43435
|
+
return delayMs > 0 ? delayMs : 0;
|
|
43436
|
+
}
|
|
43437
|
+
}
|
|
43438
|
+
return;
|
|
43439
|
+
}
|
|
43440
|
+
function isContextOverflow(message, code) {
|
|
43441
|
+
const lowerMessage = message.toLowerCase();
|
|
43442
|
+
return lowerMessage.includes("context_length_exceeded") || lowerMessage.includes("prompt is too long") || lowerMessage.includes("maximum context length") || code === "context_length_exceeded";
|
|
43443
|
+
}
|
|
43444
|
+
function isZhipuQuotaCode(code) {
|
|
43445
|
+
if (typeof code !== "number")
|
|
43446
|
+
return false;
|
|
43447
|
+
return [1113, 1304, 1308, 1309].includes(code);
|
|
43448
|
+
}
|
|
43449
|
+
function isZhipuRateLimitCode(code) {
|
|
43450
|
+
if (typeof code !== "number")
|
|
43451
|
+
return false;
|
|
43452
|
+
return [1302, 1303].includes(code);
|
|
43453
|
+
}
|
|
43454
|
+
function isZhipuOverloadedCode(code) {
|
|
43455
|
+
if (typeof code !== "number")
|
|
43456
|
+
return false;
|
|
43457
|
+
return code === 1312;
|
|
43458
|
+
}
|
|
43459
|
+
function isGeminiQuotaDetails(details) {
|
|
43460
|
+
if (!Array.isArray(details))
|
|
43461
|
+
return false;
|
|
43462
|
+
return details.some((d) => d?.["@type"]?.includes("QuotaFailure") || d?.["@type"]?.includes("google.rpc.QuotaFailure"));
|
|
43463
|
+
}
|
|
43464
|
+
function isGeminiPerMinuteLimit(message, details) {
|
|
43465
|
+
const lowerMessage = message.toLowerCase();
|
|
43466
|
+
if (lowerMessage.includes("per_minute") || lowerMessage.includes("per minute")) {
|
|
43467
|
+
return true;
|
|
43468
|
+
}
|
|
43469
|
+
if (Array.isArray(details)) {
|
|
43470
|
+
return details.some((d) => d?.["@type"]?.includes("RetryInfo"));
|
|
43471
|
+
}
|
|
43472
|
+
return false;
|
|
43473
|
+
}
|
|
43474
|
+
function classifyProviderError(error45) {
|
|
43475
|
+
const info = extractErrorInfo(error45);
|
|
43476
|
+
const { statusCode, code, type: type2, message, status, headers } = info;
|
|
43477
|
+
if (isContextOverflow(message, code)) {
|
|
43478
|
+
return {
|
|
43479
|
+
category: "context_overflow",
|
|
43480
|
+
retryable: false,
|
|
43481
|
+
shouldFallback: false,
|
|
43482
|
+
statusCode,
|
|
43483
|
+
reason: "Context length exceeded, prompt too long for model"
|
|
43484
|
+
};
|
|
43485
|
+
}
|
|
43486
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
43487
|
+
return {
|
|
43488
|
+
category: "auth",
|
|
43489
|
+
retryable: false,
|
|
43490
|
+
shouldFallback: false,
|
|
43491
|
+
statusCode,
|
|
43492
|
+
reason: statusCode === 401 ? "Invalid API key or authentication" : "Permission denied"
|
|
43493
|
+
};
|
|
43494
|
+
}
|
|
43495
|
+
if (statusCode === 400) {
|
|
43496
|
+
return {
|
|
43497
|
+
category: "bad_request",
|
|
43498
|
+
retryable: false,
|
|
43499
|
+
shouldFallback: false,
|
|
43500
|
+
statusCode,
|
|
43501
|
+
reason: "Invalid request parameters"
|
|
43502
|
+
};
|
|
43503
|
+
}
|
|
43504
|
+
if (statusCode === 429 && (code === "insufficient_quota" || type2 === "insufficient_quota")) {
|
|
43505
|
+
return {
|
|
43506
|
+
category: "quota",
|
|
43507
|
+
retryable: false,
|
|
43508
|
+
shouldFallback: true,
|
|
43509
|
+
statusCode,
|
|
43510
|
+
providerGuess: "openai",
|
|
43511
|
+
reason: "OpenAI quota exceeded, billing issue"
|
|
43512
|
+
};
|
|
43513
|
+
}
|
|
43514
|
+
if (statusCode === 402 && type2 === "billing_error") {
|
|
43515
|
+
return {
|
|
43516
|
+
category: "quota",
|
|
43517
|
+
retryable: false,
|
|
43518
|
+
shouldFallback: true,
|
|
43519
|
+
statusCode,
|
|
43520
|
+
providerGuess: "anthropic",
|
|
43521
|
+
reason: "Anthropic billing error, payment required"
|
|
43522
|
+
};
|
|
43523
|
+
}
|
|
43524
|
+
if (statusCode === 429 && status === "RESOURCE_EXHAUSTED" && isGeminiQuotaDetails(info.headers ? undefined : error45?.error?.details)) {
|
|
43525
|
+
return {
|
|
43526
|
+
category: "quota",
|
|
43527
|
+
retryable: false,
|
|
43528
|
+
shouldFallback: true,
|
|
43529
|
+
statusCode,
|
|
43530
|
+
providerGuess: "gemini",
|
|
43531
|
+
reason: "Gemini daily quota exceeded"
|
|
43532
|
+
};
|
|
43533
|
+
}
|
|
43534
|
+
if (statusCode === 429 && isZhipuQuotaCode(code)) {
|
|
43535
|
+
const quotaReasons = {
|
|
43536
|
+
1113: "\u8D26\u6237\u6B20\u8D39",
|
|
43537
|
+
1304: "\u8C03\u7528\u6B21\u6570\u8D85\u8FC7\u9650\u989D",
|
|
43538
|
+
1308: "\u4F7F\u7528\u91CF\u8D85\u8FC7\u4E0A\u9650",
|
|
43539
|
+
1309: "\u5957\u9910\u5DF2\u5230\u671F"
|
|
43540
|
+
};
|
|
43541
|
+
return {
|
|
43542
|
+
category: "quota",
|
|
43543
|
+
retryable: false,
|
|
43544
|
+
shouldFallback: true,
|
|
43545
|
+
statusCode,
|
|
43546
|
+
providerGuess: "zhipu",
|
|
43547
|
+
reason: `Zhipu/GLM: ${quotaReasons[code] ?? "quota exceeded"}`
|
|
43548
|
+
};
|
|
43549
|
+
}
|
|
43550
|
+
if (statusCode === 529 && type2 === "overloaded_error") {
|
|
43551
|
+
return {
|
|
43552
|
+
category: "overloaded",
|
|
43553
|
+
retryable: true,
|
|
43554
|
+
shouldFallback: false,
|
|
43555
|
+
statusCode,
|
|
43556
|
+
providerGuess: "anthropic",
|
|
43557
|
+
reason: "Anthropic API overloaded"
|
|
43558
|
+
};
|
|
43559
|
+
}
|
|
43560
|
+
if (statusCode === 429 && isZhipuOverloadedCode(code)) {
|
|
43561
|
+
return {
|
|
43562
|
+
category: "overloaded",
|
|
43563
|
+
retryable: true,
|
|
43564
|
+
shouldFallback: false,
|
|
43565
|
+
statusCode,
|
|
43566
|
+
providerGuess: "zhipu",
|
|
43567
|
+
reason: "Zhipu/GLM: \u5F53\u524D\u8D1F\u8F7D\u8FC7\u9AD8"
|
|
43568
|
+
};
|
|
43569
|
+
}
|
|
43570
|
+
if (statusCode === 429 && type2 === "rate_limit_error") {
|
|
43571
|
+
return {
|
|
43572
|
+
category: "rate_limit",
|
|
43573
|
+
retryable: true,
|
|
43574
|
+
shouldFallback: false,
|
|
43575
|
+
statusCode,
|
|
43576
|
+
providerGuess: "anthropic",
|
|
43577
|
+
retryAfterMs: parseRetryAfterMs(headers),
|
|
43578
|
+
reason: "Anthropic rate limit exceeded"
|
|
43579
|
+
};
|
|
43580
|
+
}
|
|
43581
|
+
if (statusCode === 429 && code === "rate_limit_exceeded") {
|
|
43582
|
+
return {
|
|
43583
|
+
category: "rate_limit",
|
|
43584
|
+
retryable: true,
|
|
43585
|
+
shouldFallback: false,
|
|
43586
|
+
statusCode,
|
|
43587
|
+
providerGuess: "openai",
|
|
43588
|
+
retryAfterMs: parseRetryAfterMs(headers),
|
|
43589
|
+
reason: "OpenAI rate limit exceeded"
|
|
43590
|
+
};
|
|
43591
|
+
}
|
|
43592
|
+
if (statusCode === 429 && status === "RESOURCE_EXHAUSTED" && isGeminiPerMinuteLimit(message, error45?.error?.details)) {
|
|
43593
|
+
return {
|
|
43594
|
+
category: "rate_limit",
|
|
43595
|
+
retryable: true,
|
|
43596
|
+
shouldFallback: false,
|
|
43597
|
+
statusCode,
|
|
43598
|
+
providerGuess: "gemini",
|
|
43599
|
+
retryAfterMs: parseRetryAfterMs(headers),
|
|
43600
|
+
reason: "Gemini per-minute rate limit exceeded"
|
|
43601
|
+
};
|
|
43602
|
+
}
|
|
43603
|
+
if (statusCode === 429 && isZhipuRateLimitCode(code)) {
|
|
43604
|
+
const rateLimitReasons = {
|
|
43605
|
+
1302: "\u5E76\u53D1\u8BF7\u6C42\u8D85\u8FC7\u9650\u5236",
|
|
43606
|
+
1303: "\u8BF7\u6C42\u9891\u7387\u8D85\u8FC7\u9650\u5236"
|
|
43607
|
+
};
|
|
43608
|
+
return {
|
|
43609
|
+
category: "rate_limit",
|
|
43610
|
+
retryable: true,
|
|
43611
|
+
shouldFallback: false,
|
|
43612
|
+
statusCode,
|
|
43613
|
+
providerGuess: "zhipu",
|
|
43614
|
+
retryAfterMs: parseRetryAfterMs(headers),
|
|
43615
|
+
reason: `Zhipu/GLM: ${rateLimitReasons[code] ?? "rate limit exceeded"}`
|
|
43616
|
+
};
|
|
43617
|
+
}
|
|
43618
|
+
if (statusCode === 429) {
|
|
43619
|
+
return {
|
|
43620
|
+
category: "rate_limit",
|
|
43621
|
+
retryable: true,
|
|
43622
|
+
shouldFallback: false,
|
|
43623
|
+
statusCode,
|
|
43624
|
+
retryAfterMs: parseRetryAfterMs(headers),
|
|
43625
|
+
reason: "Rate limit exceeded (generic 429)"
|
|
43626
|
+
};
|
|
43627
|
+
}
|
|
43628
|
+
return {
|
|
43629
|
+
category: "unknown",
|
|
43630
|
+
retryable: false,
|
|
43631
|
+
shouldFallback: false,
|
|
43632
|
+
statusCode,
|
|
43633
|
+
reason: `Unknown error: ${message.substring(0, 100)}`
|
|
43634
|
+
};
|
|
43635
|
+
}
|
|
43636
|
+
|
|
43637
|
+
// src/tools/delegate-task/tools.ts
|
|
43107
43638
|
var SISYPHUS_JUNIOR_AGENT = "sisyphus-junior";
|
|
43108
43639
|
function parseModelString(model) {
|
|
43109
43640
|
const parts = model.split("/");
|
|
@@ -43113,14 +43644,14 @@ function parseModelString(model) {
|
|
|
43113
43644
|
return;
|
|
43114
43645
|
}
|
|
43115
43646
|
function getMessageDir9(sessionID) {
|
|
43116
|
-
if (!
|
|
43647
|
+
if (!existsSync48(MESSAGE_STORAGE))
|
|
43117
43648
|
return null;
|
|
43118
|
-
const directPath =
|
|
43119
|
-
if (
|
|
43649
|
+
const directPath = join56(MESSAGE_STORAGE, sessionID);
|
|
43650
|
+
if (existsSync48(directPath))
|
|
43120
43651
|
return directPath;
|
|
43121
|
-
for (const dir of
|
|
43122
|
-
const sessionPath =
|
|
43123
|
-
if (
|
|
43652
|
+
for (const dir of readdirSync17(MESSAGE_STORAGE)) {
|
|
43653
|
+
const sessionPath = join56(MESSAGE_STORAGE, dir, sessionID);
|
|
43654
|
+
if (existsSync48(sessionPath))
|
|
43124
43655
|
return sessionPath;
|
|
43125
43656
|
}
|
|
43126
43657
|
return null;
|
|
@@ -43715,7 +44246,12 @@ Session ID: ${sessionID}`;
|
|
|
43715
44246
|
path: { id: sessionID }
|
|
43716
44247
|
});
|
|
43717
44248
|
if (messagesResult.error) {
|
|
43718
|
-
|
|
44249
|
+
const classification = classifyProviderError(messagesResult.error);
|
|
44250
|
+
const diagnosis = classification.category !== "unknown" ? `
|
|
44251
|
+
|
|
44252
|
+
\uD83D\uDD0D **\u9519\u8BEF\u5206\u7C7B**: ${classification.reason}
|
|
44253
|
+
${classification.shouldFallback ? "\uD83D\uDCA1 \u6B64\u9519\u8BEF\u53EF\u901A\u8FC7 runtime fallback \u81EA\u52A8\u5904\u7406\u3002" : classification.retryable ? "\u23F3 \u6B64\u9519\u8BEF\u53EF\u91CD\u8BD5\u3002" : ""}` : "";
|
|
44254
|
+
return `Error fetching result: ${messagesResult.error}${diagnosis}
|
|
43719
44255
|
|
|
43720
44256
|
Session ID: ${sessionID}`;
|
|
43721
44257
|
}
|
|
@@ -43753,13 +44289,14 @@ ${textContent || "(\u65E0\u6587\u672C\u8F93\u51FA)"}
|
|
|
43753
44289
|
if (syncSessionID) {
|
|
43754
44290
|
subagentSessions.delete(syncSessionID);
|
|
43755
44291
|
}
|
|
43756
|
-
|
|
43757
|
-
|
|
43758
|
-
|
|
43759
|
-
|
|
43760
|
-
|
|
43761
|
-
|
|
43762
|
-
|
|
44292
|
+
const classification = classifyProviderError(error45);
|
|
44293
|
+
const diagnosis = classification.category !== "unknown" ? `
|
|
44294
|
+
|
|
44295
|
+
\uD83D\uDD0D **\u9519\u8BEF\u5206\u7C7B**: ${classification.reason}
|
|
44296
|
+
${classification.shouldFallback ? "\uD83D\uDCA1 \u6B64\u9519\u8BEF\u53EF\u901A\u8FC7 runtime fallback \u81EA\u52A8\u5904\u7406\u3002" : classification.retryable ? "\u23F3 \u6B64\u9519\u8BEF\u53EF\u91CD\u8BD5\u3002" : ""}` : "";
|
|
44297
|
+
return `\u4EFB\u52A1\u6267\u884C\u5931\u8D25: ${error45 instanceof Error ? error45.message : String(error45)}${diagnosis}
|
|
44298
|
+
|
|
44299
|
+
Session ID: ${syncSessionID ?? "unknown"}`;
|
|
43763
44300
|
}
|
|
43764
44301
|
}
|
|
43765
44302
|
});
|
|
@@ -43888,6 +44425,9 @@ class ConcurrencyManager {
|
|
|
43888
44425
|
}
|
|
43889
44426
|
}
|
|
43890
44427
|
|
|
44428
|
+
// src/features/background-agent/manager.ts
|
|
44429
|
+
init_runtime_fallback();
|
|
44430
|
+
|
|
43891
44431
|
// src/features/background-agent/perf-aggregator.ts
|
|
43892
44432
|
function percentile(sorted, p) {
|
|
43893
44433
|
if (sorted.length === 0)
|
|
@@ -43948,12 +44488,14 @@ class PerformanceAggregator {
|
|
|
43948
44488
|
}
|
|
43949
44489
|
|
|
43950
44490
|
// src/features/background-agent/manager.ts
|
|
43951
|
-
import { existsSync as
|
|
43952
|
-
import { join as
|
|
44491
|
+
import { existsSync as existsSync49, readdirSync as readdirSync18 } from "fs";
|
|
44492
|
+
import { join as join57 } from "path";
|
|
43953
44493
|
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
43954
44494
|
var MIN_STABILITY_TIME_MS = 10 * 1000;
|
|
43955
|
-
var DEFAULT_STALE_TIMEOUT_MS =
|
|
44495
|
+
var DEFAULT_STALE_TIMEOUT_MS = 120000;
|
|
43956
44496
|
var MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
44497
|
+
var STEP_TIMEOUT_MS = 600000;
|
|
44498
|
+
var MIN_IDLE_TIME_MS = 15000;
|
|
43957
44499
|
|
|
43958
44500
|
class BackgroundManager {
|
|
43959
44501
|
static cleanupManagers = new Set;
|
|
@@ -44006,7 +44548,11 @@ class BackgroundManager {
|
|
|
44006
44548
|
parentMessageID: input.parentMessageID,
|
|
44007
44549
|
parentModel: input.parentModel,
|
|
44008
44550
|
parentAgent: input.parentAgent,
|
|
44009
|
-
model: input.model
|
|
44551
|
+
model: input.model,
|
|
44552
|
+
maxSteps: this.config?.maxSteps,
|
|
44553
|
+
maxRuntimeMs: this.config?.maxRuntimeMs,
|
|
44554
|
+
stepTimeoutMs: this.config?.stepTimeoutMs ?? STEP_TIMEOUT_MS,
|
|
44555
|
+
stepCount: 0
|
|
44010
44556
|
};
|
|
44011
44557
|
this.tasks.set(task.id, task);
|
|
44012
44558
|
if (input.parentSessionID) {
|
|
@@ -44098,7 +44644,8 @@ class BackgroundManager {
|
|
|
44098
44644
|
task.sessionID = sessionID;
|
|
44099
44645
|
task.progress = {
|
|
44100
44646
|
toolCalls: 0,
|
|
44101
|
-
lastUpdate: new Date
|
|
44647
|
+
lastUpdate: new Date,
|
|
44648
|
+
stepStartedAt: Date.now()
|
|
44102
44649
|
};
|
|
44103
44650
|
task.concurrencyKey = concurrencyKey;
|
|
44104
44651
|
task.concurrencyGroup = concurrencyKey;
|
|
@@ -44133,13 +44680,58 @@ class BackgroundManager {
|
|
|
44133
44680
|
log("[background-agent] promptAsync error:", error45);
|
|
44134
44681
|
const existingTask = this.findBySession(sessionID);
|
|
44135
44682
|
if (existingTask) {
|
|
44136
|
-
|
|
44137
|
-
|
|
44138
|
-
|
|
44139
|
-
|
|
44683
|
+
const classification = classifyProviderError(error45);
|
|
44684
|
+
if (classification.retryable || classification.shouldFallback) {
|
|
44685
|
+
const attempts = existingTask.attempts ?? [];
|
|
44686
|
+
const currentModel = input.model ?? { providerID: "", modelID: "" };
|
|
44687
|
+
const fallbackResult = resolveNextFallbackModel({
|
|
44688
|
+
agent: input.agent,
|
|
44689
|
+
currentModel,
|
|
44690
|
+
attempts,
|
|
44691
|
+
lastErrorClassification: classification
|
|
44692
|
+
});
|
|
44693
|
+
if (fallbackResult.kind === "next") {
|
|
44694
|
+
existingTask.attempts = [...attempts, {
|
|
44695
|
+
model: fallbackResult.model,
|
|
44696
|
+
error: classification
|
|
44697
|
+
}];
|
|
44698
|
+
log("[background-agent] Fallback to model:", fallbackResult.model);
|
|
44699
|
+
this.client.session.prompt({
|
|
44700
|
+
path: { id: sessionID },
|
|
44701
|
+
body: {
|
|
44702
|
+
agent: input.agent,
|
|
44703
|
+
model: fallbackResult.model,
|
|
44704
|
+
parts: [{ type: "text", text: input.prompt }]
|
|
44705
|
+
}
|
|
44706
|
+
}).catch((retryError) => {
|
|
44707
|
+
log("[background-agent] Fallback prompt error:", retryError);
|
|
44708
|
+
const task2 = this.findBySession(sessionID);
|
|
44709
|
+
if (task2) {
|
|
44710
|
+
task2.status = "error";
|
|
44711
|
+
task2.error = `Fallback failed: ${retryError instanceof Error ? retryError.message : String(retryError)}`;
|
|
44712
|
+
task2.completedAt = new Date;
|
|
44713
|
+
if (task2.concurrencyKey) {
|
|
44714
|
+
this.concurrencyManager.release(task2.concurrencyKey);
|
|
44715
|
+
task2.concurrencyKey = undefined;
|
|
44716
|
+
}
|
|
44717
|
+
this.markForNotification(task2);
|
|
44718
|
+
this.notifyParentSession(task2).catch((err) => {
|
|
44719
|
+
log("[background-agent] Failed to notify on fallback error:", err);
|
|
44720
|
+
});
|
|
44721
|
+
}
|
|
44722
|
+
});
|
|
44723
|
+
return;
|
|
44724
|
+
}
|
|
44725
|
+
existingTask.error = `All fallback models exhausted. Last error: ${classification.reason}`;
|
|
44140
44726
|
} else {
|
|
44141
|
-
|
|
44727
|
+
const errorMessage = error45 instanceof Error ? error45.message : String(error45);
|
|
44728
|
+
if (errorMessage.includes("agent.name") || errorMessage.includes("undefined")) {
|
|
44729
|
+
existingTask.error = `Agent "${input.agent}" not found. Make sure the agent is registered in your opencode.json or provided by a plugin.`;
|
|
44730
|
+
} else {
|
|
44731
|
+
existingTask.error = errorMessage;
|
|
44732
|
+
}
|
|
44142
44733
|
}
|
|
44734
|
+
existingTask.status = "error";
|
|
44143
44735
|
existingTask.completedAt = new Date;
|
|
44144
44736
|
if (existingTask.concurrencyKey) {
|
|
44145
44737
|
this.concurrencyManager.release(existingTask.concurrencyKey);
|
|
@@ -44238,7 +44830,11 @@ class BackgroundManager {
|
|
|
44238
44830
|
},
|
|
44239
44831
|
parentAgent: input.parentAgent,
|
|
44240
44832
|
concurrencyKey: input.concurrencyKey,
|
|
44241
|
-
concurrencyGroup
|
|
44833
|
+
concurrencyGroup,
|
|
44834
|
+
maxSteps: this.config?.maxSteps,
|
|
44835
|
+
maxRuntimeMs: this.config?.maxRuntimeMs,
|
|
44836
|
+
stepTimeoutMs: this.config?.stepTimeoutMs ?? STEP_TIMEOUT_MS,
|
|
44837
|
+
stepCount: 0
|
|
44242
44838
|
};
|
|
44243
44839
|
this.tasks.set(task.id, task);
|
|
44244
44840
|
subagentSessions.add(input.sessionID);
|
|
@@ -44278,12 +44874,14 @@ class BackgroundManager {
|
|
|
44278
44874
|
existingTask.parentModel = input.parentModel;
|
|
44279
44875
|
existingTask.parentAgent = input.parentAgent;
|
|
44280
44876
|
existingTask.startedAt = new Date;
|
|
44877
|
+
existingTask.stepCount = 0;
|
|
44281
44878
|
if (existingTask.progress) {
|
|
44282
44879
|
existingTask.progress.phaseTiming = undefined;
|
|
44283
44880
|
}
|
|
44284
44881
|
existingTask.progress = {
|
|
44285
44882
|
toolCalls: existingTask.progress?.toolCalls ?? 0,
|
|
44286
|
-
lastUpdate: new Date
|
|
44883
|
+
lastUpdate: new Date,
|
|
44884
|
+
stepStartedAt: Date.now()
|
|
44287
44885
|
};
|
|
44288
44886
|
this.startPolling();
|
|
44289
44887
|
if (existingTask.sessionID) {
|
|
@@ -44385,11 +44983,20 @@ class BackgroundManager {
|
|
|
44385
44983
|
const task = this.findBySession(sessionID);
|
|
44386
44984
|
if (!task || task.status !== "running")
|
|
44387
44985
|
return;
|
|
44986
|
+
task.stepCount = (task.stepCount ?? 0) + 1;
|
|
44987
|
+
if (task.progress) {
|
|
44988
|
+
task.progress.stepStartedAt = Date.now();
|
|
44989
|
+
}
|
|
44990
|
+
if (this.isStepLimitExceeded(task)) {
|
|
44991
|
+
this.tryCompleteTask(task, `step limit (${task.maxSteps} steps)`).catch((err) => {
|
|
44992
|
+
log("[background-agent] Error completing task on step limit:", err);
|
|
44993
|
+
});
|
|
44994
|
+
return;
|
|
44995
|
+
}
|
|
44388
44996
|
const startedAt = task.startedAt;
|
|
44389
44997
|
if (!startedAt)
|
|
44390
44998
|
return;
|
|
44391
44999
|
const elapsedMs = Date.now() - startedAt.getTime();
|
|
44392
|
-
const MIN_IDLE_TIME_MS = 5000;
|
|
44393
45000
|
if (elapsedMs < MIN_IDLE_TIME_MS) {
|
|
44394
45001
|
log("[background-agent] Ignoring early session.idle, elapsed:", { elapsedMs, taskId: task.id });
|
|
44395
45002
|
return;
|
|
@@ -44776,6 +45383,41 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44776
45383
|
const runtime = now - startedAt.getTime();
|
|
44777
45384
|
if (runtime < MIN_RUNTIME_BEFORE_STALE_MS)
|
|
44778
45385
|
continue;
|
|
45386
|
+
if (this.isRuntimeLimitExceeded(task)) {
|
|
45387
|
+
task.status = "cancelled";
|
|
45388
|
+
task.error = `Runtime limit exceeded (${Math.round(runtime / 60000)}min)`;
|
|
45389
|
+
task.completedAt = new Date;
|
|
45390
|
+
if (task.concurrencyKey) {
|
|
45391
|
+
this.concurrencyManager.release(task.concurrencyKey);
|
|
45392
|
+
task.concurrencyKey = undefined;
|
|
45393
|
+
}
|
|
45394
|
+
this.client.session.abort({ path: { id: sessionID } }).catch(() => {});
|
|
45395
|
+
log(`[background-agent] Task ${task.id} interrupted: runtime limit`);
|
|
45396
|
+
try {
|
|
45397
|
+
await this.notifyParentSession(task);
|
|
45398
|
+
} catch (err) {
|
|
45399
|
+
log("[background-agent] Error in notifyParentSession for runtime-limit task:", { taskId: task.id, error: err });
|
|
45400
|
+
}
|
|
45401
|
+
continue;
|
|
45402
|
+
}
|
|
45403
|
+
if (this.isStepTimeoutExceeded(task)) {
|
|
45404
|
+
const stepTimeoutMs = task.stepTimeoutMs ?? STEP_TIMEOUT_MS;
|
|
45405
|
+
task.status = "cancelled";
|
|
45406
|
+
task.error = `Step timeout exceeded (single step > ${Math.round(stepTimeoutMs / 60000)}min)`;
|
|
45407
|
+
task.completedAt = new Date;
|
|
45408
|
+
if (task.concurrencyKey) {
|
|
45409
|
+
this.concurrencyManager.release(task.concurrencyKey);
|
|
45410
|
+
task.concurrencyKey = undefined;
|
|
45411
|
+
}
|
|
45412
|
+
this.client.session.abort({ path: { id: sessionID } }).catch(() => {});
|
|
45413
|
+
log(`[background-agent] Task ${task.id} interrupted: step timeout`);
|
|
45414
|
+
try {
|
|
45415
|
+
await this.notifyParentSession(task);
|
|
45416
|
+
} catch (err) {
|
|
45417
|
+
log("[background-agent] Error in notifyParentSession for step-timeout task:", { taskId: task.id, error: err });
|
|
45418
|
+
}
|
|
45419
|
+
continue;
|
|
45420
|
+
}
|
|
44779
45421
|
const timeSinceLastUpdate = now - task.progress.lastUpdate.getTime();
|
|
44780
45422
|
if (timeSinceLastUpdate <= staleTimeoutMs)
|
|
44781
45423
|
continue;
|
|
@@ -44800,6 +45442,30 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44800
45442
|
}
|
|
44801
45443
|
}
|
|
44802
45444
|
}
|
|
45445
|
+
isStepLimitExceeded(task) {
|
|
45446
|
+
const maxSteps = task.maxSteps;
|
|
45447
|
+
if (!maxSteps || maxSteps <= 0)
|
|
45448
|
+
return false;
|
|
45449
|
+
return (task.stepCount ?? 0) >= maxSteps;
|
|
45450
|
+
}
|
|
45451
|
+
isRuntimeLimitExceeded(task) {
|
|
45452
|
+
const maxRuntimeMs = task.maxRuntimeMs;
|
|
45453
|
+
if (!maxRuntimeMs || maxRuntimeMs <= 0)
|
|
45454
|
+
return false;
|
|
45455
|
+
if (!task.startedAt)
|
|
45456
|
+
return false;
|
|
45457
|
+
const runtime = Date.now() - task.startedAt.getTime();
|
|
45458
|
+
return runtime >= maxRuntimeMs;
|
|
45459
|
+
}
|
|
45460
|
+
isStepTimeoutExceeded(task) {
|
|
45461
|
+
const stepTimeoutMs = task.stepTimeoutMs;
|
|
45462
|
+
if (!stepTimeoutMs || stepTimeoutMs <= 0)
|
|
45463
|
+
return false;
|
|
45464
|
+
if (!task.progress?.stepStartedAt)
|
|
45465
|
+
return false;
|
|
45466
|
+
const stepDuration = Date.now() - task.progress.stepStartedAt;
|
|
45467
|
+
return stepDuration >= stepTimeoutMs;
|
|
45468
|
+
}
|
|
44803
45469
|
async pollRunningTasks() {
|
|
44804
45470
|
const start = this.perfTracer?.isEnabled() ? performance.now() : undefined;
|
|
44805
45471
|
try {
|
|
@@ -44828,6 +45494,10 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44828
45494
|
log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
|
|
44829
45495
|
continue;
|
|
44830
45496
|
}
|
|
45497
|
+
if (this.isStepLimitExceeded(task)) {
|
|
45498
|
+
await this.tryCompleteTask(task, `step limit via polling (${task.maxSteps} steps)`);
|
|
45499
|
+
continue;
|
|
45500
|
+
}
|
|
44831
45501
|
await this.tryCompleteTask(task, "polling (idle status)");
|
|
44832
45502
|
continue;
|
|
44833
45503
|
}
|
|
@@ -44900,6 +45570,10 @@ ${perfSnapshot ? `| \u6392\u961F ${PerfTimer.formatDuration(new Date(0), new Dat
|
|
|
44900
45570
|
}
|
|
44901
45571
|
if (task.status !== "running")
|
|
44902
45572
|
continue;
|
|
45573
|
+
if (this.isStepLimitExceeded(task)) {
|
|
45574
|
+
await this.tryCompleteTask(task, `step limit via stability (${task.maxSteps} steps)`);
|
|
45575
|
+
continue;
|
|
45576
|
+
}
|
|
44903
45577
|
const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
|
|
44904
45578
|
if (!hasIncompleteTodos2) {
|
|
44905
45579
|
await this.tryCompleteTask(task, "stability detection");
|
|
@@ -44964,14 +45638,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
44964
45638
|
return listener;
|
|
44965
45639
|
}
|
|
44966
45640
|
function getMessageDir10(sessionID) {
|
|
44967
|
-
if (!
|
|
45641
|
+
if (!existsSync49(MESSAGE_STORAGE))
|
|
44968
45642
|
return null;
|
|
44969
|
-
const directPath =
|
|
44970
|
-
if (
|
|
45643
|
+
const directPath = join57(MESSAGE_STORAGE, sessionID);
|
|
45644
|
+
if (existsSync49(directPath))
|
|
44971
45645
|
return directPath;
|
|
44972
|
-
for (const dir of
|
|
44973
|
-
const sessionPath =
|
|
44974
|
-
if (
|
|
45646
|
+
for (const dir of readdirSync18(MESSAGE_STORAGE)) {
|
|
45647
|
+
const sessionPath = join57(MESSAGE_STORAGE, dir, sessionID);
|
|
45648
|
+
if (existsSync49(sessionPath))
|
|
44975
45649
|
return sessionPath;
|
|
44976
45650
|
}
|
|
44977
45651
|
return null;
|
|
@@ -62884,6 +63558,7 @@ var HookNameSchema = exports_external2.enum([
|
|
|
62884
63558
|
"auto-slash-command",
|
|
62885
63559
|
"edit-error-recovery",
|
|
62886
63560
|
"delegate-task-retry",
|
|
63561
|
+
"runtime-fallback",
|
|
62887
63562
|
"prometheus-md-only",
|
|
62888
63563
|
"perf-profiler",
|
|
62889
63564
|
"start-work",
|
|
@@ -63058,7 +63733,10 @@ var BackgroundTaskConfigSchema = exports_external2.object({
|
|
|
63058
63733
|
defaultConcurrency: exports_external2.number().min(1).optional(),
|
|
63059
63734
|
providerConcurrency: exports_external2.record(exports_external2.string(), exports_external2.number().min(0)).optional(),
|
|
63060
63735
|
modelConcurrency: exports_external2.record(exports_external2.string(), exports_external2.number().min(0)).optional(),
|
|
63061
|
-
staleTimeoutMs: exports_external2.number().min(60000).optional()
|
|
63736
|
+
staleTimeoutMs: exports_external2.number().min(60000).optional(),
|
|
63737
|
+
maxSteps: exports_external2.number().min(0).optional(),
|
|
63738
|
+
maxRuntimeMs: exports_external2.number().min(0).optional(),
|
|
63739
|
+
stepTimeoutMs: exports_external2.number().min(0).optional()
|
|
63062
63740
|
});
|
|
63063
63741
|
var NotificationConfigSchema = exports_external2.object({
|
|
63064
63742
|
force_enable: exports_external2.boolean().optional()
|
|
@@ -63067,6 +63745,15 @@ var GitMasterConfigSchema = exports_external2.object({
|
|
|
63067
63745
|
commit_footer: exports_external2.boolean().default(true),
|
|
63068
63746
|
include_co_authored_by: exports_external2.boolean().default(true)
|
|
63069
63747
|
});
|
|
63748
|
+
var RuntimeFallbackConfigSchema = exports_external2.object({
|
|
63749
|
+
enabled: exports_external2.boolean().default(true),
|
|
63750
|
+
max_attempts: exports_external2.number().min(0).default(3),
|
|
63751
|
+
initial_delay_ms: exports_external2.number().min(0).default(2000),
|
|
63752
|
+
backoff_factor: exports_external2.number().min(1).default(2),
|
|
63753
|
+
max_delay_ms: exports_external2.number().min(0).default(30000),
|
|
63754
|
+
respect_retry_after: exports_external2.boolean().default(true),
|
|
63755
|
+
jitter: exports_external2.boolean().default(true)
|
|
63756
|
+
});
|
|
63070
63757
|
var OhMyOpenCodeConfigSchema = exports_external2.object({
|
|
63071
63758
|
$schema: exports_external2.string().optional(),
|
|
63072
63759
|
disabled_mcps: exports_external2.array(AnyMcpNameSchema).optional(),
|
|
@@ -63085,7 +63772,8 @@ var OhMyOpenCodeConfigSchema = exports_external2.object({
|
|
|
63085
63772
|
ralph_loop: RalphLoopConfigSchema.optional(),
|
|
63086
63773
|
background_task: BackgroundTaskConfigSchema.optional(),
|
|
63087
63774
|
notification: NotificationConfigSchema.optional(),
|
|
63088
|
-
git_master: GitMasterConfigSchema.optional()
|
|
63775
|
+
git_master: GitMasterConfigSchema.optional(),
|
|
63776
|
+
runtime_fallback: RuntimeFallbackConfigSchema.optional()
|
|
63089
63777
|
});
|
|
63090
63778
|
// src/plugin-config.ts
|
|
63091
63779
|
init_shared();
|
|
@@ -65153,21 +65841,21 @@ TODO \u5217\u8868\uFF1A[\u8DEF\u5F84]
|
|
|
65153
65841
|
|
|
65154
65842
|
**\u5BF9\u4E8E\u63A2\u7D22\uFF08explore/librarian\uFF09**\uFF1A\u59CB\u7EC8\u540E\u53F0\u8FD0\u884C
|
|
65155
65843
|
\`\`\`typescript
|
|
65156
|
-
delegate_task(subagent_type="explore", run_in_background=true, ...)
|
|
65157
|
-
delegate_task(subagent_type="librarian", run_in_background=true, ...)
|
|
65844
|
+
delegate_task(subagent_type="explore", run_in_background=true, load_skills=[], ...)
|
|
65845
|
+
delegate_task(subagent_type="librarian", run_in_background=true, load_skills=[], ...)
|
|
65158
65846
|
\`\`\`
|
|
65159
65847
|
|
|
65160
65848
|
**\u5BF9\u4E8E\u4EFB\u52A1\u6267\u884C**\uFF1A\u7EDD\u4E0D\u7528\u540E\u53F0\u8FD0\u884C
|
|
65161
65849
|
\`\`\`typescript
|
|
65162
|
-
delegate_task(category="...", run_in_background=false, ...)
|
|
65850
|
+
delegate_task(category="...", run_in_background=false, load_skills=[], ...)
|
|
65163
65851
|
\`\`\`
|
|
65164
65852
|
|
|
65165
65853
|
**\u5E76\u884C\u4EFB\u52A1\u7EC4**\uFF1A\u5728\u4E00\u6761\u6D88\u606F\u4E2D\u591A\u6B21\u8C03\u7528
|
|
65166
65854
|
\`\`\`typescript
|
|
65167
65855
|
// \u4EFB\u52A12\u30013\u30014\u662F\u72EC\u7ACB\u7684\u2014\u2014\u4E00\u8D77\u8C03\u7528
|
|
65168
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A12...")
|
|
65169
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A13...")
|
|
65170
|
-
delegate_task(category="quick", prompt="\u4EFB\u52A14...")
|
|
65856
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A12...", load_skills=[])
|
|
65857
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A13...", load_skills=[])
|
|
65858
|
+
delegate_task(category="quick", prompt="\u4EFB\u52A14...", load_skills=[])
|
|
65171
65859
|
\`\`\`
|
|
65172
65860
|
|
|
65173
65861
|
**\u540E\u53F0\u7BA1\u7406**\uFF1A
|
|
@@ -66042,7 +66730,7 @@ init_file_utils();
|
|
|
66042
66730
|
init_shared();
|
|
66043
66731
|
init_logger();
|
|
66044
66732
|
import { promises as fs11 } from "fs";
|
|
66045
|
-
import { join as
|
|
66733
|
+
import { join as join59, basename as basename6 } from "path";
|
|
66046
66734
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
66047
66735
|
try {
|
|
66048
66736
|
await fs11.access(commandsDir);
|
|
@@ -66072,7 +66760,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
66072
66760
|
if (entry.isDirectory()) {
|
|
66073
66761
|
if (entry.name.startsWith("."))
|
|
66074
66762
|
continue;
|
|
66075
|
-
const subDirPath =
|
|
66763
|
+
const subDirPath = join59(commandsDir, entry.name);
|
|
66076
66764
|
const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
66077
66765
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
66078
66766
|
commands2.push(...subCommands);
|
|
@@ -66080,7 +66768,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
66080
66768
|
}
|
|
66081
66769
|
if (!isMarkdownFile(entry))
|
|
66082
66770
|
continue;
|
|
66083
|
-
const commandPath =
|
|
66771
|
+
const commandPath = join59(commandsDir, entry.name);
|
|
66084
66772
|
const baseCommandName = basename6(entry.name, ".md");
|
|
66085
66773
|
const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
|
|
66086
66774
|
try {
|
|
@@ -66127,23 +66815,23 @@ function commandsToRecord(commands2) {
|
|
|
66127
66815
|
return result;
|
|
66128
66816
|
}
|
|
66129
66817
|
async function loadUserCommands() {
|
|
66130
|
-
const userCommandsDir =
|
|
66818
|
+
const userCommandsDir = join59(getClaudeConfigDir(), "commands");
|
|
66131
66819
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
66132
66820
|
return commandsToRecord(commands2);
|
|
66133
66821
|
}
|
|
66134
66822
|
async function loadProjectCommands() {
|
|
66135
|
-
const projectCommandsDir =
|
|
66823
|
+
const projectCommandsDir = join59(process.cwd(), ".claude", "commands");
|
|
66136
66824
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
66137
66825
|
return commandsToRecord(commands2);
|
|
66138
66826
|
}
|
|
66139
66827
|
async function loadOpencodeGlobalCommands() {
|
|
66140
66828
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
66141
|
-
const opencodeCommandsDir =
|
|
66829
|
+
const opencodeCommandsDir = join59(configDir, "command");
|
|
66142
66830
|
const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
66143
66831
|
return commandsToRecord(commands2);
|
|
66144
66832
|
}
|
|
66145
66833
|
async function loadOpencodeProjectCommands() {
|
|
66146
|
-
const opencodeProjectDir =
|
|
66834
|
+
const opencodeProjectDir = join59(process.cwd(), ".opencode", "command");
|
|
66147
66835
|
const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
66148
66836
|
return commandsToRecord(commands2);
|
|
66149
66837
|
}
|
|
@@ -66151,8 +66839,8 @@ async function loadOpencodeProjectCommands() {
|
|
|
66151
66839
|
init_frontmatter();
|
|
66152
66840
|
init_file_utils();
|
|
66153
66841
|
init_shared();
|
|
66154
|
-
import { existsSync as
|
|
66155
|
-
import { join as
|
|
66842
|
+
import { existsSync as existsSync51, readdirSync as readdirSync19, readFileSync as readFileSync31 } from "fs";
|
|
66843
|
+
import { join as join60, basename as basename7 } from "path";
|
|
66156
66844
|
function parseToolsConfig(toolsStr) {
|
|
66157
66845
|
if (!toolsStr)
|
|
66158
66846
|
return;
|
|
@@ -66166,15 +66854,15 @@ function parseToolsConfig(toolsStr) {
|
|
|
66166
66854
|
return result;
|
|
66167
66855
|
}
|
|
66168
66856
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
66169
|
-
if (!
|
|
66857
|
+
if (!existsSync51(agentsDir)) {
|
|
66170
66858
|
return [];
|
|
66171
66859
|
}
|
|
66172
|
-
const entries =
|
|
66860
|
+
const entries = readdirSync19(agentsDir, { withFileTypes: true });
|
|
66173
66861
|
const agents = [];
|
|
66174
66862
|
for (const entry of entries) {
|
|
66175
66863
|
if (!isMarkdownFile(entry))
|
|
66176
66864
|
continue;
|
|
66177
|
-
const agentPath =
|
|
66865
|
+
const agentPath = join60(agentsDir, entry.name);
|
|
66178
66866
|
const agentName = basename7(entry.name, ".md");
|
|
66179
66867
|
try {
|
|
66180
66868
|
const content = readFileSync31(agentPath, "utf-8");
|
|
@@ -66204,7 +66892,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
66204
66892
|
return agents;
|
|
66205
66893
|
}
|
|
66206
66894
|
function loadUserAgents() {
|
|
66207
|
-
const userAgentsDir =
|
|
66895
|
+
const userAgentsDir = join60(getClaudeConfigDir(), "agents");
|
|
66208
66896
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
66209
66897
|
const result = {};
|
|
66210
66898
|
for (const agent of agents) {
|
|
@@ -66213,7 +66901,7 @@ function loadUserAgents() {
|
|
|
66213
66901
|
return result;
|
|
66214
66902
|
}
|
|
66215
66903
|
function loadProjectAgents() {
|
|
66216
|
-
const projectAgentsDir =
|
|
66904
|
+
const projectAgentsDir = join60(process.cwd(), ".claude", "agents");
|
|
66217
66905
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
66218
66906
|
const result = {};
|
|
66219
66907
|
for (const agent of agents) {
|
|
@@ -66225,18 +66913,18 @@ function loadProjectAgents() {
|
|
|
66225
66913
|
init_frontmatter();
|
|
66226
66914
|
init_file_utils();
|
|
66227
66915
|
init_logger();
|
|
66228
|
-
import { existsSync as
|
|
66916
|
+
import { existsSync as existsSync52, readdirSync as readdirSync20, readFileSync as readFileSync32 } from "fs";
|
|
66229
66917
|
import { homedir as homedir13 } from "os";
|
|
66230
|
-
import { join as
|
|
66918
|
+
import { join as join61, basename as basename8 } from "path";
|
|
66231
66919
|
var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
66232
66920
|
function getPluginsBaseDir() {
|
|
66233
66921
|
if (process.env.CLAUDE_PLUGINS_HOME) {
|
|
66234
66922
|
return process.env.CLAUDE_PLUGINS_HOME;
|
|
66235
66923
|
}
|
|
66236
|
-
return
|
|
66924
|
+
return join61(homedir13(), ".claude", "plugins");
|
|
66237
66925
|
}
|
|
66238
66926
|
function getInstalledPluginsPath() {
|
|
66239
|
-
return
|
|
66927
|
+
return join61(getPluginsBaseDir(), "installed_plugins.json");
|
|
66240
66928
|
}
|
|
66241
66929
|
function resolvePluginPath(path8, pluginRoot) {
|
|
66242
66930
|
return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
|
|
@@ -66261,7 +66949,7 @@ function resolvePluginPaths(obj, pluginRoot) {
|
|
|
66261
66949
|
}
|
|
66262
66950
|
function loadInstalledPlugins() {
|
|
66263
66951
|
const dbPath = getInstalledPluginsPath();
|
|
66264
|
-
if (!
|
|
66952
|
+
if (!existsSync52(dbPath)) {
|
|
66265
66953
|
return null;
|
|
66266
66954
|
}
|
|
66267
66955
|
try {
|
|
@@ -66276,11 +66964,11 @@ function getClaudeSettingsPath() {
|
|
|
66276
66964
|
if (process.env.CLAUDE_SETTINGS_PATH) {
|
|
66277
66965
|
return process.env.CLAUDE_SETTINGS_PATH;
|
|
66278
66966
|
}
|
|
66279
|
-
return
|
|
66967
|
+
return join61(homedir13(), ".claude", "settings.json");
|
|
66280
66968
|
}
|
|
66281
66969
|
function loadClaudeSettings() {
|
|
66282
66970
|
const settingsPath = getClaudeSettingsPath();
|
|
66283
|
-
if (!
|
|
66971
|
+
if (!existsSync52(settingsPath)) {
|
|
66284
66972
|
return null;
|
|
66285
66973
|
}
|
|
66286
66974
|
try {
|
|
@@ -66292,8 +66980,8 @@ function loadClaudeSettings() {
|
|
|
66292
66980
|
}
|
|
66293
66981
|
}
|
|
66294
66982
|
function loadPluginManifest(installPath) {
|
|
66295
|
-
const manifestPath =
|
|
66296
|
-
if (!
|
|
66983
|
+
const manifestPath = join61(installPath, ".claude-plugin", "plugin.json");
|
|
66984
|
+
if (!existsSync52(manifestPath)) {
|
|
66297
66985
|
return null;
|
|
66298
66986
|
}
|
|
66299
66987
|
try {
|
|
@@ -66344,7 +67032,7 @@ function discoverInstalledPlugins(options) {
|
|
|
66344
67032
|
continue;
|
|
66345
67033
|
}
|
|
66346
67034
|
const { installPath, scope, version: version3 } = installation;
|
|
66347
|
-
if (!
|
|
67035
|
+
if (!existsSync52(installPath)) {
|
|
66348
67036
|
errors5.push({
|
|
66349
67037
|
pluginKey,
|
|
66350
67038
|
installPath,
|
|
@@ -66362,21 +67050,21 @@ function discoverInstalledPlugins(options) {
|
|
|
66362
67050
|
pluginKey,
|
|
66363
67051
|
manifest: manifest ?? undefined
|
|
66364
67052
|
};
|
|
66365
|
-
if (
|
|
66366
|
-
loadedPlugin.commandsDir =
|
|
67053
|
+
if (existsSync52(join61(installPath, "commands"))) {
|
|
67054
|
+
loadedPlugin.commandsDir = join61(installPath, "commands");
|
|
66367
67055
|
}
|
|
66368
|
-
if (
|
|
66369
|
-
loadedPlugin.agentsDir =
|
|
67056
|
+
if (existsSync52(join61(installPath, "agents"))) {
|
|
67057
|
+
loadedPlugin.agentsDir = join61(installPath, "agents");
|
|
66370
67058
|
}
|
|
66371
|
-
if (
|
|
66372
|
-
loadedPlugin.skillsDir =
|
|
67059
|
+
if (existsSync52(join61(installPath, "skills"))) {
|
|
67060
|
+
loadedPlugin.skillsDir = join61(installPath, "skills");
|
|
66373
67061
|
}
|
|
66374
|
-
const hooksPath =
|
|
66375
|
-
if (
|
|
67062
|
+
const hooksPath = join61(installPath, "hooks", "hooks.json");
|
|
67063
|
+
if (existsSync52(hooksPath)) {
|
|
66376
67064
|
loadedPlugin.hooksPath = hooksPath;
|
|
66377
67065
|
}
|
|
66378
|
-
const mcpPath =
|
|
66379
|
-
if (
|
|
67066
|
+
const mcpPath = join61(installPath, ".mcp.json");
|
|
67067
|
+
if (existsSync52(mcpPath)) {
|
|
66380
67068
|
loadedPlugin.mcpPath = mcpPath;
|
|
66381
67069
|
}
|
|
66382
67070
|
plugins.push(loadedPlugin);
|
|
@@ -66387,13 +67075,13 @@ function discoverInstalledPlugins(options) {
|
|
|
66387
67075
|
function loadPluginCommands(plugins) {
|
|
66388
67076
|
const commands2 = {};
|
|
66389
67077
|
for (const plugin of plugins) {
|
|
66390
|
-
if (!plugin.commandsDir || !
|
|
67078
|
+
if (!plugin.commandsDir || !existsSync52(plugin.commandsDir))
|
|
66391
67079
|
continue;
|
|
66392
|
-
const entries =
|
|
67080
|
+
const entries = readdirSync20(plugin.commandsDir, { withFileTypes: true });
|
|
66393
67081
|
for (const entry of entries) {
|
|
66394
67082
|
if (!isMarkdownFile(entry))
|
|
66395
67083
|
continue;
|
|
66396
|
-
const commandPath =
|
|
67084
|
+
const commandPath = join61(plugin.commandsDir, entry.name);
|
|
66397
67085
|
const commandName = basename8(entry.name, ".md");
|
|
66398
67086
|
const namespacedName = `${plugin.name}:${commandName}`;
|
|
66399
67087
|
try {
|
|
@@ -66429,18 +67117,18 @@ $ARGUMENTS
|
|
|
66429
67117
|
function loadPluginSkillsAsCommands(plugins) {
|
|
66430
67118
|
const skills = {};
|
|
66431
67119
|
for (const plugin of plugins) {
|
|
66432
|
-
if (!plugin.skillsDir || !
|
|
67120
|
+
if (!plugin.skillsDir || !existsSync52(plugin.skillsDir))
|
|
66433
67121
|
continue;
|
|
66434
|
-
const entries =
|
|
67122
|
+
const entries = readdirSync20(plugin.skillsDir, { withFileTypes: true });
|
|
66435
67123
|
for (const entry of entries) {
|
|
66436
67124
|
if (entry.name.startsWith("."))
|
|
66437
67125
|
continue;
|
|
66438
|
-
const skillPath =
|
|
67126
|
+
const skillPath = join61(plugin.skillsDir, entry.name);
|
|
66439
67127
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
66440
67128
|
continue;
|
|
66441
67129
|
const resolvedPath = resolveSymlink(skillPath);
|
|
66442
|
-
const skillMdPath =
|
|
66443
|
-
if (!
|
|
67130
|
+
const skillMdPath = join61(resolvedPath, "SKILL.md");
|
|
67131
|
+
if (!existsSync52(skillMdPath))
|
|
66444
67132
|
continue;
|
|
66445
67133
|
try {
|
|
66446
67134
|
const content = readFileSync32(skillMdPath, "utf-8");
|
|
@@ -66490,13 +67178,13 @@ function parseToolsConfig2(toolsStr) {
|
|
|
66490
67178
|
function loadPluginAgents(plugins) {
|
|
66491
67179
|
const agents = {};
|
|
66492
67180
|
for (const plugin of plugins) {
|
|
66493
|
-
if (!plugin.agentsDir || !
|
|
67181
|
+
if (!plugin.agentsDir || !existsSync52(plugin.agentsDir))
|
|
66494
67182
|
continue;
|
|
66495
|
-
const entries =
|
|
67183
|
+
const entries = readdirSync20(plugin.agentsDir, { withFileTypes: true });
|
|
66496
67184
|
for (const entry of entries) {
|
|
66497
67185
|
if (!isMarkdownFile(entry))
|
|
66498
67186
|
continue;
|
|
66499
|
-
const agentPath =
|
|
67187
|
+
const agentPath = join61(plugin.agentsDir, entry.name);
|
|
66500
67188
|
const agentName = basename8(entry.name, ".md");
|
|
66501
67189
|
const namespacedName = `${plugin.name}:${agentName}`;
|
|
66502
67190
|
try {
|
|
@@ -66526,7 +67214,7 @@ function loadPluginAgents(plugins) {
|
|
|
66526
67214
|
async function loadPluginMcpServers(plugins) {
|
|
66527
67215
|
const servers = {};
|
|
66528
67216
|
for (const plugin of plugins) {
|
|
66529
|
-
if (!plugin.mcpPath || !
|
|
67217
|
+
if (!plugin.mcpPath || !existsSync52(plugin.mcpPath))
|
|
66530
67218
|
continue;
|
|
66531
67219
|
try {
|
|
66532
67220
|
const content = await Bun.file(plugin.mcpPath).text();
|
|
@@ -66558,7 +67246,7 @@ async function loadPluginMcpServers(plugins) {
|
|
|
66558
67246
|
function loadPluginHooksConfigs(plugins) {
|
|
66559
67247
|
const configs = [];
|
|
66560
67248
|
for (const plugin of plugins) {
|
|
66561
|
-
if (!plugin.hooksPath || !
|
|
67249
|
+
if (!plugin.hooksPath || !existsSync52(plugin.hooksPath))
|
|
66562
67250
|
continue;
|
|
66563
67251
|
try {
|
|
66564
67252
|
const content = readFileSync32(plugin.hooksPath, "utf-8");
|
|
@@ -66947,8 +67635,8 @@ Prometheus\uFF1A"\u5FEB\u901F\u4FEE\u590D\u2014\u2014\u6211\u770B\u5230\u62FC\u5
|
|
|
66947
67635
|
|
|
66948
67636
|
**\u5148\u505A\u7814\u7A76\uFF1A**
|
|
66949
67637
|
\`\`\`typescript
|
|
66950
|
-
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)
|
|
66951
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u53D7\u5F71\u54CD\u4EE3\u7801] \u7684\u6D4B\u8BD5\u8986\u76D6\u7387...", run_in_background=true)
|
|
67638
|
+
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=[])
|
|
67639
|
+
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=[])
|
|
66952
67640
|
\`\`\`
|
|
66953
67641
|
|
|
66954
67642
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -66971,9 +67659,9 @@ delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u53D7\u5F71\u54CD\
|
|
|
66971
67659
|
**\u8BBF\u8C08\u524D\u7814\u7A76\uFF08\u5F3A\u5236\u8981\u6C42\uFF09\uFF1A**
|
|
66972
67660
|
\`\`\`typescript
|
|
66973
67661
|
// \u5728\u5411\u7528\u6237\u63D0\u95EE\u4E4B\u524D\u542F\u52A8
|
|
66974
|
-
delegate_task(subagent_type="explore", prompt="\u5728\u4EE3\u7801\u5E93\u4E2D\u67E5\u627E\u7C7B\u4F3C\u5B9E\u73B0...", run_in_background=true)
|
|
66975
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u529F\u80FD\u7C7B\u578B] \u7684\u9879\u76EE\u6A21\u5F0F...", run_in_background=true)
|
|
66976
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u6280\u672F] \u7684\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true)
|
|
67662
|
+
delegate_task(subagent_type="explore", prompt="\u5728\u4EE3\u7801\u5E93\u4E2D\u67E5\u627E\u7C7B\u4F3C\u5B9E\u73B0...", run_in_background=true, load_skills=[])
|
|
67663
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E [\u529F\u80FD\u7C7B\u578B] \u7684\u9879\u76EE\u6A21\u5F0F...", run_in_background=true, load_skills=[])
|
|
67664
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u6280\u672F] \u7684\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true, load_skills=[])
|
|
66977
67665
|
\`\`\`
|
|
66978
67666
|
|
|
66979
67667
|
**\u8BBF\u8C08\u91CD\u70B9**\uFF08\u7814\u7A76\u4E4B\u540E\uFF09\uFF1A
|
|
@@ -67012,7 +67700,7 @@ Prometheus\uFF1A"\u6211\u53D1\u73B0\u4E86\u4E00\u4E9B\u60C5\u51B5\uFF1A
|
|
|
67012
67700
|
|
|
67013
67701
|
\u8FD0\u884C\u6B64\u68C0\u67E5\uFF1A
|
|
67014
67702
|
\`\`\`typescript
|
|
67015
|
-
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)
|
|
67703
|
+
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=[])
|
|
67016
67704
|
\`\`\`
|
|
67017
67705
|
|
|
67018
67706
|
#### \u7B2C2\u6B65\uFF1A\u8BE2\u95EE\u6D4B\u8BD5\u95EE\u9898\uFF08\u5F3A\u5236\u8981\u6C42\uFF09
|
|
@@ -67101,13 +67789,13 @@ delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u6D4B\u8BD5\u57FA\u7
|
|
|
67101
67789
|
|
|
67102
67790
|
**\u5148\u505A\u7814\u7A76\uFF1A**
|
|
67103
67791
|
\`\`\`typescript
|
|
67104
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u5F53\u524D\u7CFB\u7EDF\u67B6\u6784\u548C\u6A21\u5F0F...", run_in_background=true)
|
|
67105
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u9886\u57DF] \u7684\u67B6\u6784\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true)
|
|
67792
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E\u5F53\u524D\u7CFB\u7EDF\u67B6\u6784\u548C\u6A21\u5F0F...", run_in_background=true, load_skills=[])
|
|
67793
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E [\u9886\u57DF] \u7684\u67B6\u6784\u6700\u4F73\u5B9E\u8DF5...", run_in_background=true, load_skills=[])
|
|
67106
67794
|
\`\`\`
|
|
67107
67795
|
|
|
67108
67796
|
**Oracle \u54A8\u8BE2**\uFF08\u5F53\u98CE\u9669\u8F83\u9AD8\u65F6\u63A8\u8350\uFF09\uFF1A
|
|
67109
67797
|
\`\`\`typescript
|
|
67110
|
-
delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8BE2\uFF1A[\u4E0A\u4E0B\u6587]...", run_in_background=false)
|
|
67798
|
+
delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8BE2\uFF1A[\u4E0A\u4E0B\u6587]...", run_in_background=false, load_skills=[])
|
|
67111
67799
|
\`\`\`
|
|
67112
67800
|
|
|
67113
67801
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -67124,9 +67812,9 @@ delegate_task(subagent_type="oracle", prompt="\u9700\u8981\u67B6\u6784\u54A8\u8B
|
|
|
67124
67812
|
|
|
67125
67813
|
**\u5E76\u884C\u8C03\u7814\uFF1A**
|
|
67126
67814
|
\`\`\`typescript
|
|
67127
|
-
delegate_task(subagent_type="explore", prompt="\u67E5\u627E X \u5F53\u524D\u662F\u5982\u4F55\u5904\u7406\u7684...", run_in_background=true)
|
|
67128
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Y \u7684\u5B98\u65B9\u6587\u6863...", run_in_background=true)
|
|
67129
|
-
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E90\u5B9E\u73B0...", run_in_background=true)
|
|
67815
|
+
delegate_task(subagent_type="explore", prompt="\u67E5\u627E X \u5F53\u524D\u662F\u5982\u4F55\u5904\u7406\u7684...", run_in_background=true, load_skills=[])
|
|
67816
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Y \u7684\u5B98\u65B9\u6587\u6863...", run_in_background=true, load_skills=[])
|
|
67817
|
+
delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E90\u5B9E\u73B0...", run_in_background=true, load_skills=[])
|
|
67130
67818
|
\`\`\`
|
|
67131
67819
|
|
|
67132
67820
|
**\u8BBF\u8C08\u91CD\u70B9\uFF1A**
|
|
@@ -67152,17 +67840,17 @@ delegate_task(subagent_type="librarian", prompt="\u67E5\u627E Z \u7684\u5F00\u6E
|
|
|
67152
67840
|
|
|
67153
67841
|
**\u7528\u4E8E\u7406\u89E3\u4EE3\u7801\u5E93\uFF1A**
|
|
67154
67842
|
\`\`\`typescript
|
|
67155
|
-
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)
|
|
67843
|
+
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=[])
|
|
67156
67844
|
\`\`\`
|
|
67157
67845
|
|
|
67158
67846
|
**\u7528\u4E8E\u5916\u90E8\u77E5\u8BC6\uFF1A**
|
|
67159
67847
|
\`\`\`typescript
|
|
67160
|
-
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)
|
|
67848
|
+
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=[])
|
|
67161
67849
|
\`\`\`
|
|
67162
67850
|
|
|
67163
67851
|
**\u7528\u4E8E\u5B9E\u73B0\u793A\u4F8B\uFF1A**
|
|
67164
67852
|
\`\`\`typescript
|
|
67165
|
-
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)
|
|
67853
|
+
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=[])
|
|
67166
67854
|
\`\`\`
|
|
67167
67855
|
|
|
67168
67856
|
## \u8BBF\u8C08\u6A21\u5F0F\u53CD\u6A21\u5F0F
|
|
@@ -67260,6 +67948,7 @@ todoWrite([
|
|
|
67260
67948
|
\`\`\`typescript
|
|
67261
67949
|
delegate_task(
|
|
67262
67950
|
subagent_type="metis",
|
|
67951
|
+
load_skills=[],
|
|
67263
67952
|
prompt=\`\u5728\u6211\u751F\u6210\u5DE5\u4F5C\u8BA1\u5212\u4E4B\u524D\uFF0C\u5BA1\u67E5\u8FD9\u6B21\u89C4\u5212\u4F1A\u8BDD\uFF1A
|
|
67264
67953
|
|
|
67265
67954
|
**\u7528\u6237\u76EE\u6807**\uFF1A{\u603B\u7ED3\u7528\u6237\u60F3\u8981\u4EC0\u4E48}
|
|
@@ -67427,7 +68116,7 @@ while (true) {
|
|
|
67427
68116
|
const result = delegate_task(
|
|
67428
68117
|
subagent_type="momus",
|
|
67429
68118
|
prompt=".sisyphus/plans/{name}.md",
|
|
67430
|
-
run_in_background=false
|
|
68119
|
+
run_in_background=false, load_skills=[]
|
|
67431
68120
|
)
|
|
67432
68121
|
|
|
67433
68122
|
if (result.verdict === "OKAY") {
|
|
@@ -68130,6 +68819,13 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
68130
68819
|
log("[OhMyOpenCodePlugin] ENTRY - plugin loading", { directory: ctx.directory });
|
|
68131
68820
|
startBackgroundCheck2();
|
|
68132
68821
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx);
|
|
68822
|
+
if (process.platform === "win32") {
|
|
68823
|
+
const reservedNames = scanForReservedNames(ctx.directory, 3);
|
|
68824
|
+
if (reservedNames.length > 0) {
|
|
68825
|
+
console.warn(formatReservedNamesWarning(reservedNames));
|
|
68826
|
+
log("[oh-my-opencode] Windows reserved device names detected:", reservedNames);
|
|
68827
|
+
}
|
|
68828
|
+
}
|
|
68133
68829
|
const disabledHooks = new Set(pluginConfig.disabled_hooks ?? []);
|
|
68134
68830
|
const firstMessageVariantGate = createFirstMessageVariantGate();
|
|
68135
68831
|
const isHookEnabled = (hookName) => !disabledHooks.has(hookName);
|