evil-omo 3.15.2 → 3.15.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 +27 -16
- package/README.ko.md +27 -16
- package/README.md +1 -1
- package/README.ru.md +20 -9
- package/README.zh-cn.md +26 -15
- package/bin/evil-omo.js +1 -1
- package/bin/platform.js +14 -17
- package/dist/agents/hephaestus/gpt-5-4.d.ts +22 -1
- package/dist/cli/config-manager/config-context.d.ts +0 -1
- package/dist/cli/index.js +846 -492
- package/dist/cli/run/continuation-state.d.ts +2 -1
- package/dist/create-runtime-tmux-config.d.ts +1 -0
- package/dist/features/background-agent/spawner.d.ts +3 -0
- package/dist/features/boulder-state/storage.d.ts +1 -1
- package/dist/features/boulder-state/types.d.ts +1 -0
- package/dist/features/claude-code-plugin-loader/discovery.d.ts +2 -1
- package/dist/features/claude-code-plugin-loader/loader.d.ts +1 -0
- package/dist/features/claude-code-plugin-loader/types.d.ts +10 -0
- package/dist/hooks/atlas/background-launch-session-tracking.d.ts +11 -0
- package/dist/hooks/atlas/boulder-continuation-injector.d.ts +2 -1
- package/dist/hooks/atlas/task-context.d.ts +7 -0
- package/dist/hooks/atlas/types.d.ts +1 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +5 -5
- package/dist/hooks/comment-checker/downloader.d.ts +1 -1
- package/dist/index.js +5288 -4903
- package/dist/plugin/tool-registry.d.ts +1 -0
- package/dist/shared/agent-display-names.d.ts +1 -0
- package/dist/shared/system-directive.d.ts +5 -5
- package/dist/tools/delegate-task/resolve-call-id.d.ts +2 -0
- package/package.json +12 -12
- package/postinstall.mjs +14 -3
package/dist/cli/index.js
CHANGED
|
@@ -4917,6 +4917,196 @@ var init_command_executor = __esm(() => {
|
|
|
4917
4917
|
// src/shared/contains-path.ts
|
|
4918
4918
|
var init_contains_path = () => {};
|
|
4919
4919
|
|
|
4920
|
+
// src/shared/logger.ts
|
|
4921
|
+
import * as fs from "fs";
|
|
4922
|
+
import * as os from "os";
|
|
4923
|
+
import * as path from "path";
|
|
4924
|
+
function flush() {
|
|
4925
|
+
if (buffer.length === 0)
|
|
4926
|
+
return;
|
|
4927
|
+
const data = buffer.join("");
|
|
4928
|
+
buffer = [];
|
|
4929
|
+
try {
|
|
4930
|
+
fs.appendFileSync(logFile, data);
|
|
4931
|
+
} catch {}
|
|
4932
|
+
}
|
|
4933
|
+
function scheduleFlush() {
|
|
4934
|
+
if (flushTimer)
|
|
4935
|
+
return;
|
|
4936
|
+
flushTimer = setTimeout(() => {
|
|
4937
|
+
flushTimer = null;
|
|
4938
|
+
flush();
|
|
4939
|
+
}, FLUSH_INTERVAL_MS);
|
|
4940
|
+
}
|
|
4941
|
+
function log(message, data) {
|
|
4942
|
+
try {
|
|
4943
|
+
const timestamp2 = new Date().toISOString();
|
|
4944
|
+
const logEntry = `[${timestamp2}] ${message} ${data ? JSON.stringify(data) : ""}
|
|
4945
|
+
`;
|
|
4946
|
+
buffer.push(logEntry);
|
|
4947
|
+
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
4948
|
+
flush();
|
|
4949
|
+
} else {
|
|
4950
|
+
scheduleFlush();
|
|
4951
|
+
}
|
|
4952
|
+
} catch {}
|
|
4953
|
+
}
|
|
4954
|
+
var logFile, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50;
|
|
4955
|
+
var init_logger = __esm(() => {
|
|
4956
|
+
logFile = path.join(os.tmpdir(), "evil-omo.log");
|
|
4957
|
+
buffer = [];
|
|
4958
|
+
});
|
|
4959
|
+
|
|
4960
|
+
// src/shared/file-reference-resolver.ts
|
|
4961
|
+
var init_file_reference_resolver = __esm(() => {
|
|
4962
|
+
init_contains_path();
|
|
4963
|
+
init_logger();
|
|
4964
|
+
});
|
|
4965
|
+
// src/shared/deep-merge.ts
|
|
4966
|
+
function isPlainObject(value) {
|
|
4967
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
4968
|
+
}
|
|
4969
|
+
function deepMerge(base, override, depth = 0) {
|
|
4970
|
+
if (!base && !override)
|
|
4971
|
+
return;
|
|
4972
|
+
if (!base)
|
|
4973
|
+
return override;
|
|
4974
|
+
if (!override)
|
|
4975
|
+
return base;
|
|
4976
|
+
if (depth > MAX_DEPTH)
|
|
4977
|
+
return override ?? base;
|
|
4978
|
+
const result = { ...base };
|
|
4979
|
+
for (const key of Object.keys(override)) {
|
|
4980
|
+
if (DANGEROUS_KEYS.has(key))
|
|
4981
|
+
continue;
|
|
4982
|
+
const baseValue = base[key];
|
|
4983
|
+
const overrideValue = override[key];
|
|
4984
|
+
if (overrideValue === undefined)
|
|
4985
|
+
continue;
|
|
4986
|
+
if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
|
|
4987
|
+
result[key] = deepMerge(baseValue, overrideValue, depth + 1);
|
|
4988
|
+
} else {
|
|
4989
|
+
result[key] = overrideValue;
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
return result;
|
|
4993
|
+
}
|
|
4994
|
+
var DANGEROUS_KEYS, MAX_DEPTH = 50;
|
|
4995
|
+
var init_deep_merge = __esm(() => {
|
|
4996
|
+
DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
4997
|
+
});
|
|
4998
|
+
|
|
4999
|
+
// src/shared/snake-case.ts
|
|
5000
|
+
var init_snake_case = __esm(() => {
|
|
5001
|
+
init_deep_merge();
|
|
5002
|
+
});
|
|
5003
|
+
|
|
5004
|
+
// src/shared/tool-name.ts
|
|
5005
|
+
var init_tool_name = () => {};
|
|
5006
|
+
|
|
5007
|
+
// src/shared/pattern-matcher.ts
|
|
5008
|
+
var regexCache;
|
|
5009
|
+
var init_pattern_matcher = __esm(() => {
|
|
5010
|
+
regexCache = new Map;
|
|
5011
|
+
});
|
|
5012
|
+
// src/shared/file-utils.ts
|
|
5013
|
+
import { lstatSync, realpathSync } from "fs";
|
|
5014
|
+
function normalizeDarwinRealpath(filePath) {
|
|
5015
|
+
return filePath.startsWith("/private/var/") ? filePath.slice("/private".length) : filePath;
|
|
5016
|
+
}
|
|
5017
|
+
function resolveSymlink(filePath) {
|
|
5018
|
+
try {
|
|
5019
|
+
return normalizeDarwinRealpath(realpathSync(filePath));
|
|
5020
|
+
} catch {
|
|
5021
|
+
return filePath;
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
var init_file_utils = () => {};
|
|
5025
|
+
|
|
5026
|
+
// src/shared/context-limit-resolver.ts
|
|
5027
|
+
var init_context_limit_resolver = () => {};
|
|
5028
|
+
|
|
5029
|
+
// src/shared/normalize-sdk-response.ts
|
|
5030
|
+
function normalizeSDKResponse(response, fallback, options) {
|
|
5031
|
+
if (response === null || response === undefined) {
|
|
5032
|
+
return fallback;
|
|
5033
|
+
}
|
|
5034
|
+
if (Array.isArray(response)) {
|
|
5035
|
+
return response;
|
|
5036
|
+
}
|
|
5037
|
+
if (typeof response === "object" && "data" in response) {
|
|
5038
|
+
const data = response.data;
|
|
5039
|
+
if (data !== null && data !== undefined) {
|
|
5040
|
+
return data;
|
|
5041
|
+
}
|
|
5042
|
+
if (options?.preferResponseOnMissingData === true) {
|
|
5043
|
+
return response;
|
|
5044
|
+
}
|
|
5045
|
+
return fallback;
|
|
5046
|
+
}
|
|
5047
|
+
if (options?.preferResponseOnMissingData === true) {
|
|
5048
|
+
return response;
|
|
5049
|
+
}
|
|
5050
|
+
return fallback;
|
|
5051
|
+
}
|
|
5052
|
+
|
|
5053
|
+
// src/shared/dynamic-truncator.ts
|
|
5054
|
+
var init_dynamic_truncator = __esm(() => {
|
|
5055
|
+
init_context_limit_resolver();
|
|
5056
|
+
});
|
|
5057
|
+
|
|
5058
|
+
// src/shared/data-path.ts
|
|
5059
|
+
import * as path2 from "path";
|
|
5060
|
+
import * as os2 from "os";
|
|
5061
|
+
import { accessSync, constants, mkdirSync } from "fs";
|
|
5062
|
+
function resolveWritableDirectory(preferredDir, fallbackSuffix) {
|
|
5063
|
+
try {
|
|
5064
|
+
mkdirSync(preferredDir, { recursive: true });
|
|
5065
|
+
accessSync(preferredDir, constants.W_OK);
|
|
5066
|
+
return preferredDir;
|
|
5067
|
+
} catch {
|
|
5068
|
+
const fallbackDir = path2.join(os2.tmpdir(), fallbackSuffix);
|
|
5069
|
+
mkdirSync(fallbackDir, { recursive: true });
|
|
5070
|
+
return fallbackDir;
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
function getDataDir() {
|
|
5074
|
+
const preferredDir = process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
|
|
5075
|
+
return resolveWritableDirectory(preferredDir, "opencode-data");
|
|
5076
|
+
}
|
|
5077
|
+
function getOpenCodeStorageDir() {
|
|
5078
|
+
return path2.join(getDataDir(), "opencode", "storage");
|
|
5079
|
+
}
|
|
5080
|
+
function getCacheDir() {
|
|
5081
|
+
const preferredDir = process.env.XDG_CACHE_HOME ?? path2.join(os2.homedir(), ".cache");
|
|
5082
|
+
return resolveWritableDirectory(preferredDir, "opencode-cache");
|
|
5083
|
+
}
|
|
5084
|
+
function getOmoOpenCodeCacheDir() {
|
|
5085
|
+
return path2.join(getCacheDir(), "evil-omo");
|
|
5086
|
+
}
|
|
5087
|
+
function getOpenCodeCacheDir() {
|
|
5088
|
+
return path2.join(getCacheDir(), "opencode");
|
|
5089
|
+
}
|
|
5090
|
+
var init_data_path = () => {};
|
|
5091
|
+
|
|
5092
|
+
// src/shared/config-errors.ts
|
|
5093
|
+
function getConfigLoadErrors() {
|
|
5094
|
+
return configLoadErrors;
|
|
5095
|
+
}
|
|
5096
|
+
function clearConfigLoadErrors() {
|
|
5097
|
+
configLoadErrors = [];
|
|
5098
|
+
}
|
|
5099
|
+
function addConfigLoadError(error) {
|
|
5100
|
+
configLoadErrors.push(error);
|
|
5101
|
+
}
|
|
5102
|
+
var configLoadErrors;
|
|
5103
|
+
var init_config_errors = __esm(() => {
|
|
5104
|
+
configLoadErrors = [];
|
|
5105
|
+
});
|
|
5106
|
+
|
|
5107
|
+
// src/shared/claude-config-dir.ts
|
|
5108
|
+
var init_claude_config_dir = () => {};
|
|
5109
|
+
|
|
4920
5110
|
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
4921
5111
|
function createScanner(text, ignoreTrivia = false) {
|
|
4922
5112
|
const len = text.length;
|
|
@@ -5781,8 +5971,30 @@ var init_main = __esm(() => {
|
|
|
5781
5971
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
5782
5972
|
});
|
|
5783
5973
|
|
|
5974
|
+
// src/shared/plugin-identity.ts
|
|
5975
|
+
import { join as join3 } from "path";
|
|
5976
|
+
function detectManagedConfigFile(directory) {
|
|
5977
|
+
for (const baseName of ALL_CONFIG_BASENAMES) {
|
|
5978
|
+
const detected = detectConfigFile(join3(directory, baseName));
|
|
5979
|
+
if (detected.format !== "none") {
|
|
5980
|
+
return { ...detected, baseName };
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5983
|
+
return {
|
|
5984
|
+
format: "none",
|
|
5985
|
+
path: join3(directory, `${CONFIG_BASENAME}.json`),
|
|
5986
|
+
baseName: CONFIG_BASENAME
|
|
5987
|
+
};
|
|
5988
|
+
}
|
|
5989
|
+
var PLUGIN_NAME = "evil-omo", LEGACY_PLUGIN_NAME = "oh-my-opencode", CONFIG_BASENAME = "evil-omo", LEGACY_CONFIG_BASENAME = "oh-my-opencode", ALL_CONFIG_BASENAMES;
|
|
5990
|
+
var init_plugin_identity = __esm(() => {
|
|
5991
|
+
init_jsonc_parser();
|
|
5992
|
+
ALL_CONFIG_BASENAMES = [CONFIG_BASENAME, LEGACY_CONFIG_BASENAME];
|
|
5993
|
+
});
|
|
5994
|
+
|
|
5784
5995
|
// src/shared/jsonc-parser.ts
|
|
5785
5996
|
import { existsSync, readFileSync } from "fs";
|
|
5997
|
+
import { join as join4 } from "path";
|
|
5786
5998
|
function parseJsonc(content) {
|
|
5787
5999
|
const errors = [];
|
|
5788
6000
|
const result = parse2(content, errors, {
|
|
@@ -5806,202 +6018,25 @@ function detectConfigFile(basePath) {
|
|
|
5806
6018
|
}
|
|
5807
6019
|
return { format: "none", path: jsonPath };
|
|
5808
6020
|
}
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
return entry === packageName || entry.startsWith(`${packageName}@`);
|
|
5818
|
-
}
|
|
5819
|
-
function findManagedPluginEntry(plugins) {
|
|
5820
|
-
for (const [index, entry] of plugins.entries()) {
|
|
5821
|
-
for (const packageName of ALL_PLUGIN_NAMES) {
|
|
5822
|
-
if (matchesManagedName(entry, packageName)) {
|
|
5823
|
-
return { index, packageName };
|
|
5824
|
-
}
|
|
5825
|
-
}
|
|
5826
|
-
}
|
|
5827
|
-
return null;
|
|
5828
|
-
}
|
|
5829
|
-
function detectManagedConfigFile(directory) {
|
|
5830
|
-
for (const baseName of ALL_CONFIG_BASENAMES) {
|
|
5831
|
-
const detected = detectConfigFile(join(directory, baseName));
|
|
5832
|
-
if (detected.format !== "none") {
|
|
5833
|
-
return { ...detected, baseName };
|
|
5834
|
-
}
|
|
5835
|
-
}
|
|
5836
|
-
return {
|
|
5837
|
-
format: "none",
|
|
5838
|
-
path: join(directory, `${CONFIG_BASENAME}.json`),
|
|
5839
|
-
baseName: CONFIG_BASENAME
|
|
5840
|
-
};
|
|
5841
|
-
}
|
|
5842
|
-
var PLUGIN_NAME = "evil-omo", LEGACY_PLUGIN_NAME = "oh-my-opencode", ALL_PLUGIN_NAMES, CONFIG_BASENAME = "evil-omo", LEGACY_CONFIG_BASENAME = "oh-my-opencode", ALL_CONFIG_BASENAMES, LOG_FILENAME = "evil-omo.log", CACHE_DIR_NAME = "evil-omo", SCHEMA_FILENAME = "evil-omo.schema.json";
|
|
5843
|
-
var init_plugin_identity = __esm(() => {
|
|
5844
|
-
init_jsonc_parser();
|
|
5845
|
-
ALL_PLUGIN_NAMES = [PLUGIN_NAME, LEGACY_PLUGIN_NAME];
|
|
5846
|
-
ALL_CONFIG_BASENAMES = [CONFIG_BASENAME, LEGACY_CONFIG_BASENAME];
|
|
5847
|
-
});
|
|
5848
|
-
|
|
5849
|
-
// src/shared/logger.ts
|
|
5850
|
-
import * as fs from "fs";
|
|
5851
|
-
import * as os from "os";
|
|
5852
|
-
import * as path from "path";
|
|
5853
|
-
function log(message, data) {
|
|
5854
|
-
try {
|
|
5855
|
-
const timestamp2 = new Date().toISOString();
|
|
5856
|
-
const logEntry = `[${timestamp2}] ${message} ${data ? JSON.stringify(data) : ""}
|
|
5857
|
-
`;
|
|
5858
|
-
fs.appendFileSync(logFile, logEntry);
|
|
5859
|
-
} catch {}
|
|
5860
|
-
}
|
|
5861
|
-
var logFile;
|
|
5862
|
-
var init_logger = __esm(() => {
|
|
5863
|
-
init_plugin_identity();
|
|
5864
|
-
logFile = path.join(os.tmpdir(), LOG_FILENAME);
|
|
5865
|
-
});
|
|
5866
|
-
|
|
5867
|
-
// src/shared/file-reference-resolver.ts
|
|
5868
|
-
var init_file_reference_resolver = __esm(() => {
|
|
5869
|
-
init_contains_path();
|
|
5870
|
-
init_logger();
|
|
5871
|
-
});
|
|
5872
|
-
// src/shared/deep-merge.ts
|
|
5873
|
-
function isPlainObject(value) {
|
|
5874
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
5875
|
-
}
|
|
5876
|
-
function deepMerge(base, override, depth = 0) {
|
|
5877
|
-
if (!base && !override)
|
|
5878
|
-
return;
|
|
5879
|
-
if (!base)
|
|
5880
|
-
return override;
|
|
5881
|
-
if (!override)
|
|
5882
|
-
return base;
|
|
5883
|
-
if (depth > MAX_DEPTH)
|
|
5884
|
-
return override ?? base;
|
|
5885
|
-
const result = { ...base };
|
|
5886
|
-
for (const key of Object.keys(override)) {
|
|
5887
|
-
if (DANGEROUS_KEYS.has(key))
|
|
5888
|
-
continue;
|
|
5889
|
-
const baseValue = base[key];
|
|
5890
|
-
const overrideValue = override[key];
|
|
5891
|
-
if (overrideValue === undefined)
|
|
5892
|
-
continue;
|
|
5893
|
-
if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
|
|
5894
|
-
result[key] = deepMerge(baseValue, overrideValue, depth + 1);
|
|
5895
|
-
} else {
|
|
5896
|
-
result[key] = overrideValue;
|
|
5897
|
-
}
|
|
5898
|
-
}
|
|
5899
|
-
return result;
|
|
5900
|
-
}
|
|
5901
|
-
var DANGEROUS_KEYS, MAX_DEPTH = 50;
|
|
5902
|
-
var init_deep_merge = __esm(() => {
|
|
5903
|
-
DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
5904
|
-
});
|
|
5905
|
-
|
|
5906
|
-
// src/shared/snake-case.ts
|
|
5907
|
-
var init_snake_case = __esm(() => {
|
|
5908
|
-
init_deep_merge();
|
|
5909
|
-
});
|
|
5910
|
-
|
|
5911
|
-
// src/shared/tool-name.ts
|
|
5912
|
-
var init_tool_name = () => {};
|
|
5913
|
-
|
|
5914
|
-
// src/shared/pattern-matcher.ts
|
|
5915
|
-
var regexCache;
|
|
5916
|
-
var init_pattern_matcher = __esm(() => {
|
|
5917
|
-
regexCache = new Map;
|
|
5918
|
-
});
|
|
5919
|
-
// src/shared/file-utils.ts
|
|
5920
|
-
import { lstatSync, realpathSync } from "fs";
|
|
5921
|
-
function normalizeDarwinRealpath(filePath) {
|
|
5922
|
-
return filePath.startsWith("/private/var/") ? filePath.slice("/private".length) : filePath;
|
|
5923
|
-
}
|
|
5924
|
-
function resolveSymlink(filePath) {
|
|
5925
|
-
try {
|
|
5926
|
-
return normalizeDarwinRealpath(realpathSync(filePath));
|
|
5927
|
-
} catch {
|
|
5928
|
-
return filePath;
|
|
5929
|
-
}
|
|
5930
|
-
}
|
|
5931
|
-
var init_file_utils = () => {};
|
|
5932
|
-
|
|
5933
|
-
// src/shared/context-limit-resolver.ts
|
|
5934
|
-
var init_context_limit_resolver = () => {};
|
|
5935
|
-
|
|
5936
|
-
// src/shared/normalize-sdk-response.ts
|
|
5937
|
-
function normalizeSDKResponse(response, fallback, options) {
|
|
5938
|
-
if (response === null || response === undefined) {
|
|
5939
|
-
return fallback;
|
|
5940
|
-
}
|
|
5941
|
-
if (Array.isArray(response)) {
|
|
5942
|
-
return response;
|
|
5943
|
-
}
|
|
5944
|
-
if (typeof response === "object" && "data" in response) {
|
|
5945
|
-
const data = response.data;
|
|
5946
|
-
if (data !== null && data !== undefined) {
|
|
5947
|
-
return data;
|
|
5948
|
-
}
|
|
5949
|
-
if (options?.preferResponseOnMissingData === true) {
|
|
5950
|
-
return response;
|
|
5951
|
-
}
|
|
5952
|
-
return fallback;
|
|
6021
|
+
function detectPluginConfigFile(dir) {
|
|
6022
|
+
const canonicalResult = detectConfigFile(join4(dir, CONFIG_BASENAME));
|
|
6023
|
+
const legacyResult = detectConfigFile(join4(dir, LEGACY_CONFIG_BASENAME));
|
|
6024
|
+
if (canonicalResult.format !== "none") {
|
|
6025
|
+
return {
|
|
6026
|
+
...canonicalResult,
|
|
6027
|
+
legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined
|
|
6028
|
+
};
|
|
5953
6029
|
}
|
|
5954
|
-
if (
|
|
5955
|
-
return
|
|
6030
|
+
if (legacyResult.format !== "none") {
|
|
6031
|
+
return legacyResult;
|
|
5956
6032
|
}
|
|
5957
|
-
return
|
|
6033
|
+
return { format: "none", path: join4(dir, `${CONFIG_BASENAME}.json`) };
|
|
5958
6034
|
}
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
var init_dynamic_truncator = __esm(() => {
|
|
5962
|
-
init_context_limit_resolver();
|
|
5963
|
-
});
|
|
5964
|
-
|
|
5965
|
-
// src/shared/data-path.ts
|
|
5966
|
-
import * as path2 from "path";
|
|
5967
|
-
import * as os2 from "os";
|
|
5968
|
-
function getDataDir() {
|
|
5969
|
-
return process.env.XDG_DATA_HOME ?? path2.join(os2.homedir(), ".local", "share");
|
|
5970
|
-
}
|
|
5971
|
-
function getOpenCodeStorageDir() {
|
|
5972
|
-
return path2.join(getDataDir(), "opencode", "storage");
|
|
5973
|
-
}
|
|
5974
|
-
function getCacheDir() {
|
|
5975
|
-
return process.env.XDG_CACHE_HOME ?? path2.join(os2.homedir(), ".cache");
|
|
5976
|
-
}
|
|
5977
|
-
function getOmoOpenCodeCacheDir() {
|
|
5978
|
-
return path2.join(getCacheDir(), CACHE_DIR_NAME);
|
|
5979
|
-
}
|
|
5980
|
-
function getOpenCodeCacheDir() {
|
|
5981
|
-
return path2.join(getCacheDir(), "opencode");
|
|
5982
|
-
}
|
|
5983
|
-
var init_data_path = __esm(() => {
|
|
6035
|
+
var init_jsonc_parser = __esm(() => {
|
|
6036
|
+
init_main();
|
|
5984
6037
|
init_plugin_identity();
|
|
5985
6038
|
});
|
|
5986
6039
|
|
|
5987
|
-
// src/shared/config-errors.ts
|
|
5988
|
-
function getConfigLoadErrors() {
|
|
5989
|
-
return configLoadErrors;
|
|
5990
|
-
}
|
|
5991
|
-
function clearConfigLoadErrors() {
|
|
5992
|
-
configLoadErrors = [];
|
|
5993
|
-
}
|
|
5994
|
-
function addConfigLoadError(error) {
|
|
5995
|
-
configLoadErrors.push(error);
|
|
5996
|
-
}
|
|
5997
|
-
var configLoadErrors;
|
|
5998
|
-
var init_config_errors = __esm(() => {
|
|
5999
|
-
configLoadErrors = [];
|
|
6000
|
-
});
|
|
6001
|
-
|
|
6002
|
-
// src/shared/claude-config-dir.ts
|
|
6003
|
-
var init_claude_config_dir = () => {};
|
|
6004
|
-
|
|
6005
6040
|
// src/shared/migration/agent-names.ts
|
|
6006
6041
|
function migrateAgentNames(agents) {
|
|
6007
6042
|
const migrated = {};
|
|
@@ -6277,9 +6312,9 @@ var init_migration = __esm(() => {
|
|
|
6277
6312
|
});
|
|
6278
6313
|
|
|
6279
6314
|
// src/shared/opencode-config-dir.ts
|
|
6280
|
-
import { existsSync as existsSync2 } from "fs";
|
|
6315
|
+
import { existsSync as existsSync2, realpathSync as realpathSync2 } from "fs";
|
|
6281
6316
|
import { homedir as homedir2 } from "os";
|
|
6282
|
-
import { join as
|
|
6317
|
+
import { join as join5, resolve, win32 } from "path";
|
|
6283
6318
|
function isDevBuild(version) {
|
|
6284
6319
|
if (!version)
|
|
6285
6320
|
return false;
|
|
@@ -6289,25 +6324,35 @@ function getTauriConfigDir(identifier) {
|
|
|
6289
6324
|
const platform = process.platform;
|
|
6290
6325
|
switch (platform) {
|
|
6291
6326
|
case "darwin":
|
|
6292
|
-
return
|
|
6327
|
+
return join5(homedir2(), "Library", "Application Support", identifier);
|
|
6293
6328
|
case "win32": {
|
|
6294
|
-
const appData = process.env.APPDATA ||
|
|
6295
|
-
return
|
|
6329
|
+
const appData = process.env.APPDATA || join5(homedir2(), "AppData", "Roaming");
|
|
6330
|
+
return win32.join(appData, identifier);
|
|
6296
6331
|
}
|
|
6297
6332
|
case "linux":
|
|
6298
6333
|
default: {
|
|
6299
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
6300
|
-
return
|
|
6334
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
|
|
6335
|
+
return join5(xdgConfig, identifier);
|
|
6301
6336
|
}
|
|
6302
6337
|
}
|
|
6303
6338
|
}
|
|
6339
|
+
function resolveConfigPath(pathValue) {
|
|
6340
|
+
const resolvedPath = resolve(pathValue);
|
|
6341
|
+
if (!existsSync2(resolvedPath))
|
|
6342
|
+
return resolvedPath;
|
|
6343
|
+
try {
|
|
6344
|
+
return realpathSync2(resolvedPath);
|
|
6345
|
+
} catch {
|
|
6346
|
+
return resolvedPath;
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6304
6349
|
function getCliConfigDir() {
|
|
6305
6350
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
6306
6351
|
if (envConfigDir) {
|
|
6307
|
-
return
|
|
6352
|
+
return resolveConfigPath(envConfigDir);
|
|
6308
6353
|
}
|
|
6309
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
6310
|
-
return
|
|
6354
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir2(), ".config");
|
|
6355
|
+
return resolveConfigPath(join5(xdgConfig, "opencode"));
|
|
6311
6356
|
}
|
|
6312
6357
|
function getOpenCodeConfigDir(options) {
|
|
6313
6358
|
const { binary: binary2, version, checkExisting = true } = options;
|
|
@@ -6315,11 +6360,12 @@ function getOpenCodeConfigDir(options) {
|
|
|
6315
6360
|
return getCliConfigDir();
|
|
6316
6361
|
}
|
|
6317
6362
|
const identifier = isDevBuild(version) ? TAURI_APP_IDENTIFIER_DEV : TAURI_APP_IDENTIFIER;
|
|
6318
|
-
const
|
|
6363
|
+
const tauriDirBase = getTauriConfigDir(identifier);
|
|
6364
|
+
const tauriDir = process.platform === "win32" ? win32.isAbsolute(tauriDirBase) ? win32.normalize(tauriDirBase) : win32.resolve(tauriDirBase) : resolveConfigPath(tauriDirBase);
|
|
6319
6365
|
if (checkExisting) {
|
|
6320
6366
|
const legacyDir = getCliConfigDir();
|
|
6321
|
-
const legacyConfig =
|
|
6322
|
-
const legacyConfigC =
|
|
6367
|
+
const legacyConfig = join5(legacyDir, "opencode.json");
|
|
6368
|
+
const legacyConfigC = join5(legacyDir, "opencode.jsonc");
|
|
6323
6369
|
if (existsSync2(legacyConfig) || existsSync2(legacyConfigC)) {
|
|
6324
6370
|
return legacyDir;
|
|
6325
6371
|
}
|
|
@@ -6330,10 +6376,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
6330
6376
|
const configDir = getOpenCodeConfigDir(options);
|
|
6331
6377
|
return {
|
|
6332
6378
|
configDir,
|
|
6333
|
-
configJson:
|
|
6334
|
-
configJsonc:
|
|
6335
|
-
packageJson:
|
|
6336
|
-
omoConfig:
|
|
6379
|
+
configJson: join5(configDir, "opencode.json"),
|
|
6380
|
+
configJsonc: join5(configDir, "opencode.jsonc"),
|
|
6381
|
+
packageJson: join5(configDir, "package.json"),
|
|
6382
|
+
omoConfig: join5(configDir, `${CONFIG_BASENAME}.json`)
|
|
6337
6383
|
};
|
|
6338
6384
|
}
|
|
6339
6385
|
var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
|
|
@@ -6342,18 +6388,88 @@ var init_opencode_config_dir = __esm(() => {
|
|
|
6342
6388
|
});
|
|
6343
6389
|
|
|
6344
6390
|
// src/shared/opencode-version.ts
|
|
6345
|
-
|
|
6391
|
+
import { execSync } from "child_process";
|
|
6392
|
+
function parseVersion(version) {
|
|
6393
|
+
const cleaned = version.replace(/^v/, "").split("-")[0];
|
|
6394
|
+
return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
|
|
6395
|
+
}
|
|
6396
|
+
function compareVersions(a, b) {
|
|
6397
|
+
const partsA = parseVersion(a);
|
|
6398
|
+
const partsB = parseVersion(b);
|
|
6399
|
+
const maxLen = Math.max(partsA.length, partsB.length);
|
|
6400
|
+
for (let i2 = 0;i2 < maxLen; i2++) {
|
|
6401
|
+
const numA = partsA[i2] ?? 0;
|
|
6402
|
+
const numB = partsB[i2] ?? 0;
|
|
6403
|
+
if (numA < numB)
|
|
6404
|
+
return -1;
|
|
6405
|
+
if (numA > numB)
|
|
6406
|
+
return 1;
|
|
6407
|
+
}
|
|
6408
|
+
return 0;
|
|
6409
|
+
}
|
|
6410
|
+
function getOpenCodeVersion() {
|
|
6411
|
+
if (cachedVersion !== NOT_CACHED) {
|
|
6412
|
+
return cachedVersion;
|
|
6413
|
+
}
|
|
6414
|
+
try {
|
|
6415
|
+
const result = execSync("opencode --version", {
|
|
6416
|
+
encoding: "utf-8",
|
|
6417
|
+
timeout: 5000,
|
|
6418
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6419
|
+
}).trim();
|
|
6420
|
+
const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
|
|
6421
|
+
cachedVersion = versionMatch?.[1] ?? null;
|
|
6422
|
+
return cachedVersion;
|
|
6423
|
+
} catch {
|
|
6424
|
+
cachedVersion = null;
|
|
6425
|
+
return null;
|
|
6426
|
+
}
|
|
6427
|
+
}
|
|
6428
|
+
function isOpenCodeVersionAtLeast(version) {
|
|
6429
|
+
const current = getOpenCodeVersion();
|
|
6430
|
+
if (!current)
|
|
6431
|
+
return true;
|
|
6432
|
+
return compareVersions(current, version) >= 0;
|
|
6433
|
+
}
|
|
6434
|
+
var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
|
|
6346
6435
|
var init_opencode_version = __esm(() => {
|
|
6347
6436
|
NOT_CACHED = Symbol("NOT_CACHED");
|
|
6437
|
+
cachedVersion = NOT_CACHED;
|
|
6348
6438
|
});
|
|
6349
6439
|
|
|
6350
6440
|
// src/shared/opencode-storage-detection.ts
|
|
6351
|
-
|
|
6441
|
+
import { existsSync as existsSync3 } from "fs";
|
|
6442
|
+
import { join as join6 } from "path";
|
|
6443
|
+
function isSqliteBackend() {
|
|
6444
|
+
if (cachedResult === true)
|
|
6445
|
+
return true;
|
|
6446
|
+
if (cachedResult === false)
|
|
6447
|
+
return false;
|
|
6448
|
+
const check = () => {
|
|
6449
|
+
const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
|
|
6450
|
+
const dbPath = join6(getDataDir(), "opencode", "opencode.db");
|
|
6451
|
+
return versionOk && existsSync3(dbPath);
|
|
6452
|
+
};
|
|
6453
|
+
if (cachedResult === FALSE_PENDING_RETRY) {
|
|
6454
|
+
const result2 = check();
|
|
6455
|
+
cachedResult = result2;
|
|
6456
|
+
return result2;
|
|
6457
|
+
}
|
|
6458
|
+
const result = check();
|
|
6459
|
+
if (result) {
|
|
6460
|
+
cachedResult = true;
|
|
6461
|
+
} else {
|
|
6462
|
+
cachedResult = FALSE_PENDING_RETRY;
|
|
6463
|
+
}
|
|
6464
|
+
return result;
|
|
6465
|
+
}
|
|
6466
|
+
var NOT_CACHED2, FALSE_PENDING_RETRY, cachedResult;
|
|
6352
6467
|
var init_opencode_storage_detection = __esm(() => {
|
|
6353
6468
|
init_data_path();
|
|
6354
6469
|
init_opencode_version();
|
|
6355
6470
|
NOT_CACHED2 = Symbol("NOT_CACHED");
|
|
6356
6471
|
FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
|
|
6472
|
+
cachedResult = NOT_CACHED2;
|
|
6357
6473
|
});
|
|
6358
6474
|
// src/shared/external-plugin-detector.ts
|
|
6359
6475
|
var init_external_plugin_detector = __esm(() => {
|
|
@@ -6764,20 +6880,20 @@ function normalizeModelID(modelID) {
|
|
|
6764
6880
|
}
|
|
6765
6881
|
|
|
6766
6882
|
// src/shared/json-file-cache-store.ts
|
|
6767
|
-
import { existsSync as
|
|
6768
|
-
import { join as
|
|
6883
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
6884
|
+
import { join as join7 } from "path";
|
|
6769
6885
|
function toLogLabel(cacheLabel) {
|
|
6770
6886
|
return cacheLabel.toLowerCase();
|
|
6771
6887
|
}
|
|
6772
6888
|
function createJsonFileCacheStore(options) {
|
|
6773
6889
|
let memoryValue;
|
|
6774
6890
|
function getCacheFilePath() {
|
|
6775
|
-
return
|
|
6891
|
+
return join7(options.getCacheDir(), options.filename);
|
|
6776
6892
|
}
|
|
6777
6893
|
function ensureCacheDir() {
|
|
6778
6894
|
const cacheDir = options.getCacheDir();
|
|
6779
|
-
if (!
|
|
6780
|
-
|
|
6895
|
+
if (!existsSync4(cacheDir)) {
|
|
6896
|
+
mkdirSync2(cacheDir, { recursive: true });
|
|
6781
6897
|
}
|
|
6782
6898
|
}
|
|
6783
6899
|
function read() {
|
|
@@ -6785,7 +6901,7 @@ function createJsonFileCacheStore(options) {
|
|
|
6785
6901
|
return memoryValue;
|
|
6786
6902
|
}
|
|
6787
6903
|
const cacheFile = getCacheFilePath();
|
|
6788
|
-
if (!
|
|
6904
|
+
if (!existsSync4(cacheFile)) {
|
|
6789
6905
|
memoryValue = null;
|
|
6790
6906
|
log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
|
|
6791
6907
|
return null;
|
|
@@ -6805,7 +6921,7 @@ function createJsonFileCacheStore(options) {
|
|
|
6805
6921
|
}
|
|
6806
6922
|
}
|
|
6807
6923
|
function has() {
|
|
6808
|
-
return
|
|
6924
|
+
return existsSync4(getCacheFilePath());
|
|
6809
6925
|
}
|
|
6810
6926
|
function write(value) {
|
|
6811
6927
|
ensureCacheDir();
|
|
@@ -6974,14 +7090,14 @@ var init_connected_providers_cache = __esm(() => {
|
|
|
6974
7090
|
});
|
|
6975
7091
|
|
|
6976
7092
|
// src/shared/model-availability.ts
|
|
6977
|
-
import { existsSync as
|
|
6978
|
-
import { join as
|
|
7093
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
7094
|
+
import { join as join8 } from "path";
|
|
6979
7095
|
function isModelCacheAvailable() {
|
|
6980
7096
|
if (hasProviderModelsCache()) {
|
|
6981
7097
|
return true;
|
|
6982
7098
|
}
|
|
6983
|
-
const cacheFile =
|
|
6984
|
-
return
|
|
7099
|
+
const cacheFile = join8(getOpenCodeCacheDir(), "models.json");
|
|
7100
|
+
return existsSync5(cacheFile);
|
|
6985
7101
|
}
|
|
6986
7102
|
var init_model_availability = __esm(() => {
|
|
6987
7103
|
init_logger();
|
|
@@ -48294,17 +48410,43 @@ var init_hook_message_injector = __esm(() => {
|
|
|
48294
48410
|
});
|
|
48295
48411
|
|
|
48296
48412
|
// src/shared/opencode-storage-paths.ts
|
|
48297
|
-
import { join as
|
|
48413
|
+
import { join as join9 } from "path";
|
|
48298
48414
|
var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
|
|
48299
48415
|
var init_opencode_storage_paths = __esm(() => {
|
|
48300
48416
|
init_data_path();
|
|
48301
48417
|
OPENCODE_STORAGE = getOpenCodeStorageDir();
|
|
48302
|
-
MESSAGE_STORAGE =
|
|
48303
|
-
PART_STORAGE =
|
|
48304
|
-
SESSION_STORAGE =
|
|
48418
|
+
MESSAGE_STORAGE = join9(OPENCODE_STORAGE, "message");
|
|
48419
|
+
PART_STORAGE = join9(OPENCODE_STORAGE, "part");
|
|
48420
|
+
SESSION_STORAGE = join9(OPENCODE_STORAGE, "session");
|
|
48305
48421
|
});
|
|
48306
48422
|
|
|
48307
48423
|
// src/shared/opencode-message-dir.ts
|
|
48424
|
+
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
48425
|
+
import { join as join10 } from "path";
|
|
48426
|
+
function getMessageDir(sessionID) {
|
|
48427
|
+
if (!sessionID.startsWith("ses_"))
|
|
48428
|
+
return null;
|
|
48429
|
+
if (/[/\\]|\.\./.test(sessionID))
|
|
48430
|
+
return null;
|
|
48431
|
+
if (!existsSync6(MESSAGE_STORAGE))
|
|
48432
|
+
return null;
|
|
48433
|
+
const directPath = join10(MESSAGE_STORAGE, sessionID);
|
|
48434
|
+
if (existsSync6(directPath)) {
|
|
48435
|
+
return directPath;
|
|
48436
|
+
}
|
|
48437
|
+
try {
|
|
48438
|
+
for (const dir of readdirSync(MESSAGE_STORAGE)) {
|
|
48439
|
+
const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
|
|
48440
|
+
if (existsSync6(sessionPath)) {
|
|
48441
|
+
return sessionPath;
|
|
48442
|
+
}
|
|
48443
|
+
}
|
|
48444
|
+
} catch (error) {
|
|
48445
|
+
log("[opencode-message-dir] Failed to scan message directories", { sessionID, error: String(error) });
|
|
48446
|
+
return null;
|
|
48447
|
+
}
|
|
48448
|
+
return null;
|
|
48449
|
+
}
|
|
48308
48450
|
var init_opencode_message_dir = __esm(() => {
|
|
48309
48451
|
init_opencode_storage_paths();
|
|
48310
48452
|
init_logger();
|
|
@@ -48591,6 +48733,7 @@ var init_hook_loader = __esm(() => {
|
|
|
48591
48733
|
});
|
|
48592
48734
|
|
|
48593
48735
|
// src/features/claude-code-plugin-loader/loader.ts
|
|
48736
|
+
var cachedPluginComponentsByKey;
|
|
48594
48737
|
var init_loader = __esm(() => {
|
|
48595
48738
|
init_logger();
|
|
48596
48739
|
init_discovery();
|
|
@@ -48605,6 +48748,7 @@ var init_loader = __esm(() => {
|
|
|
48605
48748
|
init_agent_loader();
|
|
48606
48749
|
init_mcp_server_loader();
|
|
48607
48750
|
init_hook_loader();
|
|
48751
|
+
cachedPluginComponentsByKey = new Map;
|
|
48608
48752
|
});
|
|
48609
48753
|
|
|
48610
48754
|
// src/features/claude-code-plugin-loader/index.ts
|
|
@@ -48741,16 +48885,15 @@ function getConfigJsonc() {
|
|
|
48741
48885
|
return getConfigContext().paths.configJsonc;
|
|
48742
48886
|
}
|
|
48743
48887
|
function getOmoConfigPath() {
|
|
48888
|
+
const configDir = getConfigContext().paths.configDir;
|
|
48889
|
+
const detected = detectPluginConfigFile(configDir);
|
|
48890
|
+
if (detected.format !== "none")
|
|
48891
|
+
return detected.path;
|
|
48744
48892
|
return getConfigContext().paths.omoConfig;
|
|
48745
48893
|
}
|
|
48746
|
-
function getExistingOmoConfigPath() {
|
|
48747
|
-
const detected = detectManagedConfigFile(getConfigDir());
|
|
48748
|
-
return detected.format === "none" ? null : detected.path;
|
|
48749
|
-
}
|
|
48750
48894
|
var configContext = null;
|
|
48751
48895
|
var init_config_context = __esm(() => {
|
|
48752
48896
|
init_shared();
|
|
48753
|
-
init_plugin_identity();
|
|
48754
48897
|
});
|
|
48755
48898
|
|
|
48756
48899
|
// src/cli/config-manager/npm-dist-tags.ts
|
|
@@ -48791,17 +48934,17 @@ async function getPluginNameWithVersion(currentVersion, packageName = DEFAULT_PA
|
|
|
48791
48934
|
}
|
|
48792
48935
|
var DEFAULT_PACKAGE_NAME, PRIORITIZED_TAGS;
|
|
48793
48936
|
var init_plugin_name_with_version = __esm(() => {
|
|
48794
|
-
|
|
48937
|
+
init_shared();
|
|
48795
48938
|
DEFAULT_PACKAGE_NAME = PLUGIN_NAME;
|
|
48796
48939
|
PRIORITIZED_TAGS = ["latest", "beta", "next"];
|
|
48797
48940
|
});
|
|
48798
48941
|
|
|
48799
48942
|
// src/cli/config-manager/ensure-config-directory-exists.ts
|
|
48800
|
-
import { existsSync as
|
|
48943
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
|
|
48801
48944
|
function ensureConfigDirectoryExists() {
|
|
48802
48945
|
const configDir = getConfigDir();
|
|
48803
|
-
if (!
|
|
48804
|
-
|
|
48946
|
+
if (!existsSync7(configDir)) {
|
|
48947
|
+
mkdirSync3(configDir, { recursive: true });
|
|
48805
48948
|
}
|
|
48806
48949
|
}
|
|
48807
48950
|
var init_ensure_config_directory_exists = __esm(() => {
|
|
@@ -48838,14 +48981,14 @@ function formatErrorWithSuggestion(err, context) {
|
|
|
48838
48981
|
}
|
|
48839
48982
|
|
|
48840
48983
|
// src/cli/config-manager/opencode-config-format.ts
|
|
48841
|
-
import { existsSync as
|
|
48984
|
+
import { existsSync as existsSync8 } from "fs";
|
|
48842
48985
|
function detectConfigFormat() {
|
|
48843
48986
|
const configJsonc = getConfigJsonc();
|
|
48844
48987
|
const configJson = getConfigJson();
|
|
48845
|
-
if (
|
|
48988
|
+
if (existsSync8(configJsonc)) {
|
|
48846
48989
|
return { format: "jsonc", path: configJsonc };
|
|
48847
48990
|
}
|
|
48848
|
-
if (
|
|
48991
|
+
if (existsSync8(configJson)) {
|
|
48849
48992
|
return { format: "json", path: configJson };
|
|
48850
48993
|
}
|
|
48851
48994
|
return { format: "none", path: configJson };
|
|
@@ -48901,7 +49044,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
|
|
|
48901
49044
|
};
|
|
48902
49045
|
}
|
|
48903
49046
|
const { format: format2, path: path3 } = detectConfigFormat();
|
|
48904
|
-
const pluginEntry = await getPluginNameWithVersion(currentVersion,
|
|
49047
|
+
const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME);
|
|
48905
49048
|
try {
|
|
48906
49049
|
if (format2 === "none") {
|
|
48907
49050
|
const config2 = { plugin: [pluginEntry] };
|
|
@@ -48919,24 +49062,28 @@ async function addPluginToOpenCodeConfig(currentVersion) {
|
|
|
48919
49062
|
}
|
|
48920
49063
|
const config = parseResult.config;
|
|
48921
49064
|
const plugins = config.plugin ?? [];
|
|
48922
|
-
const
|
|
48923
|
-
|
|
48924
|
-
|
|
48925
|
-
|
|
48926
|
-
|
|
48927
|
-
|
|
49065
|
+
const canonicalEntries = plugins.filter((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`));
|
|
49066
|
+
const legacyEntries = plugins.filter((plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`));
|
|
49067
|
+
const otherPlugins = plugins.filter((plugin) => !(plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)) && !(plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)));
|
|
49068
|
+
const normalizedPlugins = [...otherPlugins];
|
|
49069
|
+
if (canonicalEntries.length > 0) {
|
|
49070
|
+
normalizedPlugins.push(canonicalEntries[0]);
|
|
49071
|
+
} else if (legacyEntries.length > 0) {
|
|
49072
|
+
const versionMatch = legacyEntries[0].match(/@(.+)$/);
|
|
49073
|
+
const preservedVersion = versionMatch ? versionMatch[1] : null;
|
|
49074
|
+
normalizedPlugins.push(preservedVersion ? `${PLUGIN_NAME}@${preservedVersion}` : pluginEntry);
|
|
48928
49075
|
} else {
|
|
48929
|
-
|
|
49076
|
+
normalizedPlugins.push(pluginEntry);
|
|
48930
49077
|
}
|
|
48931
|
-
config.plugin =
|
|
49078
|
+
config.plugin = normalizedPlugins;
|
|
48932
49079
|
if (format2 === "jsonc") {
|
|
48933
49080
|
const content = readFileSync5(path3, "utf-8");
|
|
48934
|
-
const pluginArrayRegex = /"plugin"\s*:\s
|
|
49081
|
+
const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
|
|
48935
49082
|
const match = content.match(pluginArrayRegex);
|
|
48936
49083
|
if (match) {
|
|
48937
|
-
const formattedPlugins =
|
|
49084
|
+
const formattedPlugins = normalizedPlugins.map((p) => `"${p}"`).join(`,
|
|
48938
49085
|
`);
|
|
48939
|
-
const newContent = content.replace(pluginArrayRegex,
|
|
49086
|
+
const newContent = content.replace(pluginArrayRegex, `$1[
|
|
48940
49087
|
${formattedPlugins}
|
|
48941
49088
|
]`);
|
|
48942
49089
|
writeFileSync3(path3, newContent);
|
|
@@ -48958,15 +49105,13 @@ async function addPluginToOpenCodeConfig(currentVersion) {
|
|
|
48958
49105
|
};
|
|
48959
49106
|
}
|
|
48960
49107
|
}
|
|
48961
|
-
var PACKAGE_NAME;
|
|
48962
49108
|
var init_add_plugin_to_opencode_config = __esm(() => {
|
|
48963
|
-
|
|
49109
|
+
init_shared();
|
|
48964
49110
|
init_config_context();
|
|
48965
49111
|
init_ensure_config_directory_exists();
|
|
48966
49112
|
init_opencode_config_format();
|
|
48967
49113
|
init_parse_opencode_config_file();
|
|
48968
49114
|
init_plugin_name_with_version();
|
|
48969
|
-
PACKAGE_NAME = PLUGIN_NAME;
|
|
48970
49115
|
});
|
|
48971
49116
|
|
|
48972
49117
|
// src/cli/model-fallback-requirements.ts
|
|
@@ -49092,7 +49237,7 @@ function generateModelConfig(config) {
|
|
|
49092
49237
|
for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
|
|
49093
49238
|
if (role === "librarian") {
|
|
49094
49239
|
if (avail.opencodeGo) {
|
|
49095
|
-
agents[role] = { model: "opencode-go/minimax-m2.
|
|
49240
|
+
agents[role] = { model: "opencode-go/minimax-m2.7" };
|
|
49096
49241
|
} else if (avail.zai) {
|
|
49097
49242
|
agents[role] = { model: ZAI_MODEL };
|
|
49098
49243
|
}
|
|
@@ -49104,7 +49249,7 @@ function generateModelConfig(config) {
|
|
|
49104
49249
|
} else if (avail.opencodeZen) {
|
|
49105
49250
|
agents[role] = { model: "opencode/claude-haiku-4-5" };
|
|
49106
49251
|
} else if (avail.opencodeGo) {
|
|
49107
|
-
agents[role] = { model: "opencode-go/minimax-m2.
|
|
49252
|
+
agents[role] = { model: "opencode-go/minimax-m2.7" };
|
|
49108
49253
|
} else if (avail.copilot) {
|
|
49109
49254
|
agents[role] = { model: "github-copilot/gpt-5-mini" };
|
|
49110
49255
|
} else {
|
|
@@ -49161,13 +49306,11 @@ function generateModelConfig(config) {
|
|
|
49161
49306
|
};
|
|
49162
49307
|
return isOpenAiOnlyAvailability(avail) ? applyOpenAiOnlyModelCatalog(generatedConfig) : generatedConfig;
|
|
49163
49308
|
}
|
|
49164
|
-
var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/
|
|
49309
|
+
var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/gpt-5-nano", SCHEMA_URL = "https://raw.githubusercontent.com/D4ch1au/evil-oh-my-openagent/dev/assets/evil-omo.schema.json";
|
|
49165
49310
|
var init_model_fallback = __esm(() => {
|
|
49166
49311
|
init_model_fallback_requirements();
|
|
49167
49312
|
init_openai_only_model_catalog();
|
|
49168
49313
|
init_fallback_chain_resolution();
|
|
49169
|
-
init_plugin_identity();
|
|
49170
|
-
SCHEMA_URL = `https://raw.githubusercontent.com/D4ch1au/evil-oh-my-openagent/dev/assets/${SCHEMA_FILENAME}`;
|
|
49171
49314
|
});
|
|
49172
49315
|
|
|
49173
49316
|
// src/cli/config-manager/generate-omo-config.ts
|
|
@@ -49196,7 +49339,7 @@ function deepMergeRecord(target, source) {
|
|
|
49196
49339
|
}
|
|
49197
49340
|
|
|
49198
49341
|
// src/cli/config-manager/write-omo-config.ts
|
|
49199
|
-
import { existsSync as
|
|
49342
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
49200
49343
|
function isEmptyOrWhitespace2(content) {
|
|
49201
49344
|
return content.trim().length === 0;
|
|
49202
49345
|
}
|
|
@@ -49211,13 +49354,12 @@ function writeOmoConfig(installConfig) {
|
|
|
49211
49354
|
};
|
|
49212
49355
|
}
|
|
49213
49356
|
const omoConfigPath = getOmoConfigPath();
|
|
49214
|
-
const existingConfigPath = getExistingOmoConfigPath() ?? omoConfigPath;
|
|
49215
49357
|
try {
|
|
49216
49358
|
const newConfig = generateOmoConfig(installConfig);
|
|
49217
|
-
if (
|
|
49359
|
+
if (existsSync9(omoConfigPath)) {
|
|
49218
49360
|
try {
|
|
49219
|
-
const stat = statSync2(
|
|
49220
|
-
const content = readFileSync6(
|
|
49361
|
+
const stat = statSync2(omoConfigPath);
|
|
49362
|
+
const content = readFileSync6(omoConfigPath, "utf-8");
|
|
49221
49363
|
if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
|
|
49222
49364
|
writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
|
|
49223
49365
|
`);
|
|
@@ -49230,7 +49372,6 @@ function writeOmoConfig(installConfig) {
|
|
|
49230
49372
|
return { success: true, configPath: omoConfigPath };
|
|
49231
49373
|
}
|
|
49232
49374
|
const merged = deepMergeRecord(newConfig, existing);
|
|
49233
|
-
merged.$schema = newConfig.$schema;
|
|
49234
49375
|
writeFileSync4(omoConfigPath, JSON.stringify(merged, null, 2) + `
|
|
49235
49376
|
`);
|
|
49236
49377
|
} catch (parseErr) {
|
|
@@ -49346,7 +49487,7 @@ async function isOpenCodeInstalled() {
|
|
|
49346
49487
|
const result = await findOpenCodeBinaryWithVersion();
|
|
49347
49488
|
return result !== null;
|
|
49348
49489
|
}
|
|
49349
|
-
async function
|
|
49490
|
+
async function getOpenCodeVersion2() {
|
|
49350
49491
|
const result = await findOpenCodeBinaryWithVersion();
|
|
49351
49492
|
return result?.version ?? null;
|
|
49352
49493
|
}
|
|
@@ -49358,10 +49499,10 @@ var init_opencode_binary = __esm(() => {
|
|
|
49358
49499
|
});
|
|
49359
49500
|
|
|
49360
49501
|
// src/cli/config-manager/detect-current-config.ts
|
|
49361
|
-
import { existsSync as
|
|
49502
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
49362
49503
|
function detectProvidersFromOmoConfig() {
|
|
49363
|
-
const omoConfigPath =
|
|
49364
|
-
if (!
|
|
49504
|
+
const omoConfigPath = getOmoConfigPath();
|
|
49505
|
+
if (!existsSync10(omoConfigPath)) {
|
|
49365
49506
|
return {
|
|
49366
49507
|
hasOpenAI: true,
|
|
49367
49508
|
hasOpencodeZen: true,
|
|
@@ -49399,6 +49540,9 @@ function detectProvidersFromOmoConfig() {
|
|
|
49399
49540
|
};
|
|
49400
49541
|
}
|
|
49401
49542
|
}
|
|
49543
|
+
function isOurPlugin(plugin) {
|
|
49544
|
+
return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`);
|
|
49545
|
+
}
|
|
49402
49546
|
function detectCurrentConfig() {
|
|
49403
49547
|
const result = {
|
|
49404
49548
|
isInstalled: false,
|
|
@@ -49422,7 +49566,7 @@ function detectCurrentConfig() {
|
|
|
49422
49566
|
}
|
|
49423
49567
|
const openCodeConfig = parseResult.config;
|
|
49424
49568
|
const plugins = openCodeConfig.plugin ?? [];
|
|
49425
|
-
result.isInstalled =
|
|
49569
|
+
result.isInstalled = plugins.some(isOurPlugin);
|
|
49426
49570
|
if (!result.isInstalled) {
|
|
49427
49571
|
return result;
|
|
49428
49572
|
}
|
|
@@ -49438,17 +49582,16 @@ function detectCurrentConfig() {
|
|
|
49438
49582
|
}
|
|
49439
49583
|
var init_detect_current_config = __esm(() => {
|
|
49440
49584
|
init_shared();
|
|
49441
|
-
init_plugin_identity();
|
|
49442
49585
|
init_config_context();
|
|
49443
49586
|
init_opencode_config_format();
|
|
49444
49587
|
init_parse_opencode_config_file();
|
|
49445
49588
|
});
|
|
49446
49589
|
|
|
49447
49590
|
// src/cli/config-manager/bun-install.ts
|
|
49448
|
-
import { existsSync as
|
|
49449
|
-
import { join as
|
|
49591
|
+
import { existsSync as existsSync11 } from "fs";
|
|
49592
|
+
import { join as join11 } from "path";
|
|
49450
49593
|
function getDefaultWorkspaceDir() {
|
|
49451
|
-
return
|
|
49594
|
+
return join11(getOpenCodeCacheDir(), "packages");
|
|
49452
49595
|
}
|
|
49453
49596
|
function readProcessOutput(stream) {
|
|
49454
49597
|
if (!stream) {
|
|
@@ -49474,7 +49617,7 @@ async function runBunInstallWithDetails(options) {
|
|
|
49474
49617
|
const outputMode = options?.outputMode ?? "pipe";
|
|
49475
49618
|
const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
|
|
49476
49619
|
const packageJsonPath = `${cacheDir}/package.json`;
|
|
49477
|
-
if (!
|
|
49620
|
+
if (!existsSync11(packageJsonPath)) {
|
|
49478
49621
|
return {
|
|
49479
49622
|
success: false,
|
|
49480
49623
|
error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
|
|
@@ -49618,37 +49761,42 @@ function getWindowsAppdataDir() {
|
|
|
49618
49761
|
return null;
|
|
49619
49762
|
return process.env.APPDATA ?? path4.join(os3.homedir(), "AppData", "Roaming");
|
|
49620
49763
|
}
|
|
49621
|
-
|
|
49764
|
+
function getUserConfigDir() {
|
|
49765
|
+
return getOpenCodeConfigDir({ binary: "opencode" });
|
|
49766
|
+
}
|
|
49767
|
+
function getUserOpencodeConfig() {
|
|
49768
|
+
return path4.join(getUserConfigDir(), "opencode.json");
|
|
49769
|
+
}
|
|
49770
|
+
function getUserOpencodeConfigJsonc() {
|
|
49771
|
+
return path4.join(getUserConfigDir(), "opencode.jsonc");
|
|
49772
|
+
}
|
|
49773
|
+
var PACKAGE_NAME = "oh-my-openagent", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
|
|
49622
49774
|
var init_constants3 = __esm(() => {
|
|
49623
49775
|
init_data_path();
|
|
49624
49776
|
init_opencode_config_dir();
|
|
49625
|
-
|
|
49626
|
-
PACKAGE_NAME2 = PLUGIN_NAME;
|
|
49627
|
-
NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
|
|
49777
|
+
NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
|
|
49628
49778
|
CACHE_ROOT_DIR = getOpenCodeCacheDir();
|
|
49629
49779
|
CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
|
|
49630
49780
|
VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
|
|
49631
|
-
|
|
49632
|
-
USER_OPENCODE_CONFIG = path4.join(USER_CONFIG_DIR, "opencode.json");
|
|
49633
|
-
USER_OPENCODE_CONFIG_JSONC = path4.join(USER_CONFIG_DIR, "opencode.jsonc");
|
|
49634
|
-
INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
|
|
49781
|
+
INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
|
|
49635
49782
|
});
|
|
49636
49783
|
|
|
49637
49784
|
// src/hooks/auto-update-checker/checker/config-paths.ts
|
|
49638
49785
|
import * as os4 from "os";
|
|
49639
49786
|
import * as path5 from "path";
|
|
49640
49787
|
function getConfigPaths(directory) {
|
|
49788
|
+
const userConfigDir = getUserConfigDir();
|
|
49641
49789
|
const paths = [
|
|
49642
49790
|
path5.join(directory, ".opencode", "opencode.json"),
|
|
49643
49791
|
path5.join(directory, ".opencode", "opencode.jsonc"),
|
|
49644
|
-
|
|
49645
|
-
|
|
49792
|
+
getUserOpencodeConfig(),
|
|
49793
|
+
getUserOpencodeConfigJsonc()
|
|
49646
49794
|
];
|
|
49647
49795
|
if (process.platform === "win32") {
|
|
49648
49796
|
const crossPlatformDir = path5.join(os4.homedir(), ".config");
|
|
49649
49797
|
const appdataDir = getWindowsAppdataDir();
|
|
49650
49798
|
if (appdataDir) {
|
|
49651
|
-
const alternateDir =
|
|
49799
|
+
const alternateDir = userConfigDir === crossPlatformDir ? appdataDir : crossPlatformDir;
|
|
49652
49800
|
const alternateConfig = path5.join(alternateDir, "opencode", "opencode.json");
|
|
49653
49801
|
const alternateConfigJsonc = path5.join(alternateDir, "opencode", "opencode.jsonc");
|
|
49654
49802
|
if (!paths.includes(alternateConfig)) {
|
|
@@ -49685,7 +49833,7 @@ function getLocalDevPath(directory) {
|
|
|
49685
49833
|
const config2 = JSON.parse(stripJsonComments(content));
|
|
49686
49834
|
const plugins = config2.plugin ?? [];
|
|
49687
49835
|
for (const entry of plugins) {
|
|
49688
|
-
if (entry.startsWith("file://") && entry.includes(
|
|
49836
|
+
if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
|
|
49689
49837
|
try {
|
|
49690
49838
|
return fileURLToPath(entry);
|
|
49691
49839
|
} catch {
|
|
@@ -49717,7 +49865,7 @@ function findPackageJsonUp(startPath) {
|
|
|
49717
49865
|
try {
|
|
49718
49866
|
const content = fs5.readFileSync(pkgPath, "utf-8");
|
|
49719
49867
|
const pkg = JSON.parse(content);
|
|
49720
|
-
if (pkg.name ===
|
|
49868
|
+
if (pkg.name === PACKAGE_NAME)
|
|
49721
49869
|
return pkgPath;
|
|
49722
49870
|
} catch {}
|
|
49723
49871
|
}
|
|
@@ -49765,15 +49913,15 @@ function findPluginEntry(directory) {
|
|
|
49765
49913
|
const content = fs7.readFileSync(configPath, "utf-8");
|
|
49766
49914
|
const config2 = JSON.parse(stripJsonComments(content));
|
|
49767
49915
|
const plugins = config2.plugin ?? [];
|
|
49768
|
-
const
|
|
49769
|
-
|
|
49770
|
-
const entry = plugins[managedEntry.index];
|
|
49771
|
-
if (entry === managedEntry.packageName) {
|
|
49916
|
+
for (const entry of plugins) {
|
|
49917
|
+
if (entry === PACKAGE_NAME) {
|
|
49772
49918
|
return { entry, isPinned: false, pinnedVersion: null, configPath };
|
|
49773
49919
|
}
|
|
49774
|
-
|
|
49775
|
-
|
|
49776
|
-
|
|
49920
|
+
if (entry.startsWith(`${PACKAGE_NAME}@`)) {
|
|
49921
|
+
const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
|
|
49922
|
+
const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
|
|
49923
|
+
return { entry, isPinned, pinnedVersion, configPath };
|
|
49924
|
+
}
|
|
49777
49925
|
}
|
|
49778
49926
|
} catch {
|
|
49779
49927
|
continue;
|
|
@@ -49783,7 +49931,7 @@ function findPluginEntry(directory) {
|
|
|
49783
49931
|
}
|
|
49784
49932
|
var EXACT_SEMVER_REGEX;
|
|
49785
49933
|
var init_plugin_entry = __esm(() => {
|
|
49786
|
-
|
|
49934
|
+
init_constants3();
|
|
49787
49935
|
init_config_paths();
|
|
49788
49936
|
EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/;
|
|
49789
49937
|
});
|
|
@@ -49993,7 +50141,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
|
|
|
49993
50141
|
if (!fs9.existsSync(cachePackageJsonPath)) {
|
|
49994
50142
|
log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
|
|
49995
50143
|
return {
|
|
49996
|
-
...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [
|
|
50144
|
+
...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
|
|
49997
50145
|
message: `Created cache package.json with: ${intentVersion}`
|
|
49998
50146
|
};
|
|
49999
50147
|
}
|
|
@@ -50011,21 +50159,21 @@ function syncCachePackageJsonToIntent(pluginInfo) {
|
|
|
50011
50159
|
log("[auto-update-checker] Failed to parse cache package.json:", err);
|
|
50012
50160
|
return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
|
|
50013
50161
|
}
|
|
50014
|
-
if (!pkgJson || !pkgJson.dependencies?.[
|
|
50162
|
+
if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
|
|
50015
50163
|
log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
|
|
50016
50164
|
const nextPkgJson = {
|
|
50017
50165
|
...pkgJson ?? {},
|
|
50018
50166
|
dependencies: {
|
|
50019
50167
|
...pkgJson?.dependencies ?? {},
|
|
50020
|
-
[
|
|
50168
|
+
[PACKAGE_NAME]: intentVersion
|
|
50021
50169
|
}
|
|
50022
50170
|
};
|
|
50023
50171
|
return {
|
|
50024
50172
|
...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
|
|
50025
|
-
message: `Added ${
|
|
50173
|
+
message: `Added ${PACKAGE_NAME}: ${intentVersion}`
|
|
50026
50174
|
};
|
|
50027
50175
|
}
|
|
50028
|
-
const currentVersion = pkgJson.dependencies[
|
|
50176
|
+
const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
|
|
50029
50177
|
if (currentVersion === intentVersion) {
|
|
50030
50178
|
log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
|
|
50031
50179
|
return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
|
|
@@ -50037,7 +50185,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
|
|
|
50037
50185
|
} else {
|
|
50038
50186
|
log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
|
|
50039
50187
|
}
|
|
50040
|
-
pkgJson.dependencies[
|
|
50188
|
+
pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
|
|
50041
50189
|
return {
|
|
50042
50190
|
...writeCachePackageJson(cachePackageJsonPath, pkgJson),
|
|
50043
50191
|
message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
|
|
@@ -50103,10 +50251,11 @@ function removeFromBunLock(packageName) {
|
|
|
50103
50251
|
}
|
|
50104
50252
|
return false;
|
|
50105
50253
|
}
|
|
50106
|
-
function invalidatePackage(packageName =
|
|
50254
|
+
function invalidatePackage(packageName = PACKAGE_NAME) {
|
|
50107
50255
|
try {
|
|
50256
|
+
const userConfigDir = getUserConfigDir();
|
|
50108
50257
|
const pkgDirs = [
|
|
50109
|
-
path9.join(
|
|
50258
|
+
path9.join(userConfigDir, "node_modules", packageName),
|
|
50110
50259
|
path9.join(CACHE_DIR, "node_modules", packageName)
|
|
50111
50260
|
];
|
|
50112
50261
|
let packageRemoved = false;
|
|
@@ -50167,8 +50316,8 @@ var init_update_toasts = __esm(() => {
|
|
|
50167
50316
|
});
|
|
50168
50317
|
|
|
50169
50318
|
// src/hooks/auto-update-checker/hook/background-update-check.ts
|
|
50170
|
-
import { existsSync as
|
|
50171
|
-
import { join as
|
|
50319
|
+
import { existsSync as existsSync22 } from "fs";
|
|
50320
|
+
import { join as join23 } from "path";
|
|
50172
50321
|
function getCacheWorkspaceDir(deps) {
|
|
50173
50322
|
return deps.join(deps.getOpenCodeCacheDir(), "packages");
|
|
50174
50323
|
}
|
|
@@ -50178,8 +50327,8 @@ function getPinnedVersionToastMessage(latestVersion) {
|
|
|
50178
50327
|
function resolveActiveInstallWorkspace(deps) {
|
|
50179
50328
|
const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
|
|
50180
50329
|
const cacheDir = getCacheWorkspaceDir(deps);
|
|
50181
|
-
const configInstallPath = deps.join(configPaths.configDir, "node_modules",
|
|
50182
|
-
const cacheInstallPath = deps.join(cacheDir, "node_modules",
|
|
50330
|
+
const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME, "package.json");
|
|
50331
|
+
const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME, "package.json");
|
|
50183
50332
|
if (deps.existsSync(configInstallPath)) {
|
|
50184
50333
|
deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
|
|
50185
50334
|
return configPaths.configDir;
|
|
@@ -50225,8 +50374,8 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
|
|
|
50225
50374
|
deps.log("[auto-update-checker] Plugin not found in config");
|
|
50226
50375
|
return;
|
|
50227
50376
|
}
|
|
50228
|
-
const
|
|
50229
|
-
const currentVersion =
|
|
50377
|
+
const cachedVersion2 = deps.getCachedVersion();
|
|
50378
|
+
const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
|
|
50230
50379
|
if (!currentVersion) {
|
|
50231
50380
|
deps.log("[auto-update-checker] No version found (cached or pinned)");
|
|
50232
50381
|
return;
|
|
@@ -50258,7 +50407,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
|
|
|
50258
50407
|
await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
50259
50408
|
return;
|
|
50260
50409
|
}
|
|
50261
|
-
deps.invalidatePackage(
|
|
50410
|
+
deps.invalidatePackage(PACKAGE_NAME);
|
|
50262
50411
|
const activeWorkspace = resolveActiveInstallWorkspace(deps);
|
|
50263
50412
|
const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
|
|
50264
50413
|
if (installSuccess) {
|
|
@@ -50286,8 +50435,8 @@ var init_background_update_check = __esm(() => {
|
|
|
50286
50435
|
init_checker();
|
|
50287
50436
|
init_update_toasts();
|
|
50288
50437
|
defaultDeps = {
|
|
50289
|
-
existsSync:
|
|
50290
|
-
join:
|
|
50438
|
+
existsSync: existsSync22,
|
|
50439
|
+
join: join23,
|
|
50291
50440
|
runBunInstallWithDetails,
|
|
50292
50441
|
log,
|
|
50293
50442
|
getOpenCodeCacheDir,
|
|
@@ -50496,9 +50645,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
|
|
|
50496
50645
|
return;
|
|
50497
50646
|
hasChecked = true;
|
|
50498
50647
|
setTimeout(async () => {
|
|
50499
|
-
const
|
|
50648
|
+
const cachedVersion2 = getCachedVersion();
|
|
50500
50649
|
const localDevVersion = getLocalDevVersion(ctx.directory);
|
|
50501
|
-
const displayVersion = localDevVersion ??
|
|
50650
|
+
const displayVersion = localDevVersion ?? cachedVersion2;
|
|
50502
50651
|
await showConfigErrorsIfAny(ctx);
|
|
50503
50652
|
await updateAndShowConnectedProvidersCacheStatus(ctx);
|
|
50504
50653
|
await refreshModelCapabilitiesOnStartup(modelCapabilities);
|
|
@@ -50567,7 +50716,7 @@ var {
|
|
|
50567
50716
|
// package.json
|
|
50568
50717
|
var package_default = {
|
|
50569
50718
|
name: "evil-omo",
|
|
50570
|
-
version: "3.15.
|
|
50719
|
+
version: "3.15.3",
|
|
50571
50720
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
50572
50721
|
main: "./dist/index.js",
|
|
50573
50722
|
types: "dist/index.d.ts",
|
|
@@ -50645,17 +50794,17 @@ var package_default = {
|
|
|
50645
50794
|
typescript: "^5.7.3"
|
|
50646
50795
|
},
|
|
50647
50796
|
optionalDependencies: {
|
|
50648
|
-
"evil-omo-darwin-arm64": "3.15.
|
|
50649
|
-
"evil-omo-darwin-x64": "3.15.
|
|
50650
|
-
"evil-omo-darwin-x64-baseline": "3.15.
|
|
50651
|
-
"evil-omo-linux-x64": "3.15.
|
|
50652
|
-
"evil-omo-linux-x64-baseline": "3.15.
|
|
50653
|
-
"evil-omo-linux-arm64": "3.15.
|
|
50654
|
-
"evil-omo-linux-x64-musl": "3.15.
|
|
50655
|
-
"evil-omo-linux-x64-musl-baseline": "3.15.
|
|
50656
|
-
"evil-omo-linux-arm64-musl": "3.15.
|
|
50657
|
-
"evil-omo-windows-x64": "3.15.
|
|
50658
|
-
"evil-omo-windows-x64-baseline": "3.15.
|
|
50797
|
+
"evil-omo-darwin-arm64": "3.15.3",
|
|
50798
|
+
"evil-omo-darwin-x64": "3.15.3",
|
|
50799
|
+
"evil-omo-darwin-x64-baseline": "3.15.3",
|
|
50800
|
+
"evil-omo-linux-x64": "3.15.3",
|
|
50801
|
+
"evil-omo-linux-x64-baseline": "3.15.3",
|
|
50802
|
+
"evil-omo-linux-arm64": "3.15.3",
|
|
50803
|
+
"evil-omo-linux-x64-musl": "3.15.3",
|
|
50804
|
+
"evil-omo-linux-x64-musl-baseline": "3.15.3",
|
|
50805
|
+
"evil-omo-linux-arm64-musl": "3.15.3",
|
|
50806
|
+
"evil-omo-windows-x64": "3.15.3",
|
|
50807
|
+
"evil-omo-windows-x64-baseline": "3.15.3"
|
|
50659
50808
|
},
|
|
50660
50809
|
overrides: {
|
|
50661
50810
|
"@opencode-ai/sdk": "^1.2.24"
|
|
@@ -50668,6 +50817,7 @@ var package_default = {
|
|
|
50668
50817
|
};
|
|
50669
50818
|
|
|
50670
50819
|
// src/cli/cli-installer.ts
|
|
50820
|
+
init_shared();
|
|
50671
50821
|
init_config_manager();
|
|
50672
50822
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
50673
50823
|
|
|
@@ -50826,7 +50976,7 @@ async function runCliInstaller(args, version) {
|
|
|
50826
50976
|
console.log(` ${SYMBOLS.bullet} ${err}`);
|
|
50827
50977
|
}
|
|
50828
50978
|
console.log();
|
|
50829
|
-
printInfo(
|
|
50979
|
+
printInfo(`Usage: bunx ${PLUGIN_NAME} install --no-tui --claude=<no|yes|max20> --gemini=<no|yes> --copilot=<no|yes>`);
|
|
50830
50980
|
console.log();
|
|
50831
50981
|
return 1;
|
|
50832
50982
|
}
|
|
@@ -50837,7 +50987,7 @@ async function runCliInstaller(args, version) {
|
|
|
50837
50987
|
let step = 1;
|
|
50838
50988
|
printStep(step++, totalSteps, "Checking OpenCode installation...");
|
|
50839
50989
|
const installed = await isOpenCodeInstalled();
|
|
50840
|
-
const openCodeVersion = await
|
|
50990
|
+
const openCodeVersion = await getOpenCodeVersion2();
|
|
50841
50991
|
if (!installed) {
|
|
50842
50992
|
printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
|
|
50843
50993
|
printInfo("Visit https://opencode.ai/docs for installation instructions");
|
|
@@ -50849,14 +50999,14 @@ async function runCliInstaller(args, version) {
|
|
|
50849
50999
|
printInfo(`Current config: Claude=${initial.claude}, Gemini=${initial.gemini}`);
|
|
50850
51000
|
}
|
|
50851
51001
|
const config = argsToConfig(args);
|
|
50852
|
-
printStep(step++, totalSteps,
|
|
51002
|
+
printStep(step++, totalSteps, `Adding ${PLUGIN_NAME} plugin...`);
|
|
50853
51003
|
const pluginResult = await addPluginToOpenCodeConfig(version);
|
|
50854
51004
|
if (!pluginResult.success) {
|
|
50855
51005
|
printError(`Failed: ${pluginResult.error}`);
|
|
50856
51006
|
return 1;
|
|
50857
51007
|
}
|
|
50858
51008
|
printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors2.default.dim(pluginResult.configPath)}`);
|
|
50859
|
-
printStep(step++, totalSteps,
|
|
51009
|
+
printStep(step++, totalSteps, `Writing ${PLUGIN_NAME} configuration...`);
|
|
50860
51010
|
const omoResult = writeOmoConfig(config);
|
|
50861
51011
|
if (!omoResult.success) {
|
|
50862
51012
|
printError(`Failed: ${omoResult.error}`);
|
|
@@ -50884,7 +51034,7 @@ async function runCliInstaller(args, version) {
|
|
|
50884
51034
|
console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
|
|
50885
51035
|
console.log();
|
|
50886
51036
|
printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
|
|
50887
|
-
` + `All features work like magic
|
|
51037
|
+
` + `All features work like magic-parallel agents, background tasks,
|
|
50888
51038
|
` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
|
|
50889
51039
|
console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
|
|
50890
51040
|
console.log(` ${import_picocolors2.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
|
|
@@ -51481,6 +51631,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
51481
51631
|
};
|
|
51482
51632
|
|
|
51483
51633
|
// src/cli/tui-installer.ts
|
|
51634
|
+
init_shared();
|
|
51484
51635
|
init_config_manager();
|
|
51485
51636
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
51486
51637
|
|
|
@@ -51611,7 +51762,7 @@ async function runTuiInstaller(args, version) {
|
|
|
51611
51762
|
const spinner = Y2();
|
|
51612
51763
|
spinner.start("Checking OpenCode installation");
|
|
51613
51764
|
const installed = await isOpenCodeInstalled();
|
|
51614
|
-
const openCodeVersion = await
|
|
51765
|
+
const openCodeVersion = await getOpenCodeVersion2();
|
|
51615
51766
|
if (!installed) {
|
|
51616
51767
|
spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
|
|
51617
51768
|
M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
|
|
@@ -51622,7 +51773,7 @@ async function runTuiInstaller(args, version) {
|
|
|
51622
51773
|
const config = await promptInstallConfig(detected);
|
|
51623
51774
|
if (!config)
|
|
51624
51775
|
return 1;
|
|
51625
|
-
spinner.start(
|
|
51776
|
+
spinner.start(`Adding ${PLUGIN_NAME} to OpenCode config`);
|
|
51626
51777
|
const pluginResult = await addPluginToOpenCodeConfig(version);
|
|
51627
51778
|
if (!pluginResult.success) {
|
|
51628
51779
|
spinner.stop(`Failed to add plugin: ${pluginResult.error}`);
|
|
@@ -51630,7 +51781,7 @@ async function runTuiInstaller(args, version) {
|
|
|
51630
51781
|
return 1;
|
|
51631
51782
|
}
|
|
51632
51783
|
spinner.stop(`Plugin added to ${import_picocolors4.default.cyan(pluginResult.configPath)}`);
|
|
51633
|
-
spinner.start(
|
|
51784
|
+
spinner.start(`Writing ${PLUGIN_NAME} configuration`);
|
|
51634
51785
|
const omoResult = writeOmoConfig(config);
|
|
51635
51786
|
if (!omoResult.success) {
|
|
51636
51787
|
spinner.stop(`Failed to write config: ${omoResult.error}`);
|
|
@@ -51658,7 +51809,7 @@ async function runTuiInstaller(args, version) {
|
|
|
51658
51809
|
M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
|
|
51659
51810
|
M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
|
|
51660
51811
|
Me(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
|
|
51661
|
-
` + `All features work like magic
|
|
51812
|
+
` + `All features work like magic-parallel agents, background tasks,
|
|
51662
51813
|
` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
|
|
51663
51814
|
M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
|
|
51664
51815
|
M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
|
|
@@ -66618,7 +66769,7 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
|
|
|
66618
66769
|
if (!response.body)
|
|
66619
66770
|
throw new Error("No body in SSE response");
|
|
66620
66771
|
const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
|
|
66621
|
-
let
|
|
66772
|
+
let buffer2 = "";
|
|
66622
66773
|
const abortHandler = () => {
|
|
66623
66774
|
try {
|
|
66624
66775
|
reader.cancel();
|
|
@@ -66630,11 +66781,11 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
|
|
|
66630
66781
|
const { done, value } = await reader.read();
|
|
66631
66782
|
if (done)
|
|
66632
66783
|
break;
|
|
66633
|
-
|
|
66634
|
-
const chunks =
|
|
66784
|
+
buffer2 += value;
|
|
66785
|
+
const chunks = buffer2.split(`
|
|
66635
66786
|
|
|
66636
66787
|
`);
|
|
66637
|
-
|
|
66788
|
+
buffer2 = chunks.pop() ?? "";
|
|
66638
66789
|
for (const chunk of chunks) {
|
|
66639
66790
|
const lines = chunk.split(`
|
|
66640
66791
|
`);
|
|
@@ -68043,7 +68194,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
|
68043
68194
|
|
|
68044
68195
|
// src/cli/run/opencode-binary-resolver.ts
|
|
68045
68196
|
init_spawn_with_windows_hide();
|
|
68046
|
-
import { delimiter, dirname, join as
|
|
68197
|
+
import { delimiter, dirname, join as join13 } from "path";
|
|
68047
68198
|
var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
|
|
68048
68199
|
var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
|
|
68049
68200
|
function getCommandCandidates(platform) {
|
|
@@ -68066,7 +68217,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
|
|
|
68066
68217
|
}
|
|
68067
68218
|
for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
|
|
68068
68219
|
for (const command of commandCandidates) {
|
|
68069
|
-
addCandidate(
|
|
68220
|
+
addCandidate(join13(entry, command));
|
|
68070
68221
|
}
|
|
68071
68222
|
}
|
|
68072
68223
|
return candidates;
|
|
@@ -68200,7 +68351,6 @@ async function createServerConnection(options) {
|
|
|
68200
68351
|
|
|
68201
68352
|
// src/cli/run/session-resolver.ts
|
|
68202
68353
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
68203
|
-
init_plugin_identity();
|
|
68204
68354
|
var SESSION_CREATE_MAX_RETRIES = 3;
|
|
68205
68355
|
var SESSION_CREATE_RETRY_DELAY_MS = 1000;
|
|
68206
68356
|
async function resolveSession(options) {
|
|
@@ -68218,7 +68368,7 @@ async function resolveSession(options) {
|
|
|
68218
68368
|
for (let attempt = 1;attempt <= SESSION_CREATE_MAX_RETRIES; attempt++) {
|
|
68219
68369
|
const res = await client3.session.create({
|
|
68220
68370
|
body: {
|
|
68221
|
-
title:
|
|
68371
|
+
title: "evil-omo run",
|
|
68222
68372
|
permission: [
|
|
68223
68373
|
{ permission: "question", action: "deny", pattern: "*" }
|
|
68224
68374
|
]
|
|
@@ -68450,15 +68600,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
|
|
|
68450
68600
|
var NOTEPAD_DIR = "notepads";
|
|
68451
68601
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
68452
68602
|
// src/features/boulder-state/storage.ts
|
|
68453
|
-
import { existsSync as
|
|
68454
|
-
import { dirname as dirname2, join as
|
|
68603
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
68604
|
+
import { dirname as dirname2, join as join14, basename } from "path";
|
|
68455
68605
|
var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
|
|
68456
68606
|
function getBoulderFilePath(directory) {
|
|
68457
|
-
return
|
|
68607
|
+
return join14(directory, BOULDER_DIR, BOULDER_FILE);
|
|
68458
68608
|
}
|
|
68459
68609
|
function readBoulderState(directory) {
|
|
68460
68610
|
const filePath = getBoulderFilePath(directory);
|
|
68461
|
-
if (!
|
|
68611
|
+
if (!existsSync13(filePath)) {
|
|
68462
68612
|
return null;
|
|
68463
68613
|
}
|
|
68464
68614
|
try {
|
|
@@ -68470,6 +68620,15 @@ function readBoulderState(directory) {
|
|
|
68470
68620
|
if (!Array.isArray(parsed.session_ids)) {
|
|
68471
68621
|
parsed.session_ids = [];
|
|
68472
68622
|
}
|
|
68623
|
+
if (!parsed.session_origins || typeof parsed.session_origins !== "object" || Array.isArray(parsed.session_origins)) {
|
|
68624
|
+
parsed.session_origins = {};
|
|
68625
|
+
}
|
|
68626
|
+
if (parsed.session_ids.length === 1) {
|
|
68627
|
+
const soleSessionId = parsed.session_ids[0];
|
|
68628
|
+
if (typeof soleSessionId === "string" && parsed.session_origins[soleSessionId] !== "appended" && parsed.session_origins[soleSessionId] !== "direct") {
|
|
68629
|
+
parsed.session_origins[soleSessionId] = "direct";
|
|
68630
|
+
}
|
|
68631
|
+
}
|
|
68473
68632
|
if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
|
|
68474
68633
|
parsed.task_sessions = {};
|
|
68475
68634
|
}
|
|
@@ -68479,7 +68638,7 @@ function readBoulderState(directory) {
|
|
|
68479
68638
|
}
|
|
68480
68639
|
}
|
|
68481
68640
|
function getPlanProgress(planPath) {
|
|
68482
|
-
if (!
|
|
68641
|
+
if (!existsSync13(planPath)) {
|
|
68483
68642
|
return { total: 0, completed: 0, isComplete: true };
|
|
68484
68643
|
}
|
|
68485
68644
|
try {
|
|
@@ -68497,17 +68656,26 @@ function getPlanProgress(planPath) {
|
|
|
68497
68656
|
return { total: 0, completed: 0, isComplete: true };
|
|
68498
68657
|
}
|
|
68499
68658
|
}
|
|
68659
|
+
// src/features/claude-code-session-state/state.ts
|
|
68660
|
+
init_agent_display_names();
|
|
68661
|
+
var subagentSessions = new Set;
|
|
68662
|
+
var syncSubagentSessions = new Set;
|
|
68663
|
+
var registeredAgentNames = new Set;
|
|
68664
|
+
var sessionAgentMap = new Map;
|
|
68665
|
+
function getSessionAgent(sessionID) {
|
|
68666
|
+
return sessionAgentMap.get(sessionID);
|
|
68667
|
+
}
|
|
68500
68668
|
// src/features/run-continuation-state/constants.ts
|
|
68501
68669
|
var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
|
|
68502
68670
|
// src/features/run-continuation-state/storage.ts
|
|
68503
|
-
import { existsSync as
|
|
68504
|
-
import { join as
|
|
68671
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync6 } from "fs";
|
|
68672
|
+
import { join as join15 } from "path";
|
|
68505
68673
|
function getMarkerPath(directory, sessionID) {
|
|
68506
|
-
return
|
|
68674
|
+
return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
|
|
68507
68675
|
}
|
|
68508
68676
|
function readContinuationMarker(directory, sessionID) {
|
|
68509
68677
|
const markerPath = getMarkerPath(directory, sessionID);
|
|
68510
|
-
if (!
|
|
68678
|
+
if (!existsSync14(markerPath))
|
|
68511
68679
|
return null;
|
|
68512
68680
|
try {
|
|
68513
68681
|
const raw = readFileSync10(markerPath, "utf-8");
|
|
@@ -68533,10 +68701,113 @@ function getActiveContinuationMarkerReason(marker) {
|
|
|
68533
68701
|
const [source, entry] = active;
|
|
68534
68702
|
return entry.reason ?? `${source} continuation is active`;
|
|
68535
68703
|
}
|
|
68704
|
+
// src/hooks/atlas/boulder-session-lineage.ts
|
|
68705
|
+
init_logger();
|
|
68706
|
+
|
|
68707
|
+
// src/hooks/atlas/hook-name.ts
|
|
68708
|
+
var HOOK_NAME = "atlas";
|
|
68709
|
+
|
|
68710
|
+
// src/hooks/atlas/boulder-session-lineage.ts
|
|
68711
|
+
async function isSessionInBoulderLineage(input) {
|
|
68712
|
+
const visitedSessionIDs = new Set;
|
|
68713
|
+
let currentSessionID = input.sessionID;
|
|
68714
|
+
while (!visitedSessionIDs.has(currentSessionID)) {
|
|
68715
|
+
visitedSessionIDs.add(currentSessionID);
|
|
68716
|
+
const sessionResult = await input.client.session.get({ path: { id: currentSessionID } }).catch((error48) => {
|
|
68717
|
+
log(`[${HOOK_NAME}] Failed to resolve session lineage`, {
|
|
68718
|
+
sessionID: input.sessionID,
|
|
68719
|
+
currentSessionID,
|
|
68720
|
+
error: error48
|
|
68721
|
+
});
|
|
68722
|
+
return null;
|
|
68723
|
+
});
|
|
68724
|
+
if (!sessionResult || sessionResult.error) {
|
|
68725
|
+
return false;
|
|
68726
|
+
}
|
|
68727
|
+
const parentSessionID = sessionResult.data?.parentID;
|
|
68728
|
+
if (!parentSessionID) {
|
|
68729
|
+
return false;
|
|
68730
|
+
}
|
|
68731
|
+
if (input.boulderSessionIDs.includes(parentSessionID)) {
|
|
68732
|
+
return true;
|
|
68733
|
+
}
|
|
68734
|
+
currentSessionID = parentSessionID;
|
|
68735
|
+
}
|
|
68736
|
+
return false;
|
|
68737
|
+
}
|
|
68738
|
+
|
|
68739
|
+
// src/hooks/atlas/session-last-agent.ts
|
|
68740
|
+
init_shared();
|
|
68741
|
+
import { readFileSync as readFileSync11, readdirSync as readdirSync3 } from "fs";
|
|
68742
|
+
import { join as join16 } from "path";
|
|
68743
|
+
function isCompactionAgent(agent) {
|
|
68744
|
+
return typeof agent === "string" && agent.toLowerCase() === "compaction";
|
|
68745
|
+
}
|
|
68746
|
+
function getLastAgentFromMessageDir(messageDir) {
|
|
68747
|
+
try {
|
|
68748
|
+
const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
|
|
68749
|
+
try {
|
|
68750
|
+
const content = readFileSync11(join16(messageDir, fileName), "utf-8");
|
|
68751
|
+
const parsed = JSON.parse(content);
|
|
68752
|
+
return {
|
|
68753
|
+
fileName,
|
|
68754
|
+
agent: parsed.agent,
|
|
68755
|
+
createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
|
|
68756
|
+
};
|
|
68757
|
+
} catch {
|
|
68758
|
+
return null;
|
|
68759
|
+
}
|
|
68760
|
+
}).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
|
|
68761
|
+
for (const message of messages) {
|
|
68762
|
+
if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
|
|
68763
|
+
return message.agent.toLowerCase();
|
|
68764
|
+
}
|
|
68765
|
+
}
|
|
68766
|
+
} catch {
|
|
68767
|
+
return null;
|
|
68768
|
+
}
|
|
68769
|
+
return null;
|
|
68770
|
+
}
|
|
68771
|
+
async function getLastAgentFromSession(sessionID, client3) {
|
|
68772
|
+
if (isSqliteBackend() && client3) {
|
|
68773
|
+
try {
|
|
68774
|
+
const response = await client3.session.messages({ path: { id: sessionID } });
|
|
68775
|
+
const messages = normalizeSDKResponse(response, [], {
|
|
68776
|
+
preferResponseOnMissingData: true
|
|
68777
|
+
}).sort((left, right) => {
|
|
68778
|
+
const leftTime = left.info?.time?.created ?? Number.NEGATIVE_INFINITY;
|
|
68779
|
+
const rightTime = right.info?.time?.created ?? Number.NEGATIVE_INFINITY;
|
|
68780
|
+
if (leftTime !== rightTime) {
|
|
68781
|
+
return rightTime - leftTime;
|
|
68782
|
+
}
|
|
68783
|
+
const leftId = typeof left.id === "string" ? left.id : "";
|
|
68784
|
+
const rightId = typeof right.id === "string" ? right.id : "";
|
|
68785
|
+
return rightId.localeCompare(leftId);
|
|
68786
|
+
});
|
|
68787
|
+
for (const message of messages) {
|
|
68788
|
+
const agent = message.info?.agent;
|
|
68789
|
+
if (typeof agent === "string" && !isCompactionAgent(agent)) {
|
|
68790
|
+
return agent.toLowerCase();
|
|
68791
|
+
}
|
|
68792
|
+
}
|
|
68793
|
+
} catch {
|
|
68794
|
+
return null;
|
|
68795
|
+
}
|
|
68796
|
+
return null;
|
|
68797
|
+
}
|
|
68798
|
+
const messageDir = getMessageDir(sessionID);
|
|
68799
|
+
if (!messageDir)
|
|
68800
|
+
return null;
|
|
68801
|
+
return getLastAgentFromMessageDir(messageDir);
|
|
68802
|
+
}
|
|
68803
|
+
|
|
68804
|
+
// src/cli/run/continuation-state.ts
|
|
68805
|
+
init_agent_display_names();
|
|
68806
|
+
|
|
68536
68807
|
// src/hooks/ralph-loop/storage.ts
|
|
68537
68808
|
init_frontmatter();
|
|
68538
|
-
import { existsSync as
|
|
68539
|
-
import { dirname as dirname3, join as
|
|
68809
|
+
import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
|
|
68810
|
+
import { dirname as dirname3, join as join17 } from "path";
|
|
68540
68811
|
|
|
68541
68812
|
// src/hooks/ralph-loop/constants.ts
|
|
68542
68813
|
var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
|
|
@@ -68545,15 +68816,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
68545
68816
|
|
|
68546
68817
|
// src/hooks/ralph-loop/storage.ts
|
|
68547
68818
|
function getStateFilePath(directory, customPath) {
|
|
68548
|
-
return customPath ?
|
|
68819
|
+
return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
|
|
68549
68820
|
}
|
|
68550
68821
|
function readState(directory, customPath) {
|
|
68551
68822
|
const filePath = getStateFilePath(directory, customPath);
|
|
68552
|
-
if (!
|
|
68823
|
+
if (!existsSync15(filePath)) {
|
|
68553
68824
|
return null;
|
|
68554
68825
|
}
|
|
68555
68826
|
try {
|
|
68556
|
-
const content =
|
|
68827
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
68557
68828
|
const { data, body } = parseFrontmatter(content);
|
|
68558
68829
|
const active = data.active;
|
|
68559
68830
|
const iteration = data.iteration;
|
|
@@ -68593,10 +68864,10 @@ function readState(directory, customPath) {
|
|
|
68593
68864
|
}
|
|
68594
68865
|
|
|
68595
68866
|
// src/cli/run/continuation-state.ts
|
|
68596
|
-
function getContinuationState(directory, sessionID) {
|
|
68867
|
+
async function getContinuationState(directory, sessionID, client3) {
|
|
68597
68868
|
const marker = readContinuationMarker(directory, sessionID);
|
|
68598
68869
|
return {
|
|
68599
|
-
hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
|
|
68870
|
+
hasActiveBoulder: await hasActiveBoulderContinuation(directory, sessionID, client3),
|
|
68600
68871
|
hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
|
|
68601
68872
|
hasHookMarker: marker !== null,
|
|
68602
68873
|
hasTodoHookMarker: marker?.sources.todo !== undefined,
|
|
@@ -68604,20 +68875,54 @@ function getContinuationState(directory, sessionID) {
|
|
|
68604
68875
|
activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
|
|
68605
68876
|
};
|
|
68606
68877
|
}
|
|
68607
|
-
function hasActiveBoulderContinuation(directory, sessionID) {
|
|
68878
|
+
async function hasActiveBoulderContinuation(directory, sessionID, client3) {
|
|
68608
68879
|
const boulder = readBoulderState(directory);
|
|
68609
68880
|
if (!boulder)
|
|
68610
68881
|
return false;
|
|
68611
|
-
if (!boulder.session_ids.includes(sessionID))
|
|
68612
|
-
return false;
|
|
68613
68882
|
const progress = getPlanProgress(boulder.active_plan);
|
|
68614
|
-
|
|
68883
|
+
if (progress.isComplete)
|
|
68884
|
+
return false;
|
|
68885
|
+
if (!client3)
|
|
68886
|
+
return false;
|
|
68887
|
+
const isTrackedSession = boulder.session_ids.includes(sessionID);
|
|
68888
|
+
const sessionOrigin = boulder.session_origins?.[sessionID];
|
|
68889
|
+
if (!isTrackedSession) {
|
|
68890
|
+
return false;
|
|
68891
|
+
}
|
|
68892
|
+
const isTrackedDescendant = await isTrackedDescendantSession(client3, sessionID, boulder.session_ids);
|
|
68893
|
+
if (isTrackedSession && sessionOrigin === "direct") {
|
|
68894
|
+
return true;
|
|
68895
|
+
}
|
|
68896
|
+
if (isTrackedSession && sessionOrigin !== "direct" && !isTrackedDescendant) {
|
|
68897
|
+
return false;
|
|
68898
|
+
}
|
|
68899
|
+
const sessionAgent = await getLastAgentFromSession(sessionID, client3) ?? getSessionAgent(sessionID);
|
|
68900
|
+
if (!sessionAgent) {
|
|
68901
|
+
return false;
|
|
68902
|
+
}
|
|
68903
|
+
const requiredAgentKey = getAgentConfigKey(boulder.agent ?? "atlas");
|
|
68904
|
+
const sessionAgentKey = getAgentConfigKey(sessionAgent);
|
|
68905
|
+
if (sessionAgentKey !== requiredAgentKey && !(requiredAgentKey === getAgentConfigKey("atlas") && sessionAgentKey === getAgentConfigKey("sisyphus"))) {
|
|
68906
|
+
return false;
|
|
68907
|
+
}
|
|
68908
|
+
return isTrackedSession || isTrackedDescendant;
|
|
68909
|
+
}
|
|
68910
|
+
async function isTrackedDescendantSession(client3, sessionID, trackedSessionIDs) {
|
|
68911
|
+
const ancestorSessionIDs = trackedSessionIDs.filter((trackedSessionID) => trackedSessionID !== sessionID);
|
|
68912
|
+
if (ancestorSessionIDs.length === 0) {
|
|
68913
|
+
return false;
|
|
68914
|
+
}
|
|
68915
|
+
return isSessionInBoulderLineage({
|
|
68916
|
+
client: client3,
|
|
68917
|
+
sessionID,
|
|
68918
|
+
boulderSessionIDs: ancestorSessionIDs
|
|
68919
|
+
});
|
|
68615
68920
|
}
|
|
68616
68921
|
function hasActiveRalphLoopContinuation(directory, sessionID) {
|
|
68617
|
-
const
|
|
68618
|
-
if (!
|
|
68922
|
+
const state2 = readState(directory);
|
|
68923
|
+
if (!state2 || !state2.active)
|
|
68619
68924
|
return false;
|
|
68620
|
-
if (
|
|
68925
|
+
if (state2.session_id && state2.session_id !== sessionID) {
|
|
68621
68926
|
return false;
|
|
68622
68927
|
}
|
|
68623
68928
|
return true;
|
|
@@ -68626,7 +68931,7 @@ function hasActiveRalphLoopContinuation(directory, sessionID) {
|
|
|
68626
68931
|
// src/cli/run/completion.ts
|
|
68627
68932
|
async function checkCompletionConditions(ctx) {
|
|
68628
68933
|
try {
|
|
68629
|
-
const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
|
|
68934
|
+
const continuationState = await getContinuationState(ctx.directory, ctx.sessionID, ctx.client);
|
|
68630
68935
|
if (continuationState.hasActiveHookMarker) {
|
|
68631
68936
|
const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
|
|
68632
68937
|
logWaiting(ctx, reason);
|
|
@@ -69221,7 +69526,7 @@ async function getLocalVersion(options = {}) {
|
|
|
69221
69526
|
}
|
|
69222
69527
|
}
|
|
69223
69528
|
// src/cli/doctor/constants.ts
|
|
69224
|
-
|
|
69529
|
+
init_shared();
|
|
69225
69530
|
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
69226
69531
|
var SYMBOLS3 = {
|
|
69227
69532
|
check: import_picocolors16.default.green("\u2713"),
|
|
@@ -69255,34 +69560,34 @@ var EXIT_CODES = {
|
|
|
69255
69560
|
FAILURE: 1
|
|
69256
69561
|
};
|
|
69257
69562
|
var MIN_OPENCODE_VERSION = "1.0.150";
|
|
69258
|
-
var
|
|
69563
|
+
var PACKAGE_NAME2 = PLUGIN_NAME;
|
|
69259
69564
|
var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
|
|
69260
69565
|
|
|
69261
69566
|
// src/cli/doctor/checks/system.ts
|
|
69262
|
-
import { existsSync as
|
|
69567
|
+
import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
|
|
69263
69568
|
|
|
69264
69569
|
// src/cli/doctor/checks/system-binary.ts
|
|
69265
69570
|
init_spawn_with_windows_hide();
|
|
69266
|
-
import { existsSync as
|
|
69571
|
+
import { existsSync as existsSync23 } from "fs";
|
|
69267
69572
|
import { homedir as homedir5 } from "os";
|
|
69268
|
-
import { join as
|
|
69573
|
+
import { join as join24 } from "path";
|
|
69269
69574
|
function getDesktopAppPaths(platform) {
|
|
69270
69575
|
const home = homedir5();
|
|
69271
69576
|
switch (platform) {
|
|
69272
69577
|
case "darwin":
|
|
69273
69578
|
return [
|
|
69274
69579
|
"/Applications/OpenCode.app/Contents/MacOS/OpenCode",
|
|
69275
|
-
|
|
69580
|
+
join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
|
|
69276
69581
|
];
|
|
69277
69582
|
case "win32": {
|
|
69278
69583
|
const programFiles = process.env.ProgramFiles;
|
|
69279
69584
|
const localAppData = process.env.LOCALAPPDATA;
|
|
69280
69585
|
const paths = [];
|
|
69281
69586
|
if (programFiles) {
|
|
69282
|
-
paths.push(
|
|
69587
|
+
paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
|
|
69283
69588
|
}
|
|
69284
69589
|
if (localAppData) {
|
|
69285
|
-
paths.push(
|
|
69590
|
+
paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
|
|
69286
69591
|
}
|
|
69287
69592
|
return paths;
|
|
69288
69593
|
}
|
|
@@ -69290,8 +69595,8 @@ function getDesktopAppPaths(platform) {
|
|
|
69290
69595
|
return [
|
|
69291
69596
|
"/usr/bin/opencode",
|
|
69292
69597
|
"/usr/lib/opencode/opencode",
|
|
69293
|
-
|
|
69294
|
-
|
|
69598
|
+
join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
|
|
69599
|
+
join24(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
|
|
69295
69600
|
];
|
|
69296
69601
|
default:
|
|
69297
69602
|
return [];
|
|
@@ -69303,7 +69608,7 @@ function buildVersionCommand(binaryPath, platform) {
|
|
|
69303
69608
|
}
|
|
69304
69609
|
return [binaryPath, "--version"];
|
|
69305
69610
|
}
|
|
69306
|
-
function findDesktopBinary(platform = process.platform, checkExists =
|
|
69611
|
+
function findDesktopBinary(platform = process.platform, checkExists = existsSync23) {
|
|
69307
69612
|
for (const desktopPath of getDesktopAppPaths(platform)) {
|
|
69308
69613
|
if (checkExists(desktopPath)) {
|
|
69309
69614
|
return { binary: "opencode", path: desktopPath };
|
|
@@ -69320,7 +69625,7 @@ async function findOpenCodeBinary() {
|
|
|
69320
69625
|
}
|
|
69321
69626
|
return findDesktopBinary();
|
|
69322
69627
|
}
|
|
69323
|
-
async function
|
|
69628
|
+
async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
|
|
69324
69629
|
try {
|
|
69325
69630
|
const command = buildVersionCommand(binaryPath, platform);
|
|
69326
69631
|
const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
|
|
@@ -69333,10 +69638,10 @@ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
|
|
|
69333
69638
|
return null;
|
|
69334
69639
|
}
|
|
69335
69640
|
}
|
|
69336
|
-
function
|
|
69337
|
-
const
|
|
69338
|
-
const currentParts =
|
|
69339
|
-
const minimumParts =
|
|
69641
|
+
function compareVersions2(current, minimum) {
|
|
69642
|
+
const parseVersion2 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
69643
|
+
const currentParts = parseVersion2(current);
|
|
69644
|
+
const minimumParts = parseVersion2(minimum);
|
|
69340
69645
|
const length = Math.max(currentParts.length, minimumParts.length);
|
|
69341
69646
|
for (let index = 0;index < length; index++) {
|
|
69342
69647
|
const currentPart = currentParts[index] ?? 0;
|
|
@@ -69351,12 +69656,12 @@ function compareVersions(current, minimum) {
|
|
|
69351
69656
|
|
|
69352
69657
|
// src/cli/doctor/checks/system-plugin.ts
|
|
69353
69658
|
init_shared();
|
|
69354
|
-
import { existsSync as
|
|
69659
|
+
import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
|
|
69355
69660
|
function detectConfigPath() {
|
|
69356
69661
|
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
69357
|
-
if (
|
|
69662
|
+
if (existsSync24(paths.configJsonc))
|
|
69358
69663
|
return paths.configJsonc;
|
|
69359
|
-
if (
|
|
69664
|
+
if (existsSync24(paths.configJson))
|
|
69360
69665
|
return paths.configJson;
|
|
69361
69666
|
return null;
|
|
69362
69667
|
}
|
|
@@ -69402,7 +69707,7 @@ function getPluginInfo() {
|
|
|
69402
69707
|
};
|
|
69403
69708
|
}
|
|
69404
69709
|
try {
|
|
69405
|
-
const content =
|
|
69710
|
+
const content = readFileSync20(configPath, "utf-8");
|
|
69406
69711
|
const parsedConfig = parseJsonc(content);
|
|
69407
69712
|
const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
|
|
69408
69713
|
if (!pluginEntry) {
|
|
@@ -69440,37 +69745,37 @@ function getPluginInfo() {
|
|
|
69440
69745
|
init_file_utils();
|
|
69441
69746
|
init_checker();
|
|
69442
69747
|
init_auto_update_checker();
|
|
69443
|
-
import { existsSync as
|
|
69748
|
+
import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
|
|
69444
69749
|
import { homedir as homedir6 } from "os";
|
|
69445
|
-
import { join as
|
|
69750
|
+
import { join as join25 } from "path";
|
|
69446
69751
|
init_shared();
|
|
69447
69752
|
function getPlatformDefaultCacheDir(platform = process.platform) {
|
|
69448
69753
|
if (platform === "darwin")
|
|
69449
|
-
return
|
|
69754
|
+
return join25(homedir6(), "Library", "Caches");
|
|
69450
69755
|
if (platform === "win32")
|
|
69451
|
-
return process.env.LOCALAPPDATA ??
|
|
69452
|
-
return
|
|
69756
|
+
return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
|
|
69757
|
+
return join25(homedir6(), ".cache");
|
|
69453
69758
|
}
|
|
69454
69759
|
function resolveOpenCodeCacheDir() {
|
|
69455
69760
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
69456
69761
|
if (xdgCacheHome)
|
|
69457
|
-
return
|
|
69762
|
+
return join25(xdgCacheHome, "opencode");
|
|
69458
69763
|
const fromShared = getOpenCodeCacheDir();
|
|
69459
|
-
const platformDefault =
|
|
69460
|
-
if (
|
|
69764
|
+
const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
|
|
69765
|
+
if (existsSync25(fromShared) || !existsSync25(platformDefault))
|
|
69461
69766
|
return fromShared;
|
|
69462
69767
|
return platformDefault;
|
|
69463
69768
|
}
|
|
69464
69769
|
function resolveExistingDir(dirPath) {
|
|
69465
|
-
if (!
|
|
69770
|
+
if (!existsSync25(dirPath))
|
|
69466
69771
|
return dirPath;
|
|
69467
69772
|
return resolveSymlink(dirPath);
|
|
69468
69773
|
}
|
|
69469
69774
|
function readPackageJson(filePath) {
|
|
69470
|
-
if (!
|
|
69775
|
+
if (!existsSync25(filePath))
|
|
69471
69776
|
return null;
|
|
69472
69777
|
try {
|
|
69473
|
-
const content =
|
|
69778
|
+
const content = readFileSync21(filePath, "utf-8");
|
|
69474
69779
|
return parseJsonc(content);
|
|
69475
69780
|
} catch {
|
|
69476
69781
|
return null;
|
|
@@ -69489,20 +69794,20 @@ function getLoadedPluginVersion() {
|
|
|
69489
69794
|
const candidates = [
|
|
69490
69795
|
{
|
|
69491
69796
|
cacheDir: configDir,
|
|
69492
|
-
cachePackagePath:
|
|
69493
|
-
installedPackagePath:
|
|
69797
|
+
cachePackagePath: join25(configDir, "package.json"),
|
|
69798
|
+
installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
|
|
69494
69799
|
},
|
|
69495
69800
|
{
|
|
69496
69801
|
cacheDir,
|
|
69497
|
-
cachePackagePath:
|
|
69498
|
-
installedPackagePath:
|
|
69802
|
+
cachePackagePath: join25(cacheDir, "package.json"),
|
|
69803
|
+
installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
|
|
69499
69804
|
}
|
|
69500
69805
|
];
|
|
69501
|
-
const selectedCandidate = candidates.find((candidate) =>
|
|
69806
|
+
const selectedCandidate = candidates.find((candidate) => existsSync25(candidate.installedPackagePath)) ?? candidates[0];
|
|
69502
69807
|
const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
|
|
69503
69808
|
const cachePackage = readPackageJson(cachePackagePath);
|
|
69504
69809
|
const installedPackage = readPackageJson(installedPackagePath);
|
|
69505
|
-
const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[
|
|
69810
|
+
const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME2]);
|
|
69506
69811
|
const loadedVersion = normalizeVersion(installedPackage?.version);
|
|
69507
69812
|
return {
|
|
69508
69813
|
cacheDir: selectedDir,
|
|
@@ -69522,13 +69827,14 @@ function getSuggestedInstallTag(currentVersion) {
|
|
|
69522
69827
|
|
|
69523
69828
|
// src/cli/doctor/checks/system.ts
|
|
69524
69829
|
init_shared();
|
|
69830
|
+
init_plugin_identity();
|
|
69525
69831
|
function isConfigValid(configPath) {
|
|
69526
69832
|
if (!configPath)
|
|
69527
69833
|
return true;
|
|
69528
|
-
if (!
|
|
69834
|
+
if (!existsSync26(configPath))
|
|
69529
69835
|
return false;
|
|
69530
69836
|
try {
|
|
69531
|
-
parseJsonc(
|
|
69837
|
+
parseJsonc(readFileSync22(configPath, "utf-8"));
|
|
69532
69838
|
return true;
|
|
69533
69839
|
} catch {
|
|
69534
69840
|
return false;
|
|
@@ -69551,7 +69857,7 @@ function buildMessage(status, issues) {
|
|
|
69551
69857
|
async function gatherSystemInfo() {
|
|
69552
69858
|
const [binaryInfo, pluginInfo] = await Promise.all([findOpenCodeBinary(), Promise.resolve(getPluginInfo())]);
|
|
69553
69859
|
const loadedInfo = getLoadedPluginVersion();
|
|
69554
|
-
const opencodeVersion = binaryInfo ? await
|
|
69860
|
+
const opencodeVersion = binaryInfo ? await getOpenCodeVersion3(binaryInfo.path) : null;
|
|
69555
69861
|
const pluginVersion = pluginInfo.pinnedVersion ?? loadedInfo.expectedVersion ?? loadedInfo.loadedVersion;
|
|
69556
69862
|
return {
|
|
69557
69863
|
opencodeVersion,
|
|
@@ -69579,7 +69885,7 @@ async function checkSystem() {
|
|
|
69579
69885
|
affects: ["doctor", "run"]
|
|
69580
69886
|
});
|
|
69581
69887
|
}
|
|
69582
|
-
if (systemInfo.opencodeVersion && !
|
|
69888
|
+
if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
|
|
69583
69889
|
issues.push({
|
|
69584
69890
|
title: "OpenCode version below minimum",
|
|
69585
69891
|
description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
|
|
@@ -69590,13 +69896,26 @@ async function checkSystem() {
|
|
|
69590
69896
|
}
|
|
69591
69897
|
if (!pluginInfo.registered) {
|
|
69592
69898
|
issues.push({
|
|
69593
|
-
title: `${
|
|
69899
|
+
title: `${PLUGIN_NAME} is not registered`,
|
|
69594
69900
|
description: "Plugin entry is missing from OpenCode configuration.",
|
|
69595
|
-
fix: `Run: bunx ${
|
|
69901
|
+
fix: `Run: bunx ${PLUGIN_NAME} install`,
|
|
69596
69902
|
severity: "error",
|
|
69597
69903
|
affects: ["all agents"]
|
|
69598
69904
|
});
|
|
69599
69905
|
}
|
|
69906
|
+
if (pluginInfo.entry && !pluginInfo.isLocalDev) {
|
|
69907
|
+
const isLegacyName = pluginInfo.entry === LEGACY_PLUGIN_NAME || pluginInfo.entry.startsWith(`${LEGACY_PLUGIN_NAME}@`);
|
|
69908
|
+
if (isLegacyName) {
|
|
69909
|
+
const suggestedEntry = pluginInfo.entry.replace(LEGACY_PLUGIN_NAME, PLUGIN_NAME);
|
|
69910
|
+
issues.push({
|
|
69911
|
+
title: "Using legacy package name",
|
|
69912
|
+
description: `Your opencode.json references "${LEGACY_PLUGIN_NAME}" which has been renamed to "${PLUGIN_NAME}". The old name may stop working in a future release.`,
|
|
69913
|
+
fix: `Update your opencode.json plugin entry: "${pluginInfo.entry}" \u2192 "${suggestedEntry}"`,
|
|
69914
|
+
severity: "warning",
|
|
69915
|
+
affects: ["plugin loading"]
|
|
69916
|
+
});
|
|
69917
|
+
}
|
|
69918
|
+
}
|
|
69600
69919
|
if (loadedInfo.expectedVersion && loadedInfo.loadedVersion && loadedInfo.expectedVersion !== loadedInfo.loadedVersion) {
|
|
69601
69920
|
issues.push({
|
|
69602
69921
|
title: "Loaded plugin version mismatch",
|
|
@@ -69606,11 +69925,11 @@ async function checkSystem() {
|
|
|
69606
69925
|
affects: ["plugin loading"]
|
|
69607
69926
|
});
|
|
69608
69927
|
}
|
|
69609
|
-
if (systemInfo.loadedVersion && latestVersion && !
|
|
69928
|
+
if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
|
|
69610
69929
|
issues.push({
|
|
69611
69930
|
title: "Loaded plugin is outdated",
|
|
69612
69931
|
description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
|
|
69613
|
-
fix: `Update: cd "${loadedInfo.cacheDir}" && bun add ${
|
|
69932
|
+
fix: `Update: cd "${loadedInfo.cacheDir}" && bun add ${PLUGIN_NAME}@${installTag}`,
|
|
69614
69933
|
severity: "warning",
|
|
69615
69934
|
affects: ["plugin features"]
|
|
69616
69935
|
});
|
|
@@ -69631,29 +69950,28 @@ async function checkSystem() {
|
|
|
69631
69950
|
}
|
|
69632
69951
|
|
|
69633
69952
|
// src/cli/doctor/checks/config.ts
|
|
69634
|
-
import { readFileSync as
|
|
69635
|
-
import { join as
|
|
69953
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
69954
|
+
import { join as join29 } from "path";
|
|
69636
69955
|
init_shared();
|
|
69637
|
-
init_plugin_identity();
|
|
69638
69956
|
|
|
69639
69957
|
// src/cli/doctor/checks/model-resolution-cache.ts
|
|
69640
69958
|
init_shared();
|
|
69641
|
-
import { existsSync as
|
|
69959
|
+
import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
|
|
69642
69960
|
import { homedir as homedir7 } from "os";
|
|
69643
|
-
import { join as
|
|
69961
|
+
import { join as join26 } from "path";
|
|
69644
69962
|
function getOpenCodeCacheDir2() {
|
|
69645
69963
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
69646
69964
|
if (xdgCache)
|
|
69647
|
-
return
|
|
69648
|
-
return
|
|
69965
|
+
return join26(xdgCache, "opencode");
|
|
69966
|
+
return join26(homedir7(), ".cache", "opencode");
|
|
69649
69967
|
}
|
|
69650
69968
|
function loadAvailableModelsFromCache() {
|
|
69651
|
-
const cacheFile =
|
|
69652
|
-
if (!
|
|
69969
|
+
const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
|
|
69970
|
+
if (!existsSync27(cacheFile)) {
|
|
69653
69971
|
return { providers: [], modelCount: 0, cacheExists: false };
|
|
69654
69972
|
}
|
|
69655
69973
|
try {
|
|
69656
|
-
const content =
|
|
69974
|
+
const content = readFileSync23(cacheFile, "utf-8");
|
|
69657
69975
|
const data = parseJsonc(content);
|
|
69658
69976
|
const providers = Object.keys(data);
|
|
69659
69977
|
let modelCount = 0;
|
|
@@ -69675,25 +69993,24 @@ init_model_capabilities();
|
|
|
69675
69993
|
|
|
69676
69994
|
// src/cli/doctor/checks/model-resolution-config.ts
|
|
69677
69995
|
init_shared();
|
|
69678
|
-
|
|
69679
|
-
import {
|
|
69680
|
-
|
|
69681
|
-
var USER_CONFIG_DIR2 = getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir;
|
|
69682
|
-
var PROJECT_CONFIG_DIR = join23(process.cwd(), ".opencode");
|
|
69996
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
69997
|
+
import { join as join27 } from "path";
|
|
69998
|
+
var PROJECT_CONFIG_DIR = join27(process.cwd(), ".opencode");
|
|
69683
69999
|
function loadOmoConfig() {
|
|
69684
|
-
const projectDetected =
|
|
70000
|
+
const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
|
|
69685
70001
|
if (projectDetected.format !== "none") {
|
|
69686
70002
|
try {
|
|
69687
|
-
const content =
|
|
70003
|
+
const content = readFileSync24(projectDetected.path, "utf-8");
|
|
69688
70004
|
return parseJsonc(content);
|
|
69689
70005
|
} catch {
|
|
69690
70006
|
return null;
|
|
69691
70007
|
}
|
|
69692
70008
|
}
|
|
69693
|
-
const
|
|
70009
|
+
const userConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70010
|
+
const userDetected = detectPluginConfigFile(userConfigDir);
|
|
69694
70011
|
if (userDetected.format !== "none") {
|
|
69695
70012
|
try {
|
|
69696
|
-
const content =
|
|
70013
|
+
const content = readFileSync24(userDetected.path, "utf-8");
|
|
69697
70014
|
return parseJsonc(content);
|
|
69698
70015
|
} catch {
|
|
69699
70016
|
return null;
|
|
@@ -69704,7 +70021,7 @@ function loadOmoConfig() {
|
|
|
69704
70021
|
|
|
69705
70022
|
// src/cli/doctor/checks/model-resolution-details.ts
|
|
69706
70023
|
init_shared();
|
|
69707
|
-
import { join as
|
|
70024
|
+
import { join as join28 } from "path";
|
|
69708
70025
|
|
|
69709
70026
|
// src/cli/doctor/checks/model-resolution-variant.ts
|
|
69710
70027
|
function formatModelWithVariant(model, variant) {
|
|
@@ -69746,7 +70063,7 @@ function formatCapabilityResolutionLabel(mode) {
|
|
|
69746
70063
|
}
|
|
69747
70064
|
function buildModelResolutionDetails(options) {
|
|
69748
70065
|
const details = [];
|
|
69749
|
-
const cacheFile =
|
|
70066
|
+
const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
|
|
69750
70067
|
details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
|
|
69751
70068
|
details.push("");
|
|
69752
70069
|
if (options.available.cacheExists) {
|
|
@@ -69901,11 +70218,13 @@ async function checkModels() {
|
|
|
69901
70218
|
}
|
|
69902
70219
|
|
|
69903
70220
|
// src/cli/doctor/checks/config.ts
|
|
70221
|
+
var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
|
|
69904
70222
|
function findConfigPath() {
|
|
69905
|
-
const projectConfig =
|
|
70223
|
+
const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
|
|
69906
70224
|
if (projectConfig.format !== "none")
|
|
69907
70225
|
return projectConfig.path;
|
|
69908
|
-
const
|
|
70226
|
+
const userConfigDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70227
|
+
const userConfig = detectPluginConfigFile(userConfigDir);
|
|
69909
70228
|
if (userConfig.format !== "none")
|
|
69910
70229
|
return userConfig.path;
|
|
69911
70230
|
return null;
|
|
@@ -69916,7 +70235,7 @@ function validateConfig() {
|
|
|
69916
70235
|
return { exists: false, path: null, valid: true, config: null, errors: [] };
|
|
69917
70236
|
}
|
|
69918
70237
|
try {
|
|
69919
|
-
const content =
|
|
70238
|
+
const content = readFileSync25(configPath, "utf-8");
|
|
69920
70239
|
const rawConfig = parseJsonc(content);
|
|
69921
70240
|
const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
|
|
69922
70241
|
if (!schemaResult.success) {
|
|
@@ -70020,9 +70339,9 @@ async function checkConfig() {
|
|
|
70020
70339
|
|
|
70021
70340
|
// src/cli/doctor/checks/dependencies.ts
|
|
70022
70341
|
init_spawn_with_windows_hide();
|
|
70023
|
-
import { existsSync as
|
|
70342
|
+
import { existsSync as existsSync28 } from "fs";
|
|
70024
70343
|
import { createRequire } from "module";
|
|
70025
|
-
import { dirname as dirname7, join as
|
|
70344
|
+
import { dirname as dirname7, join as join30 } from "path";
|
|
70026
70345
|
async function checkBinaryExists(binary2) {
|
|
70027
70346
|
try {
|
|
70028
70347
|
const path10 = Bun.which(binary2);
|
|
@@ -70078,15 +70397,15 @@ async function checkAstGrepNapi() {
|
|
|
70078
70397
|
path: null
|
|
70079
70398
|
};
|
|
70080
70399
|
} catch {
|
|
70081
|
-
const { existsSync:
|
|
70082
|
-
const { join:
|
|
70400
|
+
const { existsSync: existsSync29 } = await import("fs");
|
|
70401
|
+
const { join: join31 } = await import("path");
|
|
70083
70402
|
const { homedir: homedir8 } = await import("os");
|
|
70084
70403
|
const pathsToCheck = [
|
|
70085
|
-
|
|
70086
|
-
|
|
70404
|
+
join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
|
|
70405
|
+
join31(process.cwd(), "node_modules", "@ast-grep", "napi")
|
|
70087
70406
|
];
|
|
70088
70407
|
for (const napiPath of pathsToCheck) {
|
|
70089
|
-
if (
|
|
70408
|
+
if (existsSync29(napiPath)) {
|
|
70090
70409
|
return {
|
|
70091
70410
|
name: "AST-Grep NAPI",
|
|
70092
70411
|
required: false,
|
|
@@ -70111,8 +70430,8 @@ function findCommentCheckerPackageBinary() {
|
|
|
70111
70430
|
try {
|
|
70112
70431
|
const require2 = createRequire(import.meta.url);
|
|
70113
70432
|
const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
70114
|
-
const binaryPath =
|
|
70115
|
-
if (
|
|
70433
|
+
const binaryPath = join30(dirname7(pkgPath), "bin", binaryName);
|
|
70434
|
+
if (existsSync28(binaryPath))
|
|
70116
70435
|
return binaryPath;
|
|
70117
70436
|
} catch {}
|
|
70118
70437
|
return null;
|
|
@@ -70269,16 +70588,15 @@ var BUILTIN_SERVERS = {
|
|
|
70269
70588
|
"kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
|
|
70270
70589
|
};
|
|
70271
70590
|
// src/tools/lsp/server-config-loader.ts
|
|
70272
|
-
import { existsSync as
|
|
70273
|
-
import { join as
|
|
70591
|
+
import { existsSync as existsSync29, readFileSync as readFileSync26 } from "fs";
|
|
70592
|
+
import { join as join31 } from "path";
|
|
70274
70593
|
init_shared();
|
|
70275
70594
|
init_jsonc_parser();
|
|
70276
|
-
init_plugin_identity();
|
|
70277
70595
|
function loadJsonFile(path10) {
|
|
70278
|
-
if (!
|
|
70596
|
+
if (!existsSync29(path10))
|
|
70279
70597
|
return null;
|
|
70280
70598
|
try {
|
|
70281
|
-
return parseJsonc(
|
|
70599
|
+
return parseJsonc(readFileSync26(path10, "utf-8"));
|
|
70282
70600
|
} catch {
|
|
70283
70601
|
return null;
|
|
70284
70602
|
}
|
|
@@ -70287,9 +70605,9 @@ function getConfigPaths2() {
|
|
|
70287
70605
|
const cwd = process.cwd();
|
|
70288
70606
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70289
70607
|
return {
|
|
70290
|
-
project:
|
|
70291
|
-
user:
|
|
70292
|
-
opencode: detectConfigFile(
|
|
70608
|
+
project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
|
|
70609
|
+
user: detectPluginConfigFile(configDir).path,
|
|
70610
|
+
opencode: detectConfigFile(join31(configDir, "opencode")).path
|
|
70293
70611
|
};
|
|
70294
70612
|
}
|
|
70295
70613
|
function loadAllConfigs() {
|
|
@@ -70358,21 +70676,21 @@ function getMergedServers() {
|
|
|
70358
70676
|
}
|
|
70359
70677
|
|
|
70360
70678
|
// src/tools/lsp/server-installation.ts
|
|
70361
|
-
import { existsSync as
|
|
70362
|
-
import { delimiter as delimiter2, join as
|
|
70679
|
+
import { existsSync as existsSync30 } from "fs";
|
|
70680
|
+
import { delimiter as delimiter2, join as join33 } from "path";
|
|
70363
70681
|
|
|
70364
70682
|
// src/tools/lsp/server-path-bases.ts
|
|
70365
70683
|
init_shared();
|
|
70366
|
-
import { join as
|
|
70684
|
+
import { join as join32 } from "path";
|
|
70367
70685
|
function getLspServerAdditionalPathBases(workingDirectory) {
|
|
70368
70686
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70369
|
-
const dataDir =
|
|
70687
|
+
const dataDir = join32(getDataDir(), "opencode");
|
|
70370
70688
|
return [
|
|
70371
|
-
|
|
70372
|
-
|
|
70373
|
-
|
|
70374
|
-
|
|
70375
|
-
|
|
70689
|
+
join32(workingDirectory, "node_modules", ".bin"),
|
|
70690
|
+
join32(configDir, "bin"),
|
|
70691
|
+
join32(configDir, "node_modules", ".bin"),
|
|
70692
|
+
join32(dataDir, "bin"),
|
|
70693
|
+
join32(dataDir, "bin", "node_modules", ".bin")
|
|
70376
70694
|
];
|
|
70377
70695
|
}
|
|
70378
70696
|
|
|
@@ -70382,7 +70700,7 @@ function isServerInstalled(command) {
|
|
|
70382
70700
|
return false;
|
|
70383
70701
|
const cmd = command[0];
|
|
70384
70702
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
70385
|
-
if (
|
|
70703
|
+
if (existsSync30(cmd))
|
|
70386
70704
|
return true;
|
|
70387
70705
|
}
|
|
70388
70706
|
const isWindows = process.platform === "win32";
|
|
@@ -70403,14 +70721,14 @@ function isServerInstalled(command) {
|
|
|
70403
70721
|
const paths = pathEnv.split(delimiter2);
|
|
70404
70722
|
for (const p2 of paths) {
|
|
70405
70723
|
for (const suffix of exts) {
|
|
70406
|
-
if (
|
|
70724
|
+
if (existsSync30(join33(p2, cmd + suffix))) {
|
|
70407
70725
|
return true;
|
|
70408
70726
|
}
|
|
70409
70727
|
}
|
|
70410
70728
|
}
|
|
70411
70729
|
for (const base of getLspServerAdditionalPathBases(process.cwd())) {
|
|
70412
70730
|
for (const suffix of exts) {
|
|
70413
|
-
if (
|
|
70731
|
+
if (existsSync30(join33(base, cmd + suffix))) {
|
|
70414
70732
|
return true;
|
|
70415
70733
|
}
|
|
70416
70734
|
}
|
|
@@ -70472,24 +70790,24 @@ function getInstalledLspServers() {
|
|
|
70472
70790
|
|
|
70473
70791
|
// src/cli/doctor/checks/tools-mcp.ts
|
|
70474
70792
|
init_shared();
|
|
70475
|
-
import { existsSync as
|
|
70793
|
+
import { existsSync as existsSync31, readFileSync as readFileSync27 } from "fs";
|
|
70476
70794
|
import { homedir as homedir8 } from "os";
|
|
70477
|
-
import { join as
|
|
70795
|
+
import { join as join34 } from "path";
|
|
70478
70796
|
var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
|
|
70479
70797
|
function getMcpConfigPaths() {
|
|
70480
70798
|
return [
|
|
70481
|
-
|
|
70482
|
-
|
|
70483
|
-
|
|
70799
|
+
join34(homedir8(), ".claude", ".mcp.json"),
|
|
70800
|
+
join34(process.cwd(), ".mcp.json"),
|
|
70801
|
+
join34(process.cwd(), ".claude", ".mcp.json")
|
|
70484
70802
|
];
|
|
70485
70803
|
}
|
|
70486
70804
|
function loadUserMcpConfig() {
|
|
70487
70805
|
const servers = {};
|
|
70488
70806
|
for (const configPath of getMcpConfigPaths()) {
|
|
70489
|
-
if (!
|
|
70807
|
+
if (!existsSync31(configPath))
|
|
70490
70808
|
continue;
|
|
70491
70809
|
try {
|
|
70492
|
-
const content =
|
|
70810
|
+
const content = readFileSync27(configPath, "utf-8");
|
|
70493
70811
|
const config2 = parseJsonc(content);
|
|
70494
70812
|
if (config2.mcpServers) {
|
|
70495
70813
|
Object.assign(servers, config2.mcpServers);
|
|
@@ -70689,7 +71007,6 @@ function formatIssue(issue2, index) {
|
|
|
70689
71007
|
}
|
|
70690
71008
|
|
|
70691
71009
|
// src/cli/doctor/format-default.ts
|
|
70692
|
-
init_plugin_identity();
|
|
70693
71010
|
function formatDefault(result) {
|
|
70694
71011
|
const lines = [];
|
|
70695
71012
|
lines.push(formatHeader());
|
|
@@ -70697,7 +71014,7 @@ function formatDefault(result) {
|
|
|
70697
71014
|
if (allIssues.length === 0) {
|
|
70698
71015
|
const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
|
|
70699
71016
|
const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
|
|
70700
|
-
lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7
|
|
71017
|
+
lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 evil-omo ${pluginVer})`)}`);
|
|
70701
71018
|
} else {
|
|
70702
71019
|
const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
|
|
70703
71020
|
const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
|
|
@@ -70745,7 +71062,6 @@ function formatStatus(result) {
|
|
|
70745
71062
|
|
|
70746
71063
|
// src/cli/doctor/format-verbose.ts
|
|
70747
71064
|
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
70748
|
-
init_plugin_identity();
|
|
70749
71065
|
function formatVerbose(result) {
|
|
70750
71066
|
const lines = [];
|
|
70751
71067
|
lines.push(formatHeader());
|
|
@@ -70753,7 +71069,7 @@ function formatVerbose(result) {
|
|
|
70753
71069
|
lines.push(`${import_picocolors20.default.bold("System Information")}`);
|
|
70754
71070
|
lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
|
|
70755
71071
|
lines.push(` ${formatStatusSymbol("pass")} opencode ${systemInfo.opencodeVersion ?? "unknown"}`);
|
|
70756
|
-
lines.push(` ${formatStatusSymbol("pass")}
|
|
71072
|
+
lines.push(` ${formatStatusSymbol("pass")} evil-omo ${systemInfo.pluginVersion ?? "unknown"}`);
|
|
70757
71073
|
if (systemInfo.loadedVersion) {
|
|
70758
71074
|
lines.push(` ${formatStatusSymbol("pass")} loaded ${systemInfo.loadedVersion}`);
|
|
70759
71075
|
}
|
|
@@ -70910,13 +71226,45 @@ async function doctor(options = { mode: "default" }) {
|
|
|
70910
71226
|
return result.exitCode;
|
|
70911
71227
|
}
|
|
70912
71228
|
|
|
71229
|
+
// src/cli/refresh-model-capabilities.ts
|
|
71230
|
+
init_model_capabilities_cache();
|
|
71231
|
+
async function refreshModelCapabilities(options, deps = {}) {
|
|
71232
|
+
const directory = options.directory ?? process.cwd();
|
|
71233
|
+
const loadConfig = deps.loadConfig ?? loadPluginConfig;
|
|
71234
|
+
const refreshCache = deps.refreshCache ?? refreshModelCapabilitiesCache;
|
|
71235
|
+
const stdout = deps.stdout ?? process.stdout;
|
|
71236
|
+
const stderr = deps.stderr ?? process.stderr;
|
|
71237
|
+
try {
|
|
71238
|
+
const config2 = loadConfig(directory, null);
|
|
71239
|
+
const sourceUrl = options.sourceUrl ?? config2.model_capabilities?.source_url;
|
|
71240
|
+
const snapshot = await refreshCache({ sourceUrl });
|
|
71241
|
+
const summary = {
|
|
71242
|
+
sourceUrl: snapshot.sourceUrl,
|
|
71243
|
+
generatedAt: snapshot.generatedAt,
|
|
71244
|
+
modelCount: Object.keys(snapshot.models).length
|
|
71245
|
+
};
|
|
71246
|
+
if (options.json) {
|
|
71247
|
+
stdout.write(`${JSON.stringify(summary, null, 2)}
|
|
71248
|
+
`);
|
|
71249
|
+
} else {
|
|
71250
|
+
stdout.write(`Refreshed model capabilities cache (${summary.modelCount} models) from ${summary.sourceUrl}
|
|
71251
|
+
`);
|
|
71252
|
+
}
|
|
71253
|
+
return 0;
|
|
71254
|
+
} catch (error48) {
|
|
71255
|
+
stderr.write(`Failed to refresh model capabilities cache: ${String(error48)}
|
|
71256
|
+
`);
|
|
71257
|
+
return 1;
|
|
71258
|
+
}
|
|
71259
|
+
}
|
|
71260
|
+
|
|
70913
71261
|
// src/features/mcp-oauth/storage.ts
|
|
70914
71262
|
init_shared();
|
|
70915
|
-
import { chmodSync, existsSync as
|
|
70916
|
-
import { dirname as dirname8, join as
|
|
71263
|
+
import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync8, readFileSync as readFileSync28, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
71264
|
+
import { dirname as dirname8, join as join35 } from "path";
|
|
70917
71265
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
70918
71266
|
function getMcpOauthStoragePath() {
|
|
70919
|
-
return
|
|
71267
|
+
return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
70920
71268
|
}
|
|
70921
71269
|
function normalizeHost(serverHost) {
|
|
70922
71270
|
let host = serverHost.trim();
|
|
@@ -70953,11 +71301,11 @@ function buildKey(serverHost, resource) {
|
|
|
70953
71301
|
}
|
|
70954
71302
|
function readStore() {
|
|
70955
71303
|
const filePath = getMcpOauthStoragePath();
|
|
70956
|
-
if (!
|
|
71304
|
+
if (!existsSync32(filePath)) {
|
|
70957
71305
|
return null;
|
|
70958
71306
|
}
|
|
70959
71307
|
try {
|
|
70960
|
-
const content =
|
|
71308
|
+
const content = readFileSync28(filePath, "utf-8");
|
|
70961
71309
|
return JSON.parse(content);
|
|
70962
71310
|
} catch {
|
|
70963
71311
|
return null;
|
|
@@ -70967,8 +71315,8 @@ function writeStore(store2) {
|
|
|
70967
71315
|
const filePath = getMcpOauthStoragePath();
|
|
70968
71316
|
try {
|
|
70969
71317
|
const dir = dirname8(filePath);
|
|
70970
|
-
if (!
|
|
70971
|
-
|
|
71318
|
+
if (!existsSync32(dir)) {
|
|
71319
|
+
mkdirSync8(dir, { recursive: true });
|
|
70972
71320
|
}
|
|
70973
71321
|
writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
|
|
70974
71322
|
chmodSync(filePath, 384);
|
|
@@ -71002,7 +71350,7 @@ function deleteToken(serverHost, resource) {
|
|
|
71002
71350
|
if (Object.keys(store2).length === 0) {
|
|
71003
71351
|
try {
|
|
71004
71352
|
const filePath = getMcpOauthStoragePath();
|
|
71005
|
-
if (
|
|
71353
|
+
if (existsSync32(filePath)) {
|
|
71006
71354
|
unlinkSync4(filePath);
|
|
71007
71355
|
}
|
|
71008
71356
|
return true;
|
|
@@ -71225,7 +71573,7 @@ function startCallbackServer(port) {
|
|
|
71225
71573
|
clearTimeout(timeoutId);
|
|
71226
71574
|
const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
|
|
71227
71575
|
const code = requestUrl.searchParams.get("code");
|
|
71228
|
-
const
|
|
71576
|
+
const state2 = requestUrl.searchParams.get("state");
|
|
71229
71577
|
const error48 = requestUrl.searchParams.get("error");
|
|
71230
71578
|
if (error48) {
|
|
71231
71579
|
const errorDescription = requestUrl.searchParams.get("error_description") ?? error48;
|
|
@@ -71235,7 +71583,7 @@ function startCallbackServer(port) {
|
|
|
71235
71583
|
reject(new Error(`OAuth authorization error: ${errorDescription}`));
|
|
71236
71584
|
return;
|
|
71237
71585
|
}
|
|
71238
|
-
if (!code || !
|
|
71586
|
+
if (!code || !state2) {
|
|
71239
71587
|
response.writeHead(400, { "content-type": "text/html" });
|
|
71240
71588
|
response.end("<html><body><h1>Missing code or state</h1></body></html>");
|
|
71241
71589
|
server2.close();
|
|
@@ -71245,7 +71593,7 @@ function startCallbackServer(port) {
|
|
|
71245
71593
|
response.writeHead(200, { "content-type": "text/html" });
|
|
71246
71594
|
response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
|
|
71247
71595
|
server2.close();
|
|
71248
|
-
resolve2({ code, state });
|
|
71596
|
+
resolve2({ code, state: state2 });
|
|
71249
71597
|
});
|
|
71250
71598
|
timeoutId = setTimeout(() => {
|
|
71251
71599
|
server2.close();
|
|
@@ -71281,27 +71629,25 @@ function openBrowser(url2) {
|
|
|
71281
71629
|
async function runAuthorizationCodeRedirect(options) {
|
|
71282
71630
|
const verifier = generateCodeVerifier();
|
|
71283
71631
|
const challenge = generateCodeChallenge(verifier);
|
|
71284
|
-
const
|
|
71632
|
+
const state2 = randomBytes2(16).toString("hex");
|
|
71285
71633
|
const authorizationUrl = buildAuthorizationUrl(options.authorizationEndpoint, {
|
|
71286
71634
|
clientId: options.clientId,
|
|
71287
71635
|
redirectUri: options.redirectUri,
|
|
71288
71636
|
codeChallenge: challenge,
|
|
71289
|
-
state,
|
|
71637
|
+
state: state2,
|
|
71290
71638
|
scopes: options.scopes,
|
|
71291
71639
|
resource: options.resource
|
|
71292
71640
|
});
|
|
71293
71641
|
const callbackPromise = startCallbackServer(options.callbackPort);
|
|
71294
71642
|
openBrowser(authorizationUrl);
|
|
71295
71643
|
const result = await callbackPromise;
|
|
71296
|
-
if (result.state !==
|
|
71644
|
+
if (result.state !== state2) {
|
|
71297
71645
|
throw new Error("OAuth state mismatch");
|
|
71298
71646
|
}
|
|
71299
71647
|
return { code: result.code, verifier };
|
|
71300
71648
|
}
|
|
71301
71649
|
|
|
71302
71650
|
// src/features/mcp-oauth/provider.ts
|
|
71303
|
-
init_plugin_identity();
|
|
71304
|
-
|
|
71305
71651
|
class McpOAuthProvider {
|
|
71306
71652
|
serverUrl;
|
|
71307
71653
|
configClientId;
|
|
@@ -71369,7 +71715,7 @@ class McpOAuthProvider {
|
|
|
71369
71715
|
const clientInfo = await getOrRegisterClient({
|
|
71370
71716
|
registrationEndpoint: metadata.registrationEndpoint,
|
|
71371
71717
|
serverIdentifier: this.serverUrl,
|
|
71372
|
-
clientName:
|
|
71718
|
+
clientName: "evil-omo",
|
|
71373
71719
|
redirectUris: [this.redirectUrl()],
|
|
71374
71720
|
tokenEndpointAuthMethod: "none",
|
|
71375
71721
|
clientId: this.configClientId,
|
|
@@ -71560,7 +71906,7 @@ Examples:
|
|
|
71560
71906
|
Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
|
|
71561
71907
|
Claude Native anthropic/ models (Opus, Sonnet, Haiku)
|
|
71562
71908
|
OpenAI Native openai/ models (GPT-5.4 for Oracle)
|
|
71563
|
-
Gemini Native google/ models (Gemini 3 Pro, Flash)
|
|
71909
|
+
Gemini Native google/ models (Gemini 3.1 Pro, Flash)
|
|
71564
71910
|
Copilot github-copilot/ models (fallback)
|
|
71565
71911
|
OpenCode Zen opencode/ models (opencode/claude-opus-4-6, etc.)
|
|
71566
71912
|
Z.ai zai-coding-plan/glm-5 (visual-engineering fallback)
|
|
@@ -71660,6 +72006,14 @@ Examples:
|
|
|
71660
72006
|
const exitCode = await doctor(doctorOptions);
|
|
71661
72007
|
process.exit(exitCode);
|
|
71662
72008
|
});
|
|
72009
|
+
program2.command("refresh-model-capabilities").description("Refresh the cached models.dev-based model capabilities snapshot").option("-d, --directory <path>", "Working directory to read evil-omo config from").option("--source-url <url>", "Override the models.dev source URL").option("--json", "Output refresh summary as JSON").action(async (options) => {
|
|
72010
|
+
const exitCode = await refreshModelCapabilities({
|
|
72011
|
+
directory: options.directory,
|
|
72012
|
+
sourceUrl: options.sourceUrl,
|
|
72013
|
+
json: options.json ?? false
|
|
72014
|
+
});
|
|
72015
|
+
process.exit(exitCode);
|
|
72016
|
+
});
|
|
71663
72017
|
program2.command("version").description("Show version information").action(() => {
|
|
71664
72018
|
console.log(`evil-omo v${VERSION2}`);
|
|
71665
72019
|
});
|