Skip to content

chore(deps): bump yaml to ^2.8.3 - #2642

Closed
1688mengdie wants to merge 3474 commits into
GCWing:mainfrom
BitFun-SIG:chore/security-pnpm-yaml
Closed

1688mengdie wants to merge 3474 commits into
GCWing:mainfrom
BitFun-SIG:chore/security-pnpm-yaml

Conversation

@1688mengdie

Copy link
Copy Markdown

Summary

src/web-ui pins yaml ^2.8.2, which resolves to yaml 2.8.2 in
pnpm-lock.yaml; the 2.8.x line below 2.9.0 is covered by prototype
pollution and ReDoS advisories. vite and vitest resolve through
peer-dependent lockfile entries parameterized on the yaml version, so
the vulnerable release is reachable from the vite/vitest toolchain as
well.

This PR bumps the specifier to ^2.8.3 and regenerates the lockfile,
which resolves yaml 2.9.0 (the newest release inside the caret range)
and flips every peer-parameterized key in the same change — splitting
them would leave the lockfile inconsistent.

Fixes #2635

Type and Areas

Type: security fix

Areas: Dependencies (Web UI)

Verification

  • pnpm install --frozen-lockfile — Already up to date, exit 0.
  • pnpm --dir src/web-ui run type-check — exit 0.
  • pnpm --dir src/web-ui run lint — exit 0.
  • vitest web-ui suites — 14 passed.
  • pnpm run frontend:build-all — exit 0 (vite/vitest startup smoke
    covered by type-check + vitest).

Reviewer Notes

  • The direct dependency change is one line in src/web-ui/package.json
    (^2.8.2 -> ^2.8.3); the large lockfile diff is the expected
    regeneration product: the yaml package block, and the vite/vitest
    peer entries parameterized on the yaml version (yaml@2.8.2 ->
    yaml@2.9.0) across importers, plus pnpm 10.15.0 optional platform
    annotations. Audited hunk by hunk; zero unintended version changes.
  • Rollback is a revert of the two-file change.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable. (Not applicable: no user-facing change.)

This is an AI-assisted change.

limityan and others added 30 commits August 14, 2026 14:02
…on-ui-ux

feat(harmonyos): fold settled process cards and recover hollow remote transcripts
Replace the numeric desktop rollback path with an identity-based
Session transaction owned by the Agent Runtime.

- Resolve rollback targets by stable Turn identity
- Validate stale requests before admitting durable mutations
- Preserve recovery state until authoritative reload succeeds
- Hold Session mutation exclusion across edit and rerun
- Support rollback targets from paginated history ranges
- Reset stale history windows after catalog revisions change
- Negotiate targeted rollback support with peer devices
- Remove the legacy snapshot rollback command and UI
- Add focused backend, frontend, and adapter coverage

This keeps workspace files, persisted history, runtime context, and
the frontend projection aligned to one authoritative boundary.

BREAKING CHANGE: remove the legacy rollback_to_turn command and its
numeric turn-index contract
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replace the legacy functional-agent model map with typed task model
settings for session title and Git commit generation.

- Default task models to fast without persisting default values
- Allow session titles to inherit the active session model
- Validate and reconcile task models across config boundaries
- Remove the obsolete Startchat agent runtime, APIs, and contracts
- Update settings UI, translations, dispatch handling, and tests

BREAKING CHANGE: remove ai.func_agent_models and the Startchat agent APIs.
The harness has no ACP entry point of its own, and the published
@deepseek-ai/dsh-acp is an automation surface: it withholds tool calls,
reasoning, and mode selection, because a script does not need to watch an
agent think. An IDE needs exactly those.

So add packages/dsh-acp and ship it as a dsh PROFILE rather than as
something the user installs separately. dsh symlinks its whole dependency
closure into $DSH_HOME/profiles/node_modules on every launch, so a profile
resolves every harness plugin out of the user's own installation. BitFun
therefore carries a compiled bridge, not a second copy of the harness, and
launches `dsh --profile bitfun-acp`.

The model and the key stay in dsh. cordis.yml mounts the harness's own
settings, credentials, and default-model rows, so whatever the user picked
in dsh's Models page is what an IDE session runs on. BitFun stores nothing
about the account.

This replaces the `dsh` preset from GCWing#2272, which launched the automation
surface under the same id.

Two of the changes here are not dsh-specific and apply to every ACP agent:
tool calls now render as BitFun's native Bash/Read/Edit cards grouped by
round, and the model picker handles an agent that publishes a `mode`
option instead of models, collapsing to a locked entry once a conversation
has fixed its mode.

packages/dsh-acp is deliberately not a pnpm workspace member: it pins the
whole harness 0.1.0-rc.6 train and carries its own package-lock.json, so
installing the harness is the desktop bundle build's cost rather than
every contributor's. prepare-dsh-profile.mjs fails the build rather than
shipping a bridgeless app, since the two are indistinguishable until a
user starts a session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Rust job never runs `prepare:dsh-profile`, so `packages/dsh-acp/dist-profile`
— a bitfun-desktop Tauri resource — was absent and the build script failed with
"resource path doesn't exist" on all three platforms. Create it the same way CI
already creates `src/mobile-web/dist`, and teach the preflight check and
CONTRIBUTING about it so the same failure is self-explaining locally. The
core-boundary check needs the client feature's new optional dependencies in its
reviewed list, which is the other half of the red.

Then the limitation the PR disclosed: profile materialization ran only in
`start_local_transport`, so a remote workspace launched `dsh --profile
bitfun-acp` against a host that had no such profile. It now runs for remote
transports too — one probe round trip for `$DSH_HOME`, the harness version, and
the installed stamp, then the built profile as a single tar stream over the
session's own transport when that stamp is stale. Streaming rather than SFTP is
what makes this work for container connections, and the stamp travels last so an
interrupted upload reads as stale rather than as current.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ile deps

The reviewed feature list lives in two places — the rule and the self-test's
mirror of it — and only the rule was updated, so the check passed while the
suite that guards it failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Exclude MCP tools from agent card counts, summaries, and mode tool editing
- Preserve stored MCP overrides when startup canonicalization runs before MCP registration
- Add frontend and backend regression coverage
A remote ACP client that exits during startup left nothing in the log but
a broken pipe from the first `initialize`, because the launch path copied
its stderr into a sink. Log those lines instead: they are the only place
the reason ever appears.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Materialization decided "installed" from `dsh --version` on stdout, while
the agent list decides it from `command -v`. A host where the launcher
resolves but answers nothing on stdout therefore showed as available and
then refused to launch. Resolve presence with `command -v` and keep the
version as best effort on either stream, so an unparsable answer falls
through the version gate rather than blocking a working host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`WorkspaceStdio` documents that the three IO streams are what lease the
process, and that `control` and `completion` do not keep it alive by
themselves. Both channel loops contradicted that: `control_rx.recv()`
returning `None` — which is just the last `WorkspaceProcessControl`
sender going out of scope — was matched together with `Kill`, so a
caller that drives the process purely over stdio killed it the moment it
dropped the handle it had no use for.

Remote ACP is exactly that caller. The agent was SIGKILLed microseconds
after exec, and the only trace left was a broken pipe on the first
`initialize` — no stderr, because it never got to write any.

Resolve the arm only on real signals, and cover both loops with a test
that dropping the handle lets the process run to its own exit status.
An agent that dies mid-session leaves behind the same broken pipe as one
that never started. The exit code says which.
A client that exits before answering `initialize` produced one sentence —
"exited before initialization completed" — which tells the user only what
they already know. Its stderr held the whole explanation and went to a
log file, or, for a local agent, to a terminal a packaged app does not
have.

Read both transports' stderr into the log line by line, keep the tail,
and quote it in the error the user is shown. Waiting for EOF first is
what makes the quote complete: the pipes closing is the signal that the
agent is gone, and its last lines are still in flight then.

Also ask the remote host for its Node version in the probe round trip we
already make, and refuse the launch when it is below 20.12 — the release
that added `util.parseEnv`, which the harness imports on its first line.
dsh declares no `engines`, so npm installs it onto Node 18 without a word
and the failure surfaces from deep inside the launcher.
Allow permission changes made during an active turn to affect the
next model round while keeping the current round stable.

- Keep active-turn overrides mutable and process-local
- Clear temporary overrides when the owning turn ends
- Persist session-scoped selections and clear active overrides
- Add a dedicated active-turn permission command
- Distinguish next-message and current-turn scopes in the UI
- Preserve compatibility with older session permission requests
DeepSeek Harness's PTC preset answers a whole step with one `run_code`
call whose argument is a TypeScript program. The bridge classified it by
kind alone, so it landed on the terminal card, which reads `command` —
a field the call does not have — and drew an empty card.

Give it its own identity and card: `run_code` (and anything shaped like
it: Execute kind, a `code` argument, no `command`) becomes `RunCode`,
rendered as the program plus what it printed. A shell call that happens
to carry a `code` argument is still Bash.

While reading the result path: ACP results carry their text in content
blocks, but the terminal card reads `output`/`stdout`, so every ACP Bash
card showed the command with nothing underneath it. Lift that text into
`output` for both cards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An ACP session came back empty after a restart. Its turns were never
written, and three layers each had a reason.

The projection is the only writer of these turns, but it had no storage
slot to write into. That slot arrives with the backend's
`DialogTurnStarted`, and no such event exists for a turn an external
agent runs — nothing in the local runtime starts it. Every save was
therefore deferred, forever. Allocate the slot in the projection instead,
from the turns and catalog it already holds, and decline to guess when
the session has persisted turns none of which are projected yet, where a
guess would overwrite history.

The backend then refused the save it did receive. `save_persisted_dialog_turn`
validates a turn against the runtime's history branch for that session,
and an externally driven session has none — the runtime neither starts
nor completes those turns — so a first turn failed with OutcomeUnknown.
Read the session's `provider` metadata and, when an external agent owns
it, persist straight through. A runtime-owned session still needs its
branch, which the new test pins from both sides.

Finally, the desktop path loaded every session into the session manager
before saving, which for an ACP session restored nothing and rewrote its
persisted mode to a local fallback. Skip the load for the same reason:
there is no runtime state to restore.

The `provider` key and its `acp` value move into core-types, so the ACP
client that writes them and the runtime that reads them back share one
definition rather than two string literals that have to agree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closing a dsh session and clicking it again gave a blank one: the bridge
never advertised ACP's `loadSession`, so BitFun had only `session/new` to
fall back on. Every one of a user's stored sessions carries
`acpResumeStrategy: "new"` for that reason. The reopened conversation
lost its history and its context, and its mode picker unlocked and
reverted to the roster default — a session that has already spoken must
not be able to change the composition its transcript was written under.

Implement `session/load`. A live session replays from memory; a cold one
resumes out of the harness's own persistence, which is the case that
matters, since a client restart is exactly when nothing is in memory. The
archive is read through `inspect`, not a listing: a session disposed a
moment ago is still draining, and `list` does not wait for it while
`inspect` does — reopening the session you just closed is the first thing
a user does.

The mode comes back from the session's own log rather than the roster, so
a conversation started under a preset reopens under it however the
default has moved, and `presetOptions` locks the picker for a session
whose conversation has started. A session is refused when it was never
stored, or when it belongs to another directory — answering the latter
would hand back a session whose sandbox boundary points somewhere else.

`scripts/smoke.mjs --load <id>` drives the path against a real
installation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat(acp): ship an ACP bridge for DeepSeek Harness
The 0.2.18 Desktop Package run failed in `Package (windows-x64)` with
`spawnSync npm ENOENT` out of `build-profile.mjs`, taking the whole
`frontend:build-all` down with it. Three separate Windows assumptions:

- `npm` is a `.cmd` shim there, and Node has refused to spawn one without
  a shell since CVE-2024-27980. A shell then re-splits every argument, so
  passing an absolute `--pack-destination` would break on its first space.
  Both `npm pack` and `tar` now run *in* the staging directory, which
  leaves their arguments as bare package names and one filename — no
  quoting to get wrong, and no drive letter reaching `tar -f`, which GNU
  tar would read as a remote host.
- `copyTree`'s filter derived a basename by slicing on '/', which on a
  '\'-separated path yields the whole path and therefore matched nothing.
  A vendored tree would have dragged `node_modules` along.
- `hashTree` recorded native separators, so the same sources produced a
  different content stamp per build host. Digests are unchanged on Unix
  (verified byte-for-byte against the previous script).

`prepare:dsh-profile` runs only inside `frontend:build-all`, which no CI
job invokes, so its first Windows execution ever was a release build.
Add a small `windows-latest` job that runs the packaging and asserts the
profile is complete, stamped, and carries nothing it must not ship.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…endor

fix(dsh): package the bridge profile on Windows
Preserve YAML and TOML frontmatter through Markdown and TipTap
round trips without exposing structural delimiters for editing.

- Render labeled frontmatter metadata in preview mode
- Support protected frontmatter editing in IR mode
- Preserve delimiters, line endings, comments, and body spacing
- Show unsafe syntax warnings only when IR requires fallback
- Add focused parser, preview, and editor regression tests
Add the private AgentClient, Session, and Query vertical slice over the existing Agent Runtime owner. Consolidate bounded JSON, JSON-RPC, and WebSocket mechanics in the cross-platform transport foundation while keeping IPC framing and product protocol policy with their owners. Generate strict runtime validators from the Rust wire contract and preserve bounded lifecycle and process-tree cleanup.
cargo check and desktop:dev no longer require packages/dsh-acp/dist-profile.
Official packaging still builds the profile and injects it as a Tauri resource.
…pile-resource

fix(desktop): keep the DeepSeek bridge off the compile path
Keep release-sync cron on the in-repo script and document the host
export/import path so a new server does not need a detached AutoUpdate copy.
docs(deploy): restore the OpenBitFun origin from the BitFun checkout
Remove automatic snap-back when the user scrolls into the reserved
blank below the conversation tail.

- Preserve explicit session, rollback, navigation, and tail alignment
- Keep tail-follow recovery when output catches up with the reader
- Update viewport ownership tests and FlowChat behavior documentation
nonoqing and others added 27 commits August 27, 2026 13:07
(cherry picked from commit 430911ccd7add16a0d756b948207a765ed97bc78)
(cherry picked from commit c173aebdeee8256a99c191600feedc0472f3232a)
Strengthen intent reduction safety across Agent Hook rewrites
find_actual_string compared every char window of the file against the
search string by hand. The comparison short-circuits on the first
mismatch, so ordinary source stays fast, but a file holding long runs
of one character (minified output, padded or aligned text) makes most
windows share a deep prefix with the search string and the scan turns
quadratic: 256KB of spaces with a 2KB old_string took over 20 seconds
per candidate on this machine, and edit_string_candidates can probe
several candidates per failed edit.

Quote normalization maps one char to one char, so normalizing both
sides once and searching with str::find finds the same leftmost match
in linear time. The returned slice is cut from the line-ending
normalized file by char offset, which byte offsets cannot do once
multibyte text precedes the match; a new test covers that case, and a
second test guards the runtime on long repeated runs.

Validation: cargo test --locked -p tool-runtime --lib; cargo test
--locked -p bitfun-core --lib; cargo check --locked --workspace;
cargo fmt -p tool-runtime -- --check.

Refs: GCWing#1650
AI: fully tested
Place curly quotes before the target match so quote normalization
changes the byte offset between normalized and original content.

This verifies that match locations are mapped by character offset,
not only that the matched span uses a character length.
feat(session): add rename action to session control tool
Route rename persistence through the project workspace so managed
worktree sessions retain their authoritative storage identity.

Publish manual title updates through the existing compatible event
channel and request Desktop session sync for durable remote state.

Render rename states in the SessionControl card with localized copy
and focused regression coverage.

Refs: GCWing#2471
feat(session): add rename action to SessionControl
feat(agent): migrate Minimal mode to main
The trend chart's cache hit-rate polyline dropped null buckets and joined
the remaining points into one polyline, so an idle stretch (all token
counters at zero, no cache telemetry) was visually bridged by a high
dashed line connecting the buckets on either side - the chart implied a
~97% hit rate over hours where the tooltip correctly showed no data.

- split the hit-rate series into contiguous segments that stop at
  buckets without telemetry; an isolated point renders as a dot
- add hover marker dots for every series so small values stay visible
  on a zero-baseline token axis (e.g. 276K next to a 20M peak reads as
  flat zero without an anchor)
- format the tooltip hit rate with formatHitRate (two-decimal truncate)
  instead of Math.round for consistency with the summary cards
Splitting the hit-rate series at buckets without telemetry left isolated
dots and blank stretches, which read as a broken chart. Idle buckets
already draw every token series at zero, so plot the hit rate at 0%
there too and keep one continuous dashed line; the tooltip mirrors the
line with 0.00% instead of an en dash.
Keep provider-reported cache-write tokens in the backend records, aggregates, persisted statistics, and API response while removing the noisy series from the current chart UI.

Render synthesized idle buckets at 0% for continuity, but keep active buckets without cache telemetry as gaps and show an unavailable tooltip value instead of claiming a measured 0% hit rate.

Add focused coverage for the hidden series, segmented trend, and tooltip semantics.
Upgrade the transitive h2 dependency from 0.4.15 to the latest patched 0.4.x release. This closes RUSTSEC-2026-0258, which allows unbounded empty DATA frames to cause memory exhaustion or a panic, and includes follow-up fixes that avoid rejecting legitimate small-frame traffic.

Only the locked version and checksum change; the dependency graph and application sources are unchanged.

Test: cargo check --locked -p bitfun-core; cargo tree --locked -i h2 --depth 1

AI: lightly tested
Co-authored-by: BitFun <318544290+bitfun-ai@users.noreply.github.com>
Prevent idle cleanup from evicting durable sessions while a turn is
still processing, and recheck the state immediately before removal.

Add a synchronous per-message send-now guard so rapid clicks cannot
issue duplicate steering requests. Cover both cleanup races and UI
re-entry with regression tests.
Prevent automatic compaction from dropping task state when the latest
successful TodoWrite call falls outside the exact recent suffix.

- Scope retained TodoWrite snapshots to the active dialog turn
- Ignore failed writes and avoid duplicating state already in the tail
- Preserve explicit clears and same-turn recompression checkpoints
- Render authoritative task state inside a dedicated <todo> block
DeepReview remediation changes a manager-owned session binding before the turn is admitted. The admission snapshot must track the effective route owner and all execution-affecting session bindings so stale configuration cannot start a turn.\n\nSynchronize the turn-local snapshot after the ReviewFixer binding update and reject concurrent model, route, context-window, and workspace binding changes. Add regression coverage for the successful remediation path and admission races.
Co-authored-by: BitFun <318544290+bitfun-ai@users.noreply.github.com>
…binding

fix(session): keep turn admission bindings consistent
BTW and review sessions render outside the main flow-chat container, so a direct permission request could block the child runtime without exposing any way to answer it in the side panel.

Render the shared permission mailbox in BtwSessionPanel and separate broad transcript routing from actionable ownership. Delegated subagent requests remain owned by the parent Task surface, while direct review-child requests stay with the child surface. This avoids duplicate permission panels without inheriting the parent's permission mode.

Add routing and hook regression coverage for direct and delegated requests, including the one-owner active batch behavior.
…n-panel-routing

fix(flow-chat): route permission requests to a single owner
src/web-ui pins yaml ^2.8.2, which resolves to yaml 2.8.2 in
pnpm-lock.yaml; the 2.8.x line below 2.9.0 is covered by prototype
pollution and ReDoS advisories. vite and vitest resolve through
peer-dependent lockfile entries parameterized on the yaml version, so
bumping the direct dependency and regenerating the lockfile flips those
peer keys in the same change.

Test: pnpm install --frozen-lockfile (Already up to date, exit 0);
pnpm --dir src/web-ui run type-check (exit 0); pnpm --dir src/web-ui
run lint (exit 0); vitest web-ui suites (14 passed);
pnpm run frontend:build-all (exit 0).
AI: AI-assisted, locally tested (frozen-lockfile resolution + web-ui
checks + full frontend build).
@GCWing

GCWing commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Thank you for your contribution.

The main branch has been replaced with the 1.0.0 codebase from 1.0.0-explore. As part of this migration and Git history cleanup, the affected pull requests have been temporarily closed.

If your changes are still needed, please reapply them on a fresh branch based on the new main, then open a new PR against main or update and reopen this PR. Please link any replacement PR to this one so we can retain the discussion and review context.

We apologize for the disruption and appreciate your understanding.

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.

[Security]: yaml 2.8.2 in src/web-ui is affected by prototype pollution/ReDoS advisories (fixed in 2.8.3+)