oh-my-opencode 2.4.3 → 2.4.5
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/README.ja.md +4 -3
- package/README.ko.md +4 -3
- package/README.md +4 -3
- package/README.zh-cn.md +4 -3
- package/dist/config/schema.d.ts +2 -0
- package/dist/hooks/tool-output-truncator.d.ts +6 -1
- package/dist/index.js +213 -417
- package/dist/tools/index.d.ts +0 -9
- package/package.json +1 -1
- package/dist/tools/skill/index.d.ts +0 -2
- package/dist/tools/skill/tools.d.ts +0 -10
- package/dist/tools/skill/types.d.ts +0 -41
package/dist/index.js
CHANGED
|
@@ -3622,6 +3622,7 @@ function createTodoContinuationEnforcer(ctx) {
|
|
|
3622
3622
|
pendingCountdowns.delete(sessionID);
|
|
3623
3623
|
log(`[${HOOK_NAME}] Cancelled countdown on user message`, { sessionID });
|
|
3624
3624
|
}
|
|
3625
|
+
remindedSessions.delete(sessionID);
|
|
3625
3626
|
}
|
|
3626
3627
|
if (sessionID && role === "assistant" && finish) {
|
|
3627
3628
|
remindedSessions.delete(sessionID);
|
|
@@ -4847,10 +4848,11 @@ var TRUNCATABLE_TOOLS = [
|
|
|
4847
4848
|
"interactive_bash",
|
|
4848
4849
|
"Interactive_bash"
|
|
4849
4850
|
];
|
|
4850
|
-
function createToolOutputTruncatorHook(ctx) {
|
|
4851
|
+
function createToolOutputTruncatorHook(ctx, options) {
|
|
4851
4852
|
const truncator = createDynamicTruncator(ctx);
|
|
4853
|
+
const truncateAll = options?.experimental?.truncate_all_tool_outputs ?? false;
|
|
4852
4854
|
const toolExecuteAfter = async (input, output) => {
|
|
4853
|
-
if (!TRUNCATABLE_TOOLS.includes(input.tool))
|
|
4855
|
+
if (!truncateAll && !TRUNCATABLE_TOOLS.includes(input.tool))
|
|
4854
4856
|
return;
|
|
4855
4857
|
try {
|
|
4856
4858
|
const { result, truncated } = await truncator.truncate(input.sessionID, output.output);
|
|
@@ -6059,6 +6061,10 @@ function createAnthropicAutoCompactHook(ctx, options) {
|
|
|
6059
6061
|
event: eventHandler
|
|
6060
6062
|
};
|
|
6061
6063
|
}
|
|
6064
|
+
// src/hooks/preemptive-compaction/index.ts
|
|
6065
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5 } from "fs";
|
|
6066
|
+
import { join as join19 } from "path";
|
|
6067
|
+
|
|
6062
6068
|
// src/hooks/preemptive-compaction/constants.ts
|
|
6063
6069
|
var DEFAULT_THRESHOLD = 0.85;
|
|
6064
6070
|
var MIN_TOKENS_FOR_COMPACTION = 50000;
|
|
@@ -6070,6 +6076,19 @@ var CLAUDE_DEFAULT_CONTEXT_LIMIT = 200000;
|
|
|
6070
6076
|
function isSupportedModel(modelID) {
|
|
6071
6077
|
return CLAUDE_MODEL_PATTERN.test(modelID);
|
|
6072
6078
|
}
|
|
6079
|
+
function getMessageDir4(sessionID) {
|
|
6080
|
+
if (!existsSync15(MESSAGE_STORAGE))
|
|
6081
|
+
return null;
|
|
6082
|
+
const directPath = join19(MESSAGE_STORAGE, sessionID);
|
|
6083
|
+
if (existsSync15(directPath))
|
|
6084
|
+
return directPath;
|
|
6085
|
+
for (const dir of readdirSync5(MESSAGE_STORAGE)) {
|
|
6086
|
+
const sessionPath = join19(MESSAGE_STORAGE, dir, sessionID);
|
|
6087
|
+
if (existsSync15(sessionPath))
|
|
6088
|
+
return sessionPath;
|
|
6089
|
+
}
|
|
6090
|
+
return null;
|
|
6091
|
+
}
|
|
6073
6092
|
function createState() {
|
|
6074
6093
|
return {
|
|
6075
6094
|
lastCompactionTime: new Map,
|
|
@@ -6209,6 +6228,19 @@ function createPreemptiveCompactionHook(ctx, options) {
|
|
|
6209
6228
|
if (assistants.length === 0)
|
|
6210
6229
|
return;
|
|
6211
6230
|
const lastAssistant = assistants[assistants.length - 1];
|
|
6231
|
+
if (!lastAssistant.providerID || !lastAssistant.modelID) {
|
|
6232
|
+
const messageDir = getMessageDir4(sessionID);
|
|
6233
|
+
const storedMessage = messageDir ? findNearestMessageWithFields(messageDir) : null;
|
|
6234
|
+
if (storedMessage?.model?.providerID && storedMessage?.model?.modelID) {
|
|
6235
|
+
lastAssistant.providerID = storedMessage.model.providerID;
|
|
6236
|
+
lastAssistant.modelID = storedMessage.model.modelID;
|
|
6237
|
+
log("[preemptive-compaction] using stored message model info", {
|
|
6238
|
+
sessionID,
|
|
6239
|
+
providerID: lastAssistant.providerID,
|
|
6240
|
+
modelID: lastAssistant.modelID
|
|
6241
|
+
});
|
|
6242
|
+
}
|
|
6243
|
+
}
|
|
6212
6244
|
await checkAndTriggerCompaction(sessionID, lastAssistant);
|
|
6213
6245
|
} catch {}
|
|
6214
6246
|
}
|
|
@@ -6532,8 +6564,8 @@ function createThinkModeHook() {
|
|
|
6532
6564
|
}
|
|
6533
6565
|
// src/hooks/claude-code-hooks/config.ts
|
|
6534
6566
|
import { homedir as homedir6 } from "os";
|
|
6535
|
-
import { join as
|
|
6536
|
-
import { existsSync as
|
|
6567
|
+
import { join as join20 } from "path";
|
|
6568
|
+
import { existsSync as existsSync16 } from "fs";
|
|
6537
6569
|
function normalizeHookMatcher(raw) {
|
|
6538
6570
|
return {
|
|
6539
6571
|
matcher: raw.matcher ?? raw.pattern ?? "*",
|
|
@@ -6558,11 +6590,11 @@ function normalizeHooksConfig(raw) {
|
|
|
6558
6590
|
function getClaudeSettingsPaths(customPath) {
|
|
6559
6591
|
const home = homedir6();
|
|
6560
6592
|
const paths = [
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6593
|
+
join20(home, ".claude", "settings.json"),
|
|
6594
|
+
join20(process.cwd(), ".claude", "settings.json"),
|
|
6595
|
+
join20(process.cwd(), ".claude", "settings.local.json")
|
|
6564
6596
|
];
|
|
6565
|
-
if (customPath &&
|
|
6597
|
+
if (customPath && existsSync16(customPath)) {
|
|
6566
6598
|
paths.unshift(customPath);
|
|
6567
6599
|
}
|
|
6568
6600
|
return paths;
|
|
@@ -6586,7 +6618,7 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
6586
6618
|
const paths = getClaudeSettingsPaths(customSettingsPath);
|
|
6587
6619
|
let mergedConfig = {};
|
|
6588
6620
|
for (const settingsPath of paths) {
|
|
6589
|
-
if (
|
|
6621
|
+
if (existsSync16(settingsPath)) {
|
|
6590
6622
|
try {
|
|
6591
6623
|
const content = await Bun.file(settingsPath).text();
|
|
6592
6624
|
const settings = JSON.parse(content);
|
|
@@ -6603,15 +6635,15 @@ async function loadClaudeHooksConfig(customSettingsPath) {
|
|
|
6603
6635
|
}
|
|
6604
6636
|
|
|
6605
6637
|
// src/hooks/claude-code-hooks/config-loader.ts
|
|
6606
|
-
import { existsSync as
|
|
6638
|
+
import { existsSync as existsSync17 } from "fs";
|
|
6607
6639
|
import { homedir as homedir7 } from "os";
|
|
6608
|
-
import { join as
|
|
6609
|
-
var USER_CONFIG_PATH =
|
|
6640
|
+
import { join as join21 } from "path";
|
|
6641
|
+
var USER_CONFIG_PATH = join21(homedir7(), ".config", "opencode", "opencode-cc-plugin.json");
|
|
6610
6642
|
function getProjectConfigPath() {
|
|
6611
|
-
return
|
|
6643
|
+
return join21(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
6612
6644
|
}
|
|
6613
6645
|
async function loadConfigFromPath(path4) {
|
|
6614
|
-
if (!
|
|
6646
|
+
if (!existsSync17(path4)) {
|
|
6615
6647
|
return null;
|
|
6616
6648
|
}
|
|
6617
6649
|
try {
|
|
@@ -6790,16 +6822,16 @@ async function executePreToolUseHooks(ctx, config, extendedConfig) {
|
|
|
6790
6822
|
}
|
|
6791
6823
|
|
|
6792
6824
|
// src/hooks/claude-code-hooks/transcript.ts
|
|
6793
|
-
import { join as
|
|
6794
|
-
import { mkdirSync as mkdirSync6, appendFileSync as appendFileSync5, existsSync as
|
|
6825
|
+
import { join as join22 } from "path";
|
|
6826
|
+
import { mkdirSync as mkdirSync6, appendFileSync as appendFileSync5, existsSync as existsSync18, writeFileSync as writeFileSync6, unlinkSync as unlinkSync5 } from "fs";
|
|
6795
6827
|
import { homedir as homedir8, tmpdir as tmpdir5 } from "os";
|
|
6796
6828
|
import { randomUUID } from "crypto";
|
|
6797
|
-
var TRANSCRIPT_DIR =
|
|
6829
|
+
var TRANSCRIPT_DIR = join22(homedir8(), ".claude", "transcripts");
|
|
6798
6830
|
function getTranscriptPath(sessionId) {
|
|
6799
|
-
return
|
|
6831
|
+
return join22(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
|
|
6800
6832
|
}
|
|
6801
6833
|
function ensureTranscriptDir() {
|
|
6802
|
-
if (!
|
|
6834
|
+
if (!existsSync18(TRANSCRIPT_DIR)) {
|
|
6803
6835
|
mkdirSync6(TRANSCRIPT_DIR, { recursive: true });
|
|
6804
6836
|
}
|
|
6805
6837
|
}
|
|
@@ -6886,7 +6918,7 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
6886
6918
|
}
|
|
6887
6919
|
};
|
|
6888
6920
|
entries.push(JSON.stringify(currentEntry));
|
|
6889
|
-
const tempPath =
|
|
6921
|
+
const tempPath = join22(tmpdir5(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
6890
6922
|
writeFileSync6(tempPath, entries.join(`
|
|
6891
6923
|
`) + `
|
|
6892
6924
|
`);
|
|
@@ -6906,7 +6938,7 @@ async function buildTranscriptFromSession(client, sessionId, directory, currentT
|
|
|
6906
6938
|
]
|
|
6907
6939
|
}
|
|
6908
6940
|
};
|
|
6909
|
-
const tempPath =
|
|
6941
|
+
const tempPath = join22(tmpdir5(), `opencode-transcript-${sessionId}-${randomUUID()}.jsonl`);
|
|
6910
6942
|
writeFileSync6(tempPath, JSON.stringify(currentEntry) + `
|
|
6911
6943
|
`);
|
|
6912
6944
|
return tempPath;
|
|
@@ -7118,11 +7150,11 @@ ${USER_PROMPT_SUBMIT_TAG_CLOSE}`);
|
|
|
7118
7150
|
}
|
|
7119
7151
|
|
|
7120
7152
|
// src/hooks/claude-code-hooks/todo.ts
|
|
7121
|
-
import { join as
|
|
7153
|
+
import { join as join23 } from "path";
|
|
7122
7154
|
import { homedir as homedir9 } from "os";
|
|
7123
|
-
var TODO_DIR =
|
|
7155
|
+
var TODO_DIR = join23(homedir9(), ".claude", "todos");
|
|
7124
7156
|
function getTodoPath(sessionId) {
|
|
7125
|
-
return
|
|
7157
|
+
return join23(TODO_DIR, `${sessionId}-agent-${sessionId}.json`);
|
|
7126
7158
|
}
|
|
7127
7159
|
|
|
7128
7160
|
// src/hooks/claude-code-hooks/stop.ts
|
|
@@ -7460,17 +7492,17 @@ import { relative as relative3, resolve as resolve4 } from "path";
|
|
|
7460
7492
|
|
|
7461
7493
|
// src/hooks/rules-injector/finder.ts
|
|
7462
7494
|
import {
|
|
7463
|
-
existsSync as
|
|
7464
|
-
readdirSync as
|
|
7495
|
+
existsSync as existsSync19,
|
|
7496
|
+
readdirSync as readdirSync6,
|
|
7465
7497
|
realpathSync,
|
|
7466
7498
|
statSync as statSync2
|
|
7467
7499
|
} from "fs";
|
|
7468
|
-
import { dirname as dirname4, join as
|
|
7500
|
+
import { dirname as dirname4, join as join25, relative } from "path";
|
|
7469
7501
|
|
|
7470
7502
|
// src/hooks/rules-injector/constants.ts
|
|
7471
|
-
import { join as
|
|
7472
|
-
var OPENCODE_STORAGE6 =
|
|
7473
|
-
var RULES_INJECTOR_STORAGE =
|
|
7503
|
+
import { join as join24 } from "path";
|
|
7504
|
+
var OPENCODE_STORAGE6 = join24(xdgData2 ?? "", "opencode", "storage");
|
|
7505
|
+
var RULES_INJECTOR_STORAGE = join24(OPENCODE_STORAGE6, "rules-injector");
|
|
7474
7506
|
var PROJECT_MARKERS = [
|
|
7475
7507
|
".git",
|
|
7476
7508
|
"pyproject.toml",
|
|
@@ -7497,8 +7529,8 @@ function findProjectRoot(startPath) {
|
|
|
7497
7529
|
}
|
|
7498
7530
|
while (true) {
|
|
7499
7531
|
for (const marker of PROJECT_MARKERS) {
|
|
7500
|
-
const markerPath =
|
|
7501
|
-
if (
|
|
7532
|
+
const markerPath = join25(current, marker);
|
|
7533
|
+
if (existsSync19(markerPath)) {
|
|
7502
7534
|
return current;
|
|
7503
7535
|
}
|
|
7504
7536
|
}
|
|
@@ -7510,12 +7542,12 @@ function findProjectRoot(startPath) {
|
|
|
7510
7542
|
}
|
|
7511
7543
|
}
|
|
7512
7544
|
function findRuleFilesRecursive(dir, results) {
|
|
7513
|
-
if (!
|
|
7545
|
+
if (!existsSync19(dir))
|
|
7514
7546
|
return;
|
|
7515
7547
|
try {
|
|
7516
|
-
const entries =
|
|
7548
|
+
const entries = readdirSync6(dir, { withFileTypes: true });
|
|
7517
7549
|
for (const entry of entries) {
|
|
7518
|
-
const fullPath =
|
|
7550
|
+
const fullPath = join25(dir, entry.name);
|
|
7519
7551
|
if (entry.isDirectory()) {
|
|
7520
7552
|
findRuleFilesRecursive(fullPath, results);
|
|
7521
7553
|
} else if (entry.isFile()) {
|
|
@@ -7541,7 +7573,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
7541
7573
|
let distance = 0;
|
|
7542
7574
|
while (true) {
|
|
7543
7575
|
for (const [parent, subdir] of PROJECT_RULE_SUBDIRS) {
|
|
7544
|
-
const ruleDir =
|
|
7576
|
+
const ruleDir = join25(currentDir, parent, subdir);
|
|
7545
7577
|
const files = [];
|
|
7546
7578
|
findRuleFilesRecursive(ruleDir, files);
|
|
7547
7579
|
for (const filePath of files) {
|
|
@@ -7565,7 +7597,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile) {
|
|
|
7565
7597
|
currentDir = parentDir;
|
|
7566
7598
|
distance++;
|
|
7567
7599
|
}
|
|
7568
|
-
const userRuleDir =
|
|
7600
|
+
const userRuleDir = join25(homeDir, USER_RULE_DIR);
|
|
7569
7601
|
const userFiles = [];
|
|
7570
7602
|
findRuleFilesRecursive(userRuleDir, userFiles);
|
|
7571
7603
|
for (const filePath of userFiles) {
|
|
@@ -7754,19 +7786,19 @@ function mergeGlobs(existing, newValue) {
|
|
|
7754
7786
|
|
|
7755
7787
|
// src/hooks/rules-injector/storage.ts
|
|
7756
7788
|
import {
|
|
7757
|
-
existsSync as
|
|
7789
|
+
existsSync as existsSync20,
|
|
7758
7790
|
mkdirSync as mkdirSync7,
|
|
7759
7791
|
readFileSync as readFileSync9,
|
|
7760
7792
|
writeFileSync as writeFileSync7,
|
|
7761
7793
|
unlinkSync as unlinkSync6
|
|
7762
7794
|
} from "fs";
|
|
7763
|
-
import { join as
|
|
7795
|
+
import { join as join26 } from "path";
|
|
7764
7796
|
function getStoragePath3(sessionID) {
|
|
7765
|
-
return
|
|
7797
|
+
return join26(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
|
7766
7798
|
}
|
|
7767
7799
|
function loadInjectedRules(sessionID) {
|
|
7768
7800
|
const filePath = getStoragePath3(sessionID);
|
|
7769
|
-
if (!
|
|
7801
|
+
if (!existsSync20(filePath))
|
|
7770
7802
|
return { contentHashes: new Set, realPaths: new Set };
|
|
7771
7803
|
try {
|
|
7772
7804
|
const content = readFileSync9(filePath, "utf-8");
|
|
@@ -7780,7 +7812,7 @@ function loadInjectedRules(sessionID) {
|
|
|
7780
7812
|
}
|
|
7781
7813
|
}
|
|
7782
7814
|
function saveInjectedRules(sessionID, data) {
|
|
7783
|
-
if (!
|
|
7815
|
+
if (!existsSync20(RULES_INJECTOR_STORAGE)) {
|
|
7784
7816
|
mkdirSync7(RULES_INJECTOR_STORAGE, { recursive: true });
|
|
7785
7817
|
}
|
|
7786
7818
|
const storageData = {
|
|
@@ -7793,7 +7825,7 @@ function saveInjectedRules(sessionID, data) {
|
|
|
7793
7825
|
}
|
|
7794
7826
|
function clearInjectedRules(sessionID) {
|
|
7795
7827
|
const filePath = getStoragePath3(sessionID);
|
|
7796
|
-
if (
|
|
7828
|
+
if (existsSync20(filePath)) {
|
|
7797
7829
|
unlinkSync6(filePath);
|
|
7798
7830
|
}
|
|
7799
7831
|
}
|
|
@@ -8207,6 +8239,7 @@ function invalidatePackage(packageName = PACKAGE_NAME) {
|
|
|
8207
8239
|
}
|
|
8208
8240
|
|
|
8209
8241
|
// src/hooks/auto-update-checker/index.ts
|
|
8242
|
+
var SISYPHUS_SPINNER = ["\xB7", "\u2022", "\u25CF", "\u25CB", "\u25CC", "\u25E6", " "];
|
|
8210
8243
|
function createAutoUpdateCheckerHook(ctx, options = {}) {
|
|
8211
8244
|
const { showStartupToast = true, isSisyphusEnabled = false, autoUpdate = true } = options;
|
|
8212
8245
|
const getToastMessage = (isUpdate, latestVersion) => {
|
|
@@ -8311,16 +8344,26 @@ ${errorMessages}`,
|
|
|
8311
8344
|
}
|
|
8312
8345
|
async function showVersionToast(ctx, version, message) {
|
|
8313
8346
|
const displayVersion = version ?? "unknown";
|
|
8314
|
-
await ctx
|
|
8315
|
-
body: {
|
|
8316
|
-
title: `OhMyOpenCode ${displayVersion}`,
|
|
8317
|
-
message,
|
|
8318
|
-
variant: "info",
|
|
8319
|
-
duration: 5000
|
|
8320
|
-
}
|
|
8321
|
-
}).catch(() => {});
|
|
8347
|
+
await showSpinnerToast(ctx, displayVersion, message);
|
|
8322
8348
|
log(`[auto-update-checker] Startup toast shown: v${displayVersion}`);
|
|
8323
8349
|
}
|
|
8350
|
+
async function showSpinnerToast(ctx, version, message) {
|
|
8351
|
+
const totalDuration = 5000;
|
|
8352
|
+
const frameInterval = 100;
|
|
8353
|
+
const totalFrames = Math.floor(totalDuration / frameInterval);
|
|
8354
|
+
for (let i = 0;i < totalFrames; i++) {
|
|
8355
|
+
const spinner = SISYPHUS_SPINNER[i % SISYPHUS_SPINNER.length];
|
|
8356
|
+
await ctx.client.tui.showToast({
|
|
8357
|
+
body: {
|
|
8358
|
+
title: `${spinner} OhMyOpenCode ${version}`,
|
|
8359
|
+
message,
|
|
8360
|
+
variant: "info",
|
|
8361
|
+
duration: frameInterval + 50
|
|
8362
|
+
}
|
|
8363
|
+
}).catch(() => {});
|
|
8364
|
+
await new Promise((resolve5) => setTimeout(resolve5, frameInterval));
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8324
8367
|
async function showUpdateAvailableToast(ctx, latestVersion, getToastMessage) {
|
|
8325
8368
|
await ctx.client.tui.showToast({
|
|
8326
8369
|
body: {
|
|
@@ -8347,30 +8390,23 @@ Restart OpenCode to apply.`,
|
|
|
8347
8390
|
async function showLocalDevToast(ctx, version, isSisyphusEnabled) {
|
|
8348
8391
|
const displayVersion = version ?? "dev";
|
|
8349
8392
|
const message = isSisyphusEnabled ? "Sisyphus running in local development mode." : "Running in local development mode. oMoMoMo...";
|
|
8350
|
-
await ctx
|
|
8351
|
-
body: {
|
|
8352
|
-
title: `OhMyOpenCode ${displayVersion} (dev)`,
|
|
8353
|
-
message,
|
|
8354
|
-
variant: "warning",
|
|
8355
|
-
duration: 5000
|
|
8356
|
-
}
|
|
8357
|
-
}).catch(() => {});
|
|
8393
|
+
await showSpinnerToast(ctx, `${displayVersion} (dev)`, message);
|
|
8358
8394
|
log(`[auto-update-checker] Local dev toast shown: v${displayVersion}`);
|
|
8359
8395
|
}
|
|
8360
8396
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
8361
8397
|
import {
|
|
8362
|
-
existsSync as
|
|
8398
|
+
existsSync as existsSync23,
|
|
8363
8399
|
mkdirSync as mkdirSync8,
|
|
8364
8400
|
readFileSync as readFileSync13,
|
|
8365
8401
|
writeFileSync as writeFileSync10,
|
|
8366
8402
|
unlinkSync as unlinkSync7
|
|
8367
8403
|
} from "fs";
|
|
8368
|
-
import { join as
|
|
8404
|
+
import { join as join31 } from "path";
|
|
8369
8405
|
|
|
8370
8406
|
// src/hooks/agent-usage-reminder/constants.ts
|
|
8371
|
-
import { join as
|
|
8372
|
-
var OPENCODE_STORAGE7 =
|
|
8373
|
-
var AGENT_USAGE_REMINDER_STORAGE =
|
|
8407
|
+
import { join as join30 } from "path";
|
|
8408
|
+
var OPENCODE_STORAGE7 = join30(xdgData2 ?? "", "opencode", "storage");
|
|
8409
|
+
var AGENT_USAGE_REMINDER_STORAGE = join30(OPENCODE_STORAGE7, "agent-usage-reminder");
|
|
8374
8410
|
var TARGET_TOOLS = new Set([
|
|
8375
8411
|
"grep",
|
|
8376
8412
|
"safe_grep",
|
|
@@ -8415,11 +8451,11 @@ ALWAYS prefer: Multiple parallel background_task calls > Direct tool calls
|
|
|
8415
8451
|
|
|
8416
8452
|
// src/hooks/agent-usage-reminder/storage.ts
|
|
8417
8453
|
function getStoragePath4(sessionID) {
|
|
8418
|
-
return
|
|
8454
|
+
return join31(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
8419
8455
|
}
|
|
8420
8456
|
function loadAgentUsageState(sessionID) {
|
|
8421
8457
|
const filePath = getStoragePath4(sessionID);
|
|
8422
|
-
if (!
|
|
8458
|
+
if (!existsSync23(filePath))
|
|
8423
8459
|
return null;
|
|
8424
8460
|
try {
|
|
8425
8461
|
const content = readFileSync13(filePath, "utf-8");
|
|
@@ -8429,7 +8465,7 @@ function loadAgentUsageState(sessionID) {
|
|
|
8429
8465
|
}
|
|
8430
8466
|
}
|
|
8431
8467
|
function saveAgentUsageState(state2) {
|
|
8432
|
-
if (!
|
|
8468
|
+
if (!existsSync23(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
8433
8469
|
mkdirSync8(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
8434
8470
|
}
|
|
8435
8471
|
const filePath = getStoragePath4(state2.sessionID);
|
|
@@ -8437,7 +8473,7 @@ function saveAgentUsageState(state2) {
|
|
|
8437
8473
|
}
|
|
8438
8474
|
function clearAgentUsageState(sessionID) {
|
|
8439
8475
|
const filePath = getStoragePath4(sessionID);
|
|
8440
|
-
if (
|
|
8476
|
+
if (existsSync23(filePath)) {
|
|
8441
8477
|
unlinkSync7(filePath);
|
|
8442
8478
|
}
|
|
8443
8479
|
}
|
|
@@ -8664,18 +8700,18 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
8664
8700
|
}
|
|
8665
8701
|
// src/hooks/interactive-bash-session/storage.ts
|
|
8666
8702
|
import {
|
|
8667
|
-
existsSync as
|
|
8703
|
+
existsSync as existsSync24,
|
|
8668
8704
|
mkdirSync as mkdirSync9,
|
|
8669
8705
|
readFileSync as readFileSync14,
|
|
8670
8706
|
writeFileSync as writeFileSync11,
|
|
8671
8707
|
unlinkSync as unlinkSync8
|
|
8672
8708
|
} from "fs";
|
|
8673
|
-
import { join as
|
|
8709
|
+
import { join as join33 } from "path";
|
|
8674
8710
|
|
|
8675
8711
|
// src/hooks/interactive-bash-session/constants.ts
|
|
8676
|
-
import { join as
|
|
8677
|
-
var OPENCODE_STORAGE8 =
|
|
8678
|
-
var INTERACTIVE_BASH_SESSION_STORAGE =
|
|
8712
|
+
import { join as join32 } from "path";
|
|
8713
|
+
var OPENCODE_STORAGE8 = join32(xdgData2 ?? "", "opencode", "storage");
|
|
8714
|
+
var INTERACTIVE_BASH_SESSION_STORAGE = join32(OPENCODE_STORAGE8, "interactive-bash-session");
|
|
8679
8715
|
var OMO_SESSION_PREFIX = "omo-";
|
|
8680
8716
|
function buildSessionReminderMessage(sessions) {
|
|
8681
8717
|
if (sessions.length === 0)
|
|
@@ -8687,11 +8723,11 @@ function buildSessionReminderMessage(sessions) {
|
|
|
8687
8723
|
|
|
8688
8724
|
// src/hooks/interactive-bash-session/storage.ts
|
|
8689
8725
|
function getStoragePath5(sessionID) {
|
|
8690
|
-
return
|
|
8726
|
+
return join33(INTERACTIVE_BASH_SESSION_STORAGE, `${sessionID}.json`);
|
|
8691
8727
|
}
|
|
8692
8728
|
function loadInteractiveBashSessionState(sessionID) {
|
|
8693
8729
|
const filePath = getStoragePath5(sessionID);
|
|
8694
|
-
if (!
|
|
8730
|
+
if (!existsSync24(filePath))
|
|
8695
8731
|
return null;
|
|
8696
8732
|
try {
|
|
8697
8733
|
const content = readFileSync14(filePath, "utf-8");
|
|
@@ -8706,7 +8742,7 @@ function loadInteractiveBashSessionState(sessionID) {
|
|
|
8706
8742
|
}
|
|
8707
8743
|
}
|
|
8708
8744
|
function saveInteractiveBashSessionState(state2) {
|
|
8709
|
-
if (!
|
|
8745
|
+
if (!existsSync24(INTERACTIVE_BASH_SESSION_STORAGE)) {
|
|
8710
8746
|
mkdirSync9(INTERACTIVE_BASH_SESSION_STORAGE, { recursive: true });
|
|
8711
8747
|
}
|
|
8712
8748
|
const filePath = getStoragePath5(state2.sessionID);
|
|
@@ -8719,7 +8755,7 @@ function saveInteractiveBashSessionState(state2) {
|
|
|
8719
8755
|
}
|
|
8720
8756
|
function clearInteractiveBashSessionState(sessionID) {
|
|
8721
8757
|
const filePath = getStoragePath5(sessionID);
|
|
8722
|
-
if (
|
|
8758
|
+
if (existsSync24(filePath)) {
|
|
8723
8759
|
unlinkSync8(filePath);
|
|
8724
8760
|
}
|
|
8725
8761
|
}
|
|
@@ -10663,19 +10699,19 @@ async function createGoogleAntigravityAuthPlugin({
|
|
|
10663
10699
|
};
|
|
10664
10700
|
}
|
|
10665
10701
|
// src/features/claude-code-command-loader/loader.ts
|
|
10666
|
-
import { existsSync as
|
|
10702
|
+
import { existsSync as existsSync25, readdirSync as readdirSync7, readFileSync as readFileSync15 } from "fs";
|
|
10667
10703
|
import { homedir as homedir12 } from "os";
|
|
10668
|
-
import { join as
|
|
10704
|
+
import { join as join34, basename } from "path";
|
|
10669
10705
|
function loadCommandsFromDir(commandsDir, scope) {
|
|
10670
|
-
if (!
|
|
10706
|
+
if (!existsSync25(commandsDir)) {
|
|
10671
10707
|
return [];
|
|
10672
10708
|
}
|
|
10673
|
-
const entries =
|
|
10709
|
+
const entries = readdirSync7(commandsDir, { withFileTypes: true });
|
|
10674
10710
|
const commands = [];
|
|
10675
10711
|
for (const entry of entries) {
|
|
10676
10712
|
if (!isMarkdownFile(entry))
|
|
10677
10713
|
continue;
|
|
10678
|
-
const commandPath =
|
|
10714
|
+
const commandPath = join34(commandsDir, entry.name);
|
|
10679
10715
|
const commandName = basename(entry.name, ".md");
|
|
10680
10716
|
try {
|
|
10681
10717
|
const content = readFileSync15(commandPath, "utf-8");
|
|
@@ -10718,44 +10754,44 @@ function commandsToRecord(commands) {
|
|
|
10718
10754
|
return result;
|
|
10719
10755
|
}
|
|
10720
10756
|
function loadUserCommands() {
|
|
10721
|
-
const userCommandsDir =
|
|
10757
|
+
const userCommandsDir = join34(homedir12(), ".claude", "commands");
|
|
10722
10758
|
const commands = loadCommandsFromDir(userCommandsDir, "user");
|
|
10723
10759
|
return commandsToRecord(commands);
|
|
10724
10760
|
}
|
|
10725
10761
|
function loadProjectCommands() {
|
|
10726
|
-
const projectCommandsDir =
|
|
10762
|
+
const projectCommandsDir = join34(process.cwd(), ".claude", "commands");
|
|
10727
10763
|
const commands = loadCommandsFromDir(projectCommandsDir, "project");
|
|
10728
10764
|
return commandsToRecord(commands);
|
|
10729
10765
|
}
|
|
10730
10766
|
function loadOpencodeGlobalCommands() {
|
|
10731
|
-
const opencodeCommandsDir =
|
|
10767
|
+
const opencodeCommandsDir = join34(homedir12(), ".config", "opencode", "command");
|
|
10732
10768
|
const commands = loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
10733
10769
|
return commandsToRecord(commands);
|
|
10734
10770
|
}
|
|
10735
10771
|
function loadOpencodeProjectCommands() {
|
|
10736
|
-
const opencodeProjectDir =
|
|
10772
|
+
const opencodeProjectDir = join34(process.cwd(), ".opencode", "command");
|
|
10737
10773
|
const commands = loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
10738
10774
|
return commandsToRecord(commands);
|
|
10739
10775
|
}
|
|
10740
10776
|
// src/features/claude-code-skill-loader/loader.ts
|
|
10741
|
-
import { existsSync as
|
|
10777
|
+
import { existsSync as existsSync26, readdirSync as readdirSync8, readFileSync as readFileSync16 } from "fs";
|
|
10742
10778
|
import { homedir as homedir13 } from "os";
|
|
10743
|
-
import { join as
|
|
10779
|
+
import { join as join35 } from "path";
|
|
10744
10780
|
function loadSkillsFromDir(skillsDir, scope) {
|
|
10745
|
-
if (!
|
|
10781
|
+
if (!existsSync26(skillsDir)) {
|
|
10746
10782
|
return [];
|
|
10747
10783
|
}
|
|
10748
|
-
const entries =
|
|
10784
|
+
const entries = readdirSync8(skillsDir, { withFileTypes: true });
|
|
10749
10785
|
const skills = [];
|
|
10750
10786
|
for (const entry of entries) {
|
|
10751
10787
|
if (entry.name.startsWith("."))
|
|
10752
10788
|
continue;
|
|
10753
|
-
const skillPath =
|
|
10789
|
+
const skillPath = join35(skillsDir, entry.name);
|
|
10754
10790
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
10755
10791
|
continue;
|
|
10756
10792
|
const resolvedPath = resolveSymlink(skillPath);
|
|
10757
|
-
const skillMdPath =
|
|
10758
|
-
if (!
|
|
10793
|
+
const skillMdPath = join35(resolvedPath, "SKILL.md");
|
|
10794
|
+
if (!existsSync26(skillMdPath))
|
|
10759
10795
|
continue;
|
|
10760
10796
|
try {
|
|
10761
10797
|
const content = readFileSync16(skillMdPath, "utf-8");
|
|
@@ -10792,7 +10828,7 @@ $ARGUMENTS
|
|
|
10792
10828
|
return skills;
|
|
10793
10829
|
}
|
|
10794
10830
|
function loadUserSkillsAsCommands() {
|
|
10795
|
-
const userSkillsDir =
|
|
10831
|
+
const userSkillsDir = join35(homedir13(), ".claude", "skills");
|
|
10796
10832
|
const skills = loadSkillsFromDir(userSkillsDir, "user");
|
|
10797
10833
|
return skills.reduce((acc, skill) => {
|
|
10798
10834
|
acc[skill.name] = skill.definition;
|
|
@@ -10800,7 +10836,7 @@ function loadUserSkillsAsCommands() {
|
|
|
10800
10836
|
}, {});
|
|
10801
10837
|
}
|
|
10802
10838
|
function loadProjectSkillsAsCommands() {
|
|
10803
|
-
const projectSkillsDir =
|
|
10839
|
+
const projectSkillsDir = join35(process.cwd(), ".claude", "skills");
|
|
10804
10840
|
const skills = loadSkillsFromDir(projectSkillsDir, "project");
|
|
10805
10841
|
return skills.reduce((acc, skill) => {
|
|
10806
10842
|
acc[skill.name] = skill.definition;
|
|
@@ -10808,9 +10844,9 @@ function loadProjectSkillsAsCommands() {
|
|
|
10808
10844
|
}, {});
|
|
10809
10845
|
}
|
|
10810
10846
|
// src/features/claude-code-agent-loader/loader.ts
|
|
10811
|
-
import { existsSync as
|
|
10847
|
+
import { existsSync as existsSync27, readdirSync as readdirSync9, readFileSync as readFileSync17 } from "fs";
|
|
10812
10848
|
import { homedir as homedir14 } from "os";
|
|
10813
|
-
import { join as
|
|
10849
|
+
import { join as join36, basename as basename2 } from "path";
|
|
10814
10850
|
function parseToolsConfig(toolsStr) {
|
|
10815
10851
|
if (!toolsStr)
|
|
10816
10852
|
return;
|
|
@@ -10824,15 +10860,15 @@ function parseToolsConfig(toolsStr) {
|
|
|
10824
10860
|
return result;
|
|
10825
10861
|
}
|
|
10826
10862
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
10827
|
-
if (!
|
|
10863
|
+
if (!existsSync27(agentsDir)) {
|
|
10828
10864
|
return [];
|
|
10829
10865
|
}
|
|
10830
|
-
const entries =
|
|
10866
|
+
const entries = readdirSync9(agentsDir, { withFileTypes: true });
|
|
10831
10867
|
const agents = [];
|
|
10832
10868
|
for (const entry of entries) {
|
|
10833
10869
|
if (!isMarkdownFile(entry))
|
|
10834
10870
|
continue;
|
|
10835
|
-
const agentPath =
|
|
10871
|
+
const agentPath = join36(agentsDir, entry.name);
|
|
10836
10872
|
const agentName = basename2(entry.name, ".md");
|
|
10837
10873
|
try {
|
|
10838
10874
|
const content = readFileSync17(agentPath, "utf-8");
|
|
@@ -10862,7 +10898,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
10862
10898
|
return agents;
|
|
10863
10899
|
}
|
|
10864
10900
|
function loadUserAgents() {
|
|
10865
|
-
const userAgentsDir =
|
|
10901
|
+
const userAgentsDir = join36(homedir14(), ".claude", "agents");
|
|
10866
10902
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
10867
10903
|
const result = {};
|
|
10868
10904
|
for (const agent of agents) {
|
|
@@ -10871,7 +10907,7 @@ function loadUserAgents() {
|
|
|
10871
10907
|
return result;
|
|
10872
10908
|
}
|
|
10873
10909
|
function loadProjectAgents() {
|
|
10874
|
-
const projectAgentsDir =
|
|
10910
|
+
const projectAgentsDir = join36(process.cwd(), ".claude", "agents");
|
|
10875
10911
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
10876
10912
|
const result = {};
|
|
10877
10913
|
for (const agent of agents) {
|
|
@@ -10880,9 +10916,9 @@ function loadProjectAgents() {
|
|
|
10880
10916
|
return result;
|
|
10881
10917
|
}
|
|
10882
10918
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
10883
|
-
import { existsSync as
|
|
10919
|
+
import { existsSync as existsSync28 } from "fs";
|
|
10884
10920
|
import { homedir as homedir15 } from "os";
|
|
10885
|
-
import { join as
|
|
10921
|
+
import { join as join37 } from "path";
|
|
10886
10922
|
|
|
10887
10923
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
10888
10924
|
function expandEnvVars(value) {
|
|
@@ -10951,13 +10987,13 @@ function getMcpConfigPaths() {
|
|
|
10951
10987
|
const home = homedir15();
|
|
10952
10988
|
const cwd = process.cwd();
|
|
10953
10989
|
return [
|
|
10954
|
-
{ path:
|
|
10955
|
-
{ path:
|
|
10956
|
-
{ path:
|
|
10990
|
+
{ path: join37(home, ".claude", ".mcp.json"), scope: "user" },
|
|
10991
|
+
{ path: join37(cwd, ".mcp.json"), scope: "project" },
|
|
10992
|
+
{ path: join37(cwd, ".claude", ".mcp.json"), scope: "local" }
|
|
10957
10993
|
];
|
|
10958
10994
|
}
|
|
10959
10995
|
async function loadMcpConfigFile(filePath) {
|
|
10960
|
-
if (!
|
|
10996
|
+
if (!existsSync28(filePath)) {
|
|
10961
10997
|
return null;
|
|
10962
10998
|
}
|
|
10963
10999
|
try {
|
|
@@ -11292,11 +11328,11 @@ var EXT_TO_LANG = {
|
|
|
11292
11328
|
".gql": "graphql"
|
|
11293
11329
|
};
|
|
11294
11330
|
// src/tools/lsp/config.ts
|
|
11295
|
-
import { existsSync as
|
|
11296
|
-
import { join as
|
|
11331
|
+
import { existsSync as existsSync29, readFileSync as readFileSync18 } from "fs";
|
|
11332
|
+
import { join as join38 } from "path";
|
|
11297
11333
|
import { homedir as homedir16 } from "os";
|
|
11298
11334
|
function loadJsonFile(path7) {
|
|
11299
|
-
if (!
|
|
11335
|
+
if (!existsSync29(path7))
|
|
11300
11336
|
return null;
|
|
11301
11337
|
try {
|
|
11302
11338
|
return JSON.parse(readFileSync18(path7, "utf-8"));
|
|
@@ -11307,9 +11343,9 @@ function loadJsonFile(path7) {
|
|
|
11307
11343
|
function getConfigPaths2() {
|
|
11308
11344
|
const cwd = process.cwd();
|
|
11309
11345
|
return {
|
|
11310
|
-
project:
|
|
11311
|
-
user:
|
|
11312
|
-
opencode:
|
|
11346
|
+
project: join38(cwd, ".opencode", "oh-my-opencode.json"),
|
|
11347
|
+
user: join38(homedir16(), ".config", "opencode", "oh-my-opencode.json"),
|
|
11348
|
+
opencode: join38(homedir16(), ".config", "opencode", "opencode.json")
|
|
11313
11349
|
};
|
|
11314
11350
|
}
|
|
11315
11351
|
function loadAllConfigs() {
|
|
@@ -11405,21 +11441,21 @@ function isServerInstalled(command) {
|
|
|
11405
11441
|
const pathSeparator = isWindows2 ? ";" : ":";
|
|
11406
11442
|
const paths = pathEnv.split(pathSeparator);
|
|
11407
11443
|
for (const p of paths) {
|
|
11408
|
-
if (
|
|
11444
|
+
if (existsSync29(join38(p, cmd)) || existsSync29(join38(p, cmd + ext))) {
|
|
11409
11445
|
return true;
|
|
11410
11446
|
}
|
|
11411
11447
|
}
|
|
11412
11448
|
const cwd = process.cwd();
|
|
11413
11449
|
const additionalPaths = [
|
|
11414
|
-
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11450
|
+
join38(cwd, "node_modules", ".bin", cmd),
|
|
11451
|
+
join38(cwd, "node_modules", ".bin", cmd + ext),
|
|
11452
|
+
join38(homedir16(), ".config", "opencode", "bin", cmd),
|
|
11453
|
+
join38(homedir16(), ".config", "opencode", "bin", cmd + ext),
|
|
11454
|
+
join38(homedir16(), ".config", "opencode", "node_modules", ".bin", cmd),
|
|
11455
|
+
join38(homedir16(), ".config", "opencode", "node_modules", ".bin", cmd + ext)
|
|
11420
11456
|
];
|
|
11421
11457
|
for (const p of additionalPaths) {
|
|
11422
|
-
if (
|
|
11458
|
+
if (existsSync29(p)) {
|
|
11423
11459
|
return true;
|
|
11424
11460
|
}
|
|
11425
11461
|
}
|
|
@@ -12014,16 +12050,16 @@ ${msg}`);
|
|
|
12014
12050
|
}
|
|
12015
12051
|
// src/tools/lsp/utils.ts
|
|
12016
12052
|
import { extname as extname2, resolve as resolve6 } from "path";
|
|
12017
|
-
import { existsSync as
|
|
12053
|
+
import { existsSync as existsSync30, readFileSync as readFileSync20, writeFileSync as writeFileSync12 } from "fs";
|
|
12018
12054
|
function findWorkspaceRoot(filePath) {
|
|
12019
12055
|
let dir = resolve6(filePath);
|
|
12020
|
-
if (!
|
|
12056
|
+
if (!existsSync30(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
12021
12057
|
dir = __require("path").dirname(dir);
|
|
12022
12058
|
}
|
|
12023
12059
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
12024
12060
|
while (dir !== "/") {
|
|
12025
12061
|
for (const marker of markers) {
|
|
12026
|
-
if (
|
|
12062
|
+
if (existsSync30(__require("path").join(dir, marker))) {
|
|
12027
12063
|
return dir;
|
|
12028
12064
|
}
|
|
12029
12065
|
}
|
|
@@ -24948,13 +24984,13 @@ var lsp_code_action_resolve = tool({
|
|
|
24948
24984
|
});
|
|
24949
24985
|
// src/tools/ast-grep/constants.ts
|
|
24950
24986
|
import { createRequire as createRequire4 } from "module";
|
|
24951
|
-
import { dirname as dirname6, join as
|
|
24952
|
-
import { existsSync as
|
|
24987
|
+
import { dirname as dirname6, join as join40 } from "path";
|
|
24988
|
+
import { existsSync as existsSync32, statSync as statSync4 } from "fs";
|
|
24953
24989
|
|
|
24954
24990
|
// src/tools/ast-grep/downloader.ts
|
|
24955
24991
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
24956
|
-
import { existsSync as
|
|
24957
|
-
import { join as
|
|
24992
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync10, chmodSync as chmodSync2, unlinkSync as unlinkSync9 } from "fs";
|
|
24993
|
+
import { join as join39 } from "path";
|
|
24958
24994
|
import { homedir as homedir17 } from "os";
|
|
24959
24995
|
import { createRequire as createRequire3 } from "module";
|
|
24960
24996
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -24980,19 +25016,19 @@ var PLATFORM_MAP2 = {
|
|
|
24980
25016
|
function getCacheDir3() {
|
|
24981
25017
|
if (process.platform === "win32") {
|
|
24982
25018
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
24983
|
-
const base2 = localAppData ||
|
|
24984
|
-
return
|
|
25019
|
+
const base2 = localAppData || join39(homedir17(), "AppData", "Local");
|
|
25020
|
+
return join39(base2, "oh-my-opencode", "bin");
|
|
24985
25021
|
}
|
|
24986
25022
|
const xdgCache2 = process.env.XDG_CACHE_HOME;
|
|
24987
|
-
const base = xdgCache2 ||
|
|
24988
|
-
return
|
|
25023
|
+
const base = xdgCache2 || join39(homedir17(), ".cache");
|
|
25024
|
+
return join39(base, "oh-my-opencode", "bin");
|
|
24989
25025
|
}
|
|
24990
25026
|
function getBinaryName3() {
|
|
24991
25027
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
24992
25028
|
}
|
|
24993
25029
|
function getCachedBinaryPath2() {
|
|
24994
|
-
const binaryPath =
|
|
24995
|
-
return
|
|
25030
|
+
const binaryPath = join39(getCacheDir3(), getBinaryName3());
|
|
25031
|
+
return existsSync31(binaryPath) ? binaryPath : null;
|
|
24996
25032
|
}
|
|
24997
25033
|
async function extractZip2(archivePath, destDir) {
|
|
24998
25034
|
const proc = process.platform === "win32" ? spawn5([
|
|
@@ -25018,8 +25054,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
25018
25054
|
}
|
|
25019
25055
|
const cacheDir = getCacheDir3();
|
|
25020
25056
|
const binaryName = getBinaryName3();
|
|
25021
|
-
const binaryPath =
|
|
25022
|
-
if (
|
|
25057
|
+
const binaryPath = join39(cacheDir, binaryName);
|
|
25058
|
+
if (existsSync31(binaryPath)) {
|
|
25023
25059
|
return binaryPath;
|
|
25024
25060
|
}
|
|
25025
25061
|
const { arch, os: os5 } = platformInfo;
|
|
@@ -25027,21 +25063,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
25027
25063
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
25028
25064
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
25029
25065
|
try {
|
|
25030
|
-
if (!
|
|
25066
|
+
if (!existsSync31(cacheDir)) {
|
|
25031
25067
|
mkdirSync10(cacheDir, { recursive: true });
|
|
25032
25068
|
}
|
|
25033
25069
|
const response2 = await fetch(downloadUrl, { redirect: "follow" });
|
|
25034
25070
|
if (!response2.ok) {
|
|
25035
25071
|
throw new Error(`HTTP ${response2.status}: ${response2.statusText}`);
|
|
25036
25072
|
}
|
|
25037
|
-
const archivePath =
|
|
25073
|
+
const archivePath = join39(cacheDir, assetName);
|
|
25038
25074
|
const arrayBuffer = await response2.arrayBuffer();
|
|
25039
25075
|
await Bun.write(archivePath, arrayBuffer);
|
|
25040
25076
|
await extractZip2(archivePath, cacheDir);
|
|
25041
|
-
if (
|
|
25077
|
+
if (existsSync31(archivePath)) {
|
|
25042
25078
|
unlinkSync9(archivePath);
|
|
25043
25079
|
}
|
|
25044
|
-
if (process.platform !== "win32" &&
|
|
25080
|
+
if (process.platform !== "win32" && existsSync31(binaryPath)) {
|
|
25045
25081
|
chmodSync2(binaryPath, 493);
|
|
25046
25082
|
}
|
|
25047
25083
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -25092,8 +25128,8 @@ function findSgCliPathSync() {
|
|
|
25092
25128
|
const require2 = createRequire4(import.meta.url);
|
|
25093
25129
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
25094
25130
|
const cliDir = dirname6(cliPkgPath);
|
|
25095
|
-
const sgPath =
|
|
25096
|
-
if (
|
|
25131
|
+
const sgPath = join40(cliDir, binaryName);
|
|
25132
|
+
if (existsSync32(sgPath) && isValidBinary(sgPath)) {
|
|
25097
25133
|
return sgPath;
|
|
25098
25134
|
}
|
|
25099
25135
|
} catch {}
|
|
@@ -25104,8 +25140,8 @@ function findSgCliPathSync() {
|
|
|
25104
25140
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
25105
25141
|
const pkgDir = dirname6(pkgPath);
|
|
25106
25142
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
25107
|
-
const binaryPath =
|
|
25108
|
-
if (
|
|
25143
|
+
const binaryPath = join40(pkgDir, astGrepName);
|
|
25144
|
+
if (existsSync32(binaryPath) && isValidBinary(binaryPath)) {
|
|
25109
25145
|
return binaryPath;
|
|
25110
25146
|
}
|
|
25111
25147
|
} catch {}
|
|
@@ -25113,7 +25149,7 @@ function findSgCliPathSync() {
|
|
|
25113
25149
|
if (process.platform === "darwin") {
|
|
25114
25150
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
25115
25151
|
for (const path7 of homebrewPaths) {
|
|
25116
|
-
if (
|
|
25152
|
+
if (existsSync32(path7) && isValidBinary(path7)) {
|
|
25117
25153
|
return path7;
|
|
25118
25154
|
}
|
|
25119
25155
|
}
|
|
@@ -25169,11 +25205,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
25169
25205
|
|
|
25170
25206
|
// src/tools/ast-grep/cli.ts
|
|
25171
25207
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
25172
|
-
import { existsSync as
|
|
25208
|
+
import { existsSync as existsSync33 } from "fs";
|
|
25173
25209
|
var resolvedCliPath3 = null;
|
|
25174
25210
|
var initPromise2 = null;
|
|
25175
25211
|
async function getAstGrepPath() {
|
|
25176
|
-
if (resolvedCliPath3 !== null &&
|
|
25212
|
+
if (resolvedCliPath3 !== null && existsSync33(resolvedCliPath3)) {
|
|
25177
25213
|
return resolvedCliPath3;
|
|
25178
25214
|
}
|
|
25179
25215
|
if (initPromise2) {
|
|
@@ -25181,7 +25217,7 @@ async function getAstGrepPath() {
|
|
|
25181
25217
|
}
|
|
25182
25218
|
initPromise2 = (async () => {
|
|
25183
25219
|
const syncPath = findSgCliPathSync();
|
|
25184
|
-
if (syncPath &&
|
|
25220
|
+
if (syncPath && existsSync33(syncPath)) {
|
|
25185
25221
|
resolvedCliPath3 = syncPath;
|
|
25186
25222
|
setSgCliPath(syncPath);
|
|
25187
25223
|
return syncPath;
|
|
@@ -25215,7 +25251,7 @@ async function runSg(options) {
|
|
|
25215
25251
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
25216
25252
|
args.push(...paths);
|
|
25217
25253
|
let cliPath = getSgCliPath();
|
|
25218
|
-
if (!
|
|
25254
|
+
if (!existsSync33(cliPath) && cliPath !== "sg") {
|
|
25219
25255
|
const downloadedPath = await getAstGrepPath();
|
|
25220
25256
|
if (downloadedPath) {
|
|
25221
25257
|
cliPath = downloadedPath;
|
|
@@ -25479,24 +25515,24 @@ var ast_grep_replace = tool({
|
|
|
25479
25515
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
25480
25516
|
|
|
25481
25517
|
// src/tools/grep/constants.ts
|
|
25482
|
-
import { existsSync as
|
|
25483
|
-
import { join as
|
|
25518
|
+
import { existsSync as existsSync35 } from "fs";
|
|
25519
|
+
import { join as join42, dirname as dirname7 } from "path";
|
|
25484
25520
|
import { spawnSync } from "child_process";
|
|
25485
25521
|
|
|
25486
25522
|
// src/tools/grep/downloader.ts
|
|
25487
|
-
import { existsSync as
|
|
25488
|
-
import { join as
|
|
25523
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync11, chmodSync as chmodSync3, unlinkSync as unlinkSync10, readdirSync as readdirSync10 } from "fs";
|
|
25524
|
+
import { join as join41 } from "path";
|
|
25489
25525
|
function getInstallDir() {
|
|
25490
25526
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
25491
|
-
return
|
|
25527
|
+
return join41(homeDir, ".cache", "oh-my-opencode", "bin");
|
|
25492
25528
|
}
|
|
25493
25529
|
function getRgPath() {
|
|
25494
25530
|
const isWindows2 = process.platform === "win32";
|
|
25495
|
-
return
|
|
25531
|
+
return join41(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
25496
25532
|
}
|
|
25497
25533
|
function getInstalledRipgrepPath() {
|
|
25498
25534
|
const rgPath = getRgPath();
|
|
25499
|
-
return
|
|
25535
|
+
return existsSync34(rgPath) ? rgPath : null;
|
|
25500
25536
|
}
|
|
25501
25537
|
|
|
25502
25538
|
// src/tools/grep/constants.ts
|
|
@@ -25519,13 +25555,13 @@ function getOpenCodeBundledRg() {
|
|
|
25519
25555
|
const isWindows2 = process.platform === "win32";
|
|
25520
25556
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
25521
25557
|
const candidates = [
|
|
25522
|
-
|
|
25523
|
-
|
|
25524
|
-
|
|
25525
|
-
|
|
25558
|
+
join42(execDir, rgName),
|
|
25559
|
+
join42(execDir, "bin", rgName),
|
|
25560
|
+
join42(execDir, "..", "bin", rgName),
|
|
25561
|
+
join42(execDir, "..", "libexec", rgName)
|
|
25526
25562
|
];
|
|
25527
25563
|
for (const candidate of candidates) {
|
|
25528
|
-
if (
|
|
25564
|
+
if (existsSync35(candidate)) {
|
|
25529
25565
|
return candidate;
|
|
25530
25566
|
}
|
|
25531
25567
|
}
|
|
@@ -25928,19 +25964,19 @@ var glob = tool({
|
|
|
25928
25964
|
}
|
|
25929
25965
|
});
|
|
25930
25966
|
// src/tools/slashcommand/tools.ts
|
|
25931
|
-
import { existsSync as
|
|
25967
|
+
import { existsSync as existsSync36, readdirSync as readdirSync11, readFileSync as readFileSync21 } from "fs";
|
|
25932
25968
|
import { homedir as homedir18 } from "os";
|
|
25933
|
-
import { join as
|
|
25969
|
+
import { join as join43, basename as basename3, dirname as dirname8 } from "path";
|
|
25934
25970
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
25935
|
-
if (!
|
|
25971
|
+
if (!existsSync36(commandsDir)) {
|
|
25936
25972
|
return [];
|
|
25937
25973
|
}
|
|
25938
|
-
const entries =
|
|
25974
|
+
const entries = readdirSync11(commandsDir, { withFileTypes: true });
|
|
25939
25975
|
const commands = [];
|
|
25940
25976
|
for (const entry of entries) {
|
|
25941
25977
|
if (!isMarkdownFile(entry))
|
|
25942
25978
|
continue;
|
|
25943
|
-
const commandPath =
|
|
25979
|
+
const commandPath = join43(commandsDir, entry.name);
|
|
25944
25980
|
const commandName = basename3(entry.name, ".md");
|
|
25945
25981
|
try {
|
|
25946
25982
|
const content = readFileSync21(commandPath, "utf-8");
|
|
@@ -25968,10 +26004,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
25968
26004
|
return commands;
|
|
25969
26005
|
}
|
|
25970
26006
|
function discoverCommandsSync() {
|
|
25971
|
-
const userCommandsDir =
|
|
25972
|
-
const projectCommandsDir =
|
|
25973
|
-
const opencodeGlobalDir =
|
|
25974
|
-
const opencodeProjectDir =
|
|
26007
|
+
const userCommandsDir = join43(homedir18(), ".claude", "commands");
|
|
26008
|
+
const projectCommandsDir = join43(process.cwd(), ".claude", "commands");
|
|
26009
|
+
const opencodeGlobalDir = join43(homedir18(), ".config", "opencode", "command");
|
|
26010
|
+
const opencodeProjectDir = join43(process.cwd(), ".opencode", "command");
|
|
25975
26011
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
25976
26012
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
25977
26013
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -26094,246 +26130,6 @@ Provide a command name to execute.`;
|
|
|
26094
26130
|
Try a different command name.`;
|
|
26095
26131
|
}
|
|
26096
26132
|
});
|
|
26097
|
-
// src/tools/skill/types.ts
|
|
26098
|
-
var SkillFrontmatterSchema = exports_external.object({
|
|
26099
|
-
name: exports_external.string().regex(/^[a-z0-9-]+$/, "Name must be lowercase alphanumeric with hyphens only").min(1, "Name cannot be empty"),
|
|
26100
|
-
description: exports_external.string().min(20, "Description must be at least 20 characters for discoverability"),
|
|
26101
|
-
license: exports_external.string().optional(),
|
|
26102
|
-
"allowed-tools": exports_external.array(exports_external.string()).optional(),
|
|
26103
|
-
metadata: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
26104
|
-
});
|
|
26105
|
-
// src/tools/skill/tools.ts
|
|
26106
|
-
import { existsSync as existsSync36, readdirSync as readdirSync11, readFileSync as readFileSync22 } from "fs";
|
|
26107
|
-
import { homedir as homedir19 } from "os";
|
|
26108
|
-
import { join as join43, basename as basename4 } from "path";
|
|
26109
|
-
function parseSkillFrontmatter(data) {
|
|
26110
|
-
return {
|
|
26111
|
-
name: typeof data.name === "string" ? data.name : "",
|
|
26112
|
-
description: typeof data.description === "string" ? data.description : "",
|
|
26113
|
-
license: typeof data.license === "string" ? data.license : undefined,
|
|
26114
|
-
"allowed-tools": Array.isArray(data["allowed-tools"]) ? data["allowed-tools"] : undefined,
|
|
26115
|
-
metadata: typeof data.metadata === "object" && data.metadata !== null ? data.metadata : undefined
|
|
26116
|
-
};
|
|
26117
|
-
}
|
|
26118
|
-
function discoverSkillsFromDir(skillsDir, scope) {
|
|
26119
|
-
if (!existsSync36(skillsDir)) {
|
|
26120
|
-
return [];
|
|
26121
|
-
}
|
|
26122
|
-
const entries = readdirSync11(skillsDir, { withFileTypes: true });
|
|
26123
|
-
const skills = [];
|
|
26124
|
-
for (const entry of entries) {
|
|
26125
|
-
if (entry.name.startsWith("."))
|
|
26126
|
-
continue;
|
|
26127
|
-
const skillPath = join43(skillsDir, entry.name);
|
|
26128
|
-
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
26129
|
-
const resolvedPath = resolveSymlink(skillPath);
|
|
26130
|
-
const skillMdPath = join43(resolvedPath, "SKILL.md");
|
|
26131
|
-
if (!existsSync36(skillMdPath))
|
|
26132
|
-
continue;
|
|
26133
|
-
try {
|
|
26134
|
-
const content = readFileSync22(skillMdPath, "utf-8");
|
|
26135
|
-
const { data } = parseFrontmatter(content);
|
|
26136
|
-
skills.push({
|
|
26137
|
-
name: data.name || entry.name,
|
|
26138
|
-
description: data.description || "",
|
|
26139
|
-
scope
|
|
26140
|
-
});
|
|
26141
|
-
} catch {
|
|
26142
|
-
continue;
|
|
26143
|
-
}
|
|
26144
|
-
}
|
|
26145
|
-
}
|
|
26146
|
-
return skills;
|
|
26147
|
-
}
|
|
26148
|
-
function discoverSkillsSync() {
|
|
26149
|
-
const userSkillsDir = join43(homedir19(), ".claude", "skills");
|
|
26150
|
-
const projectSkillsDir = join43(process.cwd(), ".claude", "skills");
|
|
26151
|
-
const userSkills = discoverSkillsFromDir(userSkillsDir, "user");
|
|
26152
|
-
const projectSkills = discoverSkillsFromDir(projectSkillsDir, "project");
|
|
26153
|
-
return [...projectSkills, ...userSkills];
|
|
26154
|
-
}
|
|
26155
|
-
var availableSkills = discoverSkillsSync();
|
|
26156
|
-
var skillListForDescription = availableSkills.map((s) => `- ${s.name}: ${s.description} (${s.scope})`).join(`
|
|
26157
|
-
`);
|
|
26158
|
-
async function parseSkillMd(skillPath) {
|
|
26159
|
-
const resolvedPath = resolveSymlink(skillPath);
|
|
26160
|
-
const skillMdPath = join43(resolvedPath, "SKILL.md");
|
|
26161
|
-
if (!existsSync36(skillMdPath)) {
|
|
26162
|
-
return null;
|
|
26163
|
-
}
|
|
26164
|
-
try {
|
|
26165
|
-
let content = readFileSync22(skillMdPath, "utf-8");
|
|
26166
|
-
content = await resolveCommandsInText(content);
|
|
26167
|
-
const { data, body } = parseFrontmatter(content);
|
|
26168
|
-
const frontmatter2 = parseSkillFrontmatter(data);
|
|
26169
|
-
const metadata = {
|
|
26170
|
-
name: frontmatter2.name || basename4(skillPath),
|
|
26171
|
-
description: frontmatter2.description,
|
|
26172
|
-
license: frontmatter2.license,
|
|
26173
|
-
allowedTools: frontmatter2["allowed-tools"],
|
|
26174
|
-
metadata: frontmatter2.metadata
|
|
26175
|
-
};
|
|
26176
|
-
const referencesDir = join43(resolvedPath, "references");
|
|
26177
|
-
const scriptsDir = join43(resolvedPath, "scripts");
|
|
26178
|
-
const assetsDir = join43(resolvedPath, "assets");
|
|
26179
|
-
const references = existsSync36(referencesDir) ? readdirSync11(referencesDir).filter((f) => !f.startsWith(".")) : [];
|
|
26180
|
-
const scripts = existsSync36(scriptsDir) ? readdirSync11(scriptsDir).filter((f) => !f.startsWith(".") && !f.startsWith("__")) : [];
|
|
26181
|
-
const assets = existsSync36(assetsDir) ? readdirSync11(assetsDir).filter((f) => !f.startsWith(".")) : [];
|
|
26182
|
-
return {
|
|
26183
|
-
name: metadata.name,
|
|
26184
|
-
path: resolvedPath,
|
|
26185
|
-
basePath: resolvedPath,
|
|
26186
|
-
metadata,
|
|
26187
|
-
content: body,
|
|
26188
|
-
references,
|
|
26189
|
-
scripts,
|
|
26190
|
-
assets
|
|
26191
|
-
};
|
|
26192
|
-
} catch {
|
|
26193
|
-
return null;
|
|
26194
|
-
}
|
|
26195
|
-
}
|
|
26196
|
-
async function discoverSkillsFromDirAsync(skillsDir) {
|
|
26197
|
-
if (!existsSync36(skillsDir)) {
|
|
26198
|
-
return [];
|
|
26199
|
-
}
|
|
26200
|
-
const entries = readdirSync11(skillsDir, { withFileTypes: true });
|
|
26201
|
-
const skills = [];
|
|
26202
|
-
for (const entry of entries) {
|
|
26203
|
-
if (entry.name.startsWith("."))
|
|
26204
|
-
continue;
|
|
26205
|
-
const skillPath = join43(skillsDir, entry.name);
|
|
26206
|
-
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
26207
|
-
const skillInfo = await parseSkillMd(skillPath);
|
|
26208
|
-
if (skillInfo) {
|
|
26209
|
-
skills.push(skillInfo);
|
|
26210
|
-
}
|
|
26211
|
-
}
|
|
26212
|
-
}
|
|
26213
|
-
return skills;
|
|
26214
|
-
}
|
|
26215
|
-
async function discoverSkills() {
|
|
26216
|
-
const userSkillsDir = join43(homedir19(), ".claude", "skills");
|
|
26217
|
-
const projectSkillsDir = join43(process.cwd(), ".claude", "skills");
|
|
26218
|
-
const userSkills = await discoverSkillsFromDirAsync(userSkillsDir);
|
|
26219
|
-
const projectSkills = await discoverSkillsFromDirAsync(projectSkillsDir);
|
|
26220
|
-
return [...projectSkills, ...userSkills];
|
|
26221
|
-
}
|
|
26222
|
-
function findMatchingSkills(skills, query) {
|
|
26223
|
-
const queryLower = query.toLowerCase();
|
|
26224
|
-
const queryTerms = queryLower.split(/\s+/).filter(Boolean);
|
|
26225
|
-
return skills.map((skill) => {
|
|
26226
|
-
let score = 0;
|
|
26227
|
-
const nameLower = skill.metadata.name.toLowerCase();
|
|
26228
|
-
const descLower = skill.metadata.description.toLowerCase();
|
|
26229
|
-
if (nameLower === queryLower)
|
|
26230
|
-
score += 100;
|
|
26231
|
-
if (nameLower.includes(queryLower))
|
|
26232
|
-
score += 50;
|
|
26233
|
-
for (const term of queryTerms) {
|
|
26234
|
-
if (nameLower.includes(term))
|
|
26235
|
-
score += 20;
|
|
26236
|
-
if (descLower.includes(term))
|
|
26237
|
-
score += 10;
|
|
26238
|
-
}
|
|
26239
|
-
return { skill, score };
|
|
26240
|
-
}).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score).map(({ skill }) => skill);
|
|
26241
|
-
}
|
|
26242
|
-
async function loadSkillWithReferences(skill, includeRefs) {
|
|
26243
|
-
const referencesLoaded = [];
|
|
26244
|
-
if (includeRefs && skill.references.length > 0) {
|
|
26245
|
-
for (const ref of skill.references) {
|
|
26246
|
-
const refPath = join43(skill.path, "references", ref);
|
|
26247
|
-
try {
|
|
26248
|
-
let content = readFileSync22(refPath, "utf-8");
|
|
26249
|
-
content = await resolveCommandsInText(content);
|
|
26250
|
-
referencesLoaded.push({ path: ref, content });
|
|
26251
|
-
} catch {}
|
|
26252
|
-
}
|
|
26253
|
-
}
|
|
26254
|
-
return {
|
|
26255
|
-
name: skill.name,
|
|
26256
|
-
metadata: skill.metadata,
|
|
26257
|
-
basePath: skill.basePath,
|
|
26258
|
-
body: skill.content,
|
|
26259
|
-
referencesLoaded
|
|
26260
|
-
};
|
|
26261
|
-
}
|
|
26262
|
-
function formatSkillList(skills) {
|
|
26263
|
-
if (skills.length === 0) {
|
|
26264
|
-
return "No skills found in ~/.claude/skills/";
|
|
26265
|
-
}
|
|
26266
|
-
const lines = [`# Available Skills
|
|
26267
|
-
`];
|
|
26268
|
-
for (const skill of skills) {
|
|
26269
|
-
lines.push(`- **${skill.metadata.name}**: ${skill.metadata.description || "(no description)"}`);
|
|
26270
|
-
}
|
|
26271
|
-
lines.push(`
|
|
26272
|
-
**Total**: ${skills.length} skills`);
|
|
26273
|
-
return lines.join(`
|
|
26274
|
-
`);
|
|
26275
|
-
}
|
|
26276
|
-
function formatLoadedSkills(loadedSkills) {
|
|
26277
|
-
if (loadedSkills.length === 0) {
|
|
26278
|
-
return "No skills loaded.";
|
|
26279
|
-
}
|
|
26280
|
-
const skill = loadedSkills[0];
|
|
26281
|
-
const sections = [];
|
|
26282
|
-
sections.push(`Base directory for this skill: ${skill.basePath}/`);
|
|
26283
|
-
sections.push("");
|
|
26284
|
-
sections.push(skill.body.trim());
|
|
26285
|
-
if (skill.referencesLoaded.length > 0) {
|
|
26286
|
-
sections.push(`
|
|
26287
|
-
---
|
|
26288
|
-
### Loaded References
|
|
26289
|
-
`);
|
|
26290
|
-
for (const ref of skill.referencesLoaded) {
|
|
26291
|
-
sections.push(`#### ${ref.path}
|
|
26292
|
-
`);
|
|
26293
|
-
sections.push("```");
|
|
26294
|
-
sections.push(ref.content.trim());
|
|
26295
|
-
sections.push("```\n");
|
|
26296
|
-
}
|
|
26297
|
-
}
|
|
26298
|
-
sections.push(`
|
|
26299
|
-
---
|
|
26300
|
-
**Launched skill**: ${skill.metadata.name}`);
|
|
26301
|
-
return sections.join(`
|
|
26302
|
-
`);
|
|
26303
|
-
}
|
|
26304
|
-
var skill = tool({
|
|
26305
|
-
description: `Execute a skill within the main conversation.
|
|
26306
|
-
|
|
26307
|
-
When you invoke a skill, the skill's prompt will expand and provide detailed instructions on how to complete the task.
|
|
26308
|
-
|
|
26309
|
-
Available Skills:
|
|
26310
|
-
${skillListForDescription}`,
|
|
26311
|
-
args: {
|
|
26312
|
-
skill: tool.schema.string().describe("The skill name or search query to find and load. Can be exact skill name (e.g., 'python-programmer') or keywords (e.g., 'python', 'plan').")
|
|
26313
|
-
},
|
|
26314
|
-
async execute(args) {
|
|
26315
|
-
const skills = await discoverSkills();
|
|
26316
|
-
if (!args.skill) {
|
|
26317
|
-
return formatSkillList(skills) + `
|
|
26318
|
-
|
|
26319
|
-
Provide a skill name to load.`;
|
|
26320
|
-
}
|
|
26321
|
-
const matchingSkills = findMatchingSkills(skills, args.skill);
|
|
26322
|
-
if (matchingSkills.length === 0) {
|
|
26323
|
-
return `No skills found matching "${args.skill}".
|
|
26324
|
-
|
|
26325
|
-
` + formatSkillList(skills) + `
|
|
26326
|
-
|
|
26327
|
-
Try a different skill name.`;
|
|
26328
|
-
}
|
|
26329
|
-
const loadedSkills = [];
|
|
26330
|
-
for (const skillInfo of matchingSkills.slice(0, 3)) {
|
|
26331
|
-
const loaded = await loadSkillWithReferences(skillInfo, true);
|
|
26332
|
-
loadedSkills.push(loaded);
|
|
26333
|
-
}
|
|
26334
|
-
return formatLoadedSkills(loadedSkills);
|
|
26335
|
-
}
|
|
26336
|
-
});
|
|
26337
26133
|
// src/tools/interactive-bash/constants.ts
|
|
26338
26134
|
var DEFAULT_TIMEOUT_MS4 = 60000;
|
|
26339
26135
|
var BLOCKED_TMUX_SUBCOMMANDS = [
|
|
@@ -27005,13 +26801,12 @@ var builtinTools = {
|
|
|
27005
26801
|
ast_grep_replace,
|
|
27006
26802
|
grep,
|
|
27007
26803
|
glob,
|
|
27008
|
-
slashcommand
|
|
27009
|
-
skill
|
|
26804
|
+
slashcommand
|
|
27010
26805
|
};
|
|
27011
26806
|
// src/features/background-agent/manager.ts
|
|
27012
26807
|
import { existsSync as existsSync37, readdirSync as readdirSync12 } from "fs";
|
|
27013
26808
|
import { join as join44 } from "path";
|
|
27014
|
-
function
|
|
26809
|
+
function getMessageDir5(sessionID) {
|
|
27015
26810
|
if (!existsSync37(MESSAGE_STORAGE))
|
|
27016
26811
|
return null;
|
|
27017
26812
|
const directPath = join44(MESSAGE_STORAGE, sessionID);
|
|
@@ -27255,7 +27050,7 @@ class BackgroundManager {
|
|
|
27255
27050
|
log("[background-agent] Sending notification to parent session:", { parentSessionID: task.parentSessionID });
|
|
27256
27051
|
setTimeout(async () => {
|
|
27257
27052
|
try {
|
|
27258
|
-
const messageDir =
|
|
27053
|
+
const messageDir = getMessageDir5(task.parentSessionID);
|
|
27259
27054
|
const prevMessage = messageDir ? findNearestMessageWithFields(messageDir) : null;
|
|
27260
27055
|
await this.client.session.prompt({
|
|
27261
27056
|
path: { id: task.parentSessionID },
|
|
@@ -27492,7 +27287,8 @@ var ExperimentalConfigSchema = exports_external.object({
|
|
|
27492
27287
|
aggressive_truncation: exports_external.boolean().optional(),
|
|
27493
27288
|
auto_resume: exports_external.boolean().optional(),
|
|
27494
27289
|
preemptive_compaction: exports_external.boolean().optional(),
|
|
27495
|
-
preemptive_compaction_threshold: exports_external.number().min(0.5).max(0.95).optional()
|
|
27290
|
+
preemptive_compaction_threshold: exports_external.number().min(0.5).max(0.95).optional(),
|
|
27291
|
+
truncate_all_tool_outputs: exports_external.boolean().optional()
|
|
27496
27292
|
});
|
|
27497
27293
|
var OhMyOpenCodeConfigSchema = exports_external.object({
|
|
27498
27294
|
$schema: exports_external.string().optional(),
|
|
@@ -27723,7 +27519,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
27723
27519
|
sessionRecovery.setOnRecoveryCompleteCallback(todoContinuationEnforcer.markRecoveryComplete);
|
|
27724
27520
|
}
|
|
27725
27521
|
const commentChecker = isHookEnabled("comment-checker") ? createCommentCheckerHooks() : null;
|
|
27726
|
-
const toolOutputTruncator = isHookEnabled("tool-output-truncator") ? createToolOutputTruncatorHook(ctx) : null;
|
|
27522
|
+
const toolOutputTruncator = isHookEnabled("tool-output-truncator") ? createToolOutputTruncatorHook(ctx, { experimental: pluginConfig.experimental }) : null;
|
|
27727
27523
|
const directoryAgentsInjector = isHookEnabled("directory-agents-injector") ? createDirectoryAgentsInjectorHook(ctx) : null;
|
|
27728
27524
|
const directoryReadmeInjector = isHookEnabled("directory-readme-injector") ? createDirectoryReadmeInjectorHook(ctx) : null;
|
|
27729
27525
|
const emptyTaskResponseDetector = isHookEnabled("empty-task-response-detector") ? createEmptyTaskResponseDetectorHook(ctx) : null;
|