jeo-code 0.5.3 → 0.5.5
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 +45 -22
- 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.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
154
|
+
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
153
155
|
- **[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.
|
|
154
156
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
155
157
|
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
156
|
-
- **[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.
|
|
157
|
-
- **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
|
|
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.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
154
|
+
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
153
155
|
- **[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.
|
|
154
156
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
155
157
|
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
156
|
-
- **[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.
|
|
157
|
-
- **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
|
|
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.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
154
|
+
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
153
155
|
- **[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.
|
|
154
156
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
155
157
|
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
156
|
-
- **[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.
|
|
157
|
-
- **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
|
|
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.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
154
|
+
- **[0.5.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
|
|
153
155
|
- **[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.
|
|
154
156
|
- **[0.5.2]** (2026-06-14) — `$skill` prompt invocation with prefix/fuzzy suggestions, and a per-session input-box hue (amber in cmd-mode).
|
|
155
157
|
- **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
|
|
156
|
-
- **[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.
|
|
157
|
-
- **[0.4.9]** (2026-06-14) — Live-frame width-clamp (content-sized height) replaces the constant-height approach, typed text shows during a running turn, and a docs/AGENTS refresh.
|
|
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
|
@@ -1914,17 +1914,22 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
1914
1914
|
// scrollback before the boxed footer takes over.
|
|
1915
1915
|
let promptActive = false;
|
|
1916
1916
|
let pickerActive = false;
|
|
1917
|
-
// ── Multi-line input
|
|
1918
|
-
//
|
|
1919
|
-
//
|
|
1920
|
-
//
|
|
1921
|
-
//
|
|
1922
|
-
//
|
|
1923
|
-
//
|
|
1924
|
-
// the prompt reads process.stdin directly, exactly as before (zero risk).
|
|
1917
|
+
// ── Multi-line input ───────────────────────────────────────────────────────────
|
|
1918
|
+
// Reliable multi-line input: a bracketed paste arrives as ONE buffer (fills the box,
|
|
1919
|
+
// submits intact) and Shift+Enter can insert a newline. We route the prompt's stdin
|
|
1920
|
+
// through a filter that rewrites line breaks to a private-use SENTINEL char BEFORE
|
|
1921
|
+
// readline sees them — readline inserts it as an ordinary character (no per-line
|
|
1922
|
+
// submit/race), the box renders it as a real line break, and it is expanded back to
|
|
1923
|
+
// "\n" on submit. On for any interactive TTY; JEO_NO_MULTILINE=1 reads stdin directly.
|
|
1925
1924
|
const SENTINEL = "\uE000";
|
|
1926
1925
|
const SHIFT_ENTER_SEQS = ["\u001b[27;2;13~", "\u001b[13;2u"];
|
|
1927
|
-
|
|
1926
|
+
// Multi-line input filter is ON for any interactive TTY: reliable multi-line paste
|
|
1927
|
+
// (fills the box, submits intact into the user card) is the default. The lone-"\n"
|
|
1928
|
+
// Shift+Enter rule stays opt-in (JEO_MULTILINE=1) — it needs ghostty's
|
|
1929
|
+
// `keybind = shift+enter=text:\n` and could misfire on the rare terminal that sends
|
|
1930
|
+
// LF for Enter. JEO_NO_MULTILINE=1 fully disables the filter (reads stdin directly).
|
|
1931
|
+
const multilineInput = !!process.stdin.isTTY && jeoEnv("NO_MULTILINE") !== "1";
|
|
1932
|
+
const loneLfShiftEnter = jeoEnv("MULTILINE") === "1";
|
|
1928
1933
|
const expandSentinel = (s: string): string => (multilineInput ? s.split(SENTINEL).join("\n") : s);
|
|
1929
1934
|
let keyFilter: PassThrough | undefined;
|
|
1930
1935
|
if (multilineInput) {
|
|
@@ -1935,20 +1940,38 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
1935
1940
|
return kf;
|
|
1936
1941
|
};
|
|
1937
1942
|
Object.defineProperty(kf, "isRaw", { get: () => (process.stdin as { isRaw?: boolean }).isRaw });
|
|
1938
|
-
// Forward stdin → filter, rewriting
|
|
1939
|
-
// readline sees
|
|
1940
|
-
//
|
|
1941
|
-
//
|
|
1942
|
-
//
|
|
1943
|
-
//
|
|
1944
|
-
// •
|
|
1945
|
-
//
|
|
1946
|
-
//
|
|
1943
|
+
// Forward stdin → filter, rewriting line breaks into a newline SENTINEL BEFORE
|
|
1944
|
+
// readline sees them, so multi-line input arrives as ONE buffer (no per-line submit
|
|
1945
|
+
// and no racy paste-merge). Stateful across chunks:
|
|
1946
|
+
// • Inside a bracketed paste (200~..201~): every line break → sentinel, so the
|
|
1947
|
+
// whole paste inserts as one multi-line buffer that the user reviews + submits
|
|
1948
|
+
// with Enter (fixes "paste only kept line 1").
|
|
1949
|
+
// • Outside a paste: Shift+Enter encodings → sentinel — a lone "\n" (ghostty
|
|
1950
|
+
// `keybind = shift+enter=text:\n`, passes tmux unchanged even with extended-keys
|
|
1951
|
+
// off) and the xterm "\x1b[27;2;13~" / kitty "\x1b[13;2u" sequences. Enter ("\r")
|
|
1952
|
+
// passes through and submits.
|
|
1953
|
+
let kfInPaste = false;
|
|
1947
1954
|
process.stdin.on("data", (chunk: Buffer) => {
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1955
|
+
const data = chunk.toString("utf8");
|
|
1956
|
+
let out = "";
|
|
1957
|
+
let i = 0;
|
|
1958
|
+
while (i < data.length) {
|
|
1959
|
+
if (!kfInPaste && data.startsWith(PASTE_START, i)) { kfInPaste = true; out += PASTE_START; i += PASTE_START.length; continue; }
|
|
1960
|
+
if (kfInPaste && data.startsWith(PASTE_END, i)) { kfInPaste = false; out += PASTE_END; i += PASTE_END.length; continue; }
|
|
1961
|
+
if (kfInPaste) {
|
|
1962
|
+
if (data.startsWith("\r\n", i)) { out += SENTINEL; i += 2; continue; }
|
|
1963
|
+
if (data[i] === "\n" || data[i] === "\r") { out += SENTINEL; i += 1; continue; }
|
|
1964
|
+
out += data[i]; i += 1; continue;
|
|
1965
|
+
}
|
|
1966
|
+
let matched = false;
|
|
1967
|
+
for (const seq of SHIFT_ENTER_SEQS) {
|
|
1968
|
+
if (data.startsWith(seq, i)) { out += SENTINEL; i += seq.length; matched = true; break; }
|
|
1969
|
+
}
|
|
1970
|
+
if (matched) continue;
|
|
1971
|
+
if (loneLfShiftEnter && data[i] === "\n") { out += SENTINEL; i += 1; continue; } // lone LF = Shift+Enter (opt-in)
|
|
1972
|
+
out += data[i]; i += 1;
|
|
1973
|
+
}
|
|
1974
|
+
kf.write(out);
|
|
1952
1975
|
});
|
|
1953
1976
|
keyFilter = kf;
|
|
1954
1977
|
// readline now decodes keypresses on `keyFilter`; keep process.stdin emitting
|
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 = "> ";
|