Commit 006a06f
feat/vikingbot: viking bot mvp based on openviking (#335)
* init vikingbot
* fix sandbox bug
* fix sandbox bug
* fix sandbox bug
* 默认关闭沙箱
* update
* chore: add .gitignore for Node.js project
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat: Improve workspace management and sandbox behavior
- Change default workspace to ~/.vikingbot/workspace/default
- Lazy initialize workspace (create on first use, not on onboard)
- Sandbox directories are parallel to default/ directory
- Sandbox copies templates from source workspace directly
- Pre-create sandbox directory when conversation starts
- Add get_sandbox_parent_path and get_source_workspace_path helpers
- Update SandboxManager to accept source_workspace_path
- Update ContextBuilder for lazy initialization
- Update onboard command to not create workspace upfront
- Update gateway and tui commands for new sandbox behavior
- Fix WebSearchTool import (from websearch module, not web)
- Restrict to workspace default value changed to true
* feat: Multiple feature enhancements
## New Features
### Workspace & Sandbox Improvements
- Change default workspace to ~/.vikingbot/workspace/default
- Add lazy initialization (create workspace on first use)
- Make sandbox directory parallel to default in workspace/
- Copy templates and skills from source workspace instead of main workspace
- Create sandbox directory early on conversation start
- Change restrict_to_workspace default to true
- Ensure ContextBuilder/MemoryStore/SkillsLoader read from sandbox when enabled
### WebSearch Tool
- Add WebSearchTool using ddgs library
- Add websearch/ tool directory with implementation
- Add tests/test_websearch.py
- Add ddgs dependency to pyproject.toml
### New Tools
- Add ImageTool for image processing
- Add MemoryTool for memory management
### Channels
- Add multi-channel support design documentation (specs/04-channels.md)
- Update all channel implementations for multi-channel support
- Update channel manager
- Update base channel class
### Docker & Build
- Move Dockerfile to docker/ directory
- Add docker/ directory with build files
- Add package.json/package-lock.json for Node.js dependencies
- Add srt-wrapper.mjs for SRT backend
### Scripts Organization
- Create scripts/ directory
- Add clean_vikingbot.py cleanup script
- Add README_CLEANUP.md documentation
- Remove core_agent_lines.sh (moved or deprecated)
### Skills
- Add github-proxy skill
- Update skills/README.md
### Agent Enhancements
- Update AgentLoop max_iterations from 20 to 50
- Add vikingbot/agent/agents/ directory
- Update subagent implementation
- Update filesystem/shell/web tools
- Update config loader
- Update SRT sandbox backend
- Update session manager
### Specs & Documentation
- Update specs/02-agent.md (max_iterations)
- Add multi-channel design to specs/04-channels.md
* 完善沙箱工具测试及策略优化
- 新增沙箱工具单元测试(test_sandbox_tools.py)
- 优化ExecTool安全策略:沙箱模式下跳过本地安全守卫
- 更新spec文档说明路径处理和删除文件策略
- 更新现有测试以匹配实际代码结构
* 修改沙箱默认策略:allowWrite默认为["/"]
- 允许沙箱内文件的写入/删除操作
- 提高沙箱使用便利性
* 修复沙箱安全漏洞:限制allowWrite为沙箱工作目录
- 移除默认allowWrite: ["/"]的危险配置
- 在SRT后端动态添加沙箱工作目录到allowWrite
- 确保只能操作沙箱内的文件,防止访问宿主机文件系统
* 更新spec文档:说明沙箱文件系统安全策略
- 说明SRT后端动态添加沙箱工作目录到allowWrite
- 明确沙箱内可操作、沙箱外被阻止的行为
- 记录默认配置为空列表,无需手动配置
* 默认开放/tmp目录权限给沙箱用户
- 在SRT后端动态添加/tmp到allowWrite
- 沙箱用户可以在/tmp目录下创建临时文件
* 添加VikingBot Gateway启动脚本
- 自动激活虚拟环境
- 自动kill旧进程
- nohup后台启动并输出日志到~/logs/output.log
- 自动tail日志文件
* 自动继承NODE_PATH环境变量到SRT沙箱进程
- 在启动SRT进程时传递完整的环境变量
- 确保@anthropic-ai/sandbox-runtime能被正确找到
* feat: 添加Console Web UI和部署配置
- 新增Console Web UI模块,基于FastAPI
- 添加配置管理、会话管理、工作区文件浏览API
- 集成HTMX前端,提供简洁的Web界面
- 新增deploy目录,包含本地、ECS、VKE部署配置
- 重构docker目录结构,移动到deploy/local
- 更新spec文档,添加13-console.md
- 更新飞书通道,支持图片消息接收
- 添加fastapi和uvicorn依赖
* feat: improve deployment configuration and add TOS support
- Add UV_HTTP_TIMEOUT to Dockerfile
- Change service port from 18790 to 18791
- Add health check endpoints to liveness/readiness probes
- Add TOS storage configuration and PV/PVC creation logic
- Add command timeout handling in vke_deploy.py
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat: improve console server and auto-onboard logic
- Refactor onboard command to extract _run_onboard_logic
- Add auto-onboard in gateway command when config not found
- Add /health and /healthz endpoints for Kubernetes probes
- Change default host from 127.0.0.1 to 0.0.0.0
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* fix: correct path construction in workspace API and frontend
- Fix relative path construction in list_files API
- Fix file path construction in frontend index.html
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat: multiple improvements including media storage and session workspace
## 改动 1:媒体文件保存位置改为 workspace/media
- 改动:所有频道(Feishu, Telegram, Discord)现在将媒体文件保存到 workspace/media 目录,而不是 ~/.vikingbot/media
- 原因:媒体文件放在用户的 workspace 里面更合适,更容易管理和访问,也符合工作区的概念
## 改动 2:Session workspace 初始化逻辑
- 改动:新增 session workspace 初始化逻辑,确保 ~/.vikingbot/workspace/{session_id} 目录在不存在时创建并复制模板,存在时跳过
- 原因:每个 session 应该有自己独立的 workspace,并且在创建时初始化模板文件(.md 和 skills 目录)
## 改动 3:其他改进
- Sandbox manager 改进
- SRT 后端改进
- Docker 配置更新
- Console UI 改进
- 新增 spec 文档
- 新增 .dockerignore
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat: 沙箱系统重构和优化
- 重构沙箱配置:去掉 enabled 开关,默认 backend 改为 direct,默认 mode 改为 shared
- 新增沙箱后端:direct(直接执行)、opensandbox(Alibaba OpenSandbox)、aiosandbox(agent-sandbox SDK)
- 优化 SRT 后端:文件操作通过 wrapper 进行,受沙箱规则保护;pwd 返回原始路径
- 优化 Direct 后端:重写文件操作方法,绝对路径直接使用
- 优化 AIO Sandbox 后端:修改路径处理,主目录可配置
- 移动 skills 目录:从 vikingbot/skills 移动到 workspace/skills,结构更清晰
- 更新 BUILTIN_SKILLS_DIR 路径:指向新的 workspace/skills 位置
- 更新 Console UI:去掉 Enable Sandbox 复选框,添加 Direct 选项
- 更新 Session Manager:去掉 enabled 检查,根据 mode 确保 workspace
- 更新 Agent Loop:每次消息重新初始化 ContextBuilder 等组件,支持动态 workspace
- 新增 spec 文档:16-sandbox-backends.md(沙箱后端配置指南)、17-vke-deployment.md(VKE 部署指南)
- 删除旧 spec 文档:11-sandbox-integration.md、15-opensandbox-integration.md
- 删除临时测试脚本:scripts/ 目录下的临时测试文件
- 更新测试文件:适配最新代码,MockBackend 添加缺少的方法
* feat: add html2text and beautifulsoup4 dependencies for HTML processing
Adds html2text for HTML to Markdown conversion and beautifulsoup4 for HTML parsing, enabling richer content handling in Feishu channel.
* feat: improve multi-channel matching logic in channel manager
Supports matching channels by shorthand type name (e.g., 'feishu' matches 'feishu:cli_xxx') for better backward compatibility when multiple channels of the same type are configured.
* feat: improve message tool default channel handling
Adds better logic for handling the default channel, preferring the complete channel ID (including app_id) over shorthand when available, ensuring messages are sent to the correct channel when multiple channels of the same type are configured.
* feat: add HTML to Markdown conversion and rich image support in Feishu channel
Adds comprehensive HTML processing capabilities:
- Image format validation using magic numbers to prevent uploading non-image content
- HTML to Markdown conversion using readability-lxml and html2text
- Markdown image extraction and upload to Feishu, with proper img element replacement
- URL trailing punctuation stripping for more reliable downloads
- Full support for rich content with images in Feishu interactive cards
* feat: integrate OpenCode for enhanced AI capabilities
Add OpenCode integration to enable more powerful AI features and code understanding.
Why this change:
- OpenCode provides advanced codebase analysis and session management capabilities
- Enables better context understanding across sessions
- Adds hooks system for extensibility
What changed:
- Added opencode-ai, beautifulsoup4, html2text dependencies
- Implemented hooks system with Hook base class and HookManager
- Added built-in OpenCode integration hooks
- Added opencode_mount module for FUSE-based OpenCode data access
- Added example files for hook integration
- Added test files for OpenCode integration
- Added OpenCode skill to workspace
- Added hooks specification documentation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* refactor: introduce SessionKey for multi-session isolation and better type safety
Major refactor to replace channel:chat_id strings with SessionKey data structure.
Why this change:
- Original channel:chat_id string format was error-prone and not type-safe
- Need proper isolation for multiple sessions from different channels
- Enable per-session sandbox isolation
- Better support for multiple instances of the same channel type
What changed:
- New SessionKey model with type, channel_id, chat_id fields (frozen for immutability)
- Refactored InboundMessage and OutboundMessage to use SessionKey instead of separate channel/chat_id
- Updated all channel implementations to use SessionKey
- Refactored agent loop, context builder, and tools with SessionKey support
- Added set_session_key() method to Tool base class for context-aware operations
- Updated sandbox manager for per-session isolation
- Refactored session manager to use SessionKey as key
- Updated spec documentation (01, 02, 03, 04, 07)
- Updated default model to openai/doubao-seed-2-0-pro-260215
- Changed default workspace to ~/.vikingbot/workspace/shared
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* chore: remove unused console screenshot files
Remove vikingbot-console-dashboard.png and vikingbot-console-full.png which are no longer needed.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* fix: adjust default config values
Adjust default configuration values:
- Change default workspace back to ~/.vikingbot/workspace
- Increase heartbeat interval from 5 minutes to 10 minutes
- Enable OpenCode hooks by default
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat: add default_skills config with all built-in skills
Add default_skills configuration to AgentDefaults with all 9 built-in skills: opencode, github-proxy, github, memory, cron, weather, tmux, skill-creator, summarize.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* opencode skill默认关闭
* 修改readme
* 修复vikingbot agent和tui的爆粗9哦
* add openviking tools
* add openviking tools
* 优化hook
* 优化hook
* add openviking tools
* add openviking tools
* add openviking tools
* add openviking tools
* add openviking tools
* support skill/tool memory
* hooks提交一版
* hooks提交一版
* update
* add openviking tools
* add openviking tools
* update readme
* add openviking tools
* add openviking tools
* openviking memory
* ov Server
* ov Server
* tools message
* tools message
* tools message
* support skill memory
* update part
* refactor(deploy): 优化Docker部署配置
- 重构Dockerfile,优化构建流程和镜像大小
- 新增deploy/docker/Dockerfile,提供更灵活的构建配置
- 重构build-image.sh脚本,简化镜像构建流程
- 修改build-multiarch.sh,支持多架构构建
- 重构deploy.sh部署脚本,改进部署流程
- 新增docker-entrypoint.sh,优化容器启动流程
- 重构stop.sh脚本,改进容器停止逻辑
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* refactor(deploy): 重构VKE部署流程,移除Python脚本改用Shell
- 移除README.md和VKE_DEPLOY_README.md文档
- 新增deploy.sh Shell脚本替代原Python部署脚本
- 移除test.sh测试脚本
- 简化vke_deploy.example.yaml配置文件
- 移除vke_deploy.py和vke_with_opensandbox_deploy.py Python脚本
- 整体简化VKE部署流程,使用Shell脚本替代Python实现
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* feat(agent): 增强Agent工具功能
- 修改context.py,优化上下文构建
- 修改tools/base.py,改进工具基类
- 修改tools/image.py,增强图像处理工具功能
- 修改tools/registry.py,优化工具注册机制
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* refactor(channels): 重构Channels模块,优化飞书渠道实现
- 重构base.py,改进基础Channel类实现
- 大幅重构feishu.py,优化飞书渠道的消息处理流程
- 重构utils.py,改进渠道工具函数
- 整体提升Channels模块的可维护性和性能
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* refactor: 优化Console和Hooks模块
- 修改console/console_gradio_simple.py,优化控制台界面
- 修改hooks/builtins/openviking_hooks.py,改进钩子实现
- 修改hooks/manager.py,优化钩子管理器
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* tools message
* tools message
* 添加从镜像安装的方法
* tools message
* 添加从镜像安装的方法
* 版本限制不超过3.13(openviking 3.14上没有)
* 版本限制不超过3.13(openviking 3.14上没有)
* 版本限制不超过3.13(openviking 3.14上没有)
* 版本限制不超过3.13(openviking 3.14上没有)
* 版本限制不超过3.13(openviking 3.14上没有)
* vikingbot
* 优化图片生成逻辑
* vikingbot
* vikingbot
* vikingbot
* vikingbot
* vikingbot
* 飞书图片部分优化
* update tool
* vikingbot
* feat(skill): support zip upload for add_skill API (#312)
* feat(skill): support zip upload for add_skill API
- Add temp_path field to AddSkillRequest model
- Add zip extraction support in SkillProcessor._parse_skill()
- Add smart dual-mode upload in AsyncHTTPClient.add_skill()
This enables remote HTTP clients to upload skill directories as zip files,
following the same pattern as add_resource.
* feat(cli): add zip upload support for add_skill in Rust CLI
- Add smart dual-mode upload in add_skill() (same as add_resource)
- Fix missing auth headers in upload_temp_file()
- Reuse build_headers() to avoid code duplication
* feat(agfs): agfs新增binding client (#304)
* feat(agfs): agfs新增binding client
fix: viking_fs适配binding client, 简化agfs相关参数
* feat(agfs): agfs binding-client支持windows
* docs: 补充agfs binding-client用法
* fix(agfs): 默认带上agfs binding-client依赖库; setup.py支持编译该库
* fix(agfs): add agfs binding-client linux so
* fix(agfs): code format
* fix(parser): remove redundant mkdir in DirectoryParser (#318)
* fix: use original directory name for temp URI lookup in TreeBuilder (#319)
_finalize_from_temp() applies sanitize_segment() to the temp document
directory name (e.g. __test__ -> _test_), then uses the sanitized name
to construct temp_doc_uri. However, the actual temp directory retains
its original (unsanitized) name, causing FileNotFoundError during
_move_temp_to_dest().
Use the original directory name for temp_doc_uri (locating the temp
directory), while continuing to use the sanitized name for candidate_uri
(the final destination URI).
* fix: handle is_healthy() AttributeError when not initialized (closes #298) (#322)
ObserverService.is_healthy() threw AttributeError when called before
initialize() because self._config and self._vikingdb were None.
- Add None guards to vikingdb and vlm properties returning unhealthy
ComponentStatus instead of crashing
- Add early return False in is_healthy() when dependencies not ready
- Add 4 tests covering the uninitialized state
Co-authored-by: r266-tech <r266-tech@users.noreply.github.com>
* feat(docs,ci): 完善云上部署文档与 Docker CI 流程 (#320)
- release workflow 新增 Docker 镜像构建推送至 GHCR
- 重写 examples/cloud/GUIDE.md 云上部署指南,补充架构概览、systemd/Docker/Helm 三种部署方式、多租户管理、FAQ 等章节
- ov.conf.example 占位符改为 <your-xxx> 格式,移除 rerank 配置
- 中英文部署文档(docs/zh|en/guides/03-deployment.md)对齐:Docker 改用 GHCR 预构建镜像,Kubernetes 改用 Helm chart,并引用 GUIDE.md
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agfs): import AGFSBindingClient error不阻塞http client使用 (#324)
* feat: Enhance add-resource functionality in cli and add unit tests (#323)
* tests(parsers): add unit tests for office extensions within add_resource directory
* feat: enhance add-resource functionality with new options
- Updated CLI commands to support additional parameters: --ignore-dirs, --include, --exclude, and --no-directly-upload-media.
- Modified resource processing to handle new parameters for directory scanning and file inclusion/exclusion.
- Improved README documentation for CLI usage and examples.
This update allows for more flexible resource management and better control over file uploads.
* feat(cli): enhance add-resource command with new options
- Added support for additional parameters: --no-strict, --ignore-dirs, --include, --exclude, and --no-directly-upload-media.
- Updated the handling of resource addition to accommodate new options for improved directory scanning and file management.
- Enhanced README documentation with examples for the new functionality.
This update provides users with greater flexibility in managing resources.
* chore(cli): remove unused cargo feature for edition 2024 in Cargo.toml
* chore(pyproject): update tag_regex in setuptools_scm configuration for version parsing
* feat: expose session(must_exist) and session_exists() on public API (#321)
The internal Session.exists() and SessionService.get() (added in #235)
provide session existence checks at the service layer, but these are
not accessible through the public client API (BaseClient and its
implementations).
This commit exposes two opt-in mechanisms at the public API level:
1. session(must_exist=True) — raises NotFoundError if the session
directory does not exist. Default must_exist=False preserves full
backward compatibility.
2. session_exists(session_id) — async convenience method returning
True/False without loading the full session.
Both delegate to the existing Session.exists() internally. No changes
to session.py or session_service.py — this is purely a public API
surface addition.
Files changed (7):
- base.py: updated abstract interface
- local.py: must_exist via Session.exists(), session_exists() delegate
- http.py: must_exist via get_session() HTTP call, session_exists()
- sync_http.py: pass-through
- async_client.py: session(must_exist) + session_exists()
- sync_client.py: pass-through
- test_session_lifecycle.py: 6 new tests
* feat: wrapper ov command (#325)
Co-authored-by: openviking <openviking@example.com>
* Feat/vectordb interface refactor (#327)
* refactor: route vector access through semantic gateway
* refactor vector storage to collection-bound drivers
* refactor(storage): collapse gateway/interface into single-collection backend
* refactor vectordb backend to single-collection adapter model
* chore: align naming with vikingdb and rename session test
* fix
* docs: add guide for integrating third-party vectordb adapters
* vikingbot
* vikingbot
* vikingbot
* read
* vikingbot
* vikingbot
* 更新readme
* vikingbot
* vikingbot
* vikingbot
* 格式化 + 生成图片工具增加开关 直接发给用户(默认开)
* upodate
---------
Co-authored-by: chenjunwen <chenjunwen@bytedance.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: fujiajie.1030 <fujiajie.1030@bytedance.com>
Co-authored-by: SeanZ <zhangxu.shon@bytedance.com>
Co-authored-by: chuanbao666 <sunchuanbao@bytedance.com>
Co-authored-by: Hon Jia Xuan <hjaxuan@gmail.com>
Co-authored-by: ponsde <2126824294@qq.com>
Co-authored-by: r266-tech <r2668940489@gmail.com>
Co-authored-by: r266-tech <r266-tech@users.noreply.github.com>
Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Eric Shaw <shaoeric@foxmail.com>
Co-authored-by: MaojiaSheng <shengmaojia@bytedance.com>
Co-authored-by: openviking <openviking@example.com>
Co-authored-by: kkkwjx <zhoujiahui.01@bytedance.com>1 parent e418870 commit 006a06f
File tree
156 files changed
+29865
-30
lines changed- bot
- bridge
- src
- deploy
- docker
- ecs
- vke
- k8s
- license
- scripts
- vikingbot
- agent
- tools
- websearch
- bus
- channels
- cli
- config
- console
- cron
- heartbeat
- hooks
- builtins
- openviking_mount
- providers
- sandbox
- backends
- session
- tui
- styles
- utils
- workspace
- memory
- skills
- cron
- github-proxy
- scripts
- github
- opencode
- skill-creator
- summarize
- tmux
- scripts
- weather
- openviking
- message
- prompts/templates/compression
- session
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
156 files changed
+29865
-30
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
0 commit comments