jeo-code 0.5.4 → 0.5.6
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.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/launch.ts +56 -47
- package/src/tui/app.ts +4 -6
- package/src/tui/components/input-box.ts +13 -7
package/README.ja.md
CHANGED
|
@@ -150,11 +150,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
150
150
|
## 変更履歴 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
154
|
+
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
153
155
|
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
154
156
|
- **[0.5.3]** (2026-06-15) — `$` chains multiple skills in one line (all run, in order), plus multi-line prompt input — paste-merge and gated Shift+Enter.
|
|
155
157
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
156
|
-
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
157
|
-
- **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -150,11 +150,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
150
150
|
## 변경 이력 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
154
|
+
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
153
155
|
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
154
156
|
- **[0.5.3]** (2026-06-15) — `$` chains multiple skills in one line (all run, in order), plus multi-line prompt input — paste-merge and gated Shift+Enter.
|
|
155
157
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
156
|
-
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
157
|
-
- **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -150,11 +150,11 @@ Required npm token permissions (repository secret `NPM_TOKEN`):
|
|
|
150
150
|
## Changelog
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
154
|
+
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
153
155
|
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
154
156
|
- **[0.5.3]** (2026-06-15) — `$` chains multiple skills in one line (all run, in order), plus multi-line prompt input — paste-merge and gated Shift+Enter.
|
|
155
157
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
156
|
-
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
157
|
-
- **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -150,11 +150,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
150
150
|
## 更新日志 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
154
|
+
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
153
155
|
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
154
156
|
- **[0.5.3]** (2026-06-15) — `$` chains multiple skills in one line (all run, in order), plus multi-line prompt input — paste-merge and gated Shift+Enter.
|
|
155
157
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
156
|
-
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
157
|
-
- **[0.5.0]** (2026-06-14) — Performance: workspace-scan, workflow-state, and DNA-Claw HUD caches; plus a credential-safety fix that never wipes OAuth over an invalid config.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
package/src/commands/launch.ts
CHANGED
|
@@ -2753,17 +2753,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
2753
2753
|
disabled: true,
|
|
2754
2754
|
});
|
|
2755
2755
|
appendChildren([
|
|
2756
|
-
{ value: `${role.id}:keep`, label: "Set model only", hint: `keep thinking ${roleThinking}` },
|
|
2757
|
-
{
|
|
2758
|
-
value: `${role.id}:inherit`,
|
|
2759
|
-
label: "thinking inherit",
|
|
2760
|
-
hint: `follow default (${config.thinkingLevel ?? "medium"})`,
|
|
2761
|
-
},
|
|
2762
|
-
...levels.map(level => ({
|
|
2763
|
-
value: `${role.id}:${level}`,
|
|
2764
|
-
label: `thinking ${level}`,
|
|
2765
|
-
hint: roleThinking === level ? "current" : `~${Math.round(thinkingMaxTokens(level) / 1000)}k tokens`,
|
|
2766
|
-
})),
|
|
2756
|
+
{ value: `${role.id}:keep`, label: "Set model only", hint: `keep thinking ${roleThinking} · set via /agents edit` },
|
|
2767
2757
|
]);
|
|
2768
2758
|
}
|
|
2769
2759
|
|
|
@@ -3276,28 +3266,58 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
3276
3266
|
continue;
|
|
3277
3267
|
}
|
|
3278
3268
|
if (input === "/resume" || input.startsWith("/resume ")) {
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3269
|
+
const arg = input.substring(7).trim();
|
|
3270
|
+
// Load a session into history and print its transcript so the resume is visible.
|
|
3271
|
+
const applyResume = async (rid: string): Promise<void> => {
|
|
3272
|
+
try {
|
|
3273
|
+
const { messages } = await loadSession(rid, cwd);
|
|
3274
|
+
history.length = 1;
|
|
3275
|
+
for (const m of messages) history.push(m);
|
|
3276
|
+
sessionId = rid;
|
|
3277
|
+
// Seed /retry + reply marker from the last user/assistant turn.
|
|
3278
|
+
lastUserInput = ""; lastReply = "";
|
|
3279
|
+
for (let k = history.length - 1; k >= 1; k--) {
|
|
3280
|
+
if (history[k]!.role === "user" && !lastUserInput) lastUserInput = String(history[k]!.content ?? "");
|
|
3281
|
+
if (history[k]!.role === "assistant" && !lastReply) lastReply = String(history[k]!.content ?? "");
|
|
3282
|
+
if (lastUserInput && lastReply) break;
|
|
3283
|
+
}
|
|
3284
|
+
const sep = "─".repeat(Math.min(48, Math.max(20, (process.stdout.columns ?? 80) - 1)));
|
|
3285
|
+
logLines([
|
|
3286
|
+
sep,
|
|
3287
|
+
`resumed session ${rid} · ${messages.length} message(s) (/history all for the full transcript)`,
|
|
3288
|
+
sep,
|
|
3289
|
+
...formatTranscript(history, { maxTurns: 6, color: true, unicode: true }),
|
|
3290
|
+
sep,
|
|
3291
|
+
]);
|
|
3292
|
+
} catch (err) {
|
|
3293
|
+
console.log(`! ${(err as Error).message}`);
|
|
3290
3294
|
}
|
|
3295
|
+
};
|
|
3296
|
+
if (arg) { await applyResume(arg); continue; }
|
|
3297
|
+
// No id → only sessions with a real conversation are resumable (every launch
|
|
3298
|
+
// creates an empty session; those are noise).
|
|
3299
|
+
const sessions = (await listSessions(cwd)).filter(s => s.messageCount > 0);
|
|
3300
|
+
if (sessions.length === 0) {
|
|
3301
|
+
console.log("(no saved sessions with history)");
|
|
3291
3302
|
continue;
|
|
3292
3303
|
}
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3304
|
+
// Interactive arrow-key picker on a TTY: ↑↓ to move, Enter to resume, Esc cancels.
|
|
3305
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
3306
|
+
const items: SelectItem<string>[] = sessions.slice(0, 50).map(s => ({
|
|
3307
|
+
value: s.id,
|
|
3308
|
+
label: `${s.title ? `[${s.title}] ` : ""}${(s.preview || s.id).replace(/\s+/g, " ")}`.slice(0, 76) || s.id,
|
|
3309
|
+
hint: `${s.messageCount} msgs${s.id === sessionId ? " · current" : ""}`,
|
|
3310
|
+
}));
|
|
3311
|
+
const picked = await pickFromOptions("Resume a session ↑↓ move · Enter resume · Esc cancel", items);
|
|
3312
|
+
if (picked) await applyResume(picked);
|
|
3313
|
+
else console.log("(resume cancelled)");
|
|
3314
|
+
continue;
|
|
3315
|
+
}
|
|
3316
|
+
// Non-TTY fallback: static list (resume with /resume <id>).
|
|
3317
|
+
console.log("Saved sessions — resume with /resume <id>:");
|
|
3318
|
+
for (const s of sessions.slice(0, 15)) {
|
|
3319
|
+
const marker = s.id === sessionId ? "*" : " ";
|
|
3320
|
+
console.log(` ${marker}${s.id} (${s.messageCount} msgs) ${s.title ? `[${s.title}] ` : ""}${s.preview}`);
|
|
3301
3321
|
}
|
|
3302
3322
|
continue;
|
|
3303
3323
|
}
|
|
@@ -3992,10 +4012,10 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
3992
4012
|
let roleModelArg = (roleMatch[3] ?? "").trim();
|
|
3993
4013
|
const roleThinking = /^(?:thinking|think)(?:\s+(\S+))?$/i.exec(roleModelArg);
|
|
3994
4014
|
if (roleThinking) {
|
|
3995
|
-
|
|
4015
|
+
console.log(`Subagent thinking is set via /agents — try: /agents ${role.id} thinking ${roleThinking[1] ?? "<level|inherit>"} (or /agents edit). /model only sets the default thinking.`);
|
|
3996
4016
|
continue;
|
|
3997
4017
|
}
|
|
3998
|
-
|
|
4018
|
+
|
|
3999
4019
|
if (!roleModelArg && process.stdin.isTTY && process.stdout.isTTY) {
|
|
4000
4020
|
const live = await getLiveModels();
|
|
4001
4021
|
lastPickIndex = flattenModels(live);
|
|
@@ -4007,7 +4027,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
4007
4027
|
continue;
|
|
4008
4028
|
}
|
|
4009
4029
|
roleModelArg = qualifyModelId(picked.model, picked.provider);
|
|
4010
|
-
|
|
4030
|
+
|
|
4011
4031
|
}
|
|
4012
4032
|
}
|
|
4013
4033
|
if (roleModelArg && lastPickIndex.length) {
|
|
@@ -4019,7 +4039,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
4019
4039
|
continue;
|
|
4020
4040
|
}
|
|
4021
4041
|
roleModelArg = qualifyModelId(sel.entry.model, sel.entry.provider);
|
|
4022
|
-
|
|
4042
|
+
|
|
4023
4043
|
} else if (sel.kind === "ambiguous") {
|
|
4024
4044
|
console.log(`'${roleModelArg}' matches ${sel.matches.length} models — be more specific:`);
|
|
4025
4045
|
for (const e of sel.matches.slice(0, 12)) console.log(` #${e.index} ${e.model} (${e.provider})`);
|
|
@@ -4033,20 +4053,9 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
4033
4053
|
continue;
|
|
4034
4054
|
}
|
|
4035
4055
|
if (roleModelArg) {
|
|
4036
|
-
|
|
4037
|
-
if (roleModelPickedFromSelector && process.stdin.isTTY && process.stdout.isTTY) {
|
|
4038
|
-
const cfgForRole = await readGlobalConfig();
|
|
4039
|
-
const lvl = await pickThinkingLevel(
|
|
4040
|
-
`Reasoning for ${role.title}: ${roleModelArg}`,
|
|
4041
|
-
cfgForRole.subagents?.[role.id]?.thinking,
|
|
4042
|
-
`inherit — follow default (${cfgForRole.thinkingLevel ?? "medium"})`,
|
|
4043
|
-
);
|
|
4044
|
-
thinkPatch = lvl === "inherit" ? { thinking: undefined } : lvl ? { thinking: lvl } : {};
|
|
4045
|
-
}
|
|
4046
|
-
await saveConfigPatch(raw => ({ subagents: withSubagentSetting(raw, role.id, { model: roleModelArg, ...thinkPatch }) }));
|
|
4056
|
+
await saveConfigPatch(raw => ({ subagents: withSubagentSetting(raw, role.id, { model: roleModelArg }) }));
|
|
4047
4057
|
const { provider } = await describeModel(roleModelArg);
|
|
4048
|
-
|
|
4049
|
-
console.log(`${role.title} model set to ${roleModelArg} (${provider})${thinkNote} — saved to ~/.jeo/config.json`);
|
|
4058
|
+
console.log(`${role.title} model set to ${roleModelArg} (${provider}) — saved to ~/.jeo/config.json. Set its thinking via /agents ${role.id} thinking <level> (or /agents edit).`);
|
|
4050
4059
|
} else {
|
|
4051
4060
|
const current = resolveSubagentModel(role.id, await readGlobalConfig());
|
|
4052
4061
|
const { resolved, provider } = await describeModel(current);
|
package/src/tui/app.ts
CHANGED
|
@@ -567,14 +567,12 @@ export class LaunchTui {
|
|
|
567
567
|
const border = this.theme.color && uc ? chalk.hex(uc.border) : (s: string) => s;
|
|
568
568
|
const shadow = this.theme.color && uc ? chalk.hex(uc.shadow) : border;
|
|
569
569
|
const fill = this.theme.color && uc ? (s: string) => chalk.bgHex(uc.fill)(s) : (s: string) => s;
|
|
570
|
+
// Show ALL wrapped lines — the card lives in scrollback (not a bounded live frame),
|
|
571
|
+
// so a long submitted query stays fully visible (no truncation).
|
|
570
572
|
const body = text
|
|
571
573
|
.split("\n")
|
|
572
|
-
.flatMap(line => wrapTextWithAnsi(line, Math.max(8, inner - 2)))
|
|
573
|
-
|
|
574
|
-
const clipped = body.length === 6 && text.split("\n").length > 6
|
|
575
|
-
? [...body.slice(0, 5), this.unicode ? "…" : "..."]
|
|
576
|
-
: body;
|
|
577
|
-
const rows = clipped.length ? clipped : [""];
|
|
574
|
+
.flatMap(line => wrapTextWithAnsi(line, Math.max(8, inner - 2)));
|
|
575
|
+
const rows = body.length ? body : [""];
|
|
578
576
|
const top = border(g.tl + g.h.repeat(inner) + g.tr);
|
|
579
577
|
const bottom = shadow(g.bl + g.h.repeat(inner) + g.br);
|
|
580
578
|
const mid = rows.map(line => {
|
|
@@ -101,17 +101,23 @@ export function renderInputFrame(line: string, opts: InputBoxOptions = {}): Inpu
|
|
|
101
101
|
ccol = wrapped.col;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
//
|
|
105
|
-
//
|
|
104
|
+
// Scroll the visible window so the caret row stays in view — cursor movement reveals
|
|
105
|
+
// every line (no content is unreachable). `…` markers flag rows hidden above/below.
|
|
106
106
|
const maxBodyRows = Math.max(1, Math.trunc(opts.maxBodyRows ?? rows.length));
|
|
107
|
+
const totalRows = rows.length;
|
|
107
108
|
let hidden = 0;
|
|
108
|
-
if (
|
|
109
|
-
hidden =
|
|
110
|
-
|
|
111
|
-
rows
|
|
109
|
+
if (totalRows > maxBodyRows) {
|
|
110
|
+
hidden = Math.min(Math.max(0, crow - maxBodyRows + 1), totalRows - maxBodyRows);
|
|
111
|
+
if (crow < hidden) hidden = crow; // caret above the window → scroll up to it
|
|
112
|
+
rows = rows.slice(hidden, hidden + maxBodyRows);
|
|
113
|
+
if (hidden > 0) rows[0] = `…${rows[0] ?? ""}`.slice(0, textWidth);
|
|
114
|
+
if (hidden + maxBodyRows < totalRows) {
|
|
115
|
+
const last = rows.length - 1;
|
|
116
|
+
rows[last] = `${rows[last] ?? ""}…`.slice(0, textWidth);
|
|
117
|
+
}
|
|
112
118
|
}
|
|
113
119
|
let visRow = Math.max(0, Math.min(crow - hidden, rows.length - 1));
|
|
114
|
-
if (hidden > 0 && crow - hidden === 0) ccol += 1; // shifted by the `…`
|
|
120
|
+
if (hidden > 0 && crow - hidden === 0) ccol += 1; // shifted by the leading `…`
|
|
115
121
|
if (crow - hidden < 0) { visRow = 0; ccol = 0; }
|
|
116
122
|
|
|
117
123
|
const promptMark = "> ";
|