Skip to content

v0.1.15 - 配置精简 + Ink UI 引擎 + 流式 Markdown 渲染#38

Open
Linux2010 wants to merge 21 commits into
mainfrom
feat/v0.1.15
Open

v0.1.15 - 配置精简 + Ink UI 引擎 + 流式 Markdown 渲染#38
Linux2010 wants to merge 21 commits into
mainfrom
feat/v0.1.15

Conversation

@Linux2010

Copy link
Copy Markdown
Owner

v0.1.15 变更

配置精简(参考 OpenClaude 设计)

  • 用户只需配置 4 项:apiKey, apiBaseUrl, defaultModel, fallbackModel
  • Agent 内部控制 LLM 参数:maxTokens=8192, temperature=0.1
  • 移除用户不该配置的参数:maxTokens, temperature, maxRetries, retryBaseDelay

Ink UI 引擎

  • 从 OpenClaude 复制完整 Ink 渲染引擎(103 文件,936KB)
  • 自定义 reconciler、screen buffer、diff 渲染
  • 键盘输入通过 useInput hook 处理
  • 支持中文输入和显示(CJK 可见宽度计算)

流式渲染增强

  • 完整 Markdown 流式渲染(标题、粗体、斜体、代码块、列表、引用、链接)
  • 表格流式渲染支持
  • CJK 文本可见宽度计算修复(中文占 2 格)
  • 命令面板输入清除修复

其他修复

  • CLI 异步错误处理(Promise.catch)
  • chatStream 参数传递 bug 修复
  • 测试适配(370 tests pass)

发布

  • npm: openhorse@0.1.15

🤖 Generated with Claude Code

Linux2010 and others added 21 commits June 6, 2026 10:27
The redrawInputWithPrompt function was duplicating content when
input wrapped across multiple terminal lines. The root cause was
in the line-count clearing logic: when content length was an exact
multiple of terminal width, the cursor would be on the next empty
line, causing ESC[2K to clear the wrong line.

Fix: detect exact-width-wrap (cursor on next line) and move up
before clearing, ensuring all rendered lines are properly cleared.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Terminal input line duplication when typing Chinese/Japanese/Korean text.
Root cause: .length treats CJK chars as 1 cell, but they occupy 2 cells
in the terminal. This caused line-count calculation to under-estimate
wrapped lines, leaving old content unc cleared.

Fix: add visualWidth() that correctly counts CJK as 2 cells,
use it everywhere we calculate rendered line count.

Tested: single-line (80 chars), multi-line (450 chars CJK x8),
exact-width-boundary (80, 160 chars) all clear correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. handleInput async calls without .catch() (cli.ts:204,374)
   - Command panel selection and multiline submit called async handleInput
     without error handling, risking unhandled promise rejection
   - Add .catch() to both call sites

2. History search permanently loses entries (cli.ts:493)
   - updateHistorySearch replaced inputHistory with filtered results
   - After exiting search mode, the filtered list persisted in memory
   - Fix: filter from fresh getInputHistory() without replacing the local copy

3. LSP timeout timer leak (lsp.ts:225)
   - setTimeout not stored or cleared when request completes
   - Fix: store timer in pendingRequests entry, clearTimeout in handleResponse()
     and dispose()

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Before: only code blocks rendered, all other markdown passed through raw.
Now supports:
- Headings (h1-h6) with bold + color
- Bold, italic, inline code
- Unordered/ordered lists with bullets
- Blockquotes, links, horizontal rules
- Code blocks preserved from before

Streaming-aware: buffers incomplete lines, renders on newline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Detect table rows (| ... |) and buffer them
- Flush on empty line or non-table content
- Render with box borders (┌─┬┐, ├─┼┤, └─┴┘)
- Bold header rendering
- Proper column width calculation with CJK visual width support
- Inline markdown rendering in table cells (bold, italic, code, links)
- Streaming-aware: buffers rows across multiple feed() calls

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match Claude Code style: user input echoed with dark slate
background (#1E293B) and light text (#E2E8F0).

- Single-line input: each line wrapped with background fill
- Multi-line input: same style applied per-line
- Prompt (❯) keeps its original accent color

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chalk.bgHex didn't work because chalk.level was 0 at module load time
in the CLI context. Switched to hardcoded ANSI escape sequences:

- 48;2;30;41;59 = RGB bg #1E293B (slate-800)
- 38;2;226;232;240 = RGB fg #E2E8F0 (slate-200)
- 38;2;0;212;170 = RGB fg #00D4AA (prompt accent)

Works in any terminal with true-color support, no chalk dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move chalk.level=3 to before any chalk.hex/bgHex calls (module load)
- Replace removed userInputFill/userInputPrompt functions with
  USER_INPUT_BG and USER_INPUT_ACCENT constants
- 377 tests pass

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chalk.level=3 was being set but chalk caches the level at module load
time. The hex() and bgHex() functions use the CACHED level, not the
runtime-set level.

Switched to hardcoded ANSI escape codes:
- 48;2;30;41;59 = bg #1E293B (slate-800)
- 38;2;226;232;240 = fg #E2E8F0 (slate-200)
- 38;2;0;212;170 = fg #00D4AA (accent cyan for ❯)

Bypasses chalk entirely for user input echo, guaranteeing true-color
output in any terminal that supports 24-bit colors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause found: user's terminal doesn't support background colors
at all (not even basic ANSI \x1b[41m red background). The code was
working correctly - ANSI codes were generated and output properly.

- Switched back to chalk.bgHex (cleaner than raw ANSI)
- Removed all debug logging
- Code path verified: keypress → accumulation → enter → echo ✓

On terminals that support 24-bit colors, user input will show with
dark slate background (#1E293B) and light text (#E2E8F0).
On terminals without bg color support, text renders normally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docs/version/v0.1.15.md: full release notes for v0.1.15
- docs/config.md: complete ~/.openhorse/openhorse.json config guide
- docs/openhorse.example.json: config template
- .gitignore: allow docs/version/ and config files
用户配置项(仅 3 项):
- apiKey, apiBaseUrl, defaultModel

Agent 内部控制:
- maxTokens: 代码 8192 / 分析 4096 / 简短 512
- temperature: 代码 0.1 / 分析 0.3 / 创意 0.7
- maxRetries: 指数退避自动调整
- retryBaseDelay: 500ms → 1s → 2s → 4s

变更:
- GlobalConfig: 移除 maxTokens/temperature/maxRetries/retryBaseDelay
- OpenHorseCLIConfig: 移除用户不该配置的字段
- LLMService: 内部智能默认值 (maxTokens=8192, temperature=0.1)
- cli.ts: 简化 LLM 初始化调用
- 文档更新
参考 OpenClaude 的 --fallback-model 设计:
- 用户可配置: apiKey, apiBaseUrl, defaultModel, fallbackModel (4 项)
- Agent 内部控制: maxTokens=8192, temperature=0.1, retries=指数退避

fallbackModel 用途: 主模型过载(529/超时)时自动切换到备用模型
- Remove maxTokens/temperature from test configs
- Add proper mocks for loadGlobalConfig to avoid reading real config
- Fix mask format expectation in getConfigSummary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant