jeo-code 0.9.15 → 0.9.17
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/CHANGELOG.md +15 -0
- package/README.ja.md +2 -2
- package/README.ko.md +2 -2
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/package.json +1 -1
- package/src/commands/auth.ts +20 -14
- package/src/commands/launch.ts +26 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
All notable changes to **jeo-code** are documented here.
|
|
4
|
+
|
|
4
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
7
|
|
|
@@ -8,6 +9,20 @@ The README mirrors the latest 5 entries — regenerate with `bun run changelog:s
|
|
|
8
9
|
|
|
9
10
|
## [Unreleased]
|
|
10
11
|
|
|
12
|
+
## [0.9.17] - 2026-08-18
|
|
13
|
+
_Live model discovery already existed (`listProviderModels`/`discoverModels`), but only `jeo auth login openai` ever called it — logging into Anthropic or Antigravity left the account pinned to the maintained static catalog snapshot until the next unrelated live-discovery call happened to run._
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **`jeo auth login anthropic` / `jeo auth login antigravity` now fetch and cache the account's live model list immediately after login**, matching the existing OpenAI/Codex behavior (`src/commands/auth.ts`) — the prior `reportOpenAiCodexModels` helper was generalized into `reportLiveModels(provider)` (driven by a `LIVE_MODEL_REPORT_PROVIDERS` set covering `openai`/`anthropic`/`antigravity`) so a freshly logged-in Anthropic or Antigravity account immediately shows its real, current model ids (e.g. newly released Claude/Gemini models not yet in the bundled static catalog) instead of waiting for the next launch's background discovery. The result is persisted via the existing `writeModelCache` so the very next `jeo` launch rehydrates it before any network call. Verified live: `listProviderModels("anthropic", …)` and `listProviderModels("antigravity", …)` both returned real, larger-than-catalog model sets (10 and 11 ids respectively) against live logged-in accounts, and the merged cache file reflected all three providers correctly.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## [0.9.16] - 2026-08-18
|
|
20
|
+
_Routing looked broken while it was actually working: the idle status bar and `/compact`/`/handoff` never reflected which model `routePrompt` actually routed to._
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- **`/route on`'s footer/status bar and `/compact`/`/handoff` model budget kept showing the pre-routing default model instead of what was actually routed** (`src/commands/launch.ts`) — the idle status bar (`statusBarLine`) and `/compact`'s/`/handoff`'s `activeModel` all recomputed `sessionModel || defaultModel` from scratch every render, which has no idea what `routePrompt` actually picked for the last turn. With routing on, a turn would genuinely route to (and reply from) e.g. `claude-sonnet-5`, but the footer kept showing `claude-opus-5` (the unrouted default) the whole time — indistinguishable from routing silently doing nothing. Fixed by tracking `lastActiveModel` (the model that actually served the most recently completed turn) and reading it first everywhere the idle/compaction UI previously assumed `sessionModel || defaultModel` was the truth.
|
|
24
|
+
|
|
25
|
+
|
|
11
26
|
## [0.9.15] - 2026-08-18
|
|
12
27
|
_The 0.9.14 fix wired `promptInput` into the `$a $b …` one-shot skill-chain's `io.input`, but that chain runs before the interactive REPL's own `readline.Interface` exists — so a bundled workflow skill (`$deep-interview`, with or without `--tmux`) invoked directly from the command line still froze forever on its first question._
|
|
13
28
|
|
package/README.ja.md
CHANGED
|
@@ -287,10 +287,10 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
287
287
|
|
|
288
288
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
289
289
|
- **[Unreleased]**
|
|
290
|
+
- **[0.9.17]** (2026-08-18) — Live model discovery already existed (`listProviderModels`/`discoverModels`), but only `jeo auth login openai` ever called it — logging into Anthropic or Antigravity left the account pinned to the maintained static catalog snapshot until the next unrelated live-discovery call happened to run.
|
|
291
|
+
- **[0.9.16]** (2026-08-18) — Routing looked broken while it was actually working: the idle status bar and `/compact`/`/handoff` never reflected which model `routePrompt` actually routed to.
|
|
290
292
|
- **[0.9.15]** (2026-08-18) — The 0.9.14 fix wired `promptInput` into the `$a $b …` one-shot skill-chain's `io.input`, but that chain runs before the interactive REPL's own `readline.Interface` exists — so a bundled workflow skill (`$deep-interview`, with or without `--tmux`) invoked directly from the command line still froze forever on its first question.
|
|
291
293
|
- **[0.9.14]** (2026-08-04) — A `$a $b … [intent]` skill-chain invocation of a bundled workflow skill (deep-interview/ralplan/team/ultragoal) hung forever with no error and no prompt.
|
|
292
|
-
- **[0.9.13]** (2026-08-03) — The provider-login browser tab now actually goes away — by itself on macOS, by a working button everywhere else.
|
|
293
|
-
- **[0.9.12]** (2026-08-02) — Fixes the boxed prompt's stolen keystrokes, drifting caret, and paste/attachment spacing under `jeo --tmux`.
|
|
294
294
|
|
|
295
295
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
296
296
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -288,10 +288,10 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
288
288
|
|
|
289
289
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
290
290
|
- **[Unreleased]**
|
|
291
|
+
- **[0.9.17]** (2026-08-18) — Live model discovery already existed (`listProviderModels`/`discoverModels`), but only `jeo auth login openai` ever called it — logging into Anthropic or Antigravity left the account pinned to the maintained static catalog snapshot until the next unrelated live-discovery call happened to run.
|
|
292
|
+
- **[0.9.16]** (2026-08-18) — Routing looked broken while it was actually working: the idle status bar and `/compact`/`/handoff` never reflected which model `routePrompt` actually routed to.
|
|
291
293
|
- **[0.9.15]** (2026-08-18) — The 0.9.14 fix wired `promptInput` into the `$a $b …` one-shot skill-chain's `io.input`, but that chain runs before the interactive REPL's own `readline.Interface` exists — so a bundled workflow skill (`$deep-interview`, with or without `--tmux`) invoked directly from the command line still froze forever on its first question.
|
|
292
294
|
- **[0.9.14]** (2026-08-04) — A `$a $b … [intent]` skill-chain invocation of a bundled workflow skill (deep-interview/ralplan/team/ultragoal) hung forever with no error and no prompt.
|
|
293
|
-
- **[0.9.13]** (2026-08-03) — The provider-login browser tab now actually goes away — by itself on macOS, by a working button everywhere else.
|
|
294
|
-
- **[0.9.12]** (2026-08-02) — Fixes the boxed prompt's stolen keystrokes, drifting caret, and paste/attachment spacing under `jeo --tmux`.
|
|
295
295
|
|
|
296
296
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
297
297
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -295,10 +295,10 @@ Huge thanks to [gajae-code](https://github.com/Yeachan-Heo/gajae-code) for the i
|
|
|
295
295
|
|
|
296
296
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
297
297
|
- **[Unreleased]**
|
|
298
|
+
- **[0.9.17]** (2026-08-18) — Live model discovery already existed (`listProviderModels`/`discoverModels`), but only `jeo auth login openai` ever called it — logging into Anthropic or Antigravity left the account pinned to the maintained static catalog snapshot until the next unrelated live-discovery call happened to run.
|
|
299
|
+
- **[0.9.16]** (2026-08-18) — Routing looked broken while it was actually working: the idle status bar and `/compact`/`/handoff` never reflected which model `routePrompt` actually routed to.
|
|
298
300
|
- **[0.9.15]** (2026-08-18) — The 0.9.14 fix wired `promptInput` into the `$a $b …` one-shot skill-chain's `io.input`, but that chain runs before the interactive REPL's own `readline.Interface` exists — so a bundled workflow skill (`$deep-interview`, with or without `--tmux`) invoked directly from the command line still froze forever on its first question.
|
|
299
301
|
- **[0.9.14]** (2026-08-04) — A `$a $b … [intent]` skill-chain invocation of a bundled workflow skill (deep-interview/ralplan/team/ultragoal) hung forever with no error and no prompt.
|
|
300
|
-
- **[0.9.13]** (2026-08-03) — The provider-login browser tab now actually goes away — by itself on macOS, by a working button everywhere else.
|
|
301
|
-
- **[0.9.12]** (2026-08-02) — Fixes the boxed prompt's stolen keystrokes, drifting caret, and paste/attachment spacing under `jeo --tmux`.
|
|
302
302
|
|
|
303
303
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
304
304
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -287,10 +287,10 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
287
287
|
|
|
288
288
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
289
289
|
- **[Unreleased]**
|
|
290
|
+
- **[0.9.17]** (2026-08-18) — Live model discovery already existed (`listProviderModels`/`discoverModels`), but only `jeo auth login openai` ever called it — logging into Anthropic or Antigravity left the account pinned to the maintained static catalog snapshot until the next unrelated live-discovery call happened to run.
|
|
291
|
+
- **[0.9.16]** (2026-08-18) — Routing looked broken while it was actually working: the idle status bar and `/compact`/`/handoff` never reflected which model `routePrompt` actually routed to.
|
|
290
292
|
- **[0.9.15]** (2026-08-18) — The 0.9.14 fix wired `promptInput` into the `$a $b …` one-shot skill-chain's `io.input`, but that chain runs before the interactive REPL's own `readline.Interface` exists — so a bundled workflow skill (`$deep-interview`, with or without `--tmux`) invoked directly from the command line still froze forever on its first question.
|
|
291
293
|
- **[0.9.14]** (2026-08-04) — A `$a $b … [intent]` skill-chain invocation of a bundled workflow skill (deep-interview/ralplan/team/ultragoal) hung forever with no error and no prompt.
|
|
292
|
-
- **[0.9.13]** (2026-08-03) — The provider-login browser tab now actually goes away — by itself on macOS, by a working button everywhere else.
|
|
293
|
-
- **[0.9.12]** (2026-08-02) — Fixes the boxed prompt's stolen keystrokes, drifting caret, and paste/attachment spacing under `jeo --tmux`.
|
|
294
294
|
|
|
295
295
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
296
296
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
package/src/commands/auth.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { type StoredOAuth } from "../agent/state";
|
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
6
6
|
import { readGlobalConfig } from "../agent/state";
|
|
7
7
|
import { jeoEnv } from "../util/env";
|
|
8
|
-
import { listProviderModels
|
|
8
|
+
import { listProviderModels } from "../ai/model-discovery";
|
|
9
|
+
|
|
9
10
|
import { writeModelCache } from "../ai/model-cache";
|
|
10
11
|
import {
|
|
11
12
|
OAUTH_FLOWS,
|
|
@@ -123,7 +124,7 @@ async function runAuthLogin(rest: string[]): Promise<void> {
|
|
|
123
124
|
rl.close();
|
|
124
125
|
await loginOAuth(chosen, manualToken.trim());
|
|
125
126
|
console.log(`[SUCCESS] Stored manual OAuth bearer for ${chosen} (no auto-refresh).`);
|
|
126
|
-
if (chosen
|
|
127
|
+
if (LIVE_MODEL_REPORT_PROVIDERS.has(chosen)) await reportLiveModels(chosen);
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
130
|
|
|
@@ -131,7 +132,7 @@ async function runAuthLogin(rest: string[]): Promise<void> {
|
|
|
131
132
|
const { email } = await interactiveOAuthLogin(chosen, rl);
|
|
132
133
|
console.log(`\n[SUCCESS] OAuth login complete for ${chosen}${email ? ` (${email})` : ""}.`);
|
|
133
134
|
console.log("Stored access + refresh tokens in ~/.jeo/config.json; jeo will auto-refresh on expiry.");
|
|
134
|
-
if (chosen
|
|
135
|
+
if (LIVE_MODEL_REPORT_PROVIDERS.has(chosen)) await reportLiveModels(chosen);
|
|
135
136
|
} catch (err) {
|
|
136
137
|
console.log(`\n[FAILED] ${(err as Error).message}`);
|
|
137
138
|
console.log("Tip: paste the redirect URL when prompted, or use 'jeo auth login <provider> --token <bearer>'.");
|
|
@@ -142,30 +143,35 @@ async function runAuthLogin(rest: string[]): Promise<void> {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
/**
|
|
145
|
-
* Best-effort, timeout-bounded live
|
|
146
|
-
* successful `jeo auth login
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
146
|
+
* Best-effort, timeout-bounded live model check run immediately after a
|
|
147
|
+
* successful `jeo auth login <provider>` for the providers whose model set
|
|
148
|
+
* changes fastest (openai/Codex, anthropic, antigravity/Cloud Code Assist).
|
|
149
|
+
* Uses `preferOAuth` so the report reflects the account that was JUST logged
|
|
150
|
+
* in — never the catalog fallback, and never silently swapped to an
|
|
151
|
+
* unrelated pre-existing API key. A failure here is NEVER fatal: login has
|
|
152
|
+
* already succeeded and is not rolled back by this check. Prints only model
|
|
153
|
+
* ids/count — no tokens/secrets.
|
|
151
154
|
*/
|
|
152
|
-
|
|
155
|
+
const LIVE_MODEL_REPORT_PROVIDERS = new Set<AuthProvider>(["openai", "anthropic", "antigravity"]);
|
|
156
|
+
|
|
157
|
+
async function reportLiveModels(provider: AuthProvider): Promise<void> {
|
|
153
158
|
try {
|
|
154
|
-
const result = await listProviderModels(
|
|
159
|
+
const result = await listProviderModels(provider, { preferOAuth: true });
|
|
155
160
|
if (result.ok) {
|
|
156
161
|
// Persist immediately: the very next `jeo` launch then knows this account's
|
|
157
162
|
// real model set (including ids newer than the maintained static snapshot)
|
|
158
163
|
// before it makes any network call.
|
|
159
164
|
await writeModelCache([result]);
|
|
160
|
-
console.log(`Live
|
|
165
|
+
console.log(`Live ${provider} models (${result.models.length}): ${result.models.join(", ")}`);
|
|
161
166
|
} else {
|
|
162
|
-
console.log(`[WARN] Could not verify live
|
|
167
|
+
console.log(`[WARN] Could not verify live ${provider} models: ${result.error ?? "unknown error"} (non-fatal — login succeeded).`);
|
|
163
168
|
}
|
|
164
169
|
} catch (err) {
|
|
165
|
-
console.log(`[WARN] Could not verify live
|
|
170
|
+
console.log(`[WARN] Could not verify live ${provider} models: ${(err as Error).message} (non-fatal — login succeeded).`);
|
|
166
171
|
}
|
|
167
172
|
}
|
|
168
173
|
|
|
174
|
+
|
|
169
175
|
async function runAuthImport(rest: string[]): Promise<void> {
|
|
170
176
|
const provider = rest.find(a => a !== "--import") as AuthProvider | undefined;
|
|
171
177
|
if (!provider) {
|
package/src/commands/launch.ts
CHANGED
|
@@ -687,6 +687,19 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
687
687
|
let sessionThinking: "low" | "medium" | "high" | "xhigh" | undefined = flags.thinking ?? cfg.thinkingLevel;
|
|
688
688
|
// PromptRouter session override: undefined = follow config.routing.enabled, true/false = /route on|off wins this session.
|
|
689
689
|
let sessionRouteOverride: boolean | undefined;
|
|
690
|
+
// Last model that actually served a completed turn (routed or pinned) — the idle
|
|
691
|
+
// status bar (`statusBarLine`) and `/compact`/`/handoff` read THIS instead of
|
|
692
|
+
// recomputing `sessionModel || defaultModel`, which ignored routing entirely and
|
|
693
|
+
// kept showing the pre-routing default even while routing was actively picking a
|
|
694
|
+
// different model turn-to-turn (e.g. "/route on" routing every prompt to
|
|
695
|
+
// claude-sonnet-5 while the footer kept showing claude-opus-5 — looked exactly
|
|
696
|
+
// like routing "wasn't working" even though it was). `undefined` until the first
|
|
697
|
+
// turn completes, so the initial idle render still falls back to `sessionModel ||
|
|
698
|
+
// defaultModel` unchanged.
|
|
699
|
+
let lastActiveModel: string | undefined;
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
690
703
|
// Last routing decision (or the reason none applied) — /route why reads this.
|
|
691
704
|
let lastRouteDecision: RouteDecision | { note: string } | null = null;
|
|
692
705
|
// Bounded FIFO of this session's routing decisions — /route history reads this.
|
|
@@ -1929,7 +1942,9 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
1929
1942
|
}
|
|
1930
1943
|
}
|
|
1931
1944
|
|
|
1945
|
+
lastActiveModel = activeModel;
|
|
1932
1946
|
return { done: result.done, steps: result.steps, reply, rendered: !!tui, usage };
|
|
1947
|
+
|
|
1933
1948
|
};
|
|
1934
1949
|
|
|
1935
1950
|
|
|
@@ -3017,7 +3032,8 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
3017
3032
|
// The gjc-layout status bar pinned directly ABOVE the input box: bg-gradient
|
|
3018
3033
|
// identity block (model · thinking / branch / cwd) left, live ctx% right.
|
|
3019
3034
|
const statusBarLine = (cols: number): string => {
|
|
3020
|
-
const activeModel = sessionModel || defaultModel;
|
|
3035
|
+
const activeModel = lastActiveModel ?? (sessionModel || defaultModel);
|
|
3036
|
+
|
|
3021
3037
|
const meta = catalogMetadata(activeModel);
|
|
3022
3038
|
const used = historyTokens(history);
|
|
3023
3039
|
const theme = uiTheme;
|
|
@@ -4321,10 +4337,16 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
4321
4337
|
continue;
|
|
4322
4338
|
}
|
|
4323
4339
|
if (input === "/compact") {
|
|
4340
|
+
|
|
4324
4341
|
// Session-start default snapshot (not the live global default) — keeps a
|
|
4325
4342
|
// concurrent session's `/model` write from changing this session's context budget.
|
|
4326
|
-
|
|
4343
|
+
// Compaction budget should reflect the model that actually served the last
|
|
4344
|
+
// turn (routing may have picked something other than sessionModel/defaultModel),
|
|
4345
|
+
// not the pre-routing session-start snapshot — otherwise a routed session could
|
|
4346
|
+
// compact against the wrong context window.
|
|
4347
|
+
const activeModel = lastActiveModel ?? (sessionModel || defaultModel);
|
|
4327
4348
|
const contextTokens = catalogMetadata(activeModel)?.contextTokens;
|
|
4349
|
+
|
|
4328
4350
|
const res = await maybeCompact(history, { model: activeModel, force: true, contextTokens });
|
|
4329
4351
|
if (res.error) {
|
|
4330
4352
|
console.error(chalk.red(res.error));
|
|
@@ -4346,7 +4368,8 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
4346
4368
|
// has no ACP/SDK-broker managed-session boundary to hand off INTO, so this
|
|
4347
4369
|
// NEVER mutates history (see buildHandoffDocument's doc comment).
|
|
4348
4370
|
const parsed = parseHandoffCommand(input) ?? {};
|
|
4349
|
-
const activeModel = sessionModel || defaultModel;
|
|
4371
|
+
const activeModel = lastActiveModel ?? (sessionModel || defaultModel);
|
|
4372
|
+
|
|
4350
4373
|
const cfg = await readGlobalConfig();
|
|
4351
4374
|
// `Config` (state.ts) predates config-schema.ts's `compaction` field and is
|
|
4352
4375
|
// out of this change's scope — read the passthrough-preserved value via a
|