oh-my-opencode 3.17.0 → 3.17.2

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 (30) hide show
  1. package/README.ja.md +4 -0
  2. package/README.ko.md +4 -0
  3. package/README.ru.md +4 -0
  4. package/README.zh-cn.md +4 -0
  5. package/dist/cli/doctor/spawn-with-timeout.d.ts +8 -0
  6. package/dist/cli/index.js +714 -460
  7. package/dist/cli/install-validators.d.ts +1 -0
  8. package/dist/cli/model-fallback-types.d.ts +1 -0
  9. package/dist/cli/provider-model-id-transform.d.ts +1 -1
  10. package/dist/cli/types.d.ts +3 -0
  11. package/dist/create-tools.d.ts +2 -1
  12. package/dist/features/background-agent/session-existence.d.ts +1 -1
  13. package/dist/features/background-agent/subagent-spawn-limits.d.ts +1 -1
  14. package/dist/features/background-agent/task-poller.d.ts +1 -0
  15. package/dist/features/builtin-commands/commands.d.ts +2 -1
  16. package/dist/hooks/atlas/system-reminder-templates.d.ts +2 -2
  17. package/dist/hooks/directory-agents-injector/hook.d.ts +7 -7
  18. package/dist/hooks/directory-readme-injector/hook.d.ts +7 -7
  19. package/dist/hooks/model-fallback/next-fallback.d.ts +8 -0
  20. package/dist/index.js +752 -446
  21. package/dist/openclaw/config.d.ts +1 -1
  22. package/dist/openclaw/dispatcher.d.ts +0 -1
  23. package/dist/openclaw/gateway-url-validation.d.ts +1 -0
  24. package/dist/tools/delegate-task/delegated-model-config.d.ts +3 -0
  25. package/dist/tools/delegate-task/fallback-entry-resolution.d.ts +12 -0
  26. package/dist/tools/delegate-task/fallback-entry-settings.d.ts +7 -0
  27. package/dist/tools/delegate-task/subagent-discovery.d.ts +15 -0
  28. package/dist/tools/delegate-task/sync-task-fallback.d.ts +12 -0
  29. package/dist/tools/skill/constants.d.ts +1 -1
  30. package/package.json +12 -12
package/dist/cli/index.js CHANGED
@@ -5036,7 +5036,7 @@ var init_context_limit_resolver = () => {};
5036
5036
 
5037
5037
  // src/shared/normalize-sdk-response.ts
5038
5038
  function normalizeSDKResponse(response, fallback, options) {
5039
- if (response === null || response === undefined) {
5039
+ if (response == null) {
5040
5040
  return fallback;
5041
5041
  }
5042
5042
  if (Array.isArray(response)) {
@@ -5044,7 +5044,7 @@ function normalizeSDKResponse(response, fallback, options) {
5044
5044
  }
5045
5045
  if (typeof response === "object" && "data" in response) {
5046
5046
  const data = response.data;
5047
- if (data !== null && data !== undefined) {
5047
+ if (data != null) {
5048
5048
  return data;
5049
5049
  }
5050
5050
  if (options?.preferResponseOnMissingData === true) {
@@ -6049,20 +6049,26 @@ var init_agent_names = __esm(() => {
6049
6049
  omo: "sisyphus",
6050
6050
  OmO: "sisyphus",
6051
6051
  Sisyphus: "sisyphus",
6052
+ "Sisyphus (Ultraworker)": "sisyphus",
6052
6053
  sisyphus: "sisyphus",
6054
+ "Hephaestus (Deep Agent)": "hephaestus",
6053
6055
  "OmO-Plan": "prometheus",
6054
6056
  "omo-plan": "prometheus",
6055
6057
  "Planner-Sisyphus": "prometheus",
6056
6058
  "planner-sisyphus": "prometheus",
6057
6059
  "Prometheus - Plan Builder": "prometheus",
6060
+ "Prometheus (Plan Builder)": "prometheus",
6058
6061
  prometheus: "prometheus",
6059
6062
  "orchestrator-sisyphus": "atlas",
6060
6063
  Atlas: "atlas",
6064
+ "Atlas (Plan Executor)": "atlas",
6061
6065
  atlas: "atlas",
6062
6066
  "plan-consultant": "metis",
6063
6067
  "Metis - Plan Consultant": "metis",
6068
+ "Metis (Plan Consultant)": "metis",
6064
6069
  metis: "metis",
6065
6070
  "Momus - Plan Critic": "momus",
6071
+ "Momus (Plan Critic)": "momus",
6066
6072
  momus: "momus",
6067
6073
  "Sisyphus-Junior": "sisyphus-junior",
6068
6074
  "sisyphus-junior": "sisyphus-junior",
@@ -6160,7 +6166,7 @@ var init_model_versions = __esm(() => {
6160
6166
  var init_agent_category = () => {};
6161
6167
 
6162
6168
  // src/shared/write-file-atomically.ts
6163
- import { closeSync, fsyncSync, openSync, renameSync, writeFileSync } from "fs";
6169
+ import { closeSync, fsyncSync, openSync, renameSync, unlinkSync, writeFileSync } from "fs";
6164
6170
  function writeFileAtomically(filePath, content) {
6165
6171
  const tempPath = `${filePath}.tmp`;
6166
6172
  writeFileSync(tempPath, content, "utf-8");
@@ -6170,7 +6176,18 @@ function writeFileAtomically(filePath, content) {
6170
6176
  } finally {
6171
6177
  closeSync(tempFileDescriptor);
6172
6178
  }
6173
- renameSync(tempPath, filePath);
6179
+ try {
6180
+ renameSync(tempPath, filePath);
6181
+ } catch (error) {
6182
+ const isWindows = process.platform === "win32";
6183
+ const isPermissionError = error instanceof Error && (error.message.includes("EPERM") || error.message.includes("EACCES"));
6184
+ if (isWindows && isPermissionError) {
6185
+ unlinkSync(filePath);
6186
+ renameSync(tempPath, filePath);
6187
+ } else {
6188
+ throw error;
6189
+ }
6190
+ }
6174
6191
  }
6175
6192
  var init_write_file_atomically = () => {};
6176
6193
 
@@ -6591,6 +6608,12 @@ var init_zip_extractor = __esm(() => {
6591
6608
  });
6592
6609
 
6593
6610
  // src/shared/binary-downloader.ts
6611
+ import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "fs";
6612
+ import * as path4 from "path";
6613
+ function getCachedBinaryPath(cacheDir, binaryName) {
6614
+ const binaryPath = path4.join(cacheDir, binaryName);
6615
+ return existsSync5(binaryPath) ? binaryPath : null;
6616
+ }
6594
6617
  var init_binary_downloader = __esm(() => {
6595
6618
  init_archive_entry_validator();
6596
6619
  init_zip_extractor();
@@ -6603,11 +6626,11 @@ var init_model_requirements = __esm(() => {
6603
6626
  sisyphus: {
6604
6627
  fallbackChain: [
6605
6628
  {
6606
- providers: ["anthropic", "github-copilot", "opencode"],
6629
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6607
6630
  model: "claude-opus-4-6",
6608
6631
  variant: "max"
6609
6632
  },
6610
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6633
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6611
6634
  { providers: ["kimi-for-coding"], model: "k2p5" },
6612
6635
  {
6613
6636
  providers: [
@@ -6616,12 +6639,13 @@ var init_model_requirements = __esm(() => {
6616
6639
  "moonshotai-cn",
6617
6640
  "firmware",
6618
6641
  "ollama-cloud",
6619
- "aihubmix"
6642
+ "aihubmix",
6643
+ "vercel"
6620
6644
  ],
6621
6645
  model: "kimi-k2.5"
6622
6646
  },
6623
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4", variant: "medium" },
6624
- { providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
6647
+ { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" },
6648
+ { providers: ["zai-coding-plan", "opencode", "vercel"], model: "glm-5" },
6625
6649
  { providers: ["opencode"], model: "big-pickle" }
6626
6650
  ],
6627
6651
  requiresAnyModel: true
@@ -6629,73 +6653,73 @@ var init_model_requirements = __esm(() => {
6629
6653
  hephaestus: {
6630
6654
  fallbackChain: [
6631
6655
  {
6632
- providers: ["openai", "github-copilot", "venice", "opencode"],
6656
+ providers: ["openai", "github-copilot", "venice", "opencode", "vercel"],
6633
6657
  model: "gpt-5.4",
6634
6658
  variant: "medium"
6635
6659
  }
6636
6660
  ],
6637
- requiresProvider: ["openai", "github-copilot", "venice", "opencode"]
6661
+ requiresProvider: ["openai", "github-copilot", "venice", "opencode", "vercel"]
6638
6662
  },
6639
6663
  oracle: {
6640
6664
  fallbackChain: [
6641
6665
  {
6642
- providers: ["openai", "github-copilot", "opencode"],
6666
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6643
6667
  model: "gpt-5.4",
6644
6668
  variant: "high"
6645
6669
  },
6646
6670
  {
6647
- providers: ["google", "github-copilot", "opencode"],
6671
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6648
6672
  model: "gemini-3.1-pro",
6649
6673
  variant: "high"
6650
6674
  },
6651
6675
  {
6652
- providers: ["anthropic", "github-copilot", "opencode"],
6676
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6653
6677
  model: "claude-opus-4-6",
6654
6678
  variant: "max"
6655
6679
  },
6656
- { providers: ["opencode-go"], model: "glm-5" }
6680
+ { providers: ["opencode-go", "vercel"], model: "glm-5" }
6657
6681
  ]
6658
6682
  },
6659
6683
  librarian: {
6660
6684
  fallbackChain: [
6661
- { providers: ["opencode-go"], model: "minimax-m2.7" },
6662
- { providers: ["opencode"], model: "minimax-m2.7-highspeed" },
6663
- { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
6664
- { providers: ["opencode"], model: "gpt-5-nano" }
6685
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6686
+ { providers: ["opencode", "vercel"], model: "minimax-m2.7-highspeed" },
6687
+ { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6688
+ { providers: ["opencode", "vercel"], model: "gpt-5-nano" }
6665
6689
  ]
6666
6690
  },
6667
6691
  explore: {
6668
6692
  fallbackChain: [
6669
- { providers: ["github-copilot", "xai"], model: "grok-code-fast-1" },
6670
- { providers: ["opencode-go"], model: "minimax-m2.7-highspeed" },
6671
- { providers: ["opencode"], model: "minimax-m2.7" },
6672
- { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
6673
- { providers: ["opencode"], model: "gpt-5-nano" }
6693
+ { providers: ["github-copilot", "xai", "vercel"], model: "grok-code-fast-1" },
6694
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7-highspeed" },
6695
+ { providers: ["opencode", "vercel"], model: "minimax-m2.7" },
6696
+ { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6697
+ { providers: ["opencode", "vercel"], model: "gpt-5-nano" }
6674
6698
  ]
6675
6699
  },
6676
6700
  "multimodal-looker": {
6677
6701
  fallbackChain: [
6678
- { providers: ["openai", "opencode"], model: "gpt-5.4", variant: "medium" },
6679
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6680
- { providers: ["zai-coding-plan"], model: "glm-4.6v" },
6681
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5-nano" }
6702
+ { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4", variant: "medium" },
6703
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6704
+ { providers: ["zai-coding-plan", "vercel"], model: "glm-4.6v" },
6705
+ { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5-nano" }
6682
6706
  ]
6683
6707
  },
6684
6708
  prometheus: {
6685
6709
  fallbackChain: [
6686
6710
  {
6687
- providers: ["anthropic", "github-copilot", "opencode"],
6711
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6688
6712
  model: "claude-opus-4-6",
6689
6713
  variant: "max"
6690
6714
  },
6691
6715
  {
6692
- providers: ["openai", "github-copilot", "opencode"],
6716
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6693
6717
  model: "gpt-5.4",
6694
6718
  variant: "high"
6695
6719
  },
6696
- { providers: ["opencode-go"], model: "glm-5" },
6720
+ { providers: ["opencode-go", "vercel"], model: "glm-5" },
6697
6721
  {
6698
- providers: ["google", "github-copilot", "opencode"],
6722
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6699
6723
  model: "gemini-3.1-pro"
6700
6724
  }
6701
6725
  ]
@@ -6703,61 +6727,61 @@ var init_model_requirements = __esm(() => {
6703
6727
  metis: {
6704
6728
  fallbackChain: [
6705
6729
  {
6706
- providers: ["anthropic", "github-copilot", "opencode"],
6730
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6707
6731
  model: "claude-opus-4-6",
6708
6732
  variant: "max"
6709
6733
  },
6710
6734
  {
6711
- providers: ["openai", "github-copilot", "opencode"],
6735
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6712
6736
  model: "gpt-5.4",
6713
6737
  variant: "high"
6714
6738
  },
6715
- { providers: ["opencode-go"], model: "glm-5" },
6739
+ { providers: ["opencode-go", "vercel"], model: "glm-5" },
6716
6740
  { providers: ["kimi-for-coding"], model: "k2p5" }
6717
6741
  ]
6718
6742
  },
6719
6743
  momus: {
6720
6744
  fallbackChain: [
6721
6745
  {
6722
- providers: ["openai", "github-copilot", "opencode"],
6746
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6723
6747
  model: "gpt-5.4",
6724
6748
  variant: "xhigh"
6725
6749
  },
6726
6750
  {
6727
- providers: ["anthropic", "github-copilot", "opencode"],
6751
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6728
6752
  model: "claude-opus-4-6",
6729
6753
  variant: "max"
6730
6754
  },
6731
6755
  {
6732
- providers: ["google", "github-copilot", "opencode"],
6756
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6733
6757
  model: "gemini-3.1-pro",
6734
6758
  variant: "high"
6735
6759
  },
6736
- { providers: ["opencode-go"], model: "glm-5" }
6760
+ { providers: ["opencode-go", "vercel"], model: "glm-5" }
6737
6761
  ]
6738
6762
  },
6739
6763
  atlas: {
6740
6764
  fallbackChain: [
6741
- { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
6742
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6765
+ { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" },
6766
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6743
6767
  {
6744
- providers: ["openai", "github-copilot", "opencode"],
6768
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6745
6769
  model: "gpt-5.4",
6746
6770
  variant: "medium"
6747
6771
  },
6748
- { providers: ["opencode-go"], model: "minimax-m2.7" }
6772
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" }
6749
6773
  ]
6750
6774
  },
6751
6775
  "sisyphus-junior": {
6752
6776
  fallbackChain: [
6753
- { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
6754
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6777
+ { providers: ["anthropic", "github-copilot", "opencode", "vercel"], model: "claude-sonnet-4-6" },
6778
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6755
6779
  {
6756
- providers: ["openai", "github-copilot", "opencode"],
6780
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6757
6781
  model: "gpt-5.4",
6758
6782
  variant: "medium"
6759
6783
  },
6760
- { providers: ["opencode-go"], model: "minimax-m2.7" },
6784
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6761
6785
  { providers: ["opencode"], model: "big-pickle" }
6762
6786
  ]
6763
6787
  }
@@ -6766,54 +6790,54 @@ var init_model_requirements = __esm(() => {
6766
6790
  "visual-engineering": {
6767
6791
  fallbackChain: [
6768
6792
  {
6769
- providers: ["google", "github-copilot", "opencode"],
6793
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6770
6794
  model: "gemini-3.1-pro",
6771
6795
  variant: "high"
6772
6796
  },
6773
- { providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
6797
+ { providers: ["zai-coding-plan", "opencode", "vercel"], model: "glm-5" },
6774
6798
  {
6775
- providers: ["anthropic", "github-copilot", "opencode"],
6799
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6776
6800
  model: "claude-opus-4-6",
6777
6801
  variant: "max"
6778
6802
  },
6779
- { providers: ["opencode-go"], model: "glm-5" },
6803
+ { providers: ["opencode-go", "vercel"], model: "glm-5" },
6780
6804
  { providers: ["kimi-for-coding"], model: "k2p5" }
6781
6805
  ]
6782
6806
  },
6783
6807
  ultrabrain: {
6784
6808
  fallbackChain: [
6785
6809
  {
6786
- providers: ["openai", "opencode"],
6810
+ providers: ["openai", "opencode", "vercel"],
6787
6811
  model: "gpt-5.4",
6788
6812
  variant: "xhigh"
6789
6813
  },
6790
6814
  {
6791
- providers: ["google", "github-copilot", "opencode"],
6815
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6792
6816
  model: "gemini-3.1-pro",
6793
6817
  variant: "high"
6794
6818
  },
6795
6819
  {
6796
- providers: ["anthropic", "github-copilot", "opencode"],
6820
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6797
6821
  model: "claude-opus-4-6",
6798
6822
  variant: "max"
6799
6823
  },
6800
- { providers: ["opencode-go"], model: "glm-5" }
6824
+ { providers: ["opencode-go", "vercel"], model: "glm-5" }
6801
6825
  ]
6802
6826
  },
6803
6827
  deep: {
6804
6828
  fallbackChain: [
6805
6829
  {
6806
- providers: ["openai", "github-copilot", "venice", "opencode"],
6830
+ providers: ["openai", "github-copilot", "venice", "opencode", "vercel"],
6807
6831
  model: "gpt-5.4",
6808
6832
  variant: "medium"
6809
6833
  },
6810
6834
  {
6811
- providers: ["anthropic", "github-copilot", "opencode"],
6835
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6812
6836
  model: "claude-opus-4-6",
6813
6837
  variant: "max"
6814
6838
  },
6815
6839
  {
6816
- providers: ["google", "github-copilot", "opencode"],
6840
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6817
6841
  model: "gemini-3.1-pro",
6818
6842
  variant: "high"
6819
6843
  }
@@ -6822,72 +6846,72 @@ var init_model_requirements = __esm(() => {
6822
6846
  artistry: {
6823
6847
  fallbackChain: [
6824
6848
  {
6825
- providers: ["google", "github-copilot", "opencode"],
6849
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6826
6850
  model: "gemini-3.1-pro",
6827
6851
  variant: "high"
6828
6852
  },
6829
6853
  {
6830
- providers: ["anthropic", "github-copilot", "opencode"],
6854
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6831
6855
  model: "claude-opus-4-6",
6832
6856
  variant: "max"
6833
6857
  },
6834
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4" }
6858
+ { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.4" }
6835
6859
  ],
6836
6860
  requiresModel: "gemini-3.1-pro"
6837
6861
  },
6838
6862
  quick: {
6839
6863
  fallbackChain: [
6840
6864
  {
6841
- providers: ["openai", "github-copilot", "opencode"],
6865
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6842
6866
  model: "gpt-5.4-mini"
6843
6867
  },
6844
6868
  {
6845
- providers: ["anthropic", "github-copilot", "opencode"],
6869
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6846
6870
  model: "claude-haiku-4-5"
6847
6871
  },
6848
6872
  {
6849
- providers: ["google", "github-copilot", "opencode"],
6873
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6850
6874
  model: "gemini-3-flash"
6851
6875
  },
6852
- { providers: ["opencode-go"], model: "minimax-m2.7" },
6853
- { providers: ["opencode"], model: "gpt-5-nano" }
6876
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6877
+ { providers: ["opencode", "vercel"], model: "gpt-5-nano" }
6854
6878
  ]
6855
6879
  },
6856
6880
  "unspecified-low": {
6857
6881
  fallbackChain: [
6858
6882
  {
6859
- providers: ["anthropic", "github-copilot", "opencode"],
6883
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6860
6884
  model: "claude-sonnet-4-6"
6861
6885
  },
6862
6886
  {
6863
- providers: ["openai", "opencode"],
6887
+ providers: ["openai", "opencode", "vercel"],
6864
6888
  model: "gpt-5.3-codex",
6865
6889
  variant: "medium"
6866
6890
  },
6867
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6891
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6868
6892
  {
6869
- providers: ["google", "github-copilot", "opencode"],
6893
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6870
6894
  model: "gemini-3-flash"
6871
6895
  },
6872
- { providers: ["opencode-go"], model: "minimax-m2.7" }
6896
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" }
6873
6897
  ]
6874
6898
  },
6875
6899
  "unspecified-high": {
6876
6900
  fallbackChain: [
6877
6901
  {
6878
- providers: ["anthropic", "github-copilot", "opencode"],
6902
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6879
6903
  model: "claude-opus-4-6",
6880
6904
  variant: "max"
6881
6905
  },
6882
6906
  {
6883
- providers: ["openai", "github-copilot", "opencode"],
6907
+ providers: ["openai", "github-copilot", "opencode", "vercel"],
6884
6908
  model: "gpt-5.4",
6885
6909
  variant: "high"
6886
6910
  },
6887
- { providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
6911
+ { providers: ["zai-coding-plan", "opencode", "vercel"], model: "glm-5" },
6888
6912
  { providers: ["kimi-for-coding"], model: "k2p5" },
6889
- { providers: ["opencode-go"], model: "glm-5" },
6890
- { providers: ["opencode"], model: "kimi-k2.5" },
6913
+ { providers: ["opencode-go", "vercel"], model: "glm-5" },
6914
+ { providers: ["opencode", "vercel"], model: "kimi-k2.5" },
6891
6915
  {
6892
6916
  providers: [
6893
6917
  "opencode",
@@ -6895,7 +6919,8 @@ var init_model_requirements = __esm(() => {
6895
6919
  "moonshotai-cn",
6896
6920
  "firmware",
6897
6921
  "ollama-cloud",
6898
- "aihubmix"
6922
+ "aihubmix",
6923
+ "vercel"
6899
6924
  ],
6900
6925
  model: "kimi-k2.5"
6901
6926
  }
@@ -6904,15 +6929,15 @@ var init_model_requirements = __esm(() => {
6904
6929
  writing: {
6905
6930
  fallbackChain: [
6906
6931
  {
6907
- providers: ["google", "github-copilot", "opencode"],
6932
+ providers: ["google", "github-copilot", "opencode", "vercel"],
6908
6933
  model: "gemini-3-flash"
6909
6934
  },
6910
- { providers: ["opencode-go"], model: "kimi-k2.5" },
6935
+ { providers: ["opencode-go", "vercel"], model: "kimi-k2.5" },
6911
6936
  {
6912
- providers: ["anthropic", "github-copilot", "opencode"],
6937
+ providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6913
6938
  model: "claude-sonnet-4-6"
6914
6939
  },
6915
- { providers: ["opencode-go"], model: "minimax-m2.7" }
6940
+ { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" }
6916
6941
  ]
6917
6942
  }
6918
6943
  };
@@ -6956,20 +6981,20 @@ function normalizeModelID(modelID) {
6956
6981
  }
6957
6982
 
6958
6983
  // src/shared/json-file-cache-store.ts
6959
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
6960
- import { join as join6 } from "path";
6984
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
6985
+ import { join as join7 } from "path";
6961
6986
  function toLogLabel(cacheLabel) {
6962
6987
  return cacheLabel.toLowerCase();
6963
6988
  }
6964
6989
  function createJsonFileCacheStore(options) {
6965
6990
  let memoryValue;
6966
6991
  function getCacheFilePath() {
6967
- return join6(options.getCacheDir(), options.filename);
6992
+ return join7(options.getCacheDir(), options.filename);
6968
6993
  }
6969
6994
  function ensureCacheDir() {
6970
6995
  const cacheDir = options.getCacheDir();
6971
- if (!existsSync5(cacheDir)) {
6972
- mkdirSync3(cacheDir, { recursive: true });
6996
+ if (!existsSync6(cacheDir)) {
6997
+ mkdirSync4(cacheDir, { recursive: true });
6973
6998
  }
6974
6999
  }
6975
7000
  function read() {
@@ -6977,7 +7002,7 @@ function createJsonFileCacheStore(options) {
6977
7002
  return memoryValue;
6978
7003
  }
6979
7004
  const cacheFile = getCacheFilePath();
6980
- if (!existsSync5(cacheFile)) {
7005
+ if (!existsSync6(cacheFile)) {
6981
7006
  memoryValue = null;
6982
7007
  log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
6983
7008
  return null;
@@ -6997,7 +7022,7 @@ function createJsonFileCacheStore(options) {
6997
7022
  }
6998
7023
  }
6999
7024
  function has() {
7000
- return existsSync5(getCacheFilePath());
7025
+ return existsSync6(getCacheFilePath());
7001
7026
  }
7002
7027
  function write(value) {
7003
7028
  ensureCacheDir();
@@ -7166,14 +7191,14 @@ var init_connected_providers_cache = __esm(() => {
7166
7191
  });
7167
7192
 
7168
7193
  // src/shared/model-availability.ts
7169
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
7170
- import { join as join7 } from "path";
7194
+ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
7195
+ import { join as join8 } from "path";
7171
7196
  function isModelCacheAvailable() {
7172
7197
  if (hasProviderModelsCache()) {
7173
7198
  return true;
7174
7199
  }
7175
- const cacheFile = join7(getOpenCodeCacheDir(), "models.json");
7176
- return existsSync6(cacheFile);
7200
+ const cacheFile = join8(getOpenCodeCacheDir(), "models.json");
7201
+ return existsSync7(cacheFile);
7177
7202
  }
7178
7203
  var init_model_availability = __esm(() => {
7179
7204
  init_logger();
@@ -7182,21 +7207,14 @@ var init_model_availability = __esm(() => {
7182
7207
  });
7183
7208
 
7184
7209
  // src/shared/provider-model-id-transform.ts
7185
- function transformModelForProvider(provider, model) {
7186
- if (provider === "github-copilot") {
7187
- return model.replace("claude-opus-4-6", "claude-opus-4.6").replace("claude-sonnet-4-6", "claude-sonnet-4.6").replace("claude-sonnet-4-5", "claude-sonnet-4.5").replace("claude-haiku-4-5", "claude-haiku-4.5").replace("claude-sonnet-4", "claude-sonnet-4").replace(/gemini-3\.1-pro(?!-)/g, "gemini-3.1-pro-preview").replace(/gemini-3-flash(?!-)/g, "gemini-3-flash-preview");
7188
- }
7189
- if (provider === "google") {
7190
- return model.replace(/gemini-3\.1-pro(?!-)/g, "gemini-3.1-pro-preview").replace(/gemini-3-flash(?!-)/g, "gemini-3-flash-preview");
7191
- }
7192
- return model;
7193
- }
7210
+ var init_provider_model_id_transform = () => {};
7194
7211
 
7195
7212
  // src/shared/model-resolution-pipeline.ts
7196
7213
  var init_model_resolution_pipeline = __esm(() => {
7197
7214
  init_logger();
7198
7215
  init_connected_providers_cache();
7199
7216
  init_model_availability();
7217
+ init_provider_model_id_transform();
7200
7218
  });
7201
7219
 
7202
7220
  // src/shared/known-variants.ts
@@ -48469,19 +48487,19 @@ var init_constants = __esm(() => {
48469
48487
  });
48470
48488
 
48471
48489
  // src/shared/opencode-storage-paths.ts
48472
- import { join as join8 } from "path";
48490
+ import { join as join9 } from "path";
48473
48491
  var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
48474
48492
  var init_opencode_storage_paths = __esm(() => {
48475
48493
  init_data_path();
48476
48494
  OPENCODE_STORAGE = getOpenCodeStorageDir();
48477
- MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
48478
- PART_STORAGE = join8(OPENCODE_STORAGE, "part");
48479
- SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
48495
+ MESSAGE_STORAGE = join9(OPENCODE_STORAGE, "message");
48496
+ PART_STORAGE = join9(OPENCODE_STORAGE, "part");
48497
+ SESSION_STORAGE = join9(OPENCODE_STORAGE, "session");
48480
48498
  });
48481
48499
 
48482
48500
  // src/shared/compaction-marker.ts
48483
- import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync5 } from "fs";
48484
- import { join as join9 } from "path";
48501
+ import { existsSync as existsSync8, readdirSync, readFileSync as readFileSync5 } from "fs";
48502
+ import { join as join10 } from "path";
48485
48503
  function isCompactionPart(part) {
48486
48504
  return typeof part === "object" && part !== null && part.type === "compaction";
48487
48505
  }
@@ -48495,20 +48513,20 @@ function isCompactionMessage(message) {
48495
48513
  return isCompactionAgent(message.info?.agent ?? message.agent) || hasCompactionPart(message.parts);
48496
48514
  }
48497
48515
  function getCompactionPartStorageDir(messageID) {
48498
- return join9(PART_STORAGE, messageID);
48516
+ return join10(PART_STORAGE, messageID);
48499
48517
  }
48500
48518
  function hasCompactionPartInStorage(messageID) {
48501
48519
  if (!messageID) {
48502
48520
  return false;
48503
48521
  }
48504
48522
  const partDir = getCompactionPartStorageDir(messageID);
48505
- if (!existsSync7(partDir)) {
48523
+ if (!existsSync8(partDir)) {
48506
48524
  return false;
48507
48525
  }
48508
48526
  try {
48509
48527
  return readdirSync(partDir).filter((fileName) => fileName.endsWith(".json")).some((fileName) => {
48510
48528
  try {
48511
- const content = readFileSync5(join9(partDir, fileName), "utf-8");
48529
+ const content = readFileSync5(join10(partDir, fileName), "utf-8");
48512
48530
  return isCompactionPart(JSON.parse(content));
48513
48531
  } catch {
48514
48532
  return false;
@@ -48541,23 +48559,23 @@ var init_hook_message_injector = __esm(() => {
48541
48559
  });
48542
48560
 
48543
48561
  // src/shared/opencode-message-dir.ts
48544
- import { existsSync as existsSync8, readdirSync as readdirSync2 } from "fs";
48545
- import { join as join10 } from "path";
48562
+ import { existsSync as existsSync9, readdirSync as readdirSync2 } from "fs";
48563
+ import { join as join11 } from "path";
48546
48564
  function getMessageDir(sessionID) {
48547
48565
  if (!sessionID.startsWith("ses_"))
48548
48566
  return null;
48549
48567
  if (/[/\\]|\.\./.test(sessionID))
48550
48568
  return null;
48551
- if (!existsSync8(MESSAGE_STORAGE))
48569
+ if (!existsSync9(MESSAGE_STORAGE))
48552
48570
  return null;
48553
- const directPath = join10(MESSAGE_STORAGE, sessionID);
48554
- if (existsSync8(directPath)) {
48571
+ const directPath = join11(MESSAGE_STORAGE, sessionID);
48572
+ if (existsSync9(directPath)) {
48555
48573
  return directPath;
48556
48574
  }
48557
48575
  try {
48558
48576
  for (const dir of readdirSync2(MESSAGE_STORAGE)) {
48559
- const sessionPath = join10(MESSAGE_STORAGE, dir, sessionID);
48560
- if (existsSync8(sessionPath)) {
48577
+ const sessionPath = join11(MESSAGE_STORAGE, dir, sessionID);
48578
+ if (existsSync9(sessionPath)) {
48561
48579
  return sessionPath;
48562
48580
  }
48563
48581
  }
@@ -48590,7 +48608,7 @@ function getAgentDisplayName(configKey) {
48590
48608
  }
48591
48609
  return configKey;
48592
48610
  }
48593
- function getAgentConfigKey(agentName) {
48611
+ function resolveKnownAgentConfigKey(agentName) {
48594
48612
  const lower = stripAgentListSortPrefix(agentName).trim().toLowerCase();
48595
48613
  const reversed = REVERSE_DISPLAY_NAMES[lower];
48596
48614
  if (reversed !== undefined)
@@ -48600,7 +48618,11 @@ function getAgentConfigKey(agentName) {
48600
48618
  return legacy;
48601
48619
  if (AGENT_DISPLAY_NAMES[lower] !== undefined)
48602
48620
  return lower;
48603
- return lower;
48621
+ return;
48622
+ }
48623
+ function getAgentConfigKey(agentName) {
48624
+ const lower = stripAgentListSortPrefix(agentName).trim().toLowerCase();
48625
+ return resolveKnownAgentConfigKey(agentName) ?? lower;
48604
48626
  }
48605
48627
  var AGENT_DISPLAY_NAMES, INVISIBLE_AGENT_CHARACTERS_REGEX, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
48606
48628
  var init_agent_display_names = __esm(() => {
@@ -49088,18 +49110,18 @@ var init_plugin_name_with_version = __esm(() => {
49088
49110
  });
49089
49111
 
49090
49112
  // src/cli/config-manager/backup-config.ts
49091
- import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync4 } from "fs";
49113
+ import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "fs";
49092
49114
  import { dirname as dirname2 } from "path";
49093
49115
  function backupConfigFile(configPath) {
49094
- if (!existsSync9(configPath)) {
49116
+ if (!existsSync10(configPath)) {
49095
49117
  return { success: true };
49096
49118
  }
49097
49119
  const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
49098
49120
  const backupPath = `${configPath}.backup-${timestamp2}`;
49099
49121
  try {
49100
49122
  const dir = dirname2(backupPath);
49101
- if (!existsSync9(dir)) {
49102
- mkdirSync4(dir, { recursive: true });
49123
+ if (!existsSync10(dir)) {
49124
+ mkdirSync5(dir, { recursive: true });
49103
49125
  }
49104
49126
  copyFileSync2(configPath, backupPath);
49105
49127
  return { success: true, backupPath };
@@ -49113,11 +49135,11 @@ function backupConfigFile(configPath) {
49113
49135
  var init_backup_config = () => {};
49114
49136
 
49115
49137
  // src/cli/config-manager/ensure-config-directory-exists.ts
49116
- import { existsSync as existsSync10, mkdirSync as mkdirSync5 } from "fs";
49138
+ import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
49117
49139
  function ensureConfigDirectoryExists() {
49118
49140
  const configDir = getConfigDir();
49119
- if (!existsSync10(configDir)) {
49120
- mkdirSync5(configDir, { recursive: true });
49141
+ if (!existsSync11(configDir)) {
49142
+ mkdirSync6(configDir, { recursive: true });
49121
49143
  }
49122
49144
  }
49123
49145
  var init_ensure_config_directory_exists = __esm(() => {
@@ -49154,14 +49176,14 @@ function formatErrorWithSuggestion(err, context) {
49154
49176
  }
49155
49177
 
49156
49178
  // src/cli/config-manager/opencode-config-format.ts
49157
- import { existsSync as existsSync11 } from "fs";
49179
+ import { existsSync as existsSync12 } from "fs";
49158
49180
  function detectConfigFormat() {
49159
49181
  const configJsonc = getConfigJsonc();
49160
49182
  const configJson = getConfigJson();
49161
- if (existsSync11(configJsonc)) {
49183
+ if (existsSync12(configJsonc)) {
49162
49184
  return { format: "jsonc", path: configJsonc };
49163
49185
  }
49164
- if (existsSync11(configJson)) {
49186
+ if (existsSync12(configJson)) {
49165
49187
  return { format: "json", path: configJson };
49166
49188
  }
49167
49189
  return { format: "none", path: configJson };
@@ -49175,29 +49197,29 @@ import { readFileSync as readFileSync6, statSync } from "fs";
49175
49197
  function isEmptyOrWhitespace(content) {
49176
49198
  return content.trim().length === 0;
49177
49199
  }
49178
- function parseOpenCodeConfigFileWithError(path4) {
49200
+ function parseOpenCodeConfigFileWithError(path5) {
49179
49201
  try {
49180
- const stat = statSync(path4);
49202
+ const stat = statSync(path5);
49181
49203
  if (stat.size === 0) {
49182
- return { config: null, error: `Config file is empty: ${path4}. Delete it or add valid JSON content.` };
49204
+ return { config: null, error: `Config file is empty: ${path5}. Delete it or add valid JSON content.` };
49183
49205
  }
49184
- const content = readFileSync6(path4, "utf-8");
49206
+ const content = readFileSync6(path5, "utf-8");
49185
49207
  if (isEmptyOrWhitespace(content)) {
49186
- return { config: null, error: `Config file contains only whitespace: ${path4}. Delete it or add valid JSON content.` };
49208
+ return { config: null, error: `Config file contains only whitespace: ${path5}. Delete it or add valid JSON content.` };
49187
49209
  }
49188
49210
  const config = parseJsonc(content);
49189
- if (config === null || config === undefined) {
49190
- return { config: null, error: `Config file parsed to null/undefined: ${path4}. Ensure it contains valid JSON.` };
49211
+ if (config == null) {
49212
+ return { config: null, error: `Config file parsed to null/undefined: ${path5}. Ensure it contains valid JSON.` };
49191
49213
  }
49192
49214
  if (typeof config !== "object" || Array.isArray(config)) {
49193
49215
  return {
49194
49216
  config: null,
49195
- error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path4}`
49217
+ error: `Config file must contain a JSON object, not ${Array.isArray(config) ? "an array" : typeof config}: ${path5}`
49196
49218
  };
49197
49219
  }
49198
49220
  return { config };
49199
49221
  } catch (err) {
49200
- return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path4}`) };
49222
+ return { config: null, error: formatErrorWithSuggestion(err, `parse config file ${path5}`) };
49201
49223
  }
49202
49224
  }
49203
49225
  var init_parse_opencode_config_file = __esm(() => {
@@ -49298,20 +49320,20 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49298
49320
  error: formatErrorWithSuggestion(err, "create config directory")
49299
49321
  };
49300
49322
  }
49301
- const { format: format2, path: path4 } = detectConfigFormat();
49323
+ const { format: format2, path: path5 } = detectConfigFormat();
49302
49324
  const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME);
49303
49325
  try {
49304
49326
  if (format2 === "none") {
49305
49327
  const config2 = { plugin: [pluginEntry] };
49306
- writeFileSync3(path4, JSON.stringify(config2, null, 2) + `
49328
+ writeFileSync3(path5, JSON.stringify(config2, null, 2) + `
49307
49329
  `);
49308
- return { success: true, configPath: path4 };
49330
+ return { success: true, configPath: path5 };
49309
49331
  }
49310
- const parseResult = parseOpenCodeConfigFileWithError(path4);
49332
+ const parseResult = parseOpenCodeConfigFileWithError(path5);
49311
49333
  if (!parseResult.config) {
49312
49334
  return {
49313
49335
  success: false,
49314
- configPath: path4,
49336
+ configPath: path5,
49315
49337
  error: parseResult.error ?? "Failed to parse config file"
49316
49338
  };
49317
49339
  }
@@ -49327,28 +49349,24 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49327
49349
  if (!compatibility.canUpgrade) {
49328
49350
  return {
49329
49351
  success: false,
49330
- configPath: path4,
49352
+ configPath: path5,
49331
49353
  error: compatibility.reason ?? "Version compatibility check failed"
49332
49354
  };
49333
49355
  }
49334
- const backupResult = backupConfigFile(path4);
49356
+ const backupResult = backupConfigFile(path5);
49335
49357
  if (!backupResult.success) {
49336
49358
  return {
49337
49359
  success: false,
49338
- configPath: path4,
49360
+ configPath: path5,
49339
49361
  error: `Failed to create backup: ${backupResult.error}`
49340
49362
  };
49341
49363
  }
49342
49364
  }
49343
49365
  const normalizedPlugins = [...otherPlugins];
49344
- if (canonicalEntries.length > 0 || legacyEntries.length > 0) {
49345
- normalizedPlugins.push(pluginEntry);
49346
- } else {
49347
- normalizedPlugins.push(pluginEntry);
49348
- }
49366
+ normalizedPlugins.push(pluginEntry);
49349
49367
  config.plugin = normalizedPlugins;
49350
49368
  if (format2 === "jsonc") {
49351
- const content = readFileSync7(path4, "utf-8");
49369
+ const content = readFileSync7(path5, "utf-8");
49352
49370
  const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/;
49353
49371
  const match = content.match(pluginArrayRegex);
49354
49372
  if (match) {
@@ -49357,21 +49375,21 @@ async function addPluginToOpenCodeConfig(currentVersion) {
49357
49375
  const newContent = content.replace(pluginArrayRegex, `$1[
49358
49376
  ${formattedPlugins}
49359
49377
  ]`);
49360
- writeFileSync3(path4, newContent);
49378
+ writeFileSync3(path5, newContent);
49361
49379
  } else {
49362
49380
  const newContent = content.replace(/(\{)/, `$1
49363
49381
  "plugin": ["${pluginEntry}"],`);
49364
- writeFileSync3(path4, newContent);
49382
+ writeFileSync3(path5, newContent);
49365
49383
  }
49366
49384
  } else {
49367
- writeFileSync3(path4, JSON.stringify(config, null, 2) + `
49385
+ writeFileSync3(path5, JSON.stringify(config, null, 2) + `
49368
49386
  `);
49369
49387
  }
49370
- return { success: true, configPath: path4 };
49388
+ return { success: true, configPath: path5 };
49371
49389
  } catch (err) {
49372
49390
  return {
49373
49391
  success: false,
49374
- configPath: path4,
49392
+ configPath: path5,
49375
49393
  error: formatErrorWithSuggestion(err, "update opencode config")
49376
49394
  };
49377
49395
  }
@@ -49438,6 +49456,7 @@ function toProviderAvailability(config) {
49438
49456
  zai: config.hasZaiCodingPlan,
49439
49457
  kimiForCoding: config.hasKimiForCoding,
49440
49458
  opencodeGo: config.hasOpencodeGo,
49459
+ vercelAiGateway: config.hasVercelAiGateway,
49441
49460
  isMaxPlan: config.isMax20
49442
49461
  };
49443
49462
  }
@@ -49450,20 +49469,74 @@ function isProviderAvailable(provider, availability) {
49450
49469
  opencode: availability.opencodeZen,
49451
49470
  "zai-coding-plan": availability.zai,
49452
49471
  "kimi-for-coding": availability.kimiForCoding,
49453
- "opencode-go": availability.opencodeGo
49472
+ "opencode-go": availability.opencodeGo,
49473
+ vercel: availability.vercelAiGateway
49454
49474
  };
49455
49475
  return mapping[provider] ?? false;
49456
49476
  }
49457
49477
 
49458
49478
  // src/cli/provider-model-id-transform.ts
49459
- var init_provider_model_id_transform = () => {};
49479
+ function inferSubProvider(model) {
49480
+ if (model.startsWith("claude-"))
49481
+ return "anthropic";
49482
+ if (model.startsWith("gpt-"))
49483
+ return "openai";
49484
+ if (model.startsWith("gemini-"))
49485
+ return "google";
49486
+ if (model.startsWith("grok-"))
49487
+ return "xai";
49488
+ if (model.startsWith("minimax-"))
49489
+ return "minimax";
49490
+ if (model.startsWith("kimi-"))
49491
+ return "moonshotai";
49492
+ if (model.startsWith("glm-"))
49493
+ return "zai";
49494
+ return;
49495
+ }
49496
+ function claudeVersionDot(model) {
49497
+ return model.replace(CLAUDE_VERSION_DOT, "claude-$1-$2.$3");
49498
+ }
49499
+ function applyGatewayTransforms(model) {
49500
+ return claudeVersionDot(model).replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview");
49501
+ }
49502
+ function transformModelForProvider2(provider, model) {
49503
+ if (provider === "vercel") {
49504
+ const slashIndex = model.indexOf("/");
49505
+ if (slashIndex !== -1) {
49506
+ const subProvider2 = model.substring(0, slashIndex);
49507
+ const subModel = model.substring(slashIndex + 1);
49508
+ return `${subProvider2}/${applyGatewayTransforms(subModel)}`;
49509
+ }
49510
+ const subProvider = inferSubProvider(model);
49511
+ if (subProvider) {
49512
+ return `${subProvider}/${applyGatewayTransforms(model)}`;
49513
+ }
49514
+ return model;
49515
+ }
49516
+ if (provider === "github-copilot") {
49517
+ return claudeVersionDot(model).replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview").replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview");
49518
+ }
49519
+ if (provider === "google") {
49520
+ return model.replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview").replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview");
49521
+ }
49522
+ if (provider === "anthropic") {
49523
+ return claudeVersionDot(model);
49524
+ }
49525
+ return model;
49526
+ }
49527
+ var CLAUDE_VERSION_DOT, GEMINI_31_PRO_PREVIEW, GEMINI_3_FLASH_PREVIEW;
49528
+ var init_provider_model_id_transform2 = __esm(() => {
49529
+ CLAUDE_VERSION_DOT = /claude-(\w+)-(\d+)-(\d+)/g;
49530
+ GEMINI_31_PRO_PREVIEW = /gemini-3\.1-pro(?!-)/g;
49531
+ GEMINI_3_FLASH_PREVIEW = /gemini-3-flash(?!-)/g;
49532
+ });
49460
49533
 
49461
49534
  // src/cli/fallback-chain-resolution.ts
49462
49535
  function resolveModelFromChain(fallbackChain, availability) {
49463
49536
  for (const entry of fallbackChain) {
49464
49537
  for (const provider of entry.providers) {
49465
49538
  if (isProviderAvailable(provider, availability)) {
49466
- const transformedModel = transformModelForProvider(provider, entry.model);
49539
+ const transformedModel = transformModelForProvider2(provider, entry.model);
49467
49540
  return {
49468
49541
  model: `${provider}/${transformedModel}`,
49469
49542
  variant: entry.variant
@@ -49490,13 +49563,13 @@ function isRequiredProviderAvailable(requiredProviders, availability) {
49490
49563
  }
49491
49564
  var init_fallback_chain_resolution = __esm(() => {
49492
49565
  init_model_fallback_requirements();
49493
- init_provider_model_id_transform();
49566
+ init_provider_model_id_transform2();
49494
49567
  });
49495
49568
 
49496
49569
  // src/cli/model-fallback.ts
49497
49570
  function toFallbackModelObject(entry, provider) {
49498
49571
  return {
49499
- model: `${provider}/${transformModelForProvider(provider, entry.model)}`,
49572
+ model: `${provider}/${transformModelForProvider2(provider, entry.model)}`,
49500
49573
  ...entry.variant ? { variant: entry.variant } : {},
49501
49574
  ...entry.reasoningEffort ? { reasoningEffort: entry.reasoningEffort } : {},
49502
49575
  ...entry.temperature !== undefined ? { temperature: entry.temperature } : {},
@@ -49537,7 +49610,7 @@ function attachAllFallbackModels(config, fallbackChain, availability) {
49537
49610
  }
49538
49611
  function generateModelConfig(config) {
49539
49612
  const avail = toProviderAvailability(config);
49540
- const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai || avail.kimiForCoding || avail.opencodeGo;
49613
+ const hasAnyProvider = avail.native.claude || avail.native.openai || avail.native.gemini || avail.opencodeZen || avail.copilot || avail.zai || avail.kimiForCoding || avail.opencodeGo || avail.vercelAiGateway;
49541
49614
  if (!hasAnyProvider) {
49542
49615
  return {
49543
49616
  $schema: SCHEMA_URL,
@@ -49554,6 +49627,8 @@ function generateModelConfig(config) {
49554
49627
  agentConfig = { model: "opencode-go/minimax-m2.7" };
49555
49628
  } else if (avail.zai) {
49556
49629
  agentConfig = { model: ZAI_MODEL };
49630
+ } else if (avail.vercelAiGateway) {
49631
+ agentConfig = { model: "vercel/minimax/minimax-m2.7" };
49557
49632
  }
49558
49633
  if (agentConfig) {
49559
49634
  agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
@@ -49570,6 +49645,8 @@ function generateModelConfig(config) {
49570
49645
  agentConfig = { model: "opencode-go/minimax-m2.7" };
49571
49646
  } else if (avail.copilot) {
49572
49647
  agentConfig = { model: "github-copilot/gpt-5-mini" };
49648
+ } else if (avail.vercelAiGateway) {
49649
+ agentConfig = { model: "vercel/minimax/minimax-m2.7-highspeed" };
49573
49650
  } else {
49574
49651
  agentConfig = { model: "opencode/gpt-5-nano" };
49575
49652
  }
@@ -49633,7 +49710,7 @@ var init_model_fallback = __esm(() => {
49633
49710
  init_model_fallback_requirements();
49634
49711
  init_openai_only_model_catalog();
49635
49712
  init_fallback_chain_resolution();
49636
- init_provider_model_id_transform();
49713
+ init_provider_model_id_transform2();
49637
49714
  });
49638
49715
 
49639
49716
  // src/cli/config-manager/generate-omo-config.ts
@@ -49645,12 +49722,12 @@ var init_generate_omo_config = __esm(() => {
49645
49722
  });
49646
49723
 
49647
49724
  // src/shared/migrate-legacy-config-file.ts
49648
- import { existsSync as existsSync12, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
49649
- import { join as join11, dirname as dirname3, basename } from "path";
49725
+ import { existsSync as existsSync13, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
49726
+ import { join as join12, dirname as dirname3, basename } from "path";
49650
49727
  function buildCanonicalPath(legacyPath) {
49651
49728
  const dir = dirname3(legacyPath);
49652
49729
  const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
49653
- return join11(dir, `${CONFIG_BASENAME}${ext}`);
49730
+ return join12(dir, `${CONFIG_BASENAME}${ext}`);
49654
49731
  }
49655
49732
  function archiveLegacyConfigFile(legacyPath) {
49656
49733
  const backupPath = `${legacyPath}.bak`;
@@ -49682,12 +49759,12 @@ function archiveLegacyConfigFile(legacyPath) {
49682
49759
  }
49683
49760
  }
49684
49761
  function migrateLegacyConfigFile(legacyPath) {
49685
- if (!existsSync12(legacyPath))
49762
+ if (!existsSync13(legacyPath))
49686
49763
  return false;
49687
49764
  if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
49688
49765
  return false;
49689
49766
  const canonicalPath = buildCanonicalPath(legacyPath);
49690
- if (existsSync12(canonicalPath))
49767
+ if (existsSync13(canonicalPath))
49691
49768
  return false;
49692
49769
  try {
49693
49770
  const content = readFileSync8(legacyPath, "utf-8");
@@ -49698,7 +49775,7 @@ function migrateLegacyConfigFile(legacyPath) {
49698
49775
  to: canonicalPath,
49699
49776
  archivedLegacyConfig
49700
49777
  });
49701
- return archivedLegacyConfig;
49778
+ return true;
49702
49779
  } catch (error) {
49703
49780
  log("[migrateLegacyConfigFile] Failed to migrate legacy config file", { legacyPath, error });
49704
49781
  return false;
@@ -49728,8 +49805,8 @@ function deepMergeRecord(target, source) {
49728
49805
  }
49729
49806
 
49730
49807
  // src/cli/config-manager/write-omo-config.ts
49731
- import { existsSync as existsSync13, readFileSync as readFileSync9, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49732
- import { basename as basename2, dirname as dirname4, extname, join as join12 } from "path";
49808
+ import { existsSync as existsSync14, readFileSync as readFileSync9, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
49809
+ import { basename as basename2, dirname as dirname4, extname, join as join13 } from "path";
49733
49810
  function isEmptyOrWhitespace2(content) {
49734
49811
  return content.trim().length === 0;
49735
49812
  }
@@ -49744,12 +49821,12 @@ function writeOmoConfig(installConfig) {
49744
49821
  };
49745
49822
  }
49746
49823
  const detectedConfigPath = getOmoConfigPath();
49747
- const canonicalConfigPath = join12(dirname4(detectedConfigPath), `${CONFIG_BASENAME}${extname(detectedConfigPath) || ".json"}`);
49824
+ const canonicalConfigPath = join13(dirname4(detectedConfigPath), `${CONFIG_BASENAME}${extname(detectedConfigPath) || ".json"}`);
49748
49825
  const shouldMigrateLegacyPath = basename2(detectedConfigPath).startsWith(LEGACY_CONFIG_BASENAME);
49749
- const omoConfigPath = shouldMigrateLegacyPath ? migrateLegacyConfigFile(detectedConfigPath) || existsSync13(canonicalConfigPath) ? canonicalConfigPath : detectedConfigPath : detectedConfigPath;
49826
+ const omoConfigPath = shouldMigrateLegacyPath ? migrateLegacyConfigFile(detectedConfigPath) || existsSync14(canonicalConfigPath) ? canonicalConfigPath : detectedConfigPath : detectedConfigPath;
49750
49827
  try {
49751
49828
  const newConfig = generateOmoConfig(installConfig);
49752
- if (existsSync13(omoConfigPath)) {
49829
+ if (existsSync14(omoConfigPath)) {
49753
49830
  const backupResult = backupConfigFile(omoConfigPath);
49754
49831
  if (!backupResult.success) {
49755
49832
  return {
@@ -49903,16 +49980,17 @@ var init_opencode_binary = __esm(() => {
49903
49980
  });
49904
49981
 
49905
49982
  // src/cli/config-manager/detect-current-config.ts
49906
- import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
49983
+ import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
49907
49984
  function detectProvidersFromOmoConfig() {
49908
49985
  const omoConfigPath = getOmoConfigPath();
49909
- if (!existsSync14(omoConfigPath)) {
49986
+ if (!existsSync15(omoConfigPath)) {
49910
49987
  return {
49911
49988
  hasOpenAI: true,
49912
49989
  hasOpencodeZen: true,
49913
49990
  hasZaiCodingPlan: false,
49914
49991
  hasKimiForCoding: false,
49915
- hasOpencodeGo: false
49992
+ hasOpencodeGo: false,
49993
+ hasVercelAiGateway: false
49916
49994
  };
49917
49995
  }
49918
49996
  try {
@@ -49924,7 +50002,8 @@ function detectProvidersFromOmoConfig() {
49924
50002
  hasOpencodeZen: true,
49925
50003
  hasZaiCodingPlan: false,
49926
50004
  hasKimiForCoding: false,
49927
- hasOpencodeGo: false
50005
+ hasOpencodeGo: false,
50006
+ hasVercelAiGateway: false
49928
50007
  };
49929
50008
  }
49930
50009
  const configStr = JSON.stringify(omoConfig);
@@ -49933,14 +50012,16 @@ function detectProvidersFromOmoConfig() {
49933
50012
  const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/');
49934
50013
  const hasKimiForCoding = configStr.includes('"kimi-for-coding/');
49935
50014
  const hasOpencodeGo = configStr.includes('"opencode-go/');
49936
- return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo };
50015
+ const hasVercelAiGateway = configStr.includes('"vercel/');
50016
+ return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo, hasVercelAiGateway };
49937
50017
  } catch {
49938
50018
  return {
49939
50019
  hasOpenAI: true,
49940
50020
  hasOpencodeZen: true,
49941
50021
  hasZaiCodingPlan: false,
49942
50022
  hasKimiForCoding: false,
49943
- hasOpencodeGo: false
50023
+ hasOpencodeGo: false,
50024
+ hasVercelAiGateway: false
49944
50025
  };
49945
50026
  }
49946
50027
  }
@@ -49962,13 +50043,14 @@ function detectCurrentConfig() {
49962
50043
  hasOpencodeZen: true,
49963
50044
  hasZaiCodingPlan: false,
49964
50045
  hasKimiForCoding: false,
49965
- hasOpencodeGo: false
50046
+ hasOpencodeGo: false,
50047
+ hasVercelAiGateway: false
49966
50048
  };
49967
- const { format: format2, path: path4 } = detectConfigFormat();
50049
+ const { format: format2, path: path5 } = detectConfigFormat();
49968
50050
  if (format2 === "none") {
49969
50051
  return result;
49970
50052
  }
49971
- const parseResult = parseOpenCodeConfigFileWithError(path4);
50053
+ const parseResult = parseOpenCodeConfigFileWithError(path5);
49972
50054
  if (!parseResult.config) {
49973
50055
  return result;
49974
50056
  }
@@ -49984,12 +50066,13 @@ function detectCurrentConfig() {
49984
50066
  }
49985
50067
  const providers = openCodeConfig.provider;
49986
50068
  result.hasGemini = providers ? "google" in providers : false;
49987
- const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo } = detectProvidersFromOmoConfig();
50069
+ const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding, hasOpencodeGo, hasVercelAiGateway } = detectProvidersFromOmoConfig();
49988
50070
  result.hasOpenAI = hasOpenAI;
49989
50071
  result.hasOpencodeZen = hasOpencodeZen;
49990
50072
  result.hasZaiCodingPlan = hasZaiCodingPlan;
49991
50073
  result.hasKimiForCoding = hasKimiForCoding;
49992
50074
  result.hasOpencodeGo = hasOpencodeGo;
50075
+ result.hasVercelAiGateway = hasVercelAiGateway;
49993
50076
  return result;
49994
50077
  }
49995
50078
  var init_detect_current_config = __esm(() => {
@@ -50000,10 +50083,10 @@ var init_detect_current_config = __esm(() => {
50000
50083
  });
50001
50084
 
50002
50085
  // src/cli/config-manager/bun-install.ts
50003
- import { existsSync as existsSync15 } from "fs";
50004
- import { join as join13 } from "path";
50086
+ import { existsSync as existsSync16 } from "fs";
50087
+ import { join as join14 } from "path";
50005
50088
  function getDefaultWorkspaceDir() {
50006
- return join13(getOpenCodeCacheDir(), "packages");
50089
+ return join14(getOpenCodeCacheDir(), "packages");
50007
50090
  }
50008
50091
  function readProcessOutput(stream) {
50009
50092
  if (!stream) {
@@ -50029,7 +50112,7 @@ async function runBunInstallWithDetails(options) {
50029
50112
  const outputMode = options?.outputMode ?? "pipe";
50030
50113
  const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
50031
50114
  const packageJsonPath = `${cacheDir}/package.json`;
50032
- if (!existsSync15(packageJsonPath)) {
50115
+ if (!existsSync16(packageJsonPath)) {
50033
50116
  return {
50034
50117
  success: false,
50035
50118
  error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
@@ -50171,7 +50254,7 @@ var require_windows = __commonJS((exports2, module) => {
50171
50254
  module.exports = isexe;
50172
50255
  isexe.sync = sync;
50173
50256
  var fs5 = __require("fs");
50174
- function checkPathExt(path5, options) {
50257
+ function checkPathExt(path6, options) {
50175
50258
  var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
50176
50259
  if (!pathext) {
50177
50260
  return true;
@@ -50182,25 +50265,25 @@ var require_windows = __commonJS((exports2, module) => {
50182
50265
  }
50183
50266
  for (var i2 = 0;i2 < pathext.length; i2++) {
50184
50267
  var p2 = pathext[i2].toLowerCase();
50185
- if (p2 && path5.substr(-p2.length).toLowerCase() === p2) {
50268
+ if (p2 && path6.substr(-p2.length).toLowerCase() === p2) {
50186
50269
  return true;
50187
50270
  }
50188
50271
  }
50189
50272
  return false;
50190
50273
  }
50191
- function checkStat(stat, path5, options) {
50274
+ function checkStat(stat, path6, options) {
50192
50275
  if (!stat.isSymbolicLink() && !stat.isFile()) {
50193
50276
  return false;
50194
50277
  }
50195
- return checkPathExt(path5, options);
50278
+ return checkPathExt(path6, options);
50196
50279
  }
50197
- function isexe(path5, options, cb) {
50198
- fs5.stat(path5, function(er, stat) {
50199
- cb(er, er ? false : checkStat(stat, path5, options));
50280
+ function isexe(path6, options, cb) {
50281
+ fs5.stat(path6, function(er, stat) {
50282
+ cb(er, er ? false : checkStat(stat, path6, options));
50200
50283
  });
50201
50284
  }
50202
- function sync(path5, options) {
50203
- return checkStat(fs5.statSync(path5), path5, options);
50285
+ function sync(path6, options) {
50286
+ return checkStat(fs5.statSync(path6), path6, options);
50204
50287
  }
50205
50288
  });
50206
50289
 
@@ -50209,13 +50292,13 @@ var require_mode = __commonJS((exports2, module) => {
50209
50292
  module.exports = isexe;
50210
50293
  isexe.sync = sync;
50211
50294
  var fs5 = __require("fs");
50212
- function isexe(path5, options, cb) {
50213
- fs5.stat(path5, function(er, stat) {
50295
+ function isexe(path6, options, cb) {
50296
+ fs5.stat(path6, function(er, stat) {
50214
50297
  cb(er, er ? false : checkStat(stat, options));
50215
50298
  });
50216
50299
  }
50217
- function sync(path5, options) {
50218
- return checkStat(fs5.statSync(path5), options);
50300
+ function sync(path6, options) {
50301
+ return checkStat(fs5.statSync(path6), options);
50219
50302
  }
50220
50303
  function checkStat(stat, options) {
50221
50304
  return stat.isFile() && checkMode(stat, options);
@@ -50246,7 +50329,7 @@ var require_isexe = __commonJS((exports2, module) => {
50246
50329
  }
50247
50330
  module.exports = isexe;
50248
50331
  isexe.sync = sync;
50249
- function isexe(path5, options, cb) {
50332
+ function isexe(path6, options, cb) {
50250
50333
  if (typeof options === "function") {
50251
50334
  cb = options;
50252
50335
  options = {};
@@ -50256,7 +50339,7 @@ var require_isexe = __commonJS((exports2, module) => {
50256
50339
  throw new TypeError("callback not provided");
50257
50340
  }
50258
50341
  return new Promise(function(resolve2, reject) {
50259
- isexe(path5, options || {}, function(er, is) {
50342
+ isexe(path6, options || {}, function(er, is) {
50260
50343
  if (er) {
50261
50344
  reject(er);
50262
50345
  } else {
@@ -50265,7 +50348,7 @@ var require_isexe = __commonJS((exports2, module) => {
50265
50348
  });
50266
50349
  });
50267
50350
  }
50268
- core3(path5, options || {}, function(er, is) {
50351
+ core3(path6, options || {}, function(er, is) {
50269
50352
  if (er) {
50270
50353
  if (er.code === "EACCES" || options && options.ignoreErrors) {
50271
50354
  er = null;
@@ -50275,9 +50358,9 @@ var require_isexe = __commonJS((exports2, module) => {
50275
50358
  cb(er, is);
50276
50359
  });
50277
50360
  }
50278
- function sync(path5, options) {
50361
+ function sync(path6, options) {
50279
50362
  try {
50280
- return core3.sync(path5, options || {});
50363
+ return core3.sync(path6, options || {});
50281
50364
  } catch (er) {
50282
50365
  if (options && options.ignoreErrors || er.code === "EACCES") {
50283
50366
  return false;
@@ -50291,7 +50374,7 @@ var require_isexe = __commonJS((exports2, module) => {
50291
50374
  // node_modules/which/which.js
50292
50375
  var require_which = __commonJS((exports2, module) => {
50293
50376
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
50294
- var path5 = __require("path");
50377
+ var path6 = __require("path");
50295
50378
  var COLON = isWindows ? ";" : ":";
50296
50379
  var isexe = require_isexe();
50297
50380
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -50327,7 +50410,7 @@ var require_which = __commonJS((exports2, module) => {
50327
50410
  return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
50328
50411
  const ppRaw = pathEnv[i2];
50329
50412
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
50330
- const pCmd = path5.join(pathPart, cmd);
50413
+ const pCmd = path6.join(pathPart, cmd);
50331
50414
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
50332
50415
  resolve2(subStep(p2, i2, 0));
50333
50416
  });
@@ -50354,7 +50437,7 @@ var require_which = __commonJS((exports2, module) => {
50354
50437
  for (let i2 = 0;i2 < pathEnv.length; i2++) {
50355
50438
  const ppRaw = pathEnv[i2];
50356
50439
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
50357
- const pCmd = path5.join(pathPart, cmd);
50440
+ const pCmd = path6.join(pathPart, cmd);
50358
50441
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
50359
50442
  for (let j2 = 0;j2 < pathExt.length; j2++) {
50360
50443
  const cur = p2 + pathExt[j2];
@@ -50395,7 +50478,7 @@ var require_path_key = __commonJS((exports2, module) => {
50395
50478
 
50396
50479
  // node_modules/cross-spawn/lib/util/resolveCommand.js
50397
50480
  var require_resolveCommand = __commonJS((exports2, module) => {
50398
- var path5 = __require("path");
50481
+ var path6 = __require("path");
50399
50482
  var which = require_which();
50400
50483
  var getPathKey = require_path_key();
50401
50484
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -50412,7 +50495,7 @@ var require_resolveCommand = __commonJS((exports2, module) => {
50412
50495
  try {
50413
50496
  resolved = which.sync(parsed.command, {
50414
50497
  path: env[getPathKey({ env })],
50415
- pathExt: withoutPathExt ? path5.delimiter : undefined
50498
+ pathExt: withoutPathExt ? path6.delimiter : undefined
50416
50499
  });
50417
50500
  } catch (e2) {} finally {
50418
50501
  if (shouldSwitchCwd) {
@@ -50420,7 +50503,7 @@ var require_resolveCommand = __commonJS((exports2, module) => {
50420
50503
  }
50421
50504
  }
50422
50505
  if (resolved) {
50423
- resolved = path5.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
50506
+ resolved = path6.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
50424
50507
  }
50425
50508
  return resolved;
50426
50509
  }
@@ -50465,8 +50548,8 @@ var require_shebang_command = __commonJS((exports2, module) => {
50465
50548
  if (!match) {
50466
50549
  return null;
50467
50550
  }
50468
- const [path5, argument] = match[0].replace(/#! ?/, "").split(" ");
50469
- const binary2 = path5.split("/").pop();
50551
+ const [path6, argument] = match[0].replace(/#! ?/, "").split(" ");
50552
+ const binary2 = path6.split("/").pop();
50470
50553
  if (binary2 === "env") {
50471
50554
  return argument;
50472
50555
  }
@@ -50494,7 +50577,7 @@ var require_readShebang = __commonJS((exports2, module) => {
50494
50577
 
50495
50578
  // node_modules/cross-spawn/lib/parse.js
50496
50579
  var require_parse = __commonJS((exports2, module) => {
50497
- var path5 = __require("path");
50580
+ var path6 = __require("path");
50498
50581
  var resolveCommand = require_resolveCommand();
50499
50582
  var escape = require_escape();
50500
50583
  var readShebang = require_readShebang();
@@ -50519,7 +50602,7 @@ var require_parse = __commonJS((exports2, module) => {
50519
50602
  const needsShell = !isExecutableRegExp.test(commandFile);
50520
50603
  if (parsed.options.forceShell || needsShell) {
50521
50604
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
50522
- parsed.command = path5.normalize(parsed.command);
50605
+ parsed.command = path6.normalize(parsed.command);
50523
50606
  parsed.command = escape.command(parsed.command);
50524
50607
  parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
50525
50608
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -50623,21 +50706,21 @@ var require_cross_spawn = __commonJS((exports2, module) => {
50623
50706
  });
50624
50707
 
50625
50708
  // src/hooks/auto-update-checker/constants.ts
50626
- import * as path5 from "path";
50709
+ import * as path6 from "path";
50627
50710
  import * as os4 from "os";
50628
50711
  function getWindowsAppdataDir() {
50629
50712
  if (process.platform !== "win32")
50630
50713
  return null;
50631
- return process.env.APPDATA ?? path5.join(os4.homedir(), "AppData", "Roaming");
50714
+ return process.env.APPDATA ?? path6.join(os4.homedir(), "AppData", "Roaming");
50632
50715
  }
50633
50716
  function getUserConfigDir() {
50634
50717
  return getOpenCodeConfigDir({ binary: "opencode" });
50635
50718
  }
50636
50719
  function getUserOpencodeConfig() {
50637
- return path5.join(getUserConfigDir(), "opencode.json");
50720
+ return path6.join(getUserConfigDir(), "opencode.json");
50638
50721
  }
50639
50722
  function getUserOpencodeConfigJsonc() {
50640
- return path5.join(getUserConfigDir(), "opencode.jsonc");
50723
+ return path6.join(getUserConfigDir(), "opencode.jsonc");
50641
50724
  }
50642
50725
  var PACKAGE_NAME2, ACCEPTED_PACKAGE_NAMES2, NPM_REGISTRY_URL, NPM_FETCH_TIMEOUT = 5000, CACHE_ROOT_DIR, CACHE_DIR, VERSION_FILE, INSTALLED_PACKAGE_JSON, INSTALLED_PACKAGE_JSON_CANDIDATES;
50643
50726
  var init_constants3 = __esm(() => {
@@ -50648,30 +50731,30 @@ var init_constants3 = __esm(() => {
50648
50731
  ACCEPTED_PACKAGE_NAMES2 = ACCEPTED_PACKAGE_NAMES;
50649
50732
  NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`;
50650
50733
  CACHE_ROOT_DIR = getOpenCodeCacheDir();
50651
- CACHE_DIR = path5.join(CACHE_ROOT_DIR, "packages");
50652
- VERSION_FILE = path5.join(CACHE_ROOT_DIR, "version");
50653
- INSTALLED_PACKAGE_JSON = path5.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
50654
- INSTALLED_PACKAGE_JSON_CANDIDATES = ACCEPTED_PACKAGE_NAMES2.map((name) => path5.join(CACHE_DIR, "node_modules", name, "package.json"));
50734
+ CACHE_DIR = path6.join(CACHE_ROOT_DIR, "packages");
50735
+ VERSION_FILE = path6.join(CACHE_ROOT_DIR, "version");
50736
+ INSTALLED_PACKAGE_JSON = path6.join(CACHE_DIR, "node_modules", PACKAGE_NAME2, "package.json");
50737
+ INSTALLED_PACKAGE_JSON_CANDIDATES = ACCEPTED_PACKAGE_NAMES2.map((name) => path6.join(CACHE_DIR, "node_modules", name, "package.json"));
50655
50738
  });
50656
50739
 
50657
50740
  // src/hooks/auto-update-checker/checker/config-paths.ts
50658
50741
  import * as os5 from "os";
50659
- import * as path6 from "path";
50742
+ import * as path7 from "path";
50660
50743
  function getConfigPaths(directory) {
50661
50744
  const userConfigDir = getUserConfigDir();
50662
50745
  const paths = [
50663
- path6.join(directory, ".opencode", "opencode.json"),
50664
- path6.join(directory, ".opencode", "opencode.jsonc"),
50746
+ path7.join(directory, ".opencode", "opencode.json"),
50747
+ path7.join(directory, ".opencode", "opencode.jsonc"),
50665
50748
  getUserOpencodeConfig(),
50666
50749
  getUserOpencodeConfigJsonc()
50667
50750
  ];
50668
50751
  if (process.platform === "win32") {
50669
- const crossPlatformDir = path6.join(os5.homedir(), ".config");
50752
+ const crossPlatformDir = path7.join(os5.homedir(), ".config");
50670
50753
  const appdataDir = getWindowsAppdataDir();
50671
50754
  if (appdataDir) {
50672
50755
  const alternateDir = userConfigDir === crossPlatformDir ? appdataDir : crossPlatformDir;
50673
- const alternateConfig = path6.join(alternateDir, "opencode", "opencode.json");
50674
- const alternateConfigJsonc = path6.join(alternateDir, "opencode", "opencode.jsonc");
50756
+ const alternateConfig = path7.join(alternateDir, "opencode", "opencode.json");
50757
+ const alternateConfigJsonc = path7.join(alternateDir, "opencode", "opencode.jsonc");
50675
50758
  if (!paths.includes(alternateConfig)) {
50676
50759
  paths.push(alternateConfig);
50677
50760
  }
@@ -50729,13 +50812,13 @@ var init_local_dev_path = __esm(() => {
50729
50812
 
50730
50813
  // src/hooks/auto-update-checker/checker/package-json-locator.ts
50731
50814
  import * as fs6 from "fs";
50732
- import * as path7 from "path";
50815
+ import * as path8 from "path";
50733
50816
  function findPackageJsonUp(startPath) {
50734
50817
  try {
50735
50818
  const stat = fs6.statSync(startPath);
50736
- let dir = stat.isDirectory() ? startPath : path7.dirname(startPath);
50819
+ let dir = stat.isDirectory() ? startPath : path8.dirname(startPath);
50737
50820
  for (let i2 = 0;i2 < 10; i2++) {
50738
- const pkgPath = path7.join(dir, "package.json");
50821
+ const pkgPath = path8.join(dir, "package.json");
50739
50822
  if (fs6.existsSync(pkgPath)) {
50740
50823
  try {
50741
50824
  const content = fs6.readFileSync(pkgPath, "utf-8");
@@ -50744,7 +50827,7 @@ function findPackageJsonUp(startPath) {
50744
50827
  return pkgPath;
50745
50828
  } catch {}
50746
50829
  }
50747
- const parent = path7.dirname(dir);
50830
+ const parent = path8.dirname(dir);
50748
50831
  if (parent === dir)
50749
50832
  break;
50750
50833
  dir = parent;
@@ -50819,7 +50902,7 @@ var init_plugin_entry = __esm(() => {
50819
50902
 
50820
50903
  // src/hooks/auto-update-checker/checker/cached-version.ts
50821
50904
  import * as fs9 from "fs";
50822
- import * as path8 from "path";
50905
+ import * as path9 from "path";
50823
50906
  import { fileURLToPath as fileURLToPath2 } from "url";
50824
50907
  function readPackageVersion(packageJsonPath) {
50825
50908
  const content = fs9.readFileSync(packageJsonPath, "utf-8");
@@ -50835,7 +50918,7 @@ function getCachedVersion() {
50835
50918
  } catch {}
50836
50919
  }
50837
50920
  try {
50838
- const currentDir = path8.dirname(fileURLToPath2(import.meta.url));
50921
+ const currentDir = path9.dirname(fileURLToPath2(import.meta.url));
50839
50922
  const pkgPath = findPackageJsonUp(currentDir);
50840
50923
  if (pkgPath) {
50841
50924
  return readPackageVersion(pkgPath);
@@ -50844,7 +50927,7 @@ function getCachedVersion() {
50844
50927
  log("[auto-update-checker] Failed to resolve version from current directory:", err);
50845
50928
  }
50846
50929
  try {
50847
- const execDir = path8.dirname(fs9.realpathSync(process.execPath));
50930
+ const execDir = path9.dirname(fs9.realpathSync(process.execPath));
50848
50931
  const pkgPath = findPackageJsonUp(execDir);
50849
50932
  if (pkgPath) {
50850
50933
  return readPackageVersion(pkgPath);
@@ -50987,7 +51070,7 @@ var init_check_for_update = __esm(() => {
50987
51070
  // src/hooks/auto-update-checker/checker/sync-package-json.ts
50988
51071
  import * as crypto from "crypto";
50989
51072
  import * as fs10 from "fs";
50990
- import * as path9 from "path";
51073
+ import * as path10 from "path";
50991
51074
  function safeUnlink(filePath) {
50992
51075
  try {
50993
51076
  fs10.unlinkSync(filePath);
@@ -51004,7 +51087,7 @@ function getIntentVersion(pluginInfo) {
51004
51087
  function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
51005
51088
  const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
51006
51089
  try {
51007
- fs10.mkdirSync(path9.dirname(cachePackageJsonPath), { recursive: true });
51090
+ fs10.mkdirSync(path10.dirname(cachePackageJsonPath), { recursive: true });
51008
51091
  fs10.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
51009
51092
  fs10.renameSync(tmpPath, cachePackageJsonPath);
51010
51093
  return { synced: true, error: null };
@@ -51015,7 +51098,7 @@ function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
51015
51098
  }
51016
51099
  }
51017
51100
  function syncCachePackageJsonToIntent(pluginInfo) {
51018
- const cachePackageJsonPath = path9.join(CACHE_DIR, "package.json");
51101
+ const cachePackageJsonPath = path10.join(CACHE_DIR, "package.json");
51019
51102
  const intentVersion = getIntentVersion(pluginInfo);
51020
51103
  if (!fs10.existsSync(cachePackageJsonPath)) {
51021
51104
  log("[auto-update-checker] Cache package.json missing, creating workspace package.json", { intentVersion });
@@ -51091,7 +51174,7 @@ var init_checker = __esm(() => {
51091
51174
 
51092
51175
  // src/hooks/auto-update-checker/cache.ts
51093
51176
  import * as fs11 from "fs";
51094
- import * as path10 from "path";
51177
+ import * as path11 from "path";
51095
51178
  function stripTrailingCommas(json3) {
51096
51179
  return json3.replace(/,(\s*[}\]])/g, "$1");
51097
51180
  }
@@ -51120,8 +51203,8 @@ function deleteBinaryBunLock(lockPath) {
51120
51203
  }
51121
51204
  }
51122
51205
  function removeFromBunLock(packageName) {
51123
- const textLockPath = path10.join(CACHE_DIR, "bun.lock");
51124
- const binaryLockPath = path10.join(CACHE_DIR, "bun.lockb");
51206
+ const textLockPath = path11.join(CACHE_DIR, "bun.lock");
51207
+ const binaryLockPath = path11.join(CACHE_DIR, "bun.lockb");
51125
51208
  if (fs11.existsSync(textLockPath)) {
51126
51209
  return removeFromTextBunLock(textLockPath, packageName);
51127
51210
  }
@@ -51134,8 +51217,8 @@ function invalidatePackage(packageName = PACKAGE_NAME2) {
51134
51217
  try {
51135
51218
  const userConfigDir = getUserConfigDir();
51136
51219
  const pkgDirs = [
51137
- path10.join(userConfigDir, "node_modules", packageName),
51138
- path10.join(CACHE_DIR, "node_modules", packageName)
51220
+ path11.join(userConfigDir, "node_modules", packageName),
51221
+ path11.join(CACHE_DIR, "node_modules", packageName)
51139
51222
  ];
51140
51223
  let packageRemoved = false;
51141
51224
  let lockRemoved = false;
@@ -51195,8 +51278,8 @@ var init_update_toasts = __esm(() => {
51195
51278
  });
51196
51279
 
51197
51280
  // src/hooks/auto-update-checker/hook/background-update-check.ts
51198
- import { existsSync as existsSync27 } from "fs";
51199
- import { join as join26 } from "path";
51281
+ import { existsSync as existsSync28 } from "fs";
51282
+ import { join as join27 } from "path";
51200
51283
  function getCacheWorkspaceDir(deps) {
51201
51284
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
51202
51285
  }
@@ -51314,8 +51397,8 @@ var init_background_update_check = __esm(() => {
51314
51397
  init_checker();
51315
51398
  init_update_toasts();
51316
51399
  defaultDeps = {
51317
- existsSync: existsSync27,
51318
- join: join26,
51400
+ existsSync: existsSync28,
51401
+ join: join27,
51319
51402
  runBunInstallWithDetails,
51320
51403
  log,
51321
51404
  getOpenCodeCacheDir,
@@ -51608,7 +51691,7 @@ var {
51608
51691
  // package.json
51609
51692
  var package_default = {
51610
51693
  name: "oh-my-opencode",
51611
- version: "3.17.0",
51694
+ version: "3.17.2",
51612
51695
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
51613
51696
  main: "./dist/index.js",
51614
51697
  types: "dist/index.d.ts",
@@ -51687,17 +51770,17 @@ var package_default = {
51687
51770
  typescript: "^5.7.3"
51688
51771
  },
51689
51772
  optionalDependencies: {
51690
- "oh-my-opencode-darwin-arm64": "3.17.0",
51691
- "oh-my-opencode-darwin-x64": "3.17.0",
51692
- "oh-my-opencode-darwin-x64-baseline": "3.17.0",
51693
- "oh-my-opencode-linux-arm64": "3.17.0",
51694
- "oh-my-opencode-linux-arm64-musl": "3.17.0",
51695
- "oh-my-opencode-linux-x64": "3.17.0",
51696
- "oh-my-opencode-linux-x64-baseline": "3.17.0",
51697
- "oh-my-opencode-linux-x64-musl": "3.17.0",
51698
- "oh-my-opencode-linux-x64-musl-baseline": "3.17.0",
51699
- "oh-my-opencode-windows-x64": "3.17.0",
51700
- "oh-my-opencode-windows-x64-baseline": "3.17.0"
51773
+ "oh-my-opencode-darwin-arm64": "3.17.2",
51774
+ "oh-my-opencode-darwin-x64": "3.17.2",
51775
+ "oh-my-opencode-darwin-x64-baseline": "3.17.2",
51776
+ "oh-my-opencode-linux-arm64": "3.17.2",
51777
+ "oh-my-opencode-linux-arm64-musl": "3.17.2",
51778
+ "oh-my-opencode-linux-x64": "3.17.2",
51779
+ "oh-my-opencode-linux-x64-baseline": "3.17.2",
51780
+ "oh-my-opencode-linux-x64-musl": "3.17.2",
51781
+ "oh-my-opencode-linux-x64-musl-baseline": "3.17.2",
51782
+ "oh-my-opencode-windows-x64": "3.17.2",
51783
+ "oh-my-opencode-windows-x64-baseline": "3.17.2"
51701
51784
  },
51702
51785
  overrides: {},
51703
51786
  trustedDependencies: [
@@ -51742,6 +51825,7 @@ function formatConfigSummary(config) {
51742
51825
  lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models"));
51743
51826
  lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal"));
51744
51827
  lines.push(formatProvider("Kimi For Coding", config.hasKimiForCoding, "Sisyphus/Prometheus fallback"));
51828
+ lines.push(formatProvider("Vercel AI Gateway", config.hasVercelAiGateway, "universal proxy"));
51745
51829
  lines.push("");
51746
51830
  lines.push(import_picocolors.default.dim("\u2500".repeat(40)));
51747
51831
  lines.push("");
@@ -51825,6 +51909,9 @@ function validateNonTuiArgs(args) {
51825
51909
  if (args.kimiForCoding !== undefined && !["no", "yes"].includes(args.kimiForCoding)) {
51826
51910
  errors.push(`Invalid --kimi-for-coding value: ${args.kimiForCoding} (expected: no, yes)`);
51827
51911
  }
51912
+ if (args.vercelAiGateway !== undefined && !["no", "yes"].includes(args.vercelAiGateway)) {
51913
+ errors.push(`Invalid --vercel-ai-gateway value: ${args.vercelAiGateway} (expected: no, yes)`);
51914
+ }
51828
51915
  return { valid: errors.length === 0, errors };
51829
51916
  }
51830
51917
  function argsToConfig(args) {
@@ -51837,7 +51924,8 @@ function argsToConfig(args) {
51837
51924
  hasOpencodeZen: args.opencodeZen === "yes",
51838
51925
  hasZaiCodingPlan: args.zaiCodingPlan === "yes",
51839
51926
  hasKimiForCoding: args.kimiForCoding === "yes",
51840
- hasOpencodeGo: args.opencodeGo === "yes"
51927
+ hasOpencodeGo: args.opencodeGo === "yes",
51928
+ hasVercelAiGateway: args.vercelAiGateway === "yes"
51841
51929
  };
51842
51930
  }
51843
51931
  function detectedToInitialValues(detected) {
@@ -51853,7 +51941,8 @@ function detectedToInitialValues(detected) {
51853
51941
  opencodeZen: detected.hasOpencodeZen ? "yes" : "no",
51854
51942
  zaiCodingPlan: detected.hasZaiCodingPlan ? "yes" : "no",
51855
51943
  kimiForCoding: detected.hasKimiForCoding ? "yes" : "no",
51856
- opencodeGo: detected.hasOpencodeGo ? "yes" : "no"
51944
+ opencodeGo: detected.hasOpencodeGo ? "yes" : "no",
51945
+ vercelAiGateway: detected.hasVercelAiGateway ? "yes" : "no"
51857
51946
  };
51858
51947
  }
51859
51948
 
@@ -51943,8 +52032,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname5(proce
51943
52032
  return decodedFile;
51944
52033
  };
51945
52034
  }
51946
- function normalizeWindowsPath(path4) {
51947
- return path4.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
52035
+ function normalizeWindowsPath(path5) {
52036
+ return path5.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
51948
52037
  }
51949
52038
 
51950
52039
  // node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -54259,9 +54348,9 @@ async function addSourceContext(frames) {
54259
54348
  LRU_FILE_CONTENTS_CACHE.reduce();
54260
54349
  return frames;
54261
54350
  }
54262
- function getContextLinesFromFile(path4, ranges, output) {
54351
+ function getContextLinesFromFile(path5, ranges, output) {
54263
54352
  return new Promise((resolve2) => {
54264
- const stream = createReadStream(path4);
54353
+ const stream = createReadStream(path5);
54265
54354
  const lineReaded = createInterface({
54266
54355
  input: stream
54267
54356
  });
@@ -54277,7 +54366,7 @@ function getContextLinesFromFile(path4, ranges, output) {
54277
54366
  let rangeStart = range[0];
54278
54367
  let rangeEnd = range[1];
54279
54368
  function onStreamError() {
54280
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path4, 1);
54369
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path5, 1);
54281
54370
  lineReaded.close();
54282
54371
  lineReaded.removeAllListeners();
54283
54372
  destroyStreamAndResolve();
@@ -54345,8 +54434,8 @@ function clearLineContext(frame) {
54345
54434
  delete frame.context_line;
54346
54435
  delete frame.post_context;
54347
54436
  }
54348
- function shouldSkipContextLinesForFile(path4) {
54349
- return path4.startsWith("node:") || path4.endsWith(".min.js") || path4.endsWith(".min.cjs") || path4.endsWith(".min.mjs") || path4.startsWith("data:");
54437
+ function shouldSkipContextLinesForFile(path5) {
54438
+ return path5.startsWith("node:") || path5.endsWith(".min.js") || path5.endsWith(".min.cjs") || path5.endsWith(".min.mjs") || path5.startsWith("data:");
54350
54439
  }
54351
54440
  function shouldSkipContextLinesForFrame(frame) {
54352
54441
  if (frame.lineno !== undefined && frame.lineno > MAX_CONTEXTLINES_LINENO)
@@ -56359,11 +56448,11 @@ init_data_path();
56359
56448
  init_logger();
56360
56449
  init_plugin_identity();
56361
56450
  init_write_file_atomically();
56362
- import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync11 } from "fs";
56363
- import { join as join14 } from "path";
56451
+ import { existsSync as existsSync17, mkdirSync as mkdirSync7, readFileSync as readFileSync11 } from "fs";
56452
+ import { join as join15 } from "path";
56364
56453
  var POSTHOG_ACTIVITY_STATE_FILE = "posthog-activity.json";
56365
56454
  function getPostHogActivityStateFilePath() {
56366
- return join14(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE);
56455
+ return join15(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE);
56367
56456
  }
56368
56457
  function getUtcDayString(date) {
56369
56458
  return date.toISOString().slice(0, 10);
@@ -56376,7 +56465,7 @@ function isPostHogActivityState(value) {
56376
56465
  }
56377
56466
  function readPostHogActivityState() {
56378
56467
  const stateFilePath = getPostHogActivityStateFilePath();
56379
- if (!existsSync16(stateFilePath)) {
56468
+ if (!existsSync17(stateFilePath)) {
56380
56469
  return {};
56381
56470
  }
56382
56471
  try {
@@ -56397,7 +56486,7 @@ function readPostHogActivityState() {
56397
56486
  function writePostHogActivityState(nextState) {
56398
56487
  const stateFilePath = getPostHogActivityStateFilePath();
56399
56488
  try {
56400
- mkdirSync6(join14(getDataDir(), CACHE_DIR_NAME), { recursive: true });
56489
+ mkdirSync7(join15(getDataDir(), CACHE_DIR_NAME), { recursive: true });
56401
56490
  writeFileAtomically(stateFilePath, `${JSON.stringify(nextState, null, 2)}
56402
56491
  `);
56403
56492
  } catch (error) {
@@ -56469,17 +56558,36 @@ function getSharedProperties(source) {
56469
56558
  plugin_name: PLUGIN_NAME,
56470
56559
  package_version: package_default.version,
56471
56560
  runtime: "bun",
56472
- source
56561
+ runtime_version: process.versions.bun ?? process.version,
56562
+ source,
56563
+ $os: os3.platform(),
56564
+ $os_version: os3.release(),
56565
+ os_arch: os3.arch(),
56566
+ os_type: os3.type(),
56567
+ cpu_count: os3.cpus().length,
56568
+ cpu_model: os3.cpus()[0]?.model,
56569
+ total_memory_gb: Math.round(os3.totalmem() / 1024 / 1024 / 1024),
56570
+ locale: Intl.DateTimeFormat().resolvedOptions().locale,
56571
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
56572
+ shell: process.env.SHELL,
56573
+ ci: Boolean(process.env.CI),
56574
+ terminal: process.env.TERM_PROGRAM
56473
56575
  };
56474
56576
  }
56475
56577
  function createPostHogClient(source, options) {
56476
56578
  if (shouldDisablePostHog() || !hasPostHogApiKey()) {
56477
56579
  return NO_OP_POSTHOG;
56478
56580
  }
56479
- const configuredClient = new PostHog(getPostHogApiKey(), {
56480
- ...options,
56481
- host: getPostHogHost()
56482
- });
56581
+ let configuredClient;
56582
+ try {
56583
+ configuredClient = new PostHog(getPostHogApiKey(), {
56584
+ ...options,
56585
+ host: getPostHogHost(),
56586
+ disableGeoip: false
56587
+ });
56588
+ } catch {
56589
+ return NO_OP_POSTHOG;
56590
+ }
56483
56591
  const sharedProperties = getSharedProperties(source);
56484
56592
  return {
56485
56593
  capture: (message) => {
@@ -56612,7 +56720,7 @@ async function runCliInstaller(args, version2) {
56612
56720
  if (!config.hasClaude) {
56613
56721
  printInfo("Note: Sisyphus agent performs best with Claude Opus 4.5+. " + "Other models work but may have reduced orchestration quality.");
56614
56722
  }
56615
- if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
56723
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen && !config.hasVercelAiGateway) {
56616
56724
  printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
56617
56725
  }
56618
56726
  console.log(`${SYMBOLS.star} ${import_picocolors3.default.bold(import_picocolors3.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
@@ -57339,6 +57447,16 @@ async function promptInstallConfig(detected) {
57339
57447
  });
57340
57448
  if (!opencodeGo)
57341
57449
  return null;
57450
+ const vercelAiGateway = await selectOrCancel({
57451
+ message: "Do you have a Vercel AI Gateway API key?",
57452
+ options: [
57453
+ { value: "no", label: "No", hint: "Will use other configured providers" },
57454
+ { value: "yes", label: "Yes", hint: "Universal proxy for OpenAI, Anthropic, Google, etc." }
57455
+ ],
57456
+ initialValue: initial.vercelAiGateway
57457
+ });
57458
+ if (!vercelAiGateway)
57459
+ return null;
57342
57460
  return {
57343
57461
  hasClaude: claude !== "no",
57344
57462
  isMax20: claude === "max20",
@@ -57348,7 +57466,8 @@ async function promptInstallConfig(detected) {
57348
57466
  hasOpencodeZen: opencodeZen === "yes",
57349
57467
  hasZaiCodingPlan: zaiCodingPlan === "yes",
57350
57468
  hasKimiForCoding: kimiForCoding === "yes",
57351
- hasOpencodeGo: opencodeGo === "yes"
57469
+ hasOpencodeGo: opencodeGo === "yes",
57470
+ hasVercelAiGateway: vercelAiGateway === "yes"
57352
57471
  };
57353
57472
  }
57354
57473
 
@@ -57405,7 +57524,7 @@ async function runTuiInstaller(args, version2) {
57405
57524
  M2.info(`${import_picocolors5.default.bold("Note:")} Sisyphus agent performs best with Claude Opus 4.5+.
57406
57525
  ` + `Other models work but may have reduced orchestration quality.`);
57407
57526
  }
57408
- if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
57527
+ if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen && !config.hasVercelAiGateway) {
57409
57528
  M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
57410
57529
  }
57411
57530
  Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
@@ -57631,10 +57750,10 @@ function formatToolHeader(toolName, input) {
57631
57750
  };
57632
57751
  }
57633
57752
  if (toolName === "list") {
57634
- const path4 = str2(input.path);
57753
+ const path5 = str2(input.path);
57635
57754
  return {
57636
57755
  icon: "\u2192",
57637
- title: path4 ? `List ${path4}` : "List"
57756
+ title: path5 ? `List ${path5}` : "List"
57638
57757
  };
57639
57758
  }
57640
57759
  if (toolName === "read") {
@@ -58143,7 +58262,7 @@ async function processEvents(ctx, stream, state) {
58143
58262
  }
58144
58263
  // src/plugin-config.ts
58145
58264
  import * as fs4 from "fs";
58146
- import * as path4 from "path";
58265
+ import * as path5 from "path";
58147
58266
 
58148
58267
  // node_modules/zod/v4/classic/external.js
58149
58268
  var exports_external = {};
@@ -58910,10 +59029,10 @@ function mergeDefs(...defs) {
58910
59029
  function cloneDef(schema2) {
58911
59030
  return mergeDefs(schema2._zod.def);
58912
59031
  }
58913
- function getElementAtPath(obj, path4) {
58914
- if (!path4)
59032
+ function getElementAtPath(obj, path5) {
59033
+ if (!path5)
58915
59034
  return obj;
58916
- return path4.reduce((acc, key) => acc?.[key], obj);
59035
+ return path5.reduce((acc, key) => acc?.[key], obj);
58917
59036
  }
58918
59037
  function promiseAllObject(promisesObj) {
58919
59038
  const keys = Object.keys(promisesObj);
@@ -59294,11 +59413,11 @@ function aborted(x2, startIndex = 0) {
59294
59413
  }
59295
59414
  return false;
59296
59415
  }
59297
- function prefixIssues(path4, issues) {
59416
+ function prefixIssues(path5, issues) {
59298
59417
  return issues.map((iss) => {
59299
59418
  var _a;
59300
59419
  (_a = iss).path ?? (_a.path = []);
59301
- iss.path.unshift(path4);
59420
+ iss.path.unshift(path5);
59302
59421
  return iss;
59303
59422
  });
59304
59423
  }
@@ -59481,7 +59600,7 @@ function formatError2(error, mapper = (issue2) => issue2.message) {
59481
59600
  }
59482
59601
  function treeifyError(error, mapper = (issue2) => issue2.message) {
59483
59602
  const result = { errors: [] };
59484
- const processError = (error2, path4 = []) => {
59603
+ const processError = (error2, path5 = []) => {
59485
59604
  var _a, _b;
59486
59605
  for (const issue2 of error2.issues) {
59487
59606
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -59491,7 +59610,7 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
59491
59610
  } else if (issue2.code === "invalid_element") {
59492
59611
  processError({ issues: issue2.issues }, issue2.path);
59493
59612
  } else {
59494
- const fullpath = [...path4, ...issue2.path];
59613
+ const fullpath = [...path5, ...issue2.path];
59495
59614
  if (fullpath.length === 0) {
59496
59615
  result.errors.push(mapper(issue2));
59497
59616
  continue;
@@ -59523,8 +59642,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
59523
59642
  }
59524
59643
  function toDotPath(_path) {
59525
59644
  const segs = [];
59526
- const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
59527
- for (const seg of path4) {
59645
+ const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
59646
+ for (const seg of path5) {
59528
59647
  if (typeof seg === "number")
59529
59648
  segs.push(`[${seg}]`);
59530
59649
  else if (typeof seg === "symbol")
@@ -71271,13 +71390,13 @@ function resolveRef(ref, ctx) {
71271
71390
  if (!ref.startsWith("#")) {
71272
71391
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
71273
71392
  }
71274
- const path4 = ref.slice(1).split("/").filter(Boolean);
71275
- if (path4.length === 0) {
71393
+ const path5 = ref.slice(1).split("/").filter(Boolean);
71394
+ if (path5.length === 0) {
71276
71395
  return ctx.rootSchema;
71277
71396
  }
71278
71397
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
71279
- if (path4[0] === defsKey) {
71280
- const key = path4[1];
71398
+ if (path5[0] === defsKey) {
71399
+ const key = path5[1];
71281
71400
  if (!key || !ctx.defs[key]) {
71282
71401
  throw new Error(`Reference not found: ${ref}`);
71283
71402
  }
@@ -72210,6 +72329,22 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
72210
72329
  init_shared();
72211
72330
  init_migrate_legacy_config_file();
72212
72331
  init_plugin_identity();
72332
+ function loadExplicitGitMasterOverrides(configPath) {
72333
+ try {
72334
+ if (!fs4.existsSync(configPath)) {
72335
+ return;
72336
+ }
72337
+ const content = fs4.readFileSync(configPath, "utf-8");
72338
+ const rawConfig = parseJsonc(content);
72339
+ const gitMaster = rawConfig.git_master;
72340
+ if (gitMaster && typeof gitMaster === "object" && !Array.isArray(gitMaster)) {
72341
+ return gitMaster;
72342
+ }
72343
+ } catch {
72344
+ return;
72345
+ }
72346
+ return;
72347
+ }
72213
72348
  var PARTIAL_STRING_ARRAY_KEYS = new Set([
72214
72349
  "disabled_mcps",
72215
72350
  "disabled_agents",
@@ -72337,42 +72472,55 @@ function mergeConfigs(base, override) {
72337
72472
  function loadPluginConfig(directory, ctx) {
72338
72473
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
72339
72474
  const userDetected = detectPluginConfigFile(configDir);
72340
- let userConfigPath = userDetected.format !== "none" ? userDetected.path : path4.join(configDir, `${CONFIG_BASENAME}.json`);
72475
+ let userConfigPath = userDetected.format !== "none" ? userDetected.path : path5.join(configDir, `${CONFIG_BASENAME}.json`);
72341
72476
  if (userDetected.legacyPath) {
72342
72477
  log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
72343
72478
  canonicalPath: userDetected.path,
72344
72479
  legacyPath: userDetected.legacyPath
72345
72480
  });
72346
72481
  }
72347
- if (userDetected.format !== "none" && path4.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
72482
+ if (userDetected.format !== "none" && path5.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
72348
72483
  const migrated = migrateLegacyConfigFile(userDetected.path);
72349
- const canonicalPath = path4.join(path4.dirname(userDetected.path), `${CONFIG_BASENAME}${path4.extname(userDetected.path)}`);
72484
+ const canonicalPath = path5.join(path5.dirname(userDetected.path), `${CONFIG_BASENAME}${path5.extname(userDetected.path)}`);
72350
72485
  if (migrated || fs4.existsSync(canonicalPath)) {
72351
72486
  userConfigPath = canonicalPath;
72352
72487
  }
72353
72488
  }
72354
- const projectBasePath = path4.join(directory, ".opencode");
72489
+ const projectBasePath = path5.join(directory, ".opencode");
72355
72490
  const projectDetected = detectPluginConfigFile(projectBasePath);
72356
- let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path4.join(projectBasePath, `${CONFIG_BASENAME}.json`);
72491
+ let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path5.join(projectBasePath, `${CONFIG_BASENAME}.json`);
72357
72492
  if (projectDetected.legacyPath) {
72358
72493
  log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
72359
72494
  canonicalPath: projectDetected.path,
72360
72495
  legacyPath: projectDetected.legacyPath
72361
72496
  });
72362
72497
  }
72363
- if (projectDetected.format !== "none" && path4.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
72498
+ if (projectDetected.format !== "none" && path5.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
72364
72499
  const projectMigrated = migrateLegacyConfigFile(projectDetected.path);
72365
- const canonicalProjectPath = path4.join(path4.dirname(projectDetected.path), `${CONFIG_BASENAME}${path4.extname(projectDetected.path)}`);
72500
+ const canonicalProjectPath = path5.join(path5.dirname(projectDetected.path), `${CONFIG_BASENAME}${path5.extname(projectDetected.path)}`);
72366
72501
  if (projectMigrated || fs4.existsSync(canonicalProjectPath)) {
72367
72502
  projectConfigPath = canonicalProjectPath;
72368
72503
  }
72369
72504
  }
72370
72505
  const userConfig = loadConfigFromPath(userConfigPath, ctx);
72506
+ const userGitMasterOverrides = loadExplicitGitMasterOverrides(userConfigPath);
72371
72507
  let config2 = userConfig ?? OhMyOpenCodeConfigSchema.parse({});
72508
+ const defaultGitMaster = OhMyOpenCodeConfigSchema.parse({}).git_master;
72372
72509
  const projectConfig = loadConfigFromPath(projectConfigPath, ctx);
72510
+ const projectGitMasterOverrides = loadExplicitGitMasterOverrides(projectConfigPath);
72373
72511
  if (projectConfig) {
72374
72512
  config2 = mergeConfigs(config2, projectConfig);
72375
72513
  }
72514
+ if (userGitMasterOverrides || projectGitMasterOverrides) {
72515
+ config2 = {
72516
+ ...config2,
72517
+ git_master: {
72518
+ ...defaultGitMaster,
72519
+ ...userGitMasterOverrides ?? {},
72520
+ ...projectGitMasterOverrides ?? {}
72521
+ }
72522
+ };
72523
+ }
72376
72524
  config2 = {
72377
72525
  ...config2,
72378
72526
  mcp_env_allowlist: userConfig?.mcp_env_allowlist ?? []
@@ -72620,7 +72768,7 @@ var serializeObjectParam = ({ allowReserved, explode, name, style, value, valueO
72620
72768
 
72621
72769
  // node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
72622
72770
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
72623
- var defaultPathSerializer = ({ path: path5, url: _url2 }) => {
72771
+ var defaultPathSerializer = ({ path: path6, url: _url2 }) => {
72624
72772
  let url2 = _url2;
72625
72773
  const matches = _url2.match(PATH_PARAM_RE);
72626
72774
  if (matches) {
@@ -72639,7 +72787,7 @@ var defaultPathSerializer = ({ path: path5, url: _url2 }) => {
72639
72787
  name = name.substring(1);
72640
72788
  style = "matrix";
72641
72789
  }
72642
- const value = path5[name];
72790
+ const value = path6[name];
72643
72791
  if (value === undefined || value === null) {
72644
72792
  continue;
72645
72793
  }
@@ -72670,11 +72818,11 @@ var defaultPathSerializer = ({ path: path5, url: _url2 }) => {
72670
72818
  }
72671
72819
  return url2;
72672
72820
  };
72673
- var getUrl = ({ baseUrl, path: path5, query, querySerializer, url: _url2 }) => {
72821
+ var getUrl = ({ baseUrl, path: path6, query, querySerializer, url: _url2 }) => {
72674
72822
  const pathUrl = _url2.startsWith("/") ? _url2 : `/${_url2}`;
72675
72823
  let url2 = (baseUrl ?? "") + pathUrl;
72676
- if (path5) {
72677
- url2 = defaultPathSerializer({ path: path5, url: url2 });
72824
+ if (path6) {
72825
+ url2 = defaultPathSerializer({ path: path6, url: url2 });
72678
72826
  }
72679
72827
  let search = query ? querySerializer(query) : "";
72680
72828
  if (search.startsWith("?")) {
@@ -73904,7 +74052,7 @@ var import_picocolors10 = __toESM(require_picocolors(), 1);
73904
74052
 
73905
74053
  // src/cli/run/opencode-binary-resolver.ts
73906
74054
  init_spawn_with_windows_hide();
73907
- import { delimiter, dirname as dirname7, join as join16 } from "path";
74055
+ import { delimiter, dirname as dirname7, join as join17 } from "path";
73908
74056
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
73909
74057
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
73910
74058
  function getCommandCandidates(platform) {
@@ -73927,7 +74075,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
73927
74075
  }
73928
74076
  for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
73929
74077
  for (const command of commandCandidates) {
73930
- addCandidate(join16(entry, command));
74078
+ addCandidate(join17(entry, command));
73931
74079
  }
73932
74080
  }
73933
74081
  return candidates;
@@ -74312,15 +74460,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
74312
74460
  var NOTEPAD_DIR = "notepads";
74313
74461
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
74314
74462
  // src/features/boulder-state/storage.ts
74315
- import { existsSync as existsSync18, readFileSync as readFileSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, readdirSync as readdirSync3 } from "fs";
74316
- import { dirname as dirname8, join as join17, basename as basename4 } from "path";
74463
+ import { existsSync as existsSync19, readFileSync as readFileSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync8, readdirSync as readdirSync3 } from "fs";
74464
+ import { dirname as dirname8, join as join18, basename as basename4 } from "path";
74317
74465
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
74318
74466
  function getBoulderFilePath(directory) {
74319
- return join17(directory, BOULDER_DIR, BOULDER_FILE);
74467
+ return join18(directory, BOULDER_DIR, BOULDER_FILE);
74320
74468
  }
74321
74469
  function readBoulderState(directory) {
74322
74470
  const filePath = getBoulderFilePath(directory);
74323
- if (!existsSync18(filePath)) {
74471
+ if (!existsSync19(filePath)) {
74324
74472
  return null;
74325
74473
  }
74326
74474
  try {
@@ -74357,7 +74505,7 @@ var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
74357
74505
  var TODO_TASK_PATTERN = /^\d+\.\s+/;
74358
74506
  var FINAL_WAVE_TASK_PATTERN = /^F\d+\.\s+/i;
74359
74507
  function getPlanProgress(planPath) {
74360
- if (!existsSync18(planPath)) {
74508
+ if (!existsSync19(planPath)) {
74361
74509
  return { total: 0, completed: 0, isComplete: true };
74362
74510
  }
74363
74511
  try {
@@ -74433,14 +74581,14 @@ function getSessionAgent(sessionID) {
74433
74581
  // src/features/run-continuation-state/constants.ts
74434
74582
  var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
74435
74583
  // src/features/run-continuation-state/storage.ts
74436
- import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync14, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
74437
- import { join as join18 } from "path";
74584
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync14, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
74585
+ import { join as join19 } from "path";
74438
74586
  function getMarkerPath(directory, sessionID) {
74439
- return join18(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
74587
+ return join19(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
74440
74588
  }
74441
74589
  function readContinuationMarker(directory, sessionID) {
74442
74590
  const markerPath = getMarkerPath(directory, sessionID);
74443
- if (!existsSync19(markerPath))
74591
+ if (!existsSync20(markerPath))
74444
74592
  return null;
74445
74593
  try {
74446
74594
  const raw = readFileSync14(markerPath, "utf-8");
@@ -74505,7 +74653,7 @@ async function isSessionInBoulderLineage(input) {
74505
74653
  init_shared();
74506
74654
  init_compaction_marker();
74507
74655
  import { readFileSync as readFileSync15, readdirSync as readdirSync4 } from "fs";
74508
- import { join as join19 } from "path";
74656
+ import { join as join20 } from "path";
74509
74657
  var defaultSessionLastAgentDeps = {
74510
74658
  getMessageDir,
74511
74659
  isSqliteBackend,
@@ -74553,7 +74701,7 @@ async function getLastAgentFromSession(sessionID, client3, deps = {}) {
74553
74701
  try {
74554
74702
  const messages = readdirSync4(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
74555
74703
  try {
74556
- const content = readFileSync15(join19(messageDir, fileName), "utf-8");
74704
+ const content = readFileSync15(join20(messageDir, fileName), "utf-8");
74557
74705
  const parsed = JSON.parse(content);
74558
74706
  return {
74559
74707
  fileName,
@@ -74586,8 +74734,8 @@ init_agent_display_names();
74586
74734
 
74587
74735
  // src/hooks/ralph-loop/storage.ts
74588
74736
  init_frontmatter();
74589
- import { existsSync as existsSync20, readFileSync as readFileSync16, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync9 } from "fs";
74590
- import { dirname as dirname9, join as join20 } from "path";
74737
+ import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync10 } from "fs";
74738
+ import { dirname as dirname9, join as join21 } from "path";
74591
74739
 
74592
74740
  // src/hooks/ralph-loop/constants.ts
74593
74741
  var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
@@ -74596,11 +74744,11 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
74596
74744
 
74597
74745
  // src/hooks/ralph-loop/storage.ts
74598
74746
  function getStateFilePath(directory, customPath) {
74599
- return customPath ? join20(directory, customPath) : join20(directory, DEFAULT_STATE_FILE);
74747
+ return customPath ? join21(directory, customPath) : join21(directory, DEFAULT_STATE_FILE);
74600
74748
  }
74601
74749
  function readState(directory, customPath) {
74602
74750
  const filePath = getStateFilePath(directory, customPath);
74603
- if (!existsSync20(filePath)) {
74751
+ if (!existsSync21(filePath)) {
74604
74752
  return null;
74605
74753
  }
74606
74754
  try {
@@ -74920,6 +75068,9 @@ async function getMainSessionStatus(ctx) {
74920
75068
  query: { directory: ctx.directory }
74921
75069
  });
74922
75070
  const statuses = normalizeSDKResponse(statusesRes, {});
75071
+ if (!(ctx.sessionID in statuses)) {
75072
+ return "idle";
75073
+ }
74923
75074
  const status = statuses[ctx.sessionID]?.type;
74924
75075
  if (status === "idle" || status === "busy" || status === "retry") {
74925
75076
  return status;
@@ -75369,30 +75520,61 @@ async function getLocalVersion(options = {}) {
75369
75520
  }
75370
75521
  }
75371
75522
  // src/cli/doctor/checks/system.ts
75372
- import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
75523
+ import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
75373
75524
 
75374
75525
  // src/cli/doctor/checks/system-binary.ts
75375
- init_spawn_with_windows_hide();
75376
- import { existsSync as existsSync28 } from "fs";
75526
+ import { existsSync as existsSync29 } from "fs";
75377
75527
  import { homedir as homedir5 } from "os";
75378
- import { join as join27 } from "path";
75528
+ import { join as join28 } from "path";
75529
+
75530
+ // src/cli/doctor/spawn-with-timeout.ts
75531
+ init_spawn_with_windows_hide();
75532
+ var DEFAULT_SPAWN_TIMEOUT_MS = 1e4;
75533
+ async function spawnWithTimeout(command, options, timeoutMs = DEFAULT_SPAWN_TIMEOUT_MS) {
75534
+ let proc;
75535
+ try {
75536
+ proc = spawnWithWindowsHide(command, options);
75537
+ } catch {
75538
+ return { stdout: "", stderr: "", exitCode: 1, timedOut: false };
75539
+ }
75540
+ let timer;
75541
+ const timeoutPromise = new Promise((resolve2) => {
75542
+ timer = setTimeout(() => resolve2("timeout"), timeoutMs);
75543
+ });
75544
+ const processPromise = (async () => {
75545
+ await proc.exited;
75546
+ return "done";
75547
+ })();
75548
+ const race = await Promise.race([processPromise, timeoutPromise]);
75549
+ if (race === "timeout") {
75550
+ proc.kill("SIGTERM");
75551
+ await proc.exited.catch(() => {});
75552
+ return { stdout: "", stderr: "", exitCode: 1, timedOut: true };
75553
+ }
75554
+ clearTimeout(timer);
75555
+ const stdout = proc.stdout ? await new Response(proc.stdout).text() : "";
75556
+ const stderr = proc.stderr ? await new Response(proc.stderr).text() : "";
75557
+ return { stdout, stderr, exitCode: proc.exitCode ?? 1, timedOut: false };
75558
+ }
75559
+
75560
+ // src/cli/doctor/checks/system-binary.ts
75379
75561
  function getDesktopAppPaths(platform) {
75380
75562
  const home = homedir5();
75381
75563
  switch (platform) {
75382
75564
  case "darwin":
75383
75565
  return [
75384
75566
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
75385
- join27(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
75567
+ join28(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
75386
75568
  ];
75387
75569
  case "win32": {
75388
75570
  const programFiles = process.env.ProgramFiles;
75389
75571
  const localAppData = process.env.LOCALAPPDATA;
75390
75572
  const paths = [];
75391
75573
  if (programFiles) {
75392
- paths.push(join27(programFiles, "OpenCode", "OpenCode.exe"));
75574
+ paths.push(join28(programFiles, "OpenCode", "OpenCode.exe"));
75393
75575
  }
75394
75576
  if (localAppData) {
75395
- paths.push(join27(localAppData, "OpenCode", "OpenCode.exe"));
75577
+ paths.push(join28(localAppData, "OpenCode", "OpenCode.exe"));
75396
75578
  }
75397
75579
  return paths;
75398
75580
  }
@@ -75400,8 +75582,8 @@ function getDesktopAppPaths(platform) {
75400
75582
  return [
75401
75583
  "/usr/bin/opencode",
75402
75584
  "/usr/lib/opencode/opencode",
75403
- join27(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
75404
- join27(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
75585
+ join28(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
75586
+ join28(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
75405
75587
  ];
75406
75588
  default:
75407
75589
  return [];
@@ -75413,7 +75595,7 @@ function buildVersionCommand(binaryPath, platform) {
75413
75595
  }
75414
75596
  return [binaryPath, "--version"];
75415
75597
  }
75416
- function findDesktopBinary(platform = process.platform, checkExists = existsSync28) {
75598
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync29) {
75417
75599
  for (const desktopPath of getDesktopAppPaths(platform)) {
75418
75600
  if (checkExists(desktopPath)) {
75419
75601
  return { binary: "opencode", path: desktopPath };
@@ -75423,9 +75605,9 @@ function findDesktopBinary(platform = process.platform, checkExists = existsSync
75423
75605
  }
75424
75606
  async function findOpenCodeBinary() {
75425
75607
  for (const binary2 of OPENCODE_BINARIES2) {
75426
- const path11 = Bun.which(binary2);
75427
- if (path11) {
75428
- return { binary: binary2, path: path11 };
75608
+ const path12 = Bun.which(binary2);
75609
+ if (path12) {
75610
+ return { binary: binary2, path: path12 };
75429
75611
  }
75430
75612
  }
75431
75613
  return findDesktopBinary();
@@ -75433,12 +75615,10 @@ async function findOpenCodeBinary() {
75433
75615
  async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
75434
75616
  try {
75435
75617
  const command = buildVersionCommand(binaryPath, platform);
75436
- const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
75437
- const output = await new Response(processResult.stdout).text();
75438
- await processResult.exited;
75439
- if (processResult.exitCode !== 0)
75618
+ const result = await spawnWithTimeout(command, { stdout: "pipe", stderr: "pipe" });
75619
+ if (result.timedOut || result.exitCode !== 0)
75440
75620
  return null;
75441
- return output.trim() || null;
75621
+ return result.stdout.trim() || null;
75442
75622
  } catch {
75443
75623
  return null;
75444
75624
  }
@@ -75461,12 +75641,12 @@ function compareVersions3(current, minimum) {
75461
75641
 
75462
75642
  // src/cli/doctor/checks/system-plugin.ts
75463
75643
  init_shared();
75464
- import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
75644
+ import { existsSync as existsSync30, readFileSync as readFileSync24 } from "fs";
75465
75645
  function detectConfigPath() {
75466
75646
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
75467
- if (existsSync29(paths.configJsonc))
75647
+ if (existsSync30(paths.configJsonc))
75468
75648
  return paths.configJsonc;
75469
- if (existsSync29(paths.configJson))
75649
+ if (existsSync30(paths.configJson))
75470
75650
  return paths.configJson;
75471
75651
  return null;
75472
75652
  }
@@ -75550,34 +75730,34 @@ function getPluginInfo() {
75550
75730
  init_file_utils();
75551
75731
  init_checker();
75552
75732
  init_auto_update_checker();
75553
- import { existsSync as existsSync30, readFileSync as readFileSync25 } from "fs";
75733
+ import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
75554
75734
  import { homedir as homedir6 } from "os";
75555
- import { join as join28 } from "path";
75735
+ import { join as join29 } from "path";
75556
75736
  init_shared();
75557
75737
  function getPlatformDefaultCacheDir(platform = process.platform) {
75558
75738
  if (platform === "darwin")
75559
- return join28(homedir6(), "Library", "Caches");
75739
+ return join29(homedir6(), "Library", "Caches");
75560
75740
  if (platform === "win32")
75561
- return process.env.LOCALAPPDATA ?? join28(homedir6(), "AppData", "Local");
75562
- return join28(homedir6(), ".cache");
75741
+ return process.env.LOCALAPPDATA ?? join29(homedir6(), "AppData", "Local");
75742
+ return join29(homedir6(), ".cache");
75563
75743
  }
75564
75744
  function resolveOpenCodeCacheDir() {
75565
75745
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
75566
75746
  if (xdgCacheHome)
75567
- return join28(xdgCacheHome, "opencode");
75747
+ return join29(xdgCacheHome, "opencode");
75568
75748
  const fromShared = getOpenCodeCacheDir();
75569
- const platformDefault = join28(getPlatformDefaultCacheDir(), "opencode");
75570
- if (existsSync30(fromShared) || !existsSync30(platformDefault))
75749
+ const platformDefault = join29(getPlatformDefaultCacheDir(), "opencode");
75750
+ if (existsSync31(fromShared) || !existsSync31(platformDefault))
75571
75751
  return fromShared;
75572
75752
  return platformDefault;
75573
75753
  }
75574
75754
  function resolveExistingDir(dirPath) {
75575
- if (!existsSync30(dirPath))
75755
+ if (!existsSync31(dirPath))
75576
75756
  return dirPath;
75577
75757
  return resolveSymlink(dirPath);
75578
75758
  }
75579
75759
  function readPackageJson(filePath) {
75580
- if (!existsSync30(filePath))
75760
+ if (!existsSync31(filePath))
75581
75761
  return null;
75582
75762
  try {
75583
75763
  const content = readFileSync25(filePath, "utf-8");
@@ -75595,11 +75775,11 @@ function normalizeVersion(value) {
75595
75775
  function createPackageCandidates(rootDir) {
75596
75776
  return ACCEPTED_PACKAGE_NAMES.map((packageName) => ({
75597
75777
  packageName,
75598
- installedPackagePath: join28(rootDir, "node_modules", packageName, "package.json")
75778
+ installedPackagePath: join29(rootDir, "node_modules", packageName, "package.json")
75599
75779
  }));
75600
75780
  }
75601
75781
  function selectInstalledPackage(candidate) {
75602
- return candidate.packageCandidates.find((packageCandidate) => existsSync30(packageCandidate.installedPackagePath)) ?? candidate.packageCandidates[0];
75782
+ return candidate.packageCandidates.find((packageCandidate) => existsSync31(packageCandidate.installedPackagePath)) ?? candidate.packageCandidates[0];
75603
75783
  }
75604
75784
  function getExpectedVersion(cachePackage, packageName) {
75605
75785
  return normalizeVersion(cachePackage?.dependencies?.[packageName]) ?? normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME]);
@@ -75611,16 +75791,16 @@ function getLoadedPluginVersion() {
75611
75791
  const candidates = [
75612
75792
  {
75613
75793
  cacheDir: configDir,
75614
- cachePackagePath: join28(configDir, "package.json"),
75794
+ cachePackagePath: join29(configDir, "package.json"),
75615
75795
  packageCandidates: createPackageCandidates(configDir)
75616
75796
  },
75617
75797
  {
75618
75798
  cacheDir,
75619
- cachePackagePath: join28(cacheDir, "package.json"),
75799
+ cachePackagePath: join29(cacheDir, "package.json"),
75620
75800
  packageCandidates: createPackageCandidates(cacheDir)
75621
75801
  }
75622
75802
  ];
75623
- const selectedCandidate = candidates.find((candidate) => candidate.packageCandidates.some((packageCandidate) => existsSync30(packageCandidate.installedPackagePath))) ?? candidates[0];
75803
+ const selectedCandidate = candidates.find((candidate) => candidate.packageCandidates.some((packageCandidate) => existsSync31(packageCandidate.installedPackagePath))) ?? candidates[0];
75624
75804
  const { cacheDir: selectedDir, cachePackagePath } = selectedCandidate;
75625
75805
  const selectedPackage = selectInstalledPackage(selectedCandidate);
75626
75806
  const installedPackagePath = selectedPackage.installedPackagePath;
@@ -75659,7 +75839,7 @@ var defaultDeps3 = {
75659
75839
  function isConfigValid(configPath) {
75660
75840
  if (!configPath)
75661
75841
  return true;
75662
- if (!existsSync31(configPath))
75842
+ if (!existsSync32(configPath))
75663
75843
  return false;
75664
75844
  try {
75665
75845
  parseJsonc(readFileSync26(configPath, "utf-8"));
@@ -75785,28 +75965,28 @@ async function checkSystem(deps = defaultDeps3) {
75785
75965
 
75786
75966
  // src/cli/doctor/checks/config.ts
75787
75967
  import { readFileSync as readFileSync29 } from "fs";
75788
- import { join as join32 } from "path";
75968
+ import { join as join33 } from "path";
75789
75969
  init_shared();
75790
75970
 
75791
75971
  // src/cli/doctor/checks/model-resolution-cache.ts
75792
75972
  init_shared();
75793
- import { existsSync as existsSync32, readFileSync as readFileSync27 } from "fs";
75973
+ import { existsSync as existsSync33, readFileSync as readFileSync27 } from "fs";
75794
75974
  import { homedir as homedir7 } from "os";
75795
- import { join as join29 } from "path";
75975
+ import { join as join30 } from "path";
75796
75976
  function getUserConfigDir2() {
75797
75977
  const xdgConfig = process.env.XDG_CONFIG_HOME;
75798
75978
  if (xdgConfig)
75799
- return join29(xdgConfig, "opencode");
75800
- return join29(homedir7(), ".config", "opencode");
75979
+ return join30(xdgConfig, "opencode");
75980
+ return join30(homedir7(), ".config", "opencode");
75801
75981
  }
75802
75982
  function loadCustomProviderNames() {
75803
75983
  const configDir = getUserConfigDir2();
75804
75984
  const candidatePaths = [
75805
- join29(configDir, "opencode.json"),
75806
- join29(configDir, "opencode.jsonc")
75985
+ join30(configDir, "opencode.json"),
75986
+ join30(configDir, "opencode.jsonc")
75807
75987
  ];
75808
75988
  for (const configPath of candidatePaths) {
75809
- if (!existsSync32(configPath))
75989
+ if (!existsSync33(configPath))
75810
75990
  continue;
75811
75991
  try {
75812
75992
  const content = readFileSync27(configPath, "utf-8");
@@ -75819,9 +75999,9 @@ function loadCustomProviderNames() {
75819
75999
  return [];
75820
76000
  }
75821
76001
  function loadAvailableModelsFromCache() {
75822
- const cacheFile = join29(getOpenCodeCacheDir(), "models.json");
76002
+ const cacheFile = join30(getOpenCodeCacheDir(), "models.json");
75823
76003
  const customProviders = loadCustomProviderNames();
75824
- if (!existsSync32(cacheFile)) {
76004
+ if (!existsSync33(cacheFile)) {
75825
76005
  if (customProviders.length > 0) {
75826
76006
  return { providers: customProviders, modelCount: 0, cacheExists: true };
75827
76007
  }
@@ -75852,8 +76032,8 @@ init_model_capabilities();
75852
76032
  // src/cli/doctor/checks/model-resolution-config.ts
75853
76033
  init_shared();
75854
76034
  import { readFileSync as readFileSync28 } from "fs";
75855
- import { join as join30 } from "path";
75856
- var PROJECT_CONFIG_DIR = join30(process.cwd(), ".opencode");
76035
+ import { join as join31 } from "path";
76036
+ var PROJECT_CONFIG_DIR = join31(process.cwd(), ".opencode");
75857
76037
  function loadOmoConfig() {
75858
76038
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
75859
76039
  if (projectDetected.format !== "none") {
@@ -75879,7 +76059,7 @@ function loadOmoConfig() {
75879
76059
 
75880
76060
  // src/cli/doctor/checks/model-resolution-details.ts
75881
76061
  init_shared();
75882
- import { join as join31 } from "path";
76062
+ import { join as join32 } from "path";
75883
76063
 
75884
76064
  // src/cli/doctor/checks/model-resolution-variant.ts
75885
76065
  function formatModelWithVariant(model, variant) {
@@ -75921,7 +76101,7 @@ function formatCapabilityResolutionLabel(mode) {
75921
76101
  }
75922
76102
  function buildModelResolutionDetails(options) {
75923
76103
  const details = [];
75924
- const cacheFile = join31(getOpenCodeCacheDir(), "models.json");
76104
+ const cacheFile = join32(getOpenCodeCacheDir(), "models.json");
75925
76105
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
75926
76106
  details.push("");
75927
76107
  if (options.available.cacheExists) {
@@ -76076,7 +76256,7 @@ async function checkModels() {
76076
76256
  }
76077
76257
 
76078
76258
  // src/cli/doctor/checks/config.ts
76079
- var PROJECT_CONFIG_DIR2 = join32(process.cwd(), ".opencode");
76259
+ var PROJECT_CONFIG_DIR2 = join33(process.cwd(), ".opencode");
76080
76260
  function findConfigPath() {
76081
76261
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
76082
76262
  if (projectConfig.format !== "none")
@@ -76196,30 +76376,55 @@ async function checkConfig() {
76196
76376
  }
76197
76377
 
76198
76378
  // src/cli/doctor/checks/dependencies.ts
76199
- init_spawn_with_windows_hide();
76200
- import { existsSync as existsSync33 } from "fs";
76379
+ import { existsSync as existsSync34 } from "fs";
76201
76380
  import { createRequire } from "module";
76202
- import { dirname as dirname13, join as join33 } from "path";
76381
+ import { dirname as dirname13, join as join35 } from "path";
76382
+
76383
+ // src/hooks/comment-checker/downloader.ts
76384
+ import { join as join34 } from "path";
76385
+ import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
76386
+ init_binary_downloader();
76387
+ init_logger();
76388
+ init_plugin_identity();
76389
+ var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
76390
+ var DEBUG_FILE = join34(tmpdir3(), "comment-checker-debug.log");
76391
+ function getCacheDir2() {
76392
+ if (process.platform === "win32") {
76393
+ const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
76394
+ const base2 = localAppData || join34(homedir8(), "AppData", "Local");
76395
+ return join34(base2, CACHE_DIR_NAME, "bin");
76396
+ }
76397
+ const xdgCache = process.env.XDG_CACHE_HOME;
76398
+ const base = xdgCache || join34(homedir8(), ".cache");
76399
+ return join34(base, CACHE_DIR_NAME, "bin");
76400
+ }
76401
+ function getBinaryName() {
76402
+ return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
76403
+ }
76404
+ function getCachedBinaryPath2() {
76405
+ return getCachedBinaryPath(getCacheDir2(), getBinaryName());
76406
+ }
76407
+
76408
+ // src/cli/doctor/checks/dependencies.ts
76203
76409
  async function checkBinaryExists(binary2) {
76204
76410
  try {
76205
- const path11 = Bun.which(binary2);
76206
- if (path11) {
76207
- return { exists: true, path: path11 };
76411
+ const path12 = Bun.which(binary2);
76412
+ if (path12) {
76413
+ return { exists: true, path: path12 };
76208
76414
  }
76209
76415
  } catch {}
76210
76416
  return { exists: false, path: null };
76211
76417
  }
76212
76418
  async function getBinaryVersion(binary2) {
76213
76419
  try {
76214
- const proc = spawnWithWindowsHide([binary2, "--version"], { stdout: "pipe", stderr: "pipe" });
76215
- const output = await new Response(proc.stdout).text();
76216
- await proc.exited;
76217
- if (proc.exitCode === 0) {
76218
- return output.trim().split(`
76219
- `)[0];
76220
- }
76221
- } catch {}
76222
- return null;
76420
+ const result = await spawnWithTimeout([binary2, "--version"], { stdout: "pipe", stderr: "pipe" });
76421
+ if (result.timedOut || result.exitCode !== 0)
76422
+ return null;
76423
+ return result.stdout.trim().split(`
76424
+ `)[0] ?? null;
76425
+ } catch {
76426
+ return null;
76427
+ }
76223
76428
  }
76224
76429
  async function checkAstGrepCli() {
76225
76430
  const binaryCheck = await checkBinaryExists("sg");
@@ -76255,15 +76460,15 @@ async function checkAstGrepNapi() {
76255
76460
  path: null
76256
76461
  };
76257
76462
  } catch {
76258
- const { existsSync: existsSync34 } = await import("fs");
76259
- const { join: join34 } = await import("path");
76260
- const { homedir: homedir8 } = await import("os");
76463
+ const { existsSync: existsSync35 } = await import("fs");
76464
+ const { join: join36 } = await import("path");
76465
+ const { homedir: homedir9 } = await import("os");
76261
76466
  const pathsToCheck = [
76262
- join34(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
76263
- join34(process.cwd(), "node_modules", "@ast-grep", "napi")
76467
+ join36(homedir9(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
76468
+ join36(process.cwd(), "node_modules", "@ast-grep", "napi")
76264
76469
  ];
76265
76470
  for (const napiPath of pathsToCheck) {
76266
- if (existsSync34(napiPath)) {
76471
+ if (existsSync35(napiPath)) {
76267
76472
  return {
76268
76473
  name: "AST-Grep NAPI",
76269
76474
  required: false,
@@ -76288,13 +76493,24 @@ function findCommentCheckerPackageBinary() {
76288
76493
  try {
76289
76494
  const require2 = createRequire(import.meta.url);
76290
76495
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
76291
- const binaryPath = join33(dirname13(pkgPath), "bin", binaryName);
76292
- if (existsSync33(binaryPath))
76496
+ const binaryPath = join35(dirname13(pkgPath), "bin", binaryName);
76497
+ if (existsSync34(binaryPath))
76293
76498
  return binaryPath;
76294
76499
  } catch {}
76295
76500
  return null;
76296
76501
  }
76297
76502
  async function checkCommentChecker() {
76503
+ const cachedPath = getCachedBinaryPath2();
76504
+ if (cachedPath) {
76505
+ const version4 = await getBinaryVersion(cachedPath);
76506
+ return {
76507
+ name: "Comment Checker",
76508
+ required: false,
76509
+ installed: true,
76510
+ version: version4,
76511
+ path: cachedPath
76512
+ };
76513
+ }
76298
76514
  const binaryCheck = await checkBinaryExists("comment-checker");
76299
76515
  const resolvedPath = binaryCheck.exists ? binaryCheck.path : findCommentCheckerPackageBinary();
76300
76516
  if (!resolvedPath) {
@@ -76318,7 +76534,6 @@ async function checkCommentChecker() {
76318
76534
  }
76319
76535
 
76320
76536
  // src/cli/doctor/checks/tools-gh.ts
76321
- init_spawn_with_windows_hide();
76322
76537
  async function checkBinaryExists2(binary2) {
76323
76538
  try {
76324
76539
  const binaryPath = Bun.which(binary2);
@@ -76329,13 +76544,11 @@ async function checkBinaryExists2(binary2) {
76329
76544
  }
76330
76545
  async function getGhVersion() {
76331
76546
  try {
76332
- const processResult = spawnWithWindowsHide(["gh", "--version"], { stdout: "pipe", stderr: "pipe" });
76333
- const output = await new Response(processResult.stdout).text();
76334
- await processResult.exited;
76335
- if (processResult.exitCode !== 0)
76547
+ const result = await spawnWithTimeout(["gh", "--version"], { stdout: "pipe", stderr: "pipe" });
76548
+ if (result.timedOut || result.exitCode !== 0)
76336
76549
  return null;
76337
- const matchedVersion = output.match(/gh version (\S+)/);
76338
- return matchedVersion?.[1] ?? output.trim().split(`
76550
+ const matchedVersion = result.stdout.match(/gh version (\S+)/);
76551
+ return matchedVersion?.[1] ?? result.stdout.trim().split(`
76339
76552
  `)[0] ?? null;
76340
76553
  } catch {
76341
76554
  return null;
@@ -76343,16 +76556,12 @@ async function getGhVersion() {
76343
76556
  }
76344
76557
  async function getGhAuthStatus() {
76345
76558
  try {
76346
- const processResult = spawnWithWindowsHide(["gh", "auth", "status"], {
76347
- stdout: "pipe",
76348
- stderr: "pipe",
76349
- env: { ...process.env, GH_NO_UPDATE_NOTIFIER: "1" }
76350
- });
76351
- const stdout = await new Response(processResult.stdout).text();
76352
- const stderr = await new Response(processResult.stderr).text();
76353
- await processResult.exited;
76354
- const output = stderr || stdout;
76355
- if (processResult.exitCode === 0) {
76559
+ const result = await spawnWithTimeout(["gh", "auth", "status"], { stdout: "pipe", stderr: "pipe", env: { ...process.env, GH_NO_UPDATE_NOTIFIER: "1" } });
76560
+ if (result.timedOut) {
76561
+ return { authenticated: false, username: null, scopes: [], error: "gh auth status timed out" };
76562
+ }
76563
+ const output = result.stderr || result.stdout;
76564
+ if (result.exitCode === 0) {
76356
76565
  const usernameMatch = output.match(/Logged in to github\.com account (\S+)/);
76357
76566
  const scopesMatch = output.match(/Token scopes?:\s*(.+)/i);
76358
76567
  return {
@@ -76446,15 +76655,15 @@ var BUILTIN_SERVERS = {
76446
76655
  "kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
76447
76656
  };
76448
76657
  // src/tools/lsp/server-config-loader.ts
76449
- import { existsSync as existsSync34, readFileSync as readFileSync30 } from "fs";
76450
- import { join as join34 } from "path";
76658
+ import { existsSync as existsSync35, readFileSync as readFileSync30 } from "fs";
76659
+ import { join as join36 } from "path";
76451
76660
  init_shared();
76452
76661
  init_jsonc_parser();
76453
- function loadJsonFile(path11) {
76454
- if (!existsSync34(path11))
76662
+ function loadJsonFile(path12) {
76663
+ if (!existsSync35(path12))
76455
76664
  return null;
76456
76665
  try {
76457
- return parseJsonc(readFileSync30(path11, "utf-8"));
76666
+ return parseJsonc(readFileSync30(path12, "utf-8"));
76458
76667
  } catch {
76459
76668
  return null;
76460
76669
  }
@@ -76463,9 +76672,9 @@ function getConfigPaths2() {
76463
76672
  const cwd = process.cwd();
76464
76673
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
76465
76674
  return {
76466
- project: detectPluginConfigFile(join34(cwd, ".opencode")).path,
76675
+ project: detectPluginConfigFile(join36(cwd, ".opencode")).path,
76467
76676
  user: detectPluginConfigFile(configDir).path,
76468
- opencode: detectConfigFile(join34(configDir, "opencode")).path
76677
+ opencode: detectConfigFile(join36(configDir, "opencode")).path
76469
76678
  };
76470
76679
  }
76471
76680
  function loadAllConfigs() {
@@ -76534,21 +76743,21 @@ function getMergedServers() {
76534
76743
  }
76535
76744
 
76536
76745
  // src/tools/lsp/server-installation.ts
76537
- import { existsSync as existsSync35 } from "fs";
76538
- import { delimiter as delimiter2, join as join36 } from "path";
76746
+ import { existsSync as existsSync36 } from "fs";
76747
+ import { delimiter as delimiter2, join as join38 } from "path";
76539
76748
 
76540
76749
  // src/tools/lsp/server-path-bases.ts
76541
76750
  init_shared();
76542
- import { join as join35 } from "path";
76751
+ import { join as join37 } from "path";
76543
76752
  function getLspServerAdditionalPathBases(workingDirectory) {
76544
76753
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
76545
- const dataDir = join35(getDataDir(), "opencode");
76754
+ const dataDir = join37(getDataDir(), "opencode");
76546
76755
  return [
76547
- join35(workingDirectory, "node_modules", ".bin"),
76548
- join35(configDir, "bin"),
76549
- join35(configDir, "node_modules", ".bin"),
76550
- join35(dataDir, "bin"),
76551
- join35(dataDir, "bin", "node_modules", ".bin")
76756
+ join37(workingDirectory, "node_modules", ".bin"),
76757
+ join37(configDir, "bin"),
76758
+ join37(configDir, "node_modules", ".bin"),
76759
+ join37(dataDir, "bin"),
76760
+ join37(dataDir, "bin", "node_modules", ".bin")
76552
76761
  ];
76553
76762
  }
76554
76763
 
@@ -76558,7 +76767,7 @@ function isServerInstalled(command) {
76558
76767
  return false;
76559
76768
  const cmd = command[0];
76560
76769
  if (cmd.includes("/") || cmd.includes("\\")) {
76561
- if (existsSync35(cmd))
76770
+ if (existsSync36(cmd))
76562
76771
  return true;
76563
76772
  }
76564
76773
  const isWindows = process.platform === "win32";
@@ -76579,14 +76788,14 @@ function isServerInstalled(command) {
76579
76788
  const paths = pathEnv.split(delimiter2);
76580
76789
  for (const p2 of paths) {
76581
76790
  for (const suffix of exts) {
76582
- if (existsSync35(join36(p2, cmd + suffix))) {
76791
+ if (existsSync36(join38(p2, cmd + suffix))) {
76583
76792
  return true;
76584
76793
  }
76585
76794
  }
76586
76795
  }
76587
76796
  for (const base of getLspServerAdditionalPathBases(process.cwd())) {
76588
76797
  for (const suffix of exts) {
76589
- if (existsSync35(join36(base, cmd + suffix))) {
76798
+ if (existsSync36(join38(base, cmd + suffix))) {
76590
76799
  return true;
76591
76800
  }
76592
76801
  }
@@ -76648,21 +76857,21 @@ function getInstalledLspServers() {
76648
76857
 
76649
76858
  // src/cli/doctor/checks/tools-mcp.ts
76650
76859
  init_shared();
76651
- import { existsSync as existsSync36, readFileSync as readFileSync31 } from "fs";
76652
- import { homedir as homedir8 } from "os";
76653
- import { join as join37 } from "path";
76860
+ import { existsSync as existsSync37, readFileSync as readFileSync31 } from "fs";
76861
+ import { homedir as homedir9 } from "os";
76862
+ import { join as join39 } from "path";
76654
76863
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
76655
76864
  function getMcpConfigPaths() {
76656
76865
  return [
76657
- join37(homedir8(), ".claude", ".mcp.json"),
76658
- join37(process.cwd(), ".mcp.json"),
76659
- join37(process.cwd(), ".claude", ".mcp.json")
76866
+ join39(homedir9(), ".claude", ".mcp.json"),
76867
+ join39(process.cwd(), ".mcp.json"),
76868
+ join39(process.cwd(), ".claude", ".mcp.json")
76660
76869
  ];
76661
76870
  }
76662
76871
  function loadUserMcpConfig() {
76663
76872
  const servers = {};
76664
76873
  for (const configPath of getMcpConfigPaths()) {
76665
- if (!existsSync36(configPath))
76874
+ if (!existsSync37(configPath))
76666
76875
  continue;
76667
76876
  try {
76668
76877
  const content = readFileSync31(configPath, "utf-8");
@@ -77025,6 +77234,14 @@ function formatJsonOutput2(result) {
77025
77234
  }
77026
77235
 
77027
77236
  // src/cli/doctor/runner.ts
77237
+ var DOCTOR_TIMEOUT_MS = 30000;
77238
+
77239
+ class DoctorTimeoutError extends Error {
77240
+ constructor() {
77241
+ super("Doctor timed out");
77242
+ this.name = "DoctorTimeoutError";
77243
+ }
77244
+ }
77028
77245
  async function runCheck(check2) {
77029
77246
  const start = performance.now();
77030
77247
  try {
@@ -77054,14 +77271,49 @@ function calculateSummary(results, duration3) {
77054
77271
  function determineExitCode(results) {
77055
77272
  return results.some((r2) => r2.status === "fail") ? EXIT_CODES.FAILURE : EXIT_CODES.SUCCESS;
77056
77273
  }
77274
+ function buildTimeoutResult(start, options) {
77275
+ const timeoutResult = {
77276
+ results: [{ name: "Timeout", status: "fail", message: "Doctor timed out after 30s", issues: [{ title: "Doctor timeout", description: "Checks did not complete within 30s. A subprocess may be hanging.", severity: "error" }] }],
77277
+ systemInfo: { opencodeVersion: null, opencodePath: null, pluginVersion: null, loadedVersion: null, bunVersion: null, configPath: null, configValid: false, isLocalDev: false },
77278
+ tools: { lspServers: [], astGrepCli: false, astGrepNapi: false, commentChecker: false, ghCli: { installed: false, authenticated: false, username: null }, mcpBuiltin: [], mcpUser: [] },
77279
+ summary: { total: 1, passed: 0, failed: 1, warnings: 0, skipped: 0, duration: Math.round(performance.now() - start) },
77280
+ exitCode: EXIT_CODES.FAILURE
77281
+ };
77282
+ if (options.json) {
77283
+ console.log(formatJsonOutput2(timeoutResult));
77284
+ } else {
77285
+ console.error(`
77286
+ Doctor timed out after 30s. A subprocess may be hanging.`);
77287
+ console.error(`Try running with --verbose to identify the stuck check.
77288
+ `);
77289
+ }
77290
+ return timeoutResult;
77291
+ }
77057
77292
  async function runDoctor(options) {
77058
77293
  const start = performance.now();
77059
77294
  const allChecks = getAllCheckDefinitions();
77060
- const [results, systemInfo, tools] = await Promise.all([
77295
+ const checksPromise = Promise.all([
77061
77296
  Promise.all(allChecks.map(runCheck)),
77062
77297
  gatherSystemInfo(),
77063
77298
  gatherToolsSummary()
77064
77299
  ]);
77300
+ let timer;
77301
+ const timeoutPromise = new Promise((_3, reject) => {
77302
+ timer = setTimeout(() => reject(new DoctorTimeoutError), DOCTOR_TIMEOUT_MS);
77303
+ });
77304
+ let results;
77305
+ let systemInfo;
77306
+ let tools;
77307
+ try {
77308
+ [results, systemInfo, tools] = await Promise.race([checksPromise, timeoutPromise]);
77309
+ } catch (error48) {
77310
+ clearTimeout(timer);
77311
+ if (error48 instanceof DoctorTimeoutError) {
77312
+ return buildTimeoutResult(start, options);
77313
+ }
77314
+ throw error48;
77315
+ }
77316
+ clearTimeout(timer);
77065
77317
  const duration3 = performance.now() - start;
77066
77318
  const summary = calculateSummary(results, duration3);
77067
77319
  const exitCode = determineExitCode(results);
@@ -77120,11 +77372,11 @@ async function refreshModelCapabilities(options, deps = {}) {
77120
77372
 
77121
77373
  // src/features/mcp-oauth/storage.ts
77122
77374
  init_shared();
77123
- import { chmodSync, existsSync as existsSync37, mkdirSync as mkdirSync11, readFileSync as readFileSync32, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
77124
- import { dirname as dirname14, join as join38 } from "path";
77375
+ import { chmodSync as chmodSync2, existsSync as existsSync38, mkdirSync as mkdirSync12, readFileSync as readFileSync32, renameSync as renameSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync10 } from "fs";
77376
+ import { dirname as dirname14, join as join40 } from "path";
77125
77377
  var STORAGE_FILE_NAME = "mcp-oauth.json";
77126
77378
  function getMcpOauthStoragePath() {
77127
- return join38(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
77379
+ return join40(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
77128
77380
  }
77129
77381
  function normalizeHost(serverHost) {
77130
77382
  let host = serverHost.trim();
@@ -77161,7 +77413,7 @@ function buildKey(serverHost, resource) {
77161
77413
  }
77162
77414
  function readStore() {
77163
77415
  const filePath = getMcpOauthStoragePath();
77164
- if (!existsSync37(filePath)) {
77416
+ if (!existsSync38(filePath)) {
77165
77417
  return null;
77166
77418
  }
77167
77419
  try {
@@ -77175,12 +77427,12 @@ function writeStore(store2) {
77175
77427
  const filePath = getMcpOauthStoragePath();
77176
77428
  try {
77177
77429
  const dir = dirname14(filePath);
77178
- if (!existsSync37(dir)) {
77179
- mkdirSync11(dir, { recursive: true });
77430
+ if (!existsSync38(dir)) {
77431
+ mkdirSync12(dir, { recursive: true });
77180
77432
  }
77181
77433
  const tempPath = `${filePath}.tmp.${Date.now()}`;
77182
77434
  writeFileSync10(tempPath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
77183
- chmodSync(tempPath, 384);
77435
+ chmodSync2(tempPath, 384);
77184
77436
  renameSync4(tempPath, filePath);
77185
77437
  return true;
77186
77438
  } catch {
@@ -77212,8 +77464,8 @@ function deleteToken(serverHost, resource) {
77212
77464
  if (Object.keys(store2).length === 0) {
77213
77465
  try {
77214
77466
  const filePath = getMcpOauthStoragePath();
77215
- if (existsSync37(filePath)) {
77216
- unlinkSync4(filePath);
77467
+ if (existsSync38(filePath)) {
77468
+ unlinkSync6(filePath);
77217
77469
  }
77218
77470
  return true;
77219
77471
  } catch {
@@ -77795,20 +78047,21 @@ function createMcpOAuthCommand() {
77795
78047
  var VERSION2 = package_default.version;
77796
78048
  var program2 = new Command;
77797
78049
  program2.name("oh-my-opencode").description("The ultimate OpenCode plugin - multi-model orchestration, LSP tools, and more").version(VERSION2, "-v, --version", "Show version number").enablePositionalOptions();
77798
- program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--openai <value>", "OpenAI/ChatGPT subscription: no, yes (default: no)").option("--gemini <value>", "Gemini integration: no, yes").option("--copilot <value>", "GitHub Copilot subscription: no, yes").option("--opencode-zen <value>", "OpenCode Zen access: no, yes (default: no)").option("--zai-coding-plan <value>", "Z.ai Coding Plan subscription: no, yes (default: no)").option("--kimi-for-coding <value>", "Kimi For Coding subscription: no, yes (default: no)").option("--opencode-go <value>", "OpenCode Go subscription: no, yes (default: no)").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
78050
+ program2.command("install").description("Install and configure oh-my-opencode with interactive setup").option("--no-tui", "Run in non-interactive mode (requires all options)").option("--claude <value>", "Claude subscription: no, yes, max20").option("--openai <value>", "OpenAI/ChatGPT subscription: no, yes (default: no)").option("--gemini <value>", "Gemini integration: no, yes").option("--copilot <value>", "GitHub Copilot subscription: no, yes").option("--opencode-zen <value>", "OpenCode Zen access: no, yes (default: no)").option("--zai-coding-plan <value>", "Z.ai Coding Plan subscription: no, yes (default: no)").option("--kimi-for-coding <value>", "Kimi For Coding subscription: no, yes (default: no)").option("--opencode-go <value>", "OpenCode Go subscription: no, yes (default: no)").option("--vercel-ai-gateway <value>", "Vercel AI Gateway: no, yes (default: no)").option("--skip-auth", "Skip authentication setup hints").addHelpText("after", `
77799
78051
  Examples:
77800
78052
  $ bunx oh-my-opencode install
77801
78053
  $ bunx oh-my-opencode install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no
77802
78054
  $ bunx oh-my-opencode install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes
77803
78055
 
77804
- Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
78056
+ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi > Vercel):
77805
78057
  Claude Native anthropic/ models (Opus, Sonnet, Haiku)
77806
78058
  OpenAI Native openai/ models (GPT-5.4 for Oracle)
77807
78059
  Gemini Native google/ models (Gemini 3.1 Pro, Flash)
77808
78060
  Copilot github-copilot/ models (fallback)
77809
78061
  OpenCode Zen opencode/ models (opencode/claude-opus-4-6, etc.)
77810
- Z.ai zai-coding-plan/glm-5 (visual-engineering fallback)
78062
+ Z.ai zai-coding-plan/glm-5 (visual-engineering fallback)
77811
78063
  Kimi kimi-for-coding/k2p5 (Sisyphus/Prometheus fallback)
78064
+ Vercel vercel/ models (universal proxy, always last fallback)
77812
78065
  `).action(async (options) => {
77813
78066
  const args = {
77814
78067
  tui: options.tui !== false,
@@ -77820,6 +78073,7 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
77820
78073
  zaiCodingPlan: options.zaiCodingPlan,
77821
78074
  kimiForCoding: options.kimiForCoding,
77822
78075
  opencodeGo: options.opencodeGo,
78076
+ vercelAiGateway: options.vercelAiGateway,
77823
78077
  skipAuth: options.skipAuth ?? false
77824
78078
  };
77825
78079
  const exitCode = await install(args);