Commit Graph
508 Commits
Author SHA1 Message Date
Evo ab3cb26494 docs(oauth): point OAuth client OTP to sidebar OAuth setup entry from #2178 (#2192)
* docs(oauth): point OAuth client OTP to sidebar OAuth setup entry

* docs(oauth, zh): point OAuth client OTP to sidebar OAuth setup entry
2026-05-22 16:17:12 +08:00
Evo 01b9b3d583 docs(mcp): document code_outline / code_search / code_expand from #2146 (#2176)
* docs(mcp): add code_outline / code_search / code_expand rows for #2146

* docs(mcp): 中文同步 code_outline / code_search / code_expand for #2146
2026-05-22 11:18:28 +08:00
LinQiang391andCursor 87039cac4c docs(openclaw): align plugin docs with ClawHub standard install experience (#2150)
Use explicit clawhub: prefix across all install paths (README, INSTALL, INSTALL-ZH, INSTALL-AGENT, SKILL.md) since bare specs resolve to npm on current OpenClaw. Restructure ClawHub README with Quick Start first screen, How It Works, Tools table, Data Flow and Privacy section. Move engineering details into collapsible section. Demote ov-install to fallback. Fix ov-install params, OpenClaw min version, and parameter table. Allow images in ClawHub bundle.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 20:15:23 +08:00
Zayn Jarvis 4aeb25e5b9 docs: replace legacy console / port 8020 references with Web Studio (/studio) (#2175)
Follow-up to #2160 (console removal) and #2170 (OAuth UI moved to web-studio).
Six guides still showed the old `python -m openviking.console.bootstrap`
launch + `-p 8020:8020` docker run snippets, which now fail because the
console package is gone and the image no longer exposes 8020.

- docs/{en,zh}/getting-started/04-setup-for-agent.md: drop `-p 8020:8020`
  from docker run and the "ports: 1933:1933, 8020:8020" summary; note that
  Web Studio is served by the OV server at `/studio` so no extra port is
  needed.
- docs/{en,zh}/guides/03-deployment.md: drop 4× `-p 8020:8020` snippets,
  replace "OpenViking Console on port 8020" with the inline `/studio`
  mention, and update the "access this after startup" list to point at
  `http://localhost:1933/studio` (with 1934 documented as a legacy Caddy
  fallback consistent with the updated 12-public-access guide).
- docs/{en,zh}/guides/05-observability.md: rewrite the "Web Studio for
  web-based investigation" section. The standalone-bootstrap launch is
  gone; instead direct readers to `/studio` and its observability-relevant
  pages — Home (token/retrieval/context-commit trends, /api/v1/console/*
  BFF), Request Logs (audit), Resources, Retrieval, Sessions. Update the
  "choose an entry point" table accordingly.

docs/design/mcp-oauth2-1.md is intentionally untouched — it's a historical
design document. The README inside openviking/observability/usage_audit/
and 12-public-access.md were already updated in earlier PRs.
2026-05-21 20:00:41 +08:00
AutoCoder 9a37e75395 feat(mcp): add code_outline / code_search / code_expand tools (#2146) 2026-05-21 19:30:51 +08:00
t0saki da59289591 feat(oauth): move authorize UI into web-studio (#2160 follow-up) (#2170)
#2160 dropped the legacy `/console` standalone service but deliberately
left the OAuth authorize page's `/console` link and Quick-authorize panel
in place, calling out a follow-up to re-point them at web-studio. This
PR is that follow-up.

Backend
- `provider.authorize()` now defaults to redirecting to
  `/studio/oauth/consent` (same-origin SPA) instead of the server-rendered
  `/oauth/authorize/page`. New `FALLBACK_AUTHORIZE_PAGE` constant exposed
  for callers that need to opt into the legacy path.
- New public endpoint `GET /api/v1/auth/oauth/pending/{pending_id}` returns
  the minimum info the consent UI needs (client_name, redirect_host,
  scopes); deliberately does NOT expose display_code or full redirect_uri.
- `POST /api/v1/auth/oauth-verify` now accepts either `pending_id`
  (Studio consent path) or `code` (cross-device fallback).
- HTML `/oauth/authorize/page` template stripped of `/console` link, the
  `/console/api/v1/...` JS, and the Quick-authorize same-origin panel.
  It now serves as a pure cross-device fallback that points users at
  `/studio/oauth/verify` on another already-signed-in device.

Web Studio
- New `<IdentityPicker>` shared component: "current identity" or
  "use a different API key" — the temporary key is never persisted.
- New routes `/studio/oauth/consent` (same-device consent card) and
  `/studio/oauth/verify` (cross-device code entry).
- ConnectionDialog gains an "OAuth client OTP" section (same
  IdentityPicker), driving `POST /api/v1/auth/otp`.
- API key storage is unchanged: only sessionStorage. No new localStorage
  writes, no cross-tab channels — the consent UI runs inside Studio's own
  tab, so it reads the session-stored key directly.

Docs
- 11-oauth.md (zh/en): refreshed quickstart, How-it-works, Claude.ai
  walkthrough, curl example, and troubleshooting around the Studio
  consent / cross-device verify split.
- 12-public-access.md (zh/en): rewritten to lead with public HTTPS;
  the `:1934` Caddy block is now a one-paragraph compatibility note for
  deployments that already bookmarked it.
- mcp-oauth2-1.md: top-level "Studio migration" note explains the new
  default path; Phase 1 history retained.
- Caddyfile / docker-compose.yml comments reworded from "aggregated
  proxy" to "legacy fallback" to match the new docs.

Tests
- `tests/server/oauth/test_router.py` fixture pins to
  FALLBACK_AUTHORIZE_PAGE so existing end-to-end assertions keep working.
- 4 new tests cover the pending-info endpoint and pending_id verify path.
- 55 passed locally; ruff format+check, web-studio tsc/eslint/prettier
  all clean.

Security notes
- Consent UI requires explicit user click; client_name + redirect_host
  shown for phishing identification.
- Knowing a pending_id does not bypass Bearer auth.
- display_code is not returned by GET pending — the cross-device
  brute-force protection is preserved.
- `ctx.from_oauth` gate (router.py) untouched: OAuth bearer still
  cannot mint new OAuth state or OTPs.
2026-05-21 17:57:33 +08:00
Yuan Shenheng a27c18eee9 fix(examples): wait before quickstart preview (#2167) 2026-05-21 17:11:32 +08:00
Lumos088 dbb67f75d5 Add files via upload (#2162) 2026-05-21 16:45:55 +08:00
Zayn Jarvis d6a024efa5 feat(docker)!: drop legacy console (keep BFF + Caddy), ship web-studio in pip, fix favicons (#2160)
The OpenViking docker image still launched the legacy `openviking/console`
standalone service on port 8020. Now that web-studio is bundled into the OV
server itself at /studio (see #2156), that process is redundant and the
port is just a confusing artefact.

This change retires the old console (python package + 8020 + console-frontend
favicons) but **keeps the in-compose Caddy as a stable single-ingress on
port 1934**, just simplified to one upstream now that there's no 8020. The
server-side BFF at `openviking/server/routers/console.py` (under
`/api/v1/console/*`) is also kept — web-studio uses the same endpoints.

**The OAuth authorize page (`openviking/server/oauth/router.py`) is
deliberately untouched in this PR** — the console-link button and Quick
authorize same-origin panel will be re-pointed at web-studio in a focused
follow-up.

BREAKING CHANGES:
- Port 8020 is gone from the docker image and docker-compose.yml; Caddy at
  1934 now forwards everything to 1933 (web-studio lives at /studio there).
  Anything bookmarked at `http://host:8020/...` must migrate to
  `http://host:1933/studio/`.
- `python -m openviking.console.bootstrap` no longer exists; the python
  package `openviking.console` has been removed.

Pip packaging:
- web-studio dist is now shipped inside the wheel under
  `openviking/web_studio/dist/` (mirroring the old `openviking/console/static/`
  layout). The dockerfile copies `--from=web-studio-builder /web-studio/dist`
  into the source tree before `uv sync`, so the wheel produced by the
  default docker build always carries the SPA. Building the wheel without
  running `npm run build` first leaves the directory empty, which gracefully
  degrades /studio to a 404 without breaking server startup.
- Favicon assets (`favicon.ico` / `favicon-32.png` / `apple-touch-icon.png`,
  ~11 KB total) are duplicated into `openviking/server/static/` and shipped
  via package-data so `/favicon.*` and `/mcp/favicon.*` routes are always
  registered, regardless of whether the web-studio dist is bundled.
- `pyproject.toml` and `setup.py` `package-data` drop `console/static/**`
  and add `server/static/**` + `web_studio/dist/**`.
- New favicons (the 16/32/180 set in both `openviking/server/static/` and
  `web-studio/public/`) are downscaled from the canonical
  `web-studio/public/openviking-icon.png`, so the small-icon family matches
  the SPA's high-res rel="icon" target — the studio tab icon now stays
  consistent whether the browser uses the HTML link tag or falls back to
  auto-fetching `/favicon.ico`.

Server:
- `openviking/server/app.py` now reads `/studio` from
  `Path(__file__).parent.parent / 'web_studio' / 'dist'` by default;
  `OPENVIKING_WEB_STUDIO_DIR` still wins for dev mode pointing at a
  repo-local build. Favicon routes are unconditionally registered and
  load from `openviking/server/static/`.
- `openviking/observability/usage_audit/projection.py` drops the legacy
  `/console/*` skip prefix (the BFF prefix `/api/v1/console/*` remains).

Docker:
- `web-studio-builder` stage moved earlier (Stage 2) so its dist can flow
  into `py-builder` before `uv sync` runs.
- Runtime stage no longer separately copies the dist or sets
  `OPENVIKING_WEB_STUDIO_DIR`; the in-package path is the default.
- Entrypoint renamed `openviking-console-entrypoint.sh` -> `openviking-entrypoint.sh`
  and stripped of the `python -m openviking.console.bootstrap` launch.
- `EXPOSE 1933 8020` -> `EXPOSE 1933`.
- `docker-compose.yml` drops the openviking service's 8020 port mapping;
  the caddy service stays but no longer needs port 8020 exposed.
- `Caddyfile` simplified to a single `:1934 { reverse_proxy openviking:1933 }`
  — the legacy `/console/*` route to :8020 is gone.

Docs:
- en/zh quickstart updated to drop the 8020 mapping and explain that the
  API server now also serves `/studio`.
- Other guides (`12-public-access.md`, `11-oauth.md`, `05-observability.md`,
  `04-setup-for-agent.md`, `03-deployment.md`) are intentionally left for a
  focused follow-up PR alongside the OAuth quick-authorize reintroduction.

Tests:
- Deleted `tests/misc/test_console_{proxy,static_assets}.py` (covered the
  removed console package). `tests/observability/test_console_router.py`
  stays — it covers the BFF, which remains.
2026-05-21 16:41:29 +08:00
CuSO41108 4d406b76c8 docs: fix Chinese quickstart authentication links (#2152) 2026-05-21 14:14:02 +08:00
Evo 344bc71f92 docs(server): document public_base_url and upload_signed_ttl_seconds (#1847) (#2153)
* docs(server): document public_base_url and upload_signed_ttl_seconds (#1847)

* docs(server): document public_base_url and upload_signed_ttl_seconds (#1847) — ZH mirror
2026-05-21 14:13:06 +08:00
Evo 27ed1e1d81 docs(api): document Watch Management endpoints from #2110 (#2123)
* docs(api): document Watch Management endpoints from #2110

* docs(api): document Watch Management endpoints from #2110 (ZH)
2026-05-20 13:36:37 +08:00
Evo c11e19fdcd docs(mcp): document list_watches and cancel_watch in MCP integration table (#2110) (#2134)
* docs(mcp): document list_watches and cancel_watch in MCP integration table (#2110)

* docs(mcp): mirror Watch tools table update to zh guide (#2110)
2026-05-20 13:35:38 +08:00
t0saki 41a33ec16a feat(mcp): progressive single-entrypoint upload for local files (#1847)
* feat(mcp): progressive single-entrypoint upload for local files

Extends `add_resource` MCP tool to handle local-file paths via a server-orchestrated
two-step flow, eliminating the need for `ov` CLI in sandboxed agent environments
(Claude web, Manus) where local FS is unavailable and CLI install is blocked.

Behavior:
- Remote URL  → unchanged.
- Local path  → server mints a 6-char base62 token, returns prose Step 1 / Step 2
                instructions pointing at /api/v1/resources/temp_upload_signed.
                Agent uploads, then re-calls add_resource(temp_file_id=...).
- temp_file_id → resolved against per-tenant subdir, ingested via existing pipeline.

Token: in-memory dict, 10-min TTL, dict.pop doubles as replay protection.
Per-tenant temp-dir isolation ({root}/{aid}/{uid}/{tfid}); legacy CLI uploads
keep flat layout via dual-lookup in resolve_uploaded_temp_file_id.

Public base URL resolves env > config > listen-host fallback (12-factor: runtime
env trumps image-baked config; production deployments behind MCP proxy + nginx
must set OPENVIKING_PUBLIC_BASE_URL since the agent-facing URL is not derivable
from the server's request scope).

* feat(mcp): infer public base URL from request headers + emit fallback hint

Adds a third fallback layer between explicit operator config and listen-host
fallback: capture X-Forwarded-Host / X-Forwarded-Proto / Host headers in the
MCP identity middleware and use them when neither OPENVIKING_PUBLIC_BASE_URL
nor ServerConfig.public_base_url is set.

Resolution order is now: env > config > X-Forwarded-* > Host > listen-host.
The first two are explicit; the rest are inferred. When an inferred source is
used, the add_resource prose response appends a troubleshooting hint asking
the user to set OPENVIKING_PUBLIC_BASE_URL on the server if upload fails —
because inferred URLs can be wrong if the reverse-proxy chain doesn't forward
X-Forwarded headers, or if the server listens on 0.0.0.0.

Documents the variable in docker-compose.yml (commented-out env block) and
in the MCP integration guides (zh + en) — covers when it's required and the
full resolution chain.

* fix(mcp): address Copilot review on PR #1847

- Relax temp_file_id regex from `[a-zA-Z0-9]+` extension to any non-separator
  chars, and dedupe to a single TEMP_FILE_ID_RE in local_input_guard. The old
  pattern rejected `Path("report.my-file").suffix == ".my-file"` and similar
  legitimate filenames, breaking the progressive upload flow.
- Hoist `_resolve_temp_or_path` import to module level in mcp_endpoint
  (verified no circular import).
- Add `_is_safe_namespace_component` defense-in-depth at the signed-upload
  route so a future code path that mints tokens from less-trusted input
  still cannot escape the per-tenant directory.
- Broaden partial-file cleanup to any exception via try/finally + flag,
  not just HTTPException — prevents OSError/IO failures from leaving
  half-written files behind.
- Scope `_cleanup_temp_files` to the tenant subdir at the signed-upload
  route to bound the rglob scan; the legacy `/temp_upload` route still
  cleans the root level.
- Add round-trip test for unusual filename extensions (.my-file, .bak~, .中文).

* docs(mcp): reflect server-minted temp_file_id in progressive-upload flow

Post-rebase onto TempUploadStore, the agent no longer learns the temp_file_id
from the MCP prose — the server mints it at upload time and returns it in the
JSON response body. Update both en + zh docs accordingly. Also note that the
signed endpoint shares the same persistence layer as /temp_upload, so
local/shared modes (and multi-worker via shared) apply uniformly.

* fix(mcp): address Copilot review on rebased PR #1847

- Drop `upload_signed_max_bytes` config field. The signed endpoint now relies on
  TempUploadStore's streaming `temp_upload.shared_max_size_bytes` check (single
  source of truth, fires even when Content-Length is missing/chunked). Map
  oversize from InvalidArgumentError back to 413.
- Normalize `X-Forwarded-Host` / `X-Forwarded-Proto` to the first comma-separated
  value in `_resolve_public_base_url`, matching the OAuth issuer resolver. Fixes
  malformed upload URLs under multi-hop proxy chains.
- Complete the `public_base_url` field comment to reflect all five fallback layers
  in the resolver, not just env > field > listen.
- Add `watch_interval` / `to` parameters to the MCP tool tables in both en + zh
  integration guides — they were merged in from main's Watch Management API
  during the rebase but the table wasn't updated.
2026-05-19 12:32:45 +08:00
Qin Haojie 9846bbca5d fix(vlm): honor LiteLLM native routes (#2111) 2026-05-18 17:11:01 +08:00
Qin Haojie 578148a855 docs: clarify resource API field names (#2107) 2026-05-18 14:57:43 +08:00
Simon Shiandqin-ctx 72b407ffa8 feat(embedder): expose encoding_format for OpenAI/Azure providers (#2092)
* feat(embedder): expose encoding_format for OpenAI/Azure providers

The OpenAI Python SDK 2.x defaults to encoding_format="base64" so the
client can decode embeddings into native float arrays locally. Some
self-hosted or vendor-fronted OpenAI-compatible gateways cannot
deserialize base64 embedding payloads coming back from upstream models
and silently hang for tens of seconds before returning HTTP 500 (e.g.
gateways that wrap providers like Qwen, GLM, Doubao, etc. behind a
strongly-typed Java SDK).

Add an optional `encoding_format` field on EmbeddingModelConfig that
gets forwarded to OpenAIDenseEmbedder. The field is unset by default,
so existing deployments keep the SDK's default behavior. Users hitting
the base64 incompatibility can set:

    "embedding": {
      "dense": {
        "provider": "openai",
        "encoding_format": "float",
        ...
      }
    }

Wiring is intentionally limited to provider="openai" and
provider="azure" — the only two factory branches that route to
OpenAIDenseEmbedder for an actual upstream HTTP gateway. Other
providers either don't expose this knob (volcengine/vikingdb/jina/...)
or run against local stacks where the issue cannot occur (ollama).

* test(embedder): improve encoding_format validation error handling

- Add ValidationError import from pydantic for explicit exception handling
- Update test_rejects_unknown_value to assert ValidationError instead of generic Exception
- Improve test specificity by catching the exact validation error type raised by pydantic models

* docs(embedder): complete encoding_format configuration guide

---------

Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
2026-05-18 14:13:03 +08:00
Evo b1c3936ae5 docs(en/metrics): add per-channel one-turn resolution PromQL example from #2037 (#2082) 2026-05-18 14:08:23 +08:00
Evo 2146f85b99 docs(deployment): document embedding + ollama probes on /ready from #1910 (#2086)
* docs(deployment): document embedding + ollama probes in /ready response (EN)

* docs(deployment): document embedding + ollama probes in /ready response (ZH)
2026-05-18 14:07:15 +08:00
Evo 1d34e23aaa docs(changelog): add v0.3.17 entry (EN+ZH) (#2088)
* docs(changelog): add v0.3.17 entry (EN)

* docs(changelog): add v0.3.17 entry (ZH)
2026-05-18 14:06:45 +08:00
LinQiang391andLinQiang391 933ece4acb docs(openclaw): use canonical OpenViking plugin package (#2099)
Co-authored-by: LinQiang391 <linqiang391@users.noreply.github.com>
2026-05-18 10:55:01 +08:00
Evo bc8fe8be67 docs(openclaw): document plugin-source / plugin-package and plugin-version auto-detect from #2072 (#2077)
* docs(openclaw): document plugin-source / plugin-package and plugin-version auto-detect from #2072 (en)

* docs(openclaw): document plugin-source / plugin-package and plugin-version auto-detect from #2072 (zh)
2026-05-15 20:44:49 +08:00
Evo debf5f2b52 docs(observability): document server.observability.dump_body from #2052 (#2063)
* docs(observability): document server.observability.dump_body from #2052

* docs(observability): document server.observability.dump_body from #2052 (EN)
2026-05-15 18:11:12 +08:00
yepper 9ebfd59342 feat(metrics): add vikingbot feedback observability (#2037)
* feat(metrics): add vikingbot feedback observability

* fix(bot): align feedback observability contracts

* fix(metrics): decouple feedback collector bootstrap
2026-05-15 17:30:24 +08:00
MaojiaSheng f45b22a9a8 fix: backup vlm token usage stat (#2068)
* ov vlm circuit_breaker

* ov vlm failover

* fix: ov vlm failover

* fix: ov vlm failover
2026-05-15 16:31:36 +08:00
Zayn JarvisandClaude Opus 4.6 910e9dc1c9 docs: replace indigo favicons with crystal sailboat (#2067)
Update favicon-32.png, apple-touch-icon.png, and favicon.ico
in both docs/images/ and openviking/console/static/.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 15:08:20 +08:00
Zayn JarvisandClaude Opus 4.6 d1c0730484 docs: update readme logo to crystal sailboat (#2066)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 14:36:15 +08:00
t0saki 42484bf91d fix(plugin/codex): default-on assistant capture, recommend env vars over ov.conf for tuning (#2065)
Two related fixes to plugin tuning ergonomics:

1. `captureAssistantTurns` defaults to true (mirrors claude-code-memory-plugin).
   A memory plugin that only captures the user side of every turn extracts
   half the conversation and produces noticeably worse memories. Operators
   who want the old user-only behavior can still set
   `OPENVIKING_CAPTURE_ASSISTANT_TURNS=0` or `codex.captureAssistantTurns=false`.

2. README + agent-integrations docs (zh+en) now recommend `OPENVIKING_*`
   environment variables in shell rc as the primary way to tune the plugin.
   The previous docs claimed the tuning block lived in `ovcli.conf`, but
   `scripts/config.mjs` only reads `codex.*` from `ov.conf` — and `ov.conf`
   is server-scope, so per-machine plugin tuning doesn't belong there
   anyway. The legacy `ov.conf` path is acknowledged and kept working for
   backward compat, but de-emphasized.
2026-05-15 13:07:33 +08:00
Evo 8f9e1c0d97 docs(api): document observer.filesystem from #2045 (#2057)
* docs(api): document observer.filesystem from #2045

* docs(api): document observer.filesystem from #2045

* docs(metrics): list filesystem component from #2045

* docs(metrics): list filesystem component from #2045
2026-05-15 11:27:05 +08:00
Qin Haojie 77b604a641 fix(storage): 优化路径锁与语义刷新并发 (#2029)
* fix(storage): refine path lock semantic refresh concurrency

Use exact path locks for source commits, tree locks only for lifecycle and schema scopes, and coalesce derived semantic writes to avoid stale summary overwrites under concurrent resource and memory updates.

* chore: split benchmark changes into separate PR

* chore: keep semantic refresh design notes out of docs

* style: format lock changes

* fix: preserve resource lifecycle locks

* Revert "fix: preserve resource lifecycle locks"

This reverts commit d2fb274f85.

* fix(resource): simplify lifecycle locking

* fix(queuefs): consolidate semantic sidecar writes
2026-05-14 20:44:28 +08:00
Evo e80b0a0ff8 docs(vlm): document backup config for automatic failover from #2040 (#2042)
* docs(vlm): document backup config for automatic failover (#2040)

* docs(vlm): mirror backup config doc to zh (#2040)
2026-05-14 20:22:20 +08:00
AutoCoderandClaude Sonnet 4.6 185bce8934 docs(design): consolidate openclaw plugin docs into single design doc (#2043)
Replace openclaw-integration.md and openclaw-context-engine-refactor.md
with openclaw-plugin-design.md covering the three main chains (assemble,
afterTurn, compact), session mapping, tool registry, and config reference.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 17:02:33 +08:00
t0saki c73a32f270 fix(plugin/codex): allow empty api_key (unauthenticated local OV) (#2023)
* fix(plugin/codex): allow empty api_key (unauthenticated local OV)

Reported: with an ovcli.conf that has no `api_key` (typical local OV
without auth), the plugin would not start cleanly. Root cause: .mcp.json
ships with `bearer_token_env_var: "OPENVIKING_API_KEY"`, and when that
env var resolves to an empty string at codex launch (because ovcli.conf
has no key), Codex interprets it as "auth configured but not provided"
and falls back to its OAuth dance — which then fails against an OV that
doesn't speak OAuth.

Hook side is unaffected: scripts/config.mjs already gates the Bearer
header on `if (cfg.apiKey)`, so empty api_key → no Authorization header
sent → OV accepts in unauth mode. Verified end-to-end with auto-recall
against `http://127.0.0.1:1933` and an empty-key ovcli.conf.

Fix: at install time, detect whether ANY api_key is configured (env or
ovcli.conf) and conditionally render `.mcp.json` *with or without*
`bearer_token_env_var`:

  - api_key present → keep `bearer_token_env_var: "OPENVIKING_API_KEY"`
  - api_key absent  → drop the field entirely (Codex will then just hit
                      OV without Authorization and treat 200 as success)

Implementation uses node (already required) to read/edit the cached
.mcp.json as proper JSON rather than sed, so we don't have to worry
about field-position-dependent regexes.

Installer footer now also reports the resolved auth mode so the user
sees `MCP auth: Bearer (OPENVIKING_API_KEY)` vs `MCP auth: none
(unauthenticated)` at the end of the run.

env_http_headers stays in both modes — identity headers
(X-OpenViking-Account / User / Agent) are independent of auth and OV
accepts empty values (defaults to "default").

* fix(plugin/codex): support runtime OPENVIKING_CLI_CONFIG_FILE swap

Reported: setting OPENVIKING_CLI_CONFIG_FILE=ovcli-local.conf (a config
without api_key, for benchmark-memory isolation) and running codex fails
with:

  Environment variable OPENVIKING_API_KEY for MCP server 'openviking-memory'
  is empty

Two issues stacked on top of each other:

1. Codex 0.130 hard-fails MCP startup when bearer_token_env_var resolves
   to an EMPTY env var (confirmed empirically — not OAuth fallback, just
   a startup error).

2. The previous codex() wrapper exported `OPENVIKING_API_KEY=""` via the
   inline-prefix syntax `OPENVIKING_API_KEY="${...:-${...:-}}" codex`,
   which sets the variable to an empty string when no key is resolvable.
   So even my prior fix (don't render bearer_token_env_var when no key
   at install time) didn't help users who install with one conf and run
   with another via OPENVIKING_CLI_CONFIG_FILE.

Fix is two parts:

a) Build the env prefix dynamically into a bash array, skipping any
   OPENVIKING_* whose resolved value is empty. So an empty api_key
   produces no OPENVIKING_API_KEY at all in codex's env — neither
   set-to-empty nor set-to-something.

b) Have the wrapper re-render the cached .mcp.json's bearer_token_env_var
   on every codex launch based on the currently-active ovcli.conf. The
   idempotent fast-path skips writing when the desired state already
   matches. This makes swapping configs at runtime (typical benchmark
   isolation workflow) work without re-running the installer.

The wrapper now uses `env "${_env_args[@]}" codex "$@"` instead of the
inline-prefix form for the same reason — proper handling of conditional
env-var presence.

Manual setup snippets in README + docs (en/zh) updated to the same
empty-aware pattern; the cache-rendering bit is left to the installer-
emitted wrapper since it's noisy and only needed when actually swapping
configs.

Validated with synthetic test:

  ovcli-local.conf (no api_key)
    → env passed to codex: URL=..., ACCOUNT=..., USER=..., AGENT_ID=codex
      (no OPENVIKING_API_KEY at all)
    → cache .mcp.json rewritten to drop bearer_token_env_var

  ovcli.conf (with api_key)
    → env passed to codex: URL=..., API_KEY=..., ACCOUNT=..., USER=..., AGENT_ID=codex
    → cache .mcp.json rewritten to re-add bearer_token_env_var

  Idempotent: re-render with same hasKey state does not bump file mtime.

* fix(plugin/codex): wrapper also re-renders cache .mcp.json URL

Previously the codex() wrapper only re-rendered bearer_token_env_var
based on the active ovcli.conf, but the cached .mcp.json URL stayed
whatever was baked at install time. Result: swapping
OPENVIKING_CLI_CONFIG_FILE to a config that points at a different OV
server (e.g. localhost) would still hit the install-time URL —
typically the remote production OV — and fail auth.

Reported in testing:

  OPENVIKING_CLI_CONFIG_FILE=ovcli-local.conf codex
  # ovcli-local.conf: { "url": "http://127.0.0.1:1933" }
  # cache .mcp.json still says url=https://ov-dev.tosaki.top/mcp
  # Codex hits remote ov-dev with no bearer → 401 → "Not logged in" OAuth dance

Fix: the rewrite block now also patches s.url from the conf-resolved
URL (`${_ov_url%/}/mcp`, or `$OPENVIKING_MCP_URL` if explicitly set).
Same idempotent fast-path — only writes when something actually changed.

Tested both directions:
  ovcli-local.conf (no key, localhost)
    → cache .mcp.json: url=http://127.0.0.1:1933/mcp, no bearer field
    → env passed to codex: no OPENVIKING_API_KEY
    → /mcp: Auth: None, tools list populated
  ovcli.conf (with key, remote)
    → cache .mcp.json: url=https://ov-dev.tosaki.top/mcp, bearer present
    → /mcp: Auth: Bearer token, tools list populated
2026-05-13 21:40:30 +08:00
t0saki b0076110ae refactor(plugin/codex): switch MCP from local stdio to OV /mcp directly (#2022)
* refactor(plugin/codex): switch MCP from local stdio server to OV /mcp (http)

Codex 0.130 supports streamable-HTTP MCP servers with bearer auth via
`bearer_token_env_var` in `.mcp.json` (and per-header env binding via
`env_http_headers`). OpenViking server has exposed `/mcp` natively since
1.27, so the local stdio MCP middleman (`src/memory-server.ts` +
`servers/memory-server.js` + the npm-ci runtime bootstrap) is dead weight:
the model now gets a strictly larger tool set (search, store, read, list,
grep, glob, forget, add_resource, health — vs the previous recall/store/
forget/health) by talking to OV directly, and the plugin loses its only
build/dependency surface.

What changed

- `.mcp.json`: switched to `url` + `bearer_token_env_var: "OPENVIKING_API_KEY"`
  + `env_http_headers` for the multi-tenant identity headers. URL is a
  `__OPENVIKING_MCP_URL__` placeholder; installer renders it from ovcli.conf
  / `OPENVIKING_URL` at install time. API key never lands on disk in the
  cached .mcp.json — it's pulled from process env at codex launch.

- `setup-helper/install.sh`: resolves the OV /mcp URL (OPENVIKING_MCP_URL >
  OPENVIKING_URL/mcp > ovcli.conf.url/mcp > localhost), renders the
  .mcp.json placeholder into the cached copy, and appends a `codex()` shell
  function wrapper to the user's rc that promotes ovcli.conf fields into
  env vars before exec'ing codex (mirrors the claude-code-memory-plugin
  pattern; needed because Codex reads OPENVIKING_API_KEY from process env
  at MCP launch, not from any file).

- Deleted: `src/memory-server.ts`, `servers/memory-server.js`, `tsconfig.json`,
  `package.json`, `package-lock.json`, `scripts/bootstrap-runtime.mjs`,
  `scripts/runtime-common.mjs`, `scripts/start-memory-server.mjs`. Net
  ~2400 lines removed. Hook scripts remain zero-dep .mjs running on
  Codex's bundled Node 22.

- README + docs/{en,zh}/agent-integrations/04-codex.md: rewritten to
  describe the new architecture. The MCP tools list and protocol details
  are now referenced via a link to docs/{en,zh}/guides/06-mcp-integration.md
  rather than duplicated in the plugin docs.

- Plugin version: 0.4.1 → 0.5.0.

Validation

Verified end-to-end on Codex 0.130 against `ov-dev.tosaki.top`:

  /mcp
  🔌 MCP Tools
    • openviking-memory
      • Auth: Bearer token
      • Tools: add_resource, forget, glob, grep, health, list, read, search, store

`openviking-memory.health` returned `OpenViking is healthy ... storage: VikingFS`;
Stop hook reported `appended 2 turn(s) to OpenViking session <id>`.

Notes

- `.mcp.json` headers that don't have a corresponding env var (e.g. user
  didn't set `OPENVIKING_USER`) are simply not sent — `env_http_headers`
  silently omits missing vars per Codex's MCP runtime.
- Rotating the API key now just needs `codex` restart (env re-reads from
  ovcli.conf via the wrapper). URL changes still need a re-install since
  the URL is baked into the cached .mcp.json.
- The shell function wrapper has a marker-delimited block so re-running
  the installer replaces it in place rather than appending duplicates.

* review(plugin/codex): address copilot feedback on installer + docs

1. Switch the codex() shell-function wrapper from jq to node. The installer
   already hard-requires node 22+, while jq is not always present; the old
   wrapper would silently fall through to `command codex` with no env
   injection when jq was missing, which caused Codex to start with no
   Bearer token, OV to return 401, and Codex to drop into its OAuth
   fallback. Now there is a single tool dependency for both the installer
   and the wrapper it emits.

2. Marker-replacement is now defensive: rewrite-in-place only triggers
   when BOTH the BEGIN and END markers exist in the rc. If only BEGIN
   is present (manual edit / corruption), warn and append a fresh block
   instead of awk-dropping everything from BEGIN to EOF.

3. When no rc is detected, omit the `source $RC` line from the final
   "Next:" hint and tell the user to paste the snippet manually instead
   of printing `source ` with a trailing space.

4. Docs (README + 04-codex.md zh/en): use the full env var names
   (OPENVIKING_API_KEY / OPENVIKING_ACCOUNT / OPENVIKING_USER /
   OPENVIKING_AGENT_ID) instead of `_ACCOUNT` / `_USER` shorthand;
   update the manual-setup snippets to the node-based wrapper.

The wrapper body is now defined once and reused for both the appended-to-rc
path and the manual-paste path, so the two cannot drift.
2026-05-13 21:08:57 +08:00
t0saki 8034abc158 docs(plugin/codex): dedicated agent-integrations page (zh+en) + fix MCP startup (#2019)
* docs(plugin/codex): add dedicated agent-integrations page + fix MCP startup

Follow-up to #1957. Lifts Codex out of `04-other-plugins.md` into its own
`04-codex.md` (en + zh) with full install steps, configuration, hook
behavior, and troubleshooting — mirrors the shape of `02-claude-code.md`.

Renumbers `04-other-plugins.md` → `05-` and `05-langchain-langgraph.md`
→ `06-`. Overview tables in both locales updated; cross-refs fixed.

Also fixes two install/runtime bugs surfaced while validating the fresh
installer flow against the merged PR:

1. **Stale repo clone**: `setup-helper/install.sh` previously skipped the
   clone if `~/.openviking/openviking-repo` already existed, so a user
   who installed before #1957 merged ended up with a pre-PR plugin
   checkout (no `scripts/`, no `servers/memory-server.js`). The installer
   now `git fetch + reset --hard` an existing checkout to `$REPO_REF`
   (default `main`), matching the claude-code installer pattern.

2. **`${CODEX_PLUGIN_ROOT}` not expanded in `.mcp.json`**: Codex 0.130
   does not substitute env vars in `.mcp.json` `args`/`env` and does not
   always inject `CODEX_PLUGIN_ROOT` into MCP child env. The literal
   string `${CODEX_PLUGIN_ROOT}` was being passed to node, which then
   tried to resolve `${CODEX_PLUGIN_ROOT}/scripts/start-memory-server.mjs`
   against codex's cwd and failed with `MODULE_NOT_FOUND`. Fix:
   - `.mcp.json`: `args: ["scripts/start-memory-server.mjs"]` + `cwd: "."`
     (matches the syntax 0.1.0 used, which Codex does honor)
   - `scripts/runtime-common.mjs`: derive plugin root from
     `import.meta.url` as a fallback so the launcher works regardless of
     whether `CODEX_PLUGIN_ROOT` is set in the spawn env

Bumps plugin to 0.4.1 (package.json + plugin.json + lockfile) since the
runtime-common.mjs change invalidates the install-state hash and forces
a re-install of node_modules into the per-user runtime data root.

* fix(plugin/codex): hooks.json must use relative paths, not ${CODEX_PLUGIN_ROOT}

Same root cause as the .mcp.json fix in the previous commit: Codex 0.130
does not expand ${CODEX_PLUGIN_ROOT} in hooks.json `command` strings. The
shell that runs the hook sees the literal ${CODEX_PLUGIN_ROOT} and expands
it to "" (or leaves it literal), so node tries to load `/scripts/...mjs`
and exits 1.

Symptom in the chat UI:
  • SessionStart hook (failed)  error: hook exited with code 1
  • UserPromptSubmit hook (failed)
  • Stop hook (failed)

Fix: use `./scripts/<name>.mjs` paths, matching the pattern Codex's own
bundled plugins (e.g. figma) use. Codex's hook dispatcher resolves these
relative to the plugin root (where hooks.json lives).

The MCP launcher fix from the prior commit already handles the same class
of bug for .mcp.json; this catches the hooks path.

* fix(plugin/codex): hooks.json needs absolute paths rendered at install time

Previous fix (relative ./scripts/...) was based on the figma example but
empirically does not work on Codex 0.130: the hook subprocess runs with
cwd = user's cwd (not plugin root) and CODEX_PLUGIN_ROOT is NOT injected
into the env. So both ${CODEX_PLUGIN_ROOT}/scripts/foo.mjs and
./scripts/foo.mjs resolve to the wrong absolute path and node exits 1.

Verified with a probe shell script wired into hooks.json:
  argv: /tmp/codex-hook-probe.sh SessionStart
  cwd: /Users/<user>
  CODEX_PLUGIN_ROOT: <unset>
  CODEX_PLUGIN_DATA: <unset>

(The "Under-development features are incomplete" banner Codex prints when
plugin_hooks is enabled is real - the hook env wiring is unfinished in
0.130.)

Fix: keep the source hooks.json as a template (uses __OPENVIKING_PLUGIN_ROOT__
placeholder) and have install.sh sed-render the cache copy with the
absolute $CACHE_DIR path on every install. The cached hooks.json is now
fully self-contained absolute-path commands; the repo's checked-in copy
stays portable.

.mcp.json is unaffected: Codex 0.130 does honor the `cwd: "."` field for
MCP servers, so relative args resolve against plugin root there.

* fix(plugin/codex): bump UserPromptSubmit timeout to 15s

Empirically the auto-recall hook can take 0.8s–4s end-to-end (depending on
result count and remote OV latency), and Codex 0.130 sometimes adds 4-5s
of spawn overhead before our script even starts. The original 8s budget
was borderline and produced spurious "hook timed out after 8s" UI errors
on slow paths even when the recall would have succeeded.

15s matches the auto-recall internal timeoutMs default (config.mjs:186)
and gives enough headroom for spawn-time variance without holding the
user's input noticeably longer in the worst case.

* fix(plugin/codex): installer accepts OPENVIKING_REPO_BRANCH as alias

Per review feedback: the claude-code installer uses OPENVIKING_REPO_BRANCH
for the same purpose. Aliasing both names lets users reuse one env var
across installers without remembering which plugin uses which name.

Precedence: OPENVIKING_REPO_REF > OPENVIKING_REPO_BRANCH > "main".
2026-05-13 20:33:36 +08:00
e92180a7e1 feat(plugin/codex): add lifecycle hooks (recall, capture, pre-compact) to codex-memory-plugin (#1957)
* feat(plugin/codex): add lifecycle hooks (recall, capture, pre-compact)

Brings the codex-memory-plugin to feature parity with the claude-code-memory-plugin
by wiring the four Codex lifecycle hooks via `hooks.json`:

- SessionStart  -> bootstrap-runtime.mjs (npm ci into ${CODEX_PLUGIN_DATA}/runtime)
- UserPromptSubmit -> auto-recall.mjs (search OV, inject via hookSpecificOutput.additionalContext)
- Stop -> auto-capture.mjs (incremental transcript capture + last_assistant_message commit)
- PreCompact -> pre-compact-capture.mjs (full transcript -> single OV session -> commit)

Differences from the Claude Code plugin baked into the scripts:

- Codex output schema does not allow `decision: "approve"`; no-op is `{}`
- Stop/PreCompact only support `systemMessage`, not `additionalContext`
- Plugin envs are CODEX_PLUGIN_ROOT / CODEX_PLUGIN_DATA
- Config section is `codex` (was `claude_code`); config file defaults to
  `~/.openviking/ovcli.conf`, falling back to legacy `~/.openviking/ov.conf`

Other changes:

- src/memory-server.ts now reads ovcli.conf-style configs (top-level `url`,
  `api_key`, `account`, `user`, `agent_id`) so the plugin works against
  hosted OpenViking deployments out of the box. Env-var-only operation
  (OPENVIKING_URL set, no config file) is also supported.
- .mcp.json points at scripts/start-memory-server.mjs, which boots the same
  runtime the hooks use, so the MCP path benefits from npm-ci bootstrap.
- README rewritten with architecture diagram, validation SOP, configuration
  reference, and a Codex-vs-Claude-Code differences table.

Validated end-to-end against an OpenViking deployment:

- Auto-recall returns ranked memories with full content and emits
  hookSpecificOutput.additionalContext.
- Auto-capture (last_assistant_message path) creates a session, commits, and
  the OV pipeline extracts events + preferences within ~60s.
- Pre-compact-capture posts a full 4-turn transcript to one OV session,
  commits with archived=true, and produces structured leaf memories
  (preferences, events, entities) under viking://user/<user>/memories/.

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

* refactor(plugin/codex): drop SessionStart, split Stop=add_message vs PreCompact=commit

Codex's `Stop` hook fires per turn, not at session end, so committing per-Stop
over-fragments memory extraction. And codex re-fires `SessionStart` on short
reconnects, so registering an `npm ci` bootstrap there reinstalls the runtime
unnecessarily.

This change keeps one long-lived OpenViking session per codex `session_id`
across all `Stop` invocations, and only triggers the OV memory extractor on
`PreCompact` (or via an idle-sweep best-effort commit when codex exits without
compacting).

- hooks.json: drop SessionStart entry; keep UserPromptSubmit/Stop/PreCompact
- scripts/session-state.mjs (new): per-codex-session state under
  ~/.openviking/codex-plugin-state/, tracks ovSessionId + capturedTurnCount
- scripts/auto-capture.mjs (Stop): incremental add_message only, idle-sweep at
  the tail to commit stale codex sessions (default IDLE_TTL=30 min, override
  with OPENVIKING_CODEX_IDLE_TTL_MS)
- scripts/pre-compact-capture.mjs (PreCompact): catch-up append + commit the
  long-lived OV session, then null out ovSessionId so the next Stop opens a
  fresh OV session for the post-compact half
- MCP runtime install stays lazy in start-memory-server.mjs (already there);
  no SessionStart hook means short reconnects don't re-trigger npm ci
- VERIFICATION.md: end-to-end SOP against a live OV server (~3 min)
- bump plugin to 0.3.0

Verified end-to-end against ov.zaynjarvis.com:
  Stop adds turns idempotently and incrementally; PreCompact commits to
  history/archive_001/ with extractor producing memories under
  viking://user/<user>/memories/profile.md after ~30 s; post-compact Stop
  opens a fresh OV session; idle-sweep commits stale state files.

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

* refactor(plugin/codex): replace idle-sweep with SessionStart(source=clear) commit

Per Zayn's followup ("非必要不要加 idle commit"): drop the idle-sweep added
in the previous commit and use codex's actual context-disappearing signal —
SessionStart with source=clear — to commit orphaned sessions.

Codex hook signal map:
- /compact         → PreCompact      ✅ commit (already)
- /clear           → SessionStart(source=clear) for the NEW session_id;
                     the prior transcript is orphaned. Now committed.
- /new             → SessionStart(source=startup); ambiguous with fresh
                     codex startup, so we don't act on it.
- /resume / short reconnect → SessionStart(source=resume|startup); no-op
                     to avoid corrupting still-active sessions.
- SIGTERM/Ctrl+C/exit → no hook fires. Documented as a known gap; users
                     should /compact before /exit if they want commit.

Changes:
- new scripts/session-start-commit.mjs: gates internally on source=clear,
  iterates listStates(), and commits any state file whose codexSessionId
  != the new SessionStart session_id, then clears that state file
- hooks/hooks.json: re-register SessionStart pointing at the new script
  (timeout 30s)
- scripts/auto-capture.mjs: remove sweepIdleSessions() and
  IDLE_TTL_MS env handling; Stop is now strictly add_message
- README/VERIFICATION.md: update arch diagram, replace idle-sweep step
  with SessionStart(source=clear) verify (positive + negative paths),
  add "Known gap: SIGTERM/exit are silent" section
- bump to 0.3.1

Verified end-to-end against ov.zaynjarvis.com:
  Stop add+idempotent ✓
  SessionStart source=startup → {} ✓
  SessionStart source=resume → {} ✓
  SessionStart source=clear → committed prior OV session, history/archive_001/
  appeared, profile.md gained "Favorite snack: dark chocolate" within 30 s.

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

* chore(plugin/codex): SessionStart matcher = "clear" (native dispatcher gate)

Codex's hooks dispatcher matches the SessionStart hook's `matcher` field
against the SessionStart `source` value. Setting matcher to "clear" means
codex won't even spawn our script on `source=startup` or `source=resume`
(short reconnects); we previously gated this in-script. The internal
source check in session-start-commit.mjs is kept as defense-in-depth.

Source: codex-rs/hooks/src/events/session_start.rs `select_handlers(...,
matcher_input: Some(request.source.as_str()))` and
codex-rs/hooks/src/events/common.rs `is_exact_matcher` — "clear" is
all-alphanumeric so it's matched as exact equality, not regex.

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

* refactor(plugin/codex): active-window heuristic + idle-TTL sweep at SessionStart (v0.4.0)

Source of truth: examples/codex-memory-plugin/DESIGN.md (added in this commit).

Behavioral changes:

- SessionStart matcher widens from `clear` to `clear|startup`. Both sources
  run the same active-window heuristic; `resume` is a hard no-op (still fires
  on short reconnects).
- Heuristic (DESIGN.md §3): count state files (excluding new session_id) within
  ACTIVE_WINDOW_MS (default 2 min). 0 → noop, 1 → commit it (just-ended
  session), ≥2 → skip and rely on idle TTL. Tunable via
  OPENVIKING_CODEX_ACTIVE_WINDOW_MS.
- Idle-TTL sweep returns at the tail of session-start-commit.mjs only (not
  every Stop). Default IDLE_TTL_MS = 30 min via OPENVIKING_CODEX_IDLE_TTL_MS.
  Catches SIGTERM/Ctrl+C/`/exit` orphans and the ≥2-active skip path.
- Stop hook deliberately does NOT sweep — state-write-on-every-turn already
  gives us the freshness signal. Marker comment added.
- Stop hook adds post-compact transcript-shrink defense: if
  allTurns.length < state.capturedTurnCount, reset capturedTurnCount = 0.
- Commit-on-failure preserves state everywhere (PreCompact, heuristic,
  idle sweep). A non-2xx /commit no longer clears ovSessionId; the next
  sweep retries.
- session-state.mjs saveState now uses atomic write (tmpfile + rename) for
  crash safety. listStates ignores the brief `<id>.json.tmp` window.

Bump: package.json + .codex-plugin/plugin.json → 0.4.0.

Docs: README "How It Works" gained a DESIGN.md pointer and rewrites the
SessionStart section to reflect heuristic + idle TTL. VERIFICATION.md step 6
now exercises all four heuristic branches (0/1/≥2 active, idle TTL, resume).

Phase-2 resume context inject documented in DESIGN.md but explicitly out of
scope here.

Verified locally with synthetic stdin tests against a fake OV server:
1-active commit, ≥2-active skip, idle TTL sweep, resume noop,
unreachable-server keeps state.

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

* refactor(plugin/codex): align config loading with claude-code plugin

Addresses three review points on PR #1957:

1. Honor OPENVIKING_CLI_CONFIG_FILE for the ovcli.conf override path
   (matches the convention used by `ov` CLI and claude-code-memory-plugin).
   OPENVIKING_CONFIG_FILE stays as the ov.conf override; for backward
   compat it still works when pointed at an ovcli-shaped file.

2. Strict env-first priority for every connection / identity field
   (baseUrl, apiKey, account, user, agentId). Env vars now win over
   ovcli.conf, which wins over ov.conf's codex.* block / server.*,
   which wins over built-in defaults.

3. Unify hook and MCP-server config loading: src/memory-server.ts now
   imports loadConfig from scripts/config.mjs (relative path stays
   valid post-compile because servers/ and scripts/ are siblings),
   eliminating the divergent account/user/agentId fallback chains
   the PR-Agent reviewer flagged.

Auth header: emit Authorization: Bearer (primary, required by OpenViking
Cloud) plus the legacy X-API-Key during the transition window. All six
fetch sites updated (4 hook scripts + memory-server.ts + compiled
servers/memory-server.js).

README: document the new resolution chain, OPENVIKING_CLI_CONFIG_FILE,
OPENVIKING_BEARER_TOKEN alias, and the Authorization: Bearer migration.

* docs(plugin/codex): put installation first

* fix(plugin/codex): harden runtime and capture paths

* docs(plugin/codex): align local marketplace name

* docs(plugin/codex): add one-line installer

* fix(plugin/codex): support branch installer testing

* fix(plugin/codex): keep installer env surface stable

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: zhengxiao.wu <zhengxiao.wu@bytedance.com>
2026-05-13 19:25:30 +08:00
Jiahui Zhou fa0be9c958 feat: make queuefs backend configurable (#2018)
fix: harden request wait tracker against queue races

update

refactor queuefs mode config

docs: document queuefs mode and refactor mount resolver
2026-05-13 18:31:07 +08:00
Lumos088 6a65776b63 Add files via upload (#2013) 2026-05-13 15:31:36 +08:00
MaojiaSheng 15817dcf15 Revert "Feat/fs count api (#1989)" (#1997)
This reverts commit 3222b14d0c.
2026-05-12 21:01:48 +08:00
Ryanba 4f42c26225 docs(server): clarify Python 3.14 Ark warning (#1987) 2026-05-12 19:27:22 +08:00
dingbenanddingben.db@bytedance.com <dingben.db@bytedance.com@bytedance.com> 3222b14d0c Feat/fs count api (#1989)
* feat(fs): add count API for directory entry counting

Adds a dedicated `count` endpoint that returns the exact number of files
and sub-directories under a directory by traversing the filesystem,
distinct from `stat`'s vector-index-based estimate. Wired through
VikingFS, FSService, HTTP router and sync/async/local SDK clients.

* feat(cli): add `ov count` command for directory entry counting

Wires the new fs.count HTTP endpoint into the Rust CLI. Adds
`-r/--recursive` and `-a/--all` flags. Documentation updated with
CLI usage examples.

* fix

---------

Co-authored-by: dingben.db@bytedance.com <dingben.db@bytedance.com@bytedance.com>
2026-05-12 17:41:38 +08:00
Hao Zhe 81d1b5afd7 feat(langchain): add LangChain and LangGraph context adapters (#1964)
* feat(langchain-langgraph): add adapter primitives

* feat(langchain-langgraph): add context backend lifecycle

* fix(langchain-langgraph): harden context backend integration

* fix(langchain-langgraph): accept canonical store result URIs

* docs(langchain): point users to runnable examples

* docs(langchain): add missing integration examples

* refactor(langchain): address integration review feedback

* fix(langchain): address review-blocking integration bugs

* fix(langchain): honor user ids and safe store filters

* fix(langchain): reject unsupported store TTL writes
2026-05-12 16:28:11 +08:00
Asish Kumar 25e7615c51 feat(vlm): support extra request body passthrough (#1973)
Add VLM configuration support for provider-specific JSON body fields and pass them through to OpenAI-compatible and LiteLLM completion calls.

Document the option and cover OpenAI, LiteLLM, DashScope merge behavior, and legacy flat config migration.
2026-05-12 14:59:52 +08:00
MaojiaSheng c2345b9e6a feat: CLI optmization for counting (#1980)
* feat: ov add-resource (spec -L --level), ov stat (return count for dir)

* feat: ov add-resource (spec -L --level), ov stat (return count for dir)
2026-05-12 11:27:07 +08:00
Qin Haojie 5fdbfd4e49 feat(ovpack): support vector snapshots and consistency checks (#1965)
* feat(ovpack): add vector snapshot backup support

* feat(ovpack): add vector snapshots and consistency checks

* fix(ovpack): validate reserved paths and index expectations

* fix(ovpack): limit consistency report output

* fix(ovpack): isolate archive content namespace

* chore(ovpack): move consistency cli under system
2026-05-11 21:11:42 +08:00
Evo 68b049528d docs(observability): note ov tui image preview capability (#1917)
* docs(observability): note ov tui image preview capability

Follows volcengine/OpenViking#1916 (feat: ov CLI support) which added
image_preview.rs supporting png/jpg/jpeg/gif/bmp/webp/tiff/tif files.

* docs(observability): note ov tui image preview capability (zh mirror)
2026-05-11 20:22:20 +08:00
Evo db3d5db156 docs(storage): document task_tracker backend config from #1949 (#1971)
* docs(storage): document task_tracker backend config from #1949

* docs(storage): document task_tracker backend config from #1949 (ZH)
2026-05-11 20:20:17 +08:00
Evo 4237d5018f docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947 (#1948)
* docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947

* docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947

* docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947

* docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947

* docs(retrieval): align score_propagation_alpha default 0.5→1.0 with #1947
2026-05-11 18:00:39 +08:00
Evo 7c69819684 docs(telemetry): list session create/add_message endpoints + SDK methods (#1943) (#1958)
* docs(telemetry): list session create/add_message endpoints + SDK methods (#1943)

* docs(telemetry): 镜像 EN — list session create/add_message endpoints + SDK methods (#1943)
2026-05-11 17:59:45 +08:00
Evo 217eaa5448 docs(api): document isLocked field in stat() response (#1940) (#1956)
* docs(api): document isLocked field in stat() response (#1940)

* docs(api,zh): document isLocked field in stat() response (#1940)
2026-05-11 17:58:56 +08:00