* feat(mcp): return images as native content blocks
* test(mcp): allow configured tool decorators
* feat(mcp): return audio as native content blocks
* feat(mcp): add embedded-resource download mode
* fix(mcp): bound native media reads
* fix(mcp): add actionable media download fallback
* fix(mcp): point directory reads at list, share URI suffix parsing
- directory hint now names the list tool / `ov ls` / `ov tree`
- audio MIME sniffing ignores query/fragment like the extension gate
does, so `clip.ogg?v=2` no longer fails as an unsupported format
- bound the preflight stat fan-out with the existing read semaphore
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXgAtkdLQZhXu4ZbHpaDqR
* fix(mcp): validate video reads before fallback
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Hardcoded gray RGB made primary and secondary copy hard to read on
both light and dark terminals. Use default foreground (SGR 39) for
body text and dim (SGR 2) for muted text; leave accent colors as-is.
* feat(resources): support source headers for HTTP imports
Allow HTTP(S) resource imports to pass request headers for authenticated object storage sources. Fetch authenticated sources into a request-scoped snapshot and keep credentials out of parser inputs and queued jobs.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* fix(resources): reserve source headers from args
Treat source_headers as a top-level add_resource field so it is rejected from args and filtered consistently from queued processor inputs.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* feat(resources): accept TOS auth through args
Replace generic source header passthrough with explicit tos_signature and tos_access args for HTTP TOS object imports. Keep credentials request-scoped and out of parser and queue payloads.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* refactor(resources): name transient TOS args
Centralize TOS credentials that are accepted from args but excluded from durable resource jobs.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
---------
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
Directory L1 overviews previously fed the model bare `[N]` file indices and
`[N] filename: summary` source lines, then post-processed by replacing `[N]`
with the entry filename. Because the model naturally copied the filename next
to the index (e.g. `### [1] filename` or `→ [1] filename`), the substitution
produced duplicated headings like `### filename filename` in both Quick
Navigation and Detailed Description sections.
Replace the index-reference scheme with collision-free link placeholders:
- Feed each entry a compact placeholder `(link: viking://input_sample_fN)` for
files and `viking://input_sample_cN` for subdirectories, and instruct the
model to emit standard Markdown links `[display title](placeholder)`.
- Resolve placeholders back to real `viking://` URIs (built from
`dir_uri + "/" + name`) in post-processing via `_replace_link_references`,
replacing the old `_replace_index_references`.
- Apply consistently across the single, truncated, and batched generation
paths; batched partials resolve placeholders before merge so the merge step
needs no further substitution.
This eliminates the duplicated-heading class of bugs entirely (bare `[N]`
collisions are far less likely than reused digits) and yields clickable,
accurate resource links in the generated overview, matching the Markdown
link convention already used elsewhere (session memory extraction).
Co-authored-by: Maojia Sheng <shengmaojia@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
When a memory has no existing content (current_value is None), PatchOp routed
the write through _extract_replace_when_no_original, which returned only the
FIRST block's replace text — via StrPatch.get_first_replace() for objects, and
blocks[0] for the dict (JSON-parsed) form.
The StrPatch schema instructs the model to split non-adjacent edits into
separate blocks, so a brand-new memory routinely arrives as a multi-block
patch (e.g. one block per extracted fact or preference). Taking only blocks[0]
silently discarded every subsequent block — entire facts/preferences extracted
from the session were dropped with no log, warning, telemetry, or
caller-visible signal. The existing-content path (apply_str_patch) already
iterates all blocks; the no-original branch was an asymmetric omission.
Concatenate every block's replace content (joined by newline) in both the
StrPatch and dict forms. The common single-block case is unchanged
("\n".join([x]) == x), and the existing-content path is untouched.
Add regression tests covering multi-block StrPatch and dict-form patches
(silent loss before the fix), plus single-block and existing-content cases
to pin the unchanged behaviour.
* fix(bot): use user-scoped resources URI in VikingSearchTool
VikingSearchTool hardcoded `viking://resources/` (shared namespace)
as the search target for resources, but user-uploaded resources are
stored under `viking://user/<user_id>/resources/`. The server correctly
treats `resources` as a standalone scope without user-path resolution,
so the shared URI returned zero results in user API key mode.
This patch adds `_current_resources_uri()` — mirroring the existing
`_current_skill_uri()` pattern — to derive the user-scoped resources
URI from the current memory URI. All three hardcoded sites are replaced:
1. `_fs_retrieval_uris()` — default root retrieval list
2. `VikingSearchTool.execute()` — sender-fanout branch
3. `VikingSearchTool.execute()` — actor-peer-id branch
Verified: Vikingbot chat API search for resources now returns correct
results instead of empty arrays.
* fix(bot): include current resource targets in retrieval
* fix(bot): use home aliases for scoped file targets
Emit current-user resource, memory, and skill targets with viking://~/ aliases instead of deriving sibling URIs from memory targets.
---------
Co-authored-by: 王旭晨 <wangxc4@chinatelecom.cn>
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
third_party/leveldb-1.23 auto-detects a system tcmalloc with
check_library_exists() and links it with PUBLIC propagation. Because the
Python abi3 engine module transitively links that tcmalloc, it mixes the
tcmalloc heap with the Python allocator inside the same process, which
corrupts memory and intermittently SIGSEGVs in vectordb::Schema /
bytes_row construction. Official wheels never link tcmalloc, so this
only reproduced on machines that have libtcmalloc installed.
Force HAVE_TCMALLOC off by default (opt-in via -DHAVE_TCMALLOC=ON) so
source builds behave like the released wheels.
Allow openai-codex VLM configuration to carry reasoning_effort through credential normalization and into Responses API requests so deployments can tune model effort without out-of-tree patches.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously initialize_memory_files only seeded template variables for
fields that declared an init_value. Fields without one were omitted from
extra_fields, so Jinja (DebugUndefined) wrote their literal "{{ field }}"
placeholders into initialized memory files such as identity.md.
Seed every field, defaulting a missing init_value to an empty string, so
placeholders resolve to empty instead of leaking into the file.
Fixes#4207
* feat(sdk): sync go/ts/python SDKs with server find/search, recall, and admin changes
Server-side changes recently landed that the language SDKs had drifted from:
- find/search results now return `tags` and no longer return
`category`/`match_reason`/`relations`/`overview` (#3730). Go's strict
struct was the only one broken; update MatchedContext accordingly.
- new admin endpoints for agent-evolution and per-account settings (#3695).
- public `search/recall` endpoint was missing from all SDKs.
Changes:
- python: add `level`/`since`/`until`/`time_field` to find/search; add an
`extra` escape hatch to find/search/add_resource/write/batch_write so new
server fields can be passed without an SDK bump (only forwarded when set,
preserving `level=0`); add `recall` and the four admin methods.
- go: fix MatchedContext (add Tags, drop removed fields), add Recall and the
four admin methods.
- typescript: type MatchedContext/FindResult, add RecallOptions, add `recall`
and the four admin methods.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
feat(sdk): unify options APIs and sync latest server interfaces
- migrate complex Python SDK calls to typed options dictionaries
- add dedicated context search and consistent extra-field handling
- align Go and TypeScript options with omission-aware serialization
- support session config, event tags, Agent Evolution date filters,
OpenViking Assets, batch write, downloads, and create_parent
- refresh SDK tests and examples across all three languages
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): address options API review findings
- fix Go session extra merging and Python message precedence
- adapt LangChain calls to the Python options API
- migrate repository examples, tests, and documentation
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): complete options migration and message parity
- migrate remaining Python SDK benchmarks to options dictionaries
- normalize empty parts consistently for single and batch messages
- add regression guards for repository SDK call sites
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): align reindex options after main rebase
- preserve reindex tags in Python typed options
- add reindex extra support for Go and TypeScript
- reject official fields passed through extra across SDKs
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
feat(sdk): support legacy keyword options
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
docs(sdk): use explicit Python SDK arguments
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): support set tags extra options
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): expose Go add resource options
Expose AddType and ProcessingMode through Go AddResourceOptions and serialize them to the resources API. Add a regression test covering the resulting request payload.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
feat(sdk): flatten core Python client options
Co-authored-by: TRAE CLI <traecli@bytedance.com>
docs(sdk): align Python examples with flattened options
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): preserve core API compatibility
Co-authored-by: TRAE CLI <traecli@bytedance.com>
refactor(python-sdk): move resource hints to options
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): align resource option callers
Co-authored-by: TRAE CLI <traecli@bytedance.com>
test(sdk): cover recursive reindex forwarding
Co-authored-by: TRAE CLI <traecli@bytedance.com>
fix(sdk): preserve Go options compatibility
Co-authored-by: TRAE CLI <traecli@bytedance.com>
feat(python-sdk): expose message peer id
Co-authored-by: TRAE CLI <traecli@bytedance.com>
test(python-sdk): consolidate options coverage
Co-authored-by: TRAE CLI <traecli@bytedance.com>
feat(python-sdk): add parts and flatten image search
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* docs(sdk): align Python call examples
Co-authored-by: TRAE CLI <traecli@bytedance.com>
---------
Co-authored-by: TRAE CLI <traecli@bytedance.com>
Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
Reapply previously injected recall blocks to historical user messages from a per-session, atomically persisted ledger. This preserves byte-stable request prefixes across turns while still performing fresh recall for the newest prompt.\n\nFixes #4137
* fix(ov_dream): accept a message whose content is a plain string (#4221)
parse_messages() assumed every OpenClaw message body was a block list.
Iterating a plain string yields characters, so `"p".get("type")` raised
AttributeError out of the parser — before any session was committed, which
made one such message disable the skill for the whole workspace rather than
skip that message. The reporter measured 91 string bodies in 1609 real
messages.
Flatten the body through a helper that treats a string as text and skips
blocks that are not dicts.
* test(ov_dream): consolidate string content coverage
---------
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
SKILL.md now teaches only the core tool set that every supported
deployment registers; deployment-dependent tools (tree/write/edit,
watch management) move to
skills/openviking-memory/references/optional-tools.md, read only when
the session actually registered them. Legacy recall is dropped
entirely (0.4.15 folds it into search mode="context"). Adds a test
that relative markdown links inside skills resolve. Rebased onto the
viking://~ URI convention from a83b8171.
* feat(uri)!: reject uid-less current-user shorthand in favor of viking://~
viking://user/<segment> (memories/resources/skills/peers/privacy/sessions
without a user id) was ambiguous with a user literally named after the
segment, and a user actually named e.g. "memories" was unreachable for
USER/ADMIN callers. Now that the viking://~ home alias (#4167) covers the
same need unambiguously, the shorthand fails closed at the request
boundary instead of expanding:
- resolve_current_user_uri raises NamespaceShapeError with a corrective
hint naming both viking://~/<rest> and the explicit-uid form. Silently
parsing the reserved segment as a peer user id would misdirect reads
and writes, so rejection is the only safe removal.
- Bare viking://user falls through to the canonical parser and keeps
container semantics (a user key listing it sees only its own space).
- The self-id escape stays: a caller whose user_id equals a reserved
name keeps viking://user/<own-id> as their canonical root. ROOT-role
literal parsing and the legacy viking://session alias are unchanged.
- AddTargetsConfig normalizes stored legacy config spellings
(viking://user/resources|skills) to the viking://~ form at validation
so existing ov.conf/user_config deployments keep working; the accepted
per-user spelling is now viking://~/resources and viking://~/skills.
- usage_reporter keeps canonicalizing the historical shorthand found in
old transcripts and additionally recognizes viking://~/memories/.
BREAKING CHANGE: requests using the uid-less viking://user/<segment>
spelling now fail with 400; use viking://~/<segment> or an explicit
viking://user/{user_id}/<segment> URI.
* refactor(clients): migrate first-party emitters to the viking://~ home alias
Every in-repo client that emitted the removed uid-less current-user
shorthand now sends viking://~/... instead: vikingbot fallbacks and
default sentinels, the LangChain store/tools defaults, the shared
recall-core.mjs (all synced plugin copies), the codex/claude-code/
openclaw/openwebui/dsh/zcode/pi plugin emitters, quick-app examples,
Go SDK example, tau2 benchmark targets, and the eval golden dataset.
Compat kept where legacy strings live in stored user configs: bot and
ov_dream sentinels accept both spellings while emitting only ~, and
recall-core still rewrites legacy viking://user/<reserved> config values
client-side. langchain_openviking._uri now classifies viking://~ with
the explicit-user shape so canonicalized server responses keep matching
a ~ root. Plugin READMEs note the server requirement for the alias.
* docs: replace current-user shorthand guidance with the viking://~ home alias
Rewrite every EN/ZH doc and model-facing prompt that advertised the
uid-less viking://user/<segment> spelling: URI concept catalogue,
context-types/storage/extraction/retrieval/session/privacy concepts,
configuration guide (with the legacy add_targets auto-normalization
note), resources/skills/sessions/retrieval/admin API references, FAQ,
capability reference, and the openviking-memory / ov-experience-memory /
openclaw / ov-resources skills. The stale MCP viking://user/<path>
dialect passage in the MCP guide is replaced by ~ guidance, and bare
viking://user is documented as the container of user spaces.
* test(api): migrate live API session-used tests off the removed shorthand
tests/api_test/sessions sent uid-less viking://user/skills/... URIs to
record_used, which the request boundary now rejects with 400 (caught by
the API & CLI Integration Tests CI job; these tests need a live server
and are not part of the local suites). The api_test client authenticates
as an admin-role user key, so the viking://~ home alias expands for it.
tests/api_test/common/test_edge_cases.py is left as is: it asserts a 400
for a non-resource add target, which still holds.
The api_key_watch_interval mechanism reloads account info across replicas
by polling compute_store_signature() (a (path, size, modTime) signature
over accounts.json + users.json). On S3FS this never detected writer-side
changes: S3FS stat() serves from a sliding-TTL StatCache (default 60s,
re-armed on every get()), so the watcher's 30s poll kept the entry alive
forever and the signature never moved -> reload() never fired. localfs
stats live, so it worked there.
Thread a bypass_cache flag from the watcher's stat call down to S3FS so
signature stats read fresh backend metadata:
- FsContext(View): add bypass_cache field + builder/getter
- ragfs-python build_fs_context: parse ctx["bypass_cache"]
- S3FS stat(): skip stat_cache.get() when bypass_cache is set
- AsyncAGFSClient.stat(bypass_cache=...): inject ctx flag
- legacy _stat_signature: stat with bypass_cache=True
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* feat: add freshness-aware parent aggregation
Defer wide-directory abstract/overview regeneration until the configured freshness threshold is reached while continuing changed-file semantic and vector processing.
Persist freshness metadata atomically, make parent bubbling L0-aware, preserve separate semantic/vector statuses, and keep explicit waits synchronous.
Rebuild every sampled summary on threshold refresh and always retry directory vectorization so stale sidecars or transient vector failures cannot be silently accepted.
Add focused coverage for freshness policy, pending-state consumption, sampled-summary refresh, vector retries, and parent bubbling.
Co-authored-by: TRAE CLI <traecli@bytedance.com>
* feat: ov reindex support --recursive
* feat: ov reindex support --recursive
* feat: ov reindex support --recursive
* feat: ov reindex support --recursive, and applied to memory
* feat: ov reindex support --recursive, and applied to memory
---------
Co-authored-by: TRAE CLI <traecli@bytedance.com>