@tritard/waterbrother 0.16.7 → 0.16.8

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 -0
  2. package/package.json +1 -1
  3. package/src/cli.js +62 -9
package/README.md CHANGED
@@ -29,6 +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
33
  - prompts for default model and agent profile
33
34
  - Multi-provider chat integration through provider adapters and model registry
34
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.7",
3
+ "version": "0.16.8",
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,16 +2830,65 @@ async function chooseProviderInteractive(defaultProvider = 'xai') {
2830
2830
  return selected?.value || defaultProvider;
2831
2831
  }
2832
2832
 
2833
- async function chooseModelInteractive(defaultModel, provider = '') {
2834
- const catalog = MODEL_CATALOG.filter((model) => !provider || model.provider === provider);
2835
- const defaultIndex = Math.max(0, catalog.findIndex((model) => model.id === defaultModel));
2836
- const options = catalog.map((model, index) => ({
2837
- value: model.id,
2838
- label: `${model.id}${index === defaultIndex ? ' (default)' : ''}`
2833
+ async function chooseModelInteractive(defaultModel, provider = '', { apiKey = '', baseUrl = '', allowRemote = true } = {}) {
2834
+ const normalizedProvider = normalizeProvider(provider);
2835
+ let remoteModels = [];
2836
+ if (allowRemote && normalizedProvider) {
2837
+ try {
2838
+ remoteModels = await listModels({
2839
+ provider: normalizedProvider,
2840
+ apiKey,
2841
+ baseUrl
2842
+ });
2843
+ } catch {
2844
+ remoteModels = [];
2845
+ }
2846
+ }
2847
+
2848
+ const seen = new Set();
2849
+ const options = [];
2850
+
2851
+ for (const model of remoteModels) {
2852
+ const value = String(model?.id || "").trim();
2853
+ if (!value || seen.has(value)) continue;
2854
+ seen.add(value);
2855
+ options.push({
2856
+ value,
2857
+ label: model?.notes ? `${value} - ${model.notes}` : value
2858
+ });
2859
+ }
2860
+
2861
+ for (const model of MODEL_CATALOG) {
2862
+ if (normalizedProvider && model.provider !== normalizedProvider) continue;
2863
+ const value = String(model?.id || "").trim();
2864
+ if (!value || seen.has(value)) continue;
2865
+ seen.add(value);
2866
+ options.push({
2867
+ value,
2868
+ label: model?.notes ? `${value} - ${model.notes}` : value
2869
+ });
2870
+ }
2871
+
2872
+ if (!options.length) {
2873
+ options.push({
2874
+ value: defaultModel,
2875
+ label: `${defaultModel} (default)`
2876
+ });
2877
+ }
2878
+
2879
+ const defaultIndex = Math.max(0, options.findIndex((model) => model.value === defaultModel));
2880
+ const titledOptions = options.map((model, index) => ({
2881
+ value: model.value,
2882
+ label: `${model.label}${index === defaultIndex ? " (default)" : ""}`
2839
2883
  }));
2884
+
2840
2885
  const selected = await chooseFromInteractiveMenu({
2841
- title: 'Select default model:',
2842
- options,
2886
+ title: remoteModels.length
2887
+ ? `Select default model for ${normalizedProvider} (live list):`
2888
+ : normalizedProvider
2889
+ ? `Select default model for ${normalizedProvider}:`
2890
+ : "Select default model:",
2891
+ options: titledOptions,
2843
2892
  defaultIndex
2844
2893
  });
2845
2894
  return selected?.value || defaultModel;
@@ -2927,7 +2976,11 @@ async function runOnboardingWizard(config, { cwd }) {
2927
2976
  }
2928
2977
 
2929
2978
  next.baseUrl = providerSpec?.defaultBaseUrl || next.baseUrl || '';
2930
- next.model = await chooseModelInteractive(next.model || getDefaultModelForProvider(next.provider), next.provider);
2979
+ next.model = await chooseModelInteractive(next.model || getDefaultModelForProvider(next.provider), next.provider, {
2980
+ apiKey: next.apiKey,
2981
+ baseUrl: next.baseUrl,
2982
+ allowRemote: providerSpec?.supportsRemoteModelList !== false
2983
+ });
2931
2984
  next.agentProfile = await chooseAgentProfileInteractive(next.agentProfile || 'coder');
2932
2985
  if (!next.approvalMode) next.approvalMode = 'on-request';
2933
2986
  if (!next.designModel) next.designModel = getDefaultDesignModelForProvider(next.provider);