Commit Graph
405 Commits
Author SHA1 Message Date
b7aa01d227 feat(plugins): add OpenViking memory integration for TRAE CLI (#4026)
* feat: add OpenViking memory integration for TRAE CLI

Add TRAE CLI lifecycle hooks and MCP proxy support, wire the integration into the shared installer, and cover idempotent install and uninstall behavior.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

* fix(trae-cli): cover archive installs and hook payload aliases

* fix: keep TRAE CLI installation explicit

Leave TRAE Desktop detection unchanged and avoid auto-selecting TRAE CLI. TRAE CLI remains available through an explicit harness selection or --harness trae-cli.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

* fix(trae-cli): auto-select installed CLI commands

Detect traecli and traex only when they are available in PATH, then mark and select the TRAE CLI harness automatically.

---------

Co-authored-by: “bianhaonan” <“bianhaonan@bytedance.com”>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-17 14:59:43 +08:00
Zonas ZhouandClaude 6e77291265 feat(pdf): refactor MinerU parsing to the official file_parse API (#3953)
* feat(pdf): refactor MinerU parsing to the official file_parse API

* feat(pdf): remove mineru_api_key from configuration and examples

* feat(pdf): preflight MinerU /health during service initialization

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-17 13:48:49 +08:00
d7ab37c76e feat(plugins): add OpenViking memory for DSH (#3993)
* feat(plugins): add OpenViking memory for DSH

* feat(dsh-plugin): graft review items — source whitelist, dsh constructors, live recall gate

Applies the #task-65 review verdict's graft list from #3991 onto the
#3993 base:

- capture whitelist: drop every plugin-sourced user message (any plugin,
  not just this one) so injected context never mirrors into memory as
  human input; recall queries keep their existing scope
- pre-step: register with prepend so this listener sees the final
  claimed batch, and short-circuit on signal.aborted around each await
- adopt dsh constructors behind exact-pinned peers (devDependencies
  mirror the pins): tools flow through @deepseek-ai/dsh-tools defineTool
  (declarative parameters, output schema/render, presentCall per tool),
  plugin messages through @deepseek-ai/dsh-llm createUserMessage; a
  registration-shape test makes a future rc pin bump fail CI instead of
  a user install when the ToolDefinition contract moves
- live-recall.test.mjs: opt-in (OPENVIKING_E2E=1) real-backend gate —
  store a sentinel via session commit, wait for extraction, assert
  recall returns it; passed against a live OpenViking server in 124s
  (note: commit with the default keep_recent_count=10 extracts nothing
  from short sessions — the test pins keepRecentCount 0)
- README: why injection is pre-step user messages, not the system
  prompt (complete:true personas silently drop prompt assembly), plus
  peer-pin rationale and a Testing section

Tests: 15 pass + 1 env-gated (node --test), requires npm ci for the
pinned dsh devDependencies — CI step lands separately (workflow scope).

* ci(pr): install DSH plugin deps before running memory plugin tests

* fix(dsh-plugin): finalize neutral plugin integration

Remove product-specific identifiers from the DSH plugin surface and harden its lifecycle, HTTP contracts, archive tooling, and ordered offline delivery.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

---------

Co-authored-by: Zayn Jarvis <zaynjarvis@gmail.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-14 18:05:22 +08:00
t0sakiandZayn Jarvis 8abd61fcb6 feat(plugins): add Agent Plugins 1.0 portable package (#3998)
* feat(plugins): add Agent Plugins 1.0 portable package

Add agent-plugins/, an Agent Plugins 1.0 conformant package
(https://agent-plugins.org/specification) that any conforming client can
load: plugin.json manifest, an openviking-memory skill teaching the
hook-less recall + persist loop, and an mcp.json stdio entry running a
stdio -> streamable-HTTP proxy that resolves credentials from
OPENVIKING_* env -> ~/.openviking/ovcli.conf -> ~/.openviking/ov.conf,
same as the ov CLI.

servers/shared/* are generated copies of memory-plugin-shared/lib, wired
into sync.mjs / sync.test.mjs TARGETS so they cannot drift silently.
config.mjs / debug-log.mjs / mcp-proxy.mjs are adapted from
claude-code-memory-plugin with the hook-tuning knobs dropped.
plugin.test.mjs validates spec conformance (schema URLs and matching
spec versions, name rules, closed manifest root, semver, skill
frontmatter, referenced files staying inside the plugin root, node
--check on all .mjs) and runs in CI via pr.yml.

The skill treats tree/write/edit as optional, since they only exist on
servers that carry #3936.

Docs: docs/{en,zh}/agent-integrations/15-agent-plugins.md, registered in
the VitePress sidebar and the integration overview tables, plus a link
from the three root READMEs. The docs recommend the per-client plugin
whenever the harness has hooks, with the shared installer one-liner.

Based on #3994 by @ZaynJarvis.

Co-Authored-By: Zayn Jarvis <zaynjarvis@gmail.com>

* docs(agent-plugins): pluralize README title

---------

Co-authored-by: Zayn Jarvis <zaynjarvis@gmail.com>
2026-08-14 14:33:54 +08:00
t0saki 33043cb1b8 feat(plugins): expose session commit trace IDs (#3977)
Preserve result.trace_id across plugin HTTP wrappers, include it in commit success and failure logs, and surface it in user-visible commit confirmations where supported.
2026-08-13 23:29:41 +08:00
chenjwandqin-ctx ed1bd4b897 refactor(memory): 统一 V3 提取并提升会话提交与评测稳定性 (#3346)
* fix(memory): disable unsupported tool and skill extraction

* refactor(memory): retire SessionCompressorV2

* docs: design service import cycle fix

* fix(import): break QueueFS service import cycle

* update

* docs: design memory overview lock coverage fix

* fix(memory): cover overview files in update leases

* docs: design session commit default concurrency 50

* perf(queue): raise session commit concurrency to 50

* docs: revise session commit concurrency design

* docs: plan session commit default 8

* perf(queue): default session commit concurrency to 8

* fix(bot): disable cron during eval chat

* docs: design memory link lock stabilization

* docs: plan memory link lock stabilization

* fix(memory): stabilize link update lock coverage

* docs: cover remapped post-group link locks

* docs: design plain-content patch validation

* docs: design first failing patch diagnostics

* fix: report actual failing patch block

* fix(memory): remap replacement links before locking

* fix(bot): include trusted identity in health probe

* test: consolidate memory contract coverage

---------

Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
2026-08-13 21:48:49 +08:00
luo jiyin ddee56e0bc fix: make fake Codex launcher cross-platform (#3962) 2026-08-13 14:18:33 +08:00
agent 2d5aa9cd3d fix(plugins): ship Experience skill in plugin packages (#3946)
* fix(plugins): ship experience memory skill

* fix(openclaw): drop unpublished selector aliases
2026-08-12 11:18:22 +08:00
Zayn JarvisandClaude Opus 5 4920297ccc feat(mcp): add write/edit/tree tools for viking:// as agent working directory (#3936)
* fix(storage): keep non-memory appends free of memory trailers

ContentWriteCoordinator._write_in_place routed every append through
MemoryFileUtils, which strips the existing trailing newline and appends
a reserved MEMORY_FIELDS metadata trailer, even for resource/skill files
where MEMORY_FIELDS is not a reserved format (see content_visibility).
Append to non-memory files now concatenates raw content instead, matching
POSIX append semantics and the documented visibility rules.

* feat(mcp): add write tool with exact-string edit support

Agents could not use viking:// as a working directory through MCP: no
tool could create or update file content. Add a write tool covering full
writes (mode=replace as create-or-overwrite, append, strict create) and
targeted edits (a list of {old_string, new_string, replace_all}
exact-string replacements applied in order, all-or-nothing), following
the Write/Edit conventions of common agent harnesses.

Edits read via read_visible and write back through the content-write
coordinator, so memory metadata trailers are preserved and semantic /
vector re-indexing triggers as with any other write. Parent directories
are created automatically by the storage layer. Descriptions spell out
writable scopes (resources, user memories/resources, agent) and the
wait=true knob for read-after-write search consistency.

Also update the stale tool-count comment in app.py and the MCP tool
tables in the en/zh guides (13 -> 14 tools).

* feat(mcp): add tree tool, split targeted edits into edit tool

tree renders the recursive directory tree under a viking:// URI,
indented by depth with file sizes, for whole-layout orientation;
level_limit/node_limit bound the output and include_abstract adds
per-file summaries. Missing directories report "(nothing under ...)"
instead of an error, matching the read tool's convention.

edit(uri, old_string, new_string, replace_all) takes over the targeted
exact-string replacement that previously lived in write's edits array,
matching the classic Edit tool signature harnesses already train on.
write now only does full-content writes (content + mode), removing the
mutually-exclusive content/edits schema ambiguity. Edits still read via
read_visible and write back through the content-write coordinator, so
memory metadata trailers are preserved and re-indexing triggers as with
any other write.

* test(plugin): update canonical MCP tool list for tree/write/edit

The marketplace test pins the server-registered MCP tool list; add the
new tree, write, and edit tools to fix plugin-tests CI.

* feat(storage): support plain files at the user scope root

Agents treating viking:// as a working directory naturally drop files
like viking://user/zeus-persona.md at the user root, but the write
coordinator only accepted the memories/ and resources/ subtrees.

Two changes make that work:

- Namespace shorthand: a dotted first segment under viking://user/ is a
  file name, not a user id (canonical user ids are dot-free by
  convention), so viking://user/zeus-persona.md now canonicalizes to
  viking://user/<current-user>/zeus-persona.md, matching how the
  reserved memories/resources/skills segments already shorthand.
  Dot-free segments still address an explicit user, and an exact match
  with the current user id still wins.

- Coordinator: plain files directly under the user root (or in
  non-managed subdirectories) anchor their semantic refresh at the
  parent directory. The managed subtrees skills/, peers/, privacy/ and
  sessions/ remain read-only with an actionable error message.

* fix(namespace): narrow user-root shorthand to text-file extensions

Review on #3936 (codex /review-pr) flagged that treating any dotted
segment as a user-root file shorthand would silently re-route canonical
URIs for valid dotted user ids (e.g. alice.smith) into the current
user space. Shorthand now triggers only when the first segment ends
in a common text-file extension; dotted or email-style user ids keep
resolving as canonical user ids. Adds regression tests pinning both
behaviors.

* fix(mcp): resolve user URIs against current user

* test(mcp): pin plain-file writes directly at the user root

The user-root shorthand exists so an agent can drop viking://user/persona.md
into its workspace, but every new test went through an intermediate directory
(viking://user/project/zeus-persona.md), leaving the no-directory shape — the
one that anchors the write coordinator's refresh at the user root itself —
uncovered. Add the missing case.

Also correct the write tool docstring: the create-extension allowlist applies
to any newly created file, including one created by mode="replace" falling
back to create, not only to an explicit mode="create".

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 11:11:27 +08:00
agent 00f3738edb feat(usage): emit resource-scoped experience usage records (#3921)
* feat(usage): expand experience tracking and log schema

* fix(usage): preserve experience count event names

* refactor(agent-evolution): use generic OpenViking tools

* fix(usage): capture generic OpenViking tool events

* feat(skills): guide cross-agent experience retrieval

* fix(usage): address generic tool migration review
2026-08-11 22:20:18 +08:00
t0saki 7e26fab61c fix(memory-plugins): report tool output verbatim, let the server externalize (#3933)
Coding-agent plugins capped a tool part's `tool_output` at 2000 chars before
POSTing it to `/api/v1/sessions/{id}/messages`. That cap sits below the server's
own externalization threshold (`tool_output_externalization.threshold_chars`,
default 20000), so output in the 2k-20k band was destroyed for no reason and
anything larger never reached `ToolResultStore` - leaving `tool_output_ref`
permanently empty and the `/tool-results` read-back path unusable.

Raise the `captureToolMaxChars` default to 1000000 (a guard against pathological
payloads, not a truncation policy) and lift the opencode/pi clamps that would
otherwise pin it back to 20000. claude-code had no knob at all - two hardcoded
`TOOL_OUTPUT_PART_MAX_CHARS = 2000` constants - so it gains the same config
entry and both capture scripts now read it.

Also stop pi from sending tool output twice: for a tool-only payload the
rawText-derived text part re-rendered the same output the tool part carries.
2026-08-11 19:17:54 +08:00
zihengli cd55ec89a6 feat(assets): support fixed Git commits, explicit targets, and private repository auth (#3703)
* feat/openviking_assets_support_git_commit_id

* feat/openviking_assets_support_to

* feat/private_git_support_watch

* fix: doc_and_ut

* fix: doc_and_ut

* fix: adapt git token url
2026-08-11 14:07:21 +08:00
Qin Haojieandsponge225 b877ababa5 perf(queue): 流式调度语义向量化任务 (#3636)
* perf(queue): stream semantic vectorization tasks

* fix(queue): isolate semantic work context

* feat(config): make parse concurrency configurable

* test(queue): update semantic vectorization fakes

* fix(queue): correct semantic vectorization conflict resolution

---------

Co-authored-by: sponge225 <1670519171@qq.com>
2026-08-10 21:24:11 +08:00
Qin Haojie 9d5cbae70e fix(examples): align quick start with server mode (#3923) 2026-08-10 20:59:35 +08:00
Qin Haojie 7abd6ab249 refactor(client): remove Python embedded mode (#3712)
* refactor(client): remove Python embedded mode

Consolidate Python consumers on the HTTP SDK while keeping shared server and storage capabilities unchanged.

* refactor(client): remove obsolete embedded leftovers
2026-08-10 18:00:00 +08:00
Kuang Mi c25a7219db fix(opencode-plugin): serialize saveState to prevent ENOENT rename race (#3885) 2026-08-10 11:19:40 +08:00
Xinmin Zeng b1ec59bda6 fix(pi): resolve config path from module URL (#3655)
Fixes #3648
2026-08-07 20:04:33 +08:00
ValorandValor fdb4b571ca feat(opencode): add hook-only installation mode (#3734)
* feat(opencode): add hook-only installation mode

* test(opencode): cover hook-only plugin configuration

---------

Co-authored-by: Valor <210239105+zrh805@users.noreply.github.com>
2026-08-07 17:11:45 +08:00
baojun-zhang bd5cce09c7 feat(pathlock): adjust pathlock config (#3854) 2026-08-07 13:21:30 +08:00
Zayn JarvisandClaude Fable 5 03bd469417 fix(openclaw-plugin): drop SecretRef exec resolver from packaged plugin (#3849)
Marketplace install scanners (ArkClaw) block plugins whose shipped code
contains child_process. Keep env/file SecretRef sources; configuring
{source:"exec"} now fails with a clear error pointing at env/file.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 18:50:38 +08:00
Zayn JarvisandClaude Fable 5 1be7b83640 fix(openclaw-plugin): narrow ParsedMemoryOpenVikingConfig.apiKey to string (#3832)
parse() resolves SecretRef values to plain strings before returning, but the
parsed type still inherited string | OpenVikingSecretRef from the input type,
breaking tsc -p tsconfig.build.json (release prepack) since #3618.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 16:10:33 +08:00
agent 61c42e3bb0 feat(openclaw): add experience memory tools (#3827) 2026-08-06 15:52:31 +08:00
t0sakiandTRAE CLI fb82168659 fix(claude-plugin): count recalled memory URIs (#3821)
Derive the statusline recall count from unique viking:// references in the injected context and bump the plugin to 0.4.4.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-06 14:55:25 +08:00
t0sakiandTRAE CLI 8e98a3c744 fix(memory-plugin): preserve commit payload on retry (#3822)
Keep retention options when retryable Claude session commits are queued and replayed. Add coverage for retryable storage conflicts.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-06 14:53:58 +08:00
t0sakiandTRAE CLI 0ab48f96fc fix(session): recover partial capture sessions (#3820)
Treat messages.jsonl as the materialization boundary for session-aware recall,
repair partial session roots during the existing authoritative append path,
and preserve Claude capture cursors when writes never reach the server.
Also replay explicitly retryable storage conflicts across memory plugins.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-06 14:48:42 +08:00
jiakun-lu b8738e05f1 feat(server): make HTTP keep-alive idle timeout configurable (#3743) 2026-08-06 14:11:46 +08:00
t0saki 674f5e6039 fix(retrieval): honor context tier ceilings and stop cooling unserved recalls (#3746)
* fix(retrieval): honor tier ceilings and stop cooling unserved recalls

Follow-up to #3534, from its post-merge review round.

- The abstract-to-overview substitute now applies only to categories whose
  stored abstract is the whole file body. A resource or skill whose abstract is
  missing (`processing_mode=vectors_only`) or over the per-entry cap read its
  body and returned an overview instead, which for a short file is the body
  almost verbatim — crossing the opt-in deepening boundary those categories are
  documented to have, and doing it even under an explicit `detail="abstract"`.
  They now degrade to a bare URI and their body is never read.
- A digest reporting `no_relevant` blanks `rendered`, so the client injects
  nothing, yet those URIs still entered the dedup ledger and were cooled for
  `dedup_turns` turns. That contradicted the ledger's own bare-URI grace rule
  and held memories back from the later turn they were relevant to.
- Flat retrieval reaches built-in memory types outside the four named ones
  (`cases`, `patterns`, `tools`, `trajectories`, skill-usage memories) and
  reported them as an undeclared `memories` category that no tier or penalty
  table covered, so other-peer hits skipped the score penalty and callers could
  not pin their tier. The catch-all is now a declared category with both; it
  stays out of `quotas`, whose buckets it would overlap. Skill-usage memories
  also stop being misread as the `skills` category.
- ZCode, OpenCode and pi own an OV session id but did not forward it, so their
  recalls silently ran without query expansion or cross-turn dedup.
- The context-request deadline covered only the server's 30s rewrite fuse, but
  the pipeline is serial: expansion, retrieval and budgeting all precede it.
  45s covers both fuses and the work between them.
- `plugin` config scope and the `/recall` successor example now match what the
  code actually does.

* fix(retrieval): make the context deadline and expansion opt-out reachable

Forwarding a session id turns on server-side query expansion, an LLM call with
its own 5s fuse, but neither the deadline that was supposed to cover it nor the
switch that turns it off reached the two harnesses this PR newly enabled it for.

- `contextRequestTimeoutMs()` now derives the deadline from the request body
  rather than from `cfg` plus a rewrite flag. The body is what states which
  server stages will run: a session takes the expansion fuse, `rewrite` takes
  the digest fuse, and a bare retrieval takes neither and keeps the caller's own
  budget. Reading `cfg` alone could not tell those apart.
- OpenCode pinned `timeoutMs: 5000` after spreading the helper's options and pi
  ignored them entirely, so the helper's deadline was dead code in both. Their
  own budgets are now defaults rather than ceilings. OpenCode's 5s in particular
  was shorter than the expansion fuse it had just enabled, so a legal request
  would have been aborted client-side and dropped back to the path with neither
  dedup nor expansion.
- OpenCode and pi read `OPENVIKING_RECALL_QUERY_EXPANSION` (and
  `recallQueryExpansion` in their own config files) and set the `configured`
  flag the shared body builder requires, so the documented opt-out exists where
  the cost was introduced.
- The integration overview no longer implies every harness reads the same
  environment knobs, and describes the deadline as per-stage rather than
  rewrite-only.
2026-08-05 23:52:15 +08:00
2cc96e393e feat(retrieval): assemble auto-recall context server-side via /search mode="context" (#3534)
* feat(retrieval): assemble auto-recall context server-side via /search mode="context"

Auto-recall assembly lived in every harness plugin: each one searched per
memory type, read hits back one by one, and stitched a context block with its
own budget and degradation rules. The implementations drifted, and the shared
weaknesses showed up in production injections — roughly half of the entries
degraded to a bare URI plus a score, character budgets distorted up to 6x on
CJK text, and adjacent turns re-injected the same memories.

This moves assembly into the server as one round trip. /find stays an unchanged
stateless primitive. /search gains mode="context" (mode="list" is the default
and byte-identical to before), and /recall becomes a thin preset over the same
kernel with its v1 field names folded onto the new contract.

New assembly kernel under openviking/retrieve/context_assembler/:

- Token budgeting with a CJK-aware estimate replaces the character budget.
- detail="auto" fills breadth-first then deepens: every candidate gets a
  readable floor, then overview, then full for high-scoring entries. An
  oversized tier falls back to the previous one instead of being truncated,
  bounded by max_tokens / candidates * 2 per entry.
- Overview extraction dispatches by source: memory files use their leading
  Summary section, code files reuse code_outline signatures, long documents use
  a heading tree plus first paragraph.
- Directory hits start at overview and read their .overview.md sidecar, since
  directories carry no stored abstract; their full tier stays capped at
  overview. v1 injected the sidecar as if it were a whole file.
- Quotas generalize beyond memory types to resources and skills, with purpose
  presets supplying ratios when quotas are absent.
- dedup_turns keeps a per-session ledger at {session_uri}/.recall_log.json so
  every harness inherits cross-turn dedup; exclude_uris remains as the
  stateless fallback.
- Rendering flattens to one <memory uri=... type=... score=... detail=...>
  element per entry. Every tier carries its URI, so the model can always drill
  down through the MCP read tool.
- Query expansion and digest rewriting are opt-in and fail closed: both have
  timeout fuses, and a failed rewrite still returns the unrewritten block.
  Retrieval failures are counted into stats rather than silently yielding an
  empty block.

Plugins now send one context request, falling back to /recall and then to raw
find on older deployments, and cache that outcome so only the first turn pays
for the probe. The tri-state recallRewrite knob chooses between local host-CLI
compression and the server digest, and client-side settings move to a plugin
section in ovcli.conf.

* refactor(retrieval): give context tiers a per-category default

The tier ladder assumed `abstract` is a cheap summary. For memory files it
is not: the memory writer stores the whole stripped body in that scalar
because it doubles as the embedding text, so `abstract` costs the same as
`full` and the ladder runs `uri < overview < abstract = full`. Two of the
model's properties fell out of that: exempting `abstract` from the per-entry
cap let a single entry eat several times the budget, and `detail` — which
only ever set a ceiling — collapsed to two distinguishable behaviours across
its four values, since `auto` already allowed `full` for memory.

Tiers now come from a per-category constant table that treats the storage
shape as a given: `events` starts at overview (the one memory type whose
`# Summary` extraction is a real compression) and may deepen to full on
leftover budget; every other category is served at `abstract`, which for
memory already is the complete file at zero read cost and for resources and
skills is the generated 256-char summary. The table carries the note to move
`events` back to `abstract` once the writer stores a separate summary scalar.

Falling out of that: prefetch now reads only the candidates whose planned
tier needs a body rather than every candidate, `detail` becomes a real pin
(start and ceiling) and additionally accepts a per-category map, and
`full_score_threshold` is gone — leftover budget is spent in score order
instead of behind an absolute threshold the observed score band cannot
support. `auto` is still accepted on the wire as a synonym for "unset".

Assembly fixes found alongside:

- Removing the abstract cap exemption would turn an oversized abstract into
  a bare URI, so it now falls back to overview first — for memory that is a
  cheaper substitute, not a step up.
- Rewrite timeouts were reported as failures on Python 3.10, where
  `asyncio.TimeoutError` is a separate class from the builtin.
- `stats.rewrite_usage` read `token_tracker` off `VLMConfig`, which has no
  such attribute; usage was structurally always null. It now reads the model
  instance's tracker and reports only when the call count moved by exactly
  one, since that tracker is shared.
- A single malformed ledger record made every deduped recall in that session
  fail, and the file was never rewritten, so it could not heal. Records are
  now coerced on read and dropped on the next write, along with records left
  ahead of the clock by an archive rotation.
- Entries served as a bare URI no longer enter the dedup cooldown: they lost
  to budget pressure, not to the reader having already seen them.
- The render envelope only neutralised a literal `</memory>`, so a body could
  forge a sibling entry with its own uri, type and score.
- Flat-mode gathering re-derived the category from the URI, reading
  `viking://resources/backup/memories/events/log.md` as an event.
- Cooled and excluded URIs are compensated with extra rows, so a fully cooled
  bucket falls through to the next-best hits instead of coming back empty.
- `/recall` quotas overlay the v1 bucket defaults again; `{"events": 5}` had
  started dropping the other three buckets.
- The MCP `recall` signature sent its own defaults as if the caller had, which
  resolved a different profile than `POST /recall`; an unknown `detail` value
  raised `KeyError` through the whole call instead of degrading.

* feat(codex): inject profile context on session start

Reuse the shared profile builder for startup, clear, and resume hooks while preserving archive injection and orphan-session status output.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

* fix(retrieval): raise rewrite timeout default to 30s

* docs(agents): document low-latency recall settings

* fix(codex): prefer luna as recall compressor fallback

* refactor(plugins): unify recall compression setting

* feat(plugins): enable recall compression by default

* docs(agents): use absolute links in image docs

* fix(retrieval): address context assembly review feedback

Co-authored-by: TRAE CLI <noreply@bytedance.com>

* test: trim redundant context assembly coverage

* fix(retrieval): address second-round context assembly review

- Drop the backticked `/search` from the deprecated-recall row in both API
  overviews. The reference checker scans the whole row after the method cell
  for backticked paths, so it read the description as a route named
  `POST /search` and Build Docs failed on an unknown, undocumented route.
- Accept ovcli.conf's full field set in both Python readers. The file's schema
  belongs to the Rust CLI, which writes `root_api_key`, `output`,
  `echo_command`, `show_progress` and `verbose` and ignores unknown keys; the
  two Python readers had drifted into stricter subsets, so the shipped example
  already failed to load in both. Adding the new `plugin` section to a working
  ovcli.conf would have broken `ov doctor` and every SDK client the same way.
- Return 400 from `mode="context"` for a request `mode="list"` also rejects.
  Retrieval validates query and image_url before searching, and the gather
  fuse swallowed that rejection along with genuine scope failures, so a body
  of `{"mode":"context"}` came back 200 with an empty block instead of the
  documented parameter error. Runtime failures still degrade into
  `stats.retrieval_errors`.
- Let a context request that asks for a server-side digest outlast the
  server's rewrite fuse. The plugin's ordinary 15s request timeout is shorter
  than the 30s fuse, so a rewrite that finished inside its own budget was
  aborted client-side, discarding the whole response — including the
  uncompressed block the server returns when a rewrite fails — and falling
  back to `/recall`. The deadline is only extended when the body actually
  requests a rewrite, and `OPENVIKING_RECALL_CONTEXT_TIMEOUT_MS` /
  `plugin.recallContextTimeoutMs` pins it.

* chore(plugins): sync shared modules into the zcode snapshot

* fix(retrieval): align context quotas and plugin defaults

Restore cross-domain coding recall, reuse authoritative actor resource
scopes, and make bucket quotas the sole width control in purpose mode.
Keep plugin defaults server-owned while preserving explicit legacy limit
settings through quota conversion.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

* fix(retrieval): preserve recall compatibility

Restore the deprecated recall threshold default, distinguish successful empty rewrites from compressor failures, and document legacy quota floors across coding-agent plugins.

Co-authored-by: TRAE CLI <noreply@bytedance.com>

---------

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
2026-08-05 12:31:21 +08:00
t0sakiandTRAE CLI f08293411d fix(zcode): make memory capture reliable (#3728)
Use ZCode rollout logs as the authoritative incremental source, advance capture state only for the acknowledged prefix, and persist host turn identity with the OpenViking turn_id contract.

Detach Stop writes, package ZCode in the TOS marketplace artifact, add end-to-end regressions, and move the integration docs under community plugins.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-04 14:33:54 +08:00
Kchenandchenpengfei c7ee8e753a feat(queue): make ExternalParse worker concurrency configurable (#3710)
* feat(config): make external parse concurrency configurable

* refactor(config): move external parse concurrency to queue workers

---------

Co-authored-by: chenpengfei <chenpengfei@bytedance.com>
2026-08-04 12:10:01 +08:00
阿舟的AI小站(超级个体)andwoshiguanxiaoliang 2c374e79d9 feat(integrations): add ZCode memory plugin (#3678)
* feat(integrations): add ZCode memory plugin

Add examples/zcode-memory-plugin — a thin ZCode lifecycle adapter that reuses
the shared memory-plugin-shared runtime for recall, capture, commit, and MCP
proxy. No memory logic is duplicated.

Key design decisions (see docs/design/zcode-memory-plugin-design.md):
- Vendor shared runtime into scripts/shared/ via sync.mjs (self-contained plugin)
- 4 hook events only (SessionStart, UserPromptSubmit, PreToolUse, Stop) —
  ZCode does not support PreCompact/SessionEnd/SubagentStart/SubagentStop
- Output schema: ZCode-canonical keys only (no Claude-Code 'decision: approve')
- Config-driven install: hooks + MCP merged into ~/.zcode/cli/config.json
- install.sh wiring: detection, TUI, validation, install, uninstall

Verified locally:
- 22/22 node:test cases pass (turns parser + hook output schema)
- sync.test.mjs passes
- install → uninstall cycle: hooks/MCP correctly written and cleaned
- URI guard denies viking:// paths with MCP redirect
- Capture writes to OV session with zc- prefix

Closes #3127
Related: #3442, #3544

* chore: remove non-essential files from PR, add .scratch to .gitignore

- Remove .scratch/ working notes (local ticket files, not codebase artifacts)
- Remove package.json and .gitignore from plugin dir (TRAE/Cursor don't have them)
- Add .scratch/ to root .gitignore

* fix(zcode): use verified ZCode field names + rollout fallback for capture

- Update zcode-turns.mjs to probe responseText/responsePreview (verified
  from ZCode reverse-engineering in #3127 by @quinn-zenith) instead of
  the TRAE-inferred last_assistant_message
- Add rollout file fallback: when stdin payload lacks user content (the
  known ZCode limitation), read ~/.zcode/cli/rollout/model-io-sess-*.jsonl
  to extract the last user+assistant pair from request.messages+response
- Fix concurrent session isolation: normalize sessionId→session_id in
  zcode-hook.mjs before resolveNativeSessionId to prevent cwd-fallback
  collision when two ZCode windows run in the same directory
- Add 2 new test cases for rollout fallback (14 turns tests total, 24 total)
- All 24 tests pass

* fix(zcode): address maintainer review blockers (config safety, MCP ownership, turnId)

Addresses 3 blockers from @huangruiteng's review (CHANGES_REQUESTED):

1. Config safety: distinguish ENOENT from parse errors — malformed
   config.json now aborts instead of overwriting. Use backup+tmp+rename
   for atomic writes.

2. MCP ownership: only replace/delete mcp.servers.openviking entries
   tagged as openviking-memory. User-managed entries with the same name
   are preserved on install and untouched on uninstall.

3. TurnId-based dedup: rollout entries carry monotonic turnId — now used
   as the primary dedup key (capturedTurnIds set) instead of stableHash.
   extractUnseenRolloutTurns scans ALL unseen entries since lastTurnId,
   not just the last row — recovers missed turns after hook failure.
   Fail-closed when no turns are found.

Also updates DESIGN.md to reflect verified field names (responseText/
responsePreview) and the turnId contract.

27/27 tests pass (was 24). Added 3 new rollout tests: incremental
capture with lastTurnId, multi-entry scan, turnId propagation.

* docs(zcode): update stale field name references in design spec

Update test case descriptions to match verified field names
(responseText/responsePreview instead of last_assistant_message)
and add rollout fallback + turnId test coverage descriptions.

* fix(zcode): dedup key includes role + first-capture returns all turns

Fix two bugs found in code review pass 2:

1. Assistant turns silently dropped: user and assistant from the same
   rollout entry shared a turnId, so dedup via capturedTurnIds dropped
   the assistant. Fix: dedup key is now ${turnId}:${role}, not turnId
   alone. Regression test added.

2. First-capture data loss: when no lastKnownTurnId was set, only the
   last rollout entry was returned, losing prior turns. Fix: first-time
   capture now returns ALL entries.

Also: add backup step to config atomic write (copyFileSync before tmp+rename),
fix line width in zcode-turns.mjs, add 2 lifecycle tests (missed Stop
recovery, user+assistant same turnId).

29/29 tests pass (was 27).

* test(zcode): add concurrent session isolation tests

Two new test cases addressing maintainer criterion 4 (concurrent sessions):

1. Two sessions read their own rollout files — verifies session A cannot
   see session B's content and vice versa (sentinel-based assertion)
2. Independent lastTurnId state per session — verifies incremental capture
   progresses independently when one session has prior state and another
   is fresh

31/31 tests pass (was 29).

* fix(zcode): correct rollout file path pattern (model-io-<sessionId>)

The rollout path used model-io-sess-${sessionId} but ZCode filenames are
model-io-<sessionId> where sessionId already includes the sess_ prefix.
This caused the rollout fallback to always miss the file and return empty,
defeating capture entirely in production.

Verified on live two-session ZCode setup:
- Session A (sess_8c6ce483): 2 messages, 2 commits
- Session B (sess_74759710): 2 messages, 2 commits
- No cross-contamination between sessions

31/31 tests pass. Updated all test rollout filename patterns.

* docs(zcode): fix stale rollout path in comments and DESIGN.md

Comments referenced model-io-sess-<sessionId> but actual pattern is
model-io-<sessionId> (fixed in code already, comments were stale).

---------

Co-authored-by: woshiguanxiaoliang <woshiguanxiaoliang@noreply.gitcode.com>
2026-08-04 11:58:18 +08:00
Haoyu ZhangandQin Haojie 3f3554256b feat: 支持基于火山方舟的音视频多模态理解 (#3563)
* feat: add audio and video understanding via VLM

* docs: design media resource guards

* fix: bound media staging concurrency

* fix: cap unknown-size media staging

* test: stage media in routing fake

* test: exercise media staging callbacks

* test: trim media understanding coverage

* chore: 清理实现计划文档

* fix: 修复多凭证切换问题

---------

Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
2026-08-03 16:44:22 +08:00
Hao Zhe b2e1972610 refactor(langchain): extract standalone integration package (#3685)
* refactor(langchain): extract standalone integration package

* fix(langchain): preserve optional legacy imports

* fix(langchain): guard legacy submodule imports
2026-08-03 15:01:13 +08:00
Qin Haojie 9295a3b955 fix(session): remove actor scope from session lifecycle (#3661)
Keep sessions user-scoped and remove legacy agent fallback that could leak an actor view into commit memory writes.
2026-07-31 19:52:19 +08:00
zihengli 36d419aaa6 fix:openviking assets import external connector switch (#3634)
* fix:openviking assets import external connector switch

* fix(tests): update quick-start fake embedder compatibility

* fix:openviking assets import external connector switch

* fix:openviking assets import external connector switch
2026-07-31 13:55:41 +08:00
zgy 49b182045b refactor(parser): Refactor code summaries to fixed skeleton-first routing (#3568)
* Refactor code summary skeleton routing

* Simplify code skeleton routing configuration

* Render C tag skeletons as signatures

* Revert "Render C tag skeletons as signatures"

This reverts commit 8e342055f8.

* Simplify fixed code skeleton summary route

* Inline process skeleton rendering

* Simplify code skeleton routing entrypoints

* Fix code summary review issues

* Address final code summary review feedback

* Route failed tags skeletons to LLM fallback

* Restore CUDA and TS extension routing

* Improve code skeleton query coverage

* Route semantic code detection through skeleton support

* Move process skeleton engine into ast package

* Admit skeleton-supported files during directory scan

* Align code summary docs after main merge

* Reduce code skeleton fallback log verbosity

* chore: require grep-ast 0.9.0
2026-07-31 11:38:57 +08:00
baojun-zhang 7c956f23bc feat(config): add compatible default timeout for ragfs pathlock (#3641)
- add storage.agfs.pathlock.lock_timeout_secs
- use pathlock default timeout instead of hardcoded zero in wrapper
- map legacy storage.transaction.lock_timeout when new config is unset
- remote redolog by using  persistent `session_commit` queue.
2026-07-31 11:23:27 +08:00
Ziyang Guo abc387955d feat(openclaw-plugin): SecretRef support for config.apiKey (#3522) (#3618)
Issue #3522 — the OpenClaw plugin's `config.apiKey` only accepted a plain
string, resolved through local `${ENV_VAR}` interpolation. `INSTALL*.md`
documented this as a known limitation: users who store their other OpenClaw
provider credentials (LLM, TTS, MCP servers) through the standard
`{source, id[, provider]}` SecretRef mechanism (env / file mount /
exec-backed vault such as 1Password, Vault, gopass) had to keep the
OpenViking key as cleartext inside `openclaw.json`.

### config.ts — `string | OpenVikingSecretRef` widening

* Add `OpenVikingSecretRef = "env"|"file"|"exec"` discriminated union type,
  matching the shape OpenClaw core uses for its own credential fields
  (`env` + `file` implemented in-plugin, `exec` forwarded to `child_process`
  so providers like `@transmitt0r/openclaw-plugin-onepassword` can manage
  the OpenViking key without SDK coupling).
* Add `resolveSecret()` resolver with explicit, actionable errors:
  - env: unset var = throw, no silent empty fallback
  - file: `~` expanded, UTF-8 read, whitespace trimmed; unreadable file
    rethrows with the OpenViking field name prefixed so config misconfigs
    surface with a clear label and path
  - exec: lazy `require("node:child_process").execFileSync(provider,[id])`,
    stdout trimmed, 15s timeout; errors prefixed with provider + id
  - unknown source / missing id / missing exec provider = explicit throw
* `memoryOpenVikingConfigSchema.parse()` widens `rawApiKey` to
  `string | OpenVikingSecretRef`, then passes it through
  `resolveSecret(rawApiKey, "config.apiKey")` *before* the existing
  `resolveEnvVars` pass. Plain strings transparently fall through
  `resolveSecret` unchanged, so `${ENV_VAR}` interpolation is preserved
  100% backward-compatibly.
* `OPENVIKING_API_KEY` env fallback is unchanged and triggers only when the
  `apiKey` config key is absent — a user who deliberately sets `apiKey: ""`
  still gets "" (explicitly unauthenticated), not the env fallback.
* `uiHints.apiKey.help` documents the SecretRef shape and recommends it.

### openclaw.plugin.json — widening schema + UI hints

* `configSchema.properties.apiKey` becomes `oneOf: [string, env ref, file ref, exec ref]`.
  Each object variant has a `title`, `additionalProperties: false`,
  `required`, and explicit description per field, so OpenClaw's config UI
  can render them individually instead of showing a generic JSON object blob.
* `uiHints.apiKey.help` matches the new config.ts wording.

### INSTALL.md / INSTALL-ZH.md — SecretRef usage tables

Replace the old "plaintext / chmod 0600" caveat bullet with a 3-row table
(env / file / exec) showing example JSON + notes (Kubernetes secretKeyRef
mount for `file`, 1Password `op://` URL convention for `exec`). The
backward-compat string path is retained at the end of the new bullet so
existing deployments that haven't migrated yet still get the old permission
advice — no surprise behaviour for upgrading users.

### tests/ut/config.test.ts — SecretRef regression suite (10 new cases)

Under a new `describe("… SecretRef (#3522)")`:

1. Backward compat: `${OV_KEY}` interpolation still resolves.
2. env source — happy path with a fresh env var.
3. env source — unset var throws, no silent fallback.
4. file source — real `mkdtemp`-created file, trimmed whitespace. Cleanup
   in `afterEach`.
5. file source — missing-path error message contains readable label + path.
6. exec source — `vi.spyOn(child_process.execFileSync)` asserts provider +
   args, stdout trimmed.
7. exec source — missing `provider` field errors.
8. Schema validation — unknown `source` and missing `id` each throw with
   error messages that name the problem.
9. Env fallback boundary — explicit `apiKey: ""` is NOT overridden by
   OPENVIKING_API_KEY, but `apiKey` absent IS (backward-compat behaviour
   contract pinned with a test so future refactors can't regress).

Covers every branch inside `resolveSecret()`, plus the backward-compat
contracts issue #3522 called out.
2026-07-30 16:21:06 +08:00
zihengli 47bbf7a66a feat(cli): add Openviking asset manifest mode to add-resource (#3358)
* feat: implement server-resolved OpenViking Assets manifests

Add the openviking-assets/1 declaration flow with server-owned configuration parsing and native Rust CLI execution.

- Resolve one flat Manifest against one Catalog through an authenticated server endpoint with strict schema and Git semantic validation.
- Reject recursive includes and unsafe clone URLs; return a resolved plan without submitting resources or running server-side batches.
- Keep local credential aliases, manifest state, dry-run, failure isolation, and per-asset create/sync orchestration in the CLI.
- Generate normalized stable asset identities on the server and remove the CLI direct SHA-1 dependency.
- Update flat examples and add server resolver/API plus Rust CLI coverage.

* feat: implement server-resolved OpenViking Assets manifests

* feat: implement server-resolved OpenViking Assets manifests

* fix(pathlock): tolerate missing lock token after recursive delete

* feat: implement server-resolved OpenViking Assets manifests

* feat: implement server-resolved OpenViking Assets manifests
2026-07-30 15:29:07 +08:00
yufeng 229300e886 fix(codex): preserve session tool activity (#3579) 2026-07-29 12:05:48 +08:00
zihengli a1e468b982 feat(connector): support more git like platform (#3531)
* feat(connector): support more git like platform

* feat(connector): support more git like platform

* feat(connector): support more git like platform

* feat(connector): support more git like platform

* feat(connector): support more git like platform
2026-07-28 19:17:47 +08:00
agent 8391d3a758 feat: add global Agent Evolution switch and HTTP usage sink (#3223)
* feat: add per-user agent evolution settings

* simplify Agent Evolution user settings

* fix: preserve agent evolution client compatibility

* feat(snapshot): add path diff API

* feat(snapshot): expose path diff in clients and CLI

* fix(agent-evolution): gate case memory production

* fix(agent-evolution): preserve configuration compatibility

* feat(usage): add built-in HTTP sink

* fix(agent-evolution): address PR review findings

* fix(usage): isolate HTTP outbox by destination

* docs(usage): define CountRecord HTTP mapping

* docs(usage): plan CountRecord HTTP implementation

* feat(usage): emit CountRecord over HTTP

* docs(agent-evolution): design global switch

* docs(agent-evolution): plan global switch migration

* feat(agent-evolution): make production switch global

* fix(agent-evolution): preserve embedded defaults

* test(agent-evolution): cover failed archive policy replay

* docs(agent-evolution): clarify embedded compatibility

* docs(agent-evolution): expose global switch in example config

* refactor(agent-evolution): align global setting terminology

* fix(agent-evolution): preserve session skill extraction

* fix(usage-reporter): capitalize count record keys
2026-07-27 20:09:38 +08:00
t0saki 29ba81b53e feat(plugins): identify memory plugin traffic with a User-Agent (#3532)
Every harness memory plugin sent OpenViking requests under Node's default
`user-agent: node`, so server-side and gateway logs could not attribute
traffic to a harness or a plugin version.

Send `openviking-memory-<harness>/<version>` from all six harnesses
(claude-code, codex, opencode, pi, cursor, trae) on both the data plane
and the MCP proxy. Versions come from each harness's own manifest, or
from OPENVIKING_INTEGRATION_VERSION for cursor/trae; an unreadable
manifest degrades to 0.0.0 rather than throwing inside a short-lived hook.

The header is purely informational — neither the open-source server nor
the commercial gateway consumes it, and no auth or identity header
changes.
2026-07-27 15:31:21 +08:00
Zayn Jarvis 3043e25194 docs(openclaw): document manual plugin configuration (#3446)
* docs(openclaw): document manual plugin configuration

* docs(openclaw): clarify manual config safety

* docs(openclaw): sync manual config guidance
2026-07-23 10:46:53 +08:00
yijie zhao 09cd4782df fix: allow opencode recall after session context (#3464)
* fix: allow opencode recall after session context

* test: cover opencode recall with session context
2026-07-22 19:32:13 +08:00
yufeng 085aaf832d docs: correct context paths and refine navigation (#3385) 2026-07-21 11:45:17 +08:00
Hao Zhe 3b2571b36e feat(openclaw): add catalog icon (#3362) 2026-07-20 14:55:30 +08:00
huangruitengandhuangruiteng 379c19f66e fix(codex): preserve recall on Windows spawn failure (#3308)
Co-authored-by: huangruiteng <huangruiteng@bytedance.com>
2026-07-19 13:35:41 +08:00
Hao Zhe ebe7fa2a7d fix(plugins): align OpenCode and OpenClaw contracts (#3232) 2026-07-17 17:06:27 +08:00
MaojiaShengandqin-ctx 3c70f8d370 feat(parse): add large image processing for image parser (#3265)
* feat(parse): add large image processing for image parser

- Add large_image_processor.py: detect large images (>10MB or >4096px),
  create low-res previews, split into grid tiles, and generate grid
  overlay images with tile labels
- Refactor ImageParser.parse() to integrate large image processing pipeline
- Enable SVG-to-PNG conversion in utils.py (cairosvg/wand)
- Rename ImageConfig.max_dimension to preview_max_dimension and add new
  config fields: max_file_size_mb, max_tile_size_mb, max_tile_dimension_px,
  tile_overlap_px, large_image_threshold_dimension
- Update ov.conf.example with new image config options

* fix(parse): correct tile dimension comment from 1024px to 2048px

* fix(parse): fix tile label path in grid overlay to include tiles/ directory

* fix(parse): register missing image extensions for ImageParser

TIFF, ICO, DIB, ICNS, SGI, JP2 were not in IMAGE_EXTENSIONS, causing
them to fallback to TextParser. All are supported by PIL.

* fix(parse): preserve PNG format for tiles instead of always converting to JPEG

* fix(parse): address review feedback for large image processing

- Wire config.image to ImageParser in ParserRegistry (was missing)
- Remove unnecessary preview creation for small images (broke LA mode PNG)
- Enforce max_tile_size_mb on tiles with quality reduction and resize fallback
- Remove 64-tile hard cap that conflicted with max_tile_dimension_px
- Add comment explaining why original file is not saved for large images

* refactor(parse): remove max_tile_size_mb as it is a soft suggestion

max_tile_size_mb was a soft constraint that was not enforced
consistently. Remove it from config, constants, and all enforcement
logic. Tile dimension (max_tile_dimension_px) remains the sole constraint.

* fix(parse): use CJK-capable font for grid overlay labels

The old font loading only tried macOS-specific paths and fell back to
PIL's default bitmap font, which cannot render CJK characters in
filenames. Add a cross-platform CJK font lookup that covers Linux
(Noto/Droid/WQY/DejaVu), macOS (PingFang), and Windows (MSYH/SimSun).

* fix(parse): convert non-VLM-supported image formats to PNG on save

Image formats like TIFF, ICO, DIB, ICNS, SGI, JP2 are not recognized
by VLM backends (OpenAI/LiteLLM/VolcEngine only support PNG/JPEG/GIF/
WebP/BMP) or by embedding_utils for image vectorization. When a file
with one of these extensions is parsed, convert it to PNG and use a
.png extension so that downstream pipelines see consistent data.

SVG files (already PNG-converted via cairosvg) also get the .png
extension for the same reason.

* fix(parse): import io for SVG conversion

---------

Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
2026-07-16 17:37:05 +08:00