AsyncHTTPClient.create_session() takes (session_id, options); memory_policy
is a key of CreateSessionOptions, not a keyword argument. Three production
call sites still pass it as a keyword and raise
TypeError: AsyncHTTPClient.create_session() got an unexpected keyword
argument 'memory_policy'
on every session that does not already exist:
- openviking/ingest/replay.py, ConversationReplayClient.ensure_session:
`ingest backfill` fails on every new session. The orchestrator catches
per-session exceptions, so a first backfill prints one error per session
and finishes with 0 commits.
- bot/vikingbot/openviking_mount/ov_server.py, VikingClient.ensure_session.
- openviking/session/train/components/session_commit.py,
SessionCommitPolicyTrainer._commit_one, which swallows the TypeError and
returns a failed commit record with an empty task_id.
All three now pass options={"memory_policy": policy}, and options=None when
no policy is configured. benchmark/locomo/vikingbot/import_to_ov.py already
used that form.
The three test fakes accepted the obsolete keyword, so none of the paths had
regression coverage. They now mirror the real SDK signature: reverting any
one of the three fixes fails its tests.
Fixes#4493
* 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>
* 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>
* 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.
* feat: support oidc and ldap auth
* feat: support oidc and ldap auth
* fix: remove heima partner, clean up auth docs, add web-studio unsupported auth banner
- Remove heima from partner list in README (en/zh/ja)
- Remove unsupported env var references (OPENVIKING_AUTH_MODE, OPENVIKING_USERNAME,
OPENVIKING_PASSWORD) from LDAP auth docs
- Remove temporary switch bash snippets from auth docs
- Fix ldap_password description
- Add web-studio unsupported-auth-mode banner for oidc/ldap servers
* fix: address OIDC/LDAP review comments on auth plugin design
Key changes driven by PR review:
- **Role mapping**: OIDC and LDAP external identities always resolve to
USER role. Removed map_role() calls and group_membership-based role
mapping. Admin access is gated by the root API key mechanism only.
- **LDAP credential extraction**: Removed query-parameter-based username/
password extraction (security concern — passwords in URLs can leak via
shell history, proxy logs, and monitoring). Clients must use Basic Auth
header or form data.
- **OIDC identifier sanitization**: Auth0 and other providers may include
characters like "|" in the `sub` claim. These are now replaced with "_"
to produce valid OpenViking user identifiers.
- **Dead code removal**: Removed _extract_groups, memberof_attribute,
require_root_api_key_for_admin, _initialize_api_key_manager, and
get_request_context_checks from both plugins since they are no longer
needed.
- **Docs**: Removed query-parameter curl example, memberof_attribute and
require_root_api_key_for_admin config references.
Co-authored-by: TRAE CLI <noreply@bytedance.com>
* feat: support oidc and ldap auth
* feat: support oidc and ldap auth
* fix(auth): bind lazy OIDC imports at module scope
---------
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
* fix(bot): only require VKE credentials when the TOS storage path needs them
Sweep findings: C-14. Gate AK/SK validation on an actual TOS deployment and drop the unused cluster ID.
(cherry picked from commit 8790ba509f)
* fix(server): apply configured temp_upload.default_mode to uploads
Sweep findings: B-11, D-01. Apply the documented configured upload mode when requests omit it.
(cherry picked from commit a0dc2498e8)
* fix(bot): make one-click Docker deployment generate a working config and port mapping
Sweep findings: C-12. Generate the active ov.conf and keep gateway and Docker ports aligned.
(cherry picked from commit c22af83ab6)
* fix(server): make --bot work and propagate bot flags to workers
Sweep findings: B-09, B-15. Honor the public Bot alias and replay resolved Bot settings in worker processes.
(cherry picked from commit 32a898ca14)
* fix(docker): derive entrypoint/health port from configured server port
Sweep findings: F-06. Keep server startup and every container health check on the same effective port.
(cherry picked from commit 000795c7e3)
---------
Co-authored-by: zhiheng.liu <zhiheng.liu@bytedance.com>
* fix(bot): never silently replace corrupt config, session, or cron stores
Sweep findings: C-03, C-05, C-06. Fail fast on corrupt persisted state before any overwrite.
* test(bot): drop corrupt-state regression tests per review
The three fixes (loader raise on invalid config, session/cron refuse to
overwrite corrupt state) stay; the accompanying tests are removed as not
worth their weight.
* fix(bot): pass sender_name in all channel adapters
Sweep findings: C-01. Supply display-name fallbacks so inbound messages reach the bus.
* fix(bot): make sender_name optional and wire real WhatsApp pushName
Root-cause guard: _handle_message required sender_name positionally, but
InboundMessage.sender_name is str|None=None and context.py already falls back
to sender_id, so the required-ness was an accidental signature/contract
mismatch. Make it optional (reordered after the still-required chat_id/content;
all 11 call sites use keyword args) so no future adapter can crash on it.
WhatsApp: the previous call read data.get("senderName")/data.get("pushName"),
neither of which the bridge ever sends, so it silently always fell back to the
numeric id. Forward baileys' msg.pushName through the bridge payload and read it
in Python, so WhatsApp group chats show real display names like other channels.
Commit 4d34025c added the required `sender_name` parameter to
`BaseChannel._handle_message()` and updated `feishu.py`, but
`slack.py` and `email.py` were not updated in the same change.
This caused a `TypeError` on every inbound message in both channels.
Because Slack SDK swallows exceptions in asyncio listener callbacks,
the error was silent — the bot received events, added emoji reactions,
but never called the LLM or sent any reply.
Fix: pass `sender_name=sender_id` in SlackChannel and
`sender_name=sender` in EmailChannel.
Co-authored-by: scott.kim <scott@ScottMacBookPro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
`ov chat --with-bot` regressed in 0.4.5: a config with only a `vlm` section
(no `bot.agents`) and a `server` whose effective auth mode is `api_key` fails
with `litellm.InternalServerError: OpenAIException - Missing credentials ...
set OPENAI_API_KEY`, even though the user configured e.g. deepseek. 0.4.3
worked.
Root cause: the 0.4.5 ov_server auth rewrite made
`_merge_current_ov_server_config` call `_fill_user_api_key_from_ovcli()` ->
`load_ovcli_config()` whenever the effective auth mode is `api_key`. When the
user only configured `vlm` and has no valid ovcli identity, that raises
`ValueError`, which is re-raised. `load_config()`'s broad
`except (json.JSONDecodeError, ValueError)` then swallows it and silently falls
back to a default `Config()` — model `openai/doubao-seed-2-0-pro-260215`, empty
provider, empty api_key. `_make_provider` takes the legacy LiteLLMProvider
branch on that `openai/*` model with no key -> the OpenAI missing-credentials
error. In 0.4.3 the ovcli lookup only ran in `remote` mode (api_key present),
so a vlm-only config never hit it.
Fix: a missing/invalid ovcli (OpenViking user) identity only affects OpenViking
memory/file tools — it must not abort loading the rest of the bot config. On
`load_ovcli_config()` failure, warn and continue with the user api_key unset
instead of re-raising. Degraded OpenViking auth is still surfaced separately by
validate_openviking_auth(). This restores 0.4.3 behavior for vlm-only configs
while keeping the user-key auto-fill when ovcli is configured.
Adds a regression test covering both the ovcli-fails and ovcli-succeeds paths.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
PR #2944 added `bot.agents.thinking` (default `true`) which mutates
provider reasoning params for VolcEngine (`thinking={"type":"enabled"}`),
DashScope (`extra_body.enable_thinking`), and OpenAI reasoning models
(`reasoning_effort`), but the canonical Vikingbot config tables and
samples in bot/README.md and bot/README_CN.md were not updated.
Document the new default-on option and its per-provider behavior in both
the EN and ZH config reference and sample config so operators can
discover the off-switch (latency/cost/compatibility tuning).
* feat(grep): integrate VikingDB bm25 keyword search for grep engine
* fix(grep): address CI review feedback: max-size eviction to _count_cache, use Literal, Split regex alternation into individual keywords for bm25 (max 10)
* fix(schema): use dynamic __version__ for schema_version and handle dev suffixes in version comparison
* fix(schema): upsert data to vikingdb lack of content
* chore: add benchmark for retrieval
* fix(grep): vikingdb return 200 and no results means no matching content, not necessary to fallback to local fs
* fix(benchmark): sub uri args; add report
* refactor: code format by ruff
* optimize: move grep config (engine and switch_to_remote_threshold) to ov.conf
* optimize: auto adapt remote_return_limit by agg API; rm unnecessary params in keywords search
* fix: adjust benchmark scripts
* fix(grep): store full content for BM25; use PathScope depth; reduce redundant API calls
* refactor: new benchmark
* fix: step1 add resource by real code data
* feat(benchmark): split grep benchmark into effectiveness/performance suites with async reindex
* optimize (benchmark): adjust keywords and ground truth for testing
* fix: truncate 64KB for content field
* optimize: effectiveness add resource plainly
* optimize: change param use of SearchByKeywords from "keywords" to "query"
* optimize(benchmark): refactor effectiveness scripts
* optimize: ensure raw data for content field
* optimize: fulltext analyzer's stop-words only use symbols
* fix: adapt to new ov cli for benchmark
* optimize: reuse file content to avoid re-read AGFS file
* optimize: tune grep vikingdb defaults and refresh bm25 benchmark scripts
* optimize: benchmark client timeout
* update README
* fix: rm unused param
* fix: default values in docs
* optimize: increase truncate byte size to 1MB for content field for VikingDB
* fix(logger): harden queued stream logging (#2786)
* fix(logger): replace StreamHandler with QueueHandler+QueueListener to prevent thread deadlock
When log.output='stdout' (default) and the server is managed by systemd,
concurrent log writes can deadlock because logging.StreamHandler holds a
thread lock across stream.flush() which blocks on systemd-piped file I/O.
During session.commit() phase 2, multiple async coroutines (memory
extraction, summarization) concurrently call logger.info()/warning()
with large payloads. The first thread's flush() blocks on the pipe,
while all subsequent threads block on handler.acquire() forever.
This permanently silences the server log and prevents _write_done_file()
from executing, leaving phase 2 hanging without .done.
Fix: use QueueHandler + QueueListener from stdlib logging.handlers
(Python 3.2+). QueueHandler.emit() does queue.put(record) with no lock
or I/O, returning immediately. QueueListener has a dedicated single
thread as the sole consumer touching the real StreamHandler, making
lock contention impossible.
Changes in _create_log_handler(): stdout/stderr branches now create
a shared QueueListener with unbounded queue, returning QueueHandler
instances to callers. _build_standard_handler() delegates formatter
and filter setup to the real handler in the listener thread.
Closes: #2752
* fix(logger): harden queued stream logging
---------
Co-authored-by: njuboy11 <njuboy11@users.noreply.github.com>
---------
Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
Co-authored-by: njuboy11 <njuboy11@users.noreply.github.com>