Skip to content

feat(rules): expose rule search across agent integrations - #7005

Merged
qin-ctx merged 6 commits into
volcengine:mainfrom
CaucherWang:review/dsh-rule-search
Nov 5, 2026
Merged

qin-ctx merged 6 commits into
volcengine:mainfrom
CaucherWang:review/dsh-rule-search

Conversation

@CaucherWang

@CaucherWang CaucherWang commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Description

Agents need a dedicated way to retrieve task constraints before acting. This PR exposes Rule Search across agent integrations and preserves complete constraint blocks, including applicability conditions and exceptions, within bounded tool responses. Undelivered rules and expired lookup history are explicitly marked incomplete.

Human Involvement

  • A human participated in the implementation or review loop
  • This PR was generated entirely by AI agents without human participation in the loop

Related Issue

No linked issue.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test update

Changes Made

  • Expose MCP rule_search and dedicated tools for LangChain/LangGraph, OpenClaw, Hermes, Magpie, and OpenWebUI. Distribute the Rule Search skill through host bundles and shared installers, update manifests, and document integration capabilities in English and Chinese.
  • Bound pi Rule Search output to 50 KiB and 2,000 lines, stopping between complete Rule blocks. Bound VikingBot inline Rule results to 50,000 characters, save oversized source results when possible, and retain only the latest Rule lookup during compaction. Mark omitted Rules and expired lookup history with delivery.complete=false; document how to complete the check before acting.
  • Keep tool call/result pairing, chronological order, and the latest user correction during VikingBot compaction. Enforce the configured character budget (240,000 by default), including the final fallback reply; refuse a model request when required context cannot fit. Propagate MCP failures as execution errors.
  • Exclude inline image Base64 payloads from text character accounting while retaining the existing media byte limit. When a Rule lookup expires, remove only its call/result pair and preserve parallel tool progress for retention or summarization; retain that progress verbatim if summarization fails.
  • Preserve positive Jev exception vetoes at a zero applicability threshold, while ensuring exception probability 0.0 never vetoes an unconditional Rule. Clarify verbatim rule quotations and add regression coverage for schemas, adapters, rule selection, and context preservation.
  • Track Cursor skill installation ownership outside the skill directory. Upgrade or uninstall only unchanged installer-owned directories; preserve existing unmanaged copies, user edits, and symlinks. Use unique staging directories and restore the old copy if publication fails.

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • Targeted new and existing unit tests pass locally
  • I have tested this on the following platforms:
    • Linux
    • macOS
    • Windows

Validation:

  • Blocking review comments: 191 relevant Python regressions passed after fixing image/text budget accounting and mixed-tool Rule-history expiration. Ten new cases first reproduced both failures, then passed with supported images preserved and parallel draft-write progress retained or summarized.
  • Follow-up fixes: 183 relevant Python regressions passed (RuleService/Jev, Rules API, VikingBot, and MCP Rule Search), plus 49 Node tests for pi, Cursor installation ownership, bundle closure, and synchronized skills.
  • Reproduced the budget bypass, unconditional-rule zero-probability veto, and Cursor unmanaged/symlink overwrite before applying the fixes. Added byte/line boundaries, oversized single Rules, save failures, repeated compaction, final fallback, managed upgrades, and user-edit preservation coverage.
  • Follow-up Ruff lint/format checks, installer Bash syntax, JavaScript syntax, and skill frontmatter/synchronization checks passed.
  • RuleService: 99 tests passed.
  • VikingBot compaction, outcomes, provider thinking/streaming, and MCP error handling: 121 tests passed.
  • MCP Rule Search, read compatibility, and tool schemas: 40 tests passed.
  • After merging the latest official main, LangChain Store/integration, memory JSON serialization, and gateway native tool suites: 638 tests passed.
  • Ruff checks passed for the changed core Python files; the updated MCP test file also passed the formatting check.

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Additional Notes

  • The branch includes official main through 02611deb3.
  • Benchmark code, experiment artifacts, and local debug records are excluded.
  • Validation above covers interfaces and rule preservation; it does not establish live-agent applicability accuracy. Test runs reported dependency/deprecation warnings.
  • A follow-up attempt at the entire MCP endpoint suite stalled in the unrelated session-memory store section and was stopped; the focused MCP Rule Search tests passed. The historical complete-suite results above are from the earlier PR validation.

@ZaynJarvis ZaynJarvis added the agent-plugins Agent harness and plugin integrations label Nov 5, 2026
Prevent oversized rule delivery and retained lookups from exhausting agent context, keep zero-probability exceptions from vetoing rules, and preserve user-managed Cursor skills.

@qin-ctx qin-ctx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule Search 补齐各 Agent 的约束查询入口,有实际价值。但上下文压缩引入了两项回归:普通图片请求会被新增的字符预算检查拒绝;旧 Rule 查询过期时,同轮其他工具的结果也会被删除。这两项问题需要在合入前解决。

Comment thread bot/vikingbot/agent/loop.py Resolved
Comment thread bot/vikingbot/agent/loop.py Resolved
Keep image payloads under the media budget rather than the text budget, and retain parallel tool progress when old rule lookups expire.
@qin-ctx
qin-ctx merged commit ed3fe91 into volcengine:main Nov 5, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in OpenViking project Nov 5, 2026
donghao95 added a commit to donghao95/OpenViking that referenced this pull request Nov 6, 2026
* fix(magpie): add opt-in sessionless capture and raise recall budget (volcengine#7073)

* fix(magpie): warn on missing capture sessions and raise recall budget

Log a fixed capture diagnostic once without replacing recall status. Default recall to 2000 ms and show editable 2000/3000 ms recall/host budgets, preserving saved settings.

Validation: syntax checks and npm pack dry-run passed; 126 tests passed, 0 failed, 1 Bun-host test skipped (Bun unavailable). Refs volcengine#7007.

* feat(magpie): add opt-in capture without host sessions

Add captureWithoutSession (false by default). Derive capture identity from client scope and the shaped opening message without changing stateless recall. Preserve real session precedence and recheck file opt-in in queued delivery.

Validation: 131 tests passed, 0 failed, 1 actual Bun-host test skipped (runtime unavailable); syntax checks, npm pack dry-run and diff checks passed. Refs volcengine#7007.

* fix(magpie): retire derived capture queues on native takeover

Resolve derived capture scope before checking native ownership. Parse native-marked history for capture cleanup while preserving recall's existing native-context exclusion. Persist ownership and remove pending snapshots so already-reading workers cannot deliver them.

Validation: new system-envelope and nativeAgents regressions failed before the fix. Full plugin suite now has 134 passed, 0 failed, 1 actual Bun-host integration skipped (runtime unavailable). Syntax and diff checks passed. Refs volcengine#7007.

* fix(magpie): fit recall requests within host hook budget

Keep the 2000 ms recall default while capping HTTP waits by the validated host budget, elapsed hook setup and a 200 ms result-processing reserve. Share an internal deadline across search and profile without confusing it with host cancellation.

Cover 1000/3000 ms host budgets, partial search results, external cancellation and exhausted/invalid budget settings. Update both READMEs.

Validation: plugin syntax checks passed; plugin tests 138 passed, 1 existing Bun-host integration skipped; related shared tests 140 passed; package dry-run and whitespace checks passed.

* fix(magpie): handle derived capture queue conflicts and takeover

* fix(magpie): register sessionless capture settings in shared schema

* feat(ui): add the request client and settle the module props (volcengine#7091)

* docs(ui): align module and component docs with the shipped state

Three kinds of drift between the docs and the code:

- `VikingBot` was removed with the other placeholder APIs, but the
  `console` module still claimed to compose it. Describe the conversation
  view as module-internal instead, so the module boundary is settled:
  `console` composes `Tui` plus a conversation view it implements itself.
- Module counts still said five. There are four module directories.
- FileTree and FilePreview read as implemented. Both are placeholder
  views to be rewritten against their contracts; FileTree renders every
  documented row type, FilePreview has the tab shell and editing
  foundation with its body not yet wired to FileViewer.

Also note in the module README that the components the composite views
build on are placeholders too, so a module's real implementation depends
on those views landing first.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* feat(ui): add the request client and settle the module props

The modules need a request layer before their Hooks can land, and hosts
need the module props before they can integrate the containers. This adds
the first and defines the second.

The client lives in `src/client/` and ships from `@openviking/react/client`:

- `createOvClient` implements `OvClient` over `fetch` with no runtime
  dependencies, joining the service address with the API path, resolving
  configuration field by field, and turning both an HTTP failure and a
  native `status: 'error'` response into `OvClientError`.
- `OpenVikingProvider` distributes the configuration through Context. A
  host passes identity values, not headers: `apiKey` becomes `X-API-Key`,
  `accountId` `X-OpenViking-Account`, `userId` `X-OpenViking-User` and
  `resourceId` `V-Resource-Id`. The open-source edition passes `apiKey`;
  the commercial edition authenticates with the browser cookie, so it
  omits it and sets `credentials` to `include` for cross-origin calls.
- The hook modules read the client through is internal: a host never needs
  to know which requests a module sends, so exporting it would be noise.

The four modules now declare their public props — request options, the
controlled value, callbacks, slots and copy — and export Labels, Slots
and enum types from the subpath only. No prop carries data, because the
module loads its own; the placeholder components still render a name and
a placeholder message and consume none of it yet.

Tests cover path joining, identity-to-header mapping, per-request
override, header re-evaluation, cookie policy, error shapes and that the
Provider sends nothing when it mounts.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): correct the request client's body, errors and config layering

Six review findings on volcengine#7091, all confirmed against the built client.

- A serialized body now declares `Content-Type: application/json`. Without
  it fetch sends `text/plain`, and a Pydantic JSON endpoint such as
  `POST /api/v1/content/write` rejects the body before validation runs.
- A rejected fetch now becomes `OvClientError` with `NETWORK_ERROR` and
  the original error as its cause, matching the documented single
  failure type. An abort keeps its `AbortError` so callers can still
  tell cancellation apart.
- An explicit empty identity field now clears the inherited header
  instead of being indistinguishable from an omitted one, so a
  cookie-only request can drop an inherited credential or account.
- `OvRequestOptions` now exposes `baseURL`, which the layering docs
  already promised: a per-request address override works, and an empty
  string still means same origin.
- A nested Provider now inherits the configuration it does not declare
  rather than starting from its own props alone, so an inner Provider
  that changes only `userId` keeps the outer address and credential.
  The merge is a pure function in `options.ts`, tested directly.
- Both module READMEs now show the shipped API: Provider identity props
  instead of a `headers` prop, and `options: { resourceId }` instead of
  calling an internal hook with arguments.

Regression tests cover each finding, including the actual emitted
headers and the `NETWORK_ERROR` path. Test files are split so each stays
under the lint limit.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): evaluate a default identity callback once per request

`request` resolved the default identity layer twice: once for the base
layer and again inside `resolveClientOptions`. With
`apiKey: () => 'token-' + ++calls`, a single request ran the callback
twice and sent the first value, so an async refresh refreshed twice and
could send the older credential; a second failure could also sink an
otherwise valid request.

`resolveClientOptions` now takes the already-evaluated layer, and the
request path evaluates the defaults once and shares the result between
the parent configuration and the request override.

Three tests pin the behaviour: one evaluation per request, one
evaluation when the request overrides a different field, and a fresh
evaluation for each request.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): report body-read failures and inherit the transport

Two follow-up findings from the re-review at 2c12046.

`response.json().catch(() => undefined)` swallowed every rejection, so a
connection dropped after the headers arrived fulfilled the request with
`undefined` — including an abort, which callers could no longer
distinguish. The client now reads the text first and reports a read
failure through the same `normalizeTransportError` path as the request
itself: cancellation keeps its `AbortError`, anything else becomes
`NETWORK_ERROR`. A body that is not JSON is returned as text instead of
being dropped.

`mergeProviderConfig` did not carry `fetch` to the next layer, so an
inner Provider without its own transport fell back to the global one —
and threw `createOvClient needs a fetch implementation` where none
exists. The transport is now part of the inherited configuration, and an
inner Provider replaces it only by declaring its own.

Tests cover the body-read failure, cancellation during the read, a
non-JSON body, transport inheritance and an explicit replacement.
Verified that the nested Provider renders with no global fetch and only
an outer transport, which previously threw.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>

* feat(rules): expose rule search across agent integrations (volcengine#7005)

* feat(rules): expose task constraints across agent integrations

Preserve complete Rules and the latest user context through tool previews and compaction, and retain exception vetoes at zero thresholds.

* test(mcp): keep read alias coverage compatible with live context

* fix(rule-search): respect output budgets and installer ownership

Prevent oversized rule delivery and retained lookups from exhausting agent context, keep zero-probability exceptions from vetoing rules, and preserve user-managed Cursor skills.

* fix(vikingbot): preserve images and progress during compaction

Keep image payloads under the media budget rather than the text budget, and retain parallel tool progress when old rule lookups expire.

---------

Co-authored-by: zeyu wang <wangzeyu.bd@bytedance.com>

* fix(parser): preserve embedded Feishu whiteboards (volcengine#7075)

* fix(parser): preserve embedded Feishu whiteboards

* chore(parser): keep whiteboard fix focused

* refactor(parser): simplify whiteboard request and preview handling

* fix(parser): preserve content inside Feishu table cells (volcengine#7083)

* feat(ui): order public Props fields and enforce it with a lint rule (volcengine#7100)

* feat(ui): order public Props fields and enforce it with a lint rule

Public Props had grown in whatever order each module was written, so a
reader could not tell at a glance what was required or where the
callbacks were. Two independent rules now decide the order: required
fields before optional ones, and within that, parameters before
callbacks, slots, labels and low-frequency configuration.

Applying it moved `requestOptions` from the top of every module's Props
to the bottom, `labels` and `slots` after the callbacks, and the
`task-center` filters ahead of the callback that reports the selection.
`tui` was the only component with required callbacks, which the rule
forbids: `onValueChange` and `onSubmit` are now optional, where omission
makes the input read-only and disables submission. Its docs said
"Required" for both and now say so.

`@typescript-eslint/member-ordering` cannot express this — its member
types have no notion of optionality, so every interface field is just a
`signature`. The rule is a small custom plugin instead, mounted through
rslint's community-plugin support and scoped to `**/types.ts`, where the
public Props live; the Props of internal subcomponents such as
`FileTreeBodyProps` are not a public contract and stay out of scope.

Both checks were verified by breaking the code on purpose: a
`requestOptions` moved to the top reports an order violation, and a
required `onValueChange` reports that an event callback must be optional.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* refactor(ui): classify callbacks by type and drop the duplicated rule text

The rule classified a field's category by its name prefix (`on*`,
`render*`, `get*`) but checked "callbacks must be optional" only for
`on*`, so a required `renderItem` broke one rule and passed the other.
A name prefix cannot separate a switch from a callback anyway:
`disableEdit` and `onSelect` both read as words, and only the type tells
them apart.

Category is now decided by the declared type — a function type is a
callback — so `onSelect`, `renderItem` and `getRowAttributes` are
callbacks while `disableEdit` is a parameter. Both checks share the same
predicate. Existing code reports the same results as before, which
confirms the two approaches agreed on it; the type-based one also covers
the render callbacks and cannot misread a boolean switch.

With the rule enforcing the order, the AGENTS section repeating the two
dimensions, their combination and a sample interface added nothing a
reader could not get from the rule. It now states the order in one line
and names the rule. The note about keeping related fields adjacent
stays: that part is a judgement the rule cannot make.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): resolve aliased and method-signature callbacks

`isFunctionType` only recognised an inline function node, so an ordinary
callback type alias bypassed both checks. With `type Render = () => void`,
`renderItem: Render` produced no diagnostic while `renderItem: () => void`
correctly reported that a callback must be optional, and
`renderItem?: Render` placed before `disabled?: boolean` was accepted.
Method syntax (`renderItem(): void`) bypassed enforcement too, because
the member filter dropped `TSMethodSignature`.

A field's category now resolves the declared type: function and
constructor types, type aliases that point at them (including aliases of
aliases), parenthesised types, and callable members inside unions or
intersections. Method signatures count as callbacks. The alias table is
built from `TSTypeAliasDeclaration` in the same file, which is where the
public Props and their aliases live.

A cross-file alias still cannot be resolved from the syntax alone, so
AGENTS now says not to declare a callback in public Props through an
external type alias.

Verified against the three shapes from the report: a required
`renderItem: Render` and a required `renderItem(): void` both report that
a callback must be optional, and `renderItem?: Render` before
`disabled?: boolean` reports the order violation. Existing code reports
nothing new.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): resolve aliases after the file is read and skip accessors

Three follow-ups on the alias handling, each reproduced before fixing.

Aliases were collected during traversal while each interface was checked
immediately, so a type declared after its use was invisible:
`renderItem: Render` followed by `type Render = () => void` produced no
diagnostic. Interface checks now run at `Program:exit`, once the whole
file's aliases are known.

Treating every `TSMethodSignature` as a callback also rejected accessors.
A getter's value is a property, and TypeScript does not allow marking a
getter optional, so `get disabled(): boolean` could never satisfy the
rule. Accessors (`kind: 'get'` / `'set'`) are excluded; ordinary methods
still count.

Following an alias body dropped the type arguments supplied at the use
site: `type Maybe<T> = T | undefined` with `renderItem: Maybe<() => void>`
resolved to `T | undefined` and lost the function. Resolution now binds
the alias parameters to the arguments and substitutes them, so a generic
wrapper preserves the callable type.

Verified each repro, plus a setter, plus the ordering path with an
optional aliased callback. Existing code reports nothing new.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* refactor(ui): keep the Props rule to inline function types

Resolving every equivalent spelling of a callable type by hand — type
aliases, forward references, generic wrappers, accessors — kept growing
the rule without covering the code it actually checks. Every callback in
the existing public Props is an inline function type; the alias and
getter forms came from constructed examples, not from the codebase.

The rule is back to recognising a function or constructor type directly,
about half its previous size. AGENTS now states the constraint that
makes that sufficient: write callbacks in public Props as inline
function types, not aliases or wrappers. The unsupported forms are
explicitly out of scope rather than silently missed.

This only affects authoring ergonomics, not the correctness of any
shipped component. When TypeScript 7.1 exposes a compiler API, real type
resolution can replace the syntax-level check.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* docs(ui): drop the callback-writing constraint from AGENTS

The rule only recognises inline function types, but constraining how
callbacks are written to suit a check that affects authoring ergonomics
is not worth a rule. The unsupported forms simply go unchecked until the
rule can resolve types; a one-off scan when it can will catch anything
that slipped through.

The rule's own comment keeps a short note that aliases, generics and
accessors are not resolved yet.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>

* refactor(config): 迁移配置调用并移除旧 SDK 方法 (volcengine#7050)

* refactor(config): migrate callers off deprecated settings APIs

将 Studio 和 CLI 迁移到 configuration,并返回生效的 Agent Evolution 开关。
用户 settings 支持添加位置读写;旧 HTTP API 继续兼容,移除三种 SDK 的旧方法。

* test(config): consolidate configuration contract coverage

将开关继承和用户设置覆盖集中到已有契约测试,删除重复用例及其 Fake。
恢复无需改写的旧接口集成测试,使 PR 测试代码相对 main 净减少 34 行。

* fix(docs): include legacy add-location APIs in reference checks

将用户设置旧路由纳入公开 API 检查,并在中英文文档中分别列出 GET、PATCH、DELETE,消除配置迁移新增的文档检查错误。

* fix(api): allow users to manage their own settings

* fix(config): defer add-target write checks until resource use

配置读写只校验添加位置 URI 与归属,取消目录写权限查询。实际资源和技能添加继续执行写权限检查。改写现有契约测试并同步接口文档,修复组授权目录误报 403 和配置写入后响应失败。

* docs(config): remove redundant add-target permission explanation

* refactor(config): validate only submitted user settings

Keep settings reads and sparse merges free of input validation, and share runtime checks across configuration writes. Require home aliases for private add targets, including peer resource directories.

* Revert "fix(account-store): 防止 NAS 多副本 ENOENT 导致 User 覆盖 (volcengine#6998)" (volcengine#7111)

This reverts commit 828df79.

* fix: tree-sitter process() is a synchronous native call that can stall for… (volcengine#7059)

* tree-sitter process() is a synchronous native call that can stall for the
grammar download timeout. Running it on the SEMANTIC event-loop thread froze
all concurrent semantic tasks. Wrap extract_skeleton_result in asyncio.to_thread
so blocking parse/download work executes off the event loop.

* feat(parse): preload tree-sitter grammars in image and bundle proxy manifest

Production containers usually cannot reach GitHub, while the image build
network can. Avoid on-demand grammar downloads (which block on a 60s
timeout) by preloading all grammars at build time, and keep on-demand
downloads working for non-Docker users via an optional proxy manifest.

- Dockerfile: download_all() at build time with a completeness check that
  fails the image if any language is missing; copy the populated cache into
  the runtime image and pin OPENVIKING_TREE_SITTER_CACHE_DIR.
- process_engine: lazily point tree-sitter-language-pack at
  OPENVIKING_TREE_SITTER_CACHE_DIR before process(); without this the pack
  looks under <cache>/v<version>/libs and misses the preloaded files.
- aider_repomap: apply the same cache-dir configuration before the
  grep-ast tags-query path calls get_parser.
- Bundle parsers.json with bundle URLs rewritten through gh-proxy.com and
  ship it as package data; users opt in via
  TREE_SITTER_LANGUAGE_PACK_MANIFEST_URL. A cache miss still downloads on
  demand, so behavior for non-Docker users is unchanged.
- docs: document Docker preload, the proxy manifest env var, and offline
  prewarming.

* Fix/task cancellation (volcengine#7082)

* fix(task): settle cancellation and admission before ACK

* fix(task): preserve cancellation context for recovery

Retain the last stage and auth so recovered deliveries can cancel external Runtime work and finish cleanup after the Task is cancelled.

* refactor(ui): use prefixed BEM class names for component styles (volcengine#7112)

Replace the six CSS Modules files with plain stylesheets. Class names are
`ov-<block>` for the root, `ov-<block>__<element>` for parts, and `--` for
modifiers. Theme variables keep the `--ov-ui-` prefix.

Update the frontend guide and the FileTree and FilePreview docs with the
class name tables, and align AGENTS.md and the READMEs.

Co-authored-by: Claude Code <noreply@anthropic.com>

* fix(pathlock): use Redis time to prevent clock-skew takeovers (volcengine#6718)

* fix(pathlock): use Redis time to prevent clock-skew takeovers

* chore(pathlock): keep server-time fix focused on code and tests

* test(pathlock): benchmark Redis server-clock lease overhead

Add an opt-in A/B performance test and document local results to quantify server-time acquisition and renewal costs across batch sizes and concurrency levels.

* fix(pathlock): preserve live holders during failed Redis handoff

Use Redis time for atomic handoff rollback so client clock skew cannot remove live sibling locks. Add regressions for delayed adoption, expired sources, and concurrent renewals.

* feat(ui): settle the module props and drop the user-usage module (volcengine#7126)

* refactor(ui): remove the user-usage module

The current design has no usage page under the personal terminal: every
usage-related frame lives under the ROOT Key or Admin Key groups, and the
普通 user group contains none. An earlier review had concluded the
opposite, but that was against an older design; the current one does not
support it.

Removing it the way resource-import was removed: the directory, the
package and Rslib entries, the stylesheet aggregation, the root exports,
the docs pages in both locales, the sidebar entries, the demo and the
index rows.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* refactor(ui): inline the module placeholders

`modules/shared/` existed so four modules could share one placeholder
component and stylesheet. With one module gone and the remaining three
each about to grow their own view, the shared layer cost a directory and
an indirection without saving anything: each module now renders its own
container and owns its stylesheet.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* feat(ui): settle the file-browser props

Three decisions from the design review:

- The toolbar keeps search and refresh with the module, and the host adds
  its own entries through `toolbarActions`. `FileBrowserToolbarButton` is
  exported so those entries look like the module's own buttons.
- Per-row state — uploading progress, conflicts, retention settings — is
  the module's, so no prop carries it.
- The preview tabs follow from the resource, so the module owns them too.

Dividers between host entries come from a CSS adjacent-sibling rule
rather than counting nodes: `toolbarActions` is a node, so it may be one
element, a fragment or a conditional, and counting would miss cases.

The module covers only the tree and the preview; the command panel
belongs to `console`.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* feat(ui): settle the task-center props

The commercial console keeps two task lists with different data sources:
data-source import reads scheduled watches, knowledge compile reads
compile targets. Their schedule columns mean different things — an
interval in minutes versus a daily or weekly clock time — so one shared
set of columns does not fit.

The props now carry a tab and a scope, a `columns` override per tab, and
callbacks for the two things a view cannot do itself: open a resource and
write a schedule change. Filtering, the detail drawer and the schedule
edit control stay inside the module. Whether "others' tasks" appears
depends on the current identity, which the module reads from `/health`,
so the host passes no permission switch.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* refactor(ui): drop `onResourceChange` and finish the module bookkeeping

The callback reported "a task or resource change", but the console cannot
observe one: a compile or memory submission finishes after the request
returns, so the component could only fire when the task was created, when
no resource had changed yet. It also carried just a URI, so a host could
not tell a create from an update, and it overlapped `onOpenUri`. Task
progress belongs to the task data source, and the module docs now say so.

The rest is bookkeeping left from removing `user-usage`: the module count
in both READMEs, the docs index rows, the demo, the sidebar entries, the
package and Rslib entries and the stylesheet aggregation.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): ship the module styles, restore placeholder copy and split the schedule callbacks

Five review findings.

The toolbar button imported a CSS Module, but the JS build runs with
`emitCss: false`, so the hashed classes reached the bundle with no rules
behind them: `modules/file-browser/style.css` shipped empty and the
whole-package stylesheet had no `toolbarButton` at all. The styles are
plain CSS with `ov-` BEM class names now, the same convention the
components follow, and both the module stylesheet and the package one
carry them.

The file-browser docs said `FileBrowserToolbarButton` was on the root
entry, but it is only on the subpath — the root entry keeps to component
bodies and their main Props. The docs say so now.

Inlining the placeholders dropped the visible "Functionality is not
available yet" copy, so a host that wired a module into its layout got no
hint that the area was still a placeholder, which `modules/AGENTS.md`
requires to be visible. Each module renders it again, with its own
stylesheet.

`onScheduleChange` collapsed two different schedules into one
`intervalMinutes`. A compile target schedules on a daily or weekly clock
time, which the native `update_schedule` expresses as
`{ frequency, hour, minute, weekday? }` and no minute count can carry.
The callback is now two: `onSaveScheduleInterval` for import tasks and
`onSaveCompileSchedule` for compile targets, the latter taking the native
shape so a host can forward it as-is.

Both return a Promise, which closes the loop the docs described but the
contract did not provide: resolve after a successful write and the module
reloads, reject and it keeps the edit and shows `labels.saveFailed`.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ui): make the placeholder copy replaceable

Restoring the visible placeholder text hard-coded it, so a host that
passed a full set of Chinese labels still got the English sentence under
the title. The shared `ModulePlaceholder` it replaced had accepted
`labels.description`, and `frontend/AGENTS.md` requires public components
to offer replaceable default copy.

Each module's labels gain an optional `description`, defaulting to the
current English sentence. Verified with `renderToStaticMarkup`: omitting
it renders the default, passing it renders the override.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>

* fix(parse): preserve body after empty ATX headings (volcengine#7117)

* fix(parse): preserve body after empty ATX headings

* test(parse): consolidate empty-heading regression coverage

---------

Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>

* fix(sdk/go): accept inline skill Markdown (volcengine#7103)

Co-authored-by: ydflow <314143294+ydflow@users.noreply.github.com>

* fix(queuefs): 错误诊断只保留有界元数据

* fix(config): 兼容旧添加位置配置,避免升级后启动失败 (volcengine#7140)

将旧 resources 和 skills 添加位置配置转换为家目录别名,保留请求目标的现有校验规则。

Co-authored-by: qin-ptr <222410531+qin-ptr@users.noreply.github.com>
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>

* fix(embedding): 为图片旧投递补齐有界的文本语义输入

* test: 隔离配置夹具并等待文件操作前置任务完成

* ci: 服务端检查与发布默认只运行 Linux amd64

* fix(session): back off predecessor-blocked commit retries

(cherry picked from commit c4c6ce3)

* ci: 验证上游兼容并打包 Linux amd64 离线运行制品

* fix(ci): 修正路径锁测试命令与 MCP 路由文档索引

* ci: 固定运行依赖闭包并记录 Linux 制品校验信息

* ci: Hermes 兼容检查也限定为 Linux amd64

* test: 对齐取消终态时序并隔离策略日志捕获

* ci: 保留指定离线制品目录的完整内容

* ci: 提供合成回归配置并修正 fork 缓存保存边界

---------

Co-authored-by: yufeng <119399272+yufeng201@users.noreply.github.com>
Co-authored-by: LaamGinghong <33472924+LaamGinghong@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Caucher Wang <caucherw@gmail.com>
Co-authored-by: zeyu wang <wangzeyu.bd@bytedance.com>
Co-authored-by: Lusen Dong <cicomaple@gmail.com>
Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
Co-authored-by: nocvalight <hitxiaojian@gmail.com>
Co-authored-by: chenxiaobin-monkey <chenxiaobin@bytedance.com>
Co-authored-by: runyunzhou <164479727+runyunzhou@users.noreply.github.com>
Co-authored-by: zhanglistar <zhanglinuxstar@gmail.com>
Co-authored-by: LI <2484593937@qq.com>
Co-authored-by: ydflow <389051175@qq.com>
Co-authored-by: ydflow <314143294+ydflow@users.noreply.github.com>
Co-authored-by: trim <trim@trimdeMac-mini.local>
Co-authored-by: bot-of-qin-ctx <qin_haojie@qq.com>
Co-authored-by: qin-ptr <222410531+qin-ptr@users.noreply.github.com>
Co-authored-by: 97Three <115765389+97Three@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-plugins Agent harness and plugin integrations

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants