parse() resolves SecretRef values to plain strings before returning, but the
parsed type still inherited string | OpenVikingSecretRef from the input type,
breaking tsc -p tsconfig.build.json (release prepack) since #3618.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Issue #3522 — the OpenClaw plugin's `config.apiKey` only accepted a plain
string, resolved through local `${ENV_VAR}` interpolation. `INSTALL*.md`
documented this as a known limitation: users who store their other OpenClaw
provider credentials (LLM, TTS, MCP servers) through the standard
`{source, id[, provider]}` SecretRef mechanism (env / file mount /
exec-backed vault such as 1Password, Vault, gopass) had to keep the
OpenViking key as cleartext inside `openclaw.json`.
### config.ts — `string | OpenVikingSecretRef` widening
* Add `OpenVikingSecretRef = "env"|"file"|"exec"` discriminated union type,
matching the shape OpenClaw core uses for its own credential fields
(`env` + `file` implemented in-plugin, `exec` forwarded to `child_process`
so providers like `@transmitt0r/openclaw-plugin-onepassword` can manage
the OpenViking key without SDK coupling).
* Add `resolveSecret()` resolver with explicit, actionable errors:
- env: unset var = throw, no silent empty fallback
- file: `~` expanded, UTF-8 read, whitespace trimmed; unreadable file
rethrows with the OpenViking field name prefixed so config misconfigs
surface with a clear label and path
- exec: lazy `require("node:child_process").execFileSync(provider,[id])`,
stdout trimmed, 15s timeout; errors prefixed with provider + id
- unknown source / missing id / missing exec provider = explicit throw
* `memoryOpenVikingConfigSchema.parse()` widens `rawApiKey` to
`string | OpenVikingSecretRef`, then passes it through
`resolveSecret(rawApiKey, "config.apiKey")` *before* the existing
`resolveEnvVars` pass. Plain strings transparently fall through
`resolveSecret` unchanged, so `${ENV_VAR}` interpolation is preserved
100% backward-compatibly.
* `OPENVIKING_API_KEY` env fallback is unchanged and triggers only when the
`apiKey` config key is absent — a user who deliberately sets `apiKey: ""`
still gets "" (explicitly unauthenticated), not the env fallback.
* `uiHints.apiKey.help` documents the SecretRef shape and recommends it.
### openclaw.plugin.json — widening schema + UI hints
* `configSchema.properties.apiKey` becomes `oneOf: [string, env ref, file ref, exec ref]`.
Each object variant has a `title`, `additionalProperties: false`,
`required`, and explicit description per field, so OpenClaw's config UI
can render them individually instead of showing a generic JSON object blob.
* `uiHints.apiKey.help` matches the new config.ts wording.
### INSTALL.md / INSTALL-ZH.md — SecretRef usage tables
Replace the old "plaintext / chmod 0600" caveat bullet with a 3-row table
(env / file / exec) showing example JSON + notes (Kubernetes secretKeyRef
mount for `file`, 1Password `op://` URL convention for `exec`). The
backward-compat string path is retained at the end of the new bullet so
existing deployments that haven't migrated yet still get the old permission
advice — no surprise behaviour for upgrading users.
### tests/ut/config.test.ts — SecretRef regression suite (10 new cases)
Under a new `describe("… SecretRef (#3522)")`:
1. Backward compat: `${OV_KEY}` interpolation still resolves.
2. env source — happy path with a fresh env var.
3. env source — unset var throws, no silent fallback.
4. file source — real `mkdtemp`-created file, trimmed whitespace. Cleanup
in `afterEach`.
5. file source — missing-path error message contains readable label + path.
6. exec source — `vi.spyOn(child_process.execFileSync)` asserts provider +
args, stdout trimmed.
7. exec source — missing `provider` field errors.
8. Schema validation — unknown `source` and missing `id` each throw with
error messages that name the problem.
9. Env fallback boundary — explicit `apiKey: ""` is NOT overridden by
OPENVIKING_API_KEY, but `apiKey` absent IS (backward-compat behaviour
contract pinned with a test so future refactors can't regress).
Covers every branch inside `resolveSecret()`, plus the backward-compat
contracts issue #3522 called out.
Treat failed session archives as terminal skipped state so later commits can continue, and replace OpenClaw's fixed auto-commit token threshold with a context-window ratio while tolerating the deprecated config key.
Co-authored-by: LinQiang391 <linqiang391@users.noreply.github.com>
* fix(openclaw): treat agent_prefix as prefix only
* fix(openclaw): treat agent_prefix as prefix only
---------
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
* feat(session): make commit two-phase with async memory extraction
Session commit now returns immediately after archiving messages (Phase 1).
Summary generation and memory extraction (Phase 2) run in the background
via asyncio.create_task(), returning a task_id for polling progress.
- Add get_task() API across all client layers for querying background task status
- get_session() auto-creates session if it does not exist
- Remove wait parameter and telemetry from commit endpoint
- Add .done completion marker to archive directories
- Update docs (EN/ZH) and tests for new two-phase flow
* feat(session): add .meta.json persistence and auto_create control for get_session
SessionService.get() now defaults to auto_create=False, raising NotFoundError
for missing sessions. A new SessionMeta dataclass tracks created_at, updated_at,
message_count, commit_count, memories_extracted (by category), last_commit_at,
and cumulative llm_token_usage. Meta is persisted to .meta.json and updated on
add_message, commit Phase 1 (message clear), and commit Phase 2 completion
(token usage, memory counts via bind_telemetry). All client layers
(local/async/sync/HTTP) and API docs updated accordingly.
* fix: remove session vectorize
* support commit for openclaw-plugin
Made-with: Cursor
* feat(openclaw-plugin): archive-aware context assembler with lazy-read optimization
- Implement get_context_for_assemble with token-budget-aware archive trimming
- Write .meta.json during commit for pre-stored token counts
- Lazy-read archives from newest to oldest, skip old archives when budget exhausted
- Backward-compatible: fall back to reading overview for old archives without .meta.json
- Pass agentId through getContextForAssemble in client.ts
- Use sessionKey from OpenClaw in assemble to match afterTurn session resolution
- Emit non-error toolResult for pending/running tools instead of synthetic error
- Log warning and mark stats on ls(history) failure instead of silent swallow
* refactor(openclaw-plugin): unify OV session identity to sessionId
Made-with: Cursor
* feat(openclaw-plugin): add memory chain integration test script
Made-with: Cursor
* add test and desc of openclaw-plugin
* change commit to async
---------
Co-authored-by: qin-ctx <qinhaojie.exe@bytedance.com>
Co-authored-by: wlff123 <wulf234@163.com>
Co-authored-by: Eurekaxun <eurekaxun@163.com>
Co-authored-by: lin-qiang123 <1667704220@qq.com>
* feat(openclaw-context-plugin): migrate OpenViking memory plugin to context engine
1. Rename the OpenClaw plugin from memory-openviking to openclaw-context-plugin and switch its kind from memory to context-engine.
2. Keep auto-recall and ingest-reply-assist on before_prompt_build to preserve the existing prompt injection behavior.
3. Move the canonical auto-capture flow from the old agent_end-style lifecycle to ContextEngine afterTurn.
4. Delegate compact handling to the legacy compact engine when it is available, so existing compaction behavior can still be reused.
5. Preserve the OpenViking tools and local process management while updating setup helpers, installers, docs, and OpenClaw config paths to plugins.slots.contextEngine.
Co-authored-by: GPT-5.4 <noreply@openai.com>
* refactor(openclaw-context-plugin): rename plugin id to context-openviking
- rename the runtime plugin id, package name, install destination, and OpenClaw config keys from openclaw-context-plugin to context-openviking
- keep the source directory at examples/openclaw-context-plugin unchanged while updating docs, installers, and setup helpers to use the new runtime name
- remove unused sys imports from the demo scripts so ruff check stays green
---------
Co-authored-by: GPT-5.4 <noreply@openai.com>