oh-my-opencode 2.12.1 → 2.12.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.
- package/README.ja.md +32 -7
- package/README.ko.md +32 -7
- package/README.md +17 -8
- package/README.zh-cn.md +32 -7
- package/dist/agents/sisyphus-prompt-builder.d.ts +1 -0
- package/dist/cli/config-manager.d.ts +9 -0
- package/dist/cli/index.js +185 -81
- package/dist/features/claude-code-command-loader/loader.d.ts +5 -0
- package/dist/features/context-injector/collector.d.ts +11 -0
- package/dist/features/context-injector/collector.test.d.ts +1 -0
- package/dist/features/context-injector/index.d.ts +3 -0
- package/dist/features/context-injector/injector.d.ts +39 -0
- package/dist/features/context-injector/injector.test.d.ts +1 -0
- package/dist/features/context-injector/types.d.ts +83 -0
- package/dist/features/opencode-skill-loader/async-loader.d.ts +6 -0
- package/dist/features/opencode-skill-loader/async-loader.test.d.ts +1 -0
- package/dist/features/opencode-skill-loader/blocking.d.ts +2 -0
- package/dist/features/opencode-skill-loader/blocking.test.d.ts +1 -0
- package/dist/features/opencode-skill-loader/discover-worker.d.ts +1 -0
- package/dist/features/opencode-skill-loader/loader.d.ts +5 -0
- package/dist/features/opencode-skill-loader/types.d.ts +6 -0
- package/dist/features/skill-mcp-manager/env-cleaner.d.ts +2 -0
- package/dist/features/skill-mcp-manager/env-cleaner.test.d.ts +1 -0
- package/dist/features/skill-mcp-manager/manager.d.ts +8 -0
- package/dist/hooks/ralph-loop/types.d.ts +2 -0
- package/dist/hooks/session-recovery/index.d.ts +2 -0
- package/dist/hooks/session-recovery/index.test.d.ts +1 -0
- package/dist/hooks/tool-output-truncator.test.d.ts +1 -0
- package/dist/index.js +1176 -465
- package/dist/shared/frontmatter.d.ts +2 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/opencode-config-dir.d.ts +19 -0
- package/dist/shared/opencode-config-dir.test.d.ts +1 -0
- package/dist/shared/opencode-version.d.ts +10 -0
- package/dist/shared/opencode-version.test.d.ts +1 -0
- package/dist/shared/permission-compat.d.ts +12 -0
- package/dist/shared/permission-compat.test.d.ts +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -2657,7 +2657,7 @@ var require_napi = __commonJS((exports, module) => {
|
|
|
2657
2657
|
var require_package = __commonJS((exports, module) => {
|
|
2658
2658
|
module.exports = {
|
|
2659
2659
|
name: "oh-my-opencode",
|
|
2660
|
-
version: "2.12.
|
|
2660
|
+
version: "2.12.2",
|
|
2661
2661
|
description: "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
|
|
2662
2662
|
main: "dist/index.js",
|
|
2663
2663
|
types: "dist/index.d.ts",
|
|
@@ -2713,8 +2713,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
2713
2713
|
"@code-yeongyu/comment-checker": "^0.6.1",
|
|
2714
2714
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
2715
2715
|
"@openauthjs/openauth": "^0.4.3",
|
|
2716
|
-
"@opencode-ai/plugin": "^1.
|
|
2717
|
-
"@opencode-ai/sdk": "^1.
|
|
2716
|
+
"@opencode-ai/plugin": "^1.1.1",
|
|
2717
|
+
"@opencode-ai/sdk": "^1.1.1",
|
|
2718
2718
|
commander: "^14.0.2",
|
|
2719
2719
|
hono: "^4.10.4",
|
|
2720
2720
|
"js-yaml": "^4.1.1",
|
|
@@ -3338,9 +3338,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
3338
3338
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
3339
3339
|
|
|
3340
3340
|
// src/cli/config-manager.ts
|
|
3341
|
-
import { existsSync as
|
|
3342
|
-
import { homedir } from "os";
|
|
3343
|
-
import { join as join2 } from "path";
|
|
3341
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync, statSync } from "fs";
|
|
3344
3342
|
|
|
3345
3343
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
3346
3344
|
/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */
|
|
@@ -6007,6 +6005,8 @@ function log(message, data) {
|
|
|
6007
6005
|
}
|
|
6008
6006
|
// src/shared/deep-merge.ts
|
|
6009
6007
|
var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
6008
|
+
// src/shared/dynamic-truncator.ts
|
|
6009
|
+
var ANTHROPIC_ACTUAL_LIMIT = process.env.ANTHROPIC_1M_CONTEXT === "true" || process.env.VERTEX_ANTHROPIC_1M_CONTEXT === "true" ? 1e6 : 200000;
|
|
6010
6010
|
// src/shared/jsonc-parser.ts
|
|
6011
6011
|
import { existsSync, readFileSync } from "fs";
|
|
6012
6012
|
|
|
@@ -6875,13 +6875,109 @@ function detectConfigFile(basePath) {
|
|
|
6875
6875
|
}
|
|
6876
6876
|
return { format: "none", path: jsonPath };
|
|
6877
6877
|
}
|
|
6878
|
+
// src/shared/opencode-config-dir.ts
|
|
6879
|
+
import { existsSync as existsSync2 } from "fs";
|
|
6880
|
+
import { homedir } from "os";
|
|
6881
|
+
import { join as join2 } from "path";
|
|
6882
|
+
var TAURI_APP_IDENTIFIER = "ai.opencode.desktop";
|
|
6883
|
+
var TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
|
|
6884
|
+
function isDevBuild(version) {
|
|
6885
|
+
if (!version)
|
|
6886
|
+
return false;
|
|
6887
|
+
return version.includes("-dev") || version.includes(".dev");
|
|
6888
|
+
}
|
|
6889
|
+
function getTauriConfigDir(identifier) {
|
|
6890
|
+
const platform = process.platform;
|
|
6891
|
+
switch (platform) {
|
|
6892
|
+
case "darwin":
|
|
6893
|
+
return join2(homedir(), "Library", "Application Support", identifier);
|
|
6894
|
+
case "win32": {
|
|
6895
|
+
const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
|
|
6896
|
+
return join2(appData, identifier);
|
|
6897
|
+
}
|
|
6898
|
+
case "linux":
|
|
6899
|
+
default: {
|
|
6900
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
|
|
6901
|
+
return join2(xdgConfig, identifier);
|
|
6902
|
+
}
|
|
6903
|
+
}
|
|
6904
|
+
}
|
|
6905
|
+
function getCliConfigDir() {
|
|
6906
|
+
if (process.platform === "win32") {
|
|
6907
|
+
const crossPlatformDir = join2(homedir(), ".config", "opencode");
|
|
6908
|
+
const crossPlatformConfig = join2(crossPlatformDir, "opencode.json");
|
|
6909
|
+
if (existsSync2(crossPlatformConfig)) {
|
|
6910
|
+
return crossPlatformDir;
|
|
6911
|
+
}
|
|
6912
|
+
const appData = process.env.APPDATA || join2(homedir(), "AppData", "Roaming");
|
|
6913
|
+
const appdataDir = join2(appData, "opencode");
|
|
6914
|
+
const appdataConfig = join2(appdataDir, "opencode.json");
|
|
6915
|
+
if (existsSync2(appdataConfig)) {
|
|
6916
|
+
return appdataDir;
|
|
6917
|
+
}
|
|
6918
|
+
return crossPlatformDir;
|
|
6919
|
+
}
|
|
6920
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
|
|
6921
|
+
return join2(xdgConfig, "opencode");
|
|
6922
|
+
}
|
|
6923
|
+
function getOpenCodeConfigDir(options) {
|
|
6924
|
+
const { binary: binary2, version, checkExisting = true } = options;
|
|
6925
|
+
if (binary2 === "opencode") {
|
|
6926
|
+
return getCliConfigDir();
|
|
6927
|
+
}
|
|
6928
|
+
const identifier = isDevBuild(version) ? TAURI_APP_IDENTIFIER_DEV : TAURI_APP_IDENTIFIER;
|
|
6929
|
+
const tauriDir = getTauriConfigDir(identifier);
|
|
6930
|
+
if (checkExisting) {
|
|
6931
|
+
const legacyDir = getCliConfigDir();
|
|
6932
|
+
const legacyConfig = join2(legacyDir, "opencode.json");
|
|
6933
|
+
const legacyConfigC = join2(legacyDir, "opencode.jsonc");
|
|
6934
|
+
if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
|
|
6935
|
+
return legacyDir;
|
|
6936
|
+
}
|
|
6937
|
+
}
|
|
6938
|
+
return tauriDir;
|
|
6939
|
+
}
|
|
6940
|
+
function getOpenCodeConfigPaths(options) {
|
|
6941
|
+
const configDir = getOpenCodeConfigDir(options);
|
|
6942
|
+
return {
|
|
6943
|
+
configDir,
|
|
6944
|
+
configJson: join2(configDir, "opencode.json"),
|
|
6945
|
+
configJsonc: join2(configDir, "opencode.jsonc"),
|
|
6946
|
+
packageJson: join2(configDir, "package.json"),
|
|
6947
|
+
omoConfig: join2(configDir, "oh-my-opencode.json")
|
|
6948
|
+
};
|
|
6949
|
+
}
|
|
6950
|
+
// src/shared/opencode-version.ts
|
|
6951
|
+
var NOT_CACHED = Symbol("NOT_CACHED");
|
|
6878
6952
|
// src/cli/config-manager.ts
|
|
6879
|
-
var OPENCODE_CONFIG_DIR = join2(homedir(), ".config", "opencode");
|
|
6880
|
-
var OPENCODE_JSON = join2(OPENCODE_CONFIG_DIR, "opencode.json");
|
|
6881
|
-
var OPENCODE_JSONC = join2(OPENCODE_CONFIG_DIR, "opencode.jsonc");
|
|
6882
|
-
var OPENCODE_PACKAGE_JSON = join2(OPENCODE_CONFIG_DIR, "package.json");
|
|
6883
|
-
var OMO_CONFIG = join2(OPENCODE_CONFIG_DIR, "oh-my-opencode.json");
|
|
6884
6953
|
var OPENCODE_BINARIES = ["opencode", "opencode-desktop"];
|
|
6954
|
+
var configContext = null;
|
|
6955
|
+
function initConfigContext(binary2, version) {
|
|
6956
|
+
const paths = getOpenCodeConfigPaths({ binary: binary2, version });
|
|
6957
|
+
configContext = { binary: binary2, version, paths };
|
|
6958
|
+
}
|
|
6959
|
+
function getConfigContext() {
|
|
6960
|
+
if (!configContext) {
|
|
6961
|
+
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
6962
|
+
configContext = { binary: "opencode", version: null, paths };
|
|
6963
|
+
}
|
|
6964
|
+
return configContext;
|
|
6965
|
+
}
|
|
6966
|
+
function getConfigDir() {
|
|
6967
|
+
return getConfigContext().paths.configDir;
|
|
6968
|
+
}
|
|
6969
|
+
function getConfigJson() {
|
|
6970
|
+
return getConfigContext().paths.configJson;
|
|
6971
|
+
}
|
|
6972
|
+
function getConfigJsonc() {
|
|
6973
|
+
return getConfigContext().paths.configJsonc;
|
|
6974
|
+
}
|
|
6975
|
+
function getPackageJson() {
|
|
6976
|
+
return getConfigContext().paths.packageJson;
|
|
6977
|
+
}
|
|
6978
|
+
function getOmoConfig() {
|
|
6979
|
+
return getConfigContext().paths.omoConfig;
|
|
6980
|
+
}
|
|
6885
6981
|
var CHATGPT_HOTFIX_REPO = "code-yeongyu/opencode-openai-codex-auth#fix/orphaned-function-call-output-with-tools";
|
|
6886
6982
|
var BUN_INSTALL_TIMEOUT_SECONDS = 60;
|
|
6887
6983
|
var BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000;
|
|
@@ -6924,13 +7020,15 @@ async function fetchLatestVersion(packageName) {
|
|
|
6924
7020
|
}
|
|
6925
7021
|
}
|
|
6926
7022
|
function detectConfigFormat() {
|
|
6927
|
-
|
|
6928
|
-
|
|
7023
|
+
const configJsonc = getConfigJsonc();
|
|
7024
|
+
const configJson = getConfigJson();
|
|
7025
|
+
if (existsSync3(configJsonc)) {
|
|
7026
|
+
return { format: "jsonc", path: configJsonc };
|
|
6929
7027
|
}
|
|
6930
|
-
if (
|
|
6931
|
-
return { format: "json", path:
|
|
7028
|
+
if (existsSync3(configJson)) {
|
|
7029
|
+
return { format: "json", path: configJson };
|
|
6932
7030
|
}
|
|
6933
|
-
return { format: "none", path:
|
|
7031
|
+
return { format: "none", path: configJson };
|
|
6934
7032
|
}
|
|
6935
7033
|
function isEmptyOrWhitespace(content) {
|
|
6936
7034
|
return content.trim().length === 0;
|
|
@@ -6958,15 +7056,16 @@ function parseConfigWithError(path2) {
|
|
|
6958
7056
|
}
|
|
6959
7057
|
}
|
|
6960
7058
|
function ensureConfigDir() {
|
|
6961
|
-
|
|
6962
|
-
|
|
7059
|
+
const configDir = getConfigDir();
|
|
7060
|
+
if (!existsSync3(configDir)) {
|
|
7061
|
+
mkdirSync(configDir, { recursive: true });
|
|
6963
7062
|
}
|
|
6964
7063
|
}
|
|
6965
7064
|
function addPluginToOpenCodeConfig() {
|
|
6966
7065
|
try {
|
|
6967
7066
|
ensureConfigDir();
|
|
6968
7067
|
} catch (err) {
|
|
6969
|
-
return { success: false, configPath:
|
|
7068
|
+
return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
|
|
6970
7069
|
}
|
|
6971
7070
|
const { format: format2, path: path2 } = detectConfigFormat();
|
|
6972
7071
|
const pluginName = "oh-my-opencode";
|
|
@@ -7070,44 +7169,45 @@ function writeOmoConfig(installConfig) {
|
|
|
7070
7169
|
try {
|
|
7071
7170
|
ensureConfigDir();
|
|
7072
7171
|
} catch (err) {
|
|
7073
|
-
return { success: false, configPath:
|
|
7172
|
+
return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
|
|
7074
7173
|
}
|
|
7174
|
+
const omoConfigPath = getOmoConfig();
|
|
7075
7175
|
try {
|
|
7076
7176
|
const newConfig = generateOmoConfig(installConfig);
|
|
7077
|
-
if (
|
|
7177
|
+
if (existsSync3(omoConfigPath)) {
|
|
7078
7178
|
try {
|
|
7079
|
-
const stat = statSync(
|
|
7080
|
-
const content = readFileSync2(
|
|
7179
|
+
const stat = statSync(omoConfigPath);
|
|
7180
|
+
const content = readFileSync2(omoConfigPath, "utf-8");
|
|
7081
7181
|
if (stat.size === 0 || isEmptyOrWhitespace(content)) {
|
|
7082
|
-
writeFileSync(
|
|
7182
|
+
writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
|
|
7083
7183
|
`);
|
|
7084
|
-
return { success: true, configPath:
|
|
7184
|
+
return { success: true, configPath: omoConfigPath };
|
|
7085
7185
|
}
|
|
7086
7186
|
const existing = parseJsonc(content);
|
|
7087
7187
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
7088
|
-
writeFileSync(
|
|
7188
|
+
writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
|
|
7089
7189
|
`);
|
|
7090
|
-
return { success: true, configPath:
|
|
7190
|
+
return { success: true, configPath: omoConfigPath };
|
|
7091
7191
|
}
|
|
7092
7192
|
delete existing.agents;
|
|
7093
7193
|
const merged = deepMerge(existing, newConfig);
|
|
7094
|
-
writeFileSync(
|
|
7194
|
+
writeFileSync(omoConfigPath, JSON.stringify(merged, null, 2) + `
|
|
7095
7195
|
`);
|
|
7096
7196
|
} catch (parseErr) {
|
|
7097
7197
|
if (parseErr instanceof SyntaxError) {
|
|
7098
|
-
writeFileSync(
|
|
7198
|
+
writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
|
|
7099
7199
|
`);
|
|
7100
|
-
return { success: true, configPath:
|
|
7200
|
+
return { success: true, configPath: omoConfigPath };
|
|
7101
7201
|
}
|
|
7102
7202
|
throw parseErr;
|
|
7103
7203
|
}
|
|
7104
7204
|
} else {
|
|
7105
|
-
writeFileSync(
|
|
7205
|
+
writeFileSync(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
|
|
7106
7206
|
`);
|
|
7107
7207
|
}
|
|
7108
|
-
return { success: true, configPath:
|
|
7208
|
+
return { success: true, configPath: omoConfigPath };
|
|
7109
7209
|
} catch (err) {
|
|
7110
|
-
return { success: false, configPath:
|
|
7210
|
+
return { success: false, configPath: omoConfigPath, error: formatErrorWithSuggestion(err, "write oh-my-opencode config") };
|
|
7111
7211
|
}
|
|
7112
7212
|
}
|
|
7113
7213
|
async function findOpenCodeBinaryWithVersion() {
|
|
@@ -7120,7 +7220,9 @@ async function findOpenCodeBinaryWithVersion() {
|
|
|
7120
7220
|
const output = await new Response(proc.stdout).text();
|
|
7121
7221
|
await proc.exited;
|
|
7122
7222
|
if (proc.exitCode === 0) {
|
|
7123
|
-
|
|
7223
|
+
const version = output.trim();
|
|
7224
|
+
initConfigContext(binary2, version);
|
|
7225
|
+
return { binary: binary2, version };
|
|
7124
7226
|
}
|
|
7125
7227
|
} catch {
|
|
7126
7228
|
continue;
|
|
@@ -7140,7 +7242,7 @@ async function addAuthPlugins(config) {
|
|
|
7140
7242
|
try {
|
|
7141
7243
|
ensureConfigDir();
|
|
7142
7244
|
} catch (err) {
|
|
7143
|
-
return { success: false, configPath:
|
|
7245
|
+
return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
|
|
7144
7246
|
}
|
|
7145
7247
|
const { format: format2, path: path2 } = detectConfigFormat();
|
|
7146
7248
|
try {
|
|
@@ -7178,14 +7280,15 @@ function setupChatGPTHotfix() {
|
|
|
7178
7280
|
try {
|
|
7179
7281
|
ensureConfigDir();
|
|
7180
7282
|
} catch (err) {
|
|
7181
|
-
return { success: false, configPath:
|
|
7283
|
+
return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
|
|
7182
7284
|
}
|
|
7285
|
+
const packageJsonPath = getPackageJson();
|
|
7183
7286
|
try {
|
|
7184
7287
|
let packageJson = {};
|
|
7185
|
-
if (
|
|
7288
|
+
if (existsSync3(packageJsonPath)) {
|
|
7186
7289
|
try {
|
|
7187
|
-
const stat = statSync(
|
|
7188
|
-
const content = readFileSync2(
|
|
7290
|
+
const stat = statSync(packageJsonPath);
|
|
7291
|
+
const content = readFileSync2(packageJsonPath, "utf-8");
|
|
7189
7292
|
if (stat.size > 0 && !isEmptyOrWhitespace(content)) {
|
|
7190
7293
|
packageJson = JSON.parse(content);
|
|
7191
7294
|
if (typeof packageJson !== "object" || packageJson === null || Array.isArray(packageJson)) {
|
|
@@ -7203,11 +7306,11 @@ function setupChatGPTHotfix() {
|
|
|
7203
7306
|
const deps = packageJson.dependencies ?? {};
|
|
7204
7307
|
deps["opencode-openai-codex-auth"] = CHATGPT_HOTFIX_REPO;
|
|
7205
7308
|
packageJson.dependencies = deps;
|
|
7206
|
-
writeFileSync(
|
|
7309
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + `
|
|
7207
7310
|
`);
|
|
7208
|
-
return { success: true, configPath:
|
|
7311
|
+
return { success: true, configPath: packageJsonPath };
|
|
7209
7312
|
} catch (err) {
|
|
7210
|
-
return { success: false, configPath:
|
|
7313
|
+
return { success: false, configPath: packageJsonPath, error: formatErrorWithSuggestion(err, "setup ChatGPT hotfix in package.json") };
|
|
7211
7314
|
}
|
|
7212
7315
|
}
|
|
7213
7316
|
async function runBunInstall() {
|
|
@@ -7217,7 +7320,7 @@ async function runBunInstall() {
|
|
|
7217
7320
|
async function runBunInstallWithDetails() {
|
|
7218
7321
|
try {
|
|
7219
7322
|
const proc = Bun.spawn(["bun", "install"], {
|
|
7220
|
-
cwd:
|
|
7323
|
+
cwd: getConfigDir(),
|
|
7221
7324
|
stdout: "pipe",
|
|
7222
7325
|
stderr: "pipe"
|
|
7223
7326
|
});
|
|
@@ -7306,7 +7409,7 @@ function addProviderConfig(config) {
|
|
|
7306
7409
|
try {
|
|
7307
7410
|
ensureConfigDir();
|
|
7308
7411
|
} catch (err) {
|
|
7309
|
-
return { success: false, configPath:
|
|
7412
|
+
return { success: false, configPath: getConfigDir(), error: formatErrorWithSuggestion(err, "create config directory") };
|
|
7310
7413
|
}
|
|
7311
7414
|
const { format: format2, path: path2 } = detectConfigFormat();
|
|
7312
7415
|
try {
|
|
@@ -7361,15 +7464,16 @@ function detectCurrentConfig() {
|
|
|
7361
7464
|
}
|
|
7362
7465
|
result.hasGemini = plugins.some((p2) => p2.startsWith("opencode-antigravity-auth"));
|
|
7363
7466
|
result.hasChatGPT = plugins.some((p2) => p2.startsWith("opencode-openai-codex-auth"));
|
|
7364
|
-
|
|
7467
|
+
const omoConfigPath = getOmoConfig();
|
|
7468
|
+
if (!existsSync3(omoConfigPath)) {
|
|
7365
7469
|
return result;
|
|
7366
7470
|
}
|
|
7367
7471
|
try {
|
|
7368
|
-
const stat = statSync(
|
|
7472
|
+
const stat = statSync(omoConfigPath);
|
|
7369
7473
|
if (stat.size === 0) {
|
|
7370
7474
|
return result;
|
|
7371
7475
|
}
|
|
7372
|
-
const content = readFileSync2(
|
|
7476
|
+
const content = readFileSync2(omoConfigPath, "utf-8");
|
|
7373
7477
|
if (isEmptyOrWhitespace(content)) {
|
|
7374
7478
|
return result;
|
|
7375
7479
|
}
|
|
@@ -9147,7 +9251,10 @@ async function createOpencodeServer(options) {
|
|
|
9147
9251
|
port: 4096,
|
|
9148
9252
|
timeout: 5000
|
|
9149
9253
|
}, options ?? {});
|
|
9150
|
-
const
|
|
9254
|
+
const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
|
|
9255
|
+
if (options.config?.logLevel)
|
|
9256
|
+
args.push(`--log-level=${options.config.logLevel}`);
|
|
9257
|
+
const proc = spawn(`opencode`, args, {
|
|
9151
9258
|
signal: options.signal,
|
|
9152
9259
|
env: {
|
|
9153
9260
|
...process.env,
|
|
@@ -10078,18 +10185,14 @@ function getOpenCodeCheckDefinition() {
|
|
|
10078
10185
|
}
|
|
10079
10186
|
|
|
10080
10187
|
// src/cli/doctor/checks/plugin.ts
|
|
10081
|
-
import { existsSync as
|
|
10082
|
-
import { homedir as homedir4 } from "os";
|
|
10083
|
-
import { join as join5 } from "path";
|
|
10084
|
-
var OPENCODE_CONFIG_DIR2 = join5(homedir4(), ".config", "opencode");
|
|
10085
|
-
var OPENCODE_JSON2 = join5(OPENCODE_CONFIG_DIR2, "opencode.json");
|
|
10086
|
-
var OPENCODE_JSONC2 = join5(OPENCODE_CONFIG_DIR2, "opencode.jsonc");
|
|
10188
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
10087
10189
|
function detectConfigPath() {
|
|
10088
|
-
|
|
10089
|
-
|
|
10190
|
+
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
10191
|
+
if (existsSync6(paths.configJsonc)) {
|
|
10192
|
+
return { path: paths.configJsonc, format: "jsonc" };
|
|
10090
10193
|
}
|
|
10091
|
-
if (
|
|
10092
|
-
return { path:
|
|
10194
|
+
if (existsSync6(paths.configJson)) {
|
|
10195
|
+
return { path: paths.configJson, format: "json" };
|
|
10093
10196
|
}
|
|
10094
10197
|
return null;
|
|
10095
10198
|
}
|
|
@@ -10148,13 +10251,14 @@ function getPluginInfo() {
|
|
|
10148
10251
|
async function checkPluginRegistration() {
|
|
10149
10252
|
const info = getPluginInfo();
|
|
10150
10253
|
if (!info.configPath) {
|
|
10254
|
+
const expectedPaths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
10151
10255
|
return {
|
|
10152
10256
|
name: CHECK_NAMES[CHECK_IDS.PLUGIN_REGISTRATION],
|
|
10153
10257
|
status: "fail",
|
|
10154
10258
|
message: "OpenCode config file not found",
|
|
10155
10259
|
details: [
|
|
10156
10260
|
"Run: bunx oh-my-opencode install",
|
|
10157
|
-
`Expected: ${
|
|
10261
|
+
`Expected: ${expectedPaths.configJson} or ${expectedPaths.configJsonc}`
|
|
10158
10262
|
]
|
|
10159
10263
|
};
|
|
10160
10264
|
}
|
|
@@ -10188,9 +10292,9 @@ function getPluginCheckDefinition() {
|
|
|
10188
10292
|
}
|
|
10189
10293
|
|
|
10190
10294
|
// src/cli/doctor/checks/config.ts
|
|
10191
|
-
import { existsSync as
|
|
10192
|
-
import { homedir as
|
|
10193
|
-
import { join as
|
|
10295
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
10296
|
+
import { homedir as homedir4 } from "os";
|
|
10297
|
+
import { join as join5 } from "path";
|
|
10194
10298
|
|
|
10195
10299
|
// node_modules/zod/v4/classic/external.js
|
|
10196
10300
|
var exports_external = {};
|
|
@@ -22722,9 +22826,9 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
|
|
|
22722
22826
|
ralph_loop: RalphLoopConfigSchema.optional()
|
|
22723
22827
|
});
|
|
22724
22828
|
// src/cli/doctor/checks/config.ts
|
|
22725
|
-
var USER_CONFIG_DIR2 =
|
|
22726
|
-
var USER_CONFIG_BASE =
|
|
22727
|
-
var PROJECT_CONFIG_BASE =
|
|
22829
|
+
var USER_CONFIG_DIR2 = join5(homedir4(), ".config", "opencode");
|
|
22830
|
+
var USER_CONFIG_BASE = join5(USER_CONFIG_DIR2, `${PACKAGE_NAME2}`);
|
|
22831
|
+
var PROJECT_CONFIG_BASE = join5(process.cwd(), ".opencode", PACKAGE_NAME2);
|
|
22728
22832
|
function findConfigPath() {
|
|
22729
22833
|
const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
|
|
22730
22834
|
if (projectDetected.format !== "none") {
|
|
@@ -22764,7 +22868,7 @@ function getConfigInfo() {
|
|
|
22764
22868
|
errors: []
|
|
22765
22869
|
};
|
|
22766
22870
|
}
|
|
22767
|
-
if (!
|
|
22871
|
+
if (!existsSync7(configPath.path)) {
|
|
22768
22872
|
return {
|
|
22769
22873
|
exists: false,
|
|
22770
22874
|
path: configPath.path,
|
|
@@ -22821,20 +22925,20 @@ function getConfigCheckDefinition() {
|
|
|
22821
22925
|
}
|
|
22822
22926
|
|
|
22823
22927
|
// src/cli/doctor/checks/auth.ts
|
|
22824
|
-
import { existsSync as
|
|
22825
|
-
import { homedir as
|
|
22826
|
-
import { join as
|
|
22827
|
-
var
|
|
22828
|
-
var
|
|
22829
|
-
var
|
|
22928
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
22929
|
+
import { homedir as homedir5 } from "os";
|
|
22930
|
+
import { join as join6 } from "path";
|
|
22931
|
+
var OPENCODE_CONFIG_DIR = join6(homedir5(), ".config", "opencode");
|
|
22932
|
+
var OPENCODE_JSON = join6(OPENCODE_CONFIG_DIR, "opencode.json");
|
|
22933
|
+
var OPENCODE_JSONC = join6(OPENCODE_CONFIG_DIR, "opencode.jsonc");
|
|
22830
22934
|
var AUTH_PLUGINS = {
|
|
22831
22935
|
anthropic: { plugin: "builtin", name: "Anthropic (Claude)" },
|
|
22832
22936
|
openai: { plugin: "opencode-openai-codex-auth", name: "OpenAI (ChatGPT)" },
|
|
22833
22937
|
google: { plugin: "opencode-antigravity-auth", name: "Google (Gemini)" }
|
|
22834
22938
|
};
|
|
22835
22939
|
function getOpenCodeConfig() {
|
|
22836
|
-
const configPath =
|
|
22837
|
-
if (!
|
|
22940
|
+
const configPath = existsSync8(OPENCODE_JSONC) ? OPENCODE_JSONC : OPENCODE_JSON;
|
|
22941
|
+
if (!existsSync8(configPath))
|
|
22838
22942
|
return null;
|
|
22839
22943
|
try {
|
|
22840
22944
|
const content = readFileSync6(configPath, "utf-8");
|
|
@@ -23266,19 +23370,19 @@ function getLspCheckDefinition() {
|
|
|
23266
23370
|
}
|
|
23267
23371
|
|
|
23268
23372
|
// src/cli/doctor/checks/mcp.ts
|
|
23269
|
-
import { existsSync as
|
|
23270
|
-
import { homedir as
|
|
23271
|
-
import { join as
|
|
23373
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
23374
|
+
import { homedir as homedir6 } from "os";
|
|
23375
|
+
import { join as join7 } from "path";
|
|
23272
23376
|
var BUILTIN_MCP_SERVERS = ["context7", "websearch_exa", "grep_app"];
|
|
23273
23377
|
var MCP_CONFIG_PATHS = [
|
|
23274
|
-
|
|
23275
|
-
|
|
23276
|
-
|
|
23378
|
+
join7(homedir6(), ".claude", ".mcp.json"),
|
|
23379
|
+
join7(process.cwd(), ".mcp.json"),
|
|
23380
|
+
join7(process.cwd(), ".claude", ".mcp.json")
|
|
23277
23381
|
];
|
|
23278
23382
|
function loadUserMcpConfig() {
|
|
23279
23383
|
const servers = {};
|
|
23280
23384
|
for (const configPath of MCP_CONFIG_PATHS) {
|
|
23281
|
-
if (!
|
|
23385
|
+
if (!existsSync9(configPath))
|
|
23282
23386
|
continue;
|
|
23283
23387
|
try {
|
|
23284
23388
|
const content = readFileSync7(configPath, "utf-8");
|
|
@@ -3,3 +3,8 @@ export declare function loadUserCommands(): Record<string, CommandDefinition>;
|
|
|
3
3
|
export declare function loadProjectCommands(): Record<string, CommandDefinition>;
|
|
4
4
|
export declare function loadOpencodeGlobalCommands(): Record<string, CommandDefinition>;
|
|
5
5
|
export declare function loadOpencodeProjectCommands(): Record<string, CommandDefinition>;
|
|
6
|
+
export declare function loadUserCommandsAsync(): Promise<Record<string, CommandDefinition>>;
|
|
7
|
+
export declare function loadProjectCommandsAsync(): Promise<Record<string, CommandDefinition>>;
|
|
8
|
+
export declare function loadOpencodeGlobalCommandsAsync(): Promise<Record<string, CommandDefinition>>;
|
|
9
|
+
export declare function loadOpencodeProjectCommandsAsync(): Promise<Record<string, CommandDefinition>>;
|
|
10
|
+
export declare function loadAllCommandsAsync(): Promise<Record<string, CommandDefinition>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PendingContext, RegisterContextOptions } from "./types";
|
|
2
|
+
export declare class ContextCollector {
|
|
3
|
+
private sessions;
|
|
4
|
+
register(sessionID: string, options: RegisterContextOptions): void;
|
|
5
|
+
getPending(sessionID: string): PendingContext;
|
|
6
|
+
consume(sessionID: string): PendingContext;
|
|
7
|
+
clear(sessionID: string): void;
|
|
8
|
+
hasPending(sessionID: string): boolean;
|
|
9
|
+
private sortEntries;
|
|
10
|
+
}
|
|
11
|
+
export declare const contextCollector: ContextCollector;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ContextCollector, contextCollector } from "./collector";
|
|
2
|
+
export { injectPendingContext, createContextInjectorHook, createContextInjectorMessagesTransformHook, } from "./injector";
|
|
3
|
+
export type { ContextSourceType, ContextPriority, ContextEntry, RegisterContextOptions, PendingContext, MessageContext, OutputParts, InjectionStrategy, } from "./types";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ContextCollector } from "./collector";
|
|
2
|
+
import type { Message, Part } from "@opencode-ai/sdk";
|
|
3
|
+
interface OutputPart {
|
|
4
|
+
type: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
interface InjectionResult {
|
|
9
|
+
injected: boolean;
|
|
10
|
+
contextLength: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function injectPendingContext(collector: ContextCollector, sessionID: string, parts: OutputPart[]): InjectionResult;
|
|
13
|
+
interface ChatMessageInput {
|
|
14
|
+
sessionID: string;
|
|
15
|
+
agent?: string;
|
|
16
|
+
model?: {
|
|
17
|
+
providerID: string;
|
|
18
|
+
modelID: string;
|
|
19
|
+
};
|
|
20
|
+
messageID?: string;
|
|
21
|
+
}
|
|
22
|
+
interface ChatMessageOutput {
|
|
23
|
+
message: Record<string, unknown>;
|
|
24
|
+
parts: OutputPart[];
|
|
25
|
+
}
|
|
26
|
+
export declare function createContextInjectorHook(collector: ContextCollector): {
|
|
27
|
+
"chat.message": (_input: ChatMessageInput, _output: ChatMessageOutput) => Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
interface MessageWithParts {
|
|
30
|
+
info: Message;
|
|
31
|
+
parts: Part[];
|
|
32
|
+
}
|
|
33
|
+
type MessagesTransformHook = {
|
|
34
|
+
"experimental.chat.messages.transform"?: (input: Record<string, never>, output: {
|
|
35
|
+
messages: MessageWithParts[];
|
|
36
|
+
}) => Promise<void>;
|
|
37
|
+
};
|
|
38
|
+
export declare function createContextInjectorMessagesTransformHook(collector: ContextCollector): MessagesTransformHook;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source identifier for context injection
|
|
3
|
+
* Each source registers context that will be merged and injected together
|
|
4
|
+
*/
|
|
5
|
+
export type ContextSourceType = "keyword-detector" | "rules-injector" | "directory-agents" | "directory-readme" | "custom";
|
|
6
|
+
/**
|
|
7
|
+
* Priority levels for context ordering
|
|
8
|
+
* Higher priority contexts appear first in the merged output
|
|
9
|
+
*/
|
|
10
|
+
export type ContextPriority = "critical" | "high" | "normal" | "low";
|
|
11
|
+
/**
|
|
12
|
+
* A single context entry registered by a source
|
|
13
|
+
*/
|
|
14
|
+
export interface ContextEntry {
|
|
15
|
+
/** Unique identifier for this entry within the source */
|
|
16
|
+
id: string;
|
|
17
|
+
/** The source that registered this context */
|
|
18
|
+
source: ContextSourceType;
|
|
19
|
+
/** The actual context content to inject */
|
|
20
|
+
content: string;
|
|
21
|
+
/** Priority for ordering (default: normal) */
|
|
22
|
+
priority: ContextPriority;
|
|
23
|
+
/** Timestamp when registered */
|
|
24
|
+
timestamp: number;
|
|
25
|
+
/** Optional metadata for debugging/logging */
|
|
26
|
+
metadata?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for registering context
|
|
30
|
+
*/
|
|
31
|
+
export interface RegisterContextOptions {
|
|
32
|
+
/** Unique ID for this context entry (used for deduplication) */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Source identifier */
|
|
35
|
+
source: ContextSourceType;
|
|
36
|
+
/** The content to inject */
|
|
37
|
+
content: string;
|
|
38
|
+
/** Priority for ordering (default: normal) */
|
|
39
|
+
priority?: ContextPriority;
|
|
40
|
+
/** Optional metadata */
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Result of getting pending context for a session
|
|
45
|
+
*/
|
|
46
|
+
export interface PendingContext {
|
|
47
|
+
/** Merged context string, ready for injection */
|
|
48
|
+
merged: string;
|
|
49
|
+
/** Individual entries that were merged */
|
|
50
|
+
entries: ContextEntry[];
|
|
51
|
+
/** Whether there's any content to inject */
|
|
52
|
+
hasContent: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Message context from the original user message
|
|
56
|
+
* Used when injecting to match the message format
|
|
57
|
+
*/
|
|
58
|
+
export interface MessageContext {
|
|
59
|
+
agent?: string;
|
|
60
|
+
model?: {
|
|
61
|
+
providerID?: string;
|
|
62
|
+
modelID?: string;
|
|
63
|
+
};
|
|
64
|
+
path?: {
|
|
65
|
+
cwd?: string;
|
|
66
|
+
root?: string;
|
|
67
|
+
};
|
|
68
|
+
tools?: Record<string, boolean>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Output parts from chat.message hook
|
|
72
|
+
*/
|
|
73
|
+
export interface OutputParts {
|
|
74
|
+
parts: Array<{
|
|
75
|
+
type: string;
|
|
76
|
+
text?: string;
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
}>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Injection strategy
|
|
82
|
+
*/
|
|
83
|
+
export type InjectionStrategy = "prepend-parts" | "storage" | "auto";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SkillScope, LoadedSkill } from "./types";
|
|
2
|
+
import type { SkillMcpConfig } from "../skill-mcp-manager/types";
|
|
3
|
+
export declare function mapWithConcurrency<T, R>(items: T[], mapper: (item: T) => Promise<R>, concurrency: number): Promise<R[]>;
|
|
4
|
+
export declare function loadMcpJsonFromDirAsync(skillDir: string): Promise<SkillMcpConfig | undefined>;
|
|
5
|
+
export declare function loadSkillFromPathAsync(skillPath: string, resolvedPath: string, defaultName: string, scope: SkillScope): Promise<LoadedSkill | null>;
|
|
6
|
+
export declare function discoverSkillsInDirAsync(skillsDir: string): Promise<LoadedSkill[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|