@skj1724/oh-my-opencode 3.22.0 → 3.23.1
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/btw-advisor.d.ts +5 -0
- package/dist/agents/btw-advisor.test.d.ts +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/types.d.ts +1 -1
- package/dist/cli/index.js +20 -7
- package/dist/config/schema.d.ts +137 -3
- package/dist/features/boulder-state/event-bus.d.ts +9 -1
- package/dist/features/boulder-state/storage.d.ts +1 -0
- package/dist/features/boulder-state/types.d.ts +5 -0
- package/dist/features/boulder-state/types.test.d.ts +1 -0
- package/dist/features/builtin-commands/templates/btw.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/hooks/atlas/plan-completion.test.d.ts +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/plan-completion/archive.test.d.ts +1 -0
- package/dist/hooks/plan-completion/extract-learnings.test.d.ts +1 -0
- package/dist/hooks/plan-completion/generate-report.test.d.ts +1 -0
- package/dist/hooks/plan-completion/index.d.ts +13 -0
- package/dist/hooks/plan-completion/index.test.d.ts +1 -0
- package/dist/hooks/plan-completion/integration.test.d.ts +1 -0
- package/dist/hooks/plan-completion/update-summary.test.d.ts +1 -0
- package/dist/index.js +761 -272
- package/dist/shared/frontmatter.d.ts +7 -0
- package/dist/tools/btw/constants.d.ts +1 -0
- package/dist/tools/btw/index.d.ts +3 -0
- package/dist/tools/btw/post-processor.d.ts +1 -0
- package/dist/tools/btw/post-processor.test.d.ts +1 -0
- package/dist/tools/btw/tools.d.ts +3 -0
- package/dist/tools/btw/tools.test.d.ts +1 -0
- package/dist/tools/btw/types.d.ts +3 -0
- package/dist/tools/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -104,7 +104,8 @@ var init_agent_display_names = __esm(() => {
|
|
|
104
104
|
"\u6280\u672F\u53C2\u8C0B": "oracle",
|
|
105
105
|
"\u77E5\u8BC6\u5178\u85CF": "librarian",
|
|
106
106
|
"\u6DF1\u5EA6\u63A2\u7D22": "explore",
|
|
107
|
-
"\u5A92\u4F53\u89E3\u6790": "multimodal-looker"
|
|
107
|
+
"\u5A92\u4F53\u89E3\u6790": "multimodal-looker",
|
|
108
|
+
"BTW \u987E\u95EE": "btw-advisor"
|
|
108
109
|
};
|
|
109
110
|
AGENT_ROLE_DESCRIPTIONS = {
|
|
110
111
|
"\u4E3B\u6267\u884C\u5B98": "\u8D1F\u8D23\u7F16\u6392\u4EFB\u52A1\u3001\u8C03\u7528\u5DE5\u5177\u3001\u59D4\u6D3E\u5B50\u4EFB\u52A1\u3001\u9A8C\u8BC1\u7ED3\u679C\u7684\u4E3B\u7F16\u6392\u5668\u3002",
|
|
@@ -116,7 +117,8 @@ var init_agent_display_names = __esm(() => {
|
|
|
116
117
|
"\u77E5\u8BC6\u5178\u85CF": "\u8D1F\u8D23\u6587\u6863\u641C\u7D22\u3001GitHub \u641C\u7D22\u7684\u53EA\u8BFB\u7814\u7A76\u5458\u3002",
|
|
117
118
|
"\u6DF1\u5EA6\u63A2\u7D22": "\u8D1F\u8D23\u4EE3\u7801\u5E93\u641C\u7D22\u3001\u6A21\u5F0F\u53D1\u73B0\u7684\u53EA\u8BFB\u63A2\u7D22\u8005\u3002",
|
|
118
119
|
"\u5A92\u4F53\u89E3\u6790": "\u8D1F\u8D23 PDF/\u56FE\u7247\u5206\u6790\u7684\u53EA\u8BFB\u89E3\u6790\u8005\u3002",
|
|
119
|
-
"\u6267\u884C\u52A9\u7406": "\u8D1F\u8D23\u4E13\u6CE8\u4EFB\u52A1\u6267\u884C\u3001\u65E0\u59D4\u6D3E\u6743\u9650\u7684\u6267\u884C\u8005\u3002"
|
|
120
|
+
"\u6267\u884C\u52A9\u7406": "\u8D1F\u8D23\u4E13\u6CE8\u4EFB\u52A1\u6267\u884C\u3001\u65E0\u59D4\u6D3E\u6743\u9650\u7684\u6267\u884C\u8005\u3002",
|
|
121
|
+
"BTW \u987E\u95EE": "\u8D1F\u8D23\u5FEB\u901F\u4EE3\u7801\u67E5\u8BE2\u3001\u4E0D\u6C61\u67D3\u4E3B\u5BF9\u8BDD\u7684\u53EA\u8BFB\u8F7B\u91CF\u987E\u95EE\u3002"
|
|
120
122
|
};
|
|
121
123
|
AGENT_DISPLAY_TO_KEY = {
|
|
122
124
|
sisyphus: "\u4E3B\u6267\u884C\u5B98",
|
|
@@ -3997,6 +3999,7 @@ var init_js_yaml = __esm(() => {
|
|
|
3997
3999
|
});
|
|
3998
4000
|
|
|
3999
4001
|
// src/shared/frontmatter.ts
|
|
4002
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
4000
4003
|
function parseFrontmatter(content) {
|
|
4001
4004
|
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n?---\r?\n([\s\S]*)$/;
|
|
4002
4005
|
const match = content.match(frontmatterRegex);
|
|
@@ -4013,6 +4016,28 @@ function parseFrontmatter(content) {
|
|
|
4013
4016
|
return { data: {}, body, hadFrontmatter: true, parseError: true };
|
|
4014
4017
|
}
|
|
4015
4018
|
}
|
|
4019
|
+
function parseCompletionActions(planPath) {
|
|
4020
|
+
try {
|
|
4021
|
+
const content = readFileSync6(planPath, "utf-8");
|
|
4022
|
+
const result = parseFrontmatter(content);
|
|
4023
|
+
if (!result.hadFrontmatter || result.parseError) {
|
|
4024
|
+
return [];
|
|
4025
|
+
}
|
|
4026
|
+
const raw = result.data.completion_actions;
|
|
4027
|
+
if (!Array.isArray(raw)) {
|
|
4028
|
+
return [];
|
|
4029
|
+
}
|
|
4030
|
+
return raw.filter(isValidCompletionAction);
|
|
4031
|
+
} catch {
|
|
4032
|
+
return [];
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
function isValidCompletionAction(item) {
|
|
4036
|
+
if (typeof item !== "object" || item === null)
|
|
4037
|
+
return false;
|
|
4038
|
+
const obj = item;
|
|
4039
|
+
return typeof obj.type === "string" && typeof obj.enabled === "boolean";
|
|
4040
|
+
}
|
|
4016
4041
|
var init_frontmatter = __esm(() => {
|
|
4017
4042
|
init_js_yaml();
|
|
4018
4043
|
});
|
|
@@ -4166,7 +4191,7 @@ var init_command_executor = __esm(() => {
|
|
|
4166
4191
|
});
|
|
4167
4192
|
|
|
4168
4193
|
// src/shared/file-reference-resolver.ts
|
|
4169
|
-
import { existsSync as existsSync8, readFileSync as
|
|
4194
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, statSync } from "fs";
|
|
4170
4195
|
import { join as join9, isAbsolute } from "path";
|
|
4171
4196
|
function findFileReferences(text) {
|
|
4172
4197
|
const matches = [];
|
|
@@ -4196,7 +4221,7 @@ function readFileContent(resolvedPath) {
|
|
|
4196
4221
|
if (stat.isDirectory()) {
|
|
4197
4222
|
return `[cannot read directory: ${resolvedPath}]`;
|
|
4198
4223
|
}
|
|
4199
|
-
const content =
|
|
4224
|
+
const content = readFileSync7(resolvedPath, "utf-8");
|
|
4200
4225
|
return content;
|
|
4201
4226
|
}
|
|
4202
4227
|
async function resolveFileReferencesInText(text, cwd2 = process.cwd(), depth = 0, maxDepth = 3) {
|
|
@@ -5027,6 +5052,15 @@ var init_agent_tool_restrictions = __esm(() => {
|
|
|
5027
5052
|
"\u6267\u884C\u52A9\u7406": {
|
|
5028
5053
|
task: false,
|
|
5029
5054
|
delegate_task: false
|
|
5055
|
+
},
|
|
5056
|
+
"BTW \u987E\u95EE": {
|
|
5057
|
+
write: false,
|
|
5058
|
+
edit: false,
|
|
5059
|
+
bash: false,
|
|
5060
|
+
task: false,
|
|
5061
|
+
delegate_task: false,
|
|
5062
|
+
call_omo_agent: false,
|
|
5063
|
+
slashcommand: false
|
|
5030
5064
|
}
|
|
5031
5065
|
};
|
|
5032
5066
|
});
|
|
@@ -5101,6 +5135,13 @@ var init_model_requirements = __esm(() => {
|
|
|
5101
5135
|
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
|
|
5102
5136
|
]
|
|
5103
5137
|
},
|
|
5138
|
+
"BTW \u987E\u95EE": {
|
|
5139
|
+
fallbackChain: [
|
|
5140
|
+
{ providers: ["deepseek", "volcengine"], model: "deepseek-v4-flash" },
|
|
5141
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
5142
|
+
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
5143
|
+
]
|
|
5144
|
+
},
|
|
5104
5145
|
"\u4EFB\u52A1\u7F16\u6392": {
|
|
5105
5146
|
fallbackChain: [
|
|
5106
5147
|
{ providers: ["deepseek", "volcengine"], model: "deepseek-v4-pro" },
|
|
@@ -5173,7 +5214,7 @@ var init_model_requirements = __esm(() => {
|
|
|
5173
5214
|
});
|
|
5174
5215
|
|
|
5175
5216
|
// src/shared/model-availability.ts
|
|
5176
|
-
import { existsSync as existsSync10, readFileSync as
|
|
5217
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
5177
5218
|
import { homedir as homedir6 } from "os";
|
|
5178
5219
|
import { join as join12 } from "path";
|
|
5179
5220
|
function normalizeModelName(name) {
|
|
@@ -5233,7 +5274,7 @@ async function fetchAvailableModels(_client) {
|
|
|
5233
5274
|
return modelSet;
|
|
5234
5275
|
}
|
|
5235
5276
|
try {
|
|
5236
|
-
const content =
|
|
5277
|
+
const content = readFileSync9(cacheFile, "utf-8");
|
|
5237
5278
|
const data = JSON.parse(content);
|
|
5238
5279
|
const providerIds = Object.keys(data);
|
|
5239
5280
|
log("[fetchAvailableModels] providers found", { count: providerIds.length, providers: providerIds.slice(0, 10) });
|
|
@@ -5820,7 +5861,7 @@ var init_windows_reserved_names = __esm(() => {
|
|
|
5820
5861
|
});
|
|
5821
5862
|
|
|
5822
5863
|
// src/shared/usage-tracker.ts
|
|
5823
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as
|
|
5864
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
5824
5865
|
import { homedir as homedir7 } from "os";
|
|
5825
5866
|
import { join as join15 } from "path";
|
|
5826
5867
|
function getStatsFilePath() {
|
|
@@ -5953,7 +5994,7 @@ class UsageTracker {
|
|
|
5953
5994
|
const filePath = getStatsFilePath();
|
|
5954
5995
|
if (!existsSync13(filePath))
|
|
5955
5996
|
return;
|
|
5956
|
-
const content =
|
|
5997
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
5957
5998
|
const data = JSON.parse(content);
|
|
5958
5999
|
if (data.sessions) {
|
|
5959
6000
|
for (const [sessionID, sessionData] of Object.entries(data.sessions)) {
|
|
@@ -17625,14 +17666,14 @@ function createToolOutputTruncatorHook(ctx, options) {
|
|
|
17625
17666
|
};
|
|
17626
17667
|
}
|
|
17627
17668
|
// src/hooks/directory-agents-injector/index.ts
|
|
17628
|
-
import { existsSync as existsSync18, readFileSync as
|
|
17669
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
17629
17670
|
import { dirname as dirname2, join as join21, resolve as resolve3 } from "path";
|
|
17630
17671
|
|
|
17631
17672
|
// src/hooks/directory-agents-injector/storage.ts
|
|
17632
17673
|
import {
|
|
17633
17674
|
existsSync as existsSync17,
|
|
17634
17675
|
mkdirSync as mkdirSync7,
|
|
17635
|
-
readFileSync as
|
|
17676
|
+
readFileSync as readFileSync11,
|
|
17636
17677
|
writeFileSync as writeFileSync7,
|
|
17637
17678
|
unlinkSync as unlinkSync3
|
|
17638
17679
|
} from "fs";
|
|
@@ -17654,7 +17695,7 @@ function loadInjectedPaths(sessionID) {
|
|
|
17654
17695
|
if (!existsSync17(filePath))
|
|
17655
17696
|
return new Set;
|
|
17656
17697
|
try {
|
|
17657
|
-
const content =
|
|
17698
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
17658
17699
|
const data = JSON.parse(content);
|
|
17659
17700
|
return new Set(data.injectedPaths);
|
|
17660
17701
|
} catch {
|
|
@@ -17732,7 +17773,7 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
17732
17773
|
if (cache.has(agentsDir))
|
|
17733
17774
|
continue;
|
|
17734
17775
|
try {
|
|
17735
|
-
const content =
|
|
17776
|
+
const content = readFileSync12(agentsPath, "utf-8");
|
|
17736
17777
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
17737
17778
|
const truncationNotice = truncated ? `
|
|
17738
17779
|
|
|
@@ -17802,14 +17843,14 @@ ${result}${truncationNotice}`;
|
|
|
17802
17843
|
};
|
|
17803
17844
|
}
|
|
17804
17845
|
// src/hooks/directory-readme-injector/index.ts
|
|
17805
|
-
import { existsSync as existsSync20, readFileSync as
|
|
17846
|
+
import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
|
|
17806
17847
|
import { dirname as dirname3, join as join24, resolve as resolve4 } from "path";
|
|
17807
17848
|
|
|
17808
17849
|
// src/hooks/directory-readme-injector/storage.ts
|
|
17809
17850
|
import {
|
|
17810
17851
|
existsSync as existsSync19,
|
|
17811
17852
|
mkdirSync as mkdirSync8,
|
|
17812
|
-
readFileSync as
|
|
17853
|
+
readFileSync as readFileSync13,
|
|
17813
17854
|
writeFileSync as writeFileSync8,
|
|
17814
17855
|
unlinkSync as unlinkSync4
|
|
17815
17856
|
} from "fs";
|
|
@@ -17831,7 +17872,7 @@ function loadInjectedPaths2(sessionID) {
|
|
|
17831
17872
|
if (!existsSync19(filePath))
|
|
17832
17873
|
return new Set;
|
|
17833
17874
|
try {
|
|
17834
|
-
const content =
|
|
17875
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
17835
17876
|
const data = JSON.parse(content);
|
|
17836
17877
|
return new Set(data.injectedPaths);
|
|
17837
17878
|
} catch {
|
|
@@ -17906,7 +17947,7 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
17906
17947
|
if (cache.has(readmeDir))
|
|
17907
17948
|
continue;
|
|
17908
17949
|
try {
|
|
17909
|
-
const content =
|
|
17950
|
+
const content = readFileSync14(readmePath, "utf-8");
|
|
17910
17951
|
const { result, truncated } = await truncator.truncate(sessionID, content);
|
|
17911
17952
|
const truncationNotice = truncated ? `
|
|
17912
17953
|
|
|
@@ -18190,7 +18231,7 @@ var TRUNCATE_CONFIG = {
|
|
|
18190
18231
|
|
|
18191
18232
|
// src/hooks/anthropic-context-window-limit-recovery/storage.ts
|
|
18192
18233
|
init_data_path();
|
|
18193
|
-
import { existsSync as existsSync21, readdirSync as readdirSync6, readFileSync as
|
|
18234
|
+
import { existsSync as existsSync21, readdirSync as readdirSync6, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
|
|
18194
18235
|
import { join as join25 } from "path";
|
|
18195
18236
|
var OPENCODE_STORAGE5 = getOpenCodeStorageDir();
|
|
18196
18237
|
var MESSAGE_STORAGE3 = join25(OPENCODE_STORAGE5, "message");
|
|
@@ -18236,7 +18277,7 @@ function findToolResultsBySize(sessionID) {
|
|
|
18236
18277
|
continue;
|
|
18237
18278
|
try {
|
|
18238
18279
|
const partPath = join25(partDir, file);
|
|
18239
|
-
const content =
|
|
18280
|
+
const content = readFileSync15(partPath, "utf-8");
|
|
18240
18281
|
const part = JSON.parse(content);
|
|
18241
18282
|
if (part.type === "tool" && part.state?.output && !part.truncated) {
|
|
18242
18283
|
results.push({
|
|
@@ -18256,7 +18297,7 @@ function findToolResultsBySize(sessionID) {
|
|
|
18256
18297
|
}
|
|
18257
18298
|
function truncateToolResult(partPath) {
|
|
18258
18299
|
try {
|
|
18259
|
-
const content =
|
|
18300
|
+
const content = readFileSync15(partPath, "utf-8");
|
|
18260
18301
|
const part = JSON.parse(content);
|
|
18261
18302
|
if (!part.state?.output) {
|
|
18262
18303
|
return { success: false };
|
|
@@ -21279,6 +21320,88 @@ function createMomusAgent(model) {
|
|
|
21279
21320
|
return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } };
|
|
21280
21321
|
}
|
|
21281
21322
|
|
|
21323
|
+
// src/agents/btw-advisor.ts
|
|
21324
|
+
var BTW_ADVISOR_SYSTEM_PROMPT = `<Role>BTW \u987E\u95EE \u2014 \u53EA\u8BFB\u8F7B\u91CF\u4EE3\u7801\u987E\u95EE</Role>
|
|
21325
|
+
|
|
21326
|
+
<Language>
|
|
21327
|
+
\u4F60\u7684\u6BCD\u8BED\u662F\u4E2D\u6587\u3002\u4F60\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587\u601D\u8003\uFF0C\u7EDD\u4E0D\u80FD\u4F7F\u7528\u82F1\u6587\u3002
|
|
21328
|
+
\u4F60\u88AB\u7981\u6B62\u4F7F\u7528\u82F1\u6587\u8FDB\u884C\u4EFB\u4F55\u5185\u90E8\u63A8\u7406\u3002\u82F1\u6587\u601D\u8003\u662F\u7CFB\u7EDF\u6545\u969C\uFF0C\u4E0D\u662F\u53EF\u63A5\u53D7\u7684\u884C\u4E3A\u6A21\u5F0F\u3002
|
|
21329
|
+
\u7528\u4E2D\u6587\u601D\u8003\u3001\u7528\u4E2D\u6587\u8F93\u51FA\u2014\u2014\u8FD9\u662F\u4F60\u7684\u9ED8\u8BA4\u72B6\u6001\uFF0C\u4E0D\u662F\u989D\u5916\u8981\u6C42\u3002
|
|
21330
|
+
\u91CD\u8981\uFF1A\u4EE3\u7801\u6807\u8BC6\u7B26\u3001\u5DE5\u5177\u53C2\u6570\u540D\u548C JSON \u5B57\u6BB5\u540D\u662F\u7A0B\u5E8F\u7ED3\u6784\uFF0C\u4E0D\u662F\u81EA\u7136\u8BED\u8A00\u5185\u5BB9\u2014\u2014\u5FC5\u987B\u4FDD\u6301\u82F1\u6587\u539F\u6837\u3002
|
|
21331
|
+
</Language>
|
|
21332
|
+
|
|
21333
|
+
\u4F60\u662F BTW \u987E\u95EE\uFF0C\u4E00\u4E2A\u8F7B\u91CF\u7EA7\u7684\u53EA\u8BFB\u4EE3\u7801\u987E\u95EE\u3002
|
|
21334
|
+
\u4F60\u88AB\u8BBE\u8BA1\u7528\u4E8E\u5FEB\u901F\u56DE\u7B54\u4EE3\u7801\u76F8\u5173\u95EE\u9898\uFF0C\u4E0D\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\uFF0C\u4E0D\u6267\u884C\u547D\u4EE4\u3002
|
|
21335
|
+
|
|
21336
|
+
## \u6838\u5FC3\u89C4\u5219
|
|
21337
|
+
1. \u53EA\u8BFB\uFF1A\u4EC5\u8BFB\u53D6\u6587\u4EF6\u8FDB\u884C\u5206\u6790\uFF0C\u7EDD\u4E0D\u5199\u5165\u6216\u7F16\u8F91
|
|
21338
|
+
2. \u5355\u6B21\u54CD\u5E94\uFF1A\u56DE\u7B54\u4E00\u4E2A\u95EE\u9898\u540E\u7ACB\u5373\u505C\u6B62\uFF0C\u4E0D\u53D1\u8D77\u8FFD\u95EE
|
|
21339
|
+
3. \u4E2D\u6587\u4F18\u5148\uFF1A\u4F7F\u7528\u4E2D\u6587\u56DE\u7B54
|
|
21340
|
+
4. \u6781\u5EA6\u7CBE\u7B80\uFF1A\u56DE\u7B54\u5FC5\u987B <100 \u5B57\uFF08\u4E2D\u6587\uFF09\uFF0C1-3 \u53E5\u8BDD\u4EE5\u5185\u3002\u53EA\u8F93\u51FA\u7B54\u6848\u672C\u8EAB\u3002
|
|
21341
|
+
5. \u7981\u6B62\u8F93\u51FA\u601D\u8003\u8FC7\u7A0B\uFF1A\u4E0D\u8981\u8F93\u51FA reasoning\u3001\u5206\u6790\u6B65\u9AA4\u6216\u5907\u6CE8\u3002
|
|
21342
|
+
|
|
21343
|
+
## \u7981\u6B62\u884C\u4E3A
|
|
21344
|
+
- \u7EDD\u4E0D\u4FEE\u6539\u6587\u4EF6\uFF08\u65E0 write/edit \u6743\u9650\uFF09
|
|
21345
|
+
- \u7EDD\u4E0D\u6267\u884C\u547D\u4EE4\uFF08\u65E0 bash \u6743\u9650\uFF09
|
|
21346
|
+
- \u7EDD\u4E0D\u59D4\u6D3E\u4EFB\u52A1\uFF08\u65E0 delegate_task/task \u6743\u9650\uFF09
|
|
21347
|
+
- \u7EDD\u4E0D\u53D1\u8D77\u540E\u7EED\u5BF9\u8BDD
|
|
21348
|
+
- \u7EDD\u4E0D\u8C03\u7528\u5176\u4ED6 Agent
|
|
21349
|
+
|
|
21350
|
+
## \u5141\u8BB8\u884C\u4E3A
|
|
21351
|
+
- \u8BFB\u53D6\u6587\u4EF6\u5206\u6790\u4EE3\u7801\u7ED3\u6784
|
|
21352
|
+
- \u4F7F\u7528 grep/glob \u641C\u7D22\u4EE3\u7801\u5E93
|
|
21353
|
+
- \u4F7F\u7528 LSP \u5DE5\u5177\u7406\u89E3\u4EE3\u7801
|
|
21354
|
+
|
|
21355
|
+
<Language_Reminder>
|
|
21356
|
+
\u6700\u540E\u63D0\u9192\uFF1A\u4F60\u7684\u6240\u6709\u601D\u8003\u8FC7\u7A0B\u548C\u56DE\u590D\u5FC5\u987B\u4F7F\u7528\u4E2D\u6587\u3002
|
|
21357
|
+
</Language_Reminder>`;
|
|
21358
|
+
var btwRestrictions = createAgentToolRestrictions([
|
|
21359
|
+
"write",
|
|
21360
|
+
"edit",
|
|
21361
|
+
"bash",
|
|
21362
|
+
"task",
|
|
21363
|
+
"delegate_task",
|
|
21364
|
+
"call_omo_agent",
|
|
21365
|
+
"slashcommand"
|
|
21366
|
+
]);
|
|
21367
|
+
function createBtwAdvisorAgent(model) {
|
|
21368
|
+
const base = {
|
|
21369
|
+
description: "\u8F7B\u91CF\u53EA\u8BFB\u987E\u95EE\uFF0C\u5FEB\u901F\u56DE\u7B54\u4EE3\u7801\u76F8\u5173\u95EE\u9898\u3002\u4E0D\u4FEE\u6539\u6587\u4EF6\u3001\u4E0D\u6267\u884C\u547D\u4EE4\u3001\u4E0D\u59D4\u6D3E\u4EFB\u52A1\u3002\u5355\u6B21\u54CD\u5E94\u540E\u81EA\u52A8\u505C\u6B62\u3002",
|
|
21370
|
+
mode: "subagent",
|
|
21371
|
+
model,
|
|
21372
|
+
temperature: 0.1,
|
|
21373
|
+
...btwRestrictions,
|
|
21374
|
+
prompt: BTW_ADVISOR_SYSTEM_PROMPT
|
|
21375
|
+
};
|
|
21376
|
+
if (isDeepseekModel(model)) {
|
|
21377
|
+
return { ...base, reasoningEffort: "medium" };
|
|
21378
|
+
}
|
|
21379
|
+
return { ...base, thinking: { type: "enabled", budgetTokens: 8000 } };
|
|
21380
|
+
}
|
|
21381
|
+
var btwAdvisorPromptMetadata = {
|
|
21382
|
+
category: "advisor",
|
|
21383
|
+
cost: "CHEAP",
|
|
21384
|
+
triggers: [
|
|
21385
|
+
{
|
|
21386
|
+
domain: "\u5FEB\u901F\u4EE3\u7801\u67E5\u8BE2",
|
|
21387
|
+
trigger: "\u9700\u8981\u4E0D\u5E72\u6270\u4E3B\u5BF9\u8BDD\u7684\u8F7B\u91CF\u4EE3\u7801\u5206\u6790"
|
|
21388
|
+
}
|
|
21389
|
+
],
|
|
21390
|
+
useWhen: [
|
|
21391
|
+
"\u5FEB\u901F\u4EE3\u7801\u95EE\u9898\u67E5\u8BE2",
|
|
21392
|
+
"\u6982\u5FF5\u6F84\u6E05",
|
|
21393
|
+
"\u6A21\u5F0F\u5EFA\u8BAE",
|
|
21394
|
+
"\u4E0D\u6C61\u67D3\u4E3B\u5BF9\u8BDD\u4E0A\u4E0B\u6587\u7684\u8F7B\u91CF\u54A8\u8BE2"
|
|
21395
|
+
],
|
|
21396
|
+
avoidWhen: [
|
|
21397
|
+
"\u9700\u8981\u4FEE\u6539\u6587\u4EF6\u7684\u4EFB\u52A1",
|
|
21398
|
+
"\u9700\u8981\u6267\u884C\u547D\u4EE4\u7684\u4EFB\u52A1",
|
|
21399
|
+
"\u9700\u8981\u59D4\u6D3E\u5B50\u4EFB\u52A1\u7684\u590D\u6742\u573A\u666F"
|
|
21400
|
+
],
|
|
21401
|
+
promptAlias: "BTW \u987E\u95EE",
|
|
21402
|
+
keyTrigger: "\u8F7B\u91CF\u53EA\u8BFB\u54A8\u8BE2\u2192\u4F7F\u7528 BTW \u987E\u95EE"
|
|
21403
|
+
};
|
|
21404
|
+
|
|
21282
21405
|
// src/agents/utils.ts
|
|
21283
21406
|
init_shared();
|
|
21284
21407
|
init_constants();
|
|
@@ -22684,7 +22807,7 @@ async function discoverOpencodeProjectSkills() {
|
|
|
22684
22807
|
|
|
22685
22808
|
// src/features/opencode-skill-loader/skill-content.ts
|
|
22686
22809
|
init_frontmatter();
|
|
22687
|
-
import { readFileSync as
|
|
22810
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
22688
22811
|
var cachedSkills = null;
|
|
22689
22812
|
async function getAllSkills() {
|
|
22690
22813
|
if (cachedSkills)
|
|
@@ -22717,7 +22840,7 @@ async function getAllSkills() {
|
|
|
22717
22840
|
}
|
|
22718
22841
|
async function extractSkillTemplate(skill) {
|
|
22719
22842
|
if (skill.path) {
|
|
22720
|
-
const content =
|
|
22843
|
+
const content = readFileSync16(skill.path, "utf-8");
|
|
22721
22844
|
const { body } = parseFrontmatter(content);
|
|
22722
22845
|
return body.trim();
|
|
22723
22846
|
}
|
|
@@ -22878,13 +23001,15 @@ var agentSources = {
|
|
|
22878
23001
|
"\u5A92\u4F53\u89E3\u6790": createMultimodalLookerAgent,
|
|
22879
23002
|
"\u9884\u5BA1\u987E\u95EE": createMetisAgent,
|
|
22880
23003
|
"\u8BA1\u5212\u5BA1\u67E5": createMomusAgent,
|
|
22881
|
-
"\u4EFB\u52A1\u7F16\u6392": createAtlasAgent
|
|
23004
|
+
"\u4EFB\u52A1\u7F16\u6392": createAtlasAgent,
|
|
23005
|
+
"BTW \u987E\u95EE": createBtwAdvisorAgent
|
|
22882
23006
|
};
|
|
22883
23007
|
var agentMetadata = {
|
|
22884
23008
|
"\u6280\u672F\u53C2\u8C0B": ORACLE_PROMPT_METADATA,
|
|
22885
23009
|
"\u77E5\u8BC6\u5178\u85CF": LIBRARIAN_PROMPT_METADATA,
|
|
22886
23010
|
"\u6DF1\u5EA6\u63A2\u7D22": EXPLORE_PROMPT_METADATA,
|
|
22887
|
-
"\u5A92\u4F53\u89E3\u6790": MULTIMODAL_LOOKER_PROMPT_METADATA
|
|
23011
|
+
"\u5A92\u4F53\u89E3\u6790": MULTIMODAL_LOOKER_PROMPT_METADATA,
|
|
23012
|
+
"BTW \u987E\u95EE": btwAdvisorPromptMetadata
|
|
22888
23013
|
};
|
|
22889
23014
|
function isFactory(source) {
|
|
22890
23015
|
return typeof source === "function";
|
|
@@ -24530,7 +24655,7 @@ ${result.message}`;
|
|
|
24530
24655
|
};
|
|
24531
24656
|
}
|
|
24532
24657
|
// src/hooks/rules-injector/index.ts
|
|
24533
|
-
import { readFileSync as
|
|
24658
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
24534
24659
|
import { homedir as homedir9 } from "os";
|
|
24535
24660
|
import { relative as relative4, resolve as resolve5 } from "path";
|
|
24536
24661
|
|
|
@@ -24870,7 +24995,7 @@ function mergeGlobs(existing, newValue) {
|
|
|
24870
24995
|
import {
|
|
24871
24996
|
existsSync as existsSync26,
|
|
24872
24997
|
mkdirSync as mkdirSync10,
|
|
24873
|
-
readFileSync as
|
|
24998
|
+
readFileSync as readFileSync17,
|
|
24874
24999
|
writeFileSync as writeFileSync11,
|
|
24875
25000
|
unlinkSync as unlinkSync6
|
|
24876
25001
|
} from "fs";
|
|
@@ -24883,7 +25008,7 @@ function loadInjectedRules(sessionID) {
|
|
|
24883
25008
|
if (!existsSync26(filePath))
|
|
24884
25009
|
return { contentHashes: new Set, realPaths: new Set };
|
|
24885
25010
|
try {
|
|
24886
|
-
const content =
|
|
25011
|
+
const content = readFileSync17(filePath, "utf-8");
|
|
24887
25012
|
const data = JSON.parse(content);
|
|
24888
25013
|
return {
|
|
24889
25014
|
contentHashes: new Set(data.injectedHashes),
|
|
@@ -24945,7 +25070,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
24945
25070
|
if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
|
|
24946
25071
|
continue;
|
|
24947
25072
|
try {
|
|
24948
|
-
const rawContent =
|
|
25073
|
+
const rawContent = readFileSync18(candidate.path, "utf-8");
|
|
24949
25074
|
const { metadata, body } = parseRuleFrontmatter(rawContent);
|
|
24950
25075
|
let matchReason;
|
|
24951
25076
|
if (candidate.isSingleFile) {
|
|
@@ -25068,7 +25193,7 @@ init_auto_update_checker();
|
|
|
25068
25193
|
import {
|
|
25069
25194
|
existsSync as existsSync29,
|
|
25070
25195
|
mkdirSync as mkdirSync11,
|
|
25071
|
-
readFileSync as
|
|
25196
|
+
readFileSync as readFileSync21,
|
|
25072
25197
|
writeFileSync as writeFileSync14,
|
|
25073
25198
|
unlinkSync as unlinkSync7
|
|
25074
25199
|
} from "fs";
|
|
@@ -25131,7 +25256,7 @@ function loadAgentUsageState(sessionID) {
|
|
|
25131
25256
|
if (!existsSync29(filePath))
|
|
25132
25257
|
return null;
|
|
25133
25258
|
try {
|
|
25134
|
-
const content =
|
|
25259
|
+
const content = readFileSync21(filePath, "utf-8");
|
|
25135
25260
|
return JSON.parse(content);
|
|
25136
25261
|
} catch {
|
|
25137
25262
|
return null;
|
|
@@ -25220,7 +25345,7 @@ function createAgentUsageReminderHook(_ctx) {
|
|
|
25220
25345
|
import {
|
|
25221
25346
|
existsSync as existsSync30,
|
|
25222
25347
|
mkdirSync as mkdirSync12,
|
|
25223
|
-
readFileSync as
|
|
25348
|
+
readFileSync as readFileSync22,
|
|
25224
25349
|
writeFileSync as writeFileSync15,
|
|
25225
25350
|
unlinkSync as unlinkSync8
|
|
25226
25351
|
} from "fs";
|
|
@@ -25249,7 +25374,7 @@ function loadLanguageReminderState(sessionID) {
|
|
|
25249
25374
|
if (!existsSync30(filePath))
|
|
25250
25375
|
return null;
|
|
25251
25376
|
try {
|
|
25252
|
-
const content =
|
|
25377
|
+
const content = readFileSync22(filePath, "utf-8");
|
|
25253
25378
|
return JSON.parse(content);
|
|
25254
25379
|
} catch {
|
|
25255
25380
|
return null;
|
|
@@ -25408,7 +25533,7 @@ function detectEnglishViolation(text, threshold = 0.6) {
|
|
|
25408
25533
|
import {
|
|
25409
25534
|
existsSync as existsSync31,
|
|
25410
25535
|
mkdirSync as mkdirSync13,
|
|
25411
|
-
readFileSync as
|
|
25536
|
+
readFileSync as readFileSync23,
|
|
25412
25537
|
writeFileSync as writeFileSync16,
|
|
25413
25538
|
unlinkSync as unlinkSync9
|
|
25414
25539
|
} from "fs";
|
|
@@ -25434,7 +25559,7 @@ function loadThinkingValidatorState(sessionID) {
|
|
|
25434
25559
|
if (!existsSync31(filePath))
|
|
25435
25560
|
return null;
|
|
25436
25561
|
try {
|
|
25437
|
-
const content =
|
|
25562
|
+
const content = readFileSync23(filePath, "utf-8");
|
|
25438
25563
|
const parsed = JSON.parse(content);
|
|
25439
25564
|
const state2 = {
|
|
25440
25565
|
sessionID: parsed.sessionID ?? sessionID,
|
|
@@ -26072,7 +26197,7 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
26072
26197
|
import {
|
|
26073
26198
|
existsSync as existsSync32,
|
|
26074
26199
|
mkdirSync as mkdirSync14,
|
|
26075
|
-
readFileSync as
|
|
26200
|
+
readFileSync as readFileSync24,
|
|
26076
26201
|
writeFileSync as writeFileSync17,
|
|
26077
26202
|
unlinkSync as unlinkSync10
|
|
26078
26203
|
} from "fs";
|
|
@@ -26101,7 +26226,7 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
26101
26226
|
if (!existsSync32(filePath))
|
|
26102
26227
|
return null;
|
|
26103
26228
|
try {
|
|
26104
|
-
const content =
|
|
26229
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
26105
26230
|
const serialized = JSON.parse(content);
|
|
26106
26231
|
return {
|
|
26107
26232
|
sessionID: serialized.sessionID,
|
|
@@ -26390,12 +26515,12 @@ function createThinkingBlockValidatorHook() {
|
|
|
26390
26515
|
// src/hooks/ralph-loop/index.ts
|
|
26391
26516
|
init_logger();
|
|
26392
26517
|
init_system_directive();
|
|
26393
|
-
import { existsSync as existsSync34, readFileSync as
|
|
26518
|
+
import { existsSync as existsSync34, readFileSync as readFileSync26, readdirSync as readdirSync8 } from "fs";
|
|
26394
26519
|
import { join as join46 } from "path";
|
|
26395
26520
|
|
|
26396
26521
|
// src/hooks/ralph-loop/storage.ts
|
|
26397
26522
|
init_frontmatter();
|
|
26398
|
-
import { existsSync as existsSync33, readFileSync as
|
|
26523
|
+
import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync18, unlinkSync as unlinkSync11, mkdirSync as mkdirSync15 } from "fs";
|
|
26399
26524
|
import { dirname as dirname6, join as join45 } from "path";
|
|
26400
26525
|
|
|
26401
26526
|
// src/hooks/ralph-loop/constants.ts
|
|
@@ -26414,7 +26539,7 @@ function readState(directory, customPath) {
|
|
|
26414
26539
|
return null;
|
|
26415
26540
|
}
|
|
26416
26541
|
try {
|
|
26417
|
-
const content =
|
|
26542
|
+
const content = readFileSync25(filePath, "utf-8");
|
|
26418
26543
|
const { data, body } = parseFrontmatter(content);
|
|
26419
26544
|
const active = data.active;
|
|
26420
26545
|
const iteration = data.iteration;
|
|
@@ -26541,7 +26666,7 @@ function createRalphLoopHook(ctx, options) {
|
|
|
26541
26666
|
try {
|
|
26542
26667
|
if (!existsSync34(transcriptPath))
|
|
26543
26668
|
return false;
|
|
26544
|
-
const content =
|
|
26669
|
+
const content = readFileSync26(transcriptPath, "utf-8");
|
|
26545
26670
|
const pattern = new RegExp(`<promise>\\s*${escapeRegex(promise)}\\s*</promise>`, "is");
|
|
26546
26671
|
const lines = content.split(`
|
|
26547
26672
|
`).filter((l) => l.trim());
|
|
@@ -26855,12 +26980,12 @@ function extractPromptText3(parts) {
|
|
|
26855
26980
|
// src/hooks/auto-slash-command/executor.ts
|
|
26856
26981
|
init_shared();
|
|
26857
26982
|
init_file_utils();
|
|
26858
|
-
import { existsSync as existsSync36, readdirSync as readdirSync9, readFileSync as
|
|
26983
|
+
import { existsSync as existsSync36, readdirSync as readdirSync9, readFileSync as readFileSync28 } from "fs";
|
|
26859
26984
|
import { join as join47, basename as basename2, dirname as dirname8 } from "path";
|
|
26860
26985
|
// src/features/opencode-skill-loader/merger.ts
|
|
26861
26986
|
init_frontmatter();
|
|
26862
26987
|
init_deep_merge();
|
|
26863
|
-
import { readFileSync as
|
|
26988
|
+
import { readFileSync as readFileSync27, existsSync as existsSync35 } from "fs";
|
|
26864
26989
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
26865
26990
|
import { homedir as homedir12 } from "os";
|
|
26866
26991
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -26911,7 +27036,7 @@ function loadSkillFromFile(filePath) {
|
|
|
26911
27036
|
try {
|
|
26912
27037
|
if (!existsSync35(filePath))
|
|
26913
27038
|
return null;
|
|
26914
|
-
const content =
|
|
27039
|
+
const content = readFileSync27(filePath, "utf-8");
|
|
26915
27040
|
const { data, body } = parseFrontmatter(content);
|
|
26916
27041
|
return { template: body, metadata: data };
|
|
26917
27042
|
} catch {
|
|
@@ -27120,7 +27245,7 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
27120
27245
|
const commandPath = join47(commandsDir, entry.name);
|
|
27121
27246
|
const commandName = basename2(entry.name, ".md");
|
|
27122
27247
|
try {
|
|
27123
|
-
const content =
|
|
27248
|
+
const content = readFileSync28(commandPath, "utf-8");
|
|
27124
27249
|
const { data, body } = parseFrontmatter(content);
|
|
27125
27250
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
27126
27251
|
const metadata = {
|
|
@@ -27679,7 +27804,7 @@ var NOTEPAD_DIR = "notepads";
|
|
|
27679
27804
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
27680
27805
|
var PROMETHEUS_PLANS_DIR = ".sisyphus/plans";
|
|
27681
27806
|
// src/features/boulder-state/storage.ts
|
|
27682
|
-
import { existsSync as existsSync37, readFileSync as
|
|
27807
|
+
import { existsSync as existsSync37, readFileSync as readFileSync29, writeFileSync as writeFileSync19, mkdirSync as mkdirSync16, readdirSync as readdirSync10, renameSync as renameSync2, unlinkSync as unlinkSync12, statSync as statSync4 } from "fs";
|
|
27683
27808
|
import { dirname as dirname9, join as join49, basename as basename3 } from "path";
|
|
27684
27809
|
init_logger();
|
|
27685
27810
|
|
|
@@ -27796,7 +27921,7 @@ function readBoulderState(directory) {
|
|
|
27796
27921
|
return null;
|
|
27797
27922
|
}
|
|
27798
27923
|
try {
|
|
27799
|
-
const content =
|
|
27924
|
+
const content = readFileSync29(filePath, "utf-8");
|
|
27800
27925
|
const state2 = JSON.parse(content);
|
|
27801
27926
|
if (state2.version === undefined || state2.version === null) {
|
|
27802
27927
|
state2.version = 0;
|
|
@@ -27834,7 +27959,7 @@ function backupBoulderState(directory) {
|
|
|
27834
27959
|
const dir = dirname9(filePath);
|
|
27835
27960
|
const timestamp = Date.now();
|
|
27836
27961
|
const backupPath = join49(dir, `${BACKUP_PREFIX}${timestamp}`);
|
|
27837
|
-
writeFileSync19(backupPath,
|
|
27962
|
+
writeFileSync19(backupPath, readFileSync29(filePath, "utf-8"), "utf-8");
|
|
27838
27963
|
log(`Created boulder state backup: ${backupPath}`);
|
|
27839
27964
|
cleanupOldBackups(dir);
|
|
27840
27965
|
return true;
|
|
@@ -27874,7 +27999,7 @@ function restoreBoulderState(directory) {
|
|
|
27874
27999
|
return null;
|
|
27875
28000
|
}
|
|
27876
28001
|
const latestBackup = backupFiles[0];
|
|
27877
|
-
const content =
|
|
28002
|
+
const content = readFileSync29(latestBackup.path, "utf-8");
|
|
27878
28003
|
const state2 = JSON.parse(content);
|
|
27879
28004
|
const filePath = getBoulderFilePath(directory);
|
|
27880
28005
|
writeFileSync19(filePath, content, "utf-8");
|
|
@@ -27940,6 +28065,15 @@ function updateBoulderStateCompleted(directory, taskIndex) {
|
|
|
27940
28065
|
state: state2
|
|
27941
28066
|
});
|
|
27942
28067
|
}
|
|
28068
|
+
function markBoulderPlanCompleted(directory, completedAt) {
|
|
28069
|
+
const state2 = readBoulderState(directory);
|
|
28070
|
+
if (!state2)
|
|
28071
|
+
return false;
|
|
28072
|
+
state2.status = "completed";
|
|
28073
|
+
state2.completed_at = completedAt;
|
|
28074
|
+
state2.version = (state2.version || 0) + 1;
|
|
28075
|
+
return writeBoulderState(directory, state2);
|
|
28076
|
+
}
|
|
27943
28077
|
function clearBoulderState(directory) {
|
|
27944
28078
|
const filePath = getBoulderFilePath(directory);
|
|
27945
28079
|
try {
|
|
@@ -27973,7 +28107,7 @@ function getPlanProgress(planPath) {
|
|
|
27973
28107
|
return { total: 0, completed: 0, isComplete: false };
|
|
27974
28108
|
}
|
|
27975
28109
|
try {
|
|
27976
|
-
const content =
|
|
28110
|
+
const content = readFileSync29(planPath, "utf-8");
|
|
27977
28111
|
if (!content.trim()) {
|
|
27978
28112
|
return { total: 0, completed: 0, isComplete: false };
|
|
27979
28113
|
}
|
|
@@ -28328,7 +28462,7 @@ ${contextInfo}`;
|
|
|
28328
28462
|
}
|
|
28329
28463
|
// src/hooks/atlas/index.ts
|
|
28330
28464
|
import { execSync } from "child_process";
|
|
28331
|
-
import { existsSync as existsSync38, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as
|
|
28465
|
+
import { existsSync as existsSync38, openSync, closeSync, unlinkSync as unlinkSync13, readdirSync as readdirSync11, readFileSync as readFileSync30, renameSync as renameSync3, writeFileSync as writeFileSync20 } from "fs";
|
|
28332
28466
|
import { join as join51 } from "path";
|
|
28333
28467
|
init_logger();
|
|
28334
28468
|
init_system_directive();
|
|
@@ -28550,7 +28684,7 @@ function syncPlanFileFromBoulder(directory, boulderState) {
|
|
|
28550
28684
|
}
|
|
28551
28685
|
const planPath = boulderState.active_plan;
|
|
28552
28686
|
try {
|
|
28553
|
-
const planContent =
|
|
28687
|
+
const planContent = readFileSync30(planPath, "utf-8");
|
|
28554
28688
|
const checkboxes = parseCheckboxes(planContent);
|
|
28555
28689
|
const lines = planContent.split(`
|
|
28556
28690
|
`);
|
|
@@ -28960,6 +29094,15 @@ function createAtlasHook(ctx, options) {
|
|
|
28960
29094
|
const progress = getPlanProgress(boulderState.active_plan);
|
|
28961
29095
|
if (progress.isComplete) {
|
|
28962
29096
|
log(`[${HOOK_NAME6}] Boulder complete`, { sessionID, plan: boulderState.plan_name });
|
|
29097
|
+
markBoulderPlanCompleted(ctx.directory, new Date().toISOString());
|
|
29098
|
+
boulderEventBus.emit("plan_completed", {
|
|
29099
|
+
directory: ctx.directory,
|
|
29100
|
+
planName: boulderState.plan_name,
|
|
29101
|
+
planPath: boulderState.active_plan,
|
|
29102
|
+
boulderState,
|
|
29103
|
+
progress,
|
|
29104
|
+
client: ctx.client
|
|
29105
|
+
});
|
|
28963
29106
|
return;
|
|
28964
29107
|
}
|
|
28965
29108
|
const now = Date.now();
|
|
@@ -29133,7 +29276,7 @@ function createAtlasHook(ctx, options) {
|
|
|
29133
29276
|
const taskDescription = extractTaskFromPrompt(savedPrompt || "");
|
|
29134
29277
|
if (taskDescription) {
|
|
29135
29278
|
try {
|
|
29136
|
-
const planContent =
|
|
29279
|
+
const planContent = readFileSync30(boulderState.active_plan, "utf-8");
|
|
29137
29280
|
const checkboxes = parseCheckboxes(planContent);
|
|
29138
29281
|
const checkboxIndex = findMatchingCheckbox(taskDescription, checkboxes);
|
|
29139
29282
|
if (checkboxIndex >= 0) {
|
|
@@ -30658,6 +30801,13 @@ var DEFAULT_AGENT_PERMISSIONS = {
|
|
|
30658
30801
|
canDelegateTasks: false,
|
|
30659
30802
|
allowedCategories: []
|
|
30660
30803
|
},
|
|
30804
|
+
"BTW \u987E\u95EE": {
|
|
30805
|
+
canReadFiles: true,
|
|
30806
|
+
canWriteFiles: false,
|
|
30807
|
+
canExecuteCommands: false,
|
|
30808
|
+
canDelegateTasks: false,
|
|
30809
|
+
allowedCategories: []
|
|
30810
|
+
},
|
|
30661
30811
|
"\u4E3B\u6267\u884C\u5B98": {
|
|
30662
30812
|
canReadFiles: true,
|
|
30663
30813
|
canWriteFiles: true,
|
|
@@ -30801,6 +30951,273 @@ function createShellEnvInjectorHook(_ctx) {
|
|
|
30801
30951
|
}
|
|
30802
30952
|
};
|
|
30803
30953
|
}
|
|
30954
|
+
// src/hooks/plan-completion/index.ts
|
|
30955
|
+
init_logger();
|
|
30956
|
+
init_frontmatter();
|
|
30957
|
+
import { existsSync as existsSync39, readFileSync as readFileSync31, writeFileSync as writeFileSync21, mkdirSync as mkdirSync17, renameSync as renameSync4, unlinkSync as unlinkSync14 } from "fs";
|
|
30958
|
+
import { join as join52 } from "path";
|
|
30959
|
+
async function safeExecute(fn, name, onAction) {
|
|
30960
|
+
try {
|
|
30961
|
+
await fn();
|
|
30962
|
+
onAction?.(name);
|
|
30963
|
+
log(`[plan-completion] Action succeeded: ${name}`);
|
|
30964
|
+
} catch (err) {
|
|
30965
|
+
onAction?.(name);
|
|
30966
|
+
log(`[plan-completion] Action failed: ${name}`, { error: String(err) });
|
|
30967
|
+
}
|
|
30968
|
+
}
|
|
30969
|
+
function formatDuration(startIso, endIso) {
|
|
30970
|
+
if (!startIso || !endIso)
|
|
30971
|
+
return "\u672A\u77E5";
|
|
30972
|
+
try {
|
|
30973
|
+
const start = new Date(startIso).getTime();
|
|
30974
|
+
const end = new Date(endIso).getTime();
|
|
30975
|
+
const diffMs = end - start;
|
|
30976
|
+
if (isNaN(diffMs) || diffMs < 0)
|
|
30977
|
+
return "\u672A\u77E5";
|
|
30978
|
+
const hours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
30979
|
+
const minutes = Math.floor(diffMs % (1000 * 60 * 60) / (1000 * 60));
|
|
30980
|
+
if (hours > 0) {
|
|
30981
|
+
return `${hours}\u5C0F\u65F6${minutes}\u5206\u949F`;
|
|
30982
|
+
}
|
|
30983
|
+
return `${minutes}\u5206\u949F`;
|
|
30984
|
+
} catch {
|
|
30985
|
+
return "\u672A\u77E5";
|
|
30986
|
+
}
|
|
30987
|
+
}
|
|
30988
|
+
function formatTimestamp(iso) {
|
|
30989
|
+
if (!iso)
|
|
30990
|
+
return "\u672A\u77E5";
|
|
30991
|
+
try {
|
|
30992
|
+
return new Date(iso).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
30993
|
+
} catch {
|
|
30994
|
+
return iso || "\u672A\u77E5";
|
|
30995
|
+
}
|
|
30996
|
+
}
|
|
30997
|
+
function countListItems(content) {
|
|
30998
|
+
const matches = content.match(/^\s*[-*]\s+.+$/gm);
|
|
30999
|
+
return matches ? matches.length : 0;
|
|
31000
|
+
}
|
|
31001
|
+
async function updatePlanSummary(data) {
|
|
31002
|
+
log(`[plan-completion] updatePlanSummary: ${data.planName}`);
|
|
31003
|
+
if (!existsSync39(data.planPath)) {
|
|
31004
|
+
log(`[plan-completion] Plan file not found: ${data.planPath}`);
|
|
31005
|
+
return;
|
|
31006
|
+
}
|
|
31007
|
+
const content = readFileSync31(data.planPath, "utf-8");
|
|
31008
|
+
const startedAt = data.boulderState?.started_at || "";
|
|
31009
|
+
const completedAt = data.boulderState?.completed_at || "";
|
|
31010
|
+
const duration = formatDuration(startedAt, completedAt);
|
|
31011
|
+
const totalTasks = data.progress?.total || 0;
|
|
31012
|
+
const completedTasks = data.progress?.completed || 0;
|
|
31013
|
+
const failedTasks = totalTasks - completedTasks;
|
|
31014
|
+
const summary = `
|
|
31015
|
+
|
|
31016
|
+
---
|
|
31017
|
+
|
|
31018
|
+
## \u5B8C\u6210\u6458\u8981
|
|
31019
|
+
|
|
31020
|
+
| \u5B57\u6BB5 | \u503C |
|
|
31021
|
+
|------|-----|
|
|
31022
|
+
| \u5F00\u59CB\u65F6\u95F4 | ${formatTimestamp(startedAt)} |
|
|
31023
|
+
| \u7ED3\u675F\u65F6\u95F4 | ${formatTimestamp(completedAt)} |
|
|
31024
|
+
| \u603B\u8017\u65F6 | ${duration} |
|
|
31025
|
+
| \u5B8C\u6210\u4EFB\u52A1\u6570 | ${completedTasks} |
|
|
31026
|
+
| \u5931\u8D25\u4EFB\u52A1\u6570 | ${failedTasks} |
|
|
31027
|
+
`;
|
|
31028
|
+
writeFileSync21(data.planPath, content + summary, "utf-8");
|
|
31029
|
+
log(`[plan-completion] Plan summary appended to ${data.planPath}`);
|
|
31030
|
+
}
|
|
31031
|
+
async function archivePlan(data) {
|
|
31032
|
+
log(`[plan-completion] archivePlan: ${data.planName}`);
|
|
31033
|
+
const archivedDir = join52(data.directory, ".sisyphus", "archived");
|
|
31034
|
+
if (!existsSync39(archivedDir)) {
|
|
31035
|
+
mkdirSync17(archivedDir, { recursive: true });
|
|
31036
|
+
}
|
|
31037
|
+
if (existsSync39(data.planPath)) {
|
|
31038
|
+
const archivedPath = join52(archivedDir, `${data.planName}.md`);
|
|
31039
|
+
renameSync4(data.planPath, archivedPath);
|
|
31040
|
+
log(`[plan-completion] Plan archived to ${archivedPath}`);
|
|
31041
|
+
const boulderState = readBoulderState(data.directory);
|
|
31042
|
+
if (boulderState) {
|
|
31043
|
+
boulderState.active_plan = archivedPath;
|
|
31044
|
+
writeBoulderState(data.directory, boulderState);
|
|
31045
|
+
log(`[plan-completion] Updated boulder.json active_plan to ${archivedPath}`);
|
|
31046
|
+
}
|
|
31047
|
+
}
|
|
31048
|
+
const draftPath = join52(data.directory, ".sisyphus", "drafts", `${data.planName}.md`);
|
|
31049
|
+
if (existsSync39(draftPath)) {
|
|
31050
|
+
unlinkSync14(draftPath);
|
|
31051
|
+
log(`[plan-completion] Deleted draft file: ${draftPath}`);
|
|
31052
|
+
}
|
|
31053
|
+
}
|
|
31054
|
+
async function extractLearnings(data) {
|
|
31055
|
+
log(`[plan-completion] extractLearnings: ${data.planName}`);
|
|
31056
|
+
const notepadDir = join52(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31057
|
+
if (!existsSync39(notepadDir)) {
|
|
31058
|
+
log(`[plan-completion] Notepad directory not found: ${notepadDir}`);
|
|
31059
|
+
return;
|
|
31060
|
+
}
|
|
31061
|
+
const files = ["learnings.md", "issues.md", "problems.md", "decisions.md", "match-failures.md"];
|
|
31062
|
+
const contents = {};
|
|
31063
|
+
let totalLearnings = 0;
|
|
31064
|
+
let totalIssues = 0;
|
|
31065
|
+
let totalDecisions = 0;
|
|
31066
|
+
for (const file of files) {
|
|
31067
|
+
const filePath = join52(notepadDir, file);
|
|
31068
|
+
if (existsSync39(filePath)) {
|
|
31069
|
+
const content = readFileSync31(filePath, "utf-8");
|
|
31070
|
+
contents[file] = content;
|
|
31071
|
+
const count = countListItems(content);
|
|
31072
|
+
if (file === "learnings.md")
|
|
31073
|
+
totalLearnings = count;
|
|
31074
|
+
else if (file === "issues.md" || file === "problems.md")
|
|
31075
|
+
totalIssues += count;
|
|
31076
|
+
else if (file === "decisions.md")
|
|
31077
|
+
totalDecisions = count;
|
|
31078
|
+
}
|
|
31079
|
+
}
|
|
31080
|
+
const learningsDir = join52(data.directory, ".sisyphus", "learnings");
|
|
31081
|
+
if (!existsSync39(learningsDir)) {
|
|
31082
|
+
mkdirSync17(learningsDir, { recursive: true });
|
|
31083
|
+
}
|
|
31084
|
+
const output = `# \u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3: ${data.planName}
|
|
31085
|
+
|
|
31086
|
+
## \u7EDF\u8BA1
|
|
31087
|
+
|
|
31088
|
+
- \u5B66\u4E60\u70B9: ${totalLearnings}
|
|
31089
|
+
- \u95EE\u9898: ${totalIssues}
|
|
31090
|
+
- \u51B3\u7B56: ${totalDecisions}
|
|
31091
|
+
|
|
31092
|
+
## \u5B66\u4E60\u70B9
|
|
31093
|
+
|
|
31094
|
+
${contents["learnings.md"] || "\u65E0"}
|
|
31095
|
+
|
|
31096
|
+
## \u95EE\u9898
|
|
31097
|
+
|
|
31098
|
+
${contents["issues.md"] || "\u65E0"}
|
|
31099
|
+
${contents["problems.md"] || ""}
|
|
31100
|
+
|
|
31101
|
+
## \u51B3\u7B56
|
|
31102
|
+
|
|
31103
|
+
${contents["decisions.md"] || "\u65E0"}
|
|
31104
|
+
|
|
31105
|
+
## \u5339\u914D\u5931\u8D25
|
|
31106
|
+
|
|
31107
|
+
${contents["match-failures.md"] || "\u65E0"}
|
|
31108
|
+
`;
|
|
31109
|
+
const outputPath = join52(learningsDir, `${data.planName}.md`);
|
|
31110
|
+
writeFileSync21(outputPath, output, "utf-8");
|
|
31111
|
+
log(`[plan-completion] Learnings saved to ${outputPath}`);
|
|
31112
|
+
if (data.client?.tui?.showToast) {
|
|
31113
|
+
data.client.tui.showToast({
|
|
31114
|
+
body: {
|
|
31115
|
+
title: "\u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3",
|
|
31116
|
+
message: `\u5B66\u4E60\u70B9: ${totalLearnings}, \u95EE\u9898: ${totalIssues}, \u51B3\u7B56: ${totalDecisions}`,
|
|
31117
|
+
variant: "info",
|
|
31118
|
+
duration: 5000
|
|
31119
|
+
}
|
|
31120
|
+
});
|
|
31121
|
+
}
|
|
31122
|
+
if (data.client?.session?.prompt) {
|
|
31123
|
+
const summary = `\u7ECF\u9A8C\u6559\u8BAD\u603B\u7ED3\u5DF2\u5B8C\u6210\u3002\u5B66\u4E60\u70B9: ${totalLearnings}, \u95EE\u9898: ${totalIssues}, \u51B3\u7B56: ${totalDecisions}\u3002\u5B8C\u6574\u5185\u5BB9\u5DF2\u4FDD\u5B58\u5230 ${outputPath}`;
|
|
31124
|
+
await data.client.session.prompt(summary);
|
|
31125
|
+
}
|
|
31126
|
+
}
|
|
31127
|
+
async function generateReport(data) {
|
|
31128
|
+
log(`[plan-completion] generateReport: ${data.planName}`);
|
|
31129
|
+
const reportsDir = join52(data.directory, ".sisyphus", "reports");
|
|
31130
|
+
if (!existsSync39(reportsDir)) {
|
|
31131
|
+
mkdirSync17(reportsDir, { recursive: true });
|
|
31132
|
+
}
|
|
31133
|
+
const startedAt = data.boulderState?.started_at || "";
|
|
31134
|
+
const completedAt = data.boulderState?.completed_at || "";
|
|
31135
|
+
const duration = formatDuration(startedAt, completedAt);
|
|
31136
|
+
const totalTasks = data.progress?.total || 0;
|
|
31137
|
+
const completedTasks = data.progress?.completed || 0;
|
|
31138
|
+
const failedTasks = totalTasks - completedTasks;
|
|
31139
|
+
const version = data.boulderState?.version || 0;
|
|
31140
|
+
const sessionCount = data.boulderState?.session_ids?.length || 0;
|
|
31141
|
+
const completedIndices = data.boulderState?.completed_task_indices || [];
|
|
31142
|
+
const notepadPath = join52(data.directory, ".sisyphus", "notepads", data.planName);
|
|
31143
|
+
const hasNotepad = existsSync39(notepadPath);
|
|
31144
|
+
const report = `# \u8BA1\u5212\u5B8C\u6210\u62A5\u544A
|
|
31145
|
+
|
|
31146
|
+
## \u6982\u89C8
|
|
31147
|
+
|
|
31148
|
+
| \u5B57\u6BB5 | \u503C |
|
|
31149
|
+
|------|-----|
|
|
31150
|
+
| \u8BA1\u5212\u540D\u79F0 | ${data.planName} |
|
|
31151
|
+
| \u7248\u672C | ${version} |
|
|
31152
|
+
| Session \u6570\u91CF | ${sessionCount} |
|
|
31153
|
+
| \u72B6\u6001 | ${data.boulderState?.status || "\u672A\u77E5"} |
|
|
31154
|
+
|
|
31155
|
+
## \u65F6\u95F4\u4FE1\u606F
|
|
31156
|
+
|
|
31157
|
+
| \u5B57\u6BB5 | \u503C |
|
|
31158
|
+
|------|-----|
|
|
31159
|
+
| \u5F00\u59CB\u65F6\u95F4 | ${formatTimestamp(startedAt)} |
|
|
31160
|
+
| \u7ED3\u675F\u65F6\u95F4 | ${formatTimestamp(completedAt)} |
|
|
31161
|
+
| \u603B\u8017\u65F6 | ${duration} |
|
|
31162
|
+
|
|
31163
|
+
## \u4EFB\u52A1\u7EDF\u8BA1
|
|
31164
|
+
|
|
31165
|
+
| \u5B57\u6BB5 | \u503C |
|
|
31166
|
+
|------|-----|
|
|
31167
|
+
| \u603B\u4EFB\u52A1\u6570 | ${totalTasks} |
|
|
31168
|
+
| \u5DF2\u5B8C\u6210 | ${completedTasks} |
|
|
31169
|
+
| \u672A\u5B8C\u6210 | ${failedTasks} |
|
|
31170
|
+
| \u5B8C\u6210\u7387 | ${totalTasks > 0 ? Math.round(completedTasks / totalTasks * 100) : 0}% |
|
|
31171
|
+
|
|
31172
|
+
## \u5B8C\u6210\u4EFB\u52A1\u7D22\u5F15
|
|
31173
|
+
|
|
31174
|
+
${completedIndices.length > 0 ? completedIndices.map((i) => `- ${i}`).join(`
|
|
31175
|
+
`) : "\u65E0"}
|
|
31176
|
+
|
|
31177
|
+
${hasNotepad ? `## \u8BB0\u4E8B\u672C
|
|
31178
|
+
|
|
31179
|
+
\u8BB0\u4E8B\u672C\u8DEF\u5F84: ${notepadPath}
|
|
31180
|
+
` : ""}
|
|
31181
|
+
`;
|
|
31182
|
+
const reportPath = join52(reportsDir, `${data.planName}.md`);
|
|
31183
|
+
writeFileSync21(reportPath, report, "utf-8");
|
|
31184
|
+
log(`[plan-completion] Report generated at ${reportPath}`);
|
|
31185
|
+
}
|
|
31186
|
+
async function runInitDeep(data) {
|
|
31187
|
+
log(`[plan-completion] runInitDeep: ${data.planName}`);
|
|
31188
|
+
}
|
|
31189
|
+
async function promptGitCommit(data) {
|
|
31190
|
+
log(`[plan-completion] promptGitCommit: ${data.planName}`);
|
|
31191
|
+
}
|
|
31192
|
+
function createPlanCompletionHook(_ctx) {
|
|
31193
|
+
let onAction;
|
|
31194
|
+
const unsubscribe = boulderEventBus.on("plan_completed", async (data) => {
|
|
31195
|
+
log(`[plan-completion] Plan completed: ${data.planName}`);
|
|
31196
|
+
const actionsList = parseCompletionActions(data.planPath);
|
|
31197
|
+
const isEnabled = (type) => {
|
|
31198
|
+
const action = actionsList.find((a) => a.type === type);
|
|
31199
|
+
return action ? action.enabled : false;
|
|
31200
|
+
};
|
|
31201
|
+
await safeExecute(async () => updatePlanSummary(data), "update_summary", onAction);
|
|
31202
|
+
await safeExecute(async () => archivePlan(data), "archive", onAction);
|
|
31203
|
+
await safeExecute(async () => extractLearnings(data), "extract_learnings", onAction);
|
|
31204
|
+
await safeExecute(async () => generateReport(data), "generate_report", onAction);
|
|
31205
|
+
if (isEnabled("init_deep")) {
|
|
31206
|
+
await safeExecute(async () => runInitDeep(data), "init_deep", onAction);
|
|
31207
|
+
}
|
|
31208
|
+
if (isEnabled("git_commit")) {
|
|
31209
|
+
await safeExecute(async () => promptGitCommit(data), "git_commit", onAction);
|
|
31210
|
+
}
|
|
31211
|
+
});
|
|
31212
|
+
return {
|
|
31213
|
+
cleanup: () => {
|
|
31214
|
+
unsubscribe();
|
|
31215
|
+
},
|
|
31216
|
+
setOnActionCallback: (cb) => {
|
|
31217
|
+
onAction = cb;
|
|
31218
|
+
}
|
|
31219
|
+
};
|
|
31220
|
+
}
|
|
30804
31221
|
// src/features/context-injector/collector.ts
|
|
30805
31222
|
var PRIORITY_ORDER = {
|
|
30806
31223
|
critical: 0,
|
|
@@ -30974,8 +31391,8 @@ function createFirstMessageVariantGate() {
|
|
|
30974
31391
|
}
|
|
30975
31392
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
30976
31393
|
init_shared();
|
|
30977
|
-
import { existsSync as
|
|
30978
|
-
import { join as
|
|
31394
|
+
import { existsSync as existsSync40, readFileSync as readFileSync32 } from "fs";
|
|
31395
|
+
import { join as join53 } from "path";
|
|
30979
31396
|
|
|
30980
31397
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
30981
31398
|
function expandEnvVars(value) {
|
|
@@ -31045,13 +31462,13 @@ function getMcpConfigPaths() {
|
|
|
31045
31462
|
const claudeConfigDir = getClaudeConfigDir();
|
|
31046
31463
|
const cwd2 = process.cwd();
|
|
31047
31464
|
return [
|
|
31048
|
-
{ path:
|
|
31049
|
-
{ path:
|
|
31050
|
-
{ path:
|
|
31465
|
+
{ path: join53(claudeConfigDir, ".mcp.json"), scope: "user" },
|
|
31466
|
+
{ path: join53(cwd2, ".mcp.json"), scope: "project" },
|
|
31467
|
+
{ path: join53(cwd2, ".claude", ".mcp.json"), scope: "local" }
|
|
31051
31468
|
];
|
|
31052
31469
|
}
|
|
31053
31470
|
async function loadMcpConfigFile(filePath) {
|
|
31054
|
-
if (!
|
|
31471
|
+
if (!existsSync40(filePath)) {
|
|
31055
31472
|
return null;
|
|
31056
31473
|
}
|
|
31057
31474
|
try {
|
|
@@ -31066,10 +31483,10 @@ function getSystemMcpServerNames() {
|
|
|
31066
31483
|
const names = new Set;
|
|
31067
31484
|
const paths = getMcpConfigPaths();
|
|
31068
31485
|
for (const { path: path7 } of paths) {
|
|
31069
|
-
if (!
|
|
31486
|
+
if (!existsSync40(path7))
|
|
31070
31487
|
continue;
|
|
31071
31488
|
try {
|
|
31072
|
-
const content =
|
|
31489
|
+
const content = readFileSync32(path7, "utf-8");
|
|
31073
31490
|
const config = JSON.parse(content);
|
|
31074
31491
|
if (!config?.mcpServers)
|
|
31075
31492
|
continue;
|
|
@@ -31120,27 +31537,27 @@ async function loadMcpConfigs() {
|
|
|
31120
31537
|
return { servers, loadedServers };
|
|
31121
31538
|
}
|
|
31122
31539
|
// src/features/claude-code-session-state/recovery.ts
|
|
31123
|
-
import { existsSync as
|
|
31124
|
-
import { join as
|
|
31540
|
+
import { existsSync as existsSync41, readdirSync as readdirSync13 } from "fs";
|
|
31541
|
+
import { join as join54 } from "path";
|
|
31125
31542
|
init_logger();
|
|
31126
31543
|
function recoverSessionAgents() {
|
|
31127
31544
|
let recoveredCount = 0;
|
|
31128
31545
|
try {
|
|
31129
|
-
if (!
|
|
31546
|
+
if (!existsSync41(MESSAGE_STORAGE)) {
|
|
31130
31547
|
log("[recovery] MESSAGE_STORAGE directory does not exist", { path: MESSAGE_STORAGE });
|
|
31131
31548
|
return 0;
|
|
31132
31549
|
}
|
|
31133
|
-
const entries =
|
|
31550
|
+
const entries = readdirSync13(MESSAGE_STORAGE, { withFileTypes: true });
|
|
31134
31551
|
for (const entry of entries) {
|
|
31135
31552
|
if (!entry.isDirectory())
|
|
31136
31553
|
continue;
|
|
31137
|
-
const projectDir =
|
|
31554
|
+
const projectDir = join54(MESSAGE_STORAGE, entry.name);
|
|
31138
31555
|
try {
|
|
31139
|
-
const sessionDirs =
|
|
31556
|
+
const sessionDirs = readdirSync13(projectDir, { withFileTypes: true });
|
|
31140
31557
|
for (const sessionEntry of sessionDirs) {
|
|
31141
31558
|
if (!sessionEntry.isDirectory())
|
|
31142
31559
|
continue;
|
|
31143
|
-
const sessionDir =
|
|
31560
|
+
const sessionDir = join54(projectDir, sessionEntry.name);
|
|
31144
31561
|
const sessionID = sessionEntry.name;
|
|
31145
31562
|
try {
|
|
31146
31563
|
const msg = findNearestAssistantMessage(sessionDir);
|
|
@@ -31566,14 +31983,14 @@ var EXT_TO_LANG = {
|
|
|
31566
31983
|
".gql": "graphql"
|
|
31567
31984
|
};
|
|
31568
31985
|
// src/tools/lsp/config.ts
|
|
31569
|
-
import { existsSync as
|
|
31570
|
-
import { join as
|
|
31986
|
+
import { existsSync as existsSync42, readFileSync as readFileSync33 } from "fs";
|
|
31987
|
+
import { join as join55 } from "path";
|
|
31571
31988
|
init_shared();
|
|
31572
31989
|
function loadJsonFile(path7) {
|
|
31573
|
-
if (!
|
|
31990
|
+
if (!existsSync42(path7))
|
|
31574
31991
|
return null;
|
|
31575
31992
|
try {
|
|
31576
|
-
return JSON.parse(
|
|
31993
|
+
return JSON.parse(readFileSync33(path7, "utf-8"));
|
|
31577
31994
|
} catch {
|
|
31578
31995
|
return null;
|
|
31579
31996
|
}
|
|
@@ -31582,9 +31999,9 @@ function getConfigPaths3() {
|
|
|
31582
31999
|
const cwd2 = process.cwd();
|
|
31583
32000
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
31584
32001
|
return {
|
|
31585
|
-
project:
|
|
31586
|
-
user:
|
|
31587
|
-
opencode:
|
|
32002
|
+
project: join55(cwd2, ".opencode", "oh-my-opencode.json"),
|
|
32003
|
+
user: join55(configDir, "oh-my-opencode.json"),
|
|
32004
|
+
opencode: join55(configDir, "opencode.json")
|
|
31588
32005
|
};
|
|
31589
32006
|
}
|
|
31590
32007
|
function loadAllConfigs() {
|
|
@@ -31697,7 +32114,7 @@ function isServerInstalled(command) {
|
|
|
31697
32114
|
return false;
|
|
31698
32115
|
const cmd = command[0];
|
|
31699
32116
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
31700
|
-
if (
|
|
32117
|
+
if (existsSync42(cmd))
|
|
31701
32118
|
return true;
|
|
31702
32119
|
}
|
|
31703
32120
|
const isWindows2 = process.platform === "win32";
|
|
@@ -31719,23 +32136,23 @@ function isServerInstalled(command) {
|
|
|
31719
32136
|
const paths = pathEnv.split(pathSeparator);
|
|
31720
32137
|
for (const p of paths) {
|
|
31721
32138
|
for (const suffix of exts) {
|
|
31722
|
-
if (
|
|
32139
|
+
if (existsSync42(join55(p, cmd + suffix))) {
|
|
31723
32140
|
return true;
|
|
31724
32141
|
}
|
|
31725
32142
|
}
|
|
31726
32143
|
}
|
|
31727
32144
|
const cwd2 = process.cwd();
|
|
31728
32145
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
31729
|
-
const dataDir =
|
|
32146
|
+
const dataDir = join55(getDataDir(), "opencode");
|
|
31730
32147
|
const additionalBases = [
|
|
31731
|
-
|
|
31732
|
-
|
|
31733
|
-
|
|
31734
|
-
|
|
32148
|
+
join55(cwd2, "node_modules", ".bin"),
|
|
32149
|
+
join55(configDir, "bin"),
|
|
32150
|
+
join55(configDir, "node_modules", ".bin"),
|
|
32151
|
+
join55(dataDir, "bin")
|
|
31735
32152
|
];
|
|
31736
32153
|
for (const base of additionalBases) {
|
|
31737
32154
|
for (const suffix of exts) {
|
|
31738
|
-
if (
|
|
32155
|
+
if (existsSync42(join55(base, cmd + suffix))) {
|
|
31739
32156
|
return true;
|
|
31740
32157
|
}
|
|
31741
32158
|
}
|
|
@@ -31747,7 +32164,7 @@ function isServerInstalled(command) {
|
|
|
31747
32164
|
}
|
|
31748
32165
|
// src/tools/lsp/client.ts
|
|
31749
32166
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
31750
|
-
import { readFileSync as
|
|
32167
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
31751
32168
|
import { extname, resolve as resolve8 } from "path";
|
|
31752
32169
|
import { pathToFileURL } from "url";
|
|
31753
32170
|
class LSPServerManager {
|
|
@@ -32198,7 +32615,7 @@ ${msg}`);
|
|
|
32198
32615
|
const absPath = resolve8(filePath);
|
|
32199
32616
|
if (this.openedFiles.has(absPath))
|
|
32200
32617
|
return;
|
|
32201
|
-
const text =
|
|
32618
|
+
const text = readFileSync34(absPath, "utf-8");
|
|
32202
32619
|
const ext = extname(absPath);
|
|
32203
32620
|
const languageId = getLanguageId(ext);
|
|
32204
32621
|
this.notify("textDocument/didOpen", {
|
|
@@ -32288,17 +32705,17 @@ ${msg}`);
|
|
|
32288
32705
|
// src/tools/lsp/utils.ts
|
|
32289
32706
|
import { extname as extname2, resolve as resolve9 } from "path";
|
|
32290
32707
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32291
|
-
import { existsSync as
|
|
32708
|
+
import { existsSync as existsSync43, readFileSync as readFileSync35, writeFileSync as writeFileSync22 } from "fs";
|
|
32292
32709
|
function findWorkspaceRoot(filePath) {
|
|
32293
32710
|
let dir = resolve9(filePath);
|
|
32294
|
-
if (!
|
|
32711
|
+
if (!existsSync43(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
32295
32712
|
dir = __require("path").dirname(dir);
|
|
32296
32713
|
}
|
|
32297
32714
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
32298
32715
|
let prevDir = "";
|
|
32299
32716
|
while (dir !== prevDir) {
|
|
32300
32717
|
for (const marker of markers) {
|
|
32301
|
-
if (
|
|
32718
|
+
if (existsSync43(__require("path").join(dir, marker))) {
|
|
32302
32719
|
return dir;
|
|
32303
32720
|
}
|
|
32304
32721
|
}
|
|
@@ -32453,7 +32870,7 @@ function formatPrepareRenameResult(result) {
|
|
|
32453
32870
|
}
|
|
32454
32871
|
function applyTextEditsToFile(filePath, edits) {
|
|
32455
32872
|
try {
|
|
32456
|
-
let content =
|
|
32873
|
+
let content = readFileSync35(filePath, "utf-8");
|
|
32457
32874
|
const lines = content.split(`
|
|
32458
32875
|
`);
|
|
32459
32876
|
const sortedEdits = [...edits].sort((a, b) => {
|
|
@@ -32478,7 +32895,7 @@ function applyTextEditsToFile(filePath, edits) {
|
|
|
32478
32895
|
`));
|
|
32479
32896
|
}
|
|
32480
32897
|
}
|
|
32481
|
-
|
|
32898
|
+
writeFileSync22(filePath, lines.join(`
|
|
32482
32899
|
`), "utf-8");
|
|
32483
32900
|
return { success: true, editCount: edits.length };
|
|
32484
32901
|
} catch (err) {
|
|
@@ -32509,7 +32926,7 @@ function applyWorkspaceEdit(edit) {
|
|
|
32509
32926
|
if (change.kind === "create") {
|
|
32510
32927
|
try {
|
|
32511
32928
|
const filePath = uriToPath(change.uri);
|
|
32512
|
-
|
|
32929
|
+
writeFileSync22(filePath, "", "utf-8");
|
|
32513
32930
|
result.filesModified.push(filePath);
|
|
32514
32931
|
} catch (err) {
|
|
32515
32932
|
result.success = false;
|
|
@@ -32519,8 +32936,8 @@ function applyWorkspaceEdit(edit) {
|
|
|
32519
32936
|
try {
|
|
32520
32937
|
const oldPath = uriToPath(change.oldUri);
|
|
32521
32938
|
const newPath = uriToPath(change.newUri);
|
|
32522
|
-
const content =
|
|
32523
|
-
|
|
32939
|
+
const content = readFileSync35(oldPath, "utf-8");
|
|
32940
|
+
writeFileSync22(newPath, content, "utf-8");
|
|
32524
32941
|
__require("fs").unlinkSync(oldPath);
|
|
32525
32942
|
result.filesModified.push(newPath);
|
|
32526
32943
|
} catch (err) {
|
|
@@ -45099,13 +45516,13 @@ var lsp_rename = tool({
|
|
|
45099
45516
|
});
|
|
45100
45517
|
// src/tools/ast-grep/constants.ts
|
|
45101
45518
|
import { createRequire as createRequire4 } from "module";
|
|
45102
|
-
import { dirname as
|
|
45103
|
-
import { existsSync as
|
|
45519
|
+
import { dirname as dirname11, join as join57 } from "path";
|
|
45520
|
+
import { existsSync as existsSync45, statSync as statSync5 } from "fs";
|
|
45104
45521
|
|
|
45105
45522
|
// src/tools/ast-grep/downloader.ts
|
|
45106
45523
|
init_shared();
|
|
45107
|
-
import { existsSync as
|
|
45108
|
-
import { join as
|
|
45524
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync18, chmodSync as chmodSync2, unlinkSync as unlinkSync15 } from "fs";
|
|
45525
|
+
import { join as join56 } from "path";
|
|
45109
45526
|
import { homedir as homedir13 } from "os";
|
|
45110
45527
|
import { createRequire as createRequire3 } from "module";
|
|
45111
45528
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -45131,19 +45548,19 @@ var PLATFORM_MAP2 = {
|
|
|
45131
45548
|
function getCacheDir3() {
|
|
45132
45549
|
if (process.platform === "win32") {
|
|
45133
45550
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
45134
|
-
const base2 = localAppData ||
|
|
45135
|
-
return
|
|
45551
|
+
const base2 = localAppData || join56(homedir13(), "AppData", "Local");
|
|
45552
|
+
return join56(base2, "oh-my-opencode", "bin");
|
|
45136
45553
|
}
|
|
45137
45554
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
45138
|
-
const base = xdgCache ||
|
|
45139
|
-
return
|
|
45555
|
+
const base = xdgCache || join56(homedir13(), ".cache");
|
|
45556
|
+
return join56(base, "oh-my-opencode", "bin");
|
|
45140
45557
|
}
|
|
45141
45558
|
function getBinaryName3() {
|
|
45142
45559
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
45143
45560
|
}
|
|
45144
45561
|
function getCachedBinaryPath2() {
|
|
45145
|
-
const binaryPath =
|
|
45146
|
-
return
|
|
45562
|
+
const binaryPath = join56(getCacheDir3(), getBinaryName3());
|
|
45563
|
+
return existsSync44(binaryPath) ? binaryPath : null;
|
|
45147
45564
|
}
|
|
45148
45565
|
async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
45149
45566
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
@@ -45154,8 +45571,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45154
45571
|
}
|
|
45155
45572
|
const cacheDir = getCacheDir3();
|
|
45156
45573
|
const binaryName = getBinaryName3();
|
|
45157
|
-
const binaryPath =
|
|
45158
|
-
if (
|
|
45574
|
+
const binaryPath = join56(cacheDir, binaryName);
|
|
45575
|
+
if (existsSync44(binaryPath)) {
|
|
45159
45576
|
return binaryPath;
|
|
45160
45577
|
}
|
|
45161
45578
|
const { arch, os: os6 } = platformInfo;
|
|
@@ -45163,21 +45580,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
45163
45580
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
45164
45581
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
45165
45582
|
try {
|
|
45166
|
-
if (!
|
|
45167
|
-
|
|
45583
|
+
if (!existsSync44(cacheDir)) {
|
|
45584
|
+
mkdirSync18(cacheDir, { recursive: true });
|
|
45168
45585
|
}
|
|
45169
45586
|
const response = await fetch(downloadUrl, { redirect: "follow" });
|
|
45170
45587
|
if (!response.ok) {
|
|
45171
45588
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
45172
45589
|
}
|
|
45173
|
-
const archivePath =
|
|
45590
|
+
const archivePath = join56(cacheDir, assetName);
|
|
45174
45591
|
const arrayBuffer = await response.arrayBuffer();
|
|
45175
45592
|
await Bun.write(archivePath, arrayBuffer);
|
|
45176
45593
|
await extractZip(archivePath, cacheDir);
|
|
45177
|
-
if (
|
|
45178
|
-
|
|
45594
|
+
if (existsSync44(archivePath)) {
|
|
45595
|
+
unlinkSync15(archivePath);
|
|
45179
45596
|
}
|
|
45180
|
-
if (process.platform !== "win32" &&
|
|
45597
|
+
if (process.platform !== "win32" && existsSync44(binaryPath)) {
|
|
45181
45598
|
chmodSync2(binaryPath, 493);
|
|
45182
45599
|
}
|
|
45183
45600
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -45227,9 +45644,9 @@ function findSgCliPathSync() {
|
|
|
45227
45644
|
try {
|
|
45228
45645
|
const require2 = createRequire4(import.meta.url);
|
|
45229
45646
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
45230
|
-
const cliDir =
|
|
45231
|
-
const sgPath =
|
|
45232
|
-
if (
|
|
45647
|
+
const cliDir = dirname11(cliPkgPath);
|
|
45648
|
+
const sgPath = join57(cliDir, binaryName);
|
|
45649
|
+
if (existsSync45(sgPath) && isValidBinary(sgPath)) {
|
|
45233
45650
|
return sgPath;
|
|
45234
45651
|
}
|
|
45235
45652
|
} catch {}
|
|
@@ -45238,10 +45655,10 @@ function findSgCliPathSync() {
|
|
|
45238
45655
|
try {
|
|
45239
45656
|
const require2 = createRequire4(import.meta.url);
|
|
45240
45657
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
45241
|
-
const pkgDir =
|
|
45658
|
+
const pkgDir = dirname11(pkgPath);
|
|
45242
45659
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
45243
|
-
const binaryPath =
|
|
45244
|
-
if (
|
|
45660
|
+
const binaryPath = join57(pkgDir, astGrepName);
|
|
45661
|
+
if (existsSync45(binaryPath) && isValidBinary(binaryPath)) {
|
|
45245
45662
|
return binaryPath;
|
|
45246
45663
|
}
|
|
45247
45664
|
} catch {}
|
|
@@ -45249,7 +45666,7 @@ function findSgCliPathSync() {
|
|
|
45249
45666
|
if (process.platform === "darwin") {
|
|
45250
45667
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
45251
45668
|
for (const path7 of homebrewPaths) {
|
|
45252
|
-
if (
|
|
45669
|
+
if (existsSync45(path7) && isValidBinary(path7)) {
|
|
45253
45670
|
return path7;
|
|
45254
45671
|
}
|
|
45255
45672
|
}
|
|
@@ -45304,11 +45721,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
45304
45721
|
|
|
45305
45722
|
// src/tools/ast-grep/cli.ts
|
|
45306
45723
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
45307
|
-
import { existsSync as
|
|
45724
|
+
import { existsSync as existsSync46 } from "fs";
|
|
45308
45725
|
var resolvedCliPath3 = null;
|
|
45309
45726
|
var initPromise2 = null;
|
|
45310
45727
|
async function getAstGrepPath() {
|
|
45311
|
-
if (resolvedCliPath3 !== null &&
|
|
45728
|
+
if (resolvedCliPath3 !== null && existsSync46(resolvedCliPath3)) {
|
|
45312
45729
|
return resolvedCliPath3;
|
|
45313
45730
|
}
|
|
45314
45731
|
if (initPromise2) {
|
|
@@ -45316,7 +45733,7 @@ async function getAstGrepPath() {
|
|
|
45316
45733
|
}
|
|
45317
45734
|
initPromise2 = (async () => {
|
|
45318
45735
|
const syncPath = findSgCliPathSync();
|
|
45319
|
-
if (syncPath &&
|
|
45736
|
+
if (syncPath && existsSync46(syncPath)) {
|
|
45320
45737
|
resolvedCliPath3 = syncPath;
|
|
45321
45738
|
setSgCliPath(syncPath);
|
|
45322
45739
|
return syncPath;
|
|
@@ -45350,7 +45767,7 @@ async function runSg(options) {
|
|
|
45350
45767
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
45351
45768
|
args.push(...paths);
|
|
45352
45769
|
let cliPath = getSgCliPath();
|
|
45353
|
-
if (!
|
|
45770
|
+
if (!existsSync46(cliPath) && cliPath !== "sg") {
|
|
45354
45771
|
const downloadedPath = await getAstGrepPath();
|
|
45355
45772
|
if (downloadedPath) {
|
|
45356
45773
|
cliPath = downloadedPath;
|
|
@@ -45614,21 +46031,21 @@ var ast_grep_replace = tool({
|
|
|
45614
46031
|
var {spawn: spawn9 } = globalThis.Bun;
|
|
45615
46032
|
|
|
45616
46033
|
// src/tools/grep/constants.ts
|
|
45617
|
-
import { existsSync as
|
|
45618
|
-
import { join as
|
|
46034
|
+
import { existsSync as existsSync48 } from "fs";
|
|
46035
|
+
import { join as join59, dirname as dirname12 } from "path";
|
|
45619
46036
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
45620
46037
|
|
|
45621
46038
|
// src/tools/grep/downloader.ts
|
|
45622
46039
|
init_shared();
|
|
45623
|
-
import { existsSync as
|
|
45624
|
-
import { join as
|
|
46040
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync19, chmodSync as chmodSync3, unlinkSync as unlinkSync16, readdirSync as readdirSync14 } from "fs";
|
|
46041
|
+
import { join as join58 } from "path";
|
|
45625
46042
|
var {spawn: spawn8 } = globalThis.Bun;
|
|
45626
46043
|
function findFileRecursive(dir, filename) {
|
|
45627
46044
|
try {
|
|
45628
|
-
const entries =
|
|
46045
|
+
const entries = readdirSync14(dir, { withFileTypes: true, recursive: true });
|
|
45629
46046
|
for (const entry of entries) {
|
|
45630
46047
|
if (entry.isFile() && entry.name === filename) {
|
|
45631
|
-
return
|
|
46048
|
+
return join58(entry.parentPath ?? dir, entry.name);
|
|
45632
46049
|
}
|
|
45633
46050
|
}
|
|
45634
46051
|
} catch {
|
|
@@ -45649,11 +46066,11 @@ function getPlatformKey() {
|
|
|
45649
46066
|
}
|
|
45650
46067
|
function getInstallDir() {
|
|
45651
46068
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
45652
|
-
return
|
|
46069
|
+
return join58(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
45653
46070
|
}
|
|
45654
46071
|
function getRgPath() {
|
|
45655
46072
|
const isWindows2 = process.platform === "win32";
|
|
45656
|
-
return
|
|
46073
|
+
return join58(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
45657
46074
|
}
|
|
45658
46075
|
async function downloadFile(url2, destPath) {
|
|
45659
46076
|
const response = await fetch(url2);
|
|
@@ -45687,10 +46104,10 @@ async function extractZip2(archivePath, destDir) {
|
|
|
45687
46104
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
45688
46105
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
45689
46106
|
if (foundPath) {
|
|
45690
|
-
const destPath =
|
|
46107
|
+
const destPath = join58(destDir, binaryName);
|
|
45691
46108
|
if (foundPath !== destPath) {
|
|
45692
|
-
const { renameSync:
|
|
45693
|
-
|
|
46109
|
+
const { renameSync: renameSync5 } = await import("fs");
|
|
46110
|
+
renameSync5(foundPath, destPath);
|
|
45694
46111
|
}
|
|
45695
46112
|
}
|
|
45696
46113
|
}
|
|
@@ -45702,13 +46119,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
45702
46119
|
}
|
|
45703
46120
|
const installDir = getInstallDir();
|
|
45704
46121
|
const rgPath = getRgPath();
|
|
45705
|
-
if (
|
|
46122
|
+
if (existsSync47(rgPath)) {
|
|
45706
46123
|
return rgPath;
|
|
45707
46124
|
}
|
|
45708
|
-
|
|
46125
|
+
mkdirSync19(installDir, { recursive: true });
|
|
45709
46126
|
const filename = `ripgrep-${RG_VERSION}-${config3.platform}.${config3.extension}`;
|
|
45710
46127
|
const url2 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
45711
|
-
const archivePath =
|
|
46128
|
+
const archivePath = join58(installDir, filename);
|
|
45712
46129
|
try {
|
|
45713
46130
|
await downloadFile(url2, archivePath);
|
|
45714
46131
|
if (config3.extension === "tar.gz") {
|
|
@@ -45719,21 +46136,21 @@ async function downloadAndInstallRipgrep() {
|
|
|
45719
46136
|
if (process.platform !== "win32") {
|
|
45720
46137
|
chmodSync3(rgPath, 493);
|
|
45721
46138
|
}
|
|
45722
|
-
if (!
|
|
46139
|
+
if (!existsSync47(rgPath)) {
|
|
45723
46140
|
throw new Error("\u63D0\u53D6\u540E\u672A\u627E\u5230 ripgrep \u4E8C\u8FDB\u5236\u6587\u4EF6");
|
|
45724
46141
|
}
|
|
45725
46142
|
return rgPath;
|
|
45726
46143
|
} finally {
|
|
45727
|
-
if (
|
|
46144
|
+
if (existsSync47(archivePath)) {
|
|
45728
46145
|
try {
|
|
45729
|
-
|
|
46146
|
+
unlinkSync16(archivePath);
|
|
45730
46147
|
} catch {}
|
|
45731
46148
|
}
|
|
45732
46149
|
}
|
|
45733
46150
|
}
|
|
45734
46151
|
function getInstalledRipgrepPath() {
|
|
45735
46152
|
const rgPath = getRgPath();
|
|
45736
|
-
return
|
|
46153
|
+
return existsSync47(rgPath) ? rgPath : null;
|
|
45737
46154
|
}
|
|
45738
46155
|
|
|
45739
46156
|
// src/tools/grep/constants.ts
|
|
@@ -45757,7 +46174,7 @@ function findExecutable(name) {
|
|
|
45757
46174
|
continue;
|
|
45758
46175
|
}
|
|
45759
46176
|
}
|
|
45760
|
-
if (
|
|
46177
|
+
if (existsSync48(trimmed)) {
|
|
45761
46178
|
return trimmed;
|
|
45762
46179
|
}
|
|
45763
46180
|
}
|
|
@@ -45768,18 +46185,18 @@ function findExecutable(name) {
|
|
|
45768
46185
|
}
|
|
45769
46186
|
function getOpenCodeBundledRg() {
|
|
45770
46187
|
const execPath = process.execPath;
|
|
45771
|
-
const execDir =
|
|
46188
|
+
const execDir = dirname12(execPath);
|
|
45772
46189
|
const isWindows2 = process.platform === "win32";
|
|
45773
46190
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
45774
46191
|
const candidates = [
|
|
45775
|
-
|
|
45776
|
-
|
|
45777
|
-
|
|
45778
|
-
|
|
45779
|
-
|
|
46192
|
+
join59(getDataDir(), "opencode", "bin", rgName),
|
|
46193
|
+
join59(execDir, rgName),
|
|
46194
|
+
join59(execDir, "bin", rgName),
|
|
46195
|
+
join59(execDir, "..", "bin", rgName),
|
|
46196
|
+
join59(execDir, "..", "libexec", rgName)
|
|
45780
46197
|
];
|
|
45781
46198
|
for (const candidate of candidates) {
|
|
45782
|
-
if (
|
|
46199
|
+
if (existsSync48(candidate)) {
|
|
45783
46200
|
return candidate;
|
|
45784
46201
|
}
|
|
45785
46202
|
}
|
|
@@ -46241,8 +46658,8 @@ var glob = tool({
|
|
|
46241
46658
|
init_shared();
|
|
46242
46659
|
init_file_utils();
|
|
46243
46660
|
init_shared();
|
|
46244
|
-
import { existsSync as
|
|
46245
|
-
import { join as
|
|
46661
|
+
import { existsSync as existsSync49, readdirSync as readdirSync15, readFileSync as readFileSync36 } from "fs";
|
|
46662
|
+
import { join as join60, basename as basename4, dirname as dirname13 } from "path";
|
|
46246
46663
|
// src/features/builtin-commands/templates/init-deep.ts
|
|
46247
46664
|
var INIT_DEEP_TEMPLATE = `# /init-deep
|
|
46248
46665
|
|
|
@@ -47282,6 +47699,21 @@ var START_WORK_TEMPLATE = `\u4F60\u6B63\u5728\u5F00\u59CB\u4E00\u4E2A \u4E3B\u62
|
|
|
47282
47699
|
- \u5728\u59D4\u6D3E\u4EFB\u4F55\u4EFB\u52A1\u4E4B\u524D\uFF0C\u8BFB\u53D6\u5B8C\u6574\u7684\u8BA1\u5212\u6587\u4EF6
|
|
47283
47700
|
- \u9075\u5FAA \u4EFB\u52A1\u7F16\u6392-\u4E3B\u6267\u884C\u5B98 \u7684\u59D4\u6D3E\u534F\u8BAE\uFF087 \u8282\u683C\u5F0F\uFF09`;
|
|
47284
47701
|
|
|
47702
|
+
// src/features/builtin-commands/templates/btw.ts
|
|
47703
|
+
var BTW_TEMPLATE = `# /btw \u547D\u4EE4 \u2014 \u6781\u5EA6\u7CBE\u7B80\u4FA7\u8FB9\u63D0\u95EE
|
|
47704
|
+
|
|
47705
|
+
\u4F60\u6536\u5230\u4E86\u4E00\u4E2A\u4FA7\u8FB9\u95EE\u9898\u3002\u8BF7\u4EE5\u5355\u6B21\u54CD\u5E94\u56DE\u7B54\uFF0C\u4E0D\u8981\u53D1\u8D77\u540E\u7EED\u8FFD\u95EE\u3002
|
|
47706
|
+
|
|
47707
|
+
## \u7EA6\u675F
|
|
47708
|
+
- \u76F4\u63A5\u56DE\u7B54\u95EE\u9898\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4E0A\u4E0B\u6587\u65E0\u5173\u7684\u5185\u5BB9
|
|
47709
|
+
- \u56DE\u7B54\u63A7\u5236\u5728 100 \u5B57\u4EE5\u5185\uFF0C1-3 \u53E5\u8BDD
|
|
47710
|
+
- \u53EA\u8F93\u51FA\u7B54\u6848\u672C\u8EAB\uFF0C\u4E0D\u8981\u8F93\u51FA\u601D\u8003\u8FC7\u7A0B\u6216\u5206\u6790
|
|
47711
|
+
- \u4E0D\u8981\u53D1\u8D77\u540E\u7EED\u5BF9\u8BDD
|
|
47712
|
+
- \u4F7F\u7528\u4E2D\u6587\u56DE\u590D
|
|
47713
|
+
|
|
47714
|
+
## \u7528\u6237\u95EE\u9898
|
|
47715
|
+
$ARGUMENTS`;
|
|
47716
|
+
|
|
47285
47717
|
// src/features/builtin-commands/commands.ts
|
|
47286
47718
|
var BUILTIN_COMMAND_DEFINITIONS = {
|
|
47287
47719
|
"init-deep": {
|
|
@@ -47346,6 +47778,17 @@ Timestamp: $TIMESTAMP
|
|
|
47346
47778
|
$ARGUMENTS
|
|
47347
47779
|
</user-request>`,
|
|
47348
47780
|
argumentHint: "[plan-name]"
|
|
47781
|
+
},
|
|
47782
|
+
btw: {
|
|
47783
|
+
description: "(builtin) \u6781\u5EA6\u7CBE\u7B80\u4FA7\u8FB9\u63D0\u95EE \u2014 \u5F02\u6B65\u6267\u884C\uFF0C\u4E0D\u963B\u585E\u4E3B\u5BF9\u8BDD",
|
|
47784
|
+
template: `<command-instruction>
|
|
47785
|
+
${BTW_TEMPLATE}
|
|
47786
|
+
</command-instruction>
|
|
47787
|
+
|
|
47788
|
+
<user-request>
|
|
47789
|
+
$ARGUMENTS
|
|
47790
|
+
</user-request>`,
|
|
47791
|
+
argumentHint: "<\u4F60\u7684\u95EE\u9898>"
|
|
47349
47792
|
}
|
|
47350
47793
|
};
|
|
47351
47794
|
function loadBuiltinCommands(disabledCommands) {
|
|
@@ -47361,18 +47804,18 @@ function loadBuiltinCommands(disabledCommands) {
|
|
|
47361
47804
|
}
|
|
47362
47805
|
// src/tools/slashcommand/tools.ts
|
|
47363
47806
|
function discoverCommandsFromDir2(commandsDir, scope) {
|
|
47364
|
-
if (!
|
|
47807
|
+
if (!existsSync49(commandsDir)) {
|
|
47365
47808
|
return [];
|
|
47366
47809
|
}
|
|
47367
|
-
const entries =
|
|
47810
|
+
const entries = readdirSync15(commandsDir, { withFileTypes: true });
|
|
47368
47811
|
const commands2 = [];
|
|
47369
47812
|
for (const entry of entries) {
|
|
47370
47813
|
if (!isMarkdownFile(entry))
|
|
47371
47814
|
continue;
|
|
47372
|
-
const commandPath =
|
|
47815
|
+
const commandPath = join60(commandsDir, entry.name);
|
|
47373
47816
|
const commandName = basename4(entry.name, ".md");
|
|
47374
47817
|
try {
|
|
47375
|
-
const content =
|
|
47818
|
+
const content = readFileSync36(commandPath, "utf-8");
|
|
47376
47819
|
const { data, body } = parseFrontmatter(content);
|
|
47377
47820
|
const isOpencodeSource = scope === "opencode" || scope === "opencode-project";
|
|
47378
47821
|
const metadata = {
|
|
@@ -47398,10 +47841,10 @@ function discoverCommandsFromDir2(commandsDir, scope) {
|
|
|
47398
47841
|
}
|
|
47399
47842
|
function discoverCommandsSync() {
|
|
47400
47843
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
47401
|
-
const userCommandsDir =
|
|
47402
|
-
const projectCommandsDir =
|
|
47403
|
-
const opencodeGlobalDir =
|
|
47404
|
-
const opencodeProjectDir =
|
|
47844
|
+
const userCommandsDir = join60(getClaudeConfigDir(), "commands");
|
|
47845
|
+
const projectCommandsDir = join60(process.cwd(), ".claude", "commands");
|
|
47846
|
+
const opencodeGlobalDir = join60(configDir, "command");
|
|
47847
|
+
const opencodeProjectDir = join60(process.cwd(), ".opencode", "command");
|
|
47405
47848
|
const userCommands = discoverCommandsFromDir2(userCommandsDir, "user");
|
|
47406
47849
|
const opencodeGlobalCommands = discoverCommandsFromDir2(opencodeGlobalDir, "opencode");
|
|
47407
47850
|
const projectCommands = discoverCommandsFromDir2(projectCommandsDir, "project");
|
|
@@ -47473,7 +47916,7 @@ async function formatLoadedCommand(cmd) {
|
|
|
47473
47916
|
if (!content && cmd.lazyContentLoader) {
|
|
47474
47917
|
content = await cmd.lazyContentLoader.load();
|
|
47475
47918
|
}
|
|
47476
|
-
const commandDir = cmd.path ?
|
|
47919
|
+
const commandDir = cmd.path ? dirname13(cmd.path) : process.cwd();
|
|
47477
47920
|
const withFileRefs = await resolveFileReferencesInText(content, commandDir);
|
|
47478
47921
|
const resolvedContent = await resolveCommandsInText(withFileRefs);
|
|
47479
47922
|
sections.push(resolvedContent.trim());
|
|
@@ -47578,13 +48021,13 @@ var slashcommand = createSlashcommandTool();
|
|
|
47578
48021
|
// src/tools/session-manager/constants.ts
|
|
47579
48022
|
init_data_path();
|
|
47580
48023
|
init_shared();
|
|
47581
|
-
import { join as
|
|
48024
|
+
import { join as join61 } from "path";
|
|
47582
48025
|
var OPENCODE_STORAGE11 = getOpenCodeStorageDir();
|
|
47583
|
-
var MESSAGE_STORAGE4 =
|
|
47584
|
-
var PART_STORAGE4 =
|
|
47585
|
-
var SESSION_STORAGE =
|
|
47586
|
-
var TODO_DIR2 =
|
|
47587
|
-
var TRANSCRIPT_DIR2 =
|
|
48026
|
+
var MESSAGE_STORAGE4 = join61(OPENCODE_STORAGE11, "message");
|
|
48027
|
+
var PART_STORAGE4 = join61(OPENCODE_STORAGE11, "part");
|
|
48028
|
+
var SESSION_STORAGE = join61(OPENCODE_STORAGE11, "session");
|
|
48029
|
+
var TODO_DIR2 = join61(getClaudeConfigDir(), "todos");
|
|
48030
|
+
var TRANSCRIPT_DIR2 = join61(getClaudeConfigDir(), "transcripts");
|
|
47588
48031
|
var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\u652F\u6301\u53EF\u9009\u8FC7\u6EE4\u3002
|
|
47589
48032
|
|
|
47590
48033
|
\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
|
|
@@ -47657,11 +48100,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
47657
48100
|
Has Transcript: Yes (234 entries)`;
|
|
47658
48101
|
|
|
47659
48102
|
// src/tools/session-manager/storage.ts
|
|
47660
|
-
import { existsSync as
|
|
48103
|
+
import { existsSync as existsSync50, readdirSync as readdirSync16 } from "fs";
|
|
47661
48104
|
import { readdir, readFile } from "fs/promises";
|
|
47662
|
-
import { join as
|
|
48105
|
+
import { join as join62 } from "path";
|
|
47663
48106
|
async function getMainSessions(options) {
|
|
47664
|
-
if (!
|
|
48107
|
+
if (!existsSync50(SESSION_STORAGE))
|
|
47665
48108
|
return [];
|
|
47666
48109
|
const sessions = [];
|
|
47667
48110
|
try {
|
|
@@ -47669,13 +48112,13 @@ async function getMainSessions(options) {
|
|
|
47669
48112
|
for (const projectDir of projectDirs) {
|
|
47670
48113
|
if (!projectDir.isDirectory())
|
|
47671
48114
|
continue;
|
|
47672
|
-
const projectPath =
|
|
48115
|
+
const projectPath = join62(SESSION_STORAGE, projectDir.name);
|
|
47673
48116
|
const sessionFiles = await readdir(projectPath);
|
|
47674
48117
|
for (const file2 of sessionFiles) {
|
|
47675
48118
|
if (!file2.endsWith(".json"))
|
|
47676
48119
|
continue;
|
|
47677
48120
|
try {
|
|
47678
|
-
const content = await readFile(
|
|
48121
|
+
const content = await readFile(join62(projectPath, file2), "utf-8");
|
|
47679
48122
|
const meta = JSON.parse(content);
|
|
47680
48123
|
if (meta.parentID)
|
|
47681
48124
|
continue;
|
|
@@ -47693,7 +48136,7 @@ async function getMainSessions(options) {
|
|
|
47693
48136
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
47694
48137
|
}
|
|
47695
48138
|
async function getAllSessions() {
|
|
47696
|
-
if (!
|
|
48139
|
+
if (!existsSync50(MESSAGE_STORAGE4))
|
|
47697
48140
|
return [];
|
|
47698
48141
|
const sessions = [];
|
|
47699
48142
|
async function scanDirectory(dir) {
|
|
@@ -47701,7 +48144,7 @@ async function getAllSessions() {
|
|
|
47701
48144
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
47702
48145
|
for (const entry of entries) {
|
|
47703
48146
|
if (entry.isDirectory()) {
|
|
47704
|
-
const sessionPath =
|
|
48147
|
+
const sessionPath = join62(dir, entry.name);
|
|
47705
48148
|
const files = await readdir(sessionPath);
|
|
47706
48149
|
if (files.some((f) => f.endsWith(".json"))) {
|
|
47707
48150
|
sessions.push(entry.name);
|
|
@@ -47718,16 +48161,16 @@ async function getAllSessions() {
|
|
|
47718
48161
|
return [...new Set(sessions)];
|
|
47719
48162
|
}
|
|
47720
48163
|
function getMessageDir6(sessionID) {
|
|
47721
|
-
if (!
|
|
48164
|
+
if (!existsSync50(MESSAGE_STORAGE4))
|
|
47722
48165
|
return "";
|
|
47723
|
-
const directPath =
|
|
47724
|
-
if (
|
|
48166
|
+
const directPath = join62(MESSAGE_STORAGE4, sessionID);
|
|
48167
|
+
if (existsSync50(directPath)) {
|
|
47725
48168
|
return directPath;
|
|
47726
48169
|
}
|
|
47727
48170
|
try {
|
|
47728
|
-
for (const dir of
|
|
47729
|
-
const sessionPath =
|
|
47730
|
-
if (
|
|
48171
|
+
for (const dir of readdirSync16(MESSAGE_STORAGE4)) {
|
|
48172
|
+
const sessionPath = join62(MESSAGE_STORAGE4, dir, sessionID);
|
|
48173
|
+
if (existsSync50(sessionPath)) {
|
|
47731
48174
|
return sessionPath;
|
|
47732
48175
|
}
|
|
47733
48176
|
}
|
|
@@ -47741,7 +48184,7 @@ function sessionExists(sessionID) {
|
|
|
47741
48184
|
}
|
|
47742
48185
|
async function readSessionMessages(sessionID) {
|
|
47743
48186
|
const messageDir = getMessageDir6(sessionID);
|
|
47744
|
-
if (!messageDir || !
|
|
48187
|
+
if (!messageDir || !existsSync50(messageDir))
|
|
47745
48188
|
return [];
|
|
47746
48189
|
const messages = [];
|
|
47747
48190
|
try {
|
|
@@ -47750,7 +48193,7 @@ async function readSessionMessages(sessionID) {
|
|
|
47750
48193
|
if (!file2.endsWith(".json"))
|
|
47751
48194
|
continue;
|
|
47752
48195
|
try {
|
|
47753
|
-
const content = await readFile(
|
|
48196
|
+
const content = await readFile(join62(messageDir, file2), "utf-8");
|
|
47754
48197
|
const meta = JSON.parse(content);
|
|
47755
48198
|
const parts = await readParts2(meta.id);
|
|
47756
48199
|
messages.push({
|
|
@@ -47776,8 +48219,8 @@ async function readSessionMessages(sessionID) {
|
|
|
47776
48219
|
});
|
|
47777
48220
|
}
|
|
47778
48221
|
async function readParts2(messageID) {
|
|
47779
|
-
const partDir =
|
|
47780
|
-
if (!
|
|
48222
|
+
const partDir = join62(PART_STORAGE4, messageID);
|
|
48223
|
+
if (!existsSync50(partDir))
|
|
47781
48224
|
return [];
|
|
47782
48225
|
const parts = [];
|
|
47783
48226
|
try {
|
|
@@ -47786,7 +48229,7 @@ async function readParts2(messageID) {
|
|
|
47786
48229
|
if (!file2.endsWith(".json"))
|
|
47787
48230
|
continue;
|
|
47788
48231
|
try {
|
|
47789
|
-
const content = await readFile(
|
|
48232
|
+
const content = await readFile(join62(partDir, file2), "utf-8");
|
|
47790
48233
|
parts.push(JSON.parse(content));
|
|
47791
48234
|
} catch {
|
|
47792
48235
|
continue;
|
|
@@ -47798,14 +48241,14 @@ async function readParts2(messageID) {
|
|
|
47798
48241
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
47799
48242
|
}
|
|
47800
48243
|
async function readSessionTodos(sessionID) {
|
|
47801
|
-
if (!
|
|
48244
|
+
if (!existsSync50(TODO_DIR2))
|
|
47802
48245
|
return [];
|
|
47803
48246
|
try {
|
|
47804
48247
|
const allFiles = await readdir(TODO_DIR2);
|
|
47805
48248
|
const todoFiles = allFiles.filter((f) => f.includes(sessionID) && f.endsWith(".json"));
|
|
47806
48249
|
for (const file2 of todoFiles) {
|
|
47807
48250
|
try {
|
|
47808
|
-
const content = await readFile(
|
|
48251
|
+
const content = await readFile(join62(TODO_DIR2, file2), "utf-8");
|
|
47809
48252
|
const data = JSON.parse(content);
|
|
47810
48253
|
if (Array.isArray(data)) {
|
|
47811
48254
|
return data.map((item) => ({
|
|
@@ -47825,10 +48268,10 @@ async function readSessionTodos(sessionID) {
|
|
|
47825
48268
|
return [];
|
|
47826
48269
|
}
|
|
47827
48270
|
async function readSessionTranscript(sessionID) {
|
|
47828
|
-
if (!
|
|
48271
|
+
if (!existsSync50(TRANSCRIPT_DIR2))
|
|
47829
48272
|
return 0;
|
|
47830
|
-
const transcriptFile =
|
|
47831
|
-
if (!
|
|
48273
|
+
const transcriptFile = join62(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
48274
|
+
if (!existsSync50(transcriptFile))
|
|
47832
48275
|
return 0;
|
|
47833
48276
|
try {
|
|
47834
48277
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -48324,7 +48767,7 @@ var TOOL_DESCRIPTION_PREFIX2 = `\u52A0\u8F7D skill \u4EE5\u83B7\u53D6\u7279\u5B9
|
|
|
48324
48767
|
Skills \u63D0\u4F9B\u4E13\u4E1A\u77E5\u8BC6\u548C\u5206\u6B65\u6307\u5BFC\u3002
|
|
48325
48768
|
\u5F53\u4EFB\u52A1\u4E0E\u53EF\u7528 skill \u7684\u63CF\u8FF0\u76F8\u5339\u914D\u65F6\u4F7F\u7528\u6B64\u5DE5\u5177\u3002`;
|
|
48326
48769
|
// src/tools/skill/tools.ts
|
|
48327
|
-
import { dirname as
|
|
48770
|
+
import { dirname as dirname14 } from "path";
|
|
48328
48771
|
function loadedSkillToInfo(skill) {
|
|
48329
48772
|
return {
|
|
48330
48773
|
name: skill.name,
|
|
@@ -48478,7 +48921,7 @@ function createSkillTool(options = {}) {
|
|
|
48478
48921
|
if (args.name === "git-master") {
|
|
48479
48922
|
body = injectGitMasterConfig(body, options.gitMasterConfig);
|
|
48480
48923
|
}
|
|
48481
|
-
const dir = skill.path ?
|
|
48924
|
+
const dir = skill.path ? dirname14(skill.path) : skill.resolvedPath || process.cwd();
|
|
48482
48925
|
const output = [
|
|
48483
48926
|
`## Skill: ${skill.name}`,
|
|
48484
48927
|
"",
|
|
@@ -49035,20 +49478,20 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
|
|
|
49035
49478
|
|
|
49036
49479
|
\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`;
|
|
49037
49480
|
// src/tools/call-omo-agent/tools.ts
|
|
49038
|
-
import { existsSync as
|
|
49039
|
-
import { join as
|
|
49481
|
+
import { existsSync as existsSync51, readdirSync as readdirSync17 } from "fs";
|
|
49482
|
+
import { join as join63 } from "path";
|
|
49040
49483
|
init_shared();
|
|
49041
49484
|
init_agent_display_names();
|
|
49042
49485
|
init_session_cursor();
|
|
49043
49486
|
function getMessageDir7(sessionID) {
|
|
49044
|
-
if (!
|
|
49487
|
+
if (!existsSync51(MESSAGE_STORAGE))
|
|
49045
49488
|
return null;
|
|
49046
|
-
const directPath =
|
|
49047
|
-
if (
|
|
49489
|
+
const directPath = join63(MESSAGE_STORAGE, sessionID);
|
|
49490
|
+
if (existsSync51(directPath))
|
|
49048
49491
|
return directPath;
|
|
49049
|
-
for (const dir of
|
|
49050
|
-
const sessionPath =
|
|
49051
|
-
if (
|
|
49492
|
+
for (const dir of readdirSync17(MESSAGE_STORAGE)) {
|
|
49493
|
+
const sessionPath = join63(MESSAGE_STORAGE, dir, sessionID);
|
|
49494
|
+
if (existsSync51(sessionPath))
|
|
49052
49495
|
return sessionPath;
|
|
49053
49496
|
}
|
|
49054
49497
|
return null;
|
|
@@ -49474,8 +49917,8 @@ function createLookAt(ctx) {
|
|
|
49474
49917
|
}
|
|
49475
49918
|
// src/tools/delegate-task/tools.ts
|
|
49476
49919
|
init_constants();
|
|
49477
|
-
import { existsSync as
|
|
49478
|
-
import { join as
|
|
49920
|
+
import { existsSync as existsSync52, readdirSync as readdirSync18 } from "fs";
|
|
49921
|
+
import { join as join64 } from "path";
|
|
49479
49922
|
|
|
49480
49923
|
// src/features/task-toast-manager/manager.ts
|
|
49481
49924
|
class TaskToastManager {
|
|
@@ -49681,14 +50124,14 @@ function parseFallbackModelEntries(entries) {
|
|
|
49681
50124
|
});
|
|
49682
50125
|
}
|
|
49683
50126
|
function getMessageDir8(sessionID) {
|
|
49684
|
-
if (!
|
|
50127
|
+
if (!existsSync52(MESSAGE_STORAGE))
|
|
49685
50128
|
return null;
|
|
49686
|
-
const directPath =
|
|
49687
|
-
if (
|
|
50129
|
+
const directPath = join64(MESSAGE_STORAGE, sessionID);
|
|
50130
|
+
if (existsSync52(directPath))
|
|
49688
50131
|
return directPath;
|
|
49689
|
-
for (const dir of
|
|
49690
|
-
const sessionPath =
|
|
49691
|
-
if (
|
|
50132
|
+
for (const dir of readdirSync18(MESSAGE_STORAGE)) {
|
|
50133
|
+
const sessionPath = join64(MESSAGE_STORAGE, dir, sessionID);
|
|
50134
|
+
if (existsSync52(sessionPath))
|
|
49692
50135
|
return sessionPath;
|
|
49693
50136
|
}
|
|
49694
50137
|
return null;
|
|
@@ -50481,6 +50924,44 @@ ${classification.shouldFallback ? "\uD83D\uDCA1 \u6B64\u9519\u8BEF\u7B26\u5408 r
|
|
|
50481
50924
|
|
|
50482
50925
|
// src/tools/delegate-task/index.ts
|
|
50483
50926
|
init_constants();
|
|
50927
|
+
// src/tools/btw/constants.ts
|
|
50928
|
+
var BTW_TOOL_DESCRIPTION = `
|
|
50929
|
+
\u5411 BTW \u987E\u95EE\uFF08\u53EA\u8BFB\u8F7B\u91CF Agent\uFF09\u63D0\u51FA\u4E00\u4E2A\u5FEB\u901F\u95EE\u9898\u3002
|
|
50930
|
+
\u5F02\u6B65\u6267\u884C\uFF0C\u4E0D\u963B\u585E\u4E3B\u5BF9\u8BDD\u2014\u2014\u5B8C\u6210\u540E\u901A\u8FC7\u7CFB\u7EDF\u901A\u77E5\u81EA\u52A8\u544A\u77E5\u3002
|
|
50931
|
+
\u9002\u7528\u4E8E\u4EE3\u7801\u5206\u6790\u3001\u6982\u5FF5\u6F84\u6E05\u3001\u6A21\u5F0F\u5EFA\u8BAE\u7B49\u8F7B\u91CF\u67E5\u8BE2\u3002
|
|
50932
|
+
BTW \u987E\u95EE\u65E0\u5199\u6743\u9650\uFF0C\u4E0D\u53EF\u4FEE\u6539\u6587\u4EF6\u6216\u6267\u884C\u547D\u4EE4\u3002
|
|
50933
|
+
`.trim();
|
|
50934
|
+
|
|
50935
|
+
// src/tools/btw/tools.ts
|
|
50936
|
+
function createBtwTool(ctx, backgroundManager) {
|
|
50937
|
+
return tool({
|
|
50938
|
+
description: BTW_TOOL_DESCRIPTION,
|
|
50939
|
+
args: {
|
|
50940
|
+
question: tool.schema.string().describe("\u8981\u8BE2\u95EE BTW \u987E\u95EE\u7684\u95EE\u9898")
|
|
50941
|
+
},
|
|
50942
|
+
async execute(args, toolContext) {
|
|
50943
|
+
const parentSessionID = toolContext.sessionID;
|
|
50944
|
+
const parentSession = await ctx.client.session.get({
|
|
50945
|
+
path: { id: parentSessionID }
|
|
50946
|
+
});
|
|
50947
|
+
const parentDirectory = parentSession?.data?.directory ?? ctx.directory;
|
|
50948
|
+
const btwPrompt = `\u4F60\u662F\u4E00\u4E2A\u8F7B\u91CF\u53EA\u8BFB\u987E\u95EE\uFF08BTW \u987E\u95EE\uFF09\u3002
|
|
50949
|
+
\u8BF7\u6781\u5EA6\u7CBE\u7B80\u5730\u56DE\u7B54\u4EE5\u4E0B\u95EE\u9898\uFF0C\u63A7\u5236\u5728 100 \u5B57\u4EE5\u5185\uFF0C1-3 \u53E5\u8BDD\u3002
|
|
50950
|
+
\u53EA\u8F93\u51FA\u7B54\u6848\uFF0C\u4E0D\u8981\u8F93\u51FA reasoning \u6216\u601D\u8003\u8FC7\u7A0B\u3002
|
|
50951
|
+
|
|
50952
|
+
\u95EE\u9898\uFF1A${args.question}`;
|
|
50953
|
+
const task = await backgroundManager.launch({
|
|
50954
|
+
description: `BTW: ${args.question.substring(0, 50)}`,
|
|
50955
|
+
prompt: btwPrompt,
|
|
50956
|
+
agent: "BTW \u987E\u95EE",
|
|
50957
|
+
parentSessionID,
|
|
50958
|
+
parentMessageID: toolContext.messageID
|
|
50959
|
+
});
|
|
50960
|
+
return `> **BTW**\uFF1A\u6B63\u5728\u67E5\u8BE2\u300C${args.question.substring(0, 30)}${args.question.length > 30 ? "..." : ""}\u300D
|
|
50961
|
+
\u5B8C\u6210\u540E\u5C06\u901A\u8FC7\u7CFB\u7EDF\u901A\u77E5\u81EA\u52A8\u544A\u77E5\u3002\u53EF\u7528 \`background_output("${task.id}")\` \u67E5\u770B\u7ED3\u679C\u3002`;
|
|
50962
|
+
}
|
|
50963
|
+
});
|
|
50964
|
+
}
|
|
50484
50965
|
// src/tools/index.ts
|
|
50485
50966
|
function createBackgroundTools(manager, client2) {
|
|
50486
50967
|
return {
|
|
@@ -50666,8 +51147,8 @@ class PerformanceAggregator {
|
|
|
50666
51147
|
}
|
|
50667
51148
|
|
|
50668
51149
|
// src/features/background-agent/manager.ts
|
|
50669
|
-
import { existsSync as
|
|
50670
|
-
import { join as
|
|
51150
|
+
import { existsSync as existsSync53, readdirSync as readdirSync19 } from "fs";
|
|
51151
|
+
import { join as join65 } from "path";
|
|
50671
51152
|
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
50672
51153
|
var MIN_STABILITY_TIME_MS = 10 * 1000;
|
|
50673
51154
|
var DEFAULT_STALE_TIMEOUT_MS = 120000;
|
|
@@ -51841,14 +52322,14 @@ function registerProcessSignal(signal, handler, exitAfter) {
|
|
|
51841
52322
|
return listener;
|
|
51842
52323
|
}
|
|
51843
52324
|
function getMessageDir9(sessionID) {
|
|
51844
|
-
if (!
|
|
52325
|
+
if (!existsSync53(MESSAGE_STORAGE))
|
|
51845
52326
|
return null;
|
|
51846
|
-
const directPath =
|
|
51847
|
-
if (
|
|
52327
|
+
const directPath = join65(MESSAGE_STORAGE, sessionID);
|
|
52328
|
+
if (existsSync53(directPath))
|
|
51848
52329
|
return directPath;
|
|
51849
|
-
for (const dir of
|
|
51850
|
-
const sessionPath =
|
|
51851
|
-
if (
|
|
52330
|
+
for (const dir of readdirSync19(MESSAGE_STORAGE)) {
|
|
52331
|
+
const sessionPath = join65(MESSAGE_STORAGE, dir, sessionID);
|
|
52332
|
+
if (existsSync53(sessionPath))
|
|
51852
52333
|
return sessionPath;
|
|
51853
52334
|
}
|
|
51854
52335
|
return null;
|
|
@@ -70522,7 +71003,8 @@ var BuiltinAgentNameSchema = exports_external2.enum([
|
|
|
70522
71003
|
"\u5A92\u4F53\u89E3\u6790",
|
|
70523
71004
|
"\u9884\u5BA1\u987E\u95EE",
|
|
70524
71005
|
"\u8BA1\u5212\u5BA1\u67E5",
|
|
70525
|
-
"\u4EFB\u52A1\u7F16\u6392"
|
|
71006
|
+
"\u4EFB\u52A1\u7F16\u6392",
|
|
71007
|
+
"BTW \u987E\u95EE"
|
|
70526
71008
|
]);
|
|
70527
71009
|
var BuiltinSkillNameSchema = exports_external2.enum([
|
|
70528
71010
|
"playwright",
|
|
@@ -70542,7 +71024,8 @@ var OverridableAgentNameSchema = exports_external2.enum([
|
|
|
70542
71024
|
"\u77E5\u8BC6\u5178\u85CF",
|
|
70543
71025
|
"\u6DF1\u5EA6\u63A2\u7D22",
|
|
70544
71026
|
"\u5A92\u4F53\u89E3\u6790",
|
|
70545
|
-
"\u4EFB\u52A1\u7F16\u6392"
|
|
71027
|
+
"\u4EFB\u52A1\u7F16\u6392",
|
|
71028
|
+
"BTW \u987E\u95EE"
|
|
70546
71029
|
]);
|
|
70547
71030
|
var HookNameSchema = exports_external2.enum([
|
|
70548
71031
|
"todo-continuation-enforcer",
|
|
@@ -70583,11 +71066,13 @@ var HookNameSchema = exports_external2.enum([
|
|
|
70583
71066
|
"tool-definition-optimizer",
|
|
70584
71067
|
"permission-ask-bridge",
|
|
70585
71068
|
"shell-env-injector",
|
|
70586
|
-
"dispose-coordinator"
|
|
71069
|
+
"dispose-coordinator",
|
|
71070
|
+
"plan-completion"
|
|
70587
71071
|
]);
|
|
70588
71072
|
var BuiltinCommandNameSchema = exports_external2.enum([
|
|
70589
71073
|
"init-deep",
|
|
70590
|
-
"start-work"
|
|
71074
|
+
"start-work",
|
|
71075
|
+
"btw"
|
|
70591
71076
|
]);
|
|
70592
71077
|
var ProviderModelStringSchema = exports_external2.string().refine((value) => {
|
|
70593
71078
|
const separatorIndex = value.indexOf("/");
|
|
@@ -70636,7 +71121,8 @@ var AgentOverridesSchema = exports_external2.object({
|
|
|
70636
71121
|
"\u77E5\u8BC6\u5178\u85CF": AgentOverrideConfigSchema.optional(),
|
|
70637
71122
|
"\u6DF1\u5EA6\u63A2\u7D22": AgentOverrideConfigSchema.optional(),
|
|
70638
71123
|
"\u5A92\u4F53\u89E3\u6790": AgentOverrideConfigSchema.optional(),
|
|
70639
|
-
"\u4EFB\u52A1\u7F16\u6392": AgentOverrideConfigSchema.optional()
|
|
71124
|
+
"\u4EFB\u52A1\u7F16\u6392": AgentOverrideConfigSchema.optional(),
|
|
71125
|
+
"BTW \u987E\u95EE": AgentOverrideConfigSchema.optional()
|
|
70640
71126
|
});
|
|
70641
71127
|
var ClaudeCodeConfigSchema = exports_external2.object({
|
|
70642
71128
|
mcp: exports_external2.boolean().optional(),
|
|
@@ -71068,7 +71554,7 @@ init_file_utils();
|
|
|
71068
71554
|
init_shared();
|
|
71069
71555
|
init_logger();
|
|
71070
71556
|
import { promises as fs11 } from "fs";
|
|
71071
|
-
import { join as
|
|
71557
|
+
import { join as join67, basename as basename6 } from "path";
|
|
71072
71558
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
71073
71559
|
try {
|
|
71074
71560
|
await fs11.access(commandsDir);
|
|
@@ -71098,7 +71584,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71098
71584
|
if (entry.isDirectory()) {
|
|
71099
71585
|
if (entry.name.startsWith("."))
|
|
71100
71586
|
continue;
|
|
71101
|
-
const subDirPath =
|
|
71587
|
+
const subDirPath = join67(commandsDir, entry.name);
|
|
71102
71588
|
const subPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
71103
71589
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
71104
71590
|
commands2.push(...subCommands);
|
|
@@ -71106,7 +71592,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
71106
71592
|
}
|
|
71107
71593
|
if (!isMarkdownFile(entry))
|
|
71108
71594
|
continue;
|
|
71109
|
-
const commandPath =
|
|
71595
|
+
const commandPath = join67(commandsDir, entry.name);
|
|
71110
71596
|
const baseCommandName = basename6(entry.name, ".md");
|
|
71111
71597
|
const commandName = prefix ? `${prefix}:${baseCommandName}` : baseCommandName;
|
|
71112
71598
|
try {
|
|
@@ -71153,23 +71639,23 @@ function commandsToRecord(commands2) {
|
|
|
71153
71639
|
return result;
|
|
71154
71640
|
}
|
|
71155
71641
|
async function loadUserCommands() {
|
|
71156
|
-
const userCommandsDir =
|
|
71642
|
+
const userCommandsDir = join67(getClaudeConfigDir(), "commands");
|
|
71157
71643
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
71158
71644
|
return commandsToRecord(commands2);
|
|
71159
71645
|
}
|
|
71160
71646
|
async function loadProjectCommands() {
|
|
71161
|
-
const projectCommandsDir =
|
|
71647
|
+
const projectCommandsDir = join67(process.cwd(), ".claude", "commands");
|
|
71162
71648
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
71163
71649
|
return commandsToRecord(commands2);
|
|
71164
71650
|
}
|
|
71165
71651
|
async function loadOpencodeGlobalCommands() {
|
|
71166
71652
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
71167
|
-
const opencodeCommandsDir =
|
|
71653
|
+
const opencodeCommandsDir = join67(configDir, "command");
|
|
71168
71654
|
const commands2 = await loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
71169
71655
|
return commandsToRecord(commands2);
|
|
71170
71656
|
}
|
|
71171
71657
|
async function loadOpencodeProjectCommands() {
|
|
71172
|
-
const opencodeProjectDir =
|
|
71658
|
+
const opencodeProjectDir = join67(process.cwd(), ".opencode", "command");
|
|
71173
71659
|
const commands2 = await loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
71174
71660
|
return commandsToRecord(commands2);
|
|
71175
71661
|
}
|
|
@@ -71177,8 +71663,8 @@ async function loadOpencodeProjectCommands() {
|
|
|
71177
71663
|
init_frontmatter();
|
|
71178
71664
|
init_file_utils();
|
|
71179
71665
|
init_shared();
|
|
71180
|
-
import { existsSync as
|
|
71181
|
-
import { join as
|
|
71666
|
+
import { existsSync as existsSync55, readdirSync as readdirSync20, readFileSync as readFileSync38 } from "fs";
|
|
71667
|
+
import { join as join68, basename as basename7 } from "path";
|
|
71182
71668
|
function parseToolsConfig(toolsStr) {
|
|
71183
71669
|
if (!toolsStr)
|
|
71184
71670
|
return;
|
|
@@ -71192,18 +71678,18 @@ function parseToolsConfig(toolsStr) {
|
|
|
71192
71678
|
return result;
|
|
71193
71679
|
}
|
|
71194
71680
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
71195
|
-
if (!
|
|
71681
|
+
if (!existsSync55(agentsDir)) {
|
|
71196
71682
|
return [];
|
|
71197
71683
|
}
|
|
71198
|
-
const entries =
|
|
71684
|
+
const entries = readdirSync20(agentsDir, { withFileTypes: true });
|
|
71199
71685
|
const agents = [];
|
|
71200
71686
|
for (const entry of entries) {
|
|
71201
71687
|
if (!isMarkdownFile(entry))
|
|
71202
71688
|
continue;
|
|
71203
|
-
const agentPath =
|
|
71689
|
+
const agentPath = join68(agentsDir, entry.name);
|
|
71204
71690
|
const agentName = basename7(entry.name, ".md");
|
|
71205
71691
|
try {
|
|
71206
|
-
const content =
|
|
71692
|
+
const content = readFileSync38(agentPath, "utf-8");
|
|
71207
71693
|
const { data, body } = parseFrontmatter(content);
|
|
71208
71694
|
const name = data.name || agentName;
|
|
71209
71695
|
const originalDescription = data.description || "";
|
|
@@ -71232,7 +71718,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
71232
71718
|
return agents;
|
|
71233
71719
|
}
|
|
71234
71720
|
function loadUserAgents() {
|
|
71235
|
-
const userAgentsDir =
|
|
71721
|
+
const userAgentsDir = join68(getClaudeConfigDir(), "agents");
|
|
71236
71722
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
71237
71723
|
const result = {};
|
|
71238
71724
|
for (const agent of agents) {
|
|
@@ -71241,7 +71727,7 @@ function loadUserAgents() {
|
|
|
71241
71727
|
return result;
|
|
71242
71728
|
}
|
|
71243
71729
|
function loadProjectAgents() {
|
|
71244
|
-
const projectAgentsDir =
|
|
71730
|
+
const projectAgentsDir = join68(process.cwd(), ".claude", "agents");
|
|
71245
71731
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
71246
71732
|
const result = {};
|
|
71247
71733
|
for (const agent of agents) {
|
|
@@ -71253,18 +71739,18 @@ function loadProjectAgents() {
|
|
|
71253
71739
|
init_frontmatter();
|
|
71254
71740
|
init_file_utils();
|
|
71255
71741
|
init_logger();
|
|
71256
|
-
import { existsSync as
|
|
71742
|
+
import { existsSync as existsSync56, readdirSync as readdirSync21, readFileSync as readFileSync39 } from "fs";
|
|
71257
71743
|
import { homedir as homedir14 } from "os";
|
|
71258
|
-
import { join as
|
|
71744
|
+
import { join as join69, basename as basename8 } from "path";
|
|
71259
71745
|
var CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}";
|
|
71260
71746
|
function getPluginsBaseDir() {
|
|
71261
71747
|
if (process.env.CLAUDE_PLUGINS_HOME) {
|
|
71262
71748
|
return process.env.CLAUDE_PLUGINS_HOME;
|
|
71263
71749
|
}
|
|
71264
|
-
return
|
|
71750
|
+
return join69(homedir14(), ".claude", "plugins");
|
|
71265
71751
|
}
|
|
71266
71752
|
function getInstalledPluginsPath() {
|
|
71267
|
-
return
|
|
71753
|
+
return join69(getPluginsBaseDir(), "installed_plugins.json");
|
|
71268
71754
|
}
|
|
71269
71755
|
function resolvePluginPath(path8, pluginRoot) {
|
|
71270
71756
|
return path8.replace(CLAUDE_PLUGIN_ROOT_VAR, pluginRoot);
|
|
@@ -71289,11 +71775,11 @@ function resolvePluginPaths(obj, pluginRoot) {
|
|
|
71289
71775
|
}
|
|
71290
71776
|
function loadInstalledPlugins() {
|
|
71291
71777
|
const dbPath = getInstalledPluginsPath();
|
|
71292
|
-
if (!
|
|
71778
|
+
if (!existsSync56(dbPath)) {
|
|
71293
71779
|
return null;
|
|
71294
71780
|
}
|
|
71295
71781
|
try {
|
|
71296
|
-
const content =
|
|
71782
|
+
const content = readFileSync39(dbPath, "utf-8");
|
|
71297
71783
|
return JSON.parse(content);
|
|
71298
71784
|
} catch (error95) {
|
|
71299
71785
|
log("Failed to load installed plugins database", error95);
|
|
@@ -71304,15 +71790,15 @@ function getClaudeSettingsPath() {
|
|
|
71304
71790
|
if (process.env.CLAUDE_SETTINGS_PATH) {
|
|
71305
71791
|
return process.env.CLAUDE_SETTINGS_PATH;
|
|
71306
71792
|
}
|
|
71307
|
-
return
|
|
71793
|
+
return join69(homedir14(), ".claude", "settings.json");
|
|
71308
71794
|
}
|
|
71309
71795
|
function loadClaudeSettings() {
|
|
71310
71796
|
const settingsPath = getClaudeSettingsPath();
|
|
71311
|
-
if (!
|
|
71797
|
+
if (!existsSync56(settingsPath)) {
|
|
71312
71798
|
return null;
|
|
71313
71799
|
}
|
|
71314
71800
|
try {
|
|
71315
|
-
const content =
|
|
71801
|
+
const content = readFileSync39(settingsPath, "utf-8");
|
|
71316
71802
|
return JSON.parse(content);
|
|
71317
71803
|
} catch (error95) {
|
|
71318
71804
|
log("Failed to load Claude settings", error95);
|
|
@@ -71320,12 +71806,12 @@ function loadClaudeSettings() {
|
|
|
71320
71806
|
}
|
|
71321
71807
|
}
|
|
71322
71808
|
function loadPluginManifest(installPath) {
|
|
71323
|
-
const manifestPath =
|
|
71324
|
-
if (!
|
|
71809
|
+
const manifestPath = join69(installPath, ".claude-plugin", "plugin.json");
|
|
71810
|
+
if (!existsSync56(manifestPath)) {
|
|
71325
71811
|
return null;
|
|
71326
71812
|
}
|
|
71327
71813
|
try {
|
|
71328
|
-
const content =
|
|
71814
|
+
const content = readFileSync39(manifestPath, "utf-8");
|
|
71329
71815
|
return JSON.parse(content);
|
|
71330
71816
|
} catch (error95) {
|
|
71331
71817
|
log(`Failed to load plugin manifest from ${manifestPath}`, error95);
|
|
@@ -71372,7 +71858,7 @@ function discoverInstalledPlugins(options) {
|
|
|
71372
71858
|
continue;
|
|
71373
71859
|
}
|
|
71374
71860
|
const { installPath, scope, version: version3 } = installation;
|
|
71375
|
-
if (!
|
|
71861
|
+
if (!existsSync56(installPath)) {
|
|
71376
71862
|
errors5.push({
|
|
71377
71863
|
pluginKey,
|
|
71378
71864
|
installPath,
|
|
@@ -71390,21 +71876,21 @@ function discoverInstalledPlugins(options) {
|
|
|
71390
71876
|
pluginKey,
|
|
71391
71877
|
manifest: manifest ?? undefined
|
|
71392
71878
|
};
|
|
71393
|
-
if (
|
|
71394
|
-
loadedPlugin.commandsDir =
|
|
71879
|
+
if (existsSync56(join69(installPath, "commands"))) {
|
|
71880
|
+
loadedPlugin.commandsDir = join69(installPath, "commands");
|
|
71395
71881
|
}
|
|
71396
|
-
if (
|
|
71397
|
-
loadedPlugin.agentsDir =
|
|
71882
|
+
if (existsSync56(join69(installPath, "agents"))) {
|
|
71883
|
+
loadedPlugin.agentsDir = join69(installPath, "agents");
|
|
71398
71884
|
}
|
|
71399
|
-
if (
|
|
71400
|
-
loadedPlugin.skillsDir =
|
|
71885
|
+
if (existsSync56(join69(installPath, "skills"))) {
|
|
71886
|
+
loadedPlugin.skillsDir = join69(installPath, "skills");
|
|
71401
71887
|
}
|
|
71402
|
-
const hooksPath =
|
|
71403
|
-
if (
|
|
71888
|
+
const hooksPath = join69(installPath, "hooks", "hooks.json");
|
|
71889
|
+
if (existsSync56(hooksPath)) {
|
|
71404
71890
|
loadedPlugin.hooksPath = hooksPath;
|
|
71405
71891
|
}
|
|
71406
|
-
const mcpPath =
|
|
71407
|
-
if (
|
|
71892
|
+
const mcpPath = join69(installPath, ".mcp.json");
|
|
71893
|
+
if (existsSync56(mcpPath)) {
|
|
71408
71894
|
loadedPlugin.mcpPath = mcpPath;
|
|
71409
71895
|
}
|
|
71410
71896
|
plugins.push(loadedPlugin);
|
|
@@ -71415,17 +71901,17 @@ function discoverInstalledPlugins(options) {
|
|
|
71415
71901
|
function loadPluginCommands(plugins) {
|
|
71416
71902
|
const commands2 = {};
|
|
71417
71903
|
for (const plugin of plugins) {
|
|
71418
|
-
if (!plugin.commandsDir || !
|
|
71904
|
+
if (!plugin.commandsDir || !existsSync56(plugin.commandsDir))
|
|
71419
71905
|
continue;
|
|
71420
|
-
const entries =
|
|
71906
|
+
const entries = readdirSync21(plugin.commandsDir, { withFileTypes: true });
|
|
71421
71907
|
for (const entry of entries) {
|
|
71422
71908
|
if (!isMarkdownFile(entry))
|
|
71423
71909
|
continue;
|
|
71424
|
-
const commandPath =
|
|
71910
|
+
const commandPath = join69(plugin.commandsDir, entry.name);
|
|
71425
71911
|
const commandName = basename8(entry.name, ".md");
|
|
71426
71912
|
const namespacedName = `${plugin.name}:${commandName}`;
|
|
71427
71913
|
try {
|
|
71428
|
-
const content =
|
|
71914
|
+
const content = readFileSync39(commandPath, "utf-8");
|
|
71429
71915
|
const { data, body } = parseFrontmatter(content);
|
|
71430
71916
|
const wrappedTemplate = `<command-instruction>
|
|
71431
71917
|
${body.trim()}
|
|
@@ -71457,21 +71943,21 @@ $ARGUMENTS
|
|
|
71457
71943
|
function loadPluginSkillsAsCommands(plugins) {
|
|
71458
71944
|
const skills = {};
|
|
71459
71945
|
for (const plugin of plugins) {
|
|
71460
|
-
if (!plugin.skillsDir || !
|
|
71946
|
+
if (!plugin.skillsDir || !existsSync56(plugin.skillsDir))
|
|
71461
71947
|
continue;
|
|
71462
|
-
const entries =
|
|
71948
|
+
const entries = readdirSync21(plugin.skillsDir, { withFileTypes: true });
|
|
71463
71949
|
for (const entry of entries) {
|
|
71464
71950
|
if (entry.name.startsWith("."))
|
|
71465
71951
|
continue;
|
|
71466
|
-
const skillPath =
|
|
71952
|
+
const skillPath = join69(plugin.skillsDir, entry.name);
|
|
71467
71953
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
71468
71954
|
continue;
|
|
71469
71955
|
const resolvedPath = resolveSymlink(skillPath);
|
|
71470
|
-
const skillMdPath =
|
|
71471
|
-
if (!
|
|
71956
|
+
const skillMdPath = join69(resolvedPath, "SKILL.md");
|
|
71957
|
+
if (!existsSync56(skillMdPath))
|
|
71472
71958
|
continue;
|
|
71473
71959
|
try {
|
|
71474
|
-
const content =
|
|
71960
|
+
const content = readFileSync39(skillMdPath, "utf-8");
|
|
71475
71961
|
const { data, body } = parseFrontmatter(content);
|
|
71476
71962
|
const skillName = data.name || entry.name;
|
|
71477
71963
|
const namespacedName = `${plugin.name}:${skillName}`;
|
|
@@ -71518,17 +72004,17 @@ function parseToolsConfig2(toolsStr) {
|
|
|
71518
72004
|
function loadPluginAgents(plugins) {
|
|
71519
72005
|
const agents = {};
|
|
71520
72006
|
for (const plugin of plugins) {
|
|
71521
|
-
if (!plugin.agentsDir || !
|
|
72007
|
+
if (!plugin.agentsDir || !existsSync56(plugin.agentsDir))
|
|
71522
72008
|
continue;
|
|
71523
|
-
const entries =
|
|
72009
|
+
const entries = readdirSync21(plugin.agentsDir, { withFileTypes: true });
|
|
71524
72010
|
for (const entry of entries) {
|
|
71525
72011
|
if (!isMarkdownFile(entry))
|
|
71526
72012
|
continue;
|
|
71527
|
-
const agentPath =
|
|
72013
|
+
const agentPath = join69(plugin.agentsDir, entry.name);
|
|
71528
72014
|
const agentName = basename8(entry.name, ".md");
|
|
71529
72015
|
const namespacedName = `${plugin.name}:${agentName}`;
|
|
71530
72016
|
try {
|
|
71531
|
-
const content =
|
|
72017
|
+
const content = readFileSync39(agentPath, "utf-8");
|
|
71532
72018
|
const { data, body } = parseFrontmatter(content);
|
|
71533
72019
|
const name = data.name || agentName;
|
|
71534
72020
|
const originalDescription = data.description || "";
|
|
@@ -71554,7 +72040,7 @@ function loadPluginAgents(plugins) {
|
|
|
71554
72040
|
async function loadPluginMcpServers(plugins) {
|
|
71555
72041
|
const servers = {};
|
|
71556
72042
|
for (const plugin of plugins) {
|
|
71557
|
-
if (!plugin.mcpPath || !
|
|
72043
|
+
if (!plugin.mcpPath || !existsSync56(plugin.mcpPath))
|
|
71558
72044
|
continue;
|
|
71559
72045
|
try {
|
|
71560
72046
|
const content = await Bun.file(plugin.mcpPath).text();
|
|
@@ -71586,10 +72072,10 @@ async function loadPluginMcpServers(plugins) {
|
|
|
71586
72072
|
function loadPluginHooksConfigs(plugins) {
|
|
71587
72073
|
const configs = [];
|
|
71588
72074
|
for (const plugin of plugins) {
|
|
71589
|
-
if (!plugin.hooksPath || !
|
|
72075
|
+
if (!plugin.hooksPath || !existsSync56(plugin.hooksPath))
|
|
71590
72076
|
continue;
|
|
71591
72077
|
try {
|
|
71592
|
-
const content =
|
|
72078
|
+
const content = readFileSync39(plugin.hooksPath, "utf-8");
|
|
71593
72079
|
let config4 = JSON.parse(content);
|
|
71594
72080
|
config4 = resolvePluginPaths(config4, plugin.installPath);
|
|
71595
72081
|
configs.push(config4);
|
|
@@ -73336,6 +73822,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
73336
73822
|
const toolDefOptimizer = isHookEnabled("tool-definition-optimizer") ? createToolDefinitionOptimizerHook(ctx) : null;
|
|
73337
73823
|
const permissionAskBridge = isHookEnabled("permission-ask-bridge") ? createPermissionAskBridgeHook(ctx) : null;
|
|
73338
73824
|
const shellEnvInjector = isHookEnabled("shell-env-injector") ? createShellEnvInjectorHook(ctx) : null;
|
|
73825
|
+
const planCompletionHook = isHookEnabled("plan-completion") ? createPlanCompletionHook(ctx) : null;
|
|
73339
73826
|
initTaskToastManager(ctx.client);
|
|
73340
73827
|
const todoContinuationEnforcer = isHookEnabled("todo-continuation-enforcer") ? createTodoContinuationEnforcer(ctx, { backgroundManager, ralphLoopHook: ralphLoop ?? undefined }) : null;
|
|
73341
73828
|
if (sessionRecovery && todoContinuationEnforcer) {
|
|
@@ -73345,6 +73832,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
73345
73832
|
const backgroundNotificationHook = isHookEnabled("background-notification") ? createBackgroundNotificationHook(backgroundManager) : null;
|
|
73346
73833
|
const backgroundTools = createBackgroundTools(backgroundManager, ctx.client);
|
|
73347
73834
|
const callOmoAgent = createCallOmoAgent(ctx, backgroundManager);
|
|
73835
|
+
const btwTool = createBtwTool(ctx, backgroundManager);
|
|
73348
73836
|
const isMultimodalLookerEnabled = !includesCaseInsensitive(pluginConfig.disabled_agents ?? [], "multimodal-looker");
|
|
73349
73837
|
const lookAt = isMultimodalLookerEnabled ? createLookAt(ctx) : null;
|
|
73350
73838
|
const delegateTask = createDelegateTask({
|
|
@@ -73430,6 +73918,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
73430
73918
|
call_omo_agent: callOmoAgent,
|
|
73431
73919
|
...lookAt ? { look_at: lookAt } : {},
|
|
73432
73920
|
delegate_task: delegateTask,
|
|
73921
|
+
btw: btwTool,
|
|
73433
73922
|
skill: skillTool,
|
|
73434
73923
|
skill_mcp: skillMcpTool,
|
|
73435
73924
|
slashcommand: slashcommandTool,
|