oh-my-opencode 3.6.0 → 3.7.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 (93) hide show
  1. package/README.ja.md +6 -6
  2. package/README.ko.md +6 -6
  3. package/README.md +6 -6
  4. package/README.zh-cn.md +6 -6
  5. package/dist/agents/sisyphus-junior/gpt.d.ts +4 -14
  6. package/dist/cli/index.js +357 -104
  7. package/dist/cli/run/event-handlers.d.ts +1 -0
  8. package/dist/cli/run/opencode-bin-path.d.ts +3 -0
  9. package/dist/cli/run/opencode-binary-resolver.d.ts +5 -0
  10. package/dist/cli/run/session-resolver.d.ts +1 -0
  11. package/dist/cli/run/types.d.ts +29 -0
  12. package/dist/config/schema/browser-automation.d.ts +2 -0
  13. package/dist/config/schema/experimental.d.ts +1 -0
  14. package/dist/config/schema/hooks.d.ts +1 -0
  15. package/dist/config/schema/oh-my-opencode-config.d.ts +3 -0
  16. package/dist/create-hooks.d.ts +3 -0
  17. package/dist/create-managers.d.ts +1 -0
  18. package/dist/features/background-agent/manager.d.ts +3 -0
  19. package/dist/features/builtin-skills/skills/index.d.ts +1 -0
  20. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +10 -0
  21. package/dist/features/tmux-subagent/action-executor-core.d.ts +21 -0
  22. package/dist/features/tmux-subagent/action-executor.d.ts +3 -12
  23. package/dist/features/tmux-subagent/grid-planning.d.ts +2 -2
  24. package/dist/features/tmux-subagent/pane-split-availability.d.ts +3 -2
  25. package/dist/features/tmux-subagent/polling-manager.d.ts +1 -0
  26. package/dist/features/tmux-subagent/spawn-target-finder.d.ts +1 -1
  27. package/dist/hooks/context-window-monitor.d.ts +5 -1
  28. package/dist/hooks/directory-agents-injector/hook.d.ts +3 -1
  29. package/dist/hooks/directory-readme-injector/hook.d.ts +3 -1
  30. package/dist/hooks/hashline-read-enhancer/hook.d.ts +18 -0
  31. package/dist/hooks/hashline-read-enhancer/index.d.ts +1 -0
  32. package/dist/hooks/index.d.ts +1 -0
  33. package/dist/hooks/preemptive-compaction.d.ts +4 -1
  34. package/dist/hooks/rules-injector/hook.d.ts +3 -1
  35. package/dist/hooks/think-mode/switcher.d.ts +7 -0
  36. package/dist/hooks/tool-output-truncator.d.ts +3 -0
  37. package/dist/index.js +1758 -830
  38. package/dist/plugin/hooks/create-core-hooks.d.ts +3 -0
  39. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -0
  40. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +4 -1
  41. package/dist/shared/dynamic-truncator.d.ts +7 -3
  42. package/dist/shared/fallback-model-availability.d.ts +9 -2
  43. package/dist/shared/git-worktree/index.d.ts +2 -0
  44. package/dist/shared/git-worktree/parse-status-porcelain-line.d.ts +6 -0
  45. package/dist/shared/index.d.ts +2 -0
  46. package/dist/shared/model-availability.d.ts +0 -5
  47. package/dist/shared/session-directory-resolver.d.ts +7 -0
  48. package/dist/shared/tmux/tmux-utils/layout.d.ts +2 -2
  49. package/dist/tools/call-omo-agent/tools.d.ts +1 -1
  50. package/dist/tools/delegate-task/sync-prompt-sender.d.ts +7 -1
  51. package/dist/tools/hashline-edit/constants.d.ts +2 -0
  52. package/dist/tools/hashline-edit/edit-operations.d.ts +6 -0
  53. package/dist/tools/hashline-edit/hash-computation.d.ts +3 -0
  54. package/dist/tools/hashline-edit/index.d.ts +7 -0
  55. package/dist/tools/hashline-edit/tools.d.ts +2 -0
  56. package/dist/tools/hashline-edit/types.d.ts +22 -0
  57. package/dist/tools/hashline-edit/validation.d.ts +6 -0
  58. package/dist/tools/index.d.ts +1 -0
  59. package/package.json +8 -8
  60. package/dist/features/background-agent/background-event-handler.d.ts +0 -26
  61. package/dist/features/background-agent/background-manager-shutdown.d.ts +0 -25
  62. package/dist/features/background-agent/notification-tracker.d.ts +0 -6
  63. package/dist/features/background-agent/notify-parent-session.d.ts +0 -10
  64. package/dist/features/background-agent/poll-running-tasks.d.ts +0 -15
  65. package/dist/features/background-agent/process-signal.d.ts +0 -2
  66. package/dist/features/background-agent/session-validator.d.ts +0 -7
  67. package/dist/features/background-agent/spawner/task-factory.d.ts +0 -2
  68. package/dist/features/background-agent/spawner/task-resumer.d.ts +0 -3
  69. package/dist/features/background-agent/spawner/task-starter.d.ts +0 -3
  70. package/dist/features/background-agent/stale-task-pruner.d.ts +0 -15
  71. package/dist/features/background-agent/task-canceller.d.ts +0 -27
  72. package/dist/features/background-agent/task-completer.d.ts +0 -13
  73. package/dist/features/background-agent/task-launch.d.ts +0 -15
  74. package/dist/features/background-agent/task-queries.d.ts +0 -7
  75. package/dist/features/background-agent/task-queue-processor.d.ts +0 -14
  76. package/dist/features/background-agent/task-resumer.d.ts +0 -14
  77. package/dist/features/background-agent/task-starter.d.ts +0 -27
  78. package/dist/features/background-agent/task-tracker.d.ts +0 -18
  79. package/dist/features/tmux-subagent/manager-cleanup.d.ts +0 -12
  80. package/dist/features/tmux-subagent/session-cleaner.d.ts +0 -23
  81. package/dist/features/tmux-subagent/session-spawner.d.ts +0 -34
  82. package/dist/hooks/interactive-bash-session/interactive-bash-session-hook.d.ts +0 -23
  83. package/dist/shared/available-models-fetcher.d.ts +0 -4
  84. package/dist/shared/model-cache-availability.d.ts +0 -2
  85. package/dist/tools/background-task/modules/background-cancel.d.ts +0 -4
  86. package/dist/tools/background-task/modules/background-output.d.ts +0 -3
  87. package/dist/tools/background-task/modules/background-task.d.ts +0 -3
  88. package/dist/tools/background-task/modules/formatters.d.ts +0 -11
  89. package/dist/tools/background-task/modules/message-processing.d.ts +0 -59
  90. package/dist/tools/background-task/modules/utils.d.ts +0 -16
  91. package/dist/tools/call-omo-agent/agent-type-normalizer.d.ts +0 -2
  92. package/dist/tools/call-omo-agent/sync-agent-executor.d.ts +0 -4
  93. package/dist/tools/delegate-task/skill-content-resolver.d.ts +0 -9
package/dist/cli/index.js CHANGED
@@ -4930,10 +4930,7 @@ function normalizeSDKResponse(response, fallback, options) {
4930
4930
  }
4931
4931
 
4932
4932
  // src/shared/dynamic-truncator.ts
4933
- var ANTHROPIC_ACTUAL_LIMIT;
4934
- var init_dynamic_truncator = __esm(() => {
4935
- ANTHROPIC_ACTUAL_LIMIT = process.env.ANTHROPIC_1M_CONTEXT === "true" || process.env.VERTEX_ANTHROPIC_1M_CONTEXT === "true" ? 1e6 : 200000;
4936
- });
4933
+ var init_dynamic_truncator = () => {};
4937
4934
 
4938
4935
  // src/shared/data-path.ts
4939
4936
  import * as path2 from "path";
@@ -7007,6 +7004,18 @@ var init_model_resolver = __esm(() => {
7007
7004
  init_model_resolution_pipeline();
7008
7005
  });
7009
7006
 
7007
+ // src/shared/model-name-matcher.ts
7008
+ var init_model_name_matcher = __esm(() => {
7009
+ init_logger();
7010
+ });
7011
+
7012
+ // src/shared/fallback-model-availability.ts
7013
+ var init_fallback_model_availability = __esm(() => {
7014
+ init_connected_providers_cache();
7015
+ init_logger();
7016
+ init_model_name_matcher();
7017
+ });
7018
+
7010
7019
  // src/features/hook-message-injector/constants.ts
7011
7020
  var init_constants = __esm(() => {
7012
7021
  init_shared();
@@ -7045,6 +7054,26 @@ var init_opencode_message_dir = __esm(() => {
7045
7054
  });
7046
7055
 
7047
7056
  // src/shared/agent-display-names.ts
7057
+ function getAgentDisplayName(configKey) {
7058
+ const exactMatch = AGENT_DISPLAY_NAMES[configKey];
7059
+ if (exactMatch !== undefined)
7060
+ return exactMatch;
7061
+ const lowerKey = configKey.toLowerCase();
7062
+ for (const [k, v] of Object.entries(AGENT_DISPLAY_NAMES)) {
7063
+ if (k.toLowerCase() === lowerKey)
7064
+ return v;
7065
+ }
7066
+ return configKey;
7067
+ }
7068
+ function getAgentConfigKey(agentName) {
7069
+ const lower = agentName.toLowerCase();
7070
+ const reversed = REVERSE_DISPLAY_NAMES[lower];
7071
+ if (reversed !== undefined)
7072
+ return reversed;
7073
+ if (AGENT_DISPLAY_NAMES[lower] !== undefined)
7074
+ return lower;
7075
+ return lower;
7076
+ }
7048
7077
  var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES;
7049
7078
  var init_agent_display_names = __esm(() => {
7050
7079
  AGENT_DISPLAY_NAMES = {
@@ -7166,10 +7195,15 @@ async function getAvailableServerPort(preferredPort = DEFAULT_SERVER_PORT, hostn
7166
7195
  }
7167
7196
  var DEFAULT_SERVER_PORT = 4096, MAX_PORT_ATTEMPTS = 20;
7168
7197
  var init_port_utils = () => {};
7198
+ // src/shared/git-worktree/parse-status-porcelain.ts
7199
+ var init_parse_status_porcelain = () => {};
7169
7200
  // src/shared/git-worktree/collect-git-diff-stats.ts
7170
- var init_collect_git_diff_stats = () => {};
7201
+ var init_collect_git_diff_stats = __esm(() => {
7202
+ init_parse_status_porcelain();
7203
+ });
7171
7204
  // src/shared/git-worktree/index.ts
7172
7205
  var init_git_worktree = __esm(() => {
7206
+ init_parse_status_porcelain();
7173
7207
  init_collect_git_diff_stats();
7174
7208
  });
7175
7209
 
@@ -7177,6 +7211,9 @@ var init_git_worktree = __esm(() => {
7177
7211
  var init_safe_create_hook = __esm(() => {
7178
7212
  init_logger();
7179
7213
  });
7214
+ // src/shared/session-directory-resolver.ts
7215
+ var init_session_directory_resolver = () => {};
7216
+
7180
7217
  // src/shared/index.ts
7181
7218
  var init_shared = __esm(() => {
7182
7219
  init_model_resolution_pipeline();
@@ -7207,6 +7244,7 @@ var init_shared = __esm(() => {
7207
7244
  init_model_requirements();
7208
7245
  init_model_resolver();
7209
7246
  init_model_availability();
7247
+ init_fallback_model_availability();
7210
7248
  init_connected_providers_cache();
7211
7249
  init_session_utils();
7212
7250
  init_tmux();
@@ -7218,6 +7256,7 @@ var init_shared = __esm(() => {
7218
7256
  init_safe_create_hook();
7219
7257
  init_opencode_storage_paths();
7220
7258
  init_opencode_message_dir();
7259
+ init_session_directory_resolver();
7221
7260
  });
7222
7261
 
7223
7262
  // src/cli/config-manager/config-context.ts
@@ -8868,6 +8907,7 @@ var init_startup_toasts = __esm(() => {
8868
8907
  // src/hooks/auto-update-checker/hook.ts
8869
8908
  function createAutoUpdateCheckerHook(ctx, options = {}) {
8870
8909
  const { showStartupToast = true, isSisyphusEnabled = false, autoUpdate = true } = options;
8910
+ const isCliRunMode = process.env.OPENCODE_CLI_RUN_MODE === "true";
8871
8911
  const getToastMessage = (isUpdate, latestVersion) => {
8872
8912
  if (isSisyphusEnabled) {
8873
8913
  return isUpdate ? `Sisyphus on steroids is steering OpenCode.
@@ -8881,6 +8921,8 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
8881
8921
  event: ({ event }) => {
8882
8922
  if (event.type !== "session.created")
8883
8923
  return;
8924
+ if (isCliRunMode)
8925
+ return;
8884
8926
  if (hasChecked)
8885
8927
  return;
8886
8928
  const props = event.properties;
@@ -8957,7 +8999,7 @@ var {
8957
8999
  // package.json
8958
9000
  var package_default = {
8959
9001
  name: "oh-my-opencode",
8960
- version: "3.6.0",
9002
+ version: "3.7.1",
8961
9003
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
8962
9004
  main: "dist/index.js",
8963
9005
  types: "dist/index.d.ts",
@@ -9031,13 +9073,13 @@ var package_default = {
9031
9073
  typescript: "^5.7.3"
9032
9074
  },
9033
9075
  optionalDependencies: {
9034
- "oh-my-opencode-darwin-arm64": "3.6.0",
9035
- "oh-my-opencode-darwin-x64": "3.6.0",
9036
- "oh-my-opencode-linux-arm64": "3.6.0",
9037
- "oh-my-opencode-linux-arm64-musl": "3.6.0",
9038
- "oh-my-opencode-linux-x64": "3.6.0",
9039
- "oh-my-opencode-linux-x64-musl": "3.6.0",
9040
- "oh-my-opencode-windows-x64": "3.6.0"
9076
+ "oh-my-opencode-darwin-arm64": "3.7.1",
9077
+ "oh-my-opencode-darwin-x64": "3.7.1",
9078
+ "oh-my-opencode-linux-arm64": "3.7.1",
9079
+ "oh-my-opencode-linux-arm64-musl": "3.7.1",
9080
+ "oh-my-opencode-linux-x64": "3.7.1",
9081
+ "oh-my-opencode-linux-x64-musl": "3.7.1",
9082
+ "oh-my-opencode-windows-x64": "3.7.1"
9041
9083
  },
9042
9084
  trustedDependencies: [
9043
9085
  "@ast-grep/cli",
@@ -10145,7 +10187,8 @@ function serializeError(error) {
10145
10187
  function getSessionTag(ctx, payload) {
10146
10188
  const props = payload.properties;
10147
10189
  const info = props?.info;
10148
- const sessionID = props?.sessionID ?? info?.sessionID;
10190
+ const part = props?.part;
10191
+ const sessionID = props?.sessionID ?? props?.sessionId ?? info?.sessionID ?? info?.sessionId ?? part?.sessionID ?? part?.sessionId;
10149
10192
  const isMainSession = sessionID === ctx.sessionID;
10150
10193
  if (isMainSession)
10151
10194
  return import_picocolors5.default.green("[MAIN]");
@@ -10166,9 +10209,9 @@ function logEventVerbose(ctx, payload) {
10166
10209
  case "message.part.updated": {
10167
10210
  const partProps = props;
10168
10211
  const part = partProps?.part;
10169
- if (part?.type === "tool-invocation") {
10170
- const toolPart = part;
10171
- console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${toolPart.toolName} [${toolPart.state}]`));
10212
+ if (part?.type === "tool") {
10213
+ const status = part.state?.status ?? "unknown";
10214
+ console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
10172
10215
  } else if (part?.type === "text" && part.text) {
10173
10216
  const preview = part.text.slice(0, 80).replace(/\n/g, "\\n");
10174
10217
  console.error(import_picocolors5.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
@@ -10225,11 +10268,20 @@ var import_picocolors7 = __toESM(require_picocolors(), 1);
10225
10268
 
10226
10269
  // src/cli/run/event-handlers.ts
10227
10270
  var import_picocolors6 = __toESM(require_picocolors(), 1);
10271
+ function getSessionId(props) {
10272
+ return props?.sessionID ?? props?.sessionId;
10273
+ }
10274
+ function getInfoSessionId(props) {
10275
+ return props?.info?.sessionID ?? props?.info?.sessionId;
10276
+ }
10277
+ function getPartSessionId(props) {
10278
+ return props?.part?.sessionID ?? props?.part?.sessionId;
10279
+ }
10228
10280
  function handleSessionIdle(ctx, payload, state) {
10229
10281
  if (payload.type !== "session.idle")
10230
10282
  return;
10231
10283
  const props = payload.properties;
10232
- if (props?.sessionID === ctx.sessionID) {
10284
+ if (getSessionId(props) === ctx.sessionID) {
10233
10285
  state.mainSessionIdle = true;
10234
10286
  }
10235
10287
  }
@@ -10237,7 +10289,7 @@ function handleSessionStatus(ctx, payload, state) {
10237
10289
  if (payload.type !== "session.status")
10238
10290
  return;
10239
10291
  const props = payload.properties;
10240
- if (props?.sessionID !== ctx.sessionID)
10292
+ if (getSessionId(props) !== ctx.sessionID)
10241
10293
  return;
10242
10294
  if (props?.status?.type === "busy") {
10243
10295
  state.mainSessionIdle = false;
@@ -10251,7 +10303,7 @@ function handleSessionError(ctx, payload, state) {
10251
10303
  if (payload.type !== "session.error")
10252
10304
  return;
10253
10305
  const props = payload.properties;
10254
- if (props?.sessionID === ctx.sessionID) {
10306
+ if (getSessionId(props) === ctx.sessionID) {
10255
10307
  state.mainSessionError = true;
10256
10308
  state.lastError = serializeError(props?.error);
10257
10309
  console.error(import_picocolors6.default.red(`
@@ -10262,11 +10314,11 @@ function handleMessagePartUpdated(ctx, payload, state) {
10262
10314
  if (payload.type !== "message.part.updated")
10263
10315
  return;
10264
10316
  const props = payload.properties;
10265
- if (props?.info?.sessionID !== ctx.sessionID)
10266
- return;
10267
- if (props?.info?.role !== "assistant")
10317
+ const partSid = getPartSessionId(props);
10318
+ const infoSid = getInfoSessionId(props);
10319
+ if ((partSid ?? infoSid) !== ctx.sessionID)
10268
10320
  return;
10269
- const part = props.part;
10321
+ const part = props?.part;
10270
10322
  if (!part)
10271
10323
  return;
10272
10324
  if (part.type === "text" && part.text) {
@@ -10277,12 +10329,53 @@ function handleMessagePartUpdated(ctx, payload, state) {
10277
10329
  }
10278
10330
  state.lastPartText = part.text;
10279
10331
  }
10332
+ if (part.type === "tool") {
10333
+ handleToolPart(ctx, part, state);
10334
+ }
10335
+ }
10336
+ function handleToolPart(_ctx, part, state) {
10337
+ const toolName = part.tool || part.name || "unknown";
10338
+ const status = part.state?.status;
10339
+ if (status === "running") {
10340
+ state.currentTool = toolName;
10341
+ let inputPreview = "";
10342
+ const input = part.state?.input;
10343
+ if (input) {
10344
+ if (input.command) {
10345
+ inputPreview = ` ${import_picocolors6.default.dim(String(input.command).slice(0, 60))}`;
10346
+ } else if (input.pattern) {
10347
+ inputPreview = ` ${import_picocolors6.default.dim(String(input.pattern).slice(0, 40))}`;
10348
+ } else if (input.filePath) {
10349
+ inputPreview = ` ${import_picocolors6.default.dim(String(input.filePath))}`;
10350
+ } else if (input.query) {
10351
+ inputPreview = ` ${import_picocolors6.default.dim(String(input.query).slice(0, 40))}`;
10352
+ }
10353
+ }
10354
+ state.hasReceivedMeaningfulWork = true;
10355
+ process.stdout.write(`
10356
+ ${import_picocolors6.default.cyan(">")} ${import_picocolors6.default.bold(toolName)}${inputPreview}
10357
+ `);
10358
+ }
10359
+ if (status === "completed" || status === "error") {
10360
+ const output = part.state?.output || "";
10361
+ const maxLen = 200;
10362
+ const preview = output.length > maxLen ? output.slice(0, maxLen) + "..." : output;
10363
+ if (preview.trim()) {
10364
+ const lines = preview.split(`
10365
+ `).slice(0, 3);
10366
+ process.stdout.write(import_picocolors6.default.dim(` \u2514\u2500 ${lines.join(`
10367
+ `)}
10368
+ `));
10369
+ }
10370
+ state.currentTool = null;
10371
+ state.lastPartText = "";
10372
+ }
10280
10373
  }
10281
10374
  function handleMessageUpdated(ctx, payload, state) {
10282
10375
  if (payload.type !== "message.updated")
10283
10376
  return;
10284
10377
  const props = payload.properties;
10285
- if (props?.info?.sessionID !== ctx.sessionID)
10378
+ if (getInfoSessionId(props) !== ctx.sessionID)
10286
10379
  return;
10287
10380
  if (props?.info?.role !== "assistant")
10288
10381
  return;
@@ -10294,7 +10387,7 @@ function handleToolExecute(ctx, payload, state) {
10294
10387
  if (payload.type !== "tool.execute")
10295
10388
  return;
10296
10389
  const props = payload.properties;
10297
- if (props?.sessionID !== ctx.sessionID)
10390
+ if (getSessionId(props) !== ctx.sessionID)
10298
10391
  return;
10299
10392
  const toolName = props?.name || "unknown";
10300
10393
  state.currentTool = toolName;
@@ -10320,7 +10413,7 @@ function handleToolResult(ctx, payload, state) {
10320
10413
  if (payload.type !== "tool.result")
10321
10414
  return;
10322
10415
  const props = payload.properties;
10323
- if (props?.sessionID !== ctx.sessionID)
10416
+ if (getSessionId(props) !== ctx.sessionID)
10324
10417
  return;
10325
10418
  const output = props?.output || "";
10326
10419
  const maxLen = 200;
@@ -10335,6 +10428,25 @@ function handleToolResult(ctx, payload, state) {
10335
10428
  state.currentTool = null;
10336
10429
  state.lastPartText = "";
10337
10430
  }
10431
+ function handleTuiToast(_ctx, payload, state) {
10432
+ if (payload.type !== "tui.toast.show")
10433
+ return;
10434
+ const props = payload.properties;
10435
+ const title = props?.title ? `${props.title}: ` : "";
10436
+ const message = props?.message?.trim();
10437
+ const variant = props?.variant ?? "info";
10438
+ if (!message)
10439
+ return;
10440
+ if (variant === "error") {
10441
+ state.mainSessionError = true;
10442
+ state.lastError = `${title}${message}`;
10443
+ console.error(import_picocolors6.default.red(`
10444
+ [tui.toast.error] ${state.lastError}`));
10445
+ return;
10446
+ }
10447
+ const colorize = variant === "warning" ? import_picocolors6.default.yellow : import_picocolors6.default.dim;
10448
+ console.log(colorize(`[toast:${variant}] ${title}${message}`));
10449
+ }
10338
10450
 
10339
10451
  // src/cli/run/event-stream-processor.ts
10340
10452
  async function processEvents(ctx, stream, state) {
@@ -10355,6 +10467,7 @@ async function processEvents(ctx, stream, state) {
10355
10467
  handleMessageUpdated(ctx, payload, state);
10356
10468
  handleToolExecute(ctx, payload, state);
10357
10469
  handleToolResult(ctx, payload, state);
10470
+ handleTuiToast(ctx, payload, state);
10358
10471
  } catch (err) {
10359
10472
  console.error(import_picocolors7.default.red(`[event error] ${err}`));
10360
10473
  }
@@ -22787,7 +22900,8 @@ var BackgroundTaskConfigSchema = exports_external.object({
22787
22900
  var BrowserAutomationProviderSchema = exports_external.enum([
22788
22901
  "playwright",
22789
22902
  "agent-browser",
22790
- "dev-browser"
22903
+ "dev-browser",
22904
+ "playwright-cli"
22791
22905
  ]);
22792
22906
  var BrowserAutomationConfigSchema = exports_external.object({
22793
22907
  provider: BrowserAutomationProviderSchema.default("playwright")
@@ -22886,7 +23000,8 @@ var ExperimentalConfigSchema = exports_external.object({
22886
23000
  dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
22887
23001
  task_system: exports_external.boolean().optional(),
22888
23002
  plugin_load_timeout_ms: exports_external.number().min(1000).optional(),
22889
- safe_hook_creation: exports_external.boolean().optional()
23003
+ safe_hook_creation: exports_external.boolean().optional(),
23004
+ hashline_edit: exports_external.boolean().optional()
22890
23005
  });
22891
23006
  // src/config/schema/git-master.ts
22892
23007
  var GitMasterConfigSchema = exports_external.object({
@@ -22936,7 +23051,8 @@ var HookNameSchema = exports_external.enum([
22936
23051
  "stop-continuation-guard",
22937
23052
  "tasks-todowrite-disabler",
22938
23053
  "write-existing-file-guard",
22939
- "anthropic-effort"
23054
+ "anthropic-effort",
23055
+ "hashline-read-enhancer"
22940
23056
  ]);
22941
23057
  // src/config/schema/notification.ts
22942
23058
  var NotificationConfigSchema = exports_external.object({
@@ -24624,7 +24740,99 @@ async function createOpencode(options) {
24624
24740
  // src/cli/run/server-connection.ts
24625
24741
  init_port_utils();
24626
24742
  var import_picocolors8 = __toESM(require_picocolors(), 1);
24743
+
24744
+ // src/cli/run/opencode-binary-resolver.ts
24745
+ import { delimiter, dirname, join as join8 } from "path";
24746
+ var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
24747
+ var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
24748
+ function getCommandCandidates(platform) {
24749
+ if (platform !== "win32")
24750
+ return [...OPENCODE_COMMANDS];
24751
+ return OPENCODE_COMMANDS.flatMap((command) => WINDOWS_SUFFIXES.map((suffix) => `${command}${suffix}`));
24752
+ }
24753
+ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = process.platform) {
24754
+ const seen = new Set;
24755
+ const candidates = [];
24756
+ const commandCandidates = getCommandCandidates(platform);
24757
+ const addCandidate = (binaryPath) => {
24758
+ if (!binaryPath || seen.has(binaryPath))
24759
+ return;
24760
+ seen.add(binaryPath);
24761
+ candidates.push(binaryPath);
24762
+ };
24763
+ for (const command of commandCandidates) {
24764
+ addCandidate(which(command));
24765
+ }
24766
+ for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
24767
+ for (const command of commandCandidates) {
24768
+ addCandidate(join8(entry, command));
24769
+ }
24770
+ }
24771
+ return candidates;
24772
+ }
24773
+ async function canExecuteBinary(binaryPath) {
24774
+ try {
24775
+ const proc = Bun.spawn([binaryPath, "--version"], {
24776
+ stdout: "pipe",
24777
+ stderr: "pipe"
24778
+ });
24779
+ await proc.exited;
24780
+ return proc.exitCode === 0;
24781
+ } catch {
24782
+ return false;
24783
+ }
24784
+ }
24785
+ async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = canExecuteBinary, which = Bun.which, platform = process.platform) {
24786
+ const candidates = collectCandidateBinaryPaths(pathEnv, which, platform);
24787
+ for (const candidate of candidates) {
24788
+ if (await probe(candidate)) {
24789
+ return candidate;
24790
+ }
24791
+ }
24792
+ return null;
24793
+ }
24794
+ function buildPathWithBinaryFirst(pathEnv, binaryPath) {
24795
+ const preferredDir = dirname(binaryPath);
24796
+ const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
24797
+ return [preferredDir, ...existing].join(delimiter);
24798
+ }
24799
+ async function withWorkingOpencodePath(startServer, finder = findWorkingOpencodeBinary) {
24800
+ const originalPath = process.env.PATH;
24801
+ const binaryPath = await finder(originalPath);
24802
+ if (!binaryPath) {
24803
+ return startServer();
24804
+ }
24805
+ process.env.PATH = buildPathWithBinaryFirst(originalPath, binaryPath);
24806
+ try {
24807
+ return await startServer();
24808
+ } finally {
24809
+ process.env.PATH = originalPath;
24810
+ }
24811
+ }
24812
+
24813
+ // src/cli/run/opencode-bin-path.ts
24814
+ import { delimiter as delimiter2, dirname as dirname2 } from "path";
24815
+ import { createRequire } from "module";
24816
+ var resolveFromCurrentModule = createRequire(import.meta.url).resolve;
24817
+ function prependResolvedOpencodeBinToPath(env = process.env, resolve2 = resolveFromCurrentModule) {
24818
+ let resolvedPath;
24819
+ try {
24820
+ resolvedPath = resolve2("opencode-ai/bin/opencode");
24821
+ } catch {
24822
+ return;
24823
+ }
24824
+ const opencodeBinDir = dirname2(resolvedPath);
24825
+ const currentPath = env.PATH ?? "";
24826
+ const pathSegments = currentPath ? currentPath.split(delimiter2) : [];
24827
+ if (pathSegments.includes(opencodeBinDir)) {
24828
+ return;
24829
+ }
24830
+ env.PATH = currentPath ? `${opencodeBinDir}${delimiter2}${currentPath}` : opencodeBinDir;
24831
+ }
24832
+
24833
+ // src/cli/run/server-connection.ts
24627
24834
  async function createServerConnection(options) {
24835
+ prependResolvedOpencodeBinToPath();
24628
24836
  const { port, attach, signal } = options;
24629
24837
  if (attach !== undefined) {
24630
24838
  console.log(import_picocolors8.default.dim("Attaching to existing server at"), import_picocolors8.default.cyan(attach));
@@ -24638,7 +24846,7 @@ async function createServerConnection(options) {
24638
24846
  const available = await isPortAvailable(port, "127.0.0.1");
24639
24847
  if (available) {
24640
24848
  console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(port.toString()));
24641
- const { client: client5, server: server3 } = await createOpencode({ signal, port, hostname: "127.0.0.1" });
24849
+ const { client: client5, server: server3 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
24642
24850
  console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server3.url));
24643
24851
  return { client: client5, cleanup: () => server3.close() };
24644
24852
  }
@@ -24652,7 +24860,7 @@ async function createServerConnection(options) {
24652
24860
  } else {
24653
24861
  console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(selectedPort.toString()));
24654
24862
  }
24655
- const { client: client3, server: server2 } = await createOpencode({ signal, port: selectedPort, hostname: "127.0.0.1" });
24863
+ const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port: selectedPort, hostname: "127.0.0.1" }));
24656
24864
  console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server2.url));
24657
24865
  return { client: client3, cleanup: () => server2.close() };
24658
24866
  }
@@ -24662,9 +24870,12 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
24662
24870
  var SESSION_CREATE_MAX_RETRIES = 3;
24663
24871
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
24664
24872
  async function resolveSession(options) {
24665
- const { client: client3, sessionId } = options;
24873
+ const { client: client3, sessionId, directory } = options;
24666
24874
  if (sessionId) {
24667
- const res = await client3.session.get({ path: { id: sessionId } });
24875
+ const res = await client3.session.get({
24876
+ path: { id: sessionId },
24877
+ query: { directory }
24878
+ });
24668
24879
  if (res.error || !res.data) {
24669
24880
  throw new Error(`Session not found: ${sessionId}`);
24670
24881
  }
@@ -24677,7 +24888,8 @@ async function resolveSession(options) {
24677
24888
  permission: [
24678
24889
  { permission: "question", action: "deny", pattern: "*" }
24679
24890
  ]
24680
- }
24891
+ },
24892
+ query: { directory }
24681
24893
  });
24682
24894
  if (res.error) {
24683
24895
  console.error(import_picocolors9.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
@@ -24764,6 +24976,7 @@ async function executeOnCompleteHook(options) {
24764
24976
  }
24765
24977
 
24766
24978
  // src/cli/run/agent-resolver.ts
24979
+ init_agent_display_names();
24767
24980
  var import_picocolors11 = __toESM(require_picocolors(), 1);
24768
24981
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
24769
24982
  var DEFAULT_AGENT = "sisyphus";
@@ -24771,18 +24984,22 @@ var normalizeAgentName = (agent) => {
24771
24984
  if (!agent)
24772
24985
  return;
24773
24986
  const trimmed = agent.trim();
24774
- if (!trimmed)
24987
+ if (trimmed.length === 0)
24775
24988
  return;
24776
- const lowered = trimmed.toLowerCase();
24777
- const coreMatch = CORE_AGENT_ORDER.find((name) => name.toLowerCase() === lowered);
24778
- return coreMatch ?? trimmed;
24989
+ const configKey = getAgentConfigKey(trimmed);
24990
+ const displayName = getAgentDisplayName(configKey);
24991
+ const isKnownAgent = displayName !== configKey;
24992
+ return {
24993
+ configKey,
24994
+ resolvedName: isKnownAgent ? displayName : trimmed
24995
+ };
24779
24996
  };
24780
- var isAgentDisabled = (agent, config2) => {
24781
- const lowered = agent.toLowerCase();
24782
- if (lowered === "sisyphus" && config2.sisyphus_agent?.disabled === true) {
24997
+ var isAgentDisabled = (agentConfigKey, config2) => {
24998
+ const lowered = agentConfigKey.toLowerCase();
24999
+ if (lowered === DEFAULT_AGENT && config2.sisyphus_agent?.disabled === true) {
24783
25000
  return true;
24784
25001
  }
24785
- return (config2.disabled_agents ?? []).some((disabled) => disabled.toLowerCase() === lowered);
25002
+ return (config2.disabled_agents ?? []).some((disabled) => getAgentConfigKey(disabled) === lowered);
24786
25003
  };
24787
25004
  var pickFallbackAgent = (config2) => {
24788
25005
  for (const agent of CORE_AGENT_ORDER) {
@@ -24796,19 +25013,22 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
24796
25013
  const cliAgent = normalizeAgentName(options.agent);
24797
25014
  const envAgent = normalizeAgentName(env.OPENCODE_DEFAULT_AGENT);
24798
25015
  const configAgent = normalizeAgentName(pluginConfig.default_run_agent);
24799
- const resolved = cliAgent ?? envAgent ?? configAgent ?? DEFAULT_AGENT;
24800
- const normalized = normalizeAgentName(resolved) ?? DEFAULT_AGENT;
24801
- if (isAgentDisabled(normalized, pluginConfig)) {
25016
+ const resolved = cliAgent ?? envAgent ?? configAgent ?? {
25017
+ configKey: DEFAULT_AGENT,
25018
+ resolvedName: getAgentDisplayName(DEFAULT_AGENT)
25019
+ };
25020
+ if (isAgentDisabled(resolved.configKey, pluginConfig)) {
24802
25021
  const fallback = pickFallbackAgent(pluginConfig);
25022
+ const fallbackName = getAgentDisplayName(fallback);
24803
25023
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
24804
25024
  if (fallbackDisabled) {
24805
- console.log(import_picocolors11.default.yellow(`Requested agent "${normalized}" is disabled and no enabled core agent was found. Proceeding with "${fallback}".`));
24806
- return fallback;
25025
+ console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
25026
+ return fallbackName;
24807
25027
  }
24808
- console.log(import_picocolors11.default.yellow(`Requested agent "${normalized}" is disabled. Falling back to "${fallback}".`));
24809
- return fallback;
25028
+ console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
25029
+ return fallbackName;
24810
25030
  }
24811
- return normalized;
25031
+ return resolved.resolvedName;
24812
25032
  };
24813
25033
 
24814
25034
  // src/cli/run/poll-for-completion.ts
@@ -24832,7 +25052,10 @@ async function checkCompletionConditions(ctx) {
24832
25052
  }
24833
25053
  }
24834
25054
  async function areAllTodosComplete(ctx) {
24835
- const todosRes = await ctx.client.session.todo({ path: { id: ctx.sessionID } });
25055
+ const todosRes = await ctx.client.session.todo({
25056
+ path: { id: ctx.sessionID },
25057
+ query: { directory: ctx.directory }
25058
+ });
24836
25059
  const todos = normalizeSDKResponse(todosRes, []);
24837
25060
  const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
24838
25061
  if (incompleteTodos.length > 0) {
@@ -24846,12 +25069,15 @@ async function areAllChildrenIdle(ctx) {
24846
25069
  return areAllDescendantsIdle(ctx, ctx.sessionID, allStatuses);
24847
25070
  }
24848
25071
  async function fetchAllStatuses(ctx) {
24849
- const statusRes = await ctx.client.session.status();
25072
+ const statusRes = await ctx.client.session.status({
25073
+ query: { directory: ctx.directory }
25074
+ });
24850
25075
  return normalizeSDKResponse(statusRes, {});
24851
25076
  }
24852
25077
  async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
24853
25078
  const childrenRes = await ctx.client.session.children({
24854
- path: { id: sessionID }
25079
+ path: { id: sessionID },
25080
+ query: { directory: ctx.directory }
24855
25081
  });
24856
25082
  const children = normalizeSDKResponse(childrenRes, []);
24857
25083
  for (const child of children) {
@@ -24869,6 +25095,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
24869
25095
  }
24870
25096
 
24871
25097
  // src/cli/run/poll-for-completion.ts
25098
+ init_shared();
24872
25099
  var DEFAULT_POLL_INTERVAL_MS = 500;
24873
25100
  var DEFAULT_REQUIRED_CONSECUTIVE = 3;
24874
25101
  var ERROR_GRACE_CYCLES = 3;
@@ -24880,6 +25107,7 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
24880
25107
  let consecutiveCompleteChecks = 0;
24881
25108
  let errorCycleCount = 0;
24882
25109
  let firstWorkTimestamp = null;
25110
+ const pollStartTimestamp = Date.now();
24883
25111
  while (!abortController.signal.aborted) {
24884
25112
  await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
24885
25113
  if (eventState.mainSessionError) {
@@ -24895,6 +25123,12 @@ Session ended with error: ${eventState.lastError}`));
24895
25123
  } else {
24896
25124
  errorCycleCount = 0;
24897
25125
  }
25126
+ const mainSessionStatus = await getMainSessionStatus(ctx);
25127
+ if (mainSessionStatus === "busy" || mainSessionStatus === "retry") {
25128
+ eventState.mainSessionIdle = false;
25129
+ } else if (mainSessionStatus === "idle") {
25130
+ eventState.mainSessionIdle = true;
25131
+ }
24898
25132
  if (!eventState.mainSessionIdle) {
24899
25133
  consecutiveCompleteChecks = 0;
24900
25134
  continue;
@@ -24904,8 +25138,11 @@ Session ended with error: ${eventState.lastError}`));
24904
25138
  continue;
24905
25139
  }
24906
25140
  if (!eventState.hasReceivedMeaningfulWork) {
25141
+ if (Date.now() - pollStartTimestamp < minStabilizationMs) {
25142
+ consecutiveCompleteChecks = 0;
25143
+ continue;
25144
+ }
24907
25145
  consecutiveCompleteChecks = 0;
24908
- continue;
24909
25146
  }
24910
25147
  if (firstWorkTimestamp === null) {
24911
25148
  firstWorkTimestamp = Date.now();
@@ -24929,6 +25166,21 @@ All tasks completed.`));
24929
25166
  }
24930
25167
  return 130;
24931
25168
  }
25169
+ async function getMainSessionStatus(ctx) {
25170
+ try {
25171
+ const statusesRes = await ctx.client.session.status({
25172
+ query: { directory: ctx.directory }
25173
+ });
25174
+ const statuses = normalizeSDKResponse(statusesRes, {});
25175
+ const status = statuses[ctx.sessionID]?.type;
25176
+ if (status === "idle" || status === "busy" || status === "retry") {
25177
+ return status;
25178
+ }
25179
+ return null;
25180
+ } catch {
25181
+ return null;
25182
+ }
25183
+ }
24932
25184
 
24933
25185
  // src/cli/run/runner.ts
24934
25186
  var DEFAULT_TIMEOUT_MS = 600000;
@@ -24984,7 +25236,8 @@ Interrupted. Shutting down...`));
24984
25236
  try {
24985
25237
  const sessionID = await resolveSession({
24986
25238
  client: client3,
24987
- sessionId: options.sessionId
25239
+ sessionId: options.sessionId,
25240
+ directory
24988
25241
  });
24989
25242
  console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
24990
25243
  const ctx = { client: client3, sessionID, directory, abortController };
@@ -25235,24 +25488,24 @@ import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
25235
25488
  // src/cli/doctor/checks/system-binary.ts
25236
25489
  import { existsSync as existsSync16 } from "fs";
25237
25490
  import { homedir as homedir5 } from "os";
25238
- import { join as join12 } from "path";
25491
+ import { join as join13 } from "path";
25239
25492
  function getDesktopAppPaths(platform) {
25240
25493
  const home = homedir5();
25241
25494
  switch (platform) {
25242
25495
  case "darwin":
25243
25496
  return [
25244
25497
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
25245
- join12(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
25498
+ join13(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
25246
25499
  ];
25247
25500
  case "win32": {
25248
25501
  const programFiles = process.env.ProgramFiles;
25249
25502
  const localAppData = process.env.LOCALAPPDATA;
25250
25503
  const paths = [];
25251
25504
  if (programFiles) {
25252
- paths.push(join12(programFiles, "OpenCode", "OpenCode.exe"));
25505
+ paths.push(join13(programFiles, "OpenCode", "OpenCode.exe"));
25253
25506
  }
25254
25507
  if (localAppData) {
25255
- paths.push(join12(localAppData, "OpenCode", "OpenCode.exe"));
25508
+ paths.push(join13(localAppData, "OpenCode", "OpenCode.exe"));
25256
25509
  }
25257
25510
  return paths;
25258
25511
  }
@@ -25260,8 +25513,8 @@ function getDesktopAppPaths(platform) {
25260
25513
  return [
25261
25514
  "/usr/bin/opencode",
25262
25515
  "/usr/lib/opencode/opencode",
25263
- join12(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
25264
- join12(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
25516
+ join13(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
25517
+ join13(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
25265
25518
  ];
25266
25519
  default:
25267
25520
  return [];
@@ -25401,21 +25654,21 @@ init_checker();
25401
25654
  init_auto_update_checker();
25402
25655
  import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
25403
25656
  import { homedir as homedir6 } from "os";
25404
- import { join as join13 } from "path";
25657
+ import { join as join14 } from "path";
25405
25658
  init_shared();
25406
25659
  function getPlatformDefaultCacheDir(platform = process.platform) {
25407
25660
  if (platform === "darwin")
25408
- return join13(homedir6(), "Library", "Caches");
25661
+ return join14(homedir6(), "Library", "Caches");
25409
25662
  if (platform === "win32")
25410
- return process.env.LOCALAPPDATA ?? join13(homedir6(), "AppData", "Local");
25411
- return join13(homedir6(), ".cache");
25663
+ return process.env.LOCALAPPDATA ?? join14(homedir6(), "AppData", "Local");
25664
+ return join14(homedir6(), ".cache");
25412
25665
  }
25413
25666
  function resolveOpenCodeCacheDir() {
25414
25667
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
25415
25668
  if (xdgCacheHome)
25416
- return join13(xdgCacheHome, "opencode");
25669
+ return join14(xdgCacheHome, "opencode");
25417
25670
  const fromShared = getOpenCodeCacheDir();
25418
- const platformDefault = join13(getPlatformDefaultCacheDir(), "opencode");
25671
+ const platformDefault = join14(getPlatformDefaultCacheDir(), "opencode");
25419
25672
  if (existsSync18(fromShared) || !existsSync18(platformDefault))
25420
25673
  return fromShared;
25421
25674
  return platformDefault;
@@ -25438,8 +25691,8 @@ function normalizeVersion(value) {
25438
25691
  }
25439
25692
  function getLoadedPluginVersion() {
25440
25693
  const cacheDir = resolveOpenCodeCacheDir();
25441
- const cachePackagePath = join13(cacheDir, "package.json");
25442
- const installedPackagePath = join13(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
25694
+ const cachePackagePath = join14(cacheDir, "package.json");
25695
+ const installedPackagePath = join14(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
25443
25696
  const cachePackage = readPackageJson(cachePackagePath);
25444
25697
  const installedPackage = readPackageJson(installedPackagePath);
25445
25698
  const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME4]);
@@ -25568,22 +25821,22 @@ async function checkSystem() {
25568
25821
 
25569
25822
  // src/cli/doctor/checks/config.ts
25570
25823
  import { readFileSync as readFileSync23 } from "fs";
25571
- import { join as join17 } from "path";
25824
+ import { join as join18 } from "path";
25572
25825
  init_shared();
25573
25826
 
25574
25827
  // src/cli/doctor/checks/model-resolution-cache.ts
25575
25828
  init_shared();
25576
25829
  import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
25577
25830
  import { homedir as homedir7 } from "os";
25578
- import { join as join14 } from "path";
25831
+ import { join as join15 } from "path";
25579
25832
  function getOpenCodeCacheDir2() {
25580
25833
  const xdgCache = process.env.XDG_CACHE_HOME;
25581
25834
  if (xdgCache)
25582
- return join14(xdgCache, "opencode");
25583
- return join14(homedir7(), ".cache", "opencode");
25835
+ return join15(xdgCache, "opencode");
25836
+ return join15(homedir7(), ".cache", "opencode");
25584
25837
  }
25585
25838
  function loadAvailableModelsFromCache() {
25586
- const cacheFile = join14(getOpenCodeCacheDir2(), "models.json");
25839
+ const cacheFile = join15(getOpenCodeCacheDir2(), "models.json");
25587
25840
  if (!existsSync20(cacheFile)) {
25588
25841
  return { providers: [], modelCount: 0, cacheExists: false };
25589
25842
  }
@@ -25610,10 +25863,10 @@ init_model_requirements();
25610
25863
  // src/cli/doctor/checks/model-resolution-config.ts
25611
25864
  init_shared();
25612
25865
  import { readFileSync as readFileSync22 } from "fs";
25613
- import { join as join15 } from "path";
25866
+ import { join as join16 } from "path";
25614
25867
  var PACKAGE_NAME5 = "oh-my-opencode";
25615
- var USER_CONFIG_BASE = join15(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
25616
- var PROJECT_CONFIG_BASE = join15(process.cwd(), ".opencode", PACKAGE_NAME5);
25868
+ var USER_CONFIG_BASE = join16(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
25869
+ var PROJECT_CONFIG_BASE = join16(process.cwd(), ".opencode", PACKAGE_NAME5);
25617
25870
  function loadOmoConfig() {
25618
25871
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
25619
25872
  if (projectDetected.format !== "none") {
@@ -25638,7 +25891,7 @@ function loadOmoConfig() {
25638
25891
 
25639
25892
  // src/cli/doctor/checks/model-resolution-details.ts
25640
25893
  init_shared();
25641
- import { join as join16 } from "path";
25894
+ import { join as join17 } from "path";
25642
25895
 
25643
25896
  // src/cli/doctor/checks/model-resolution-variant.ts
25644
25897
  function formatModelWithVariant(model, variant) {
@@ -25677,7 +25930,7 @@ function getCategoryEffectiveVariant(categoryName, requirement, config2) {
25677
25930
  // src/cli/doctor/checks/model-resolution-details.ts
25678
25931
  function buildModelResolutionDetails(options) {
25679
25932
  const details = [];
25680
- const cacheFile = join16(getOpenCodeCacheDir(), "models.json");
25933
+ const cacheFile = join17(getOpenCodeCacheDir(), "models.json");
25681
25934
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
25682
25935
  details.push("");
25683
25936
  if (options.available.cacheExists) {
@@ -25789,8 +26042,8 @@ async function checkModels() {
25789
26042
  }
25790
26043
 
25791
26044
  // src/cli/doctor/checks/config.ts
25792
- var USER_CONFIG_BASE2 = join17(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
25793
- var PROJECT_CONFIG_BASE2 = join17(process.cwd(), ".opencode", PACKAGE_NAME4);
26045
+ var USER_CONFIG_BASE2 = join18(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
26046
+ var PROJECT_CONFIG_BASE2 = join18(process.cwd(), ".opencode", PACKAGE_NAME4);
25794
26047
  function findConfigPath() {
25795
26048
  const projectConfig = detectConfigFile(PROJECT_CONFIG_BASE2);
25796
26049
  if (projectConfig.format !== "none")
@@ -25910,8 +26163,8 @@ async function checkConfig() {
25910
26163
 
25911
26164
  // src/cli/doctor/checks/dependencies.ts
25912
26165
  import { existsSync as existsSync21 } from "fs";
25913
- import { createRequire } from "module";
25914
- import { dirname as dirname3, join as join18 } from "path";
26166
+ import { createRequire as createRequire2 } from "module";
26167
+ import { dirname as dirname5, join as join19 } from "path";
25915
26168
  async function checkBinaryExists(binary2) {
25916
26169
  try {
25917
26170
  const path9 = Bun.which(binary2);
@@ -25968,11 +26221,11 @@ async function checkAstGrepNapi() {
25968
26221
  };
25969
26222
  } catch {
25970
26223
  const { existsSync: existsSync22 } = await import("fs");
25971
- const { join: join19 } = await import("path");
26224
+ const { join: join20 } = await import("path");
25972
26225
  const { homedir: homedir8 } = await import("os");
25973
26226
  const pathsToCheck = [
25974
- join19(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
25975
- join19(process.cwd(), "node_modules", "@ast-grep", "napi")
26227
+ join20(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
26228
+ join20(process.cwd(), "node_modules", "@ast-grep", "napi")
25976
26229
  ];
25977
26230
  for (const napiPath of pathsToCheck) {
25978
26231
  if (existsSync22(napiPath)) {
@@ -25998,9 +26251,9 @@ async function checkAstGrepNapi() {
25998
26251
  function findCommentCheckerPackageBinary() {
25999
26252
  const binaryName = process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
26000
26253
  try {
26001
- const require2 = createRequire(import.meta.url);
26254
+ const require2 = createRequire2(import.meta.url);
26002
26255
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
26003
- const binaryPath = join18(dirname3(pkgPath), "bin", binaryName);
26256
+ const binaryPath = join19(dirname5(pkgPath), "bin", binaryName);
26004
26257
  if (existsSync21(binaryPath))
26005
26258
  return binaryPath;
26006
26259
  } catch {}
@@ -26120,7 +26373,7 @@ init_jsonc_parser();
26120
26373
  // src/tools/lsp/server-installation.ts
26121
26374
  init_shared();
26122
26375
  import { existsSync as existsSync22 } from "fs";
26123
- import { join as join19 } from "path";
26376
+ import { join as join20 } from "path";
26124
26377
  function isServerInstalled(command) {
26125
26378
  if (command.length === 0)
26126
26379
  return false;
@@ -26148,23 +26401,23 @@ function isServerInstalled(command) {
26148
26401
  const paths = pathEnv.split(pathSeparator);
26149
26402
  for (const p2 of paths) {
26150
26403
  for (const suffix of exts) {
26151
- if (existsSync22(join19(p2, cmd + suffix))) {
26404
+ if (existsSync22(join20(p2, cmd + suffix))) {
26152
26405
  return true;
26153
26406
  }
26154
26407
  }
26155
26408
  }
26156
26409
  const cwd = process.cwd();
26157
26410
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
26158
- const dataDir = join19(getDataDir(), "opencode");
26411
+ const dataDir = join20(getDataDir(), "opencode");
26159
26412
  const additionalBases = [
26160
- join19(cwd, "node_modules", ".bin"),
26161
- join19(configDir, "bin"),
26162
- join19(configDir, "node_modules", ".bin"),
26163
- join19(dataDir, "bin")
26413
+ join20(cwd, "node_modules", ".bin"),
26414
+ join20(configDir, "bin"),
26415
+ join20(configDir, "node_modules", ".bin"),
26416
+ join20(dataDir, "bin")
26164
26417
  ];
26165
26418
  for (const base of additionalBases) {
26166
26419
  for (const suffix of exts) {
26167
- if (existsSync22(join19(base, cmd + suffix))) {
26420
+ if (existsSync22(join20(base, cmd + suffix))) {
26168
26421
  return true;
26169
26422
  }
26170
26423
  }
@@ -26200,13 +26453,13 @@ function getLspServerStats(servers) {
26200
26453
  init_shared();
26201
26454
  import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
26202
26455
  import { homedir as homedir8 } from "os";
26203
- import { join as join20 } from "path";
26456
+ import { join as join21 } from "path";
26204
26457
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
26205
26458
  function getMcpConfigPaths() {
26206
26459
  return [
26207
- join20(homedir8(), ".claude", ".mcp.json"),
26208
- join20(process.cwd(), ".mcp.json"),
26209
- join20(process.cwd(), ".claude", ".mcp.json")
26460
+ join21(homedir8(), ".claude", ".mcp.json"),
26461
+ join21(process.cwd(), ".mcp.json"),
26462
+ join21(process.cwd(), ".claude", ".mcp.json")
26210
26463
  ];
26211
26464
  }
26212
26465
  function loadUserMcpConfig() {
@@ -26618,10 +26871,10 @@ async function doctor(options = { mode: "default" }) {
26618
26871
  // src/features/mcp-oauth/storage.ts
26619
26872
  init_shared();
26620
26873
  import { chmodSync, existsSync as existsSync24, mkdirSync as mkdirSync3, readFileSync as readFileSync25, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
26621
- import { dirname as dirname4, join as join21 } from "path";
26874
+ import { dirname as dirname6, join as join22 } from "path";
26622
26875
  var STORAGE_FILE_NAME = "mcp-oauth.json";
26623
26876
  function getMcpOauthStoragePath() {
26624
- return join21(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
26877
+ return join22(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
26625
26878
  }
26626
26879
  function normalizeHost(serverHost) {
26627
26880
  let host = serverHost.trim();
@@ -26671,7 +26924,7 @@ function readStore() {
26671
26924
  function writeStore(store) {
26672
26925
  const filePath = getMcpOauthStoragePath();
26673
26926
  try {
26674
- const dir = dirname4(filePath);
26927
+ const dir = dirname6(filePath);
26675
26928
  if (!existsSync24(dir)) {
26676
26929
  mkdirSync3(dir, { recursive: true });
26677
26930
  }