mirror of
https://github.com/volcengine/OpenViking.git
synced 2026-10-01 01:38:07 +08:00
cli@0.4.14
21
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b7aa01d227 |
feat(plugins): add OpenViking memory integration for TRAE CLI (#4026)
* feat: add OpenViking memory integration for TRAE CLI Add TRAE CLI lifecycle hooks and MCP proxy support, wire the integration into the shared installer, and cover idempotent install and uninstall behavior. Co-authored-by: TRAE CLI <noreply@bytedance.com> * fix(trae-cli): cover archive installs and hook payload aliases * fix: keep TRAE CLI installation explicit Leave TRAE Desktop detection unchanged and avoid auto-selecting TRAE CLI. TRAE CLI remains available through an explicit harness selection or --harness trae-cli. Co-authored-by: TRAE CLI <noreply@bytedance.com> * fix(trae-cli): auto-select installed CLI commands Detect traecli and traex only when they are available in PATH, then mark and select the TRAE CLI harness automatically. --------- Co-authored-by: “bianhaonan” <“bianhaonan@bytedance.com”> Co-authored-by: TRAE CLI <noreply@bytedance.com> |
||
|
|
d7ab37c76e |
feat(plugins): add OpenViking memory for DSH (#3993)
* feat(plugins): add OpenViking memory for DSH * feat(dsh-plugin): graft review items — source whitelist, dsh constructors, live recall gate Applies the #task-65 review verdict's graft list from #3991 onto the #3993 base: - capture whitelist: drop every plugin-sourced user message (any plugin, not just this one) so injected context never mirrors into memory as human input; recall queries keep their existing scope - pre-step: register with prepend so this listener sees the final claimed batch, and short-circuit on signal.aborted around each await - adopt dsh constructors behind exact-pinned peers (devDependencies mirror the pins): tools flow through @deepseek-ai/dsh-tools defineTool (declarative parameters, output schema/render, presentCall per tool), plugin messages through @deepseek-ai/dsh-llm createUserMessage; a registration-shape test makes a future rc pin bump fail CI instead of a user install when the ToolDefinition contract moves - live-recall.test.mjs: opt-in (OPENVIKING_E2E=1) real-backend gate — store a sentinel via session commit, wait for extraction, assert recall returns it; passed against a live OpenViking server in 124s (note: commit with the default keep_recent_count=10 extracts nothing from short sessions — the test pins keepRecentCount 0) - README: why injection is pre-step user messages, not the system prompt (complete:true personas silently drop prompt assembly), plus peer-pin rationale and a Testing section Tests: 15 pass + 1 env-gated (node --test), requires npm ci for the pinned dsh devDependencies — CI step lands separately (workflow scope). * ci(pr): install DSH plugin deps before running memory plugin tests * fix(dsh-plugin): finalize neutral plugin integration Remove product-specific identifiers from the DSH plugin surface and harden its lifecycle, HTTP contracts, archive tooling, and ordered offline delivery. Co-authored-by: TRAE CLI <noreply@bytedance.com> --------- Co-authored-by: Zayn Jarvis <zaynjarvis@gmail.com> Co-authored-by: TRAE CLI <noreply@bytedance.com> |
||
|
|
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> |
||
|
|
33043cb1b8 |
feat(plugins): expose session commit trace IDs (#3977)
Preserve result.trace_id across plugin HTTP wrappers, include it in commit success and failure logs, and surface it in user-visible commit confirmations where supported. |
||
|
|
00f3738edb |
feat(usage): emit resource-scoped experience usage records (#3921)
* feat(usage): expand experience tracking and log schema * fix(usage): preserve experience count event names * refactor(agent-evolution): use generic OpenViking tools * fix(usage): capture generic OpenViking tool events * feat(skills): guide cross-agent experience retrieval * fix(usage): address generic tool migration review |
||
|
|
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.
|
||
|
|
0ab48f96fc |
fix(session): recover partial capture sessions (#3820)
Treat messages.jsonl as the materialization boundary for session-aware recall, repair partial session roots during the existing authoritative append path, and preserve Claude capture cursors when writes never reach the server. Also replay explicitly retryable storage conflicts across memory plugins. Co-authored-by: TRAE CLI <noreply@bytedance.com> |
||
|
|
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. |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
229300e886 | fix(codex): preserve session tool activity (#3579) | ||
|
|
29ba81b53e |
feat(plugins): identify memory plugin traffic with a User-Agent (#3532)
Every harness memory plugin sent OpenViking requests under Node's default `user-agent: node`, so server-side and gateway logs could not attribute traffic to a harness or a plugin version. Send `openviking-memory-<harness>/<version>` from all six harnesses (claude-code, codex, opencode, pi, cursor, trae) on both the data plane and the MCP proxy. Versions come from each harness's own manifest, or from OPENVIKING_INTEGRATION_VERSION for cursor/trae; an unreadable manifest degrades to 0.0.0 rather than throwing inside a short-lived hook. The header is purely informational — neither the open-source server nor the commercial gateway consumes it, and no auth or identity header changes. |
||
|
|
ccc271ff27 |
feat: add extensible usage reporting (#3222)
* feat: add extensible usage reporting * fix: harden usage reporter lifecycle * fix: scope experience usage events correctly * refactor: generalize usage event schema * docs: design Codex experience memory tools * docs: plan Codex experience memory tools * feat: add Codex experience memory tools * docs: remove temporary Codex implementation plans * fix: capture Codex MCP tool parts * fix: harden experience usage reporting * fix: reload credentials for local MCP tools * fix: preserve MCP tool-level errors * fix: bound synchronous sink shutdown * fix: enforce sink shutdown timeout * fix: enforce experience tool contracts * fix(usage-reporter): keep tool schemas and replay ids stable * fix(usage-reporter): reject unidentifiable tool events |
||
|
|
6f10e26361 |
perf(plugins): batch add-message writes and shared async detach across memory plugins (#3261)
* Batch add-message writes across memory plugins * fix(plugins): stop batch enqueue at first failure and bump plugin versions Keep pending-queue entries a contiguous prefix when a mid-stream enqueue fails: consumers mark the first sent+queued payloads as captured, so a queued entry after a gap could silently drop the gapped message. Bump claude-code 0.4.3, codex 0.7.3, opencode 0.2.3, cursor/trae 0.1.2 so existing installs pick up the batch write path. |
||
|
|
82999c8b4b |
fix(plugins): pin MCP-Protocol-Version header to the negotiated version (#3214)
* fix(plugins): pin MCP-Protocol-Version header to the negotiated version The shared stdio proxy forwarded the client's un-negotiated protocolVersion ask as the MCP-Protocol-Version header on initialize and cached it for follow-up requests, never reading the version the server actually negotiated in the initialize response. Strict streamable-HTTP upstreams (e.g. modelcontextprotocol/go-sdk servers) validate that header on every request and answer HTTP 400 'Unsupported protocol version' before negotiation can run, so clients on a newer spec than the upstream (Trae sends 2025-11-25) failed MCP registration outright. Send the proxy default (2025-06-18) while initializing, adopt result.protocolVersion from the initialize response for all subsequent requests, and keep the client's ask intact in the forwarded initialize body so end-to-end version negotiation still happens. * chore(plugins): bump patch versions for the MCP proxy protocol fix claude-code 0.4.2, codex 0.7.2, cursor 0.1.1, trae 0.1.1, opencode 0.2.2. |
||
|
|
9cf42405a8 | fix(installer): avoid silent exit after harness selection (#3128) | ||
|
|
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 |
||
|
|
2a81edc707 | Add workspace peer mode for memory plugins (#3099) | ||
|
|
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. |
||
|
|
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.
|