release: sync develop to main#240
Merged
Merged
Conversation
Bumps [rand](https://github.com/rust-random/rand) from 0.8.6 to 0.10.2. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](rust-random/rand@0.8.6...0.10.2) --- updated-dependencies: - dependency-name: rand dependency-version: 0.10.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
New connector.html / connector.zh-CN.html walk a non-developer through installing, getting a token, writing one config file, and — importantly — keeping the ACP connector updated, with the "bot can't see attached files → update the connector" failure mode called out prominently (the exact symptom from a real haowe_codex report). Linked from both homepages' Docs grids; recorded in website/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The MCP post_message tool maps to the channel.messages.create resource, which crosses MCP → loopback HTTP → connector WS → gateway. Four changes cut latency on that path and make it measurable: - loopback: HTTP keep-alive so the MCP↔connector socket is reused across resource calls instead of reconnecting per call (Connection: close → keep-alive, with carry-over buffering for pipelined requests, a clean-EOF signal, and a 120s idle timeout). Helps every tool, not just post_message. - gateway: spawn the post-commit broadcast (Redis PUBLISH + chain resolution + bot@bot trigger) off the reply's critical path, so post_message returns as soon as the row commits. Ordering stays correct — the frontend re-sorts incoming message frames by channel_seq. - gateway: resolve mention_names in one batched ANY() query instead of one round-trip per name (the lone N+1 in the create path), mirroring validate_mention_ids. Group-token expansion and error/order semantics preserved. - instrumentation: debug-level timing spans on the connector WS round-trip and the gateway db-path, plus the off-path broadcast, so the dominant hop is a number rather than a guess. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New website/mcp.html: a GitHub Pages reference for the Cheers MCP server — its 26 tools grouped by capability with read/write/destructive access tags, the four-hop request path, and where post_message spends its time. Reuses the site's existing chrome (nav, theme toggle, table/callout/docs-grid recipes and amber palette) so it matches index.html and plugin-dev.html. Wire it into the nav and developer docs of index.html and plugin-dev.html, and list it in website/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`cargo fmt --check` (CI: Agent Package Check) rejected the `timeout(...)` call in handle_connection. Formatting only — no behaviour change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…seam `resource::dispatch` is db-only by design, so a successful write there is only half the operation: creating a message must also broadcast the live frame and trigger @mentioned bots, leaving a channel must re-broadcast presence, and an fs.* write must nudge open Desk views. Those need AppState (fanout / stream_registry / bot_locator), which dispatch doesn't have — so each effect was patched in at the bot-bridge WS boundary. That put the rule "creating a message ⇒ broadcast + trigger" at exactly one call site. A second transport (the Streamable-HTTP MCP endpoint we're considering) calling resource::dispatch directly would persist the row, return ok, and silently skip the broadcast and the trigger — no error, just a channel that never updates and an @mentioned bot that never wakes. Introduce gateway::resource_effects::dispatch_with_effects(state, principal, frame): dispatch plus the effects it can't perform, so every transport routes through one seam and gets the complete semantics of each verb. Moves the four effect blocks (messages.create, channel.leave, fs.*, bot.status.write) out of agent_bridge, which shrinks by ~114 lines to a single call. Behaviour-preserving: same effects, same ok-gating, same off-critical-path spawn for the message broadcast. `workspace.read` stays intercepted at the bridge — it is an alternate dispatch, not a post-dispatch effect, and fails loudly rather than silently elsewhere. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rf-2c79e9 post_message: trim the hot path, add a transport-neutral effects seam, document the MCP
Dev loop for renderer plugins without admin install: drop a .html on the drawer (or Load extension) and its renderers join the candidates for this browser session only, marked ⏱ in pickers. A same-id session plugin shadows the installed one so a deployed plugin can be iterated on live; reload restores the installed version. - PluginMeta gains inline bundle?/transient? (session-only; never on the wire); SandboxRenderer uses the inline bundle instead of fetching - manifest shape validation extracted to dependency-free pluginManifest.ts (shared by admin upload + temp load), with vitest coverage; uploads now reject empty/renderer-less (legacy panels) manifests with a named reason - 2 MiB bundle cap on the temp load path (server install cap follows in the protocol PR) - delete retired panels/cheers:init protocol examples (notes-plugin, research-plugin); point RESEARCH_SCENARIO at a current-protocol example - PLUGIN_DEVELOPMENT.md restructured as the normative reference (Quickstart dev loop, protocol reference incl. cheers:resource + lifecycle/conflict flows, cookbook, troubleshooting); RENDERER_PLUGIN.md marked design original deferring to it; WORKBENCH/examples/READMEs updated Verified e2e (kind stack + vite): temp-load md-checklist → ⏱ candidate ranked first → checklist renders in sandbox → toggle saves (v2) and persists in the file → session plugin gone after reload. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… vocabulary, server-side validation, inline SDK
The plugin contract gets a version and a normative spec, so it can evolve
without breaking installed plugins.
- manifest gains protocol (absent = 1, the documented default covering all
pre-field installs); hosts skip plugins declaring an unimplemented
protocol instead of half-rendering them; the server rejects them at
install
- match vocabulary (protocol 1 final): format accepts a string OR list;
dataHas = top-level keys of parsed structured content (format-agnostic
successor of jsonHas, which stays valid with frozen JSON-only semantics);
dataKind object|array — the only way to claim a JSON array. Specificity
counts the new constraints; unknown match keys are ignored by design
- builtin chart migrates jsonHas -> dataHas (same behavior)
- server: validate_manifest on PUT /workbench/plugins/:id — id charset +
path-param match, title, protocol, legacy panels reject, per-renderer
shape, match type-checks; 2 MiB bundle / 64 KiB manifest caps (413). The
old "{}"-manifest default hole is closed; already-installed rows are
never revalidated
- cheers-plugin-sdk.js (docs/arch/examples): ~50-line copy-paste-inline
helper wrapping ready/render/save/resource; examples declare protocol: 1
- PLUGIN_DEVELOPMENT.md: protocol field + vocabulary + server error table +
SDK section + explicit JSON-RPC/MCP-Apps deferral note; zh doc pointer
Tests: 8 new cargo cases (validation matrix), 14 vitest cases across the
registry vocabulary + manifest validation; full suites green (165 cargo /
41 vitest).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four official plugins ship inside the gateway binary and seed into
workbench_plugins at startup, so a fresh install has a useful renderer set
with zero admin steps. They double as reference implementations (all built
on the inline SDK):
cheers-checklist md task lines -> interactive checklist
cheers-table JSON array of objects -> editable table, columns
inferred from the union of row keys (dataKind:"array")
cheers-kanban-md '## heading' columns + task-line cards; moves/toggles
rewrite only those lines, everything else byte-for-byte
cheers-frontmatter flat 'key: value' frontmatter form; unparseable lines
read-only + preserved; body never touched
Seeding policy (pure decide(), unit- and integration-tested): the binary is
the source of truth (origin='system', migration 0048 adds the column + a
workbench_official_plugin_state version ledger); admin deletions stick
across restarts of the same release and are only undone by a release
shipping a higher manifest version; ids admins claimed are never touched.
The API refuses PUT on official rows (copy under a new id to customize);
DELETE stays allowed. A unit test walks every embedded bundle through
extract_manifest + validate_manifest so CI cannot ship a malformed one.
Also fixes the Dockerfile mtime-touch line to cover assets/ — include_str!
deps are tracked via dep-info mtimes, so an assets-only change would have
shipped a stale binary.
Frontend: Official badge + sticky-deletion confirm in Settings; PluginMeta
gains origin.
Verified on the kind stack: boot log seeds 4; same-version restart seeds 0
(idempotent, deletions stick); PUT on official id -> 400; legacy panels ->
400; 3 MiB bundle -> 413; todo.md offers 'Checklist · cheers-checklist'
from the installed set and renders/saves; Settings shows 4 Official badges.
cargo test 171 passed (+4 sqlx integration vs real Postgres); vitest 41.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v4...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…erving writes Structured boards can now be .yaml/.yml, and — the point of choosing YAML over JSON — their comments survive machine rewrites. The lens save path patches the parsed Document (yamlDoc.applyEdits: deep diff -> setIn/deleteIn on the CST) instead of re-serializing, so '# notes for humans/bots' and blank lines ride through UI edits untouched. Documented loss cases (correctness over comment retention): unparseable input, multi-document streams, and anchors/aliases fall back to a full re-stringify; an array whose length/order changed is replaced wholesale. - Format layer: YAML_FMT with serialize(data, prevText) round-trip context (useFile threads the last-loaded text); .yaml seeds serialize as YAML - registry: formatOf classifies yaml; dataHas/dataKind evaluate on parsed YAML (jsonHas stays frozen to JSON, tested); builtin table/kanban/chart claim ['json','yaml'] - builtin table becomes PICKABLE: columns come from template config when present, else inferred from the union of row keys (dataKind:'array' gates the offer) — this is also the official YAML answer, since sandboxed plugins would have to inline their own parser (documented) - docs: match table + yaml plugin note + YAML 1.2 semantics warning Tests: 11 yamlDoc round-trip cases (comments above/inline, blank lines, key add/delete, nested edits, array-resize/anchor/multi-doc fallbacks), 5 registry yaml cases; 55 vitest total green. Verified live (kind stack): seeded ydemo/rows.yaml (commented array) -> builtin Table auto-offered with inferred name/role columns -> cell edit -> Save -> Raw shows both comments intact plus the edit; metrics.yaml with 'series' renders the chart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 26.1.0 to 26.1.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.1.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@codemirror/lang-markdown](https://github.com/codemirror/lang-markdown) from 6.5.0 to 6.5.1. - [Changelog](https://github.com/codemirror/lang-markdown/blob/main/CHANGELOG.md) - [Commits](https://github.com/codemirror/lang-markdown/commits) --- updated-dependencies: - dependency-name: "@codemirror/lang-markdown" dependency-version: 6.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [agent-client-protocol](https://github.com/agentclientprotocol/rust-sdk) from 1.0.1 to 1.2.0. - [Release notes](https://github.com/agentclientprotocol/rust-sdk/releases) - [Commits](agentclientprotocol/rust-sdk@agent-client-protocol-http-v1.0.1...agent-client-protocol-http-v1.2.0) --- updated-dependencies: - dependency-name: agent-client-protocol dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.16 to 8.5.19. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.5.16...8.5.19) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.19 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 2.1.9 to 4.1.10. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.10 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.41 to 0.23.42. - [Release notes](https://github.com/rustls/rustls/releases) - [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md) - [Commits](rustls/rustls@v/0.23.41...v/0.23.42) --- updated-dependencies: - dependency-name: rustls dependency-version: 0.23.42 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [clap](https://github.com/clap-rs/clap) from 4.6.1 to 4.6.2. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](clap-rs/clap@clap_complete-v4.6.1...clap_complete-v4.6.2) --- updated-dependencies: - dependency-name: clap dependency-version: 4.6.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.23 to 1.1.3+spec-1.1.0. - [Commits](toml-rs/toml@toml-v0.8.23...toml-v1.1.3) --- updated-dependencies: - dependency-name: toml dependency-version: 1.1.3+spec-1.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
The GitHub repository moved from haowei2000/Cheers to ElePerson/Cheers
(2026-07-16). Repo web links 301-redirect, but the GitHub Pages URL does
NOT — haowei2000.github.io/Cheers is dead — and GHCR packages don't
transfer either. Sweep every tracked reference to the old owner:
- READMEs: badges, release links, and the (broken) live-overview Pages
link -> eleperson.github.io/Cheers
- runtime defaults: connector_release_repo (server/src/config.rs),
install.sh CHEERS_CONNECTOR_REPO default, BotOnboardingWizard
CONNECTOR_RELEASES_REPO, enrollment instructions text — releases moved
with the repo, so the new owner is the correct default (old URLs also
still redirect for anything already deployed)
- ghcr.io/haowei2000/* -> ghcr.io/eleperson/* in Helm/deployment docs,
matching cd.yml's ${{ github.repository_owner }} (images land there on
the next main push; container packages do not transfer with the repo)
- website/ landing pages, docs/help guides, CHANGELOG compare links,
issue-template security-advisory URL, Chart.yaml home
Verified: github.com/ElePerson/Cheers, releases/latest, and
eleperson.github.io/Cheers all return 200; zero 'haowei2000' left in
tracked files; cargo check + tsc clean (modulo pre-existing PdfViewer).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The GitHub repo moved from haowei2000/Cheers to ElePerson/Cheers on 2026-07-16. Old links only work via GitHub's transfer redirect (and the old GitHub Pages URL is already dead), so update the hardcoded owner in user-facing surfaces: website pages, READMEs, docs/help guides, the connector-download fallbacks (BotOnboardingWizard, gateway config default, install.sh), the enrollment help text, and the Helm chart home URL. Every rewritten URL was verified to resolve, including the releases/latest connector asset download. ghcr.io/haowei2000/* image references are left as-is: GHCR packages do not transfer with the repo, and no public images exist under eleperson yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thread_rng() -> rng(), Rng::gen_range -> RngExt::random_range Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- create ~/.cheers/workspace in setup (connector requires allowed_roots to exist) - add troubleshooting row for allowed_roots does not exist - point all links at ElePerson/Cheers after the repo transfer - escape & in Q&A hrefs; unpin release tag in gh download callout Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…vior - PLUGIN_DEVELOPMENT.md: cheers:render is sent on ready and after a conflicted save; external edits do not push a re-render - pluginManifest.ts: correct the bundle-cap comment (server cap lands with install validation) - WorkbenchDrawer: measure the 2 MiB cap in UTF-8 bytes; accept .htm and uppercase extensions on drop Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
chore: point repo references at ElePerson/Cheers after transfer
…gistry, validator parity - SDK: enforce single-in-flight save (host does not correlate saves); document the rule as normative in PLUGIN_DEVELOPMENT.md - registry.ts: replace literal NUL glob placeholders with \u0000 escapes so the file diffs as text on GitHub - pluginManifest.ts: mirror the server's per-key manifest validation so session loads and installs accept the same manifests - server: accept protocol 1.0 (JSON number equal to 1) — the frontend cannot distinguish 1.0 from 1 after JSON.parse - examples: lit-review uses dataHas instead of deprecated jsonHas Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Literal 0x00 bytes in globToRegExp made git classify the file as binary, hiding every diff of this file on GitHub. Same runtime value via \u0000 escapes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nto HEAD # Conflicts: # frontend/src/features/chat/workbench/renderers/registry.ts
- Dockerfile: make the asset cache-bust predicate actually match (relative find paths never matched */assets/*) - workbench_official: checked i32 conversion for manifest version; SkipAdminClaimed logs at info - checklist/kanban manifests: offer renderers for * [ ] bullets too - table plugin: Set-based column dedup (survives constructor/toString keys) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s' into HEAD # Conflicts: # frontend/src/features/chat/workbench/renderers/registry.ts
… cases - builtin table: only offered for arrays of plain objects; render and update guard non-object rows so a null or scalar row can neither crash the app nor corrupt the file on save - yamlDoc: preserve header comments of comment-only files across the first save; disable lineWidth refolding of untouched scalars; align the array-replacement contract comment with the code and name the same-length-reorder comment hazard - docs: write-side YAML 1.1 ambiguity note (unquoted no/yes/on/off) - pluginManifest: yaml joins the documented format list Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
chore: update owner references after repo transfer to ElePerson
…lop/actions/setup-node-7 chore(deps): Bump actions/setup-node from 4 to 7
…rs-acp-connector-rs/develop/clap-4.6.2 chore(deps): Bump clap from 4.6.1 to 4.6.2 in /packages/cheers-acp-connector-rs
…rs-acp-connector-rs/develop/rustls-0.23.42 chore(deps): Bump rustls from 0.23.41 to 0.23.42 in /packages/cheers-acp-connector-rs
# Conflicts: # website/README.md # website/index.html # website/index.zh-CN.html
…ntext-a7f6b6 docs(website): user-facing ACP connector guide (EN + 中文)
…rs-acp-connector-rs/develop/toml-1.1.3spec-1.1.0 chore(deps): Bump toml from 0.8.23 to 1.1.3+spec-1.1.0 in /packages/cheers-acp-connector-rs
…rs-acp-connector-rs/develop/agent-client-protocol-1.2.0 chore(deps): Bump agent-client-protocol from 1.0.1 to 1.2.0 in /packages/cheers-acp-connector-rs
…nd/develop/types/node-26.1.1 chore(deps-dev): Bump @types/node from 26.1.0 to 26.1.1 in /frontend
…nd/develop/codemirror/lang-markdown-6.5.1 chore(deps): Bump @codemirror/lang-markdown from 6.5.0 to 6.5.1 in /frontend
…nd/develop/postcss-8.5.19 chore(deps-dev): Bump postcss from 8.5.16 to 8.5.19 in /frontend
…nd/develop/vitest-4.1.10 chore(deps-dev): Bump vitest from 2.1.9 to 4.1.10 in /frontend
…s-acp-connector-rs/develop/rand-0.10.2 chore(deps): bump rand from 0.8.6 to 0.10.2 in /packages/cheers-acp-connector-rs
feat(workbench): session-level temporary plugins + normative plugin docs
feat(workbench): plugin protocol 1 — versioned manifest, match vocabulary, server validation, SDK
feat(workbench): official renderer plugin set, seeded by the gateway
feat(workbench): YAML boards with comment-preserving writes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings main up to date with develop:
🤖 Generated with Claude Code