Commit Graph
67 Commits
Author SHA1 Message Date
t0saki a83b81715b feat(uri)!: remove uid-less current-user shorthand in favor of viking://~ (#4196)
* 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.
2026-08-21 19:00:19 +08:00
t0saki c7044075ef feat(dsh): serve tools over the shared stdio MCP proxy (#4157)
* feat(dsh): serve tools over the shared stdio MCP proxy

Replace the dsh bundle's seven hand-registered `viking_*` tools with the
OpenViking MCP surface, reached through the same stdio proxy every other
memory integration starts, and collapse the four duplicated proxy
entrypoints onto a shared config builder.

The bundle now mounts `@deepseek-ai/dsh-mcp-client` (which ships with dsh
itself) on `servers/mcp-proxy.mjs`. Pointing an MCP SDK client straight at
the server's `/mcp` endpoint does not work: with `stateless_http=True` the
server still answers `GET /mcp` with an idle 200 SSE stream, and once the
SDK client opens that standalone stream it stops resolving POST responses,
so `tools/list` never returns. The stdio proxy owns the transport itself
and is unaffected.

`trimSlash`, `normalizePath`, `uniq`, the watched-credential-path list and
the cfg -> proxyConfig mapping existed in four near-identical copies
(claude-code, codex, opencode, agent-plugins; the last one carried a
"keep in sync with claude-code" comment). They move to
`memory-plugin-shared/lib/mcp-proxy-config.mjs` and all five entrypoints —
including the new dsh one — now shape their config through
`buildMcpProxyConfig`. Behavior is preserved per field, including codex's
explicit `mcpUrl` override, claude-code's `ovcli.conf` credential-source
probe, and opencode's extra watched config file.

The bridge is mounted last in `apply()` so a proxy that fails to start
cannot hold up profile injection, recall, capture, commit, or the URI
guard registrations above it.

* feat(dsh): add to the unified installer and ship the shared skill

The bundle now registers its own isolated `ctx.skills` provider serving the
shared `openviking-memory` skill, so DSH gets the same guidance the Claude
Code, Codex, and Cursor integrations ship. `sync.mjs` distributes the skill
to the bundle, and the provider uses `includeDefaultRoots: false` so it
never shadows DSH's own project/user skill catalog.

`install.sh` grows a `dsh` harness id, auto-detected like the others, plus a
profile prompt that defaults to `web` (`--dsh-profile` / `OPENVIKING_DSH_PROFILE`
answer it up front). The installer always installs the published package:
`dsh plugin` forwards to pnpm, and a linked source tree cannot resolve the
dsh peers the bundle imports because Node resolves them from the checkout's
realpath rather than from the profile.

Documentation is restructured around installing rather than internals. The
integration page now leads with the one-line installer and keeps behavior at
the level the other harness pages use, with configuration in a details block;
design rationale moves to the bundle README, which itself leads with Install
and groups the rationale under "Design notes". Capability-reference claims
that dsh is outside the unified installer are corrected.

* chore(dsh): release 0.2.0

The MCP tool surface, the stdio proxy transport, and the bundled skill all
change what the bundle does for an existing user, so this is a minor bump
rather than a patch. 0.1.0 remains the native-`viking_*` tool surface.

* docs(dsh): note pnpm's 24h minimum release age

pnpm 11 refuses releases younger than minimumReleaseAge (24 hours by
default), and surfaces it as a registry 404, so installing a freshly
published version reads as "the package does not exist".

* fix(dsh): honour dev source mode in the installer

install_dsh ignored SOURCE_MODE and always fetched the published package,
so selecting "current checkout" installed npm's build instead of the
working tree and validation still reported success.

npm is the bundle's only distribution channel, so the github/tos choice
does not apply to it: every mode except dev now installs the published
package, and dev packs the checkout with npm pack first. It has to arrive
as a real package rather than a link, because a linked source tree
resolves its dsh peers from its own realpath and misses the profile's
hoisted node_modules. The install line reports which source was used.

* fix(dsh): make repeated installs actually overwrite

Two ways a re-run silently kept stale code:

pnpm treats an already-satisfied version as a no-op regardless of which
tarball the file: dependency points at, so a dev re-install after editing
the checkout left the previous build in place. Local installs now drop the
package before adding it back; that is confined to local sources, since
doing it for the registry path would leave nothing installed when add
fails.

A bare package name has the same effect in reverse: a profile holding a
dev build satisfies it, so switching back to the published package was a
no-op. The registry path now asks for @latest.

The packed tarball is named after a fingerprint of the checkout's shipped
files, so an unchanged checkout skips the pack and keeps a stable path in
the profile lockfile.
2026-08-20 19:05:18 +08:00
98a0104aaa Fix/filter invalid attr tags (#4123)
* fix(fs): filter invalid tags from attrs

Hide legacy non key-value search tags from filesystem attributes while preserving valid tags. Add regression coverage for the read boundary.

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

* feat(session): update auto commit policy defaults

Raise token and message thresholds, clear the retained-message default, and expand the corresponding bounds. Synchronize the session API and configuration documentation.

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>
2026-08-19 21:11:18 +08:00
zgyandqin-ctx dc39985ad1 refactor: remove resource relation edges (#3956)
* refactor: remove resource relation edges

* fix: remove stale relation references

---------

Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
2026-08-19 17:54:29 +08:00
t0saki 458e7fae37 docs: add a cross-integration capability reference page (#4076)
* docs: fix integration docs and comments that contradict the code

- codex: credential resolution in the default `auto` mode is env-first — `credentials.mjs`
  only falls back to `ovcli.conf` when no credential env var is set, while the docs and the
  `config.mjs` header comment claimed `ovcli.conf` wins by default. Also document
  `OPENVIKING_CREDENTIAL_SOURCE=cli`, which was undocumented.
- codex: the four hook scripts send the key as `X-API-Key` in addition to
  `Authorization: Bearer`; the README documented Bearer only.
- claude-code: the OV session id is `cc-<cc_session_id>` verbatim (`deriveHarnessSessionId`
  does no hashing), not `cc-<sha256(cc_session_id)>`.
- claude-code: `hooks.json` registers 9 hooks, not 7 — the responsibilities table was
  missing the `PreToolUse` `viking://` guard and the `PostToolUse` skill-experience hook.
- claude-code: archival is triggered client-side (the `Stop` hook commits once
  server-reported pending tokens cross `commitTokenThreshold`, default 20000, plus
  unconditional commits from `PreCompact` / `SessionEnd` / `SubagentStop`). The README
  attributed it to a server-side `auto_commit_threshold`, but
  `memory.session_auto_commit.default_enabled` is false and no plugin sends a policy.
- trae / opencode: the MCP proxy transparently exposes the full server tool set (16 tools);
  the docs listed a 4-item sample or 11-13 tools and omitted `tree` / `write` / `edit`.
- trae-cli: the installer registers the MCP server as `openviking-memory`, but the verify
  step told users to look for `openviking`.
- pi: the manual install block omitted the `pi install <dest>` registration step that the
  one-click installer runs, so a hand-copied extension is never registered.
- install.sh: `--uninstall` handles cursor, trae, trae-cn, trae-cli and zcode; the `--help`
  text still said Cursor/TRAE only.
- mcp_endpoint.py: the module docstring enumerated 13 tools and omitted `recall`,
  `list_watches` and `cancel_watch`; replaced the stale enumeration with a pointer to the
  `@mcp.tool` registrations.

* docs: add a cross-integration capability reference page

The agent-integrations section had per-integration install guides but no place
to compare integrations against each other. This adds one bilingual page that
does that, and wires it into the existing pages in both directions.

- New page `docs/{en,zh}/agent-integrations/16-capability-reference.md`: a
  dimension-first comparison of every OpenViking integration — active tool
  surface, automatic hook surface, install/credential/config layering, recall
  and injection, session and commit lifecycle (including a shutdown-path x
  harness end-state matrix), compaction takeover, write/delete boundaries,
  degradation, and a per-harness profile card for each integration.
- Sidebar: `StructuredSidebarCopy` gains an optional `topItems` field so a
  section can list flat entries next to its overview; agent-integrations uses
  it to place the new page beside the overview. Other sections are unaffected.
- Links both ways: the overview and all 14 per-integration pages link to the
  reference, and the reference links back to each integration page from its
  profile card, from the non-coding integration table, and from the custom
  agent integration paths. Section cross-references (§x.x) are real in-page
  anchor links, generated from the built heading ids.
- trae-cli is documented as TraeCode CLI 2.0 only, installed through a codex
  plugin alias; 1.0 and its standalone plugin are called out as unsupported.
- The MCP tool surface is described as 15 tools throughout, matching the
  removal of the `recall` tool in favour of `search` with `mode="context"`.
  Pages outside this change that still mention an MCP `recall` tool
  (04-codex, 12-cursor, 15-agent-plugins, guides/06-mcp-integration) need a
  follow-up sweep once that removal lands.

* docs: 更新服务端 MCP 工具面描述,简化信息并明确更新方式
2026-08-18 20:38:06 +08:00
Zayn Jarvis c1fc0b730e docs(hermes): recommend memory setup openviking (#4098)
* docs(hermes): recommend memory setup openviking

Point Hermes docs at `hermes memory setup openviking` and describe the
real wizard. Shorten Volcengine console agent guides to TOS + cloud API
key, and mark docs/images as console-only.

* docs(hermes): drop setup filler

Keep the command and the two connection paths. Remove picker
explanations and wizard narration.

* docs: keep images AGENTS.md.local local-only

Ignore AGENTS.md.local like AGENTS.md. Drop the unused
docs/images/README.md.

* docs(console): keep harness setup to command plus API key

Drop installer narration, idempotency notes, and copied site
guides. Console pages only need the TOS command and cloud key.

* docs(console): restore Install / Verify / Troubleshoot

Keep the short cloud setup, put it back under the three section
headings the console pages use.

* docs(console): add Reference links

Point each harness page at docs.openviking.net, the coding-agent
blog where it exists, and the example source.

* docs(console): label Reference as manual settings and blog

Use Docs on Manual Settings for the full site page. Use Blog
about how it works where a how-it-works writeup exists.
2026-08-18 20:19:29 +08:00
t0sakiandTRAE CLI add72f9bed feat(plugins): install TraeCode CLI 2.0 via Codex alias (#4079)
* feat(plugins): install TraeCode CLI via Codex alias

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

* fix(installer): keep trae-cli as public harness

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

---------

Co-authored-by: TRAE CLI <traecli@bytedance.com>
2026-08-18 16:21:47 +08:00
t0saki eb5aaf78e9 feat(mcp): consolidate recall into context search (#4075) 2026-08-18 12:45:45 +08:00
b7aa01d227 feat(plugins): add OpenViking memory integration for TRAE CLI (#4026)
* feat: add OpenViking memory integration for TRAE CLI

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

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

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

* fix: keep TRAE CLI installation explicit

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

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

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

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

---------

Co-authored-by: “bianhaonan” <“bianhaonan@bytedance.com”>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
2026-08-17 14:59:43 +08:00
t0sakiandZayn Jarvis 8abd61fcb6 feat(plugins): add Agent Plugins 1.0 portable package (#3998)
* feat(plugins): add Agent Plugins 1.0 portable package

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

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

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

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

Based on #3994 by @ZaynJarvis.

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

* docs(agent-plugins): pluralize README title

---------

Co-authored-by: Zayn Jarvis <zaynjarvis@gmail.com>
2026-08-14 14:33:54 +08:00
ManAsWindandlinweiye 2e9b6610ab docs: refine DeerFlow agent integration guide (#3968)
* docs: add DeerFlow agent access guide

* docs: refine DeerFlow and Hermes agent guides

---------

Co-authored-by: linweiye <linweiye.voph@bytedance.com>
2026-08-13 15:31:45 +08:00
t0saki 7e26fab61c fix(memory-plugins): report tool output verbatim, let the server externalize (#3933)
Coding-agent plugins capped a tool part's `tool_output` at 2000 chars before
POSTing it to `/api/v1/sessions/{id}/messages`. That cap sits below the server's
own externalization threshold (`tool_output_externalization.threshold_chars`,
default 20000), so output in the 2k-20k band was destroyed for no reason and
anything larger never reached `ToolResultStore` - leaving `tool_output_ref`
permanently empty and the `/tool-results` read-back path unusable.

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

Also stop pi from sending tool output twice: for a tool-only payload the
rawText-derived text part re-rendered the same output the tool part carries.
2026-08-11 19:17:54 +08:00
Qin Haojie 7abd6ab249 refactor(client): remove Python embedded mode (#3712)
* refactor(client): remove Python embedded mode

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

* refactor(client): remove obsolete embedded leftovers
2026-08-10 18:00:00 +08:00
t0saki 674f5e6039 fix(retrieval): honor context tier ceilings and stop cooling unserved recalls (#3746)
* fix(retrieval): honor tier ceilings and stop cooling unserved recalls

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

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

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

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

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

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

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

New assembly kernel under openviking/retrieve/context_assembler/:

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

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

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

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

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

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

Assembly fixes found alongside:

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

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

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

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

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

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

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

* refactor(plugins): unify recall compression setting

* feat(plugins): enable recall compression by default

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

* fix(retrieval): address context assembly review feedback

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

* test: trim redundant context assembly coverage

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

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

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

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

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

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

* fix(retrieval): preserve recall compatibility

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

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

---------

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

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

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

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

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

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

Closes #3127
Related: #3442, #3544

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Fix two bugs found in code review pass 2:

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

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

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

29/29 tests pass (was 27).

* test(zcode): add concurrent session isolation tests

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

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

31/31 tests pass (was 29).

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

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

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

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

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

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

---------

Co-authored-by: woshiguanxiaoliang <woshiguanxiaoliang@noreply.gitcode.com>
2026-08-04 11:58:18 +08:00
t0saki e910c5feb0 fix(packaging): decouple langchain client from server (#3711) 2026-08-03 21:56:49 +08:00
Hao Zhe b2e1972610 refactor(langchain): extract standalone integration package (#3685)
* refactor(langchain): extract standalone integration package

* fix(langchain): preserve optional legacy imports

* fix(langchain): guard legacy submodule imports
2026-08-03 15:01:13 +08:00
Hao Zhe c1d38eb47f feat(langchain): support request-scoped actor peers (#3626) 2026-08-01 22:55:33 +08:00
Hao Zheandzhiheng.liu de9c3cec15 fix(storage): preserve deletion and session durability (#3553)
* fix(ragfs): preserve cache visibility on partial S3 deletes

Surface exact and per-object S3 deletion failures, while always invalidating the affected directory and stat cache scope after a recursive delete attempt.

Source-PR: #3407
Original-Commit: 8d6addf28e

* fix(session): preserve legacy policy and peer identity compatibility

Parse string false and other legacy boolean-like memory policy values without silently enabling extraction or breaking persisted configs. Encode mixed-script peers losslessly, while retaining their former lossy IDs as read-only retrieval and extraction aliases.

Source-PR: #3422
Original-Commit: 0dfd5a9ed9

* fix(memory): drain timer flush tasks during shutdown

Retain the shielded timer flush task and await it when close cancels the timer loop, so batch failures are observed and submitters are resolved without unhandled task exceptions.

Source-PR: #3438
Original-Commit: ca1d74e164

* fix(storage): preserve peer isolation and cache correctness

* fix(ingest): reserve encoded peer namespace

* ci: skip embedding-dependent resource test without secrets

* fix(ragfs): invalidate caches after partial remove

---------

Co-authored-by: zhiheng.liu <zhiheng.liu@bytedance.com>
2026-07-31 21:45:29 +08:00
zgy 49b182045b refactor(parser): Refactor code summaries to fixed skeleton-first routing (#3568)
* Refactor code summary skeleton routing

* Simplify code skeleton routing configuration

* Render C tag skeletons as signatures

* Revert "Render C tag skeletons as signatures"

This reverts commit 8e342055f8.

* Simplify fixed code skeleton summary route

* Inline process skeleton rendering

* Simplify code skeleton routing entrypoints

* Fix code summary review issues

* Address final code summary review feedback

* Route failed tags skeletons to LLM fallback

* Restore CUDA and TS extension routing

* Improve code skeleton query coverage

* Route semantic code detection through skeleton support

* Move process skeleton engine into ast package

* Admit skeleton-supported files during directory scan

* Align code summary docs after main merge

* Reduce code skeleton fallback log verbosity

* chore: require grep-ast 0.9.0
2026-07-31 11:38:57 +08:00
Hao Zhe d2082ad2f7 fix(langchain): manage context wrapper resources (#3599)
Give with_openviking_context a deterministic lifecycle owner, reuse adapter clients without sharing invocation state, and preserve loop-scoped async behavior. Make component copies lifecycle-safe and reject post-close use before history access.
2026-07-30 14:30:02 +08:00
Hao Zhe 8db65ea9de fix(langchain): isolate async history and preserve cancellation semantics (#3575)
* fix(langchain): make async recording concurrency-safe

* fix(langchain): scope async state to each invocation

* fix(langchain): preserve cancellation progress on Python 3.10
2026-07-29 12:02:29 +08:00
Hao Zhe 8eb89a636b feat(langchain): add native async integration support (#3536)
* feat(langchain): add native async integration support

* fix(langchain): make async client lifecycle safe

* fix(langchain): make async lifecycle loop-safe

* docs(langchain): clarify async lifecycle invariants
2026-07-28 14:35:02 +08:00
Hao Zhe ea6e2dbb41 feat(integrations): unify LangChain and LangGraph session recording (#3530)
* feat(integrations): add reusable LangChain session recorder

* fix(integrations): harden session recorder retries
2026-07-27 18:27:56 +08:00
yufeng a949517f27 docs: add OpenViking Helper integration and fix stale links (#3445)
* docs: add OpenViking Helper integration

* docs: use mock data in Helper screenshots
2026-07-22 14:14:57 +08:00
huangruitengandhuangruiteng 810a22d881 docs: isolate OpenViking installs for Hermes (#3365)
* docs: isolate OpenViking installs for Hermes

* docs: keep install guidance scoped to Hermes

---------

Co-authored-by: huangruiteng <huangruiteng@bytedance.com>
2026-07-20 08:21:03 +08:00
yufeng 0a14967f6b docs: align MCP references with implementation (#3146)
* docs: align MCP references with implementation

* docs: fix remaining factual drift

* docs: correct remaining API examples

* docs: fix observer status response type
2026-07-11 15:54:07 +08:00
yufeng d14dd69665 feat: add Cursor and TRAE memory integrations (#3109)
* feat: add Cursor and TRAE memory integrations

* fix: install Cursor plugin from shared command

* refactor: share Cursor and TRAE integration runtime

* fix: migrate legacy OpenViking MCP entry

* docs: simplify Cursor and TRAE setup guides

* fix: harden Cursor and TRAE memory integrations

* refactor: standardize Cursor and TRAE integrations

* refactor: clarify Cursor and TRAE hook entrypoints

* fix: address Cursor and TRAE integration review
2026-07-10 16:57:19 +08:00
t0sakiandZaynJarvis 85b9878be3 feat(pi): add OpenViking context takeover (#3081)
Co-authored-by: ZaynJarvis <31875147+ZaynJarvis@users.noreply.github.com>
2026-07-08 20:15:16 +08:00
t0saki b511d91ee5 feat(plugins): retrofit OpenCode and pi memory integrations (hybrid MCP, shared lib, 4-harness installer) (#3079)
* feat(plugins): align opencode and pi memory integrations

* fix(installer): tolerate missing optional harness CLIs

* fix(installer): install opencode file wrapper

* fix(opencode): import path for logger initialization

* fix(installer): register pi extension after copy

* feat(plugins): use MCP for opencode integration

* docs: move OpenCode and pi integrations to dedicated pages

Promote the OpenCode plugin and pi extension out of the community-plugins
page into their own numbered agent-integrations pages (10-opencode, 11-pi,
en + zh), update the overview routing table, and refresh the OpenCode image
cards to the hybrid MCP architecture (unified installer, openviking_* MCP
tools, ovcli.conf credentials).

* docs: bare TOS installer commands and reference more examples

Drop --harness from TOS-mirror install commands (image cards use the bare
installer URL, matching the claude-code/codex cards); add Open WebUI tool
server and an examples/ pointer to the community-plugins page (en + zh).

* docs: bare TOS installer commands across agent-integration pages

TOS-mirror install commands carry no flags anywhere; the installer wizard
asks for source, harnesses, language, and credentials.
2026-07-08 15:54:37 +08:00
t0saki f905562534 feat(plugins): stdio MCP proxy, remote marketplace install, and type-quota recall for memory plugins (#3039)
* feat: add memory plugin mcp harness

* refactor: vendor shared memory plugin modules

* feat: add type quota recall api

* feat: commit codex memory by token threshold

* feat: capture codex tool calls as parts

* feat: add claude skill experience recall

* chore: fix lint in type quota recall server files

* feat: remote marketplace install with unified openviking naming

- Fix root .claude-plugin/marketplace.json git-subdir discriminator key
  ("type" -> "source"); claude plugin validate now passes.
- Unified installer gains --source remote|archive|dev: remote registers a
  synthesized git-subdir marketplace for Claude Code and a git marketplace
  for Codex (no repo clone); archive consumes the slim TOS marketplace zip;
  dev registers the checkout's examples/ directory for both harnesses.
- One marketplace name (openviking) across all modes and harnesses, so the
  plugin id is always openviking-memory@openviking; installer migrates old
  openviking-plugins-local registrations and config.toml sections.
- Restore legacy Claude Code (<2.0) support: claude mcp add (stdio proxy)
  plus node-based hooks merge into ~/.claude/settings.json.
- Restore optional statusline registration (fetches sources on opt-in).
- Checkbox TUI harness selection via /dev/tty with non-tty fallback.
- Add examples/.agents/plugins/marketplace.json so Codex directory installs
  drop the synthetic symlink marketplace.
- Add shared setup wizard (scripts/setup.mjs) for pure-marketplace installs.
- release-tos.yml: upload memory-plugin-shared/install.sh and build/upload
  the memory-plugin-marketplace zip; tos-install.sh prefers it and pins all
  fetches to TOS via OPENVIKING_SHARED_INSTALL_URL.
- CI: bash -n on installer scripts; marketplace contract tests updated.

* fix(installer): register Claude remote marketplace as a directory

File-type marketplaces (bare marketplace.json path) make Claude Code derive
a wrong installLocation and 'marketplace update' fails with EISDIR. Write
the synthesized manifest to <dir>/.claude-plugin/marketplace.json and add
the directory instead; compare registered sources by exact match so the
old file registration migrates cleanly.

* feat(statusline): show model name and native-style context percentage

A custom statusLine replaces Claude Code's native line including its context
indicator, so reproduce it from the statusline stdin payload: 'Fable 5 ·
ctx 42%' right after the health segment, with native color thresholds
(<70% dim, 70-89% yellow, >=90% red). Falls back from used_percentage to
remaining_percentage to token counts, and stays visible in bypass mode
since it describes the CC conversation, not OV. Opt out with
OPENVIKING_STATUSLINE_CTX=off. Line cap raised 80 -> 100 visible chars.

* fix(installer): keep checkout progress off stdout in plugin_dir_on_disk

Callers capture the function's stdout, so ensure_checkout's info lines were
concatenated into the statusline command registered in settings.json.

* fix(installer): re-register codex git marketplace instead of upgrading

Codex doesn't expose which --ref a git marketplace was added with, and
'marketplace upgrade' refreshes the old ref — so a URL match must not skip
re-registration or a ref override installs the wrong snapshot. Also remove
the stale pre-unification plugin cache directory during migration.

* fix(installer): include .agents in codex sparse checkout

A plugin-dir-only sparse checkout omits the repo-root marketplace manifest
and fails with 'marketplace root does not contain a supported manifest'.
Adding --sparse .agents keeps the snapshot slim (~7.5M vs full repo).

* feat(installer): bilingual prompts, dist channel selection, and TOS git marketplace for codex

- Interactive language selection (English/中文, --lang, auto-detected from
  locale); every user-facing prompt is bilingual.
- Download-source selection (--dist github|tos, prompted interactively):
  github keeps the remote marketplaces; tos serves GitHub-blocked regions.
- Credentials step now always shows the current ovcli.conf values (masked
  key) and offers keep-or-reconfigure instead of silently reusing them.
- Codex on TOS installs from a TOS-hosted git repo over dumb HTTP and keeps
  remote updates (codex plugin marketplace upgrade); falls back to the
  archive directory if the repo is unavailable. release-tos.yml builds and
  uploads the single-commit bare repo (repack + update-server-info).
- Claude Code on TOS warns that directory marketplaces cannot auto-update.
- tos-install.sh bootstraps shrink to TOS_BASE + --dist tos.
- Docs (READMEs, agent-integrations pages, image cards, en+zh) now all use
  the single shared installer and drop the deleted wrapper instructions.

* feat(installer): unify all choice prompts on an arrow-key TUI menu

Language, download source, connection mode, keep-or-reconfigure
credentials, statusline enable/replace, and legacy-mode confirmation all
render as the same single-select menu (arrow keys / digit shortcuts /
enter, radio-style highlight) instead of mixed numbered and y/N prompts.
Falls back to numbered input when /dev/tty can't be drawn on and to the
default choice when non-interactive. Free-text fields (URL, API key) stay
line inputs; the harness picker keeps its checkbox multi-select.

* fix(installer): stop piping plugin lists into grep -q under pipefail

grep -q exits on first match and SIGPIPEs the producer, so with pipefail
the 'codex plugin list | grep -q' check read as a miss every time (codex's
list is long; claude's short list masked the bug). Capture the output and
substring-match in bash instead — validation no longer false-warns.

Also: drop the stdio-proxy line from the Done summary; always offer the
install-source menu unless --dist/--source was given (with a checkout the
menu gains a dev option and defaults to it); surface the Claude-on-TOS
no-auto-update warning at source resolution instead of after install.

* fix: unignore examples/memory-plugin-shared/lib and commit the shared modules

The Python build-artifact 'lib/' gitignore rule silently swallowed the
shared plugin module source, so CI checkouts had only the vendored copies
and sync.test.mjs failed with ENOENT on the source directory.

* fix(recall): budget summary/uri fallbacks and sanitize non-finite scores

max_chars is the recall API's contract, but only full fragments counted
toward it — VikingBot's client-side heuristic, faithfully ported, lets
summary and uri fallbacks render far past the budget (repro: max_chars=100
rendered 548 chars). Every fragment now counts; oversized summaries degrade
to uri fragments and entries that can't even fit a uri line are dropped
(reported via stats.dropped). VikingBot itself is intentionally unchanged.

Also run _sanitize_floats over the /recall response like the neighboring
/find and /search routes, so inf/nan scores return 0.0 instead of a 500.
2026-07-07 12:33:59 +08:00
Qin Haojie a8b9ff57cd docs: clarify OpenCode integration setup (#3053) 2026-07-07 12:14:40 +08:00
t0sakiandbaobaodae 72d04cd488 feat(ingest): replay local agent-harness logs into OpenViking sessions (#2892)
* feat(ingest): replay local agent-harness logs into OV sessions / 本地 agent harness 日志重放入库

Add openviking/ingest/: parse Claude Code / Codex / OpenCode / Hermes / OpenClaw conversation logs into normalized messages and replay them through OpenViking's existing session pipeline (create_session -> batch_add_messages -> commit -> async memory extraction), instead of a bespoke ETL.

Supports one-shot backfill ("存量") and cursor-driven incremental polling ("新增", WatchScheduler-style, no fs-event dependency), per-harness enable/mode/paths config, and meaningful peer_id on every turn (assistant = {harness}/{model}; user = git identity for single-user harnesses, original username for group-chat harnesses). Cursor IDE is a registered but deferred stub.

Read-position cursors persist under ~/.openviking/ingest/state.db for crash-safe, idempotent resume. New openviking-ingest CLI (backfill/watch/run/status/list-sources) and an "ingest" section on OpenVikingConfig. Verified end-to-end against a local server: 3-message fixture -> session commit -> 10 memories extracted -> idempotent re-run.

Inspired by / supersedes volcengine/OpenViking#2674.

Co-authored-by: baobaodae <2014596548@qq.com>

* docs(ingest): bilingual guide + ov.conf.example for openviking-ingest / 本地日志入库双语文档与配置示例

Add docs/{zh,en}/agent-integrations/09-log-ingestion.md (auto-registered in the VitePress sidebar) and an `ingest` section in examples/ov.conf.example (off by default).

* fix(ingest): address review — gating, crash-safe batch replay, commit recovery, single-instance lock / 修复评审问题

Fixes the merge-blockers from the adversarial review:
- master switch ingest.enabled now actually gates enabled_harnesses();
- idempotent per-batch append with a durable pending-intent reconciled against the server message count on restart (no duplicate imports after a mid-append crash);
- bounded reads (<=100 msgs/call) so huge sessions don't materialize at once;
- needs_commit flag + commit_if_needed so appended-but-uncommitted sessions still get extracted (commit even when no new source rows);
- poller keeps dirty sessions until a commit actually succeeds;
- OpenCode advances its SQLite cursor only past complete rows (late part text no longer skipped);
- single-instance file lock guards concurrent ingest processes;
- positive-value config validation (no poll busy-loop); malformed ov.conf surfaces instead of silently defaulting.

Adds 6 tests (config gating/validation, crash reconcile both ways, commit recovery).

* refactor(ingest): expose as 'openviking-server ingest' subcommand; English-only code/docs

- Route the ingest CLI through 'openviking-server ingest ...' (same dispatch as 'init'/'doctor') and drop the separate 'openviking-ingest' console_script.
- Remove mixed-in Chinese terms (存量/新增) from source docstrings, CLI help, and the English doc; the Chinese doc keeps them.

* style(ingest): ruff format + import sort (isort I)

Run ruff 0.15.16 (from the uv cache) with the repo config: fixes 5 I001 import-order errors in tests and reformats 9 files. 'ruff check' and 'ruff format --check' now pass on all added/edited files.

---------

Co-authored-by: baobaodae <2014596548@qq.com>
2026-06-30 12:14:31 +08:00
t0saki 2c1c8bc785 docs(codex): revert #2879 doc changes; demote marketplace to local-only (#2901)
#2879 added a Codex marketplace section to the English integration docs. Revert
those docs-only additions so docs/ matches the pre-#2879 state — no marketplace
content in the agent-integration pages.

Keep the marketplace path in the plugin README, but demote it: it is local-only
(unauthenticated http://127.0.0.1:1933), does not support authenticated or
remote/cloud servers, and is not recommended. Reorder the Quick Start so the
one-line installer is path A (recommended, supports remote/cloud) and the
marketplace install is path B (local-only, not recommended).
2026-06-30 12:10:49 +08:00
LinQiang391andLinQiang391 8708debe10 feat(codex): support upstream marketplace install (#2879)
Co-authored-by: LinQiang391 <linqiang391@users.noreply.github.com>
2026-06-30 11:22:41 +08:00
Zayn Jarvis e43a4c5e6e ci(opencode-plugin): publish scoped npm package (#2807)
* fix(opencode-plugin): use js source install wrapper

* ci(opencode-plugin): publish scoped npm package
2026-06-24 21:21:57 +08:00
Zayn Jarvis 5e622ba6ea docs(plugin): keep one OpenCode plugin (#2540)
* docs(plugin): keep one OpenCode plugin

* docs(opencode): expand plugin install guide
2026-06-22 10:26:46 +08:00
Evo 38430aa20d docs(hermes): update OpenViking peer identity wording (#2686) 2026-06-17 20:48:51 +08:00
Zayn Jarvis c6990e4cd6 [codex] tighten memory recall, capture, and resume (#2598)
* Fix Codex memory hook recall noise and stop timeouts

* Tighten Codex recall compression output

* Add Codex archive resume and capture filtering

* Wrap Codex memory injection for capture filtering

* Detect Codex recall compressor profile

* Refresh Codex compressor profile on startup

* fix codex ov credential resolution

* [codex] resolve compressor profile via models_cache.json, not codex exec probe

SessionStart used to spawn 'codex exec' sequentially against each
candidate model to detect which one would respond — up to 3 probes ×
~15s timeout each, on every session start, even on resume. The
configured-on-startup default made this a guaranteed first-page-load
tax of several seconds.

Replace the probe with a lookup against codex's own model catalogue
(~/.codex/models_cache.json, refreshed by codex CLI's etag-backed
fetch). The first candidate whose slug is present wins. SessionStart
now goes cache-first: load the persisted profile if any, only resolve
on cache miss. The runtime compress path (auto-recall) deletes the
cached profile on any compress failure so the next SessionStart
re-resolves against the current catalogue.

- recall-compressor-profile.mjs:
  * loadCodexModelsCache(env) reads ~/.codex/models_cache.json; missing
    cache yields {present:false,slugs:Set()}.
  * resolveRecallCompressorProfile picks the first available candidate
    by slug; falls back optimistically to the first candidate when
    the catalogue is missing.
  * invalidateRecallCompressorProfileCache() rms the persisted file.
  * detectRecallCompressorProfile is now cache-first and never spawns.
- auto-recall.mjs: runCodexCompressor invalidates the cache on spawn
  error, timeout, non-zero exit, and read failure (best-effort,
  no error surface to user).
- recall-compressor-profile.test.mjs: 11 unit tests covering catalogue
  read, candidate selection (with/without configured first), missing
  catalogue fallback, configured_off path, invalidate, cache-first
  detect, and re-resolve after invalidate.

Notes:
- buildCodexExecArgs is still exported so auto-recall can spawn the
  actual compress run; the change only removes the *probe* spawn, not
  the compress spawn.
- recallCompressDetectTtlMs and recallCompressDetectTimeoutMs are
  preserved in config for back-compat; the timeout no longer matters
  but the TTL still bounds how stale a cached profile may be.

* [codex] omit X-OpenViking-Actor-Peer env_http_headers when no peer configured

syncMcpConfig used to unconditionally write all three OV header→env
mappings. The wrapper strips empty OPENVIKING_PEER_ID before exec'ing
codex, so an unset env var would silently flip the header to "" — the
OV side then has to disambiguate that from "no peer scope". Match the
bearer_token_env_var pattern: present only when there's something to
send. Also drops a stale X-OpenViking-Actor-Peer entry when the peer
is unset (e.g. after switching ovcli configs).

- Existing test 4 became two cases: with-peer keeps the mapping,
  without-peer drops it (symmetric to bearer).
- New test asserts an in-place drop when the cached .mcp.json had a
  stale peer mapping but the active config no longer has a peer.

* [codex] runtime_failed compressor marker stops same-session retry storms

Previous fix invalidated the profile cache on compress failure. Within a
single codex session that still bled `recallCompressTimeoutMs` of wall
time per UserPromptSubmit because the next hook reread cache (miss),
fell back to fallbackRecallCompressorProfile, and tried the same model.

Replace plain invalidate with a runtime_failed sentinel cached in the
profile slot. UserPromptSubmit's compressMemoryContext already short-
circuits on `profile.enabled === false`, so the marker stops further
spawns for the rest of the codex process. The next SessionStart cache-
first detect treats `source === 'runtime_failed'` as cache miss and
re-resolves against the current models_cache.json, so a transient
failure self-recovers across codex restarts without operator action.
detect_on_startup=false respects the marker (no auto-recover, matches
the "manual control" intent of that flag).

- recall-compressor-profile.mjs:
  * markRecallCompressorRuntimeFailed(cfg, {failedModel}) writes the
    disabled sentinel.
  * detectRecallCompressorProfile branches on cached.source ===
    'runtime_failed': cache hit otherwise, recover-via-resolve when
    startup-detect on, respect marker when off.
- auto-recall.mjs::runCodexCompressor: swap invalidate-on-error with
  markRecallCompressorRuntimeFailed(cfg, {failedModel: profile.model}).
- recall-compressor-profile.test.mjs: 4 new tests covering marker
  write, cross-restart recovery picking a different slug, and the
  detect_on_startup=false honor path. 20/20 pass.

invalidateRecallCompressorProfileCache is kept as a public API for
explicit operator use (e.g. a future `ov codex reset-compressor`
command), but is no longer called from the runtime path.
2026-06-16 02:05:18 +08:00
t0saki aca58bf3b9 feat: TOS release upload + GitHub-free install path for memory plugins (#2575)
* ci: upload source zip and plugin installers to TOS on release

Add a standalone workflow (20. Release TOS Upload) that runs on release
publish (or manual dispatch with a tag for backfill) and uploads:

- the source archive to releases/<tag>/ and releases/latest/
- both memory-plugin install.sh scripts to versioned paths and to
  stable root paths for a China-reachable one-liner URL

Reuses the existing TOS secrets (AK/SK/region/endpoint) with a new
TOS_RELEASE_BUCKET secret so release artifacts stay out of the docs
bucket. Missing secrets skip gracefully (fork-friendly); real upload
failures fail the workflow.

* ci: server-side copy for the latest source zip

* feat(plugins): GitHub-free TOS install path for memory plugins

Domestic users can't reach github.com / raw.githubusercontent.com, so the
existing one-liner installers stall at their step-3 `git clone`. Add a
GitHub-free path that sources everything from Volcengine TOS:

- Both install.sh learn OPENVIKING_REPO_ARCHIVE_URL: when set, fetch the
  source from a zip (curl + unzip) instead of git clone. A
  .openviking-archive-source marker makes re-runs idempotent and refuses
  to clobber a git checkout or unrelated data at REPO_DIR.
- New setup-helper/tos-install.sh bootstrap per plugin: sets the TOS
  archive URL, downloads the real install.sh from TOS to a temp file
  (kept off the stdin pipe so prompts stay interactive), and delegates.
- release-tos.yml uploads both tos-install.sh alongside install.sh.

One-liner for users behind the GFW:
  bash <(curl -fsSL https://ovrelease.tos-cn-beijing.volces.com/claude-code-memory-plugin/tos-install.sh)

The GitHub default path is unchanged; archive mode only activates when
OPENVIKING_REPO_ARCHIVE_URL is set.

* docs: document the TOS (GitHub-free) install path for memory plugins

Main agent-integration docs (zh/en, claude-code + codex) keep the GitHub
one-liner and add the TOS equivalent for regions where GitHub is hard to
reach. The CDN integration cards switch their install one-liner to the TOS
bootstrap only, since that gallery is served where GitHub raw is unreliable.

* docs: trim the TOS install note to one line
2026-06-15 14:20:09 +08:00
Qin Haojie 49e4d76913 feat(core): add actor peer filesystem view (#2594)
* feat(core): enforce actor scoped retrieval

* fix(core): narrow actor peer filtering to retrieval

* fix(core): enforce actor peer filesystem view
2026-06-13 15:49:34 +08:00
t0saki 7237ac611c fix(plugins): skip shell aliases when wrapping extra launch commands (#2471)
Adding a shell-alias name (e.g. `cc` from `alias cc=claude`) to
OPENVIKING_CC_WRAP_EXTRA / OPENVIKING_CODEX_WRAP_EXTRA broke the wrapper:
bash expands the alias mid-eval and clobbers the base `claude`/`codex`
function (so `command cc` ends up running the C compiler), while zsh
aborts with a parse error on every shell start. Guard the wrapper-defining
loop to skip names that are already shell aliases — an alias already
routes through the base wrapper once it expands, so it needs no function.
Also reject heads starting with `-`, which `alias`/`command` would
otherwise misparse as an option.

Also document the custom-launch-command feature and the alias guidance:
- 8 agent-integration docs (en/zh main + CDN cards): brief install note,
  plus two troubleshooting rows (wrapper-not-sourced, alias gap)
- claude/codex plugin READMEs (+ README_CN, which was missing the section
  entirely): wrap the real target command, never the alias name
2026-06-06 12:40:14 +08:00
Evo 863f68db97 docs(openclaw): document autoRecallTimeoutMs config in integration guide (#2391) (#2472)
* docs(openclaw): document autoRecallTimeoutMs config in integration guide (#2391)

* docs(openclaw): document autoRecallTimeoutMs config in integration guide (#2391)
2026-06-06 10:17:44 +08:00
Hao Zhe ed2e5483c5 feat(cli): rename config providers (#2463)
* feat: rename ov config providers

* fix: align config provider JSON labels
2026-06-05 18:24:41 +08:00
t0saki 0f6160edaf docs: refresh Claude Code & Codex memory plugin integration docs (#2457)
* docs: refresh Claude Code & Codex memory plugin integration docs

- Fix dead anchor #1-wrap-claude-to-inject-env-from-ovcliconf -> #configuring-mcp
  in the Claude Code manual setup (zh/en agent-integrations + CDN cards)
- Add the post-install wrapper activation step (source .../wrapper.sh) to the
  Claude Code docs, and make Codex's activation shell-agnostic
  (source ~/.zshrc -> source .../codex-memory-plugin/setup-helper/wrapper.sh)
- Rewrite Claude Code manual step 1 to the guarded `source wrapper.sh` form
- Convert Claude Code "How it works" into a lifecycle bullet list
- Language polish pass across all eight Claude Code / Codex docs
- Sync docs/images/agents/zh/index.json summaries with the refreshed intros

* docs: foolproof the verify step against an inactive wrapper

Add a guard note to the Verify section of every Claude Code / Codex doc:
if `type claude` / `type codex` prints a path instead of "shell function",
the wrapper isn't active, so re-source it (or open a new terminal) before
launching — otherwise Claude Code silently connects to 127.0.0.1 with no
auth, and Codex starts without OPENVIKING_API_KEY and reports
"MCP server is not logged in". For Claude Code, also state explicitly to
launch `claude` from the terminal where the wrapper is active.

Applies to all eight surfaces (zh/en, agent-integrations guides + CDN cards).
2026-06-05 15:52:39 +08:00
Qin Haojie ff258768c2 feat(memory): 引入 User/Peer 记忆隔离模型 (#2236)
* feat(memory): introduce user and peer memory isolation

Unify agent-scoped memory behavior into user-owned memory spaces, add peer_id compatibility for session and retrieval paths, and wire memory_policy through session commit flows.

* feat(memory): align session identity around peer IDs

* feat(search): pass peer id through retrieval

* refactor(memory): remove agent identity from integrations

* fix(memory): isolate peer identity from self extraction

* fix(tau2): provision benchmark user configs

* fix(auth): allow admin keys to access data APIs

* fix(openclaw): enable peer memory policy for peer roles

* fix(openclaw): resolve sender for peer recall

* refactor(session): simplify memory extraction routing

* refactor(ov-cli): reduce formatting-only diff

* refactor(message): remove unused message helpers

* refactor(retrieval): simplify peer target resolution

* refactor(namespace): remove deprecated agent namespace policy

* fix(agent): propagate peer id through integrations

* fix(auth): align integration clients with api-key mode
2026-06-05 10:55:48 +08:00
yufeng f627a09662 docs: fix Claude agent documentation links (#2443) 2026-06-04 21:36:52 +08:00
t0saki 77a2ee88c3 docs: overhaul agent-integrations section (#2217)
* docs: overhaul agent-integrations section for clarity and beginner-friendliness

Restructure the agent-integrations documentation (EN + ZH) to be concise,
beginner-friendly, and consistently structured across all runtimes.

* docs(mcp-clients): clarify OAuth flow for Claude Desktop / Claude.ai

* docs(mcp-clients): add public access guide link for OAuth section

* docs: address review — clarify dev-mode auth, add missing import

* docs(mcp-guide): update verified platforms, fix OAuth section scope
2026-05-25 17:15:05 +08:00