mindweave 2.4.0 → 2.4.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.
package/README.md CHANGED
@@ -71,7 +71,7 @@ else is configured inside a session.
71
71
 
72
72
  Short version, one line each. The depth is in the linked pages.
73
73
 
74
- - **14 providers, 54 models, one key** — DeepSeek, Anthropic, OpenAI, Gemini, xAI,
74
+ - **14 providers, 52 models, one key** — DeepSeek, Anthropic, OpenAI, Gemini, xAI,
75
75
  Mistral, Groq, Cerebras, Qwen, Kimi, GLM, Meta, MiniMax, Tencent. Only the driver you
76
76
  use is loaded. Switch with `/provider` and `/model`; remembered per project.
77
77
  [PROVIDERS.md](src/drivers/PROVIDERS.md)
package/dist/cli/App.js CHANGED
@@ -46,6 +46,7 @@ import { projectDir } from "../memory/store.js";
46
46
  import { parseUndoArg, undoNotice } from "../tools/checkpoints.js";
47
47
  import { DEFAULT_MODEL_CONFIG, thinkLevels, thinkLabel, modelLabel, modelsOfProvider, providerOf, usableFallback, needsKeySetup, withModel, saveModelConfig, refreshModels } from "../dynamo/model.js";
48
48
  import { allProviders, manifestForModel, modelsOf } from "../drivers/registry.js";
49
+ import { orderProviders, orderModels } from "./pickerOrder.js";
49
50
  import { accessRefusal } from "../drivers/providerError.js";
50
51
  import { resolveAttachments, stripAttachments } from "./attachments.js";
51
52
  import { collapsePastes, wrapPastedText } from "../memory/pastedText.js";
@@ -123,6 +124,19 @@ function missingKeyFor(model) {
123
124
  return null;
124
125
  return { envVar: provider.apiKeyEnv, label: provider.label, keysUrl: provider.keysUrl };
125
126
  }
127
+ /**
128
+ * The providers `/provider` lists, in display order: the default first, then the ones
129
+ * you have a key for, then the rest, each group alphabetical. Called by the render, the
130
+ * selection handler and the initial-cursor lookup, so all three index the same order —
131
+ * see pickerOrder.
132
+ */
133
+ function orderedProviderList() {
134
+ return orderProviders(allProviders(), (p) => hasApiKey(p.apiKeyEnv), providerOf(DEFAULT_MODEL_CONFIG.model).id);
135
+ }
136
+ /** One provider's models in display order: its default first, the rest alphabetical. */
137
+ function orderedModelList(model) {
138
+ return orderModels(modelsOfProvider(model));
139
+ }
126
140
  // After you pick a session in /continue, the three ways to resume it.
127
141
  const RESUME_MODES = [
128
142
  { label: "Compact & continue", description: "summarize the old chat first so it won't eat your context, then pick up where you left off" },
@@ -1979,10 +1993,11 @@ export function App({ resumeSessionId, initialScreen }) {
1979
1993
  // the choice for this project, and confirm.
1980
1994
  async function applyModel(index) {
1981
1995
  const s = session.current;
1982
- // Index into the SAME list the picker rendered — the current provider's models,
1983
- // not every model everywhere. Indexing the global list here would silently select
1984
- // a different model than the one on screen, and would type-check perfectly.
1985
- const choice = s ? modelsOfProvider(s.modelConfig.model)[index] : undefined;
1996
+ // Index into the SAME list the picker rendered — the current provider's models in
1997
+ // display order, not every model everywhere. Indexing a differently-ordered list
1998
+ // here would silently select a different model than the one on screen, and would
1999
+ // type-check perfectly.
2000
+ const choice = s ? orderedModelList(s.modelConfig.model)[index] : undefined;
1986
2001
  if (!s || !choice)
1987
2002
  return;
1988
2003
  s.modelConfig = withModel(s.modelConfig, choice.id);
@@ -1997,7 +2012,8 @@ export function App({ resumeSessionId, initialScreen }) {
1997
2012
  */
1998
2013
  async function applyProvider(index) {
1999
2014
  const s = session.current;
2000
- const provider = allProviders()[index];
2015
+ // The display-ordered list, matching what the picker rendered and its cursor.
2016
+ const provider = orderedProviderList()[index];
2001
2017
  if (!s || !provider)
2002
2018
  return;
2003
2019
  if (providerOf(s.modelConfig.model).id === provider.id) {
@@ -2459,7 +2475,7 @@ export function App({ resumeSessionId, initialScreen }) {
2459
2475
  if (name === "/model") {
2460
2476
  await refreshModels();
2461
2477
  if (arg) {
2462
- const picked = resolveChoice(arg, modelsOfProvider(s.modelConfig.model), "model");
2478
+ const picked = resolveChoice(arg, orderedModelList(s.modelConfig.model), "model");
2463
2479
  if (picked.kind === "error")
2464
2480
  return say(picked.message);
2465
2481
  await applyModel(picked.index);
@@ -2908,7 +2924,7 @@ export function App({ resumeSessionId, initialScreen }) {
2908
2924
  // provider you are already on otherwise says no more than any other row, leaving the
2909
2925
  // one thing you came to check — what you are on right now — off the screen.
2910
2926
  const activeLabel = modelLabel(activeModel);
2911
- const providers = allProviders();
2927
+ const providers = orderedProviderList();
2912
2928
  const items = providers.map((p) => {
2913
2929
  const n = modelsOf(p).length;
2914
2930
  const models = `${n} model${n === 1 ? "" : "s"}`;
@@ -2922,8 +2938,9 @@ export function App({ resumeSessionId, initialScreen }) {
2922
2938
  }
2923
2939
  if (overlay.kind === "model") {
2924
2940
  const id = cur?.modelConfig.model ?? DEFAULT_MODEL_CONFIG.model;
2925
- // Only the current provider's models. Switching provider is /provider's job.
2926
- const models = modelsOfProvider(id);
2941
+ // Only the current provider's models, in display order (default first, rest A→Z).
2942
+ // Switching provider is /provider's job.
2943
+ const models = orderedModelList(id);
2927
2944
  // The two facts that decide the choice and are nowhere else on the screen: how much
2928
2945
  // it can hold, and whether it can see an image you attach. They lead the description
2929
2946
  // because the row truncates from the RIGHT — put behind the prose they would be the