jeo-code 0.5.3 → 0.5.4

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 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.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
153
154
  - **[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
155
  - **[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
156
  - **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
156
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.
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.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
153
154
  - **[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
155
  - **[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
156
  - **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
156
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.
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.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
153
154
  - **[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
155
  - **[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
156
  - **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
156
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.
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.4]** (2026-06-15) — Reliable multi-line input is ON by default — a paste fills the box and submits as one message.
153
154
  - **[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
155
  - **[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
156
  - **[0.5.1]** (2026-06-14) — cmd-mode `!<command>` shell escape — run a shell command without engaging the agent.
156
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.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jeo-code",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Clean, highly optimized AI coding agent using spec-first loop",
5
5
  "type": "module",
6
6
  "main": "src/cli.ts",
@@ -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 (JEO_MULTILINE=1, gated) ──────────────────────────────────
1918
- // Shift+Enter inserts a newline instead of submitting. ghostty (and most terminals)
1919
- // send Shift+Enter as a distinct escape sequence (\x1b[27;2;13~ legacy, \x1b[13;2u
1920
- // kitty) that node:readline otherwise mangles into garbage. We route stdin through a
1921
- // filter that rewrites those sequences to a private-use SENTINEL char BEFORE readline
1922
- // sees them readline inserts it as an ordinary character (no submit), and we render
1923
- // it as a real line break and expand it to "\n" on submit. Default OFF: when disabled
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
- const multilineInput = jeoEnv("MULTILINE") === "1" && !!process.stdin.isTTY;
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 Shift+Enter into the newline sentinel BEFORE
1939
- // readline sees it. Three encodings are handled so it works across setups:
1940
- // a lone "\n" (0x0a) chunk what ghostty's `keybind = shift+enter=text:\n`
1941
- // sends; a normal byte that passes through tmux UNCHANGED (works even with
1942
- // tmux extended-keys off). Enter sends "\r" in raw mode, so a lone "\n" is
1943
- // unambiguously Shift+Enter. This is the reliable ghostty+tmux path.
1944
- // • the xterm legacy "\x1b[27;2;13~" and kitty "\x1b[13;2u" sequences — direct
1945
- // terminal (no tmux) or tmux with extended-keys on. (Sent atomically, so a
1946
- // per-chunk replace suffices; no partial buffering that could swallow ESC.)
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
- let data = chunk.toString("utf8");
1949
- if (data === "\n") data = SENTINEL;
1950
- else for (const seq of SHIFT_ENTER_SEQS) if (data.includes(seq)) data = data.split(seq).join(SENTINEL);
1951
- kf.write(data);
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