@tiens.nguyen/gu-cli 1.0.899 → 1.0.900

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 (2) hide show
  1. package/gu-repl.mjs +27 -3
  2. package/package.json +1 -1
package/gu-repl.mjs CHANGED
@@ -7170,7 +7170,6 @@ async function useCoderInThisFolder({ ps, rows, beforeChoices, url, host, locali
7170
7170
  console.log(GUTTER + dim("restart it with `gu api restart`, then add that provider again.\n"));
7171
7171
  }
7172
7172
  sessionCodingModel = offered.id;
7173
- setModelFallback(null); // #343
7174
7173
  sessionCodingLabel = model;
7175
7174
  sessionCodingUrl = url;
7176
7175
  // …and the host the bar puts in front of it (#263): left alone, the PREVIOUS coder's
@@ -7179,6 +7178,7 @@ async function useCoderInThisFolder({ ps, rows, beforeChoices, url, host, locali
7179
7178
  // The folder follows the SERVER's key (task #245) — its default, which a first key already is.
7180
7179
  sessionCodingKeyId = "";
7181
7180
  sessionApiKeyTail = key ? key.slice(-4) : "";
7181
+ setModelFallback(null); // #343 — AFTER the name, server and tail: it repaints the bar (GH #397)
7182
7182
  keyChoicePending = false;
7183
7183
  await saveSessionCoding(cwd);
7184
7184
  await saveSessionCodingKeyId(cwd);
@@ -7201,7 +7201,12 @@ async function useCoderInThisFolder({ ps, rows, beforeChoices, url, host, locali
7201
7201
  // The bar still said "coding model not set · /model" under the success line of the FIRST model
7202
7202
  // added on a fresh install, until the next turn repainted it (GH #397).
7203
7203
  noModelAtAll = after?.payload ? nothingToAnswerWith(after.payload) : false;
7204
- if (after?.payload) agentMissing = after.payload.agentMissing === true;
7204
+ if (after?.payload) {
7205
+ agentMissing = after.payload.agentMissing === true;
7206
+ // The first model added IS the account default now. Startup read the default while there was
7207
+ // none, so picking "(default)" later left the bar with no model name at all (GH #397).
7208
+ seedDefaultCoder(after.payload);
7209
+ }
7205
7210
  if (barPinned()) paintBar();
7206
7211
  }
7207
7212
 
@@ -7461,7 +7466,6 @@ async function applyChosenCoder(chosen, { def = "", tag = "", quick = false } =
7461
7466
  tail: sessionApiKeyTail,
7462
7467
  };
7463
7468
  sessionCodingModel = chosen.id === def ? "" : chosen.id;
7464
- setModelFallback(null); // #343: the warning named the coder that was just replaced
7465
7469
  // Remember the friendly name for the token footer, which should never show a raw
7466
7470
  // "<kind>::<model>" wire id.
7467
7471
  sessionCodingLabel = chosen.id === def ? "" : chosen.model;
@@ -7471,6 +7475,12 @@ async function applyChosenCoder(chosen, { def = "", tag = "", quick = false } =
7471
7475
  // The server goes WITH the model, before any await (#263): set after the save below, the bar
7472
7476
  // could repaint in between and show the NEW model under the OLD server for a moment.
7473
7477
  activeCoderWhere = coderWhere(chosen.kind, chosen.url);
7478
+ // The old provider's key tail must not sit beside the new model while the key is looked up (it
7479
+ // was shown for a moment: Kimi with Qwen's tail). Blank until coderKeyState answers below.
7480
+ sessionApiKeyTail = "";
7481
+ // AFTER the fields above: this repaints the bar, and between the id and its name it showed the
7482
+ // raw "<row id>::<model>" wire id for a frame (GH #397). #343: the warning named the old coder.
7483
+ setModelFallback(null);
7474
7484
  // WRITTEN NOW, not at the end of the next turn: `/model` then `/exit` is how the choice is
7475
7485
  // made and then tested, and that path never reaches saveSession.
7476
7486
  await saveSessionCoding(resolve(process.cwd()));
@@ -14462,6 +14472,20 @@ async function main() {
14462
14472
  // payload fields, which key-choice-regression.test.mjs forbids for exactly that reason.
14463
14473
  activeCoderWhere = whereOfActiveCoder(probe?.codingChoices, sessionCodingModel);
14464
14474
  }
14475
+ // THE KEY TAIL BESIDE THE MODEL, at startup too (GH #397). It was read only when the folder had
14476
+ // its own key choice, so the normal case — the server's default key — showed a model with no
14477
+ // key until the first /model switch.
14478
+ if (!sessionApiKeyTail) {
14479
+ try {
14480
+ const choices = Array.isArray(probe?.codingChoices) ? probe.codingChoices : [];
14481
+ const active = choices.find((c) => c.id === sessionCodingModel) ?? choices.find((c) => c.isDefault);
14482
+ const { codingNeedsKey } = await import("./coding-key-prompt.mjs");
14483
+ if (active && codingNeedsKey(active.kind, active.url)) {
14484
+ const kd = await fetchCodingKey(active.backendId || "");
14485
+ sessionApiKeyTail = kd?.key ? kd.key.slice(-4) : "";
14486
+ }
14487
+ } catch { /* the bar works without the tail */ }
14488
+ }
14465
14489
  // Task #133: no RAG storage question any more — the terminal ALWAYS keeps the index on
14466
14490
  // this machine. `/rag-cloud` opts into additionally mirroring it to the user's S3 bucket.
14467
14491
  // Startup banner (task #131): the gu logo on the left, compact status facts on the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gu-cli",
3
- "version": "1.0.899",
3
+ "version": "1.0.900",
4
4
  "description": "gu: the coding agent in your terminal. It reads your repo, makes the change and runs the tests, with your own models (Ollama or any OpenAI-compatible provider). Free installs keep the agent, its API and its database on your machine. macOS, Linux and Windows.",
5
5
  "keywords": [
6
6
  "ai",