Full Code of volcengine/OpenViking for AI

main 33f1a8f42b40 cached
1502 files
11.0 MB
3.0M tokens
11207 symbols
2 requests
Copy disabled (too large) Download .txt
Showing preview only (11,787K chars total). Download the full file to get everything.
Repository: volcengine/OpenViking
Branch: main
Commit: 33f1a8f42b40
Files: 1502
Total size: 11.0 MB

Directory structure:
gitextract_9tihp5kp/

├── .clang-format
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.yml
│   │   └── question.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── _build.yml
│       ├── _codeql.yml
│       ├── _lint.yml
│       ├── _publish.yml
│       ├── _test_full.yml
│       ├── _test_lite.yml
│       ├── build-docker-image.yml
│       ├── ci.yml
│       ├── pr-review.yml
│       ├── pr.yml
│       ├── release-vikingbot-first.yml
│       ├── release.yml
│       ├── rust-cli.yml
│       └── schedule.yml
├── .gitignore
├── .pr_agent.toml
├── .pre-commit-config.yaml
├── CONTRIBUTING.md
├── CONTRIBUTING_CN.md
├── CONTRIBUTING_JA.md
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── README_CN.md
├── README_JA.md
├── bot/
│   ├── .coveragerc
│   ├── .dockerignore
│   ├── .github/
│   │   └── workflows/
│   │       ├── release.yml
│   │       └── test.yml
│   ├── .gitignore
│   ├── README.md
│   ├── README_CN.md
│   ├── SECURITY.md
│   ├── bridge/
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── server.ts
│   │   │   ├── types.d.ts
│   │   │   └── whatsapp.ts
│   │   └── tsconfig.json
│   ├── deploy/
│   │   ├── Dockerfile
│   │   ├── docker/
│   │   │   ├── Dockerfile
│   │   │   ├── README.md
│   │   │   ├── build-image.sh
│   │   │   ├── build-multiarch.sh
│   │   │   ├── deploy.sh
│   │   │   ├── deploy_langfuse.sh
│   │   │   ├── docker-entrypoint.sh
│   │   │   ├── image_upload.example.yaml
│   │   │   ├── image_upload.sh
│   │   │   ├── langfuse/
│   │   │   │   └── docker-compose.yml
│   │   │   └── stop.sh
│   │   ├── ecs/
│   │   │   └── README.md
│   │   └── vke/
│   │       ├── README.md
│   │       ├── deploy.sh
│   │       ├── k8s/
│   │       │   ├── deployment.yaml
│   │       │   ├── pvc-nas-example.yaml
│   │       │   ├── pvc-tos-example.yaml
│   │       │   └── pvc-tos.yaml
│   │       └── vke_deploy.example.yaml
│   ├── docs/
│   │   ├── CHANNEL.md
│   │   ├── openclaw-plugin-analysis.md
│   │   └── rfc-openviking-cli-ov-chat.md
│   ├── eval/
│   │   ├── locomo/
│   │   │   ├── judge.py
│   │   │   ├── run_eval.py
│   │   │   └── stat_judge_result.py
│   │   └── skillsbench/
│   │       └── skill_bench_eval.py
│   ├── license/
│   │   └── LICENSE
│   ├── package.json
│   ├── scripts/
│   │   ├── clean_vikingbot.sh
│   │   ├── restart_openviking_server.sh
│   │   ├── start_vikingbot_in_ecs.sh
│   │   └── test_all.sh
│   ├── tests/
│   │   ├── conftest.py
│   │   ├── example.py
│   │   ├── experience_data_mini.json
│   │   └── test_chat_functionality.py
│   ├── vikingbot/
│   │   ├── __init__.py
│   │   ├── __main__.py
│   │   ├── agent/
│   │   │   ├── __init__.py
│   │   │   ├── context.py
│   │   │   ├── loop.py
│   │   │   ├── memory.py
│   │   │   ├── skills.py
│   │   │   ├── subagent.py
│   │   │   └── tools/
│   │   │       ├── __init__.py
│   │   │       ├── base.py
│   │   │       ├── cron.py
│   │   │       ├── factory.py
│   │   │       ├── filesystem.py
│   │   │       ├── image.py
│   │   │       ├── message.py
│   │   │       ├── ov_file.py
│   │   │       ├── registry.py
│   │   │       ├── shell.py
│   │   │       ├── spawn.py
│   │   │       ├── web.py
│   │   │       └── websearch/
│   │   │           ├── __init__.py
│   │   │           ├── base.py
│   │   │           ├── brave.py
│   │   │           ├── ddgs.py
│   │   │           ├── exa.py
│   │   │           ├── registry.py
│   │   │           └── tavily.py
│   │   ├── bus/
│   │   │   ├── __init__.py
│   │   │   ├── events.py
│   │   │   └── queue.py
│   │   ├── channels/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── chat.py
│   │   │   ├── dingtalk.py
│   │   │   ├── discord.py
│   │   │   ├── email.py
│   │   │   ├── feishu.py
│   │   │   ├── manager.py
│   │   │   ├── mochat.py
│   │   │   ├── openapi.py
│   │   │   ├── openapi_models.py
│   │   │   ├── qq.py
│   │   │   ├── single_turn.py
│   │   │   ├── slack.py
│   │   │   ├── telegram.py
│   │   │   ├── utils.py
│   │   │   └── whatsapp.py
│   │   ├── cli/
│   │   │   ├── __init__.py
│   │   │   └── commands.py
│   │   ├── config/
│   │   │   ├── __init__.py
│   │   │   ├── loader.py
│   │   │   └── schema.py
│   │   ├── console/
│   │   │   ├── README_GRADIO.md
│   │   │   ├── __init__.py
│   │   │   └── web_console.py
│   │   ├── cron/
│   │   │   ├── __init__.py
│   │   │   ├── service.py
│   │   │   └── types.py
│   │   ├── heartbeat/
│   │   │   ├── __init__.py
│   │   │   └── service.py
│   │   ├── hooks/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── builtins/
│   │   │   │   ├── __init__.py
│   │   │   │   └── openviking_hooks.py
│   │   │   └── manager.py
│   │   ├── integrations/
│   │   │   ├── __init__.py
│   │   │   └── langfuse.py
│   │   ├── openviking_mount/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── fuse_finder.py
│   │   │   ├── fuse_proxy.py
│   │   │   ├── fuse_simple.py
│   │   │   ├── fuse_simple_debug.py
│   │   │   ├── manager.py
│   │   │   ├── mount.py
│   │   │   ├── ov_server.py
│   │   │   ├── session_integration.py
│   │   │   ├── user_apikey_manager.py
│   │   │   └── viking_fuse.py
│   │   ├── providers/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── litellm_provider.py
│   │   │   ├── registry.py
│   │   │   └── transcription.py
│   │   ├── sandbox/
│   │   │   ├── __init__.py
│   │   │   ├── backends/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── aiosandbox.py
│   │   │   │   ├── direct.py
│   │   │   │   ├── opensandbox.py
│   │   │   │   ├── srt-wrapper.mjs
│   │   │   │   └── srt.py
│   │   │   ├── base.py
│   │   │   └── manager.py
│   │   ├── session/
│   │   │   ├── __init__.py
│   │   │   └── manager.py
│   │   ├── tests/
│   │   │   ├── __init__.py
│   │   │   ├── integration/
│   │   │   │   └── __init__.py
│   │   │   └── unit/
│   │   │       ├── __init__.py
│   │   │       ├── test_agent/
│   │   │       │   └── __init__.py
│   │   │       ├── test_bus/
│   │   │       │   └── __init__.py
│   │   │       ├── test_channels/
│   │   │       │   └── __init__.py
│   │   │       └── test_config/
│   │   │           └── __init__.py
│   │   └── utils/
│   │       ├── __init__.py
│   │       ├── helpers.py
│   │       └── tracing.py
│   └── workspace/
│       ├── HEARTBEAT.md
│       ├── SOUL.md
│       ├── TOOLS.md
│       ├── USER.md
│       ├── memory/
│       │   └── MEMORY.md
│       └── skills/
│           ├── README.md
│           ├── cron/
│           │   └── SKILL.md
│           ├── github/
│           │   └── SKILL.md
│           ├── github-proxy/
│           │   ├── SKILL.md
│           │   └── scripts/
│           │       └── convert_url.py
│           ├── opencode/
│           │   ├── SKILL.md
│           │   ├── list_sessions.py
│           │   ├── opencode_utils.py
│           │   └── status.json
│           ├── skill-creator/
│           │   └── SKILL.md
│           ├── summarize/
│           │   └── SKILL.md
│           ├── tmux/
│           │   ├── SKILL.md
│           │   └── scripts/
│           │       ├── find-sessions.sh
│           │       └── wait-for-text.sh
│           └── weather/
│               └── SKILL.md
├── build_support/
│   ├── __init__.py
│   └── x86_profiles.py
├── crates/
│   └── ov_cli/
│       ├── Cargo.toml
│       ├── README.md
│       ├── install.sh
│       ├── src/
│       │   ├── client.rs
│       │   ├── commands/
│       │   │   ├── admin.rs
│       │   │   ├── chat.rs
│       │   │   ├── content.rs
│       │   │   ├── filesystem.rs
│       │   │   ├── mod.rs
│       │   │   ├── observer.rs
│       │   │   ├── pack.rs
│       │   │   ├── relations.rs
│       │   │   ├── resources.rs
│       │   │   ├── search.rs
│       │   │   ├── session.rs
│       │   │   └── system.rs
│       │   ├── config.rs
│       │   ├── error.rs
│       │   ├── main.rs
│       │   ├── output.rs
│       │   ├── tui/
│       │   │   ├── app.rs
│       │   │   ├── event.rs
│       │   │   ├── mod.rs
│       │   │   ├── tree.rs
│       │   │   └── ui.rs
│       │   └── utils.rs
│       └── test_ov.sh
├── deploy/
│   └── helm/
│       ├── README.md
│       └── openviking/
│           ├── .helmignore
│           ├── Chart.yaml
│           ├── templates/
│           │   ├── NOTES.txt
│           │   ├── _helpers.tpl
│           │   ├── configmap.yaml
│           │   ├── deployment.yaml
│           │   ├── ingress.yaml
│           │   ├── pvc.yaml
│           │   └── service.yaml
│           └── values.yaml
├── docker-compose.yml
├── docs/
│   ├── design/
│   │   ├── multi-tenant-design.md
│   │   └── openclaw-integration.md
│   ├── en/
│   │   ├── about/
│   │   │   ├── 01-about-us.md
│   │   │   ├── 02-changelog.md
│   │   │   └── 03-roadmap.md
│   │   ├── api/
│   │   │   ├── 01-overview.md
│   │   │   ├── 02-resources.md
│   │   │   ├── 03-filesystem.md
│   │   │   ├── 04-skills.md
│   │   │   ├── 05-sessions.md
│   │   │   ├── 06-retrieval.md
│   │   │   ├── 07-system.md
│   │   │   └── 08-admin.md
│   │   ├── concepts/
│   │   │   ├── 01-architecture.md
│   │   │   ├── 02-context-types.md
│   │   │   ├── 03-context-layers.md
│   │   │   ├── 04-viking-uri.md
│   │   │   ├── 05-storage.md
│   │   │   ├── 06-extraction.md
│   │   │   ├── 07-retrieval.md
│   │   │   ├── 08-session.md
│   │   │   └── 09-transaction.md
│   │   ├── faq/
│   │   │   └── faq.md
│   │   ├── getting-started/
│   │   │   ├── 01-introduction.md
│   │   │   ├── 02-quickstart.md
│   │   │   └── 03-quickstart-server.md
│   │   └── guides/
│   │       ├── 01-configuration.md
│   │       ├── 02-volcengine-purchase-guide.md
│   │       ├── 03-deployment.md
│   │       ├── 04-authentication.md
│   │       ├── 05-monitoring.md
│   │       ├── 06-mcp-integration.md
│   │       └── 07-operation-telemetry.md
│   └── zh/
│       ├── about/
│       │   ├── 01-about-us.md
│       │   ├── 02-changelog.md
│       │   └── 03-roadmap.md
│       ├── api/
│       │   ├── 01-overview.md
│       │   ├── 02-resources.md
│       │   ├── 03-filesystem.md
│       │   ├── 04-skills.md
│       │   ├── 05-sessions.md
│       │   ├── 06-retrieval.md
│       │   ├── 07-system.md
│       │   └── 08-admin.md
│       ├── concepts/
│       │   ├── 01-architecture.md
│       │   ├── 02-context-types.md
│       │   ├── 03-context-layers.md
│       │   ├── 04-viking-uri.md
│       │   ├── 05-storage.md
│       │   ├── 06-extraction.md
│       │   ├── 07-retrieval.md
│       │   ├── 08-session.md
│       │   └── 09-transaction.md
│       ├── faq/
│       │   └── faq.md
│       ├── getting-started/
│       │   ├── 01-introduction.md
│       │   ├── 02-quickstart.md
│       │   └── 03-quickstart-server.md
│       └── guides/
│           ├── 01-configuration.md
│           ├── 02-volcengine-purchase-guide.md
│           ├── 03-deployment.md
│           ├── 04-authentication.md
│           ├── 05-monitoring.md
│           ├── 06-mcp-integration.md
│           └── 07-operation-telemetry.md
├── examples/
│   ├── claude-memory-plugin/
│   │   ├── .claude-plugin/
│   │   │   └── plugin.json
│   │   ├── README.md
│   │   ├── hooks/
│   │   │   ├── common.sh
│   │   │   ├── hooks.json
│   │   │   ├── session-end.sh
│   │   │   ├── session-start.sh
│   │   │   ├── stop.sh
│   │   │   └── user-prompt-submit.sh
│   │   ├── scripts/
│   │   │   ├── ov_memory.py
│   │   │   └── run_e2e_claude_session.sh
│   │   └── skills/
│   │       └── memory-recall/
│   │           └── SKILL.md
│   ├── cloud/
│   │   ├── .gitignore
│   │   ├── GUIDE.md
│   │   ├── alice.py
│   │   ├── bob.py
│   │   ├── ov.conf.example
│   │   └── setup_users.py
│   ├── common/
│   │   ├── __init__.py
│   │   ├── boring_logging_config.py
│   │   ├── recipe.py
│   │   └── resource_manager.py
│   ├── k8s-helm/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── README.md
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── secret.yaml
│   │   │   └── service.yaml
│   │   └── values.yaml
│   ├── mcp-query/
│   │   ├── README.md
│   │   ├── ov.conf.example
│   │   ├── pyproject.toml
│   │   └── server.py
│   ├── misc/
│   │   └── memory_demo.py
│   ├── multi_tenant/
│   │   ├── README.md
│   │   ├── admin_workflow.py
│   │   ├── admin_workflow.sh
│   │   ├── ov.conf.example
│   │   └── pyproject.toml
│   ├── openclaw-plugin/
│   │   ├── .gitignore
│   │   ├── INSTALL-AGENT.md
│   │   ├── INSTALL-ZH.md
│   │   ├── INSTALL.md
│   │   ├── README.md
│   │   ├── client.ts
│   │   ├── config.ts
│   │   ├── context-engine.ts
│   │   ├── demo-memory-ajie.py
│   │   ├── demo-memory-xiaomei.py
│   │   ├── index.ts
│   │   ├── install.ps1
│   │   ├── install.sh
│   │   ├── memory-ranking.ts
│   │   ├── openclaw.plugin.json
│   │   ├── package.json
│   │   ├── process-manager.ts
│   │   ├── setup-helper/
│   │   │   ├── install.js
│   │   │   └── package.json
│   │   ├── skills/
│   │   │   └── install-openviking-memory/
│   │   │       └── SKILL.md
│   │   ├── text-utils.ts
│   │   └── tsconfig.json
│   ├── opencode/
│   │   └── plugin/
│   │       ├── README.md
│   │       ├── index.mjs
│   │       ├── package.json
│   │       └── skills/
│   │           └── openviking/
│   │               └── SKILL.md
│   ├── opencode-memory-plugin/
│   │   ├── .gitignore
│   │   ├── INSTALL-ZH.md
│   │   ├── README.md
│   │   ├── openviking-config.example.json
│   │   └── openviking-memory.ts
│   ├── ov.conf.example
│   ├── ovcli.conf.example
│   ├── quick_start.py
│   ├── server_client/
│   │   ├── README.md
│   │   ├── client_async.py
│   │   ├── client_cli.sh
│   │   ├── client_sync.py
│   │   ├── ov.conf.example
│   │   ├── ovcli.conf.example
│   │   └── pyproject.toml
│   ├── skills/
│   │   ├── ov-add-data/
│   │   │   └── SKILL.md
│   │   ├── ov-search-context/
│   │   │   └── SKILL.md
│   │   └── ov-server-operate/
│   │       └── SKILL.md
│   └── watch_resource_example.py
├── openviking/
│   ├── __init__.py
│   ├── agfs_manager.py
│   ├── async_client.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── local.py
│   │   └── session.py
│   ├── client.py
│   ├── console/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── app.py
│   │   ├── bootstrap.py
│   │   ├── config.py
│   │   └── static/
│   │       ├── app.js
│   │       ├── index.html
│   │       └── styles.css
│   ├── core/
│   │   ├── __init__.py
│   │   ├── building_tree.py
│   │   ├── context.py
│   │   ├── directories.py
│   │   ├── mcp_converter.py
│   │   └── skill_loader.py
│   ├── eval/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── datasets/
│   │   │   └── local_doc_example_glm5.jsonl
│   │   ├── ragas/
│   │   │   ├── __init__.py
│   │   │   ├── analyze_records.py
│   │   │   ├── base.py
│   │   │   ├── generator.py
│   │   │   ├── pipeline.py
│   │   │   ├── play_recorder.py
│   │   │   ├── playback.py
│   │   │   ├── rag_eval.py
│   │   │   ├── record_analysis.py
│   │   │   └── types.py
│   │   └── recorder/
│   │       ├── __init__.py
│   │       ├── async_writer.py
│   │       ├── playback.py
│   │       ├── recorder.py
│   │       ├── recording_client.py
│   │       ├── types.py
│   │       └── wrapper.py
│   ├── message/
│   │   ├── __init__.py
│   │   ├── message.py
│   │   └── part.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── embedder/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── gemini_embedders.py
│   │   │   ├── jina_embedders.py
│   │   │   ├── minimax_embedders.py
│   │   │   ├── openai_embedders.py
│   │   │   ├── vikingdb_embedders.py
│   │   │   ├── volcengine_embedders.py
│   │   │   └── voyage_embedders.py
│   │   └── vlm/
│   │       ├── __init__.py
│   │       ├── backends/
│   │       │   ├── litellm_vlm.py
│   │       │   ├── openai_vlm.py
│   │       │   └── volcengine_vlm.py
│   │       ├── base.py
│   │       ├── llm.py
│   │       ├── registry.py
│   │       └── token_usage.py
│   ├── parse/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── converter.py
│   │   ├── custom.py
│   │   ├── directory_scan.py
│   │   ├── ovpack/
│   │   │   └── __init__.py
│   │   ├── parsers/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base_parser.py
│   │   │   ├── code/
│   │   │   │   ├── README.md
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ast/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── extractor.py
│   │   │   │   │   ├── languages/
│   │   │   │   │   │   ├── __init__.py
│   │   │   │   │   │   ├── base.py
│   │   │   │   │   │   ├── cpp.py
│   │   │   │   │   │   ├── csharp.py
│   │   │   │   │   │   ├── go.py
│   │   │   │   │   │   ├── java.py
│   │   │   │   │   │   ├── js_ts.py
│   │   │   │   │   │   ├── python.py
│   │   │   │   │   │   └── rust.py
│   │   │   │   │   └── skeleton.py
│   │   │   │   └── code.py
│   │   │   ├── constants.py
│   │   │   ├── directory.py
│   │   │   ├── epub.py
│   │   │   ├── excel.py
│   │   │   ├── html.py
│   │   │   ├── legacy_doc.py
│   │   │   ├── markdown.py
│   │   │   ├── media/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── audio.py
│   │   │   │   ├── constants.py
│   │   │   │   ├── image.py
│   │   │   │   ├── utils.py
│   │   │   │   └── video.py
│   │   │   ├── pdf.py
│   │   │   ├── powerpoint.py
│   │   │   ├── text.py
│   │   │   ├── upload_utils.py
│   │   │   ├── word.py
│   │   │   └── zip_parser.py
│   │   ├── registry.py
│   │   ├── resource_detector/
│   │   │   ├── __init__.py
│   │   │   ├── detect_info.py
│   │   │   ├── recursive.py
│   │   │   ├── size.py
│   │   │   └── visit.py
│   │   ├── tree_builder.py
│   │   └── vlm.py
│   ├── prompts/
│   │   ├── __init__.py
│   │   ├── manager.py
│   │   └── templates/
│   │       ├── compression/
│   │       │   ├── dedup_decision.yaml
│   │       │   ├── field_compress.yaml
│   │       │   ├── memory_extraction.yaml
│   │       │   ├── memory_merge.yaml
│   │       │   ├── memory_merge_bundle.yaml
│   │       │   └── structured_summary.yaml
│   │       ├── indexing/
│   │       │   └── relevance_scoring.yaml
│   │       ├── parsing/
│   │       │   ├── chapter_analysis.yaml
│   │       │   ├── context_generation.yaml
│   │       │   ├── image_summary.yaml
│   │       │   └── semantic_grouping.yaml
│   │       ├── processing/
│   │       │   ├── interaction_learning.yaml
│   │       │   ├── strategy_extraction.yaml
│   │       │   └── tool_chain_analysis.yaml
│   │       ├── retrieval/
│   │       │   └── intent_analysis.yaml
│   │       ├── semantic/
│   │       │   ├── code_ast_summary.yaml
│   │       │   ├── code_summary.yaml
│   │       │   ├── document_summary.yaml
│   │       │   ├── file_summary.yaml
│   │       │   └── overview_generation.yaml
│   │       ├── skill/
│   │       │   └── overview_generation.yaml
│   │       ├── test/
│   │       │   └── skill_test_generation.yaml
│   │       └── vision/
│   │           ├── batch_filtering.yaml
│   │           ├── image_filtering.yaml
│   │           ├── image_understanding.yaml
│   │           ├── page_understanding.yaml
│   │           ├── page_understanding_batch.yaml
│   │           ├── table_understanding.yaml
│   │           └── unified_analysis.yaml
│   ├── pyagfs/
│   │   ├── __init__.py
│   │   ├── binding_client.py
│   │   ├── client.py
│   │   ├── exceptions.py
│   │   └── helpers.py
│   ├── resource/
│   │   ├── __init__.py
│   │   ├── watch_manager.py
│   │   └── watch_scheduler.py
│   ├── retrieve/
│   │   ├── __init__.py
│   │   ├── hierarchical_retriever.py
│   │   ├── intent_analyzer.py
│   │   ├── memory_lifecycle.py
│   │   └── retrieval_stats.py
│   ├── server/
│   │   ├── __init__.py
│   │   ├── api_keys.py
│   │   ├── app.py
│   │   ├── auth.py
│   │   ├── bootstrap.py
│   │   ├── config.py
│   │   ├── dependencies.py
│   │   ├── identity.py
│   │   ├── models.py
│   │   ├── routers/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── bot.py
│   │   │   ├── content.py
│   │   │   ├── debug.py
│   │   │   ├── filesystem.py
│   │   │   ├── observer.py
│   │   │   ├── pack.py
│   │   │   ├── relations.py
│   │   │   ├── resources.py
│   │   │   ├── search.py
│   │   │   ├── sessions.py
│   │   │   ├── system.py
│   │   │   └── tasks.py
│   │   └── telemetry.py
│   ├── service/
│   │   ├── __init__.py
│   │   ├── core.py
│   │   ├── debug_service.py
│   │   ├── fs_service.py
│   │   ├── pack_service.py
│   │   ├── relation_service.py
│   │   ├── resource_service.py
│   │   ├── search_service.py
│   │   ├── session_service.py
│   │   └── task_tracker.py
│   ├── session/
│   │   ├── __init__.py
│   │   ├── compressor.py
│   │   ├── memory_archiver.py
│   │   ├── memory_deduplicator.py
│   │   ├── memory_extractor.py
│   │   ├── session.py
│   │   └── tool_skill_utils.py
│   ├── storage/
│   │   ├── __init__.py
│   │   ├── collection_schemas.py
│   │   ├── errors.py
│   │   ├── expr.py
│   │   ├── local_fs.py
│   │   ├── observers/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base_observer.py
│   │   │   ├── lock_observer.py
│   │   │   ├── queue_observer.py
│   │   │   ├── retrieval_observer.py
│   │   │   ├── vikingdb_observer.py
│   │   │   └── vlm_observer.py
│   │   ├── queuefs/
│   │   │   ├── __init__.py
│   │   │   ├── embedding_msg.py
│   │   │   ├── embedding_msg_converter.py
│   │   │   ├── embedding_queue.py
│   │   │   ├── embedding_tracker.py
│   │   │   ├── named_queue.py
│   │   │   ├── queue_manager.py
│   │   │   ├── semantic_dag.py
│   │   │   ├── semantic_msg.py
│   │   │   ├── semantic_processor.py
│   │   │   └── semantic_queue.py
│   │   ├── transaction/
│   │   │   ├── __init__.py
│   │   │   ├── lock_context.py
│   │   │   ├── lock_handle.py
│   │   │   ├── lock_manager.py
│   │   │   ├── path_lock.py
│   │   │   └── redo_log.py
│   │   ├── vectordb/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── collection/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── collection.py
│   │   │   │   ├── http_collection.py
│   │   │   │   ├── local_collection.py
│   │   │   │   ├── result.py
│   │   │   │   ├── vikingdb_clients.py
│   │   │   │   ├── vikingdb_collection.py
│   │   │   │   ├── volcengine_clients.py
│   │   │   │   └── volcengine_collection.py
│   │   │   ├── engine/
│   │   │   │   └── __init__.py
│   │   │   ├── index/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── index.py
│   │   │   │   └── local_index.py
│   │   │   ├── meta/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── collection_meta.py
│   │   │   │   ├── dict.py
│   │   │   │   ├── index_meta.py
│   │   │   │   └── local_dict.py
│   │   │   ├── project/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── http_project.py
│   │   │   │   ├── local_project.py
│   │   │   │   ├── project.py
│   │   │   │   ├── project_group.py
│   │   │   │   ├── vikingdb_project.py
│   │   │   │   └── volcengine_project.py
│   │   │   ├── service/
│   │   │   │   ├── README_FASTAPI.md
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api_fastapi.py
│   │   │   │   ├── app_models.py
│   │   │   │   ├── code.py
│   │   │   │   └── server_fastapi.py
│   │   │   ├── store/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── bytes_row.py
│   │   │   │   ├── data.py
│   │   │   │   ├── file_store.py
│   │   │   │   ├── local_store.py
│   │   │   │   ├── serializable.py
│   │   │   │   ├── store.py
│   │   │   │   └── store_manager.py
│   │   │   ├── utils/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api_utils.py
│   │   │   │   ├── config_utils.py
│   │   │   │   ├── constants.py
│   │   │   │   ├── data_processor.py
│   │   │   │   ├── data_utils.py
│   │   │   │   ├── dict_utils.py
│   │   │   │   ├── file_utils.py
│   │   │   │   ├── id_generator.py
│   │   │   │   ├── logging_init.py
│   │   │   │   ├── stale_lock.py
│   │   │   │   ├── str_to_uint64.py
│   │   │   │   └── validation.py
│   │   │   └── vectorize/
│   │   │       ├── __init__.py
│   │   │       ├── base.py
│   │   │       ├── vectorizer.py
│   │   │       ├── vectorizer_factory.py
│   │   │       └── volcengine_vectorizer.py
│   │   ├── vectordb_adapters/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── factory.py
│   │   │   ├── http_adapter.py
│   │   │   ├── local_adapter.py
│   │   │   ├── vikingdb_private_adapter.py
│   │   │   └── volcengine_adapter.py
│   │   ├── viking_fs.py
│   │   ├── viking_vector_index_backend.py
│   │   └── vikingdb_manager.py
│   ├── sync_client.py
│   ├── telemetry/
│   │   ├── __init__.py
│   │   ├── backends/
│   │   │   ├── __init__.py
│   │   │   └── memory.py
│   │   ├── context.py
│   │   ├── execution.py
│   │   ├── operation.py
│   │   ├── registry.py
│   │   ├── request.py
│   │   ├── resource_summary.py
│   │   ├── runtime.py
│   │   └── snapshot.py
│   └── utils/
│       ├── __init__.py
│       ├── agfs_utils.py
│       ├── code_hosting_utils.py
│       ├── embedding_utils.py
│       ├── media_processor.py
│       ├── process_lock.py
│       ├── resource_processor.py
│       ├── skill_processor.py
│       ├── summarizer.py
│       └── time_utils.py
├── openviking_cli/
│   ├── __init__.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── http.py
│   │   └── sync_http.py
│   ├── exceptions.py
│   ├── retrieve/
│   │   ├── __init__.py
│   │   └── types.py
│   ├── rust_cli.py
│   ├── server_bootstrap.py
│   ├── session/
│   │   ├── __init__.py
│   │   └── user_id.py
│   └── utils/
│       ├── __init__.py
│       ├── async_utils.py
│       ├── config/
│       │   ├── __init__.py
│       │   ├── agfs_config.py
│       │   ├── config_loader.py
│       │   ├── consts.py
│       │   ├── embedding_config.py
│       │   ├── log_config.py
│       │   ├── open_viking_config.py
│       │   ├── parser_config.py
│       │   ├── rerank_config.py
│       │   ├── storage_config.py
│       │   ├── transaction_config.py
│       │   ├── vectordb_config.py
│       │   └── vlm_config.py
│       ├── downloader.py
│       ├── extractor.py
│       ├── llm.py
│       ├── logger.py
│       ├── rerank.py
│       ├── rerank_openai.py
│       ├── storage.py
│       └── uri.py
├── pyproject.toml
├── setup.py
├── src/
│   ├── CMakeLists.txt
│   ├── common/
│   │   ├── ann_utils.h
│   │   ├── io_utils.h
│   │   ├── json_utils.h
│   │   ├── log_utils.cpp
│   │   ├── log_utils.h
│   │   ├── string_utils.h
│   │   └── zip_sort.h
│   ├── cpu_feature_probe.cpp
│   ├── index/
│   │   ├── common_structs.h
│   │   ├── detail/
│   │   │   ├── fields_dict.h
│   │   │   ├── index_manager_impl.cpp
│   │   │   ├── index_manager_impl.h
│   │   │   ├── meta/
│   │   │   │   ├── bruteforce_meta.h
│   │   │   │   ├── manager_meta.h
│   │   │   │   ├── scalar_index_meta.cpp
│   │   │   │   ├── scalar_index_meta.h
│   │   │   │   ├── vector_index_meta.cpp
│   │   │   │   └── vector_index_meta.h
│   │   │   ├── scalar/
│   │   │   │   ├── bitmap_holder/
│   │   │   │   │   ├── bitmap.cpp
│   │   │   │   │   ├── bitmap.h
│   │   │   │   │   ├── bitmap_field_group.cpp
│   │   │   │   │   ├── bitmap_field_group.h
│   │   │   │   │   ├── bitmap_utils.h
│   │   │   │   │   ├── dir_index.cpp
│   │   │   │   │   ├── dir_index.h
│   │   │   │   │   ├── ranged_map.cpp
│   │   │   │   │   └── ranged_map.h
│   │   │   │   ├── filter/
│   │   │   │   │   ├── filter_ops.cpp
│   │   │   │   │   ├── filter_ops.h
│   │   │   │   │   ├── op_base.cpp
│   │   │   │   │   ├── op_base.h
│   │   │   │   │   ├── sort_ops.cpp
│   │   │   │   │   └── sort_ops.h
│   │   │   │   ├── scalar_index.cpp
│   │   │   │   └── scalar_index.h
│   │   │   ├── search_context.h
│   │   │   └── vector/
│   │   │       ├── common/
│   │   │       │   ├── bruteforce.h
│   │   │       │   ├── quantization_int8.h
│   │   │       │   ├── quantizer.h
│   │   │       │   ├── space_int8.h
│   │   │       │   ├── space_ip.h
│   │   │       │   ├── space_l2.h
│   │   │       │   └── vector_base.h
│   │   │       ├── sparse_retrieval/
│   │   │       │   ├── common.h
│   │   │       │   ├── sparse_data_holder.h
│   │   │       │   ├── sparse_datapoint.cpp
│   │   │       │   ├── sparse_datapoint.h
│   │   │       │   ├── sparse_dataset.h
│   │   │       │   ├── sparse_distance_measure.h
│   │   │       │   ├── sparse_row_index.cpp
│   │   │       │   └── sparse_row_index.h
│   │   │       ├── vector_index_adapter.h
│   │   │       └── vector_recall.h
│   │   ├── index_engine.cpp
│   │   ├── index_engine.h
│   │   └── index_manager.h
│   ├── py_accessors.h
│   ├── pybind11_interface.cpp
│   └── store/
│       ├── bytes_row.cpp
│       ├── bytes_row.h
│       ├── common_structs.h
│       ├── kv_store.h
│       ├── persist_store.cpp
│       ├── persist_store.h
│       ├── volatile_store.cpp
│       └── volatile_store.h
├── tests/
│   ├── README.md
│   ├── __init__.py
│   ├── agfs/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_fs_binding.py
│   │   ├── test_fs_binding_s3.py
│   │   ├── test_fs_local.py
│   │   └── test_fs_s3.py
│   ├── cli/
│   │   ├── conftest.py
│   │   └── test_user_identifier.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_chat_integration.py
│   │   ├── test_file_operations.py
│   │   ├── test_filesystem.py
│   │   ├── test_import_export.py
│   │   ├── test_lifecycle.py
│   │   ├── test_relations.py
│   │   ├── test_resource_management.py
│   │   ├── test_search.py
│   │   ├── test_skill_management.py
│   │   └── test_windows_path_handling.py
│   ├── conftest.py
│   ├── engine/
│   │   ├── CMakeLists.txt
│   │   ├── test_common.cpp
│   │   └── test_index_engine.cpp
│   ├── eval/
│   │   ├── test_ragas_basic.py
│   │   ├── test_ragas_eval.py
│   │   └── test_ragas_validation.py
│   ├── integration/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_add_resource_index.py
│   │   ├── test_full_workflow.py
│   │   ├── test_gemini_e2e.py
│   │   ├── test_gemini_embedding_it.py
│   │   ├── test_gemini_openviking_it.py
│   │   ├── test_http_integration.py
│   │   ├── test_quick_start_lite.py
│   │   └── test_watch_e2e.py
│   ├── misc/
│   │   ├── test_code_parser.py
│   │   ├── test_config_validation.py
│   │   ├── test_debug_service.py
│   │   ├── test_embedding_input_type.py
│   │   ├── test_extract_zip.py
│   │   ├── test_mkdir.py
│   │   ├── test_port_check.py
│   │   ├── test_process_lock.py
│   │   ├── test_rerank_openai.py
│   │   ├── test_resource_processor_mv.py
│   │   ├── test_semantic_config.py
│   │   ├── test_tree_builder_dedup.py
│   │   ├── test_vectordb_engine_loader.py
│   │   ├── test_vikingdb_observer.py
│   │   ├── test_vikingfs_find_without_rerank.py
│   │   ├── test_vikingfs_uri_guard.py
│   │   └── test_x86_profiles.py
│   ├── models/
│   │   ├── test_embedding_telemetry_usage.py
│   │   └── test_vlm_strip_think_tags.py
│   ├── parse/
│   │   ├── __init__.py
│   │   ├── test_add_directory.py
│   │   ├── test_ast_extractor.py
│   │   ├── test_directory_parser_routing.py
│   │   ├── test_directory_scan.py
│   │   ├── test_filename_safety.py
│   │   ├── test_html_parser_utils.py
│   │   ├── test_pdf_bookmark_extraction.py
│   │   └── test_url_filename_preservation.py
│   ├── resource/
│   │   ├── __init__.py
│   │   ├── test_watch_manager.py
│   │   └── test_watch_scheduler.py
│   ├── retrieve/
│   │   ├── test_hierarchical_retriever_rerank.py
│   │   └── test_hierarchical_retriever_target_dirs.py
│   ├── server/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_admin_api.py
│   │   ├── test_api_content.py
│   │   ├── test_api_filesystem.py
│   │   ├── test_api_key_manager.py
│   │   ├── test_api_observer.py
│   │   ├── test_api_relations.py
│   │   ├── test_api_resources.py
│   │   ├── test_api_search.py
│   │   ├── test_api_sessions.py
│   │   ├── test_auth.py
│   │   ├── test_error_scenarios.py
│   │   ├── test_http_client_sdk.py
│   │   ├── test_identity.py
│   │   └── test_server_health.py
│   ├── service/
│   │   ├── test_resource_service_watch.py
│   │   └── test_watch_recovery.py
│   ├── session/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_memory_dedup_actions.py
│   │   ├── test_memory_extractor_language.py
│   │   ├── test_memory_extractor_response_types.py
│   │   ├── test_session_commit.py
│   │   ├── test_session_compressor_vikingdb.py
│   │   ├── test_session_context.py
│   │   ├── test_session_lifecycle.py
│   │   ├── test_session_messages.py
│   │   └── test_session_usage.py
│   ├── storage/
│   │   ├── mock_backend.py
│   │   ├── test_collection_schemas.py
│   │   ├── test_embedding_msg_converter_tenant.py
│   │   ├── test_semantic_dag_skip_files.py
│   │   ├── test_semantic_dag_stats.py
│   │   ├── test_semantic_processor_mv_vector_store.py
│   │   ├── test_stale_lock.py
│   │   ├── test_vectordb_adaptor.py
│   │   └── test_vectordb_collection_loading.py
│   ├── telemetry/
│   │   ├── test_execution.py
│   │   ├── test_layering_rules.py
│   │   └── test_resource_summary.py
│   ├── test_code_hosting_utils.py
│   ├── test_config_loader.py
│   ├── test_edge_cases.py
│   ├── test_edge_cases_simple.py
│   ├── test_memory_lifecycle.py
│   ├── test_session_async_commit.py
│   ├── test_session_task_tracking.py
│   ├── test_task_tracker.py
│   ├── test_telemetry_runtime.py
│   ├── test_upload_utils.py
│   ├── transaction/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_concurrent_lock.py
│   │   ├── test_e2e.py
│   │   ├── test_lock_context.py
│   │   ├── test_lock_manager.py
│   │   ├── test_path_lock.py
│   │   └── test_redo_log.py
│   ├── unit/
│   │   ├── __init__.py
│   │   ├── retrieve/
│   │   │   └── test_retrieval_stats.py
│   │   ├── session/
│   │   │   ├── test_deduplicator_uri.py
│   │   │   └── test_memory_archiver.py
│   │   ├── test_embedding_config_gemini.py
│   │   ├── test_embedding_config_voyage.py
│   │   ├── test_extra_headers_embedding.py
│   │   ├── test_extra_headers_vlm.py
│   │   ├── test_gemini_embedder.py
│   │   ├── test_jina_embedder.py
│   │   ├── test_minimax_embedder_simple.py
│   │   ├── test_ollama_embedding_factory.py
│   │   ├── test_openai_embedder.py
│   │   ├── test_skill_processor_none.py
│   │   ├── test_stream_config_vlm.py
│   │   ├── test_time_utils.py
│   │   ├── test_uri_short_format.py
│   │   ├── test_vlm_response_formats.py
│   │   ├── test_voyage_embedder.py
│   │   └── tool_skill/
│   │       ├── test_tool_skill_calibration.py
│   │       ├── test_tool_skill_memory_guardrails.py
│   │       └── test_tool_skill_utils.py
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── mock_agfs.py
│   │   └── mock_context.py
│   └── vectordb/
│       ├── benchmark_stress.py
│       ├── test_bytes_row.py
│       ├── test_collection_large_scale.py
│       ├── test_crash_recovery.py
│       ├── test_data_processor.py
│       ├── test_filter_ops.py
│       ├── test_openviking_vectordb.py
│       ├── test_project_group.py
│       ├── test_pydantic_validation.py
│       ├── test_recall.py
│       └── test_vikingdb_project.py
└── third_party/
    ├── agfs/
    │   ├── .github/
    │   │   └── workflows/
    │   │       └── daily-build.yml
    │   ├── .gitignore
    │   ├── LICENSE
    │   ├── README.md
    │   ├── agfs-fuse/
    │   │   ├── .gitignore
    │   │   ├── Makefile
    │   │   ├── README.md
    │   │   ├── cmd/
    │   │   │   └── agfs-fuse/
    │   │   │       └── main.go
    │   │   ├── go.mod
    │   │   ├── go.sum
    │   │   └── pkg/
    │   │       ├── cache/
    │   │       │   ├── cache.go
    │   │       │   └── cache_test.go
    │   │       ├── fusefs/
    │   │       │   ├── file.go
    │   │       │   ├── fs.go
    │   │       │   ├── handles.go
    │   │       │   ├── handles_test.go
    │   │       │   └── node.go
    │   │       └── version/
    │   │           └── version.go
    │   ├── agfs-mcp/
    │   │   ├── .gitignore
    │   │   ├── .mcp.json
    │   │   ├── README.md
    │   │   ├── demos/
    │   │   │   ├── hackernews_research.py
    │   │   │   ├── parallel_research.py
    │   │   │   ├── start_agents.sh
    │   │   │   ├── start_agents_tmux.sh
    │   │   │   ├── stop_agents.sh
    │   │   │   ├── stop_agents_tmux.sh
    │   │   │   └── task_loop.py
    │   │   ├── pyproject.toml
    │   │   └── src/
    │   │       └── agfs_mcp/
    │   │           ├── __init__.py
    │   │           └── server.py
    │   ├── agfs-sdk/
    │   │   ├── go/
    │   │   │   ├── README.md
    │   │   │   ├── client.go
    │   │   │   ├── client_test.go
    │   │   │   ├── go.mod
    │   │   │   └── types.go
    │   │   └── python/
    │   │       ├── README.md
    │   │       ├── examples/
    │   │       │   ├── advanced_usage.py
    │   │       │   ├── basic_usage.py
    │   │       │   └── helpers_usage.py
    │   │       ├── pyagfs/
    │   │       │   ├── __init__.py
    │   │       │   ├── binding_client.py
    │   │       │   ├── client.py
    │   │       │   ├── exceptions.py
    │   │       │   └── helpers.py
    │   │       └── pyproject.toml
    │   ├── agfs-shell/
    │   │   ├── .gitignore
    │   │   ├── Makefile
    │   │   ├── README.md
    │   │   ├── agfs_shell/
    │   │   │   ├── __init__.py
    │   │   │   ├── arg_parser.py
    │   │   │   ├── ast_nodes.py
    │   │   │   ├── builtins.py
    │   │   │   ├── cli.py
    │   │   │   ├── command_decorators.py
    │   │   │   ├── commands/
    │   │   │   │   ├── __init__.py
    │   │   │   │   ├── base.py
    │   │   │   │   ├── basename.py
    │   │   │   │   ├── break_cmd.py
    │   │   │   │   ├── cat.py
    │   │   │   │   ├── cd.py
    │   │   │   │   ├── continue_cmd.py
    │   │   │   │   ├── cp.py
    │   │   │   │   ├── cut.py
    │   │   │   │   ├── date.py
    │   │   │   │   ├── dirname.py
    │   │   │   │   ├── download.py
    │   │   │   │   ├── echo.py
    │   │   │   │   ├── env.py
    │   │   │   │   ├── exit.py
    │   │   │   │   ├── export.py
    │   │   │   │   ├── false.py
    │   │   │   │   ├── grep.py
    │   │   │   │   ├── head.py
    │   │   │   │   ├── help.py
    │   │   │   │   ├── jq.py
    │   │   │   │   ├── llm.py
    │   │   │   │   ├── local.py
    │   │   │   │   ├── ls.py
    │   │   │   │   ├── mkdir.py
    │   │   │   │   ├── mount.py
    │   │   │   │   ├── mv.py
    │   │   │   │   ├── plugins.py
    │   │   │   │   ├── pwd.py
    │   │   │   │   ├── return_cmd.py
    │   │   │   │   ├── rev.py
    │   │   │   │   ├── rm.py
    │   │   │   │   ├── sleep.py
    │   │   │   │   ├── sort.py
    │   │   │   │   ├── stat.py
    │   │   │   │   ├── tail.py
    │   │   │   │   ├── tee.py
    │   │   │   │   ├── test.py
    │   │   │   │   ├── touch.py
    │   │   │   │   ├── tr.py
    │   │   │   │   ├── tree.py
    │   │   │   │   ├── true.py
    │   │   │   │   ├── uniq.py
    │   │   │   │   ├── unset.py
    │   │   │   │   ├── upload.py
    │   │   │   │   └── wc.py
    │   │   │   ├── completer.py
    │   │   │   ├── config.py
    │   │   │   ├── control_flow.py
    │   │   │   ├── control_parser.py
    │   │   │   ├── executor.py
    │   │   │   ├── exit_codes.py
    │   │   │   ├── expression.py
    │   │   │   ├── filesystem.py
    │   │   │   ├── lexer.py
    │   │   │   ├── parser.py
    │   │   │   ├── pipeline.py
    │   │   │   ├── process.py
    │   │   │   ├── shell.py
    │   │   │   ├── streams.py
    │   │   │   ├── utils/
    │   │   │   │   ├── __init__.py
    │   │   │   │   └── formatters.py
    │   │   │   └── webapp_server.py
    │   │   ├── build.py
    │   │   ├── examples/
    │   │   │   ├── enqueue_task.as
    │   │   │   └── task_queue_worker.as
    │   │   ├── pyproject.toml
    │   │   ├── scripts/
    │   │   │   └── test_functions.as
    │   │   ├── tests/
    │   │   │   ├── test_builtins.py
    │   │   │   ├── test_parser.py
    │   │   │   └── test_pipeline.py
    │   │   └── webapp/
    │   │       ├── .gitignore
    │   │       ├── index.html
    │   │       ├── package.json
    │   │       ├── setup.sh
    │   │       ├── src/
    │   │       │   ├── App.css
    │   │       │   ├── App.jsx
    │   │       │   ├── components/
    │   │       │   │   ├── ContextMenu.jsx
    │   │       │   │   ├── Editor.jsx
    │   │       │   │   ├── FileTree.jsx
    │   │       │   │   ├── MenuBar.jsx
    │   │       │   │   └── Terminal.jsx
    │   │       │   └── main.jsx
    │   │       └── vite.config.js
    │   └── install.sh
    ├── croaring/
    │   ├── LICENSE
    │   ├── roaring.c
    │   ├── roaring.h
    │   └── roaring.hh
    ├── krl/
    │   ├── CMakeLists.txt
    │   ├── include/
    │   │   ├── krl.h
    │   │   ├── krl_internal.h
    │   │   ├── platform_macros.h
    │   │   └── safe_memory.h
    │   └── src/
    │       ├── IPdistance_simd.cpp
    │       └── L2distance_simd.cpp
    ├── leveldb-1.23/
    │   ├── .appveyor.yml
    │   ├── .clang-format
    │   ├── .gitignore
    │   ├── .gitmodules
    │   ├── .travis.yml
    │   ├── AUTHORS
    │   ├── CMakeLists.txt
    │   ├── CONTRIBUTING.md
    │   ├── LICENSE
    │   ├── NEWS
    │   ├── README.md
    │   ├── TODO
    │   ├── benchmarks/
    │   │   ├── db_bench.cc
    │   │   ├── db_bench_sqlite3.cc
    │   │   └── db_bench_tree_db.cc
    │   ├── cmake/
    │   │   └── leveldbConfig.cmake.in
    │   ├── db/
    │   │   ├── autocompact_test.cc
    │   │   ├── builder.cc
    │   │   ├── builder.h
    │   │   ├── c.cc
    │   │   ├── c_test.c
    │   │   ├── corruption_test.cc
    │   │   ├── db_impl.cc
    │   │   ├── db_impl.h
    │   │   ├── db_iter.cc
    │   │   ├── db_iter.h
    │   │   ├── db_test.cc
    │   │   ├── dbformat.cc
    │   │   ├── dbformat.h
    │   │   ├── dbformat_test.cc
    │   │   ├── dumpfile.cc
    │   │   ├── fault_injection_test.cc
    │   │   ├── filename.cc
    │   │   ├── filename.h
    │   │   ├── filename_test.cc
    │   │   ├── leveldbutil.cc
    │   │   ├── log_format.h
    │   │   ├── log_reader.cc
    │   │   ├── log_reader.h
    │   │   ├── log_test.cc
    │   │   ├── log_writer.cc
    │   │   ├── log_writer.h
    │   │   ├── memtable.cc
    │   │   ├── memtable.h
    │   │   ├── recovery_test.cc
    │   │   ├── repair.cc
    │   │   ├── skiplist.h
    │   │   ├── skiplist_test.cc
    │   │   ├── snapshot.h
    │   │   ├── table_cache.cc
    │   │   ├── table_cache.h
    │   │   ├── version_edit.cc
    │   │   ├── version_edit.h
    │   │   ├── version_edit_test.cc
    │   │   ├── version_set.cc
    │   │   ├── version_set.h
    │   │   ├── version_set_test.cc
    │   │   ├── write_batch.cc
    │   │   ├── write_batch_internal.h
    │   │   └── write_batch_test.cc
    │   ├── doc/
    │   │   ├── benchmark.html
    │   │   ├── impl.md
    │   │   ├── index.md
    │   │   ├── log_format.md
    │   │   └── table_format.md
    │   ├── helpers/
    │   │   └── memenv/
    │   │       ├── memenv.cc
    │   │       ├── memenv.h
    │   │       └── memenv_test.cc
    │   ├── include/
    │   │   ├── leveldb/
    │   │   │   ├── c.h
    │   │   │   ├── cache.h
    │   │   │   ├── comparator.h
    │   │   │   ├── db.h
    │   │   │   ├── dumpfile.h
    │   │   │   ├── env.h
    │   │   │   ├── export.h
    │   │   │   ├── filter_policy.h
    │   │   │   ├── iterator.h
    │   │   │   ├── options.h
    │   │   │   ├── slice.h
    │   │   │   ├── status.h
    │   │   │   ├── table.h
    │   │   │   ├── table_builder.h
    │   │   │   └── write_batch.h
    │   │   └── port/
    │   │       └── port_config.h
    │   ├── issues/
    │   │   ├── issue178_test.cc
    │   │   ├── issue200_test.cc
    │   │   └── issue320_test.cc
    │   ├── port/
    │   │   ├── README.md
    │   │   ├── port.h
    │   │   ├── port_config.h.in
    │   │   ├── port_example.h
    │   │   ├── port_stdcxx.h
    │   │   └── thread_annotations.h
    │   ├── table/
    │   │   ├── block.cc
    │   │   ├── block.h
    │   │   ├── block_builder.cc
    │   │   ├── block_builder.h
    │   │   ├── filter_block.cc
    │   │   ├── filter_block.h
    │   │   ├── filter_block_test.cc
    │   │   ├── format.cc
    │   │   ├── format.h
    │   │   ├── iterator.cc
    │   │   ├── iterator_wrapper.h
    │   │   ├── merger.cc
    │   │   ├── merger.h
    │   │   ├── table.cc
    │   │   ├── table_builder.cc
    │   │   ├── table_test.cc
    │   │   ├── two_level_iterator.cc
    │   │   └── two_level_iterator.h
    │   └── util/
    │       ├── arena.cc
    │       ├── arena.h
    │       ├── arena_test.cc
    │       ├── bloom.cc
    │       ├── bloom_test.cc
    │       ├── cache.cc
    │       ├── cache_test.cc
    │       ├── coding.cc
    │       ├── coding.h
    │       ├── coding_test.cc
    │       ├── comparator.cc
    │       ├── crc32c.cc
    │       ├── crc32c.h
    │       ├── crc32c_test.cc
    │       ├── env.cc
    │       ├── env_posix.cc
    │       ├── env_posix_test.cc
    │       ├── env_posix_test_helper.h
    │       ├── env_test.cc
    │       ├── env_windows.cc
    │       ├── env_windows_test.cc
    │       ├── env_windows_test_helper.h
    │       ├── filter_policy.cc
    │       ├── hash.cc
    │       ├── hash.h
    │       ├── hash_test.cc
    │       ├── histogram.cc
    │       ├── histogram.h
    │       ├── logging.cc
    │       ├── logging.h
    │       ├── logging_test.cc
    │       ├── mutexlock.h
    │       ├── no_destructor.h
    │       ├── no_destructor_test.cc
    │       ├── options.cc
    │       ├── posix_logger.h
    │       ├── random.h
    │       ├── status.cc
    │       ├── status_test.cc
    │       ├── testutil.cc
    │       ├── testutil.h
    │       └── windows_logger.h
    ├── rapidjson/
    │   ├── LICENSE
    │   ├── allocators.h
    │   ├── document.h
    │   ├── encodedstream.h
    │   ├── encodings.h
    │   ├── error/
    │   │   ├── en.h
    │   │   └── error.h
    │   ├── filereadstream.h
    │   ├── filewritestream.h
    │   ├── fwd.h
    │   ├── internal/
    │   │   ├── biginteger.h
    │   │   ├── diyfp.h
    │   │   ├── dtoa.h
    │   │   ├── ieee754.h
    │   │   ├── itoa.h
    │   │   ├── meta.h
    │   │   ├── pow10.h
    │   │   ├── regex.h
    │   │   ├── stack.h
    │   │   ├── strfunc.h
    │   │   ├── strtod.h
    │   │   └── swap.h
    │   ├── istreamwrapper.h
    │   ├── memorybuffer.h
    │   ├── memorystream.h
    │   ├── msinttypes/
    │   │   ├── inttypes.h
    │   │   └── stdint.h
    │   ├── ostreamwrapper.h
    │   ├── pointer.h
    │   ├── prettywriter.h
    │   ├── rapidjson.h
    │   ├── reader.h
    │   ├── schema.h
    │   ├── stream.h
    │   ├── stringbuffer.h
    │   └── writer.h
    └── spdlog-1.14.1/
        ├── .clang-format
        ├── .clang-tidy
        ├── .git-blame-ignore-revs
        ├── .gitattributes
        ├── .github/
        │   └── workflows/
        │       └── ci.yml
        ├── .gitignore
        ├── CMakeLists.txt
        ├── INSTALL
        ├── LICENSE
        ├── README.md
        ├── appveyor.yml
        ├── bench/
        │   ├── CMakeLists.txt
        │   ├── async_bench.cpp
        │   ├── bench.cpp
        │   ├── formatter-bench.cpp
        │   ├── latency.cpp
        │   └── utils.h
        ├── cmake/
        │   ├── ide.cmake
        │   ├── pch.h.in
        │   ├── spdlog.pc.in
        │   ├── spdlogCPack.cmake
        │   ├── spdlogConfig.cmake.in
        │   ├── utils.cmake
        │   └── version.rc.in
        ├── example/
        │   ├── CMakeLists.txt
        │   └── example.cpp
        ├── include/
        │   └── spdlog/
        │       ├── async.h
        │       ├── async_logger-inl.h
        │       ├── async_logger.h
        │       ├── cfg/
        │       │   ├── argv.h
        │       │   ├── env.h
        │       │   ├── helpers-inl.h
        │       │   └── helpers.h
        │       ├── common-inl.h
        │       ├── common.h
        │       ├── details/
        │       │   ├── backtracer-inl.h
        │       │   ├── backtracer.h
        │       │   ├── circular_q.h
        │       │   ├── console_globals.h
        │       │   ├── file_helper-inl.h
        │       │   ├── file_helper.h
        │       │   ├── fmt_helper.h
        │       │   ├── log_msg-inl.h
        │       │   ├── log_msg.h
        │       │   ├── log_msg_buffer-inl.h
        │       │   ├── log_msg_buffer.h
        │       │   ├── mpmc_blocking_q.h
        │       │   ├── null_mutex.h
        │       │   ├── os-inl.h
        │       │   ├── os.h
        │       │   ├── periodic_worker-inl.h
        │       │   ├── periodic_worker.h
        │       │   ├── registry-inl.h
        │       │   ├── registry.h
        │       │   ├── synchronous_factory.h
        │       │   ├── tcp_client-windows.h
        │       │   ├── tcp_client.h
        │       │   ├── thread_pool-inl.h
        │       │   ├── thread_pool.h
        │       │   ├── udp_client-windows.h
        │       │   ├── udp_client.h
        │       │   └── windows_include.h
        │       ├── fmt/
        │       │   ├── bin_to_hex.h
        │       │   ├── bundled/
        │       │   │   ├── args.h
        │       │   │   ├── chrono.h
        │       │   │   ├── color.h
        │       │   │   ├── compile.h
        │       │   │   ├── core.h
        │       │   │   ├── fmt.license.rst
        │       │   │   ├── format-inl.h
        │       │   │   ├── format.h
        │       │   │   ├── locale.h
        │       │   │   ├── os.h
        │       │   │   ├── ostream.h
        │       │   │   ├── printf.h
        │       │   │   ├── ranges.h
        │       │   │   ├── std.h
        │       │   │   └── xchar.h
        │       │   ├── chrono.h
        │       │   ├── compile.h
        │       │   ├── fmt.h
        │       │   ├── ostr.h
        │       │   ├── ranges.h
        │       │   ├── std.h
        │       │   └── xchar.h
        │       ├── formatter.h
        │       ├── fwd.h
        │       ├── logger-inl.h
        │       ├── logger.h
        │       ├── mdc.h
        │       ├── pattern_formatter-inl.h
        │       ├── pattern_formatter.h
        │       ├── sinks/
        │       │   ├── android_sink.h
        │       │   ├── ansicolor_sink-inl.h
        │       │   ├── ansicolor_sink.h
        │       │   ├── base_sink-inl.h
        │       │   ├── base_sink.h
        │       │   ├── basic_file_sink-inl.h
        │       │   ├── basic_file_sink.h
        │       │   ├── callback_sink.h
        │       │   ├── daily_file_sink.h
        │       │   ├── dist_sink.h
        │       │   ├── dup_filter_sink.h
        │       │   ├── hourly_file_sink.h
        │       │   ├── kafka_sink.h
        │       │   ├── mongo_sink.h
        │       │   ├── msvc_sink.h
        │       │   ├── null_sink.h
        │       │   ├── ostream_sink.h
        │       │   ├── qt_sinks.h
        │       │   ├── ringbuffer_sink.h
        │       │   ├── rotating_file_sink-inl.h
        │       │   ├── rotating_file_sink.h
        │       │   ├── sink-inl.h
        │       │   ├── sink.h
        │       │   ├── stdout_color_sinks-inl.h
        │       │   ├── stdout_color_sinks.h
        │       │   ├── stdout_sinks-inl.h
        │       │   ├── stdout_sinks.h
        │       │   ├── syslog_sink.h
        │       │   ├── systemd_sink.h
        │       │   ├── tcp_sink.h
        │       │   ├── udp_sink.h
        │       │   ├── win_eventlog_sink.h
        │       │   ├── wincolor_sink-inl.h
        │       │   └── wincolor_sink.h
        │       ├── spdlog-inl.h
        │       ├── spdlog.h
        │       ├── stopwatch.h
        │       ├── tweakme.h
        │       └── version.h
        ├── scripts/
        │   ├── ci_setup_clang.sh
        │   ├── extract_version.py
        │   └── format.sh
        ├── src/
        │   ├── async.cpp
        │   ├── bundled_fmtlib_format.cpp
        │   ├── cfg.cpp
        │   ├── color_sinks.cpp
        │   ├── file_sinks.cpp
        │   ├── spdlog.cpp
        │   └── stdout_sinks.cpp
        └── tests/
            ├── CMakeLists.txt
            ├── includes.h
            ├── main.cpp
            ├── test_async.cpp
            ├── test_backtrace.cpp
            ├── test_bin_to_hex.cpp
            ├── test_cfg.cpp
            ├── test_circular_q.cpp
            ├── test_create_dir.cpp
            ├── test_custom_callbacks.cpp
            ├── test_daily_logger.cpp
            ├── test_dup_filter.cpp
            ├── test_errors.cpp
            ├── test_eventlog.cpp
            ├── test_file_helper.cpp
            ├── test_file_logging.cpp
            ├── test_fmt_helper.cpp
            ├── test_macros.cpp
            ├── test_misc.cpp
            ├── test_mpmc_q.cpp
            ├── test_pattern_formatter.cpp
            ├── test_registry.cpp
            ├── test_sink.h
            ├── test_stdout_api.cpp
            ├── test_stopwatch.cpp
            ├── test_systemd.cpp
            ├── test_time_point.cpp
            ├── utils.cpp
            └── utils.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
IndentWidth: 2
TabWidth: 2

Language: Cpp
Standard: Cpp11
BasedOnStyle: Google
# indent
AccessModifierOffset: -1
ContinuationIndentWidth: 4
# align
BreakBeforeTernaryOperators: true
BreakBeforeBinaryOperators: false
ColumnLimit: 80
# constructor
BreakConstructorInitializersBeforeComma: false
ConstructorInitializerIndentWidth: 4
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# blocks
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
Cpp11BracedListStyle: true
# other
AlwaysBreakTemplateDeclarations: true
DerivePointerAlignment: false
PointerAlignment: Left

# clang 3.9+
BreakStringLiterals: false
SortIncludes: false
ReflowComments: true



================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: Report a bug or unexpected behavior
title: "[Bug]: "
labels: ["bug"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to report a bug! Please fill out the form below.

  - type: textarea
    id: description
    attributes:
      label: Bug Description
      description: A clear and concise description of what the bug is.
      placeholder: Describe the bug...
    validations:
      required: true

  - type: textarea
    id: reproduce
    attributes:
      label: Steps to Reproduce
      description: Steps to reproduce the behavior.
      placeholder: |
        1. Initialize client with '...'
        2. Call method '...'
        3. See error
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: What did you expect to happen?
    validations:
      required: true

  - type: textarea
    id: actual
    attributes:
      label: Actual Behavior
      description: What actually happened?
    validations:
      required: true

  - type: textarea
    id: code
    attributes:
      label: Minimal Reproducible Example
      description: If applicable, provide a minimal code example that reproduces the issue.
      render: python

  - type: textarea
    id: logs
    attributes:
      label: Error Logs
      description: If applicable, paste any error messages or stack traces.
      render: shell

  - type: input
    id: version
    attributes:
      label: OpenViking Version
      description: What version of OpenViking are you using?
      placeholder: e.g., 0.1.0
    validations:
      required: true

  - type: input
    id: python-version
    attributes:
      label: Python Version
      description: What version of Python are you using?
      placeholder: e.g., 3.10.0
    validations:
      required: true

  - type: dropdown
    id: os
    attributes:
      label: Operating System
      options:
        - Linux
        - macOS
        - Windows
        - Other
    validations:
      required: true

  - type: dropdown
    id: backend
    attributes:
      label: Model Backend
      description: Which model backend are you using?
      options:
        - Volcengine (Doubao)
        - OpenAI
        - Other

  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Documentation
    url: https://www.openviking.ai/docs
    about: Check the documentation for guides and API reference
  - name: Lark Community
    url: https://applink.larkoffice.com/client/chat/chatter/add_by_link?link_token=dd9l9590-7e6e-49f5-bf41-18aef1ma06v3
    about: Join our Lark group for discussions and support
  - name: Questions & Discussions
    url: https://github.com/volcengine/OpenViking/discussions
    about: Ask questions and share ideas in GitHub Discussions


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Suggest a new feature or enhancement
title: "[Feature]: "
labels: ["enhancement"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for suggesting a feature! Please fill out the form below.

  - type: textarea
    id: problem
    attributes:
      label: Problem Statement
      description: Is your feature request related to a problem? Please describe.
      placeholder: A clear description of what the problem is. Ex. I'm always frustrated when...
    validations:
      required: true

  - type: textarea
    id: solution
    attributes:
      label: Proposed Solution
      description: Describe the solution you'd like.
      placeholder: A clear description of what you want to happen.
    validations:
      required: true

  - type: textarea
    id: alternatives
    attributes:
      label: Alternatives Considered
      description: Describe any alternative solutions or features you've considered.

  - type: dropdown
    id: area
    attributes:
      label: Feature Area
      description: Which area of OpenViking does this feature relate to?
      options:
        - Core (Client/Engine)
        - Filesystem Operations
        - Retrieval/Search
        - Session Management
        - Model Integration
        - Storage/VectorDB
        - CLI Tools
        - Documentation
        - Other
    validations:
      required: true

  - type: textarea
    id: use-case
    attributes:
      label: Use Case
      description: Describe the use case for this feature.
      placeholder: How would you use this feature in your project?
    validations:
      required: true

  - type: textarea
    id: code-example
    attributes:
      label: Example API (Optional)
      description: If applicable, provide an example of how the API might look.
      render: python

  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: Add any other context, screenshots, or references about the feature request.

  - type: checkboxes
    id: contribution
    attributes:
      label: Contribution
      options:
        - label: I am willing to contribute to implementing this feature


================================================
FILE: .github/ISSUE_TEMPLATE/question.yml
================================================
name: Question
description: Ask a question about OpenViking usage
title: "[Question]: "
labels: ["question"]
body:
  - type: markdown
    attributes:
      value: |
        Have a question about OpenViking? We're here to help!

  - type: textarea
    id: question
    attributes:
      label: Your Question
      description: What would you like to know?
      placeholder: Describe your question clearly...
    validations:
      required: true

  - type: textarea
    id: context
    attributes:
      label: Context
      description: Provide any relevant context or background.
      placeholder: |
        - What are you trying to achieve?
        - What have you tried so far?

  - type: textarea
    id: code
    attributes:
      label: Code Example (Optional)
      description: If applicable, share relevant code.
      render: python

  - type: dropdown
    id: area
    attributes:
      label: Related Area
      options:
        - Installation / Setup
        - Configuration
        - API Usage
        - Retrieval / Search
        - Session Management
        - Performance
        - Other

  - type: checkboxes
    id: checked-docs
    attributes:
      label: Before Asking
      options:
        - label: I have checked the [documentation](https://www.openviking.ai/docs)
          required: true


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Description

<!-- Provide a brief description of the changes in this PR -->

## Related Issue

<!-- Link to the related issue (if applicable) -->
<!-- Fixes #(issue number) -->

## Type of Change

<!-- Mark the relevant option with an "x" -->

- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] Performance improvement
- [ ] Test update

## Changes Made

<!-- List the main changes made in this PR -->

-
-
-

## Testing

<!-- Describe how you tested your changes -->

- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] I have tested this on the following platforms:
  - [ ] Linux
  - [ ] macOS
  - [ ] Windows

## Checklist

- [ ] My code follows the project's coding style
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] Any dependent changes have been merged and published

## Screenshots (if applicable)

<!-- Add screenshots to help explain your changes -->

## Additional Notes

<!-- Add any additional notes or context about the PR -->


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  # GitHub Actions 依赖更新
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "dependencies"
      - "github-actions"

  # Python 依赖更新
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "dependencies"
      - "python"
    # 忽略主要版本更新,避免破坏性变更
    ignore:
      - dependency-name: "*"
        update-types: ["version-update:semver-major"]


================================================
FILE: .github/workflows/_build.yml
================================================
name: 15. _Build Distribution

on:
  workflow_call:
    inputs:
      os_json:
        description: 'JSON string of runner labels to build on (ubuntu-24.04=x86_64, ubuntu-24.04-arm=aarch64, macos-14=arm64, macos-15-intel=x86_64, windows-latest=x86_64)'
        required: false
        type: string
        default: '["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        type: string
        default: '["3.10", "3.11", "3.12", "3.13", "3.14"]'
      build_sdist:
        description: 'Whether to build source distribution'
        required: false
        type: boolean
        default: true
      build_wheels:
        description: 'Whether to build wheel distribution'
        required: false
        type: boolean
        default: true
  workflow_dispatch:
    inputs:
      build_sdist:
        description: 'Whether to build source distribution'
        required: false
        type: boolean
        default: true
      build_wheels:
        description: 'Whether to build wheel distribution'
        required: false
        type: boolean
        default: true
      os_json:
        description: 'JSON string of runner labels to build on (ubuntu-24.04=x86_64, ubuntu-24.04-arm=aarch64, macos-14=arm64, macos-15-intel=x86_64, windows-latest=x86_64)'
        required: false
        default: '["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        default: '["3.10", "3.11", "3.12", "3.13", "3.14"]'

jobs:
  build-sdist:
    name: Build source distribution py3.12
    if: inputs.build_sdist
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
      with:
        submodules: recursive
        fetch-depth: 0  # Required for setuptools_scm to detect version from git tags

    - name: Fetch all tags
      run: git fetch --force --tags

    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: '3.12'

    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Create venv
      run: uv venv

    - name: Install build dependencies
      run: uv pip install build setuptools_scm

    - name: Clean workspace (force ignore dirty)
      shell: bash
      run: |
        git reset --hard HEAD
        git clean -fd
        # For sdist, ensure local runtime binaries are not packaged even if present
        rm -rf openviking/bin openviking/lib third_party/agfs/bin || true
        rm -f openviking/storage/vectordb/*.so openviking/storage/vectordb/*.dylib openviking/storage/vectordb/*.dll openviking/storage/vectordb/*.exe || true
        rm -rf openviking/_version.py openviking.egg-info
        # Ignore uv.lock changes to avoid dirty state in setuptools_scm
        git update-index --assume-unchanged uv.lock || true

    - name: Debug Git and SCM
      shell: bash
      run: |
        echo "=== Git Describe ==="
        git describe --tags --long --dirty --always
        echo "=== Setuptools SCM Version ==="
        uv run --frozen python -m setuptools_scm
        echo "=== Git Status (Ignored included) ==="
        git status --ignored
        echo "=== Check openviking/_version.py ==="
        if [ -f openviking/_version.py ]; then cat openviking/_version.py; else echo "Not found"; fi

    - name: Build sdist
      run: uv run --frozen python -m build --sdist

    - name: Store the distribution packages
      uses: actions/upload-artifact@v7
      with:
        name: python-package-distributions-sdist
        path: dist/*.tar.gz

    - name: Display built sdist version
      continue-on-error: true
      run: |
        VERSION=$(ls dist/*.tar.gz | head -n 1 | xargs basename | sed -E 's/^[^-]+-(.+)\.tar\.gz$/\1/')
        echo "Build Version: $VERSION"
        echo "::notice::Build sdist Version: $VERSION"

  build-linux:
    name: Build distribution on Linux ${{ matrix.arch }} (glibc 2.31) py${{ matrix.python-version }}
    # Run if Linux runners are requested (explicit labels or generic 'linux')
    if: >-
      inputs.build_wheels &&
      (
        contains(inputs.os_json, 'linux') ||
        contains(inputs.os_json, '"ubuntu-24.04"') ||
        contains(inputs.os_json, 'ubuntu-24.04-arm')
      )
    runs-on: ${{ matrix.arch == 'aarch64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
    container: ubuntu:20.04
    env:
      DEBIAN_FRONTEND: noninteractive
      TZ: Etc/UTC
    strategy:
      fail-fast: false
      matrix:
        python-version: ${{ fromJson(inputs.python_json) }}
        arch: ${{ contains(inputs.os_json, 'linux') && fromJson('["x86_64","aarch64"]') || (contains(inputs.os_json, '"ubuntu-24.04"') && contains(inputs.os_json, 'ubuntu-24.04-arm')) && fromJson('["x86_64","aarch64"]') || contains(inputs.os_json, 'ubuntu-24.04-arm') && fromJson('["aarch64"]') || fromJson('["x86_64"]') }}
    
    steps:
    - name: Install system dependencies (Linux)
      run: |
        # Replace archive.ubuntu.com with azure.archive.ubuntu.com for better stability in GH Actions
        sed -i 's/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/azure.archive.ubuntu.com\/ubuntu\//g' /etc/apt/sources.list
        # Retry apt-get update
        for i in 1 2 3 4 5; do apt-get update && break || sleep 5; done
        apt-get install -y \
          git ca-certificates cmake build-essential tzdata curl \
          libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
          libffi-dev liblzma-dev libgdbm-dev libnss3-dev libncurses5-dev \
          libncursesw5-dev tk-dev uuid-dev libexpat1-dev
        ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
        dpkg-reconfigure -f noninteractive tzdata

    - uses: actions/checkout@v6
      with:
        submodules: recursive
        fetch-depth: 0  # Required for setuptools_scm to detect version from git tags

    - name: Fetch all tags
      run: |
        git config --global --add safe.directory "$GITHUB_WORKSPACE"
        git fetch --force --tags

    - name: Build CPython (Dynamic Selection)
      run: |
        # Map short version to full version for our specific build environment
        PYTHON_VERSION="${{ matrix.python-version }}"
        case "$PYTHON_VERSION" in
          "3.9") PYTHON_FULL="3.9.18" ;;
          "3.10") PYTHON_FULL="3.10.13" ;;
          "3.11") PYTHON_FULL="3.11.8" ;;
          "3.12") PYTHON_FULL="3.12.2" ;;
          "3.13") PYTHON_FULL="3.13.2" ;;
          "3.14") PYTHON_FULL="3.14.3" ;;
          *)
            echo "Error: Unknown python version $PYTHON_VERSION"
            exit 1
            ;;
        esac
        
        PYTHON_PREFIX="/opt/python/${PYTHON_FULL}"
        PYTHON_BIN="${PYTHON_PREFIX}/bin/python${{ matrix.python-version }}"
        if [ ! -x "$PYTHON_BIN" ]; then
          curl -fsSL -o /tmp/Python-${PYTHON_FULL}.tgz \
            https://www.python.org/ftp/python/${PYTHON_FULL}/Python-${PYTHON_FULL}.tgz
          tar -xzf /tmp/Python-${PYTHON_FULL}.tgz -C /tmp
          cd /tmp/Python-${PYTHON_FULL}
          CFLAGS="-fPIC" \
          ./configure --prefix="${PYTHON_PREFIX}" --with-ensurepip=install --enable-shared
          make -j"$(nproc)"
          make install
        fi
        echo "PYTHON_BIN=${PYTHON_BIN}" >> "$GITHUB_ENV"
        echo "LD_LIBRARY_PATH=${PYTHON_PREFIX}/lib:${LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
        export LD_LIBRARY_PATH="${PYTHON_PREFIX}/lib:${LD_LIBRARY_PATH}"
        "$PYTHON_BIN" -V
    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: '1.25.1'

    - name: Set up Rust
      uses: dtolnay/rust-toolchain@v1
      with:
        toolchain: stable
        targets: ${{ matrix.arch == 'aarch64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}
    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Create venv (Linux)
      run: uv venv --python "$PYTHON_BIN"

    - name: Seed pip (Linux)
      run: uv run python -m ensurepip --upgrade

    - name: Install dependencies
      run: uv sync --frozen

    - name: Install build dependencies
      run: uv pip install setuptools setuptools_scm pybind11 cmake wheel build

    - name: Build Rust CLI (Linux)
      run: cargo build --release --target ${{ matrix.arch == 'aarch64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }} -p ov_cli

    - name: Copy Rust CLI binary (Linux)
      run: |
        mkdir -p openviking/bin
        cp target/${{ matrix.arch == 'aarch64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}/release/ov openviking/bin/
        chmod +x openviking/bin/ov
    - name: Clean workspace (force ignore dirty)
      shell: bash
      run: |
        git reset --hard HEAD
        git clean -fd
        rm -rf openviking/_version.py openviking.egg-info
        # Ignore uv.lock changes to avoid dirty state in setuptools_scm
        git update-index --assume-unchanged uv.lock || true

    - name: Debug Git and SCM
      shell: bash
      run: |
        echo "=== Git Describe ==="
        git describe --tags --long --dirty --always
        echo "=== Setuptools SCM Version ==="
        uv run --frozen python -m setuptools_scm
        echo "=== Git Status (Ignored included) ==="
        git status --ignored
        echo "=== Check openviking/_version.py ==="
        if [ -f openviking/_version.py ]; then cat openviking/_version.py; else echo "Not found"; fi

    - name: Build package (Wheel Only)
      run: uv run --frozen python -m build --wheel

    - name: Install patchelf (Linux)
      run: |
        PATCHELF_VERSION=0.18.0
        curl -fsSL -o /tmp/patchelf-${PATCHELF_VERSION}.tar.gz \
          https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}.tar.gz
        tar -xzf /tmp/patchelf-${PATCHELF_VERSION}.tar.gz -C /tmp
        cd /tmp/patchelf-${PATCHELF_VERSION}
        ./configure
        make -j"$(nproc)"
        make install
        patchelf --version

    - name: Repair wheels (Linux)
      run: |
        uv pip install auditwheel
        # Repair wheels and output to a temporary directory
        uv run auditwheel repair dist/*.whl -w dist_fixed
        # Remove original non-compliant wheels
        rm dist/*.whl
        # Move repaired wheels back to dist
        mv dist_fixed/*.whl dist/
        rmdir dist_fixed

    - name: Store the distribution packages
      uses: actions/upload-artifact@v7
      with:
        name: python-package-distributions-linux-${{ matrix.arch }}-${{ matrix.python-version }}
        path: dist/

    - name: Display built wheel version
      continue-on-error: true
      run: |
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Build Version: $VERSION"
        echo "::notice::Build Wheel Version (Linux ${{ matrix.arch }} glibc 2.31 py${{ matrix.python-version }}): $VERSION"

  build-other:
    name: Build non-Linux distributions
    # Run only when non-Linux runners are explicitly requested
    if: inputs.build_wheels && (contains(inputs.os_json, 'macos') || contains(inputs.os_json, 'windows'))
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: ${{ fromJson(inputs.os_json) }}
        python-version: ${{ fromJson(inputs.python_json) }}
        # Exclude ubuntu-24.04 from this matrix if it was passed in inputs
        exclude:
          - os: linux
          - os: ubuntu-24.04
          - os: ubuntu-24.04-arm

    steps:
    - uses: actions/checkout@v6
      with:
        submodules: recursive
        fetch-depth: 0  # Required for setuptools_scm to detect version from git tags

    - name: Fetch all tags
      run: git fetch --force --tags

    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}

    - name: Configure macOS wheel architecture tag
      if: runner.os == 'macOS'
      shell: bash
      run: |
        if [[ "${{ matrix.os }}" == "macos-14" ]]; then
          TARGET_ARCH="arm64"
          MACOS_VERSION="14.0"
        elif [[ "${{ matrix.os }}" == "macos-15-intel" ]]; then
          TARGET_ARCH="x86_64"
          MACOS_VERSION="15.0"
        else
          echo "Unsupported macOS runner for release wheels: ${{ matrix.os }}"
          exit 1
        fi

        echo "ARCHFLAGS=-arch ${TARGET_ARCH}" >> "$GITHUB_ENV"
        echo "CMAKE_OSX_ARCHITECTURES=${TARGET_ARCH}" >> "$GITHUB_ENV"
        echo "_PYTHON_HOST_PLATFORM=macosx-${MACOS_VERSION}-${TARGET_ARCH}" >> "$GITHUB_ENV"
        echo "Configured macOS wheel platform: macosx-${MACOS_VERSION}-${TARGET_ARCH}"

    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: '1.25.1'

    - name: Set up Rust
      uses: dtolnay/rust-toolchain@v1
      with:
        toolchain: stable
    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Install system dependencies (macOS)
      if: runner.os == 'macOS'
      run: brew install cmake

    - name: Install system dependencies (Windows)
      if: runner.os == 'Windows'
      run: |
        choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
        choco install mingw

    - name: Install dependencies
      run: uv sync --frozen

    - name: Install build dependencies
      run: uv pip install setuptools setuptools_scm pybind11 cmake wheel build

    - name: Build Rust CLI (macOS/Windows)
      shell: bash
      run: |
        if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
          cargo build --release --target x86_64-pc-windows-msvc -p ov_cli
        else
          cargo build --release -p ov_cli
        fi

    - name: Copy Rust CLI binary (macOS/Windows)
      shell: bash
      run: |
        mkdir -p openviking/bin
        if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
          cp target/x86_64-pc-windows-msvc/release/ov.exe openviking/bin/
        else
          cp target/release/ov openviking/bin/
          chmod +x openviking/bin/ov
        fi
    - name: Clean workspace (force ignore dirty)
      shell: bash
      run: |
        git reset --hard HEAD
        git clean -fd
        rm -rf openviking/_version.py openviking.egg-info
        # Ignore uv.lock changes to avoid dirty state in setuptools_scm
        git update-index --assume-unchanged uv.lock || true

    - name: Debug Git and SCM
      shell: bash
      run: |
        echo "=== Git Describe ==="
        git describe --tags --long --dirty --always
        echo "=== Setuptools SCM Version ==="
        uv run --frozen python -m setuptools_scm
        echo "=== Git Status (Ignored included) ==="
        git status --ignored
        echo "=== Check openviking/_version.py ==="
        if [ -f openviking/_version.py ]; then cat openviking/_version.py; else echo "Not found"; fi

    - name: Build package (Wheel Only)
      run: uv run --frozen python -m build --wheel

    - name: Store the distribution packages
      uses: actions/upload-artifact@v7
      with:
        name: python-package-distributions-${{ matrix.os == 'macos-14' && 'macos-arm64' || matrix.os == 'macos-15-intel' && 'macos-x86_64' || matrix.os == 'windows-latest' && 'windows-x86_64' || matrix.os }}-${{ matrix.python-version }}
        path: dist/

    - name: Display built wheel version
      shell: bash
      continue-on-error: true
      run: |
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Build Version: $VERSION"
        echo "::notice::Build Wheel Version (${{ matrix.os == 'macos-14' && 'macOS arm64 (macos-14)' || matrix.os == 'macos-15-intel' && 'macOS x86_64 (macos-15-intel)' || matrix.os == 'windows-latest' && 'Windows x86_64 (windows-latest)' || matrix.os }} py${{ matrix.python-version }}): $VERSION"

  verify-macos-14-wheel-on-macos-15:
    name: Verify macOS 14 arm64 wheel installs on macOS 15
    needs: [build-other]
    if: >-
      inputs.build_wheels &&
      contains(inputs.os_json, 'macos-14') &&
      contains(inputs.python_json, '3.12')
    runs-on: macos-15
    steps:
    - name: Set up Python 3.12
      uses: actions/setup-python@v6
      with:
        python-version: '3.12'

    - name: Download macOS arm64 wheel artifact
      uses: actions/download-artifact@v8
      with:
        name: python-package-distributions-macos-arm64-3.12
        path: dist/

    - name: Install built wheel
      shell: bash
      run: |
        python -m pip install --upgrade pip
        python -m pip install dist/*.whl

    - name: Smoke test native extension loading
      shell: bash
      run: |
        python - <<'PY'
        import importlib
        import importlib.util

        import openviking.storage.vectordb.engine as engine

        native_spec = importlib.util.find_spec("openviking.storage.vectordb.engine._native")
        if native_spec is None or native_spec.origin is None:
            raise SystemExit("openviking storage native backend extension was not installed")

        native_module = importlib.import_module("openviking.storage.vectordb.engine._native")
        if engine.ENGINE_VARIANT != "native":
            raise SystemExit(
                f"expected native engine variant on macOS arm64 wheel, got {engine.ENGINE_VARIANT}"
            )

        print(f"Loaded runtime engine variant {engine.ENGINE_VARIANT}")
        print(f"Loaded native extension from {native_spec.origin}")
        print(f"Imported backend module {native_module.__name__}")
        PY


================================================
FILE: .github/workflows/_codeql.yml
================================================
name: 14. _CodeQL Scan

on:
  workflow_call:
  workflow_dispatch:

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-24.04
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'python', 'cpp' ]

    steps:
    - name: Checkout repository
      uses: actions/checkout@v6
      with:
        submodules: recursive

    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: '3.11'

    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: 'stable'

    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Install system dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y cmake build-essential

    - name: Install dependencies
      run: |
        uv sync --frozen
        uv pip install setuptools pybind11 cmake wheel

    - name: Initialize CodeQL
      uses: github/codeql-action/init@v4
      with:
        languages: ${{ matrix.language }}
        queries: security-and-quality

    - name: Build extensions
      if: matrix.language == 'cpp'
      run: uv run python setup.py build_ext --inplace

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v4
      with:
        category: "/language:${{ matrix.language }}"


================================================
FILE: .github/workflows/_lint.yml
================================================
name: 11. _Lint Checks

on:
  workflow_call:
  workflow_dispatch:

jobs:
  lint:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
      with:
        fetch-depth: 0 # Required to calculate the git diff



    - name: Set up Python
      uses: actions/setup-python@v6
      with:
        python-version: '3.11'

    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: 'stable'

    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Install dependencies
      run: uv sync --frozen --extra dev

    # --- NEW STEP: Get the list of changed files ---
    - name: Get changed files
      id: files
      run: |
        # Compare the PR head to the base branch
        echo "changed_files=$(git diff --name-only --diff-filter=d origin/${{ github.base_ref }} HEAD | grep '\.py$' | xargs)" >> $GITHUB_OUTPUT

    # --- UPDATED STEPS: Use the file list ---
    - name: List files
      run: echo "The changed files are ${{ steps.files.outputs.changed_files }}"

    - name: Format with ruff (Changed files only)
      if: steps.files.outputs.changed_files != ''
      run: uv run ruff format --check ${{ steps.files.outputs.changed_files }}  

    - name: Lint with ruff (Changed files only)
      if: steps.files.outputs.changed_files != ''
      run: uv run ruff check ${{ steps.files.outputs.changed_files }}

    - name: Type check with mypy (Changed files only)
      if: steps.files.outputs.changed_files != ''
      # Note: Running mypy on specific files may miss cross-file type errors
      run: uv run mypy ${{ steps.files.outputs.changed_files }}
      continue-on-error: true


================================================
FILE: .github/workflows/_publish.yml
================================================
name: 16. _Publish Distribution

on:
  workflow_call:
    inputs:
      target:
        description: 'Publish Target'
        required: false
        type: string
        default: 'pypi'  # Callers (like release.yml) typically want PyPI
      build_run_id:
        description: 'Build Workflow Run ID (Optional, defaults to current run)'
        required: false
        type: string
        default: ''
  workflow_dispatch:
    inputs:
      target:
        description: 'Select where to publish'
        required: true
        type: choice
        default: 'testpypi'
        options:
        - testpypi
        - pypi
        - both
      build_run_id:
        description: 'Build Workflow Run ID (Required for manual dispatch, find it in the Build run URL)'
        required: true
        type: string

jobs:
  permission-check:
    name: Check write permission
    runs-on: ubuntu-24.04
    permissions:
      contents: read
    outputs:
      allowed: ${{ steps.check.outputs.allowed }}
    steps:
    - name: Verify actor permission
      id: check
      uses: actions/github-script@v8
      with:
        script: |
          // Only check permission for manual dispatch
          if (context.eventName !== 'workflow_dispatch') {
            core.setOutput('allowed', 'true');
            return;
          }
          const { owner, repo } = context.repo;
          const actor = context.actor;
          const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
            owner,
            repo,
            username: actor,
          });
          const perm = data.permission;
          core.info(`Actor ${actor} permission: ${perm}`);
          const allowed = ['admin', 'maintain', 'write'].includes(perm);
          core.setOutput('allowed', allowed ? 'true' : 'false');
          if (!allowed) {
            core.setFailed(`User ${actor} does not have write permission`);
          }

  publish-testpypi:
    name: Publish to TestPyPI
    needs: [permission-check]
    if: >-
      needs.permission-check.outputs.allowed == 'true' &&
      (inputs.target == 'testpypi' || inputs.target == 'both')
    runs-on: ubuntu-24.04
    environment:
      name: testpypi
      url: https://test.pypi.org/p/openviking
    permissions:
      id-token: write
      actions: read  # Required for downloading artifacts from other runs

    steps:
    - name: Download all the dists (Same Run)
      if: inputs.build_run_id == ''
      uses: actions/download-artifact@v8
      with:
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Download all the dists (Cross Run)
      if: inputs.build_run_id != ''
      uses: actions/download-artifact@v8
      with:
        run-id: ${{ inputs.build_run_id }}
        github-token: ${{ secrets.GITHUB_TOKEN }}
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Publish distribution to TestPyPI
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        repository-url: https://test.pypi.org/legacy/
        skip-existing: true
        verbose: true

    - name: Display published version
      run: |
        # Get version from the first wheel file found
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Published to TestPyPI (or already existed) with version: $VERSION"
        echo "::notice::Published to TestPyPI (or already existed) with version: $VERSION"

  publish-pypi:
    name: Publish to PyPI
    needs: [permission-check]
    if: >-
      needs.permission-check.outputs.allowed == 'true' &&
      (inputs.target == 'pypi' || inputs.target == 'both')
    runs-on: ubuntu-24.04
    environment:
      name: pypi
      url: https://pypi.org/p/openviking
    permissions:
      id-token: write
      actions: read  # Required for downloading artifacts from other runs

    steps:
    - name: Download all the dists (Same Run)
      if: inputs.build_run_id == ''
      uses: actions/download-artifact@v8
      with:
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Download all the dists (Cross Run)
      if: inputs.build_run_id != ''
      uses: actions/download-artifact@v8
      with:
        run-id: ${{ inputs.build_run_id }}
        github-token: ${{ secrets.GITHUB_TOKEN }}
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Publish distribution to PyPI
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        skip-existing: true
        verbose: true

    - name: Display published version
      run: |
        # Get version from the first wheel file found
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Published to PyPI (or already existed) with version: $VERSION"
        echo "::notice::Published to PyPI (or already existed) with version: $VERSION"


================================================
FILE: .github/workflows/_test_full.yml
================================================
name: 13. _Test Suite (Full)

on:
  workflow_call:
    inputs:
      os_json:
        description: 'JSON string of OS to run on'
        required: false
        type: string
        default: '["ubuntu-24.04", "macos-14", "windows-latest"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        type: string
        default: '["3.10", "3.11", "3.12", "3.13"]'
  workflow_dispatch:
    inputs:
      os_json:
        description: 'JSON string of OS to run on'
        required: false
        default: '["ubuntu-24.04", "macos-14", "windows-latest"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        default: '["3.10", "3.11", "3.12", "3.13"]'

jobs:
  test:
    name: Full Test (${{ matrix.os }}, ${{ matrix.python-version }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: ${{ fromJson(inputs.os_json || '["ubuntu-24.04", "macos-14", "windows-latest"]') }}
        python-version: ${{ fromJson(inputs.python_json || '["3.10", "3.11", "3.12", "3.13"]') }}

    steps:
    - uses: actions/checkout@v6
      with:
        submodules: recursive

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}

    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: '1.25.1'

    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Install system dependencies (Ubuntu)
      if: runner.os == 'Linux'
      run: |
        sudo apt-get update
        sudo apt-get install -y cmake build-essential

    - name: Install system dependencies (macOS)
      if: runner.os == 'macOS'
      run: brew install cmake

    - name: Install system dependencies (Windows)
      if: runner.os == 'Windows'
      run: |
        choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
        choco install mingw

    - name: Add MinGW to PATH (Windows)
      if: runner.os == 'Windows'
      run: echo "C:\mingw64\bin" >> $env:GITHUB_PATH

    - name: Install Python dependencies
      run: uv sync --frozen --extra test

    - name: Install build dependencies
      run: uv pip install setuptools pybind11 cmake wheel

    - name: Build C++ extensions
      run: uv run python setup.py build_ext --inplace

    # TODO: Once unit tests are fixed, switch this back to running the full test suite
    # run: uv run pytest tests/ -v --cov=openviking --cov-report=term
    - name: Run Lite Integration Test (Temporary Replacement)
      shell: bash
      run: |
        export PYTHONPATH=$PYTHONPATH:$(pwd)
        uv run python tests/integration/test_quick_start_lite.py


================================================
FILE: .github/workflows/_test_lite.yml
================================================
name: 12. _Test Suite (Lite)

on:
  workflow_call:
    inputs:
      os_json:
        description: 'JSON string of OS to run on'
        required: false
        type: string
        default: '["ubuntu-24.04"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        type: string
        default: '["3.10"]'
  workflow_dispatch:
    inputs:
      os_json:
        description: 'JSON string of OS to run on'
        required: false
        default: '["ubuntu-24.04"]'
      python_json:
        description: 'JSON string of Python versions'
        required: false
        default: '["3.10"]'

jobs:
  test-lite:
    name: Lite Test (${{ matrix.os }}, ${{ matrix.python-version }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: ${{ fromJson(inputs.os_json) }}
        python-version: ${{ fromJson(inputs.python_json) }}

    steps:
    - uses: actions/checkout@v6
      with:
        submodules: recursive

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v6
      with:
        python-version: ${{ matrix.python-version }}

    - name: Set up Go
      uses: actions/setup-go@v6
      with:
        go-version: '1.25.1'

    - name: Install uv
      uses: astral-sh/setup-uv@v7
      with:
        enable-cache: true

    - name: Install system dependencies (Ubuntu)
      if: runner.os == 'Linux'
      run: |
        sudo apt-get update
        sudo apt-get install -y cmake build-essential

    - name: Install system dependencies (macOS)
      if: runner.os == 'macOS'
      run: brew install cmake

    - name: Install system dependencies (Windows)
      if: runner.os == 'Windows'
      run: |
        choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
        choco install mingw

    - name: Add MinGW to PATH (Windows)
      if: runner.os == 'Windows'
      run: echo "C:\mingw64\bin" >> $env:GITHUB_PATH

    - name: Install Python dependencies
      run: uv sync --frozen --extra test

    - name: Install build dependencies
      run: uv pip install setuptools pybind11 cmake wheel

    - name: Build C++ extensions
      run: uv run python setup.py build_ext --inplace

    - name: Run Lite Integration Test (Quick Start)
      shell: bash
      run: |
        export PYTHONPATH=$PYTHONPATH:$(pwd)
        # Using bash shell ensures this works across platforms (including Windows via Git Bash)
        uv run python tests/integration/test_quick_start_lite.py


================================================
FILE: .github/workflows/build-docker-image.yml
================================================
name: Build and Push Docker Image

on:
  workflow_dispatch:
    inputs:
      version:
        description: "application version for OpenViking"
        required: true
        type: string
  push:
    tags: [ "v*.*.*" ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push-image:
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Log in to the Container registry
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v6
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4

      - name: Build and push Docker image
        id: push
        uses: docker/build-push-action@v7
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: ${{ github.ref_type == 'tag' || github.event_name == 'workflow_dispatch' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          build-args: |
            # fallback to 0.0.0 if no version is provided
            OPENVIKING_VERSION=${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.version) || (github.ref_type == 'tag' && github.ref_name) || '0.0.0' }}


================================================
FILE: .github/workflows/ci.yml
================================================
name: 02. Main Branch Checks

on:
  workflow_dispatch:
  push:
    branches: [ main ]
    paths-ignore:
      - 'docs/**'
      - '**.md'
      - 'LICENSE'
      - 'CONTRIBUTING.md'
      - '**.png'
      - '**.jpg'
      - '**.jpeg'
      - '**.gif'
      - '**.svg'
      - '.gitignore'
      - '.editorconfig'

permissions:
  actions: read
  contents: read
  security-events: write

jobs:
  test-full:
    uses: ./.github/workflows/_test_full.yml

  security-scan:
    uses: ./.github/workflows/_codeql.yml


================================================
FILE: .github/workflows/pr-review.yml
================================================
name: PR Review (Qodo)

on:
  pull_request_target:
    types: [opened, synchronize, reopened, ready_for_review]
  issue_comment:

jobs:
  pr_review:
    if: ${{ github.event.sender.type != 'Bot' }}
    runs-on: ubuntu-24.04
    permissions:
      issues: write
      pull-requests: write
      contents: write
    steps:
      # Checkout required so PR-Agent reads .pr_agent.toml from repo root.
      # All review rules, custom labels, ignore patterns, and tool configs
      # live in .pr_agent.toml — no inline extra_instructions needed here.
      - name: Checkout
        uses: actions/checkout@v4

      - name: PR Agent
        uses: qodo-ai/pr-agent@main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_KEY: ${{ secrets.DOUBAO_API_KEY }}
          OPENAI.API_BASE: "https://ark.cn-beijing.volces.com/api/coding/v3"
          config.model: "ark-code-latest"
          github_action_config.auto_review: "true"
          github_action_config.auto_describe: "true"
          github_action_config.auto_improve: "true"


================================================
FILE: .github/workflows/pr.yml
================================================
name: 01. Pull Request Checks

on:
  workflow_dispatch:
  pull_request:
    branches: [ main, develop ]
    paths-ignore:
      - 'docs/**'
      - '**.md'
      - 'LICENSE'
      - 'CONTRIBUTING.md'
      - '**.png'
      - '**.jpg'
      - '**.jpeg'
      - '**.gif'
      - '**.svg'
      - '.gitignore'
      - '.editorconfig'

jobs:
  lint:
    uses: ./.github/workflows/_lint.yml

  test-lite:
    uses: ./.github/workflows/_test_lite.yml
    with:
      os_json: '["ubuntu-24.04"]'
      python_json: '["3.10"]'

  check-deps:
    runs-on: ubuntu-24.04
    outputs:
      deps_changed: ${{ steps.check.outputs.deps_changed }}
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Check for dependency changes
        id: check
        run: |
          git fetch origin ${{ github.base_ref }}
          
          # Define grep pattern for dependency files
          PATTERN="pyproject\.toml|setup\.py|uv\.lock|src/CMakeLists\.txt|third_party/|\.github/workflows/_build\.yml"
          
          # Check for changes
          CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }} HEAD | grep -E "$PATTERN" || true)
          
          if [ -n "$CHANGED_FILES" ]; then
            echo "Dependency changes detected:"
            echo "$CHANGED_FILES"
            echo "deps_changed=true" >> $GITHUB_OUTPUT
          else
            echo "No dependency changes detected."
            echo "deps_changed=false" >> $GITHUB_OUTPUT
          fi

  build:
    needs: check-deps
    if: ${{ needs.check-deps.outputs.deps_changed == 'true' }}
    uses: ./.github/workflows/_build.yml


================================================
FILE: .github/workflows/release-vikingbot-first.yml
================================================
name: First Release to PyPI

on:
  workflow_dispatch:  # 手动触发

jobs:
  release:
    runs-on: ubuntu-24.04
    defaults:
      run:
        working-directory: bot
    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'

      - name: Install build dependencies
        run: pip install build

      - name: Build package
        run: python -m build

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.VIKINGBOT_PYPI_API_TOKEN }}
          packages-dir: bot/dist/


================================================
FILE: .github/workflows/release.yml
================================================
name: 03. Release

on:
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      target:
        description: 'Select where to publish'
        required: true
        type: choice
        default: 'testpypi'
        options:
        - none
        - testpypi
        - pypi
        - both
      build_sdist:
        description: 'Whether to build source distribution'
        required: false
        type: boolean
        default: true
      build_wheels:
        description: 'Whether to build wheel distribution'
        required: false
        type: boolean
        default: true
      os_json:
        description: 'JSON string of runner labels to build on (Manual only; ubuntu-24.04=x86_64, ubuntu-24.04-arm=aarch64, macos-14=arm64, macos-15-intel=x86_64, windows-latest=x86_64)'
        required: false
        type: string
        default: '["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]'
      python_json:
        description: 'JSON string of Python versions (Manual only)'
        required: false
        type: string
        default: '["3.10", "3.11", "3.12", "3.13", "3.14"]'

permissions:
  contents: write
  id-token: write
  actions: read

jobs:
  build:
    # Skip this workflow for CLI releases (tags starting with cli-)
    if: "!startsWith(github.event.release.tag_name, 'cli-')"
    uses: ./.github/workflows/_build.yml
    with:
      os_json: ${{ inputs.os_json || '["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]' }}
      python_json: ${{ inputs.python_json || '["3.10", "3.11", "3.12", "3.13", "3.14"]' }}
      build_sdist: ${{ github.event_name == 'release' || inputs.build_sdist != false }}
      build_wheels: ${{ github.event_name == 'release' || inputs.build_wheels != false }}

  permission-check:
    name: Check write permission
    needs: [build]
    runs-on: ubuntu-24.04
    permissions:
      contents: read
    outputs:
      allowed: ${{ steps.check.outputs.allowed }}
    steps:
    - name: Verify actor permission
      id: check
      uses: actions/github-script@v8
      with:
        script: |
          // Only check permission for manual dispatch
          if (context.eventName !== 'workflow_dispatch') {
            core.setOutput('allowed', 'true');
            return;
          }
          const { owner, repo } = context.repo;
          const actor = context.actor;
          const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
            owner,
            repo,
            username: actor,
          });
          const perm = data.permission;
          core.info(`Actor ${actor} permission: ${perm}`);
          const allowed = ['admin', 'maintain', 'write'].includes(perm);
          core.setOutput('allowed', allowed ? 'true' : 'false');
          if (!allowed) {
            core.setFailed(`User ${actor} does not have write permission`);
          }

  publish-testpypi:
    name: Publish to TestPyPI
    needs: [build, permission-check]
    if: >-
      needs.permission-check.outputs.allowed == 'true' &&
      (inputs.target == 'testpypi' || inputs.target == 'both')
    runs-on: ubuntu-24.04
    environment:
      name: testpypi
      url: https://test.pypi.org/p/openviking
    permissions:
      id-token: write
      actions: read
    steps:
    - name: Download all the dists (Same Run)
      uses: actions/download-artifact@v8
      with:
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Publish distribution to TestPyPI
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        repository-url: https://test.pypi.org/legacy/
        skip-existing: true
        verbose: true

    - name: Display published version
      run: |
        # Get version from the first wheel file found
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Published to TestPyPI (or already existed) with version: $VERSION"
        echo "::notice::Published to TestPyPI (or already existed) with version: $VERSION"

  publish-pypi:
    name: Publish to PyPI
    needs: [build, permission-check]
    if: >-
      needs.permission-check.outputs.allowed == 'true' &&
      (github.event_name == 'release' || inputs.target == 'pypi' || inputs.target == 'both')
    runs-on: ubuntu-24.04
    environment:
      name: pypi
      url: https://pypi.org/p/openviking
    permissions:
      id-token: write
      actions: read
    steps:
    - name: Download all the dists (Same Run)
      uses: actions/download-artifact@v8
      with:
        pattern: python-package-distributions-*
        path: dist/
        merge-multiple: true

    - name: Publish distribution to PyPI
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        skip-existing: true
        verbose: true

    - name: Display published version
      run: |
        # Get version from the first wheel file found
        VERSION=$(ls dist/*.whl | head -n 1 | xargs basename | cut -d- -f2)
        echo "Published to PyPI (or already existed) with version: $VERSION"
        echo "::notice::Published to PyPI (or already existed) with version: $VERSION"

  docker:
    name: Build and Push Docker Image
    needs: [build, permission-check]
    if: >-
      needs.permission-check.outputs.allowed == 'true' &&
      github.event_name == 'release'
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          submodules: recursive

      - name: Log in to the Container registry
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v6
        with:
          images: ghcr.io/${{ github.repository }}

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4

      - name: Build and push Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          build-args: |
            OPENVIKING_VERSION=${{ github.event.release.tag_name }}


================================================
FILE: .github/workflows/rust-cli.yml
================================================
name: Rust CLI Build

on:
  workflow_call:
  push:
    branches: [ main, feat/rust-cli ]
    paths:
      - 'crates/**'
      - 'Cargo.toml'
      - '.github/workflows/rust-cli.yml'
    tags:
      - 'cli@*'  # Trigger release on tags starting with cli@
  pull_request:
    branches: [ main ]
    paths:
      - 'crates/**'
      - 'Cargo.toml'
      - '.github/workflows/rust-cli.yml'

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-gnu
            artifact_name: ov-linux-x86_64
          - os: ubuntu-24.04
            target: aarch64-unknown-linux-gnu
            artifact_name: ov-linux-aarch64
          - os: macos-15-intel
            target: x86_64-apple-darwin
            artifact_name: ov-macos-x86_64
          - os: macos-14
            target: aarch64-apple-darwin
            artifact_name: ov-macos-aarch64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: ov-windows-x86_64.exe

    steps:
    - uses: actions/checkout@v6

    - name: Install Rust
      uses: dtolnay/rust-toolchain@v1
      with:
        toolchain: stable
        targets: ${{ matrix.target }}

    - name: Install system dependencies (Linux)
      if: runner.os == 'Linux'
      run: |
        sudo apt-get update
        sudo apt-get install -y pkg-config libssl-dev

    - name: Install cross-compilation tools (Linux ARM64)
      if: matrix.target == 'aarch64-unknown-linux-gnu'
      run: |
        sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
        echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
        echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
        echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV

    - name: Cache Cargo registry and index
      uses: actions/cache@v5
      with:
        path: |
          ~/.cargo/registry/index
          ~/.cargo/registry/cache
          ~/.cargo/git/db
        key: ${{ runner.os }}-cargo-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: |
          ${{ runner.os }}-cargo-${{ matrix.target }}-
          ${{ runner.os }}-cargo-

    - name: Cache build artifacts
      uses: actions/cache@v5
      with:
        path: target
        key: ${{ runner.os }}-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('crates/**/*.rs') }}
        restore-keys: |
          ${{ runner.os }}-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}-
          ${{ runner.os }}-target-${{ matrix.target }}-

    - name: Build CLI
      run: cargo build --release --target ${{ matrix.target }} -p ov_cli
        
    - name: Create compressed artifacts
      shell: bash
      run: |
        mkdir -p artifacts
        cd target/${{ matrix.target }}/release

        if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
          # Windows: create zip
          7z a ../../../artifacts/${{ matrix.artifact_name }}.zip ov.exe
          cd ../../../artifacts
          # Use PowerShell to get hash in correct format
          powershell -Command "(Get-FileHash -Algorithm SHA256 '${{ matrix.artifact_name }}.zip').Hash.ToLower() + '  ${{ matrix.artifact_name }}.zip'" > ${{ matrix.artifact_name }}.zip.sha256
        else
          # Unix: create tar.gz
          tar czf ../../../artifacts/${{ matrix.artifact_name }}.tar.gz ov
          cd ../../../artifacts
          # shasum format: <hash>  <filename>
          shasum -a 256 ${{ matrix.artifact_name }}.tar.gz > ${{ matrix.artifact_name }}.tar.gz.sha256
        fi

    - name: Verify checksum format
      shell: bash
      run: |
        echo "Contents of checksum file:"
        cat artifacts/*.sha256
        echo ""
        echo "Verifying checksum locally:"
        cd artifacts
        if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
          sha256sum -c *.sha256 || shasum -a 256 -c *.sha256 || echo "Checksum verification skipped on Windows"
        else
          shasum -a 256 -c *.sha256
        fi

    - name: Upload artifacts
      uses: actions/upload-artifact@v7
      with:
        name: ${{ matrix.artifact_name }}
        path: artifacts/*

  release:
    name: Create GitHub Release
    runs-on: ubuntu-24.04
    needs: build
    if: startsWith(github.ref, 'refs/tags/cli@')
    permissions:
      contents: write
    steps:
    - name: Checkout code
      uses: actions/checkout@v6

    - name: Get version from tag
      id: get_version
      run: echo "version=${GITHUB_REF#refs/tags/cli@}" >> $GITHUB_OUTPUT

    - name: Download all artifacts
      uses: actions/download-artifact@v8
      with:
        path: artifacts

    - name: Display artifact structure
      run: ls -R artifacts/

    - name: Create GitHub Release
      uses: softprops/action-gh-release@v2
      with:
        name: CLI v${{ steps.get_version.outputs.version }}
        body: |
          # OpenViking CLI v${{ steps.get_version.outputs.version }}

          ## Installation

          ### Quick Install (macOS/Linux)
          ```bash
          curl -fsSL https://raw.githubusercontent.com/${{ github.repository }}/refs/tags/cli@${{ steps.get_version.outputs.version }}/crates/ov_cli/install.sh | bash
          ```

          ### Manual Installation
          Download the appropriate binary for your platform below, extract it, and add it to your PATH.

          The CLI command is simply `ov`:
          ```bash
          # After extraction
          chmod +x ov  # Unix only
          mv ov /usr/local/bin/  # or any directory in your PATH

          # Verify installation
          ov --version
          ```

          ### Checksums
          SHA256 checksums are provided for each binary for verification.

          ## Changes
          See the [commit history](https://github.com/${{ github.repository }}/commits/cli@${{ steps.get_version.outputs.version }}) for details.
        files: |
          artifacts/**/*.tar.gz
          artifacts/**/*.zip
          artifacts/**/*.sha256
        draft: false
        prerelease: ${{ contains(steps.get_version.outputs.version, 'alpha') || contains(steps.get_version.outputs.version, 'beta') || contains(steps.get_version.outputs.version, 'rc') }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/schedule.yml
================================================
name: 04. Weekly Security Scan

on:
  schedule:
    - cron: '0 0 * * 0'  # Run at 00:00 on Sunday

permissions:
  actions: read
  contents: read
  security-events: write

jobs:
  security-scan:
    uses: ./.github/workflows/_codeql.yml


================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
openviking.egg-info/
data/

# Rust
target/
**/*.rs.bk
*.pdb

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
.ruff_cache/
cover/
test_data/
test_data_sync/

# Virtual environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# macOS
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# OpenViking specific
/data/*
/demo_data/*
/benchmark_data/*
.claude
.openviking
*.code-workspace

# AI Coding
CLAUDE.md
*.so
AGENTS.md

# Git worktrees
.worktrees/

# Logs
*.log
logs/

# Temporary files
*.tmp
*.temp
.tmp/
ov.conf

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env.local
.env.development.local
.env.test.local
.env.production.local

# mkdocs documentation
/site
docs/superpowers/

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/
openviking/bin/
third_party/agfs/bin/
test_scripts/
examples/data/
openviking/_version.py
specs/
.trae/


================================================
FILE: .pr_agent.toml
================================================
# =============================================================================
# Qodo PR-Agent Configuration for OpenViking
# =============================================================================
# OpenViking: polyglot (Python/TypeScript/Rust) context database for AI agents.
# By ByteDance/Volcengine — Apache-2.0 licensed.
#
# Rules derived from: real bug history (PRs #505, #728, #749, #740/#745),
# codebase conventions, CI pipeline (ruff, mypy, pytest), and Qodo best
# practices (Rule System blog, 2.2 PR History, raw configuration.toml).
#
# Principle: edit only what you need (Qodo Tip #1). Every override here has
# a documented reason tied to OpenViking's specific patterns.
# =============================================================================

# ---------------------------------------------------------------------------
# Global Config
# ---------------------------------------------------------------------------
[config]
output_relevant_configurations = false
# Use high reasoning for this complex polyglot codebase with subtle async/
# concurrency bugs. Worth the extra latency for quality.
reasoning_effort = "high"
# More context around hunks helps the model understand memory pipeline flows
# that often span multiple functions.
patch_extra_lines_before = 8
patch_extra_lines_after = 3
allow_dynamic_context = true
# Auto-detect language from PR content (Chinese contributors are common)
response_language = "en-US"
# Custom labels for OpenViking-specific PR categorization
enable_custom_labels = true

# ---------------------------------------------------------------------------
# Ignore: skip generated/vendored/lock files from analysis
# Reduces noise and token waste on files humans don't review.
# ---------------------------------------------------------------------------
[ignore]
glob = [
    # Lock files (auto-generated, not human-authored)
    'uv.lock',
    '*.lock',
    'package-lock.json',
    # Third-party vendored code (not our responsibility)
    'third_party/**',
    # Rust build artifacts
    'target/**',
    # Test data fixtures (binary/large JSON blobs)
    'db_test_*/**',
    'test_data/**',
    'test_data_sync/**',
    # Worktree scratch spaces
    '.worktrees/**',
    # Build support (C++ profiles, not core logic)
    'build_support/**',
]

# ---------------------------------------------------------------------------
# Auto-triggers on PR open
# ---------------------------------------------------------------------------
[github_app]
pr_commands = [
    "/describe",
    "/review",
    "/improve --pr_code_suggestions.commitable_code_suggestions=false",
]

# ---------------------------------------------------------------------------
# Custom Labels: OpenViking-specific PR categorization
# Each description is a conditional statement (Qodo best practice) so the
# model knows exactly when to apply it.
# ---------------------------------------------------------------------------
[custom_labels."memory-pipeline"]
description = "Apply when the PR modifies memory extraction, deduplication, archival, or any code in openviking/session/ that touches MemoryCategory, SessionCompressor, MemoryDeduplicator, or MemoryExtractor."

[custom_labels."async-change"]
description = "Apply when the PR modifies async/await patterns, changes commit() to commit_async(), adds asyncio.gather/TaskGroup usage, or modifies any coroutine in the session or storage layer."

[custom_labels."embedding-vectorization"]
description = "Apply when the PR modifies embedding models, vectorization logic, chunked vectorization, or VLM provider integrations in openviking/embedding/ or openviking/vlm/."

[custom_labels."plugin-bot"]
description = "Apply when the PR modifies TypeScript code in bot/ or examples/openclaw-plugin/, including hook handlers, process management, or client initialization."

[custom_labels."api-breaking"]
description = "Apply when the PR removes, renames, or changes the type of any public API parameter, REST endpoint, SDK method, or configuration key that external consumers depend on."

[custom_labels."multi-tenant"]
description = "Apply when the PR modifies authentication, authorization, account/user routing, root key handling, or RequestContext identity resolution."

[custom_labels."retrieval"]
description = "Apply when the PR modifies the retrieval pipeline: find, rerank, semantic search, or context level (L0/L1/L2) scoring logic."

[custom_labels."rust-cli"]
description = "Apply when the PR modifies Rust source files (src/*.rs) or Cargo.toml for the CLI tool."

# ---------------------------------------------------------------------------
# Review Tool
# ---------------------------------------------------------------------------
[pr_reviewer]
persistent_comment = true
final_update_message = true
# Increased from default 3 → 8 because OpenViking PRs often span multiple
# subsystems (Python core + TypeScript bot + config) with cross-cutting concerns.
num_max_findings = 8
enable_intro_text = true
enable_help_text = false
publish_output_no_suggestions = true

# --- Feature toggles (overrides from defaults) ---
require_score_review = true          # Score each PR 1-100 (disabled by default, useful for quality tracking)
require_tests_review = true          # Check if tests are present (default: true)
require_estimate_effort_to_review = true  # Effort estimate label (default: true)
require_can_be_split_review = true   # Flag large PRs that should be split (default: false → enabled)
require_security_review = true       # Dedicated security audit section (default: true)
require_todo_scan = true             # Surface TODO/FIXME/HACK in changed code (default: false → enabled)
require_ticket_analysis_review = true # Check ticket compliance if linked

# --- Labels ---
enable_review_labels_security = true
enable_review_labels_effort = true

extra_instructions = """\
You are reviewing OpenViking — an agent-native context database.
Stack: Python 3.10+ core (FastAPI, pydantic, httpx, loguru), TypeScript bot
(Vikingbot/OpenClaw plugin), Rust CLI, C++ extensions (AGFS).

## Severity Classification (exactly ONE per finding)

[Critical] — Blocks release. Security vulnerability, data loss/corruption, crash in
production path, resource leak without cleanup, auth bypass.

[Bug] — Must fix before merge. Logic error, behavioral regression, API contract
violation, race condition, missing await on coroutine, silent exception swallowing.

[Perf] — Performance regression. O(n²)+ algorithmic complexity, unbounded collection
growth, N+1 queries against VikingDB, redundant embedding/VLM API calls,
unnecessary large object copies in hot paths.

[Suggestion] — Recommended improvement. Missing tests, dead code, naming inconsistency,
poor observability (missing telemetry/logging), unclear intent, unrelated changes in PR.

## Rules (structured as: WHEN condition → THEN check → BECAUSE rationale)

### PYTHON CORE (openviking/, openviking_cli/)

R1. ASYNC DISCIPLINE
WHEN code is inside an async function or coroutine
THEN verify all I/O calls use async variants (commit_async not commit,
     httpx.AsyncClient not requests, async for on streams)
BECAUSE blocking calls in async context starve the event loop.
     Real bug: PR #728 replaced blocking commit() with commit_async().
     Also check: missing `await` on coroutine calls (silent bug — returns
     coroutine object instead of result).

R2. MEMORY PIPELINE COMPLETENESS
WHEN code touches MemoryCategory, MemoryExtractor, MemoryDeduplicator,
     SessionCompressor, or MemoryArchiver
THEN verify all 6 categories are handled: PREFERENCES, ENTITIES, PATTERNS,
     EVENTS, TOOLS, SKILLS. Check that match/if-elif chains on DedupDecision
     (KEEP/MERGE/DELETE/SKIP) are exhaustive.
BECAUSE partial handling silently drops memories. The 6-category model is
     a core invariant of the extraction pipeline.

R3. QUADRATIC REPROCESSING GUARD
WHEN code enqueues items (SemanticMsg, embedding tasks) inside a loop that
     also processes the queue, or when a callback re-enqueues work
THEN flag as [Perf] or [Bug] — this pattern causes O(n²) reprocessing.
BECAUSE PR #505 fixed exactly this: misdirected SemanticMsg enqueue inside
     a processing loop caused quadratic growth.

R4. VLM/EMBEDDING API RESILIENCE
WHEN code calls VLM providers (OpenAI, Doubao/Ark, Gemini) or embedding APIs
THEN verify: (a) timeout is set (ai_timeout or explicit), (b) retry/fallback
     exists for transient failures, (c) streaming responses handle partial
     failure gracefully, (d) JSON output uses json-repair not raw json.loads.
BECAUSE PR #740 was reverted (#745) due to streaming response issues, then
     re-landed in #756 with proper handling. This is a repeat-risk area.

R5. TYPE SAFETY
WHEN new Python code is added or modified
THEN check: no bare `type: ignore` (must have explanation comment), consistent
     Optional[X] vs X|None style within each file, proper use of
     TYPE_CHECKING imports for circular dependency avoidance.
BECAUSE CI enforces ruff + mypy on changed files. Suppressions without
     rationale hide real type errors.

R6. LICENSE HEADERS
WHEN a new .py file is created in openviking/ or openviking_cli/
THEN it MUST contain at the top:
     # Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.
     # SPDX-License-Identifier: Apache-2.0
BECAUSE Apache-2.0 compliance requires headers on all source files.
     Every existing file in these directories follows this convention.

R7. ERROR HANDLING
WHEN code uses try/except
THEN verify: no bare `except:` or `except Exception:` without logging (loguru)
     or re-raising. Narrow exceptions to specific types where possible.
BECAUSE PR #148f6e3 fixed overly broad `except Exception` to specific
     (ImportError, ModuleNotFoundError, AttributeError). Broad catches hide
     real bugs.

### TYPESCRIPT / BOT (bot/, examples/openclaw-plugin/)

R8. PLUGIN HOOK TIMEOUT
WHEN code registers or modifies a hook handler (before_prompt_build,
     after_prompt_build, etc.) or calls getClient()
THEN verify the call has timeout protection (Promise.race with timeout,
     AbortController, or equivalent).
BECAUSE PR #749 added timeout protection to getClient() after discovering
     hooks could hang indefinitely, blocking the entire bot.

R9. PROCESS LIFECYCLE
WHEN code spawns child processes or manages bot lifecycle
THEN verify: SIGTERM/SIGINT handlers exist, stdio streams are properly
     closed, and cleanup runs in all exit paths (including uncaught exceptions).
BECAUSE the bot uses process-manager.ts for lifecycle; leaked processes or
     file descriptors degrade the host system.

### CROSS-CUTTING

R10. API BACKWARD COMPATIBILITY
WHEN a PR modifies public interfaces (FastAPI endpoints, SDK client params,
     RequestContext fields, config keys in ov.conf)
THEN verify: existing params are not removed or renamed (only deprecated),
     new params have defaults, multi-tenant changes preserve single-tenant
     behavior as the default path.
BECAUSE PR #767 added account/user params — these must be optional to avoid
     breaking existing single-tenant deployments.

R11. CONCURRENCY SAFETY
WHEN code modifies shared mutable state (dicts, lists, sets) in async
     functions, or uses _pending_semantic_changes or similar shared structures
THEN verify proper synchronization (asyncio.Lock, thread-safe collections)
     and that no produce-and-consume-in-same-loop pattern exists.
BECAUSE the SessionCompressor._pending_semantic_changes dict is accessed
     from multiple async paths; unsynchronized access causes data races.

R12. RETRIEVAL PIPELINE INTEGRITY
WHEN code modifies find/rerank/search logic or ContextLevel scoring (L0/L1/L2)
THEN verify: rerank is optional (PR #754 fixed find-without-rerank), level-2
     scores are preserved through the pipeline, and search results maintain
     their ranking order.
BECAUSE PR #754 fixed a bug where find() required rerank and level-2 scores
     were silently dropped.

R13. TESTING REQUIREMENTS
WHEN a PR fixes a bug → it MUST include a regression test or explicitly
     explain in the PR description why one is impractical.
WHEN a PR adds a feature → it SHOULD include unit tests for the happy path
     and at least one error/edge case.
WHEN a PR modifies embedding/VLM integration → verify test isolation (no
     hardcoded API keys — construct test keys dynamically as in PR #148f6e3).
BECAUSE the repo uses pytest; test patterns should use fixtures, not globals.

R14. DOCUMENTATION CONSISTENCY
WHEN a PR modifies docs/ (en/ and zh/cn/ and ja/) or README files
THEN verify all language versions are updated consistently. Flag if only
     one language is updated when the content change is substantive.
BECAUSE the repo maintains en/zh/ja translations (PR #755 added Japanese docs).

R15. TELEMETRY & OBSERVABILITY
WHEN code adds or modifies operations that call external services (VLM, embedding,
     VikingDB) or processes memories
THEN verify telemetry integration exists (get_current_telemetry pattern) and that
     timing/count metrics are recorded for the operation.
BECAUSE PR #735 added memory extract telemetry breakdown — new operations
     should follow this pattern for production observability.

## Output Format
Be specific: reference exact variable names, function calls, line numbers.
When suggesting a fix, include a minimal code block.
Match PR language (Chinese PR → Chinese review, English PR → English review).
"""

# ---------------------------------------------------------------------------
# Improve Tool (code suggestions)
# ---------------------------------------------------------------------------
[pr_code_suggestions]
commitable_code_suggestions = false
persistent_comment = true
focus_only_on_problems = true
# Filter low-confidence suggestions. 0 = show all, 7+ = high quality only.
# Set to 5 to balance signal-to-noise for this codebase.
suggestions_score_threshold = 5
# Extended mode for thorough analysis of large PRs
auto_extended_mode = true
num_code_suggestions_per_chunk = 4
max_number_of_calls = 3
parallel_calls = true

extra_instructions = """\
Focus suggestions on these OpenViking-specific anti-patterns:

1. BLOCKING IN ASYNC: Replace `commit()`, `requests.get()`, `time.sleep()` with
   `commit_async()`, `httpx.AsyncClient`, `asyncio.sleep()` inside async functions.

2. QUADRATIC LOOPS: Simplify nested loops over memory categories or semantic queues.
   If an inner loop re-processes items already in the outer loop, suggest flattening
   or using a set-based approach.

3. PROMPT CONSTRUCTION: Extract repeated LLM prompt strings into Jinja2 templates
   (the dependency exists in pyproject.toml). Inline f-string prompts over 5 lines
   should be templated.

4. LOGGING: Replace `print()` with `logger = get_logger(__name__)` (loguru pattern
   used throughout the codebase). Include structured context in log messages.

5. VALIDATION: Prefer pydantic models for API request/response validation over raw
   dicts. The codebase already depends on pydantic>=2.0.0.

6. API RESILIENCE: Flag any VLM/embedding API call missing timeout or retry logic.
   Suggest wrapping with httpx timeout config or litellm retry patterns.

7. RESOURCE CLEANUP: Ensure context managers (async with) are used for DB connections,
   HTTP clients, and file handles. Flag bare open() without context manager.
"""

# ---------------------------------------------------------------------------
# Describe Tool
# ---------------------------------------------------------------------------
[pr_description]
generate_ai_title = false
use_bullet_points = true
add_original_user_description = true
enable_pr_type = true
enable_pr_diagram = true
enable_semantic_files_types = true
collapsible_file_list = 'adaptive'
collapsible_file_list_threshold = 8
enable_large_pr_handling = true
include_generated_by_header = true
publish_labels = true
final_update_message = true

extra_instructions = """\
For OpenViking PRs, structure the description to include:
- **Layer affected**: core (Python), bot (TypeScript), CLI (Rust), AGFS (C++/Go), or docs.
- **Backward compatibility**: state whether existing APIs, config keys, or SDK params are affected.
- **Memory pipeline impact**: if session/ is touched, list which of the 6 memory categories
  (PREFERENCES, ENTITIES, PATTERNS, EVENTS, TOOLS, SKILLS) are affected.
- **Multi-tenant impact**: if auth/identity is touched, note whether single-tenant default is preserved.
"""


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.14.14
    hooks:
      - id: ruff
        args: [ --fix ]
      - id: ruff-format


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guide

Thank you for your interest in OpenViking! We welcome contributions of all kinds:

- Bug reports
- Feature requests
- Documentation improvements
- Code contributions

---

## Development Setup

### Prerequisites

- **Python**: 3.10+
- **Go**: 1.22+ (Required for building AGFS components from source)
- **Rust**: 1.88+ (Required for source builds because the bundled `ov` CLI is built during packaging)
- **C++ Compiler**: GCC 9+ or Clang 11+ (Required for building core extensions, must support C++17)
- **CMake**: 3.12+

#### Platform-Specific Native Build Tools

- **Linux**: Install `build-essential`; some environments may also require `pkg-config`
- **macOS**: Install Xcode Command Line Tools (`xcode-select --install`)
- **Windows**: Install CMake and MinGW for local native builds

#### Supported Platforms (Pre-compiled Wheels)

OpenViking provides pre-compiled **Wheel** packages for the following environments:

- **Windows**: x86_64
- **macOS**: x86_64, arm64 (Apple Silicon)
- **Linux**: x86_64, arm64 (manylinux)

For other platforms (e.g., FreeBSD), the package will be automatically compiled from source during installation via `pip`. Ensure you have the [Prerequisites](#prerequisites) installed.

### 1. Fork and Clone

```bash
git clone https://github.com/YOUR_USERNAME/openviking.git
cd openviking
```

### 2. Install Dependencies

We recommend using `uv` for Python environment management:

```bash
# Install uv (if not installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Sync dependencies and create virtual environment
uv sync --all-extras
source .venv/bin/activate  # Linux/macOS
# or .venv\Scripts\activate  # Windows
```

#### Local Development & Native Rebuilds

OpenViking defaults to `binding-client` mode for AGFS, which requires pre-built native artifacts. If you modify the **AGFS (Go)** code, the bundled **Rust CLI**, or the **C++ extensions**, or if the pre-built artifacts are not found, you need to re-compile and re-install them. Run the following command in the project root:

```bash
uv pip install -e . --force-reinstall
```

This command ensures that `setup.py` is re-executed, triggering rebuilds for AGFS, the bundled `ov` CLI, and the C++ components.

### 3. Configure Environment

Create a configuration file `~/.openviking/ov.conf`:

```json
{
  "embedding": {
    "dense": {
      "provider": "volcengine",
      "api_key": "your-api-key",
      "model": "doubao-embedding-vision-250615",
      "api_base": "https://ark.cn-beijing.volces.com/api/v3",
      "dimension": 1024,
      "input": "multimodal"
    }
  },
  "vlm": {
    "api_key": "your-api-key",
    "model": "doubao-seed-2-0-pro-260215",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

Set the environment variable:

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf
```

### 4. Verify Installation

```python
import asyncio
import openviking as ov

async def main():
    client = ov.AsyncOpenViking(path="./test_data")
    await client.initialize()
    print("OpenViking initialized successfully!")
    await client.close()

asyncio.run(main())
```

### 5. Build Rust CLI (Optional)

The Rust CLI (`ov`) provides a high-performance command-line client for interacting with OpenViking Server.

Even if you do not plan to use `ov` directly, the Rust toolchain is still required when building OpenViking from source because packaging also builds the bundled CLI binary.

```bash
# Build and install from source
cargo install --path crates/ov_cli

# Or use the quick install script (downloads pre-built binary)
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

After installation, run `ov --help` to see all available commands. CLI connection config goes in `~/.openviking/ovcli.conf`.

---

## Project Structure

```
openviking/
├── pyproject.toml        # Project configuration
├── Cargo.toml            # Rust workspace configuration
├── third_party/          # Third-party dependencies
│   └── agfs/             # AGFS filesystem
│
├── openviking/           # Python SDK
│   ├── async_client.py   # AsyncOpenViking client
│   ├── sync_client.py    # SyncOpenViking client
│   ├── client/           # Local and HTTP client implementations
│   ├── console/          # Standalone console UI and proxy service
│   ├── core/             # Core data models and directory abstractions
│   ├── message/          # Session message and part models
│   ├── models/           # Embedding and VLM backends
│   ├── parse/            # Resource parsers and detectors
│   ├── resource/         # Resource processing and watch management
│   ├── retrieve/         # Retrieval system
│   ├── server/           # HTTP server
│   ├── service/          # Shared service layer
│   ├── session/          # Session management and compression
│   ├── storage/          # Storage layer
│   ├── telemetry/        # Operation telemetry
│   ├── trace/            # Trace and runtime tracing helpers
│   ├── utils/            # Utilities and configuration helpers
│   └── prompts/          # Prompt templates
│
├── crates/               # Rust components
│   └── ov_cli/           # Rust CLI client
│       ├── src/          # CLI source code
│       └── install.sh    # Quick install script
│
├── src/                  # C++ extensions (pybind11)
│
├── tests/                # Test suite
│   ├── client/           # Client tests
│   ├── console/          # Console tests
│   ├── core/             # Core logic tests
│   ├── parse/            # Parser tests
│   ├── resource/         # Resource processing tests
│   ├── retrieve/         # Retrieval tests
│   ├── server/           # Server tests
│   ├── service/          # Service layer tests
│   ├── session/          # Session tests
│   ├── storage/          # Storage tests
│   ├── telemetry/        # Telemetry tests
│   ├── vectordb/         # Vector database tests
│   └── integration/      # End-to-end tests
│
└── docs/                 # Documentation
    ├── en/               # English docs
    └── zh/               # Chinese docs
```

---

## Code Style

We use the following tools to maintain code consistency:

| Tool | Purpose | Config |
|------|---------|--------|
| **Ruff** | Linting, Formatting, Import sorting | `pyproject.toml` |
| **mypy** | Type checking | `pyproject.toml` |

### Automated Checks (Recommended)

We use [pre-commit](https://pre-commit.com/) to automatically run these checks before every commit. This ensures your code always meets the standards without manual effort.

1. **Install pre-commit**:
   ```bash
   pip install pre-commit
   ```

2. **Install the git hooks**:
   ```bash
   pre-commit install
   ```

Now, `ruff` (check & format) will run automatically when you run `git commit`. If any check fails, it may automatically fix the file. You just need to add the changes and commit again.

### Running Checks

```bash
# Format code
ruff format openviking/

# Lint
ruff check openviking/

# Type check
mypy openviking/
```

### Style Guidelines

1. **Line width**: 100 characters
2. **Indentation**: 4 spaces
3. **Strings**: Prefer double quotes
4. **Type hints**: Encouraged but not required
5. **Docstrings**: Required for public APIs (1-2 lines max)

---

## Testing

### Running Tests

```bash
# Run all tests
pytest

# Run specific test module
pytest tests/client/ -v
pytest tests/server/ -v
pytest tests/parse/ -v

# Run specific test file
pytest tests/client/test_lifecycle.py

# Run specific test
pytest tests/client/test_lifecycle.py::TestClientInitialization::test_initialize_success

# Run by keyword
pytest -k "search" -v

# Run with coverage
pytest --cov=openviking --cov-report=term-missing
```

### Writing Tests

Tests are organized in subdirectories under `tests/`. The project uses `asyncio_mode = "auto"`, so async tests do **not** need the `@pytest.mark.asyncio` decorator:

```python
# tests/client/test_example.py
from openviking import AsyncOpenViking


class TestAsyncOpenViking:
    async def test_initialize(self, uninitialized_client: AsyncOpenViking):
        await uninitialized_client.initialize()
        assert uninitialized_client._service is not None
        await uninitialized_client.close()

    async def test_add_resource(self, client: AsyncOpenViking, sample_markdown_file):
        result = await client.add_resource(
            path=str(sample_markdown_file),
            reason="test document"
        )
        assert "root_uri" in result
        assert result["root_uri"].startswith("viking://")
```

Common fixtures are defined in `tests/conftest.py`, including `client` (initialized `AsyncOpenViking`), `uninitialized_client`, `temp_dir`, `sample_markdown_file`, and more.

---

## Contribution Workflow

### 1. Create a Branch

```bash
git checkout main
git pull origin main
git checkout -b feature/your-feature-name
```

Branch naming conventions:
- `feature/xxx` - New features
- `fix/xxx` - Bug fixes
- `docs/xxx` - Documentation updates
- `refactor/xxx` - Code refactoring

### 2. Make Changes

- Follow code style guidelines
- Add tests for new functionality
- Update documentation as needed

### 3. Commit Changes

```bash
git add .
git commit -m "feat: add new parser for xlsx files"
```

### 4. Push and Create PR

```bash
git push origin feature/your-feature-name
```

Then create a Pull Request on GitHub.

---

## Commit Convention

We follow [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <subject>

<body>

<footer>
```

### Types

| Type | Description |
|------|-------------|
| `feat` | New feature |
| `fix` | Bug fix |
| `docs` | Documentation |
| `style` | Code style (no logic change) |
| `refactor` | Code refactoring |
| `perf` | Performance improvement |
| `test` | Tests |
| `chore` | Build/tooling |

### Examples

```bash
# New feature
git commit -m "feat(parser): add support for xlsx files"

# Bug fix
git commit -m "fix(retrieval): fix score calculation in rerank"

# Documentation
git commit -m "docs: update quick start guide"

# Refactoring
git commit -m "refactor(storage): simplify interface methods"
```

---

## Pull Request Guidelines

### PR Title

Use the same format as commit messages.

### PR Description Template

```markdown
## Summary

Brief description of the changes and their purpose.

## Type of Change

- [ ] New feature (feat)
- [ ] Bug fix (fix)
- [ ] Documentation (docs)
- [ ] Refactoring (refactor)
- [ ] Other

## Testing

Describe how to test these changes:
- [ ] Unit tests pass
- [ ] Manual testing completed

## Related Issues

- Fixes #123
- Related to #456

## Checklist

- [ ] Code follows project style guidelines
- [ ] Tests added for new functionality
- [ ] Documentation updated (if needed)
- [ ] All tests pass
```

---

## CI/CD Workflows

We use **GitHub Actions** for Continuous Integration and Continuous Deployment. Our workflows are designed to be modular and tiered.

### 1. Automatic Workflows

| Event | Workflow | Description |
|-------|----------|-------------|
| **Pull Request** | `pr.yml` | Runs **Lint** (Ruff, Mypy) and **Test Lite** (Integration tests on Linux + Python 3.10). Provides fast feedback for contributors. (Displayed as **01. Pull Request Checks**) |
| **Push to Main** | `ci.yml` | Runs **Test Full** (All OS: Linux/Win/Mac, All Py versions: 3.10-3.14) and **CodeQL** (Security scan). Ensures main branch stability. (Displayed as **02. Main Branch Checks**) |
| **Release Published** | `release.yml` | Triggered when you create a Release on GitHub. Automatically builds source distribution and wheels, determines version from Git Tag, and publishes to **PyPI**. (Displayed as **03. Release**) |
| **Weekly Cron** | `schedule.yml` | Runs **CodeQL** security scan every Sunday. (Displayed as **04. Weekly Security Scan**) |

Other repository workflows also exist for PR review automation, Docker image builds, and Rust CLI packaging.

### 2. Manual Trigger Workflows

Maintainers can manually trigger the following workflows from the "Actions" tab to perform specific tasks or debug issues.

#### A. Lint Checks (`11. _Lint Checks`)
Runs code style checks (Ruff) and type checks (Mypy). No arguments required.

> **Tip**: It is recommended to install [pre-commit](https://pre-commit.com/) locally to run these checks automatically before committing (see [Automated Checks](#automated-checks-recommended) section above).

#### B. Test Suite (Lite) (`12. _Test Suite (Lite)`)
Runs fast integration tests, supports custom matrix configuration.

*   **Inputs**:
    *   `os_json`: JSON string array of OS to run on (e.g., `["ubuntu-24.04"]`).
    *   `python_json`: JSON string array of Python versions (e.g., `["3.10"]`).

#### C. Test Suite (Full) (`13. _Test Suite (Full)`)
Runs the full test suite on all supported platforms (Linux/Mac/Win) and Python versions (3.10-3.14). Supports custom matrix configuration when triggered manually.

*   **Inputs**:
    *   `os_json`: List of OS to run on (Default: `["ubuntu-24.04", "macos-14", "windows-latest"]`).
    *   `python_json`: List of Python versions (Default: `["3.10", "3.11", "3.12", "3.13", "3.14"]`).

#### D. Security Scan (`14. _CodeQL Scan`)
Runs CodeQL security analysis. No arguments required.

#### E. Build Distribution (`15. _Build Distribution`)
Builds Python wheel packages only, does not publish.

*   **Inputs**:
    *   `os_json`: List of OS to build on (Default: `["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]`).
    *   `python_json`: List of Python versions (Default: `["3.10", "3.11", "3.12", "3.13", "3.14"]`).
    *   `build_sdist`: Whether to build source distribution (Default: `true`).
    *   `build_wheels`: Whether to build wheel distribution (Default: `true`).

#### F. Publish Distribution (`16. _Publish Distribution`)
Publishes built packages (requires build Run ID) to PyPI.

*   **Inputs**:
    *   `target`: Select publish target (`testpypi`, `pypi`, `both`).
    *   `build_run_id`: Build Workflow Run ID (Required, get it from the Build run URL).

#### G. Manual Release (`03. Release`)
One-stop build and publish (includes build and publish steps).

> **Version Numbering & Tag Convention**:
> This project uses `setuptools_scm` to automatically extract version numbers from Git Tags.
> *   **Tag Naming Convention**: Must follow the `vX.Y.Z` format (e.g., `v0.1.0`, `v1.2.3`). Tags must be compliant with Semantic Versioning.
> *   **Release Build**: When a Release event is triggered, the version number directly corresponds to the Git Tag (e.g., `v0.1.0` -> `0.1.0`).
> *   **Manual/Non-Tag Build**: The version number will include the commit count since the last Tag (e.g., `0.1.1.dev3`).
> *   **Confirm Version**: After the publish job completes, you can see the published version directly in the **Notifications** area at the top of the Workflow **Summary** page (e.g., `Successfully published to PyPI with version: 0.1.8`). You can also verify it in the logs or the **Artifacts** filenames.

*   **Inputs**:
    *   `target`: Select publish target.
        *   `none`: Build artifacts only (no publish). Used for verifying build capability.
        *   `testpypi`: Publish to TestPyPI. Used for Beta testing.
        *   `pypi`: Publish to official PyPI.
        *   `both`: Publish to both.
    *   `os_json`: Build platforms (Default includes all).
    *   `python_json`: Python versions (Default includes all).
    *   `build_sdist`: Whether to build source distribution (Default: `true`).
    *   `build_wheels`: Whether to build wheel distribution (Default: `true`).

> **Publishing Notes**:
> *   **Test First**: It is strongly recommended to publish to **TestPyPI** for verification before publishing to official PyPI. Note that PyPI and TestPyPI are completely independent environments, and accounts and package data are not shared.
> *   **No Overwrites**: Neither PyPI nor TestPyPI allow overwriting existing packages with the same name and version. If you need to republish, you must upgrade the version number (e.g., tag a new version or generate a new dev version). If you try to publish an existing version, the workflow will fail.

---

## Issue Guidelines

### Bug Reports

Please provide:

1. **Environment**
   - Python version
   - OpenViking version
   - Operating system

2. **Steps to Reproduce**
   - Detailed steps
   - Code snippets

3. **Expected vs Actual Behavior**

4. **Error Logs** (if any)

### Feature Requests

Please describe:

1. **Problem**: What problem are you trying to solve?
2. **Solution**: What solution do you propose?
3. **Alternatives**: Have you considered other approaches?

---

## Documentation

Documentation is in Markdown format under `docs/`:

- `docs/en/` - English documentation
- `docs/zh/` - Chinese documentation

### Documentation Guidelines

1. Code examples must be runnable
2. Keep documentation in sync with code
3. Use clear, concise language

---

## Code of Conduct

By participating in this project, you agree to:

1. **Be respectful**: Maintain a friendly and professional attitude
2. **Be inclusive**: Welcome contributors from all backgrounds
3. **Be constructive**: Provide helpful feedback
4. **Stay focused**: Keep discussions technical

---

## Getting Help

If you have questions:

- [GitHub Issues](https://github.com/volcengine/openviking/issues)
- [Discussions](https://github.com/volcengine/openviking/discussions)

---

Thank you for contributing!


================================================
FILE: CONTRIBUTING_CN.md
================================================
# 贡献指南

感谢你对 OpenViking 感兴趣!我们欢迎各种形式的贡献:

- 报告 Bug
- 提交功能请求
- 改进文档
- 贡献代码

---

## 开发环境设置

### 前置要求

- **Python**: 3.10+
- **Go**: 1.22+ (从源码构建 AGFS 组件需要)
- **Rust**: 1.88+(从源码构建需要;打包流程会同时构建内置 `ov` CLI)
- **C++ 编译器**: GCC 9+ 或 Clang 11+ (构建核心扩展需要,必须支持 C++17)
- **CMake**: 3.12+

#### 平台相关的本地构建工具

- **Linux**: 建议安装 `build-essential`;某些环境下还可能需要 `pkg-config`
- **macOS**: 安装 Xcode Command Line Tools(`xcode-select --install`)
- **Windows**: 本地原生构建建议安装 CMake 和 MinGW

#### 支持的平台 (预编译 Wheel 包)

OpenViking 为以下环境提供预编译的 **Wheel** 包,安装时无需本地编译:

- **Windows**: x86_64
- **macOS**: x86_64, arm64 (Apple Silicon)
- **Linux**: x86_64, arm64 (manylinux)

对于其他平台(如 FreeBSD 等),安装时 `pip` 将会自动从源码进行编译。请确保已安装上述[前置要求](#前置要求)中的工具。

### 1. Fork 并克隆

```bash
git clone https://github.com/YOUR_USERNAME/openviking.git
cd openviking
```

### 2. 安装依赖

我们推荐使用 `uv` 进行 Python 环境管理:

```bash
# 安装 uv (如果尚未安装)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 同步依赖并创建虚拟环境
uv sync --all-extras
source .venv/bin/activate  # Linux/macOS
# 或者 .venv\Scripts\activate  # Windows
```

#### 本地开发与原生组件重建

OpenViking 默认使用 `binding-client` 模式,这依赖预先构建的原生产物。如果你修改了 **AGFS (Go)** 代码、内置的 **Rust CLI**,或 **C++ 扩展**,或者这些预编译产物未找到,你需要重新编译并安装它们,以使更改在本地环境中生效。在项目根目录下运行以下命令:

```bash
uv pip install -e . --force-reinstall
```

该命令会强制重新执行 `setup.py`,触发 AGFS、内置 `ov` CLI 和 C++ 组件的重新编译与安装。

### 3. 配置环境

创建配置文件 `~/.openviking/ov.conf`:

```json
{
  "embedding": {
    "dense": {
      "provider": "volcengine",
      "api_key": "your-api-key",
      "model": "doubao-embedding-vision-250615",
      "api_base": "https://ark.cn-beijing.volces.com/api/v3",
      "dimension": 1024,
      "input": "multimodal"
    }
  },
  "vlm": {
    "api_key": "your-api-key",
    "model": "doubao-seed-2-0-pro-260215",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

设置环境变量:

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf
```

### 4. 验证安装

```python
import asyncio
import openviking as ov

async def main():
    client = ov.AsyncOpenViking(path="./test_data")
    await client.initialize()
    print("OpenViking initialized successfully!")
    await client.close()

asyncio.run(main())
```

### 5. 构建 Rust CLI(可选)

Rust CLI (`ov`) 提供高性能的命令行客户端,用于连接 OpenViking Server 进行操作。

即使你不打算直接使用 `ov`,只要走 OpenViking 的源码构建流程,Rust 工具链仍然是必需的,因为打包过程也会构建内置 CLI 二进制。

```bash
# 从源码编译安装
cargo install --path crates/ov_cli

# 或者使用一键安装脚本(下载预编译二进制)
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

安装后通过 `ov --help` 查看所有可用命令。CLI 连接配置见 `~/.openviking/ovcli.conf`。

---

## 项目结构

```
openviking/
├── pyproject.toml        # 项目配置
├── Cargo.toml            # Rust workspace 配置
├── third_party/          # 第三方依赖
│   └── agfs/             # AGFS 文件系统
│
├── openviking/           # Python SDK
│   ├── async_client.py   # AsyncOpenViking 客户端
│   ├── sync_client.py    # SyncOpenViking 客户端
│   ├── client/           # 本地与 HTTP 客户端实现
│   ├── console/          # 独立 console UI 与代理服务
│   ├── core/             # 核心数据模型与目录抽象
│   ├── message/          # 会话消息与 part 模型
│   ├── models/           # Embedding 与 VLM 后端
│   ├── parse/            # 资源解析器与检测器
│   ├── resource/         # 资源处理与 watch 管理
│   ├── retrieve/         # 检索系统
│   ├── server/           # HTTP 服务端
│   ├── service/          # 共享 service 层
│   ├── session/          # 会话管理与压缩
│   ├── storage/          # 存储层
│   ├── telemetry/        # 操作级 telemetry
│   ├── trace/            # trace 与运行时跟踪辅助
│   ├── utils/            # 工具类与配置辅助
│   └── prompts/          # 提示词模板
│
├── crates/               # Rust 组件
│   └── ov_cli/           # Rust CLI 客户端
│       ├── src/          # CLI 源码
│       └── install.sh    # 一键安装脚本
│
├── src/                  # C++ 扩展 (pybind11)
│
├── tests/                # 测试套件
│   ├── client/           # 客户端测试
│   ├── console/          # Console 测试
│   ├── core/             # 核心逻辑测试
│   ├── parse/            # 解析器测试
│   ├── resource/         # 资源处理测试
│   ├── retrieve/         # 检索测试
│   ├── server/           # 服务端测试
│   ├── service/          # Service 层测试
│   ├── session/          # 会话测试
│   ├── storage/          # 存储测试
│   ├── telemetry/        # Telemetry 测试
│   ├── vectordb/         # 向量数据库测试
│   └── integration/      # 端到端测试
│
└── docs/                 # 文档
    ├── en/               # 英文文档
    └── zh/               # 中文文档
```

---

## 代码风格

我们使用以下工具来保持代码一致性:

| 工具 | 用途 | 配置 |
|------|---------|--------|
| **Ruff** | Linting, 格式化, 导入排序 | `pyproject.toml` |
| **mypy** | 类型检查 | `pyproject.toml` |

### 自动检查(推荐)

我们使用 [pre-commit](https://pre-commit.com/) 在每次提交前自动运行这些检查。这确保您的代码无需手动努力即可符合标准。

1. **安装 pre-commit**:
   ```bash
   pip install pre-commit
   ```

2. **安装 git hooks**:
   ```bash
   pre-commit install
   ```

现在,当您运行 `git commit` 时,`ruff`(检查和格式化)将自动运行。如果任何检查失败,它可能会自动修复文件。您只需添加更改并再次提交即可。

### 运行检查

```bash
# 格式化代码
ruff format openviking/

# Lint 检查
ruff check openviking/

# 类型检查
mypy openviking/
```

### 风格指南

1. **行宽**:100 字符
2. **缩进**:4 个空格
3. **字符串**:推荐使用双引号
4. **类型提示**:鼓励但不强制
5. **Docstrings**:公共 API 必须包含(最多 1-2 行)

---

## 测试

### 运行测试

```bash
# 运行所有测试
pytest

# 运行特定测试模块
pytest tests/client/ -v
pytest tests/server/ -v
pytest tests/parse/ -v

# 运行特定测试文件
pytest tests/client/test_lifecycle.py

# 运行特定测试
pytest tests/client/test_lifecycle.py::TestClientInitialization::test_initialize_success

# 按关键字运行
pytest -k "search" -v

# 运行并生成覆盖率报告
pytest --cov=openviking --cov-report=term-missing
```

### 编写测试

测试按模块组织在 `tests/` 的子目录中。项目使用 `asyncio_mode = "auto"`,异步测试**不需要** `@pytest.mark.asyncio` 装饰器:

```python
# tests/client/test_example.py
from openviking import AsyncOpenViking


class TestAsyncOpenViking:
    async def test_initialize(self, uninitialized_client: AsyncOpenViking):
        await uninitialized_client.initialize()
        assert uninitialized_client._service is not None
        await uninitialized_client.close()

    async def test_add_resource(self, client: AsyncOpenViking, sample_markdown_file):
        result = await client.add_resource(
            path=str(sample_markdown_file),
            reason="test document"
        )
        assert "root_uri" in result
        assert result["root_uri"].startswith("viking://")
```

常用 fixture 定义在 `tests/conftest.py` 中,包括 `client`(已初始化的 `AsyncOpenViking`)、`uninitialized_client`、`temp_dir`、`sample_markdown_file` 等。

---

## 贡献流程

### 1. 创建分支

```bash
git checkout main
git pull origin main
git checkout -b feature/your-feature-name
```

分支命名规范:
- `feature/xxx` - 新功能
- `fix/xxx` - Bug 修复
- `docs/xxx` - 文档更新
- `refactor/xxx` - 代码重构

### 2. 修改代码

- 遵循代码风格指南
- 为新功能添加测试
- 根据需要更新文档

### 3. 提交更改

```bash
git add .
git commit -m "feat: add new parser for xlsx files"
```

### 4. 推送并创建 PR

```bash
git push origin feature/your-feature-name
```

然后在 GitHub 上创建一个 Pull Request。

---

## 提交规范

我们遵循 [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <subject>

<body>

<footer>
```

### 类型

| 类型 | 描述 |
|------|-------------|
| `feat` | 新功能 |
| `fix` | Bug 修复 |
| `docs` | 文档 |
| `style` | 代码风格(不影响逻辑) |
| `refactor` | 代码重构 |
| `perf` | 性能优化 |
| `test` | 测试 |
| `chore` | 构建/工具 |

### 示例

```bash
# 新功能
git commit -m "feat(parser): add support for xlsx files"

# Bug 修复
git commit -m "fix(retrieval): fix score calculation in rerank"

# 文档
git commit -m "docs: update quick start guide"

# 重构
git commit -m "refactor(storage): simplify interface methods"
```

---

## Pull Request 指南

### PR 标题

使用与提交消息相同的格式。

### PR 描述模板

```markdown
## Summary

简要描述更改及其目的。

## Type of Change

- [ ] New feature (feat)
- [ ] Bug fix (fix)
- [ ] Documentation (docs)
- [ ] Refactoring (refactor)
- [ ] Other

## Testing

描述如何测试这些更改:
- [ ] Unit tests pass
- [ ] Manual testing completed

## Related Issues

- Fixes #123
- Related to #456

## Checklist

- [ ] Code follows project style guidelines
- [ ] Tests added for new functionality
- [ ] Documentation updated (if needed)
- [ ] All tests pass
```

---

## CI/CD 工作流

我们使用 **GitHub Actions** 进行持续集成和持续部署。我们的工作流设计为模块化和分层的。

### 1. 自动工作流

| 事件 | 工作流 | 描述 |
|-------|----------|-------------|
| **Pull Request** | `pr.yml` | 运行 **Lint** (Ruff, Mypy) 和 **Test Lite** (Linux + Python 3.10 上的集成测试)。为贡献者提供快速反馈。(显示为 **01. Pull Request Checks**) |
| **Push to Main** | `ci.yml` | 运行 **Test Full** (所有操作系统:Linux/Win/Mac,所有 Py版本:3.10-3.14) 和 **CodeQL** (安全扫描)。确保主分支稳定性。(显示为 **02. Main Branch Checks**) |
| **Release Published** | `release.yml` | 当您在 GitHub 上创建 Release 时触发。自动构建源码包和 wheel 包,基于 Git Tag 确定版本号,并发布到 **PyPI**。(显示为 **03. Release**) |
| **Weekly Cron** | `schedule.yml` | 每周日运行 **CodeQL** 安全扫描。(显示为 **04. Weekly Security Scan**) |

仓库中另外还有用于 PR review 自动化、Docker 镜像构建和 Rust CLI 打包的工作流。

### 2. 手动触发工作流

维护者可以从 "Actions" 选项卡手动触发以下工作流,以执行特定任务或调试问题。

#### A. 代码检查 (`11. _Lint Checks`)
运行代码风格检查 (Ruff) 和类型检查 (Mypy) 。无需参数。

> **提示**:建议在本地安装 [pre-commit](https://pre-commit.com/) 以在提交前自动运行这些检查(详见上文[自动检查](#自动检查推荐)章节)。

#### B. 简易测试 (`12. _Test Suite (Lite)`)
运行快速集成测试,支持自定义矩阵配置。

*   **Inputs**:
    *   `os_json`: 操作系统列表的 JSON 字符串数组 (例如 `["ubuntu-24.04"]`)。
    *   `python_json`: Python 版本列表的 JSON 字符串数组 (例如 `["3.10"]`)。

#### C. 完整测试 (`13. _Test Suite (Full)`)
在所有支持的平台 (Linux/Mac/Win) 和 Python 版本 (3.10-3.14) 上运行完整的测试套件。手动触发时支持自定义矩阵配置。

*   **Inputs**:
    *   `os_json`: 操作系统列表 (默认: `["ubuntu-24.04", "macos-14", "windows-latest"]`)。
    *   `python_json`: Python 版本列表 (默认: `["3.10", "3.11", "3.12", "3.13", "3.14"]`)。

#### D. 安全扫描 (`14. _CodeQL Scan`)
运行 CodeQL 安全分析。无需参数。

#### E. 构建发行版 (`15. _Build Distribution`)
仅构建 Python wheel 包,不发布。

*   **Inputs**:
    *   `os_json`: 操作系统列表 (默认: `["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]`)。
    *   `python_json`: Python 版本列表 (默认: `["3.10", "3.11", "3.12", "3.13", "3.14"]`)。
    *   `build_sdist`: 是否构建源码包 (默认: `true`)。
    *   `build_wheels`: 是否构建 Wheel 包 (默认: `true`)。

#### F. 发布发行版 (`16. _Publish Distribution`)
将已构建的包(需要提供构建运行 ID)发布到 PyPI。

*   **Inputs**:
    *   `target`: 选择发布目标 (`testpypi`, `pypi`, `both`)。
    *   `build_run_id`: 构建 Workflow 的 Run ID (必需,从构建运行的 URL 中获取)。

#### G. 手动发布 (`03. Release`)
一站式构建并发布(包含构建和发布步骤)。

> **版本号与 Tag 规范**:
> 本项目使用 `setuptools_scm` 自动从 Git Tag 提取版本号。
> *   **Tag 命名规范**:必须遵循 `vX.Y.Z` 格式(例如 `v0.1.0`, `v1.2.3`)。Tag 必须是符合语义化版本规范的。
> *   **Release 构建**:当触发 Release 事件时,版本号直接对应 Git Tag(例如 `v0.1.0` -> `0.1.0`)。
> *   **手动构建/非 Tag 构建**:版本号会包含距离上一个 Tag 的提交次数(例如 `0.1.1.dev3`)。
> *   **确认版本号**:发布任务完成后,您可以在 Workflow 运行详情页的 **Summary** 页面顶部(**Notifications** 区域)直接看到发布的版本号(例如 `Successfully published to PyPI with version: 0.1.8`)。您也可以在日志或 **Artifacts** 产物文件名中确认。

*   **Inputs**:
    *   `target`: 选择发布目标。
        *   `none`: 仅构建工件(不发布)。用于验证构建能力。
        *   `testpypi`: 发布到 TestPyPI。用于 Beta 测试。
        *   `pypi`: 发布到官方 PyPI。
        *   `both`: 发布到两者。
    *   `os_json`: 构建平台 (默认包含所有)。
    *   `python_json`: Python 版本 (默认包含所有)。
    *   `build_sdist`: 是否构建源码包 (默认: `true`)。
    *   `build_wheels`: 是否构建 Wheel 包 (默认: `true`)。

> **发布注意事项**:
> *   **测试优先**:强烈建议在发布到正式 PyPI 之前,先发布到 **TestPyPI** 进行验证。请注意,PyPI 和 TestPyPI 是两个完全独立的环境,账号和包数据互不相通。
> *   **版本不可覆盖**:PyPI 和 TestPyPI 均**不允许覆盖**已发布的同名同版本包。如果您需要重新发布,必须升级版本号(例如打一个新的 Tag 或产生新的 dev 版本)。如果尝试发布已存在的版本,工作流将会失败。

---

## Issue 指南

### Bug 报告

请提供:

1. **环境**
   - Python 版本
   - OpenViking 版本
   - 操作系统

2. **复现步骤**
   - 详细步骤
   - 代码片段

3. **预期与实际行为**

4. **错误日志**(如果有)

### 功能请求

请描述:

1. **问题**:您试图解决什么问题?
2. **解决方案**:您建议什么解决方案?
3. **替代方案**:您是否考虑过其他方法?

---

## 文档

文档采用 Markdown 格式,位于 `docs/` 目录下:

- `docs/en/` - 英文文档
- `docs/zh/` - 中文文档

### 文档指南

1. 代码示例必须可运行
2. 保持文档与代码同步
3. 使用清晰、简洁的语言

---

## 行为准则

参与本项目即表示您同意:

1. **尊重**:保持友好和专业的态度
2. **包容**:欢迎来自不同背景的贡献者
3. **建设性**:提供有帮助的反馈
4. **专注**:保持讨论集中在技术层面

---

## 获取帮助

如果您有问题:

- [GitHub Issues](https://github.com/volcengine/openviking/issues)
- [Discussions](https://github.com/volcengine/openviking/discussions)

---

感谢您的贡献!


================================================
FILE: CONTRIBUTING_JA.md
================================================
# コントリビューションガイド

OpenVikingに興味をお持ちいただきありがとうございます!あらゆる種類のコントリビューションを歓迎します:

- バグレポート
- 機能リクエスト
- ドキュメントの改善
- コードのコントリビューション

---

## 開発環境のセットアップ

### 前提条件

- **Python**: 3.10以上
- **Go**: 1.22以上(AGFSコンポーネントのソースビルドに必要)
- **Rust**: 1.88以上(ソースビルド時に同梱の `ov` CLI もビルドされるため必須)
- **C++コンパイラ**: GCC 9以上 または Clang 11以上(コア拡張のビルドに必要、C++17サポートが必須)
- **CMake**: 3.12以上

#### プラットフォーム別のネイティブビルドツール

- **Linux**: `build-essential` の導入を推奨。環境によっては `pkg-config` も必要です
- **macOS**: Xcode Command Line Tools をインストール(`xcode-select --install`)
- **Windows**: ローカルのネイティブビルドには CMake と MinGW を推奨

#### サポートされているプラットフォーム(プリコンパイル済みWheel)

OpenVikingは以下の環境向けにプリコンパイル済み**Wheel**パッケージを提供しています:

- **Windows**: x86_64
- **macOS**: x86_64、arm64(Apple Silicon)
- **Linux**: x86_64、arm64(manylinux)

その他のプラットフォーム(例:FreeBSD)では、`pip`によるインストール時にソースから自動コンパイルされます。[前提条件](#前提条件)がインストールされていることを確認してください。

### 1. フォークとクローン

```bash
git clone https://github.com/YOUR_USERNAME/openviking.git
cd openviking
```

### 2. 依存関係のインストール

Python環境管理には`uv`の使用を推奨します:

```bash
# uvのインストール(未インストールの場合)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 依存関係の同期と仮想環境の作成
uv sync --all-extras
source .venv/bin/activate  # Linux/macOS
# または .venv\Scripts\activate  # Windows
```

#### ローカル開発とネイティブコンポーネントの再ビルド

OpenVikingはAGFSに対してデフォルトで`binding-client`モードを使用し、事前にビルドされたネイティブ成果物を利用します。**AGFS(Go)**コード、同梱の**Rust CLI**、または**C++拡張**を変更した場合や、プリビルド成果物が見つからない場合は、再コンパイルと再インストールが必要です。プロジェクトルートで以下のコマンドを実行してください:

```bash
uv pip install -e . --force-reinstall
```

このコマンドにより`setup.py`が再実行され、AGFS、同梱 `ov` CLI、C++コンポーネントの再ビルドがトリガーされます。

### 3. 環境設定

設定ファイル `~/.openviking/ov.conf` を作成します:

```json
{
  "embedding": {
    "dense": {
      "provider": "volcengine",
      "api_key": "your-api-key",
      "model": "doubao-embedding-vision-250615",
      "api_base": "https://ark.cn-beijing.volces.com/api/v3",
      "dimension": 1024,
      "input": "multimodal"
    }
  },
  "vlm": {
    "api_key": "your-api-key",
    "model": "doubao-seed-2-0-pro-260215",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

環境変数を設定します:

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf
```

### 4. インストールの確認

```python
import asyncio
import openviking as ov

async def main():
    client = ov.AsyncOpenViking(path="./test_data")
    await client.initialize()
    print("OpenViking initialized successfully!")
    await client.close()

asyncio.run(main())
```

### 5. Rust CLIのビルド(オプション)

Rust CLI(`ov`)は、OpenViking Serverとやり取りするための高性能コマンドラインクライアントを提供します。

`ov` を直接使わない場合でも、OpenViking をソースからビルドするなら Rust ツールチェーンは必要です。パッケージング時に同梱 CLI バイナリも一緒にビルドされるためです。

**前提条件**: Rust >= 1.88

```bash
# ソースからビルドしてインストール
cargo install --path crates/ov_cli

# またはクイックインストールスクリプトを使用(プリビルドバイナリをダウンロード)
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

インストール後、`ov --help`を実行して利用可能なすべてのコマンドを確認できます。CLI接続設定は`~/.openviking/ovcli.conf`に記述します。

---

## プロジェクト構成

```
openviking/
├── pyproject.toml        # プロジェクト設定
├── Cargo.toml            # Rustワークスペース設定
├── third_party/          # サードパーティ依存関係
│   └── agfs/             # AGFSファイルシステム
│
├── openviking/           # Python SDK
│   ├── async_client.py   # AsyncOpenVikingクライアント
│   ├── sync_client.py    # SyncOpenVikingクライアント
│   ├── client/           # ローカル / HTTP クライアント実装
│   ├── console/          # スタンドアロン console UI とプロキシサービス
│   ├── core/             # コアデータモデルとディレクトリ抽象
│   ├── message/          # セッションメッセージと part モデル
│   ├── models/           # Embedding / VLM バックエンド
│   ├── parse/            # リソースパーサーと検出器
│   ├── resource/         # リソース処理と watch 管理
│   ├── retrieve/         # 検索システム
│   ├── server/           # HTTPサーバー
│   ├── service/          # 共通 service レイヤー
│   ├── session/          # セッション管理と圧縮
│   ├── storage/          # ストレージレイヤー
│   ├── telemetry/        # オペレーション telemetry
│   ├── trace/            # trace とランタイム追跡補助
│   ├── utils/            # ユーティリティと設定補助
│   └── prompts/          # プロンプトテンプレート
│
├── crates/               # Rustコンポーネント
│   └── ov_cli/           # Rust CLIクライアント
│       ├── src/          # CLIソースコード
│       └── install.sh    # クイックインストールスクリプト
│
├── src/                  # C++拡張(pybind11)
│
├── tests/                # テストスイート
│   ├── client/           # クライアントテスト
│   ├── console/          # Console テスト
│   ├── core/             # コアロジックテスト
│   ├── parse/            # パーサーテスト
│   ├── resource/         # リソース処理テスト
│   ├── retrieve/         # 検索テスト
│   ├── server/           # サーバーテスト
│   ├── service/          # Service レイヤーテスト
│   ├── session/          # セッションテスト
│   ├── storage/          # ストレージテスト
│   ├── telemetry/        # Telemetry テスト
│   ├── vectordb/         # ベクトルデータベーステスト
│   └── integration/      # E2E テスト
│
└── docs/                 # ドキュメント
    ├── en/               # 英語ドキュメント
    └── zh/               # 中国語ドキュメント
```

---

## コードスタイル

コードの一貫性を維持するために以下のツールを使用しています:

| ツール | 目的 | 設定 |
|------|---------|--------|
| **Ruff** | リンティング、フォーマット、インポートソート | `pyproject.toml` |
| **mypy** | 型チェック | `pyproject.toml` |

### 自動チェック(推奨)

[pre-commit](https://pre-commit.com/)を使用して、コミット前にこれらのチェックを自動実行します。これにより、手動の作業なしでコードが常に基準を満たすことが保証されます。

1. **pre-commitのインストール**:
   ```bash
   pip install pre-commit
   ```

2. **gitフックのインストール**:
   ```bash
   pre-commit install
   ```

これで、`git commit`実行時に`ruff`(チェックとフォーマット)が自動的に実行されます。チェックが失敗した場合、ファイルが自動修正されることがあります。変更をaddして再度コミットするだけです。

### チェックの実行

```bash
# コードのフォーマット
ruff format openviking/

# リント
ruff check openviking/

# 型チェック
mypy openviking/
```

### スタイルガイドライン

1. **行幅**: 100文字
2. **インデント**: スペース4つ
3. **文字列**: ダブルクォートを推奨
4. **型ヒント**: 推奨(必須ではない)
5. **Docstring**: パブリックAPIには必須(最大1〜2行)

---

## テスト

### テストの実行

```bash
# 全テストの実行
pytest

# 特定のテストモジュールの実行
pytest tests/client/ -v
pytest tests/server/ -v
pytest tests/parse/ -v

# 特定のテストファイルの実行
pytest tests/client/test_lifecycle.py

# 特定のテストの実行
pytest tests/client/test_lifecycle.py::TestClientInitialization::test_initialize_success

# キーワードで実行
pytest -k "search" -v

# カバレッジ付きで実行
pytest --cov=openviking --cov-report=term-missing
```

### テストの書き方

テストは`tests/`配下のサブディレクトリに整理されています。プロジェクトは`asyncio_mode = "auto"`を使用しているため、非同期テストに`@pytest.mark.asyncio`デコレーターは**不要**です:

```python
# tests/client/test_example.py
from openviking import AsyncOpenViking


class TestAsyncOpenViking:
    async def test_initialize(self, uninitialized_client: AsyncOpenViking):
        await uninitialized_client.initialize()
        assert uninitialized_client._service is not None
        await uninitialized_client.close()

    async def test_add_resource(self, client: AsyncOpenViking, sample_markdown_file):
        result = await client.add_resource(
            path=str(sample_markdown_file),
            reason="test document"
        )
        assert "root_uri" in result
        assert result["root_uri"].startswith("viking://")
```

共通フィクスチャは`tests/conftest.py`に定義されており、`client`(初期化済み`AsyncOpenViking`)、`uninitialized_client`、`temp_dir`、`sample_markdown_file` などが含まれます。

---

## コントリビューションワークフロー

### 1. ブランチの作成

```bash
git checkout main
git pull origin main
git checkout -b feature/your-feature-name
```

ブランチ命名規則:
- `feature/xxx` - 新機能
- `fix/xxx` - バグ修正
- `docs/xxx` - ドキュメント更新
- `refactor/xxx` - コードリファクタリング

### 2. 変更の実施

- コードスタイルガイドラインに従う
- 新機能にはテストを追加する
- 必要に応じてドキュメントを更新する

### 3. 変更のコミット

```bash
git add .
git commit -m "feat: add new parser for xlsx files"
```

### 4. プッシュとPRの作成

```bash
git push origin feature/your-feature-name
```

その後、GitHubでプルリクエストを作成します。

---

## コミット規約

[Conventional Commits](https://www.conventionalcommits.org/)に従います:

```
<type>(<scope>): <subject>

<body>

<footer>
```

### タイプ

| タイプ | 説明 |
|------|-------------|
| `feat` | 新機能 |
| `fix` | バグ修正 |
| `docs` | ドキュメント |
| `style` | コードスタイル(ロジック変更なし) |
| `refactor` | コードリファクタリング |
| `perf` | パフォーマンス改善 |
| `test` | テスト |
| `chore` | ビルド/ツーリング |

### 例

```bash
# 新機能
git commit -m "feat(parser): add support for xlsx files"

# バグ修正
git commit -m "fix(retrieval): fix score calculation in rerank"

# ドキュメント
git commit -m "docs: update quick start guide"

# リファクタリング
git commit -m "refactor(storage): simplify interface methods"
```

---

## プルリクエストガイドライン

### PRタイトル

コミットメッセージと同じフォーマットを使用します。

### PR説明テンプレート

```markdown
## 概要

変更内容とその目的の簡単な説明。

## 変更の種類

- [ ] 新機能(feat)
- [ ] バグ修正(fix)
- [ ] ドキュメント(docs)
- [ ] リファクタリング(refactor)
- [ ] その他

## テスト

これらの変更のテスト方法を記述してください:
- [ ] ユニットテストが通過する
- [ ] 手動テストが完了している

## 関連Issue

- Fixes #123
- Related to #456

## チェックリスト

- [ ] コードがプロジェクトのスタイルガイドラインに従っている
- [ ] 新機能にテストが追加されている
- [ ] ドキュメントが更新されている(必要な場合)
- [ ] すべてのテストが通過する
```

---

## CI/CDワークフロー

継続的インテグレーションとデプロイメントに**GitHub Actions**を使用しています。ワークフローはモジュール化され、段階的に設計されています。

### 1. 自動ワークフロー

| イベント | ワークフロー | 説明 |
|-------|----------|-------------|
| **プルリクエスト** | `pr.yml` | **Lint**(Ruff、Mypy)と**Test Lite**(Linux + Python 3.10での統合テスト)を実行。コントリビューターに迅速なフィードバックを提供。(**01. Pull Request Checks**として表示) |
| **mainへのプッシュ** | `ci.yml` | **Test Full**(全OS:Linux/Win/Mac、全Pyバージョン:3.10-3.14)と**CodeQL**(セキュリティスキャン)を実行。mainブランチの安定性を保証。(**02. Main Branch Checks**として表示) |
| **リリース公開** | `release.yml` | GitHubでリリースを作成すると発動。自動的にソースディストリビューションとwheelをビルドし、Gitタグからバージョンを判定して**PyPI**に公開。(**03. Release**として表示) |
| **週次Cron** | `schedule.yml` | 毎週日曜日に**CodeQL**セキュリティスキャンを実行。(**04. Weekly Security Scan**として表示) |

このほか、PR review の自動化、Docker イメージのビルド、Rust CLI のパッケージング用ワークフローも用意されています。

### 2. 手動トリガーワークフロー

メンテナーは「Actions」タブから以下のワークフローを手動でトリガーして、特定のタスクを実行したり問題をデバッグしたりできます。

#### A. Lintチェック (`11. _Lint Checks`)
コードスタイルチェック(Ruff)と型チェック(Mypy)を実行。引数は不要です。

> **ヒント**: コミット前にこれらのチェックを自動的に実行するため、ローカルに[pre-commit](https://pre-commit.com/)をインストールすることを推奨します(上記の[自動チェック](#自動チェック推奨)セクションを参照)。

#### B. テストスイート(Lite)(`12. _Test Suite (Lite)`)
高速統合テストを実行し、カスタムマトリックス設定をサポートします。

*   **入力**:
    *   `os_json`: 実行するOSのJSON文字列配列(例:`["ubuntu-24.04"]`)。
    *   `python_json`: Pythonバージョンの JSON文字列配列(例:`["3.10"]`)。

#### C. テストスイート(Full)(`13. _Test Suite (Full)`)
サポートされているすべてのプラットフォーム(Linux/Mac/Win)とPythonバージョン(3.10-3.14)で完全なテストスイートを実行。手動トリガー時にカスタムマトリックス設定をサポートします。

*   **入力**:
    *   `os_json`: 実行するOSのリスト(デフォルト:`["ubuntu-24.04", "macos-14", "windows-latest"]`)。
    *   `python_json`: Pythonバージョンのリスト(デフォルト:`["3.10", "3.11", "3.12", "3.13", "3.14"]`)。

#### D. セキュリティスキャン (`14. _CodeQL Scan`)
CodeQLセキュリティ分析を実行。引数は不要です。

#### E. ディストリビューションビルド (`15. _Build Distribution`)
Pythonのwheelパッケージのみをビルドし、公開はしません。

*   **入力**:
    *   `os_json`: ビルドするOSのリスト(デフォルト:`["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "macos-15-intel", "windows-latest"]`)。
    *   `python_json`: Pythonバージョンのリスト(デフォルト:`["3.10", "3.11", "3.12", "3.13", "3.14"]`)。
    *   `build_sdist`: ソースディストリビューションをビルドするか(デフォルト:`true`)。
    *   `build_wheels`: wheelディストリビューションをビルドするか(デフォルト:`true`)。

#### F. ディストリビューション公開 (`16. _Publish Distribution`)
ビルド済みパッケージをPyPIに公開(ビルドRun IDが必要)。

*   **入力**:
    *   `target`: 公開先を選択(`testpypi`、`pypi`、`both`)。
    *   `build_run_id`: ビルドワークフローのRun ID(必須、ビルド実行URLから取得)。

#### G. 手動リリース (`03. Release`)
ワンストップのビルドと公開(ビルドと公開ステップを含む)。

> **バージョン番号とタグ規約**:
> このプロジェクトは`setuptools_scm`を使用してGitタグからバージョン番号を自動抽出します。
> *   **タグ命名規約**: `vX.Y.Z`形式に従う必要があります(例:`v0.1.0`、`v1.2.3`)。タグはセマンティックバージョニングに準拠する必要があります。
> *   **リリースビルド**: リリースイベントがトリガーされると、バージョン番号はGitタグに直接対応します(例:`v0.1.0` -> `0.1.0`)。
> *   **手動/非タグビルド**: バージョン番号には最後のタグからのコミット数が含まれます(例:`0.1.1.dev3`)。
> *   **バージョン確認**: 公開ジョブ完了後、ワークフロー**Summary**ページ上部の**Notifications**エリアで公開バージョンを直接確認できます(例:`Successfully published to PyPI with version: 0.1.8`)。ログまたは**Artifacts**のファイル名でも確認できます。

*   **入力**:
    *   `target`: 公開先を選択。
        *   `none`: アーティファクトのビルドのみ(公開なし)。ビルド機能の検証に使用。
        *   `testpypi`: TestPyPIに公開。ベータテストに使用。
        *   `pypi`: 公式PyPIに公開。
        *   `both`: 両方に公開。
    *   `os_json`: ビルドプラットフォーム(デフォルトはすべて含む)。
    *   `python_json`: Pythonバージョン(デフォルトはすべて含む)。
    *   `build_sdist`: ソースディストリビューションをビルドするか(デフォルト:`true`)。
    *   `build_wheels`: wheelディストリビューションをビルドするか(デフォルト:`true`)。

> **公開に関する注意事項**:
> *   **先にテスト**: 公式PyPIに公開する前に、**TestPyPI**で検証することを強く推奨します。PyPIとTestPyPIは完全に独立した環境であり、アカウントやパッケージデータは共有されません。
> *   **上書き不可**: PyPIもTestPyPIも、同じ名前とバージョンの既存パッケージの上書きを許可しません。再公開が必要な場合は、バージョン番号をアップグレードする必要があります(例:新しいバージョンをタグ付けするか、新しいdevバージョンを生成)。既存のバージョンを公開しようとすると、ワークフローが失敗します。

---

## Issueガイドライン

### バグレポート

以下を提供してください:

1. **環境**
   - Pythonバージョン
   - OpenVikingバージョン
   - オペレーティングシステム

2. **再現手順**
   - 詳細な手順
   - コードスニペット

3. **期待される動作と実際の動作**

4. **エラーログ**(ある場合)

### 機能リクエスト

以下を記述してください:

1. **問題**: どのような問題を解決しようとしていますか?
2. **解決策**: どのような解決策を提案しますか?
3. **代替案**: 他のアプローチを検討しましたか?

---

## ドキュメント

ドキュメントは`docs/`配下にMarkdown形式で管理されています:

- `docs/en/` - 英語ドキュメント
- `docs/zh/` - 中国語ドキュメント

### ドキュメントガイドライン

1. コード例は実行可能であること
2. ドキュメントとコードの同期を維持すること
3. 明確で簡潔な言葉を使用すること

---

## 行動規範

このプロジェクトに参加することで、以下に同意するものとします:

1. **敬意を持つ**: 友好的でプロフェッショナルな態度を維持する
2. **包括的である**: あらゆるバックグラウンドのコントリビューターを歓迎する
3. **建設的である**: 有益なフィードバックを提供する
4. **集中する**: 議論を技術的な内容に保つ

---

## ヘルプ

質問がある場合:

- [GitHub Issues](https://github.com/volcengine/openviking/issues)
- [Discussions](https://github.com/volcengine/openviking/discussions)

---

コントリビューションありがとうございます!


================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["crates/ov_cli"]
resolver = "2"

[profile.release]
opt-level = 3
lto = true
strip = true


================================================
FILE: Dockerfile
================================================
# syntax=docker/dockerfile:1.9

# Stage 1: provide Go toolchain (required by setup.py -> build_agfs_artifacts -> make build)
FROM golang:1.26-trixie AS go-toolchain

# Stage 2: provide Rust toolchain (required by setup.py -> build_ov_cli_artifact -> cargo build)
FROM rust:1.88-trixie AS rust-toolchain

# Stage 3: build Python environment with uv (builds AGFS + Rust CLI + C++ extension from source)
FROM ghcr.io/astral-sh/uv:python3.13-trixie-slim AS py-builder

# Reuse Go toolchain from stage 1 so setup.py can compile agfs-server in-place.
COPY --from=go-toolchain /usr/local/go /usr/local/go
# Reuse Rust toolchain from stage 2 so setup.py can compile ov CLI in-place.
COPY --from=rust-toolchain /usr/local/cargo /usr/local/cargo
COPY --from=rust-toolchain /usr/local/rustup /usr/local/rustup
ENV CARGO_HOME=/usr/local/cargo
ENV RUSTUP_HOME=/usr/local/rustup
ENV PATH="/usr/local/cargo/bin:/usr/local/go/bin:${PATH}"
ARG OPENVIKING_VERSION=0.0.0
ARG TARGETPLATFORM
ENV SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OPENVIKING=${OPENVIKING_VERSION}

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    cmake \
    git \
 && rm -rf /var/lib/apt/lists/*

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_NO_DEV=1
WORKDIR /app

# Copy source required for setup.py artifact builds and native extension build.
COPY Cargo.toml Cargo.lock ./
COPY pyproject.toml uv.lock setup.py README.md ./
COPY build_support/ build_support/
COPY crates/ crates/
COPY openviking/ openviking/
COPY openviking_cli/ openviking_cli/
COPY src/ src/
COPY third_party/ third_party/

# Install project and dependencies (triggers setup.py artifact builds + build_extension).
RUN --mount=type=cache,target=/root/.cache/uv,id=uv-${TARGETPLATFORM} \
    uv sync --no-editable

# Stage 4: runtime
FROM python:3.13-slim-trixie

RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    libstdc++6 \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY --from=py-builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
ENV OPENVIKING_CONFIG_FILE="/app/ov.conf"

EXPOSE 1933

HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
    CMD curl -fsS http://127.0.0.1:1933/health || exit 1

# Default runs server; override command to run CLI, e.g.:
# docker run --rm <image> -v "$HOME/.openviking/ovcli.conf:/root/.openviking/ovcli.conf" openviking --help
CMD ["openviking-server"]


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: MANIFEST.in
================================================
graft src
graft third_party/leveldb-1.23
graft third_party/spdlog-1.14.1
graft third_party/croaring
graft third_party/rapidjson
recursive-include third_party/agfs/agfs-server *.go go.mod go.sum Makefile
recursive-include third_party/agfs/agfs-sdk/go *.go go.mod
include third_party/agfs/bin/agfs-server
include LICENSE
include README.md
include pyproject.toml
include setup.py
recursive-include openviking *.yaml

# sdist should be source-only: never ship runtime binaries from working tree
prune openviking/bin
prune openviking/lib
recursive-exclude openviking *.so *.dylib *.dll *.exe
global-exclude *.py[cod]
global-exclude __pycache__
global-exclude .git*
global-exclude .DS_Store
prune src/build


================================================
FILE: Makefile
================================================
# Makefile for OpenViking

# Variables
PYTHON ?= python3
SETUP_PY := setup.py
AGFS_SERVER_DIR := third_party/agfs/agfs-server
OV_CLI_DIR := crates/ov_cli

# Dependency Versions
MIN_PYTHON_VERSION := 3.10
MIN_GO_VERSION := 1.22
MIN_CMAKE_VERSION := 3.12
MIN_RUST_VERSION := 1.88
MIN_GCC_VERSION := 9
MIN_CLANG_VERSION := 11

# Output directories to clean
CLEAN_DIRS := \
	build/ \
	dist/ \
	*.egg-info/ \
	openviking/bin/ \
	openviking/lib/ \
	$(AGFS_SERVER_DIR)/build/ \
	$(OV_CLI_DIR)/target/ \
	src/cmake_build/ \
	.pytest_cache/ \
	.coverage \
	htmlcov/ \
	**/__pycache__/

.PHONY: all build clean help check-pip check-deps

all: build

help:
	@echo "Available targets:"
	@echo "  build       - Build AGFS, ov CLI, and C++ extensions using setup.py"
	@echo "  clean       - Remove build artifacts and temporary files"
	@echo "  check-deps  - Check if required dependencies (Go, Rust, CMake, etc.) are installed"
	@echo "  help        - Show this help message"

check-pip:
	@if command -v uv > /dev/null 2>&1 && uv pip --help > /dev/null 2>&1; then \
		echo "  [OK] uv pip found"; \
	elif $(PYTHON) -m pip --version > /dev/null 2>&1; then \
		echo "  [OK] pip found"; \
	else \
		echo "Error: Neither uv pip nor pip found for $(PYTHON)."; \
		echo "Try fixing your environment by running:"; \
		echo "  uv sync          # if using uv"; \
		echo "  or"; \
		echo "  $(PYTHON) -m ensurepip --upgrade"; \
		exit 1; \
	fi

check-deps:
	@echo "Checking dependencies..."
	@# Python check
	@$(PYTHON) -c "import sys; v=sys.version_info; exit(0 if v.major > 3 or (v.major == 3 and v.minor >= 10) else 1)" || (echo "Error: Python >= $(MIN_PYTHON_VERSION) is required."; exit 1)
	@echo "  [OK] Python $$( $(PYTHON) -V | cut -d' ' -f2 )"
	@# Go check
	@command -v go > /dev/null 2>&1 || (echo "Error: Go is not installed."; exit 1)
	@GO_VER=$$(go version | awk '{print $$3}' | sed 's/go//'); \
	$(PYTHON) -c "v='$$GO_VER'.split('.'); exit(0 if int(v[0]) > 1 or (int(v[0]) == 1 and int(v[1]) >= 22) else 1)" || (echo "Error: Go >= $(MIN_GO_VERSION) is required. Found $$GO_VER"; exit 1); \
	echo "  [OK] Go $$GO_VER"
	@# CMake check
	@command -v cmake > /dev/null 2>&1 || (echo "Error: CMake is not installed."; exit 1)
	@CMAKE_VER=$$(cmake --version | head -n1 | awk '{print $$3}'); \
	$(PYTHON) -c "v='$$CMAKE_VER'.split('.'); exit(0 if int(v[0]) > 3 or (int(v[0]) == 3 and int(v[1]) >= 12) else 1)" || (echo "Error: CMake >= $(MIN_CMAKE_VERSION) is required. Found $$CMAKE_VER"; exit 1); \
	echo "  [OK] CMake $$CMAKE_VER"
	@# Rust check
	@command -v rustc > /dev/null 2>&1 || (echo "Error: Rust is not installed."; exit 1)
	@RUST_VER=$$(rustc --version | awk '{print $$2}'); \
	$(PYTHON) -c "v='$$RUST_VER'.split('.'); exit(0 if int(v[0]) > 1 or (int(v[0]) == 1 and int(v[1]) >= 88) else 1)" || (echo "Error: Rust >= $(MIN_RUST_VERSION) is required. Found $$RUST_VER"; exit 1); \
	echo "  [OK] Rust $$RUST_VER"
	@# C++ Compiler check
	@if command -v clang++ > /dev/null 2>&1; then \
		CLANG_VER_FULL=$$(clang++ --version | head -n1 | grep -oE "[0-9]+\.[0-9]+\.[0-9]+" | head -n1); \
		CLANG_VER=$$(echo $$CLANG_VER_FULL | cut -d. -f1); \
		if [ $$CLANG_VER -lt $(MIN_CLANG_VERSION) ]; then echo "Error: Clang >= $(MIN_CLANG_VERSION) is required. Found $$CLANG_VER_FULL"; exit 1; fi; \
		echo "  [OK] Clang $$CLANG_VER_FULL"; \
	elif command -v g++ > /dev/null 2>&1; then \
		GCC_VER_FULL=$$(g++ -dumpversion); \
		GCC_VER=$$(echo $$GCC_VER_FULL | cut -d. -f1); \
		if [ $$GCC_VER -lt $(MIN_GCC_VERSION) ]; then echo "Error: GCC >= $(MIN_GCC_VERSION) is required. Found $$GCC_VER_FULL"; exit 1; fi; \
		echo "  [OK] GCC $$GCC_VER_FULL"; \
	else \
		echo "Error: C++ compiler (GCC or Clang) is required."; exit 1; \
	fi

build: check-deps check-pip
	@echo "Starting build process via setup.py..."
	$(PYTHON) $(SETUP_PY) build_ext --inplace
	@if command -v uv > /dev/null 2>&1 && uv pip --help > /dev/null 2>&1; then \
		echo "  [OK] uv pip found, use uv pip to install..."; \
		uv pip install -e .; \
	else \
		echo "  [OK] pip found, use pip to install..."; \
		$(PYTHON) -m pip install -e .; \
	fi
	@echo "Build completed successfully."

clean:
	@echo "Cleaning up build artifacts..."
	@for dir in $(CLEAN_DIRS); do \
		if [ -d "$$dir" ] || [ -f "$$dir" ]; then \
			echo "Removing $$dir"; \
			rm -rf $$dir; \
		fi \
	done
	@find . -name "*.pyc" -delete
	@find . -name "__pycache__" -type d -exec rm -rf {} +
	@echo "Cleanup completed."


================================================
FILE: README.md
================================================
<div align="center">

<a href="https://openviking.ai/" target="_blank">
  <picture>
    <img alt="OpenViking" src="docs/images/ov-logo.png" width="200px" height="auto">
  </picture>
</a>

### OpenViking: The Context Database for AI Agents

English / [中文](README_CN.md) / [日本語](README_JA.md)

<a href="https://www.openviking.ai">Website</a> · <a href="https://github.com/volcengine/OpenViking">GitHub</a> · <a href="https://github.com/volcengine/OpenViking/issues">Issues</a> · <a href="https://www.openviking.ai/docs">Docs</a>

[![][release-shield]][release-link]
[![][github-stars-shield]][github-stars-link]
[![][github-issues-shield]][github-issues-shield-link]
[![][github-contributors-shield]][github-contributors-link]
[![][license-shield]][license-shield-link]
[![][last-commit-shield]][last-commit-shield-link]

👋 Join our Community

📱 <a href="./docs/en/about/01-about-us.md#lark-group">Lark Group</a> · <a href="./docs/en/about/01-about-us.md#wechat-group">WeChat</a> · <a href="https://discord.com/invite/eHvx8E9XF3">Discord</a> · <a href="https://x.com/openvikingai">X</a>

<a href="https://trendshift.io/repositories/19668" target="_blank"><img src="https://trendshift.io/api/badge/repositories/19668" alt="volcengine%2FOpenViking | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>

</div>

---

## Overview

### Challenges in Agent Development

In the AI era, data is abundant, but high-quality context is hard to come by. When building AI Agents, developers often face these challenges:

- **Fragmented Context**: Memories are in code, resources are in vector databases, and skills are scattered, making them difficult to manage uniformly.
- **Surging Context Demand**: An Agent's long-running tasks produce context at every execution. Simple truncation or compression leads to information loss.
- **Poor Retrieval Effectiveness**: Traditional RAG uses flat storage, lacking a global view and making it difficult to understand the full context of information.
- **Unobservable Context**: The implicit retrieval chain of traditional RAG is like a black box, making it hard to debug when errors occur.
- **Limited Memory Iteration**: Current memory is just a record of user interactions, lacking Agent-related task memory.

### The OpenViking Solution

**OpenViking** is an open-source **Context Database** designed specifically for AI Agents.

We aim to define a minimalist context interaction paradigm for Agents, allowing developers to completely say goodbye to the hassle of context management. OpenViking abandons the fragmented vector storage model of traditional RAG and innovatively adopts a **"file system paradigm"** to unify the structured organization of memories, resources, and skills needed by Agents.

With OpenViking, developers can build an Agent's brain just like managing local files:

- **Filesystem Management Paradigm** → **Solves Fragmentation**: Unified context management of memories, resources, and skills based on a filesystem paradigm.
- **Tiered Context Loading** → **Reduces Token Consumption**: L0/L1/L2 three-tier structure, loaded on demand, significantly saving costs.
- **Directory Recursive Retrieval** → **Improves Retrieval Effect**: Supports native filesystem retrieval methods, combining directory positioning with semantic search to achieve recursive and precise context acquisition.
- **Visualized Retrieval Trajectory** → **Observable Context**: Supports visualization of directory retrieval trajectories, allowing users to clearly observe the root cause of issues and guide retrieval logic optimization.
- **Automatic Session Management** → **Context Self-Iteration**: Automatically compresses content, resource references, tool calls, etc., in conversations, extracting long-term memory, making the Agent smarter with use.

---

## Quick Start

### Prerequisites

Before starting with OpenViking, please ensure your environment meets the following requirements:

- **Python Version**: 3.10 or higher
- **Go Version**: 1.22 or higher (Required for building AGFS components)
- **C++ Compiler**: GCC 9+ or Clang 11+ (Required for building core extensions)
- **Operating System**: Linux, macOS, Windows
- **Network Connection**: A stable network connection is required (for downloading dependencies and accessing model services)

### 1. Installation

#### Python Package

```bash
pip install openviking --upgrade --force-reinstall
```

#### Rust CLI (Optional)

```bash
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

Or build from source:

```bash
cargo install --git https://github.com/volcengine/OpenViking ov_cli
```

### 2. Model Preparation

OpenViking requires the following model capabilities:
- **VLM Model**: For image and content understanding
- **Embedding Model**: For vectorization and semantic retrieval

#### Supported VLM Providers

OpenViking supports three VLM providers:

| Provider | Description | Get API Key |
|----------|-------------|-------------|
| `volcengine` | Volcengine Doubao Models | [Volcengine Console](https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&type=new&utm_content=OpenViking&utm_medium=devrel&utm_source=OWO&utm_term=OpenViking) |
| `openai` | OpenAI Official API | [OpenAI Platform](https://platform.openai.com) |
| `litellm` | Unified access to various third-party models (Anthropic, DeepSeek, Gemini, vLLM, Ollama, etc.) | See [LiteLLM Providers](https://docs.litellm.ai/docs/providers) |

> 💡 **Tip**:
> - `litellm` supports unified access to various models. The `model` field must follow the [LiteLLM format specification](https://docs.litellm.ai/docs/providers)
> - The system auto-detects common models (e.g., `claude-*`, `deepseek-*`, `gemini-*`, `hosted_vllm/*`, `ollama/*`, etc.). For other models, use the full prefix according to LiteLLM format

#### Provider-Specific Notes

<details>
<summary><b>Volcengine (Doubao)</b></summary>

Volcengine supports both model names and endpoint IDs. Using model names is recommended for simplicity:

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "doubao-seed-2-0-pro-260215",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

You can also use endpoint IDs (found in [Volcengine ARK Console](https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&type=new&utm_content=OpenViking&utm_medium=devrel&utm_source=OWO&utm_term=OpenViking):

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "ep-20241220174930-xxxxx",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

</details>

<details>
<summary><b>OpenAI</b></summary>

Use OpenAI's official API:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://api.openai.com/v1"
  }
}
```

You can also use a custom OpenAI-compatible endpoint:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://your-custom-endpoint.com/v1"
  }
}
```

</details>

<details>
<summary><b>LiteLLM (Anthropic, DeepSeek, Gemini, Qwen, vLLM, Ollama, etc.)</b></summary>

LiteLLM provides unified access to various models. The `model` field should follow LiteLLM's naming convention. Here we use Claude and Qwen as examples:

**Anthropic:**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "claude-3-5-sonnet-20240620",
    "api_key": "your-anthropic-api-key"
  }
}
```

**Qwen (DashScope):**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "dashscope/qwen-turbo", // see https://docs.litellm.ai/docs/providers/dashscope for more details
    "api_key": "your-dashscope-api-key",
    "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1"
  }
}
```

> 💡 **Tip for Qwen**: 
> - For **China/Beijing** region, use `api_base`: `https://dashscope.aliyuncs.com/compatible-mode/v1`
> - For **International** region, use `api_base`: `https://dashscope-intl.aliyuncs.com/compatible-mode/v1`

**Common model formats:**

| Provider | Model Example | Notes |
|----------|---------------|-------|
| Anthropic | `claude-3-5-sonnet-20240620` | Auto-detected, uses `ANTHROPIC_API_KEY` |
| DeepSeek | `deepseek-chat` | Auto-detected, uses `DEEPSEEK_API_KEY` |
| Gemini | `gemini-pro` | Auto-detected, uses `GEMINI_API_KEY` |
| Qwen | `dashscope/qwen-turbo` | Set `api_base` based on region (see above) |
| OpenRouter | `openrouter/openai/gpt-4o` | Full prefix required |
| vLLM | `hosted_vllm/llama-3.1-8b` | Set `api_base` to vLLM server |
| Ollama | `ollama/llama3.1` | Set `api_base` to Ollama server |

**Local Models (vLLM / Ollama):**

```bash

# Start Ollama
ollama serve
```

```json
// Ollama
{
  "vlm": {
    "provider": "litellm",
    "model": "ollama/llama3.1",
    "api_base": "http://localhost:11434"
  }
}
```

For complete model support, see [LiteLLM Providers Documentation](https://docs.litellm.ai/docs/providers).

</details>

### 3. Environment Configuration

#### Server Configuration Template

Create a configuration file `~/.openviking/ov.conf`, remove the comments before copy:

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // Log output: "stdout" or "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "<api-endpoint>",   // API endpoint address
      "api_key"  : "<your-api-key>",   // Model service API Key
      "provider" : "<provider-type>",  // Provider type: "volcengine" or "openai" (currently supported)
      "dimension": 1024,               // Vector dimension
      "model"    : "<model-name>"      // Embedding model name (e.g., doubao-embedding-vision-250615 or text-embedding-3-large)
    },
    "max_concurrent": 10               // Max concurrent embedding requests (default: 10)
  },
  "vlm": {
    "api_base" : "<api-endpoint>",     // API endpoint address
    "api_key"  : "<your-api-key>",     // Model service API Key
    "provider" : "<provider-type>",    // Provider type (volcengine, openai, deepseek, anthropic, etc.)
    "model"    : "<model-name>",       // VLM model name (e.g., doubao-seed-2-0-pro-260215 or gpt-4-vision-preview)
    "max_concurrent": 100              // Max concurrent LLM calls for semantic processing (default: 100)
  }
}
```

> **Note**: For embedding models, currently `volcengine` (Doubao), `openai`, and `jina` providers are supported. For VLM models, we support three providers: `volcengine`, `openai`, and `litellm`. The `litellm` provider supports various models including Anthropic (Claude), DeepSeek, Gemini, Moonshot, Zhipu, DashScope, MiniMax, vLLM, Ollama, and more.

#### Server Configuration Examples

👇 Expand to see the configuration example for your model service:

<details>
<summary><b>Example 1: Using Volcengine (Doubao Models)</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // Log output: "stdout" or "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
      "api_key"  : "your-volcengine-api-key",
      "provider" : "volcengine",
      "dimension": 1024,
      "model"    : "doubao-embedding-vision-250615"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
    "api_key"  : "your-volcengine-api-key",
    "provider" : "volcengine",
    "model"    : "doubao-seed-2-0-pro-260215",
    "max_concurrent": 100
  }
}
```

</details>

<details>
<summary><b>Example 2: Using OpenAI Models</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // Log output: "stdout" or "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://api.openai.com/v1",
      "api_key"  : "your-openai-api-key",
      "provider" : "openai",
      "dimension": 3072,
      "model"    : "text-embedding-3-large"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://api.openai.com/v1",
    "api_key"  : "your-openai-api-key",
    "provider" : "openai",
    "model"    : "gpt-4-vision-preview",
    "max_concurrent": 100
  }
}
```

</details>

#### Set Server Configuration Environment Variable

After creating the configuration file, set the environment variable to point to it (Linux/macOS):

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf # by default
```

On Windows, use one of the following:

PowerShell:

```powershell
$env:OPENVIKING_CONFIG_FILE = "$HOME/.openviking/ov.conf"
```

Command Prompt (cmd.exe):

```bat
set "OPENVIKING_CONFIG_FILE=%USERPROFILE%\.openviking\ov.conf"
```

> 💡 **Tip**: You can also place the configuration file in other locations, just specify the correct path in the environment variable.

#### CLI/Client Configuration Examples

👇 Expand to see the configuration example for your CLI/Client:

Example: ovcli.conf for visiting localhost server

```json
{
  "url": "http://localhost:1933",
  "timeout": 60.0,
  "output": "table"
}
```

After creating the configuration file, set the environment variable to point to it (Linux/macOS):

```bash
export OPENVIKING_CLI_CONFIG_FILE=~/.openviking/ovcli.conf # by default
```

On Windows, use one of the following:

PowerShell:

```powershell
$env:OPENVIKING_CLI_CONFIG_FILE = "$HOME/.openviking/ovcli.conf"
```

Command Prompt (cmd.exe):

```bat
set "OPENVIKING_CLI_CONFIG_FILE=%USERPROFILE%\.openviking\ovcli.conf"
```

### 4. Run Your First Example

> 📝 **Prerequisite**: Ensure you have completed the configuration (ov.conf and ovcli.conf) in the previous step.

Now let's run a complete example to experience the core features of OpenViking.

#### Launch Server

```bash
openviking-server
```

or you can run in background

```bash
nohup openviking-server > /data/log/openviking.log 2>&1 &
```

#### Run the CLI

```bash
ov status
ov add-resource https://github.com/volcengine/OpenViking # --wait
ov ls viking://resources/
ov tree viking://resources/volcengine -L 2
# wait some time for semantic processing if not --wait
ov find "what is openviking"
ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/zh
```

Congratulations! You have successfully run OpenViking 🎉

### VikingBot Quick Start

VikingBot is an AI agent framework built on top of OpenViking. Here's how to get started:

```bash
# Option 1: Install VikingBot from PyPI (recommended for most users)
pip install "openviking[bot]"

# Option 2: Install VikingBot from source (for development)
uv pip install -e ".[bot]"

# Start OpenViking server with Bot enabled
openviking-server --with-bot

# In another terminal, start interactive chat
ov chat
```

---

## Server Deployment Details

For production environments, we recommend running OpenViking as a standalone HTTP service to provide persistent, high-performance context support for your AI Agents.

🚀 **Deploy OpenViking on Cloud**:
To ensure optimal storage performance and data security, we recommend deploying on **Volcengine Elastic Compute Service (ECS)** using the **veLinux** operating system. We have prepared a detailed step-by-step guide to get you started quickly.

👉 **[View: Server Deployment & ECS Setup Guide](./docs/en/getting-started/03-quickstart-server.md)**


## OpenClaw Context Plugin Details

* Test Dataset: Effect testing based on LoCoMo10 (https://github.com/snap-research/locomo) long-range dialogues (1,540 cases in total after removing category5 without ground truth)
* Experimental Groups: Since users may not disable OpenClaw's native memory when using OpenViking, we added experimental groups with native memory enabled or disabled
* OpenViking Version: 0.1.18
* Model: seed-2.0-code
* Evaluation Script: https://github.com/ZaynJarvis/openclaw-eval/tree/main

| Experimental Group | Task Completion Rate | Cost: Input Tokens (Total) |
|----------|------------------|------------------|
| OpenClaw(memory-core) |	35.65% |	24,611,530 |
| OpenClaw + LanceDB (-memory-core) |	44.55% |	51,574,530 |
| OpenClaw + OpenViking Plugin (-memory-core) |	52.08% |	4,264,396 |
| OpenClaw + OpenViking Plugin (+memory-core) |	51.23% |	2,099,622 |

* Experimental Conclusions:
After integrating OpenViking:
- With native memory enabled: 43% improvement over original OpenClaw with 91% reduction in input token cost; 15% improvement over LanceDB with 96% reduction in input token cost.
- With native memory disabled: 49% improvement over original OpenClaw with 83% reduction in input token cost; 17% improvement over LanceDB with 92% reduction in input token cost.

👉 **[View: OpenClaw Context Plugin](examples/openclaw-plugin/README.md)**

👉 **[View: OpenCode Memory Plugin Example](examples/opencode-memory-plugin/README.md)**

--

## Core Concepts

After running the first example, let's dive into the design philosophy of OpenViking. These five core concepts correspond one-to-one with the solutions mentioned earlier, together building a complete context management system:

### 1. Filesystem Management Paradigm → Solves Fragmentation

We no longer view context as flat text slices but unify them into an abstract virtual filesystem. Whether it's memories, resources, or capabilities, they are mapped to virtual directories under the `viking://` protocol, each with a unique URI.

This paradigm gives Agents unprecedented context manipulation capabilities, enabling them to locate, browse, and manipulate information precisely and deterministically through standard commands like `ls` and `find`, just like a developer. This transforms context management from vague semantic matching into intuitive, traceable "file operations". Learn more: [Viking URI](./docs/en/concepts/04-viking-uri.md) | [Context Types](./docs/en/concepts/02-context-types.md)

```
viking://
├── resources/              # Resources: project docs, repos, web pages, etc.
│   ├── my_project/
│   │   ├── docs/
│   │   │   ├── api/
│   │   │   └── tutorials/
│   │   └── src/
│   └── ...
├── user/                   # User: personal preferences, habits, etc.
│   └── memories/
│       ├── preferences/
│       │   ├── writing_style
│       │   └── coding_habits
│       └── ...
└── agent/                  # Agent: skills, instructions, task memories, etc.
    ├── skills/
    │   ├── search_code
    │   ├── analyze_data
    │   └── ...
    ├── memories/
    └── instructions/
```

### 2. Tiered Context Loading → Reduces Token Consumption

Stuffing massive amounts of context into a prompt all at once is not only expensive but also prone to exceeding model windows and introducing noise. OpenViking automatically processes context into three levels upon writing:
- **L0 (Abstract)**: A one-sentence summary for quick retrieval and identification.
- **L1 (Overview)**: Contains core information and usage scenarios for Agent decision-making during the planning phase.
- **L2 (Details)**: The full original data, for deep reading by the Agent when absolutely necessary.

Learn more: [Context Layers](./docs/en/concepts/03-context-layers.md)

```
viking://resources/my_project/
├── .abstract               # L0 Layer: Abstract (~100 tokens) - Quick relevance check
├── .overview               # L1 Layer: Overview (~2k tokens) - Understand structure and key points
├── docs/
│   ├── .abstract          # Each directory has corresponding L0/L1 layers
│   ├── .overview
│   ├── api/
│   │   ├── .abstract
│   │   ├── .overview
│   │   ├── auth.md        # L2 Layer: Full content - Load on demand
│   │   └── endpoints.md
│   └── ...
└── src/
    └── ...
```

### 3. Directory Recursive Retrieval → Improves Retrieval Effect

Single vector retrieval struggles with complex query intents. OpenViking has designed an innovative **Directory Recursive Retrieval Strategy** that deeply integrates multiple retrieval methods:

1. **Intent Analysis**: Generate multiple retrieval conditions through intent analysis.
2. **Initial Positioning**: Use vector retrieval to quickly locate the high-score directory where the initial slice is located.
3. **Refined Exploration**: Perform a secondary retrieval within that directory and update high-score results to the candidate set.
4. **Recursive Drill-down**: If subdirectories exist, recursively repeat the secondary retrieval steps layer by layer.
5. **Result Aggregation**: Finally, obtain the most relevant context to return.

This "lock high-score directory first, then refine content exploration" strategy not only finds the semantically best-matching fragments but also understands the full context where the information resides, thereby improving the globality and accuracy of retrieval. Learn more: [Retrieval Mechanism](./docs/en/concepts/07-retrieval.md)

### 4. Visualized Retrieval Trajectory → Observable Context

OpenViking's organization uses a hierarchical virtual filesystem structure. All context is integrated in a unified format, and each entry corresponds to a unique URI (like a `viking://` path), breaking the traditional flat black-box management mode with a clear hierarchy that is easy to understand.

The retrieval process adopts a directory recursive strategy. The trajectory of directory browsing and file positioning for each retrieval is fully preserved, allowing users to clearly observe the root cause of problems and guide the optimization of retrieval logic. Learn more: [Retrieval Mechanism](./docs/en/concepts/07-retrieval.md)

### 5. Automatic Session Management → Context Self-Iteration

OpenViking has a built-in memory self-iteration loop. At the end of each session, developers can actively trigger the memory extraction mechanism. The system will asynchronously analyze task execution results and user feedback, and automatically update them to the User and Agent memory directories.

- **User Memory Update**: Update memories related to user preferences, making Agent responses better fit user needs.
- **Agent Experience Accumulation**: Extract core content such as operational tips and tool usage experience from task execution experience, aiding efficient decision-making in subsequent tasks.

This allows the Agent to get "smarter with use" through interactions with the world, achieving self-evolution. Learn more: [Session Management](./docs/en/concepts/08-session.md)

---

## Advanced Reading

### Documentation

For more details, please visit our [Full Documentation](./docs/en/).

### Community & Team

For more details, please see: **[About Us](./docs/en/about/01-about-us.md)**

### Join the Community

OpenViking is still in its early stages, and there are many areas for improvement and exploration. We sincerely invite every developer passionate about AI Agent technology:

- Light up a precious **Star** for us to give us the motivation to move forward.
- Visit our [**Website**](https://www.openviking.ai) to understand the philosophy we convey, and use it in your projects via the [**Documentation**](https://www.openviking.ai/docs). Feel the change it brings and give us feedback on your truest experience.
- Join our community to share your insights, help answer others' questions, and jointly create an open and mutually helpful technical atmosphere:
  - 📱 **Lark Group**: Scan the QR code to join → [View QR Code](./docs/en/about/01-about-us.md#lark-group)
  - 💬 **WeChat Group**: Scan the QR code to add assistant → [View QR Code](./docs/en/about/01-about-us.md#wechat-group)
  - 🎮 **Discord**: [Join Discord Server](https://discord.com/invite/eHvx8E9XF3)
  - 🐦 **X (Twitter)**:[Follow us](https://x.com/openvikingai)
- Become a **Contributor**, whether submitting a bug fix or contributing a new feature, every line of your code will be an important cornerstone of OpenViking's growth.

Let's work together to define and build the future of AI Agent context management. The journey has begun, looking forward to your participation!

### Star Trend

[![Star History Chart](https://api.star-history.com/svg?repos=volcengine/OpenViking&type=timeline&legend=top-left)](https://www.star-history.com/#volcengine/OpenViking&type=timeline&legend=top-left)

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](./LICENSE) file for details.


<!-- Link Definitions -->

[release-shield]: https://img.shields.io/github/v/release/volcengine/OpenViking?color=369eff&labelColor=black&logo=github&style=flat-square
[release-link]: https://github.com/volcengine/OpenViking/releases
[license-shield]: https://img.shields.io/badge/license-apache%202.0-white?labelColor=black&style=flat-square
[license-shield-link]: https://github.com/volcengine/OpenViking/blob/main/LICENSE
[last-commit-shield]: https://img.shields.io/github/last-commit/volcengine/OpenViking?color=c4f042&labelColor=black&style=flat-square
[last-commit-shield-link]: https://github.com/volcengine/OpenViking/commits/main
[github-stars-shield]: https://img.shields.io/github/stars/volcengine/OpenViking?labelColor&style=flat-square&color=ffcb47
[github-stars-link]: https://github.com/volcengine/OpenViking
[github-issues-shield]: https://img.shields.io/github/issues/volcengine/OpenViking?labelColor=black&style=flat-square&color=ff80eb
[github-issues-shield-link]: https://github.com/volcengine/OpenViking/issues
[github-contributors-shield]: https://img.shields.io/github/contributors/volcengine/OpenViking?color=c4f042&labelColor=black&style=flat-square
[github-contributors-link]: https://github.com/volcengine/OpenViking/graphs/contributors


================================================
FILE: README_CN.md
================================================
<div align="center">
<a href="https://openviking.ai/" target="_blank">
  <picture>
    <img alt="OpenViking" src="docs/images/ov-logo.png" width="200px" height="auto">
  </picture>
</a>

### OpenViking:AI 智能体的上下文数据库

[English](README.md) / 中文 / [日本語](README_JA.md)

<a href="https://www.openviking.ai">官网</a> · <a href="https://github.com/volcengine/OpenViking">GitHub</a> · <a href="https://github.com/volcengine/OpenViking/issues">问题反馈</a> · <a href="https://www.openviking.ai/docs">文档</a>

[![][release-shield]][release-link]
[![][github-stars-shield]][github-stars-link]
[![][github-issues-shield]][github-issues-shield-link]
[![][github-contributors-shield]][github-contributors-link]
[![][license-shield]][license-shield-link]
[![][last-commit-shield]][last-commit-shield-link]


👋 加入我们的社区

📱 <a href="./docs/en/about/01-about-us.md#lark-group">飞书群</a> · <a href="./docs/en/about/01-about-us.md#wechat-group">微信群</a> · <a href="https://discord.com/invite/eHvx8E9XF3">Discord</a> · <a href="https://x.com/openvikingai">X</a>

</div>

---

## 概述

### 智能体开发面临的挑战

在 AI 时代,数据丰富,但高质量的上下文却难以获得。在构建 AI 智能体时,开发者经常面临以下挑战:

- **上下文碎片化**:记忆存储在代码中,资源在向量数据库中,技能分散在各处,难以统一管理。
- **上下文需求激增**:智能体的长运行任务在每次执行时都会产生上下文。简单的截断或压缩会导致信息丢失。
- **检索效果不佳**:传统 RAG 使用扁平化存储,缺乏全局视图,难以理解信息的完整上下文。
- **上下文不可观察**:传统 RAG 的隐式检索链像黑盒,出错时难以调试。
- **记忆迭代有限**:当前记忆只是用户交互的记录,缺乏智能体相关的任务记忆。

### OpenViking 解决方案

**OpenViking** 是专为 AI 智能体设计的开源**上下文数据库**。

我们的目标是为智能体定义一个极简的上下文交互范式,让开发者完全告别上下文管理的烦恼。OpenViking 抛弃了传统 RAG 的碎片化向量存储模型,创新性地采用 **"文件系统范式"** 来统一组织智能体所需的记忆、资源和技能。

使用 OpenViking,开发者可以像管理本地文件一样构建智能体的大脑:

- **文件系统管理范式** → **解决碎片化**:基于文件系统范式统一管理记忆、资源和技能。
- **分层上下文加载** → **降低 Token 消耗**:L0/L1/L2 三层结构,按需加载,显著节省成本。
- **目录递归检索** → **提升检索效果**:支持原生文件系统检索方式,结合目录定位和语义搜索,实现递归精准的上下文获取。
- **可视化检索轨迹** → **可观察上下文**:支持目录检索轨迹可视化,让用户清晰观察问题根源,指导检索逻辑优化。
- **自动会话管理** → **上下文自迭代**:自动压缩对话中的内容、资源引用、工具调用等,提取长期记忆,让智能体越用越聪明。

---

## 快速开始

### 前置条件

在开始使用 OpenViking 之前,请确保您的环境满足以下要求:

- **Python 版本**:3.10 或更高版本
- **Go 版本**:1.22 或更高(从源码构建 AGFS 组件需要)
- **C++ 编译器**:GCC 9+ 或 Clang 11+(构建核心扩展需要,必须支持 C++17)
- **操作系统**:Linux、macOS、Windows
- **网络连接**:需要稳定的网络连接(用于下载依赖和访问模型服务)

### 1. 安装

#### Python 包

```bash
pip install openviking --upgrade --force-reinstall
```

#### Rust CLI(可选)

```bash
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

或从源码构建:

```bash
cargo install --git https://github.com/volcengine/OpenViking ov_cli
```

### 2. 模型准备

OpenViking 需要以下模型能力:
- **VLM 模型**:用于图像和内容理解
- **Embedding 模型**:用于向量化和语义检索

#### 支持的 VLM 提供商

OpenViking 支持三种 VLM 提供商:

| 提供商 | 描述 | 获取 API Key |
|----------|-------------|-------------|
| `volcengine` | 火山引擎豆包模型 | [Volcengine 控制台](https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&type=new&utm_content=OpenViking&utm_medium=devrel&utm_source=OWO&utm_term=OpenViking) |
| `openai` | OpenAI 官方 API | [OpenAI 平台](https://platform.openai.com) |
| `azure` | Azure OpenAI 服务 | [Azure OpenAI 服务](https://portal.azure.com) |
| `litellm` | 统一调用多种第三方模型 (Anthropic, DeepSeek, Gemini, vLLM, Ollama 等) | 参见 [LiteLLM 提供商](https://docs.litellm.ai/docs/providers) |

> 💡 **提示**:
> - `litellm` 支持通过统一接口调用多种模型,model 字段需遵循 [LiteLLM 格式规范](https://docs.litellm.ai/docs/providers)
> - 系统自动检测常见模型(如 `claude-*`, `deepseek-*`, `gemini-*`, `hosted_vllm/*`, `ollama/*` 等),其他模型需按 LiteLLM 格式填写完整前缀

#### 提供商特定说明

<details>
<summary><b>Volcengine (豆包)</b></summary>

Volcengine 支持模型名称和端点 ID。为简单起见,建议使用模型名称:

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "doubao-seed-2-0-pro-260215",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

您也可以使用端点 ID(可在 [Volcengine ARK 控制台](https://console.volcengine.com/ark) 中找到):

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "ep-20241220174930-xxxxx",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

</details>

<details>
<summary><b>OpenAI</b></summary>

使用 OpenAI 的官方 API:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://api.openai.com/v1"
  }
}
```

您也可以使用自定义的 OpenAI 兼容端点:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://your-custom-endpoint.com/v1"
  }
}
```

</details>

<details>
<summary><b>Azure OpenAI</b></summary>

使用 Azure OpenAI 服务。`model` 字段需要填写 Azure 上的**部署名称(deployment name)**,而非模型官方名字:

```json
{
  "vlm": {
    "provider": "azure",
    "model": "your-deployment-name",
    "api_key": "your-azure-api-key",
    "api_base": "https://your-resource-name.openai.azure.com",
    "api_version": "2025-01-01-preview"
  }
}
```

> 💡 **提示**:
> - `api_base` 填写你的 Azure OpenAI 资源端点,支持 `*.openai.azure.com` 和 `*.cognitiveservices.azure.com` 两种格式
> - `api_version` 可选,默认值为 `2025-01-01-preview`
> - `model` 必须与 Azure Portal 中创建的部署名称一致

</details>

<details>
<summary><b>LiteLLM (Anthropic, DeepSeek, Gemini, Qwen, vLLM, Ollama 等)</b></summary>

LiteLLM 提供对各种模型的统一访问。`model` 字段应遵循 LiteLLM 的命名约定。以下以 Claude 和 Qwen 为例:

**Anthropic:**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "claude-3-5-sonnet-20240620",
    "api_key": "your-anthropic-api-key"
  }
}
```

**Qwen (DashScope):**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "dashscope/qwen-turbo",
    "api_key": "your-dashscope-api-key",
    "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1"
  }
}
```

> 💡 **Qwen 提示**:
> - **中国/北京** 区域,使用 `api_base`:`https://dashscope.aliyuncs.com/compatible-mode/v1`
> - **国际** 区域,使用 `api_base`:`https://dashscope-intl.aliyuncs.com/compatible-mode/v1`

**常见模型格式:**

| 提供商 | 模型示例 | 说明 |
|----------|---------------|-------|
| Anthropic | `claude-3-5-sonnet-20240620` | 自动检测,使用 `ANTHROPIC_API_KEY` |
| DeepSeek | `deepseek-chat` | 自动检测,使用 `DEEPSEEK_API_KEY` |
| Gemini | `gemini-pro` | 自动检测,使用 `GEMINI_API_KEY` |
| Qwen | `dashscope/qwen-turbo` | 根据区域设置 `api_base`(见上方说明) |
| OpenRouter | `openrouter/openai/gpt-4o` | 需要完整前缀 |
| vLLM | `hosted_vllm/llama-3.1-8b` | 设置 `api_base` 为 vLLM 服务器 |
| Ollama | `ollama/llama3.1` | 设置 `api_base` 为 Ollama 服务器 |

**本地模型 (vLLM / Ollama):**

```bash

# 启动 Ollama
ollama serve
```

```json
// Ollama
{
  "vlm": {
    "provider": "litellm",
    "model": "ollama/llama3.1",
    "api_base": "http://localhost:11434"
  }
}
```

完整的模型支持,请参见 [LiteLLM 提供商文档](https://docs.litellm.ai/docs/providers)。

</details>

### 3. 环境配置

#### 服务器配置模板

创建配置文件 `~/.openviking/ov.conf`,复制前请删除注释:

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // 日志输出:"stdout" 或 "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "<api-endpoint>",   // API 端点地址
      "api_key"  : "<your-api-key>",   // 模型服务 API Key
      "provider" : "<provider-type>",  // 提供商类型:"volcengine"、"openai"、"azure" 等
      "api_version": "2025-01-01-preview", // (仅 azure)API 版本,可选,默认 "2025-01-01-preview"
      "dimension": 1024,               // 向量维度
      "model"    : "<model-name>"      // Embedding 模型名称或 Azure 部署名(如 doubao-embedding-vision-250615 或 text-embedding-3-large)
    },
    "max_concurrent": 10               // 最大并发 embedding 请求(默认:10)
  },
  "vlm": {
    "api_base" : "<api-endpoint>",     // API 端点地址
    "api_key"  : "<your-api-key>",     // 模型服务 API Key
    "provider" : "<provider-type>",    // 提供商类型 (volcengine, openai, azure, litellm 等)
    "api_version": "2025-01-01-preview", // (仅 azure)API 版本,可选,默认 "2025-01-01-preview"
    "model"    : "<model-name>",       // VLM 模型名称或 Azure 部署名(如 doubao-seed-2-0-pro-260215 或 gpt-4-vision-preview)
    "max_concurrent": 100              // 语义处理的最大并发 LLM 调用(默认:100)
  }
}
```

> **注意**:对于 embedding 模型,目前支持 `volcengine`(豆包)、`openai`、`azure`、`jina` 等提供商。对于 VLM 模型,我们支持 `volcengine`、`openai`、`azure` 和 `litellm` 提供商。`litellm` 提供商支持各种模型,包括 Anthropic (Claude)、DeepSeek、Gemini、Moonshot、Zhipu、DashScope、MiniMax、vLLM、Ollama 等。

#### 服务器配置示例

👇 展开查看您的模型服务的配置示例:

<details>
<summary><b>示例 1:使用 Volcengine(豆包模型)</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // 日志输出:"stdout" 或 "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
      "api_key"  : "your-volcengine-api-key",
      "provider" : "volcengine",
      "dimension": 1024,
      "model"    : "doubao-embedding-vision-250615"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
    "api_key"  : "your-volcengine-api-key",
    "provider" : "volcengine",
    "model"    : "doubao-seed-2-0-pro-260215",
    "max_concurrent": 100
  }
}
```

</details>

<details>
<summary><b>示例 2:使用 OpenAI 模型</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // 日志输出:"stdout" 或 "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://api.openai.com/v1",
      "api_key"  : "your-openai-api-key",
      "provider" : "openai",
      "dimension": 3072,
      "model"    : "text-embedding-3-large"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://api.openai.com/v1",
    "api_key"  : "your-openai-api-key",
    "provider" : "openai",
    "model"    : "gpt-4-vision-preview",
    "max_concurrent": 100
  }
}
```

</details>

<details>
<summary><b>示例 3:使用 Azure OpenAI 模型</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://your-resource-name.openai.azure.com",
      "api_key"  : "your-azure-api-key",
      "provider" : "azure",
      "api_version": "2025-01-01-preview",
      "dimension": 1024,
      "model"    : "text-embedding-3-large"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://your-resource-name.openai.azure.com",
    "api_key"  : "your-azure-api-key",
    "provider" : "azure",
    "api_version": "2025-01-01-preview",
    "model"    : "gpt-4o",
    "max_concurrent": 100
  }
}
```

> 💡 **提示**:
> - `model` 必须填写 Azure Portal 中创建的**部署名称**,而非模型官方名字
> - `api_base` 支持 `*.openai.azure.com` 和 `*.cognitiveservices.azure.com` 两种端点格式
> - Embedding 和 VLM 可以使用不同的 Azure 资源和 API Key

</details>

#### 设置服务器配置环境变量

创建配置文件后,设置环境变量指向它(Linux/macOS):

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf # 默认值
```

在 Windows 上,使用以下任一方式:

PowerShell:

```powershell
$env:OPENVIKING_CONFIG_FILE = "$HOME/.openviking/ov.conf"
```

命令提示符 (cmd.exe):

```bat
set "OPENVIKING_CONFIG_FILE=%USERPROFILE%\.openviking\ov.conf"
```

> 💡 **提示**:您也可以将配置文件放在其他位置,只需在环境变量中指定正确路径。

#### CLI/客户端配置示例

👇 展开查看您的 CLI/客户端的配置示例:

示例:用于访问本地服务器的 ovcli.conf

```json
{
  "url": "http://localhost:1933",
  "timeout": 60.0,
  "output": "table"
}
```

创建配置文件后,设置环境变量指向它(Linux/macOS):

```bash
export OPENVIKING_CLI_CONFIG_FILE=~/.openviking/ovcli.conf # 默认值
```

在 Windows 上,使用以下任一方式:

PowerShell:

```powershell
$env:OPENVIKING_CLI_CONFIG_FILE = "$HOME/.openviking/ovcli.conf"
```

命令提示符 (cmd.exe):

```bat
set "OPENVIKING_CLI_CONFIG_FILE=%USERPROFILE%\.openviking\ovcli.conf"
```

### 4. 运行您的第一个示例

> 📝 **前置条件**:确保您已完成上一步的配置(ov.conf 和 ovcli.conf)。

现在让我们运行一个完整的示例,体验 OpenViking 的核心功能。

#### 启动服务器

```bash
openviking-server
```

或者您可以在后台运行

```bash
nohup openviking-server > /data/log/openviking.log 2>&1 &
```

#### 运行 CLI

```bash
ov status
ov add-resource https://github.com/volcengine/OpenViking # --wait
ov ls viking://resources/
ov tree viking://resources/volcengine -L 2
# 如果没有使用 --wait,等待一段时间以进行语义处理
ov find "what is openviking"
ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/zh
```

恭喜!您已成功运行 OpenViking 🎉

### VikingBot 快速开始

VikingBot 是构建在 OpenViking 之上的 AI 智能体框架。以下是快速开始指南:

```bash
# 选项 1:从 PyPI 安装 VikingBot(推荐大多数用户使用)
pip install "openviking[bot]"

# 选项 2:从源码安装 VikingBot(用于开发)
uv pip install -e ".[bot]"

# 启动 OpenViking 服务器(同时启动 Bot)
openviking-server --with-bot

# 在另一个终端启动交互式聊天
ov chat
```

---

## 服务器部署详情

对于生产环境,我们建议将 OpenViking 作为独立的 HTTP 服务运行,为您的 AI 智能体提供持久、高性能的上下文支持。

🚀 **在云端部署 OpenViking**:
为确保最佳的存储性能和数据安全,我们建议在 **火山引擎弹性计算服务 (ECS)** 上使用 **veLinux** 操作系统进行部署。我们准备了详细的分步指南,帮助您快速上手。

👉 **[查看:服务器部署与 ECS 设置指南](./docs/en/getting-started/03-quickstart-server.md)**


## OpenClaw 上下文插件详情

* 测试集:基于 LoCoMo10(https://github.com/snap-research/locomo) 的长程对话进行效果测试(去除无真值的 category5 后,共 1540 条 case)
* 实验组:因用户在使用 OpenViking 时可能不关闭 OpenClaw 原生记忆,所以增加是否开关原生记忆的实验组
* OpenViking 版本:0.1.18
* 模型:seed-2.0-code
* 评测脚本:https://github.com/ZaynJarvis/openclaw-eval/tree/main

| 实验组 |	任务完成率 | 成本:输入 token (总计) |
|----------|------------------|------------------|
| OpenClaw(memory-core) |	35.65% |	24,611,530 |
| OpenClaw + LanceDB (-memory-core) |	44.55% |	51,574,530 |
| OpenClaw + OpenViking Plugin (-memory-core)	| 52.08% |	4,264,396 |
| OpenClaw + OpenViking Plugin (+memory-core)	| 51.23% |	2,099,622 |

* 实验结论:
结合 OpenViking 后,若仍开启原生记忆,效果在原 OpenClaw 上提升 43%,输入 token 成本降低 91%;在 LanceDB 上效果提升 15%,输入 token 降低 96%。若关闭原生记忆,效果在原 OpenClaw 上提升 49%,输入 token 成本降低 83%;在 LanceDB 上效果提升 17%,输入 token 降低 92%。

👉 **[查看:OpenClaw 上下文插件](examples/openclaw-plugin/README.md)**

👉 **[查看:OpenCode 记忆插件示例](examples/opencode-memory-plugin/README.md)**

## VikingBot 部署详情

OpenViking 有一个类似 nanobot 的机器人用于交互工作,现已可用。

👉 **[查看:使用 VikingBot 部署服务器](bot/README.md)**

--

## 核心概念

运行第一个示例后,让我们深入了解 OpenViking 的设计理念。这五个核心概念与前面提到的解决方案一一对应,共同构建了一个完整的上下文管理系统:

### 1. 文件系统管理范式 → 解决碎片化

我们不再将上下文视为扁平的文本切片,而是将它们统一到一个抽象的虚拟文件系统中。无论是记忆、资源还是能力,都映射到 `viking://` 协议下的虚拟目录中,每个都有唯一的 URI。

这种范式赋予智能体前所未有的上下文操作能力,使它们能够像开发者一样,通过 `ls` 和 `find` 等标准命令精确、确定地定位、浏览和操作信息。这将上下文管理从模糊的语义匹配转变为直观、可追踪的"文件操作"。了解更多:[Viking URI](./docs/en/concepts/04-viking-uri.md) | [上下文类型](./docs/en/concepts/02-context-types.md)

```
viking://
├── resources/              # 资源:项目文档、代码库、网页等
│   ├── my_project/
│   │   ├── docs/
│   │   │   ├── api/
│   │   │   └── tutorials/
│   │   └── src/
│   └── ...
├── user/                   # 用户:个人偏好、习惯等
│   └── memories/
│       ├── preferences/
│       │   ├── writing_style
│       │   └── coding_habits
│       └── ...
└── agent/                  # 智能体:技能、指令、任务记忆等
    ├── skills/
    │   ├── search_code
    │   ├── analyze_data
    │   └── ...
    ├── memories/
    └── instructions/
```

### 2. 分层上下文加载 → 降低 Token 消耗

一次性将大量上下文塞入提示不仅昂贵,而且容易超出模型窗口并引入噪声。OpenViking 在写入时自动将上下文处理为三个级别:
- **L0 (摘要)**:一句话摘要,用于快速检索和识别。
- **L1 (概览)**:包含核心信息和使用场景,用于智能体在规划阶段的决策。
- **L2 (详情)**:完整的原始数据,供智能体在绝对必要时深度阅读。

了解更多:[上下文分层](./docs/en/concepts/03-context-layers.md)

```
viking://resources/my_project/
├── .abstract               # L0 层:摘要(~100 tokens)- 快速相关性检查
├── .overview               # L1 层:概览(~2k tokens)- 理解结构和关键点
├── docs/
│   ├── .abstract          # 每个目录都有对应的 L0/L1 层
│   ├── .overview
│   ├── api/
│   │   ├── .abstract
│   │   ├── .overview
│   │   ├── auth.md        # L2 层:完整内容 - 按需加载
│   │   └── endpoints.md
│   └── ...
└── src/
    └── ...
```

### 3. 目录递归检索 → 提升检索效果

单一向量检索难以应对复杂的查询意图。OpenViking 设计了创新的**目录递归检索策略**,深度集成多种检索方法:

1. **意图分析**:通过意图分析生成多个检索条件。
2. **初始定位**:使用向量检索快速定位初始切片所在的高分目录。
3. **精细探索**:在该目录内进行二次检索,并将高分结果更新到候选集。
4. **递归深入**:如果存在子目录,则逐层递归重复二次检索步骤。
5. **结果聚合**:最终获取最相关的上下文返回。

这种"先锁定高分目录,再精细化内容探索"的策略不仅找到语义最佳匹配的片段,还能理解信息所在的完整上下文,从而提高检索的全局性和准确性。了解更多:[检索机制](./docs/en/concepts/07-retrieval.md)

### 4. 可视化检索轨迹 → 可观察上下文

OpenViking 的组织采用分层虚拟文件系统结构。所有上下文以统一格式集成,每个条目对应一个唯一的 URI(如 `viking://` 路径),打破了传统的扁平黑盒管理模式,具有清晰易懂的层次结构。

检索过程采用目录递归策略。每次检索的目录浏览和文件定位轨迹被完整保留,让用户能够清晰观察问题的根源,指导检索逻辑的优化。了解更多:[检索机制](./docs/en/concepts/07-retrieval.md)

### 5. 自动会话管理 → 上下文自迭代

OpenViking 内置了记忆自迭代循环。在每个会话结束时,开发者可以主动触发记忆提取机制。系统将异步分析任务执行结果和用户反馈,并自动更新到用户和智能体记忆目录。

- **用户记忆更新**:更新与用户偏好相关的记忆,使智能体响应更好地适应用户需求。
- **智能体经验积累**:从任务执行经验中提取操作技巧和工具使用经验等核心内容,辅助后续任务的高效决策。

这使得智能体能够通过与世界的交互"越用越聪明",实现自我进化。了解更多:[会话管理](./docs/en/concepts/08-session.md)

---

## 深入阅读

### 文档

更多详情,请访问我们的[完整文档](./docs/en/)。

### 社区与团队

更多详情,请参见:**[关于我们](./docs/en/about/01-about-us.md)**

### 加入社区

OpenViking 仍处于早期阶段,有许多改进和探索的空间。我们真诚邀请每一位对 AI 智能体技术充满热情的开发者:

- 为我们点亮一颗珍贵的 **Star**,给我们前进的动力。
- 访问我们的[**官网**](https://www.openviking.ai)了解我们传达的理念,并通过[**文档**](https://www.openviking.ai/docs)在您的项目中使用它。感受它带来的变化,并给我们最真实的体验反馈。
- 加入我们的社区,分享您的见解,帮助回答他人的问题,共同创造开放互助的技术氛围:
  - 📱 **飞书群**:扫码加入 → [查看二维码](./docs/en/about/01-about-us.md#lark-group)
  - 💬 **微信群**:扫码添加助手 → [查看二维码](./docs/en/about/01-about-us.md#wechat-group)
  - 🎮 **Discord**:[加入 Discord 服务器](https://discord.com/invite/eHvx8E9XF3)
  - 🐦 **X (Twitter)**:[关注我们](https://x.com/openvikingai)
- 成为**贡献者**,无论是提交错误修复还是贡献新功能,您的每一行代码都将是 OpenViking 成长的重要基石。

让我们共同努力,定义和构建 AI 智能体上下文管理的未来。旅程已经开始,期待您的参与!

### Star 趋势

[![Star History Chart](https://api.star-history.com/svg?repos=volcengine/OpenViking&type=timeline&legend=top-left)](https://www.star-history.com/#volcengine/OpenViking&type=timeline&legend=top-left)

## 许可证

本项目采用 Apache License 2.0 许可证 - 详情请参见 [LICENSE](./LICENSE) 文件。


<!-- Link Definitions -->

[release-shield]: https://img.shields.io/github/v/release/volcengine/OpenViking?color=369eff&labelColor=black&logo=github&style=flat-square
[release-link]: https://github.com/volcengine/OpenViking/releases
[license-shield]: https://img.shields.io/badge/license-apache%202.0-white?labelColor=black&style=flat-square
[license-shield-link]: https://github.com/volcengine/OpenViking/blob/main/LICENSE
[last-commit-shield]: https://img.shields.io/github/last-commit/volcengine/OpenViking?color=c4f042&labelColor=black&style=flat-square
[last-commit-shield-link]: https://github.com/volcengine/OpenViking/commcommits/main
[github-stars-shield]: https://img.shields.io/github/stars/volcengine/OpenViking?labelColor&style=flat-square&color=ffcb47
[github-stars-link]: https://github.com/volcengine/OpenViking
[github-issues-shield]: https://img.shields.io/github/issues/volcengine/OpenViking?labelColor=black&style=flat-square&color=ff80eb
[github-issues-shield-link]: https://github.com/volcengine/OpenViking/issues
[github-contributors-shield]: https://img.shields.io/github/contributors/volcengine/OpenViking?color=c4f042&labelColor=black&style=flat-square
[github-contributors-link]: https://github.com/volcengine/OpenViking/graphs/contributors


================================================
FILE: README_JA.md
================================================
<div align="center">

<a href="https://openviking.ai/" target="_blank">
  <picture>
    <img alt="OpenViking" src="docs/images/ov-logo.png" width="200px" height="auto">
  </picture>
</a>

### OpenViking: AIエージェントのためのコンテキストデータベース

[English](README.md) / [中文](README_CN.md) / 日本語

<a href="https://www.openviking.ai">Webサイト</a> · <a href="https://github.com/volcengine/OpenViking">GitHub</a> · <a href="https://github.com/volcengine/OpenViking/issues">Issues</a> · <a href="https://www.openviking.ai/docs">ドキュメント</a>

[![][release-shield]][release-link]
[![][github-stars-shield]][github-stars-link]
[![][github-issues-shield]][github-issues-shield-link]
[![][github-contributors-shield]][github-contributors-link]
[![][license-shield]][license-shield-link]
[![][last-commit-shield]][last-commit-shield-link]

👋 コミュニティに参加しよう

📱 <a href="./docs/en/about/01-about-us.md#lark-group">Larkグループ</a> · <a href="./docs/en/about/01-about-us.md#wechat-group">WeChat</a> · <a href="https://discord.com/invite/eHvx8E9XF3">Discord</a> · <a href="https://x.com/openvikingai">X</a>

<a href="https://trendshift.io/repositories/19668" target="_blank"><img src="https://trendshift.io/api/badge/repositories/19668" alt="volcengine%2FOpenViking | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>

</div>

---

## 概要

### エージェント開発における課題

AI時代において、データは豊富ですが、高品質なコンテキストは得がたいものです。AIエージェントを構築する際、開発者はしばしば以下の課題に直面します:

- **断片化されたコンテキスト**: メモリはコードに、リソースはベクトルデータベースに、スキルは散在しており、統一的な管理が困難です。
- **急増するコンテキスト需要**: エージェントの長時間タスクは実行のたびにコンテキストを生成します。単純な切り詰めや圧縮は情報の損失につながります。
- **検索効果の低さ**: 従来のRAGはフラットなストレージを使用し、グローバルな視点が欠けているため、情報の全体的なコンテキストを理解することが困難です。
- **観察不能なコンテキスト**: 従来のRAGの暗黙的な検索チェーンはブラックボックスのようで、エラー発生時のデバッグが困難です。
- **限定的なメモリの反復**: 現在のメモリはユーザーとのやり取りの記録に過ぎず、エージェント関連のタスクメモリが不足しています。

### OpenVikingのソリューション

**OpenViking**は、AIエージェント専用に設計されたオープンソースの**コンテキストデータベース**です。

私たちは、エージェントのためのミニマリストなコンテキストインタラクションパラダイムを定義し、開発者がコンテキスト管理の煩雑さから完全に解放されることを目指しています。OpenVikingは従来のRAGの断片化されたベクトルストレージモデルを捨て、革新的に**「ファイルシステムパラダイム」**を採用して、エージェントに必要なメモリ、リソース、スキルの構造化された組織を統一します。

OpenVikingを使えば、開発者はローカルファイルを管理するようにエージェントの頭脳を構築できます:

- **ファイルシステム管理パラダイム** → **断片化を解決**: ファイルシステムパラダイムに基づく、メモリ、リソース、スキルの統一的なコンテキスト管理。
- **階層型コンテキストローディング** → **トークン消費を削減**: L0/L1/L2の3層構造、オンデマンドでロードし、コストを大幅に削減。
- **ディレクトリ再帰検索** → **検索効果を向上**: ネイティブのファイルシステム検索手法をサポートし、ディレクトリ位置決めとセマンティック検索を組み合わせて、再帰的で精密なコンテキスト取得を実現。
- **可視化された検索軌跡** → **観察可能なコンテキスト**: ディレクトリ検索軌跡の可視化をサポートし、ユーザーが問題の根本原因を明確に観察し、検索ロジックの最適化を導くことを可能に。
- **自動セッション管理** → **コンテキストの自己反復**: 会話中のコンテンツ、リソース参照、ツール呼び出しなどを自動的に圧縮し、長期メモリを抽出して、使うほどエージェントを賢く。

---

## クイックスタート

### 前提条件

OpenVikingを始める前に、環境が以下の要件を満たしていることを確認してください:

- **Pythonバージョン**: 3.10以上
- **Goバージョン**: 1.22以上(AGFSコンポーネントのビルドに必要)
- **C++コンパイラ**: GCC 9以上 または Clang 11以上(コア拡張のビルドに必要)
- **オペレーティングシステム**: Linux、macOS、Windows
- **ネットワーク接続**: 安定したネットワーク接続が必要(依存関係のダウンロードとモデルサービスへのアクセスのため)

### 1. インストール

#### Pythonパッケージ

```bash
pip install openviking --upgrade --force-reinstall
```

#### Rust CLI(オプション)

```bash
curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/crates/ov_cli/install.sh | bash
```

またはソースからビルド:

```bash
cargo install --git https://github.com/volcengine/OpenViking ov_cli
```

### 2. モデルの準備

OpenVikingには以下のモデル機能が必要です:
- **VLMモデル**: 画像とコンテンツの理解用
- **Embeddingモデル**: ベクトル化とセマンティック検索用

#### サポートされているVLMプロバイダー

OpenVikingは3つのVLMプロバイダーをサポートしています:

| プロバイダー | 説明 | APIキーの取得 |
|----------|-------------|-------------|
| `volcengine` | Volcengine Doubaoモデル | [Volcengineコンソール](https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&type=new&utm_content=OpenViking&utm_medium=devrel&utm_source=OWO&utm_term=OpenViking) |
| `openai` | OpenAI公式API | [OpenAIプラットフォーム](https://platform.openai.com) |
| `litellm` | 様々なサードパーティモデルへの統合アクセス(Anthropic、DeepSeek、Gemini、vLLM、Ollamaなど) | [LiteLLMプロバイダー](https://docs.litellm.ai/docs/providers)を参照 |

> 💡 **ヒント**:
> - `litellm`は様々なモデルへの統合アクセスをサポートしています。`model`フィールドは[LiteLLMフォーマット仕様](https://docs.litellm.ai/docs/providers)に従う必要があります
> - システムは一般的なモデル(例:`claude-*`、`deepseek-*`、`gemini-*`、`hosted_vllm/*`、`ollama/*`など)を自動検出します。その他のモデルについては、LiteLLMフォーマットに従ったフルプレフィックスを使用してください

#### プロバイダー固有の注意事項

<details>
<summary><b>Volcengine(Doubao)</b></summary>

Volcengineはモデル名とエンドポイントIDの両方をサポートしています。簡便さのためモデル名の使用を推奨します:

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "doubao-seed-2-0-pro-260215",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

エンドポイントIDも使用できます([Volcengine ARKコンソール](https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&type=new&utm_content=OpenViking&utm_medium=devrel&utm_source=OWO&utm_term=OpenViking)で確認):

```json
{
  "vlm": {
    "provider": "volcengine",
    "model": "ep-20241220174930-xxxxx",
    "api_key": "your-api-key",
    "api_base": "https://ark.cn-beijing.volces.com/api/v3"
  }
}
```

</details>

<details>
<summary><b>OpenAI</b></summary>

OpenAIの公式APIを使用:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://api.openai.com/v1"
  }
}
```

カスタムのOpenAI互換エンドポイントも使用できます:

```json
{
  "vlm": {
    "provider": "openai",
    "model": "gpt-4o",
    "api_key": "your-api-key",
    "api_base": "https://your-custom-endpoint.com/v1"
  }
}
```

</details>

<details>
<summary><b>LiteLLM(Anthropic、DeepSeek、Gemini、Qwen、vLLM、Ollamaなど)</b></summary>

LiteLLMは様々なモデルへの統合アクセスを提供します。`model`フィールドはLiteLLMの命名規則に従う必要があります。ここではClaudeとQwenを例に説明します:

**Anthropic:**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "claude-3-5-sonnet-20240620",
    "api_key": "your-anthropic-api-key"
  }
}
```

**Qwen(DashScope):**

```json
{
  "vlm": {
    "provider": "litellm",
    "model": "dashscope/qwen-turbo", // 詳細は https://docs.litellm.ai/docs/providers/dashscope を参照
    "api_key": "your-dashscope-api-key",
    "api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1"
  }
}
```

> 💡 **Qwenのヒント**:
> - **中国/北京**リージョンの場合、`api_base`は `https://dashscope.aliyuncs.com/compatible-mode/v1` を使用
> - **国際**リージョンの場合、`api_base`は `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` を使用

**一般的なモデルフォーマット:**

| プロバイダー | モデル例 | 備考 |
|----------|---------------|-------|
| Anthropic | `claude-3-5-sonnet-20240620` | 自動検出、`ANTHROPIC_API_KEY`を使用 |
| DeepSeek | `deepseek-chat` | 自動検出、`DEEPSEEK_API_KEY`を使用 |
| Gemini | `gemini-pro` | 自動検出、`GEMINI_API_KEY`を使用 |
| Qwen | `dashscope/qwen-turbo` | リージョンに基づいて`api_base`を設定(上記参照) |
| OpenRouter | `openrouter/openai/gpt-4o` | フルプレフィックスが必要 |
| vLLM | `hosted_vllm/llama-3.1-8b` | `api_base`をvLLMサーバーに設定 |
| Ollama | `ollama/llama3.1` | `api_base`をOllamaサーバーに設定 |

**ローカルモデル(vLLM / Ollama):**

```bash

# Ollamaの起動
ollama serve
```

```json
// Ollama
{
  "vlm": {
    "provider": "litellm",
    "model": "ollama/llama3.1",
    "api_base": "http://localhost:11434"
  }
}
```

完全なモデルサポートについては、[LiteLLMプロバイダードキュメント](https://docs.litellm.ai/docs/providers)を参照してください。

</details>

### 3. 環境設定

#### サーバー設定テンプレート

設定ファイル `~/.openviking/ov.conf` を作成します。コピー前にコメントを削除してください:

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // ログ出力: "stdout" または "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "<api-endpoint>",   // APIエンドポイントアドレス
      "api_key"  : "<your-api-key>",   // モデルサービスAPIキー
      "provider" : "<provider-type>",  // プロバイダータイプ: "volcengine" または "openai"(現在サポート済み)
      "dimension": 1024,               // ベクトル次元
      "model"    : "<model-name>"      // Embeddingモデル名(例:doubao-embedding-vision-250615 または text-embedding-3-large)
    },
    "max_concurrent": 10               // 最大同時Embeddingリクエスト数(デフォルト: 10)
  },
  "vlm": {
    "api_base" : "<api-endpoint>",     // APIエンドポイントアドレス
    "api_key"  : "<your-api-key>",     // モデルサービスAPIキー
    "provider" : "<provider-type>",    // プロバイダータイプ(volcengine、openai、deepseek、anthropicなど)
    "model"    : "<model-name>",       // VLMモデル名(例:doubao-seed-2-0-pro-260215 または gpt-4-vision-preview)
    "max_concurrent": 100              // セマンティック処理の最大同時LLM呼び出し数(デフォルト: 100)
  }
}
```

> **注意**: Embeddingモデルについては、現在`volcengine`(Doubao)、`openai`、`jina`プロバイダーがサポートされています。VLMモデルについては、`volcengine`、`openai`、`litellm`の3つのプロバイダーをサポートしています。`litellm`プロバイダーは、Anthropic(Claude)、DeepSeek、Gemini、Moonshot、Zhipu、DashScope、MiniMax、vLLM、Ollamaなど様々なモデルをサポートしています。

#### サーバー設定例

👇 お使いのモデルサービスの設定例を展開して確認:

<details>
<summary><b>例1: Volcengine(Doubaoモデル)を使用</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // ログ出力: "stdout" または "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
      "api_key"  : "your-volcengine-api-key",
      "provider" : "volcengine",
      "dimension": 1024,
      "model"    : "doubao-embedding-vision-250615"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://ark.cn-beijing.volces.com/api/v3",
    "api_key"  : "your-volcengine-api-key",
    "provider" : "volcengine",
    "model"    : "doubao-seed-2-0-pro-260215",
    "max_concurrent": 100
  }
}
```

</details>

<details>
<summary><b>例2: OpenAIモデルを使用</b></summary>

```json
{
  "storage": {
    "workspace": "/home/your-name/openviking_workspace"
  },
  "log": {
    "level": "INFO",
    "output": "stdout"                 // ログ出力: "stdout" または "file"
  },
  "embedding": {
    "dense": {
      "api_base" : "https://api.openai.com/v1",
      "api_key"  : "your-openai-api-key",
      "provider" : "openai",
      "dimension": 3072,
      "model"    : "text-embedding-3-large"
    },
    "max_concurrent": 10
  },
  "vlm": {
    "api_base" : "https://api.openai.com/v1",
    "api_key"  : "your-openai-api-key",
    "provider" : "openai",
    "model"    : "gpt-4-vision-preview",
    "max_concurrent": 100
  }
}
```

</details>

#### サーバー設定の環境変数の設定

設定ファイルを作成後、環境変数を設定してファイルを指定します(Linux/macOS):

```bash
export OPENVIKING_CONFIG_FILE=~/.openviking/ov.conf # デフォルト
```

Windowsの場合、以下のいずれかを使用:

PowerShell:

```powershell
$env:OPENVIKING_CONFIG_FILE = "$HOME/.openviking/ov.conf"
```

コマンドプロンプト(cmd.exe):

```bat
set "OPENVIKING_CONFIG_FILE=%USERPROFILE%\.openviking\ov.conf"
```

> 💡 **ヒント**: 設定ファイルは他の場所に配置することもできます。環境変数で正しいパスを指定するだけです。

#### CLI/クライアント設定例

👇 CLI/クライアントの設定例を展開して確認:

例:localhostサーバー接続用のovcli.conf

```json
{
  "url": "http://localhost:1933",
  "timeout": 60.0,
  "output": "table"
}
```

設定ファイルを作成後、環境変数を設定してファイルを指定します(Linux/macOS):

```bash
export OPENVIKING_CLI_CONFIG_FILE=~/.openviking/ovcli.conf # デフォルト
```

Windowsの場合、以下のいずれかを使用:

PowerShell:

```powershell
$env:OPENVIKING_CLI_CONFIG_FILE = "$HOME/.openviking/ovcli.conf"
```

コマンドプロンプト(cmd.exe):

```bat
set "OPENVIKING_CLI_CONFIG_FILE=%USERPROFILE%\.openviking\ovcli.conf"
```

### 4. 最初の例を実行

> 📝 **前提条件**: 前のステップで設定(ov.confとovcli.conf)が完了していることを確認してください。

それでは、完全な例を実行してOpenVikingのコア機能を体験しましょう。

#### サーバーの起動

```bash
openviking-server
```

またはバックグラウンドで実行:

```bash
nohup openviking-server > /data/log/openviking.log 2>&1 &
```

#### CLIの実行

```bash
ov status
ov add-resource https://github.com/volcengine/OpenViking # --wait
ov ls viking://resources/
ov tree viking://resources/volcengine -L 2
# --waitを指定しない場合、セマンティック処理の完了を待つ
ov find "what is openviking"
ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/zh
```

おめでとうございます!OpenVikingの実行に成功しました 🎉

### VikingBotクイックスタート

VikingBotは、OpenViking上に構築されたAIエージェントフレームワークです。始め方は以下の通りです:

```bash
# オプション1: PyPIからVikingBotをインストール(ほとんどのユーザーに推奨)
pip install "openviking[bot]"

# オプション2: ソースからVikingBotをインストール(開発用)
uv pip install -e ".[bot]"

# Bot有効でOpenVikingサーバーを起動
openviking-server --with-bot

# 別のターミナルでインタラクティブチャットを開始
ov chat
```

---

## サーバーデプロイの詳細

本番環境では、AIエージェントに永続的で高性能なコンテキストサポートを提供するため、OpenVikingをスタンドアロンHTTPサービスとして実行することを推奨します。

🚀 **クラウドにOpenVikingをデプロイ**:
最適なストレージパフォーマンスとデータセキュリティを確保するため、**veLinux**オペレーティングシステムを使用した**Volcengine Elastic Compute Service(ECS)**へのデプロイを推奨します。迅速に開始するための詳細なステップバイステップガイドを用意しています。

👉 **[参照: サーバーデプロイ&ECSセットアップガイド](./docs/en/getting-started/03-quickstart-server.md)**


## OpenClawコンテキストプラグインの詳細

* テストデータセット: LoCoMo10(https://github.com/snap-research/locomo)の長距離対話に基づく効果テスト
Download .txt
gitextract_9tihp5kp/

├── .clang-format
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.yml
│   │   └── question.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── _build.yml
│       ├── _codeql.yml
│       ├── _lint.yml
│       ├── _publish.yml
│       ├── _test_full.yml
│       ├── _test_lite.yml
│       ├── build-docker-image.yml
│       ├── ci.yml
│       ├── pr-review.yml
│       ├── pr.yml
│       ├── release-vikingbot-first.yml
│       ├── release.yml
│       ├── rust-cli.yml
│       └── schedule.yml
├── .gitignore
├── .pr_agent.toml
├── .pre-commit-config.yaml
├── CONTRIBUTING.md
├── CONTRIBUTING_CN.md
├── CONTRIBUTING_JA.md
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── README_CN.md
├── README_JA.md
├── bot/
│   ├── .coveragerc
│   ├── .dockerignore
│   ├── .github/
│   │   └── workflows/
│   │       ├── release.yml
│   │       └── test.yml
│   ├── .gitignore
│   ├── README.md
│   ├── README_CN.md
│   ├── SECURITY.md
│   ├── bridge/
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── server.ts
│   │   │   ├── types.d.ts
│   │   │   └── whatsapp.ts
│   │   └── tsconfig.json
│   ├── deploy/
│   │   ├── Dockerfile
│   │   ├── docker/
│   │   │   ├── Dockerfile
│   │   │   ├── README.md
│   │   │   ├── build-image.sh
│   │   │   ├── build-multiarch.sh
│   │   │   ├── deploy.sh
│   │   │   ├── deploy_langfuse.sh
│   │   │   ├── docker-entrypoint.sh
│   │   │   ├── image_upload.example.yaml
│   │   │   ├── image_upload.sh
│   │   │   ├── langfuse/
│   │   │   │   └── docker-compose.yml
│   │   │   └── stop.sh
│   │   ├── ecs/
│   │   │   └── README.md
│   │   └── vke/
│   │       ├── README.md
│   │       ├── deploy.sh
│   │       ├── k8s/
│   │       │   ├── deployment.yaml
│   │       │   ├── pvc-nas-example.yaml
│   │       │   ├── pvc-tos-example.yaml
│   │       │   └── pvc-tos.yaml
│   │       └── vke_deploy.example.yaml
│   ├── docs/
│   │   ├── CHANNEL.md
│   │   ├── openclaw-plugin-analysis.md
│   │   └── rfc-openviking-cli-ov-chat.md
│   ├── eval/
│   │   ├── locomo/
│   │   │   ├── judge.py
│   │   │   ├── run_eval.py
│   │   │   └── stat_judge_result.py
│   │   └── skillsbench/
│   │       └── skill_bench_eval.py
│   ├── license/
│   │   └── LICENSE
│   ├── package.json
│   ├── scripts/
│   │   ├── clean_vikingbot.sh
│   │   ├── restart_openviking_server.sh
│   │   ├── start_vikingbot_in_ecs.sh
│   │   └── test_all.sh
│   ├── tests/
│   │   ├── conftest.py
│   │   ├── example.py
│   │   ├── experience_data_mini.json
│   │   └── test_chat_functionality.py
│   ├── vikingbot/
│   │   ├── __init__.py
│   │   ├── __main__.py
│   │   ├── agent/
│   │   │   ├── __init__.py
│   │   │   ├── context.py
│   │   │   ├── loop.py
│   │   │   ├── memory.py
│   │   │   ├── skills.py
│   │   │   ├── subagent.py
│   │   │   └── tools/
│   │   │       ├── __init__.py
│   │   │       ├── base.py
│   │   │       ├── cron.py
│   │   │       ├── factory.py
│   │   │       ├── filesystem.py
│   │   │       ├── image.py
│   │   │       ├── message.py
│   │   │       ├── ov_file.py
│   │   │       ├── registry.py
│   │   │       ├── shell.py
│   │   │       ├── spawn.py
│   │   │       ├── web.py
│   │   │       └── websearch/
│   │   │           ├── __init__.py
│   │   │           ├── base.py
│   │   │           ├── brave.py
│   │   │           ├── ddgs.py
│   │   │           ├── exa.py
│   │   │           ├── registry.py
│   │   │           └── tavily.py
│   │   ├── bus/
│   │   │   ├── __init__.py
│   │   │   ├── events.py
│   │   │   └── queue.py
│   │   ├── channels/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── chat.py
│   │   │   ├── dingtalk.py
│   │   │   ├── discord.py
│   │   │   ├── email.py
│   │   │   ├── feishu.py
│   │   │   ├── manager.py
│   │   │   ├── mochat.py
│   │   │   ├── openapi.py
│   │   │   ├── openapi_models.py
│   │   │   ├── qq.py
│   │   │   ├── single_turn.py
│   │   │   ├── slack.py
│   │   │   ├── telegram.py
│   │   │   ├── utils.py
│   │   │   └── whatsapp.py
│   │   ├── cli/
│   │   │   ├── __init__.py
│   │   │   └── commands.py
│   │   ├── config/
│   │   │   ├── __init__.py
│   │   │   ├── loader.py
│   │   │   └── schema.py
│   │   ├── console/
│   │   │   ├── README_GRADIO.md
│   │   │   ├── __init__.py
│   │   │   └── web_console.py
│   │   ├── cron/
│   │   │   ├── __init__.py
│   │   │   ├── service.py
│   │   │   └── types.py
│   │   ├── heartbeat/
│   │   │   ├── __init__.py
│   │   │   └── service.py
│   │   ├── hooks/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── builtins/
│   │   │   │   ├── __init__.py
│   │   │   │   └── openviking_hooks.py
│   │   │   └── manager.py
│   │   ├── integrations/
│   │   │   ├── __init__.py
│   │   │   └── langfuse.py
│   │   ├── openviking_mount/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── fuse_finder.py
│   │   │   ├── fuse_proxy.py
│   │   │   ├── fuse_simple.py
│   │   │   ├── fuse_simple_debug.py
│   │   │   ├── manager.py
│   │   │   ├── mount.py
│   │   │   ├── ov_server.py
│   │   │   ├── session_integration.py
│   │   │   ├── user_apikey_manager.py
│   │   │   └── viking_fuse.py
│   │   ├── providers/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── litellm_provider.py
│   │   │   ├── registry.py
│   │   │   └── transcription.py
│   │   ├── sandbox/
│   │   │   ├── __init__.py
│   │   │   ├── backends/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── aiosandbox.py
│   │   │   │   ├── direct.py
│   │   │   │   ├── opensandbox.py
│   │   │   │   ├── srt-wrapper.mjs
│   │   │   │   └── srt.py
│   │   │   ├── base.py
│   │   │   └── manager.py
│   │   ├── session/
│   │   │   ├── __init__.py
│   │   │   └── manager.py
│   │   ├── tests/
│   │   │   ├── __init__.py
│   │   │   ├── integration/
│   │   │   │   └── __init__.py
│   │   │   └── unit/
│   │   │       ├── __init__.py
│   │   │       ├── test_agent/
│   │   │       │   └── __init__.py
│   │   │       ├── test_bus/
│   │   │       │   └── __init__.py
│   │   │       ├── test_channels/
│   │   │       │   └── __init__.py
│   │   │       └── test_config/
│   │   │           └── __init__.py
│   │   └── utils/
│   │       ├── __init__.py
│   │       ├── helpers.py
│   │       └── tracing.py
│   └── workspace/
│       ├── HEARTBEAT.md
│       ├── SOUL.md
│       ├── TOOLS.md
│       ├── USER.md
│       ├── memory/
│       │   └── MEMORY.md
│       └── skills/
│           ├── README.md
│           ├── cron/
│           │   └── SKILL.md
│           ├── github/
│           │   └── SKILL.md
│           ├── github-proxy/
│           │   ├── SKILL.md
│           │   └── scripts/
│           │       └── convert_url.py
│           ├── opencode/
│           │   ├── SKILL.md
│           │   ├── list_sessions.py
│           │   ├── opencode_utils.py
│           │   └── status.json
│           ├── skill-creator/
│           │   └── SKILL.md
│           ├── summarize/
│           │   └── SKILL.md
│           ├── tmux/
│           │   ├── SKILL.md
│           │   └── scripts/
│           │       ├── find-sessions.sh
│           │       └── wait-for-text.sh
│           └── weather/
│               └── SKILL.md
├── build_support/
│   ├── __init__.py
│   └── x86_profiles.py
├── crates/
│   └── ov_cli/
│       ├── Cargo.toml
│       ├── README.md
│       ├── install.sh
│       ├── src/
│       │   ├── client.rs
│       │   ├── commands/
│       │   │   ├── admin.rs
│       │   │   ├── chat.rs
│       │   │   ├── content.rs
│       │   │   ├── filesystem.rs
│       │   │   ├── mod.rs
│       │   │   ├── observer.rs
│       │   │   ├── pack.rs
│       │   │   ├── relations.rs
│       │   │   ├── resources.rs
│       │   │   ├── search.rs
│       │   │   ├── session.rs
│       │   │   └── system.rs
│       │   ├── config.rs
│       │   ├── error.rs
│       │   ├── main.rs
│       │   ├── output.rs
│       │   ├── tui/
│       │   │   ├── app.rs
│       │   │   ├── event.rs
│       │   │   ├── mod.rs
│       │   │   ├── tree.rs
│       │   │   └── ui.rs
│       │   └── utils.rs
│       └── test_ov.sh
├── deploy/
│   └── helm/
│       ├── README.md
│       └── openviking/
│           ├── .helmignore
│           ├── Chart.yaml
│           ├── templates/
│           │   ├── NOTES.txt
│           │   ├── _helpers.tpl
│           │   ├── configmap.yaml
│           │   ├── deployment.yaml
│           │   ├── ingress.yaml
│           │   ├── pvc.yaml
│           │   └── service.yaml
│           └── values.yaml
├── docker-compose.yml
├── docs/
│   ├── design/
│   │   ├── multi-tenant-design.md
│   │   └── openclaw-integration.md
│   ├── en/
│   │   ├── about/
│   │   │   ├── 01-about-us.md
│   │   │   ├── 02-changelog.md
│   │   │   └── 03-roadmap.md
│   │   ├── api/
│   │   │   ├── 01-overview.md
│   │   │   ├── 02-resources.md
│   │   │   ├── 03-filesystem.md
│   │   │   ├── 04-skills.md
│   │   │   ├── 05-sessions.md
│   │   │   ├── 06-retrieval.md
│   │   │   ├── 07-system.md
│   │   │   └── 08-admin.md
│   │   ├── concepts/
│   │   │   ├── 01-architecture.md
│   │   │   ├── 02-context-types.md
│   │   │   ├── 03-context-layers.md
│   │   │   ├── 04-viking-uri.md
│   │   │   ├── 05-storage.md
│   │   │   ├── 06-extraction.md
│   │   │   ├── 07-retrieval.md
│   │   │   ├── 08-session.md
│   │   │   └── 09-transaction.md
│   │   ├── faq/
│   │   │   └── faq.md
│   │   ├── getting-started/
│   │   │   ├── 01-introduction.md
│   │   │   ├── 02-quickstart.md
│   │   │   └── 03-quickstart-server.md
│   │   └── guides/
│   │       ├── 01-configuration.md
│   │       ├── 02-volcengine-purchase-guide.md
│   │       ├── 03-deployment.md
│   │       ├── 04-authentication.md
│   │       ├── 05-monitoring.md
│   │       ├── 06-mcp-integration.md
│   │       └── 07-operation-telemetry.md
│   └── zh/
│       ├── about/
│       │   ├── 01-about-us.md
│       │   ├── 02-changelog.md
│       │   └── 03-roadmap.md
│       ├── api/
│       │   ├── 01-overview.md
│       │   ├── 02-resources.md
│       │   ├── 03-filesystem.md
│       │   ├── 04-skills.md
│       │   ├── 05-sessions.md
│       │   ├── 06-retrieval.md
│       │   ├── 07-system.md
│       │   └── 08-admin.md
│       ├── concepts/
│       │   ├── 01-architecture.md
│       │   ├── 02-context-types.md
│       │   ├── 03-context-layers.md
│       │   ├── 04-viking-uri.md
│       │   ├── 05-storage.md
│       │   ├── 06-extraction.md
│       │   ├── 07-retrieval.md
│       │   ├── 08-session.md
│       │   └── 09-transaction.md
│       ├── faq/
│       │   └── faq.md
│       ├── getting-started/
│       │   ├── 01-introduction.md
│       │   ├── 02-quickstart.md
│       │   └── 03-quickstart-server.md
│       └── guides/
│           ├── 01-configuration.md
│           ├── 02-volcengine-purchase-guide.md
│           ├── 03-deployment.md
│           ├── 04-authentication.md
│           ├── 05-monitoring.md
│           ├── 06-mcp-integration.md
│           └── 07-operation-telemetry.md
├── examples/
│   ├── claude-memory-plugin/
│   │   ├── .claude-plugin/
│   │   │   └── plugin.json
│   │   ├── README.md
│   │   ├── hooks/
│   │   │   ├── common.sh
│   │   │   ├── hooks.json
│   │   │   ├── session-end.sh
│   │   │   ├── session-start.sh
│   │   │   ├── stop.sh
│   │   │   └── user-prompt-submit.sh
│   │   ├── scripts/
│   │   │   ├── ov_memory.py
│   │   │   └── run_e2e_claude_session.sh
│   │   └── skills/
│   │       └── memory-recall/
│   │           └── SKILL.md
│   ├── cloud/
│   │   ├── .gitignore
│   │   ├── GUIDE.md
│   │   ├── alice.py
│   │   ├── bob.py
│   │   ├── ov.conf.example
│   │   └── setup_users.py
│   ├── common/
│   │   ├── __init__.py
│   │   ├── boring_logging_config.py
│   │   ├── recipe.py
│   │   └── resource_manager.py
│   ├── k8s-helm/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── README.md
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── secret.yaml
│   │   │   └── service.yaml
│   │   └── values.yaml
│   ├── mcp-query/
│   │   ├── README.md
│   │   ├── ov.conf.example
│   │   ├── pyproject.toml
│   │   └── server.py
│   ├── misc/
│   │   └── memory_demo.py
│   ├── multi_tenant/
│   │   ├── README.md
│   │   ├── admin_workflow.py
│   │   ├── admin_workflow.sh
│   │   ├── ov.conf.example
│   │   └── pyproject.toml
│   ├── openclaw-plugin/
│   │   ├── .gitignore
│   │   ├── INSTALL-AGENT.md
│   │   ├── INSTALL-ZH.md
│   │   ├── INSTALL.md
│   │   ├── README.md
│   │   ├── client.ts
│   │   ├── config.ts
│   │   ├── context-engine.ts
│   │   ├── demo-memory-ajie.py
│   │   ├── demo-memory-xiaomei.py
│   │   ├── index.ts
│   │   ├── install.ps1
│   │   ├── install.sh
│   │   ├── memory-ranking.ts
│   │   ├── openclaw.plugin.json
│   │   ├── package.json
│   │   ├── process-manager.ts
│   │   ├── setup-helper/
│   │   │   ├── install.js
│   │   │   └── package.json
│   │   ├── skills/
│   │   │   └── install-openviking-memory/
│   │   │       └── SKILL.md
│   │   ├── text-utils.ts
│   │   └── tsconfig.json
│   ├── opencode/
│   │   └── plugin/
│   │       ├── README.md
│   │       ├── index.mjs
│   │       ├── package.json
│   │       └── skills/
│   │           └── openviking/
│   │               └── SKILL.md
│   ├── opencode-memory-plugin/
│   │   ├── .gitignore
│   │   ├── INSTALL-ZH.md
│   │   ├── README.md
│   │   ├── openviking-config.example.json
│   │   └── openviking-memory.ts
│   ├── ov.conf.example
│   ├── ovcli.conf.example
│   ├── quick_start.py
│   ├── server_client/
│   │   ├── README.md
│   │   ├── client_async.py
│   │   ├── client_cli.sh
│   │   ├── client_sync.py
│   │   ├── ov.conf.example
│   │   ├── ovcli.conf.example
│   │   └── pyproject.toml
│   ├── skills/
│   │   ├── ov-add-data/
│   │   │   └── SKILL.md
│   │   ├── ov-search-context/
│   │   │   └── SKILL.md
│   │   └── ov-server-operate/
│   │       └── SKILL.md
│   └── watch_resource_example.py
├── openviking/
│   ├── __init__.py
│   ├── agfs_manager.py
│   ├── async_client.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── local.py
│   │   └── session.py
│   ├── client.py
│   ├── console/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── app.py
│   │   ├── bootstrap.py
│   │   ├── config.py
│   │   └── static/
│   │       ├── app.js
│   │       ├── index.html
│   │       └── styles.css
│   ├── core/
│   │   ├── __init__.py
│   │   ├── building_tree.py
│   │   ├── context.py
│   │   ├── directories.py
│   │   ├── mcp_converter.py
│   │   └── skill_loader.py
│   ├── eval/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── datasets/
│   │   │   └── local_doc_example_glm5.jsonl
│   │   ├── ragas/
│   │   │   ├── __init__.py
│   │   │   ├── analyze_records.py
│   │   │   ├── base.py
│   │   │   ├── generator.py
│   │   │   ├── pipeline.py
│   │   │   ├── play_recorder.py
│   │   │   ├── playback.py
│   │   │   ├── rag_eval.py
│   │   │   ├── record_analysis.py
│   │   │   └── types.py
│   │   └── recorder/
│   │       ├── __init__.py
│   │       ├── async_writer.py
│   │       ├── playback.py
│   │       ├── recorder.py
│   │       ├── recording_client.py
│   │       ├── types.py
│   │       └── wrapper.py
│   ├── message/
│   │   ├── __init__.py
│   │   ├── message.py
│   │   └── part.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── embedder/
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── gemini_embedders.py
│   │   │   ├── jina_embedders.py
│   │   │   ├── minimax_embedders.py
│   │   │   ├── openai_embedders.py
│   │   │   ├── vikingdb_embedders.py
│   │   │   ├── volcengine_embedders.py
│   │   │   └── voyage_embedders.py
│   │   └── vlm/
│   │       ├── __init__.py
│   │       ├── backends/
│   │       │   ├── litellm_vlm.py
│   │       │   ├── openai_vlm.py
│   │       │   └── volcengine_vlm.py
│   │       ├── base.py
│   │       ├── llm.py
│   │       ├── registry.py
│   │       └── token_usage.py
│   ├── parse/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── converter.py
│   │   ├── custom.py
│   │   ├── directory_scan.py
│   │   ├── ovpack/
│   │   │   └── __init__.py
│   │   ├── parsers/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base_parser.py
│   │   │   ├── code/
│   │   │   │   ├── README.md
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ast/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── extractor.py
│   │   │   │   │   ├── languages/
│   │   │   │   │   │   ├── __init__.py
│   │   │   │   │   │   ├── base.py
│   │   │   │   │   │   ├── cpp.py
│   │   │   │   │   │   ├── csharp.py
│   │   │   │   │   │   ├── go.py
│   │   │   │   │   │   ├── java.py
│   │   │   │   │   │   ├── js_ts.py
│   │   │   │   │   │   ├── python.py
│   │   │   │   │   │   └── rust.py
│   │   │   │   │   └── skeleton.py
│   │   │   │   └── code.py
│   │   │   ├── constants.py
│   │   │   ├── directory.py
│   │   │   ├── epub.py
│   │   │   ├── excel.py
│   │   │   ├── html.py
│   │   │   ├── legacy_doc.py
│   │   │   ├── markdown.py
│   │   │   ├── media/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── audio.py
│   │   │   │   ├── constants.py
│   │   │   │   ├── image.py
│   │   │   │   ├── utils.py
│   │   │   │   └── video.py
│   │   │   ├── pdf.py
│   │   │   ├── powerpoint.py
│   │   │   ├── text.py
│   │   │   ├── upload_utils.py
│   │   │   ├── word.py
│   │   │   └── zip_parser.py
│   │   ├── registry.py
│   │   ├── resource_detector/
│   │   │   ├── __init__.py
│   │   │   ├── detect_info.py
│   │   │   ├── recursive.py
│   │   │   ├── size.py
│   │   │   └── visit.py
│   │   ├── tree_builder.py
│   │   └── vlm.py
│   ├── prompts/
│   │   ├── __init__.py
│   │   ├── manager.py
│   │   └── templates/
│   │       ├── compression/
│   │       │   ├── dedup_decision.yaml
│   │       │   ├── field_compress.yaml
│   │       │   ├── memory_extraction.yaml
│   │       │   ├── memory_merge.yaml
│   │       │   ├── memory_merge_bundle.yaml
│   │       │   └── structured_summary.yaml
│   │       ├── indexing/
│   │       │   └── relevance_scoring.yaml
│   │       ├── parsing/
│   │       │   ├── chapter_analysis.yaml
│   │       │   ├── context_generation.yaml
│   │       │   ├── image_summary.yaml
│   │       │   └── semantic_grouping.yaml
│   │       ├── processing/
│   │       │   ├── interaction_learning.yaml
│   │       │   ├── strategy_extraction.yaml
│   │       │   └── tool_chain_analysis.yaml
│   │       ├── retrieval/
│   │       │   └── intent_analysis.yaml
│   │       ├── semantic/
│   │       │   ├── code_ast_summary.yaml
│   │       │   ├── code_summary.yaml
│   │       │   ├── document_summary.yaml
│   │       │   ├── file_summary.yaml
│   │       │   └── overview_generation.yaml
│   │       ├── skill/
│   │       │   └── overview_generation.yaml
│   │       ├── test/
│   │       │   └── skill_test_generation.yaml
│   │       └── vision/
│   │           ├── batch_filtering.yaml
│   │           ├── image_filtering.yaml
│   │           ├── image_understanding.yaml
│   │           ├── page_understanding.yaml
│   │           ├── page_understanding_batch.yaml
│   │           ├── table_understanding.yaml
│   │           └── unified_analysis.yaml
│   ├── pyagfs/
│   │   ├── __init__.py
│   │   ├── binding_client.py
│   │   ├── client.py
│   │   ├── exceptions.py
│   │   └── helpers.py
│   ├── resource/
│   │   ├── __init__.py
│   │   ├── watch_manager.py
│   │   └── watch_scheduler.py
│   ├── retrieve/
│   │   ├── __init__.py
│   │   ├── hierarchical_retriever.py
│   │   ├── intent_analyzer.py
│   │   ├── memory_lifecycle.py
│   │   └── retrieval_stats.py
│   ├── server/
│   │   ├── __init__.py
│   │   ├── api_keys.py
│   │   ├── app.py
│   │   ├── auth.py
│   │   ├── bootstrap.py
│   │   ├── config.py
│   │   ├── dependencies.py
│   │   ├── identity.py
│   │   ├── models.py
│   │   ├── routers/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── bot.py
│   │   │   ├── content.py
│   │   │   ├── debug.py
│   │   │   ├── filesystem.py
│   │   │   ├── observer.py
│   │   │   ├── pack.py
│   │   │   ├── relations.py
│   │   │   ├── resources.py
│   │   │   ├── search.py
│   │   │   ├── sessions.py
│   │   │   ├── system.py
│   │   │   └── tasks.py
│   │   └── telemetry.py
│   ├── service/
│   │   ├── __init__.py
│   │   ├── core.py
│   │   ├── debug_service.py
│   │   ├── fs_service.py
│   │   ├── pack_service.py
│   │   ├── relation_service.py
│   │   ├── resource_service.py
│   │   ├── search_service.py
│   │   ├── session_service.py
│   │   └── task_tracker.py
│   ├── session/
│   │   ├── __init__.py
│   │   ├── compressor.py
│   │   ├── memory_archiver.py
│   │   ├── memory_deduplicator.py
│   │   ├── memory_extractor.py
│   │   ├── session.py
│   │   └── tool_skill_utils.py
│   ├── storage/
│   │   ├── __init__.py
│   │   ├── collection_schemas.py
│   │   ├── errors.py
│   │   ├── expr.py
│   │   ├── local_fs.py
│   │   ├── observers/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base_observer.py
│   │   │   ├── lock_observer.py
│   │   │   ├── queue_observer.py
│   │   │   ├── retrieval_observer.py
│   │   │   ├── vikingdb_observer.py
│   │   │   └── vlm_observer.py
│   │   ├── queuefs/
│   │   │   ├── __init__.py
│   │   │   ├── embedding_msg.py
│   │   │   ├── embedding_msg_converter.py
│   │   │   ├── embedding_queue.py
│   │   │   ├── embedding_tracker.py
│   │   │   ├── named_queue.py
│   │   │   ├── queue_manager.py
│   │   │   ├── semantic_dag.py
│   │   │   ├── semantic_msg.py
│   │   │   ├── semantic_processor.py
│   │   │   └── semantic_queue.py
│   │   ├── transaction/
│   │   │   ├── __init__.py
│   │   │   ├── lock_context.py
│   │   │   ├── lock_handle.py
│   │   │   ├── lock_manager.py
│   │   │   ├── path_lock.py
│   │   │   └── redo_log.py
│   │   ├── vectordb/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── collection/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── collection.py
│   │   │   │   ├── http_collection.py
│   │   │   │   ├── local_collection.py
│   │   │   │   ├── result.py
│   │   │   │   ├── vikingdb_clients.py
│   │   │   │   ├── vikingdb_collection.py
│   │   │   │   ├── volcengine_clients.py
│   │   │   │   └── volcengine_collection.py
│   │   │   ├── engine/
│   │   │   │   └── __init__.py
│   │   │   ├── index/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── index.py
│   │   │   │   └── local_index.py
│   │   │   ├── meta/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── collection_meta.py
│   │   │   │   ├── dict.py
│   │   │   │   ├── index_meta.py
│   │   │   │   └── local_dict.py
│   │   │   ├── project/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── http_project.py
│   │   │   │   ├── local_project.py
│   │   │   │   ├── project.py
│   │   │   │   ├── project_group.py
│   │   │   │   ├── vikingdb_project.py
│   │   │   │   └── volcengine_project.py
│   │   │   ├── service/
│   │   │   │   ├── README_FASTAPI.md
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api_fastapi.py
│   │   │   │   ├── app_models.py
│   │   │   │   ├── code.py
│   │   │   │   └── server_fastapi.py
│   │   │   ├── store/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── bytes_row.py
│   │   │   │   ├── data.py
│   │   │   │   ├── file_store.py
│   │   │   │   ├── local_store.py
│   │   │   │   ├── serializable.py
│   │   │   │   ├── store.py
│   │   │   │   └── store_manager.py
│   │   │   ├── utils/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api_utils.py
│   │   │   │   ├── config_utils.py
│   │   │   │   ├── constants.py
│   │   │   │   ├── data_processor.py
│   │   │   │   ├── data_utils.py
│   │   │   │   ├── dict_utils.py
│   │   │   │   ├── file_utils.py
│   │   │   │   ├── id_generator.py
│   │   │   │   ├── logging_init.py
│   │   │   │   ├── stale_lock.py
│   │   │   │   ├── str_to_uint64.py
│   │   │   │   └── validation.py
│   │   │   └── vectorize/
│   │   │       ├── __init__.py
│   │   │       ├── base.py
│   │   │       ├── vectorizer.py
│   │   │       ├── vectorizer_factory.py
│   │   │       └── volcengine_vectorizer.py
│   │   ├── vectordb_adapters/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── factory.py
│   │   │   ├── http_adapter.py
│   │   │   ├── local_adapter.py
│   │   │   ├── vikingdb_private_adapter.py
│   │   │   └── volcengine_adapter.py
│   │   ├── viking_fs.py
│   │   ├── viking_vector_index_backend.py
│   │   └── vikingdb_manager.py
│   ├── sync_client.py
│   ├── telemetry/
│   │   ├── __init__.py
│   │   ├── backends/
│   │   │   ├── __init__.py
│   │   │   └── memory.py
│   │   ├── context.py
│   │   ├── execution.py
│   │   ├── operation.py
│   │   ├── registry.py
│   │   ├── request.py
│   │   ├── resource_summary.py
│   │   ├── runtime.py
│   │   └── snapshot.py
│   └── utils/
│       ├── __init__.py
│       ├── agfs_utils.py
│       ├── code_hosting_utils.py
│       ├── embedding_utils.py
│       ├── media_processor.py
│       ├── process_lock.py
│       ├── resource_processor.py
│       ├── skill_processor.py
│       ├── summarizer.py
│       └── time_utils.py
├── openviking_cli/
│   ├── __init__.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── http.py
│   │   └── sync_http.py
│   ├── exceptions.py
│   ├── retrieve/
│   │   ├── __init__.py
│   │   └── types.py
│   ├── rust_cli.py
│   ├── server_bootstrap.py
│   ├── session/
│   │   ├── __init__.py
│   │   └── user_id.py
│   └── utils/
│       ├── __init__.py
│       ├── async_utils.py
│       ├── config/
│       │   ├── __init__.py
│       │   ├── agfs_config.py
│       │   ├── config_loader.py
│       │   ├── consts.py
│       │   ├── embedding_config.py
│       │   ├── log_config.py
│       │   ├── open_viking_config.py
│       │   ├── parser_config.py
│       │   ├── rerank_config.py
│       │   ├── storage_config.py
│       │   ├── transaction_config.py
│       │   ├── vectordb_config.py
│       │   └── vlm_config.py
│       ├── downloader.py
│       ├── extractor.py
│       ├── llm.py
│       ├── logger.py
│       ├── rerank.py
│       ├── rerank_openai.py
│       ├── storage.py
│       └── uri.py
├── pyproject.toml
├── setup.py
├── src/
│   ├── CMakeLists.txt
│   ├── common/
│   │   ├── ann_utils.h
│   │   ├── io_utils.h
│   │   ├── json_utils.h
│   │   ├── log_utils.cpp
│   │   ├── log_utils.h
│   │   ├── string_utils.h
│   │   └── zip_sort.h
│   ├── cpu_feature_probe.cpp
│   ├── index/
│   │   ├── common_structs.h
│   │   ├── detail/
│   │   │   ├── fields_dict.h
│   │   │   ├── index_manager_impl.cpp
│   │   │   ├── index_manager_impl.h
│   │   │   ├── meta/
│   │   │   │   ├── bruteforce_meta.h
│   │   │   │   ├── manager_meta.h
│   │   │   │   ├── scalar_index_meta.cpp
│   │   │   │   ├── scalar_index_meta.h
│   │   │   │   ├── vector_index_meta.cpp
│   │   │   │   └── vector_index_meta.h
│   │   │   ├── scalar/
│   │   │   │   ├── bitmap_holder/
│   │   │   │   │   ├── bitmap.cpp
│   │   │   │   │   ├── bitmap.h
│   │   │   │   │   ├── bitmap_field_group.cpp
│   │   │   │   │   ├── bitmap_field_group.h
│   │   │   │   │   ├── bitmap_utils.h
│   │   │   │   │   ├── dir_index.cpp
│   │   │   │   │   ├── dir_index.h
│   │   │   │   │   ├── ranged_map.cpp
│   │   │   │   │   └── ranged_map.h
│   │   │   │   ├── filter/
│   │   │   │   │   ├── filter_ops.cpp
│   │   │   │   │   ├── filter_ops.h
│   │   │   │   │   ├── op_base.cpp
│   │   │   │   │   ├── op_base.h
│   │   │   │   │   ├── sort_ops.cpp
│   │   │   │   │   └── sort_ops.h
│   │   │   │   ├── scalar_index.cpp
│   │   │   │   └── scalar_index.h
│   │   │   ├── search_context.h
│   │   │   └── vector/
│   │   │       ├── common/
│   │   │       │   ├── bruteforce.h
│   │   │       │   ├── quantization_int8.h
│   │   │       │   ├── quantizer.h
│   │   │       │   ├── space_int8.h
│   │   │       │   ├── space_ip.h
│   │   │       │   ├── space_l2.h
│   │   │       │   └── vector_base.h
│   │   │       ├── sparse_retrieval/
│   │   │       │   ├── common.h
│   │   │       │   ├── sparse_data_holder.h
│   │   │       │   ├── sparse_datapoint.cpp
│   │   │       │   ├── sparse_datapoint.h
│   │   │       │   ├── sparse_dataset.h
│   │   │       │   ├── sparse_distance_measure.h
│   │   │       │   ├── sparse_row_index.cpp
│   │   │       │   └── sparse_row_index.h
│   │   │       ├── vector_index_adapter.h
│   │   │       └── vector_recall.h
│   │   ├── index_engine.cpp
│   │   ├── index_engine.h
│   │   └── index_manager.h
│   ├── py_accessors.h
│   ├── pybind11_interface.cpp
│   └── store/
│       ├── bytes_row.cpp
│       ├── bytes_row.h
│       ├── common_structs.h
│       ├── kv_store.h
│       ├── persist_store.cpp
│       ├── persist_store.h
│       ├── volatile_store.cpp
│       └── volatile_store.h
├── tests/
│   ├── README.md
│   ├── __init__.py
│   ├── agfs/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_fs_binding.py
│   │   ├── test_fs_binding_s3.py
│   │   ├── test_fs_local.py
│   │   └── test_fs_s3.py
│   ├── cli/
│   │   ├── conftest.py
│   │   └── test_user_identifier.py
│   ├── client/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_chat_integration.py
│   │   ├── test_file_operations.py
│   │   ├── test_filesystem.py
│   │   ├── test_import_export.py
│   │   ├── test_lifecycle.py
│   │   ├── test_relations.py
│   │   ├── test_resource_management.py
│   │   ├── test_search.py
│   │   ├── test_skill_management.py
│   │   └── test_windows_path_handling.py
│   ├── conftest.py
│   ├── engine/
│   │   ├── CMakeLists.txt
│   │   ├── test_common.cpp
│   │   └── test_index_engine.cpp
│   ├── eval/
│   │   ├── test_ragas_basic.py
│   │   ├── test_ragas_eval.py
│   │   └── test_ragas_validation.py
│   ├── integration/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_add_resource_index.py
│   │   ├── test_full_workflow.py
│   │   ├── test_gemini_e2e.py
│   │   ├── test_gemini_embedding_it.py
│   │   ├── test_gemini_openviking_it.py
│   │   ├── test_http_integration.py
│   │   ├── test_quick_start_lite.py
│   │   └── test_watch_e2e.py
│   ├── misc/
│   │   ├── test_code_parser.py
│   │   ├── test_config_validation.py
│   │   ├── test_debug_service.py
│   │   ├── test_embedding_input_type.py
│   │   ├── test_extract_zip.py
│   │   ├── test_mkdir.py
│   │   ├── test_port_check.py
│   │   ├── test_process_lock.py
│   │   ├── test_rerank_openai.py
│   │   ├── test_resource_processor_mv.py
│   │   ├── test_semantic_config.py
│   │   ├── test_tree_builder_dedup.py
│   │   ├── test_vectordb_engine_loader.py
│   │   ├── test_vikingdb_observer.py
│   │   ├── test_vikingfs_find_without_rerank.py
│   │   ├── test_vikingfs_uri_guard.py
│   │   └── test_x86_profiles.py
│   ├── models/
│   │   ├── test_embedding_telemetry_usage.py
│   │   └── test_vlm_strip_think_tags.py
│   ├── parse/
│   │   ├── __init__.py
│   │   ├── test_add_directory.py
│   │   ├── test_ast_extractor.py
│   │   ├── test_directory_parser_routing.py
│   │   ├── test_directory_scan.py
│   │   ├── test_filename_safety.py
│   │   ├── test_html_parser_utils.py
│   │   ├── test_pdf_bookmark_extraction.py
│   │   └── test_url_filename_preservation.py
│   ├── resource/
│   │   ├── __init__.py
│   │   ├── test_watch_manager.py
│   │   └── test_watch_scheduler.py
│   ├── retrieve/
│   │   ├── test_hierarchical_retriever_rerank.py
│   │   └── test_hierarchical_retriever_target_dirs.py
│   ├── server/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_admin_api.py
│   │   ├── test_api_content.py
│   │   ├── test_api_filesystem.py
│   │   ├── test_api_key_manager.py
│   │   ├── test_api_observer.py
│   │   ├── test_api_relations.py
│   │   ├── test_api_resources.py
│   │   ├── test_api_search.py
│   │   ├── test_api_sessions.py
│   │   ├── test_auth.py
│   │   ├── test_error_scenarios.py
│   │   ├── test_http_client_sdk.py
│   │   ├── test_identity.py
│   │   └── test_server_health.py
│   ├── service/
│   │   ├── test_resource_service_watch.py
│   │   └── test_watch_recovery.py
│   ├── session/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_memory_dedup_actions.py
│   │   ├── test_memory_extractor_language.py
│   │   ├── test_memory_extractor_response_types.py
│   │   ├── test_session_commit.py
│   │   ├── test_session_compressor_vikingdb.py
│   │   ├── test_session_context.py
│   │   ├── test_session_lifecycle.py
│   │   ├── test_session_messages.py
│   │   └── test_session_usage.py
│   ├── storage/
│   │   ├── mock_backend.py
│   │   ├── test_collection_schemas.py
│   │   ├── test_embedding_msg_converter_tenant.py
│   │   ├── test_semantic_dag_skip_files.py
│   │   ├── test_semantic_dag_stats.py
│   │   ├── test_semantic_processor_mv_vector_store.py
│   │   ├── test_stale_lock.py
│   │   ├── test_vectordb_adaptor.py
│   │   └── test_vectordb_collection_loading.py
│   ├── telemetry/
│   │   ├── test_execution.py
│   │   ├── test_layering_rules.py
│   │   └── test_resource_summary.py
│   ├── test_code_hosting_utils.py
│   ├── test_config_loader.py
│   ├── test_edge_cases.py
│   ├── test_edge_cases_simple.py
│   ├── test_memory_lifecycle.py
│   ├── test_session_async_commit.py
│   ├── test_session_task_tracking.py
│   ├── test_task_tracker.py
│   ├── test_telemetry_runtime.py
│   ├── test_upload_utils.py
│   ├── transaction/
│   │   ├── __init__.py
│   │   ├── conftest.py
│   │   ├── test_concurrent_lock.py
│   │   ├── test_e2e.py
│   │   ├── test_lock_context.py
│   │   ├── test_lock_manager.py
│   │   ├── test_path_lock.py
│   │   └── test_redo_log.py
│   ├── unit/
│   │   ├── __init__.py
│   │   ├── retrieve/
│   │   │   └── test_retrieval_stats.py
│   │   ├── session/
│   │   │   ├── test_deduplicator_uri.py
│   │   │   └── test_memory_archiver.py
│   │   ├── test_embedding_config_gemini.py
│   │   ├── test_embedding_config_voyage.py
│   │   ├── test_extra_headers_embedding.py
│   │   ├── test_extra_headers_vlm.py
│   │   ├── test_gemini_embedder.py
│   │   ├── test_jina_embedder.py
│   │   ├── test_minimax_embedder_simple.py
│   │   ├── test_ollama_embedding_factory.py
│   │   ├── test_openai_embedder.py
│   │   ├── test_skill_processor_none.py
│   │   ├── test_stream_config_vlm.py
│   │   ├── test_time_utils.py
│   │   ├── test_uri_short_format.py
│   │   ├── test_vlm_response_formats.py
│   │   ├── test_voyage_embedder.py
│   │   └── tool_skill/
│   │       ├── test_tool_skill_calibration.py
│   │       ├── test_tool_skill_memory_guardrails.py
│   │       └── test_tool_skill_utils.py
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── mock_agfs.py
│   │   └── mock_context.py
│   └── vectordb/
│       ├── benchmark_stress.py
│       ├── test_bytes_row.py
│       ├── test_collection_large_scale.py
│       ├── test_crash_recovery.py
│       ├── test_data_processor.py
│       ├── test_filter_ops.py
│       ├── test_openviking_vectordb.py
│       ├── test_project_group.py
│       ├── test_pydantic_validation.py
│       ├── test_recall.py
│       └── test_vikingdb_project.py
└── third_party/
    ├── agfs/
    │   ├── .github/
    │   │   └── workflows/
    │   │       └── daily-build.yml
    │   ├── .gitignore
    │   ├── LICENSE
    │   ├── README.md
    │   ├── agfs-fuse/
    │   │   ├── .gitignore
    │   │   ├── Makefile
    │   │   ├── README.md
    │   │   ├── cmd/
    │   │   │   └── agfs-fuse/
    │   │   │       └── main.go
    │   │   ├── go.mod
    │   │   ├── go.sum
    │   │   └── pkg/
    │   │       ├── cache/
    │   │       │   ├── cache.go
    │   │       │   └── cache_test.go
    │   │       ├── fusefs/
    │   │       │   ├── file.go
    │   │       │   ├── fs.go
    │   │       │   ├── handles.go
    │   │       │   ├── handles_test.go
    │   │       │   └── node.go
    │   │       └── version/
    │   │           └── version.go
    │   ├── agfs-mcp/
    │   │   ├── .gitignore
    │   │   ├── .mcp.json
    │   │   ├── README.md
    │   │   ├── demos/
    │   │   │   ├── hackernews_research.py
    │   │   │   ├── parallel_research.py
    │   │   │   ├── start_agents.sh
    │   │   │   ├── start_agents_tmux.sh
    │   │   │   ├── stop_agents.sh
    │   │   │   ├── stop_agents_tmux.sh
    │   │   │   └── task_loop.py
    │   │   ├── pyproject.toml
    │   │   └── src/
    │   │       └── agfs_mcp/
    │   │           ├── __init__.py
    │   │           └── server.py
    │   ├── agfs-sdk/
    │   │   ├── go/
    │   │   │   ├── README.md
    │   │   │   ├── client.go
    │   │   │   ├── client_test.go
    │   │   │   ├── go.mod
    │   │   │   └── types.go
    │   │   └── python/
    │   │       ├── README.md
    │   │       ├── examples/
    │   │       │   ├── advanced_usage.py
    │   │       │   ├── basic_usage.py
    │   │       │   └── helpers_usage.py
    │   │       ├── pyagfs/
    │   │       │   ├── __init__.py
    │   │       │   ├── binding_client.py
    │   │       │   ├── client.py
    │   │       │   ├── exceptions.py
    │   │       │   └── helpers.py
    │   │       └── pyproject.toml
    │   ├── agfs-shell/
    │   │   ├── .gitignore
    │   │   ├── Makefile
    │   │   ├── README.md
    │   │   ├── agfs_shell/
    │   │   │   ├── __init__.py
    │   │   │   ├── arg_parser.py
    │   │   │   ├── ast_nodes.py
    │   │   │   ├── builtins.py
    │   │   │   ├── cli.py
    │   │   │   ├── command_decorators.py
    │   │   │   ├── commands/
    │   │   │   │   ├── __init__.py
    │   │   │   │   ├── base.py
    │   │   │   │   ├── basename.py
    │   │   │   │   ├── break_cmd.py
    │   │   │   │   ├── cat.py
    │   │   │   │   ├── cd.py
    │   │   │   │   ├── continue_cmd.py
    │   │   │   │   ├── cp.py
    │   │   │   │   ├── cut.py
    │   │   │   │   ├── date.py
    │   │   │   │   ├── dirname.py
    │   │   │   │   ├── download.py
    │   │   │   │   ├── echo.py
    │   │   │   │   ├── env.py
    │   │   │   │   ├── exit.py
    │   │   │   │   ├── export.py
    │   │   │   │   ├── false.py
    │   │   │   │   ├── grep.py
    │   │   │   │   ├── head.py
    │   │   │   │   ├── help.py
    │   │   │   │   ├── jq.py
    │   │   │   │   ├── llm.py
    │   │   │   │   ├── local.py
    │   │   │   │   ├── ls.py
    │   │   │   │   ├── mkdir.py
    │   │   │   │   ├── mount.py
    │   │   │   │   ├── mv.py
    │   │   │   │   ├── plugins.py
    │   │   │   │   ├── pwd.py
    │   │   │   │   ├── return_cmd.py
    │   │   │   │   ├── rev.py
    │   │   │   │   ├── rm.py
    │   │   │   │   ├── sleep.py
    │   │   │   │   ├── sort.py
    │   │   │   │   ├── stat.py
    │   │   │   │   ├── tail.py
    │   │   │   │   ├── tee.py
    │   │   │   │   ├── test.py
    │   │   │   │   ├── touch.py
    │   │   │   │   ├── tr.py
    │   │   │   │   ├── tree.py
    │   │   │   │   ├── true.py
    │   │   │   │   ├── uniq.py
    │   │   │   │   ├── unset.py
    │   │   │   │   ├── upload.py
    │   │   │   │   └── wc.py
    │   │   │   ├── completer.py
    │   │   │   ├── config.py
    │   │   │   ├── control_flow.py
    │   │   │   ├── control_parser.py
    │   │   │   ├── executor.py
    │   │   │   ├── exit_codes.py
    │   │   │   ├── expression.py
    │   │   │   ├── filesystem.py
    │   │   │   ├── lexer.py
    │   │   │   ├── parser.py
    │   │   │   ├── pipeline.py
    │   │   │   ├── process.py
    │   │   │   ├── shell.py
    │   │   │   ├── streams.py
    │   │   │   ├── utils/
    │   │   │   │   ├── __init__.py
    │   │   │   │   └── formatters.py
    │   │   │   └── webapp_server.py
    │   │   ├── build.py
    │   │   ├── examples/
    │   │   │   ├── enqueue_task.as
    │   │   │   └── task_queue_worker.as
    │   │   ├── pyproject.toml
    │   │   ├── scripts/
    │   │   │   └── test_functions.as
    │   │   ├── tests/
    │   │   │   ├── test_builtins.py
    │   │   │   ├── test_parser.py
    │   │   │   └── test_pipeline.py
    │   │   └── webapp/
    │   │       ├── .gitignore
    │   │       ├── index.html
    │   │       ├── package.json
    │   │       ├── setup.sh
    │   │       ├── src/
    │   │       │   ├── App.css
    │   │       │   ├── App.jsx
    │   │       │   ├── components/
    │   │       │   │   ├── ContextMenu.jsx
    │   │       │   │   ├── Editor.jsx
    │   │       │   │   ├── FileTree.jsx
    │   │       │   │   ├── MenuBar.jsx
    │   │       │   │   └── Terminal.jsx
    │   │       │   └── main.jsx
    │   │       └── vite.config.js
    │   └── install.sh
    ├── croaring/
    │   ├── LICENSE
    │   ├── roaring.c
    │   ├── roaring.h
    │   └── roaring.hh
    ├── krl/
    │   ├── CMakeLists.txt
    │   ├── include/
    │   │   ├── krl.h
    │   │   ├── krl_internal.h
    │   │   ├── platform_macros.h
    │   │   └── safe_memory.h
    │   └── src/
    │       ├── IPdistance_simd.cpp
    │       └── L2distance_simd.cpp
    ├── leveldb-1.23/
    │   ├── .appveyor.yml
    │   ├── .clang-format
    │   ├── .gitignore
    │   ├── .gitmodules
    │   ├── .travis.yml
    │   ├── AUTHORS
    │   ├── CMakeLists.txt
    │   ├── CONTRIBUTING.md
    │   ├── LICENSE
    │   ├── NEWS
    │   ├── README.md
    │   ├── TODO
    │   ├── benchmarks/
    │   │   ├── db_bench.cc
    │   │   ├── db_bench_sqlite3.cc
    │   │   └── db_bench_tree_db.cc
    │   ├── cmake/
    │   │   └── leveldbConfig.cmake.in
    │   ├── db/
    │   │   ├── autocompact_test.cc
    │   │   ├── builder.cc
    │   │   ├── builder.h
    │   │   ├── c.cc
    │   │   ├── c_test.c
    │   │   ├── corruption_test.cc
    │   │   ├── db_impl.cc
    │   │   ├── db_impl.h
    │   │   ├── db_iter.cc
    │   │   ├── db_iter.h
    │   │   ├── db_test.cc
    │   │   ├── dbformat.cc
    │   │   ├── dbformat.h
    │   │   ├── dbformat_test.cc
    │   │   ├── dumpfile.cc
    │   │   ├── fault_injection_test.cc
    │   │   ├── filename.cc
    │   │   ├── filename.h
    │   │   ├── filename_test.cc
    │   │   ├── leveldbutil.cc
    │   │   ├── log_format.h
    │   │   ├── log_reader.cc
    │   │   ├── log_reader.h
    │   │   ├── log_test.cc
    │   │   ├── log_writer.cc
    │   │   ├── log_writer.h
    │   │   ├── memtable.cc
    │   │   ├── memtable.h
    │   │   ├── recovery_test.cc
    │   │   ├── repair.cc
    │   │   ├── skiplist.h
    │   │   ├── skiplist_test.cc
    │   │   ├── snapshot.h
    │   │   ├── table_cache.cc
    │   │   ├── table_cache.h
    │   │   ├── version_edit.cc
    │   │   ├── version_edit.h
    │   │   ├── version_edit_test.cc
    │   │   ├── version_set.cc
    │   │   ├── version_set.h
    │   │   ├── version_set_test.cc
    │   │   ├── write_batch.cc
    │   │   ├── write_batch_internal.h
    │   │   └── write_batch_test.cc
    │   ├── doc/
    │   │   ├── benchmark.html
    │   │   ├── impl.md
    │   │   ├── index.md
    │   │   ├── log_format.md
    │   │   └── table_format.md
    │   ├── helpers/
    │   │   └── memenv/
    │   │       ├── memenv.cc
    │   │       ├── memenv.h
    │   │       └── memenv_test.cc
    │   ├── include/
    │   │   ├── leveldb/
    │   │   │   ├── c.h
    │   │   │   ├── cache.h
    │   │   │   ├── comparator.h
    │   │   │   ├── db.h
    │   │   │   ├── dumpfile.h
    │   │   │   ├── env.h
    │   │   │   ├── export.h
    │   │   │   ├── filter_policy.h
    │   │   │   ├── iterator.h
    │   │   │   ├── options.h
    │   │   │   ├── slice.h
    │   │   │   ├── status.h
    │   │   │   ├── table.h
    │   │   │   ├── table_builder.h
    │   │   │   └── write_batch.h
    │   │   └── port/
    │   │       └── port_config.h
    │   ├── issues/
    │   │   ├── issue178_test.cc
    │   │   ├── issue200_test.cc
    │   │   └── issue320_test.cc
    │   ├── port/
    │   │   ├── README.md
    │   │   ├── port.h
    │   │   ├── port_config.h.in
    │   │   ├── port_example.h
    │   │   ├── port_stdcxx.h
    │   │   └── thread_annotations.h
    │   ├── table/
    │   │   ├── block.cc
    │   │   ├── block.h
    │   │   ├── block_builder.cc
    │   │   ├── block_builder.h
    │   │   ├── filter_block.cc
    │   │   ├── filter_block.h
    │   │   ├── filter_block_test.cc
    │   │   ├── format.cc
    │   │   ├── format.h
    │   │   ├── iterator.cc
    │   │   ├── iterator_wrapper.h
    │   │   ├── merger.cc
    │   │   ├── merger.h
    │   │   ├── table.cc
    │   │   ├── table_builder.cc
    │   │   ├── table_test.cc
    │   │   ├── two_level_iterator.cc
    │   │   └── two_level_iterator.h
    │   └── util/
    │       ├── arena.cc
    │       ├── arena.h
    │       ├── arena_test.cc
    │       ├── bloom.cc
    │       ├── bloom_test.cc
    │       ├── cache.cc
    │       ├── cache_test.cc
    │       ├── coding.cc
    │       ├── coding.h
    │       ├── coding_test.cc
    │       ├── comparator.cc
    │       ├── crc32c.cc
    │       ├── crc32c.h
    │       ├── crc32c_test.cc
    │       ├── env.cc
    │       ├── env_posix.cc
    │       ├── env_posix_test.cc
    │       ├── env_posix_test_helper.h
    │       ├── env_test.cc
    │       ├── env_windows.cc
    │       ├── env_windows_test.cc
    │       ├── env_windows_test_helper.h
    │       ├── filter_policy.cc
    │       ├── hash.cc
    │       ├── hash.h
    │       ├── hash_test.cc
    │       ├── histogram.cc
    │       ├── histogram.h
    │       ├── logging.cc
    │       ├── logging.h
    │       ├── logging_test.cc
    │       ├── mutexlock.h
    │       ├── no_destructor.h
    │       ├── no_destructor_test.cc
    │       ├── options.cc
    │       ├── posix_logger.h
    │       ├── random.h
    │       ├── status.cc
    │       ├── status_test.cc
    │       ├── testutil.cc
    │       ├── testutil.h
    │       └── windows_logger.h
    ├── rapidjson/
    │   ├── LICENSE
    │   ├── allocators.h
    │   ├── document.h
    │   ├── encodedstream.h
    │   ├── encodings.h
    │   ├── error/
    │   │   ├── en.h
    │   │   └── error.h
    │   ├── filereadstream.h
    │   ├── filewritestream.h
    │   ├── fwd.h
    │   ├── internal/
    │   │   ├── biginteger.h
    │   │   ├── diyfp.h
    │   │   ├── dtoa.h
    │   │   ├── ieee754.h
    │   │   ├── itoa.h
    │   │   ├── meta.h
    │   │   ├── pow10.h
    │   │   ├── regex.h
    │   │   ├── stack.h
    │   │   ├── strfunc.h
    │   │   ├── strtod.h
    │   │   └── swap.h
    │   ├── istreamwrapper.h
    │   ├── memorybuffer.h
    │   ├── memorystream.h
    │   ├── msinttypes/
    │   │   ├── inttypes.h
    │   │   └── stdint.h
    │   ├── ostreamwrapper.h
    │   ├── pointer.h
    │   ├── prettywriter.h
    │   ├── rapidjson.h
    │   ├── reader.h
    │   ├── schema.h
    │   ├── stream.h
    │   ├── stringbuffer.h
    │   └── writer.h
    └── spdlog-1.14.1/
        ├── .clang-format
        ├── .clang-tidy
        ├── .git-blame-ignore-revs
        ├── .gitattributes
        ├── .github/
        │   └── workflows/
        │       └── ci.yml
        ├── .gitignore
        ├── CMakeLists.txt
        ├── INSTALL
        ├── LICENSE
        ├── README.md
        ├── appveyor.yml
        ├── bench/
        │   ├── CMakeLists.txt
        │   ├── async_bench.cpp
        │   ├── bench.cpp
        │   ├── formatter-bench.cpp
        │   ├── latency.cpp
        │   └── utils.h
        ├── cmake/
        │   ├── ide.cmake
        │   ├── pch.h.in
        │   ├── spdlog.pc.in
        │   ├── spdlogCPack.cmake
        │   ├── spdlogConfig.cmake.in
        │   ├── utils.cmake
        │   └── version.rc.in
        ├── example/
        │   ├── CMakeLists.txt
        │   └── example.cpp
        ├── include/
        │   └── spdlog/
        │       ├── async.h
        │       ├── async_logger-inl.h
        │       ├── async_logger.h
        │       ├── cfg/
        │       │   ├── argv.h
        │       │   ├── env.h
        │       │   ├── helpers-inl.h
        │       │   └── helpers.h
        │       ├── common-inl.h
        │       ├── common.h
        │       ├── details/
        │       │   ├── backtracer-inl.h
        │       │   ├── backtracer.h
        │       │   ├── circular_q.h
        │       │   ├── console_globals.h
        │       │   ├── file_helper-inl.h
        │       │   ├── file_helper.h
        │       │   ├── fmt_helper.h
        │       │   ├── log_msg-inl.h
        │       │   ├── log_msg.h
        │       │   ├── log_msg_buffer-inl.h
        │       │   ├── log_msg_buffer.h
        │       │   ├── mpmc_blocking_q.h
        │       │   ├── null_mutex.h
        │       │   ├── os-inl.h
        │       │   ├── os.h
        │       │   ├── periodic_worker-inl.h
        │       │   ├── periodic_worker.h
        │       │   ├── registry-inl.h
        │       │   ├── registry.h
        │       │   ├── synchronous_factory.h
        │       │   ├── tcp_client-windows.h
        │       │   ├── tcp_client.h
        │       │   ├── thread_pool-inl.h
        │       │   ├── thread_pool.h
        │       │   ├── udp_client-windows.h
        │       │   ├── udp_client.h
        │       │   └── windows_include.h
        │       ├── fmt/
        │       │   ├── bin_to_hex.h
        │       │   ├── bundled/
        │       │   │   ├── args.h
        │       │   │   ├── chrono.h
        │       │   │   ├── color.h
        │       │   │   ├── compile.h
        │       │   │   ├── core.h
        │       │   │   ├── fmt.license.rst
        │       │   │   ├── format-inl.h
        │       │   │   ├── format.h
        │       │   │   ├── locale.h
        │       │   │   ├── os.h
        │       │   │   ├── ostream.h
        │       │   │   ├── printf.h
        │       │   │   ├── ranges.h
        │       │   │   ├── std.h
        │       │   │   └── xchar.h
        │       │   ├── chrono.h
        │       │   ├── compile.h
        │       │   ├── fmt.h
        │       │   ├── ostr.h
        │       │   ├── ranges.h
        │       │   ├── std.h
        │       │   └── xchar.h
        │       ├── formatter.h
        │       ├── fwd.h
        │       ├── logger-inl.h
        │       ├── logger.h
        │       ├── mdc.h
        │       ├── pattern_formatter-inl.h
        │       ├── pattern_formatter.h
        │       ├── sinks/
        │       │   ├── android_sink.h
        │       │   ├── ansicolor_sink-inl.h
        │       │   ├── ansicolor_sink.h
        │       │   ├── base_sink-inl.h
        │       │   ├── base_sink.h
        │       │   ├── basic_file_sink-inl.h
        │       │   ├── basic_file_sink.h
        │       │   ├── callback_sink.h
        │       │   ├── daily_file_sink.h
        │       │   ├── dist_sink.h
        │       │   ├── dup_filter_sink.h
        │       │   ├── hourly_file_sink.h
        │       │   ├── kafka_sink.h
        │       │   ├── mongo_sink.h
        │       │   ├── msvc_sink.h
        │       │   ├── null_sink.h
        │       │   ├── ostream_sink.h
        │       │   ├── qt_sinks.h
        │       │   ├── ringbuffer_sink.h
        │       │   ├── rotating_file_sink-inl.h
        │       │   ├── rotating_file_sink.h
        │       │   ├── sink-inl.h
        │       │   ├── sink.h
        │       │   ├── stdout_color_sinks-inl.h
        │       │   ├── stdout_color_sinks.h
        │       │   ├── stdout_sinks-inl.h
        │       │   ├── stdout_sinks.h
        │       │   ├── syslog_sink.h
        │       │   ├── systemd_sink.h
        │       │   ├── tcp_sink.h
        │       │   ├── udp_sink.h
        │       │   ├── win_eventlog_sink.h
        │       │   ├── wincolor_sink-inl.h
        │       │   └── wincolor_sink.h
        │       ├── spdlog-inl.h
        │       ├── spdlog.h
        │       ├── stopwatch.h
        │       ├── tweakme.h
        │       └── version.h
        ├── scripts/
        │   ├── ci_setup_clang.sh
        │   ├── extract_version.py
        │   └── format.sh
        ├── src/
        │   ├── async.cpp
        │   ├── bundled_fmtlib_format.cpp
        │   ├── cfg.cpp
        │   ├── color_sinks.cpp
        │   ├── file_sinks.cpp
        │   ├── spdlog.cpp
        │   └── stdout_sinks.cpp
        └── tests/
            ├── CMakeLists.txt
            ├── includes.h
            ├── main.cpp
            ├── test_async.cpp
            ├── test_backtrace.cpp
            ├── test_bin_to_hex.cpp
            ├── test_cfg.cpp
            ├── test_circular_q.cpp
            ├── test_create_dir.cpp
            ├── test_custom_callbacks.cpp
            ├── test_daily_logger.cpp
            ├── test_dup_filter.cpp
            ├── test_errors.cpp
            ├── test_eventlog.cpp
            ├── test_file_helper.cpp
            ├── test_file_logging.cpp
            ├── test_fmt_helper.cpp
            ├── test_macros.cpp
            ├── test_misc.cpp
            ├── test_mpmc_q.cpp
            ├── test_pattern_formatter.cpp
            ├── test_registry.cpp
            ├── test_sink.h
            ├── test_stdout_api.cpp
            ├── test_stopwatch.cpp
            ├── test_systemd.cpp
            ├── test_time_point.cpp
            ├── utils.cpp
            └── utils.h
Download .txt
Showing preview only (1,009K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (11207 symbols across 995 files)

FILE: bot/bridge/src/index.ts
  constant PORT (line 26) | const PORT = parseInt(process.env.BRIDGE_PORT || '3001', 10);
  constant AUTH_DIR (line 27) | const AUTH_DIR = process.env.AUTH_DIR || join(homedir(), '.vikingbot', '...
  constant TOKEN (line 28) | const TOKEN = process.env.BRIDGE_TOKEN || undefined;

FILE: bot/bridge/src/server.ts
  type SendCommand (line 9) | interface SendCommand {
  type BridgeMessage (line 15) | interface BridgeMessage {
  class BridgeServer (line 20) | class BridgeServer {
    method constructor (line 25) | constructor(private port: number, private authDir: string, private tok...
    method start (line 27) | async start(): Promise<void> {
    method setupClient (line 70) | private setupClient(ws: WebSocket): void {
    method handleCommand (line 95) | private async handleCommand(cmd: SendCommand): Promise<void> {
    method broadcast (line 101) | private broadcast(msg: BridgeMessage): void {
    method stop (line 110) | async stop(): Promise<void> {

FILE: bot/bridge/src/whatsapp.ts
  constant VERSION (line 18) | const VERSION = '0.1.0';
  type InboundMessage (line 20) | interface InboundMessage {
  type WhatsAppClientOptions (line 29) | interface WhatsAppClientOptions {
  class WhatsAppClient (line 36) | class WhatsAppClient {
    method constructor (line 41) | constructor(options: WhatsAppClientOptions) {
    method connect (line 45) | async connect(): Promise<void> {
    method extractMessageContent (line 136) | private extractMessageContent(msg: any): string | null {
    method sendMessage (line 173) | async sendMessage(to: string, text: string): Promise<void> {
    method disconnect (line 181) | async disconnect(): Promise<void> {

FILE: bot/eval/locomo/judge.py
  function grade_answer (line 12) | async def grade_answer(
  function load_answers (line 70) | def load_answers(input_path: str) -> tuple[list[dict], list[str]]:
  function main (line 85) | async def main():

FILE: bot/eval/locomo/run_eval.py
  function load_locomo_qa (line 10) | def load_locomo_qa(
  function run_vikingbot_chat (line 43) | def run_vikingbot_chat(question: str) -> tuple[str, dict, float]:
  function load_processed_questions (line 81) | def load_processed_questions(output_path: str) -> set:
  function main (line 92) | def main():

FILE: bot/eval/locomo/stat_judge_result.py
  function main (line 7) | def main():

FILE: bot/eval/skillsbench/skill_bench_eval.py
  function safe_rmtree (line 57) | def safe_rmtree(path: Path) -> bool:
  function get_available_tasks (line 81) | def get_available_tasks() -> list[Path]:
  function run_prepare (line 88) | def run_prepare(args: argparse.Namespace) -> None:
  function run_list (line 176) | def run_list(args: argparse.Namespace) -> None:
  function run_verification (line 196) | def run_verification(task_dir: Path, work_dir: Path, storage_workspace: ...
  function run_task (line 442) | def run_task(
  function run_run (line 664) | def run_run(args: argparse.Namespace) -> None:
  function main (line 870) | def main():

FILE: bot/tests/conftest.py
  function event_loop (line 22) | def event_loop():
  function temp_dir (line 30) | def temp_dir() -> Generator[Path, None, None]:
  function test_data_dir (line 38) | def test_data_dir(temp_dir: Path) -> Path:
  function sample_text_file (line 46) | def sample_text_file(temp_dir: Path) -> Path:
  function sample_markdown_file (line 54) | def sample_markdown_file(temp_dir: Path) -> Path:
  function sample_skill_file (line 76) | def sample_skill_file(temp_dir: Path) -> Path:
  function sample_directory (line 106) | def sample_directory(temp_dir: Path) -> Path:
  function sample_files (line 122) | def sample_files(temp_dir: Path) -> list[Path]:
  function client (line 147) | async def client(test_data_dir: Path) -> AsyncGenerator[AsyncOpenViking,...
  function uninitialized_client (line 161) | async def uninitialized_client(test_data_dir: Path) -> AsyncGenerator[As...
  function client_with_resource_sync (line 177) | async def client_with_resource_sync(
  function client_with_resource (line 190) | async def client_with_resource(

FILE: bot/tests/test_chat_functionality.py
  function temp_workspace (line 17) | def temp_workspace():
  function message_bus (line 24) | def message_bus():
  class TestSingleTurnChannel (line 29) | class TestSingleTurnChannel:
    method test_single_turn_channel_initialization (line 32) | def test_single_turn_channel_initialization(self, message_bus, temp_wo...
    method test_single_turn_channel_receives_response (line 50) | async def test_single_turn_channel_receives_response(self, message_bus...
  class TestChatChannel (line 80) | class TestChatChannel:
    method test_chat_channel_initialization (line 83) | def test_chat_channel_initialization(self, message_bus, temp_workspace):
    method test_chat_channel_send_response (line 100) | async def test_chat_channel_send_response(self, message_bus, temp_work...

FILE: bot/vikingbot/agent/context.py
  class ContextBuilder (line 19) | class ContextBuilder:
    method __init__ (line 30) | def __init__(
    method memory (line 48) | def memory(self):
    method skills (line 55) | def skills(self):
    method _ensure_templates_once (line 61) | def _ensure_templates_once(self):
    method build_system_prompt (line 69) | async def build_system_prompt(
    method _build_user_memory (line 151) | async def _build_user_memory(
    method _get_identity (line 186) | async def _get_identity(self, session_key: SessionKey) -> str:
    method _load_bootstrap_files (line 232) | def _load_bootstrap_files(self) -> str:
    method build_messages (line 245) | async def build_messages(
    method _build_user_content (line 285) | def _build_user_content(self, text: str, media: list[str] | None) -> s...
    method add_tool_result (line 304) | def add_tool_result(
    method add_assistant_message (line 324) | def add_assistant_message(

FILE: bot/vikingbot/agent/loop.py
  class AgentLoop (line 35) | class AgentLoop:
    method __init__ (line 47) | def __init__(
    method _publish_thinking_event (line 133) | async def _publish_thinking_event(
    method _register_builtin_hooks (line 167) | def _register_builtin_hooks(self):
    method _register_default_tools (line 171) | def _register_default_tools(self) -> None:
    method run (line 181) | async def run(self) -> None:
    method stop (line 209) | def stop(self) -> None:
    method _run_agent_loop (line 214) | async def _run_agent_loop(
    method _process_message (line 373) | async def _process_message(self, msg: InboundMessage) -> OutboundMessa...
    method _process_system_message (line 551) | async def _process_system_message(self, msg: InboundMessage) -> Outbou...
    method _consolidate_memory (line 586) | async def _consolidate_memory(self, session, archive_all: bool = False...
    method _consolidate_viking_memory (line 685) | async def _consolidate_viking_memory(self, session) -> None:
    method _safe_consolidate_memory (line 705) | async def _safe_consolidate_memory(self, session, archive_all: bool = ...
    method _check_cmd_auth (line 712) | def _check_cmd_auth(self, msg: InboundMessage) -> bool:
    method process_direct (line 737) | async def process_direct(

FILE: bot/vikingbot/agent/memory.py
  class MemoryStore (line 13) | class MemoryStore:
    method __init__ (line 16) | def __init__(self, workspace: Path):
    method read_long_term (line 21) | def read_long_term(self) -> str:
    method _parse_viking_memory (line 26) | def _parse_viking_memory(self, result: Any) -> str:
    method write_long_term (line 39) | def write_long_term(self, content: str) -> None:
    method append_history (line 42) | def append_history(self, entry: str) -> None:
    method get_memory_context (line 46) | def get_memory_context(self) -> str:
    method get_viking_memory_context (line 50) | async def get_viking_memory_context(self, current_message: str, worksp...
    method get_viking_user_profile (line 67) | async def get_viking_user_profile(self, workspace_id: str, user_id: st...

FILE: bot/vikingbot/agent/skills.py
  class SkillsLoader (line 14) | class SkillsLoader:
    method __init__ (line 22) | def __init__(self, workspace: Path, builtin_skills_dir: Path | None = ...
    method list_skills (line 27) | def list_skills(self, filter_unavailable: bool = True) -> list[dict[st...
    method load_skill (line 54) | def load_skill(self, name: str) -> str | None:
    method load_skills_for_context (line 77) | def load_skills_for_context(self, skill_names: list[str]) -> str:
    method build_skills_summary (line 96) | def build_skills_summary(self) -> str:
    method _get_missing_requirements (line 137) | def _get_missing_requirements(self, skill_meta: dict) -> str:
    method _get_skill_description (line 149) | def _get_skill_description(self, name: str) -> str:
    method _strip_frontmatter (line 156) | def _strip_frontmatter(self, content: str) -> str:
    method _parse_vikingbot_metadata (line 164) | def _parse_vikingbot_metadata(self, raw: str) -> dict:
    method _check_requirements (line 172) | def _check_requirements(self, skill_meta: dict) -> bool:
    method _get_skill_meta (line 183) | def _get_skill_meta(self, name: str) -> dict:
    method get_always_skills (line 188) | def get_always_skills(self) -> list[str]:
    method get_skill_metadata (line 198) | def get_skill_metadata(self, name: str) -> dict | None:

FILE: bot/vikingbot/agent/subagent.py
  class SubagentManager (line 19) | class SubagentManager:
    method __init__ (line 28) | def __init__(
    method spawn (line 47) | async def spawn(
    method _run_subagent (line 78) | async def _run_subagent(
    method _announce_result (line 171) | async def _announce_result(
    method _build_subagent_prompt (line 202) | def _build_subagent_prompt(self, task: str) -> str:
    method get_running_count (line 240) | def get_running_count(self) -> int:

FILE: bot/vikingbot/agent/tools/base.py
  class ToolContext (line 10) | class ToolContext:
  class Tool (line 46) | class Tool(ABC):
    method name (line 100) | def name(self) -> str:
    method description (line 106) | def description(self) -> str:
    method parameters (line 112) | def parameters(self) -> dict[str, Any]:
    method execute (line 117) | async def execute(self, tool_context: ToolContext, **kwargs: Any) -> str:
    method validate_params (line 130) | def validate_params(self, params: dict[str, Any]) -> list[str]:
    method _validate (line 161) | def _validate(self, val: Any, schema: dict[str, Any], path: str) -> li...
    method to_schema (line 214) | def to_schema(self) -> dict[str, Any]:

FILE: bot/vikingbot/agent/tools/cron.py
  class CronTool (line 10) | class CronTool(Tool):
    method __init__ (line 13) | def __init__(self, cron_service: CronService):
    method name (line 17) | def name(self) -> str:
    method description (line 21) | def description(self) -> str:
    method parameters (line 25) | def parameters(self) -> dict[str, Any]:
    method execute (line 53) | async def execute(
    method _add_job (line 75) | def _add_job(
    method _list_jobs (line 113) | def _list_jobs(self) -> str:
    method _remove_job (line 120) | def _remove_job(self, job_id: str | None) -> str:

FILE: bot/vikingbot/agent/tools/factory.py
  function register_default_tools (line 29) | def register_default_tools(
  function register_subagent_tools (line 130) | def register_subagent_tools(

FILE: bot/vikingbot/agent/tools/filesystem.py
  class ReadFileTool (line 12) | class ReadFileTool(Tool):
    method name (line 16) | def name(self) -> str:
    method description (line 20) | def description(self) -> str:
    method parameters (line 24) | def parameters(self) -> dict[str, Any]:
    method execute (line 31) | async def execute(self, tool_context: "ToolContext", path: str, **kwar...
  class WriteFileTool (line 44) | class WriteFileTool(Tool):
    method name (line 48) | def name(self) -> str:
    method description (line 52) | def description(self) -> str:
    method parameters (line 56) | def parameters(self) -> dict[str, Any]:
    method execute (line 66) | async def execute(
  class EditFileTool (line 79) | class EditFileTool(Tool):
    method name (line 83) | def name(self) -> str:
    method description (line 87) | def description(self) -> str:
    method parameters (line 91) | def parameters(self) -> dict[str, Any]:
    method execute (line 102) | async def execute(
  class ListDirTool (line 128) | class ListDirTool(Tool):
    method name (line 132) | def name(self) -> str:
    method description (line 136) | def description(self) -> str:
    method parameters (line 140) | def parameters(self) -> dict[str, Any]:
    method execute (line 147) | async def execute(self, tool_context: "ToolContext", path: str, **kwar...

FILE: bot/vikingbot/agent/tools/image.py
  class ImageGenerationTool (line 18) | class ImageGenerationTool(Tool):
    method name (line 22) | def name(self) -> str:
    method description (line 26) | def description(self) -> str:
    method parameters (line 30) | def parameters(self) -> dict[str, Any]:
    method __init__ (line 86) | def __init__(
    method set_send_callback (line 98) | def set_send_callback(self, callback: Callable[[OutboundMessage], Awai...
    method _is_seedream_model (line 103) | def _is_seedream_model(self) -> bool:
    method _parse_image_data (line 107) | async def _parse_image_data(self, image_str: str) -> tuple[str, str]:
    method _url_to_base64 (line 124) | async def _url_to_base64(self, url: str) -> str:
    method _build_common_kwargs (line 131) | def _build_common_kwargs(
    method _seedream_image_to_image (line 157) | async def _seedream_image_to_image(
    method execute (line 185) | async def execute(

FILE: bot/vikingbot/agent/tools/message.py
  class MessageTool (line 10) | class MessageTool(Tool):
    method __init__ (line 13) | def __init__(
    method set_send_callback (line 19) | def set_send_callback(self, callback: Callable[[OutboundMessage], Awai...
    method name (line 24) | def name(self) -> str:
    method description (line 28) | def description(self) -> str:
    method parameters (line 32) | def parameters(self) -> dict[str, Any]:
    method execute (line 41) | async def execute(self, tool_context: "ToolContext", **kwargs: Any) ->...

FILE: bot/vikingbot/agent/tools/ov_file.py
  class OVFileTool (line 14) | class OVFileTool(Tool, ABC):
    method __init__ (line 15) | def __init__(self):
    method _get_client (line 19) | async def _get_client(self, tool_context: ToolContext):
  class VikingReadTool (line 25) | class VikingReadTool(OVFileTool):
    method name (line 29) | def name(self) -> str:
    method description (line 33) | def description(self) -> str:
    method parameters (line 37) | def parameters(self) -> dict[str, Any]:
    method execute (line 55) | async def execute(
  class VikingListTool (line 66) | class VikingListTool(OVFileTool):
    method name (line 70) | def name(self) -> str:
    method description (line 74) | def description(self) -> str:
    method parameters (line 78) | def parameters(self) -> dict[str, Any]:
    method execute (line 95) | async def execute(
  class VikingSearchTool (line 120) | class VikingSearchTool(OVFileTool):
    method name (line 124) | def name(self) -> str:
    method description (line 128) | def description(self) -> str:
    method parameters (line 132) | def parameters(self) -> dict[str, Any]:
    method execute (line 145) | async def execute(
  class VikingAddResourceTool (line 169) | class VikingAddResourceTool(OVFileTool):
    method name (line 173) | def name(self) -> str:
    method description (line 177) | def description(self) -> str:
    method parameters (line 181) | def parameters(self) -> dict[str, Any]:
    method execute (line 191) | async def execute(
  class VikingGrepTool (line 225) | class VikingGrepTool(OVFileTool):
    method name (line 229) | def name(self) -> str:
    method description (line 233) | def description(self) -> str:
    method parameters (line 237) | def parameters(self) -> dict[str, Any]:
    method execute (line 258) | async def execute(
  class VikingGlobTool (line 298) | class VikingGlobTool(OVFileTool):
    method name (line 302) | def name(self) -> str:
    method description (line 306) | def description(self) -> str:
    method parameters (line 310) | def parameters(self) -> dict[str, Any]:
    method execute (line 327) | async def execute(
  class VikingSearchUserMemoryTool (line 355) | class VikingSearchUserMemoryTool(OVFileTool):
    method name (line 359) | def name(self) -> str:
    method description (line 363) | def description(self) -> str:
    method parameters (line 367) | def parameters(self) -> dict[str, Any]:
    method execute (line 374) | async def execute(self, tool_context: ToolContext, query: str, **kwarg...
  class VikingMemoryCommitTool (line 386) | class VikingMemoryCommitTool(OVFileTool):
    method name (line 390) | def name(self) -> str:
    method description (line 394) | def description(self) -> str:
    method parameters (line 398) | def parameters(self) -> dict[str, Any]:
    method execute (line 418) | async def execute(

FILE: bot/vikingbot/agent/tools/registry.py
  class ToolRegistry (line 17) | class ToolRegistry:
    method __init__ (line 24) | def __init__(self):
    method register (line 28) | def register(self, tool: Tool) -> None:
    method unregister (line 51) | def unregister(self, name: str) -> None:
    method get (line 68) | def get(self, name: str) -> Tool | None:
    method has (line 87) | def has(self, name: str) -> bool:
    method get_definitions (line 103) | def get_definitions(self) -> list[dict[str, Any]]:
    method execute (line 121) | async def execute(
    method tool_names (line 214) | def tool_names(self) -> list[str]:
    method __len__ (line 218) | def __len__(self) -> int:
    method __contains__ (line 221) | def __contains__(self, name: str) -> bool:

FILE: bot/vikingbot/agent/tools/shell.py
  class ExecTool (line 18) | class ExecTool(Tool):
    method __init__ (line 21) | def __init__(self, timeout: int = 60):
    method name (line 25) | def name(self) -> str:
    method description (line 29) | def description(self) -> str:
    method parameters (line 33) | def parameters(self) -> dict[str, Any]:
    method execute (line 46) | async def execute(

FILE: bot/vikingbot/agent/tools/spawn.py
  class SpawnTool (line 11) | class SpawnTool(Tool):
    method __init__ (line 19) | def __init__(self, manager: "SubagentManager"):
    method name (line 23) | def name(self) -> str:
    method description (line 27) | def description(self) -> str:
    method parameters (line 35) | def parameters(self) -> dict[str, Any]:
    method execute (line 51) | async def execute(

FILE: bot/vikingbot/agent/tools/web.py
  function _strip_tags (line 18) | def _strip_tags(text: str) -> str:
  function _normalize (line 26) | def _normalize(text: str) -> str:
  function _validate_url (line 32) | def _validate_url(url: str) -> tuple[bool, str]:
  class WebFetchTool (line 45) | class WebFetchTool(Tool):
    method __init__ (line 60) | def __init__(self, max_chars: int = 50000):
    method execute (line 63) | async def execute(
    method _to_markdown (line 123) | def _to_markdown(self, html: str) -> str:

FILE: bot/vikingbot/agent/tools/websearch/__init__.py
  class WebSearchTool (line 24) | class WebSearchTool(Tool):
    method __init__ (line 64) | def __init__(
    method backend (line 98) | def backend(self) -> WebSearchBackend:
    method execute (line 102) | async def execute(

FILE: bot/vikingbot/agent/tools/websearch/base.py
  class WebSearchBackend (line 7) | class WebSearchBackend(ABC):
    method name (line 12) | def name(self) -> str:
    method is_available (line 18) | def is_available(self) -> bool:
    method search (line 23) | async def search(self, query: str, count: int, **kwargs: Any) -> str:

FILE: bot/vikingbot/agent/tools/websearch/brave.py
  class BraveBackend (line 13) | class BraveBackend(WebSearchBackend):
    method __init__ (line 18) | def __init__(self, api_key: str | None = None):
    method is_available (line 22) | def is_available(self) -> bool:
    method search (line 25) | async def search(self, query: str, count: int, **kwargs: Any) -> str:

FILE: bot/vikingbot/agent/tools/websearch/ddgs.py
  class DDGSBackend (line 11) | class DDGSBackend(WebSearchBackend):
    method __init__ (line 16) | def __init__(self):
    method _get_ddgs (line 19) | def _get_ddgs(self):
    method is_available (line 27) | def is_available(self) -> bool:
    method search (line 35) | async def search(self, query: str, count: int, **kwargs: Any) -> str:

FILE: bot/vikingbot/agent/tools/websearch/exa.py
  class ExaBackend (line 13) | class ExaBackend(WebSearchBackend):
    method __init__ (line 18) | def __init__(self, api_key: str | None = None):
    method is_available (line 22) | def is_available(self) -> bool:
    method search (line 25) | async def search(

FILE: bot/vikingbot/agent/tools/websearch/registry.py
  class WebSearchBackendRegistry (line 8) | class WebSearchBackendRegistry:
    method __init__ (line 14) | def __init__(self):
    method register (line 17) | def register(self, backend_class: Type[WebSearchBackend]) -> Type[WebS...
    method get (line 31) | def get(self, name: str) -> Optional[Type[WebSearchBackend]]:
    method list_names (line 35) | def list_names(self) -> List[str]:
    method create (line 39) | def create(
    method select_auto (line 72) | def select_auto(
  function register_backend (line 103) | def register_backend(cls: Type[WebSearchBackend]) -> Type[WebSearchBacke...

FILE: bot/vikingbot/agent/tools/websearch/tavily.py
  class TavilyBackend (line 11) | class TavilyBackend(WebSearchBackend):
    method __init__ (line 16) | def __init__(self, api_key: str | None = None):
    method is_available (line 26) | def is_available(self) -> bool:
    method search (line 29) | async def search(self, query: str, count: int, **kwargs: Any) -> str:

FILE: bot/vikingbot/bus/events.py
  class OutboundEventType (line 11) | class OutboundEventType(str, Enum):
  class InboundMessage (line 22) | class InboundMessage:
  class OutboundMessage (line 34) | class OutboundMessage:
    method channel (line 47) | def channel(self) -> str:
    method is_normal_message (line 52) | def is_normal_message(self) -> bool:

FILE: bot/vikingbot/bus/queue.py
  class MessageBus (line 11) | class MessageBus:
    method __init__ (line 19) | def __init__(self):
    method publish_inbound (line 27) | async def publish_inbound(self, msg: InboundMessage) -> None:
    method consume_inbound (line 32) | async def consume_inbound(self) -> InboundMessage:
    method publish_outbound (line 36) | async def publish_outbound(self, msg: OutboundMessage) -> None:
    method consume_outbound (line 41) | async def consume_outbound(self) -> OutboundMessage:
    method subscribe_outbound (line 45) | def subscribe_outbound(
    method dispatch_outbound (line 53) | async def dispatch_outbound(self) -> None:
    method stop (line 74) | def stop(self) -> None:
    method inbound_size (line 79) | def inbound_size(self) -> int:
    method outbound_size (line 84) | def outbound_size(self) -> int:

FILE: bot/vikingbot/channels/base.py
  class BaseChannel (line 31) | class BaseChannel(ABC):
    method __init__ (line 41) | def __init__(
    method start (line 61) | async def start(self) -> None:
    method stop (line 73) | async def stop(self) -> None:
    method send (line 78) | async def send(self, msg: OutboundMessage) -> bool:
    method handle_processing_tick (line 104) | async def handle_processing_tick(self, message_id: str, tick_count: in...
    method send_processing_reaction (line 111) | async def send_processing_reaction(self, message_id: str, emoji: str) ...
    method is_allowed (line 118) | def is_allowed(self, sender_id: str) -> bool:
    method _handle_message (line 143) | async def _handle_message(
    method _parse_data_uri (line 184) | async def _parse_data_uri(self, data_uri: str) -> Tuple[bool, Any]:
    method _extract_images (line 242) | def _extract_images(self, content: str) -> tuple[list[str], str]:
    method _is_image_data (line 279) | def _is_image_data(self, data: bytes) -> bool:
    method _html_to_markdown (line 305) | def _html_to_markdown(self, html_content: str, url: str = "") -> str:
    method _process_html_content (line 343) | def _process_html_content(self, data: bytes, url: str = "") -> Tuple[b...
    method is_running (line 368) | def is_running(self) -> bool:

FILE: bot/vikingbot/channels/chat.py
  class ChatChannelConfig (line 21) | class ChatChannelConfig(BaseChannelConfig):
    method channel_id (line 28) | def channel_id(self) -> str:
  class ChatChannel (line 32) | class ChatChannel(BaseChannel):
    method __init__ (line 43) | def __init__(
    method start (line 61) | async def start(self) -> None:
    method stop (line 68) | async def stop(self) -> None:
    method send (line 72) | async def send(self, msg: OutboundMessage) -> None:
    method _run_interactive (line 114) | async def _run_interactive(self) -> None:

FILE: bot/vikingbot/channels/dingtalk.py
  class NanobotDingTalkHandler (line 36) | class NanobotDingTalkHandler(CallbackHandler):
    method __init__ (line 42) | def __init__(self, channel: "DingTalkChannel"):
    method process (line 46) | async def process(self, message: CallbackMessage):
  class DingTalkChannel (line 84) | class DingTalkChannel(BaseChannel):
    method __init__ (line 97) | def __init__(self, config: DingTalkChannelConfig, bus: MessageBus, **k...
    method start (line 110) | async def start(self) -> None:
    method stop (line 151) | async def stop(self) -> None:
    method _get_access_token (line 163) | async def _get_access_token(self) -> str | None:
    method send (line 190) | async def send(self, msg: OutboundMessage) -> None:
    method _on_message (line 231) | async def _on_message(self, content: str, sender_id: str, sender_name:...

FILE: bot/vikingbot/channels/discord.py
  class DiscordChannel (line 23) | class DiscordChannel(BaseChannel):
    method __init__ (line 28) | def __init__(self, config: DiscordChannelConfig, bus: MessageBus, **kw...
    method start (line 37) | async def start(self) -> None:
    method stop (line 60) | async def stop(self) -> None:
    method send (line 76) | async def send(self, msg: OutboundMessage) -> None:
    method _gateway_loop (line 115) | async def _gateway_loop(self) -> None:
    method _identify (line 153) | async def _identify(self) -> None:
    method _start_heartbeat (line 172) | async def _start_heartbeat(self, interval_s: float) -> None:
    method _handle_message_create (line 189) | async def _handle_message_create(self, payload: dict[str, Any]) -> None:
    method _start_typing (line 253) | async def _start_typing(self, channel_id: str) -> None:
    method _stop_typing (line 269) | async def _stop_typing(self, channel_id: str) -> None:

FILE: bot/vikingbot/channels/email.py
  class EmailChannel (line 25) | class EmailChannel(BaseChannel):
    method __init__ (line 53) | def __init__(self, config: EmailChannelConfig, bus: MessageBus, **kwar...
    method start (line 61) | async def start(self) -> None:
    method stop (line 101) | async def stop(self) -> None:
    method send (line 105) | async def send(self, msg: OutboundMessage) -> None:
    method _validate_config (line 151) | def _validate_config(self) -> bool:
    method _smtp_send (line 171) | def _smtp_send(self, msg: EmailMessage) -> None:
    method _fetch_new_messages (line 189) | def _fetch_new_messages(self) -> list[dict[str, Any]]:
    method fetch_messages_between_dates (line 198) | def fetch_messages_between_dates(
    method _fetch_messages (line 224) | def _fetch_messages(
    method _format_imap_date (line 322) | def _format_imap_date(cls, value: date) -> str:
    method _extract_message_bytes (line 328) | def _extract_message_bytes(fetched: list[Any]) -> bytes | None:
    method _extract_uid (line 339) | def _extract_uid(fetched: list[Any]) -> str:
    method _decode_header_value (line 349) | def _decode_header_value(value: str) -> str:
    method _extract_text_body (line 358) | def _extract_text_body(cls, msg: Any) -> str:
    method _html_to_text (line 398) | def _html_to_text(raw_html: str) -> str:
    method _reply_subject (line 404) | def _reply_subject(self, base_subject: str) -> str:

FILE: bot/vikingbot/channels/feishu.py
  class FeishuChannel (line 68) | class FeishuChannel(BaseChannel):
    method __init__ (line 92) | def __init__(self, config: FeishuChannelConfig, bus: MessageBus, **kwa...
    method _get_tenant_access_token (line 104) | async def _get_tenant_access_token(self) -> str:
    method _upload_image_to_feishu (line 128) | async def _upload_image_to_feishu(self, image_data: bytes) -> str:
    method _download_feishu_image (line 151) | async def _download_feishu_image(self, image_key: str, message_id: str...
    method _save_image_to_temp (line 184) | async def _save_image_to_temp(self, image_bytes: bytes) -> str:
    method _get_chat_mode (line 194) | async def _get_chat_mode(self, chat_id: str) -> str:
    method start (line 216) | async def start(self) -> None:
    method stop (line 280) | async def stop(self) -> None:
    method _add_reaction_sync (line 292) | def _add_reaction_sync(self, message_id: str, emoji_type: str) -> None:
    method _add_reaction (line 313) | async def _add_reaction(self, message_id: str, emoji_type: str = "THUM...
    method send_processing_reaction (line 325) | async def send_processing_reaction(self, message_id: str, emoji: str) ...
    method handle_processing_tick (line 331) | async def handle_processing_tick(self, message_id: str, tick_count: in...
    method _parse_md_table (line 350) | def _parse_md_table(table_text: str) -> dict | None:
    method _build_card_elements (line 374) | def _build_card_elements(self, content: str) -> list[dict]:
    method _split_headings (line 402) | def _split_headings(self, content: str) -> list[dict]:
    method _process_content_with_images (line 438) | async def _process_content_with_images(
    method send (line 495) | async def send(self, msg: OutboundMessage) -> None:
    method _on_message_sync (line 628) | def _on_message_sync(self, data: "P2ImMessageReceiveV1") -> None:
    method _on_message (line 636) | async def _on_message(self, data: "P2ImMessageReceiveV1") -> None:
    method _extract_and_upload_images (line 822) | async def _extract_and_upload_images(self, content: str) -> tuple[str,...

FILE: bot/vikingbot/channels/manager.py
  class ChannelManager (line 15) | class ChannelManager:
    method __init__ (line 25) | def __init__(self, bus: MessageBus):
    method add_channel (line 32) | def add_channel(self, channel: BaseChannel) -> None:
    method add_channel_from_config (line 38) | def add_channel_from_config(
    method load_channels_from_config (line 151) | def load_channels_from_config(
    method _start_channel (line 169) | async def _start_channel(self, name: str, channel: BaseChannel) -> None:
    method start_all (line 176) | async def start_all(self) -> None:
    method stop_all (line 194) | async def stop_all(self) -> None:
    method _dispatch_outbound (line 214) | async def _dispatch_outbound(self) -> None:
    method get_channel (line 239) | def get_channel(self, name: str) -> BaseChannel | None:
    method get_status (line 243) | def get_status(self) -> dict[str, Any]:
    method enabled_channels (line 251) | def enabled_channels(self) -> list[str]:

FILE: bot/vikingbot/channels/mochat.py
  class MochatBufferedEntry (line 46) | class MochatBufferedEntry:
  class DelayState (line 59) | class DelayState:
  class MochatTarget (line 68) | class MochatTarget:
  function _safe_dict (line 80) | def _safe_dict(value: Any) -> dict:
  function _str_field (line 85) | def _str_field(src: dict, *keys: str) -> str:
  function _make_synthetic_event (line 94) | def _make_synthetic_event(
  function normalize_mochat_content (line 123) | def normalize_mochat_content(content: Any) -> str:
  function resolve_mochat_target (line 135) | def resolve_mochat_target(raw: str) -> MochatTarget:
  function extract_mention_ids (line 154) | def extract_mention_ids(value: Any) -> list[str]:
  function resolve_was_mentioned (line 172) | def resolve_was_mentioned(payload: dict[str, Any], agent_user_id: str) -...
  function resolve_require_mention (line 189) | def resolve_require_mention(config: MochatConfig, session_id: str, group...
  function build_buffered_body (line 198) | def build_buffered_body(entries: list[MochatBufferedEntry], is_group: bo...
  function parse_timestamp (line 217) | def parse_timestamp(value: Any) -> int | None:
  class MochatChannel (line 232) | class MochatChannel(BaseChannel):
    method __init__ (line 237) | def __init__(self, config: MochatChannelConfig, bus: MessageBus, **kwa...
    method start (line 268) | async def start(self) -> None:
    method stop (line 288) | async def stop(self) -> None:
    method send (line 315) | async def send(self, msg: OutboundMessage) -> None:
    method _seed_targets_from_config (line 355) | def _seed_targets_from_config(self) -> None:
    method _normalize_id_list (line 365) | def _normalize_id_list(values: list[str]) -> tuple[list[str], bool]:
    method _start_socket_client (line 371) | async def _start_socket_client(self) -> bool:
    method _build_notify_handler (line 452) | def _build_notify_handler(self, event_name: str):
    method _subscribe_all (line 463) | async def _subscribe_all(self) -> bool:
    method _subscribe_sessions (line 470) | async def _subscribe_sessions(self, session_ids: list[str]) -> bool:
    method _subscribe_panels (line 505) | async def _subscribe_panels(self, panel_ids: list[str]) -> bool:
    method _socket_call (line 516) | async def _socket_call(self, event_name: str, payload: dict[str, Any])...
    method _refresh_loop (line 527) | async def _refresh_loop(self) -> None:
    method _refresh_targets (line 538) | async def _refresh_targets(self, subscribe_new: bool) -> None:
    method _refresh_sessions_directory (line 544) | async def _refresh_sessions_directory(self, subscribe_new: bool) -> None:
    method _refresh_panels (line 578) | async def _refresh_panels(self, subscribe_new: bool) -> None:
    method _ensure_fallback_workers (line 610) | async def _ensure_fallback_workers(self) -> None:
    method _stop_fallback_workers (line 625) | async def _stop_fallback_workers(self) -> None:
    method _session_watch_worker (line 635) | async def _session_watch_worker(self, session_id: str) -> None:
    method _panel_poll_worker (line 654) | async def _panel_poll_worker(self, panel_id: str) -> None:
    method _handle_watch_payload (line 689) | async def _handle_watch_payload(self, payload: dict[str, Any], target_...
    method _process_inbound_event (line 723) | async def _process_inbound_event(
    method _remember_message_id (line 783) | def _remember_message_id(self, key: str, message_id: str) -> bool:
    method _enqueue_delayed_entry (line 794) | async def _enqueue_delayed_entry(
    method _delay_flush_after (line 804) | async def _delay_flush_after(self, key: str, target_id: str, target_ki...
    method _flush_delayed_entries (line 808) | async def _flush_delayed_entries(
    method _dispatch_entries (line 829) | async def _dispatch_entries(
    method _cancel_delay_timers (line 858) | async def _cancel_delay_timers(self) -> None:
    method _handle_notify_chat_message (line 866) | async def _handle_notify_chat_message(self, payload: Any) -> None:
    method _handle_notify_inbox_append (line 888) | async def _handle_notify_inbox_append(self, payload: Any) -> None:
    method _mark_session_cursor (line 920) | def _mark_session_cursor(self, session_id: str, cursor: int) -> None:
    method _save_cursor_debounced (line 927) | async def _save_cursor_debounced(self) -> None:
    method _load_session_cursors (line 931) | async def _load_session_cursors(self) -> None:
    method _save_session_cursors (line 945) | async def _save_session_cursors(self) -> None:
    method _post_json (line 966) | async def _post_json(self, path: str, payload: dict[str, Any]) -> dict...
    method _api_send (line 992) | async def _api_send(
    method _read_group_id (line 1010) | def _read_group_id(metadata: dict[str, Any]) -> str | None:

FILE: bot/vikingbot/channels/openapi.py
  class OpenAPIChannelConfig (line 32) | class OpenAPIChannelConfig(BaseChannelConfig):
    method channel_id (line 42) | def channel_id(self) -> str:
  class PendingResponse (line 46) | class PendingResponse:
    method __init__ (line 49) | def __init__(self):
    method add_event (line 55) | async def add_event(self, event_type: str, data: Any):
    method set_final (line 61) | def set_final(self, content: str):
    method close_stream (line 66) | async def close_stream(self):
  class OpenAPIChannel (line 71) | class OpenAPIChannel(BaseChannel):
    method __init__ (line 80) | def __init__(
    method start (line 95) | async def start(self) -> None:
    method stop (line 105) | async def stop(self) -> None:
    method send (line 113) | async def send(self, msg: OutboundMessage) -> None:
    method get_router (line 137) | def get_router(self) -> APIRouter:
    method _create_router (line 143) | def _create_router(self) -> APIRouter:
    method _setup_routes (line 255) | def _setup_routes(self) -> None:
    method _handle_chat (line 267) | async def _handle_chat(self, request: ChatRequest) -> ChatResponse:
    method _handle_chat_stream (line 338) | async def _handle_chat_stream(self, request: ChatRequest) -> Streaming...
  function get_openapi_router (line 404) | def get_openapi_router(bus: MessageBus, config: Config) -> APIRouter:

FILE: bot/vikingbot/channels/openapi_models.py
  class MessageRole (line 10) | class MessageRole(str, Enum):
  class EventType (line 19) | class EventType(str, Enum):
  class ChatMessage (line 29) | class ChatMessage(BaseModel):
  class ChatRequest (line 39) | class ChatRequest(BaseModel):
  class ChatResponse (line 53) | class ChatResponse(BaseModel):
  class ChatStreamEvent (line 64) | class ChatStreamEvent(BaseModel):
  class SessionInfo (line 72) | class SessionInfo(BaseModel):
  class SessionCreateRequest (line 81) | class SessionCreateRequest(BaseModel):
  class SessionCreateResponse (line 90) | class SessionCreateResponse(BaseModel):
  class SessionListResponse (line 97) | class SessionListResponse(BaseModel):
  class SessionDetailResponse (line 104) | class SessionDetailResponse(BaseModel):
  class HealthResponse (line 111) | class HealthResponse(BaseModel):
  class ErrorResponse (line 119) | class ErrorResponse(BaseModel):

FILE: bot/vikingbot/channels/qq.py
  function _make_bot_class (line 27) | def _make_bot_class(channel: "QQChannel") -> "type[botpy.Client]":
  class QQChannel (line 47) | class QQChannel(BaseChannel):
    method __init__ (line 52) | def __init__(self, config: QQChannelConfig, bus: MessageBus, **kwargs):
    method start (line 59) | async def start(self) -> None:
    method _run_bot (line 78) | async def _run_bot(self) -> None:
    method stop (line 89) | async def stop(self) -> None:
    method send (line 100) | async def send(self, msg: OutboundMessage) -> None:
    method _on_message (line 118) | async def _on_message(self, data: "C2CMessage") -> None:

FILE: bot/vikingbot/channels/single_turn.py
  class SingleTurnChannelConfig (line 18) | class SingleTurnChannelConfig(BaseChannelConfig):
    method channel_id (line 25) | def channel_id(self) -> str:
  class SingleTurnChannel (line 29) | class SingleTurnChannel(BaseChannel):
    method __init__ (line 39) | def __init__(
    method start (line 59) | async def start(self) -> None:
    method stop (line 90) | async def stop(self) -> None:
    method send (line 94) | async def send(self, msg: OutboundMessage) -> None:

FILE: bot/vikingbot/channels/slack.py
  class SlackChannel (line 20) | class SlackChannel(BaseChannel):
    method __init__ (line 25) | def __init__(self, config: SlackChannelConfig, bus: MessageBus, **kwar...
    method start (line 32) | async def start(self) -> None:
    method stop (line 65) | async def stop(self) -> None:
    method send (line 75) | async def send(self, msg: OutboundMessage) -> None:
    method _on_socket_request (line 98) | async def _on_socket_request(
    method _is_allowed (line 181) | def _is_allowed(self, sender_id: str, chat_id: str, channel_type: str)...
    method _should_respond_in_channel (line 194) | def _should_respond_in_channel(self, event_type: str, text: str, chat_...
    method _strip_bot_mention (line 205) | def _strip_bot_mention(self, text: str) -> str:

FILE: bot/vikingbot/channels/telegram.py
  function _markdown_to_telegram_html (line 19) | def _markdown_to_telegram_html(text: str) -> str:
  class TelegramChannel (line 84) | class TelegramChannel(BaseChannel):
    method __init__ (line 100) | def __init__(
    method start (line 115) | async def start(self) -> None:
    method stop (line 181) | async def stop(self) -> None:
    method send (line 196) | async def send(self, msg: OutboundMessage) -> None:
    method _on_start (line 248) | async def _on_start(self, update: Update, context: ContextTypes.DEFAUL...
    method _forward_command (line 260) | async def _forward_command(self, update: Update, context: ContextTypes...
    method _on_message (line 270) | async def _on_message(self, update: Update, context: ContextTypes.DEFA...
    method _start_typing (line 378) | def _start_typing(self, chat_id: str) -> None:
    method _stop_typing (line 384) | def _stop_typing(self, chat_id: str) -> None:
    method _typing_loop (line 390) | async def _typing_loop(self, chat_id: str) -> None:
    method _on_error (line 401) | async def _on_error(self, update: object, context: ContextTypes.DEFAUL...
    method _get_extension (line 405) | def _get_extension(self, media_type: str, mime_type: str | None) -> str:

FILE: bot/vikingbot/channels/utils.py
  function is_image_file_path (line 14) | def is_image_file_path(path_str: str) -> bool:
  function extract_image_paths (line 47) | def extract_image_paths(content: str) -> Tuple[List[str], str]:
  function read_image_file (line 85) | def read_image_file(path_str: str) -> bytes:
  function image_to_data_uri (line 108) | def image_to_data_uri(image_bytes: bytes, mime_type: str = "image/png") ...

FILE: bot/vikingbot/channels/whatsapp.py
  class WhatsAppChannel (line 15) | class WhatsAppChannel(BaseChannel):
    method __init__ (line 25) | def __init__(self, config: WhatsAppChannelConfig, bus: MessageBus, **k...
    method start (line 31) | async def start(self) -> None:
    method stop (line 71) | async def stop(self) -> None:
    method send (line 80) | async def send(self, msg: OutboundMessage) -> None:
    method _handle_bridge_message (line 96) | async def _handle_bridge_message(self, raw: str) -> None:

FILE: bot/vikingbot/cli/commands.py
  function get_or_create_machine_id (line 53) | def get_or_create_machine_id() -> str:
  function _init_bot_data (line 72) | def _init_bot_data(config):
  function _flush_pending_tty_input (line 85) | def _flush_pending_tty_input() -> None:
  function _restore_terminal (line 113) | def _restore_terminal() -> None:
  function _init_prompt_session (line 125) | def _init_prompt_session() -> None:
  function _print_agent_response (line 147) | def _print_agent_response(response: str, render_markdown: bool) -> None:
  function _is_exit_command (line 157) | def _is_exit_command(command: str) -> bool:
  function _read_interactive_input_async (line 162) | async def _read_interactive_input_async() -> str:
  function version_callback (line 181) | def version_callback(value: bool):
  function main (line 188) | def main(
  function _make_provider (line 195) | def _make_provider(config, langfuse_client: None = None):
  function gateway (line 227) | def gateway(
  function prepare_agent_loop (line 294) | def prepare_agent_loop(config, bus, session_manager, cron, quiet: bool =...
  function prepare_cron (line 347) | def prepare_cron(bus, quiet: bool = False) -> CronService:
  function prepare_channel (line 404) | def prepare_channel(
  function prepare_heartbeat (line 443) | def prepare_heartbeat(config, agent_loop, session_manager) -> HeartbeatS...
  function start_console (line 469) | async def start_console(console_port):
  function _thinking_ctx (line 495) | def _thinking_ctx(logs: bool):
  function prepare_agent_channel (line 504) | def prepare_agent_channel(
  function chat (line 551) | def chat(
  function channels_status (line 649) | def channels_status():
  function _get_bridge_dir (line 691) | def _get_bridge_dir() -> Path:
  function channels_login (line 750) | def channels_login():
  function cron_list (line 789) | def cron_list(
  function cron_add (line 837) | def cron_add(
  function cron_remove (line 881) | def cron_remove(
  function cron_enable (line 898) | def cron_enable(
  function cron_run (line 918) | def cron_run(
  function status (line 944) | def status():

FILE: bot/vikingbot/config/loader.py
  function get_config_path (line 12) | def get_config_path() -> Path:
  function _resolve_ov_conf_path (line 22) | def _resolve_ov_conf_path() -> Path:
  function get_data_dir (line 35) | def get_data_dir() -> Path:
  function ensure_config (line 42) | def ensure_config(config_path: Path | None = None) -> Config:
  function load_config (line 63) | def load_config() -> Config:
  function _merge_vlm_model_config (line 111) | def _merge_vlm_model_config(bot_data: dict, vlm_data: dict) -> None:
  function _merge_ov_server_config (line 138) | def _merge_ov_server_config(bot_data: dict, ov_data: dict) -> None:
  function save_config (line 154) | def save_config(
  function convert_keys (line 189) | def convert_keys(data: Any) -> Any:
  function convert_to_camel (line 198) | def convert_to_camel(data: Any) -> Any:
  function camel_to_snake (line 207) | def camel_to_snake(name: str) -> str:
  function snake_to_camel (line 217) | def snake_to_camel(name: str) -> str:

FILE: bot/vikingbot/config/schema.py
  class ChannelType (line 11) | class ChannelType(str, Enum):
  class SandboxBackend (line 26) | class SandboxBackend(str, Enum):
  class SandboxMode (line 36) | class SandboxMode(str, Enum):
  class AgentMemoryMode (line 43) | class AgentMemoryMode(str, Enum):
  class BotMode (line 50) | class BotMode(str, Enum):
  class BaseChannelConfig (line 57) | class BaseChannelConfig(BaseModel):
    method channel_id (line 63) | def channel_id(self) -> str:
    method channel_key (line 66) | def channel_key(self):
  class MochatMentionConfig (line 73) | class MochatMentionConfig(BaseModel):
  class MochatGroupRule (line 79) | class MochatGroupRule(BaseModel):
  class SlackDMConfig (line 85) | class SlackDMConfig(BaseModel):
  class TelegramChannelConfig (line 96) | class TelegramChannelConfig(BaseChannelConfig):
    method channel_id (line 104) | def channel_id(self) -> str:
  class FeishuChannelConfig (line 109) | class FeishuChannelConfig(BaseChannelConfig):
    method channel_id (line 121) | def channel_id(self) -> str:
    method channel_key (line 125) | def channel_key(self):
  class DiscordChannelConfig (line 129) | class DiscordChannelConfig(BaseChannelConfig):
    method channel_id (line 138) | def channel_id(self) -> str:
  class WhatsAppChannelConfig (line 143) | class WhatsAppChannelConfig(BaseChannelConfig):
    method channel_id (line 151) | def channel_id(self) -> str:
  class MochatChannelConfig (line 156) | class MochatChannelConfig(BaseChannelConfig):
    method _generate_default_id (line 182) | def _generate_default_id(self) -> str:
  class DingTalkChannelConfig (line 187) | class DingTalkChannelConfig(BaseChannelConfig):
    method channel_id (line 195) | def channel_id(self) -> str:
  class EmailChannelConfig (line 200) | class EmailChannelConfig(BaseChannelConfig):
    method channel_id (line 225) | def channel_id(self) -> str:
  class SlackChannelConfig (line 230) | class SlackChannelConfig(BaseChannelConfig):
    method channel_id (line 243) | def channel_id(self) -> str:
  class QQChannelConfig (line 248) | class QQChannelConfig(BaseChannelConfig):
    method channel_id (line 256) | def channel_id(self) -> str:
  class OpenAPIChannelConfig (line 261) | class OpenAPIChannelConfig(BaseChannelConfig):
    method channel_id (line 271) | def channel_id(self) -> str:
  class ChannelsConfig (line 275) | class ChannelsConfig(BaseModel):
    method _parse_channel_config (line 280) | def _parse_channel_config(self, config: dict[str, Any]) -> BaseChannel...
    method get_all_channels (line 377) | def get_all_channels(self) -> list[BaseChannelConfig]:
  class AgentsConfig (line 388) | class AgentsConfig(BaseModel):
  class ProviderConfig (line 401) | class ProviderConfig(BaseModel):
  class ProvidersConfig (line 409) | class ProvidersConfig(BaseModel):
  class HeartbeatConfig (line 429) | class HeartbeatConfig(BaseModel):
  class GatewayConfig (line 436) | class GatewayConfig(BaseModel):
  class WebSearchConfig (line 443) | class WebSearchConfig(BaseModel):
  class OpenVikingConfig (line 451) | class OpenVikingConfig(BaseModel):
  class WebToolsConfig (line 462) | class WebToolsConfig(BaseModel):
  class ExecToolConfig (line 468) | class ExecToolConfig(BaseModel):
  class ToolsConfig (line 474) | class ToolsConfig(BaseModel):
  class SandboxNetworkConfig (line 481) | class SandboxNetworkConfig(BaseModel):
  class SandboxFilesystemConfig (line 497) | class SandboxFilesystemConfig(BaseModel):
  class SandboxRuntimeConfig (line 505) | class SandboxRuntimeConfig(BaseModel):
  class DirectBackendConfig (line 512) | class DirectBackendConfig(BaseModel):
  class SrtBackendConfig (line 518) | class SrtBackendConfig(BaseModel):
  class DockerBackendConfig (line 527) | class DockerBackendConfig(BaseModel):
  class OpenSandboxNetworkConfig (line 534) | class OpenSandboxNetworkConfig(BaseModel):
  class OpenSandboxRuntimeConfig (line 541) | class OpenSandboxRuntimeConfig(BaseModel):
  class OpenSandboxBackendConfig (line 549) | class OpenSandboxBackendConfig(BaseModel):
  class AioSandboxBackendConfig (line 564) | class AioSandboxBackendConfig(BaseModel):
  class SandboxBackendsConfig (line 570) | class SandboxBackendsConfig(BaseModel):
  class LangfuseConfig (line 580) | class LangfuseConfig(BaseModel):
  class SandboxConfig (line 589) | class SandboxConfig(BaseModel):
  class Config (line 597) | class Config(BaseSettings):
    method read_only (line 629) | def read_only(self) -> bool:
    method channels_config (line 634) | def channels_config(self) -> ChannelsConfig:
    method bot_data_path (line 641) | def bot_data_path(self) -> Path:
    method workspace_path (line 647) | def workspace_path(self) -> Path:
    method ov_data_path (line 652) | def ov_data_path(self) -> Path:
    method _get_vlm_config (line 655) | def _get_vlm_config(self) -> Optional[Dict[str, Any]]:
    method _match_provider (line 665) | def _match_provider(
    method get_provider (line 699) | def get_provider(self, model: str | None = None) -> ProviderConfig | N...
    method get_provider_name (line 704) | def get_provider_name(self, model: str | None = None) -> str | None:
    method get_api_key (line 709) | def get_api_key(self, model: str | None = None) -> str | None:
    method get_api_base (line 714) | def get_api_base(self, model: str | None = None) -> str | None:
  class SessionKey (line 730) | class SessionKey(BaseModel):
    method __hash__ (line 736) | def __hash__(self):
    method safe_name (line 739) | def safe_name(self):
    method channel_key (line 742) | def channel_key(self):
    method from_safe_name (line 746) | def from_safe_name(safe_name: str):

FILE: bot/vikingbot/console/web_console.py
  function resolve_schema_ref (line 13) | def resolve_schema_ref(
  function get_effective_schema (line 22) | def get_effective_schema(field_info: Dict[str, Any], root_schema: Dict[s...
  function create_dashboard_tab (line 30) | def create_dashboard_tab():
  function create_field_group (line 46) | def create_field_group(
  function collect_values_from_components (line 182) | def collect_values_from_components(
  function create_config_tabs (line 226) | def create_config_tabs():
  function create_sessions_tab (line 283) | def create_sessions_tab():
  function create_workspace_tab (line 357) | def create_workspace_tab():
  function create_console_app (line 408) | def create_console_app(bus=None, config=None):
  function run_console_server (line 445) | def run_console_server(port: int = 18791):

FILE: bot/vikingbot/cron/service.py
  function _now_ms (line 16) | def _now_ms() -> int:
  function _compute_next_run (line 20) | def _compute_next_run(schedule: CronSchedule, now_ms: int) -> int | None:
  class CronService (line 44) | class CronService:
    method __init__ (line 47) | def __init__(
    method _load_store (line 58) | def _load_store(self) -> CronStore:
    method _save_store (line 106) | def _save_store(self) -> None:
    method start (line 149) | async def start(self) -> None:
    method stop (line 160) | def stop(self) -> None:
    method _recompute_next_runs (line 167) | def _recompute_next_runs(self) -> None:
    method _get_next_wake_ms (line 176) | def _get_next_wake_ms(self) -> int | None:
    method _arm_timer (line 185) | def _arm_timer(self) -> None:
    method _on_timer (line 204) | async def _on_timer(self) -> None:
    method _execute_job (line 222) | async def _execute_job(self, job: CronJob) -> None:
    method list_jobs (line 257) | def list_jobs(self, include_disabled: bool = False) -> list[CronJob]:
    method add_job (line 263) | def add_job(
    method remove_job (line 300) | def remove_job(self, job_id: str) -> bool:
    method enable_job (line 314) | def enable_job(self, job_id: str, enabled: bool = True) -> CronJob | N...
    method run_job (line 330) | async def run_job(self, job_id: str, force: bool = False) -> bool:
    method status (line 343) | def status(self) -> dict:

FILE: bot/vikingbot/cron/types.py
  class CronSchedule (line 10) | class CronSchedule:
  class CronPayload (line 25) | class CronPayload:
  class CronJobState (line 36) | class CronJobState:
  class CronJob (line 46) | class CronJob:
  class CronStore (line 61) | class CronStore:

FILE: bot/vikingbot/heartbeat/service.py
  function _is_heartbeat_empty (line 27) | def _is_heartbeat_empty(content: str | None) -> bool:
  function _read_heartbeat_file (line 44) | def _read_heartbeat_file(workspace: Path) -> str | None:
  class HeartbeatService (line 55) | class HeartbeatService:
    method __init__ (line 63) | def __init__(
    method _get_all_workspaces (line 81) | def _get_all_workspaces(self) -> dict[Path, list[SessionKey]] | None:
    method start (line 101) | async def start(self) -> None:
    method stop (line 111) | def stop(self) -> None:
    method _run_loop (line 118) | async def _run_loop(self) -> None:
    method _tick (line 130) | async def _tick(self) -> None:
    method trigger_now (line 180) | async def trigger_now(self, session_key: SessionKey | None = None) -> ...

FILE: bot/vikingbot/hooks/base.py
  class HookContext (line 17) | class HookContext:
    method __post_init__ (line 26) | def __post_init__(self):
  class Hook (line 33) | class Hook(ABC):
    method execute (line 38) | async def execute(self, context: HookContext, **kwargs) -> Any:

FILE: bot/vikingbot/hooks/builtins/openviking_hooks.py
  function get_global_client (line 26) | async def get_global_client() -> VikingClient:
  class OpenVikingCompactHook (line 34) | class OpenVikingCompactHook(Hook):
    method _get_client (line 37) | async def _get_client(self, workspace_id: str) -> VikingClient:
    method execute (line 42) | async def execute(self, context: HookContext, **kwargs) -> Any:
  class OpenVikingPostCallHook (line 55) | class OpenVikingPostCallHook(Hook):
    method _get_client (line 59) | async def _get_client(self, workspace_id: str) -> VikingClient:
    method _read_skill_memory (line 63) | async def _read_skill_memory(self, workspace_id: str, skill_name: str)...
    method execute (line 86) | async def execute(self, context: HookContext, tool_name, params, resul...

FILE: bot/vikingbot/hooks/manager.py
  class HookManager (line 17) | class HookManager:
    method __init__ (line 18) | def __init__(self):
    method import_path (line 21) | def import_path(self, path):
    method register_path (line 36) | def register_path(self, hook_path_list) -> None:
    method execute_hooks (line 46) | async def execute_hooks(self, context: HookContext, **kwargs) -> List[...

FILE: bot/vikingbot/integrations/__init__.py
  function __getattr__ (line 11) | def __getattr__(name: str):

FILE: bot/vikingbot/integrations/langfuse.py
  class LangfuseClient (line 21) | class LangfuseClient:
    method __init__ (line 26) | def __init__(
    method get_instance (line 66) | def get_instance(cls) -> "LangfuseClient":
    method set_instance (line 74) | def set_instance(cls, instance: "LangfuseClient") -> None:
    method flush (line 78) | def flush(self) -> None:
    method propagate_attributes (line 84) | def propagate_attributes(
    method trace (line 150) | def trace(
    method span (line 179) | def span(
    method generation (line 202) | def generation(
    method update_generation (line 261) | def update_generation(
    method tool_call (line 306) | def tool_call(
    method end_tool_call (line 344) | def end_tool_call(

FILE: bot/vikingbot/openviking_mount/__init__.py
  function __getattr__ (line 34) | def __getattr__(name: str):

FILE: bot/vikingbot/openviking_mount/fuse_finder.py
  class OpenVikingFUSE (line 34) | class OpenVikingFUSE(Operations):
    method __init__ (line 35) | def __init__(self, mount: OpenVikingMount):
    method _should_ignore_file (line 50) | def _should_ignore_file(self, path: str) -> bool:
    method _path_to_uri (line 54) | def _path_to_uri(self, path: str) -> str:
    method _is_pdf_resource (line 62) | def _is_pdf_resource(self, name: str) -> bool:
    method _get_pdf_dir_name (line 65) | def _get_pdf_dir_name(self, pdf_name: str) -> str:
    method _has_original_pdf (line 70) | def _has_original_pdf(self, pdf_dir_name: str) -> Path | None:
    method getattr (line 76) | def getattr(self, path: str, fh: int = None) -> Dict[str, Any]:
    method readdir (line 161) | def readdir(self, path: str, fh: int) -> list:
    method open (line 194) | def open(self, path: str, flags: int) -> int:
    method read (line 211) | def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
    method create (line 242) | def create(self, path: str, mode: int, device: int = None) -> int:
    method write (line 262) | def write(self, path: str, data: bytes, offset: int, fh: int) -> int:
    method truncate (line 285) | def truncate(self, path: str, length: int, fh: int = None) -> None:
    method flush (line 299) | def flush(self, path: str, fh: int) -> None:
    method fsync (line 302) | def fsync(self, path: str, datasync: int, fh: int) -> None:
    method release (line 305) | def release(self, path: str, fh: int) -> None:
    method _handle_pdf_upload (line 320) | def _handle_pdf_upload(self, path: str, data: bytes) -> None:
    method unlink (line 352) | def unlink(self, path: str) -> None:
    method mkdir (line 377) | def mkdir(self, path: str, mode: int) -> None:
    method rmdir (line 381) | def rmdir(self, path: str) -> None:
    method rename (line 385) | def rename(self, old: str, new: str) -> None:
    method chmod (line 389) | def chmod(self, path: str, mode: int) -> None:
    method chown (line 392) | def chown(self, path: str, uid: int, gid: int) -> None:
    method utimens (line 395) | def utimens(self, path: str, times: tuple = None) -> None:
    method statfs (line 398) | def statfs(self, path: str) -> Dict[str, Any]:
  function mount_fuse (line 414) | def mount_fuse(config: MountConfig, foreground: bool = True) -> None:
  class FUSEMountManager (line 442) | class FUSEMountManager:
    method __init__ (line 443) | def __init__(self):
    method mount (line 446) | def mount(self, config: MountConfig) -> str:
    method unmount (line 449) | def unmount(self, mount_point: Path) -> None:

FILE: bot/vikingbot/openviking_mount/fuse_proxy.py
  class OpenVikingFUSE (line 35) | class OpenVikingFUSE(Operations):
    method __init__ (line 36) | def __init__(self, mount: OpenVikingMount):
    method _should_ignore_file (line 50) | def _should_ignore_file(self, path: str) -> bool:
    method _get_original_path (line 54) | def _get_original_path(self, path: str) -> Path:
    method getattr (line 59) | def getattr(self, path: str, fh: int = None) -> Dict[str, Any]:
    method readdir (line 92) | def readdir(self, path: str, fh: int) -> list:
    method open (line 108) | def open(self, path: str, flags: int) -> int:
    method read (line 116) | def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
    method create (line 132) | def create(self, path: str, mode: int, device: int = None) -> int:
    method write (line 143) | def write(self, path: str, data: bytes, offset: int, fh: int) -> int:
    method truncate (line 163) | def truncate(self, path: str, length: int, fh: int = None) -> None:
    method flush (line 175) | def flush(self, path: str, fh: int) -> None:
    method fsync (line 178) | def fsync(self, path: str, datasync: int, fh: int) -> None:
    method release (line 181) | def release(self, path: str, fh: int) -> None:
    method _handle_upload (line 192) | def _handle_upload(self, path: str, data: bytes) -> None:
    method unlink (line 224) | def unlink(self, path: str) -> None:
    method mkdir (line 246) | def mkdir(self, path: str, mode: int) -> None:
    method rmdir (line 251) | def rmdir(self, path: str) -> None:
    method rename (line 256) | def rename(self, old: str, new: str) -> None:
    method chmod (line 262) | def chmod(self, path: str, mode: int) -> None:
    method chown (line 267) | def chown(self, path: str, uid: int, gid: int) -> None:
    method utimens (line 271) | def utimens(self, path: str, times: tuple = None) -> None:
    method statfs (line 279) | def statfs(self, path: str) -> Dict[str, Any]:
  function mount_fuse (line 295) | def mount_fuse(config: MountConfig, foreground: bool = True) -> None:
  class FUSEMountManager (line 323) | class FUSEMountManager:
    method __init__ (line 324) | def __init__(self):
    method mount (line 327) | def mount(self, config: MountConfig) -> str:
    method unmount (line 330) | def unmount(self, mount_point: Path) -> None:

FILE: bot/vikingbot/openviking_mount/fuse_simple.py
  class OpenVikingFUSE (line 34) | class OpenVikingFUSE(Operations):
    method __init__ (line 35) | def __init__(self, mount: OpenVikingMount):
    method _path_to_uri (line 47) | def _path_to_uri(self, path: str) -> str:
    method _is_pdf_resource (line 55) | def _is_pdf_resource(self, name: str) -> bool:
    method _get_pdf_dir_name (line 58) | def _get_pdf_dir_name(self, pdf_name: str) -> str:
    method _has_original_pdf (line 63) | def _has_original_pdf(self, pdf_dir_name: str) -> Path | None:
    method getattr (line 69) | def getattr(self, path: str, fh: int = None) -> Dict[str, Any]:
    method readdir (line 150) | def readdir(self, path: str, fh: int) -> list:
    method open (line 183) | def open(self, path: str, flags: int) -> int:
    method read (line 195) | def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
    method create (line 226) | def create(self, path: str, mode: int, device: int = None) -> int:
    method write (line 240) | def write(self, path: str, data: bytes, offset: int, fh: int) -> int:
    method truncate (line 258) | def truncate(self, path: str, length: int, fh: int = None) -> None:
    method flush (line 271) | def flush(self, path: str, fh: int) -> None:
    method fsync (line 275) | def fsync(self, path: str, datasync: int, fh: int) -> None:
    method release (line 279) | def release(self, path: str, fh: int) -> None:
    method _handle_pdf_upload (line 293) | def _handle_pdf_upload(self, path: str, data: bytes) -> None:
    method unlink (line 325) | def unlink(self, path: str) -> None:
    method mkdir (line 350) | def mkdir(self, path: str, mode: int) -> None:
    method rmdir (line 354) | def rmdir(self, path: str) -> None:
    method rename (line 358) | def rename(self, old: str, new: str) -> None:
    method chmod (line 362) | def chmod(self, path: str, mode: int) -> None:
    method chown (line 366) | def chown(self, path: str, uid: int, gid: int) -> None:
    method utimens (line 370) | def utimens(self, path: str, times: tuple = None) -> None:
    method statfs (line 374) | def statfs(self, path: str) -> Dict[str, Any]:
  function mount_fuse (line 390) | def mount_fuse(config: MountConfig, foreground: bool = True) -> None:
  class FUSEMountManager (line 418) | class FUSEMountManager:
    method __init__ (line 419) | def __init__(self):
    method mount (line 422) | def mount(self, config: MountConfig) -> str:
    method unmount (line 425) | def unmount(self, mount_point: Path) -> None:

FILE: bot/vikingbot/openviking_mount/fuse_simple_debug.py
  class OpenVikingFUSE (line 34) | class OpenVikingFUSE(Operations):
    method __init__ (line 35) | def __init__(self, mount: OpenVikingMount):
    method _should_ignore_file (line 50) | def _should_ignore_file(self, path: str) -> bool:
    method _log_call (line 54) | def _log_call(self, method: str, *args, **kwargs):
    method _path_to_uri (line 57) | def _path_to_uri(self, path: str) -> str:
    method _is_pdf_resource (line 65) | def _is_pdf_resource(self, name: str) -> bool:
    method _get_pdf_dir_name (line 68) | def _get_pdf_dir_name(self, pdf_name: str) -> str:
    method _has_original_pdf (line 73) | def _has_original_pdf(self, pdf_dir_name: str) -> Path | None:
    method getattr (line 79) | def getattr(self, path: str, fh: int = None) -> Dict[str, Any]:
    method readdir (line 172) | def readdir(self, path: str, fh: int) -> list:
    method open (line 209) | def open(self, path: str, flags: int) -> int:
    method read (line 225) | def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
    method create (line 262) | def create(self, path: str, mode: int, device: int = None) -> int:
    method write (line 281) | def write(self, path: str, data: bytes, offset: int, fh: int) -> int:
    method truncate (line 303) | def truncate(self, path: str, length: int, fh: int = None) -> None:
    method flush (line 317) | def flush(self, path: str, fh: int) -> None:
    method fsync (line 320) | def fsync(self, path: str, datasync: int, fh: int) -> None:
    method release (line 323) | def release(self, path: str, fh: int) -> None:
    method _handle_pdf_upload (line 338) | def _handle_pdf_upload(self, path: str, data: bytes) -> None:
    method unlink (line 370) | def unlink(self, path: str) -> None:
    method mkdir (line 395) | def mkdir(self, path: str, mode: int) -> None:
    method rmdir (line 399) | def rmdir(self, path: str) -> None:
    method rename (line 403) | def rename(self, old: str, new: str) -> None:
    method chmod (line 407) | def chmod(self, path: str, mode: int) -> None:
    method chown (line 410) | def chown(self, path: str, uid: int, gid: int) -> None:
    method utimens (line 413) | def utimens(self, path: str, times: tuple = None) -> None:
    method statfs (line 416) | def statfs(self, path: str) -> Dict[str, Any]:
  function mount_fuse (line 432) | def mount_fuse(config: MountConfig, foreground: bool = True) -> None:
  class FUSEMountManager (line 460) | class FUSEMountManager:
    method __init__ (line 461) | def __init__(self):
    method mount (line 464) | def mount(self, config: MountConfig) -> str:
    method unmount (line 467) | def unmount(self, mount_point: Path) -> None:

FILE: bot/vikingbot/openviking_mount/manager.py
  class MountPoint (line 21) | class MountPoint:
  class OpenVikingMountManager (line 30) | class OpenVikingMountManager:
    method __init__ (line 37) | def __init__(self, base_mount_dir: Optional[Path] = None):
    method create_mount (line 54) | def create_mount(
    method get_mount (line 102) | def get_mount(self, mount_id: str) -> Optional[OpenVikingMount]:
    method list_mounts (line 117) | def list_mounts(self) -> List[Dict]:
    method remove_mount (line 139) | def remove_mount(self, mount_id: str, cleanup: bool = False) -> None:
    method remove_all (line 169) | def remove_all(self, cleanup: bool = False) -> None:
    method create_session_mount (line 180) | def create_session_mount(
    method create_resources_mount (line 203) | def create_resources_mount(
    method __enter__ (line 231) | def __enter__(self) -> "OpenVikingMountManager":
    method __exit__ (line 235) | def __exit__(self, exc_type, exc_val, exc_tb) -> None:
  function get_mount_manager (line 244) | def get_mount_manager(base_mount_dir: Optional[Path] = None) -> OpenViki...

FILE: bot/vikingbot/openviking_mount/mount.py
  class MountScope (line 20) | class MountScope(Enum):
  class MountConfig (line 31) | class MountConfig:
  class FileInfo (line 44) | class FileInfo:
  class OpenVikingMount (line 56) | class OpenVikingMount:
    method __init__ (line 63) | def __init__(self, config: MountConfig):
    method _ensure_mount_point (line 78) | def _ensure_mount_point(self) -> None:
    method initialize (line 85) | def initialize(self) -> None:
    method _ensure_client (line 102) | def _ensure_client(self) -> None:
    method client (line 111) | def client(self) -> Optional[ov.SyncOpenViking]:
    method _uri_to_path (line 115) | def _uri_to_path(self, uri: str) -> Path:
    method _path_to_uri (line 145) | def _path_to_uri(self, path: Union[str, Path]) -> str:
    method _get_scope_root_uri (line 167) | def _get_scope_root_uri(self) -> str:
    method list_dir (line 173) | def list_dir(self, path: Union[str, Path]) -> List[FileInfo]:
    method read_file (line 213) | def read_file(self, path: Union[str, Path]) -> str:
    method write_file (line 234) | def write_file(self, path: Union[str, Path], content: str) -> None:
    method mkdir (line 259) | def mkdir(self, path: Union[str, Path]) -> None:
    method delete (line 280) | def delete(self, path: Union[str, Path], recursive: bool = False) -> N...
    method get_abstract (line 302) | def get_abstract(self, path: Union[str, Path]) -> Optional[str]:
    method get_overview (line 323) | def get_overview(self, path: Union[str, Path]) -> Optional[str]:
    method search (line 344) | def search(self, query: str, target_path: Optional[Union[str, Path]] =...
    method add_resource (line 382) | def add_resource(
    method sync_to_disk (line 417) | def sync_to_disk(self, path: Optional[Union[str, Path]] = None) -> None:
    method _sync_recursive (line 438) | def _sync_recursive(self, uri: str, local_path: Path) -> None:
    method close (line 474) | def close(self) -> None:
    method __enter__ (line 486) | def __enter__(self) -> "OpenVikingMount":
    method __exit__ (line 492) | def __exit__(self, exc_type, exc_val, exc_tb) -> None:

FILE: bot/vikingbot/openviking_mount/ov_server.py
  class VikingClient (line 15) | class VikingClient:
    method __init__ (line 16) | def __init__(self, agent_id: Optional[str] = None):
    method _initialize (line 49) | async def _initialize(self):
    method create (line 60) | async def create(cls, agent_id: Optional[str] = None):
    method _matched_context_to_dict (line 70) | def _matched_context_to_dict(self, matched_context: Any) -> Dict[str, ...
    method _relation_to_dict (line 86) | def _relation_to_dict(self, relation: Any) -> Dict[str, Any]:
    method get_agent_space_name (line 95) | def get_agent_space_name(self, user_id: str) -> str:
    method find (line 98) | async def find(self, query: str, target_uri: Optional[str] = None):
    method add_resource (line 104) | async def add_resource(self, local_path: str, desc: str) -> Optional[D...
    method list_resources (line 109) | async def list_resources(
    method read_content (line 118) | async def read_content(self, uri: str, level: str = "abstract") -> str:
    method read_user_profile (line 140) | async def read_user_profile(self, user_id: str) -> str:
    method search (line 165) | async def search(self, query: str, target_uri: Optional[str] = "") -> ...
    method search_user_memory (line 186) | async def search_user_memory(self, query: str, user_id: str) -> list[A...
    method _check_user_exists (line 198) | async def _check_user_exists(self, user_id: str) -> bool:
    method _initialize_user (line 218) | async def _initialize_user(self, user_id: str, role: str = "user") -> ...
    method _get_or_create_user_apikey (line 247) | async def _get_or_create_user_apikey(self, user_id: str) -> Optional[s...
    method search_memory (line 291) | async def search_memory(
    method grep (line 328) | async def grep(self, uri: str, pattern: str, case_insensitive: bool = ...
    method glob (line 334) | async def glob(self, pattern: str, uri: Optional[str] = None) -> Dict[...
    method commit (line 338) | async def commit(self, session_id: str, messages: list[dict[str, Any]]...
    method close (line 436) | async def close(self):
  function main_test (line 441) | async def main_test():
  function account_test (line 464) | async def account_test():

FILE: bot/vikingbot/openviking_mount/session_integration.py
  class SessionOpenVikingManager (line 25) | class SessionOpenVikingManager:
    method __init__ (line 32) | def __init__(self, base_workspace: Optional[Path] = None):
    method get_session_workspace (line 55) | def get_session_workspace(self, session_key: str) -> Path:
    method get_session_ov_data_path (line 68) | def get_session_ov_data_path(self, session_key: str) -> Path:
    method mount_for_session (line 80) | def mount_for_session(
    method delete_session_workspace (line 171) | def delete_session_workspace(self, session_key: str) -> bool:
    method unmount_for_session (line 199) | def unmount_for_session(self, session_key: str) -> bool:
    method is_mounted (line 230) | def is_mounted(self, session_key: str) -> bool:
    method is_workspace_exists (line 234) | def is_workspace_exists(self, session_key: str) -> bool:
    method cleanup_orphaned_mounts (line 247) | def cleanup_orphaned_mounts(self) -> int:
    method get_api_mount (line 270) | def get_api_mount(self, session_key: str) -> Optional[OpenVikingMount]:
    method unmount_all (line 313) | def unmount_all(self) -> None:
    method cleanup (line 319) | async def cleanup(self) -> None:
  function get_session_ov_manager (line 329) | def get_session_ov_manager(base_workspace: Optional[Path] = None) -> Ses...

FILE: bot/vikingbot/openviking_mount/user_apikey_manager.py
  class UserApiKeyManager (line 11) | class UserApiKeyManager:
    method __init__ (line 20) | def __init__(self, ov_path: Path, server_url: str, account_id: str):
    method _ensure_config_dir (line 44) | def _ensure_config_dir(self) -> None:
    method _load (line 48) | def _load(self) -> None:
    method _save (line 66) | def _save(self) -> None:
    method get_apikey (line 85) | def get_apikey(self, user_id: str) -> Optional[str]:
    method set_apikey (line 97) | def set_apikey(self, user_id: str, api_key: str) -> None:
    method delete_apikey (line 108) | def delete_apikey(self, user_id: str) -> bool:

FILE: bot/vikingbot/openviking_mount/viking_fuse.py
  class OpenVikingFUSE (line 41) | class OpenVikingFUSE(Operations):
    method __init__ (line 49) | def __init__(self, mount: OpenVikingMount):
    method _path_to_uri (line 64) | def _path_to_uri(self, path: str) -> str:
    method getattr (line 84) | def getattr(self, path: str, fh: int = None) -> Dict[str, Any]:
    method readdir (line 154) | def readdir(self, path: str, fh: int) -> list:
    method open (line 188) | def open(self, path: str, flags: int) -> int:
    method read (line 220) | def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
    method write (line 253) | def write(self, path: str, data: bytes, offset: int, fh: int) -> int:
    method release (line 286) | def release(self, path: str, fh: int) -> None:
    method mkdir (line 301) | def mkdir(self, path: str, mode: int) -> None:
    method rmdir (line 320) | def rmdir(self, path: str) -> None:
    method unlink (line 338) | def unlink(self, path: str) -> None:
    method truncate (line 356) | def truncate(self, path: str, length: int, fh: int = None) -> None:
    method utimens (line 377) | def utimens(self, path: str, times: tuple = None) -> None:
  function mount_fuse (line 387) | def mount_fuse(
  class FUSEMountManager (line 424) | class FUSEMountManager:
    method __init__ (line 431) | def __init__(self):
    method mount (line 434) | def mount(self, mount_id: str, config: MountConfig, background: bool =...
    method unmount (line 456) | def unmount(self, mount_id: str) -> None:
    method unmount_all (line 469) | def unmount_all(self) -> None:
    method __init__ (line 486) | def __init__(self):
    method mount (line 489) | def mount(self, *args, **kwargs):
    method unmount (line 492) | def unmount(self, *args, **kwargs):
    method unmount_all (line 495) | def unmount_all(self):
  function mount_fuse (line 478) | def mount_fuse(*args, **kwargs):
  class FUSEMountManager (line 483) | class FUSEMountManager:
    method __init__ (line 431) | def __init__(self):
    method mount (line 434) | def mount(self, mount_id: str, config: MountConfig, background: bool =...
    method unmount (line 456) | def unmount(self, mount_id: str) -> None:
    method unmount_all (line 469) | def unmount_all(self) -> None:
    method __init__ (line 486) | def __init__(self):
    method mount (line 489) | def mount(self, *args, **kwargs):
    method unmount (line 492) | def unmount(self, *args, **kwargs):
    method unmount_all (line 495) | def unmount_all(self):

FILE: bot/vikingbot/providers/base.py
  class ToolCallRequest (line 9) | class ToolCallRequest:
  class LLMResponse (line 19) | class LLMResponse:
    method has_tool_calls (line 29) | def has_tool_calls(self) -> bool:
  class LLMProvider (line 34) | class LLMProvider(ABC):
    method __init__ (line 42) | def __init__(self, api_key: str | None = None, api_base: str | None = ...
    method chat (line 47) | async def chat(
    method get_default_model (line 73) | def get_default_model(self) -> str:

FILE: bot/vikingbot/providers/litellm_provider.py
  class LiteLLMProvider (line 17) | class LiteLLMProvider(LLMProvider):
    method __init__ (line 26) | def __init__(
    method _setup_env (line 57) | def _setup_env(self, api_key: str, api_base: str | None, model: str) -...
    method _resolve_model (line 78) | def _resolve_model(self, model: str) -> str:
    method _apply_model_overrides (line 97) | def _apply_model_overrides(self, model: str, kwargs: dict[str, Any]) -...
    method _handle_system_message (line 107) | def _handle_system_message(
    method chat (line 165) | async def chat(
    method _parse_response (line 313) | def _parse_response(self, response: Any) -> LLMResponse:
    method get_default_model (line 367) | def get_default_model(self) -> str:

FILE: bot/vikingbot/providers/registry.py
  class ProviderSpec (line 20) | class ProviderSpec:
    method label (line 55) | def label(self) -> str:
  function find_by_model (line 307) | def find_by_model(model: str) -> ProviderSpec | None:
  function find_gateway (line 319) | def find_gateway(
  function find_by_name (line 350) | def find_by_name(name: str) -> ProviderSpec | None:

FILE: bot/vikingbot/providers/transcription.py
  class GroqTranscriptionProvider (line 11) | class GroqTranscriptionProvider:
    method __init__ (line 18) | def __init__(self, api_key: str | None = None):
    method transcribe (line 22) | async def transcribe(self, file_path: str | Path) -> str:

FILE: bot/vikingbot/sandbox/backends/__init__.py
  function register_backend (line 9) | def register_backend(name: str) -> Callable[[Type[SandboxBackend]], Type...
  function get_backend (line 19) | def get_backend(name: str) -> Type[SandboxBackend] | None:
  function list_backends (line 24) | def list_backends() -> list[str]:

FILE: bot/vikingbot/sandbox/backends/aiosandbox.py
  class AioSandboxBackend (line 14) | class AioSandboxBackend(SandboxBackend):
    method __init__ (line 17) | def __init__(self, config: "SandboxConfig", session_key: SessionKey, w...
    method start (line 25) | async def start(self) -> None:
    method execute (line 44) | async def execute(self, command: str, timeout: int = 60, **kwargs: Any...
    method stop (line 85) | async def stop(self) -> None:
    method is_running (line 90) | def is_running(self) -> bool:
    method workspace (line 95) | def workspace(self) -> Path:
    method sandbox_cwd (line 100) | def sandbox_cwd(self) -> str:
    method read_file (line 104) | async def read_file(self, path: str) -> str:
    method write_file (line 122) | async def write_file(self, path: str, content: str) -> None:
    method list_dir (line 139) | async def list_dir(self, path: str) -> list[tuple[str, bool]]:

FILE: bot/vikingbot/sandbox/backends/direct.py
  class DirectBackend (line 18) | class DirectBackend(SandboxBackend):
    method __init__ (line 21) | def __init__(self, config: "SandboxConfig", session_key: SessionKey, w...
    method start (line 28) | async def start(self) -> None:
    method execute (line 34) | async def execute(self, command: str, timeout: int = 60, **kwargs: Any...
    method stop (line 88) | async def stop(self) -> None:
    method is_running (line 93) | def is_running(self) -> bool:
    method workspace (line 98) | def workspace(self) -> Path:
    method sandbox_cwd (line 103) | def sandbox_cwd(self) -> str:
    method read_file (line 107) | async def read_file(self, path: str) -> str:
    method write_file (line 119) | async def write_file(self, path: str, content: str) -> None:
    method list_dir (line 128) | async def list_dir(self, path: str) -> list[tuple[str, bool]]:

FILE: bot/vikingbot/sandbox/backends/opensandbox.py
  function _is_kubernetes_env (line 23) | def _is_kubernetes_env() -> bool:
  function _wait_for_server (line 31) | async def _wait_for_server(url: str, timeout: int = 60) -> bool:
  function _start_opensandbox_server (line 51) | def _start_opensandbox_server() -> "subprocess.Popen | None":
  function cleanup_opensandbox_server (line 99) | def cleanup_opensandbox_server():
  class OpenSandboxBackend (line 116) | class OpenSandboxBackend(SandboxBackend):
    method __init__ (line 117) | def __init__(self, config: "SandboxConfig", session_key: SessionKey, w...
    method start (line 140) | async def start(self) -> None:
    method execute (line 217) | async def execute(self, command: str, timeout: int = 60, **kwargs: Any...
    method stop (line 271) | async def stop(self) -> None:
    method is_running (line 285) | def is_running(self) -> bool:
    method workspace (line 289) | def workspace(self) -> Path:
    method sandbox_cwd (line 293) | def sandbox_cwd(self) -> str:
    method read_file (line 296) | async def read_file(self, path: str) -> str:
    method write_file (line 314) | async def write_file(self, path: str, content: str) -> None:
    method list_dir (line 332) | async def list_dir(self, path: str) -> list[tuple[str, bool]]:

FILE: bot/vikingbot/sandbox/backends/srt-wrapper.mjs
  function handleMessage (line 117) | async function handleMessage(message) {
  function initialize (line 155) | async function initialize(config) {
  function executeCommand (line 188) | async function executeCommand(command, timeout, customConfig) {
  function readFile (line 244) | async function readFile(path) {
  function writeFile (line 268) | async function writeFile(path, content) {
  function listDir (line 307) | async function listDir(path) {
  function executeCommandInternal (line 354) | async function executeCommandInternal(command, timeout) {
  function updateConfig (line 382) | function updateConfig(config) {
  function getProxyPorts (line 392) | function getProxyPorts() {
  function reset (line 408) | async function reset() {
  function sendResponse (line 423) | function sendResponse(response) {
  function sendError (line 427) | function sendError(message) {

FILE: bot/vikingbot/sandbox/backends/srt.py
  class SrtBackend (line 18) | class SrtBackend(SandboxBackend):
    method __init__ (line 21) | def __init__(self, config, session_key: SessionKey, workspace: Path):
    method _generate_settings (line 40) | def _generate_settings(self) -> Path:
    method start (line 55) | async def start(self) -> None:
    method execute (line 125) | async def execute(self, command: str, timeout: int = 60, **kwargs: Any...
    method stop (line 181) | async def stop(self) -> None:
    method is_running (line 210) | def is_running(self) -> bool:
    method workspace (line 215) | def workspace(self) -> Path:
    method sandbox_cwd (line 220) | def sandbox_cwd(self) -> str:
    method _load_config (line 224) | def _load_config(self) -> dict[str, Any]:
    method read_file (line 245) | async def read_file(self, path: str) -> str:
    method write_file (line 265) | async def write_file(self, path: str, content: str) -> None:
    method list_dir (line 283) | async def list_dir(self, path: str) -> list[tuple[str, bool]]:
    method _send_message (line 304) | async def _send_message(self, message: dict[str, Any]) -> None:
    method _read_responses (line 313) | async def _read_responses(self) -> None:
    method _wait_for_response (line 342) | async def _wait_for_response(self, timeout: float = 30.0) -> dict[str,...

FILE: bot/vikingbot/sandbox/base.py
  class SandboxBackend (line 8) | class SandboxBackend(ABC):
    method __init__ (line 11) | def __init__(self):
    method start (line 15) | async def start(self) -> None:
    method execute (line 19) | async def execute(self, command: str, timeout: int = 60, **kwargs: Any...
    method stop (line 23) | async def stop(self) -> None:
    method is_running (line 27) | def is_running(self) -> bool:
    method workspace (line 32) | def workspace(self) -> Path:
    method sandbox_cwd (line 36) | def sandbox_cwd(self) -> str:
    method _check_path_restriction (line 44) | def _check_path_restriction(self, path: Path) -> None:
    method _resolve_path (line 60) | def _resolve_path(self, path: str) -> Path:
    method read_file (line 76) | async def read_file(self, path: str) -> str:
    method write_file (line 98) | async def write_file(self, path: str, content: str) -> None:
    method list_dir (line 114) | async def list_dir(self, path: str) -> list[tuple[str, bool]]:
  class SandboxError (line 141) | class SandboxError(Exception):
  class SandboxNotStartedError (line 145) | class SandboxNotStartedError(SandboxError):
  class SandboxDisabledError (line 149) | class SandboxDisabledError(SandboxError):
  class SandboxExecutionError (line 153) | class SandboxExecutionError(SandboxError):
  class UnsupportedBackendError (line 157) | class UnsupportedBackendError(SandboxError):

FILE: bot/vikingbot/sandbox/manager.py
  class SandboxManager (line 15) | class SandboxManager:
    method __init__ (line 20) | def __init__(self, config: Config, sandbox_parent_path: Path, source_w...
    method get_sandbox (line 30) | async def get_sandbox(self, session_key: SessionKey) -> SandboxBackend:
    method _get_or_create_sandbox (line 33) | async def _get_or_create_sandbox(self, session_key: SessionKey) -> San...
    method _create_sandbox (line 41) | async def _create_sandbox(self, workspace_id: str) -> SandboxBackend:
    method _copy_bootstrap_files (line 55) | async def _copy_bootstrap_files(self, sandbox_workspace: Path) -> None:
    method cleanup_session (line 91) | async def cleanup_session(self, session_key: SessionKey) -> None:
    method cleanup_all (line 98) | async def cleanup_all(self) -> None:
    method get_workspace_path (line 104) | def get_workspace_path(self, session_key: SessionKey) -> Path:
    method to_workspace_id (line 107) | def to_workspace_id(self, session_key: SessionKey):
    method get_sandbox_cwd (line 115) | async def get_sandbox_cwd(self, session_key: SessionKey) -> str:

FILE: bot/vikingbot/session/manager.py
  class Session (line 18) | class Session:
    method add_message (line 31) | def add_message(
    method get_history (line 43) | def get_history(self, max_messages: int = 50) -> list[dict[str, Any]]:
    method clear (line 61) | def clear(self) -> None:
    method clone (line 66) | def clone(self) -> "Session":
  class SessionManager (line 79) | class SessionManager:
    method __init__ (line 106) | def __init__(
    method _get_session_path (line 117) | def _get_session_path(self, session_key: SessionKey) -> Path:
    method get_or_create (line 120) | def get_or_create(self, key: SessionKey, skip_heartbeat: bool = False)...
    method _init_sandbox (line 159) | async def _init_sandbox(self, key: SessionKey) -> None:
    method _load (line 168) | def _load(self, session_key: SessionKey) -> Session | None:
    method save (line 214) | async def save(self, session: Session) -> None:
    method delete (line 235) | def delete(self, key: SessionKey) -> bool:
    method list_sessions (line 259) | def list_sessions(self) -> list[dict[str, Any]]:

FILE: bot/vikingbot/utils/helpers.py
  function ensure_dir (line 8) | def ensure_dir(path: Path) -> Path:
  function set_bot_data_path (line 20) | def set_bot_data_path(path: Path) -> None:
  function get_bot_data_path (line 29) | def get_bot_data_path() -> Path:
  function get_data_path (line 37) | def get_data_path() -> Path:
  function get_sessions_path (line 42) | def get_sessions_path() -> Path:
  function get_history_path (line 47) | def get_history_path() -> Path:
  function get_bridge_path (line 52) | def get_bridge_path() -> Path:
  function get_images_path (line 57) | def get_images_path() -> Path:
  function get_media_path (line 62) | def get_media_path() -> Path:
  function get_received_path (line 67) | def get_received_path() -> Path:
  function get_mochat_path (line 72) | def get_mochat_path() -> Path:
  function get_mounts_path (line 77) | def get_mounts_path() -> Path:
  function get_source_workspace_path (line 82) | def get_source_workspace_path() -> Path:
  function get_workspace_path (line 87) | def get_workspace_path() -> Path:
  function ensure_workspace_templates (line 91) | def ensure_workspace_templates(workspace: Path) -> None:
  function ensure_session_workspace (line 175) | def ensure_session_workspace(workspace_path: Path) -> Path:
  function _create_minimal_workspace_templates (line 183) | def _create_minimal_workspace_templates(workspace: Path) -> None:
  function get_skills_path (line 261) | def get_skills_path(workspace: Path | None = None) -> Path:
  function cal_str_tokens (line 267) | def cal_str_tokens(text: str, text_type: str = "mixed") -> int:
  function timestamp (line 278) | def timestamp() -> str:
  function truncate_string (line 283) | def truncate_string(s: str, max_len: int = 100, suffix: str = "...") -> ...

FILE: bot/vikingbot/utils/tracing.py
  function get_current_session_id (line 28) | def get_current_session_id() -> str | None:
  function set_session_id (line 34) | def set_session_id(session_id: str | None) -> Generator[None, None, None]:
  function trace (line 53) | def trace(

FILE: bot/workspace/skills/github-proxy/scripts/convert_url.py
  function is_github_url (line 16) | def is_github_url(url: str) -> bool:
  function convert_url (line 23) | def convert_url(url: str, proxy: str = DEFAULT_PROXY) -> str:
  function main (line 37) | def main():

FILE: bot/workspace/skills/opencode/list_sessions.py
  class ViewSession (line 27) | class ViewSession(BaseModel):

FILE: bot/workspace/skills/opencode/opencode_utils.py
  function execute_cmd (line 14) | def execute_cmd(cmd):
  function start_opencode (line 39) | def start_opencode():
  function check_serve_status (line 79) | def check_serve_status():
  function read_new_messages (line 93) | def read_new_messages(client, session_id, last_ts):
  function read_status (line 128) | def read_status():
  function write_status (line 143) | def write_status(status):
  function list_project (line 152) | def list_project(client):

FILE: build_support/x86_profiles.py
  class EngineBuildConfig (line 13) | class EngineBuildConfig:
  function _normalize_machine (line 19) | def _normalize_machine(machine: str | None) -> str:
  function is_x86_machine (line 23) | def is_x86_machine(machine: str | None) -> bool:
  function _normalize_x86_variants (line 28) | def _normalize_x86_variants(raw_variants: Iterable[str]) -> tuple[str, ....
  function get_requested_x86_build_variants (line 42) | def get_requested_x86_build_variants(raw_value: str | None = None) -> tu...
  function get_host_engine_build_config (line 52) | def get_host_engine_build_config(machine: str | None) -> EngineBuildConfig:

FILE: crates/ov_cli/src/client.rs
  type HttpClient (line 15) | pub struct HttpClient {
    method new (line 24) | pub fn new(
    method is_local_server (line 44) | fn is_local_server(&self) -> bool {
    method zip_directory (line 54) | fn zip_directory(&self, dir_path: &Path) -> Result<NamedTempFile> {
    method upload_temp_file (line 83) | async fn upload_temp_file(&self, file_path: &Path) -> Result<String> {
    method build_headers (line 124) | fn build_headers(&self) -> reqwest::header::HeaderMap {
    method get (line 144) | pub async fn get<T: DeserializeOwned>(
    method post (line 163) | pub async fn post<B: serde::Serialize, T: DeserializeOwned>(
    method put (line 182) | pub async fn put<B: serde::Serialize, T: DeserializeOwned>(
    method delete (line 201) | pub async fn delete<T: DeserializeOwned>(
    method delete_with_body (line 220) | pub async fn delete_with_body<B: serde::Serialize, T: DeserializeOwned>(
    method handle_response (line 238) | async fn handle_response<T: DeserializeOwned>(
    method read (line 295) | pub async fn read(&self, uri: &str) -> Result<String> {
    method abstract_content (line 300) | pub async fn abstract_content(&self, uri: &str) -> Result<String> {
    method overview (line 305) | pub async fn overview(&self, uri: &str) -> Result<String> {
    method reindex (line 310) | pub async fn reindex(&self, uri: &str, regenerate: bool, wait: bool) -...
    method get_bytes (line 320) | pub async fn get_bytes(&self, uri: &str) -> Result<Vec<u8>> {
    method ls (line 366) | pub async fn ls(&self, uri: &str, simple: bool, recursive: bool, outpu...
    method tree (line 379) | pub async fn tree(&self, uri: &str, output: &str, abs_limit: i32, show...
    method mkdir (line 391) | pub async fn mkdir(&self, uri: &str) -> Result<()> {
    method rm (line 397) | pub async fn rm(&self, uri: &str, recursive: bool) -> Result<()> {
    method mv (line 406) | pub async fn mv(&self, from_uri: &str, to_uri: &str) -> Result<()> {
    method stat (line 415) | pub async fn stat(&self, uri: &str) -> Result<serde_json::Value> {
    method find (line 422) | pub async fn find(
    method search (line 438) | pub async fn search(
    method grep (line 456) | pub async fn grep(&self, uri: &str, pattern: &str, ignore_case: bool, ...
    method glob (line 467) | pub async fn glob(&self, pattern: &str, uri: &str, node_limit: i32) ->...
    method add_resource (line 478) | pub async fn add_resource(
    method add_skill (line 578) | pub async fn add_skill(
    method relations (line 626) | pub async fn relations(&self, uri: &str) -> Result<serde_json::Value> {
    method link (line 631) | pub async fn link(
    method unlink (line 645) | pub async fn unlink(&self, from_uri: &str, to_uri: &str) -> Result<ser...
    method export_ovpack (line 655) | pub async fn export_ovpack(&self, uri: &str, to: &str) -> Result<serde...
    method import_ovpack (line 663) | pub async fn import_ovpack(
    method admin_create_account (line 681) | pub async fn admin_create_account(
    method admin_list_accounts (line 693) | pub async fn admin_list_accounts(&self) -> Result<Value> {
    method admin_delete_account (line 697) | pub async fn admin_delete_account(&self, account_id: &str) -> Result<V...
    method admin_register_user (line 702) | pub async fn admin_register_user(
    method admin_list_users (line 716) | pub async fn admin_list_users(&self, account_id: &str) -> Result<Value> {
    method admin_remove_user (line 721) | pub async fn admin_remove_user(&self, account_id: &str, user_id: &str)...
    method admin_set_role (line 726) | pub async fn admin_set_role(
    method admin_regenerate_key (line 740) | pub async fn admin_regenerate_key(
    method debug_vector_scroll (line 755) | pub async fn debug_vector_scroll(
    method debug_vector_count (line 783) | pub async fn debug_vector_count(

FILE: crates/ov_cli/src/commands/admin.rs
  function create_account (line 6) | pub async fn create_account(
  function list_accounts (line 18) | pub async fn list_accounts(
  function delete_account (line 28) | pub async fn delete_account(
  function register_user (line 46) | pub async fn register_user(
  function list_users (line 59) | pub async fn list_users(
  function remove_user (line 70) | pub async fn remove_user(
  function set_role (line 89) | pub async fn set_role(
  function regenerate_key (line 102) | pub async fn regenerate_key(

FILE: crates/ov_cli/src/commands/chat.rs
  constant DEFAULT_ENDPOINT (line 22) | const DEFAULT_ENDPOINT: &str = "http://localhost:1933/bot/v1";
  constant HISTORY_FILE (line 23) | const HISTORY_FILE: &str = ".ov_chat_history";
  type ChatCommand (line 27) | pub struct ChatCommand {
    method execute (line 100) | pub async fn execute(&self) -> Result<()> {
    method send_message (line 116) | async fn send_message(&self, client: &Client, message: &str) -> Result...
    method send_message_non_stream (line 125) | async fn send_message_non_stream(&self, client: &Client, message: &str...
    method send_message_stream (line 168) | async fn send_message_stream(&self, client: &Client, message: &str) ->...
    method run_interactive (line 244) | async fn run_interactive(&self, client: &Client) -> Result<()> {
    method send_interactive_message (line 326) | async fn send_interactive_message(
    method send_interactive_message_non_stream (line 340) | async fn send_interactive_message_non_stream(
    method send_interactive_message_stream (line 395) | async fn send_interactive_message_stream(
    method print_stream_event (line 488) | fn print_stream_event(&self, event: &ChatStreamEvent) {
    method print_tool_call (line 528) | fn print_tool_call(content: &str) {
    method print_tool_result (line 542) | fn print_tool_result(content: &str) {
    method print_events (line 547) | fn print_events(&self, events: &Option<Vec<serde_json::Value>>) {
    method print_response (line 587) | fn print_response(&self, message: &str) {
    method get_history_path (line 600) | fn get_history_path(&self) -> Option<std::path::PathBuf> {
    method run (line 607) | pub async fn run(&self) -> Result<()> {
    method new (line 616) | pub fn new(
  type ChatMessage (line 63) | struct ChatMessage {
  type ChatRequest (line 70) | struct ChatRequest {
  type ChatResponse (line 83) | struct ChatResponse {
  type ChatStreamEvent (line 92) | struct ChatStreamEvent {
  function render_markdown (line 640) | fn render_markdown(text: &str) {

FILE: crates/ov_cli/src/commands/content.rs
  function read (line 8) | pub async fn read(
  function abstract_content (line 19) | pub async fn abstract_content(
  function overview (line 30) | pub async fn overview(
  function reindex (line 41) | pub async fn reindex(
  function get (line 54) | pub async fn get(

FILE: crates/ov_cli/src/commands/filesystem.rs
  function ls (line 5) | pub async fn ls(
  function tree (line 22) | pub async fn tree(
  function mkdir (line 38) | pub async fn mkdir(
  function rm (line 49) | pub async fn rm(
  function mv (line 61) | pub async fn mv(
  function stat (line 73) | pub async fn stat(

FILE: crates/ov_cli/src/commands/observer.rs
  function queue (line 5) | pub async fn queue(
  function vikingdb (line 15) | pub async fn vikingdb(
  function vlm (line 25) | pub async fn vlm(
  function transaction (line 35) | pub async fn transaction(
  function retrieval (line 45) | pub async fn retrieval(
  function system (line 55) | pub async fn system(

FILE: crates/ov_cli/src/commands/pack.rs
  function export (line 5) | pub async fn export(
  function import (line 17) | pub async fn import(

FILE: crates/ov_cli/src/commands/relations.rs
  function list_relations (line 5) | pub async fn list_relations(
  function link (line 16) | pub async fn link(
  function unlink (line 39) | pub async fn unlink(

FILE: crates/ov_cli/src/commands/resources.rs
  function add_resource (line 5) | pub async fn add_resource(
  function add_skill (line 44) | pub async fn add_skill(

FILE: crates/ov_cli/src/commands/search.rs
  function find (line 5) | pub async fn find(
  function search (line 19) | pub async fn search(
  function grep (line 34) | pub async fn grep(
  function glob (line 49) | pub async fn glob(

FILE: crates/ov_cli/src/commands/session.rs
  function new_session (line 6) | pub async fn new_session(
  function list_sessions (line 16) | pub async fn list_sessions(
  function get_session (line 26) | pub async fn get_session(
  function delete_session (line 38) | pub async fn delete_session(
  function add_message (line 58) | pub async fn add_message(
  function commit_session (line 77) | pub async fn commit_session(
  function add_memory (line 95) | pub async fn add_memory(
  function url_encode (line 156) | fn url_encode(s: &str) -> String {

FILE: crates/ov_cli/src/commands/system.rs
  function wait (line 6) | pub async fn wait(
  function status (line 23) | pub async fn status(
  function health (line 33) | pub async fn health(

FILE: crates/ov_cli/src/config.rs
  constant OPENVIKING_CLI_CONFIG_ENV (line 6) | const OPENVIKING_CLI_CONFIG_ENV: &str = "OPENVIKING_CLI_CONFIG_FILE";
  type Config (line 9) | pub struct Config {
    method load (line 53) | pub fn load() -> Result<Self> {
    method load_default (line 57) | pub fn load_default() -> Result<Self> {
    method from_file (line 74) | pub fn from_file(path: &str) -> Result<Self> {
    method save_default (line 82) | pub fn save_default(&self) -> Result<()> {
  function default_url (line 22) | fn default_url() -> String {
  function default_timeout (line 26) | fn default_timeout() -> f64 {
  function default_output_format (line 30) | fn default_output_format() -> String {
  function default_echo_command (line 34) | fn default_echo_command() -> bool {
  method default (line 39) | fn default() -> Self {
  function default_config_path (line 96) | pub fn default_config_path() -> Result<PathBuf> {
  function get_or_create_machine_id (line 105) | pub fn get_or_create_machine_id() -> Result<String> {

FILE: crates/ov_cli/src/error.rs
  type Error (line 4) | pub enum Error {
  type Result (line 33) | pub type Result<T> = std::result::Result<T, Error>;
  type CliError (line 38) | pub struct CliError {
    method new (line 45) | pub fn new(message: impl Into<String>) -> Self {
    method config (line 53) | pub fn config(message: impl Into<String>) -> Self {
    method network (line 61) | pub fn network(message: impl Into<String>) -> Self {
    method from (line 71) | fn from(err: Error) -> Self {
    method from (line 87) | fn from(err: reqwest::Error) -> Self {
    method from (line 101) | fn from(err: serde_json::Error) -> Self {

FILE: crates/ov_cli/src/main.rs
  type CliContext (line 16) | pub struct CliContext {
    method new (line 23) | pub fn new(output_format: OutputFormat, compact: bool) -> Result<Self> {
    method get_client (line 32) | pub fn get_client(&self) -> client::HttpClient {
  type Cli (line 47) | struct Cli {
  type Commands (line 61) | enum Commands {
  type SystemCommands (line 385) | enum SystemCommands {
  type ObserverCommands (line 399) | enum ObserverCommands {
  type SessionCommands (line 415) | enum SessionCommands {
  type AdminCommands (line 449) | enum AdminCommands {
  type ConfigCommands (line 506) | enum ConfigCommands {
  function main (line 514) | async fn main() {
  function handle_add_resource (line 664) | async fn handle_add_resource(
  function handle_add_skill (line 751) | async fn handle_add_skill(
  function handle_relations (line 763) | async fn handle_relations(uri: String, ctx: CliContext) -> Result<()> {
  function handle_link (line 769) | async fn handle_link(
  function handle_unlink (line 781) | async fn handle_unlink(
  function handle_export (line 792) | async fn handle_export(uri: String, to: String, ctx: CliContext) -> Resu...
  function handle_import (line 798) | async fn handle_import(
  function handle_system (line 811) | async fn handle_system(cmd: SystemCommands, ctx: CliContext) -> Result<(...
  function handle_observer (line 828) | async fn handle_observer(cmd: ObserverCommands, ctx: CliContext) -> Resu...
  function handle_session (line 852) | async fn handle_session(cmd: SessionCommands, ctx: CliContext) -> Result...
  function handle_admin (line 881) | async fn handle_admin(cmd: AdminCommands, ctx: CliContext) -> Result<()> {
  function handle_add_memory (line 925) | async fn handle_add_memory(content: String, ctx: CliContext) -> Result<(...
  function handle_config (line 930) | async fn handle_config(cmd: ConfigCommands, _ctx: CliContext) -> Result<...
  function handle_read (line 955) | async fn handle_read(uri: String, ctx: CliContext) -> Result<()> {
  function handle_abstract (line 960) | async fn handle_abstract(uri: String, ctx: CliContext) -> Result<()> {
  function handle_overview (line 965) | async fn handle_overview(uri: String, ctx: CliContext) -> Result<()> {
  function handle_reindex (line 970) | async fn handle_reindex(uri: String, regenerate: bool, wait: bool, ctx: ...
  function handle_get (line 975) | async fn handle_get(uri: String, local_path: String, ctx: CliContext) ->...
  function handle_find (line 980) | async fn handle_find(
  function handle_search (line 997) | async fn handle_search(
  function print_command_echo (line 1019) | fn print_command_echo(command: &str, params: &str, echo_enabled: bool) {
  function handle_ls (line 1025) | async fn handle_ls(uri: String, simple: bool, recursive: bool, abs_limit...
  function handle_tree (line 1041) | async fn handle_tree(uri: String, abs_limit: i32, show_all_hidden: bool,...
  function handle_mkdir (line 1056) | async fn handle_mkdir(uri: String, ctx: CliContext) -> Result<()> {
  function handle_rm (line 1061) | async fn handle_rm(uri: String, recursive: bool, ctx: CliContext) -> Res...
  function handle_mv (line 1066) | async fn handle_mv(from_uri: String, to_uri: String, ctx: CliContext) ->...
  function handle_stat (line 1071) | async fn handle_stat(uri: String, ctx: CliContext) -> Result<()> {
  function handle_grep (line 1076) | async fn handle_grep(uri: String, pattern: String, ignore_case: bool, no...
  function handle_glob (line 1086) | async fn handle_glob(pattern: String, uri: String, node_limit: i32, ctx:...
  function handle_health (line 1093) | async fn handle_health(ctx: CliContext) -> Result<()> {
  function handle_tui (line 1102) | async fn handle_tui(uri: String, ctx: CliContext) -> Result<()> {

FILE: crates/ov_cli/src/output.rs
  constant MAX_COL_WIDTH (line 5) | const MAX_COL_WIDTH: usize = 256;
  type OutputFormat (line 8) | pub enum OutputFormat {
    method from (line 14) | fn from(s: &str) -> Self {
  function output_success (line 22) | pub fn output_success<T: Serialize>(result: T, format: OutputFormat, com...
  function output_error (line 38) | pub fn output_error(code: &str, message: &str, format: OutputFormat, com...
  function print_table (line 55) | fn print_table<T: Serialize>(result: T, compact: bool) {
  function value_to_table (line 256) | fn value_to_table(value: &serde_json::Value, compact: bool) -> Option<St...
  type ColumnInfo (line 352) | struct ColumnInfo {
  function format_array_to_table (line 358) | fn format_array_to_table(items: &Vec<serde_json::Value>, compact: bool) ...
  function format_value (line 493) | fn format_value(v: &serde_json::Value) -> String {
  function pad_cell (line 503) | fn pad_cell(content: &str, width: usize, align_right: bool) -> String {
  function is_numeric_value (line 518) | fn is_numeric_value(v: &serde_json::Value) -> bool {
  function truncate_string (line 526) | fn truncate_string(s: &str, is_uri: bool, max_width: usize) -> (String, ...
  function test_object_formatting_with_alignment (line 562) | fn test_object_formatting_with_alignment() {
  function test_object_with_long_uri (line 577) | fn test_object_with_long_uri() {
  function test_empty_object (line 588) | fn test_empty_object() {

FILE: crates/ov_cli/src/tui/app.rs
  type Panel (line 6) | pub enum Panel {
  type VectorRecordsState (line 12) | pub struct VectorRecordsState {
    method new (line 22) | pub fn new() -> Self {
    method adjust_scroll (line 34) | pub fn adjust_scroll(&mut self, viewport_height: usize) {
  type App (line 46) | pub struct App {
    method new (line 62) | pub fn new(client: HttpClient) -> Self {
    method init (line 79) | pub async fn init(&mut self, uri: &str) {
    method load_content_for_selected (line 84) | pub async fn load_content_for_selected(&mut self) {
    method load_directory_content (line 127) | async fn load_directory_content(&mut self, uri: &str) {
    method load_file_content (line 162) | async fn load_file_content(&mut self, uri: &str) {
    method scroll_content_up (line 176) | pub fn scroll_content_up(&mut self) {
    method scroll_content_down (line 180) | pub fn scroll_content_down(&mut self) {
    method scroll_content_top (line 186) | pub fn scroll_content_top(&mut self) {
    method scroll_content_bottom (line 190) | pub fn scroll_content_bottom(&mut self) {
    method is_root_scope_uri (line 195) | fn is_root_scope_uri(uri: &str) -> bool {
    method toggle_focus (line 201) | pub fn toggle_focus(&mut self) {
    method load_vector_records (line 208) | pub async fn load_vector_records(&mut self, uri_prefix: Option<String>) {
    method load_next_vector_page (line 229) | pub async fn load_next_vector_page(&mut self) {
    method toggle_vector_records_mode (line 257) | pub async fn toggle_vector_records_mode(&mut self) {
    method load_vector_count (line 264) | pub async fn load_vector_count(&mut self) {
    method move_vector_cursor_up (line 281) | pub fn move_vector_cursor_up(&mut self) {
    method move_vector_cursor_down (line 287) | pub fn move_vector_cursor_down(&mut self) {
    method scroll_vector_top (line 295) | pub fn scroll_vector_top(&mut self) {
    method scroll_vector_bottom (line 299) | pub fn scroll_vector_bottom(&mut self) {

FILE: crates/ov_cli/src/tui/event.rs
  function handle_key (line 5) | pub async fn handle_key(app: &mut App, key: KeyEvent) {
  function handle_tree_key (line 29) | async fn handle_tree_key(app: &mut App, key: KeyEvent) {
  function handle_content_key (line 48) | fn handle_content_key(app: &mut App, key: KeyEvent) {

FILE: crates/ov_cli/src/tui/mod.rs
  function run_tui (line 19) | pub async fn run_tui(client: HttpClient, uri: &str) -> Result<()> {
  function run_loop (line 43) | async fn run_loop(client: HttpClient, uri: &str) -> Result<()> {

FILE: crates/ov_cli/src/tui/tree.rs
  type FsEntry (line 7) | pub struct FsEntry {
    method name (line 18) | pub fn name(&self) -> &str {
  type TreeNode (line 25) | pub struct TreeNode {
  type VisibleRow (line 34) | pub struct VisibleRow {
  type TreeState (line 44) | pub struct TreeState {
    method new (line 52) | pub fn new() -> Self {
    constant ROOT_SCOPES (line 62) | const ROOT_SCOPES: &'static [&'static str] = &["agent", "resources", "...
    method load_root (line 64) | pub async fn load_root(&mut self, client: &HttpClient, uri: &str) {
    method fetch_children (line 140) | async fn fetch_children(
    method rebuild_visible (line 179) | pub fn rebuild_visible(&mut self) {
    method flatten_node (line 189) | fn flatten_node(
    method toggle_expand (line 213) | pub async fn toggle_expand(&mut self, client: &HttpClient) {
    method get_node_mut (line 249) | fn get_node_mut<'a>(
    method move_cursor_up (line 263) | pub fn move_cursor_up(&mut self) {
    method move_cursor_down (line 269) | pub fn move_cursor_down(&mut self) {
    method selected_uri (line 275) | pub fn selected_uri(&self) -> Option<&str> {
    method selected_is_dir (line 279) | pub fn selected_is_dir(&self) -> Option<bool> {
    method adjust_scroll (line 284) | pub fn adjust_scroll(&mut self, viewport_height: usize) {

FILE: crates/ov_cli/src/tui/ui.rs
  function render (line 11) | pub fn render(frame: &mut Frame, app: &App) {
  function render_tree (line 30) | fn render_tree(frame: &mut Frame, app: &App, area: ratatui::layout::Rect) {
  function render_content (line 108) | fn render_content(frame: &mut Frame, app: &App, area: ratatui::layout::R...
  function render_vector_records (line 140) | fn render_vector_records(frame: &mut Frame, app: &App, area: ratatui::la...
  function render_status_bar (line 254) | fn render_status_bar(frame: &mut Frame, app: &App, area: ratatui::layout...

FILE: crates/ov_cli/src/utils.rs
  function truncate_utf8 (line 4) | pub fn truncate_utf8(s: &str, max_bytes: usize) -> &str {

FILE: examples/claude-memory-plugin/scripts/ov_memory.py
  class BackendInfo (line 26) | class BackendInfo:
  function _load_json (line 33) | def _load_json(path: Path) -> Dict[str, Any]:
  function _save_json (line 38) | def _save_json(path: Path, data: Dict[str, Any]) -> None:
  function _load_state (line 44) | def _load_state(path: Path) -> Dict[str, Any]:
  function _health_check (line 53) | def _health_check(url: str, timeout: float = 1.2) -> bool:
  function _resolve_local_data_path (line 64) | def _resolve_local_data_path(project_dir: Path, ov_conf: Dict[str, Any])...
  function detect_backend (line 74) | def detect_backend(project_dir: Path, ov_conf: Dict[str, Any]) -> Backen...
  class OVClient (line 98) | class OVClient:
    method __init__ (line 99) | def __init__(self, backend: BackendInfo, ov_conf_path: Path):
    method __enter__ (line 104) | def __enter__(self) -> "OVClient":
    method __exit__ (line 122) | def __exit__(self, exc_type, exc, tb) -> None:
    method create_session (line 129) | def create_session(self) -> Dict[str, Any]:
    method add_message (line 132) | def add_message(
    method commit_session (line 141) | def commit_session(self, session_id: str) -> Dict[str, Any]:
    method find (line 144) | def find(self, query: str, target_uri: str, limit: int) -> Any:
    method read (line 147) | def read(self, uri: str) -> str:
  function _as_text (line 151) | def _as_text(value: Any) -> str:
  function _short (line 159) | def _short(text: str, n: int) -> str:
  function _extract_text_parts (line 166) | def _extract_text_parts(content: Any) -> str:
  function _extract_tool_result (line 183) | def _extract_tool_result(content: Any) -> str:
  function _is_user_prompt (line 207) | def _is_user_prompt(entry: Dict[str, Any]) -> bool:
  function _assistant_chunks (line 217) | def _assistant_chunks(entry: Dict[str, Any]) -> List[str]:
  function _read_jsonl (line 253) | def _read_jsonl(path: Path) -> List[Dict[str, Any]]:
  function extract_last_turn (line 269) | def extract_last_turn(transcript_path: Path) -> Optional[Dict[str, str]]:
  function _summarize_with_claude (line 315) | def _summarize_with_claude(raw: str) -> str:
  function _fallback_summary (line 351) | def _fallback_summary(turn: Dict[str, str]) -> str:
  function summarize_turn (line 364) | def summarize_turn(turn: Dict[str, str]) -> str:
  function _contexts_from_find_result (line 376) | def _contexts_from_find_result(result: Any) -> List[Dict[str, Any]]:
  function _build_backend_from_state_or_detect (line 412) | def _build_backend_from_state_or_detect(
  function cmd_session_start (line 432) | def cmd_session_start(args: argparse.Namespace) -> Dict[str, Any]:
  function cmd_ingest_stop (line 486) | def cmd_ingest_stop(args: argparse.Namespace) -> Dict[str, Any]:
  function cmd_session_end (line 546) | def cmd_session_end(args: argparse.Namespace) -> Dict[str, Any]:
  function cmd_recall (line 593) | def cmd_recall(args: argparse.Namespace) -> int:
  function _build_parser (line 664) | def _build_parser() -> argparse.ArgumentParser:
  function main (line 685) | def main() -> int:

FILE: examples/cloud/alice.py
  function load_key_from_file (line 32) | def load_key_from_file(user="alice"):
  function main (line 41) | def main():

FILE: examples/cloud/bob.py
  function load_key_from_file (line 31) | def load_key_from_file(user="bob"):
  function main (line 40) | def main():

FILE: examples/cloud/setup_users.py
  function main (line 31) | def main():

FILE: examples/common/recipe.py
  class Recipe (line 17) | class Recipe:
    method __init__ (line 27) | def __init__(self, config_path: str = "./ov.conf", data_path: str = "....
    method search (line 50) | def search(
    method call_llm (line 113) | def call_llm(
    method query (line 148) | def query(
    method close (line 246) | def close(self):

FILE: examples/common/resource_manager.py
  function create_client (line 16) | def create_client(config_path: str = "./ov.conf", data_path: str = "./da...
  function add_resource (line 37) | def add_resource(

FILE: examples/mcp-query/server.py
  function _get_recipe (line 43) | def _get_recipe() -> Recipe:
  function create_server (line 53) | def create_server(host: str = "127.0.0.1", port: int = 2033) -> FastMCP:
  function parse_args (line 232) | def parse_args():
  function main (line 308) | def main():

FILE: examples/misc/memory_demo.py
  class Turn (line 28) | class Turn:
  class QueryCheck (line 35) | class QueryCheck:
  class CaseSpec (line 43) | class CaseSpec:
  class Hit (line 59) | class Hit:
  class DedupRecord (line 69) | class DedupRecord:
  class CaseResult (line 79) | class CaseResult:
  class DedupRecorder (line 89) | class DedupRecorder:
    method __init__ (line 92) | def __init__(self) -> None:
    method install (line 97) | def install(self) -> None:
    method uninstall (line 127) | def uninstall(self) -> None:
  function _print_section (line 133) | def _print_section(title: str, body: str = "") -> None:
  function _safe_list (line 141) | def _safe_list(items: Iterable[Any]) -> List[Any]:
  function _safe_float (line 148) | def _safe_float(value: Any) -> Optional[float]:
  function _hash_text (line 155) | def _hash_text(text: str) -> str:
  function _collect_memory_snapshot (line 159) | def _collect_memory_snapshot(client: SyncOpenViking) -> Dict[str, str]:
  function _snapshot_diff (line 184) | def _snapshot_diff(
  function _search_hits (line 194) | def _search_hits(client: SyncOpenViking, query: str, limit: int) -> List...
  function _format_hits (line 226) | def _format_hits(hits: List[Hit], max_items: int = 8) -> str:
  function _joined_hit_texts (line 241) | def _joined_hit_texts(hits: List[Hit]) -> List[str]:
  function _group_satisfied_anywhere (line 245) | def _group_satisfied_anywhere(group: List[str], texts: List[str]) -> bool:
  function _group_fully_matched_in_single_hit (line 252) | def _group_fully_matched_in_single_hit(group: List[str], texts: List[str...
  function _evaluate_query_check (line 262) | def _evaluate_query_check(check: QueryCheck, hits: List[Hit]) -> List[str]:
  function _format_records (line 279) | def _format_records(records: List[DedupRecord]) -> str:
  function _build_cases (line 293) | def _build_cases() -> List[CaseSpec]:
  function _get_or_create_session (line 541) | def _get_or_create_session(
  function _session_id (line 556) | def _session_id(cache: Dict[str, Any], key: str) -> str:
  function _evaluate_case (line 560) | def _evaluate_case(
  function _decision_coverage (line 625) | def _decision_coverage(records: List[DedupRecord]) -> Dict[str, bool]:
  function main (line 638) | def main() -> int:

FILE: examples/multi_tenant/admin_workflow.py
  function expect_error (line 39) | def expect_error(resp: httpx.Response, label: str, expected_status: int ...
  function admin_api (line 47) | def admin_api(base_url: str, root_key: str):

FILE: examples/openclaw-plugin/client.ts
  type FindResultItem (line 4) | type FindResultItem = {
  type FindResult (line 14) | type FindResult = {
  type CaptureMode (line 21) | type CaptureMode = "semantic" | "keyword";
  type ScopeName (line 22) | type ScopeName = "user" | "agent";
  type RuntimeIdentity (line 23) | type RuntimeIdentity = {
  type LocalClientCacheEntry (line 27) | type LocalClientCacheEntry = {
  type PendingClientEntry (line 32) | type PendingClientEntry = {
  constant MEMORY_URI_PATTERNS (line 45) | const MEMORY_URI_PATTERNS = [
  constant USER_STRUCTURE_DIRS (line 49) | const USER_STRUCTURE_DIRS = new Set(["memories"]);
  constant AGENT_STRUCTURE_DIRS (line 50) | const AGENT_STRUCTURE_DIRS = new Set(["memories", "skills", "instruction...
  function md5Short (line 52) | function md5Short(input: string): string {
  function isMemoryUri (line 56) | function isMemoryUri(uri: string): boolean {
  class OpenVikingClient (line 60) | class OpenVikingClient {
    method constructor (line 64) | constructor(
    method setAgentId (line 78) | setAgentId(newAgentId: string): void {
    method getAgentId (line 87) | getAgentId(): string {
    method request (line 91) | private async request<T>(path: string, init: RequestInit = {}): Promis...
    method healthCheck (line 130) | async healthCheck(): Promise<void> {
    method ls (line 134) | private async ls(uri: string): Promise<Array<Record<string, unknown>>> {
    method getRuntimeIdentity (line 140) | private async getRuntimeIdentity(): Promise<RuntimeIdentity> {
    method resolveScopeSpace (line 157) | private async resolveScopeSpace(scope: ScopeName): Promise<string> {
    method normalizeTargetUri (line 199) | private async normalizeTargetUri(targetUri: string): Promise<string> {
    method find (line 224) | async find(
    method read (line 245) | async read(uri: string): Promise<string> {
    method createSession (line 251) | async createSession(): Promise<string> {
    method addSessionMessage (line 259) | async addSessionMessage(sessionId: string, role: string, content: stri...
    method getSession (line 270) | async getSession(sessionId: string): Promise<{ message_count?: number ...
    method extractSessionMemories (line 277) | async extractSessionMemories(sessionId: string): Promise<Array<Record<...
    method deleteSession (line 284) | async deleteSession(sessionId: string): Promise<void> {
    method deleteUri (line 288) | async deleteUri(uri: string): Promise<void> {

FILE: examples/openclaw-plugin/config.ts
  type MemoryOpenVikingConfig (line 5) | type MemoryOpenVikingConfig = {
  constant DEFAULT_BASE_URL (line 28) | const DEFAULT_BASE_URL = "http://127.0.0.1:1933";
  constant DEFAULT_PORT (line 29) | const DEFAULT_PORT = 1933;
  constant DEFAULT_TARGET_URI (line 30) | const DEFAULT_TARGET_URI = "viking://user/memories";
  constant DEFAULT_TIMEOUT_MS (line 31) | const DEFAULT_TIMEOUT_MS = 15000;
  constant DEFAULT_CAPTURE_MODE (line 32) | const DEFAULT_CAPTURE_MODE = "semantic";
  constant DEFAULT_CAPTURE_MAX_LENGTH (line 33) | const DEFAULT_CAPTURE_MAX_LENGTH = 24000;
  constant DEFAULT_RECALL_LIMIT (line 34) | const DEFAULT_RECALL_LIMIT = 6;
  constant DEFAULT_RECALL_SCORE_THRESHOLD (line 35) | const DEFAULT_RECALL_SCORE_THRESHOLD = 0.01;
  constant DEFAULT_INGEST_REPLY_ASSIST (line 36) | const DEFAULT_INGEST_REPLY_ASSIST = true;
  constant DEFAULT_INGEST_REPLY_ASSIST_MIN_SPEAKER_TURNS (line 37) | const DEFAULT_INGEST_REPLY_ASSIST_MIN_SPEAKER_TURNS = 2;
  constant DEFAULT_INGEST_REPLY_ASSIST_MIN_CHARS (line 38) | const DEFAULT_INGEST_REPLY_ASSIST_MIN_CHARS = 120;
  constant DEFAULT_LOCAL_CONFIG_PATH (line 39) | const DEFAULT_LOCAL_CONFIG_PATH = join(homedir(), ".openviking", "ov.con...
  constant DEFAULT_AGENT_ID (line 41) | const DEFAULT_AGENT_ID = "default";
  function resolveAgentId (line 43) | function resolveAgentId(configured: unknown): string {
  function resolveEnvVars (line 50) | function resolveEnvVars(value: string): string {
  function toNumber (line 60) | function toNumber(value: unknown, fallback: number): number {
  function assertAllowedKeys (line 73) | function assertAllowedKeys(value: Record<string, unknown>, allowed: stri...
  function resolveDefaultBaseUrl (line 81) | function resolveDefaultBaseUrl(): string {
  method parse (line 90) | parse(value: unknown): Required<MemoryOpenVikingConfig> {
  constant DEFAULT_MEMORY_OPENVIKING_DATA_DIR (line 280) | const DEFAULT_MEMORY_OPENVIKING_DATA_DIR = join(

FILE: examples/openclaw-plugin/context-engine.ts
  type AgentMessage (line 13) | type AgentMessage = {
  type ContextEngineInfo (line 18) | type ContextEngineInfo = {
  type AssembleResult (line 24) | type AssembleResult = {
  type IngestResult (line 30) | type IngestResult = {
  type IngestBatchResult (line 34) | type IngestBatchResult = {
  type CompactResult (line 38) | type CompactResult = {
  type ContextEngine (line 45) | type ContextEngine = {
  type Logger (line 76) | type Logger = {
  function estimateTokens (line 82) | function estimateTokens(messages: AgentMessage[]): number {
  function tryLegacyCompact (line 86) | async function tryLegacyCompact(params: {
  function warnOrInfo (line 121) | function warnOrInfo(logger: Logger, message: string): void {
  function createMemoryOpenVikingContextEngine (line 129) | function createMemoryOpenVikingContextEngine(params: {

FILE: examples/openclaw-plugin/demo-memory-ajie.py
  function send_message (line 96) | def send_message(gateway_url, message, user_id, previous_messages=None):
  function extract_reply_text (line 109) | def extract_reply_text(data):
  function render_reply (line 119) | def render_reply(text):
  function run_chat (line 130) | def run_chat(gateway_url, delay):
  function run_verify (line 167) | def run_verify(gateway_url, delay):
  function main (line 229) | def main():

FILE: examples/openclaw-plugin/demo-memory-xiaomei.py
  function send_message (line 96) | def send_message(gateway_url, message, user_id, previous_messages=None):
  function extract_reply_text (line 109) | def extract_reply_text(data):
  function render_reply (line 119) | def render_reply(text):
  function run_chat (line 130) | def run_chat(gateway_url, delay):
  function run_verify (line 167) | def run_verify(gateway_url, delay):
  function main (line 229) | def main():

FILE: examples/openclaw-plugin/index.ts
  type PluginLogger (line 31) | type PluginLogger = {
  type HookAgentContext (line 38) | type HookAgentContext = {
  type OpenClawPluginApi (line 44) | type OpenClawPluginApi = {
  constant MAX_OPENVIKING_STDERR_LINES (line 70) | const MAX_OPENVIKING_STDERR_LINES = 200;
  constant MAX_OPENVIKING_STDERR_CHARS (line 71) | const MAX_OPENVIKING_STDERR_CHARS = 256_000;
  constant AUTO_RECALL_TIMEOUT_MS (line 72) | const AUTO_RECALL_TIMEOUT_MS = 5_000;
  method register (line 81) | register(api: OpenClawPluginApi) {

FILE: examples/openclaw-plugin/memory-ranking.ts
  function clampScore (line 3) | function clampScore(value: number | undefined): number {
  function normalizeDedupeText (line 10) | function normalizeDedupeText(text: string): string {
  function isEventOrCaseMemory (line 14) | function isEventOrCaseMemory(item: FindResultItem): boolean {
  function getMemoryDedupeKey (line 25) | function getMemoryDedupeKey(item: FindResultItem): string {
  function postProcessMemories (line 34) | function postProcessMemories(
  function formatMemoryLines (line 65) | function formatMemoryLines(items: FindResultItem[]): string {
  function trimForLog (line 76) | function trimForLog(value: string, limit = 260): string {
  function toJsonLog (line 84) | function toJsonLog(value: unknown, maxLen = 6000): string {
  function summarizeInjectionMemories (line 100) | function summarizeInjectionMemories(items: FindResultItem[]): Array<Reco...
  function summarizeExtractedMemories (line 110) | function summarizeExtractedMemories(
  function isPreferencesMemory (line 131) | function isPreferencesMemory(item: FindResultItem): boolean {
  function isEventMemory (line 139) | function isEventMemory(item: FindResultItem): boolean {
  function isLeafLikeMemory (line 144) | function isLeafLikeMemory(item: FindResultItem): boolean {
  constant PREFERENCE_QUERY_RE (line 148) | const PREFERENCE_QUERY_RE = /prefer|preference|favorite|favourite|like|偏...
  constant TEMPORAL_QUERY_RE (line 149) | const TEMPORAL_QUERY_RE =
  constant QUERY_TOKEN_RE (line 151) | const QUERY_TOKEN_RE = /[a-z0-9]{2,}/gi;
  constant QUERY_TOKEN_STOPWORDS (line 152) | const QUERY_TOKEN_STOPWORDS = new Set([
  type RecallQueryProfile (line 179) | type RecallQueryProfile = {
  function buildRecallQueryProfile (line 185) | function buildRecallQueryProfile(query: string): RecallQueryProfile {
  function lexicalOverlapBoost (line 196) | function lexicalOverlapBoost(tokens: string[], text: string): number {
  function rankForInjection (line 210) | function rankForInjection(item: FindResultItem, query: RecallQueryProfil...
  function pickMemoriesForInjection (line 221) | function pickMemoriesForInjection(

FILE: examples/openclaw-plugin/process-manager.ts
  constant IS_WIN (line 7) | const IS_WIN = platform() === "win32";
  function waitForHealth (line 9) | function waitForHealth(baseUrl: string, timeoutMs: number, intervalMs: n...
  function withTimeout (line 32) | function withTimeout<T>(promise: Promise<T>, timeoutMs: number, timeoutM...
  function quickTcpProbe (line 48) | function quickTcpProbe(host: string, port: number, timeoutMs: number): P...
  function quickHealthCheck (line 72) | async function quickHealthCheck(baseUrl: string, timeoutMs: number): Pro...
  function quickRecallPrecheck (line 92) | async function quickRecallPrecheck(
  type ProcessLogger (line 135) | interface ProcessLogger {
  function prepareLocalPort (line 147) | async function prepareLocalPort(
  function killProcessOnPort (line 179) | function killProcessOnPort(port: number, logger: ProcessLogger): Promise...
  function killProcessOnPortWin (line 183) | async function killProcessOnPortWin(port: number, logger: ProcessLogger)...
  function killProcessOnPortUnix (line 205) | async function killProcessOnPortUnix(port: number, logger: ProcessLogger...
  function resolvePythonCommand (line 235) | function resolvePythonCommand(logger: ProcessLogger): string {

FILE: examples/openclaw-plugin/setup-helper/install.js
  constant REPO (line 34) | const REPO = process.env.REPO || "volcengine/OpenViking";
  constant BRANCH (line 35) | const BRANCH = process.env.BRANCH || "main";
  constant GH_RAW (line 36) | const GH_RAW = `https://raw.githubusercontent.com/${REPO}/${BRANCH}`;
  constant NPM_REGISTRY (line 37) | const NPM_REGISTRY = process.env.NPM_REGISTRY || "https://registry.npmmi...
  constant PIP_INDEX_URL (line 38) | const PIP_INDEX_URL = process.env.PIP_INDEX_URL || "https://pypi.tuna.ts...
  constant IS_WIN (line 40) | const IS_WIN = process.platform === "win32";
  constant HOME (line 41) | const HOME = process.env.HOME || process.env.USERPROFILE || "";
  constant DEFAULT_OPENCLAW_DIR (line 43) | const DEFAULT_OPENCLAW_DIR = join(HOME, ".openclaw");
  constant OPENCLAW_DIR (line 44) | let OPENCLAW_DIR = DEFAULT_OPENCLAW_DIR;
  constant PLUGIN_DEST (line 45) | let PLUGIN_DEST = join(OPENCLAW_DIR, "extensions", "openviking");
  constant OPENVIKING_DIR (line 47) | const OPENVIKING_DIR = join(HOME, ".openviking");
  constant DEFAULT_SERVER_PORT (line 49) | const DEFAULT_SERVER_PORT = 1933;
  constant DEFAULT_AGFS_PORT (line 50) | const DEFAULT_AGFS_PORT = 1833;
  constant DEFAULT_VLM_MODEL (line 51) | const DEFAULT_VLM_MODEL = "doubao-seed-2-0-pro-260215";
  constant DEFAULT_EMBED_MODEL (line 52) | const DEFAULT_EMBED_MODEL = "doubao-embedding-vision-251215";
  constant REQUIRED_PLUGIN_FILES (line 54) | const REQUIRED_PLUGIN_FILES = [
  constant OPTIONAL_PLUGIN_FILES (line 64) | const OPTIONAL_PLUGIN_FILES = [
  constant OPENVIKING_PIP_SPEC (line 120) | const OPENVIKING_PIP_SPEC = openvikingVersion ? `openviking==${openvikin...
  function setOpenClawDir (line 122) | function setOpenClawDir(dir) {
  function printHelp (line 127) | function printHelp() {
  function tr (line 140) | function tr(en, zh) {
  function info (line 144) | function info(msg) {
  function warn (line 148) | function warn(msg) {
  function err (line 152) | function err(msg) {
  function bold (line 156) | function bold(msg) {
  function run (line 160) | function run(cmd, args, opts = {}) {
  function runCapture (line 175) | function runCapture(cmd, args, opts = {}) {
  function runLiveCapture (line 199) | function runLiveCapture(cmd, args, opts = {}) {
  function question (line 227) | function question(prompt, defaultValue = "") {
  function checkPython (line 238) | async function checkPython() {
  function checkNode (line 259) | async function checkNode() {
  function detectOpenClawInstances (line 271) | function detectOpenClawInstances() {
  function selectWorkdir (line 285) | async function selectWorkdir() {
  function selectMode (line 309) | async function selectMode() {
  function collectRemoteConfig (line 318) | async function collectRemoteConfig() {
  function validateEnvironment (line 325) | async function validateEnvironment() {
  function checkOpenClaw (line 369) | async function checkOpenClaw() {
  function installOpenViking (line 393) | async function installOpenViking() {
  function configureOvConf (line 511) | async function configureOvConf() {
  function downloadPluginFile (line 586) | async function downloadPluginFile(relPath, required, index, total) {
  function downloadPlugin (line 624) | async function downloadPlugin() {
  function configureOpenClawPlugin (line 642) | async function configureOpenClawPlugin(pluginPath = PLUGIN_DEST) {
  function resolvePythonPath (line 680) | async function resolvePythonPath() {
  function writeOpenvikingEnv (line 695) | async function writeOpenvikingEnv({ includePython }) {
  function wrapCommand (line 738) | function wrapCommand(command, envFiles) {
  function main (line 744) | async function main() {

FILE: examples/openclaw-plugin/text-utils.ts
  constant MEMORY_TRIGGERS (line 3) | const MEMORY_TRIGGERS = [
  constant CJK_CHAR_REGEX (line 13) | const CJK_CHAR_REGEX = /[\u3040-\u30ff\u3400-\u9fff\uf900-\ufaff\uac00-\...
  constant RELEVANT_MEMORIES_BLOCK_RE (line 14) | const RELEVANT_MEMORIES_BLOCK_RE = /<relevant-memories>[\s\S]*?<\/releva...
  constant CONVERSATION_METADATA_BLOCK_RE (line 15) | const CONVERSATION_METADATA_BLOCK_RE =
  constant SENDER_METADATA_BLOCK_RE (line 18) | const SENDER_METADATA_BLOCK_RE = /Sender\s*\([^)]*\)\s*:\s*```[\s\S]*?``...
  constant FENCED_JSON_BLOCK_RE (line 19) | const FENCED_JSON_BLOCK_RE = /```json\s*([\s\S]*?)```/gi;
  constant METADATA_JSON_KEY_RE (line 20) | const METADATA_JSON_KEY_RE =
  constant LEADING_TIMESTAMP_PREFIX_RE (line 22) | const LEADING_TIMESTAMP_PREFIX_RE = /^\s*\[[^\]\n]{1,120}\]\s*/;
  constant COMMAND_TEXT_RE (line 23) | const COMMAND_TEXT_RE = /^\/[a-z0-9_-]{1,64}\b/i;
  constant NON_CONTENT_TEXT_RE (line 24) | const NON_CONTENT_TEXT_RE = /^[\p{P}\p{S}\s]+$/u;
  constant SUBAGENT_CONTEXT_RE (line 25) | const SUBAGENT_CONTEXT_RE = /^\s*\[Subagent Context\]/i;
  constant MEMORY_INTENT_RE (line 26) | const MEMORY_INTENT_RE = /记住|记下|remember|save|store|偏好|preference|规则|rul...
  constant QUESTION_CUE_RE (line 27) | const QUESTION_CUE_RE =
  constant SPEAKER_TAG_RE (line 29) | const SPEAKER_TAG_RE = /(?:^|\s)([A-Za-z\u4e00-\u9fa5][A-Za-z0-9_\u4e00-...
  constant CAPTURE_LIMIT (line 31) | const CAPTURE_LIMIT = 3;
  function resolveCaptureMinLength (line 33) | function resolveCaptureMinLength(text: string): number {
  function looksLikeMetadataJsonBlock (line 37) | function looksLikeMetadataJsonBlock(content: string): boolean {
  function sanitizeUserTextForCapture (line 49) | function sanitizeUserTextForCapture(text: string): string {
  function looksLikeQuestionOnlyText (line 63) | function looksLikeQuestionOnlyText(text: string): boolean {
  type TranscriptLikeIngestDecision (line 75) | type TranscriptLikeIngestDecision = {
  function countSpeakerTurns (line 83) | function countSpeakerTurns(text: string): number {
  function isTranscriptLikeIngest (line 91) | function isTranscriptLikeIngest(
  function normalizeDedupeText (line 180) | function normalizeDedupeText(text: string): string {
  function normalizeCaptureDedupeText (line 184) | function normalizeCaptureDedupeText(text: string): string {
  function pickRecentUniqueTexts (line 188) | function pickRecentUniqueTexts(texts: string[], limit: number): string[] {
  function getCaptureDecision (line 209) | function getCaptureDecision(text: string, mode: CaptureMode, captureMaxL...
  function extractTextsFromUserMessages (line 291) | function extractTextsFromUserMessages(messages: unknown[]): string[] {
  function extractNewTurnTexts (line 324) | function extractNewTurnTexts(
  function extractLatestUserText (line 351) | function extractLatestUserText(messages: unknown[] | undefined): string {

FILE: examples/opencode-memory-plugin/openviking-memory.ts
  type SessionMapping (line 28) | interface SessionMapping {
  type SessionMappingPersisted (line 43) | interface SessionMappingPersisted {
  type SessionMapFile (line 57) | interface SessionMapFile {
  type BufferedMessage (line 67) | interface BufferedMessage {
  constant MAX_BUFFERED_MESSAGES_PER_SESSION (line 74) | const MAX_BUFFERED_MESSAGES_PER_SESSION = 100
  constant BUFFERED_MESSAGE_TTL_MS (line 75) | const BUFFERED_MESSAGE_TTL_MS = 15 * 60 * 1000
  constant BUFFER_CLEANUP_INTERVAL_MS (line 76) | const BUFFER_CLEANUP_INTERVAL_MS = 30 * 1000
  function ensurePluginDataDir (line 86) | function ensurePluginDataDir(): string | null {
  function initLogger (line 97) | function initLogger() {
  function safeStringify (line 104) | function safeStringify(obj: any): any {
  function log (line 134) | function log(level: "INFO" | "ERROR" | "DEBUG", toolName: string, messag...
  function initSessionMapPath (line 160) | function initSessionMapPath() {
  function serializeSessionMapping (line 167) | function serializeSessionMapping(mapping: SessionMapping): SessionMappin...
  function deserializeSessionMapping (line 182) | function deserializeSessionMapping(persisted: SessionMappingPersisted): ...
  function loadSessionMap (line 198) | async function loadSessionMap(): Promise<void> {
  function saveSessionMap (line 235) | async function saveSessionMap(): Promise<void> {
  function debouncedSaveSessionMap (line 264) | function debouncedSaveSessionMap(): void {
  type OpenVikingConfig (line 277) | interface OpenVikingConfig {
  type OpenVikingResponse (line 292) | interface OpenVikingResponse<T = unknown> {
  type SearchResult (line 300) | interface SearchResult {
  type CommitResult (line 308) | interface CommitResult {
  type SessionResult (line 324) | interface SessionResult {
  type TaskResult (line 328) | interface TaskResult {
  type CommitStartResult (line 343) | type CommitStartResult =
  constant DEFAULT_CONFIG (line 347) | const DEFAULT_CONFIG: OpenVikingConfig = {
  function loadConfig (line 358) | function loadConfig(): OpenVikingConfig {
  type HttpRequestOptions (line 413) | interface HttpRequestOptions {
  function makeRequest (line 421) | async function makeRequest<T = any>(config: OpenVikingConfig, options: H...
  function getResponseErrorMessage (line 498) | function getResponseErrorMessage(error: OpenVikingResponse["error"]): st...
  function unwrapResponse (line 504) | function unwrapResponse<T>(response: OpenVikingResponse<T>): T {
  function checkServiceHealth (line 514) | async function checkServiceHealth(config: OpenVikingConfig): Promise<boo...
  function mergeMessageContent (line 534) | function mergeMessageContent(existing: string | undefined, incoming: str...
  function upsertBufferedMessage (line 546) | function upsertBufferedMessage(
  function getAutoCommitIntervalMinutes (line 591) | function getAutoCommitIntervalMinutes(config: OpenVikingConfig): number {
  function resolveEventSessionId (line 599) | function resolveEventSessionId(event: any): string | undefined {
  function ensureOpenVikingSession (line 608) | async function ensureOpenVikingSession(
  function sleep (line 666) | async function sleep(ms: number, abortSignal?: AbortSignal): Promise<voi...
  function findRunningCommitTaskId (line 682) | async function findRunningCommitTaskId(
  function clearCommitState (line 704) | function clearCommitState(mapping: SessionMapping): void {
  constant COMMIT_TIMEOUT_MS (line 711) | const COMMIT_TIMEOUT_MS = 180000
  function detectBackgroundCommitSupport (line 713) | async function detectBackgroundCommitSupport(config: OpenVikingConfig): ...
  function finalizeCommitSuccess (line 745) | async function finalizeCommitSuccess(
  function runSynchronousCommit (line 768) | async function runSynchronousCommit(
  function flushPendingMessages (line 804) | async function flushPendingMessages(
  function startBackgroundCommit (line 866) | async function startBackgroundCommit(
  function pollCommitTaskOnce (line 958) | async function pollCommitTaskOnce(
  function waitForCommitCompletion (line 1032) | async function waitForCommitCompletion(
  function startAutoCommit (line 1096) | function startAutoCommit(config: OpenVikingConfig) {
  function stopAutoCommit (line 1114) | function stopAutoCommit() {
  function checkAndCommitSessions (line 1122) | async function checkAndCommitSessions(config: OpenVikingConfig): Promise...
  function addMessageToSession (line 1155) | async function addMessageToSession(
  function formatSearchResults (line 1190) | function formatSearchResults(
  function resolveSearchMode (line 1209) | function resolveSearchMode(
  function validateVikingUri (line 1231) | function validateVikingUri(uri: string, toolName: string): string | null {
  method execute (line 1545) | async execute(args, context) {
  method execute (line 1605) | async execute(args, context) {
  method execute (line 1658) | async execute(args, context) {
  method execute (line 1812) | async execute(args, context) {

FILE: examples/opencode/plugin/index.mjs
  function run (line 13) | async function run(cmd, opts = {}) {
  function isHealthy (line 17) | async function isHealthy() {
  function startServer (line 26) | async function startServer() {
  function makeToast (line 38) | function makeToast(client) {
  function installSkill (line 47) | function installSkill() {
  constant CACHE_TTL_MS (line 61) | const CACHE_TTL_MS = 60 * 1000
  function loadRepos (line 63) | async function loadRepos() {
  function _init (line 89) | async function _init(client) {
  function init (line 120) | async function init(client) {
  function OpenVikingPlugin (line 130) | async function OpenVikingPlugin({ client }) {

FILE: examples/server_client/client_async.py
  function _bool_mark (line 32) | def _bool_mark(value) -> str:
  function main (line 36) | async def main():

FILE: examples/server_client/client_sync.py
  function _bool_mark (line 36) | def _bool_mark(value) -> str:
  function spin (line 40) | def spin(message: str, func, *args, **kwargs):
  function main (line 62) | def main():

FILE: examples/watch_resource_example.py
  function example_basic_watch (line 25) | async def example_basic_watch():
  function example_update_watch_interval (line 59) | async def example_update_watch_interval():
  function example_cancel_watch (line 84) | async def example_cancel_watch():
  function example_handle_conflict (line 103) | async def example_handle_conflict():
  function main (line 134) | async def main():

FILE: openviking/agfs_manager.py
  class AGFSManager (line 23) | class AGFSManager:
    method __init__ (line 66) | def __init__(
    method vikingfs_path (line 89) | def vikingfs_path(self) -> Path:
    method binary_path (line 94) | def binary_path(self) -> Path:
    method url (line 103) | def url(self) -> str:
    method _check_port_available (line 107) | def _check_port_available(self) -> None:
    method _generate_config (line 121) | def _generate_config(self) -> Path:
    method _generate_config_file (line 190) | def _generate_config_file(self) -> Path:
    method start (line 203) | def start(self) -> None:
    method _wait_for_ready (line 235) | def _wait_for_ready(self, timeout: float = 5.0) -> None:
    method stop (line 260) | def stop(self) -> None:
    method is_running (line 283) | def is_running(self) -> bool:

FILE: openviking/async_client.py
  class AsyncOpenViking (line 24) | class AsyncOpenViking:
    method __new__ (line 39) | def __new__(cls, *args, **kwargs):
    method __init__ (line 46) | def __init__(
    method initialize (line 74) | async def initialize(self) -> None:
    method _ensure_initialized (line 79) | async def _ensure_initialized(self):
    method close (line 84) | async def close(self) -> None:
    method reset (line 93) | async def reset(cls) -> None:
    method session (line 107) | def session(self, session_id: Optional[str] = None, must_exist: bool =...
    method session_exists (line 119) | async def session_exists(self, session_id: str) -> bool:
    method create_session (line 131) | async def create_session(self) -> Dict[str, Any]:
    method list_sessions (line 136) | async def list_sessions(self) -> List[Any]:
    method get_session (line 141) | async def get_session(self, session_id: str) -> Dict[str, Any]:
    method delete_session (line 146) | async def delete_session(self, session_id: str) -> None:
    method add_message (line 151) | async def add_message(
    method commit_session (line 173) | async def commit_session(
    method add_resource (line 182) | async def add_resource(
    method _service (line 232) | def _service(self):
    method wait_processed (line 235) | async def wait_processed(self, timeout: float = None) -> Dict[str, Any]:
    method build_index (line 240) | async def build_index(self, resource_uris: Union[str, List[str]], **kw...
    method summarize (line 250) | async def summarize(self, resource_uris: Union[str, List[str]], **kwar...
    method add_skill (line 260) | async def add_skill(
    method search (line 283) | async def search(
    method find (line 320) | async def find(
    method abstract (line 342) | async def abstract(self, uri: str) -> str:
    method overview (line 347) | async def overview(self, uri: str) -> str:
    method read (line 352) | async def read(self, uri: str, offset: int = 0, limit: int = -1) -> str:
    method ls (line 357) | async def ls(self, uri: str, **kwargs) -> List[Any]:
    method rm (line 381) | async def rm(self, uri: str, recursive: bool = False) -> None:
    method grep (line 386) | async def grep(self, uri: str, pattern: str, case_insensitive: bool = ...
    method glob (line 391) | async def glob(self, pattern: str, uri: str = "viking://") -> Dict:
    method mv (line 396) | async def mv(self, from_uri: str, to_uri: str) -> None:
    method tree (line 401) | async def tree(self, uri: str, **kwargs) -> Dict:
    method mkdir (line 416) | async def mkdir(self, uri: str) -> None:
    method stat (line 421) | async def stat(self, uri: str) -> Dict:
    method relations (line 428) | async def relations(self, uri: str) -> List[Dict[str, Any]]:
    method link (line 433) | async def link(self, from_uri: str, uris: Any, reason: str = "") -> None:
    method unlink (line 445) | async def unlink(self, from_uri: str, uri: str) -> None:
    method export_ovpack (line 458) | async def export_ovpack(self, uri: str, to: str) -> str:
    method import_ovpack (line 472) | async def import_ovpack(
    method get_status (line 492) | def get_status(self) -> Union[SystemStatus, Dict[str, Any]]:
    method is_healthy (line 500) | def is_healthy(self) -> bool:
    method observer (line 509) | def observer(self):

FILE: openviking/client/local.py
  class LocalClient (line 22) | class LocalClient(BaseClient):
    method __init__ (line 28) | def __init__(
    method service (line 45) | def service(self) -> OpenVikingService:
    method initialize (line 51) | async def initialize(self) -> None:
    method close (line 55) | async def close(self) -> None:
    method add_resource (line 61) | async def add_resource(
    method add_skill (line 103) | async def add_skill(
    method wait_processed (line 126) | async def wait_processed(self, timeout: Optional[float] = None) -> Dic...
    method build_index (line 130) | async def build_index(self, resource_uris: Union[str, List[str]], **kw...
    method summarize (line 136) | async def summarize(self, resource_uris: Union[str, List[str]], **kwar...
    method ls (line 144) | async def ls(
    method tree (line 164) | async def tree(
    method stat (line 182) | async def stat(self, uri: str) -> Dict[str, Any]:
    method mkdir (line 186) | async def mkdir(self, uri: str) -> None:
    method rm (line 190) | async def rm(self, uri: str, recursive: bool = False) -> None:
    method mv (line 194) | async def mv(self, from_uri: str, to_uri: str) -> None:
    method read (line 200) | async def read(self, uri: str, offset: int = 0, limit: int = -1) -> str:
    method abstract (line 210) | async def abstract(self, uri: str) -> str:
    method overview (line 214) | async def overview(self, uri: str) -> str:
    method find (line 220) | async def find(
    method search (line 247) | async def search(
    method grep (line 284) | async def grep(self, uri: str, pattern: str, case_insensitive: bool = ...
    method glob (line 290) | async def glob(self, pattern: str, uri: str = "viking://") -> Dict[str...
    method relations (line 296) | async def relations(self, uri: str) -> List[Any]:
    method link (line 300) | async def link(self, from_uri: str, to_uris: Union[str, List[str]], re...
    method unlink (line 304) | async def unlink(self, from_uri: str, to_uri: str) -> None:
    method create_session (line 310) | async def create_session(self) -> Dict[str, Any]:
    method list_sessions (line 320) | async def list_sessions(self) -> List[Any]:
    method get_session (line 324) | async def get_session(self, session_id: str) -> Dict[str, Any]:
    method delete_session (line 333) | async def delete_session(self, session_id: str) -> None:
    method commit_session (line 337) | async def commit_session(
    method add_message (line 351) | async def add_message(
    method export_ovpack (line 389) | async def export_ovpack(self, uri: str, to: str) -> str:
    method import_ovpack (line 393) | async def import_ovpack(
    method health (line 407) | async def health(self) -> bool:
    method session (line 411) | def session(self, session_id: Optional[str] = None, must_exist: bool =...
    method session_exists (line 434) | async def session_exists(self, session_id: str) -> bool:
    method get_status (line 446) | def get_status(self) -> Any:
    method is_healthy (line 454) | def is_healthy(self) -> bool:
    method observer (line 463) | def observer(self) -> Any:

FILE: openviking/client/session.py
  class Session (line 19) | class Session:
    method __init__ (line 26) | def __init__(self, client: "BaseClient", session_id: str, user: UserId...
    method add_message (line 38) | async def add_message(
    method commit (line 61) | async def commit(self, telemetry: TelemetryRequest = False) -> Dict[st...
    method commit_async (line 69) | async def commit_async(self, telemetry: TelemetryRequest = False) -> D...
    method delete (line 78) | async def delete(self) -> None:
    method load (line 82) | async def load(self) -> Dict[str, Any]:
    method __repr__ (line 90) | def __repr__(self) -> str:

FILE: openviking/console/app.py
  function _is_json_content_type (line 50) | def _is_json_content_type(content_type: str) -> bool:
  function _should_default_telemetry (line 55) | def _should_default_telemetry(upstream_path: str) -> bool:
  function _with_default_telemetry (line 61) | def _with_default_telemetry(request: Request, upstream_path: str, body: ...
  function _error_response (line 80) | def _error_response(status_code: int, code: str, message: str, details: ...
  function _copy_forward_headers (line 94) | def _copy_forward_headers(request: Request) -> dict[str, str]:
  function _copy_forward_response_headers (line 102) | def _copy_forward_response_headers(upstream_response: httpx.Response) ->...
  function _forward_request (line 110) | async def _forward_request(request: Request, upstream_path: str) -> Resp...
  function _ensure_write_enabled (line 139) | def _ensure_write_enabled(request: Request) -> Optional[JSONResponse]:
  function _validate_path_param (line 153) | def _validate_path_param(value: str, name: str) -> Optional[JSONResponse]:
  function _validate_fs_path (line 163) | def _validate_fs_path(path_str: str) -> Optional[JSONResponse]:
  function _create_proxy_router (line 196) | def _create_proxy_router() -> APIRouter:
  function create_console_app (line 397) | def create_console_app(

FILE: openviking/console/bootstrap.py
  function _build_parser (line 22) | def _build_parser() -> argparse.ArgumentParser:
  function main (line 55) | def main() -> None:

FILE: openviking/console/config.py
  function _parse_cors_origins (line 11) | def _parse_cors_origins(raw_value: str | None) -> List[str]:
  class ConsoleConfig (line 18) | class ConsoleConfig:
    method normalized_base_url (line 28) | def normalized_base_url(self) -> str:
  function load_console_config (line 33) | def load_console_config(
  function as_runtime_capabilities (line 58) | def as_runtime_capabilities(config: ConsoleConfig) -> dict:

FILE: openviking/console/static/app.js
  constant API_BASE (line 1) | const API_BASE = "/console/api/v1";
  constant SESSION_KEY (line 2) | const SESSION_KEY = "ov_console_api_key";
  constant THEME_MODE_KEY (line 3) | const THEME_MODE_KEY = "ov_console_theme_mode";
  constant NAV_COLLAPSED_KEY (line 4) | const NAV_COLLAPSED_KEY = "ov_console_nav_collapsed";
  constant RESULT_COLLAPSED_KEY (line 5) | const RESULT_COLLAPSED_KEY = "ov_console_result_collapsed_v2";
  function readLocalStorage (line 127) | function readLocalStorage(key) {
  function writeLocalStorage (line 135) | function writeLocalStorage(key, value) {
  function prefersDarkTheme (line 143) | function prefersDarkTheme() {
  function resolveThemeMode (line 147) | function resolveThemeMode(mode) {
  function updateThemeButtons (line 157) | function updateThemeButtons() {
  function applyThemeMode (line 165) | function applyThemeMode(mode, { persist = true } = {}) {
  function applyShellStateClasses (line 176) | function applyShellStateClasses() {
  function setNavCollapsed (line 184) | function setNavCollapsed(collapsed, { persist = true } = {}) {
  function setResultCollapsed (line 192) | function setResultCollapsed(collapsed, { persist = true } = {}) {
  function syncResultEmptyState (line 203) | function syncResultEmptyState() {
  function setOutput (line 210) | function setOutput(value) {
  function setActivePanel (line 216) | function setActivePanel(panel) {
  function getApiKey (line 241) | function getApiKey() {
  function updateConnectionHint (line 245) | function updateConnectionHint() {
  function truncateText (line 252) | function truncateText(value, maxLength = 4000) {
  function isJsonLikeContentType (line 260) | function isJsonLikeContentType(contentType) {
  function callConsole (line 265) | async function callConsole(path, options = {}) {
  function normalizeDirUri (line 341) | function normalizeDirUri(uri) {
  function parentUri (line 352) | function parentUri(uri) {
  function joinUri (line 373) | function joinUri(baseUri, child) {
  function pickFirstNonEmpty (line 387) | function pickFirstNonEmpty(candidates) {
  function normalizeFsEntries (line 396) | function normalizeFsEntries(result, currentUri) {
  function normalizeSortString (line 492) | function normalizeSortString(value) {
  function toSortableNumber (line 499) | function toSortableNumber(value) {
  function toSortableTime (line 512) | function toSortableTime(value) {
  function compareNullable (line 524) | function compareNullable(left, right, compareFn) {
  function compareFsEntries (line 539) | function compareFsEntries(left, right, field) {
  function sortFilesystemEntries (line 571) | function sortFilesystemEntries(entries) {
  function updateFilesystemSortHeaders (line 581) | function updateFilesystemSortHeaders() {
  function bindFilesystemSort (line 595) | function bindFilesystemSort() {
  function initFsColumnResize (line 621) | function initFsColumnResize() {
  function normalizeReadContent (line 674) | function normalizeReadContent(result) {
  function readFilesystemFile (line 696) | async function readFilesystemFile(entry) {
  function statFilesystemResource (line 711) | async function statFilesystemResource(entry) {
  function renderFilesystemEntries (line 724) | function renderFilesystemEntries(target, rows, onOpen, onOpenContent) {
  function isRecord (line 798) | function isRecord(value) {
  function extractDeepestObjectArray (line 802) | function extractDeepestObjectArray(value) {
  function normalizeFindRows (line 833) | function normalizeFindRows(result) {
  function collectFindColumns (line 887) | function collectFindColumns(rows) {
  function formatFindCellValue (line 907) | function formatFindCellValue(value) {
  function renderFindCellContent (line 917) | function renderFindCellContent(td, column, value) {
  function toFindComparable (line 955) | function toFindComparable(value) {
  function compareFindValues (line 986) | function compareFindValues(left, right) {
  function sortFindRows (line 1007) | function sortFindRows(rows, column, direction) {
  function renderFindTable (line 1020) | function renderFindTable(rows) {
  function renderList (line 1092) | function renderList(target, rows, onClick) {
  function clamp (line 1119) | function clamp(value, min, max) {
  function syncWriteControls (line 1123) | function syncWriteControls() {
  function initResizablePanes (line 1130) | function initResizablePanes() {
  function buildFsTreeItem (line 1214) | function buildFsTreeItem(entry, depth) {
  function renderFsTreeLevel (line 1294) | async function renderFsTreeLevel(container, uri, depth) {
  function renderFsTree (line 1308) | async function renderFsTree() {
  function setFsViewMode (line 1313) | function setFsViewMode(mode) {
  function loadFilesystem (line 1323) | async function loadFilesystem(uri, { pushHistory = false } = {}) {
  function refreshCapabilities (line 1376) | async function refreshCapabilities() {
  function bindShellControls (line 1391) | function bindShellControls() {
  function initShellState (line 1438) | function initShellState() {
  function bindTabs (line 1452) | function bindTabs() {
  function bindConnection (line 1464) | function bindConnection() {
  function bindFilesystem (line 1498) | function bindFilesystem() {
  function bindFind (line 1592) | function bindFind() {
  function buildAddResourcePayload (line 1625) | function buildAddResourcePayload() {
  function renderAddResourceMode (line 1661) | function renderAddResourceMode() {
  function bindAddResource (line 1671) | function bindAddResource() {
  function normalizeArrayResult (line 1752) | function normalizeArrayResult(result, candidateKeys = []) {
  function normalizeTenantAccount (line 1766) | function normalizeTenantAccount(item) {
  function normalizeTenantUser (line 1800) | function normalizeTenantUser(item) {
  function updateTenantCurrentAccountLabel (line 1827) | function updateTenantCurrentAccountLabel() {
  function compareTenantRows (line 1833) | function compareTenantRows(left, right, field) {
  function sortTenantRows (line 1839) | function sortTenantRows(rows, field, direction) {
  function applyTenantAccountFilter (line 1847) | function applyTenantAccountFilter() {
  function updateTenantSortButtons (line 1854) | function updateTenantSortButtons(buttons, activeField, direction) {
  function renderAccountsTable (line 1864) | function renderAccountsTable() {
  function tenantRoleOptions (line 1960) | function tenantRoleOptions(role) {
  function renderUsersTable (line 1968) | function renderUsersTable() {
  function loadTenantUsers (line 2110) | async function loadTenantUsers(accountId, { showOutput = true } = {}) {
  function loadTenantAccounts (line 2134) | async function loadTenantAccounts({ showOutput = true } = {}) {
  function ensureTenantsLoaded (line 2163) | async function ensureTenantsLoaded() {
  function closeTenantConfirmModal (line 2169) | function closeTenantConfirmModal() {
  function updateTenantConfirmState (line 2177) | function updateTenantConfirmState() {
  function openTenantConfirmModal (line 2190) | function openTenantConfirmModal(request) {
  function performTenantAction (line 2205) | async function performTenantAction(request) {
  function executeTenantAction (line 2213) | async function executeTenantAction(request, { confirm = false } = {}) {
  function bindTenantSortButtons (line 2231) | function bindTenantSortButtons() {
  function bindAddMemory (line 2265) | function bindAddMemory() {
  function bindTenants (line 2320) | function bindTenants() {
  function bindMonitor (line 2434) | function bindMonitor() {
  function init (line 2462) | async function init() {

FILE: openviking/core/building_tree.py
  class BuildingTree (line 11) | class BuildingTree:
    method __init__ (line 21) | def __init__(
    method add_context (line 33) | def add_context(self, context: "Context") -> None:
    method root (line 39) | def root(self) -> Optional["Context"]:
    method contexts (line 46) | def contexts(self) -> List["Context"]:
    method get (line 50) | def get(self, uri: str) -> Optional["Context"]:
    method parent (line 54) | def parent(self, uri: str) -> Optional["Context"]:
    method get_children (line 61) | def get_children(self, uri: str) -> List["Context"]:
    method get_path_to_root (line 65) | def get_path_to_root(self, uri: str) -> List["Context"]:
    method to_directory_structure (line 77) | def to_directory_structure(self) -> Dict[str, Any]:
    method __len__ (line 100) | def __len__(self) -> int:
    method __iter__ (line 103) | def __iter__(self):

FILE: openviking/core/context.py
  class ResourceContentType (line 14) | class ResourceContentType(str, Enum):
  class ContextType (line 24) | class ContextType(str, Enum):
  class ContextLevel (line 32) | class ContextLevel(int, Enum):
  class Vectorize (line 40) | class Vectorize:
    method __init__ (line 46) | def __init__(self, text: str = ""):
  class Context (line 50) | class Context:
    method __init__ (line 55) | def __init__(
    method _derive_owner_space (line 103) | def _derive_owner_space(self, user: Optional[UserIdentifier]) -> str:
    method _derive_context_type (line 113) | def _derive_context_type(self) -> str:
    method _derive_category (line 122) | def _derive_category(self) -> str:
    method get_context_type (line 138) | def get_context_type(self) -> str:
    method set_vectorize (line 142) | def set_vectorize(self, vectorize: Vectorize):
    method get_vectorization_text (line 145) | def get_vectorization_text(self) -> str:
    method update_activity (line 150) | def update_activity(self):
    method to_dict (line 155) | def to_dict(self) -> Dict[str, Any]:
    method from_dict (line 193) | def from_dict(cls, data: Dict[str, Any]) -> "Context":

FILE: openviking/core/directories.py
  class DirectoryDefinition (line 22) | class DirectoryDefinition:
  function get_context_type_for_uri (line 127) | def get_context_type_for_uri(uri: str) -> str:
  class DirectoryInitializer (line 140) | class DirectoryInitializer:
    method __init__ (line 143) | def __init__(
    method initialize_account_directories (line 149) | async def initialize_account_directories(self, ctx: RequestContext) ->...
    method initialize_user_directories (line 171) | async def initialize_user_directories(self, ctx: RequestContext) -> int:
    method initialize_agent_directories (line 190) | async def initialize_agent_directories(self, ctx: RequestContext) -> int:
    method _ensure_directory (line 209) | async def _ensure_directory(
    method _ensure_directory_l0_l1_vectors (line 244) | async def _ensure_directory_l0_l1_vectors(
    method _owner_space_for_scope (line 282) | def _owner_space_for_scope(scope: str, ctx: RequestContext) -> str:
    method _check_agfs_files_exist (line 289) | async def _check_agfs_files_exist(self, uri: str, ctx: RequestContext)...
    method _initialize_children (line 300) | async def _initialize_children(
    method _create_agfs_structure (line 328) | async def _create_agfs_structure(

FILE: openviking/core/mcp_converter.py
  function mcp_to_skill (line 8) | def mcp_to_skill(mcp_config: Dict[str, Any]) -> Dict[str, Any]:
  function is_mcp_format (line 58) | def is_mcp_format(data: Dict[str, Any]) -> bool:

FILE: openviking/core/skill_loader.py
  class SkillLoader (line 12) | class SkillLoader:
    method load (line 18) | def load(cls, path: str) -> Dict[str, Any]:
    method parse (line 28) | def parse(cls, content: str, source_path: str = "") -> Dict[str, Any]:
    method _split_frontmatter (line 54) | def _split_frontmatter(cls, content: str) -> Tuple[Optional[str], str]:
    method to_skill_md (line 62) | def to_skill_md(cls, skill_dict: Dict[str, Any]) -> str:

FILE: openviking/eval/ragas/__init__.py
  class RagasConfig (line 38) | class RagasConfig:
    method from_env (line 59) | def from_env(cls) -> "RagasConfig":
  function _get_llm_config_from_env (line 77) | def _get_llm_config_from_env() -> Optional[Dict[str, str]]:
  function _create_ragas_llm_from_config (line 102) | def _create_ragas_llm_from_config() -> Optional[Any]:
  class RagasEvaluator (line 164) | class RagasEvaluator(BaseEvaluator):
    method __init__ (line 183) | def __init__(
    method evaluate_sample (line 249) | async def evaluate_sample(self, sample: EvalSample) -> EvalResult:
    method evaluate_dataset (line 255) | async def evaluate_dataset(self, dataset: EvalDataset) -> SummaryResult:

FILE: openviking/eval/ragas/analyze_records.py
  function main (line 31) | def main() -> int:

FILE: openviking/eval/ragas/base.py
  class BaseEvaluator (line 13) | class BaseEvaluator(ABC):
    method evaluate_sample (line 17) | async def evaluate_sample(self, sample: EvalSample) -> EvalResult:
    method evaluate_dataset (line 29) | async def evaluate_dataset(self, dataset: EvalDataset) -> SummaryResult:
    method _summarize (line 46) | def _summarize(self, name: str, results: List[EvalResult]) -> SummaryR...

FILE: openviking/eval/ragas/generator.py
  class DatasetGenerator (line 18) | class DatasetGenerator:
    method __init__ (line 23) | def __init__(self, llm: Optional[Any] = None):
    method generate_from_viking_path (line 33) | async def generate_from_viking_path(
    method generate_from_content (line 75) | async def generate_from_content(

FILE: openviking/eval/ragas/pipeline.py
  class RAGQueryPipeline (line 16) | class RAGQueryPipeline:
    method __init__ (line 26) | def __init__(
    method _get_client (line 43) | def _get_client(self):
    method _get_llm (line 58) | def _get_llm(self):
    method add_documents (line 67) | def add_documents(
    method add_code_repos (line 109) | def add_code_repos(
    method query (line 128) | def query(
    method close (line 198) | def close(self):

FILE: openviking/eval/ragas/play_recorder.py
  function print_playback_stats (line 36) | def print_playback_stats(stats: PlaybackStats) -> None:
  function main_async (line 99) | async def main_async(args: argparse.Namespace) -> int:
  function main (line 154) | def main() -> int:

FILE: openviking/eval/ragas/playback.py
  class PlaybackResult (line 22) | class PlaybackResult:
  class PlaybackStats (line 42) | class PlaybackStats:
    method __post_init__ (line 76) | def __post_init__(self):
    method to_dict (line 82) | def to_dict(self) -> Dict[str, Any]:
  class _AGFSCallCollector (line 128) | class _AGFSCallCollector:
    method __init__ (line 133) | def __init__(self, agfs_client: Any):
    method __getattr__ (line 137) | def __getattr__(self, name: str):
  class IOPlayback (line 163) | class IOPlayback:
    method __init__ (line 175) | def __init__(
    method _path_to_uri (line 204) | def _path_to_uri(self, path: str) -> str:
    method _init_backends (line 208) | def _init_backends(self) -> None:
    method _play_fs_operation (line 265) | async def _play_fs_operation(self, record: IORecord) -> PlaybackResult:
    method _compare_agfs_calls (line 331) | def _compare_agfs_calls(
    method _errors_match (line 374) | def _errors_match(self, playback_error: str, record_error: str) -> bool:
    method _play_vikingdb_operation (line 405) | async def _play_vikingdb_operation(self, record: IORecord) -> Playback...
    method play_record (line 519) | async def play_record(self, record: IORecord) -> PlaybackResult:
    method play (line 530) | async def play(
    method play_sync (line 645) | def play_sync(self, **kwargs) -> PlaybackStats:

FILE: openviking/eval/ragas/rag_eval.py
  function load_questions (line 29) | def load_questions(question_file: str) -> List[Dict[str, Any]]:
  class RAGEvaluator (line 56) | class RAGEvaluator:
    method __init__ (line 61) | def __init__(
    method _get_client (line 93) | def _get_client(self):
    method initialize (line 113) | async def initialize(self):
    method retrieve (line 158) | async def retrieve(self, query: str, top_k: int = 5) -> Dict[str, Any]:
    method evaluate (line 198) | async def evaluate(
    method _calculate_metrics (line 244) | def _calculate_metrics(
  function print_report (line 271) | def print_report(eval_results: Dict[str, Any]):
  function save_report (line 299) | def save_report(eval_results: Dict[str, Any], output_path: str):
  function run_ragas_evaluation (line 306) | async def run_ragas_evaluation(eval_results: Dict[str, Any]):
  function main_async (line 341) | async def main_async(args):
  function main (line 409) | def main():

FILE: openviking/eval/ragas/record_analysis.py
  class OperationStats (line 20) | class OperationStats:
  class VikingFSStats (line 46) | class VikingFSStats:
  class RecordAnalysisStats (line 78) | class RecordAnalysisStats:
    method __post_init__ (line 104) | def __post_init__(self):
    method to_dict (line 112) | def to_dict(self) -> Dict[str, Any]:
  function load_records (line 167) | def load_records(record_file: str) -> List[IORecord]:
  function _update_operation_stats (line 186) | def _update_operation_stats(
  function _finalize_operation_stats (line 215) | def _finalize_operation_stats(stats_dict: Dict[str, OperationStats]) -> ...
  function analyze_records (line 232) | def analyze_records(
  function print_analysis_stats (line 319) | def print_analysis_stats(stats: RecordAnalysisStats) -> None:

FILE: openviking/eval/ragas/types.py
  class EvalSample (line 12) | class EvalSample(BaseModel):
  class EvalResult (line 22) | class EvalResult(BaseModel):
  class EvalDataset (line 30) | class EvalDataset(BaseModel):
    method __len__ (line 37) | def __len__(self) -> int:
  class SummaryResult (line 41) | class SummaryResult(BaseModel):

FILE: openviking/eval/recorder/async_writer.py
  function _serialize_for_json (line 22) | def _serialize_for_json(obj: Any) -> Any:
  class AsyncRecordWriter (line 45) | class AsyncRecordWriter:
    method __init__ (line 59) | def __init__(self, file_path: str, batch_size: int = 100, flush_interv...
    method _ensure_dir (line 80) | def _ensure_dir(self) -> None:
    method _start_writer (line 84) | def _start_writer(self) -> None:
    method _writer_loop (line 89) | def _writer_loop(self) -> None:
    method _flush_batch (line 121) | def _flush_batch(self, batch: list[Dict[str, Any]]) -> None:
    method write_record (line 139) | def write_record(self, record: Dict[str, Any]) -> None:
    method stop (line 152) | def stop(self, timeout: float = 5.0) -> None:
    method is_running (line 170) | def is_running(self) -> bool:

FILE: openviking/eval/recorder/playback.py
  function get_record_stats (line 13) | def get_record_stats(record_file: str) -> dict:

FILE: openviking/eval/recorder/recorder.py
  class IORecorder (line 25) | class IORecorder:
    method __init__ (line 45) | def __init__(
    method get_instance (line 74) | def get_instance(cls) -> "IORecorder":
    method initialize (line 83) | def initialize(cls, enabled: bool = False, **kwargs) -> "IORecorder":
    method _serialize_response (line 89) | def _serialize_response(self, response: Any) -> Any:
    method _write_record (line 103) | def _write_record(self, record: IORecord) -> None:
    method record_fs (line 112) | def record_fs(
    method record_vikingdb (line 147) | def record_vikingdb(
    method get_records (line 182) | def get_records(self) -> List[IORecord]:
    method get_stats (line 195) | def get_stats(self) -> Dict[str, Any]:
  class RecordContext (line 228) | class RecordContext:
    method __init__ (line 231) | def __init__(
    method __enter__ (line 248) | def __enter__(self):
    method __exit__ (line 252) | def __exit__(self, exc_type, exc_val, exc_tb):
    method set_response (line 282) | def set_response(self, response: Any) -> None:
    method add_agfs_call (line 286) | def add_agfs_call(
  function get_recorder (line 317) | def get_recorder() -> IORecorder:
  function init_recorder (line 322) | def init_recorder(enabled: bool = False, **kwargs) -> IORecorder:
  function create_recording_agfs_client (line 327) | def create_recording_agfs_client(agfs_client: Any, record_file: Optional...

FILE: openviking/eval/recorder/recording_client.py
  class RecordingAGFSClient (line 20) | class RecordingAGFSClient:
    method __init__ (line 41) | def __init__(
    method _record (line 65) | def _record(
    method _serialize_response (line 87) | def _serialize_response(self, response: Any) -> Any:
    method _wrap_operation (line 110) | def _wrap_operation(self, operation: str, *args, **kwargs) -> Any:
    method stop_recording (line 126) | def stop_recording(self, timeout: float = 5.0) -> None:
    method read (line 130) | def read(self, path: str, offset: int = 0, size: int = -1, stream: boo...
    method write (line 134) | def write(self, path: str, data: Union[bytes, Iterator[bytes]], max_re...
    method ls (line 138) | def ls(self, path: str = "/") -> List[Dict[str, Any]]:
    method stat (line 142) | def stat(self, path: str) -> Dict[str, Any]:
    method mkdir (line 146) | def mkdir(self, path: str, mode: str = "755") -> Dict[str, Any]:
    method rm (line 150) | def rm(self, path: str, recursive: bool = False) -> Dict[str, Any]:
    method mv (line 154) | def mv(self, old_path: str, new_path: str) -> Dict[str, Any]:
    method grep (line 158) | def grep(
    method cat (line 169) | def cat(self, path: str, offset: int = 0, size: int = -1, stream: bool...
    method chmod (line 173) | def chmod(self, path: str, mode: int) -> Dict[str, Any]:
    method touch (line 177) | def touch(self, path: str) -> Dict[str, Any]:
    method digest (line 181) | def digest(self, path: str, algorithm: str = "xxh3") -> Dict[str, Any]:
    method create (line 185) | def create(self, path: str) -> Dict[str, Any]:
    method health (line 189) | def health(self) -> Dict[str, Any]:
    method mounts (line 193) | def mounts(self) -> List[Dict[str, Any]]:
    method mount (line 197) | def mount(self, fstype: str, path: str, config: Dict[str, Any]) -> Dic...
    method unmount (line 201) | def unmount(self, path: str) -> Dict[str, Any]:
    method open_handle (line 205) | def open_handle(self, path: str, flags: int = 0, mode: int = 420, leas...
    method close_handle (line 209) | def close_handle(self, handle_id: int) -> Dict[str, Any]:
    method handle_read (line 213) | def handle_read(self, handle_id: int, size: int = -1, offset: Optional...
    method handle_write (line 217) | def handle_write(self, handle_id: int, data: bytes, offset: Optional[i...
    method handle_seek (line 221) | def handle_seek(self, handle_id: int, offset: int, whence: int = 0) ->...
    method handle_stat (line 225) | def handle_stat(self, handle_id: int) -> Dict[str, Any]:
    method handle_sync (line 229) | def handle_sync(self, handle_id: int) -> Dict[str, Any]:
    method renew_handle (line 233) | def renew_handle(self, handle_id: int, lease: int = 60) -> Dict[str, A...
    method get_handle_info (line 237) | def get_handle_info(self, handle_id: int) -> Dict[str, Any]:
    method list_handles (line 241) | def list_handles(self) -> List[Dict[str, Any]]:
    method list_plugins (line 245) | def list_plugins(self) -> List[str]:
    method get_plugins_info (line 249) | def get_plugins_info(self) -> List[dict]:
    method load_plugin (line 253) | def load_plugin(self, library_path: str) -> Dict[str, Any]:
    method unload_plugin (line 257) | def unload_plugin(self, library_path: str) -> Dict[str, Any]:
    method __getattr__ (line 261) | def __getattr__(self, name: str) -> Any:
    method __enter__ (line 265) | def __enter__(self) -> "RecordingAGFSClient":
    method __exit__ (line 269) | def __exit__(self, exc_type, exc_val, exc_tb) -> None:

FILE: openviking/eval/recorder/types.py
  class IOType (line 12) | class IOType(Enum):
  class FSOperation (line 19) | class FSOperation(Enum):
  class VikingDBOperation (line 34) | class VikingDBOperation(Enum):
  class AGFSCallRecord (line 52) | class AGFSCallRecord:
  class IORecord (line 68) | class IORecord:
    method to_dict (line 94) | def to_dict(self) -> Dict[str, Any]:
    method from_dict (line 127) | def from_dict(cls, data: Dict[str, Any]) -> "IORecord":

FILE: openviking/eval/recorder/wrapper.py
  class _AGFSCallCollector (line 22) | class _AGFSCallCollector:
    method __init__ (line 29) | def __init__(self, agfs_client: Any):
    method __getattr__ (line 33) | def __getattr__(self, name: str):
  class RecordingVikingFS (line 67) | class RecordingVikingFS:
    method __init__ (line 84) | def __init__(self, viking_fs: Any, recorder: Optional[IORecorder] = No...
    method __getattr__ (line 96) | def __getattr__(self, name: str) -> Any:
    method _build_request (line 211) | def _build_request(self, name: str, args: tuple, kwargs: dict) -> Dict...
  class RecordingVikingDB (line 249) | class RecordingVikingDB:
    method __init__ (line 262) | def __init__(self, viking_db: Any, recorder: Optional[IORecorder] = No...
    method _record (line 273) | def _record(
    method insert (line 292) | async def insert(self, collection: str, data: Dict[str, Any]) -> str:
    method update (line 306) | async def update(self, collection: str, id: str, data: Dict[str, Any])...
    method upsert (line 325) | async def upsert(self, collection: str, data: Dict[str, Any]) -> str:
    method delete (line 339) | async def delete(self, collection: str, ids: List[str]) -> int:
    method get (line 353) | async def get(self, collection: str, ids: List[str]) -> List[Dict[str,...
    method exists (line 367) | async def exists(self, collection: str, id: str) -> bool:
    method search (line 381) | async def search(
    method filter (line 405) | async def filter(
    method create_collection (line 429) | async def create_collection(self, name: str, schema: Dict[str, Any]) -...
    method drop_collection (line 443) | async def drop_collection(self) -> bool:
    method collection_exists (line 457) | async def collection_exists(self) -> bool:
    method __getattr__ (line 471) | def __getattr__(self, name: str) -> Any:

FILE: openviking/message/message.py
  class Message (line 18) | class Message:
    method content (line 27) | def content(self) -> str:
    method to_dict (line 34) | def to_dict(self) -> dict:
    method _part_to_dict (line 45) | def _part_to_dict(self, part: Part) -> dict:
    method from_dict (line 78) | def from_dict(cls, data: dict) -> "Message":
    method create_user (line 115) | def create_user(cls, content: str, msg_id: str = None) -> "Message":
    method create_assistant (line 127) | def create_assistant(
    method get_context_parts (line 169) | def get_context_parts(self) -> List[ContextPart]:
    method get_tool_parts (line 173) | def get_tool_parts(self) -> List[ToolPart]:
    method find_tool_part (line 177) | def find_tool_part(self, tool_id: str) -> Optional[ToolPart]:
    method to_jsonl (line 184) | def to_jsonl(self) -> str:

FILE: openviking/message/part.py
  class TextPart (line 13) | class TextPart:
  class ContextPart (line 21) | class ContextPart:
  class ToolPart (line 34) | class ToolPart:
  function part_from_dict (line 56) | def part_from_dict(data: dict) -> Part:

FILE: openviking/models/embedder/base.py
  function truncate_and_normalize (line 12) | def truncate_and_normalize(embedding: List[float], dimension: Optional[i...
  class EmbedResult (line 35) | class EmbedResult:
    method is_dense (line 47) | def is_dense(self) -> bool:
    method is_sparse (line 52) | def is_sparse(self) -> bool:
    method is_hybrid (line 57) | def is_hybrid(self) -> bool:
  class EmbedderBase (line 62) | class EmbedderBase(ABC):
    method __init__ (line 68) | def __init__(self, model_name: str, config: Optional[Dict[str, Any]] =...
    method embed (line 79) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 91) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method close (line 103) | def close(self):
    method is_dense (line 108) | def is_dense(self) -> bool:
    method is_sparse (line 113) | def is_sparse(self) -> bool:
    method is_hybrid (line 118) | def is_hybrid(self) -> bool:
  class DenseEmbedderBase (line 123) | class DenseEmbedderBase(EmbedderBase):
    method embed (line 132) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method get_dimension (line 145) | def get_dimension(self) -> int:
  class SparseEmbedderBase (line 154) | class SparseEmbedderBase(EmbedderBase):
    method embed (line 165) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method is_sparse (line 178) | def is_sparse(self) -> bool:
  class HybridEmbedderBase (line 183) | class HybridEmbedderBase(EmbedderBase):
    method embed (line 194) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method get_dimension (line 207) | def get_dimension(self) -> int:
    method is_sparse (line 216) | def is_sparse(self) -> bool:
    method is_hybrid (line 221) | def is_hybrid(self) -> bool:
  class CompositeHybridEmbedder (line 226) | class CompositeHybridEmbedder(HybridEmbedderBase):
    method __init__ (line 236) | def __init__(self, dense_embedder: DenseEmbedderBase, sparse_embedder:...
    method embed (line 242) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 251) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 261) | def get_dimension(self) -> int:
    method close (line 264) | def close(self):
  function exponential_backoff_retry (line 269) | def exponential_backoff_retry(

FILE: openviking/models/embedder/gemini_embedders.py
  function _raise_api_error (line 71) | def _raise_api_error(e: APIError, model: str) -> None:
  class GeminiDenseEmbedder (line 82) | class GeminiDenseEmbedder(DenseEmbedderBase):
    method _default_dimension (line 108) | def _default_dimension(cls, model: str) -> int:
    method __init__ (line 128) | def __init__(
    method _build_config (line 170) | def _build_config(
    method __repr__ (line 185) | def __repr__(self) -> str:
    method embed (line 193) | def embed(
    method embed_batch (line 222) | def embed_batch(
    method async_embed_batch (line 280) | async def async_embed_batch(self, texts: List[str]) -> List[EmbedResult]:
    method get_dimension (line 325) | def get_dimension(self) -> int:
    method close (line 328) | def close(self):

FILE: openviking/models/embedder/jina_embedders.py
  class JinaDenseEmbedder (line 21) | class JinaDenseEmbedder(DenseEmbedderBase):
    method __init__ (line 53) | def __init__(
    method _build_extra_body (line 110) | def _build_extra_body(self, is_query: bool = False) -> Optional[Dict[s...
    method embed (line 125) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 156) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 189) | def get_dimension(self) -> int:

FILE: openviking/models/embedder/minimax_embedders.py
  class MinimaxDenseEmbedder (line 15) | class MinimaxDenseEmbedder(DenseEmbedderBase):
    method __init__ (line 33) | def __init__(
    method _create_session (line 89) | def _create_session(self) -> requests.Session:
    method _detect_dimension (line 103) | def _detect_dimension(self) -> int:
    method _call_api (line 108) | def _call_api(self, texts: List[str], is_query: bool = False) -> List[...
    method embed (line 164) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 169) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 179) | def get_dimension(self) -> int:

FILE: openviking/models/embedder/openai_embedders.py
  class OpenAIDenseEmbedder (line 19) | class OpenAIDenseEmbedder(DenseEmbedderBase):
    method __init__ (line 62) | def __init__(
    method _detect_dimension (line 142) | def _detect_dimension(self) -> int:
    method _update_telemetry_token_usage (line 151) | def _update_telemetry_token_usage(self, response) -> None:
    method _parse_param_string (line 170) | def _parse_param_string(self, param: Optional[str]) -> Dict[str, str]:
    method _build_extra_body (line 194) | def _build_extra_body(self, is_query: bool = False) -> Optional[Dict[s...
    method embed (line 225) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 255) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 289) | def get_dimension(self) -> int:
  class OpenAISparseEmbedder (line 298) | class OpenAISparseEmbedder(SparseEmbedderBase):
    method __init__ (line 304) | def __init__(self, *args, **kwargs):
    method embed (line 310) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
  class OpenAIHybridEmbedder (line 314) | class OpenAIHybridEmbedder(HybridEmbedderBase):
    method __init__ (line 320) | def __init__(self, *args, **kwargs):
    method embed (line 326) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method get_dimension (line 329) | def get_dimension(self) -> int:

FILE: openviking/models/embedder/vikingdb_embedders.py
  class VikingDBClientMixin (line 17) | class VikingDBClientMixin:
    method _init_vikingdb_client (line 20) | def _init_vikingdb_client(
    method _call_api (line 37) | def _call_api(
    method _truncate_and_normalize (line 69) | def _truncate_and_normalize(
    method _process_sparse_embedding (line 84) | def _process_sparse_embedding(self, sparse_data: Any) -> Dict[str, flo...
  class VikingDBDenseEmbedder (line 104) | class VikingDBDenseEmbedder(DenseEmbedderBase, VikingDBClientMixin):
    method __init__ (line 107) | def __init__(
    method embed (line 126) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 138) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 151) | def get_dimension(self) -> int:
  class VikingDBSparseEmbedder (line 155) | class VikingDBSparseEmbedder(SparseEmbedderBase, VikingDBClientMixin):
    method __init__ (line 158) | def __init__(
    method embed (line 176) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 188) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
  class VikingDBHybridEmbedder (line 200) | class VikingDBHybridEmbedder(HybridEmbedderBase, VikingDBClientMixin):
    method __init__ (line 203) | def __init__(
    method embed (line 226) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 244) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 259) | def get_dimension(self) -> int:

FILE: openviking/models/embedder/volcengine_embedders.py
  function is_429_error (line 21) | def is_429_error(exception: Exception) -> bool:
  function process_sparse_embedding (line 37) | def process_sparse_embedding(sparse_data: Any) -> Dict[str, float]:
  class VolcengineDenseEmbedder (line 72) | class VolcengineDenseEmbedder(DenseEmbedderBase):
    method __init__ (line 78) | def __init__(
    method _detect_dimension (line 121) | def _detect_dimension(self) -> int:
    method _update_telemetry_token_usage (line 129) | def _update_telemetry_token_usage(self, response) -> None:
    method embed (line 148) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 192) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 231) | def get_dimension(self) -> int:
  class VolcengineSparseEmbedder (line 235) | class VolcengineSparseEmbedder(SparseEmbedderBase):
    method __init__ (line 241) | def __init__(
    method embed (line 272) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 310) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
  class VolcengineHybridEmbedder (line 328) | class VolcengineHybridEmbedder(HybridEmbedderBase):
    method __init__ (line 335) | def __init__(
    method embed (line 372) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 415) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 432) | def get_dimension(self) -> int:

FILE: openviking/models/embedder/voyage_embedders.py
  function get_voyage_model_default_dimension (line 37) | def get_voyage_model_default_dimension(model_name: Optional[str]) -> int:
  class VoyageDenseEmbedder (line 44) | class VoyageDenseEmbedder(DenseEmbedderBase):
    method __init__ (line 51) | def __init__(
    method embed (line 84) | def embed(self, text: str, is_query: bool = False) -> EmbedResult:
    method embed_batch (line 99) | def embed_batch(self, texts: List[str], is_query: bool = False) -> Lis...
    method get_dimension (line 116) | def get_dimension(self) -> int:

FILE: openviking/models/vlm/backends/litellm_vlm.py
  function detect_provider_by_model (line 81) | def detect_provider_by_model(model: str) -> str | None:
  class LiteLLMVLMProvider (line 90) | class LiteLLMVLMProvider(VLMBase):
    method __init__ (line 97) | def __init__(self, config: Dict[str, Any]):
    method _setup_env (line 112) | def _setup_env(self, api_key: str, model: str | None) -> None:
    method _resolve_model (line 128) | def _resolve_model(self, model: str) -> str:
    method _detect_image_format (line 143) | def _detect_image_format(self, data: bytes) -> str:
    method _prepare_image (line 164) | def _prepare_image(self, image: Union[str, Path, bytes]) -> Dict[str, ...
    method _build_kwargs (line 195) | def _build_kwargs(self, model: str, messages: list) -> dict[str, Any]:
    method get_completion (line 221) | def get_completion(self, prompt: str, thinking: bool = False) -> str:
    method get_completion_async (line 231) | async def get_completion_async(
    method get_vision_completion (line 254) | def get_vision_completion(
    method get_vision_completion_async (line 275) | async def get_vision_completion_async(
    method _update_token_usage_from_response (line 296) | def _update_token_usage_from_response(self, response) -> None:

FILE: openviking/models/vlm/backends/openai_vlm.py
  function _build_openai_client_kwargs (line 17) | def _build_openai_client_kwargs(
  class OpenAIVLM (line 40) | class OpenAIVLM(VLMBase):
    method __init__ (line 43) | def __init__(self, config: Dict[str, Any]):
    method get_client (line 49) | def get_client(self):
    method get_async_client (line 66) | def get_async_client(self):
    method _update_token_usage_from_response (line 83) | def _update_token_usage_from_response(self, response):
    method _extract_from_chunk (line 95) | def _extract_from_chunk(self, chunk):
    method _process_streaming_response (line 116) | def _process_streaming_response(self, response):
    method _process_streaming_response_async (line 149) | async def _process_streaming_response_async(self, response):
    method get_completion (line 182) | def get_completion(self, prompt: str, thinking: bool = False) -> str:
    method get_completion_async (line 204) | async def get_completion_async(
    method _detect_image_format (line 240) | def _detect_image_format(self, data: bytes) -> str:
    method _prepare_image (line 261) | def _prepare_image(self, image: Union[str, Path, bytes]) -> Dict[str, ...
    method get_vision_completion (line 292) | def get_vision_completion(
    method get_vision_completion_async (line 325) | async def get_vision_completion_async(

FILE: openviking/models/vlm/backends/volcengine_vlm.py
  class VolcEngineVLM (line 16) | class VolcEngineVLM(OpenAIVLM):
    method __init__ (line 19) | def __init__(self, config: Dict[str, Any]):
    method get_client (line 32) | def get_client(self):
    method get_async_client (line 47) | def get_async_client(self):
    method get_completion (line 62) | def get_completion(self, prompt: str, thinking: bool = False) -> str:
    method get_completion_async (line 78) | async def get_completion_async(
    method _detect_image_format (line 108) | def _detect_image_format(self, data: bytes) -> str:
    method _prepare_image (line 174) | def _prepare_image(self, image: Union[str, Path, bytes]) -> Dict[str, ...
    method get_vision_completion (line 222) | def get_vision_completion(
    method get_vision_completion_async (line 249) | async def get_vision_completion_async(

FILE: openviking/models/vlm/base.py
  class VLMBase (line 17) | class VLMBase(ABC):
    method __init__ (line 20) | def __init__(self, config: Dict[str, Any]):
    method get_completion (line 36) | def get_completion(self, prompt: str, thinking: bool = False) -> str:
    method get_completion_async (line 41) | async def get_completion_async(
    method get_vision_completion (line 48) | def get_vision_completion(
    method get_vision_completion_async (line 58) | async def get_vision_completion_async(
    method _clean_response (line 67) | def _clean_response(self, content: str) -> str:
    method is_available (line 71) | def is_available(self) -> bool:
    method update_token_usage (line 76) | def update_token_usage(
    method get_token_usage (line 102) | def get_token_usage(self) -> Dict[str, Any]:
    method get_token_usage_summary (line 110) | def get_token_usage_summary(self) -> Dict[str, Any]:
    method reset_token_usage (line 124) | def reset_token_usage(self) -> None:
    method _extract_content_from_response (line 128) | def _extract_content_from_response(self, response) -> str:
  class VLMFactory (line 133) | class VLMFactory:
    method create (line 137) | def create(config: Dict[str, Any]) -> VLMBase:
    method get_available_providers (line 168) | def get_available_providers() -> List[str]:

FILE: openviking/models/vlm/llm.py
  function parse_json_from_response (line 23) | def parse_json_from_response(response: str) -> Optional[Any]:
  function _fix_json_quotes (line 75) | def _fix_json_quotes(json_str: str) -> str:
  function parse_json_to_model (line 92) | def parse_json_to_model(response: str, model_class: Type[T]) -> Optional...
  function get_json_schema_prompt (line 114) | def get_json_schema_prompt(schema: Dict[str, Any], description: str = ""...
  class StructuredVLM (line 141) | class StructuredVLM:
    method __init__ (line 149) | def __init__(self, vlm_config: Optional[Dict[str, Any]] = None):
    method _get_vlm (line 158) | def _get_vlm(self):
    method complete_json (line 167) | def complete_json(
    method complete_json_async (line 180) | async def complete_json_async(
    method complete_model (line 194) | def complete_model(
    method complete_model_async (line 212) | async def complete_model_async(
    method get_vision_completion (line 233) | def get_vision_completion(
    method get_vision_completion_async (line 242) | async def get_vision_completion_async(

FILE: openviking/models/vlm/registry.py
  function get_all_provider_names (line 16) | def get_all_provider_names() -> list[str]:
  function is_valid_provider (line 21) | def is_valid_provider(name: str) -> bool:

FILE: openviking/models/vlm/token_usage.py
  class TokenUsage (line 13) | class TokenUsage:
    method update (line 21) | def update(self, prompt_tokens: int, completion_tokens: int) -> None:
    method reset (line 33) | def reset(self) -> None:
    method to_dict (line 40) | def to_dict(self) -> Dict:
    method __str__ (line 53) | def __str__(self) -> str:
  class ModelTokenUsage (line 62) | class ModelTokenUsage:
    method update (line 69) | def update(self, provider: str, prompt_tokens: int, completion_tokens:...
    method get_provider_usage (line 86) | def get_provider_usage(self, provider: str) -> Optional[TokenUsage]:
    method to_dict (line 97) | def to_dict(self) -> Dict:
    method __str__ (line 114) | def __str__(self) -> str:
  class TokenUsageTracker (line 124) | class TokenUsageTracker:
    method __init__ (line 127) | def __init__(self):
    method update (line 130) | def update(
    method get_model_usage (line 146) | def get_model_usage(self, model_name: str) -> Optional[ModelTokenUsage]:
    method get_all_usage (line 157) | def get_all_usage(self) -> Dict[str, ModelTokenUsage]:
    method get_total_usage (line 165) | def get_total_usage(self) -> TokenUsage:
    method reset (line 180) | def reset(self) -> None:
    method to_dict (line 184) | def to_dict(self) -> Dict:
    method __str__ (line 200) | def __str__(self) -> str:

FILE: openviking/parse/base.py
  function calculate_media_strategy (line 24) | def calculate_media_strategy(image_count: int, line_count: int) -> str:
  function format_table_to_markdown (line 43) | def format_table_to_markdown(rows: List[List[str]], has_header: bool = T...
  function lazy_import (line 79) | def lazy_import(module_name: str, package_name: Optional[str] = None) ->...
  class ResourceCategory (line 104) | class ResourceCategory(Enum):
  class DocumentType (line 115) | class DocumentType(Enum):
  class MediaType (line 128) | class MediaType(Enum):
  class NodeType (line 141) | class NodeType(Enum):
  class ResourceNode (line 160) | class ResourceNode:
    method add_child (line 186) | def add_child(self, child: "ResourceNode") -> None:
    method get_detail_content (line 193) | def get_detail_content(self, temp_dir: Path) -> str:
    method get_detail_content_async (line 202) | async def get_detail_content_async(self, temp_uri: str) -> str:
    method get_content (line 214) | def get_content(self) -> str:
    method get_content_bytes (line 222) | def get_content_bytes(self) -> bytes:
    method is_binary (line 228) | def is_binary(self) -> bool:
    method get_content_size (line 234) | def get_content_size(self) -> int:
    method get_text (line 240) | def get_text(self, include_children: bool = True) -> str:
    method get_abstract (line 257) | def get_abstract(self, max_length: int = 256) -> str:
    method get_overview (line 280) | de
Copy disabled (too large) Download .json
Condensed preview — 1502 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (12,131K chars).
[
  {
    "path": ".clang-format",
    "chars": 757,
    "preview": "IndentWidth: 2\nTabWidth: 2\n\nLanguage: Cpp\nStandard: Cpp11\nBasedOnStyle: Google\n# indent\nAccessModifierOffset: -1\nContinu"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 2446,
    "preview": "name: Bug Report\ndescription: Report a bug or unexpected behavior\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: markd"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 534,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Documentation\n    url: https://www.openviking.ai/docs\n    about: Ch"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 2191,
    "preview": "name: Feature Request\ndescription: Suggest a new feature or enhancement\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\"]\nbod"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.yml",
    "chars": 1316,
    "preview": "name: Question\ndescription: Ask a question about OpenViking usage\ntitle: \"[Question]: \"\nlabels: [\"question\"]\nbody:\n  - t"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1474,
    "preview": "## Description\n\n<!-- Provide a brief description of the changes in this PR -->\n\n## Related Issue\n\n<!-- Link to the relat"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 476,
    "preview": "version: 2\nupdates:\n  # GitHub Actions 依赖更新\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n   "
  },
  {
    "path": ".github/workflows/_build.yml",
    "chars": 17660,
    "preview": "name: 15. _Build Distribution\n\non:\n  workflow_call:\n    inputs:\n      os_json:\n        description: 'JSON string of runn"
  },
  {
    "path": ".github/workflows/_codeql.yml",
    "chars": 1414,
    "preview": "name: 14. _CodeQL Scan\n\non:\n  workflow_call:\n  workflow_dispatch:\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubunt"
  },
  {
    "path": ".github/workflows/_lint.yml",
    "chars": 1684,
    "preview": "name: 11. _Lint Checks\n\non:\n  workflow_call:\n  workflow_dispatch:\n\njobs:\n  lint:\n    runs-on: ubuntu-24.04\n    steps:\n  "
  },
  {
    "path": ".github/workflows/_publish.yml",
    "chars": 4978,
    "preview": "name: 16. _Publish Distribution\n\non:\n  workflow_call:\n    inputs:\n      target:\n        description: 'Publish Target'\n  "
  },
  {
    "path": ".github/workflows/_test_full.yml",
    "chars": 2779,
    "preview": "name: 13. _Test Suite (Full)\n\non:\n  workflow_call:\n    inputs:\n      os_json:\n        description: 'JSON string of OS to"
  },
  {
    "path": ".github/workflows/_test_lite.yml",
    "chars": 2515,
    "preview": "name: 12. _Test Suite (Lite)\n\non:\n  workflow_call:\n    inputs:\n      os_json:\n        description: 'JSON string of OS to"
  },
  {
    "path": ".github/workflows/build-docker-image.yml",
    "chars": 1767,
    "preview": "name: Build and Push Docker Image\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: \"application"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 510,
    "preview": "name: 02. Main Branch Checks\n\non:\n  workflow_dispatch:\n  push:\n    branches: [ main ]\n    paths-ignore:\n      - 'docs/**"
  },
  {
    "path": ".github/workflows/pr-review.yml",
    "chars": 1055,
    "preview": "name: PR Review (Qodo)\n\non:\n  pull_request_target:\n    types: [opened, synchronize, reopened, ready_for_review]\n  issue_"
  },
  {
    "path": ".github/workflows/pr.yml",
    "chars": 1642,
    "preview": "name: 01. Pull Request Checks\n\non:\n  workflow_dispatch:\n  pull_request:\n    branches: [ main, develop ]\n    paths-ignore"
  },
  {
    "path": ".github/workflows/release-vikingbot-first.yml",
    "chars": 616,
    "preview": "name: First Release to PyPI\n\non:\n  workflow_dispatch:  # 手动触发\n\njobs:\n  release:\n    runs-on: ubuntu-24.04\n    defaults:\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 6568,
    "preview": "name: 03. Release\n\non:\n  release:\n    types: [published]\n  workflow_dispatch:\n    inputs:\n      target:\n        descript"
  },
  {
    "path": ".github/workflows/rust-cli.yml",
    "chars": 6455,
    "preview": "name: Rust CLI Build\n\non:\n  workflow_call:\n  push:\n    branches: [ main, feat/rust-cli ]\n    paths:\n      - 'crates/**'\n"
  },
  {
    "path": ".github/workflows/schedule.yml",
    "chars": 236,
    "preview": "name: 04. Weekly Security Scan\n\non:\n  schedule:\n    - cron: '0 0 * * 0'  # Run at 00:00 on Sunday\n\npermissions:\n  action"
  },
  {
    "path": ".gitignore",
    "chars": 1957,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n*.so\n\n# Distribution / packaging\n.Python\nbuild"
  },
  {
    "path": ".pr_agent.toml",
    "chars": 16463,
    "preview": "# =============================================================================\n# Qodo PR-Agent Configuration for OpenVi"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 156,
    "preview": "repos:\n  - repo: https://github.com/astral-sh/ruff-pre-commit\n    rev: v0.14.14\n    hooks:\n      - id: ruff\n        args"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 17453,
    "preview": "# Contributing Guide\n\nThank you for your interest in OpenViking! We welcome contributions of all kinds:\n\n- Bug reports\n-"
  },
  {
    "path": "CONTRIBUTING_CN.md",
    "chars": 11809,
    "preview": "# 贡献指南\n\n感谢你对 OpenViking 感兴趣!我们欢迎各种形式的贡献:\n\n- 报告 Bug\n- 提交功能请求\n- 改进文档\n- 贡献代码\n\n---\n\n## 开发环境设置\n\n### 前置要求\n\n- **Python**: 3.10+"
  },
  {
    "path": "CONTRIBUTING_JA.md",
    "chars": 13071,
    "preview": "# コントリビューションガイド\n\nOpenVikingに興味をお持ちいただきありがとうございます!あらゆる種類のコントリビューションを歓迎します:\n\n- バグレポート\n- 機能リクエスト\n- ドキュメントの改善\n- コードのコントリビューシ"
  },
  {
    "path": "Cargo.toml",
    "chars": 112,
    "preview": "[workspace]\nmembers = [\"crates/ov_cli\"]\nresolver = \"2\"\n\n[profile.release]\nopt-level = 3\nlto = true\nstrip = true\n"
  },
  {
    "path": "Dockerfile",
    "chars": 2452,
    "preview": "# syntax=docker/dockerfile:1.9\n\n# Stage 1: provide Go toolchain (required by setup.py -> build_agfs_artifacts -> make bu"
  },
  {
    "path": "LICENSE",
    "chars": 11356,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "MANIFEST.in",
    "chars": 701,
    "preview": "graft src\ngraft third_party/leveldb-1.23\ngraft third_party/spdlog-1.14.1\ngraft third_party/croaring\ngraft third_party/ra"
  },
  {
    "path": "Makefile",
    "chars": 4432,
    "preview": "# Makefile for OpenViking\n\n# Variables\nPYTHON ?= python3\nSETUP_PY := setup.py\nAGFS_SERVER_DIR := third_party/agfs/agfs-s"
  },
  {
    "path": "README.md",
    "chars": 25685,
    "preview": "<div align=\"center\">\n\n<a href=\"https://openviking.ai/\" target=\"_blank\">\n  <picture>\n    <img alt=\"OpenViking\" src=\"docs/"
  },
  {
    "path": "README_CN.md",
    "chars": 18381,
    "preview": "<div align=\"center\">\n<a href=\"https://openviking.ai/\" target=\"_blank\">\n  <picture>\n    <img alt=\"OpenViking\" src=\"docs/i"
  },
  {
    "path": "README_JA.md",
    "chars": 18926,
    "preview": "<div align=\"center\">\n\n<a href=\"https://openviking.ai/\" target=\"_blank\">\n  <picture>\n    <img alt=\"OpenViking\" src=\"docs/"
  },
  {
    "path": "bot/.coveragerc",
    "chars": 414,
    "preview": "[run]\nsource = vikingbot\nomit =\n    */tests/*\n    */test_*\n    */__pycache__/*\n    */venv/*\n    */.venv/*\n    */node_mod"
  },
  {
    "path": "bot/.dockerignore",
    "chars": 379,
    "preview": "# Git\n.git\n.gitignore\n.github\n\n# Python\n__pycache__\n*.pyc\n*.pyo\n*.pyd\n.Python\n*.so\n*.egg\n*.egg-info\ndist\nbuild\n.venv\nven"
  },
  {
    "path": "bot/.github/workflows/release.yml",
    "chars": 565,
    "preview": "name: Release to PyPI\n\non:\n  push:\n    tags:\n      - 'v*'\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n\n    permissions:"
  },
  {
    "path": "bot/.github/workflows/test.yml",
    "chars": 1532,
    "preview": "name: Tests\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main, develop]\n\njobs:\n  test:\n    "
  },
  {
    "path": "bot/.gitignore",
    "chars": 389,
    "preview": "# Dependencies\nnode_modules/\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n#eval\nr"
  },
  {
    "path": "bot/README.md",
    "chars": 17771,
    "preview": "# Vikingbot\n\n**Vikingbot**, built on the [Nanobot](https://github.com/HKUDS/nanobot) project, is designed to deliver an "
  },
  {
    "path": "bot/README_CN.md",
    "chars": 12648,
    "preview": "\n# Vikingbot\n\n**Vikingbot** 基于 [Nanobot](https://github.com/HKUDS/nanobot) 项目构建,旨在提供一个与 OpenViking 集成的类 OpenClaw 机器人。\n\n#"
  },
  {
    "path": "bot/SECURITY.md",
    "chars": 7325,
    "preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nIf you discover a security vulnerability in vikingbot, please report it"
  },
  {
    "path": "bot/bridge/package.json",
    "chars": 592,
    "preview": "{\n  \"name\": \"vikingbot-whatsapp-bridge\",\n  \"version\": \"0.1.0\",\n  \"description\": \"WhatsApp bridge for vikingbot using Bai"
  },
  {
    "path": "bot/bridge/src/index.ts",
    "chars": 1323,
    "preview": "#!/usr/bin/env node\n/**\n * vikingbot WhatsApp Bridge\n * \n * This bridge connects WhatsApp Web to vikingbot's Python back"
  },
  {
    "path": "bot/bridge/src/server.ts",
    "chars": 3668,
    "preview": "/**\n * WebSocket server for Python-Node.js bridge communication.\n * Security: binds to 127.0.0.1 only; optional BRIDGE_T"
  },
  {
    "path": "bot/bridge/src/types.d.ts",
    "chars": 116,
    "preview": "declare module 'qrcode-terminal' {\n  export function generate(text: string, options?: { small?: boolean }): void;\n}\n"
  },
  {
    "path": "bot/bridge/src/whatsapp.ts",
    "chars": 5085,
    "preview": "/**\n * WhatsApp client wrapper using Baileys.\n * Based on OpenClaw's working implementation.\n */\n\n/* eslint-disable @typ"
  },
  {
    "path": "bot/bridge/tsconfig.json",
    "chars": 355,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"node\",\n    \"esModuleIn"
  },
  {
    "path": "bot/deploy/Dockerfile",
    "chars": 2465,
    "preview": "FROM python:3.13-slim-bookworm\n\n# Install base tools, Node.js 20, and uv\nRUN apt-get update && \\\n    apt-get install -y "
  },
  {
    "path": "bot/deploy/docker/Dockerfile",
    "chars": 2601,
    "preview": "# Vikingbot 本地部署专用 Dockerfile\n# 固定 linux/amd64(openviking 无 linux/aarch64 wheel)\n\nFROM python:3.13-slim-bookworm\n\n# Inst"
  },
  {
    "path": "bot/deploy/docker/README.md",
    "chars": 5668,
    "preview": "# Vikingbot Docker 一键部署\n\n本目录提供 Vikingbot 的 Docker 一键部署脚本,支持本地快速部署和多架构支持。\n\n## 前置要求\n\n请先安装 Docker:\n\n- **macOS**: 下载 [Docker"
  },
  {
    "path": "bot/deploy/docker/build-image.sh",
    "chars": 1923,
    "preview": "#!/bin/bash\n# Vikingbot 镜像构建脚本\n# 用法: ./deploy/docker/build-image.sh\n# 变量: IMAGE_NAME, IMAGE_TAG, PLATFORM, NO_CACHE, PUS"
  },
  {
    "path": "bot/deploy/docker/build-multiarch.sh",
    "chars": 4320,
    "preview": "#!/bin/bash\n\n# Vikingbot 多架构镜像构建脚本\n# 功能:\n# 1. 构建跨平台 Docker 镜像(linux/amd64 + linux/arm64)\n# 2. 支持推送到远程镜像仓库\n# 3. 支持仅本地加载(不"
  },
  {
    "path": "bot/deploy/docker/deploy.sh",
    "chars": 4080,
    "preview": "#!/bin/bash\n# Vikingbot 本地一键部署脚本\n# ~/.vikingbot 会挂载到容器的 /root/.vikingbot(bridge 首次启动时自动初始化)\n# 用法: ./deploy/docker/deploy"
  },
  {
    "path": "bot/deploy/docker/deploy_langfuse.sh",
    "chars": 754,
    "preview": "#!/bin/bash\n# Deploy local Langfuse using Docker Compose\n\nset -e\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && p"
  },
  {
    "path": "bot/deploy/docker/docker-entrypoint.sh",
    "chars": 683,
    "preview": "#!/bin/bash\nset -e\n\nVIKINGBOT_DIR=\"/root/.vikingbot\"\nBRIDGE_SRC=\"/opt/vikingbot-bridge\"\nBRIDGE_DEST=\"$VIKINGBOT_DIR/brid"
  },
  {
    "path": "bot/deploy/docker/image_upload.example.yaml",
    "chars": 580,
    "preview": "# Vikingbot 镜像上传配置\n# 复制此文件到 ~/.config/vikingbot/image_upload.yaml 并填入你的信息\n\n# 火山引擎镜像仓库配置\nimage_registry: vikingbot-cn-bei"
  },
  {
    "path": "bot/deploy/docker/image_upload.sh",
    "chars": 6618,
    "preview": "#!/bin/bash\n# Vikingbot 镜像上传到火山引擎脚本\n# 将 deploy/docker/deploy.sh 产生的本地镜像上传到火山引擎镜像仓库\n# 用法: ./deploy/docker/image_upload.sh"
  },
  {
    "path": "bot/deploy/docker/langfuse/docker-compose.yml",
    "chars": 7929,
    "preview": "# Make sure to update the credential placeholders with your own secrets.\n# We mark them with # CHANGEME in the file belo"
  },
  {
    "path": "bot/deploy/docker/stop.sh",
    "chars": 908,
    "preview": "#!/bin/bash\n# Vikingbot 停止脚本\n# 用法: ./deploy/docker/stop.sh\n# 变量: CONTAINER_NAME, REMOVE_IMAGE, IMAGE_NAME, IMAGE_TAG\n\nse"
  },
  {
    "path": "bot/deploy/ecs/README.md",
    "chars": 26,
    "preview": "# ECS 部署\n\n火山引擎ECS部署方案待实现。\n"
  },
  {
    "path": "bot/deploy/vke/README.md",
    "chars": 9007,
    "preview": "# VKE 部署指南\n\n本文档介绍如何将 Vikingbot 部署到火山引擎容器服务(VKE)。\n\n## 目录\n\n- [架构概述](#架构概述)\n- [前置准备](#前置准备)\n  - [1. 火山引擎账号](#1-火山引擎账号)\n  - "
  },
  {
    "path": "bot/deploy/vke/deploy.sh",
    "chars": 11445,
    "preview": "#!/bin/bash\n# Vikingbot VKE 一键部署脚本\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJEC"
  },
  {
    "path": "bot/deploy/vke/k8s/deployment.yaml",
    "chars": 2315,
    "preview": "---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: vikingbot-data\nspec:\n  accessModes:\n    - __ACCESS_MODE"
  },
  {
    "path": "bot/deploy/vke/k8s/pvc-nas-example.yaml",
    "chars": 648,
    "preview": "# NAS静态PV示例\n# 使用前请先创建NAS实例,并替换下面的配置\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: vikingbot-nas-pv\nspec:\n  cap"
  },
  {
    "path": "bot/deploy/vke/k8s/pvc-tos-example.yaml",
    "chars": 687,
    "preview": "# TOS静态PV示例\n# 使用前请先创建TOS桶,并替换下面的配置\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: vikingbot-tos-pv\nspec:\n  capa"
  },
  {
    "path": "bot/deploy/vke/k8s/pvc-tos.yaml",
    "chars": 711,
    "preview": "apiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: vikingbot-tos-pv\nspec:\n  capacity:\n    storage: 10Gi\n  accessMod"
  },
  {
    "path": "bot/deploy/vke/vke_deploy.example.yaml",
    "chars": 2218,
    "preview": "# Vikingbot VKE 部署配置\n# 复制此文件到 ~/.config/vikingbot/vke_deploy.yaml 并填入你的信息\n#\n# 详细文档请参考: deploy/vke/README.md\n\n# ── 火山引擎凭证"
  },
  {
    "path": "bot/docs/CHANNEL.md",
    "chars": 7208,
    "preview": "## 💬 聊天应用\n\n通过 Telegram、Discord、WhatsApp、飞书、Mochat、钉钉、Slack、邮件或 QQ 与您的 vikingbot 对话 —— 随时随地。\n\n| 渠道 | 设置难度 |\n|---------|--"
  },
  {
    "path": "bot/docs/openclaw-plugin-analysis.md",
    "chars": 7335,
    "preview": "# OpenClaw 插件机制深度分析\n\n> 分析日期:2026-03-03\n> 基于 OpenClaw 最新代码库\n\n---\n\n## 目录\n\n1. [插件机制概述](#1-插件机制概述)\n2. [插件分类体系](#2-插件分类体系)\n3."
  },
  {
    "path": "bot/docs/rfc-openviking-cli-ov-chat.md",
    "chars": 9412,
    "preview": "# RFC: OpenViking CLI Support for ov chat Command\n\n**Author:** OpenViking Team\n**Status:** Implemented\n**Date:** 2025-03"
  },
  {
    "path": "bot/eval/locomo/judge.py",
    "chars": 6489,
    "preview": "import argparse\nimport csv\nimport json\nimport os\nimport asyncio\nfrom openai import AsyncOpenAI\nfrom dotenv import load_d"
  },
  {
    "path": "bot/eval/locomo/run_eval.py",
    "chars": 5804,
    "preview": "import argparse\nimport json\nimport subprocess\nimport time\nimport csv\nimport os\nimport re\n\n\ndef load_locomo_qa(\n    input"
  },
  {
    "path": "bot/eval/locomo/stat_judge_result.py",
    "chars": 2738,
    "preview": "import argparse\nimport csv\nimport json\nimport os\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Statist"
  },
  {
    "path": "bot/eval/skillsbench/skill_bench_eval.py",
    "chars": 35351,
    "preview": "\"\"\"\nSkillsBench OpenClaw Evaluator.\n\nEvaluates OpenClaw's ability to use skills by running tasks from SkillsBench.\n\nUsag"
  },
  {
    "path": "bot/license/LICENSE",
    "chars": 1076,
    "preview": "MIT License\n\nCopyright (c) 2025 nanobot contributors\n\nPermission is hereby granted, free of charge, to any person obtain"
  },
  {
    "path": "bot/package.json",
    "chars": 524,
    "preview": "{\n  \"name\": \"bot\",\n  \"version\": \"1.0.0\",\n  \"description\": \"**Vikingbot** is developed based on the project [nanobot](htt"
  },
  {
    "path": "bot/scripts/clean_vikingbot.sh",
    "chars": 429,
    "preview": "#!/bin/bash\nBOT_DIR=\"$HOME/.openviking/data/bot\"\n\necho \"🧹 Cleaning VikingBot data directory...\"\necho \"📂 Cleaning content"
  },
  {
    "path": "bot/scripts/restart_openviking_server.sh",
    "chars": 4294,
    "preview": "#!/bin/bash\n\n# Restart OpenViking Server with Bot API enabled\n# Usage: ./restart_openviking_server.sh [--port PORT] [--b"
  },
  {
    "path": "bot/scripts/start_vikingbot_in_ecs.sh",
    "chars": 896,
    "preview": "#!/bin/bash\n# VikingBot Gateway 启动脚本\n\n# 获取脚本所在目录\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT"
  },
  {
    "path": "bot/scripts/test_all.sh",
    "chars": 1344,
    "preview": "#!/bin/bash\n\n# test_all.sh - Run all tests without triggering uv sync\n# Usage: scripts/test_all.sh\n\nset -e\n\n# Get the di"
  },
  {
    "path": "bot/tests/conftest.py",
    "chars": 5211,
    "preview": "# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"Global test f"
  },
  {
    "path": "bot/tests/example.py",
    "chars": 1480,
    "preview": "import openviking as ov\n\n# Initialize OpenViking client with data directory\nclient = ov.SyncOpenViking(path=\"./data\")\n\nt"
  },
  {
    "path": "bot/tests/experience_data_mini.json",
    "chars": 1324,
    "preview": "[\n  {\n    \"unique_id\": \"rust-lang/rust169585762\",\n    \"repo\": \"rust-lang/rust\",\n    \"issue_id\": \"169585762\",\n    \"bug_de"
  },
  {
    "path": "bot/tests/test_chat_functionality.py",
    "chars": 4231,
    "preview": "# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.\n# SPDX-License-Identifier: Apache-2.0\n\"\"\"Tests for viki"
  },
  {
    "path": "bot/vikingbot/__init__.py",
    "chars": 751,
    "preview": "\"\"\"\nvikingbot - A lightweight AI agent framework\n\"\"\"\n\nimport warnings\n\n__version__ = \"0.1.3\"\n__logo__ = \"🐈\"\n\n# Suppress "
  },
  {
    "path": "bot/vikingbot/__main__.py",
    "chars": 205,
    "preview": "\"\"\"\nEntry point for running vikingbot as a module: python -m vikingbot\n\"\"\"\n\nimport sys\n\nfrom vikingbot.cli.commands impo"
  },
  {
    "path": "bot/vikingbot/agent/__init__.py",
    "chars": 289,
    "preview": "\"\"\"Agent core module.\"\"\"\n\nfrom vikingbot.agent.loop import AgentLoop\nfrom vikingbot.agent.context import ContextBuilder\n"
  },
  {
    "path": "bot/vikingbot/agent/context.py",
    "chars": 12998,
    "preview": "\"\"\"Context builder for assembling agent prompts.\"\"\"\n\nimport base64\nimport mimetypes\nimport platform\nimport time as _time"
  },
  {
    "path": "bot/vikingbot/agent/loop.py",
    "chars": 31960,
    "preview": "\"\"\"Agent loop: the core processing engine.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimport json\nimport tim"
  },
  {
    "path": "bot/vikingbot/agent/memory.py",
    "chars": 2872,
    "preview": "\"\"\"Memory system for persistent agent memory.\"\"\"\n\nfrom pathlib import Path\nfrom typing import Any\nfrom loguru import log"
  },
  {
    "path": "bot/vikingbot/agent/skills.py",
    "chars": 7857,
    "preview": "\"\"\"Skills loader for agent capabilities.\"\"\"\n\nimport json\nimport os\nfrom loguru import logger\nimport re\nimport shutil\nfro"
  },
  {
    "path": "bot/vikingbot/agent/subagent.py",
    "chars": 8483,
    "preview": "\"\"\"Subagent manager for background task execution.\"\"\"\n\nimport asyncio\nimport json\nimport uuid\nfrom pathlib import Path\nf"
  },
  {
    "path": "bot/vikingbot/agent/tools/__init__.py",
    "chars": 306,
    "preview": "\"\"\"Agent tools module.\"\"\"\n\nfrom vikingbot.agent.tools.base import Tool\nfrom vikingbot.agent.tools.registry import ToolRe"
  },
  {
    "path": "bot/vikingbot/agent/tools/base.py",
    "chars": 9023,
    "preview": "\"\"\"Base class for agent tools.\"\"\"\n\nfrom dataclasses import dataclass\n\nfrom vikingbot.config.schema import SessionKey\nfro"
  },
  {
    "path": "bot/vikingbot/agent/tools/cron.py",
    "chars": 4145,
    "preview": "\"\"\"Cron tool for scheduling reminders and tasks.\"\"\"\n\nfrom typing import Any\n\nfrom vikingbot.agent.tools.base import Tool"
  },
  {
    "path": "bot/vikingbot/agent/tools/factory.py",
    "chars": 4975,
    "preview": "\"\"\"Tool factory for centralized tool registration.\"\"\"\n\nfrom typing import TYPE_CHECKING, Callable\n\nfrom vikingbot.agent."
  },
  {
    "path": "bot/vikingbot/agent/tools/filesystem.py",
    "chars": 5448,
    "preview": "\"\"\"File system tools: read, write, edit.\"\"\"\n\nfrom typing import TYPE_CHECKING, Any\n\nfrom vikingbot.agent.tools.base impo"
  },
  {
    "path": "bot/vikingbot/agent/tools/image.py",
    "chars": 11976,
    "preview": "\"\"\"Image generation tool using LiteLLM's image generation capabilities.\"\"\"\n\nimport base64\nimport logging\nimport mimetype"
  },
  {
    "path": "bot/vikingbot/agent/tools/message.py",
    "chars": 1723,
    "preview": "\"\"\"Message tool for sending messages to users.\"\"\"\n\nfrom typing import Any, Callable, Awaitable\n\nfrom vikingbot.agent.too"
  },
  {
    "path": "bot/vikingbot/agent/tools/ov_file.py",
    "chars": 14528,
    "preview": "\"\"\"OpenViking file system tools: read, write, list, search resources.\"\"\"\n\nfrom abc import ABC\nfrom pathlib import Path\nf"
  },
  {
    "path": "bot/vikingbot/agent/tools/registry.py",
    "chars": 7135,
    "preview": "\"\"\"Tool registry for dynamic tool management.\"\"\"\n\nimport time\n\nfrom loguru import logger\n\nfrom typing import Any\n\nfrom v"
  },
  {
    "path": "bot/vikingbot/agent/tools/shell.py",
    "chars": 1678,
    "preview": "\"\"\"Shell execution tool.\"\"\"\n\nimport asyncio\nimport os\nimport re\nfrom pathlib import Path\nfrom typing import TYPE_CHECKIN"
  },
  {
    "path": "bot/vikingbot/agent/tools/spawn.py",
    "chars": 1718,
    "preview": "\"\"\"Spawn tool for creating background subagents.\"\"\"\n\nfrom typing import Any, TYPE_CHECKING\n\nfrom vikingbot.agent.tools.b"
  },
  {
    "path": "bot/vikingbot/agent/tools/web.py",
    "chars": 4799,
    "preview": "\"\"\"Web tools: web_fetch.\"\"\"\n\nimport html\nimport json\nimport re\nfrom typing import Any\nfrom urllib.parse import urlparse\n"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/__init__.py",
    "chars": 3357,
    "preview": "\"\"\"\nWeb search tool with multiple backends (brave, ddgs, exa, tavily).\n\nTo add a new backend:\n    1. Create new file: we"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/base.py",
    "chars": 835,
    "preview": "\"\"\"Web search backend base class.\"\"\"\n\nfrom abc import ABC, abstractmethod\nfrom typing import Any\n\n\nclass WebSearchBacken"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/brave.py",
    "chars": 1623,
    "preview": "\"\"\"Brave Search backend.\"\"\"\n\nimport os\nfrom typing import Any\n\nimport httpx\n\nfrom .base import WebSearchBackend\nfrom .re"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/ddgs.py",
    "chars": 1405,
    "preview": "\"\"\"DDGS (DuckDuckGo) backend - free, no API key required.\"\"\"\n\nimport asyncio\nfrom typing import Any\n\nfrom .base import W"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/exa.py",
    "chars": 1970,
    "preview": "\"\"\"Exa AI backend.\"\"\"\n\nimport os\nfrom typing import Any\n\nimport httpx\n\nfrom .base import WebSearchBackend\nfrom .registry"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/registry.py",
    "chars": 3242,
    "preview": "\"\"\"Web search backend registry.\"\"\"\n\nfrom typing import Dict, List, Type, Optional\n\nfrom .base import WebSearchBackend\n\n\n"
  },
  {
    "path": "bot/vikingbot/agent/tools/websearch/tavily.py",
    "chars": 1667,
    "preview": "\"\"\"Tavily Search backend.\"\"\"\n\nimport os\nfrom typing import Any\n\nfrom .base import WebSearchBackend\nfrom .registry import"
  },
  {
    "path": "bot/vikingbot/bus/__init__.py",
    "chars": 240,
    "preview": "\"\"\"Message bus module for decoupled channel-agent communication.\"\"\"\n\nfrom vikingbot.bus.events import InboundMessage, Ou"
  },
  {
    "path": "bot/vikingbot/bus/events.py",
    "chars": 1700,
    "preview": "\"\"\"Event types for the message bus.\"\"\"\n\nfrom dataclasses import dataclass, field\nfrom datetime import datetime\nfrom enum"
  },
  {
    "path": "bot/vikingbot/bus/queue.py",
    "chars": 3130,
    "preview": "\"\"\"Async message queue for decoupled channel-agent communication.\"\"\"\n\nimport asyncio\nfrom typing import Callable, Awaita"
  },
  {
    "path": "bot/vikingbot/channels/__init__.py",
    "chars": 201,
    "preview": "\"\"\"Chat channels module with plugin architecture.\"\"\"\n\nfrom vikingbot.channels.base import BaseChannel\nfrom vikingbot.cha"
  },
  {
    "path": "bot/vikingbot/channels/base.py",
    "chars": 12576,
    "preview": "\"\"\"Base channel interface for chat platforms.\"\"\"\n\nimport base64\nimport re\nfrom abc import ABC, abstractmethod\nfrom pathl"
  },
  {
    "path": "bot/vikingbot/channels/chat.py",
    "chars": 5499,
    "preview": "# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.\n# SPDX-License-Identifier: Apache-2.0\n\"\"\"Chat channel f"
  },
  {
    "path": "bot/vikingbot/channels/dingtalk.py",
    "chars": 9331,
    "preview": "\"\"\"DingTalk/DingDing channel implementation using Stream Mode.\"\"\"\n\nimport asyncio\nimport json\nimport time\nfrom typing im"
  },
  {
    "path": "bot/vikingbot/channels/discord.py",
    "chars": 10032,
    "preview": "\"\"\"Discord channel implementation using Discord Gateway websocket.\"\"\"\n\nimport asyncio\nimport json\nfrom pathlib import Pa"
  },
  {
    "path": "bot/vikingbot/channels/email.py",
    "chars": 14322,
    "preview": "\"\"\"Email channel implementation using IMAP polling + SMTP replies.\"\"\"\n\nimport asyncio\nimport html\nimport imaplib\nimport "
  },
  {
    "path": "bot/vikingbot/channels/feishu.py",
    "chars": 33972,
    "preview": "\"\"\"Feishu/Lark channel implementation using lark-oapi SDK with WebSocket long connection.\"\"\"\n\nimport asyncio\nimport io\ni"
  },
  {
    "path": "bot/vikingbot/channels/manager.py",
    "chars": 8634,
    "preview": "\"\"\"Channel manager for coordinating chat channels.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nfrom typing im"
  },
  {
    "path": "bot/vikingbot/channels/mochat.py",
    "chars": 37822,
    "preview": "\"\"\"Mochat channel implementation using Socket.IO with HTTP polling fallback.\"\"\"\n\nfrom __future__ import annotations\n\nimp"
  },
  {
    "path": "bot/vikingbot/channels/openapi.py",
    "chars": 15981,
    "preview": "\"\"\"OpenAPI channel for HTTP-based chat API.\"\"\"\n\nimport asyncio\nimport secrets\nimport uuid\nfrom datetime import datetime\n"
  },
  {
    "path": "bot/vikingbot/channels/openapi_models.py",
    "chars": 4191,
    "preview": "\"\"\"Pydantic models for OpenAPI channel.\"\"\"\n\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import Any, "
  },
  {
    "path": "bot/vikingbot/channels/qq.py",
    "chars": 4507,
    "preview": "\"\"\"QQ channel implementation using botpy SDK.\"\"\"\n\nimport asyncio\nfrom collections import deque\n\nfrom loguru import logge"
  },
  {
    "path": "bot/vikingbot/channels/single_turn.py",
    "chars": 3392,
    "preview": "# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.\n# SPDX-License-Identifier: Apache-2.0\n\"\"\"Single-turn ch"
  },
  {
    "path": "bot/vikingbot/channels/slack.py",
    "chars": 7558,
    "preview": "\"\"\"Slack channel implementation using Socket Mode.\"\"\"\n\nimport asyncio\nimport re\nfrom typing import Any\n\nfrom loguru impo"
  },
  {
    "path": "bot/vikingbot/channels/telegram.py",
    "chars": 15842,
    "preview": "\"\"\"Telegram channel implementation using python-telegram-bot.\"\"\"\n\nfrom __future__ import annotations\n\nimport asyncio\nimp"
  },
  {
    "path": "bot/vikingbot/channels/utils.py",
    "chars": 3249,
    "preview": "\"\"\"Shared utilities for channel implementations - image path handling, etc.\"\"\"\n\nimport base64\nimport re\nfrom pathlib imp"
  },
  {
    "path": "bot/vikingbot/channels/whatsapp.py",
    "chars": 5445,
    "preview": "\"\"\"WhatsApp channel implementation using Node.js bridge.\"\"\"\n\nimport asyncio\nimport json\nfrom typing import Any\n\nfrom log"
  },
  {
    "path": "bot/vikingbot/cli/__init__.py",
    "chars": 32,
    "preview": "\"\"\"CLI module for vikingbot.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/cli/commands.py",
    "chars": 32546,
    "preview": "\"\"\"CLI commands for vikingbot.\"\"\"\n\nimport asyncio\nimport json\nimport os\nimport select\nimport sys\nimport time\nfrom pathli"
  },
  {
    "path": "bot/vikingbot/config/__init__.py",
    "chars": 207,
    "preview": "\"\"\"Configuration module for vikingbot.\"\"\"\n\nfrom vikingbot.config.loader import load_config, get_config_path\nfrom vikingb"
  },
  {
    "path": "bot/vikingbot/config/loader.py",
    "chars": 7337,
    "preview": "\"\"\"Configuration loading utilities.\"\"\"\n\nimport json\nimport os\nfrom pathlib import Path\nfrom typing import Any\nfrom logur"
  },
  {
    "path": "bot/vikingbot/config/schema.py",
    "chars": 26745,
    "preview": "\"\"\"Configuration schema using Pydantic.\"\"\"\n\nfrom enum import Enum\nfrom pathlib import Path\nfrom typing import Any, Dict,"
  },
  {
    "path": "bot/vikingbot/console/README_GRADIO.md",
    "chars": 675,
    "preview": "\n# Vikingbot Console - Gradio 版本\n\n使用 Gradio 实现的纯 Python 控制台界面。\n\n## 运行\n\n```bash\nvikingbot gateway\n```\n\n这会自动在 http://local"
  },
  {
    "path": "bot/vikingbot/console/__init__.py",
    "chars": 57,
    "preview": "\"\"\"Vikingbot Console - Web管理界面\"\"\"\n\n__version__ = \"1.0.0\"\n"
  },
  {
    "path": "bot/vikingbot/console/web_console.py",
    "chars": 17450,
    "preview": "import json\nimport sys\nimport os\nfrom pathlib import Path\nfrom typing import Any, Dict, List, Optional, Tuple\n\nimport gr"
  },
  {
    "path": "bot/vikingbot/cron/__init__.py",
    "chars": 203,
    "preview": "\"\"\"Cron service for scheduled agent tasks.\"\"\"\n\nfrom vikingbot.cron.service import CronService\nfrom vikingbot.cron.types "
  },
  {
    "path": "bot/vikingbot/cron/service.py",
    "chars": 11917,
    "preview": "\"\"\"Cron service for scheduling agent tasks.\"\"\"\n\nimport asyncio\nimport json\nimport time\nimport uuid\nfrom pathlib import P"
  },
  {
    "path": "bot/vikingbot/cron/types.py",
    "chars": 1600,
    "preview": "\"\"\"Cron types.\"\"\"\n\nfrom dataclasses import dataclass, field\nfrom typing import Literal\n\nfrom vikingbot.config.schema imp"
  },
  {
    "path": "bot/vikingbot/heartbeat/__init__.py",
    "chars": 143,
    "preview": "\"\"\"Heartbeat service for periodic agent wake-ups.\"\"\"\n\nfrom vikingbot.heartbeat.service import HeartbeatService\n\n__all__ "
  },
  {
    "path": "bot/vikingbot/heartbeat/service.py",
    "chars": 6916,
    "preview": "\"\"\"Heartbeat service - periodic agent wake-up to check for tasks.\"\"\"\n\nimport asyncio\nfrom pathlib import Path\nfrom typin"
  },
  {
    "path": "bot/vikingbot/hooks/__init__.py",
    "chars": 162,
    "preview": "\"\"\"\nHook 机制 - 导出公共 API\n\"\"\"\n\nfrom .base import Hook, HookContext\nfrom .manager import HookManager\n\n__all__ = [\n    \"Hook\""
  },
  {
    "path": "bot/vikingbot/hooks/base.py",
    "chars": 883,
    "preview": "from abc import ABC, abstractmethod\nfrom enum import Enum\nfrom dataclasses import dataclass\nfrom typing import Any, Dict"
  },
  {
    "path": "bot/vikingbot/hooks/builtins/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "bot/vikingbot/hooks/builtins/openviking_hooks.py",
    "chars": 3928,
    "preview": "import re\nfrom typing import Any\n\nfrom loguru import logger\n\nfrom vikingbot.config.loader import load_config\nfrom viking"
  },
  {
    "path": "bot/vikingbot/hooks/manager.py",
    "chars": 2541,
    "preview": "import asyncio\nimport importlib\nfrom collections import defaultdict\nfrom typing import List, Any, Dict, Type\n\nfrom logur"
  },
  {
    "path": "bot/vikingbot/integrations/__init__.py",
    "chars": 425,
    "preview": "\"\"\"Integrations with external services.\"\"\"\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from vikingbot.integ"
  },
  {
    "path": "bot/vikingbot/integrations/langfuse.py",
    "chars": 12525,
    "preview": "\"\"\"Langfuse integration for LLM observability.\"\"\"\n\nfrom contextlib import contextmanager\nfrom typing import Any, Generat"
  },
  {
    "path": "bot/vikingbot/openviking_mount/README.md",
    "chars": 4584,
    "preview": "# OpenViking 文件系统挂载模块\n\n这个模块将 OpenViking 的虚拟文件系统挂载到本地文件系统路径,让用户可以像操作普通文件一样操作 OpenViking 上的数据。\n\n这个模块只是一个实验功能,并没有被实际使用\n\n\n##"
  },
  {
    "path": "bot/vikingbot/openviking_mount/__init__.py",
    "chars": 1111,
    "preview": "\"\"\"\nOpenViking Filesystem Mount Module\n\n这个模块将OpenViking的虚拟文件系统挂载到本地文件系统路径,\n让用户可以像操作普通文件一样操作OpenViking上的数据。\n\"\"\"\n\nfrom typ"
  },
  {
    "path": "bot/vikingbot/openviking_mount/fuse_finder.py",
    "chars": 16602,
    "preview": "#!/usr/bin/env python3\nfrom __future__ import annotations\n\nimport sys\nimport os\nimport stat\nimport errno\nimport tempfile"
  },
  {
    "path": "bot/vikingbot/openviking_mount/fuse_proxy.py",
    "chars": 11733,
    "preview": "#!/usr/bin/env python3\nfrom __future__ import annotations\n\nimport sys\nimport os\nimport stat\nimport errno\nimport tempfile"
  },
  {
    "path": "bot/vikingbot/openviking_mount/fuse_simple.py",
    "chars": 15201,
    "preview": "#!/usr/bin/env python3\nfrom __future__ import annotations\n\nimport sys\nimport os\nimport stat\nimport errno\nimport tempfile"
  },
  {
    "path": "bot/vikingbot/openviking_mount/fuse_simple_debug.py",
    "chars": 17611,
    "preview": "#!/usr/bin/env python3\nfrom __future__ import annotations\n\nimport sys\nimport os\nimport stat\nimport errno\nimport tempfile"
  },
  {
    "path": "bot/vikingbot/openviking_mount/manager.py",
    "chars": 6759,
    "preview": "\"\"\"\nOpenViking Mount Manager\n\n管理多个OpenViking挂载点的生命周期\n\"\"\"\n\nfrom __future__ import annotations\n\nimport sys\nfrom pathlib im"
  },
  {
    "path": "bot/vikingbot/openviking_mount/mount.py",
    "chars": 13157,
    "preview": "\"\"\"\nOpenViking Filesystem Mount Module - Core Implementation\n\n这个模块将OpenViking的虚拟文件系统挂载到本地文件系统路径,\n让用户可以像操作普通文件一样操作OpenVik"
  },
  {
    "path": "bot/vikingbot/openviking_mount/ov_server.py",
    "chars": 17678,
    "preview": "import asyncio\nimport hashlib\nimport time\nfrom typing import Any, Dict, List, Optional\n\nfrom loguru import logger\n\nimpor"
  },
  {
    "path": "bot/vikingbot/openviking_mount/session_integration.py",
    "chars": 10218,
    "preview": "\"\"\"\nOpenViking FUSE 会话集成\n\n提供与会话管理器的集成,自动在配置的 workspace/{session}/ 挂载 OpenViking\n每个session直接在自己的workspace下管理内容\n\"\"\"\n\nfrom "
  },
  {
    "path": "bot/vikingbot/openviking_mount/user_apikey_manager.py",
    "chars": 3709,
    "preview": "\"\"\"User API Key persistence manager for OpenViking remote mode.\"\"\"\n\nimport json\nimport hashlib\nfrom pathlib import Path\n"
  },
  {
    "path": "bot/vikingbot/openviking_mount/viking_fuse.py",
    "chars": 14050,
    "preview": "\"\"\"\nOpenViking FUSE 文件系统\n\n实现真正的 FUSE 文件系统挂载,允许使用标准文件系统 API(os、pathlib 等)\n直接操作 OpenViking 数据。\n\"\"\"\n\nfrom __future__ import"
  },
  {
    "path": "bot/vikingbot/providers/__init__.py",
    "chars": 228,
    "preview": "\"\"\"LLM provider abstraction module.\"\"\"\n\nfrom vikingbot.providers.base import LLMProvider, LLMResponse\nfrom vikingbot.pro"
  },
  {
    "path": "bot/vikingbot/providers/base.py",
    "chars": 2045,
    "preview": "\"\"\"Base LLM provider interface.\"\"\"\n\nfrom abc import ABC, abstractmethod\nfrom dataclasses import dataclass, field\nfrom ty"
  },
  {
    "path": "bot/vikingbot/providers/litellm_provider.py",
    "chars": 14716,
    "preview": "\"\"\"LiteLLM provider implementation for multi-provider support.\"\"\"\n\nimport json\nimport os\nfrom typing import Any\n\nimport "
  },
  {
    "path": "bot/vikingbot/providers/registry.py",
    "chars": 12784,
    "preview": "\"\"\"\nProvider Registry — single source of truth for LLM provider metadata.\n\nAdding a new provider:\n  1. Add a ProviderSpe"
  },
  {
    "path": "bot/vikingbot/providers/transcription.py",
    "chars": 1849,
    "preview": "\"\"\"Voice transcription provider using Groq.\"\"\"\n\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nimport httpx\n"
  },
  {
    "path": "bot/vikingbot/sandbox/__init__.py",
    "chars": 489,
    "preview": "\"\"\"Sandbox module for secure command execution.\"\"\"\n\nfrom vikingbot.sandbox.base import (\n    SandboxBackend,\n    Sandbox"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/__init__.py",
    "chars": 964,
    "preview": "\"\"\"Sandbox backend registry.\"\"\"\n\nfrom typing import TYPE_CHECKING, Type, Callable, Dict\nfrom vikingbot.sandbox.base impo"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/aiosandbox.py",
    "chars": 5944,
    "preview": "\"\"\"AIO Sandbox backend implementation using agent-sandbox SDK.\"\"\"\n\nfrom pathlib import Path\nfrom typing import Any\n\nfrom"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/direct.py",
    "chars": 4922,
    "preview": "\"\"\"Direct backend implementation - executes commands directly on host without sandboxing.\"\"\"\n\nimport asyncio\nimport os\nf"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/opensandbox.py",
    "chars": 13486,
    "preview": "\"\"\"OpenSandbox backend implementation using official SDK.\"\"\"\n\nimport asyncio\nimport atexit\nimport os\nimport subprocess\ni"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/srt-wrapper.mjs",
    "chars": 12369,
    "preview": "#!/usr/bin/env node\n/**\n * SRT (Sandbox Runtime) Node.js wrapper for Python IPC\n * \n * This script provides an IPC inter"
  },
  {
    "path": "bot/vikingbot/sandbox/backends/srt.py",
    "chars": 12578,
    "preview": "\"\"\"SRT backend implementation using @anthropic-ai/sandbox-runtime.\"\"\"\n\nimport asyncio\nimport json\nimport os\nfrom pathlib"
  },
  {
    "path": "bot/vikingbot/sandbox/base.py",
    "chars": 4942,
    "preview": "\"\"\"Abstract interface for sandbox backends.\"\"\"\n\nfrom abc import ABC, abstractmethod\nfrom pathlib import Path\nfrom typing"
  },
  {
    "path": "bot/vikingbot/sandbox/manager.py",
    "chars": 4920,
    "preview": "\"\"\"Sandbox manager for creating and managing sandbox instances.\"\"\"\n\nimport asyncio\nfrom pathlib import Path\nfrom typing "
  },
  {
    "path": "bot/vikingbot/session/__init__.py",
    "chars": 137,
    "preview": "\"\"\"Session management module.\"\"\"\n\nfrom vikingbot.session.manager import SessionManager, Session\n\n__all__ = [\"SessionMana"
  },
  {
    "path": "bot/vikingbot/session/manager.py",
    "chars": 9857,
    "preview": "\"\"\"Session management for conversation history.\"\"\"\n\nimport asyncio\nimport json\nfrom dataclasses import dataclass, field\n"
  },
  {
    "path": "bot/vikingbot/tests/__init__.py",
    "chars": 28,
    "preview": "\"\"\"Vikingbot test suite.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/integration/__init__.py",
    "chars": 25,
    "preview": "\"\"\"Integration tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/unit/__init__.py",
    "chars": 18,
    "preview": "\"\"\"Unit tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/unit/test_agent/__init__.py",
    "chars": 26,
    "preview": "\"\"\"Agent module tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/unit/test_bus/__init__.py",
    "chars": 25,
    "preview": "\"\"\"Message bus tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/unit/test_channels/__init__.py",
    "chars": 29,
    "preview": "\"\"\"Channel adapter tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/tests/unit/test_config/__init__.py",
    "chars": 27,
    "preview": "\"\"\"Configuration tests.\"\"\"\n"
  },
  {
    "path": "bot/vikingbot/utils/__init__.py",
    "chars": 675,
    "preview": "\"\"\"Utility functions for vikingbot.\"\"\"\n\nfrom vikingbot.utils.helpers import (\n    ensure_dir,\n    get_workspace_path,\n  "
  },
  {
    "path": "bot/vikingbot/utils/helpers.py",
    "chars": 8561,
    "preview": "\"\"\"Utility functions for vikingbot.\"\"\"\n\nfrom pathlib import Path\nfrom datetime import datetime\nfrom loguru import logger"
  },
  {
    "path": "bot/vikingbot/utils/tracing.py",
    "chars": 6971,
    "preview": "\"\"\"\nAbstract tracing utilities for observability.\n\nThis module provides a tracing abstraction that is not tied to any sp"
  },
  {
    "path": "bot/workspace/HEARTBEAT.md",
    "chars": 376,
    "preview": "# Heartbeat Tasks\n\nThis file is checked at regular intervals by your vikingbot agent.\nAdd tasks below that you want the "
  },
  {
    "path": "bot/workspace/SOUL.md",
    "chars": 352,
    "preview": "# Soul\n\nI am vikingbot 🐈, a personal AI assistant.\n\n## Personality\n\n- Helpful and friendly\n- Concise and to the point\n- "
  },
  {
    "path": "bot/workspace/TOOLS.md",
    "chars": 4909,
    "preview": "# Available Tools\n\n**IMPORTANT: Always use OpenViking first for knowledge queries and memory storage**\n\n## OpenViking Kn"
  },
  {
    "path": "bot/workspace/USER.md",
    "chars": 844,
    "preview": "# User Profile\n\nInformation about the user to help personalize interactions.\n\n## Basic Information\n\n- **Name**: (your na"
  },
  {
    "path": "bot/workspace/memory/MEMORY.md",
    "chars": 410,
    "preview": "# Long-term Memory\n\nThis file stores important information that should persist across sessions.\n\n## User Information\n\n(I"
  },
  {
    "path": "bot/workspace/skills/README.md",
    "chars": 879,
    "preview": "# vikingbot Skills\n\nThis directory contains built-in skills that extend vikingbot's capabilities.\n\n## Skill Format\n\nEach"
  },
  {
    "path": "bot/workspace/skills/cron/SKILL.md",
    "chars": 1171,
    "preview": "---\nname: cron\ndescription: Schedule reminders and recurring tasks.\n---\n\n# Cron\n\nUse the `cron` tool to schedule reminde"
  },
  {
    "path": "bot/workspace/skills/github/SKILL.md",
    "chars": 1373,
    "preview": "---\nname: github\ndescription: \"Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` "
  },
  {
    "path": "bot/workspace/skills/github-proxy/SKILL.md",
    "chars": 1773,
    "preview": "---\nname: github-proxy\ndescription: GitHub 国内访问加速 skill,使用 githubproxy.cc 代理加速 GitHub 仓库克隆、文件下载、Raw 文件访问等操作。使用场景:(1) 需要 "
  }
]

// ... and 1302 more files (download for full content)

About this extraction

This page contains the full source code of the volcengine/OpenViking GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1502 files (11.0 MB), approximately 3.0M tokens, and a symbol index with 11207 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!