jeo-code 0.8.35 → 0.8.36
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 +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/package.json +1 -1
- package/src/commands/launch.ts +13 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
The README mirrors the latest 5 entries — regenerate with `bun run changelog:sync`.
|
|
8
8
|
|
|
9
|
+
## [0.8.36] - 2026-07-21
|
|
10
|
+
_First full audit of gjc v0.11.5's actual ~65-PR "What's Changed" list (prior passes had used release-note prose or direct-source structural diffs — this is the first time every individual PR was read and triaged against jeo's own codebase)._
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **A raw stdin chunk boundary landing mid multi-byte UTF-8 sequence corrupted the composer's input** (`src/commands/launch.ts`'s `kfDataHandler`) — gjc parity (#2591 "preserve supplementary Unicode input"). The live stdin `"data"` handler did `chunk.toString("utf8")` on EACH raw `Buffer` chunk independently; real terminals/ptys never guarantee byte-aligned-to-character delivery (more likely under load, over SSH, or during a fast paste), so a split sequence produced the Unicode replacement character (`U+FFFD`) on BOTH sides of the split instead of the real character — corrupting any non-ASCII input: Korean/CJK IME text, emoji, accented Latin. Quantified the exact corruption before fixing: a 4-byte emoji (`😀`) split after 2 bytes decoded to `"\uFFFD" + "\uFFFD\uFFFD"`, never the original character. Fixed with a persistent `node:string_decoder` `StringDecoder` that buffers an incomplete trailing byte sequence across chunks and only emits complete characters — the standard fix for streaming UTF-8, and exactly what Node's own string-mode streams do internally. `filterPromptInputChunk`'s own separate ASCII-level carry logic (bracketed-paste markers, CRLF splits) is unaffected and unchanged; the two are complementary, not overlapping.
|
|
14
|
+
|
|
15
|
+
### Verified
|
|
16
|
+
- `test/stdin-utf8-decode.test.ts` — 5 pass (new): quantifies the OLD per-chunk `toString("utf8")` bug directly (a split 4-byte emoji really does decode to two replacement characters), proves the `StringDecoder` fix reassembles both a split 4-byte emoji AND a split 3-byte Hangul character correctly, confirms complete ASCII-only chunks are unaffected (no behavior change for the common case), and asserts the real wiring in `launch.ts`'s source (not a naive `chunk.toString("utf8")`).
|
|
17
|
+
- Real (unmocked) live verification: booted a real `jeo --tmux` session and typed real Korean + emoji text (`안녕하세요 테스트 😀🎉 한글입력`) via `tmux send-keys`, real UTF-8 bytes over a real pty — rendered correctly and completely, no corruption, no regression.
|
|
18
|
+
- Full `bun test` — 3119 pass / 0 fail across 307 files.
|
|
19
|
+
- `bun run typecheck` — no errors.
|
|
20
|
+
|
|
21
|
+
### Audit status (answering "is everything through gjc v0.11.5 covered?")
|
|
22
|
+
- **No** — not fully verified as of this entry. This pass read all ~65 PRs in v0.11.5's actual "What's Changed" list for the first time (prior passes used release-note prose for v0.10.2-v0.11.4, and direct-source structural diffs — not a PR-by-PR read — for v0.11.5's provider catalog and tool surface). Only the one fixed above was confirmed both applicable and safely portable so far; the rest of v0.11.5's list is still being triaged in-session.
|
|
23
|
+
|
|
9
24
|
## [0.8.35] - 2026-07-21
|
|
10
25
|
_Deeper gjc-parity pass: re-cloned the real, public `Yeachan-Heo/gajae-code` source and, this time, structurally compared its actual tool implementations (`packages/coding-agent/src/tools/`) against jeo's own tool surface, not just the provider catalog._
|
|
11
26
|
|
package/README.ja.md
CHANGED
|
@@ -283,11 +283,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
283
283
|
## 変更履歴 (Changelog)
|
|
284
284
|
|
|
285
285
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
286
|
+
- **[0.8.36]** (2026-07-21) — First full audit of gjc v0.11.5's actual ~65-PR "What's Changed" list (prior passes had used release-note prose or direct-source structural diffs — this is the first time every individual PR was read and triaged against jeo's own codebase).
|
|
286
287
|
- **[0.8.35]** (2026-07-21) — Deeper gjc-parity pass: re-cloned the real, public `Yeachan-Heo/gajae-code` source and, this time, structurally compared its actual tool implementations (`packages/coding-agent/src/tools/`) against jeo's own tool surface, not just the provider catalog.
|
|
287
288
|
- **[0.8.34]** (2026-07-21) — Provider/model-catalog sync against gjc's actual current source (a shallow clone of the real, public `Yeachan-Heo/gajae-code` repo at v0.11.5 — direct `packages/ai/src/models.json` comparison, not inference from release notes). The system prompt's philosophy, the `/route` command, and the `tencent` provider were explicitly out of scope and are unchanged.
|
|
288
289
|
- **[0.8.33]** (2026-07-20) — Real terminal-resize testing (repeated tmux resize-window + keystroke reproductions, byte-for-byte ANSI replay outside jeo/tmux to isolate root causes deterministically) uncovered and closed a progressive screen-corruption bug: resizing down to a narrow terminal (e.g. a ~20-column tmux pane) produced a growing stack of duplicate status-bar lines on every subsequent keystroke, and a separate, independently-reproducible scroll bug in the mid-turn live renderer.
|
|
289
290
|
- **[0.8.32]** (2026-07-20) — gjc parity: TUI display-width/wrapping is now grapheme-cluster-aware for emoji sequences (VS16 presentation, skin-tone modifiers, keycaps, ZWJ-joined emoji like family/profession glyphs), fixing box-border and wrap misalignment ("깨짐") that the old per-code-point width summation produced whenever such a sequence appeared in a message — Korean/CJK-only text was already correctly handled and is unaffected.
|
|
290
|
-
- **[0.8.31]** (2026-07-20) — `web_search` no longer silently degrades every non-Anthropic model to keyless DuckDuckGo scraping — OpenAI and Gemini sessions now get their own native, hosted search tool (matching the same active-model-gated, credential-required design Anthropic already had), with DuckDuckGo remaining the always-on terminal fallback for everyone else.
|
|
291
291
|
|
|
292
292
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
293
293
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -284,11 +284,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
284
284
|
## 변경 이력 (Changelog)
|
|
285
285
|
|
|
286
286
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
287
|
+
- **[0.8.36]** (2026-07-21) — First full audit of gjc v0.11.5's actual ~65-PR "What's Changed" list (prior passes had used release-note prose or direct-source structural diffs — this is the first time every individual PR was read and triaged against jeo's own codebase).
|
|
287
288
|
- **[0.8.35]** (2026-07-21) — Deeper gjc-parity pass: re-cloned the real, public `Yeachan-Heo/gajae-code` source and, this time, structurally compared its actual tool implementations (`packages/coding-agent/src/tools/`) against jeo's own tool surface, not just the provider catalog.
|
|
288
289
|
- **[0.8.34]** (2026-07-21) — Provider/model-catalog sync against gjc's actual current source (a shallow clone of the real, public `Yeachan-Heo/gajae-code` repo at v0.11.5 — direct `packages/ai/src/models.json` comparison, not inference from release notes). The system prompt's philosophy, the `/route` command, and the `tencent` provider were explicitly out of scope and are unchanged.
|
|
289
290
|
- **[0.8.33]** (2026-07-20) — Real terminal-resize testing (repeated tmux resize-window + keystroke reproductions, byte-for-byte ANSI replay outside jeo/tmux to isolate root causes deterministically) uncovered and closed a progressive screen-corruption bug: resizing down to a narrow terminal (e.g. a ~20-column tmux pane) produced a growing stack of duplicate status-bar lines on every subsequent keystroke, and a separate, independently-reproducible scroll bug in the mid-turn live renderer.
|
|
290
291
|
- **[0.8.32]** (2026-07-20) — gjc parity: TUI display-width/wrapping is now grapheme-cluster-aware for emoji sequences (VS16 presentation, skin-tone modifiers, keycaps, ZWJ-joined emoji like family/profession glyphs), fixing box-border and wrap misalignment ("깨짐") that the old per-code-point width summation produced whenever such a sequence appeared in a message — Korean/CJK-only text was already correctly handled and is unaffected.
|
|
291
|
-
- **[0.8.31]** (2026-07-20) — `web_search` no longer silently degrades every non-Anthropic model to keyless DuckDuckGo scraping — OpenAI and Gemini sessions now get their own native, hosted search tool (matching the same active-model-gated, credential-required design Anthropic already had), with DuckDuckGo remaining the always-on terminal fallback for everyone else.
|
|
292
292
|
|
|
293
293
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
294
294
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -291,11 +291,11 @@ Huge thanks to [gajae-code](https://github.com/Yeachan-Heo/gajae-code) for the i
|
|
|
291
291
|
## Changelog
|
|
292
292
|
|
|
293
293
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
294
|
+
- **[0.8.36]** (2026-07-21) — First full audit of gjc v0.11.5's actual ~65-PR "What's Changed" list (prior passes had used release-note prose or direct-source structural diffs — this is the first time every individual PR was read and triaged against jeo's own codebase).
|
|
294
295
|
- **[0.8.35]** (2026-07-21) — Deeper gjc-parity pass: re-cloned the real, public `Yeachan-Heo/gajae-code` source and, this time, structurally compared its actual tool implementations (`packages/coding-agent/src/tools/`) against jeo's own tool surface, not just the provider catalog.
|
|
295
296
|
- **[0.8.34]** (2026-07-21) — Provider/model-catalog sync against gjc's actual current source (a shallow clone of the real, public `Yeachan-Heo/gajae-code` repo at v0.11.5 — direct `packages/ai/src/models.json` comparison, not inference from release notes). The system prompt's philosophy, the `/route` command, and the `tencent` provider were explicitly out of scope and are unchanged.
|
|
296
297
|
- **[0.8.33]** (2026-07-20) — Real terminal-resize testing (repeated tmux resize-window + keystroke reproductions, byte-for-byte ANSI replay outside jeo/tmux to isolate root causes deterministically) uncovered and closed a progressive screen-corruption bug: resizing down to a narrow terminal (e.g. a ~20-column tmux pane) produced a growing stack of duplicate status-bar lines on every subsequent keystroke, and a separate, independently-reproducible scroll bug in the mid-turn live renderer.
|
|
297
298
|
- **[0.8.32]** (2026-07-20) — gjc parity: TUI display-width/wrapping is now grapheme-cluster-aware for emoji sequences (VS16 presentation, skin-tone modifiers, keycaps, ZWJ-joined emoji like family/profession glyphs), fixing box-border and wrap misalignment ("깨짐") that the old per-code-point width summation produced whenever such a sequence appeared in a message — Korean/CJK-only text was already correctly handled and is unaffected.
|
|
298
|
-
- **[0.8.31]** (2026-07-20) — `web_search` no longer silently degrades every non-Anthropic model to keyless DuckDuckGo scraping — OpenAI and Gemini sessions now get their own native, hosted search tool (matching the same active-model-gated, credential-required design Anthropic already had), with DuckDuckGo remaining the always-on terminal fallback for everyone else.
|
|
299
299
|
|
|
300
300
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
301
301
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -283,11 +283,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
283
283
|
## 更新日志 (Changelog)
|
|
284
284
|
|
|
285
285
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
286
|
+
- **[0.8.36]** (2026-07-21) — First full audit of gjc v0.11.5's actual ~65-PR "What's Changed" list (prior passes had used release-note prose or direct-source structural diffs — this is the first time every individual PR was read and triaged against jeo's own codebase).
|
|
286
287
|
- **[0.8.35]** (2026-07-21) — Deeper gjc-parity pass: re-cloned the real, public `Yeachan-Heo/gajae-code` source and, this time, structurally compared its actual tool implementations (`packages/coding-agent/src/tools/`) against jeo's own tool surface, not just the provider catalog.
|
|
287
288
|
- **[0.8.34]** (2026-07-21) — Provider/model-catalog sync against gjc's actual current source (a shallow clone of the real, public `Yeachan-Heo/gajae-code` repo at v0.11.5 — direct `packages/ai/src/models.json` comparison, not inference from release notes). The system prompt's philosophy, the `/route` command, and the `tencent` provider were explicitly out of scope and are unchanged.
|
|
288
289
|
- **[0.8.33]** (2026-07-20) — Real terminal-resize testing (repeated tmux resize-window + keystroke reproductions, byte-for-byte ANSI replay outside jeo/tmux to isolate root causes deterministically) uncovered and closed a progressive screen-corruption bug: resizing down to a narrow terminal (e.g. a ~20-column tmux pane) produced a growing stack of duplicate status-bar lines on every subsequent keystroke, and a separate, independently-reproducible scroll bug in the mid-turn live renderer.
|
|
289
290
|
- **[0.8.32]** (2026-07-20) — gjc parity: TUI display-width/wrapping is now grapheme-cluster-aware for emoji sequences (VS16 presentation, skin-tone modifiers, keycaps, ZWJ-joined emoji like family/profession glyphs), fixing box-border and wrap misalignment ("깨짐") that the old per-code-point width summation produced whenever such a sequence appeared in a message — Korean/CJK-only text was already correctly handled and is unaffected.
|
|
290
|
-
- **[0.8.31]** (2026-07-20) — `web_search` no longer silently degrades every non-Anthropic model to keyless DuckDuckGo scraping — OpenAI and Gemini sessions now get their own native, hosted search tool (matching the same active-model-gated, credential-required design Anthropic already had), with DuckDuckGo remaining the always-on terminal fallback for everyone else.
|
|
291
291
|
|
|
292
292
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
293
293
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
package/src/commands/launch.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { emitKeypressEvents } from "node:readline";
|
|
3
|
+
import { StringDecoder } from "node:string_decoder";
|
|
3
4
|
import { PassThrough } from "node:stream";
|
|
4
5
|
import { runAgentLoop, DEFAULT_TOOLS, TOOL_PROTOCOL, WORKING_DISCIPLINE, OUTPUT_DISCIPLINE, VERIFICATION_DIRECTIVE, isSafetyFallbackBail, stripSafetyFallbackTag, type AgentLoopEvents } from "../agent/engine";
|
|
5
6
|
import { computerSupervisor } from "../agent/computer-supervisor";
|
|
@@ -2395,8 +2396,19 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
2395
2396
|
// lives in `filterPromptInputChunk` (pure + exported) so the full keystroke wiring is
|
|
2396
2397
|
// testable without a live readline/PTY; this handler is the thin live adapter.
|
|
2397
2398
|
const kfState = { inPaste: false };
|
|
2399
|
+
// gjc parity (#2591 "preserve supplementary Unicode input"): a raw stdin "data"
|
|
2400
|
+
// chunk boundary can land MID multi-byte UTF-8 sequence (real terminals/ptys do not
|
|
2401
|
+
// guarantee byte-aligned-to-character delivery, especially under load or over
|
|
2402
|
+
// SSH/tmux) — naive per-chunk `chunk.toString("utf8")` then replaces the split
|
|
2403
|
+
// sequence's incomplete tail/head with U+FFFD on EACH side of the split, corrupting
|
|
2404
|
+
// any non-ASCII input (Korean/CJK IME text, emoji, ...) whenever this happens. A
|
|
2405
|
+
// persistent `StringDecoder` buffers an incomplete trailing byte sequence across
|
|
2406
|
+
// `write()` calls and only emits complete characters, exactly like Node's own
|
|
2407
|
+
// string-mode streams do internally — this is the standard fix for streaming UTF-8.
|
|
2408
|
+
const kfUtf8Decoder = new StringDecoder("utf8");
|
|
2398
2409
|
const kfDataHandler = (chunk: Buffer) => {
|
|
2399
|
-
const data =
|
|
2410
|
+
const data = kfUtf8Decoder.write(chunk);
|
|
2411
|
+
if (!data) return; // an incomplete sequence is buffered inside the decoder; wait for the rest
|
|
2400
2412
|
const result = filterPromptInputChunk(
|
|
2401
2413
|
data,
|
|
2402
2414
|
activeRl ? (activeRl as unknown as { line: string; cursor: number }) : null,
|