Repository navigation
[Bug][tool-fs][0.2.1-alpha.2] write/edit result-card diff runs untimed on the Host thread; an 8,000-line overwrite freezes every session for ~8 s #9371
Replies: 1 comment
|
机制确凿,修复设计也对。但先说清一件事:这条在仓库里是明文设计,不是漏了参数 —— 这决定了它是 bugfix 还是设计变更,也决定 PR 该怎么写。 1.
|
Uh oh!
There was an error while loading. Please reload this page.
Summary
After a successful
writeoredit, the tool computes the result card's hunks inoutput.presentationMetaby calling jsdiffstructuredPatchsynchronously on the Host thread, with notimeoutormaxEditLength. Myers diff costs O(N·D), so overwriting or rewriting a large file with mostly different content is near-quadratic. The write itself finishes in milliseconds, but the card diff then blocks the event loop: every session's streaming, timers, the API server, and the WebSocket mux stall.The sibling package
workspace-changesalready passestimeoutto the same function and degrades to a whole-file replacement when it expires.Environment
0.2.1-alpha.2, masterd743267388pnpm install --frozen-lockfileReproduction
Mount
fs-local+tool-fs, create a file of N JSON-ish lines, thenwriteit with N different lines (a regenerated data file, a reformatted source file, a translated catalog):editreplace_alltouching all 8,000 linesThe master column comes from an earlier run of the same repro on the same machine under similar load; growth is near-quadratic in the line count. On master a timer scheduled during the call fires only after the diff finishes. The persisted
metafor a full overwrite was about 2.4× the written bytes on master and is 0 KiB on the branch (the timed-out comparison yields no hunks).Root cause
packages/fs/tool-fs/src/diff.ts#L36execute:write.ts#L102-L108,edit.ts#L112-L115workspace-changes:packages/deliverables/workspace-changes/src/compare.ts#L41Fix
Branch:
heaven999b/deepseek-harness@fix/tool-fs-diff-timeout(compare with master) (one commit,cf714dee7d, based ond743267388; 11 files, +139/−25)diffTimeoutMs(default100, the same name and default asworkspace-changes), rejected at load unless a positive integer.computeHunkDiffs(path, before, after, timeoutMs)passestimeouttostructuredPatch; an expired comparison returns no hunks.writealready falls back to the argument-derived whole-file card whenmeta.diffsis empty (as for creates), andeditalready falls back to the generic card. The client diff-card model behaves the same way. The write/edit operation itself is never affected.docs/config-catalog.md(en/zh) are updated.A targeted edit has a tiny edit distance and finishes far below 100 ms, so normal cards are unchanged.
Verification
degrades to no hunks when the comparison exceeds the timeout— a 4,000-line rewrite with a 1 ms budget returns[]within 1 s (on master the untimed comparison runs to completion and returns hunks).write overwrite: a timed-out diff leaves empty meta and presentResult falls back to the whole-file cardedit replace_all: a timed-out diff leaves empty meta and presentResult falls back to the generic carddiffTimeoutMs: 0and2.5d743267388.vitest run packages/fs/tool-fs/tests --coverage --coverage.include='packages/fs/tool-fs/src/**/*.ts': 221 tests pass; everysrcfile at 100% statements/branches/functions/lines.tsc -b packages/fs/tool-fs/tsconfig.jsonandtsc -b tsconfig.host.json(includes the specs): clean.gen-config-catalog --check,verify-translation-pairing,verify-md-wrap, staged oxlint andgit diff --check: pass.write2k/4k/8k lines,edit replace_all8k lines) produced the "branch" column above.metais UI presentation only and normal edits are unaffected, so no keyless snapshot was re-recorded.Follow-up not included: when a large diff does complete within budget (many scattered small changes),
metacan still be large and is persisted in the session log.tool-fs-searchbounds its meta withsearchMetaMaxBytes(64 KiB); an equivalent byte cap for write/edit diffs would be a separate change.Related
structuredPatch,write diff slow,edit large file freeze,event loop blocked: no existing report.All reactions