qwen-code/scripts/pty-e2e.sh
ChiGao cd1ac72874
feat(opentui): bundle assets, CI matrix and parity tooling (Batch 7) (#10770)
* feat(opentui): add the build, CI and parity tooling for the renderer migration

Batch 7 of the ink→OpenTUI migration (#8662): everything the renderer
needs to be built, verified and shipped — ink stays the default.

Bundled builds silently lose code-block syntax highlighting because
@opentui/core resolves its tree-sitter assets package-relatively, which
misses inside the esbuild bundle. Relocate the runtime assets (parser
worker, grammar wasms/scm, web-tree-sitter, native render library) next
to the bundle, and gate OTUI_ASSET_ROOT on the tree being complete for
the running platform — @opentui/core throws on any missing key, so an
incomplete relocation must fall back instead of half-configuring.
Standalone archives gain a Bun runtime (the renderer needs bun:ffi) and
per-target @opentui platform packages via the existing release
packaging, with --runtime=node restoring classic packaging.

The renderer matrix drives interactive E2E under node+ink and bun+opentui,
but Batch 6's renderer gate silently falls back to ink on an unsupported
runtime, so a green opentui leg could be a false green. QWEN_TUI_RENDERER_STRICT
turns that fallback into a loud startup failure for the matrix legs only;
user-facing default behavior is unchanged.

Parity tooling: a tui-parity workflow with component snapshots and a
no-flicker gate (zero full-screen clears, balanced DEC 2026) that runs
offline without model credentials, an ink→opentui codemod with a
self-test, the PTY/tmux comparison harnesses, and the cli scripts/ tree
is now covered by the package typecheck.

* fix(ci): build all packages in the tui-parity jobs

With prepare skipped, npm ci leaves the CLI's workspace dependencies
unbuilt, and a workspace-scoped build of the CLI alone resolves their
types from a dist that does not exist yet. The parity jobs must run the
repository-root build like the other E2E legs.

* fix(build): enforce renderer strict mode and drop musl from standalone packages

Address yiliang114's review on the Batch 7 build/CI work:

- propagate QWEN_TUI_RENDERER_STRICT into RendererSelection so the
  dispatcher also fails loudly when the OpenTUI entry returns false or
  throws, closing the false-green path in the E2E renderer matrix
- stage the OpenTUI platform packages only for the bun runtime and drop
  the -musl variants: the bundled Bun binaries are glibc-linked and
  cannot start on musl hosts, so the musl render packages claimed
  support the archives cannot deliver
- wipe dist/opentui-assets before re-copying so a stale tree from an
  earlier bundle cannot satisfy the key-existence runtime gate
- route the script-PTY capture branch through spawnScriptPty so the
  argv form follows the platform, and give it the destroy() that
  finish() expects from the node-pty-like interface
- harden pty-e2e.sh (set -euo pipefail, mktemp+trap, full TCL escaping
  of the prompt) and tmux-compare.sh (missing-binary check, mktemp+trap)
- pin the CI Bun setups to 1.3.14 = DEFAULT_BUN_VERSION so an upstream
  Bun release cannot flip the gating legs on its own

* fix(build): keep classic Node packaging as the standalone default

The temporary OpenTUI preview flavor (--runtime=bun) stays available but
no longer replaces the default release archives, keeping Batch 7 additive
for existing standalone users.

* fix(scripts): compare prettier-normalized output in the codemod self-test

Address F1 and F3 from the deep verification report:

- The self-test compared the codemod's raw output against the
  prettier-formatted fixtures/after.tsx, so 2 of 17 tests failed as
  committed. Normalize both sides through the repo prettier config
  before comparing (tests 1 and 6); the harness awaits because
  prettier 3's format() is async-only.
- Refresh the tui-parity.yml baseline entry from 2190 to the measured
  2508 bytes so the ratchet tracks real growth.

* fix(build): gate standalone opentui assets by runtime flavor

Node archives carry no opentui-assets tree at all: the renderer needs
bun:ffi, and cross-built archives would only hold another platform's
native library that the all-or-nothing asset gate could never activate.
Bun archives now prune every @opentui/core-* directory that does not
belong to the build target, dropping the build host's library from the
archive. The npm-package allowlist comment is corrected to match the
observed fallback behavior.

* test(cli): cover the OpenTUI strict-mode dispatch and e2e renderer matrix

main() now has coverage for the four dispatch outcomes: strict mode
throws both when the OpenTUI entry declines to start and when it boots
with an error, and non-strict mode falls through to startInteractiveUI.
resolveE2eCliCommand gains coverage for the opentui leg — bun on PATH
resolves to bun, and a missing bun fails with the actionable error.
2026-09-02 08:36:20 +00:00

27 lines
1.1 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# PTY 自动化 E2E模拟键盘输入+读屏,复用本机 qwen 配置/凭据做真实模型调用,无需人工。
# 用法: scripts/pty-e2e.sh "你的提示" [wait_sec]
set -euo pipefail
PROMPT="${1:-hi}"; WAIT="${2:-20}"
OUT=$(mktemp /tmp/pty-e2e.XXXXXX.log)
EXP=$(mktemp /tmp/pty-e2e.exp.XXXXXX)
trap 'rm -f "$OUT" "$EXP"' EXIT
# $PROMPT 会被展开进 expect 的 TCL 源码TCL 双引号字符串里 \ " $ [ 都
# 有替换语义($var 与 [command] 可注入),四个字符都要先转义。
ESCAPED_PROMPT=$(printf '%s' "$PROMPT" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\$/\\$/g' -e 's/\[/\\[/g')
cat > "$EXP" <<EXP
set timeout $WAIT
log_file -a $OUT
spawn qwen2
sleep 3
send "$ESCAPED_PROMPT"
sleep 1
send "\r"
sleep $WAIT
send "\x03"
sleep 1
close
EXP
expect "$EXP" >/dev/null 2>&1 || true
echo "=== 输入是否显示 ==="; tr -c '[:print:]\n' ' ' < "$OUT" | grep -cF -- "$PROMPT" || true
echo "=== 是否有模型回复/工具/错误 ==="; tr -c '[:print:]\n' ' ' < "$OUT" | grep -a -oE "live error|Error|✗|✓|Read|Bash|markdown|qwen3|Thinking" | sort | uniq -c | head || true