Repository navigation
fix(workflow): preserve UTF-8 in command outputs - #1275
Conversation
Signed-off-by: ydflow <314143294+ydflow@users.noreply.github.com>
|
No findings in the specified PR diff. The testing record satisfies the review criteria: it documents a build followed by two real-CLI cases covering preserved UTF-8 output, downstream consumption, persisted results, and failure diagnostics. Baseline failures and remaining CI coverage are clearly disclosed. Review was read-only; I did not run, build, or install anything from the PR. |
SaulMoro
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
@ydflow Approving. We built this head and main (d60e68f5) and ran a two-step local workflow (init --self, pull, workflow start --driver local). The first step emits {"summary":"检查完成 café 😀"}.
main |
this head | |
|---|---|---|
| Success run: exit, outcome | 0, succeeded | 0, succeeded |
Stored output, next step's input, result.json |
���查完成 café 😀 |
检查完成 café 😀 |
| Failing run: stored failure message | ���行失败 café 😀 |
执行失败 café 😀 |
[P3 nit] The new e2e test sets itself up through internal modules (resolveProjectDataHome, syncWorkflowDefinitions) and a hand-written config.yaml. The neighbouring workflow e2e tests run init --self and pull through the CLI.
Outside this PR: src/utils/exec.ts:48-57 decodes each chunk with chunk.toString() the same way, and with stream set it also prints the broken text to the terminal. The same setEncoding('utf8') fix would apply there in a follow-up.
#1251 edits the startCommand call site for the working directory. This PR changes only the stdout and stderr decoding, so the two don't conflict.
Summary
A local workflow command's UTF-8 character can cross stdout pipe chunks.
startCommanddecoded each Buffer independently, so the command could succeed with valid JSON while silently changing a string value before saving it and handing it to the next step.Built-CLI reproduction, two command steps:
Use each pipe's
setEncoding('utf8')so stdout and stderr keep independent decoder state across chunks and flush at EOF. After the fix, the original value reaches both steps' stored outputs and attemptresult.jsonfiles. Failed-command stderr also retains the original diagnostic. The English and Chinese workflow guides state the encoding contract.Type of Change
Test Plan
npm run buildnpm run typechecknpm run lintgit diff --checknpx vitest run src/__tests__/workflow-command-utf8.test.ts: 6 passed. The subprocess boundary emits individual bytes on interleaved stdout/stderr; the real driver and engine persist the result. Covers Chinese, accented text, emoji, ASCII, a stored failure diagnostic and an incomplete trailing sequence at EOF. Before the fix: 5 failed, ASCII control passed.npx vitest run --config vitest.e2e.config.ts src/__tests__/e2e/workflow-command-utf8.test.ts --retry 0: 2 passed. Real Node commands split a UTF-8 character across two OS-pipe writes. Success checks the emitter's output, the next command's env-template input and output, both attempt result files and CLI exit 0. Failure checks the stored stderr diagnostic and CLI exit 1. Both cases fail on the pre-fix build with the damaged text above. No AI tool or live model is used.origin/mainatd60e68fand fix(workflow): close the #1080 workspace gaps (#1246) #1251 at3ef4e1884260306e2e733663d875096458f25503. The merge is clean; build, the same 6 regressions and 2 real-CLI cases pass there too. The published branch contains only this fix.d60e68f: the unchanged driver file gives 66 passed / 23 failed / 3 skipped, and the unchanged adapter file gives 19 passed / 7 failed. No failing name in those two files differs between branch and baseline. These include POSIX shell/process-signal cases; this is not a green Windows suite.npx vitest run --maxWorkers=4 --bail=10 --reporter=jsonattempt stopped early, recording 107 passed, 7 failed, 12 pending. All seven observed failing names reproduce in unchangedlocal-agent.test.tson pristined60e68f. This is not a completed full-suite result.EPERMremoving a temporary fixture directory during cleanup; the later six-case run passed with the same cleanup code and assertions. Its cause is not established; the failed attempt is retained in the local record.The remaining platform and full-suite coverage is left to CI.
Related Issues
Follow-up to #1242, which fixed the separate prompt-tool stdout path in
local-tool-adapter.ts. This fixes command steps inlocal-driver.ts, including stderr. No open PR was found for this path. #1251 changes workspace handling in the same module; compatibility was checked as above.Notes for Reviewers
Runtime changes are limited to four added and two removed lines in
startCommand. Its local stdout/stderr accumulators feed the close/error result,commandReport, the attempt result file and the engine's existing step state. No workflow schema, command-line option or dependency changes.Door: two-way; reverting changes decoding behavior, with no migration.
Blast radius: local command stdout values and stderr diagnostics, including values consumed by later workflow steps.