oh-my-opencode 3.5.0 → 3.5.2
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/cli/index.js +25 -21
- package/dist/config/schema/categories.d.ts +2 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker/pinned-version-updater.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +1 -1
- package/dist/index.js +171 -91
- package/dist/shared/merge-categories.d.ts +6 -0
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -8326,10 +8326,9 @@ var init_cached_version = __esm(() => {
|
|
|
8326
8326
|
|
|
8327
8327
|
// src/hooks/auto-update-checker/checker/pinned-version-updater.ts
|
|
8328
8328
|
import * as fs9 from "fs";
|
|
8329
|
-
function
|
|
8329
|
+
function replacePluginEntry(configPath, oldEntry, newEntry) {
|
|
8330
8330
|
try {
|
|
8331
8331
|
const content = fs9.readFileSync(configPath, "utf-8");
|
|
8332
|
-
const newEntry = `${PACKAGE_NAME3}@${newVersion}`;
|
|
8333
8332
|
const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
|
|
8334
8333
|
if (!pluginMatch || pluginMatch.index === undefined) {
|
|
8335
8334
|
log(`[auto-update-checker] No "plugin" array found in ${configPath}`);
|
|
@@ -8368,6 +8367,10 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
|
|
|
8368
8367
|
return false;
|
|
8369
8368
|
}
|
|
8370
8369
|
}
|
|
8370
|
+
function revertPinnedVersion(configPath, failedVersion, originalEntry) {
|
|
8371
|
+
const failedEntry = `${PACKAGE_NAME3}@${failedVersion}`;
|
|
8372
|
+
return replacePluginEntry(configPath, failedEntry, originalEntry);
|
|
8373
|
+
}
|
|
8371
8374
|
var init_pinned_version_updater = __esm(() => {
|
|
8372
8375
|
init_logger();
|
|
8373
8376
|
init_constants3();
|
|
@@ -8642,23 +8645,23 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
|
|
|
8642
8645
|
return;
|
|
8643
8646
|
}
|
|
8644
8647
|
if (pluginInfo.isPinned) {
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
log("[auto-update-checker] Failed to update pinned version in config");
|
|
8649
|
-
return;
|
|
8650
|
-
}
|
|
8651
|
-
log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME3}@${latestVersion}`);
|
|
8648
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8649
|
+
log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
|
|
8650
|
+
return;
|
|
8652
8651
|
}
|
|
8653
8652
|
invalidatePackage(PACKAGE_NAME3);
|
|
8654
8653
|
const installSuccess = await runBunInstallSafe();
|
|
8655
8654
|
if (installSuccess) {
|
|
8656
8655
|
await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
|
|
8657
8656
|
log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
|
|
8658
|
-
|
|
8659
|
-
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8660
|
-
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
8657
|
+
return;
|
|
8661
8658
|
}
|
|
8659
|
+
if (pluginInfo.isPinned) {
|
|
8660
|
+
revertPinnedVersion(pluginInfo.configPath, latestVersion, pluginInfo.entry);
|
|
8661
|
+
log("[auto-update-checker] Config reverted due to install failure");
|
|
8662
|
+
}
|
|
8663
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8664
|
+
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
8662
8665
|
}
|
|
8663
8666
|
var init_background_update_check = __esm(() => {
|
|
8664
8667
|
init_config_manager();
|
|
@@ -8867,7 +8870,7 @@ var {
|
|
|
8867
8870
|
// package.json
|
|
8868
8871
|
var package_default = {
|
|
8869
8872
|
name: "oh-my-opencode",
|
|
8870
|
-
version: "3.5.
|
|
8873
|
+
version: "3.5.2",
|
|
8871
8874
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
8872
8875
|
main: "dist/index.js",
|
|
8873
8876
|
types: "dist/index.d.ts",
|
|
@@ -8941,13 +8944,13 @@ var package_default = {
|
|
|
8941
8944
|
typescript: "^5.7.3"
|
|
8942
8945
|
},
|
|
8943
8946
|
optionalDependencies: {
|
|
8944
|
-
"oh-my-opencode-darwin-arm64": "3.5.
|
|
8945
|
-
"oh-my-opencode-darwin-x64": "3.5.
|
|
8946
|
-
"oh-my-opencode-linux-arm64": "3.5.
|
|
8947
|
-
"oh-my-opencode-linux-arm64-musl": "3.5.
|
|
8948
|
-
"oh-my-opencode-linux-x64": "3.5.
|
|
8949
|
-
"oh-my-opencode-linux-x64-musl": "3.5.
|
|
8950
|
-
"oh-my-opencode-windows-x64": "3.5.
|
|
8947
|
+
"oh-my-opencode-darwin-arm64": "3.5.2",
|
|
8948
|
+
"oh-my-opencode-darwin-x64": "3.5.2",
|
|
8949
|
+
"oh-my-opencode-linux-arm64": "3.5.2",
|
|
8950
|
+
"oh-my-opencode-linux-arm64-musl": "3.5.2",
|
|
8951
|
+
"oh-my-opencode-linux-x64": "3.5.2",
|
|
8952
|
+
"oh-my-opencode-linux-x64-musl": "3.5.2",
|
|
8953
|
+
"oh-my-opencode-windows-x64": "3.5.2"
|
|
8951
8954
|
},
|
|
8952
8955
|
trustedDependencies: [
|
|
8953
8956
|
"@ast-grep/cli",
|
|
@@ -22716,7 +22719,8 @@ var CategoryConfigSchema = exports_external.object({
|
|
|
22716
22719
|
textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
|
|
22717
22720
|
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
|
|
22718
22721
|
prompt_append: exports_external.string().optional(),
|
|
22719
|
-
is_unstable_agent: exports_external.boolean().optional()
|
|
22722
|
+
is_unstable_agent: exports_external.boolean().optional(),
|
|
22723
|
+
disable: exports_external.boolean().optional()
|
|
22720
22724
|
});
|
|
22721
22725
|
var BuiltinCategoryNameSchema = exports_external.enum([
|
|
22722
22726
|
"visual-engineering",
|
|
@@ -27,6 +27,7 @@ export declare const CategoryConfigSchema: z.ZodObject<{
|
|
|
27
27
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
28
28
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
29
29
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
30
31
|
}, z.core.$strip>;
|
|
31
32
|
export declare const BuiltinCategoryNameSchema: z.ZodEnum<{
|
|
32
33
|
"visual-engineering": "visual-engineering";
|
|
@@ -66,6 +67,7 @@ export declare const CategoriesConfigSchema: z.ZodRecord<z.ZodString, z.ZodObjec
|
|
|
66
67
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
67
68
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
68
69
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
70
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
69
71
|
}, z.core.$strip>>;
|
|
70
72
|
export type CategoryConfig = z.infer<typeof CategoryConfigSchema>;
|
|
71
73
|
export type CategoriesConfig = z.infer<typeof CategoriesConfigSchema>;
|
|
@@ -1158,6 +1158,7 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
1158
1158
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
1159
1159
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
1160
1160
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
1161
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
1161
1162
|
}, z.core.$strip>>>;
|
|
1162
1163
|
claude_code: z.ZodOptional<z.ZodObject<{
|
|
1163
1164
|
mcp: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -3,6 +3,6 @@ export { getLocalDevVersion } from "./checker/local-dev-version";
|
|
|
3
3
|
export { findPluginEntry } from "./checker/plugin-entry";
|
|
4
4
|
export type { PluginEntryInfo } from "./checker/plugin-entry";
|
|
5
5
|
export { getCachedVersion } from "./checker/cached-version";
|
|
6
|
-
export { updatePinnedVersion } from "./checker/pinned-version-updater";
|
|
6
|
+
export { updatePinnedVersion, revertPinnedVersion } from "./checker/pinned-version-updater";
|
|
7
7
|
export { getLatestVersion } from "./checker/latest-version";
|
|
8
8
|
export { checkForUpdate } from "./checker/check-for-update";
|
package/dist/index.js
CHANGED
|
@@ -12252,7 +12252,14 @@ function readBoulderState(directory) {
|
|
|
12252
12252
|
}
|
|
12253
12253
|
try {
|
|
12254
12254
|
const content = readFileSync(filePath, "utf-8");
|
|
12255
|
-
|
|
12255
|
+
const parsed = JSON.parse(content);
|
|
12256
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12257
|
+
return null;
|
|
12258
|
+
}
|
|
12259
|
+
if (!Array.isArray(parsed.session_ids)) {
|
|
12260
|
+
parsed.session_ids = [];
|
|
12261
|
+
}
|
|
12262
|
+
return parsed;
|
|
12256
12263
|
} catch {
|
|
12257
12264
|
return null;
|
|
12258
12265
|
}
|
|
@@ -12274,7 +12281,10 @@ function appendSessionId(directory, sessionId) {
|
|
|
12274
12281
|
const state = readBoulderState(directory);
|
|
12275
12282
|
if (!state)
|
|
12276
12283
|
return null;
|
|
12277
|
-
if (!state.session_ids
|
|
12284
|
+
if (!state.session_ids?.includes(sessionId)) {
|
|
12285
|
+
if (!Array.isArray(state.session_ids)) {
|
|
12286
|
+
state.session_ids = [];
|
|
12287
|
+
}
|
|
12278
12288
|
state.session_ids.push(sessionId);
|
|
12279
12289
|
if (writeBoulderState(directory, state)) {
|
|
12280
12290
|
return state;
|
|
@@ -26785,7 +26795,7 @@ function createCommentCheckerHooks(config2) {
|
|
|
26785
26795
|
"tool.execute.after": async (input, output) => {
|
|
26786
26796
|
debugLog3("tool.execute.after:", { tool: input.tool, callID: input.callID });
|
|
26787
26797
|
const toolLower = input.tool.toLowerCase();
|
|
26788
|
-
const outputLower = output.output.toLowerCase();
|
|
26798
|
+
const outputLower = (output.output ?? "").toLowerCase();
|
|
26789
26799
|
const isToolFailure = outputLower.includes("error:") || outputLower.includes("failed to") || outputLower.includes("could not") || outputLower.startsWith("error");
|
|
26790
26800
|
if (isToolFailure) {
|
|
26791
26801
|
debugLog3("skipping due to tool failure in output");
|
|
@@ -34207,6 +34217,63 @@ async function enforceMainPaneWidth(mainPaneId, windowWidth) {
|
|
|
34207
34217
|
}
|
|
34208
34218
|
// src/shared/model-suggestion-retry.ts
|
|
34209
34219
|
init_logger();
|
|
34220
|
+
function extractMessage(error45) {
|
|
34221
|
+
if (typeof error45 === "string")
|
|
34222
|
+
return error45;
|
|
34223
|
+
if (error45 instanceof Error)
|
|
34224
|
+
return error45.message;
|
|
34225
|
+
if (typeof error45 === "object" && error45 !== null) {
|
|
34226
|
+
const obj = error45;
|
|
34227
|
+
if (typeof obj.message === "string")
|
|
34228
|
+
return obj.message;
|
|
34229
|
+
try {
|
|
34230
|
+
return JSON.stringify(error45);
|
|
34231
|
+
} catch {
|
|
34232
|
+
return "";
|
|
34233
|
+
}
|
|
34234
|
+
}
|
|
34235
|
+
return String(error45);
|
|
34236
|
+
}
|
|
34237
|
+
function parseModelSuggestion(error45) {
|
|
34238
|
+
if (!error45)
|
|
34239
|
+
return null;
|
|
34240
|
+
if (typeof error45 === "object") {
|
|
34241
|
+
const errObj = error45;
|
|
34242
|
+
if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
|
|
34243
|
+
const data = errObj.data;
|
|
34244
|
+
const suggestions = data.suggestions;
|
|
34245
|
+
if (Array.isArray(suggestions) && suggestions.length > 0 && typeof suggestions[0] === "string") {
|
|
34246
|
+
return {
|
|
34247
|
+
providerID: String(data.providerID ?? ""),
|
|
34248
|
+
modelID: String(data.modelID ?? ""),
|
|
34249
|
+
suggestion: suggestions[0]
|
|
34250
|
+
};
|
|
34251
|
+
}
|
|
34252
|
+
return null;
|
|
34253
|
+
}
|
|
34254
|
+
for (const key of ["data", "error", "cause"]) {
|
|
34255
|
+
const nested = errObj[key];
|
|
34256
|
+
if (nested && typeof nested === "object") {
|
|
34257
|
+
const result = parseModelSuggestion(nested);
|
|
34258
|
+
if (result)
|
|
34259
|
+
return result;
|
|
34260
|
+
}
|
|
34261
|
+
}
|
|
34262
|
+
}
|
|
34263
|
+
const message = extractMessage(error45);
|
|
34264
|
+
if (!message)
|
|
34265
|
+
return null;
|
|
34266
|
+
const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.\s]+)/i);
|
|
34267
|
+
const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
|
|
34268
|
+
if (modelMatch && suggestionMatch) {
|
|
34269
|
+
return {
|
|
34270
|
+
providerID: modelMatch[1].trim(),
|
|
34271
|
+
modelID: modelMatch[2].trim(),
|
|
34272
|
+
suggestion: suggestionMatch[1].trim()
|
|
34273
|
+
};
|
|
34274
|
+
}
|
|
34275
|
+
return null;
|
|
34276
|
+
}
|
|
34210
34277
|
async function promptWithModelSuggestionRetry(client, args) {
|
|
34211
34278
|
const promptPromise = client.session.promptAsync(args);
|
|
34212
34279
|
let timeoutID = null;
|
|
@@ -34222,6 +34289,30 @@ async function promptWithModelSuggestionRetry(client, args) {
|
|
|
34222
34289
|
clearTimeout(timeoutID);
|
|
34223
34290
|
}
|
|
34224
34291
|
}
|
|
34292
|
+
async function promptSyncWithModelSuggestionRetry(client, args) {
|
|
34293
|
+
try {
|
|
34294
|
+
await client.session.prompt(args);
|
|
34295
|
+
} catch (error45) {
|
|
34296
|
+
const suggestion = parseModelSuggestion(error45);
|
|
34297
|
+
if (!suggestion || !args.body.model) {
|
|
34298
|
+
throw error45;
|
|
34299
|
+
}
|
|
34300
|
+
log("[model-suggestion-retry] Model not found, retrying with suggestion", {
|
|
34301
|
+
original: `${suggestion.providerID}/${suggestion.modelID}`,
|
|
34302
|
+
suggested: suggestion.suggestion
|
|
34303
|
+
});
|
|
34304
|
+
await client.session.prompt({
|
|
34305
|
+
...args,
|
|
34306
|
+
body: {
|
|
34307
|
+
...args.body,
|
|
34308
|
+
model: {
|
|
34309
|
+
providerID: suggestion.providerID,
|
|
34310
|
+
modelID: suggestion.suggestion
|
|
34311
|
+
}
|
|
34312
|
+
}
|
|
34313
|
+
});
|
|
34314
|
+
}
|
|
34315
|
+
}
|
|
34225
34316
|
// src/shared/opencode-server-auth.ts
|
|
34226
34317
|
function getServerBasicAuthHeader() {
|
|
34227
34318
|
const password = process.env.OPENCODE_SERVER_PASSWORD;
|
|
@@ -36308,10 +36399,9 @@ function getCachedVersion() {
|
|
|
36308
36399
|
// src/hooks/auto-update-checker/checker/pinned-version-updater.ts
|
|
36309
36400
|
init_logger();
|
|
36310
36401
|
import * as fs12 from "fs";
|
|
36311
|
-
function
|
|
36402
|
+
function replacePluginEntry(configPath, oldEntry, newEntry) {
|
|
36312
36403
|
try {
|
|
36313
36404
|
const content = fs12.readFileSync(configPath, "utf-8");
|
|
36314
|
-
const newEntry = `${PACKAGE_NAME}@${newVersion}`;
|
|
36315
36405
|
const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
|
|
36316
36406
|
if (!pluginMatch || pluginMatch.index === undefined) {
|
|
36317
36407
|
log(`[auto-update-checker] No "plugin" array found in ${configPath}`);
|
|
@@ -36350,6 +36440,10 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
|
|
|
36350
36440
|
return false;
|
|
36351
36441
|
}
|
|
36352
36442
|
}
|
|
36443
|
+
function revertPinnedVersion(configPath, failedVersion, originalEntry) {
|
|
36444
|
+
const failedEntry = `${PACKAGE_NAME}@${failedVersion}`;
|
|
36445
|
+
return replacePluginEntry(configPath, failedEntry, originalEntry);
|
|
36446
|
+
}
|
|
36353
36447
|
// src/hooks/auto-update-checker/checker/latest-version.ts
|
|
36354
36448
|
async function getLatestVersion(channel = "latest") {
|
|
36355
36449
|
const controller = new AbortController;
|
|
@@ -36592,23 +36686,23 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
|
|
|
36592
36686
|
return;
|
|
36593
36687
|
}
|
|
36594
36688
|
if (pluginInfo.isPinned) {
|
|
36595
|
-
|
|
36596
|
-
|
|
36597
|
-
|
|
36598
|
-
log("[auto-update-checker] Failed to update pinned version in config");
|
|
36599
|
-
return;
|
|
36600
|
-
}
|
|
36601
|
-
log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME}@${latestVersion}`);
|
|
36689
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
36690
|
+
log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
|
|
36691
|
+
return;
|
|
36602
36692
|
}
|
|
36603
36693
|
invalidatePackage(PACKAGE_NAME);
|
|
36604
36694
|
const installSuccess = await runBunInstallSafe();
|
|
36605
36695
|
if (installSuccess) {
|
|
36606
36696
|
await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
|
|
36607
36697
|
log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
|
|
36608
|
-
|
|
36609
|
-
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
36610
|
-
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
36698
|
+
return;
|
|
36611
36699
|
}
|
|
36700
|
+
if (pluginInfo.isPinned) {
|
|
36701
|
+
revertPinnedVersion(pluginInfo.configPath, latestVersion, pluginInfo.entry);
|
|
36702
|
+
log("[auto-update-checker] Config reverted due to install failure");
|
|
36703
|
+
}
|
|
36704
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
36705
|
+
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
36612
36706
|
}
|
|
36613
36707
|
|
|
36614
36708
|
// src/hooks/auto-update-checker/hook/config-errors-toast.ts
|
|
@@ -42751,7 +42845,7 @@ function createEditErrorRecoveryHook(_ctx) {
|
|
|
42751
42845
|
"tool.execute.after": async (input, output) => {
|
|
42752
42846
|
if (input.tool.toLowerCase() !== "edit")
|
|
42753
42847
|
return;
|
|
42754
|
-
const outputLower = output.output.toLowerCase();
|
|
42848
|
+
const outputLower = (output.output ?? "").toLowerCase();
|
|
42755
42849
|
const hasEditError = EDIT_ERROR_PATTERNS.some((pattern) => outputLower.includes(pattern.toLowerCase()));
|
|
42756
42850
|
if (hasEditError) {
|
|
42757
42851
|
output.output += `
|
|
@@ -42884,7 +42978,7 @@ function getAgentFromSession(sessionID, directory) {
|
|
|
42884
42978
|
if (memoryAgent)
|
|
42885
42979
|
return memoryAgent;
|
|
42886
42980
|
const boulderState = readBoulderState(directory);
|
|
42887
|
-
if (boulderState?.session_ids
|
|
42981
|
+
if (boulderState?.session_ids?.includes(sessionID) && boulderState.agent) {
|
|
42888
42982
|
return boulderState.agent;
|
|
42889
42983
|
}
|
|
42890
42984
|
return getAgentFromMessageFiles(sessionID);
|
|
@@ -43039,15 +43133,16 @@ function createTaskResumeInfoHook() {
|
|
|
43039
43133
|
const toolExecuteAfter = async (input, output) => {
|
|
43040
43134
|
if (!TARGET_TOOLS2.includes(input.tool))
|
|
43041
43135
|
return;
|
|
43042
|
-
|
|
43136
|
+
const outputText = output.output ?? "";
|
|
43137
|
+
if (outputText.startsWith("Error:") || outputText.startsWith("Failed"))
|
|
43043
43138
|
return;
|
|
43044
|
-
if (
|
|
43139
|
+
if (outputText.includes(`
|
|
43045
43140
|
to continue:`))
|
|
43046
43141
|
return;
|
|
43047
|
-
const sessionId = extractSessionId(
|
|
43142
|
+
const sessionId = extractSessionId(outputText);
|
|
43048
43143
|
if (!sessionId)
|
|
43049
43144
|
return;
|
|
43050
|
-
output.output =
|
|
43145
|
+
output.output = outputText.trimEnd() + `
|
|
43051
43146
|
|
|
43052
43147
|
to continue: task(session_id="${sessionId}", prompt="...")`;
|
|
43053
43148
|
};
|
|
@@ -43548,7 +43643,7 @@ function createAtlasEventHandler(input) {
|
|
|
43548
43643
|
return;
|
|
43549
43644
|
log(`[${HOOK_NAME7}] session.idle`, { sessionID });
|
|
43550
43645
|
const boulderState = readBoulderState(ctx.directory);
|
|
43551
|
-
const isBoulderSession = boulderState?.session_ids
|
|
43646
|
+
const isBoulderSession = boulderState?.session_ids?.includes(sessionID) ?? false;
|
|
43552
43647
|
const isBackgroundTaskSession = subagentSessions.has(sessionID);
|
|
43553
43648
|
if (!isBackgroundTaskSession && !isBoulderSession) {
|
|
43554
43649
|
log(`[${HOOK_NAME7}] Skipped: not boulder or background task session`, { sessionID });
|
|
@@ -43717,7 +43812,23 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
|
|
|
43717
43812
|
|
|
43718
43813
|
${buildVerificationReminder(sessionId)}
|
|
43719
43814
|
|
|
43720
|
-
**STEP 5:
|
|
43815
|
+
**STEP 5: READ SUBAGENT NOTEPAD (LEARNINGS, ISSUES, PROBLEMS)**
|
|
43816
|
+
|
|
43817
|
+
The subagent was instructed to record findings in notepad files. Read them NOW:
|
|
43818
|
+
\`\`\`
|
|
43819
|
+
Glob(".sisyphus/notepads/${planName}/*.md")
|
|
43820
|
+
\`\`\`
|
|
43821
|
+
Then \`Read\` each file found \u2014 especially:
|
|
43822
|
+
- **learnings.md**: Patterns, conventions, successful approaches discovered
|
|
43823
|
+
- **issues.md**: Problems, blockers, gotchas encountered during work
|
|
43824
|
+
- **problems.md**: Unresolved issues, technical debt flagged
|
|
43825
|
+
|
|
43826
|
+
**USE this information to:**
|
|
43827
|
+
- Inform your next delegation (avoid known pitfalls)
|
|
43828
|
+
- Adjust your plan if blockers were discovered
|
|
43829
|
+
- Propagate learnings to subsequent subagents
|
|
43830
|
+
|
|
43831
|
+
**STEP 6: CHECK BOULDER STATE DIRECTLY (EVERY TIME \u2014 NO EXCEPTIONS)**
|
|
43721
43832
|
|
|
43722
43833
|
Do NOT rely on cached progress. Read the plan file NOW:
|
|
43723
43834
|
\`\`\`
|
|
@@ -43726,7 +43837,7 @@ Read(".sisyphus/plans/${planName}.md")
|
|
|
43726
43837
|
Count exactly: how many \`- [ ]\` remain? How many \`- [x]\` completed?
|
|
43727
43838
|
This is YOUR ground truth. Use it to decide what comes next.
|
|
43728
43839
|
|
|
43729
|
-
**STEP
|
|
43840
|
+
**STEP 7: MARK COMPLETION IN PLAN FILE (IMMEDIATELY)**
|
|
43730
43841
|
|
|
43731
43842
|
RIGHT NOW - Do not delay. Verification passed \u2192 Mark IMMEDIATELY.
|
|
43732
43843
|
|
|
@@ -43736,12 +43847,12 @@ Update the plan file \`.sisyphus/plans/${planName}.md\`:
|
|
|
43736
43847
|
|
|
43737
43848
|
**DO THIS BEFORE ANYTHING ELSE. Unmarked = Untracked = Lost progress.**
|
|
43738
43849
|
|
|
43739
|
-
**STEP
|
|
43850
|
+
**STEP 8: COMMIT ATOMIC UNIT**
|
|
43740
43851
|
|
|
43741
43852
|
- Stage ONLY the verified changes
|
|
43742
43853
|
- Commit with clear message describing what was done
|
|
43743
43854
|
|
|
43744
|
-
**STEP
|
|
43855
|
+
**STEP 9: PROCEED TO NEXT TASK**
|
|
43745
43856
|
|
|
43746
43857
|
- Read the plan file AGAIN to identify the next \`- [ ]\` task
|
|
43747
43858
|
- Start immediately - DO NOT STOP
|
|
@@ -43835,7 +43946,7 @@ function createToolExecuteAfterHandler2(input) {
|
|
|
43835
43946
|
const boulderState = readBoulderState(ctx.directory);
|
|
43836
43947
|
if (boulderState) {
|
|
43837
43948
|
const progress = getPlanProgress(boulderState.active_plan);
|
|
43838
|
-
if (toolInput.sessionID && !boulderState.session_ids
|
|
43949
|
+
if (toolInput.sessionID && !boulderState.session_ids?.includes(toolInput.sessionID)) {
|
|
43839
43950
|
appendSessionId(ctx.directory, toolInput.sessionID);
|
|
43840
43951
|
log(`[${HOOK_NAME7}] Appended session to boulder`, {
|
|
43841
43952
|
sessionID: toolInput.sessionID,
|
|
@@ -49445,10 +49556,7 @@ async function createOrGetSession(args, toolContext, ctx) {
|
|
|
49445
49556
|
const createResult = await ctx.client.session.create({
|
|
49446
49557
|
body: {
|
|
49447
49558
|
parentID: toolContext.sessionID,
|
|
49448
|
-
title: `${args.description} (@${args.subagent_type} subagent)
|
|
49449
|
-
permission: [
|
|
49450
|
-
{ permission: "question", action: "deny", pattern: "*" }
|
|
49451
|
-
]
|
|
49559
|
+
title: `${args.description} (@${args.subagent_type} subagent)`
|
|
49452
49560
|
},
|
|
49453
49561
|
query: {
|
|
49454
49562
|
directory: parentDirectory
|
|
@@ -49471,6 +49579,7 @@ Original error: ${createResult.error}`);
|
|
|
49471
49579
|
}
|
|
49472
49580
|
const sessionID = createResult.data.id;
|
|
49473
49581
|
log(`[call_omo_agent] Created session: ${sessionID}`);
|
|
49582
|
+
subagentSessions.add(sessionID);
|
|
49474
49583
|
return { sessionID, isNew: true };
|
|
49475
49584
|
}
|
|
49476
49585
|
}
|
|
@@ -49656,30 +49765,6 @@ var LOOK_AT_DESCRIPTION = `Analyze media files (PDFs, images, diagrams) that req
|
|
|
49656
49765
|
import { basename as basename5 } from "path";
|
|
49657
49766
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
49658
49767
|
|
|
49659
|
-
// src/tools/look-at/session-poller.ts
|
|
49660
|
-
var DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
49661
|
-
var DEFAULT_TIMEOUT_MS6 = 120000;
|
|
49662
|
-
async function pollSessionUntilIdle(client2, sessionID, options) {
|
|
49663
|
-
const pollInterval = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
49664
|
-
const timeout = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS6;
|
|
49665
|
-
const startTime = Date.now();
|
|
49666
|
-
while (Date.now() - startTime < timeout) {
|
|
49667
|
-
const statusResult = await client2.session.status().catch((error45) => {
|
|
49668
|
-
log(`[look_at] session.status error (treating as idle):`, error45);
|
|
49669
|
-
return { data: undefined, error: error45 };
|
|
49670
|
-
});
|
|
49671
|
-
if (statusResult.error || !statusResult.data) {
|
|
49672
|
-
return;
|
|
49673
|
-
}
|
|
49674
|
-
const sessionStatus = statusResult.data[sessionID];
|
|
49675
|
-
if (!sessionStatus || sessionStatus.type === "idle") {
|
|
49676
|
-
return;
|
|
49677
|
-
}
|
|
49678
|
-
await new Promise((resolve11) => setTimeout(resolve11, pollInterval));
|
|
49679
|
-
}
|
|
49680
|
-
throw new Error(`[look_at] Polling timed out after ${timeout}ms waiting for session ${sessionID} to become idle`);
|
|
49681
|
-
}
|
|
49682
|
-
|
|
49683
49768
|
// src/tools/look-at/assistant-message-extractor.ts
|
|
49684
49769
|
function isObject3(value) {
|
|
49685
49770
|
return typeof value === "object" && value !== null;
|
|
@@ -49925,9 +50010,9 @@ Original error: ${createResult.error}`;
|
|
|
49925
50010
|
const sessionID = createResult.data.id;
|
|
49926
50011
|
log(`[look_at] Created session: ${sessionID}`);
|
|
49927
50012
|
const { agentModel, agentVariant } = await resolveMultimodalLookerAgentMetadata(ctx);
|
|
49928
|
-
log(`[look_at] Sending
|
|
50013
|
+
log(`[look_at] Sending prompt with ${isBase64Input ? "base64 image" : "file"} to session ${sessionID}`);
|
|
49929
50014
|
try {
|
|
49930
|
-
await
|
|
50015
|
+
await promptSyncWithModelSuggestionRetry(ctx.client, {
|
|
49931
50016
|
path: { id: sessionID },
|
|
49932
50017
|
body: {
|
|
49933
50018
|
agent: MULTIMODAL_LOOKER_AGENT,
|
|
@@ -49946,14 +50031,7 @@ Original error: ${createResult.error}`;
|
|
|
49946
50031
|
}
|
|
49947
50032
|
});
|
|
49948
50033
|
} catch (promptError) {
|
|
49949
|
-
log(`[look_at]
|
|
49950
|
-
return `Error: Failed to send prompt to multimodal-looker agent: ${promptError instanceof Error ? promptError.message : String(promptError)}`;
|
|
49951
|
-
}
|
|
49952
|
-
log(`[look_at] Polling session ${sessionID} until idle...`);
|
|
49953
|
-
try {
|
|
49954
|
-
await pollSessionUntilIdle(ctx.client, sessionID, { pollIntervalMs: 500, timeoutMs: 120000 });
|
|
49955
|
-
} catch (pollError) {
|
|
49956
|
-
log(`[look_at] Polling error (will still try to fetch messages):`, pollError);
|
|
50034
|
+
log(`[look_at] Prompt error (ignored, will still fetch messages):`, promptError);
|
|
49957
50035
|
}
|
|
49958
50036
|
log(`[look_at] Fetching messages from session ${sessionID}...`);
|
|
49959
50037
|
const messagesResult = await ctx.client.session.messages({
|
|
@@ -49977,6 +50055,15 @@ Original error: ${createResult.error}`;
|
|
|
49977
50055
|
}
|
|
49978
50056
|
// src/tools/delegate-task/tools.ts
|
|
49979
50057
|
init_constants();
|
|
50058
|
+
|
|
50059
|
+
// src/shared/merge-categories.ts
|
|
50060
|
+
init_constants();
|
|
50061
|
+
function mergeCategories(userCategories) {
|
|
50062
|
+
const merged = userCategories ? { ...DEFAULT_CATEGORIES, ...userCategories } : { ...DEFAULT_CATEGORIES };
|
|
50063
|
+
return Object.fromEntries(Object.entries(merged).filter(([, config3]) => !config3.disable));
|
|
50064
|
+
}
|
|
50065
|
+
|
|
50066
|
+
// src/tools/delegate-task/tools.ts
|
|
49980
50067
|
init_logger();
|
|
49981
50068
|
|
|
49982
50069
|
// src/tools/delegate-task/prompt-builder.ts
|
|
@@ -50798,10 +50885,7 @@ async function createSyncSession(client2, input) {
|
|
|
50798
50885
|
const createResult = await client2.session.create({
|
|
50799
50886
|
body: {
|
|
50800
50887
|
parentID: input.parentSessionID,
|
|
50801
|
-
title: `${input.description} (@${input.agentToUse} subagent)
|
|
50802
|
-
permission: [
|
|
50803
|
-
{ permission: "question", action: "deny", pattern: "*" }
|
|
50804
|
-
]
|
|
50888
|
+
title: `${input.description} (@${input.agentToUse} subagent)`
|
|
50805
50889
|
},
|
|
50806
50890
|
query: {
|
|
50807
50891
|
directory: parentDirectory
|
|
@@ -50985,9 +51069,6 @@ session_id: ${sessionID}
|
|
|
50985
51069
|
}
|
|
50986
51070
|
}
|
|
50987
51071
|
}
|
|
50988
|
-
// src/tools/delegate-task/category-resolver.ts
|
|
50989
|
-
init_constants();
|
|
50990
|
-
|
|
50991
51072
|
// src/tools/delegate-task/sisyphus-junior-agent.ts
|
|
50992
51073
|
var SISYPHUS_JUNIOR_AGENT2 = "sisyphus-junior";
|
|
50993
51074
|
|
|
@@ -50999,6 +51080,9 @@ function resolveCategoryConfig(categoryName, options) {
|
|
|
50999
51080
|
const defaultConfig = DEFAULT_CATEGORIES[categoryName];
|
|
51000
51081
|
const userConfig = userCategories?.[categoryName];
|
|
51001
51082
|
const hasExplicitUserConfig = userConfig !== undefined;
|
|
51083
|
+
if (userConfig?.disable) {
|
|
51084
|
+
return null;
|
|
51085
|
+
}
|
|
51002
51086
|
const categoryReq = CATEGORY_MODEL_REQUIREMENTS[categoryName];
|
|
51003
51087
|
if (categoryReq?.requiresModel && availableModels && !hasExplicitUserConfig) {
|
|
51004
51088
|
if (!isModelAvailable(categoryReq.requiresModel, availableModels)) {
|
|
@@ -51148,7 +51232,8 @@ async function resolveCategoryExecution(args, executorCtx, inheritedModel, syste
|
|
|
51148
51232
|
const { client: client2, userCategories, sisyphusJuniorModel } = executorCtx;
|
|
51149
51233
|
const availableModels = await getAvailableModelsForDelegateTask(client2);
|
|
51150
51234
|
const categoryName = args.category;
|
|
51151
|
-
const
|
|
51235
|
+
const enabledCategories = mergeCategories(userCategories);
|
|
51236
|
+
const categoryExists = enabledCategories[categoryName] !== undefined;
|
|
51152
51237
|
const resolved = resolveCategoryConfig(categoryName, {
|
|
51153
51238
|
userCategories,
|
|
51154
51239
|
inheritedModel,
|
|
@@ -51157,7 +51242,7 @@ async function resolveCategoryExecution(args, executorCtx, inheritedModel, syste
|
|
|
51157
51242
|
});
|
|
51158
51243
|
if (!resolved) {
|
|
51159
51244
|
const requirement2 = CATEGORY_MODEL_REQUIREMENTS[categoryName];
|
|
51160
|
-
const allCategoryNames = Object.keys(
|
|
51245
|
+
const allCategoryNames = Object.keys(enabledCategories).join(", ");
|
|
51161
51246
|
if (categoryExists && requirement2?.requiresModel) {
|
|
51162
51247
|
return {
|
|
51163
51248
|
agentToUse: "",
|
|
@@ -51232,7 +51317,7 @@ Available categories: ${allCategoryNames}`
|
|
|
51232
51317
|
}
|
|
51233
51318
|
const categoryPromptAppend = resolved.promptAppend || undefined;
|
|
51234
51319
|
if (!categoryModel && !actualModel) {
|
|
51235
|
-
const categoryNames = Object.keys(
|
|
51320
|
+
const categoryNames = Object.keys(enabledCategories);
|
|
51236
51321
|
return {
|
|
51237
51322
|
agentToUse: "",
|
|
51238
51323
|
categoryModel: undefined,
|
|
@@ -51342,7 +51427,7 @@ Create the work plan directly - that's your job as the planning agent.`
|
|
|
51342
51427
|
// src/tools/delegate-task/tools.ts
|
|
51343
51428
|
function createDelegateTask(options) {
|
|
51344
51429
|
const { userCategories } = options;
|
|
51345
|
-
const allCategories =
|
|
51430
|
+
const allCategories = mergeCategories(userCategories);
|
|
51346
51431
|
const categoryNames = Object.keys(allCategories);
|
|
51347
51432
|
const categoryExamples = categoryNames.map((k) => `'${k}'`).join(", ");
|
|
51348
51433
|
const availableCategories = options.availableCategories ?? Object.entries(allCategories).map(([name, categoryConfig]) => {
|
|
@@ -52714,14 +52799,10 @@ class BackgroundManager {
|
|
|
52714
52799
|
});
|
|
52715
52800
|
const parentDirectory = parentSession?.data?.directory ?? this.directory;
|
|
52716
52801
|
log(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${parentDirectory}`);
|
|
52717
|
-
const inheritedPermission = parentSession?.data?.permission;
|
|
52718
|
-
const permissionRules = Array.isArray(inheritedPermission) ? inheritedPermission.filter((r) => r?.permission !== "question") : [];
|
|
52719
|
-
permissionRules.push({ permission: "question", action: "deny", pattern: "*" });
|
|
52720
52802
|
const createResult = await this.client.session.create({
|
|
52721
52803
|
body: {
|
|
52722
52804
|
parentID: input.parentSessionID,
|
|
52723
|
-
title: `${input.description} (@${input.agent} subagent)
|
|
52724
|
-
permission: permissionRules
|
|
52805
|
+
title: `${input.description} (@${input.agent} subagent)`
|
|
52725
52806
|
},
|
|
52726
52807
|
query: {
|
|
52727
52808
|
directory: parentDirectory
|
|
@@ -62180,7 +62261,7 @@ ${rows.join(`
|
|
|
62180
62261
|
`)}`;
|
|
62181
62262
|
}
|
|
62182
62263
|
function buildCategorySection(userCategories) {
|
|
62183
|
-
const allCategories =
|
|
62264
|
+
const allCategories = mergeCategories(userCategories);
|
|
62184
62265
|
const categoryRows = Object.entries(allCategories).map(([name, config3]) => {
|
|
62185
62266
|
const temp = config3.temperature ?? 0.5;
|
|
62186
62267
|
return `| \`${name}\` | ${temp} | ${getCategoryDescription(name, userCategories)} |`;
|
|
@@ -62256,7 +62337,7 @@ task(category="[category]", load_skills=["skill-1", "skill-2"], run_in_backgroun
|
|
|
62256
62337
|
- Missing a relevant skill = suboptimal output quality`;
|
|
62257
62338
|
}
|
|
62258
62339
|
function buildDecisionMatrix(agents, userCategories) {
|
|
62259
|
-
const allCategories =
|
|
62340
|
+
const allCategories = mergeCategories(userCategories);
|
|
62260
62341
|
const categoryRows = Object.entries(allCategories).map(([name]) => `| ${getCategoryDescription(name, userCategories)} | \`category="${name}", load_skills=[...]\` |`);
|
|
62261
62342
|
const agentRows = agents.map((a) => {
|
|
62262
62343
|
const shortDesc = truncateDescription(a.description);
|
|
@@ -62274,7 +62355,6 @@ ${agentRows.join(`
|
|
|
62274
62355
|
**NEVER provide both category AND agent - they are mutually exclusive.**`;
|
|
62275
62356
|
}
|
|
62276
62357
|
// src/agents/atlas/agent.ts
|
|
62277
|
-
init_constants();
|
|
62278
62358
|
var MODE7 = "primary";
|
|
62279
62359
|
function getAtlasPromptSource(model) {
|
|
62280
62360
|
if (model && isGptModel2(model)) {
|
|
@@ -62297,7 +62377,7 @@ function buildDynamicOrchestratorPrompt(ctx) {
|
|
|
62297
62377
|
const skills = ctx?.availableSkills ?? [];
|
|
62298
62378
|
const userCategories = ctx?.userCategories;
|
|
62299
62379
|
const model = ctx?.model;
|
|
62300
|
-
const allCategories =
|
|
62380
|
+
const allCategories = mergeCategories(userCategories);
|
|
62301
62381
|
const availableCategories = Object.entries(allCategories).map(([name]) => ({
|
|
62302
62382
|
name,
|
|
62303
62383
|
description: getCategoryDescription(name, userCategories)
|
|
@@ -63173,13 +63253,12 @@ function buildAvailableSkills(discoveredSkills, browserProvider, disabledSkills)
|
|
|
63173
63253
|
}
|
|
63174
63254
|
|
|
63175
63255
|
// src/agents/agent-builder.ts
|
|
63176
|
-
init_constants();
|
|
63177
63256
|
function isFactory(source) {
|
|
63178
63257
|
return typeof source === "function";
|
|
63179
63258
|
}
|
|
63180
63259
|
function buildAgent(source, model, categories, gitMasterConfig, browserProvider, disabledSkills) {
|
|
63181
63260
|
const base = isFactory(source) ? source(model) : { ...source };
|
|
63182
|
-
const categoryConfigs = categories
|
|
63261
|
+
const categoryConfigs = mergeCategories(categories);
|
|
63183
63262
|
const agentWithCategory = base;
|
|
63184
63263
|
if (agentWithCategory.category) {
|
|
63185
63264
|
const categoryConfig = categoryConfigs[agentWithCategory.category];
|
|
@@ -63589,7 +63668,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
63589
63668
|
});
|
|
63590
63669
|
const isFirstRunNoCache = availableModels.size === 0 && (!connectedProviders || connectedProviders.length === 0);
|
|
63591
63670
|
const result = {};
|
|
63592
|
-
const mergedCategories = categories
|
|
63671
|
+
const mergedCategories = mergeCategories(categories);
|
|
63593
63672
|
const availableCategories = Object.entries(mergedCategories).map(([name]) => ({
|
|
63594
63673
|
name,
|
|
63595
63674
|
description: categories?.[name]?.description ?? CATEGORY_DESCRIPTIONS[name] ?? "General tasks"
|
|
@@ -66632,8 +66711,8 @@ function createManagers(args) {
|
|
|
66632
66711
|
// src/plugin/available-categories.ts
|
|
66633
66712
|
init_constants();
|
|
66634
66713
|
function createAvailableCategories(pluginConfig) {
|
|
66635
|
-
const
|
|
66636
|
-
return Object.entries(
|
|
66714
|
+
const categories = mergeCategories(pluginConfig.categories);
|
|
66715
|
+
return Object.entries(categories).map(([name, categoryConfig]) => {
|
|
66637
66716
|
const model = typeof categoryConfig.model === "string" ? categoryConfig.model : undefined;
|
|
66638
66717
|
return {
|
|
66639
66718
|
name,
|
|
@@ -67381,7 +67460,8 @@ var CategoryConfigSchema = exports_external.object({
|
|
|
67381
67460
|
textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
|
|
67382
67461
|
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
|
|
67383
67462
|
prompt_append: exports_external.string().optional(),
|
|
67384
|
-
is_unstable_agent: exports_external.boolean().optional()
|
|
67463
|
+
is_unstable_agent: exports_external.boolean().optional(),
|
|
67464
|
+
disable: exports_external.boolean().optional()
|
|
67385
67465
|
});
|
|
67386
67466
|
var BuiltinCategoryNameSchema = exports_external.enum([
|
|
67387
67467
|
"visual-engineering",
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CategoriesConfig, CategoryConfig } from "../config/schema";
|
|
2
|
+
/**
|
|
3
|
+
* Merge default and user categories, filtering out disabled ones.
|
|
4
|
+
* Single source of truth for category merging across the codebase.
|
|
5
|
+
*/
|
|
6
|
+
export declare function mergeCategories(userCategories?: CategoriesConfig): Record<string, CategoryConfig>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-opencode",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.2",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"typescript": "^5.7.3"
|
|
75
75
|
},
|
|
76
76
|
"optionalDependencies": {
|
|
77
|
-
"oh-my-opencode-darwin-arm64": "3.5.
|
|
78
|
-
"oh-my-opencode-darwin-x64": "3.5.
|
|
79
|
-
"oh-my-opencode-linux-arm64": "3.5.
|
|
80
|
-
"oh-my-opencode-linux-arm64-musl": "3.5.
|
|
81
|
-
"oh-my-opencode-linux-x64": "3.5.
|
|
82
|
-
"oh-my-opencode-linux-x64-musl": "3.5.
|
|
83
|
-
"oh-my-opencode-windows-x64": "3.5.
|
|
77
|
+
"oh-my-opencode-darwin-arm64": "3.5.2",
|
|
78
|
+
"oh-my-opencode-darwin-x64": "3.5.2",
|
|
79
|
+
"oh-my-opencode-linux-arm64": "3.5.2",
|
|
80
|
+
"oh-my-opencode-linux-arm64-musl": "3.5.2",
|
|
81
|
+
"oh-my-opencode-linux-x64": "3.5.2",
|
|
82
|
+
"oh-my-opencode-linux-x64-musl": "3.5.2",
|
|
83
|
+
"oh-my-opencode-windows-x64": "3.5.2"
|
|
84
84
|
},
|
|
85
85
|
"trustedDependencies": [
|
|
86
86
|
"@ast-grep/cli",
|