@tritard/waterbrother 0.16.8 → 0.16.9

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 (3) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/cli.js +43 -18
package/README.md CHANGED
@@ -29,7 +29,7 @@ It is Vercel-ready via `vercel.json` (clean URLs, no build step required).
29
29
  - First-run onboarding wizard in terminal
30
30
  - asks for provider first
31
31
  - asks for API key when the selected provider requires one
32
- - tries a live provider model list after credentials, then falls back to the built-in catalog
32
+ - tries a live provider model list after credentials, shows when that live list is in use, then falls back to the built-in catalog
33
33
  - prompts for default model and agent profile
34
34
  - Multi-provider chat integration through provider adapters and model registry
35
35
  - Vision command for local images: `waterbrother vision <image-path> <prompt>`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.16.8",
3
+ "version": "0.16.9",
4
4
  "description": "Waterbrother: bring-your-own-model coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -2830,7 +2830,7 @@ async function chooseProviderInteractive(defaultProvider = 'xai') {
2830
2830
  return selected?.value || defaultProvider;
2831
2831
  }
2832
2832
 
2833
- async function chooseModelInteractive(defaultModel, provider = '', { apiKey = '', baseUrl = '', allowRemote = true } = {}) {
2833
+ async function buildModelPickerOptions(defaultModel, provider = '', { apiKey = '', baseUrl = '', allowRemote = true } = {}) {
2834
2834
  const normalizedProvider = normalizeProvider(provider);
2835
2835
  let remoteModels = [];
2836
2836
  if (allowRemote && normalizedProvider) {
@@ -2882,31 +2882,51 @@ async function chooseModelInteractive(defaultModel, provider = '', { apiKey = ''
2882
2882
  label: `${model.label}${index === defaultIndex ? " (default)" : ""}`
2883
2883
  }));
2884
2884
 
2885
+ return {
2886
+ normalizedProvider,
2887
+ options: titledOptions,
2888
+ defaultIndex,
2889
+ usedRemote: remoteModels.length > 0
2890
+ };
2891
+ }
2892
+
2893
+ async function chooseModelInteractive(defaultModel, provider = '', { apiKey = '', baseUrl = '', allowRemote = true } = {}) {
2894
+ const picker = await buildModelPickerOptions(defaultModel, provider, { apiKey, baseUrl, allowRemote });
2895
+ if (picker.usedRemote) {
2896
+ console.log(dim(`Using live ${picker.normalizedProvider} model list.`));
2897
+ } else if (picker.normalizedProvider) {
2898
+ console.log(dim(`Live ${picker.normalizedProvider} model list unavailable. Falling back to the built-in catalog.`));
2899
+ }
2900
+
2885
2901
  const selected = await chooseFromInteractiveMenu({
2886
- title: remoteModels.length
2887
- ? `Select default model for ${normalizedProvider} (live list):`
2888
- : normalizedProvider
2889
- ? `Select default model for ${normalizedProvider}:`
2902
+ title: picker.usedRemote
2903
+ ? `Select default model for ${picker.normalizedProvider} (live list):`
2904
+ : picker.normalizedProvider
2905
+ ? `Select default model for ${picker.normalizedProvider}:`
2890
2906
  : "Select default model:",
2891
- options: titledOptions,
2892
- defaultIndex
2907
+ options: picker.options,
2908
+ defaultIndex: picker.defaultIndex
2893
2909
  });
2894
2910
  return selected?.value || defaultModel;
2895
2911
  }
2896
2912
 
2897
- async function chooseRuntimeModelInteractive(currentModel, provider = '') {
2898
- const normalizedProvider = normalizeProvider(provider);
2899
- const catalog = MODEL_CATALOG.filter((model) => !normalizedProvider || model.provider === normalizedProvider);
2900
- if (catalog.length === 0) return currentModel;
2901
- const defaultIndex = Math.max(0, catalog.findIndex((model) => model.id === currentModel));
2902
- const options = catalog.map((model, index) => ({
2903
- value: model.id,
2904
- label: `${model.id}${index === defaultIndex ? ' (current)' : ''}`
2913
+ async function chooseRuntimeModelInteractive(currentModel, provider = '', { apiKey = '', baseUrl = '', allowRemote = true } = {}) {
2914
+ const picker = await buildModelPickerOptions(currentModel, provider, { apiKey, baseUrl, allowRemote });
2915
+ if (!picker.options.length) return currentModel;
2916
+ const options = picker.options.map((model, index) => ({
2917
+ value: model.value,
2918
+ label: model.value === currentModel || index === picker.defaultIndex
2919
+ ? model.label.replace(/ \(default\)$/, "") + " (current)"
2920
+ : model.label.replace(/ \(default\)$/, "")
2905
2921
  }));
2906
2922
  const selected = await chooseFromInteractiveMenu({
2907
- title: normalizedProvider ? `Select ${normalizedProvider} model:` : 'Select model:',
2923
+ title: picker.usedRemote
2924
+ ? `Select ${picker.normalizedProvider} model (live list):`
2925
+ : picker.normalizedProvider
2926
+ ? `Select ${picker.normalizedProvider} model:`
2927
+ : 'Select model:',
2908
2928
  options,
2909
- defaultIndex
2929
+ defaultIndex: picker.defaultIndex
2910
2930
  });
2911
2931
  return selected?.value || currentModel;
2912
2932
  }
@@ -8296,7 +8316,12 @@ Be concrete about surfaces — name actual pages/flows. Choose the best stack fo
8296
8316
 
8297
8317
  if (line === "/models") {
8298
8318
  try {
8299
- const selectedModel = await chooseRuntimeModelInteractive(agent.getModel(), context.runtime.provider);
8319
+ const providerSpec = getProviderSpec(context.runtime.provider);
8320
+ const selectedModel = await chooseRuntimeModelInteractive(agent.getModel(), context.runtime.provider, {
8321
+ apiKey: context.runtime.apiKey,
8322
+ baseUrl: context.runtime.baseUrl,
8323
+ allowRemote: providerSpec?.supportsRemoteModelList !== false
8324
+ });
8300
8325
  const { config } = await loadConfigLayers(context.cwd);
8301
8326
  const nextRuntime = await applyRuntimeSelection({
8302
8327
  config,