oh-my-opencode 2.5.4 → 2.6.0

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.
Files changed (45) hide show
  1. package/README.ja.md +13 -5
  2. package/README.ko.md +13 -5
  3. package/README.md +43 -5
  4. package/README.zh-cn.md +13 -5
  5. package/dist/cli/get-local-version/formatter.d.ts +3 -0
  6. package/dist/cli/get-local-version/index.d.ts +3 -0
  7. package/dist/cli/get-local-version/types.d.ts +13 -0
  8. package/dist/cli/index.js +1241 -108
  9. package/dist/config/index.d.ts +1 -1
  10. package/dist/config/schema.d.ts +87 -0
  11. package/dist/features/background-agent/manager.d.ts +1 -0
  12. package/dist/features/claude-code-plugin-loader/index.d.ts +3 -0
  13. package/dist/features/claude-code-plugin-loader/loader.d.ts +20 -0
  14. package/dist/features/claude-code-plugin-loader/types.d.ts +173 -0
  15. package/dist/hooks/anthropic-auto-compact/index.d.ts +1 -1
  16. package/dist/hooks/anthropic-auto-compact/pruning-deduplication.d.ts +7 -0
  17. package/dist/hooks/anthropic-auto-compact/pruning-deduplication.test.d.ts +1 -0
  18. package/dist/hooks/anthropic-auto-compact/pruning-executor.d.ts +3 -0
  19. package/dist/hooks/anthropic-auto-compact/pruning-purge-errors.d.ts +7 -0
  20. package/dist/hooks/anthropic-auto-compact/pruning-storage.d.ts +2 -0
  21. package/dist/hooks/anthropic-auto-compact/pruning-supersede.d.ts +6 -0
  22. package/dist/hooks/anthropic-auto-compact/pruning-types.d.ts +36 -0
  23. package/dist/hooks/anthropic-auto-compact/types.d.ts +5 -0
  24. package/dist/hooks/index.d.ts +1 -0
  25. package/dist/hooks/session-notification-utils.d.ts +9 -0
  26. package/dist/hooks/thinking-block-validator/index.d.ts +30 -0
  27. package/dist/index.js +2723 -644
  28. package/dist/shared/claude-config-dir.d.ts +1 -0
  29. package/dist/shared/claude-config-dir.test.d.ts +1 -0
  30. package/dist/shared/index.d.ts +2 -0
  31. package/dist/shared/jsonc-parser.d.ts +15 -0
  32. package/dist/shared/jsonc-parser.test.d.ts +1 -0
  33. package/dist/tools/ast-grep/index.d.ts +2 -90
  34. package/dist/tools/ast-grep/tools.d.ts +3 -88
  35. package/dist/tools/background-task/tools.d.ts +4 -38
  36. package/dist/tools/call-omo-agent/tools.d.ts +2 -21
  37. package/dist/tools/glob/tools.d.ts +2 -11
  38. package/dist/tools/grep/tools.d.ts +2 -13
  39. package/dist/tools/index.d.ts +3 -367
  40. package/dist/tools/interactive-bash/tools.d.ts +2 -9
  41. package/dist/tools/look-at/tools.d.ts +2 -12
  42. package/dist/tools/lsp/tools.d.ts +12 -152
  43. package/dist/tools/session-manager/tools.d.ts +5 -52
  44. package/dist/tools/slashcommand/tools.d.ts +2 -9
  45. package/package.json +2 -1
package/dist/cli/index.js CHANGED
@@ -2244,7 +2244,7 @@ var require_picocolors = __commonJS((exports, module) => {
2244
2244
  var require_package = __commonJS((exports, module) => {
2245
2245
  module.exports = {
2246
2246
  name: "oh-my-opencode",
2247
- version: "2.5.3",
2247
+ version: "2.5.4",
2248
2248
  description: "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
2249
2249
  main: "dist/index.js",
2250
2250
  types: "dist/index.d.ts",
@@ -2303,6 +2303,7 @@ var require_package = __commonJS((exports, module) => {
2303
2303
  "@opencode-ai/sdk": "^1.0.162",
2304
2304
  commander: "^14.0.2",
2305
2305
  hono: "^4.10.4",
2306
+ "jsonc-parser": "^3.3.1",
2306
2307
  picocolors: "^1.1.1",
2307
2308
  picomatch: "^4.0.2",
2308
2309
  "xdg-basedir": "^5.1.0",
@@ -2923,12 +2924,886 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
2923
2924
  // src/cli/config-manager.ts
2924
2925
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2925
2926
  import { homedir } from "os";
2926
- import { join } from "path";
2927
- var OPENCODE_CONFIG_DIR = join(homedir(), ".config", "opencode");
2928
- var OPENCODE_JSON = join(OPENCODE_CONFIG_DIR, "opencode.json");
2929
- var OPENCODE_JSONC = join(OPENCODE_CONFIG_DIR, "opencode.jsonc");
2930
- var OPENCODE_PACKAGE_JSON = join(OPENCODE_CONFIG_DIR, "package.json");
2931
- var OMO_CONFIG = join(OPENCODE_CONFIG_DIR, "oh-my-opencode.json");
2927
+ import { join as join2 } from "path";
2928
+ // src/shared/command-executor.ts
2929
+ import { exec } from "child_process";
2930
+ import { promisify } from "util";
2931
+ var execAsync = promisify(exec);
2932
+ // src/shared/logger.ts
2933
+ import * as fs from "fs";
2934
+ import * as os from "os";
2935
+ import * as path from "path";
2936
+ var logFile = path.join(os.tmpdir(), "oh-my-opencode.log");
2937
+ function log(message, data) {
2938
+ try {
2939
+ const timestamp = new Date().toISOString();
2940
+ const logEntry = `[${timestamp}] ${message} ${data ? JSON.stringify(data) : ""}
2941
+ `;
2942
+ fs.appendFileSync(logFile, logEntry);
2943
+ } catch {}
2944
+ }
2945
+ // src/shared/deep-merge.ts
2946
+ var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
2947
+ // node_modules/jsonc-parser/lib/esm/impl/scanner.js
2948
+ function createScanner(text, ignoreTrivia = false) {
2949
+ const len = text.length;
2950
+ let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
2951
+ function scanHexDigits(count, exact) {
2952
+ let digits = 0;
2953
+ let value2 = 0;
2954
+ while (digits < count || !exact) {
2955
+ let ch = text.charCodeAt(pos);
2956
+ if (ch >= 48 && ch <= 57) {
2957
+ value2 = value2 * 16 + ch - 48;
2958
+ } else if (ch >= 65 && ch <= 70) {
2959
+ value2 = value2 * 16 + ch - 65 + 10;
2960
+ } else if (ch >= 97 && ch <= 102) {
2961
+ value2 = value2 * 16 + ch - 97 + 10;
2962
+ } else {
2963
+ break;
2964
+ }
2965
+ pos++;
2966
+ digits++;
2967
+ }
2968
+ if (digits < count) {
2969
+ value2 = -1;
2970
+ }
2971
+ return value2;
2972
+ }
2973
+ function setPosition(newPosition) {
2974
+ pos = newPosition;
2975
+ value = "";
2976
+ tokenOffset = 0;
2977
+ token = 16;
2978
+ scanError = 0;
2979
+ }
2980
+ function scanNumber() {
2981
+ let start = pos;
2982
+ if (text.charCodeAt(pos) === 48) {
2983
+ pos++;
2984
+ } else {
2985
+ pos++;
2986
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
2987
+ pos++;
2988
+ }
2989
+ }
2990
+ if (pos < text.length && text.charCodeAt(pos) === 46) {
2991
+ pos++;
2992
+ if (pos < text.length && isDigit(text.charCodeAt(pos))) {
2993
+ pos++;
2994
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
2995
+ pos++;
2996
+ }
2997
+ } else {
2998
+ scanError = 3;
2999
+ return text.substring(start, pos);
3000
+ }
3001
+ }
3002
+ let end = pos;
3003
+ if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
3004
+ pos++;
3005
+ if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
3006
+ pos++;
3007
+ }
3008
+ if (pos < text.length && isDigit(text.charCodeAt(pos))) {
3009
+ pos++;
3010
+ while (pos < text.length && isDigit(text.charCodeAt(pos))) {
3011
+ pos++;
3012
+ }
3013
+ end = pos;
3014
+ } else {
3015
+ scanError = 3;
3016
+ }
3017
+ }
3018
+ return text.substring(start, end);
3019
+ }
3020
+ function scanString() {
3021
+ let result = "", start = pos;
3022
+ while (true) {
3023
+ if (pos >= len) {
3024
+ result += text.substring(start, pos);
3025
+ scanError = 2;
3026
+ break;
3027
+ }
3028
+ const ch = text.charCodeAt(pos);
3029
+ if (ch === 34) {
3030
+ result += text.substring(start, pos);
3031
+ pos++;
3032
+ break;
3033
+ }
3034
+ if (ch === 92) {
3035
+ result += text.substring(start, pos);
3036
+ pos++;
3037
+ if (pos >= len) {
3038
+ scanError = 2;
3039
+ break;
3040
+ }
3041
+ const ch2 = text.charCodeAt(pos++);
3042
+ switch (ch2) {
3043
+ case 34:
3044
+ result += '"';
3045
+ break;
3046
+ case 92:
3047
+ result += "\\";
3048
+ break;
3049
+ case 47:
3050
+ result += "/";
3051
+ break;
3052
+ case 98:
3053
+ result += "\b";
3054
+ break;
3055
+ case 102:
3056
+ result += "\f";
3057
+ break;
3058
+ case 110:
3059
+ result += `
3060
+ `;
3061
+ break;
3062
+ case 114:
3063
+ result += "\r";
3064
+ break;
3065
+ case 116:
3066
+ result += "\t";
3067
+ break;
3068
+ case 117:
3069
+ const ch3 = scanHexDigits(4, true);
3070
+ if (ch3 >= 0) {
3071
+ result += String.fromCharCode(ch3);
3072
+ } else {
3073
+ scanError = 4;
3074
+ }
3075
+ break;
3076
+ default:
3077
+ scanError = 5;
3078
+ }
3079
+ start = pos;
3080
+ continue;
3081
+ }
3082
+ if (ch >= 0 && ch <= 31) {
3083
+ if (isLineBreak(ch)) {
3084
+ result += text.substring(start, pos);
3085
+ scanError = 2;
3086
+ break;
3087
+ } else {
3088
+ scanError = 6;
3089
+ }
3090
+ }
3091
+ pos++;
3092
+ }
3093
+ return result;
3094
+ }
3095
+ function scanNext() {
3096
+ value = "";
3097
+ scanError = 0;
3098
+ tokenOffset = pos;
3099
+ lineStartOffset = lineNumber;
3100
+ prevTokenLineStartOffset = tokenLineStartOffset;
3101
+ if (pos >= len) {
3102
+ tokenOffset = len;
3103
+ return token = 17;
3104
+ }
3105
+ let code = text.charCodeAt(pos);
3106
+ if (isWhiteSpace(code)) {
3107
+ do {
3108
+ pos++;
3109
+ value += String.fromCharCode(code);
3110
+ code = text.charCodeAt(pos);
3111
+ } while (isWhiteSpace(code));
3112
+ return token = 15;
3113
+ }
3114
+ if (isLineBreak(code)) {
3115
+ pos++;
3116
+ value += String.fromCharCode(code);
3117
+ if (code === 13 && text.charCodeAt(pos) === 10) {
3118
+ pos++;
3119
+ value += `
3120
+ `;
3121
+ }
3122
+ lineNumber++;
3123
+ tokenLineStartOffset = pos;
3124
+ return token = 14;
3125
+ }
3126
+ switch (code) {
3127
+ case 123:
3128
+ pos++;
3129
+ return token = 1;
3130
+ case 125:
3131
+ pos++;
3132
+ return token = 2;
3133
+ case 91:
3134
+ pos++;
3135
+ return token = 3;
3136
+ case 93:
3137
+ pos++;
3138
+ return token = 4;
3139
+ case 58:
3140
+ pos++;
3141
+ return token = 6;
3142
+ case 44:
3143
+ pos++;
3144
+ return token = 5;
3145
+ case 34:
3146
+ pos++;
3147
+ value = scanString();
3148
+ return token = 10;
3149
+ case 47:
3150
+ const start = pos - 1;
3151
+ if (text.charCodeAt(pos + 1) === 47) {
3152
+ pos += 2;
3153
+ while (pos < len) {
3154
+ if (isLineBreak(text.charCodeAt(pos))) {
3155
+ break;
3156
+ }
3157
+ pos++;
3158
+ }
3159
+ value = text.substring(start, pos);
3160
+ return token = 12;
3161
+ }
3162
+ if (text.charCodeAt(pos + 1) === 42) {
3163
+ pos += 2;
3164
+ const safeLength = len - 1;
3165
+ let commentClosed = false;
3166
+ while (pos < safeLength) {
3167
+ const ch = text.charCodeAt(pos);
3168
+ if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
3169
+ pos += 2;
3170
+ commentClosed = true;
3171
+ break;
3172
+ }
3173
+ pos++;
3174
+ if (isLineBreak(ch)) {
3175
+ if (ch === 13 && text.charCodeAt(pos) === 10) {
3176
+ pos++;
3177
+ }
3178
+ lineNumber++;
3179
+ tokenLineStartOffset = pos;
3180
+ }
3181
+ }
3182
+ if (!commentClosed) {
3183
+ pos++;
3184
+ scanError = 1;
3185
+ }
3186
+ value = text.substring(start, pos);
3187
+ return token = 13;
3188
+ }
3189
+ value += String.fromCharCode(code);
3190
+ pos++;
3191
+ return token = 16;
3192
+ case 45:
3193
+ value += String.fromCharCode(code);
3194
+ pos++;
3195
+ if (pos === len || !isDigit(text.charCodeAt(pos))) {
3196
+ return token = 16;
3197
+ }
3198
+ case 48:
3199
+ case 49:
3200
+ case 50:
3201
+ case 51:
3202
+ case 52:
3203
+ case 53:
3204
+ case 54:
3205
+ case 55:
3206
+ case 56:
3207
+ case 57:
3208
+ value += scanNumber();
3209
+ return token = 11;
3210
+ default:
3211
+ while (pos < len && isUnknownContentCharacter(code)) {
3212
+ pos++;
3213
+ code = text.charCodeAt(pos);
3214
+ }
3215
+ if (tokenOffset !== pos) {
3216
+ value = text.substring(tokenOffset, pos);
3217
+ switch (value) {
3218
+ case "true":
3219
+ return token = 8;
3220
+ case "false":
3221
+ return token = 9;
3222
+ case "null":
3223
+ return token = 7;
3224
+ }
3225
+ return token = 16;
3226
+ }
3227
+ value += String.fromCharCode(code);
3228
+ pos++;
3229
+ return token = 16;
3230
+ }
3231
+ }
3232
+ function isUnknownContentCharacter(code) {
3233
+ if (isWhiteSpace(code) || isLineBreak(code)) {
3234
+ return false;
3235
+ }
3236
+ switch (code) {
3237
+ case 125:
3238
+ case 93:
3239
+ case 123:
3240
+ case 91:
3241
+ case 34:
3242
+ case 58:
3243
+ case 44:
3244
+ case 47:
3245
+ return false;
3246
+ }
3247
+ return true;
3248
+ }
3249
+ function scanNextNonTrivia() {
3250
+ let result;
3251
+ do {
3252
+ result = scanNext();
3253
+ } while (result >= 12 && result <= 15);
3254
+ return result;
3255
+ }
3256
+ return {
3257
+ setPosition,
3258
+ getPosition: () => pos,
3259
+ scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
3260
+ getToken: () => token,
3261
+ getTokenValue: () => value,
3262
+ getTokenOffset: () => tokenOffset,
3263
+ getTokenLength: () => pos - tokenOffset,
3264
+ getTokenStartLine: () => lineStartOffset,
3265
+ getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
3266
+ getTokenError: () => scanError
3267
+ };
3268
+ }
3269
+ function isWhiteSpace(ch) {
3270
+ return ch === 32 || ch === 9;
3271
+ }
3272
+ function isLineBreak(ch) {
3273
+ return ch === 10 || ch === 13;
3274
+ }
3275
+ function isDigit(ch) {
3276
+ return ch >= 48 && ch <= 57;
3277
+ }
3278
+ var CharacterCodes;
3279
+ (function(CharacterCodes2) {
3280
+ CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
3281
+ CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
3282
+ CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
3283
+ CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
3284
+ CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
3285
+ CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
3286
+ CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
3287
+ CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
3288
+ CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
3289
+ CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
3290
+ CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
3291
+ CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
3292
+ CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
3293
+ CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
3294
+ CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
3295
+ CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
3296
+ CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
3297
+ CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
3298
+ CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
3299
+ CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
3300
+ CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
3301
+ CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
3302
+ CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
3303
+ CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
3304
+ CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
3305
+ CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
3306
+ CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
3307
+ CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
3308
+ CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
3309
+ CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
3310
+ CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
3311
+ CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
3312
+ CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
3313
+ CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
3314
+ CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
3315
+ CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
3316
+ CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
3317
+ CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
3318
+ CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
3319
+ CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
3320
+ CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
3321
+ CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
3322
+ CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
3323
+ CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
3324
+ CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
3325
+ CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
3326
+ CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
3327
+ CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
3328
+ CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
3329
+ CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
3330
+ CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
3331
+ CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
3332
+ CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
3333
+ CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
3334
+ CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
3335
+ CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
3336
+ CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
3337
+ CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
3338
+ CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
3339
+ CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
3340
+ CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
3341
+ CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
3342
+ CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
3343
+ CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
3344
+ CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
3345
+ CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
3346
+ CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
3347
+ CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
3348
+ CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
3349
+ CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
3350
+ CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
3351
+ CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
3352
+ CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
3353
+ CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
3354
+ CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
3355
+ CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
3356
+ CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
3357
+ CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
3358
+ CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
3359
+ CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
3360
+ })(CharacterCodes || (CharacterCodes = {}));
3361
+
3362
+ // node_modules/jsonc-parser/lib/esm/impl/string-intern.js
3363
+ var cachedSpaces = new Array(20).fill(0).map((_3, index) => {
3364
+ return " ".repeat(index);
3365
+ });
3366
+ var maxCachedValues = 200;
3367
+ var cachedBreakLinesWithSpaces = {
3368
+ " ": {
3369
+ "\n": new Array(maxCachedValues).fill(0).map((_3, index) => {
3370
+ return `
3371
+ ` + " ".repeat(index);
3372
+ }),
3373
+ "\r": new Array(maxCachedValues).fill(0).map((_3, index) => {
3374
+ return "\r" + " ".repeat(index);
3375
+ }),
3376
+ "\r\n": new Array(maxCachedValues).fill(0).map((_3, index) => {
3377
+ return `\r
3378
+ ` + " ".repeat(index);
3379
+ })
3380
+ },
3381
+ "\t": {
3382
+ "\n": new Array(maxCachedValues).fill(0).map((_3, index) => {
3383
+ return `
3384
+ ` + "\t".repeat(index);
3385
+ }),
3386
+ "\r": new Array(maxCachedValues).fill(0).map((_3, index) => {
3387
+ return "\r" + "\t".repeat(index);
3388
+ }),
3389
+ "\r\n": new Array(maxCachedValues).fill(0).map((_3, index) => {
3390
+ return `\r
3391
+ ` + "\t".repeat(index);
3392
+ })
3393
+ }
3394
+ };
3395
+
3396
+ // node_modules/jsonc-parser/lib/esm/impl/parser.js
3397
+ var ParseOptions;
3398
+ (function(ParseOptions2) {
3399
+ ParseOptions2.DEFAULT = {
3400
+ allowTrailingComma: false
3401
+ };
3402
+ })(ParseOptions || (ParseOptions = {}));
3403
+ function parse(text, errors = [], options = ParseOptions.DEFAULT) {
3404
+ let currentProperty = null;
3405
+ let currentParent = [];
3406
+ const previousParents = [];
3407
+ function onValue(value) {
3408
+ if (Array.isArray(currentParent)) {
3409
+ currentParent.push(value);
3410
+ } else if (currentProperty !== null) {
3411
+ currentParent[currentProperty] = value;
3412
+ }
3413
+ }
3414
+ const visitor = {
3415
+ onObjectBegin: () => {
3416
+ const object = {};
3417
+ onValue(object);
3418
+ previousParents.push(currentParent);
3419
+ currentParent = object;
3420
+ currentProperty = null;
3421
+ },
3422
+ onObjectProperty: (name) => {
3423
+ currentProperty = name;
3424
+ },
3425
+ onObjectEnd: () => {
3426
+ currentParent = previousParents.pop();
3427
+ },
3428
+ onArrayBegin: () => {
3429
+ const array = [];
3430
+ onValue(array);
3431
+ previousParents.push(currentParent);
3432
+ currentParent = array;
3433
+ currentProperty = null;
3434
+ },
3435
+ onArrayEnd: () => {
3436
+ currentParent = previousParents.pop();
3437
+ },
3438
+ onLiteralValue: onValue,
3439
+ onError: (error, offset, length) => {
3440
+ errors.push({ error, offset, length });
3441
+ }
3442
+ };
3443
+ visit(text, visitor, options);
3444
+ return currentParent[0];
3445
+ }
3446
+ function visit(text, visitor, options = ParseOptions.DEFAULT) {
3447
+ const _scanner = createScanner(text, false);
3448
+ const _jsonPath = [];
3449
+ let suppressedCallbacks = 0;
3450
+ function toNoArgVisit(visitFunction) {
3451
+ return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
3452
+ }
3453
+ function toOneArgVisit(visitFunction) {
3454
+ return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
3455
+ }
3456
+ function toOneArgVisitWithPath(visitFunction) {
3457
+ return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
3458
+ }
3459
+ function toBeginVisit(visitFunction) {
3460
+ return visitFunction ? () => {
3461
+ if (suppressedCallbacks > 0) {
3462
+ suppressedCallbacks++;
3463
+ } else {
3464
+ let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
3465
+ if (cbReturn === false) {
3466
+ suppressedCallbacks = 1;
3467
+ }
3468
+ }
3469
+ } : () => true;
3470
+ }
3471
+ function toEndVisit(visitFunction) {
3472
+ return visitFunction ? () => {
3473
+ if (suppressedCallbacks > 0) {
3474
+ suppressedCallbacks--;
3475
+ }
3476
+ if (suppressedCallbacks === 0) {
3477
+ visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
3478
+ }
3479
+ } : () => true;
3480
+ }
3481
+ const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
3482
+ const disallowComments = options && options.disallowComments;
3483
+ const allowTrailingComma = options && options.allowTrailingComma;
3484
+ function scanNext() {
3485
+ while (true) {
3486
+ const token = _scanner.scan();
3487
+ switch (_scanner.getTokenError()) {
3488
+ case 4:
3489
+ handleError(14);
3490
+ break;
3491
+ case 5:
3492
+ handleError(15);
3493
+ break;
3494
+ case 3:
3495
+ handleError(13);
3496
+ break;
3497
+ case 1:
3498
+ if (!disallowComments) {
3499
+ handleError(11);
3500
+ }
3501
+ break;
3502
+ case 2:
3503
+ handleError(12);
3504
+ break;
3505
+ case 6:
3506
+ handleError(16);
3507
+ break;
3508
+ }
3509
+ switch (token) {
3510
+ case 12:
3511
+ case 13:
3512
+ if (disallowComments) {
3513
+ handleError(10);
3514
+ } else {
3515
+ onComment();
3516
+ }
3517
+ break;
3518
+ case 16:
3519
+ handleError(1);
3520
+ break;
3521
+ case 15:
3522
+ case 14:
3523
+ break;
3524
+ default:
3525
+ return token;
3526
+ }
3527
+ }
3528
+ }
3529
+ function handleError(error, skipUntilAfter = [], skipUntil = []) {
3530
+ onError(error);
3531
+ if (skipUntilAfter.length + skipUntil.length > 0) {
3532
+ let token = _scanner.getToken();
3533
+ while (token !== 17) {
3534
+ if (skipUntilAfter.indexOf(token) !== -1) {
3535
+ scanNext();
3536
+ break;
3537
+ } else if (skipUntil.indexOf(token) !== -1) {
3538
+ break;
3539
+ }
3540
+ token = scanNext();
3541
+ }
3542
+ }
3543
+ }
3544
+ function parseString(isValue) {
3545
+ const value = _scanner.getTokenValue();
3546
+ if (isValue) {
3547
+ onLiteralValue(value);
3548
+ } else {
3549
+ onObjectProperty(value);
3550
+ _jsonPath.push(value);
3551
+ }
3552
+ scanNext();
3553
+ return true;
3554
+ }
3555
+ function parseLiteral() {
3556
+ switch (_scanner.getToken()) {
3557
+ case 11:
3558
+ const tokenValue = _scanner.getTokenValue();
3559
+ let value = Number(tokenValue);
3560
+ if (isNaN(value)) {
3561
+ handleError(2);
3562
+ value = 0;
3563
+ }
3564
+ onLiteralValue(value);
3565
+ break;
3566
+ case 7:
3567
+ onLiteralValue(null);
3568
+ break;
3569
+ case 8:
3570
+ onLiteralValue(true);
3571
+ break;
3572
+ case 9:
3573
+ onLiteralValue(false);
3574
+ break;
3575
+ default:
3576
+ return false;
3577
+ }
3578
+ scanNext();
3579
+ return true;
3580
+ }
3581
+ function parseProperty() {
3582
+ if (_scanner.getToken() !== 10) {
3583
+ handleError(3, [], [2, 5]);
3584
+ return false;
3585
+ }
3586
+ parseString(false);
3587
+ if (_scanner.getToken() === 6) {
3588
+ onSeparator(":");
3589
+ scanNext();
3590
+ if (!parseValue()) {
3591
+ handleError(4, [], [2, 5]);
3592
+ }
3593
+ } else {
3594
+ handleError(5, [], [2, 5]);
3595
+ }
3596
+ _jsonPath.pop();
3597
+ return true;
3598
+ }
3599
+ function parseObject() {
3600
+ onObjectBegin();
3601
+ scanNext();
3602
+ let needsComma = false;
3603
+ while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
3604
+ if (_scanner.getToken() === 5) {
3605
+ if (!needsComma) {
3606
+ handleError(4, [], []);
3607
+ }
3608
+ onSeparator(",");
3609
+ scanNext();
3610
+ if (_scanner.getToken() === 2 && allowTrailingComma) {
3611
+ break;
3612
+ }
3613
+ } else if (needsComma) {
3614
+ handleError(6, [], []);
3615
+ }
3616
+ if (!parseProperty()) {
3617
+ handleError(4, [], [2, 5]);
3618
+ }
3619
+ needsComma = true;
3620
+ }
3621
+ onObjectEnd();
3622
+ if (_scanner.getToken() !== 2) {
3623
+ handleError(7, [2], []);
3624
+ } else {
3625
+ scanNext();
3626
+ }
3627
+ return true;
3628
+ }
3629
+ function parseArray() {
3630
+ onArrayBegin();
3631
+ scanNext();
3632
+ let isFirstElement = true;
3633
+ let needsComma = false;
3634
+ while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
3635
+ if (_scanner.getToken() === 5) {
3636
+ if (!needsComma) {
3637
+ handleError(4, [], []);
3638
+ }
3639
+ onSeparator(",");
3640
+ scanNext();
3641
+ if (_scanner.getToken() === 4 && allowTrailingComma) {
3642
+ break;
3643
+ }
3644
+ } else if (needsComma) {
3645
+ handleError(6, [], []);
3646
+ }
3647
+ if (isFirstElement) {
3648
+ _jsonPath.push(0);
3649
+ isFirstElement = false;
3650
+ } else {
3651
+ _jsonPath[_jsonPath.length - 1]++;
3652
+ }
3653
+ if (!parseValue()) {
3654
+ handleError(4, [], [4, 5]);
3655
+ }
3656
+ needsComma = true;
3657
+ }
3658
+ onArrayEnd();
3659
+ if (!isFirstElement) {
3660
+ _jsonPath.pop();
3661
+ }
3662
+ if (_scanner.getToken() !== 4) {
3663
+ handleError(8, [4], []);
3664
+ } else {
3665
+ scanNext();
3666
+ }
3667
+ return true;
3668
+ }
3669
+ function parseValue() {
3670
+ switch (_scanner.getToken()) {
3671
+ case 3:
3672
+ return parseArray();
3673
+ case 1:
3674
+ return parseObject();
3675
+ case 10:
3676
+ return parseString(true);
3677
+ default:
3678
+ return parseLiteral();
3679
+ }
3680
+ }
3681
+ scanNext();
3682
+ if (_scanner.getToken() === 17) {
3683
+ if (options.allowEmptyContent) {
3684
+ return true;
3685
+ }
3686
+ handleError(4, [], []);
3687
+ return false;
3688
+ }
3689
+ if (!parseValue()) {
3690
+ handleError(4, [], []);
3691
+ return false;
3692
+ }
3693
+ if (_scanner.getToken() !== 17) {
3694
+ handleError(9, [], []);
3695
+ }
3696
+ return true;
3697
+ }
3698
+
3699
+ // node_modules/jsonc-parser/lib/esm/main.js
3700
+ var ScanError;
3701
+ (function(ScanError2) {
3702
+ ScanError2[ScanError2["None"] = 0] = "None";
3703
+ ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
3704
+ ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
3705
+ ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
3706
+ ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
3707
+ ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
3708
+ ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
3709
+ })(ScanError || (ScanError = {}));
3710
+ var SyntaxKind;
3711
+ (function(SyntaxKind2) {
3712
+ SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
3713
+ SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
3714
+ SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
3715
+ SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
3716
+ SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
3717
+ SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
3718
+ SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
3719
+ SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
3720
+ SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
3721
+ SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
3722
+ SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
3723
+ SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
3724
+ SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
3725
+ SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
3726
+ SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
3727
+ SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
3728
+ SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
3729
+ })(SyntaxKind || (SyntaxKind = {}));
3730
+ var parse2 = parse;
3731
+ var ParseErrorCode;
3732
+ (function(ParseErrorCode2) {
3733
+ ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
3734
+ ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
3735
+ ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
3736
+ ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
3737
+ ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
3738
+ ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
3739
+ ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
3740
+ ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
3741
+ ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
3742
+ ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
3743
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
3744
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
3745
+ ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
3746
+ ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
3747
+ ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
3748
+ ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
3749
+ })(ParseErrorCode || (ParseErrorCode = {}));
3750
+ function printParseErrorCode(code) {
3751
+ switch (code) {
3752
+ case 1:
3753
+ return "InvalidSymbol";
3754
+ case 2:
3755
+ return "InvalidNumberFormat";
3756
+ case 3:
3757
+ return "PropertyNameExpected";
3758
+ case 4:
3759
+ return "ValueExpected";
3760
+ case 5:
3761
+ return "ColonExpected";
3762
+ case 6:
3763
+ return "CommaExpected";
3764
+ case 7:
3765
+ return "CloseBraceExpected";
3766
+ case 8:
3767
+ return "CloseBracketExpected";
3768
+ case 9:
3769
+ return "EndOfFileExpected";
3770
+ case 10:
3771
+ return "InvalidCommentToken";
3772
+ case 11:
3773
+ return "UnexpectedEndOfComment";
3774
+ case 12:
3775
+ return "UnexpectedEndOfString";
3776
+ case 13:
3777
+ return "UnexpectedEndOfNumber";
3778
+ case 14:
3779
+ return "InvalidUnicode";
3780
+ case 15:
3781
+ return "InvalidEscapeCharacter";
3782
+ case 16:
3783
+ return "InvalidCharacter";
3784
+ }
3785
+ return "<unknown ParseErrorCode>";
3786
+ }
3787
+
3788
+ // src/shared/jsonc-parser.ts
3789
+ function parseJsonc(content) {
3790
+ const errors = [];
3791
+ const result = parse2(content, errors, {
3792
+ allowTrailingComma: true,
3793
+ disallowComments: false
3794
+ });
3795
+ if (errors.length > 0) {
3796
+ const errorMessages = errors.map((e2) => `${printParseErrorCode(e2.error)} at offset ${e2.offset}`).join(", ");
3797
+ throw new SyntaxError(`JSONC parse error: ${errorMessages}`);
3798
+ }
3799
+ return result;
3800
+ }
3801
+ // src/cli/config-manager.ts
3802
+ var OPENCODE_CONFIG_DIR = join2(homedir(), ".config", "opencode");
3803
+ var OPENCODE_JSON = join2(OPENCODE_CONFIG_DIR, "opencode.json");
3804
+ var OPENCODE_JSONC = join2(OPENCODE_CONFIG_DIR, "opencode.jsonc");
3805
+ var OPENCODE_PACKAGE_JSON = join2(OPENCODE_CONFIG_DIR, "package.json");
3806
+ var OMO_CONFIG = join2(OPENCODE_CONFIG_DIR, "oh-my-opencode.json");
2932
3807
  var CHATGPT_HOTFIX_REPO = "code-yeongyu/opencode-openai-codex-auth#fix/orphaned-function-call-output-with-tools";
2933
3808
  async function fetchLatestVersion(packageName) {
2934
3809
  try {
@@ -2950,67 +3825,10 @@ function detectConfigFormat() {
2950
3825
  }
2951
3826
  return { format: "none", path: OPENCODE_JSON };
2952
3827
  }
2953
- function stripJsoncComments(content) {
2954
- let result = "";
2955
- let i = 0;
2956
- let inString = false;
2957
- let escape = false;
2958
- while (i < content.length) {
2959
- const char = content[i];
2960
- if (escape) {
2961
- result += char;
2962
- escape = false;
2963
- i++;
2964
- continue;
2965
- }
2966
- if (char === "\\") {
2967
- result += char;
2968
- escape = true;
2969
- i++;
2970
- continue;
2971
- }
2972
- if (char === '"' && !inString) {
2973
- inString = true;
2974
- result += char;
2975
- i++;
2976
- continue;
2977
- }
2978
- if (char === '"' && inString) {
2979
- inString = false;
2980
- result += char;
2981
- i++;
2982
- continue;
2983
- }
2984
- if (inString) {
2985
- result += char;
2986
- i++;
2987
- continue;
2988
- }
2989
- if (char === "/" && content[i + 1] === "/") {
2990
- while (i < content.length && content[i] !== `
2991
- `) {
2992
- i++;
2993
- }
2994
- continue;
2995
- }
2996
- if (char === "/" && content[i + 1] === "*") {
2997
- i += 2;
2998
- while (i < content.length - 1 && !(content[i] === "*" && content[i + 1] === "/")) {
2999
- i++;
3000
- }
3001
- i += 2;
3002
- continue;
3003
- }
3004
- result += char;
3005
- i++;
3006
- }
3007
- return result.replace(/,(\s*[}\]])/g, "$1");
3008
- }
3009
- function parseConfig(path, isJsonc) {
3828
+ function parseConfig(path2, isJsonc) {
3010
3829
  try {
3011
- const content = readFileSync(path, "utf-8");
3012
- const cleaned = isJsonc ? stripJsoncComments(content) : content;
3013
- return JSON.parse(cleaned);
3830
+ const content = readFileSync(path2, "utf-8");
3831
+ return parseJsonc(content);
3014
3832
  } catch {
3015
3833
  return null;
3016
3834
  }
@@ -3022,26 +3840,26 @@ function ensureConfigDir() {
3022
3840
  }
3023
3841
  function addPluginToOpenCodeConfig() {
3024
3842
  ensureConfigDir();
3025
- const { format, path } = detectConfigFormat();
3843
+ const { format: format2, path: path2 } = detectConfigFormat();
3026
3844
  const pluginName = "oh-my-opencode";
3027
3845
  try {
3028
- if (format === "none") {
3846
+ if (format2 === "none") {
3029
3847
  const config2 = { plugin: [pluginName] };
3030
- writeFileSync(path, JSON.stringify(config2, null, 2) + `
3848
+ writeFileSync(path2, JSON.stringify(config2, null, 2) + `
3031
3849
  `);
3032
- return { success: true, configPath: path };
3850
+ return { success: true, configPath: path2 };
3033
3851
  }
3034
- const config = parseConfig(path, format === "jsonc");
3852
+ const config = parseConfig(path2, format2 === "jsonc");
3035
3853
  if (!config) {
3036
- return { success: false, configPath: path, error: "Failed to parse config" };
3854
+ return { success: false, configPath: path2, error: "Failed to parse config" };
3037
3855
  }
3038
3856
  const plugins = config.plugin ?? [];
3039
3857
  if (plugins.some((p2) => p2.startsWith(pluginName))) {
3040
- return { success: true, configPath: path };
3858
+ return { success: true, configPath: path2 };
3041
3859
  }
3042
3860
  config.plugin = [...plugins, pluginName];
3043
- if (format === "jsonc") {
3044
- const content = readFileSync(path, "utf-8");
3861
+ if (format2 === "jsonc") {
3862
+ const content = readFileSync(path2, "utf-8");
3045
3863
  const pluginArrayRegex = /"plugin"\s*:\s*\[([\s\S]*?)\]/;
3046
3864
  const match = content.match(pluginArrayRegex);
3047
3865
  if (match) {
@@ -3051,19 +3869,19 @@ function addPluginToOpenCodeConfig() {
3051
3869
  const newContent = content.replace(pluginArrayRegex, `"plugin": [
3052
3870
  ${newArrayContent}
3053
3871
  ]`);
3054
- writeFileSync(path, newContent);
3872
+ writeFileSync(path2, newContent);
3055
3873
  } else {
3056
3874
  const newContent = content.replace(/^(\s*\{)/, `$1
3057
3875
  "plugin": ["${pluginName}"],`);
3058
- writeFileSync(path, newContent);
3876
+ writeFileSync(path2, newContent);
3059
3877
  }
3060
3878
  } else {
3061
- writeFileSync(path, JSON.stringify(config, null, 2) + `
3879
+ writeFileSync(path2, JSON.stringify(config, null, 2) + `
3062
3880
  `);
3063
3881
  }
3064
- return { success: true, configPath: path };
3882
+ return { success: true, configPath: path2 };
3065
3883
  } catch (err) {
3066
- return { success: false, configPath: path, error: String(err) };
3884
+ return { success: false, configPath: path2, error: String(err) };
3067
3885
  }
3068
3886
  }
3069
3887
  function deepMerge(target, source) {
@@ -3119,8 +3937,7 @@ function writeOmoConfig(installConfig) {
3119
3937
  const newConfig = generateOmoConfig(installConfig);
3120
3938
  if (existsSync(OMO_CONFIG)) {
3121
3939
  const content = readFileSync(OMO_CONFIG, "utf-8");
3122
- const cleaned = stripJsoncComments(content);
3123
- const existing = JSON.parse(cleaned);
3940
+ const existing = parseJsonc(content);
3124
3941
  delete existing.agents;
3125
3942
  const merged = deepMerge(existing, newConfig);
3126
3943
  writeFileSync(OMO_CONFIG, JSON.stringify(merged, null, 2) + `
@@ -3161,9 +3978,9 @@ async function getOpenCodeVersion() {
3161
3978
  }
3162
3979
  async function addAuthPlugins(config) {
3163
3980
  ensureConfigDir();
3164
- const { format, path } = detectConfigFormat();
3981
+ const { format: format2, path: path2 } = detectConfigFormat();
3165
3982
  try {
3166
- const existingConfig = format !== "none" ? parseConfig(path, format === "jsonc") : null;
3983
+ const existingConfig = format2 !== "none" ? parseConfig(path2, format2 === "jsonc") : null;
3167
3984
  const plugins = existingConfig?.plugin ?? [];
3168
3985
  if (config.hasGemini) {
3169
3986
  const version = await fetchLatestVersion("opencode-antigravity-auth");
@@ -3178,11 +3995,11 @@ async function addAuthPlugins(config) {
3178
3995
  }
3179
3996
  }
3180
3997
  const newConfig = { ...existingConfig ?? {}, plugin: plugins };
3181
- writeFileSync(path, JSON.stringify(newConfig, null, 2) + `
3998
+ writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
3182
3999
  `);
3183
- return { success: true, configPath: path };
4000
+ return { success: true, configPath: path2 };
3184
4001
  } catch (err) {
3185
- return { success: false, configPath: path, error: String(err) };
4002
+ return { success: false, configPath: path2, error: String(err) };
3186
4003
  }
3187
4004
  }
3188
4005
  function setupChatGPTHotfix() {
@@ -3270,9 +4087,9 @@ var CODEX_PROVIDER_CONFIG = {
3270
4087
  };
3271
4088
  function addProviderConfig(config) {
3272
4089
  ensureConfigDir();
3273
- const { format, path } = detectConfigFormat();
4090
+ const { format: format2, path: path2 } = detectConfigFormat();
3274
4091
  try {
3275
- const existingConfig = format !== "none" ? parseConfig(path, format === "jsonc") : null;
4092
+ const existingConfig = format2 !== "none" ? parseConfig(path2, format2 === "jsonc") : null;
3276
4093
  const newConfig = { ...existingConfig ?? {} };
3277
4094
  const providers = newConfig.provider ?? {};
3278
4095
  if (config.hasGemini) {
@@ -3284,11 +4101,11 @@ function addProviderConfig(config) {
3284
4101
  if (Object.keys(providers).length > 0) {
3285
4102
  newConfig.provider = providers;
3286
4103
  }
3287
- writeFileSync(path, JSON.stringify(newConfig, null, 2) + `
4104
+ writeFileSync(path2, JSON.stringify(newConfig, null, 2) + `
3288
4105
  `);
3289
- return { success: true, configPath: path };
4106
+ return { success: true, configPath: path2 };
3290
4107
  } catch (err) {
3291
- return { success: false, configPath: path, error: String(err) };
4108
+ return { success: false, configPath: path2, error: String(err) };
3292
4109
  }
3293
4110
  }
3294
4111
  function detectCurrentConfig() {
@@ -3299,11 +4116,11 @@ function detectCurrentConfig() {
3299
4116
  hasChatGPT: true,
3300
4117
  hasGemini: false
3301
4118
  };
3302
- const { format, path } = detectConfigFormat();
3303
- if (format === "none") {
4119
+ const { format: format2, path: path2 } = detectConfigFormat();
4120
+ if (format2 === "none") {
3304
4121
  return result;
3305
4122
  }
3306
- const openCodeConfig = parseConfig(path, format === "jsonc");
4123
+ const openCodeConfig = parseConfig(path2, format2 === "jsonc");
3307
4124
  if (!openCodeConfig) {
3308
4125
  return result;
3309
4126
  }
@@ -3319,7 +4136,7 @@ function detectCurrentConfig() {
3319
4136
  }
3320
4137
  try {
3321
4138
  const content = readFileSync(OMO_CONFIG, "utf-8");
3322
- const omoConfig = JSON.parse(stripJsoncComments(content));
4139
+ const omoConfig = parseJsonc(content);
3323
4140
  const agents = omoConfig.agents ?? {};
3324
4141
  if (agents["Sisyphus"]?.model === "opencode/big-pickle") {
3325
4142
  result.hasClaude = false;
@@ -3946,7 +4763,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
3946
4763
 
3947
4764
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
3948
4765
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
3949
- var defaultPathSerializer = ({ path, url: _url }) => {
4766
+ var defaultPathSerializer = ({ path: path2, url: _url }) => {
3950
4767
  let url = _url;
3951
4768
  const matches = _url.match(PATH_PARAM_RE);
3952
4769
  if (matches) {
@@ -3965,7 +4782,7 @@ var defaultPathSerializer = ({ path, url: _url }) => {
3965
4782
  name = name.substring(1);
3966
4783
  style = "matrix";
3967
4784
  }
3968
- const value = path[name];
4785
+ const value = path2[name];
3969
4786
  if (value === undefined || value === null) {
3970
4787
  continue;
3971
4788
  }
@@ -3996,11 +4813,11 @@ var defaultPathSerializer = ({ path, url: _url }) => {
3996
4813
  }
3997
4814
  return url;
3998
4815
  };
3999
- var getUrl = ({ baseUrl, path, query, querySerializer, url: _url }) => {
4816
+ var getUrl = ({ baseUrl, path: path2, query, querySerializer, url: _url }) => {
4000
4817
  const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
4001
4818
  let url = (baseUrl ?? "") + pathUrl;
4002
- if (path) {
4003
- url = defaultPathSerializer({ path, url });
4819
+ if (path2) {
4820
+ url = defaultPathSerializer({ path: path2, url });
4004
4821
  }
4005
4822
  let search = query ? querySerializer(query) : "";
4006
4823
  if (search.startsWith("?")) {
@@ -5482,20 +6299,16 @@ Sending prompt...`));
5482
6299
 
5483
6300
  Session ended with error: ${eventState.lastError}`));
5484
6301
  console.error(import_picocolors5.default.yellow("Check if todos were completed before the error."));
5485
- abortController.abort();
5486
- await eventProcessor.catch(() => {});
5487
6302
  cleanup();
5488
- return 1;
6303
+ process.exit(1);
5489
6304
  }
5490
6305
  const shouldExit = await checkCompletionConditions(ctx);
5491
6306
  if (shouldExit) {
5492
6307
  console.log(import_picocolors5.default.green(`
5493
6308
 
5494
6309
  All tasks completed.`));
5495
- abortController.abort();
5496
- await eventProcessor.catch(() => {});
5497
6310
  cleanup();
5498
- return 0;
6311
+ process.exit(0);
5499
6312
  }
5500
6313
  }
5501
6314
  await eventProcessor.catch(() => {});
@@ -5515,6 +6328,307 @@ All tasks completed.`));
5515
6328
  return 1;
5516
6329
  }
5517
6330
  }
6331
+ // src/hooks/auto-update-checker/checker.ts
6332
+ import * as fs2 from "fs";
6333
+ import * as path3 from "path";
6334
+ import { fileURLToPath } from "url";
6335
+
6336
+ // src/hooks/auto-update-checker/constants.ts
6337
+ import * as path2 from "path";
6338
+ import * as os2 from "os";
6339
+ var PACKAGE_NAME = "oh-my-opencode";
6340
+ var NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
6341
+ var NPM_FETCH_TIMEOUT = 5000;
6342
+ function getCacheDir() {
6343
+ if (process.platform === "win32") {
6344
+ return path2.join(process.env.LOCALAPPDATA ?? os2.homedir(), "opencode");
6345
+ }
6346
+ return path2.join(os2.homedir(), ".cache", "opencode");
6347
+ }
6348
+ var CACHE_DIR = getCacheDir();
6349
+ var VERSION_FILE = path2.join(CACHE_DIR, "version");
6350
+ var INSTALLED_PACKAGE_JSON = path2.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
6351
+ function getUserConfigDir() {
6352
+ if (process.platform === "win32") {
6353
+ return process.env.APPDATA ?? path2.join(os2.homedir(), "AppData", "Roaming");
6354
+ }
6355
+ return process.env.XDG_CONFIG_HOME ?? path2.join(os2.homedir(), ".config");
6356
+ }
6357
+ var USER_CONFIG_DIR = getUserConfigDir();
6358
+ var USER_OPENCODE_CONFIG = path2.join(USER_CONFIG_DIR, "opencode", "opencode.json");
6359
+ var USER_OPENCODE_CONFIG_JSONC = path2.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
6360
+
6361
+ // src/hooks/auto-update-checker/checker.ts
6362
+ function isLocalDevMode(directory) {
6363
+ return getLocalDevPath(directory) !== null;
6364
+ }
6365
+ function stripJsonComments(json) {
6366
+ return json.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m2, g2) => g2 ? "" : m2).replace(/,(\s*[}\]])/g, "$1");
6367
+ }
6368
+ function getConfigPaths(directory) {
6369
+ return [
6370
+ path3.join(directory, ".opencode", "opencode.json"),
6371
+ path3.join(directory, ".opencode", "opencode.jsonc"),
6372
+ USER_OPENCODE_CONFIG,
6373
+ USER_OPENCODE_CONFIG_JSONC
6374
+ ];
6375
+ }
6376
+ function getLocalDevPath(directory) {
6377
+ for (const configPath of getConfigPaths(directory)) {
6378
+ try {
6379
+ if (!fs2.existsSync(configPath))
6380
+ continue;
6381
+ const content = fs2.readFileSync(configPath, "utf-8");
6382
+ const config = JSON.parse(stripJsonComments(content));
6383
+ const plugins = config.plugin ?? [];
6384
+ for (const entry of plugins) {
6385
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
6386
+ try {
6387
+ return fileURLToPath(entry);
6388
+ } catch {
6389
+ return entry.replace("file://", "");
6390
+ }
6391
+ }
6392
+ }
6393
+ } catch {
6394
+ continue;
6395
+ }
6396
+ }
6397
+ return null;
6398
+ }
6399
+ function findPackageJsonUp(startPath) {
6400
+ try {
6401
+ const stat = fs2.statSync(startPath);
6402
+ let dir = stat.isDirectory() ? startPath : path3.dirname(startPath);
6403
+ for (let i = 0;i < 10; i++) {
6404
+ const pkgPath = path3.join(dir, "package.json");
6405
+ if (fs2.existsSync(pkgPath)) {
6406
+ try {
6407
+ const content = fs2.readFileSync(pkgPath, "utf-8");
6408
+ const pkg = JSON.parse(content);
6409
+ if (pkg.name === PACKAGE_NAME)
6410
+ return pkgPath;
6411
+ } catch {}
6412
+ }
6413
+ const parent = path3.dirname(dir);
6414
+ if (parent === dir)
6415
+ break;
6416
+ dir = parent;
6417
+ }
6418
+ } catch {}
6419
+ return null;
6420
+ }
6421
+ function findPluginEntry(directory) {
6422
+ for (const configPath of getConfigPaths(directory)) {
6423
+ try {
6424
+ if (!fs2.existsSync(configPath))
6425
+ continue;
6426
+ const content = fs2.readFileSync(configPath, "utf-8");
6427
+ const config = JSON.parse(stripJsonComments(content));
6428
+ const plugins = config.plugin ?? [];
6429
+ for (const entry of plugins) {
6430
+ if (entry === PACKAGE_NAME) {
6431
+ return { entry, isPinned: false, pinnedVersion: null, configPath };
6432
+ }
6433
+ if (entry.startsWith(`${PACKAGE_NAME}@`)) {
6434
+ const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
6435
+ const isPinned = pinnedVersion !== "latest";
6436
+ return { entry, isPinned, pinnedVersion: isPinned ? pinnedVersion : null, configPath };
6437
+ }
6438
+ }
6439
+ } catch {
6440
+ continue;
6441
+ }
6442
+ }
6443
+ return null;
6444
+ }
6445
+ function getCachedVersion() {
6446
+ try {
6447
+ if (fs2.existsSync(INSTALLED_PACKAGE_JSON)) {
6448
+ const content = fs2.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
6449
+ const pkg = JSON.parse(content);
6450
+ if (pkg.version)
6451
+ return pkg.version;
6452
+ }
6453
+ } catch {}
6454
+ try {
6455
+ const currentDir = path3.dirname(fileURLToPath(import.meta.url));
6456
+ const pkgPath = findPackageJsonUp(currentDir);
6457
+ if (pkgPath) {
6458
+ const content = fs2.readFileSync(pkgPath, "utf-8");
6459
+ const pkg = JSON.parse(content);
6460
+ if (pkg.version)
6461
+ return pkg.version;
6462
+ }
6463
+ } catch (err) {
6464
+ log("[auto-update-checker] Failed to resolve version from current directory:", err);
6465
+ }
6466
+ return null;
6467
+ }
6468
+ async function getLatestVersion() {
6469
+ const controller = new AbortController;
6470
+ const timeoutId = setTimeout(() => controller.abort(), NPM_FETCH_TIMEOUT);
6471
+ try {
6472
+ const response = await fetch(NPM_REGISTRY_URL, {
6473
+ signal: controller.signal,
6474
+ headers: { Accept: "application/json" }
6475
+ });
6476
+ if (!response.ok)
6477
+ return null;
6478
+ const data = await response.json();
6479
+ return data.latest ?? null;
6480
+ } catch {
6481
+ return null;
6482
+ } finally {
6483
+ clearTimeout(timeoutId);
6484
+ }
6485
+ }
6486
+
6487
+ // src/cli/get-local-version/formatter.ts
6488
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
6489
+ var SYMBOLS2 = {
6490
+ check: import_picocolors6.default.green("\u2713"),
6491
+ cross: import_picocolors6.default.red("\u2717"),
6492
+ arrow: import_picocolors6.default.cyan("\u2192"),
6493
+ info: import_picocolors6.default.blue("\u2139"),
6494
+ warn: import_picocolors6.default.yellow("\u26A0"),
6495
+ pin: import_picocolors6.default.magenta("\uD83D\uDCCC"),
6496
+ dev: import_picocolors6.default.cyan("\uD83D\uDD27")
6497
+ };
6498
+ function formatVersionOutput(info) {
6499
+ const lines = [];
6500
+ lines.push("");
6501
+ lines.push(import_picocolors6.default.bold(import_picocolors6.default.white("oh-my-opencode Version Information")));
6502
+ lines.push(import_picocolors6.default.dim("\u2500".repeat(50)));
6503
+ lines.push("");
6504
+ if (info.currentVersion) {
6505
+ lines.push(` Current Version: ${import_picocolors6.default.cyan(info.currentVersion)}`);
6506
+ } else {
6507
+ lines.push(` Current Version: ${import_picocolors6.default.dim("unknown")}`);
6508
+ }
6509
+ if (!info.isLocalDev && info.latestVersion) {
6510
+ lines.push(` Latest Version: ${import_picocolors6.default.cyan(info.latestVersion)}`);
6511
+ }
6512
+ lines.push("");
6513
+ switch (info.status) {
6514
+ case "up-to-date":
6515
+ lines.push(` ${SYMBOLS2.check} ${import_picocolors6.default.green("You're up to date!")}`);
6516
+ break;
6517
+ case "outdated":
6518
+ lines.push(` ${SYMBOLS2.warn} ${import_picocolors6.default.yellow("Update available")}`);
6519
+ lines.push(` ${import_picocolors6.default.dim("Run:")} ${import_picocolors6.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
6520
+ break;
6521
+ case "local-dev":
6522
+ lines.push(` ${SYMBOLS2.dev} ${import_picocolors6.default.cyan("Running in local development mode")}`);
6523
+ lines.push(` ${import_picocolors6.default.dim("Using file:// protocol from config")}`);
6524
+ break;
6525
+ case "pinned":
6526
+ lines.push(` ${SYMBOLS2.pin} ${import_picocolors6.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
6527
+ lines.push(` ${import_picocolors6.default.dim("Update check skipped for pinned versions")}`);
6528
+ break;
6529
+ case "error":
6530
+ lines.push(` ${SYMBOLS2.cross} ${import_picocolors6.default.red("Unable to check for updates")}`);
6531
+ lines.push(` ${import_picocolors6.default.dim("Network error or npm registry unavailable")}`);
6532
+ break;
6533
+ case "unknown":
6534
+ lines.push(` ${SYMBOLS2.info} ${import_picocolors6.default.yellow("Version information unavailable")}`);
6535
+ break;
6536
+ }
6537
+ lines.push("");
6538
+ return lines.join(`
6539
+ `);
6540
+ }
6541
+ function formatJsonOutput(info) {
6542
+ return JSON.stringify(info, null, 2);
6543
+ }
6544
+
6545
+ // src/cli/get-local-version/index.ts
6546
+ async function getLocalVersion(options = {}) {
6547
+ const directory = options.directory ?? process.cwd();
6548
+ try {
6549
+ if (isLocalDevMode(directory)) {
6550
+ const currentVersion2 = getCachedVersion();
6551
+ const info2 = {
6552
+ currentVersion: currentVersion2,
6553
+ latestVersion: null,
6554
+ isUpToDate: false,
6555
+ isLocalDev: true,
6556
+ isPinned: false,
6557
+ pinnedVersion: null,
6558
+ status: "local-dev"
6559
+ };
6560
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
6561
+ return 0;
6562
+ }
6563
+ const pluginInfo = findPluginEntry(directory);
6564
+ if (pluginInfo?.isPinned) {
6565
+ const info2 = {
6566
+ currentVersion: pluginInfo.pinnedVersion,
6567
+ latestVersion: null,
6568
+ isUpToDate: false,
6569
+ isLocalDev: false,
6570
+ isPinned: true,
6571
+ pinnedVersion: pluginInfo.pinnedVersion,
6572
+ status: "pinned"
6573
+ };
6574
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
6575
+ return 0;
6576
+ }
6577
+ const currentVersion = getCachedVersion();
6578
+ if (!currentVersion) {
6579
+ const info2 = {
6580
+ currentVersion: null,
6581
+ latestVersion: null,
6582
+ isUpToDate: false,
6583
+ isLocalDev: false,
6584
+ isPinned: false,
6585
+ pinnedVersion: null,
6586
+ status: "unknown"
6587
+ };
6588
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
6589
+ return 1;
6590
+ }
6591
+ const latestVersion = await getLatestVersion();
6592
+ if (!latestVersion) {
6593
+ const info2 = {
6594
+ currentVersion,
6595
+ latestVersion: null,
6596
+ isUpToDate: false,
6597
+ isLocalDev: false,
6598
+ isPinned: false,
6599
+ pinnedVersion: null,
6600
+ status: "error"
6601
+ };
6602
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
6603
+ return 0;
6604
+ }
6605
+ const isUpToDate = currentVersion === latestVersion;
6606
+ const info = {
6607
+ currentVersion,
6608
+ latestVersion,
6609
+ isUpToDate,
6610
+ isLocalDev: false,
6611
+ isPinned: false,
6612
+ pinnedVersion: null,
6613
+ status: isUpToDate ? "up-to-date" : "outdated"
6614
+ };
6615
+ console.log(options.json ? formatJsonOutput(info) : formatVersionOutput(info));
6616
+ return 0;
6617
+ } catch (error) {
6618
+ const info = {
6619
+ currentVersion: null,
6620
+ latestVersion: null,
6621
+ isUpToDate: false,
6622
+ isLocalDev: false,
6623
+ isPinned: false,
6624
+ pinnedVersion: null,
6625
+ status: "error"
6626
+ };
6627
+ console.log(options.json ? formatJsonOutput(info) : formatVersionOutput(info));
6628
+ return 1;
6629
+ }
6630
+ }
6631
+
5518
6632
  // src/cli/index.ts
5519
6633
  var packageJson = await Promise.resolve().then(() => __toESM(require_package(), 1));
5520
6634
  var VERSION = packageJson.version;
@@ -5560,6 +6674,25 @@ Unlike 'opencode run', this command waits until:
5560
6674
  const exitCode = await run(runOptions);
5561
6675
  process.exit(exitCode);
5562
6676
  });
6677
+ program2.command("get-local-version").description("Show current installed version and check for updates").option("-d, --directory <path>", "Working directory to check config from").option("--json", "Output in JSON format for scripting").addHelpText("after", `
6678
+ Examples:
6679
+ $ bunx oh-my-opencode get-local-version
6680
+ $ bunx oh-my-opencode get-local-version --json
6681
+ $ bunx oh-my-opencode get-local-version --directory /path/to/project
6682
+
6683
+ This command shows:
6684
+ - Current installed version
6685
+ - Latest available version on npm
6686
+ - Whether you're up to date
6687
+ - Special modes (local dev, pinned version)
6688
+ `).action(async (options) => {
6689
+ const versionOptions = {
6690
+ directory: options.directory,
6691
+ json: options.json ?? false
6692
+ };
6693
+ const exitCode = await getLocalVersion(versionOptions);
6694
+ process.exit(exitCode);
6695
+ });
5563
6696
  program2.command("version").description("Show version information").action(() => {
5564
6697
  console.log(`oh-my-opencode v${VERSION}`);
5565
6698
  });