evil-omo 3.15.3 → 3.16.1

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 (59) hide show
  1. package/LICENSE.md +82 -82
  2. package/README.ja.md +353 -353
  3. package/README.ko.md +347 -347
  4. package/README.md +51 -51
  5. package/README.ru.md +374 -374
  6. package/README.zh-cn.md +352 -352
  7. package/bin/evil-omo.js +201 -201
  8. package/bin/platform.d.ts +14 -14
  9. package/bin/platform.js +82 -82
  10. package/bin/platform.test.ts +218 -218
  11. package/dist/agents/dynamic-agent-core-sections.d.ts +7 -0
  12. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  13. package/dist/cli/config-manager/backup-config.d.ts +6 -0
  14. package/dist/cli/config-manager/version-compatibility.d.ts +9 -0
  15. package/dist/cli/config-manager.d.ts +4 -0
  16. package/dist/cli/doctor/constants.d.ts +1 -1
  17. package/dist/cli/index.js +917 -822
  18. package/dist/cli/minimum-opencode-version.d.ts +1 -0
  19. package/dist/cli/model-fallback-types.d.ts +3 -0
  20. package/dist/cli/types.d.ts +1 -0
  21. package/dist/create-managers.d.ts +14 -0
  22. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +5 -2
  23. package/dist/features/boulder-state/storage.d.ts +7 -0
  24. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +1 -1
  25. package/dist/features/claude-code-mcp-loader/env-expander.d.ts +5 -2
  26. package/dist/features/claude-code-plugin-loader/loader.d.ts +15 -0
  27. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +2 -0
  28. package/dist/features/claude-code-plugin-loader/types.d.ts +11 -0
  29. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  30. package/dist/features/mcp-oauth/provider.d.ts +1 -0
  31. package/dist/features/mcp-oauth/refresh-mutex.d.ts +26 -0
  32. package/dist/features/skill-mcp-manager/error-redaction.d.ts +10 -0
  33. package/dist/features/skill-mcp-manager/oauth-handler.d.ts +7 -0
  34. package/dist/features/skill-mcp-manager/types.d.ts +3 -1
  35. package/dist/hooks/atlas/types.d.ts +1 -0
  36. package/dist/hooks/auto-update-checker/constants.d.ts +2 -2
  37. package/dist/hooks/keyword-detector/hook.d.ts +2 -1
  38. package/dist/hooks/ralph-loop/constants.d.ts +1 -0
  39. package/dist/hooks/ralph-loop/oracle-verification-detector.d.ts +8 -0
  40. package/dist/hooks/read-image-resizer/png-fallback-resizer.d.ts +2 -0
  41. package/dist/hooks/runtime-fallback/auto-retry-signal.d.ts +4 -0
  42. package/dist/hooks/runtime-fallback/error-classifier.d.ts +1 -5
  43. package/dist/hooks/session-recovery/types.d.ts +2 -0
  44. package/dist/hooks/todo-continuation-enforcer/pending-question-detection.d.ts +1 -1
  45. package/dist/hooks/todo-continuation-enforcer/token-limit-detection.d.ts +4 -0
  46. package/dist/hooks/todo-continuation-enforcer/types.d.ts +7 -0
  47. package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
  48. package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +2 -0
  49. package/dist/index.js +2025 -1302
  50. package/dist/plugin/chat-params.d.ts +1 -0
  51. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  52. package/dist/shared/agent-display-names.d.ts +9 -2
  53. package/dist/shared/compaction-marker.d.ts +12 -0
  54. package/dist/shared/index.d.ts +1 -0
  55. package/dist/shared/internal-initiator-marker.d.ts +1 -0
  56. package/dist/shared/session-prompt-params-state.d.ts +1 -0
  57. package/dist/tools/background-task/constants.d.ts +1 -1
  58. package/package.json +16 -18
  59. package/postinstall.mjs +133 -71
package/dist/cli/index.js CHANGED
@@ -5995,9 +5995,13 @@ var init_plugin_identity = __esm(() => {
5995
5995
  // src/shared/jsonc-parser.ts
5996
5996
  import { existsSync, readFileSync } from "fs";
5997
5997
  import { join as join4 } from "path";
5998
+ function stripBom(content) {
5999
+ return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
6000
+ }
5998
6001
  function parseJsonc(content) {
6002
+ content = content.replace(/^\uFEFF/, "");
5999
6003
  const errors = [];
6000
- const result = parse2(content, errors, {
6004
+ const result = parse2(stripBom(content), errors, {
6001
6005
  allowTrailingComma: true,
6002
6006
  disallowComments: false
6003
6007
  });
@@ -6038,47 +6042,8 @@ var init_jsonc_parser = __esm(() => {
6038
6042
  });
6039
6043
 
6040
6044
  // src/shared/migration/agent-names.ts
6041
- function migrateAgentNames(agents) {
6042
- const migrated = {};
6043
- let changed = false;
6044
- for (const [key, value] of Object.entries(agents)) {
6045
- const newKey = AGENT_NAME_MAP[key.toLowerCase()] ?? AGENT_NAME_MAP[key] ?? key;
6046
- if (newKey !== key) {
6047
- changed = true;
6048
- }
6049
- migrated[newKey] = value;
6050
- }
6051
- return { migrated, changed };
6052
- }
6053
- var AGENT_NAME_MAP, BUILTIN_AGENT_NAMES;
6045
+ var BUILTIN_AGENT_NAMES;
6054
6046
  var init_agent_names = __esm(() => {
6055
- AGENT_NAME_MAP = {
6056
- omo: "sisyphus",
6057
- OmO: "sisyphus",
6058
- Sisyphus: "sisyphus",
6059
- sisyphus: "sisyphus",
6060
- "OmO-Plan": "prometheus",
6061
- "omo-plan": "prometheus",
6062
- "Planner-Sisyphus": "prometheus",
6063
- "planner-sisyphus": "prometheus",
6064
- "Prometheus (Planner)": "prometheus",
6065
- prometheus: "prometheus",
6066
- "orchestrator-sisyphus": "atlas",
6067
- Atlas: "atlas",
6068
- atlas: "atlas",
6069
- "plan-consultant": "metis",
6070
- "Metis (Plan Consultant)": "metis",
6071
- metis: "metis",
6072
- "Momus (Plan Reviewer)": "momus",
6073
- momus: "momus",
6074
- "Sisyphus-Junior": "sisyphus-junior",
6075
- "sisyphus-junior": "sisyphus-junior",
6076
- build: "build",
6077
- oracle: "oracle",
6078
- librarian: "librarian",
6079
- explore: "explore",
6080
- "multimodal-looker": "multimodal-looker"
6081
- };
6082
6047
  BUILTIN_AGENT_NAMES = new Set([
6083
6048
  "sisyphus",
6084
6049
  "oracle",
@@ -6094,212 +6059,19 @@ var init_agent_names = __esm(() => {
6094
6059
  });
6095
6060
 
6096
6061
  // src/shared/migration/hook-names.ts
6097
- function migrateHookNames(hooks) {
6098
- const migrated = [];
6099
- const removed = [];
6100
- let changed = false;
6101
- for (const hook of hooks) {
6102
- const mapping = HOOK_NAME_MAP[hook];
6103
- if (mapping === null) {
6104
- removed.push(hook);
6105
- changed = true;
6106
- continue;
6107
- }
6108
- const newHook = mapping ?? hook;
6109
- if (newHook !== hook) {
6110
- changed = true;
6111
- }
6112
- migrated.push(newHook);
6113
- }
6114
- return { migrated, changed, removed };
6115
- }
6116
- var HOOK_NAME_MAP;
6117
- var init_hook_names = __esm(() => {
6118
- HOOK_NAME_MAP = {
6119
- "anthropic-auto-compact": "anthropic-context-window-limit-recovery",
6120
- "sisyphus-orchestrator": "atlas",
6121
- "sisyphus-gpt-hephaestus-reminder": "no-sisyphus-gpt",
6122
- "empty-message-sanitizer": null,
6123
- "delegate-task-english-directive": null,
6124
- "gpt-permission-continuation": null
6125
- };
6126
- });
6062
+ var init_hook_names = () => {};
6127
6063
 
6128
6064
  // src/shared/migration/model-versions.ts
6129
- function migrationKey(oldModel, newModel) {
6130
- return `model-version:${oldModel}->${newModel}`;
6131
- }
6132
- function migrateModelVersions(configs, appliedMigrations) {
6133
- const migrated = {};
6134
- let changed = false;
6135
- const newMigrations = [];
6136
- for (const [key, value] of Object.entries(configs)) {
6137
- if (value && typeof value === "object" && !Array.isArray(value)) {
6138
- const config = value;
6139
- if (typeof config.model === "string" && MODEL_VERSION_MAP[config.model]) {
6140
- const oldModel = config.model;
6141
- const newModel = MODEL_VERSION_MAP[oldModel];
6142
- const mKey = migrationKey(oldModel, newModel);
6143
- if (appliedMigrations?.has(mKey)) {
6144
- migrated[key] = value;
6145
- continue;
6146
- }
6147
- migrated[key] = { ...config, model: newModel };
6148
- changed = true;
6149
- newMigrations.push(mKey);
6150
- continue;
6151
- }
6152
- }
6153
- migrated[key] = value;
6154
- }
6155
- return { migrated, changed, newMigrations };
6156
- }
6157
- var MODEL_VERSION_MAP;
6158
- var init_model_versions = __esm(() => {
6159
- MODEL_VERSION_MAP = {
6160
- "anthropic/claude-opus-4-5": "anthropic/claude-opus-4-6",
6161
- "anthropic/claude-sonnet-4-5": "anthropic/claude-sonnet-4-6",
6162
- "openai/gpt-5.3-codex": "openai/gpt-5.4"
6163
- };
6164
- });
6065
+ var init_model_versions = () => {};
6165
6066
 
6166
6067
  // src/shared/migration/agent-category.ts
6167
6068
  var init_agent_category = () => {};
6168
6069
 
6169
- // src/shared/write-file-atomically.ts
6170
- import { closeSync, fsyncSync, openSync, renameSync, writeFileSync } from "fs";
6171
- function writeFileAtomically(filePath, content) {
6172
- const tempPath = `${filePath}.tmp`;
6173
- writeFileSync(tempPath, content, "utf-8");
6174
- const tempFileDescriptor = openSync(tempPath, "r");
6175
- try {
6176
- fsyncSync(tempFileDescriptor);
6177
- } finally {
6178
- closeSync(tempFileDescriptor);
6179
- }
6180
- renameSync(tempPath, filePath);
6181
- }
6182
- var init_write_file_atomically = () => {};
6183
-
6184
6070
  // src/shared/migration/config-migration.ts
6185
- import * as fs2 from "fs";
6186
- function migrateConfigFile(configPath, rawConfig) {
6187
- const copy = structuredClone(rawConfig);
6188
- let needsWrite = false;
6189
- const existingMigrations = Array.isArray(copy._migrations) ? new Set(copy._migrations) : new Set;
6190
- const allNewMigrations = [];
6191
- if (copy.agents && typeof copy.agents === "object") {
6192
- const { migrated, changed } = migrateAgentNames(copy.agents);
6193
- if (changed) {
6194
- copy.agents = migrated;
6195
- needsWrite = true;
6196
- }
6197
- }
6198
- if (copy.agents && typeof copy.agents === "object") {
6199
- const { migrated, changed, newMigrations } = migrateModelVersions(copy.agents, existingMigrations);
6200
- if (changed) {
6201
- copy.agents = migrated;
6202
- needsWrite = true;
6203
- log("Migrated model versions in agents config");
6204
- }
6205
- allNewMigrations.push(...newMigrations);
6206
- }
6207
- if (copy.categories && typeof copy.categories === "object") {
6208
- const { migrated, changed, newMigrations } = migrateModelVersions(copy.categories, existingMigrations);
6209
- if (changed) {
6210
- copy.categories = migrated;
6211
- needsWrite = true;
6212
- log("Migrated model versions in categories config");
6213
- }
6214
- allNewMigrations.push(...newMigrations);
6215
- }
6216
- if (allNewMigrations.length > 0) {
6217
- const updatedMigrations = Array.from(existingMigrations);
6218
- updatedMigrations.push(...allNewMigrations);
6219
- copy._migrations = updatedMigrations;
6220
- needsWrite = true;
6221
- }
6222
- if (copy.omo_agent) {
6223
- copy.sisyphus_agent = copy.omo_agent;
6224
- delete copy.omo_agent;
6225
- needsWrite = true;
6226
- }
6227
- if (copy.experimental && typeof copy.experimental === "object") {
6228
- const experimental = copy.experimental;
6229
- if ("hashline_edit" in experimental) {
6230
- if (copy.hashline_edit === undefined) {
6231
- copy.hashline_edit = experimental.hashline_edit;
6232
- }
6233
- delete experimental.hashline_edit;
6234
- if (Object.keys(experimental).length === 0) {
6235
- delete copy.experimental;
6236
- }
6237
- needsWrite = true;
6238
- }
6239
- }
6240
- if (copy.disabled_agents && Array.isArray(copy.disabled_agents)) {
6241
- const migrated = [];
6242
- let changed = false;
6243
- for (const agent of copy.disabled_agents) {
6244
- const newAgent = AGENT_NAME_MAP[agent.toLowerCase()] ?? AGENT_NAME_MAP[agent] ?? agent;
6245
- if (newAgent !== agent) {
6246
- changed = true;
6247
- }
6248
- migrated.push(newAgent);
6249
- }
6250
- if (changed) {
6251
- copy.disabled_agents = migrated;
6252
- needsWrite = true;
6253
- }
6254
- }
6255
- if (copy.disabled_hooks && Array.isArray(copy.disabled_hooks)) {
6256
- const { migrated, changed, removed } = migrateHookNames(copy.disabled_hooks);
6257
- if (changed) {
6258
- copy.disabled_hooks = migrated;
6259
- needsWrite = true;
6260
- }
6261
- if (removed.length > 0) {
6262
- log(`Removed obsolete hooks from disabled_hooks: ${removed.join(", ")} (these hooks no longer exist in v3.0.0)`);
6263
- }
6264
- }
6265
- if (needsWrite) {
6266
- const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
6267
- const backupPath = `${configPath}.bak.${timestamp2}`;
6268
- let backupSucceeded = false;
6269
- try {
6270
- fs2.copyFileSync(configPath, backupPath);
6271
- backupSucceeded = true;
6272
- } catch {
6273
- backupSucceeded = false;
6274
- }
6275
- let writeSucceeded = false;
6276
- try {
6277
- writeFileAtomically(configPath, JSON.stringify(copy, null, 2) + `
6278
- `);
6279
- writeSucceeded = true;
6280
- } catch (err) {
6281
- log(`Failed to write migrated config to ${configPath}:`, err);
6282
- }
6283
- for (const key of Object.keys(rawConfig)) {
6284
- delete rawConfig[key];
6285
- }
6286
- Object.assign(rawConfig, copy);
6287
- if (writeSucceeded) {
6288
- const backupMessage = backupSucceeded ? ` (backup: ${backupPath})` : "";
6289
- log(`Migrated config file: ${configPath}${backupMessage}`);
6290
- } else {
6291
- const backupMessage = backupSucceeded ? ` (backup: ${backupPath})` : "";
6292
- log(`Applied migrated config in-memory for: ${configPath}${backupMessage}`);
6293
- }
6294
- }
6295
- return needsWrite;
6296
- }
6297
6071
  var init_config_migration = __esm(() => {
6298
6072
  init_logger();
6299
- init_write_file_atomically();
6300
6073
  init_agent_names();
6301
6074
  init_hook_names();
6302
- init_model_versions();
6303
6075
  });
6304
6076
 
6305
6077
  // src/shared/migration.ts
@@ -6520,6 +6292,9 @@ var init_binary_downloader = __esm(() => {
6520
6292
  init_zip_extractor();
6521
6293
  });
6522
6294
 
6295
+ // src/shared/write-file-atomically.ts
6296
+ var init_write_file_atomically = () => {};
6297
+
6523
6298
  // src/shared/model-requirements.ts
6524
6299
  var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
6525
6300
  var init_model_requirements = __esm(() => {
@@ -6880,7 +6655,7 @@ function normalizeModelID(modelID) {
6880
6655
  }
6881
6656
 
6882
6657
  // src/shared/json-file-cache-store.ts
6883
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6658
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
6884
6659
  import { join as join7 } from "path";
6885
6660
  function toLogLabel(cacheLabel) {
6886
6661
  return cacheLabel.toLowerCase();
@@ -6927,7 +6702,7 @@ function createJsonFileCacheStore(options) {
6927
6702
  ensureCacheDir();
6928
6703
  const cacheFile = getCacheFilePath();
6929
6704
  try {
6930
- writeFileSync2(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2));
6705
+ writeFileSync(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2));
6931
6706
  memoryValue = value;
6932
6707
  log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value));
6933
6708
  } catch (error) {
@@ -48392,6 +48167,57 @@ var init_constants = __esm(() => {
48392
48167
  init_shared();
48393
48168
  });
48394
48169
 
48170
+ // src/shared/opencode-storage-paths.ts
48171
+ import { join as join9 } from "path";
48172
+ var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48173
+ var init_opencode_storage_paths = __esm(() => {
48174
+ init_data_path();
48175
+ OPENCODE_STORAGE = getOpenCodeStorageDir();
48176
+ MESSAGE_STORAGE = join9(OPENCODE_STORAGE, "message");
48177
+ PART_STORAGE = join9(OPENCODE_STORAGE, "part");
48178
+ SESSION_STORAGE = join9(OPENCODE_STORAGE, "session");
48179
+ });
48180
+
48181
+ // src/shared/compaction-marker.ts
48182
+ import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync4 } from "fs";
48183
+ import { join as join10 } from "path";
48184
+ function isCompactionPart(part) {
48185
+ return typeof part === "object" && part !== null && part.type === "compaction";
48186
+ }
48187
+ function isCompactionAgent(agent) {
48188
+ return typeof agent === "string" && agent.trim().toLowerCase() === "compaction";
48189
+ }
48190
+ function hasCompactionPart(parts) {
48191
+ return Array.isArray(parts) && parts.some((part) => isCompactionPart(part));
48192
+ }
48193
+ function isCompactionMessage(message) {
48194
+ return isCompactionAgent(message.info?.agent ?? message.agent) || hasCompactionPart(message.parts);
48195
+ }
48196
+ function hasCompactionPartInStorage(messageID) {
48197
+ if (!messageID) {
48198
+ return false;
48199
+ }
48200
+ const partDir = join10(PART_STORAGE, messageID);
48201
+ if (!existsSync6(partDir)) {
48202
+ return false;
48203
+ }
48204
+ try {
48205
+ return readdirSync(partDir).filter((fileName) => fileName.endsWith(".json")).some((fileName) => {
48206
+ try {
48207
+ const content = readFileSync4(join10(partDir, fileName), "utf-8");
48208
+ return isCompactionPart(JSON.parse(content));
48209
+ } catch {
48210
+ return false;
48211
+ }
48212
+ });
48213
+ } catch {
48214
+ return false;
48215
+ }
48216
+ }
48217
+ var init_compaction_marker = __esm(() => {
48218
+ init_opencode_storage_paths();
48219
+ });
48220
+
48395
48221
  // src/features/hook-message-injector/injector.ts
48396
48222
  import { randomBytes } from "crypto";
48397
48223
  var processPrefix;
@@ -48400,6 +48226,7 @@ var init_injector = __esm(() => {
48400
48226
  init_logger();
48401
48227
  init_opencode_storage_detection();
48402
48228
  init_shared();
48229
+ init_compaction_marker();
48403
48230
  processPrefix = randomBytes(4).toString("hex");
48404
48231
  });
48405
48232
 
@@ -48409,35 +48236,24 @@ var init_hook_message_injector = __esm(() => {
48409
48236
  init_constants();
48410
48237
  });
48411
48238
 
48412
- // src/shared/opencode-storage-paths.ts
48413
- import { join as join9 } from "path";
48414
- var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48415
- var init_opencode_storage_paths = __esm(() => {
48416
- init_data_path();
48417
- OPENCODE_STORAGE = getOpenCodeStorageDir();
48418
- MESSAGE_STORAGE = join9(OPENCODE_STORAGE, "message");
48419
- PART_STORAGE = join9(OPENCODE_STORAGE, "part");
48420
- SESSION_STORAGE = join9(OPENCODE_STORAGE, "session");
48421
- });
48422
-
48423
48239
  // src/shared/opencode-message-dir.ts
48424
- import { existsSync as existsSync6, readdirSync } from "fs";
48425
- import { join as join10 } from "path";
48240
+ import { existsSync as existsSync7, readdirSync as readdirSync2 } from "fs";
48241
+ import { join as join11 } from "path";
48426
48242
  function getMessageDir(sessionID) {
48427
48243
  if (!sessionID.startsWith("ses_"))
48428
48244
  return null;
48429
48245
  if (/[/\\]|\.\./.test(sessionID))
48430
48246
  return null;
48431
- if (!existsSync6(MESSAGE_STORAGE))
48247
+ if (!existsSync7(MESSAGE_STORAGE))
48432
48248
  return null;
48433
- const directPath = join10(MESSAGE_STORAGE, sessionID);
48434
- if (existsSync6(directPath)) {
48249
+ const directPath = join11(MESSAGE_STORAGE, sessionID);
48250
+ if (existsSync7(directPath)) {
48435
48251
  return directPath;
48436
48252
  }
48437
48253
  try {
48438
- for (const dir of readdirSync(MESSAGE_STORAGE)) {
48439
- const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
48440
- if (existsSync6(sessionPath)) {
48254
+ for (const dir of readdirSync2(MESSAGE_STORAGE)) {
48255
+ const sessionPath = join11(MESSAGE_STORAGE, dir, sessionID);
48256
+ if (existsSync7(sessionPath)) {
48441
48257
  return sessionPath;
48442
48258
  }
48443
48259
  }
@@ -48472,22 +48288,25 @@ function getAgentConfigKey(agentName) {
48472
48288
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48473
48289
  if (reversed !== undefined)
48474
48290
  return reversed;
48291
+ const legacy = LEGACY_DISPLAY_NAMES[lower];
48292
+ if (legacy !== undefined)
48293
+ return legacy;
48475
48294
  if (AGENT_DISPLAY_NAMES[lower] !== undefined)
48476
48295
  return lower;
48477
48296
  return lower;
48478
48297
  }
48479
- var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES;
48298
+ var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
48480
48299
  var init_agent_display_names = __esm(() => {
48481
48300
  AGENT_DISPLAY_NAMES = {
48482
- sisyphus: "Sisyphus (Ultraworker)",
48483
- hephaestus: "Hephaestus (Deep Agent)",
48484
- prometheus: "Prometheus (Plan Builder)",
48485
- atlas: "Atlas (Plan Executor)",
48301
+ sisyphus: "Sisyphus - Ultraworker",
48302
+ hephaestus: "Hephaestus - Deep Agent",
48303
+ prometheus: "Prometheus - Plan Builder",
48304
+ atlas: "Atlas - Plan Executor",
48486
48305
  "sisyphus-junior": "Sisyphus-Junior",
48487
- metis: "Metis (Plan Consultant)",
48488
- momus: "Momus (Plan Critic)",
48489
- athena: "Athena (Council)",
48490
- "athena-junior": "Athena-Junior (Council)",
48306
+ metis: "Metis - Plan Consultant",
48307
+ momus: "Momus - Plan Critic",
48308
+ athena: "Athena - Council",
48309
+ "athena-junior": "Athena-Junior - Council",
48491
48310
  oracle: "oracle",
48492
48311
  librarian: "librarian",
48493
48312
  explore: "explore",
@@ -48495,6 +48314,16 @@ var init_agent_display_names = __esm(() => {
48495
48314
  "council-member": "council-member"
48496
48315
  };
48497
48316
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
48317
+ LEGACY_DISPLAY_NAMES = {
48318
+ "sisyphus (ultraworker)": "sisyphus",
48319
+ "hephaestus (deep agent)": "hephaestus",
48320
+ "prometheus (plan builder)": "prometheus",
48321
+ "atlas (plan executor)": "atlas",
48322
+ "metis (plan consultant)": "metis",
48323
+ "momus (plan critic)": "momus",
48324
+ "athena (council)": "athena",
48325
+ "athena-junior (council)": "athena-junior"
48326
+ };
48498
48327
  });
48499
48328
 
48500
48329
  // src/shared/session-utils.ts
@@ -48658,9 +48487,18 @@ var init_session_tools_store = __esm(() => {
48658
48487
  var init_prompt_tools = __esm(() => {
48659
48488
  init_session_tools_store();
48660
48489
  });
48490
+
48491
+ // src/shared/internal-initiator-marker.ts
48492
+ var init_internal_initiator_marker = () => {};
48493
+ // src/features/claude-code-plugin-loader/scope-filter.ts
48494
+ var init_scope_filter = __esm(() => {
48495
+ init_contains_path();
48496
+ });
48497
+
48661
48498
  // src/features/claude-code-plugin-loader/discovery.ts
48662
48499
  var init_discovery = __esm(() => {
48663
48500
  init_logger();
48501
+ init_scope_filter();
48664
48502
  });
48665
48503
 
48666
48504
  // src/features/claude-code-plugin-loader/command-loader.ts
@@ -48711,7 +48549,7 @@ var init_env_expander = __esm(() => {
48711
48549
  });
48712
48550
 
48713
48551
  // src/features/claude-code-mcp-loader/scope-filter.ts
48714
- var init_scope_filter = __esm(() => {
48552
+ var init_scope_filter2 = __esm(() => {
48715
48553
  init_contains_path();
48716
48554
  });
48717
48555
 
@@ -48722,7 +48560,7 @@ var init_transformer = __esm(() => {
48722
48560
  // src/features/claude-code-plugin-loader/mcp-server-loader.ts
48723
48561
  var init_mcp_server_loader = __esm(() => {
48724
48562
  init_env_expander();
48725
- init_scope_filter();
48563
+ init_scope_filter2();
48726
48564
  init_transformer();
48727
48565
  init_logger();
48728
48566
  });
@@ -48858,6 +48696,8 @@ var init_shared = __esm(() => {
48858
48696
  init_project_discovery_dirs();
48859
48697
  init_session_directory_resolver();
48860
48698
  init_prompt_tools();
48699
+ init_compaction_marker();
48700
+ init_internal_initiator_marker();
48861
48701
  init_plugin_command_discovery();
48862
48702
  init_plugin_identity();
48863
48703
  init_log_legacy_plugin_startup_warning();
@@ -48939,12 +48779,37 @@ var init_plugin_name_with_version = __esm(() => {
48939
48779
  PRIORITIZED_TAGS = ["latest", "beta", "next"];
48940
48780
  });
48941
48781
 
48782
+ // src/cli/config-manager/backup-config.ts
48783
+ import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync3 } from "fs";
48784
+ import { dirname } from "path";
48785
+ function backupConfigFile(configPath) {
48786
+ if (!existsSync8(configPath)) {
48787
+ return { success: true };
48788
+ }
48789
+ const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
48790
+ const backupPath = `${configPath}.backup-${timestamp2}`;
48791
+ try {
48792
+ const dir = dirname(backupPath);
48793
+ if (!existsSync8(dir)) {
48794
+ mkdirSync3(dir, { recursive: true });
48795
+ }
48796
+ copyFileSync(configPath, backupPath);
48797
+ return { success: true, backupPath };
48798
+ } catch (err) {
48799
+ return {
48800
+ success: false,
48801
+ error: err instanceof Error ? err.message : "Failed to create backup"
48802
+ };
48803
+ }
48804
+ }
48805
+ var init_backup_config = () => {};
48806
+
48942
48807
  // src/cli/config-manager/ensure-config-directory-exists.ts
48943
- import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
48808
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
48944
48809
  function ensureConfigDirectoryExists() {
48945
48810
  const configDir = getConfigDir();
48946
- if (!existsSync7(configDir)) {
48947
- mkdirSync3(configDir, { recursive: true });
48811
+ if (!existsSync9(configDir)) {
48812
+ mkdirSync4(configDir, { recursive: true });
48948
48813
  }
48949
48814
  }
48950
48815
  var init_ensure_config_directory_exists = __esm(() => {
@@ -48981,14 +48846,14 @@ function formatErrorWithSuggestion(err, context) {
48981
48846
  }
48982
48847
 
48983
48848
  // src/cli/config-manager/opencode-config-format.ts
48984
- import { existsSync as existsSync8 } from "fs";
48849
+ import { existsSync as existsSync10 } from "fs";
48985
48850
  function detectConfigFormat() {
48986
48851
  const configJsonc = getConfigJsonc();
48987
48852
  const configJson = getConfigJson();
48988
- if (existsSync8(configJsonc)) {
48853
+ if (existsSync10(configJsonc)) {
48989
48854
  return { format: "jsonc", path: configJsonc };
48990
48855
  }
48991
- if (existsSync8(configJson)) {
48856
+ if (existsSync10(configJson)) {
48992
48857
  return { format: "json", path: configJson };
48993
48858
  }
48994
48859
  return { format: "none", path: configJson };
@@ -48998,7 +48863,7 @@ var init_opencode_config_format = __esm(() => {
48998
48863
  });
48999
48864
 
49000
48865
  // src/cli/config-manager/parse-opencode-config-file.ts
49001
- import { readFileSync as readFileSync4, statSync } from "fs";
48866
+ import { readFileSync as readFileSync5, statSync } from "fs";
49002
48867
  function isEmptyOrWhitespace(content) {
49003
48868
  return content.trim().length === 0;
49004
48869
  }
@@ -49008,7 +48873,7 @@ function parseOpenCodeConfigFileWithError(path3) {
49008
48873
  if (stat.size === 0) {
49009
48874
  return { config: null, error: `Config file is empty: ${path3}. Delete it or add valid JSON content.` };
49010
48875
  }
49011
- const content = readFileSync4(path3, "utf-8");
48876
+ const content = readFileSync5(path3, "utf-8");
49012
48877
  if (isEmptyOrWhitespace(content)) {
49013
48878
  return { config: null, error: `Config file contains only whitespace: ${path3}. Delete it or add valid JSON content.` };
49014
48879
  }
@@ -49031,8 +48896,90 @@ var init_parse_opencode_config_file = __esm(() => {
49031
48896
  init_shared();
49032
48897
  });
49033
48898
 
48899
+ // src/cli/config-manager/version-compatibility.ts
48900
+ function parseVersion2(version) {
48901
+ const clean = version.replace(/^v/, "").split("-")[0];
48902
+ return clean.split(".").map(Number);
48903
+ }
48904
+ function compareVersions2(a, b) {
48905
+ const partsA = parseVersion2(a);
48906
+ const partsB = parseVersion2(b);
48907
+ const maxLen = Math.max(partsA.length, partsB.length);
48908
+ for (let i2 = 0;i2 < maxLen; i2++) {
48909
+ const numA = partsA[i2] ?? 0;
48910
+ const numB = partsB[i2] ?? 0;
48911
+ if (numA !== numB) {
48912
+ return numA - numB;
48913
+ }
48914
+ }
48915
+ return 0;
48916
+ }
48917
+ function checkVersionCompatibility(currentVersion, newVersion) {
48918
+ if (!currentVersion) {
48919
+ return {
48920
+ canUpgrade: true,
48921
+ isDowngrade: false,
48922
+ isMajorBump: false,
48923
+ requiresMigration: false
48924
+ };
48925
+ }
48926
+ const cleanCurrent = currentVersion.replace(/^v/, "");
48927
+ const cleanNew = newVersion.replace(/^v/, "");
48928
+ try {
48929
+ const comparison = compareVersions2(cleanNew, cleanCurrent);
48930
+ if (comparison < 0) {
48931
+ return {
48932
+ canUpgrade: false,
48933
+ reason: `Downgrade from ${currentVersion} to ${newVersion} is not allowed`,
48934
+ isDowngrade: true,
48935
+ isMajorBump: false,
48936
+ requiresMigration: false
48937
+ };
48938
+ }
48939
+ if (comparison === 0) {
48940
+ return {
48941
+ canUpgrade: true,
48942
+ reason: `Version ${newVersion} is already installed`,
48943
+ isDowngrade: false,
48944
+ isMajorBump: false,
48945
+ requiresMigration: false
48946
+ };
48947
+ }
48948
+ const currentMajor = cleanCurrent.split(".")[0];
48949
+ const newMajor = cleanNew.split(".")[0];
48950
+ const isMajorBump = currentMajor !== newMajor;
48951
+ if (isMajorBump) {
48952
+ return {
48953
+ canUpgrade: true,
48954
+ reason: `Major version upgrade from ${currentVersion} to ${newVersion} - configuration migration may be required`,
48955
+ isDowngrade: false,
48956
+ isMajorBump: true,
48957
+ requiresMigration: true
48958
+ };
48959
+ }
48960
+ return {
48961
+ canUpgrade: true,
48962
+ isDowngrade: false,
48963
+ isMajorBump: false,
48964
+ requiresMigration: false
48965
+ };
48966
+ } catch {
48967
+ return {
48968
+ canUpgrade: true,
48969
+ reason: `Unable to compare versions ${currentVersion} and ${newVersion} - proceeding with caution`,
48970
+ isDowngrade: false,
48971
+ isMajorBump: false,
48972
+ requiresMigration: false
48973
+ };
48974
+ }
48975
+ }
48976
+ function extractVersionFromPluginEntry(entry) {
48977
+ const match = entry.match(/@(.+)$/);
48978
+ return match ? match[1] : null;
48979
+ }
48980
+
49034
48981
  // src/cli/config-manager/add-plugin-to-opencode-config.ts
49035
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
48982
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
49036
48983
  async function addPluginToOpenCodeConfig(currentVersion) {
49037
48984
  try {
49038
48985
  ensureConfigDirectoryExists();
@@ -49048,7 +48995,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49048
48995
  try {
49049
48996
  if (format2 === "none") {
49050
48997
  const config2 = { plugin: [pluginEntry] };
49051
- writeFileSync3(path3, JSON.stringify(config2, null, 2) + `
48998
+ writeFileSync2(path3, JSON.stringify(config2, null, 2) + `
49052
48999
  `);
49053
49000
  return { success: true, configPath: path3 };
49054
49001
  }
@@ -49065,19 +49012,35 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49065
49012
  const canonicalEntries = plugins.filter((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`));
49066
49013
  const legacyEntries = plugins.filter((plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`));
49067
49014
  const otherPlugins = plugins.filter((plugin) => !(plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`)) && !(plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`)));
49015
+ const existingEntry = canonicalEntries[0] ?? legacyEntries[0];
49016
+ if (existingEntry) {
49017
+ const installedVersion = extractVersionFromPluginEntry(existingEntry);
49018
+ const compatibility = checkVersionCompatibility(installedVersion, currentVersion);
49019
+ if (!compatibility.canUpgrade) {
49020
+ return {
49021
+ success: false,
49022
+ configPath: path3,
49023
+ error: compatibility.reason ?? "Version compatibility check failed"
49024
+ };
49025
+ }
49026
+ const backupResult = backupConfigFile(path3);
49027
+ if (!backupResult.success) {
49028
+ return {
49029
+ success: false,
49030
+ configPath: path3,
49031
+ error: `Failed to create backup: ${backupResult.error}`
49032
+ };
49033
+ }
49034
+ }
49068
49035
  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);
49036
+ if (canonicalEntries.length > 0 || legacyEntries.length > 0) {
49037
+ normalizedPlugins.push(pluginEntry);
49075
49038
  } else {
49076
49039
  normalizedPlugins.push(pluginEntry);
49077
49040
  }
49078
49041
  config.plugin = normalizedPlugins;
49079
49042
  if (format2 === "jsonc") {
49080
- const content = readFileSync5(path3, "utf-8");
49043
+ const content = readFileSync6(path3, "utf-8");
49081
49044
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
49082
49045
  const match = content.match(pluginArrayRegex);
49083
49046
  if (match) {
@@ -49086,14 +49049,14 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49086
49049
  const newContent = content.replace(pluginArrayRegex, `$1[
49087
49050
  ${formattedPlugins}
49088
49051
  ]`);
49089
- writeFileSync3(path3, newContent);
49052
+ writeFileSync2(path3, newContent);
49090
49053
  } else {
49091
49054
  const newContent = content.replace(/(\{)/, `$1
49092
49055
  "plugin": ["${pluginEntry}"],`);
49093
- writeFileSync3(path3, newContent);
49056
+ writeFileSync2(path3, newContent);
49094
49057
  }
49095
49058
  } else {
49096
- writeFileSync3(path3, JSON.stringify(config, null, 2) + `
49059
+ writeFileSync2(path3, JSON.stringify(config, null, 2) + `
49097
49060
  `);
49098
49061
  }
49099
49062
  return { success: true, configPath: path3 };
@@ -49107,6 +49070,7 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49107
49070
  }
49108
49071
  var init_add_plugin_to_opencode_config = __esm(() => {
49109
49072
  init_shared();
49073
+ init_backup_config();
49110
49074
  init_config_context();
49111
49075
  init_ensure_config_directory_exists();
49112
49076
  init_opencode_config_format();
@@ -49222,6 +49186,47 @@ var init_fallback_chain_resolution = __esm(() => {
49222
49186
  });
49223
49187
 
49224
49188
  // src/cli/model-fallback.ts
49189
+ function toFallbackModelObject(entry, provider) {
49190
+ return {
49191
+ model: `${provider}/${transformModelForProvider(provider, entry.model)}`,
49192
+ ...entry.variant ? { variant: entry.variant } : {},
49193
+ ...entry.reasoningEffort ? { reasoningEffort: entry.reasoningEffort } : {},
49194
+ ...entry.temperature !== undefined ? { temperature: entry.temperature } : {},
49195
+ ...entry.top_p !== undefined ? { top_p: entry.top_p } : {},
49196
+ ...entry.maxTokens !== undefined ? { maxTokens: entry.maxTokens } : {},
49197
+ ...entry.thinking ? { thinking: entry.thinking } : {}
49198
+ };
49199
+ }
49200
+ function collectAvailableFallbacks(fallbackChain, availability) {
49201
+ const expandedFallbacks = fallbackChain.flatMap((entry) => entry.providers.filter((provider) => isProviderAvailable(provider, availability)).map((provider) => toFallbackModelObject(entry, provider)));
49202
+ return expandedFallbacks.filter((entry, index, allEntries) => allEntries.findIndex((candidate) => candidate.model === entry.model && candidate.variant === entry.variant) === index);
49203
+ }
49204
+ function attachFallbackModels(config, fallbackChain, availability) {
49205
+ const uniqueFallbacks = collectAvailableFallbacks(fallbackChain, availability);
49206
+ const primaryIndex = uniqueFallbacks.findIndex((entry) => entry.model === config.model);
49207
+ if (primaryIndex === -1) {
49208
+ return config;
49209
+ }
49210
+ const fallbackModels = uniqueFallbacks.slice(primaryIndex + 1);
49211
+ if (fallbackModels.length === 0) {
49212
+ return config;
49213
+ }
49214
+ return {
49215
+ ...config,
49216
+ fallback_models: fallbackModels
49217
+ };
49218
+ }
49219
+ function attachAllFallbackModels(config, fallbackChain, availability) {
49220
+ const uniqueFallbacks = collectAvailableFallbacks(fallbackChain, availability);
49221
+ const fallbackModels = uniqueFallbacks.filter((entry) => entry.model !== config.model);
49222
+ if (fallbackModels.length === 0) {
49223
+ return config;
49224
+ }
49225
+ return {
49226
+ ...config,
49227
+ fallback_models: fallbackModels
49228
+ };
49229
+ }
49225
49230
  function generateModelConfig(config) {
49226
49231
  const avail = toProviderAvailability(config);
49227
49232
  const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai || avail.kimiForCoding || avail.opencodeGo;
@@ -49236,25 +49241,31 @@ function generateModelConfig(config) {
49236
49241
  const categories = {};
49237
49242
  for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
49238
49243
  if (role === "librarian") {
49244
+ let agentConfig;
49239
49245
  if (avail.opencodeGo) {
49240
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49246
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49241
49247
  } else if (avail.zai) {
49242
- agents[role] = { model: ZAI_MODEL };
49248
+ agentConfig = { model: ZAI_MODEL };
49249
+ }
49250
+ if (agentConfig) {
49251
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49243
49252
  }
49244
49253
  continue;
49245
49254
  }
49246
49255
  if (role === "explore") {
49256
+ let agentConfig;
49247
49257
  if (avail.native.claude) {
49248
- agents[role] = { model: "anthropic/claude-haiku-4-5" };
49258
+ agentConfig = { model: "anthropic/claude-haiku-4-5" };
49249
49259
  } else if (avail.opencodeZen) {
49250
- agents[role] = { model: "opencode/claude-haiku-4-5" };
49260
+ agentConfig = { model: "opencode/claude-haiku-4-5" };
49251
49261
  } else if (avail.opencodeGo) {
49252
- agents[role] = { model: "opencode-go/minimax-m2.7" };
49262
+ agentConfig = { model: "opencode-go/minimax-m2.7" };
49253
49263
  } else if (avail.copilot) {
49254
- agents[role] = { model: "github-copilot/gpt-5-mini" };
49264
+ agentConfig = { model: "github-copilot/gpt-5-mini" };
49255
49265
  } else {
49256
- agents[role] = { model: "opencode/gpt-5-nano" };
49266
+ agentConfig = { model: "opencode/gpt-5-nano" };
49257
49267
  }
49268
+ agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
49258
49269
  continue;
49259
49270
  }
49260
49271
  if (role === "sisyphus") {
@@ -49265,7 +49276,8 @@ function generateModelConfig(config) {
49265
49276
  const resolved2 = resolveModelFromChain(fallbackChain, avail);
49266
49277
  if (resolved2) {
49267
49278
  const variant = resolved2.variant ?? req.variant;
49268
- agents[role] = variant ? { model: resolved2.model, variant } : { model: resolved2.model };
49279
+ const agentConfig = variant ? { model: resolved2.model, variant } : { model: resolved2.model };
49280
+ agents[role] = attachFallbackModels(agentConfig, fallbackChain, avail);
49269
49281
  }
49270
49282
  continue;
49271
49283
  }
@@ -49278,7 +49290,8 @@ function generateModelConfig(config) {
49278
49290
  const resolved = resolveModelFromChain(req.fallbackChain, avail);
49279
49291
  if (resolved) {
49280
49292
  const variant = resolved.variant ?? req.variant;
49281
- agents[role] = variant ? { model: resolved.model, variant } : { model: resolved.model };
49293
+ const agentConfig = variant ? { model: resolved.model, variant } : { model: resolved.model };
49294
+ agents[role] = attachFallbackModels(agentConfig, req.fallbackChain, avail);
49282
49295
  } else {
49283
49296
  agents[role] = { model: ULTIMATE_FALLBACK };
49284
49297
  }
@@ -49294,7 +49307,8 @@ function generateModelConfig(config) {
49294
49307
  const resolved = resolveModelFromChain(fallbackChain, avail);
49295
49308
  if (resolved) {
49296
49309
  const variant = resolved.variant ?? req.variant;
49297
- categories[cat] = variant ? { model: resolved.model, variant } : { model: resolved.model };
49310
+ const categoryConfig = variant ? { model: resolved.model, variant } : { model: resolved.model };
49311
+ categories[cat] = attachFallbackModels(categoryConfig, fallbackChain, avail);
49298
49312
  } else {
49299
49313
  categories[cat] = { model: ULTIMATE_FALLBACK };
49300
49314
  }
@@ -49311,6 +49325,7 @@ var init_model_fallback = __esm(() => {
49311
49325
  init_model_fallback_requirements();
49312
49326
  init_openai_only_model_catalog();
49313
49327
  init_fallback_chain_resolution();
49328
+ init_provider_model_id_transform();
49314
49329
  });
49315
49330
 
49316
49331
  // src/cli/config-manager/generate-omo-config.ts
@@ -49321,28 +49336,8 @@ var init_generate_omo_config = __esm(() => {
49321
49336
  init_model_fallback();
49322
49337
  });
49323
49338
 
49324
- // src/cli/config-manager/deep-merge-record.ts
49325
- function deepMergeRecord(target, source) {
49326
- const result = { ...target };
49327
- for (const key of Object.keys(source)) {
49328
- if (key === "__proto__" || key === "constructor" || key === "prototype")
49329
- continue;
49330
- const sourceValue = source[key];
49331
- const targetValue = result[key];
49332
- if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
49333
- result[key] = deepMergeRecord(targetValue, sourceValue);
49334
- } else if (sourceValue !== undefined) {
49335
- result[key] = sourceValue;
49336
- }
49337
- }
49338
- return result;
49339
- }
49340
-
49341
49339
  // src/cli/config-manager/write-omo-config.ts
49342
- import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49343
- function isEmptyOrWhitespace2(content) {
49344
- return content.trim().length === 0;
49345
- }
49340
+ import { existsSync as existsSync11, writeFileSync as writeFileSync3 } from "fs";
49346
49341
  function writeOmoConfig(installConfig) {
49347
49342
  try {
49348
49343
  ensureConfigDirectoryExists();
@@ -49356,36 +49351,11 @@ function writeOmoConfig(installConfig) {
49356
49351
  const omoConfigPath = getOmoConfigPath();
49357
49352
  try {
49358
49353
  const newConfig = generateOmoConfig(installConfig);
49359
- if (existsSync9(omoConfigPath)) {
49360
- try {
49361
- const stat = statSync2(omoConfigPath);
49362
- const content = readFileSync6(omoConfigPath, "utf-8");
49363
- if (stat.size === 0 || isEmptyOrWhitespace2(content)) {
49364
- writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49365
- `);
49366
- return { success: true, configPath: omoConfigPath };
49367
- }
49368
- const existing = parseJsonc(content);
49369
- if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
49370
- writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49371
- `);
49372
- return { success: true, configPath: omoConfigPath };
49373
- }
49374
- const merged = deepMergeRecord(newConfig, existing);
49375
- writeFileSync4(omoConfigPath, JSON.stringify(merged, null, 2) + `
49376
- `);
49377
- } catch (parseErr) {
49378
- if (parseErr instanceof SyntaxError) {
49379
- writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49380
- `);
49381
- return { success: true, configPath: omoConfigPath };
49382
- }
49383
- throw parseErr;
49384
- }
49385
- } else {
49386
- writeFileSync4(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49387
- `);
49354
+ if (existsSync11(omoConfigPath)) {
49355
+ return { success: true, configPath: omoConfigPath };
49388
49356
  }
49357
+ writeFileSync3(omoConfigPath, JSON.stringify(newConfig, null, 2) + `
49358
+ `);
49389
49359
  return { success: true, configPath: omoConfigPath };
49390
49360
  } catch (err) {
49391
49361
  return {
@@ -49396,7 +49366,6 @@ function writeOmoConfig(installConfig) {
49396
49366
  }
49397
49367
  }
49398
49368
  var init_write_omo_config = __esm(() => {
49399
- init_shared();
49400
49369
  init_config_context();
49401
49370
  init_ensure_config_directory_exists();
49402
49371
  init_generate_omo_config();
@@ -49499,10 +49468,10 @@ var init_opencode_binary = __esm(() => {
49499
49468
  });
49500
49469
 
49501
49470
  // src/cli/config-manager/detect-current-config.ts
49502
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
49471
+ import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
49503
49472
  function detectProvidersFromOmoConfig() {
49504
49473
  const omoConfigPath = getOmoConfigPath();
49505
- if (!existsSync10(omoConfigPath)) {
49474
+ if (!existsSync12(omoConfigPath)) {
49506
49475
  return {
49507
49476
  hasOpenAI: true,
49508
49477
  hasOpencodeZen: true,
@@ -49543,9 +49512,13 @@ function detectProvidersFromOmoConfig() {
49543
49512
  function isOurPlugin(plugin) {
49544
49513
  return plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`);
49545
49514
  }
49515
+ function findOurPluginEntry(plugins) {
49516
+ return plugins.find(isOurPlugin) ?? null;
49517
+ }
49546
49518
  function detectCurrentConfig() {
49547
49519
  const result = {
49548
49520
  isInstalled: false,
49521
+ installedVersion: null,
49549
49522
  hasClaude: true,
49550
49523
  isMax20: true,
49551
49524
  hasOpenAI: true,
@@ -49566,7 +49539,11 @@ function detectCurrentConfig() {
49566
49539
  }
49567
49540
  const openCodeConfig = parseResult.config;
49568
49541
  const plugins = openCodeConfig.plugin ?? [];
49569
- result.isInstalled = plugins.some(isOurPlugin);
49542
+ const ourPluginEntry = findOurPluginEntry(plugins);
49543
+ result.isInstalled = !!ourPluginEntry;
49544
+ if (ourPluginEntry) {
49545
+ result.installedVersion = extractVersionFromPluginEntry(ourPluginEntry);
49546
+ }
49570
49547
  if (!result.isInstalled) {
49571
49548
  return result;
49572
49549
  }
@@ -49588,10 +49565,10 @@ var init_detect_current_config = __esm(() => {
49588
49565
  });
49589
49566
 
49590
49567
  // src/cli/config-manager/bun-install.ts
49591
- import { existsSync as existsSync11 } from "fs";
49592
- import { join as join11 } from "path";
49568
+ import { existsSync as existsSync13 } from "fs";
49569
+ import { join as join12 } from "path";
49593
49570
  function getDefaultWorkspaceDir() {
49594
- return join11(getOpenCodeCacheDir(), "packages");
49571
+ return join12(getOpenCodeCacheDir(), "packages");
49595
49572
  }
49596
49573
  function readProcessOutput(stream) {
49597
49574
  if (!stream) {
@@ -49617,7 +49594,7 @@ async function runBunInstallWithDetails(options) {
49617
49594
  const outputMode = options?.outputMode ?? "pipe";
49618
49595
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
49619
49596
  const packageJsonPath = `${cacheDir}/package.json`;
49620
- if (!existsSync11(packageJsonPath)) {
49597
+ if (!existsSync13(packageJsonPath)) {
49621
49598
  return {
49622
49599
  success: false,
49623
49600
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -49693,6 +49670,7 @@ var init_config_manager = __esm(() => {
49693
49670
  init_opencode_binary();
49694
49671
  init_detect_current_config();
49695
49672
  init_bun_install();
49673
+ init_backup_config();
49696
49674
  });
49697
49675
 
49698
49676
  // node_modules/sisteransi/src/index.js
@@ -49770,15 +49748,15 @@ function getUserOpencodeConfig() {
49770
49748
  function getUserOpencodeConfigJsonc() {
49771
49749
  return path4.join(getUserConfigDir(), "opencode.jsonc");
49772
49750
  }
49773
- var PACKAGE_NAME = "oh-my-openagent", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
49751
+ var PACKAGE_NAME2 = "oh-my-opencode", NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON;
49774
49752
  var init_constants3 = __esm(() => {
49775
49753
  init_data_path();
49776
49754
  init_opencode_config_dir();
49777
- NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
49755
+ NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
49778
49756
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
49779
49757
  CACHE_DIR = path4.join(CACHE_ROOT_DIR, "packages");
49780
49758
  VERSION_FILE = path4.join(CACHE_ROOT_DIR, "version");
49781
- INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
49759
+ INSTALLED_PACKAGE_JSON = path4.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
49782
49760
  });
49783
49761
 
49784
49762
  // src/hooks/auto-update-checker/checker/config-paths.ts
@@ -49819,7 +49797,7 @@ function stripJsonComments(json3) {
49819
49797
  }
49820
49798
 
49821
49799
  // src/hooks/auto-update-checker/checker/local-dev-path.ts
49822
- import * as fs4 from "fs";
49800
+ import * as fs3 from "fs";
49823
49801
  import { fileURLToPath } from "url";
49824
49802
  function isLocalDevMode(directory) {
49825
49803
  return getLocalDevPath(directory) !== null;
@@ -49827,13 +49805,13 @@ function isLocalDevMode(directory) {
49827
49805
  function getLocalDevPath(directory) {
49828
49806
  for (const configPath of getConfigPaths(directory)) {
49829
49807
  try {
49830
- if (!fs4.existsSync(configPath))
49808
+ if (!fs3.existsSync(configPath))
49831
49809
  continue;
49832
- const content = fs4.readFileSync(configPath, "utf-8");
49810
+ const content = fs3.readFileSync(configPath, "utf-8");
49833
49811
  const config2 = JSON.parse(stripJsonComments(content));
49834
49812
  const plugins = config2.plugin ?? [];
49835
49813
  for (const entry of plugins) {
49836
- if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
49814
+ if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME2)) {
49837
49815
  try {
49838
49816
  return fileURLToPath(entry);
49839
49817
  } catch {
@@ -49853,19 +49831,19 @@ var init_local_dev_path = __esm(() => {
49853
49831
  });
49854
49832
 
49855
49833
  // src/hooks/auto-update-checker/checker/package-json-locator.ts
49856
- import * as fs5 from "fs";
49834
+ import * as fs4 from "fs";
49857
49835
  import * as path6 from "path";
49858
49836
  function findPackageJsonUp(startPath) {
49859
49837
  try {
49860
- const stat = fs5.statSync(startPath);
49838
+ const stat = fs4.statSync(startPath);
49861
49839
  let dir = stat.isDirectory() ? startPath : path6.dirname(startPath);
49862
49840
  for (let i2 = 0;i2 < 10; i2++) {
49863
49841
  const pkgPath = path6.join(dir, "package.json");
49864
- if (fs5.existsSync(pkgPath)) {
49842
+ if (fs4.existsSync(pkgPath)) {
49865
49843
  try {
49866
- const content = fs5.readFileSync(pkgPath, "utf-8");
49844
+ const content = fs4.readFileSync(pkgPath, "utf-8");
49867
49845
  const pkg = JSON.parse(content);
49868
- if (pkg.name === PACKAGE_NAME)
49846
+ if (pkg.name === PACKAGE_NAME2)
49869
49847
  return pkgPath;
49870
49848
  } catch {}
49871
49849
  }
@@ -49882,7 +49860,7 @@ var init_package_json_locator = __esm(() => {
49882
49860
  });
49883
49861
 
49884
49862
  // src/hooks/auto-update-checker/checker/local-dev-version.ts
49885
- import * as fs6 from "fs";
49863
+ import * as fs5 from "fs";
49886
49864
  function getLocalDevVersion(directory) {
49887
49865
  const localPath = getLocalDevPath(directory);
49888
49866
  if (!localPath)
@@ -49891,7 +49869,7 @@ function getLocalDevVersion(directory) {
49891
49869
  const pkgPath = findPackageJsonUp(localPath);
49892
49870
  if (!pkgPath)
49893
49871
  return null;
49894
- const content = fs6.readFileSync(pkgPath, "utf-8");
49872
+ const content = fs5.readFileSync(pkgPath, "utf-8");
49895
49873
  const pkg = JSON.parse(content);
49896
49874
  return pkg.version ?? null;
49897
49875
  } catch {
@@ -49904,23 +49882,25 @@ var init_local_dev_version = __esm(() => {
49904
49882
  });
49905
49883
 
49906
49884
  // src/hooks/auto-update-checker/checker/plugin-entry.ts
49907
- import * as fs7 from "fs";
49885
+ import * as fs6 from "fs";
49908
49886
  function findPluginEntry(directory) {
49909
49887
  for (const configPath of getConfigPaths(directory)) {
49910
49888
  try {
49911
- if (!fs7.existsSync(configPath))
49889
+ if (!fs6.existsSync(configPath))
49912
49890
  continue;
49913
- const content = fs7.readFileSync(configPath, "utf-8");
49891
+ const content = fs6.readFileSync(configPath, "utf-8");
49914
49892
  const config2 = JSON.parse(stripJsonComments(content));
49915
49893
  const plugins = config2.plugin ?? [];
49916
49894
  for (const entry of plugins) {
49917
- if (entry === PACKAGE_NAME) {
49918
- return { entry, isPinned: false, pinnedVersion: null, configPath };
49919
- }
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 };
49895
+ for (const pluginName of MATCH_PLUGIN_NAMES) {
49896
+ if (entry === pluginName) {
49897
+ return { entry, isPinned: false, pinnedVersion: null, configPath };
49898
+ }
49899
+ if (entry.startsWith(`${pluginName}@`)) {
49900
+ const pinnedVersion = entry.slice(pluginName.length + 1);
49901
+ const isPinned = EXACT_SEMVER_REGEX.test(pinnedVersion.trim());
49902
+ return { entry, isPinned, pinnedVersion, configPath };
49903
+ }
49924
49904
  }
49925
49905
  }
49926
49906
  } catch {
@@ -49929,21 +49909,23 @@ function findPluginEntry(directory) {
49929
49909
  }
49930
49910
  return null;
49931
49911
  }
49932
- var EXACT_SEMVER_REGEX;
49912
+ var EXACT_SEMVER_REGEX, MATCH_PLUGIN_NAMES;
49933
49913
  var init_plugin_entry = __esm(() => {
49934
49914
  init_constants3();
49935
49915
  init_config_paths();
49916
+ init_plugin_identity();
49936
49917
  EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/;
49918
+ MATCH_PLUGIN_NAMES = [PACKAGE_NAME2, PLUGIN_NAME, LEGACY_PLUGIN_NAME];
49937
49919
  });
49938
49920
 
49939
49921
  // src/hooks/auto-update-checker/checker/cached-version.ts
49940
- import * as fs8 from "fs";
49922
+ import * as fs7 from "fs";
49941
49923
  import * as path7 from "path";
49942
49924
  import { fileURLToPath as fileURLToPath2 } from "url";
49943
49925
  function getCachedVersion() {
49944
49926
  try {
49945
- if (fs8.existsSync(INSTALLED_PACKAGE_JSON)) {
49946
- const content = fs8.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
49927
+ if (fs7.existsSync(INSTALLED_PACKAGE_JSON)) {
49928
+ const content = fs7.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
49947
49929
  const pkg = JSON.parse(content);
49948
49930
  if (pkg.version)
49949
49931
  return pkg.version;
@@ -49953,7 +49935,7 @@ function getCachedVersion() {
49953
49935
  const currentDir = path7.dirname(fileURLToPath2(import.meta.url));
49954
49936
  const pkgPath = findPackageJsonUp(currentDir);
49955
49937
  if (pkgPath) {
49956
- const content = fs8.readFileSync(pkgPath, "utf-8");
49938
+ const content = fs7.readFileSync(pkgPath, "utf-8");
49957
49939
  const pkg = JSON.parse(content);
49958
49940
  if (pkg.version)
49959
49941
  return pkg.version;
@@ -49962,10 +49944,10 @@ function getCachedVersion() {
49962
49944
  log("[auto-update-checker] Failed to resolve version from current directory:", err);
49963
49945
  }
49964
49946
  try {
49965
- const execDir = path7.dirname(fs8.realpathSync(process.execPath));
49947
+ const execDir = path7.dirname(fs7.realpathSync(process.execPath));
49966
49948
  const pkgPath = findPackageJsonUp(execDir);
49967
49949
  if (pkgPath) {
49968
- const content = fs8.readFileSync(pkgPath, "utf-8");
49950
+ const content = fs7.readFileSync(pkgPath, "utf-8");
49969
49951
  const pkg = JSON.parse(content);
49970
49952
  if (pkg.version)
49971
49953
  return pkg.version;
@@ -49973,6 +49955,23 @@ function getCachedVersion() {
49973
49955
  } catch (err) {
49974
49956
  log("[auto-update-checker] Failed to resolve version from execPath:", err);
49975
49957
  }
49958
+ try {
49959
+ const currentFile = fileURLToPath2(import.meta.url);
49960
+ let dir = path7.dirname(currentFile);
49961
+ for (let i2 = 0;i2 < 10; i2++) {
49962
+ const pkgPath = path7.join(dir, "package.json");
49963
+ if (fs7.existsSync(pkgPath)) {
49964
+ const content = fs7.readFileSync(pkgPath, "utf-8");
49965
+ const pkg = JSON.parse(content);
49966
+ if (pkg.version)
49967
+ return pkg.version;
49968
+ }
49969
+ const parent = path7.dirname(dir);
49970
+ if (parent === dir)
49971
+ break;
49972
+ dir = parent;
49973
+ }
49974
+ } catch {}
49976
49975
  return null;
49977
49976
  }
49978
49977
  var init_cached_version = __esm(() => {
@@ -50107,11 +50106,11 @@ var init_check_for_update = __esm(() => {
50107
50106
 
50108
50107
  // src/hooks/auto-update-checker/checker/sync-package-json.ts
50109
50108
  import * as crypto from "crypto";
50110
- import * as fs9 from "fs";
50109
+ import * as fs8 from "fs";
50111
50110
  import * as path8 from "path";
50112
50111
  function safeUnlink(filePath) {
50113
50112
  try {
50114
- fs9.unlinkSync(filePath);
50113
+ fs8.unlinkSync(filePath);
50115
50114
  } catch (err) {
50116
50115
  log(`[auto-update-checker] Failed to cleanup temp file: ${filePath}`, err);
50117
50116
  }
@@ -50125,9 +50124,9 @@ function getIntentVersion(pluginInfo) {
50125
50124
  function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
50126
50125
  const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
50127
50126
  try {
50128
- fs9.mkdirSync(path8.dirname(cachePackageJsonPath), { recursive: true });
50129
- fs9.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
50130
- fs9.renameSync(tmpPath, cachePackageJsonPath);
50127
+ fs8.mkdirSync(path8.dirname(cachePackageJsonPath), { recursive: true });
50128
+ fs8.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
50129
+ fs8.renameSync(tmpPath, cachePackageJsonPath);
50131
50130
  return { synced: true, error: null };
50132
50131
  } catch (err) {
50133
50132
  log("[auto-update-checker] Failed to write cache package.json:", err);
@@ -50138,17 +50137,17 @@ function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
50138
50137
  function syncCachePackageJsonToIntent(pluginInfo) {
50139
50138
  const cachePackageJsonPath = path8.join(CACHE_DIR, "package.json");
50140
50139
  const intentVersion = getIntentVersion(pluginInfo);
50141
- if (!fs9.existsSync(cachePackageJsonPath)) {
50140
+ if (!fs8.existsSync(cachePackageJsonPath)) {
50142
50141
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
50143
50142
  return {
50144
- ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME]: intentVersion } }),
50143
+ ...writeCachePackageJson(cachePackageJsonPath, { dependencies: { [PACKAGE_NAME2]: intentVersion } }),
50145
50144
  message: `Created cache package.json with: ${intentVersion}`
50146
50145
  };
50147
50146
  }
50148
50147
  let content;
50149
50148
  let pkgJson;
50150
50149
  try {
50151
- content = fs9.readFileSync(cachePackageJsonPath, "utf-8");
50150
+ content = fs8.readFileSync(cachePackageJsonPath, "utf-8");
50152
50151
  } catch (err) {
50153
50152
  log("[auto-update-checker] Failed to read cache package.json:", err);
50154
50153
  return { synced: false, error: "parse_error", message: "Failed to read cache package.json" };
@@ -50159,21 +50158,21 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50159
50158
  log("[auto-update-checker] Failed to parse cache package.json:", err);
50160
50159
  return { synced: false, error: "parse_error", message: "Failed to parse cache package.json (malformed JSON)" };
50161
50160
  }
50162
- if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME]) {
50161
+ if (!pkgJson || !pkgJson.dependencies?.[PACKAGE_NAME2]) {
50163
50162
  log("[auto-update-checker] Plugin missing from cache package.json dependencies, adding dependency", { intentVersion });
50164
50163
  const nextPkgJson = {
50165
50164
  ...pkgJson ?? {},
50166
50165
  dependencies: {
50167
50166
  ...pkgJson?.dependencies ?? {},
50168
- [PACKAGE_NAME]: intentVersion
50167
+ [PACKAGE_NAME2]: intentVersion
50169
50168
  }
50170
50169
  };
50171
50170
  return {
50172
50171
  ...writeCachePackageJson(cachePackageJsonPath, nextPkgJson),
50173
- message: `Added ${PACKAGE_NAME}: ${intentVersion}`
50172
+ message: `Added ${PACKAGE_NAME2}: ${intentVersion}`
50174
50173
  };
50175
50174
  }
50176
- const currentVersion = pkgJson.dependencies[PACKAGE_NAME];
50175
+ const currentVersion = pkgJson.dependencies[PACKAGE_NAME2];
50177
50176
  if (currentVersion === intentVersion) {
50178
50177
  log("[auto-update-checker] Cache package.json already matches intent:", intentVersion);
50179
50178
  return { synced: false, error: null, message: `Already matches intent: ${intentVersion}` };
@@ -50185,7 +50184,7 @@ function syncCachePackageJsonToIntent(pluginInfo) {
50185
50184
  } else {
50186
50185
  log(`[auto-update-checker] Updating cache package.json: "${currentVersion}" \u2192 "${intentVersion}"`);
50187
50186
  }
50188
- pkgJson.dependencies[PACKAGE_NAME] = intentVersion;
50187
+ pkgJson.dependencies[PACKAGE_NAME2] = intentVersion;
50189
50188
  return {
50190
50189
  ...writeCachePackageJson(cachePackageJsonPath, pkgJson),
50191
50190
  message: `Updated: "${currentVersion}" \u2192 "${intentVersion}"`
@@ -50211,18 +50210,18 @@ var init_checker = __esm(() => {
50211
50210
  });
50212
50211
 
50213
50212
  // src/hooks/auto-update-checker/cache.ts
50214
- import * as fs10 from "fs";
50213
+ import * as fs9 from "fs";
50215
50214
  import * as path9 from "path";
50216
50215
  function stripTrailingCommas(json3) {
50217
50216
  return json3.replace(/,(\s*[}\]])/g, "$1");
50218
50217
  }
50219
50218
  function removeFromTextBunLock(lockPath, packageName) {
50220
50219
  try {
50221
- const content = fs10.readFileSync(lockPath, "utf-8");
50220
+ const content = fs9.readFileSync(lockPath, "utf-8");
50222
50221
  const lock = JSON.parse(stripTrailingCommas(content));
50223
50222
  if (lock.packages?.[packageName]) {
50224
50223
  delete lock.packages[packageName];
50225
- fs10.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
50224
+ fs9.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
50226
50225
  log(`[auto-update-checker] Removed from bun.lock: ${packageName}`);
50227
50226
  return true;
50228
50227
  }
@@ -50233,7 +50232,7 @@ function removeFromTextBunLock(lockPath, packageName) {
50233
50232
  }
50234
50233
  function deleteBinaryBunLock(lockPath) {
50235
50234
  try {
50236
- fs10.unlinkSync(lockPath);
50235
+ fs9.unlinkSync(lockPath);
50237
50236
  log(`[auto-update-checker] Removed bun.lockb to force re-resolution`);
50238
50237
  return true;
50239
50238
  } catch {
@@ -50243,15 +50242,15 @@ function deleteBinaryBunLock(lockPath) {
50243
50242
  function removeFromBunLock(packageName) {
50244
50243
  const textLockPath = path9.join(CACHE_DIR, "bun.lock");
50245
50244
  const binaryLockPath = path9.join(CACHE_DIR, "bun.lockb");
50246
- if (fs10.existsSync(textLockPath)) {
50245
+ if (fs9.existsSync(textLockPath)) {
50247
50246
  return removeFromTextBunLock(textLockPath, packageName);
50248
50247
  }
50249
- if (fs10.existsSync(binaryLockPath)) {
50248
+ if (fs9.existsSync(binaryLockPath)) {
50250
50249
  return deleteBinaryBunLock(binaryLockPath);
50251
50250
  }
50252
50251
  return false;
50253
50252
  }
50254
- function invalidatePackage(packageName = PACKAGE_NAME) {
50253
+ function invalidatePackage(packageName = PACKAGE_NAME2) {
50255
50254
  try {
50256
50255
  const userConfigDir = getUserConfigDir();
50257
50256
  const pkgDirs = [
@@ -50261,8 +50260,8 @@ function invalidatePackage(packageName = PACKAGE_NAME) {
50261
50260
  let packageRemoved = false;
50262
50261
  let lockRemoved = false;
50263
50262
  for (const pkgDir of pkgDirs) {
50264
- if (fs10.existsSync(pkgDir)) {
50265
- fs10.rmSync(pkgDir, { recursive: true, force: true });
50263
+ if (fs9.existsSync(pkgDir)) {
50264
+ fs9.rmSync(pkgDir, { recursive: true, force: true });
50266
50265
  log(`[auto-update-checker] Package removed: ${pkgDir}`);
50267
50266
  packageRemoved = true;
50268
50267
  }
@@ -50291,7 +50290,7 @@ var init_cache = __esm(() => {
50291
50290
  async function showUpdateAvailableToast(ctx, latestVersion, getToastMessage) {
50292
50291
  await ctx.client.tui.showToast({
50293
50292
  body: {
50294
- title: `OhMyOpenCode ${latestVersion}`,
50293
+ title: `EvilOMO ${latestVersion}`,
50295
50294
  message: getToastMessage(true, latestVersion),
50296
50295
  variant: "info",
50297
50296
  duration: 8000
@@ -50302,7 +50301,7 @@ async function showUpdateAvailableToast(ctx, latestVersion, getToastMessage) {
50302
50301
  async function showAutoUpdatedToast(ctx, oldVersion, newVersion) {
50303
50302
  await ctx.client.tui.showToast({
50304
50303
  body: {
50305
- title: "OhMyOpenCode Updated!",
50304
+ title: "EvilOMO Updated!",
50306
50305
  message: `v${oldVersion} \u2192 v${newVersion}
50307
50306
  Restart OpenCode to apply.`,
50308
50307
  variant: "success",
@@ -50316,8 +50315,8 @@ var init_update_toasts = __esm(() => {
50316
50315
  });
50317
50316
 
50318
50317
  // src/hooks/auto-update-checker/hook/background-update-check.ts
50319
- import { existsSync as existsSync22 } from "fs";
50320
- import { join as join23 } from "path";
50318
+ import { existsSync as existsSync24 } from "fs";
50319
+ import { join as join25 } from "path";
50321
50320
  function getCacheWorkspaceDir(deps) {
50322
50321
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
50323
50322
  }
@@ -50327,8 +50326,8 @@ function getPinnedVersionToastMessage(latestVersion) {
50327
50326
  function resolveActiveInstallWorkspace(deps) {
50328
50327
  const configPaths = deps.getOpenCodeConfigPaths({ binary: "opencode" });
50329
50328
  const cacheDir = getCacheWorkspaceDir(deps);
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");
50329
+ const configInstallPath = deps.join(configPaths.configDir, "node_modules", PACKAGE_NAME2, "package.json");
50330
+ const cacheInstallPath = deps.join(cacheDir, "node_modules", PACKAGE_NAME2, "package.json");
50332
50331
  if (deps.existsSync(configInstallPath)) {
50333
50332
  deps.log(`[auto-update-checker] Active workspace: config-dir (${configPaths.configDir})`);
50334
50333
  return configPaths.configDir;
@@ -50407,7 +50406,7 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
50407
50406
  await deps.showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
50408
50407
  return;
50409
50408
  }
50410
- deps.invalidatePackage(PACKAGE_NAME);
50409
+ deps.invalidatePackage(PACKAGE_NAME2);
50411
50410
  const activeWorkspace = resolveActiveInstallWorkspace(deps);
50412
50411
  const installSuccess = await runBunInstallSafe(activeWorkspace, deps);
50413
50412
  if (installSuccess) {
@@ -50435,8 +50434,8 @@ var init_background_update_check = __esm(() => {
50435
50434
  init_checker();
50436
50435
  init_update_toasts();
50437
50436
  defaultDeps = {
50438
- existsSync: existsSync22,
50439
- join: join23,
50437
+ existsSync: existsSync24,
50438
+ join: join25,
50440
50439
  runBunInstallWithDetails,
50441
50440
  log,
50442
50441
  getOpenCodeCacheDir,
@@ -50583,7 +50582,7 @@ async function showSpinnerToast(ctx, version2, message) {
50583
50582
  const spinner = SISYPHUS_SPINNER[i2 % SISYPHUS_SPINNER.length];
50584
50583
  await ctx.client.tui.showToast({
50585
50584
  body: {
50586
- title: `${spinner} OhMyOpenCode ${version2}`,
50585
+ title: `${spinner} EvilOMO ${version2}`,
50587
50586
  message,
50588
50587
  variant: "info",
50589
50588
  duration: frameInterval + 50
@@ -50716,7 +50715,7 @@ var {
50716
50715
  // package.json
50717
50716
  var package_default = {
50718
50717
  name: "evil-omo",
50719
- version: "3.15.3",
50718
+ version: "3.16.1",
50720
50719
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
50721
50720
  main: "./dist/index.js",
50722
50721
  types: "dist/index.d.ts",
@@ -50775,8 +50774,8 @@ var package_default = {
50775
50774
  "@clack/prompts": "^0.11.0",
50776
50775
  "@code-yeongyu/comment-checker": "^0.7.0",
50777
50776
  "@modelcontextprotocol/sdk": "^1.25.2",
50778
- "@opencode-ai/plugin": "^1.2.24",
50779
- "@opencode-ai/sdk": "^1.2.24",
50777
+ "@opencode-ai/plugin": "^1.4.0",
50778
+ "@opencode-ai/sdk": "^1.4.0",
50780
50779
  commander: "^14.0.2",
50781
50780
  "detect-libc": "^2.0.0",
50782
50781
  diff: "^8.0.3",
@@ -50785,7 +50784,7 @@ var package_default = {
50785
50784
  picocolors: "^1.1.1",
50786
50785
  picomatch: "^4.0.2",
50787
50786
  "vscode-jsonrpc": "^8.2.0",
50788
- zod: "^4.1.8"
50787
+ zod: "^4.3.0"
50789
50788
  },
50790
50789
  devDependencies: {
50791
50790
  "@types/js-yaml": "^4.0.9",
@@ -50794,21 +50793,19 @@ var package_default = {
50794
50793
  typescript: "^5.7.3"
50795
50794
  },
50796
50795
  optionalDependencies: {
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"
50808
- },
50809
- overrides: {
50810
- "@opencode-ai/sdk": "^1.2.24"
50796
+ "evil-omo-darwin-arm64": "3.16.0",
50797
+ "evil-omo-darwin-x64": "3.16.0",
50798
+ "evil-omo-darwin-x64-baseline": "3.16.0",
50799
+ "evil-omo-linux-x64": "3.16.0",
50800
+ "evil-omo-linux-x64-baseline": "3.16.0",
50801
+ "evil-omo-linux-arm64": "3.16.0",
50802
+ "evil-omo-linux-x64-musl": "3.16.0",
50803
+ "evil-omo-linux-x64-musl-baseline": "3.16.0",
50804
+ "evil-omo-linux-arm64-musl": "3.16.0",
50805
+ "evil-omo-windows-x64": "3.16.0",
50806
+ "evil-omo-windows-x64-baseline": "3.16.0"
50811
50807
  },
50808
+ overrides: {},
50812
50809
  trustedDependencies: [
50813
50810
  "@ast-grep/cli",
50814
50811
  "@ast-grep/napi",
@@ -50819,7 +50816,7 @@ var package_default = {
50819
50816
  // src/cli/cli-installer.ts
50820
50817
  init_shared();
50821
50818
  init_config_manager();
50822
- var import_picocolors2 = __toESM(require_picocolors(), 1);
50819
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
50823
50820
 
50824
50821
  // src/cli/install-validators.ts
50825
50822
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -50966,6 +50963,56 @@ function detectedToInitialValues(detected) {
50966
50963
  };
50967
50964
  }
50968
50965
 
50966
+ // src/cli/doctor/constants.ts
50967
+ init_shared();
50968
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
50969
+ var SYMBOLS2 = {
50970
+ check: import_picocolors2.default.green("\u2713"),
50971
+ cross: import_picocolors2.default.red("\u2717"),
50972
+ warn: import_picocolors2.default.yellow("\u26A0"),
50973
+ info: import_picocolors2.default.blue("\u2139"),
50974
+ arrow: import_picocolors2.default.cyan("\u2192"),
50975
+ bullet: import_picocolors2.default.dim("\u2022"),
50976
+ skip: import_picocolors2.default.dim("\u25CB")
50977
+ };
50978
+ var STATUS_COLORS = {
50979
+ pass: import_picocolors2.default.green,
50980
+ fail: import_picocolors2.default.red,
50981
+ warn: import_picocolors2.default.yellow,
50982
+ skip: import_picocolors2.default.dim
50983
+ };
50984
+ var CHECK_IDS = {
50985
+ SYSTEM: "system",
50986
+ CONFIG: "config",
50987
+ TOOLS: "tools",
50988
+ MODELS: "models"
50989
+ };
50990
+ var CHECK_NAMES = {
50991
+ [CHECK_IDS.SYSTEM]: "System",
50992
+ [CHECK_IDS.CONFIG]: "Configuration",
50993
+ [CHECK_IDS.TOOLS]: "Tools",
50994
+ [CHECK_IDS.MODELS]: "Models"
50995
+ };
50996
+ var EXIT_CODES = {
50997
+ SUCCESS: 0,
50998
+ FAILURE: 1
50999
+ };
51000
+ var MIN_OPENCODE_VERSION = "1.4.0";
51001
+ var PACKAGE_NAME = PLUGIN_NAME;
51002
+ var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
51003
+
51004
+ // src/cli/minimum-opencode-version.ts
51005
+ init_opencode_version();
51006
+ function getUnsupportedOpenCodeVersionMessage(openCodeVersion) {
51007
+ if (!openCodeVersion) {
51008
+ return null;
51009
+ }
51010
+ if (compareVersions(openCodeVersion, MIN_OPENCODE_VERSION) >= 0) {
51011
+ return null;
51012
+ }
51013
+ return `Detected OpenCode ${openCodeVersion}, but ${MIN_OPENCODE_VERSION}+ is required. Update OpenCode, then rerun the installer.`;
51014
+ }
51015
+
50969
51016
  // src/cli/cli-installer.ts
50970
51017
  async function runCliInstaller(args, version) {
50971
51018
  const validation = validateNonTuiArgs(args);
@@ -50993,6 +51040,11 @@ async function runCliInstaller(args, version) {
50993
51040
  printInfo("Visit https://opencode.ai/docs for installation instructions");
50994
51041
  } else {
50995
51042
  printSuccess(`OpenCode ${openCodeVersion ?? ""} detected`);
51043
+ const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion);
51044
+ if (unsupportedVersionMessage) {
51045
+ printWarning(unsupportedVersionMessage);
51046
+ return 1;
51047
+ }
50996
51048
  }
50997
51049
  if (isUpdate) {
50998
51050
  const initial = detectedToInitialValues(detected);
@@ -51005,47 +51057,37 @@ async function runCliInstaller(args, version) {
51005
51057
  printError(`Failed: ${pluginResult.error}`);
51006
51058
  return 1;
51007
51059
  }
51008
- printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors2.default.dim(pluginResult.configPath)}`);
51060
+ printSuccess(`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${import_picocolors3.default.dim(pluginResult.configPath)}`);
51009
51061
  printStep(step++, totalSteps, `Writing ${PLUGIN_NAME} configuration...`);
51010
51062
  const omoResult = writeOmoConfig(config);
51011
51063
  if (!omoResult.success) {
51012
51064
  printError(`Failed: ${omoResult.error}`);
51013
51065
  return 1;
51014
51066
  }
51015
- printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors2.default.dim(omoResult.configPath)}`);
51067
+ printSuccess(`Config written ${SYMBOLS.arrow} ${import_picocolors3.default.dim(omoResult.configPath)}`);
51016
51068
  printBox(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
51017
51069
  if (!config.hasClaude) {
51018
- console.log();
51019
- console.log(import_picocolors2.default.bgRed(import_picocolors2.default.white(import_picocolors2.default.bold(" CRITICAL WARNING "))));
51020
- console.log();
51021
- console.log(import_picocolors2.default.red(import_picocolors2.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
51022
- console.log(import_picocolors2.default.red(" Without Claude, you may experience significantly degraded performance:"));
51023
- console.log(import_picocolors2.default.dim(" \u2022 Reduced orchestration quality"));
51024
- console.log(import_picocolors2.default.dim(" \u2022 Weaker tool selection and delegation"));
51025
- console.log(import_picocolors2.default.dim(" \u2022 Less reliable task completion"));
51026
- console.log();
51027
- console.log(import_picocolors2.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
51028
- console.log();
51070
+ printInfo("Note: Sisyphus agent performs best with Claude Opus 4.5+. " + "Other models work but may have reduced orchestration quality.");
51029
51071
  }
51030
51072
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
51031
51073
  printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
51032
51074
  }
51033
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
51034
- console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
51075
+ console.log(`${SYMBOLS.star} ${import_picocolors3.default.bold(import_picocolors3.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
51076
+ console.log(` Run ${import_picocolors3.default.cyan("opencode")} to start!`);
51035
51077
  console.log();
51036
- printBox(`${import_picocolors2.default.bold("Pro Tip:")} Include ${import_picocolors2.default.cyan("ultrawork")} (or ${import_picocolors2.default.cyan("ulw")}) in your prompt.
51078
+ printBox(`${import_picocolors3.default.bold("Pro Tip:")} Include ${import_picocolors3.default.cyan("ultrawork")} (or ${import_picocolors3.default.cyan("ulw")}) in your prompt.
51037
51079
  ` + `All features work like magic-parallel agents, background tasks,
51038
51080
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51039
- console.log(`${SYMBOLS.star} ${import_picocolors2.default.yellow("If you found this helpful, consider starring the repo!")}`);
51040
- console.log(` ${import_picocolors2.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
51081
+ console.log(`${SYMBOLS.star} ${import_picocolors3.default.yellow("If you found this helpful, consider starring the repo!")}`);
51082
+ console.log(` ${import_picocolors3.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
51041
51083
  console.log();
51042
- console.log(import_picocolors2.default.dim("oMoMoMoMo... Enjoy!"));
51084
+ console.log(import_picocolors3.default.dim("oMoMoMoMo... Enjoy!"));
51043
51085
  console.log();
51044
51086
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
51045
- printBox(`Run ${import_picocolors2.default.cyan("opencode auth login")} and select your provider:
51046
- ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors2.default.gray("\u2192 Claude Pro/Max")}
51047
- ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors2.default.gray("\u2192 Gemini")}
51048
- ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors2.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
51087
+ printBox(`Run ${import_picocolors3.default.cyan("opencode auth login")} and select your provider:
51088
+ ` + (config.hasClaude ? ` ${SYMBOLS.bullet} Anthropic ${import_picocolors3.default.gray("\u2192 Claude Pro/Max")}
51089
+ ` : "") + (config.hasGemini ? ` ${SYMBOLS.bullet} Google ${import_picocolors3.default.gray("\u2192 Gemini")}
51090
+ ` : "") + (config.hasCopilot ? ` ${SYMBOLS.bullet} GitHub ${import_picocolors3.default.gray("\u2192 Copilot")}` : ""), "Authenticate Your Providers");
51049
51091
  }
51050
51092
  return 0;
51051
51093
  }
@@ -51440,7 +51482,7 @@ class LD extends x {
51440
51482
  }
51441
51483
 
51442
51484
  // node_modules/@clack/prompts/dist/index.mjs
51443
- var import_picocolors3 = __toESM(require_picocolors(), 1);
51485
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
51444
51486
  var import_sisteransi2 = __toESM(require_src(), 1);
51445
51487
  import y2 from "process";
51446
51488
  function ce() {
@@ -51473,13 +51515,13 @@ var b2 = (t) => {
51473
51515
  switch (t) {
51474
51516
  case "initial":
51475
51517
  case "active":
51476
- return import_picocolors3.default.cyan(le);
51518
+ return import_picocolors4.default.cyan(le);
51477
51519
  case "cancel":
51478
- return import_picocolors3.default.red(L2);
51520
+ return import_picocolors4.default.red(L2);
51479
51521
  case "error":
51480
- return import_picocolors3.default.yellow(W2);
51522
+ return import_picocolors4.default.yellow(W2);
51481
51523
  case "submit":
51482
- return import_picocolors3.default.green(C);
51524
+ return import_picocolors4.default.green(C);
51483
51525
  }
51484
51526
  };
51485
51527
  var G2 = (t) => {
@@ -51489,7 +51531,7 @@ var G2 = (t) => {
51489
51531
  const $2 = a < r2.length && l2 > 0, g2 = a < r2.length && l2 + a < r2.length;
51490
51532
  return r2.slice(l2, l2 + a).map((p2, v, f) => {
51491
51533
  const j2 = v === 0 && $2, E = v === f.length - 1 && g2;
51492
- return j2 || E ? import_picocolors3.default.dim("...") : i2(p2, v + l2 === n);
51534
+ return j2 || E ? import_picocolors4.default.dim("...") : i2(p2, v + l2 === n);
51493
51535
  });
51494
51536
  };
51495
51537
  var ve = (t) => {
@@ -51497,29 +51539,29 @@ var ve = (t) => {
51497
51539
  const s = r2.label ?? String(r2.value);
51498
51540
  switch (i2) {
51499
51541
  case "selected":
51500
- return `${import_picocolors3.default.dim(s)}`;
51542
+ return `${import_picocolors4.default.dim(s)}`;
51501
51543
  case "active":
51502
- return `${import_picocolors3.default.green(k2)} ${s} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}`;
51544
+ return `${import_picocolors4.default.green(k2)} ${s} ${r2.hint ? import_picocolors4.default.dim(`(${r2.hint})`) : ""}`;
51503
51545
  case "cancelled":
51504
- return `${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}`;
51546
+ return `${import_picocolors4.default.strikethrough(import_picocolors4.default.dim(s))}`;
51505
51547
  default:
51506
- return `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(s)}`;
51548
+ return `${import_picocolors4.default.dim(P2)} ${import_picocolors4.default.dim(s)}`;
51507
51549
  }
51508
51550
  };
51509
51551
  return new LD({ options: t.options, initialValue: t.initialValue, render() {
51510
- const r2 = `${import_picocolors3.default.gray(o)}
51552
+ const r2 = `${import_picocolors4.default.gray(o)}
51511
51553
  ${b2(this.state)} ${t.message}
51512
51554
  `;
51513
51555
  switch (this.state) {
51514
51556
  case "submit":
51515
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
51557
+ return `${r2}${import_picocolors4.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
51516
51558
  case "cancel":
51517
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
51518
- ${import_picocolors3.default.gray(o)}`;
51559
+ return `${r2}${import_picocolors4.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
51560
+ ${import_picocolors4.default.gray(o)}`;
51519
51561
  default:
51520
- return `${r2}${import_picocolors3.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i2, s) => n(i2, s ? "active" : "inactive") }).join(`
51521
- ${import_picocolors3.default.cyan(o)} `)}
51522
- ${import_picocolors3.default.cyan(d2)}
51562
+ return `${r2}${import_picocolors4.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i2, s) => n(i2, s ? "active" : "inactive") }).join(`
51563
+ ${import_picocolors4.default.cyan(o)} `)}
51564
+ ${import_picocolors4.default.cyan(d2)}
51523
51565
  `;
51524
51566
  }
51525
51567
  } }).prompt();
@@ -51531,53 +51573,53 @@ ${t}
51531
51573
  `), i2 = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
51532
51574
  const $2 = S2(l2);
51533
51575
  return $2.length > a ? $2.length : a;
51534
- }, 0), i2) + 2, c = r2.map((a) => `${import_picocolors3.default.gray(o)} ${import_picocolors3.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors3.default.gray(o)}`).join(`
51576
+ }, 0), i2) + 2, c = r2.map((a) => `${import_picocolors4.default.gray(o)} ${import_picocolors4.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors4.default.gray(o)}`).join(`
51535
51577
  `);
51536
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51537
- ${import_picocolors3.default.green(C)} ${import_picocolors3.default.reset(n)} ${import_picocolors3.default.gray(_2.repeat(Math.max(s - i2 - 1, 1)) + me)}
51578
+ process.stdout.write(`${import_picocolors4.default.gray(o)}
51579
+ ${import_picocolors4.default.green(C)} ${import_picocolors4.default.reset(n)} ${import_picocolors4.default.gray(_2.repeat(Math.max(s - i2 - 1, 1)) + me)}
51538
51580
  ${c}
51539
- ${import_picocolors3.default.gray(de + _2.repeat(s + 2) + pe)}
51581
+ ${import_picocolors4.default.gray(de + _2.repeat(s + 2) + pe)}
51540
51582
  `);
51541
51583
  };
51542
51584
  var xe = (t = "") => {
51543
- process.stdout.write(`${import_picocolors3.default.gray(d2)} ${import_picocolors3.default.red(t)}
51585
+ process.stdout.write(`${import_picocolors4.default.gray(d2)} ${import_picocolors4.default.red(t)}
51544
51586
 
51545
51587
  `);
51546
51588
  };
51547
51589
  var Ie = (t = "") => {
51548
- process.stdout.write(`${import_picocolors3.default.gray(ue)} ${t}
51590
+ process.stdout.write(`${import_picocolors4.default.gray(ue)} ${t}
51549
51591
  `);
51550
51592
  };
51551
51593
  var Se = (t = "") => {
51552
- process.stdout.write(`${import_picocolors3.default.gray(o)}
51553
- ${import_picocolors3.default.gray(d2)} ${t}
51594
+ process.stdout.write(`${import_picocolors4.default.gray(o)}
51595
+ ${import_picocolors4.default.gray(d2)} ${t}
51554
51596
 
51555
51597
  `);
51556
51598
  };
51557
- var M2 = { message: (t = "", { symbol: n = import_picocolors3.default.gray(o) } = {}) => {
51558
- const r2 = [`${import_picocolors3.default.gray(o)}`];
51599
+ var M2 = { message: (t = "", { symbol: n = import_picocolors4.default.gray(o) } = {}) => {
51600
+ const r2 = [`${import_picocolors4.default.gray(o)}`];
51559
51601
  if (t) {
51560
51602
  const [i2, ...s] = t.split(`
51561
51603
  `);
51562
- r2.push(`${n} ${i2}`, ...s.map((c) => `${import_picocolors3.default.gray(o)} ${c}`));
51604
+ r2.push(`${n} ${i2}`, ...s.map((c) => `${import_picocolors4.default.gray(o)} ${c}`));
51563
51605
  }
51564
51606
  process.stdout.write(`${r2.join(`
51565
51607
  `)}
51566
51608
  `);
51567
51609
  }, info: (t) => {
51568
- M2.message(t, { symbol: import_picocolors3.default.blue(q) });
51610
+ M2.message(t, { symbol: import_picocolors4.default.blue(q) });
51569
51611
  }, success: (t) => {
51570
- M2.message(t, { symbol: import_picocolors3.default.green(D) });
51612
+ M2.message(t, { symbol: import_picocolors4.default.green(D) });
51571
51613
  }, step: (t) => {
51572
- M2.message(t, { symbol: import_picocolors3.default.green(C) });
51614
+ M2.message(t, { symbol: import_picocolors4.default.green(C) });
51573
51615
  }, warn: (t) => {
51574
- M2.message(t, { symbol: import_picocolors3.default.yellow(U) });
51616
+ M2.message(t, { symbol: import_picocolors4.default.yellow(U) });
51575
51617
  }, warning: (t) => {
51576
51618
  M2.warn(t);
51577
51619
  }, error: (t) => {
51578
- M2.message(t, { symbol: import_picocolors3.default.red(K2) });
51620
+ M2.message(t, { symbol: import_picocolors4.default.red(K2) });
51579
51621
  } };
51580
- var J2 = `${import_picocolors3.default.gray(o)} `;
51622
+ var J2 = `${import_picocolors4.default.gray(o)} `;
51581
51623
  var Y2 = ({ indicator: t = "dots" } = {}) => {
51582
51624
  const n = V2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], r2 = V2 ? 80 : 120, i2 = process.env.CI === "true";
51583
51625
  let s, c, a = false, l2 = "", $2, g2 = performance.now();
@@ -51600,14 +51642,14 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51600
51642
  const h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
51601
51643
  return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
51602
51644
  }, H = (m2 = "") => {
51603
- a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors3.default.gray(o)}
51645
+ a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors4.default.gray(o)}
51604
51646
  `);
51605
51647
  let h2 = 0, w2 = 0;
51606
51648
  j2(), c = setInterval(() => {
51607
51649
  if (i2 && l2 === $2)
51608
51650
  return;
51609
51651
  B2(), $2 = l2;
51610
- const I2 = import_picocolors3.default.magenta(n[h2]);
51652
+ const I2 = import_picocolors4.default.magenta(n[h2]);
51611
51653
  if (i2)
51612
51654
  process.stdout.write(`${I2} ${l2}...`);
51613
51655
  else if (t === "timer")
@@ -51620,7 +51662,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51620
51662
  }, r2);
51621
51663
  }, N2 = (m2 = "", h2 = 0) => {
51622
51664
  a = false, clearInterval(c), B2();
51623
- const w2 = h2 === 0 ? import_picocolors3.default.green(C) : h2 === 1 ? import_picocolors3.default.red(L2) : import_picocolors3.default.red(W2);
51665
+ const w2 = h2 === 0 ? import_picocolors4.default.green(C) : h2 === 1 ? import_picocolors4.default.red(L2) : import_picocolors4.default.red(W2);
51624
51666
  l2 = R2(m2 ?? l2), t === "timer" ? process.stdout.write(`${w2} ${l2} ${O2(g2)}
51625
51667
  `) : process.stdout.write(`${w2} ${l2}
51626
51668
  `), E(), s();
@@ -51633,7 +51675,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
51633
51675
  // src/cli/tui-installer.ts
51634
51676
  init_shared();
51635
51677
  init_config_manager();
51636
- var import_picocolors4 = __toESM(require_picocolors(), 1);
51678
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
51637
51679
 
51638
51680
  // src/cli/tui-install-prompts.ts
51639
51681
  async function selectOrCancel(params) {
@@ -51754,7 +51796,7 @@ async function runTuiInstaller(args, version) {
51754
51796
  }
51755
51797
  const detected = detectCurrentConfig();
51756
51798
  const isUpdate = detected.isInstalled;
51757
- Ie(import_picocolors4.default.bgMagenta(import_picocolors4.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
51799
+ Ie(import_picocolors5.default.bgMagenta(import_picocolors5.default.white(isUpdate ? " oMoMoMoMo... Update " : " oMoMoMoMo... ")));
51758
51800
  if (isUpdate) {
51759
51801
  const initial = detectedToInitialValues(detected);
51760
51802
  M2.info(`Existing configuration detected: Claude=${initial.claude}, Gemini=${initial.gemini}`);
@@ -51764,11 +51806,17 @@ async function runTuiInstaller(args, version) {
51764
51806
  const installed = await isOpenCodeInstalled();
51765
51807
  const openCodeVersion = await getOpenCodeVersion2();
51766
51808
  if (!installed) {
51767
- spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
51809
+ spinner.stop(`OpenCode binary not found ${import_picocolors5.default.yellow("[!]")}`);
51768
51810
  M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
51769
51811
  Me("Visit https://opencode.ai/docs for installation instructions", "Installation Guide");
51770
51812
  } else {
51771
- spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${import_picocolors4.default.green("[OK]")}`);
51813
+ spinner.stop(`OpenCode ${openCodeVersion ?? "installed"} ${import_picocolors5.default.green("[OK]")}`);
51814
+ const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion);
51815
+ if (unsupportedVersionMessage) {
51816
+ M2.warn(unsupportedVersionMessage);
51817
+ Se(import_picocolors5.default.red("Installation blocked."));
51818
+ return 1;
51819
+ }
51772
51820
  }
51773
51821
  const config = await promptInstallConfig(detected);
51774
51822
  if (!config)
@@ -51777,55 +51825,46 @@ async function runTuiInstaller(args, version) {
51777
51825
  const pluginResult = await addPluginToOpenCodeConfig(version);
51778
51826
  if (!pluginResult.success) {
51779
51827
  spinner.stop(`Failed to add plugin: ${pluginResult.error}`);
51780
- Se(import_picocolors4.default.red("Installation failed."));
51828
+ Se(import_picocolors5.default.red("Installation failed."));
51781
51829
  return 1;
51782
51830
  }
51783
- spinner.stop(`Plugin added to ${import_picocolors4.default.cyan(pluginResult.configPath)}`);
51831
+ spinner.stop(`Plugin added to ${import_picocolors5.default.cyan(pluginResult.configPath)}`);
51784
51832
  spinner.start(`Writing ${PLUGIN_NAME} configuration`);
51785
51833
  const omoResult = writeOmoConfig(config);
51786
51834
  if (!omoResult.success) {
51787
51835
  spinner.stop(`Failed to write config: ${omoResult.error}`);
51788
- Se(import_picocolors4.default.red("Installation failed."));
51836
+ Se(import_picocolors5.default.red("Installation failed."));
51789
51837
  return 1;
51790
51838
  }
51791
- spinner.stop(`Config written to ${import_picocolors4.default.cyan(omoResult.configPath)}`);
51839
+ spinner.stop(`Config written to ${import_picocolors5.default.cyan(omoResult.configPath)}`);
51792
51840
  if (!config.hasClaude) {
51793
- console.log();
51794
- console.log(import_picocolors4.default.bgRed(import_picocolors4.default.white(import_picocolors4.default.bold(" CRITICAL WARNING "))));
51795
- console.log();
51796
- console.log(import_picocolors4.default.red(import_picocolors4.default.bold(" Sisyphus agent is STRONGLY optimized for Claude Opus 4.5.")));
51797
- console.log(import_picocolors4.default.red(" Without Claude, you may experience significantly degraded performance:"));
51798
- console.log(import_picocolors4.default.dim(" \u2022 Reduced orchestration quality"));
51799
- console.log(import_picocolors4.default.dim(" \u2022 Weaker tool selection and delegation"));
51800
- console.log(import_picocolors4.default.dim(" \u2022 Less reliable task completion"));
51801
- console.log();
51802
- console.log(import_picocolors4.default.yellow(" Consider subscribing to Claude Pro/Max for the best experience."));
51803
- console.log();
51841
+ M2.info(`${import_picocolors5.default.bold("Note:")} Sisyphus agent performs best with Claude Opus 4.5+.
51842
+ ` + `Other models work but may have reduced orchestration quality.`);
51804
51843
  }
51805
51844
  if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
51806
51845
  M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
51807
51846
  }
51808
51847
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
51809
- M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51810
- M2.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
51811
- Me(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
51848
+ M2.success(import_picocolors5.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
51849
+ M2.message(`Run ${import_picocolors5.default.cyan("opencode")} to start!`);
51850
+ Me(`Include ${import_picocolors5.default.cyan("ultrawork")} (or ${import_picocolors5.default.cyan("ulw")}) in your prompt.
51812
51851
  ` + `All features work like magic-parallel agents, background tasks,
51813
51852
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
51814
- M2.message(`${import_picocolors4.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51815
- M2.message(` ${import_picocolors4.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
51816
- Se(import_picocolors4.default.green("oMoMoMoMo... Enjoy!"));
51853
+ M2.message(`${import_picocolors5.default.yellow("\u2605")} If you found this helpful, consider starring the repo!`);
51854
+ M2.message(` ${import_picocolors5.default.dim("gh api --silent --method PUT /user/starred/D4ch1au/evil-oh-my-openagent >/dev/null 2>&1 || true")}`);
51855
+ Se(import_picocolors5.default.green("oMoMoMoMo... Enjoy!"));
51817
51856
  if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
51818
51857
  const providers = [];
51819
51858
  if (config.hasClaude)
51820
- providers.push(`Anthropic ${import_picocolors4.default.gray("\u2192 Claude Pro/Max")}`);
51859
+ providers.push(`Anthropic ${import_picocolors5.default.gray("\u2192 Claude Pro/Max")}`);
51821
51860
  if (config.hasGemini)
51822
- providers.push(`Google ${import_picocolors4.default.gray("\u2192 Gemini")}`);
51861
+ providers.push(`Google ${import_picocolors5.default.gray("\u2192 Gemini")}`);
51823
51862
  if (config.hasCopilot)
51824
- providers.push(`GitHub ${import_picocolors4.default.gray("\u2192 Copilot")}`);
51863
+ providers.push(`GitHub ${import_picocolors5.default.gray("\u2192 Copilot")}`);
51825
51864
  console.log();
51826
- console.log(import_picocolors4.default.bold("Authenticate Your Providers"));
51865
+ console.log(import_picocolors5.default.bold("Authenticate Your Providers"));
51827
51866
  console.log();
51828
- console.log(` Run ${import_picocolors4.default.cyan("opencode auth login")} and select:`);
51867
+ console.log(` Run ${import_picocolors5.default.cyan("opencode auth login")} and select:`);
51829
51868
  for (const provider of providers) {
51830
51869
  console.log(` ${SYMBOLS.bullet} ${provider}`);
51831
51870
  }
@@ -51841,7 +51880,7 @@ async function install(args) {
51841
51880
  }
51842
51881
 
51843
51882
  // src/cli/run/runner.ts
51844
- var import_picocolors14 = __toESM(require_picocolors(), 1);
51883
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
51845
51884
 
51846
51885
  // src/cli/run/event-state.ts
51847
51886
  function createEventState() {
@@ -51875,7 +51914,7 @@ function createEventState() {
51875
51914
  };
51876
51915
  }
51877
51916
  // src/cli/run/event-formatting.ts
51878
- var import_picocolors5 = __toESM(require_picocolors(), 1);
51917
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
51879
51918
  function serializeError(error) {
51880
51919
  if (!error)
51881
51920
  return "Unknown error";
@@ -51919,10 +51958,10 @@ function getSessionTag(ctx, payload) {
51919
51958
  const sessionID = props?.sessionID ?? props?.sessionId ?? info?.sessionID ?? info?.sessionId ?? part?.sessionID ?? part?.sessionId;
51920
51959
  const isMainSession = sessionID === ctx.sessionID;
51921
51960
  if (isMainSession)
51922
- return import_picocolors5.default.green("[MAIN]");
51961
+ return import_picocolors6.default.green("[MAIN]");
51923
51962
  if (sessionID)
51924
- return import_picocolors5.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
51925
- return import_picocolors5.default.dim("[system]");
51963
+ return import_picocolors6.default.yellow(`[${String(sessionID).slice(0, 8)}]`);
51964
+ return import_picocolors6.default.dim("[system]");
51926
51965
  }
51927
51966
  function logEventVerbose(ctx, payload) {
51928
51967
  const sessionTag = getSessionTag(ctx, payload);
@@ -51931,7 +51970,7 @@ function logEventVerbose(ctx, payload) {
51931
51970
  case "session.idle":
51932
51971
  case "session.status": {
51933
51972
  const status = props?.status?.type ?? "idle";
51934
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}: ${status}`));
51973
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}: ${status}`));
51935
51974
  break;
51936
51975
  }
51937
51976
  case "message.part.updated": {
@@ -51939,10 +51978,10 @@ function logEventVerbose(ctx, payload) {
51939
51978
  const part = partProps?.part;
51940
51979
  if (part?.type === "tool") {
51941
51980
  const status = part.state?.status ?? "unknown";
51942
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
51981
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
51943
51982
  } else if (part?.type === "text" && part.text) {
51944
51983
  const preview = part.text.slice(0, 80).replace(/\n/g, "\\n");
51945
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
51984
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
51946
51985
  }
51947
51986
  break;
51948
51987
  }
@@ -51951,7 +51990,7 @@ function logEventVerbose(ctx, payload) {
51951
51990
  const field = deltaProps?.field ?? "unknown";
51952
51991
  const delta = deltaProps?.delta ?? "";
51953
51992
  const preview = delta.slice(0, 80).replace(/\n/g, "\\n");
51954
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part.delta (${field}): "${preview}${delta.length > 80 ? "..." : ""}"`));
51993
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.part.delta (${field}): "${preview}${delta.length > 80 ? "..." : ""}"`));
51955
51994
  break;
51956
51995
  }
51957
51996
  case "message.updated": {
@@ -51960,7 +51999,7 @@ function logEventVerbose(ctx, payload) {
51960
51999
  const model = msgProps?.info?.modelID;
51961
52000
  const agent = msgProps?.info?.agent;
51962
52001
  const details = [role, agent, model].filter(Boolean).join(", ");
51963
- console.error(import_picocolors5.default.dim(`${sessionTag} message.updated (${details})`));
52002
+ console.error(import_picocolors6.default.dim(`${sessionTag} message.updated (${details})`));
51964
52003
  break;
51965
52004
  }
51966
52005
  case "tool.execute": {
@@ -51978,32 +52017,32 @@ function logEventVerbose(ctx, payload) {
51978
52017
  }
51979
52018
  }
51980
52019
  const inputPreview = inputStr.slice(0, 150);
51981
- console.error(import_picocolors5.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors5.default.bold(toolName)}`));
51982
- console.error(import_picocolors5.default.dim(` input: ${inputPreview}${inputStr.length >= 150 ? "..." : ""}`));
52020
+ console.error(import_picocolors6.default.cyan(`${sessionTag} TOOL.EXECUTE: ${import_picocolors6.default.bold(toolName)}`));
52021
+ console.error(import_picocolors6.default.dim(` input: ${inputPreview}${inputStr.length >= 150 ? "..." : ""}`));
51983
52022
  break;
51984
52023
  }
51985
52024
  case "tool.result": {
51986
52025
  const resultProps = props;
51987
52026
  const output = resultProps?.output ?? "";
51988
52027
  const preview = output.slice(0, 200).replace(/\n/g, "\\n");
51989
- console.error(import_picocolors5.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
52028
+ console.error(import_picocolors6.default.green(`${sessionTag} TOOL.RESULT: "${preview}${output.length > 200 ? "..." : ""}"`));
51990
52029
  break;
51991
52030
  }
51992
52031
  case "session.error": {
51993
52032
  const errorProps = props;
51994
52033
  const errorMsg = serializeError(errorProps?.error);
51995
- console.error(import_picocolors5.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
52034
+ console.error(import_picocolors6.default.red(`${sessionTag} SESSION.ERROR: ${errorMsg}`));
51996
52035
  break;
51997
52036
  }
51998
52037
  default:
51999
- console.error(import_picocolors5.default.dim(`${sessionTag} ${payload.type}`));
52038
+ console.error(import_picocolors6.default.dim(`${sessionTag} ${payload.type}`));
52000
52039
  }
52001
52040
  }
52002
52041
  // src/cli/run/event-stream-processor.ts
52003
- var import_picocolors8 = __toESM(require_picocolors(), 1);
52042
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
52004
52043
 
52005
52044
  // src/cli/run/event-handlers.ts
52006
- var import_picocolors7 = __toESM(require_picocolors(), 1);
52045
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
52007
52046
 
52008
52047
  // src/cli/run/tool-input-preview.ts
52009
52048
  function formatToolHeader(toolName, input) {
@@ -52139,14 +52178,14 @@ var displayChars = {
52139
52178
  };
52140
52179
 
52141
52180
  // src/cli/run/output-renderer.ts
52142
- var import_picocolors6 = __toESM(require_picocolors(), 1);
52181
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
52143
52182
  function renderAgentHeader(agent, model, variant, agentColorsByName) {
52144
52183
  if (!agent && !model)
52145
52184
  return;
52146
- const agentLabel = agent ? import_picocolors6.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52185
+ const agentLabel = agent ? import_picocolors7.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
52147
52186
  const modelBase = model ?? "";
52148
52187
  const variantSuffix = variant ? ` (${variant})` : "";
52149
- const modelLabel = model ? import_picocolors6.default.dim(`${modelBase}${variantSuffix}`) : "";
52188
+ const modelLabel = model ? import_picocolors7.default.dim(`${modelBase}${variantSuffix}`) : "";
52150
52189
  process.stdout.write(`
52151
52190
  `);
52152
52191
  if (modelLabel) {
@@ -52154,7 +52193,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52154
52193
  `);
52155
52194
  }
52156
52195
  if (agentLabel) {
52157
- process.stdout.write(` ${import_picocolors6.default.dim("\u2514\u2500")} ${agentLabel}
52196
+ process.stdout.write(` ${import_picocolors7.default.dim("\u2514\u2500")} ${agentLabel}
52158
52197
  `);
52159
52198
  }
52160
52199
  process.stdout.write(`
@@ -52162,7 +52201,7 @@ function renderAgentHeader(agent, model, variant, agentColorsByName) {
52162
52201
  }
52163
52202
  function openThinkBlock() {
52164
52203
  process.stdout.write(`
52165
- ${import_picocolors6.default.dim("\u2503 Thinking:")} `);
52204
+ ${import_picocolors7.default.dim("\u2503 Thinking:")} `);
52166
52205
  }
52167
52206
  function closeThinkBlock() {
52168
52207
  process.stdout.write(`
@@ -52196,10 +52235,10 @@ function writePaddedText(text, atLineStart) {
52196
52235
  }
52197
52236
  function colorizeWithProfileColor(text, hexColor) {
52198
52237
  if (!hexColor)
52199
- return import_picocolors6.default.magenta(text);
52238
+ return import_picocolors7.default.magenta(text);
52200
52239
  const rgb = parseHexColor(hexColor);
52201
52240
  if (!rgb)
52202
- return import_picocolors6.default.magenta(text);
52241
+ return import_picocolors7.default.magenta(text);
52203
52242
  const [r2, g2, b3] = rgb;
52204
52243
  return `\x1B[38;2;${r2};${g2};${b3}m${text}\x1B[39m`;
52205
52244
  }
@@ -52239,7 +52278,7 @@ function renderCompletionMetaLine(state, messageID) {
52239
52278
  const agent = state.currentAgent ?? "assistant";
52240
52279
  const model = state.currentModel ?? "unknown-model";
52241
52280
  const variant = state.currentVariant ? ` (${state.currentVariant})` : "";
52242
- process.stdout.write(import_picocolors7.default.dim(`
52281
+ process.stdout.write(import_picocolors8.default.dim(`
52243
52282
  ${displayChars.treeEnd} ${agent} \xB7 ${model}${variant} \xB7 ${elapsedSec}s
52244
52283
  `));
52245
52284
  state.completionMetaPrintedByMessageId[messageID] = true;
@@ -52273,7 +52312,7 @@ function handleSessionError(ctx, payload, state) {
52273
52312
  if (getSessionId(props) === ctx.sessionID) {
52274
52313
  state.mainSessionError = true;
52275
52314
  state.lastError = serializeError(props?.error);
52276
- console.error(import_picocolors7.default.red(`
52315
+ console.error(import_picocolors8.default.red(`
52277
52316
  [session.error] ${state.lastError}`));
52278
52317
  }
52279
52318
  }
@@ -52301,7 +52340,7 @@ function handleMessagePartUpdated(ctx, payload, state) {
52301
52340
  const newText = reasoningText.slice(state.lastReasoningText.length);
52302
52341
  if (newText) {
52303
52342
  const padded = writePaddedText(newText, state.thinkingAtLineStart);
52304
- process.stdout.write(import_picocolors7.default.dim(padded.output));
52343
+ process.stdout.write(import_picocolors8.default.dim(padded.output));
52305
52344
  state.thinkingAtLineStart = padded.atLineStart;
52306
52345
  state.hasReceivedMeaningfulWork = true;
52307
52346
  }
@@ -52348,7 +52387,7 @@ function handleMessagePartDelta(ctx, payload, state) {
52348
52387
  if (partType === "reasoning") {
52349
52388
  ensureThinkBlockOpen(state);
52350
52389
  const padded2 = writePaddedText(delta, state.thinkingAtLineStart);
52351
- process.stdout.write(import_picocolors7.default.dim(padded2.output));
52390
+ process.stdout.write(import_picocolors8.default.dim(padded2.output));
52352
52391
  state.thinkingAtLineStart = padded2.atLineStart;
52353
52392
  state.lastReasoningText += delta;
52354
52393
  state.hasReceivedMeaningfulWork = true;
@@ -52369,10 +52408,10 @@ function handleToolPart(_ctx, part, state) {
52369
52408
  return;
52370
52409
  state.currentTool = toolName;
52371
52410
  const header = formatToolHeader(toolName, part.state?.input ?? {});
52372
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
52411
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52373
52412
  state.hasReceivedMeaningfulWork = true;
52374
52413
  process.stdout.write(`
52375
- ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
52414
+ ${import_picocolors8.default.cyan(header.icon)} ${import_picocolors8.default.bold(header.title)}${suffix}
52376
52415
  `);
52377
52416
  }
52378
52417
  if (status === "completed" || status === "error") {
@@ -52380,10 +52419,10 @@ function handleToolPart(_ctx, part, state) {
52380
52419
  return;
52381
52420
  const output = part.state?.output || "";
52382
52421
  if (output.trim()) {
52383
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
52422
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52384
52423
  `));
52385
52424
  const padded = writePaddedText(output, true);
52386
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52425
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52387
52426
  process.stdout.write(`
52388
52427
  `);
52389
52428
  }
@@ -52445,10 +52484,10 @@ function handleToolExecute(ctx, payload, state) {
52445
52484
  const toolName = props?.name || "unknown";
52446
52485
  state.currentTool = toolName;
52447
52486
  const header = formatToolHeader(toolName, props?.input ?? {});
52448
- const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
52487
+ const suffix = header.description ? ` ${import_picocolors8.default.dim(header.description)}` : "";
52449
52488
  state.hasReceivedMeaningfulWork = true;
52450
52489
  process.stdout.write(`
52451
- ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
52490
+ ${import_picocolors8.default.cyan(header.icon)} ${import_picocolors8.default.bold(header.title)}${suffix}
52452
52491
  `);
52453
52492
  }
52454
52493
  function handleToolResult(ctx, payload, state) {
@@ -52462,10 +52501,10 @@ function handleToolResult(ctx, payload, state) {
52462
52501
  return;
52463
52502
  const output = props?.output || "";
52464
52503
  if (output.trim()) {
52465
- process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
52504
+ process.stdout.write(import_picocolors8.default.dim(` ${displayChars.treeEnd} output
52466
52505
  `));
52467
52506
  const padded = writePaddedText(output, true);
52468
- process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52507
+ process.stdout.write(import_picocolors8.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
52469
52508
  process.stdout.write(`
52470
52509
  `);
52471
52510
  }
@@ -52514,7 +52553,7 @@ async function processEvents(ctx, stream, state) {
52514
52553
  const payload = event;
52515
52554
  if (!payload?.type) {
52516
52555
  if (ctx.verbose) {
52517
- console.error(import_picocolors8.default.dim(`[event] no type: ${JSON.stringify(event)}`));
52556
+ console.error(import_picocolors9.default.dim(`[event] no type: ${JSON.stringify(event)}`));
52518
52557
  }
52519
52558
  continue;
52520
52559
  }
@@ -52532,12 +52571,12 @@ async function processEvents(ctx, stream, state) {
52532
52571
  handleToolResult(ctx, payload, state);
52533
52572
  handleTuiToast(ctx, payload, state);
52534
52573
  } catch (err) {
52535
- console.error(import_picocolors8.default.red(`[event error] ${err}`));
52574
+ console.error(import_picocolors9.default.red(`[event error] ${err}`));
52536
52575
  }
52537
52576
  }
52538
52577
  }
52539
52578
  // src/plugin-config.ts
52540
- import * as fs3 from "fs";
52579
+ import * as fs2 from "fs";
52541
52580
  import * as path3 from "path";
52542
52581
 
52543
52582
  // node_modules/zod/v4/classic/external.js
@@ -66643,10 +66682,9 @@ function parseConfigPartially(rawConfig) {
66643
66682
  }
66644
66683
  function loadConfigFromPath(configPath, _ctx) {
66645
66684
  try {
66646
- if (fs3.existsSync(configPath)) {
66647
- const content = fs3.readFileSync(configPath, "utf-8");
66685
+ if (fs2.existsSync(configPath)) {
66686
+ const content = fs2.readFileSync(configPath, "utf-8");
66648
66687
  const rawConfig = parseJsonc(content);
66649
- migrateConfigFile(configPath, rawConfig);
66650
66688
  const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
66651
66689
  if (result.success) {
66652
66690
  log(`Config loaded from ${configPath}`, { agents: result.data.agents });
@@ -68190,11 +68228,11 @@ async function createOpencode(options) {
68190
68228
 
68191
68229
  // src/cli/run/server-connection.ts
68192
68230
  init_port_utils();
68193
- var import_picocolors9 = __toESM(require_picocolors(), 1);
68231
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
68194
68232
 
68195
68233
  // src/cli/run/opencode-binary-resolver.ts
68196
68234
  init_spawn_with_windows_hide();
68197
- import { delimiter, dirname, join as join13 } from "path";
68235
+ import { delimiter, dirname as dirname2, join as join14 } from "path";
68198
68236
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
68199
68237
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
68200
68238
  function getCommandCandidates(platform) {
@@ -68217,7 +68255,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
68217
68255
  }
68218
68256
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
68219
68257
  for (const command of commandCandidates) {
68220
- addCandidate(join13(entry, command));
68258
+ addCandidate(join14(entry, command));
68221
68259
  }
68222
68260
  }
68223
68261
  return candidates;
@@ -68244,7 +68282,7 @@ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = can
68244
68282
  return null;
68245
68283
  }
68246
68284
  function buildPathWithBinaryFirst(pathEnv, binaryPath) {
68247
- const preferredDir = dirname(binaryPath);
68285
+ const preferredDir = dirname2(binaryPath);
68248
68286
  const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
68249
68287
  return [preferredDir, ...existing].join(delimiter);
68250
68288
  }
@@ -68278,13 +68316,13 @@ function isPortRangeExhausted(error48) {
68278
68316
  async function startServer(options) {
68279
68317
  const { signal, port } = options;
68280
68318
  const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
68281
- console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
68319
+ console.log(import_picocolors10.default.dim("Server listening at"), import_picocolors10.default.cyan(server2.url));
68282
68320
  return { client: client3, cleanup: () => server2.close() };
68283
68321
  }
68284
68322
  async function createServerConnection(options) {
68285
68323
  const { port, attach, signal } = options;
68286
68324
  if (attach !== undefined) {
68287
- console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
68325
+ console.log(import_picocolors10.default.dim("Attaching to existing server at"), import_picocolors10.default.cyan(attach));
68288
68326
  const client3 = createOpencodeClient({ baseUrl: attach });
68289
68327
  return { client: client3, cleanup: () => {} };
68290
68328
  }
@@ -68294,7 +68332,7 @@ async function createServerConnection(options) {
68294
68332
  }
68295
68333
  const available = await isPortAvailable(port, "127.0.0.1");
68296
68334
  if (available) {
68297
- console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(port.toString()));
68335
+ console.log(import_picocolors10.default.dim("Starting server on port"), import_picocolors10.default.cyan(port.toString()));
68298
68336
  try {
68299
68337
  return await startServer({ signal, port });
68300
68338
  } catch (error48) {
@@ -68305,12 +68343,12 @@ async function createServerConnection(options) {
68305
68343
  if (stillAvailable) {
68306
68344
  throw error48;
68307
68345
  }
68308
- console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("became occupied, attaching to existing server"));
68346
+ console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("became occupied, attaching to existing server"));
68309
68347
  const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68310
68348
  return { client: client4, cleanup: () => {} };
68311
68349
  }
68312
68350
  }
68313
- console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("is occupied, attaching to existing server"));
68351
+ console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("is occupied, attaching to existing server"));
68314
68352
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
68315
68353
  return { client: client3, cleanup: () => {} };
68316
68354
  }
@@ -68328,14 +68366,14 @@ async function createServerConnection(options) {
68328
68366
  if (defaultPortIsAvailable) {
68329
68367
  throw error48;
68330
68368
  }
68331
- console.log(import_picocolors9.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors9.default.cyan(DEFAULT_SERVER_PORT.toString()));
68369
+ console.log(import_picocolors10.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors10.default.cyan(DEFAULT_SERVER_PORT.toString()));
68332
68370
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${DEFAULT_SERVER_PORT}` });
68333
68371
  return { client: client3, cleanup: () => {} };
68334
68372
  }
68335
68373
  if (wasAutoSelected) {
68336
- console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
68374
+ console.log(import_picocolors10.default.dim("Auto-selected port"), import_picocolors10.default.cyan(selectedPort.toString()));
68337
68375
  } else {
68338
- console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(selectedPort.toString()));
68376
+ console.log(import_picocolors10.default.dim("Starting server on port"), import_picocolors10.default.cyan(selectedPort.toString()));
68339
68377
  }
68340
68378
  try {
68341
68379
  return await startServer({ signal, port: selectedPort });
@@ -68344,13 +68382,13 @@ async function createServerConnection(options) {
68344
68382
  throw error48;
68345
68383
  }
68346
68384
  const { port: retryPort } = await getAvailableServerPort(selectedPort + 1, "127.0.0.1");
68347
- console.log(import_picocolors9.default.dim("Retrying server start on port"), import_picocolors9.default.cyan(retryPort.toString()));
68385
+ console.log(import_picocolors10.default.dim("Retrying server start on port"), import_picocolors10.default.cyan(retryPort.toString()));
68348
68386
  return await startServer({ signal, port: retryPort });
68349
68387
  }
68350
68388
  }
68351
68389
 
68352
68390
  // src/cli/run/session-resolver.ts
68353
- var import_picocolors10 = __toESM(require_picocolors(), 1);
68391
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
68354
68392
  var SESSION_CREATE_MAX_RETRIES = 3;
68355
68393
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
68356
68394
  async function resolveSession(options) {
@@ -68376,11 +68414,11 @@ async function resolveSession(options) {
68376
68414
  query: { directory }
68377
68415
  });
68378
68416
  if (res.error) {
68379
- console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
68380
- console.error(import_picocolors10.default.dim(` Error: ${serializeError(res.error)}`));
68417
+ console.error(import_picocolors11.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
68418
+ console.error(import_picocolors11.default.dim(` Error: ${serializeError(res.error)}`));
68381
68419
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68382
68420
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68383
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
68421
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68384
68422
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68385
68423
  }
68386
68424
  continue;
@@ -68388,10 +68426,10 @@ async function resolveSession(options) {
68388
68426
  if (res.data?.id) {
68389
68427
  return res.data.id;
68390
68428
  }
68391
- console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
68429
+ console.error(import_picocolors11.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
68392
68430
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
68393
68431
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
68394
- console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
68432
+ console.log(import_picocolors11.default.dim(` Retrying in ${delay}ms...`));
68395
68433
  await new Promise((resolve2) => setTimeout(resolve2, delay));
68396
68434
  }
68397
68435
  }
@@ -68509,7 +68547,7 @@ async function executeOnCompleteHook(options) {
68509
68547
 
68510
68548
  // src/cli/run/agent-resolver.ts
68511
68549
  init_agent_display_names();
68512
- var import_picocolors11 = __toESM(require_picocolors(), 1);
68550
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
68513
68551
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
68514
68552
  var DEFAULT_AGENT = "sisyphus";
68515
68553
  var normalizeAgentName = (agent) => {
@@ -68554,10 +68592,10 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
68554
68592
  const fallbackName = getAgentDisplayName(fallback);
68555
68593
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
68556
68594
  if (fallbackDisabled) {
68557
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
68595
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
68558
68596
  return fallbackName;
68559
68597
  }
68560
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
68598
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
68561
68599
  return fallbackName;
68562
68600
  }
68563
68601
  return resolved.resolvedName;
@@ -68588,11 +68626,11 @@ function resolveRunModel(modelString) {
68588
68626
  }
68589
68627
 
68590
68628
  // src/cli/run/poll-for-completion.ts
68591
- var import_picocolors13 = __toESM(require_picocolors(), 1);
68629
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
68592
68630
 
68593
68631
  // src/cli/run/completion.ts
68594
68632
  init_shared();
68595
- var import_picocolors12 = __toESM(require_picocolors(), 1);
68633
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
68596
68634
  // src/features/boulder-state/constants.ts
68597
68635
  var BOULDER_DIR = ".sisyphus";
68598
68636
  var BOULDER_FILE = "boulder.json";
@@ -68600,15 +68638,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
68600
68638
  var NOTEPAD_DIR = "notepads";
68601
68639
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
68602
68640
  // src/features/boulder-state/storage.ts
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";
68641
+ import { existsSync as existsSync15, readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
68642
+ import { dirname as dirname3, join as join15, basename } from "path";
68605
68643
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
68606
68644
  function getBoulderFilePath(directory) {
68607
- return join14(directory, BOULDER_DIR, BOULDER_FILE);
68645
+ return join15(directory, BOULDER_DIR, BOULDER_FILE);
68608
68646
  }
68609
68647
  function readBoulderState(directory) {
68610
68648
  const filePath = getBoulderFilePath(directory);
68611
- if (!existsSync13(filePath)) {
68649
+ if (!existsSync15(filePath)) {
68612
68650
  return null;
68613
68651
  }
68614
68652
  try {
@@ -68637,30 +68675,83 @@ function readBoulderState(directory) {
68637
68675
  return null;
68638
68676
  }
68639
68677
  }
68678
+ var TODO_HEADING_PATTERN = /^##\s+TODOs\b/i;
68679
+ var FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wave\b/i;
68680
+ var SECOND_LEVEL_HEADING_PATTERN = /^##\s+/;
68681
+ var UNCHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
68682
+ var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
68683
+ var TODO_TASK_PATTERN = /^\d+\.\s+/;
68684
+ var FINAL_WAVE_TASK_PATTERN = /^F\d+\.\s+/i;
68640
68685
  function getPlanProgress(planPath) {
68641
- if (!existsSync13(planPath)) {
68686
+ if (!existsSync15(planPath)) {
68642
68687
  return { total: 0, completed: 0, isComplete: true };
68643
68688
  }
68644
68689
  try {
68645
68690
  const content = readFileSync9(planPath, "utf-8");
68646
- const uncheckedMatches = content.match(/^\s*[-*]\s*\[\s*\]/gm) || [];
68647
- const checkedMatches = content.match(/^\s*[-*]\s*\[[xX]\]/gm) || [];
68648
- const total = uncheckedMatches.length + checkedMatches.length;
68649
- const completed = checkedMatches.length;
68650
- return {
68651
- total,
68652
- completed,
68653
- isComplete: total > 0 && completed === total
68654
- };
68691
+ const lines = content.split(/\r?\n/);
68692
+ const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN.test(line) || FINAL_VERIFICATION_HEADING_PATTERN.test(line));
68693
+ if (hasStructuredSections) {
68694
+ return getStructuredPlanProgress(lines);
68695
+ }
68696
+ return getSimplePlanProgress(content);
68655
68697
  } catch {
68656
68698
  return { total: 0, completed: 0, isComplete: true };
68657
68699
  }
68658
68700
  }
68701
+ function getStructuredPlanProgress(lines) {
68702
+ let section = "other";
68703
+ let total = 0;
68704
+ let completed = 0;
68705
+ for (const line of lines) {
68706
+ if (SECOND_LEVEL_HEADING_PATTERN.test(line)) {
68707
+ section = TODO_HEADING_PATTERN.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN.test(line) ? "final-wave" : "other";
68708
+ continue;
68709
+ }
68710
+ if (section !== "todo" && section !== "final-wave") {
68711
+ continue;
68712
+ }
68713
+ const checkedMatch = line.match(CHECKED_CHECKBOX_PATTERN);
68714
+ const uncheckedMatch = checkedMatch ? null : line.match(UNCHECKED_CHECKBOX_PATTERN);
68715
+ const match = checkedMatch ?? uncheckedMatch;
68716
+ if (!match) {
68717
+ continue;
68718
+ }
68719
+ if (match[1].length > 0) {
68720
+ continue;
68721
+ }
68722
+ const taskBody = match[2].trim();
68723
+ const labelPattern = section === "todo" ? TODO_TASK_PATTERN : FINAL_WAVE_TASK_PATTERN;
68724
+ if (!labelPattern.test(taskBody)) {
68725
+ continue;
68726
+ }
68727
+ total++;
68728
+ if (checkedMatch) {
68729
+ completed++;
68730
+ }
68731
+ }
68732
+ return {
68733
+ total,
68734
+ completed,
68735
+ isComplete: total > 0 && completed === total
68736
+ };
68737
+ }
68738
+ function getSimplePlanProgress(content) {
68739
+ const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
68740
+ const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
68741
+ const total = uncheckedMatches.length + checkedMatches.length;
68742
+ const completed = checkedMatches.length;
68743
+ return {
68744
+ total,
68745
+ completed,
68746
+ isComplete: total > 0 && completed === total
68747
+ };
68748
+ }
68659
68749
  // src/features/claude-code-session-state/state.ts
68660
68750
  init_agent_display_names();
68661
68751
  var subagentSessions = new Set;
68662
68752
  var syncSubagentSessions = new Set;
68663
68753
  var registeredAgentNames = new Set;
68754
+ var registeredAgentAliases = new Map;
68664
68755
  var sessionAgentMap = new Map;
68665
68756
  function getSessionAgent(sessionID) {
68666
68757
  return sessionAgentMap.get(sessionID);
@@ -68668,14 +68759,14 @@ function getSessionAgent(sessionID) {
68668
68759
  // src/features/run-continuation-state/constants.ts
68669
68760
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
68670
68761
  // src/features/run-continuation-state/storage.ts
68671
- import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync6 } from "fs";
68672
- import { join as join15 } from "path";
68762
+ import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync5 } from "fs";
68763
+ import { join as join16 } from "path";
68673
68764
  function getMarkerPath(directory, sessionID) {
68674
- return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68765
+ return join16(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
68675
68766
  }
68676
68767
  function readContinuationMarker(directory, sessionID) {
68677
68768
  const markerPath = getMarkerPath(directory, sessionID);
68678
- if (!existsSync14(markerPath))
68769
+ if (!existsSync16(markerPath))
68679
68770
  return null;
68680
68771
  try {
68681
68772
  const raw = readFileSync10(markerPath, "utf-8");
@@ -68738,28 +68829,32 @@ async function isSessionInBoulderLineage(input) {
68738
68829
 
68739
68830
  // src/hooks/atlas/session-last-agent.ts
68740
68831
  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
- }
68832
+ init_compaction_marker();
68833
+ import { readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
68834
+ import { join as join17 } from "path";
68746
68835
  function getLastAgentFromMessageDir(messageDir) {
68747
68836
  try {
68748
- const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
68837
+ const messages = readdirSync4(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
68749
68838
  try {
68750
- const content = readFileSync11(join16(messageDir, fileName), "utf-8");
68839
+ const content = readFileSync11(join17(messageDir, fileName), "utf-8");
68751
68840
  const parsed = JSON.parse(content);
68752
68841
  return {
68753
68842
  fileName,
68843
+ id: parsed.id,
68754
68844
  agent: parsed.agent,
68755
68845
  createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
68756
68846
  };
68757
68847
  } catch {
68758
68848
  return null;
68759
68849
  }
68760
- }).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
68850
+ }).filter((message) => message !== null).sort((left, right) => (right?.createdAt ?? 0) - (left?.createdAt ?? 0) || (right?.fileName ?? "").localeCompare(left?.fileName ?? ""));
68761
68851
  for (const message of messages) {
68762
- if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
68852
+ if (!message)
68853
+ continue;
68854
+ if (isCompactionMessage({ agent: message.agent }) || hasCompactionPartInStorage(message?.id)) {
68855
+ continue;
68856
+ }
68857
+ if (typeof message.agent === "string") {
68763
68858
  return message.agent.toLowerCase();
68764
68859
  }
68765
68860
  }
@@ -68785,8 +68880,11 @@ async function getLastAgentFromSession(sessionID, client3) {
68785
68880
  return rightId.localeCompare(leftId);
68786
68881
  });
68787
68882
  for (const message of messages) {
68883
+ if (isCompactionMessage(message)) {
68884
+ continue;
68885
+ }
68788
68886
  const agent = message.info?.agent;
68789
- if (typeof agent === "string" && !isCompactionAgent(agent)) {
68887
+ if (typeof agent === "string") {
68790
68888
  return agent.toLowerCase();
68791
68889
  }
68792
68890
  }
@@ -68806,8 +68904,8 @@ init_agent_display_names();
68806
68904
 
68807
68905
  // src/hooks/ralph-loop/storage.ts
68808
68906
  init_frontmatter();
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";
68907
+ import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync6, unlinkSync, mkdirSync as mkdirSync7 } from "fs";
68908
+ import { dirname as dirname4, join as join18 } from "path";
68811
68909
 
68812
68910
  // src/hooks/ralph-loop/constants.ts
68813
68911
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -68816,11 +68914,11 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
68816
68914
 
68817
68915
  // src/hooks/ralph-loop/storage.ts
68818
68916
  function getStateFilePath(directory, customPath) {
68819
- return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
68917
+ return customPath ? join18(directory, customPath) : join18(directory, DEFAULT_STATE_FILE);
68820
68918
  }
68821
68919
  function readState(directory, customPath) {
68822
68920
  const filePath = getStateFilePath(directory, customPath);
68823
- if (!existsSync15(filePath)) {
68921
+ if (!existsSync17(filePath)) {
68824
68922
  return null;
68825
68923
  }
68826
68924
  try {
@@ -68948,7 +69046,7 @@ async function checkCompletionConditions(ctx) {
68948
69046
  }
68949
69047
  return true;
68950
69048
  } catch (err) {
68951
- console.error(import_picocolors12.default.red(`[completion] API error: ${err}`));
69049
+ console.error(import_picocolors13.default.red(`[completion] API error: ${err}`));
68952
69050
  return false;
68953
69051
  }
68954
69052
  }
@@ -69009,7 +69107,7 @@ function logWaiting(ctx, message) {
69009
69107
  if (!ctx.verbose) {
69010
69108
  return;
69011
69109
  }
69012
- console.log(import_picocolors12.default.dim(` Waiting: ${message}`));
69110
+ console.log(import_picocolors13.default.dim(` Waiting: ${message}`));
69013
69111
  }
69014
69112
 
69015
69113
  // src/cli/run/poll-for-completion.ts
@@ -69040,10 +69138,10 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
69040
69138
  if (eventState.mainSessionError) {
69041
69139
  errorCycleCount++;
69042
69140
  if (errorCycleCount >= ERROR_GRACE_CYCLES) {
69043
- console.error(import_picocolors13.default.red(`
69141
+ console.error(import_picocolors14.default.red(`
69044
69142
 
69045
69143
  Session ended with error: ${eventState.lastError}`));
69046
- console.error(import_picocolors13.default.yellow("Check if todos were completed before the error."));
69144
+ console.error(import_picocolors14.default.yellow("Check if todos were completed before the error."));
69047
69145
  return 1;
69048
69146
  }
69049
69147
  continue;
@@ -69054,7 +69152,7 @@ Session ended with error: ${eventState.lastError}`));
69054
69152
  if (eventState.lastEventTimestamp !== null) {
69055
69153
  const timeSinceLastEvent = Date.now() - eventState.lastEventTimestamp;
69056
69154
  if (timeSinceLastEvent > eventWatchdogMs) {
69057
- console.log(import_picocolors13.default.yellow(`
69155
+ console.log(import_picocolors14.default.yellow(`
69058
69156
  No events for ${Math.round(timeSinceLastEvent / 1000)}s, verifying session status...`));
69059
69157
  mainSessionStatus = await getMainSessionStatus(ctx);
69060
69158
  if (mainSessionStatus === "idle") {
@@ -69103,7 +69201,7 @@ Session ended with error: ${eventState.lastError}`));
69103
69201
  const hasActiveWork = hasActiveChildren || hasActiveTodos;
69104
69202
  if (hasActiveWork) {
69105
69203
  eventState.hasReceivedMeaningfulWork = true;
69106
- console.log(import_picocolors13.default.yellow(`
69204
+ console.log(import_picocolors14.default.yellow(`
69107
69205
  No meaningful work events for ${Math.round(secondaryMeaningfulWorkTimeoutMs / 1000)}s but session has active work - assuming in progress`));
69108
69206
  }
69109
69207
  }
@@ -69123,7 +69221,7 @@ Session ended with error: ${eventState.lastError}`));
69123
69221
  }
69124
69222
  consecutiveCompleteChecks++;
69125
69223
  if (consecutiveCompleteChecks >= requiredConsecutive) {
69126
- console.log(import_picocolors13.default.green(`
69224
+ console.log(import_picocolors14.default.green(`
69127
69225
 
69128
69226
  All tasks completed.`));
69129
69227
  return 0;
@@ -69292,7 +69390,7 @@ async function run(options) {
69292
69390
  };
69293
69391
  const restoreInput = suppressRunInput();
69294
69392
  const handleSigint = () => {
69295
- console.log(import_picocolors14.default.yellow(`
69393
+ console.log(import_picocolors15.default.yellow(`
69296
69394
  Interrupted. Shutting down...`));
69297
69395
  restoreInput();
69298
69396
  cleanup();
@@ -69305,9 +69403,9 @@ Interrupted. Shutting down...`));
69305
69403
  sessionId: options.sessionId,
69306
69404
  directory
69307
69405
  });
69308
- console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
69406
+ console.log(import_picocolors15.default.dim(`Session: ${sessionID}`));
69309
69407
  if (resolvedModel) {
69310
- console.log(import_picocolors14.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
69408
+ console.log(import_picocolors15.default.dim(`Model: ${resolvedModel.providerID}/${resolvedModel.modelID}`));
69311
69409
  }
69312
69410
  const ctx = {
69313
69411
  client: client3,
@@ -69370,7 +69468,7 @@ Interrupted. Shutting down...`));
69370
69468
  if (err instanceof Error && err.name === "AbortError") {
69371
69469
  return 130;
69372
69470
  }
69373
- console.error(import_picocolors14.default.red(`Error: ${serializeError(err)}`));
69471
+ console.error(import_picocolors15.default.red(`Error: ${serializeError(err)}`));
69374
69472
  return 1;
69375
69473
  } finally {
69376
69474
  timestampOutput?.restore();
@@ -69380,53 +69478,53 @@ Interrupted. Shutting down...`));
69380
69478
  init_checker();
69381
69479
 
69382
69480
  // src/cli/get-local-version/formatter.ts
69383
- var import_picocolors15 = __toESM(require_picocolors(), 1);
69384
- var SYMBOLS2 = {
69385
- check: import_picocolors15.default.green("[OK]"),
69386
- cross: import_picocolors15.default.red("[X]"),
69387
- arrow: import_picocolors15.default.cyan("->"),
69388
- info: import_picocolors15.default.blue("[i]"),
69389
- warn: import_picocolors15.default.yellow("[!]"),
69390
- pin: import_picocolors15.default.magenta("[PINNED]"),
69391
- dev: import_picocolors15.default.cyan("[DEV]")
69481
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
69482
+ var SYMBOLS3 = {
69483
+ check: import_picocolors16.default.green("[OK]"),
69484
+ cross: import_picocolors16.default.red("[X]"),
69485
+ arrow: import_picocolors16.default.cyan("->"),
69486
+ info: import_picocolors16.default.blue("[i]"),
69487
+ warn: import_picocolors16.default.yellow("[!]"),
69488
+ pin: import_picocolors16.default.magenta("[PINNED]"),
69489
+ dev: import_picocolors16.default.cyan("[DEV]")
69392
69490
  };
69393
69491
  function formatVersionOutput(info) {
69394
69492
  const lines = [];
69395
69493
  lines.push("");
69396
- lines.push(import_picocolors15.default.bold(import_picocolors15.default.white("evil-omo Version Information")));
69397
- lines.push(import_picocolors15.default.dim("\u2500".repeat(50)));
69494
+ lines.push(import_picocolors16.default.bold(import_picocolors16.default.white("evil-omo Version Information")));
69495
+ lines.push(import_picocolors16.default.dim("\u2500".repeat(50)));
69398
69496
  lines.push("");
69399
69497
  if (info.currentVersion) {
69400
- lines.push(` Current Version: ${import_picocolors15.default.cyan(info.currentVersion)}`);
69498
+ lines.push(` Current Version: ${import_picocolors16.default.cyan(info.currentVersion)}`);
69401
69499
  } else {
69402
- lines.push(` Current Version: ${import_picocolors15.default.dim("unknown")}`);
69500
+ lines.push(` Current Version: ${import_picocolors16.default.dim("unknown")}`);
69403
69501
  }
69404
69502
  if (!info.isLocalDev && info.latestVersion) {
69405
- lines.push(` Latest Version: ${import_picocolors15.default.cyan(info.latestVersion)}`);
69503
+ lines.push(` Latest Version: ${import_picocolors16.default.cyan(info.latestVersion)}`);
69406
69504
  }
69407
69505
  lines.push("");
69408
69506
  switch (info.status) {
69409
69507
  case "up-to-date":
69410
- lines.push(` ${SYMBOLS2.check} ${import_picocolors15.default.green("You're up to date!")}`);
69508
+ lines.push(` ${SYMBOLS3.check} ${import_picocolors16.default.green("You're up to date!")}`);
69411
69509
  break;
69412
69510
  case "outdated":
69413
- lines.push(` ${SYMBOLS2.warn} ${import_picocolors15.default.yellow("Update available")}`);
69414
- lines.push(` ${import_picocolors15.default.dim("Run:")} ${import_picocolors15.default.cyan("cd ~/.config/opencode && bun update evil-omo")}`);
69511
+ lines.push(` ${SYMBOLS3.warn} ${import_picocolors16.default.yellow("Update available")}`);
69512
+ lines.push(` ${import_picocolors16.default.dim("Run:")} ${import_picocolors16.default.cyan("cd ~/.config/opencode && bun update evil-omo")}`);
69415
69513
  break;
69416
69514
  case "local-dev":
69417
- lines.push(` ${SYMBOLS2.dev} ${import_picocolors15.default.cyan("Running in local development mode")}`);
69418
- lines.push(` ${import_picocolors15.default.dim("Using file:// protocol from config")}`);
69515
+ lines.push(` ${SYMBOLS3.dev} ${import_picocolors16.default.cyan("Running in local development mode")}`);
69516
+ lines.push(` ${import_picocolors16.default.dim("Using file:// protocol from config")}`);
69419
69517
  break;
69420
69518
  case "pinned":
69421
- lines.push(` ${SYMBOLS2.pin} ${import_picocolors15.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
69422
- lines.push(` ${import_picocolors15.default.dim("Update check skipped for pinned versions")}`);
69519
+ lines.push(` ${SYMBOLS3.pin} ${import_picocolors16.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
69520
+ lines.push(` ${import_picocolors16.default.dim("Update check skipped for pinned versions")}`);
69423
69521
  break;
69424
69522
  case "error":
69425
- lines.push(` ${SYMBOLS2.cross} ${import_picocolors15.default.red("Unable to check for updates")}`);
69426
- lines.push(` ${import_picocolors15.default.dim("Network error or npm registry unavailable")}`);
69523
+ lines.push(` ${SYMBOLS3.cross} ${import_picocolors16.default.red("Unable to check for updates")}`);
69524
+ lines.push(` ${import_picocolors16.default.dim("Network error or npm registry unavailable")}`);
69427
69525
  break;
69428
69526
  case "unknown":
69429
- lines.push(` ${SYMBOLS2.info} ${import_picocolors15.default.yellow("Version information unavailable")}`);
69527
+ lines.push(` ${SYMBOLS3.info} ${import_picocolors16.default.yellow("Version information unavailable")}`);
69430
69528
  break;
69431
69529
  }
69432
69530
  lines.push("");
@@ -69525,69 +69623,31 @@ async function getLocalVersion(options = {}) {
69525
69623
  return 1;
69526
69624
  }
69527
69625
  }
69528
- // src/cli/doctor/constants.ts
69529
- init_shared();
69530
- var import_picocolors16 = __toESM(require_picocolors(), 1);
69531
- var SYMBOLS3 = {
69532
- check: import_picocolors16.default.green("\u2713"),
69533
- cross: import_picocolors16.default.red("\u2717"),
69534
- warn: import_picocolors16.default.yellow("\u26A0"),
69535
- info: import_picocolors16.default.blue("\u2139"),
69536
- arrow: import_picocolors16.default.cyan("\u2192"),
69537
- bullet: import_picocolors16.default.dim("\u2022"),
69538
- skip: import_picocolors16.default.dim("\u25CB")
69539
- };
69540
- var STATUS_COLORS = {
69541
- pass: import_picocolors16.default.green,
69542
- fail: import_picocolors16.default.red,
69543
- warn: import_picocolors16.default.yellow,
69544
- skip: import_picocolors16.default.dim
69545
- };
69546
- var CHECK_IDS = {
69547
- SYSTEM: "system",
69548
- CONFIG: "config",
69549
- TOOLS: "tools",
69550
- MODELS: "models"
69551
- };
69552
- var CHECK_NAMES = {
69553
- [CHECK_IDS.SYSTEM]: "System",
69554
- [CHECK_IDS.CONFIG]: "Configuration",
69555
- [CHECK_IDS.TOOLS]: "Tools",
69556
- [CHECK_IDS.MODELS]: "Models"
69557
- };
69558
- var EXIT_CODES = {
69559
- SUCCESS: 0,
69560
- FAILURE: 1
69561
- };
69562
- var MIN_OPENCODE_VERSION = "1.0.150";
69563
- var PACKAGE_NAME2 = PLUGIN_NAME;
69564
- var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
69565
-
69566
69626
  // src/cli/doctor/checks/system.ts
69567
- import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
69627
+ import { existsSync as existsSync28, readFileSync as readFileSync22 } from "fs";
69568
69628
 
69569
69629
  // src/cli/doctor/checks/system-binary.ts
69570
69630
  init_spawn_with_windows_hide();
69571
- import { existsSync as existsSync23 } from "fs";
69631
+ import { existsSync as existsSync25 } from "fs";
69572
69632
  import { homedir as homedir5 } from "os";
69573
- import { join as join24 } from "path";
69633
+ import { join as join26 } from "path";
69574
69634
  function getDesktopAppPaths(platform) {
69575
69635
  const home = homedir5();
69576
69636
  switch (platform) {
69577
69637
  case "darwin":
69578
69638
  return [
69579
69639
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
69580
- join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69640
+ join26(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
69581
69641
  ];
69582
69642
  case "win32": {
69583
69643
  const programFiles = process.env.ProgramFiles;
69584
69644
  const localAppData = process.env.LOCALAPPDATA;
69585
69645
  const paths = [];
69586
69646
  if (programFiles) {
69587
- paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
69647
+ paths.push(join26(programFiles, "OpenCode", "OpenCode.exe"));
69588
69648
  }
69589
69649
  if (localAppData) {
69590
- paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
69650
+ paths.push(join26(localAppData, "OpenCode", "OpenCode.exe"));
69591
69651
  }
69592
69652
  return paths;
69593
69653
  }
@@ -69595,8 +69655,8 @@ function getDesktopAppPaths(platform) {
69595
69655
  return [
69596
69656
  "/usr/bin/opencode",
69597
69657
  "/usr/lib/opencode/opencode",
69598
- join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69599
- join24(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69658
+ join26(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
69659
+ join26(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
69600
69660
  ];
69601
69661
  default:
69602
69662
  return [];
@@ -69608,7 +69668,7 @@ function buildVersionCommand(binaryPath, platform) {
69608
69668
  }
69609
69669
  return [binaryPath, "--version"];
69610
69670
  }
69611
- function findDesktopBinary(platform = process.platform, checkExists = existsSync23) {
69671
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync25) {
69612
69672
  for (const desktopPath of getDesktopAppPaths(platform)) {
69613
69673
  if (checkExists(desktopPath)) {
69614
69674
  return { binary: "opencode", path: desktopPath };
@@ -69638,10 +69698,10 @@ async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
69638
69698
  return null;
69639
69699
  }
69640
69700
  }
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);
69701
+ function compareVersions3(current, minimum) {
69702
+ const parseVersion3 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
69703
+ const currentParts = parseVersion3(current);
69704
+ const minimumParts = parseVersion3(minimum);
69645
69705
  const length = Math.max(currentParts.length, minimumParts.length);
69646
69706
  for (let index = 0;index < length; index++) {
69647
69707
  const currentPart = currentParts[index] ?? 0;
@@ -69656,12 +69716,12 @@ function compareVersions2(current, minimum) {
69656
69716
 
69657
69717
  // src/cli/doctor/checks/system-plugin.ts
69658
69718
  init_shared();
69659
- import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
69719
+ import { existsSync as existsSync26, readFileSync as readFileSync20 } from "fs";
69660
69720
  function detectConfigPath() {
69661
69721
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
69662
- if (existsSync24(paths.configJsonc))
69722
+ if (existsSync26(paths.configJsonc))
69663
69723
  return paths.configJsonc;
69664
- if (existsSync24(paths.configJson))
69724
+ if (existsSync26(paths.configJson))
69665
69725
  return paths.configJson;
69666
69726
  return null;
69667
69727
  }
@@ -69745,34 +69805,34 @@ function getPluginInfo() {
69745
69805
  init_file_utils();
69746
69806
  init_checker();
69747
69807
  init_auto_update_checker();
69748
- import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
69808
+ import { existsSync as existsSync27, readFileSync as readFileSync21 } from "fs";
69749
69809
  import { homedir as homedir6 } from "os";
69750
- import { join as join25 } from "path";
69810
+ import { join as join27 } from "path";
69751
69811
  init_shared();
69752
69812
  function getPlatformDefaultCacheDir(platform = process.platform) {
69753
69813
  if (platform === "darwin")
69754
- return join25(homedir6(), "Library", "Caches");
69814
+ return join27(homedir6(), "Library", "Caches");
69755
69815
  if (platform === "win32")
69756
- return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
69757
- return join25(homedir6(), ".cache");
69816
+ return process.env.LOCALAPPDATA ?? join27(homedir6(), "AppData", "Local");
69817
+ return join27(homedir6(), ".cache");
69758
69818
  }
69759
69819
  function resolveOpenCodeCacheDir() {
69760
69820
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
69761
69821
  if (xdgCacheHome)
69762
- return join25(xdgCacheHome, "opencode");
69822
+ return join27(xdgCacheHome, "opencode");
69763
69823
  const fromShared = getOpenCodeCacheDir();
69764
- const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
69765
- if (existsSync25(fromShared) || !existsSync25(platformDefault))
69824
+ const platformDefault = join27(getPlatformDefaultCacheDir(), "opencode");
69825
+ if (existsSync27(fromShared) || !existsSync27(platformDefault))
69766
69826
  return fromShared;
69767
69827
  return platformDefault;
69768
69828
  }
69769
69829
  function resolveExistingDir(dirPath) {
69770
- if (!existsSync25(dirPath))
69830
+ if (!existsSync27(dirPath))
69771
69831
  return dirPath;
69772
69832
  return resolveSymlink(dirPath);
69773
69833
  }
69774
69834
  function readPackageJson(filePath) {
69775
- if (!existsSync25(filePath))
69835
+ if (!existsSync27(filePath))
69776
69836
  return null;
69777
69837
  try {
69778
69838
  const content = readFileSync21(filePath, "utf-8");
@@ -69794,20 +69854,20 @@ function getLoadedPluginVersion() {
69794
69854
  const candidates = [
69795
69855
  {
69796
69856
  cacheDir: configDir,
69797
- cachePackagePath: join25(configDir, "package.json"),
69798
- installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
69857
+ cachePackagePath: join27(configDir, "package.json"),
69858
+ installedPackagePath: join27(configDir, "node_modules", PACKAGE_NAME, "package.json")
69799
69859
  },
69800
69860
  {
69801
69861
  cacheDir,
69802
- cachePackagePath: join25(cacheDir, "package.json"),
69803
- installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
69862
+ cachePackagePath: join27(cacheDir, "package.json"),
69863
+ installedPackagePath: join27(cacheDir, "node_modules", PACKAGE_NAME, "package.json")
69804
69864
  }
69805
69865
  ];
69806
- const selectedCandidate = candidates.find((candidate) => existsSync25(candidate.installedPackagePath)) ?? candidates[0];
69866
+ const selectedCandidate = candidates.find((candidate) => existsSync27(candidate.installedPackagePath)) ?? candidates[0];
69807
69867
  const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
69808
69868
  const cachePackage = readPackageJson(cachePackagePath);
69809
69869
  const installedPackage = readPackageJson(installedPackagePath);
69810
- const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME2]);
69870
+ const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME]);
69811
69871
  const loadedVersion = normalizeVersion(installedPackage?.version);
69812
69872
  return {
69813
69873
  cacheDir: selectedDir,
@@ -69831,7 +69891,7 @@ init_plugin_identity();
69831
69891
  function isConfigValid(configPath) {
69832
69892
  if (!configPath)
69833
69893
  return true;
69834
- if (!existsSync26(configPath))
69894
+ if (!existsSync28(configPath))
69835
69895
  return false;
69836
69896
  try {
69837
69897
  parseJsonc(readFileSync22(configPath, "utf-8"));
@@ -69885,7 +69945,7 @@ async function checkSystem() {
69885
69945
  affects: ["doctor", "run"]
69886
69946
  });
69887
69947
  }
69888
- if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69948
+ if (systemInfo.opencodeVersion && !compareVersions3(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
69889
69949
  issues.push({
69890
69950
  title: "OpenCode version below minimum",
69891
69951
  description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
@@ -69925,7 +69985,7 @@ async function checkSystem() {
69925
69985
  affects: ["plugin loading"]
69926
69986
  });
69927
69987
  }
69928
- if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
69988
+ if (systemInfo.loadedVersion && latestVersion && !compareVersions3(systemInfo.loadedVersion, latestVersion)) {
69929
69989
  issues.push({
69930
69990
  title: "Loaded plugin is outdated",
69931
69991
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
@@ -69951,23 +70011,23 @@ async function checkSystem() {
69951
70011
 
69952
70012
  // src/cli/doctor/checks/config.ts
69953
70013
  import { readFileSync as readFileSync25 } from "fs";
69954
- import { join as join29 } from "path";
70014
+ import { join as join31 } from "path";
69955
70015
  init_shared();
69956
70016
 
69957
70017
  // src/cli/doctor/checks/model-resolution-cache.ts
69958
70018
  init_shared();
69959
- import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
70019
+ import { existsSync as existsSync29, readFileSync as readFileSync23 } from "fs";
69960
70020
  import { homedir as homedir7 } from "os";
69961
- import { join as join26 } from "path";
70021
+ import { join as join28 } from "path";
69962
70022
  function getOpenCodeCacheDir2() {
69963
70023
  const xdgCache = process.env.XDG_CACHE_HOME;
69964
70024
  if (xdgCache)
69965
- return join26(xdgCache, "opencode");
69966
- return join26(homedir7(), ".cache", "opencode");
70025
+ return join28(xdgCache, "opencode");
70026
+ return join28(homedir7(), ".cache", "opencode");
69967
70027
  }
69968
70028
  function loadAvailableModelsFromCache() {
69969
- const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
69970
- if (!existsSync27(cacheFile)) {
70029
+ const cacheFile = join28(getOpenCodeCacheDir2(), "models.json");
70030
+ if (!existsSync29(cacheFile)) {
69971
70031
  return { providers: [], modelCount: 0, cacheExists: false };
69972
70032
  }
69973
70033
  try {
@@ -69994,8 +70054,8 @@ init_model_capabilities();
69994
70054
  // src/cli/doctor/checks/model-resolution-config.ts
69995
70055
  init_shared();
69996
70056
  import { readFileSync as readFileSync24 } from "fs";
69997
- import { join as join27 } from "path";
69998
- var PROJECT_CONFIG_DIR = join27(process.cwd(), ".opencode");
70057
+ import { join as join29 } from "path";
70058
+ var PROJECT_CONFIG_DIR = join29(process.cwd(), ".opencode");
69999
70059
  function loadOmoConfig() {
70000
70060
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
70001
70061
  if (projectDetected.format !== "none") {
@@ -70021,7 +70081,7 @@ function loadOmoConfig() {
70021
70081
 
70022
70082
  // src/cli/doctor/checks/model-resolution-details.ts
70023
70083
  init_shared();
70024
- import { join as join28 } from "path";
70084
+ import { join as join30 } from "path";
70025
70085
 
70026
70086
  // src/cli/doctor/checks/model-resolution-variant.ts
70027
70087
  function formatModelWithVariant(model, variant) {
@@ -70063,7 +70123,7 @@ function formatCapabilityResolutionLabel(mode) {
70063
70123
  }
70064
70124
  function buildModelResolutionDetails(options) {
70065
70125
  const details = [];
70066
- const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
70126
+ const cacheFile = join30(getOpenCodeCacheDir(), "models.json");
70067
70127
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
70068
70128
  details.push("");
70069
70129
  if (options.available.cacheExists) {
@@ -70218,7 +70278,7 @@ async function checkModels() {
70218
70278
  }
70219
70279
 
70220
70280
  // src/cli/doctor/checks/config.ts
70221
- var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
70281
+ var PROJECT_CONFIG_DIR2 = join31(process.cwd(), ".opencode");
70222
70282
  function findConfigPath() {
70223
70283
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
70224
70284
  if (projectConfig.format !== "none")
@@ -70339,9 +70399,9 @@ async function checkConfig() {
70339
70399
 
70340
70400
  // src/cli/doctor/checks/dependencies.ts
70341
70401
  init_spawn_with_windows_hide();
70342
- import { existsSync as existsSync28 } from "fs";
70402
+ import { existsSync as existsSync30 } from "fs";
70343
70403
  import { createRequire } from "module";
70344
- import { dirname as dirname7, join as join30 } from "path";
70404
+ import { dirname as dirname8, join as join32 } from "path";
70345
70405
  async function checkBinaryExists(binary2) {
70346
70406
  try {
70347
70407
  const path10 = Bun.which(binary2);
@@ -70397,15 +70457,15 @@ async function checkAstGrepNapi() {
70397
70457
  path: null
70398
70458
  };
70399
70459
  } catch {
70400
- const { existsSync: existsSync29 } = await import("fs");
70401
- const { join: join31 } = await import("path");
70460
+ const { existsSync: existsSync31 } = await import("fs");
70461
+ const { join: join33 } = await import("path");
70402
70462
  const { homedir: homedir8 } = await import("os");
70403
70463
  const pathsToCheck = [
70404
- join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70405
- join31(process.cwd(), "node_modules", "@ast-grep", "napi")
70464
+ join33(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
70465
+ join33(process.cwd(), "node_modules", "@ast-grep", "napi")
70406
70466
  ];
70407
70467
  for (const napiPath of pathsToCheck) {
70408
- if (existsSync29(napiPath)) {
70468
+ if (existsSync31(napiPath)) {
70409
70469
  return {
70410
70470
  name: "AST-Grep NAPI",
70411
70471
  required: false,
@@ -70430,8 +70490,8 @@ function findCommentCheckerPackageBinary() {
70430
70490
  try {
70431
70491
  const require2 = createRequire(import.meta.url);
70432
70492
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
70433
- const binaryPath = join30(dirname7(pkgPath), "bin", binaryName);
70434
- if (existsSync28(binaryPath))
70493
+ const binaryPath = join32(dirname8(pkgPath), "bin", binaryName);
70494
+ if (existsSync30(binaryPath))
70435
70495
  return binaryPath;
70436
70496
  } catch {}
70437
70497
  return null;
@@ -70588,12 +70648,12 @@ var BUILTIN_SERVERS = {
70588
70648
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
70589
70649
  };
70590
70650
  // src/tools/lsp/server-config-loader.ts
70591
- import { existsSync as existsSync29, readFileSync as readFileSync26 } from "fs";
70592
- import { join as join31 } from "path";
70651
+ import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
70652
+ import { join as join33 } from "path";
70593
70653
  init_shared();
70594
70654
  init_jsonc_parser();
70595
70655
  function loadJsonFile(path10) {
70596
- if (!existsSync29(path10))
70656
+ if (!existsSync31(path10))
70597
70657
  return null;
70598
70658
  try {
70599
70659
  return parseJsonc(readFileSync26(path10, "utf-8"));
@@ -70605,9 +70665,9 @@ function getConfigPaths2() {
70605
70665
  const cwd = process.cwd();
70606
70666
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70607
70667
  return {
70608
- project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
70668
+ project: detectPluginConfigFile(join33(cwd, ".opencode")).path,
70609
70669
  user: detectPluginConfigFile(configDir).path,
70610
- opencode: detectConfigFile(join31(configDir, "opencode")).path
70670
+ opencode: detectConfigFile(join33(configDir, "opencode")).path
70611
70671
  };
70612
70672
  }
70613
70673
  function loadAllConfigs() {
@@ -70676,21 +70736,21 @@ function getMergedServers() {
70676
70736
  }
70677
70737
 
70678
70738
  // src/tools/lsp/server-installation.ts
70679
- import { existsSync as existsSync30 } from "fs";
70680
- import { delimiter as delimiter2, join as join33 } from "path";
70739
+ import { existsSync as existsSync32 } from "fs";
70740
+ import { delimiter as delimiter2, join as join35 } from "path";
70681
70741
 
70682
70742
  // src/tools/lsp/server-path-bases.ts
70683
70743
  init_shared();
70684
- import { join as join32 } from "path";
70744
+ import { join as join34 } from "path";
70685
70745
  function getLspServerAdditionalPathBases(workingDirectory) {
70686
70746
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
70687
- const dataDir = join32(getDataDir(), "opencode");
70747
+ const dataDir = join34(getDataDir(), "opencode");
70688
70748
  return [
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")
70749
+ join34(workingDirectory, "node_modules", ".bin"),
70750
+ join34(configDir, "bin"),
70751
+ join34(configDir, "node_modules", ".bin"),
70752
+ join34(dataDir, "bin"),
70753
+ join34(dataDir, "bin", "node_modules", ".bin")
70694
70754
  ];
70695
70755
  }
70696
70756
 
@@ -70700,7 +70760,7 @@ function isServerInstalled(command) {
70700
70760
  return false;
70701
70761
  const cmd = command[0];
70702
70762
  if (cmd.includes("/") || cmd.includes("\\")) {
70703
- if (existsSync30(cmd))
70763
+ if (existsSync32(cmd))
70704
70764
  return true;
70705
70765
  }
70706
70766
  const isWindows = process.platform === "win32";
@@ -70721,14 +70781,14 @@ function isServerInstalled(command) {
70721
70781
  const paths = pathEnv.split(delimiter2);
70722
70782
  for (const p2 of paths) {
70723
70783
  for (const suffix of exts) {
70724
- if (existsSync30(join33(p2, cmd + suffix))) {
70784
+ if (existsSync32(join35(p2, cmd + suffix))) {
70725
70785
  return true;
70726
70786
  }
70727
70787
  }
70728
70788
  }
70729
70789
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
70730
70790
  for (const suffix of exts) {
70731
- if (existsSync30(join33(base, cmd + suffix))) {
70791
+ if (existsSync32(join35(base, cmd + suffix))) {
70732
70792
  return true;
70733
70793
  }
70734
70794
  }
@@ -70790,21 +70850,21 @@ function getInstalledLspServers() {
70790
70850
 
70791
70851
  // src/cli/doctor/checks/tools-mcp.ts
70792
70852
  init_shared();
70793
- import { existsSync as existsSync31, readFileSync as readFileSync27 } from "fs";
70853
+ import { existsSync as existsSync33, readFileSync as readFileSync27 } from "fs";
70794
70854
  import { homedir as homedir8 } from "os";
70795
- import { join as join34 } from "path";
70855
+ import { join as join36 } from "path";
70796
70856
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
70797
70857
  function getMcpConfigPaths() {
70798
70858
  return [
70799
- join34(homedir8(), ".claude", ".mcp.json"),
70800
- join34(process.cwd(), ".mcp.json"),
70801
- join34(process.cwd(), ".claude", ".mcp.json")
70859
+ join36(homedir8(), ".claude", ".mcp.json"),
70860
+ join36(process.cwd(), ".mcp.json"),
70861
+ join36(process.cwd(), ".claude", ".mcp.json")
70802
70862
  ];
70803
70863
  }
70804
70864
  function loadUserMcpConfig() {
70805
70865
  const servers = {};
70806
70866
  for (const configPath of getMcpConfigPaths()) {
70807
- if (!existsSync31(configPath))
70867
+ if (!existsSync33(configPath))
70808
70868
  continue;
70809
70869
  try {
70810
70870
  const content = readFileSync27(configPath, "utf-8");
@@ -70974,17 +71034,17 @@ function formatStatusSymbol(status) {
70974
71034
  const colorFn = STATUS_COLORS[status];
70975
71035
  switch (status) {
70976
71036
  case "pass":
70977
- return colorFn(SYMBOLS3.check);
71037
+ return colorFn(SYMBOLS2.check);
70978
71038
  case "fail":
70979
- return colorFn(SYMBOLS3.cross);
71039
+ return colorFn(SYMBOLS2.cross);
70980
71040
  case "warn":
70981
- return colorFn(SYMBOLS3.warn);
71041
+ return colorFn(SYMBOLS2.warn);
70982
71042
  case "skip":
70983
- return colorFn(SYMBOLS3.skip);
71043
+ return colorFn(SYMBOLS2.skip);
70984
71044
  }
70985
71045
  }
70986
71046
  function formatStatusMark(available) {
70987
- return available ? import_picocolors17.default.green(SYMBOLS3.check) : import_picocolors17.default.red(SYMBOLS3.cross);
71047
+ return available ? import_picocolors17.default.green(SYMBOLS2.check) : import_picocolors17.default.red(SYMBOLS2.cross);
70988
71048
  }
70989
71049
  function formatHeader() {
70990
71050
  return `
@@ -71014,12 +71074,12 @@ function formatDefault(result) {
71014
71074
  if (allIssues.length === 0) {
71015
71075
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
71016
71076
  const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
71017
- lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 evil-omo ${pluginVer})`)}`);
71077
+ lines.push(` ${import_picocolors18.default.green(SYMBOLS2.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 evil-omo ${pluginVer})`)}`);
71018
71078
  } else {
71019
71079
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
71020
71080
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
71021
71081
  const totalStr = `${issueCount + warnCount} ${issueCount + warnCount === 1 ? "issue" : "issues"}`;
71022
- lines.push(` ${import_picocolors18.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
71082
+ lines.push(` ${import_picocolors18.default.yellow(SYMBOLS2.warn)} ${totalStr} found:
71023
71083
  `);
71024
71084
  allIssues.forEach((issue2, index) => {
71025
71085
  lines.push(formatIssue(issue2, index + 1));
@@ -71260,11 +71320,11 @@ async function refreshModelCapabilities(options, deps = {}) {
71260
71320
 
71261
71321
  // src/features/mcp-oauth/storage.ts
71262
71322
  init_shared();
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";
71323
+ import { chmodSync, existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync28, renameSync as renameSync2, unlinkSync as unlinkSync4, writeFileSync as writeFileSync9 } from "fs";
71324
+ import { dirname as dirname9, join as join37 } from "path";
71265
71325
  var STORAGE_FILE_NAME = "mcp-oauth.json";
71266
71326
  function getMcpOauthStoragePath() {
71267
- return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71327
+ return join37(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
71268
71328
  }
71269
71329
  function normalizeHost(serverHost) {
71270
71330
  let host = serverHost.trim();
@@ -71301,7 +71361,7 @@ function buildKey(serverHost, resource) {
71301
71361
  }
71302
71362
  function readStore() {
71303
71363
  const filePath = getMcpOauthStoragePath();
71304
- if (!existsSync32(filePath)) {
71364
+ if (!existsSync34(filePath)) {
71305
71365
  return null;
71306
71366
  }
71307
71367
  try {
@@ -71314,12 +71374,14 @@ function readStore() {
71314
71374
  function writeStore(store2) {
71315
71375
  const filePath = getMcpOauthStoragePath();
71316
71376
  try {
71317
- const dir = dirname8(filePath);
71318
- if (!existsSync32(dir)) {
71319
- mkdirSync8(dir, { recursive: true });
71320
- }
71321
- writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71322
- chmodSync(filePath, 384);
71377
+ const dir = dirname9(filePath);
71378
+ if (!existsSync34(dir)) {
71379
+ mkdirSync9(dir, { recursive: true });
71380
+ }
71381
+ const tempPath = `${filePath}.tmp.${Date.now()}`;
71382
+ writeFileSync9(tempPath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
71383
+ chmodSync(tempPath, 384);
71384
+ renameSync2(tempPath, filePath);
71323
71385
  return true;
71324
71386
  } catch {
71325
71387
  return false;
@@ -71350,7 +71412,7 @@ function deleteToken(serverHost, resource) {
71350
71412
  if (Object.keys(store2).length === 0) {
71351
71413
  try {
71352
71414
  const filePath = getMcpOauthStoragePath();
71353
- if (existsSync32(filePath)) {
71415
+ if (existsSync34(filePath)) {
71354
71416
  unlinkSync4(filePath);
71355
71417
  }
71356
71418
  return true;
@@ -71648,6 +71710,38 @@ async function runAuthorizationCodeRedirect(options) {
71648
71710
  }
71649
71711
 
71650
71712
  // src/features/mcp-oauth/provider.ts
71713
+ async function parseTokenResponse(tokenResponse) {
71714
+ if (!tokenResponse.ok) {
71715
+ let errorDetail = `${tokenResponse.status}`;
71716
+ try {
71717
+ const body = await tokenResponse.json();
71718
+ if (body.error) {
71719
+ errorDetail = `${tokenResponse.status} ${body.error}`;
71720
+ if (body.error_description) {
71721
+ errorDetail += `: ${body.error_description}`;
71722
+ }
71723
+ }
71724
+ } catch {}
71725
+ throw new Error(`Token exchange failed: ${errorDetail}`);
71726
+ }
71727
+ return await tokenResponse.json();
71728
+ }
71729
+ function buildOAuthTokenData(tokenData, clientInfo, fallbackRefreshToken) {
71730
+ const accessToken = tokenData.access_token;
71731
+ if (typeof accessToken !== "string") {
71732
+ throw new Error("Token response missing access_token");
71733
+ }
71734
+ return {
71735
+ accessToken,
71736
+ refreshToken: typeof tokenData.refresh_token === "string" ? tokenData.refresh_token : fallbackRefreshToken,
71737
+ expiresAt: typeof tokenData.expires_in === "number" ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
71738
+ clientInfo: {
71739
+ clientId: clientInfo.clientId,
71740
+ ...clientInfo.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
71741
+ }
71742
+ };
71743
+ }
71744
+
71651
71745
  class McpOAuthProvider {
71652
71746
  serverUrl;
71653
71747
  configClientId;
@@ -71742,33 +71836,34 @@ class McpOAuthProvider {
71742
71836
  ...metadata.resource ? { resource: metadata.resource } : {}
71743
71837
  }).toString()
71744
71838
  });
71745
- if (!tokenResponse.ok) {
71746
- let errorDetail = `${tokenResponse.status}`;
71747
- try {
71748
- const body = await tokenResponse.json();
71749
- if (body.error) {
71750
- errorDetail = `${tokenResponse.status} ${body.error}`;
71751
- if (body.error_description) {
71752
- errorDetail += `: ${body.error_description}`;
71753
- }
71754
- }
71755
- } catch {}
71756
- throw new Error(`Token exchange failed: ${errorDetail}`);
71757
- }
71758
- const tokenData = await tokenResponse.json();
71759
- const accessToken = tokenData.access_token;
71760
- if (typeof accessToken !== "string") {
71761
- throw new Error("Token response missing access_token");
71839
+ const tokenData = await parseTokenResponse(tokenResponse);
71840
+ const oauthTokenData = buildOAuthTokenData(tokenData, clientInfo);
71841
+ this.saveTokens(oauthTokenData);
71842
+ return oauthTokenData;
71843
+ }
71844
+ async refresh(refreshToken) {
71845
+ const metadata = await discoverOAuthServerMetadata(this.serverUrl);
71846
+ const clientInfo = this.clientInformation();
71847
+ const clientId = clientInfo?.clientId ?? this.configClientId;
71848
+ if (!clientId) {
71849
+ throw new Error("No client information available. Run login() or register a client first.");
71762
71850
  }
71763
- const oauthTokenData = {
71764
- accessToken,
71765
- refreshToken: typeof tokenData.refresh_token === "string" ? tokenData.refresh_token : undefined,
71766
- expiresAt: typeof tokenData.expires_in === "number" ? Math.floor(Date.now() / 1000) + tokenData.expires_in : undefined,
71767
- clientInfo: {
71768
- clientId: clientInfo.clientId,
71769
- clientSecret: clientInfo.clientSecret
71770
- }
71771
- };
71851
+ const tokenResponse = await fetch(metadata.tokenEndpoint, {
71852
+ method: "POST",
71853
+ headers: { "content-type": "application/x-www-form-urlencoded" },
71854
+ body: new URLSearchParams({
71855
+ grant_type: "refresh_token",
71856
+ refresh_token: refreshToken,
71857
+ client_id: clientId,
71858
+ ...clientInfo?.clientSecret ? { client_secret: clientInfo.clientSecret } : {},
71859
+ ...metadata.resource ? { resource: metadata.resource } : {}
71860
+ }).toString()
71861
+ });
71862
+ const tokenData = await parseTokenResponse(tokenResponse);
71863
+ const oauthTokenData = buildOAuthTokenData(tokenData, {
71864
+ clientId,
71865
+ ...clientInfo?.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
71866
+ }, refreshToken);
71772
71867
  this.saveTokens(oauthTokenData);
71773
71868
  return oauthTokenData;
71774
71869
  }