oh-my-opencode 2.4.1 → 2.4.3
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.
|
@@ -9,6 +9,9 @@ interface ToolExecuteOutput {
|
|
|
9
9
|
output: string;
|
|
10
10
|
metadata: unknown;
|
|
11
11
|
}
|
|
12
|
+
interface ToolExecuteBeforeOutput {
|
|
13
|
+
args: unknown;
|
|
14
|
+
}
|
|
12
15
|
interface EventInput {
|
|
13
16
|
event: {
|
|
14
17
|
type: string;
|
|
@@ -16,6 +19,7 @@ interface EventInput {
|
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
export declare function createDirectoryAgentsInjectorHook(ctx: PluginInput): {
|
|
22
|
+
"tool.execute.before": (input: ToolExecuteInput, output: ToolExecuteBeforeOutput) => Promise<void>;
|
|
19
23
|
"tool.execute.after": (input: ToolExecuteInput, output: ToolExecuteOutput) => Promise<void>;
|
|
20
24
|
event: ({ event }: EventInput) => Promise<void>;
|
|
21
25
|
};
|
|
@@ -9,6 +9,9 @@ interface ToolExecuteOutput {
|
|
|
9
9
|
output: string;
|
|
10
10
|
metadata: unknown;
|
|
11
11
|
}
|
|
12
|
+
interface ToolExecuteBeforeOutput {
|
|
13
|
+
args: unknown;
|
|
14
|
+
}
|
|
12
15
|
interface EventInput {
|
|
13
16
|
event: {
|
|
14
17
|
type: string;
|
|
@@ -16,6 +19,7 @@ interface EventInput {
|
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
export declare function createDirectoryReadmeInjectorHook(ctx: PluginInput): {
|
|
22
|
+
"tool.execute.before": (input: ToolExecuteInput, output: ToolExecuteBeforeOutput) => Promise<void>;
|
|
19
23
|
"tool.execute.after": (input: ToolExecuteInput, output: ToolExecuteOutput) => Promise<void>;
|
|
20
24
|
event: ({ event }: EventInput) => Promise<void>;
|
|
21
25
|
};
|
|
@@ -9,6 +9,9 @@ interface ToolExecuteOutput {
|
|
|
9
9
|
output: string;
|
|
10
10
|
metadata: unknown;
|
|
11
11
|
}
|
|
12
|
+
interface ToolExecuteBeforeOutput {
|
|
13
|
+
args: unknown;
|
|
14
|
+
}
|
|
12
15
|
interface EventInput {
|
|
13
16
|
event: {
|
|
14
17
|
type: string;
|
|
@@ -16,6 +19,7 @@ interface EventInput {
|
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
export declare function createRulesInjectorHook(ctx: PluginInput): {
|
|
22
|
+
"tool.execute.before": (input: ToolExecuteInput, output: ToolExecuteBeforeOutput) => Promise<void>;
|
|
19
23
|
"tool.execute.after": (input: ToolExecuteInput, output: ToolExecuteOutput) => Promise<void>;
|
|
20
24
|
event: ({ event }: EventInput) => Promise<void>;
|
|
21
25
|
};
|
package/dist/index.js
CHANGED
|
@@ -3271,8 +3271,7 @@ function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, directory
|
|
|
3271
3271
|
config = { ...config, prompt: config.prompt + envContext };
|
|
3272
3272
|
}
|
|
3273
3273
|
if (override) {
|
|
3274
|
-
|
|
3275
|
-
config = mergeAgentConfig(config, restOverride);
|
|
3274
|
+
config = mergeAgentConfig(config, override);
|
|
3276
3275
|
}
|
|
3277
3276
|
result[name] = config;
|
|
3278
3277
|
}
|
|
@@ -4921,18 +4920,19 @@ function clearInjectedPaths(sessionID) {
|
|
|
4921
4920
|
// src/hooks/directory-agents-injector/index.ts
|
|
4922
4921
|
function createDirectoryAgentsInjectorHook(ctx) {
|
|
4923
4922
|
const sessionCaches = new Map;
|
|
4923
|
+
const pendingBatchReads = new Map;
|
|
4924
4924
|
function getSessionCache(sessionID) {
|
|
4925
4925
|
if (!sessionCaches.has(sessionID)) {
|
|
4926
4926
|
sessionCaches.set(sessionID, loadInjectedPaths(sessionID));
|
|
4927
4927
|
}
|
|
4928
4928
|
return sessionCaches.get(sessionID);
|
|
4929
4929
|
}
|
|
4930
|
-
function resolveFilePath2(
|
|
4931
|
-
if (!
|
|
4930
|
+
function resolveFilePath2(path4) {
|
|
4931
|
+
if (!path4)
|
|
4932
4932
|
return null;
|
|
4933
|
-
if (
|
|
4934
|
-
return
|
|
4935
|
-
return resolve2(ctx.directory,
|
|
4933
|
+
if (path4.startsWith("/"))
|
|
4934
|
+
return path4;
|
|
4935
|
+
return resolve2(ctx.directory, path4);
|
|
4936
4936
|
}
|
|
4937
4937
|
function findAgentsMdUp(startDir) {
|
|
4938
4938
|
const found = [];
|
|
@@ -4953,35 +4953,59 @@ function createDirectoryAgentsInjectorHook(ctx) {
|
|
|
4953
4953
|
}
|
|
4954
4954
|
return found.reverse();
|
|
4955
4955
|
}
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
const filePath = resolveFilePath2(output.title);
|
|
4960
|
-
if (!filePath)
|
|
4956
|
+
function processFilePathForInjection(filePath, sessionID, output) {
|
|
4957
|
+
const resolved = resolveFilePath2(filePath);
|
|
4958
|
+
if (!resolved)
|
|
4961
4959
|
return;
|
|
4962
|
-
const dir = dirname2(
|
|
4963
|
-
const cache = getSessionCache(
|
|
4960
|
+
const dir = dirname2(resolved);
|
|
4961
|
+
const cache = getSessionCache(sessionID);
|
|
4964
4962
|
const agentsPaths = findAgentsMdUp(dir);
|
|
4965
|
-
const toInject = [];
|
|
4966
4963
|
for (const agentsPath of agentsPaths) {
|
|
4967
4964
|
const agentsDir = dirname2(agentsPath);
|
|
4968
4965
|
if (cache.has(agentsDir))
|
|
4969
4966
|
continue;
|
|
4970
4967
|
try {
|
|
4971
4968
|
const content = readFileSync5(agentsPath, "utf-8");
|
|
4972
|
-
|
|
4969
|
+
output.output += `
|
|
4970
|
+
|
|
4971
|
+
[Directory Context: ${agentsPath}]
|
|
4972
|
+
${content}`;
|
|
4973
4973
|
cache.add(agentsDir);
|
|
4974
4974
|
} catch {}
|
|
4975
4975
|
}
|
|
4976
|
-
|
|
4976
|
+
saveInjectedPaths(sessionID, cache);
|
|
4977
|
+
}
|
|
4978
|
+
const toolExecuteBefore = async (input, output) => {
|
|
4979
|
+
if (input.tool.toLowerCase() !== "batch")
|
|
4977
4980
|
return;
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4981
|
+
const args = output.args;
|
|
4982
|
+
if (!args?.tool_calls)
|
|
4983
|
+
return;
|
|
4984
|
+
const readFilePaths = [];
|
|
4985
|
+
for (const call of args.tool_calls) {
|
|
4986
|
+
if (call.tool.toLowerCase() === "read" && call.parameters?.filePath) {
|
|
4987
|
+
readFilePaths.push(call.parameters.filePath);
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
if (readFilePaths.length > 0) {
|
|
4991
|
+
pendingBatchReads.set(input.callID, readFilePaths);
|
|
4992
|
+
}
|
|
4993
|
+
};
|
|
4994
|
+
const toolExecuteAfter = async (input, output) => {
|
|
4995
|
+
const toolName = input.tool.toLowerCase();
|
|
4996
|
+
if (toolName === "read") {
|
|
4997
|
+
processFilePathForInjection(output.title, input.sessionID, output);
|
|
4998
|
+
return;
|
|
4999
|
+
}
|
|
5000
|
+
if (toolName === "batch") {
|
|
5001
|
+
const filePaths = pendingBatchReads.get(input.callID);
|
|
5002
|
+
if (filePaths) {
|
|
5003
|
+
for (const filePath of filePaths) {
|
|
5004
|
+
processFilePathForInjection(filePath, input.sessionID, output);
|
|
5005
|
+
}
|
|
5006
|
+
pendingBatchReads.delete(input.callID);
|
|
5007
|
+
}
|
|
4983
5008
|
}
|
|
4984
|
-
saveInjectedPaths(input.sessionID, cache);
|
|
4985
5009
|
};
|
|
4986
5010
|
const eventHandler = async ({ event }) => {
|
|
4987
5011
|
const props = event.properties;
|
|
@@ -5001,6 +5025,7 @@ ${content}`;
|
|
|
5001
5025
|
}
|
|
5002
5026
|
};
|
|
5003
5027
|
return {
|
|
5028
|
+
"tool.execute.before": toolExecuteBefore,
|
|
5004
5029
|
"tool.execute.after": toolExecuteAfter,
|
|
5005
5030
|
event: eventHandler
|
|
5006
5031
|
};
|
|
@@ -5062,18 +5087,19 @@ function clearInjectedPaths2(sessionID) {
|
|
|
5062
5087
|
// src/hooks/directory-readme-injector/index.ts
|
|
5063
5088
|
function createDirectoryReadmeInjectorHook(ctx) {
|
|
5064
5089
|
const sessionCaches = new Map;
|
|
5090
|
+
const pendingBatchReads = new Map;
|
|
5065
5091
|
function getSessionCache(sessionID) {
|
|
5066
5092
|
if (!sessionCaches.has(sessionID)) {
|
|
5067
5093
|
sessionCaches.set(sessionID, loadInjectedPaths2(sessionID));
|
|
5068
5094
|
}
|
|
5069
5095
|
return sessionCaches.get(sessionID);
|
|
5070
5096
|
}
|
|
5071
|
-
function resolveFilePath2(
|
|
5072
|
-
if (!
|
|
5097
|
+
function resolveFilePath2(path4) {
|
|
5098
|
+
if (!path4)
|
|
5073
5099
|
return null;
|
|
5074
|
-
if (
|
|
5075
|
-
return
|
|
5076
|
-
return resolve3(ctx.directory,
|
|
5100
|
+
if (path4.startsWith("/"))
|
|
5101
|
+
return path4;
|
|
5102
|
+
return resolve3(ctx.directory, path4);
|
|
5077
5103
|
}
|
|
5078
5104
|
function findReadmeMdUp(startDir) {
|
|
5079
5105
|
const found = [];
|
|
@@ -5094,35 +5120,59 @@ function createDirectoryReadmeInjectorHook(ctx) {
|
|
|
5094
5120
|
}
|
|
5095
5121
|
return found.reverse();
|
|
5096
5122
|
}
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
const filePath = resolveFilePath2(output.title);
|
|
5101
|
-
if (!filePath)
|
|
5123
|
+
function processFilePathForInjection(filePath, sessionID, output) {
|
|
5124
|
+
const resolved = resolveFilePath2(filePath);
|
|
5125
|
+
if (!resolved)
|
|
5102
5126
|
return;
|
|
5103
|
-
const dir = dirname3(
|
|
5104
|
-
const cache = getSessionCache(
|
|
5127
|
+
const dir = dirname3(resolved);
|
|
5128
|
+
const cache = getSessionCache(sessionID);
|
|
5105
5129
|
const readmePaths = findReadmeMdUp(dir);
|
|
5106
|
-
const toInject = [];
|
|
5107
5130
|
for (const readmePath of readmePaths) {
|
|
5108
5131
|
const readmeDir = dirname3(readmePath);
|
|
5109
5132
|
if (cache.has(readmeDir))
|
|
5110
5133
|
continue;
|
|
5111
5134
|
try {
|
|
5112
5135
|
const content = readFileSync7(readmePath, "utf-8");
|
|
5113
|
-
|
|
5136
|
+
output.output += `
|
|
5137
|
+
|
|
5138
|
+
[Project README: ${readmePath}]
|
|
5139
|
+
${content}`;
|
|
5114
5140
|
cache.add(readmeDir);
|
|
5115
5141
|
} catch {}
|
|
5116
5142
|
}
|
|
5117
|
-
|
|
5143
|
+
saveInjectedPaths2(sessionID, cache);
|
|
5144
|
+
}
|
|
5145
|
+
const toolExecuteBefore = async (input, output) => {
|
|
5146
|
+
if (input.tool.toLowerCase() !== "batch")
|
|
5118
5147
|
return;
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5148
|
+
const args = output.args;
|
|
5149
|
+
if (!args?.tool_calls)
|
|
5150
|
+
return;
|
|
5151
|
+
const readFilePaths = [];
|
|
5152
|
+
for (const call of args.tool_calls) {
|
|
5153
|
+
if (call.tool.toLowerCase() === "read" && call.parameters?.filePath) {
|
|
5154
|
+
readFilePaths.push(call.parameters.filePath);
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
if (readFilePaths.length > 0) {
|
|
5158
|
+
pendingBatchReads.set(input.callID, readFilePaths);
|
|
5159
|
+
}
|
|
5160
|
+
};
|
|
5161
|
+
const toolExecuteAfter = async (input, output) => {
|
|
5162
|
+
const toolName = input.tool.toLowerCase();
|
|
5163
|
+
if (toolName === "read") {
|
|
5164
|
+
processFilePathForInjection(output.title, input.sessionID, output);
|
|
5165
|
+
return;
|
|
5166
|
+
}
|
|
5167
|
+
if (toolName === "batch") {
|
|
5168
|
+
const filePaths = pendingBatchReads.get(input.callID);
|
|
5169
|
+
if (filePaths) {
|
|
5170
|
+
for (const filePath of filePaths) {
|
|
5171
|
+
processFilePathForInjection(filePath, input.sessionID, output);
|
|
5172
|
+
}
|
|
5173
|
+
pendingBatchReads.delete(input.callID);
|
|
5174
|
+
}
|
|
5124
5175
|
}
|
|
5125
|
-
saveInjectedPaths2(input.sessionID, cache);
|
|
5126
5176
|
};
|
|
5127
5177
|
const eventHandler = async ({ event }) => {
|
|
5128
5178
|
const props = event.properties;
|
|
@@ -5142,6 +5192,7 @@ ${content}`;
|
|
|
5142
5192
|
}
|
|
5143
5193
|
};
|
|
5144
5194
|
return {
|
|
5195
|
+
"tool.execute.before": toolExecuteBefore,
|
|
5145
5196
|
"tool.execute.after": toolExecuteAfter,
|
|
5146
5197
|
event: eventHandler
|
|
5147
5198
|
};
|
|
@@ -6100,11 +6151,22 @@ function createPreemptiveCompactionHook(ctx, options) {
|
|
|
6100
6151
|
await ctx.client.tui.showToast({
|
|
6101
6152
|
body: {
|
|
6102
6153
|
title: "Compaction Complete",
|
|
6103
|
-
message: "Session compacted successfully",
|
|
6154
|
+
message: "Session compacted successfully. Resuming...",
|
|
6104
6155
|
variant: "success",
|
|
6105
6156
|
duration: 2000
|
|
6106
6157
|
}
|
|
6107
6158
|
}).catch(() => {});
|
|
6159
|
+
state2.compactionInProgress.delete(sessionID);
|
|
6160
|
+
setTimeout(async () => {
|
|
6161
|
+
try {
|
|
6162
|
+
await ctx.client.session.promptAsync({
|
|
6163
|
+
path: { id: sessionID },
|
|
6164
|
+
body: { parts: [{ type: "text", text: "Continue" }] },
|
|
6165
|
+
query: { directory: ctx.directory }
|
|
6166
|
+
});
|
|
6167
|
+
} catch {}
|
|
6168
|
+
}, 500);
|
|
6169
|
+
return;
|
|
6108
6170
|
} catch (err) {
|
|
6109
6171
|
log("[preemptive-compaction] compaction failed", { sessionID, error: err });
|
|
6110
6172
|
} finally {
|
|
@@ -7740,29 +7802,28 @@ function clearInjectedRules(sessionID) {
|
|
|
7740
7802
|
var TRACKED_TOOLS = ["read", "write", "edit", "multiedit"];
|
|
7741
7803
|
function createRulesInjectorHook(ctx) {
|
|
7742
7804
|
const sessionCaches = new Map;
|
|
7805
|
+
const pendingBatchFiles = new Map;
|
|
7743
7806
|
function getSessionCache(sessionID) {
|
|
7744
7807
|
if (!sessionCaches.has(sessionID)) {
|
|
7745
7808
|
sessionCaches.set(sessionID, loadInjectedRules(sessionID));
|
|
7746
7809
|
}
|
|
7747
7810
|
return sessionCaches.get(sessionID);
|
|
7748
7811
|
}
|
|
7749
|
-
function resolveFilePath2(
|
|
7750
|
-
if (!
|
|
7812
|
+
function resolveFilePath2(path4) {
|
|
7813
|
+
if (!path4)
|
|
7751
7814
|
return null;
|
|
7752
|
-
if (
|
|
7753
|
-
return
|
|
7754
|
-
return resolve4(ctx.directory,
|
|
7815
|
+
if (path4.startsWith("/"))
|
|
7816
|
+
return path4;
|
|
7817
|
+
return resolve4(ctx.directory, path4);
|
|
7755
7818
|
}
|
|
7756
|
-
|
|
7757
|
-
|
|
7819
|
+
function processFilePathForInjection(filePath, sessionID, output) {
|
|
7820
|
+
const resolved = resolveFilePath2(filePath);
|
|
7821
|
+
if (!resolved)
|
|
7758
7822
|
return;
|
|
7759
|
-
const
|
|
7760
|
-
|
|
7761
|
-
return;
|
|
7762
|
-
const projectRoot = findProjectRoot(filePath);
|
|
7763
|
-
const cache2 = getSessionCache(input.sessionID);
|
|
7823
|
+
const projectRoot = findProjectRoot(resolved);
|
|
7824
|
+
const cache2 = getSessionCache(sessionID);
|
|
7764
7825
|
const home = homedir10();
|
|
7765
|
-
const ruleFileCandidates = findRuleFiles(projectRoot, home,
|
|
7826
|
+
const ruleFileCandidates = findRuleFiles(projectRoot, home, resolved);
|
|
7766
7827
|
const toInject = [];
|
|
7767
7828
|
for (const candidate of ruleFileCandidates) {
|
|
7768
7829
|
if (isDuplicateByRealPath(candidate.realPath, cache2.realPaths))
|
|
@@ -7770,7 +7831,7 @@ function createRulesInjectorHook(ctx) {
|
|
|
7770
7831
|
try {
|
|
7771
7832
|
const rawContent = readFileSync10(candidate.path, "utf-8");
|
|
7772
7833
|
const { metadata, body } = parseRuleFrontmatter(rawContent);
|
|
7773
|
-
const matchResult = shouldApplyRule(metadata,
|
|
7834
|
+
const matchResult = shouldApplyRule(metadata, resolved, projectRoot);
|
|
7774
7835
|
if (!matchResult.applies)
|
|
7775
7836
|
continue;
|
|
7776
7837
|
const contentHash = createContentHash(body);
|
|
@@ -7797,7 +7858,46 @@ function createRulesInjectorHook(ctx) {
|
|
|
7797
7858
|
[Match: ${rule.matchReason}]
|
|
7798
7859
|
${rule.content}`;
|
|
7799
7860
|
}
|
|
7800
|
-
saveInjectedRules(
|
|
7861
|
+
saveInjectedRules(sessionID, cache2);
|
|
7862
|
+
}
|
|
7863
|
+
function extractFilePathFromToolCall(call) {
|
|
7864
|
+
const params = call.parameters;
|
|
7865
|
+
return params?.filePath ?? params?.file_path ?? params?.path;
|
|
7866
|
+
}
|
|
7867
|
+
const toolExecuteBefore = async (input, output) => {
|
|
7868
|
+
if (input.tool.toLowerCase() !== "batch")
|
|
7869
|
+
return;
|
|
7870
|
+
const args = output.args;
|
|
7871
|
+
if (!args?.tool_calls)
|
|
7872
|
+
return;
|
|
7873
|
+
const filePaths = [];
|
|
7874
|
+
for (const call of args.tool_calls) {
|
|
7875
|
+
if (TRACKED_TOOLS.includes(call.tool.toLowerCase())) {
|
|
7876
|
+
const filePath = extractFilePathFromToolCall(call);
|
|
7877
|
+
if (filePath) {
|
|
7878
|
+
filePaths.push(filePath);
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7881
|
+
}
|
|
7882
|
+
if (filePaths.length > 0) {
|
|
7883
|
+
pendingBatchFiles.set(input.callID, filePaths);
|
|
7884
|
+
}
|
|
7885
|
+
};
|
|
7886
|
+
const toolExecuteAfter = async (input, output) => {
|
|
7887
|
+
const toolName = input.tool.toLowerCase();
|
|
7888
|
+
if (TRACKED_TOOLS.includes(toolName)) {
|
|
7889
|
+
processFilePathForInjection(output.title, input.sessionID, output);
|
|
7890
|
+
return;
|
|
7891
|
+
}
|
|
7892
|
+
if (toolName === "batch") {
|
|
7893
|
+
const filePaths = pendingBatchFiles.get(input.callID);
|
|
7894
|
+
if (filePaths) {
|
|
7895
|
+
for (const filePath of filePaths) {
|
|
7896
|
+
processFilePathForInjection(filePath, input.sessionID, output);
|
|
7897
|
+
}
|
|
7898
|
+
pendingBatchFiles.delete(input.callID);
|
|
7899
|
+
}
|
|
7900
|
+
}
|
|
7801
7901
|
};
|
|
7802
7902
|
const eventHandler = async ({ event }) => {
|
|
7803
7903
|
const props = event.properties;
|
|
@@ -7817,6 +7917,7 @@ ${rule.content}`;
|
|
|
7817
7917
|
}
|
|
7818
7918
|
};
|
|
7819
7919
|
return {
|
|
7920
|
+
"tool.execute.before": toolExecuteBefore,
|
|
7820
7921
|
"tool.execute.after": toolExecuteAfter,
|
|
7821
7922
|
event: eventHandler
|
|
7822
7923
|
};
|
|
@@ -27826,6 +27927,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
27826
27927
|
await claudeCodeHooks["tool.execute.before"](input, output);
|
|
27827
27928
|
await nonInteractiveEnv?.["tool.execute.before"](input, output);
|
|
27828
27929
|
await commentChecker?.["tool.execute.before"](input, output);
|
|
27930
|
+
await directoryAgentsInjector?.["tool.execute.before"]?.(input, output);
|
|
27931
|
+
await directoryReadmeInjector?.["tool.execute.before"]?.(input, output);
|
|
27932
|
+
await rulesInjector?.["tool.execute.before"]?.(input, output);
|
|
27829
27933
|
if (input.tool === "task") {
|
|
27830
27934
|
const args = output.args;
|
|
27831
27935
|
const subagentType = args.subagent_type;
|