Open
Conversation
* refactor: migrate RAG knowledge services to a plugin-oriented host service architecture. * feat(rag): phase 2 core refactor with RPC Action handlers * feat: 为 RAG 插件添加知识库创建和删除事件通知,并优化了 RAG 动作的参数传递和枚举使用。 * feat: 统一知识库管理为RAG引擎,支持动态配置并移除旧的外部知识库组件。 * refactor(rag): remove plugin_adapter, inline logic into RuntimeKnowledgeBase BREAKING CHANGE: RAGPluginAdapter has been removed. All plugin communication is now handled directly by RuntimeKnowledgeBase. Architecture change: - Before: RuntimeKnowledgeBase → RAGPluginAdapter → plugin_connector - After: RuntimeKnowledgeBase → plugin_connector (direct) Changes to kbmgr.py (RuntimeKnowledgeBase): - Remove RAGPluginAdapter import and usage - Inline plugin communication methods: - _on_kb_create(): Notify plugin when KB is created - _on_kb_delete(): Notify plugin when KB is deleted - _ingest_document(): Call plugin for document ingestion - _retrieve(): Call plugin for retrieval - _delete_document(): Call plugin to delete document - Simplify dispose(): Only notify plugin, no built-in VDB assumption Changes to base.py (KnowledgeBaseInterface): - Remove get_type() abstract method (outdated internal/external concept) - Add get_rag_engine_plugin_id() abstract method Changes to localagent.py: - Remove get_type() call - Simplify top_k retrieval from KB entity Deleted files: - pkg/rag/knowledge/plugin_adapter.py Benefits: - Reduced abstraction layer, simpler code - Plugin communication logic centralized in RuntimeKnowledgeBase - Easier to understand and maintain 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(api): remove ExternalKnowledgeBase infrastructure BREAKING CHANGE: ExternalKnowledgeBase has been completely removed. All knowledge bases are now unified under the single KnowledgeBase model, differentiated by their rag_engine_plugin_id. Deleted files: - pkg/api/http/controller/groups/knowledge/external.py (ExternalKBController with /external-bases routes) - pkg/api/http/service/external_kb.py (ExternalKnowledgeBaseService) - pkg/rag/knowledge/external.py (ExternalKnowledgeBase implementation) Modified files: - pkg/entity/persistence/rag.py: Remove ExternalKnowledgeBase SQLAlchemy table definition - pkg/core/app.py: Remove external_kb_service attribute from LangBotApplication - pkg/core/stages/build_app.py: Remove external_kb_service initialization Migration notes: - Existing external knowledge base data should be migrated manually - API consumers should use /api/v1/knowledge/bases for all KB operations - Use /api/v1/knowledge/engines to discover available RAG engines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(plugin): remove list_knowledge_retrievers from connector Remove deprecated list_knowledge_retrievers functionality from the plugin communication layer. This aligns with the SDK change that removed the LIST_KNOWLEDGE_RETRIEVERS action. Changes: - connector.py: Remove list_knowledge_retrievers() method - handler.py: Remove list_knowledge_retrievers() handler The functionality is replaced by the new /api/v1/knowledge/engines endpoint which lists available RAGEngine components with their capabilities and configuration schemas. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(service): update knowledge service with capability-based checks Replace type-based checks with capability-based checks for file operations, aligning with the unified knowledge base architecture. Changes to knowledge.py: - store_file(): Replace get_type() check with doc_ingestion capability check - delete_file(): Replace get_type() check with doc_ingestion capability check - list_rag_engines(): Remove list_knowledge_retrievers call, simplify to only list RAGEngine components (KnowledgeRetriever type removed) Changes to pipelines.py: - Minor cleanup related to knowledge base references The capability-based approach allows RAG engines to declare their supported features (doc_ingestion, chunking_config, rerank, hybrid_search) and the system responds accordingly, rather than hardcoding behavior based on internal/external type distinction. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(web): unify knowledge base UI, remove external KB components BREAKING CHANGE: The internal/external knowledge base distinction has been removed from the frontend. All knowledge bases are now displayed in a unified list, differentiated by their RAG engine. Changes to page.tsx: - Remove Tab component (内置/外置 tabs) - Remove selectedKbType state - Unified knowledge base list display - Single "Create Knowledge Base" button for all types Changes to KBDetailDialog.tsx: - Remove kbType prop - Simplify dialog logic for unified KB handling - Documents menu item conditionally shown based on doc_ingestion capability Changes to KBForm.tsx: - Remove retriever type handling code - Simplify form for unified KB creation - Dynamic form rendering based on RAG engine's creation_schema Changes to KBCardVO.ts: - Remove 'type' field from KBCardVO interface Changes to BackendClient.ts: - Remove all external KB related methods: - getExternalKnowledgeBases() - getExternalKnowledgeBase() - createExternalKnowledgeBase() - updateExternalKnowledgeBase() - deleteExternalKnowledgeBase() - retrieveFromExternalKnowledgeBase() Changes to api/index.ts: - Remove ExternalKnowledgeBase interface definition UI/UX improvements: - Users no longer need to understand internal vs external distinction - RAG engine selection is now the primary differentiator - Documents panel visibility is capability-driven (doc_ingestion) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(plugin): code review improvements for RAG handlers - Unify embed_model field naming to embedding_model_uuid only - Add structured error responses with error_type for RAG actions - Fix file_size and mime_type detection in _store_file_task - Improve error handling with detailed error context (error_type, original_error) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(rag): refactor KB dynamic form and vector manager - Frontend: Refactor Knowledge Base form using DynamicForm components. - Frontend: Remove obsolete jsonSchemaConverter utility. - Backend: Update VectorManager and PluginHandler to support new RAG architecture. - Chore: Update dependencies in pyproject.toml. * fix: code review fixes for RAG refactor - Remove DEBUG stderr outputs in handler.py - Move repeated `import json` to file top - Add warning log for unimplemented delete_by_filter 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(rag): consolidate valid_fields into entity constants Define MUTABLE_FIELDS, CREATE_FIELDS, ALL_DB_FIELDS as class constants in KnowledgeBase entity to eliminate duplication. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: 将知识库获取和RAG引擎信息丰富逻辑移至知识库管理器。 * refactor(rag): introduce RAGRuntimeService and clean up plugin handler - Create RAGRuntimeService to encapsulate RAG capability implementation (Embedding, VectorOps). - Refactor PluginHandler to delegate RAG actions to RAGRuntimeService. - Move KnowledgeService enrichment and creation logic to RAGManager. - Register RAGRuntimeService in Application and BuildAppStage. - Clean up legacy code in KnowledgeService. * refactor(rag): standardize logger and fix type hints - Use self.ap.logger consistently in kbmgr.py and runtime.py, removing module-level loggers. - Fix type hints for retrieve_knowledge in handler.py and connector.py to match implementation returning dict. * refactor: 将引擎徽章的样式从 Tailwind CSS 类迁移到 CSS 模块。 * fix(web): resolve React rendering errors in plugins page - Fix missing key prop in PluginComponentList by using ternary instead of Fragment - Fix RAGEngine.name type to I18nObject and use extractI18nObject() for rendering - Preserves multi-language support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(rag): update runtime service and web components * refactor: 优化知识库设置结构并增强前端距离显示健壮性。 * fix: 处理前端距离显示中的空值。 * fix(rag): document retrieve ui and kbmgr top_k validation * 更新 uv.lock 中的 PyPI 镜像源为官方地址。 * fix: address code review issues for RAG engine plugin architecture P0 fixes: - Fix ALL_DB_FIELDS missing collection_id and emoji fields - Move rag_engine_plugin_id to CREATE_FIELDS (immutable after creation) - Fix creation_settings mutable default value (dict -> None) - Rename vector delete method to delete_by_file_id for correct semantics - Fix delete_by_filter to raise NotImplementedError instead of silent no-op - Add database migration script (dbm019) for new columns and table cleanup P1 fixes: - Clean up design-hesitation comments in connector.py - Add _parse_plugin_id() with format validation for all RAG methods - Make _retrieve() raise exceptions instead of silently returning empty results - Extract _make_rag_error_response() helper for clean error formatting - Remove unused imports from handler.py P2 fixes: - Fix runtime.py indentation inconsistencies - Simplify get_file_stream to use storage abstraction uniformly - Reduce redundant DB queries in knowledge service (extract _check_doc_capability) - Fix engines.py URL encoding: use <path:plugin_id> instead of __ replacement - Add read-only mode for engine settings in KBForm edit mode - Simplify page.tsx handleKBCardClick to pass only kbId string Co-authored-by: Cursor <cursoragent@cursor.com> * fix: address code review findings for RAG plugin architecture - Frontend: add retrieval_settings param to retrieveKnowledgeBase API call - Backend: return {uuid} from PUT knowledge base to match frontend expectation - Backend: validate query is non-empty in retrieve endpoint (400 on empty) - Backend: rename vector_delete ids→file_ids for semantic clarity, keep backward compat by accepting both 'file_ids' and 'ids' in RPC handler - Backend: ensure rag_engine.name fallback is always I18nObject-compatible dict, preventing frontend extractI18nObject from receiving plain strings - Migration: fix misleading docstring about external_kb data migration Co-authored-by: Cursor <cursoragent@cursor.com> * Update langbot-plugin version to 0.2.6 * chore: update required database version from 18 to 19 * refactor: remove unused polymorphic component framework * chore: fix lint and format issues for python and frontend * fix(plugin): remove legacy `ids` fallback in rag_vector_delete handler SDK now sends `file_ids` directly, the `ids` backward-compat fallback is no longer needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(rag): deep review fixes for critical bugs, security and quality Critical: - Fix StorageMgr.load() -> storage_provider.load() (C1, AttributeError) - Update required_database_version 18 -> 19 (C2, migration never runs) Security: - Add path traversal validation in get_file_stream (C11) - Add vectors/ids/metadata length validation in rag_vector_upsert (C12) Logic fixes: - Legacy KBs: set capabilities to [] instead of ['doc_ingestion'] (C4) - Fix store_file return type int -> str (C5) - Fix retrieve_knowledge return [] -> {'results': []} when disabled (C6) - Re-raise exception in _on_kb_create instead of silently swallowing (C7) - Log warning when KB not found in memory during delete (C8) API fixes: - Catch ValueError as 400 in create_knowledge_base endpoint (C15) - Validate plugin_id format in engines endpoints (C16) Quality: - Remove dead if/else in migration with identical branches (C17) - Fix variable shadowing: rag_context -> rag_context_text (C18) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove unused os import to fix ruff lint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(plugin): remove PolymorphicComponent sync from LangBot side Remove sync_polymorphic_component_instances() from connector and handler, and the post-connection sync call in initialize(). This dead code synced an always-empty list of polymorphic instances that were never created. Companion change to langbot-plugin-sdk PolymorphicComponent removal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(rag): fix vector_delete count bug and remove vestigial instance_id parameter 1. vector_delete: assign return value from delete_by_filter to count instead of silently returning 0 for filter-based deletion. 2. Remove instance_id parameter from the entire retrieve_knowledge call chain (kbmgr → connector → handler → runtime). This parameter was a remnant of the PolymorphicComponent mechanism and is no longer used — RAGEngine operates as a stateless singleton. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(web): 支持 creation_schema 字段级别的 editable 属性控制编辑模式可修改性 - IDynamicFormItemSchema 添加 editable 可选属性 - DynamicFormItemConfig 透传 editable 属性 - DynamicFormComponent 接收 isEditing prop,按字段 editable 值控制禁用 - KBForm 解析 editable 并传递 isEditing 给动态表单组件 - editable 未指定时默认可编辑,editable: false 时编辑模式下禁用该字段 * feat(storage): 添加 size() 抽象方法及 LocalStorage/S3 实现 支持获取存储对象大小,S3 使用 head_object 避免下载整个文件 * fix(migration): 删除 external_knowledge_bases 表前记录日志警告 - 迁移时如果表中存在数据,先 warning 日志记录避免无感数据丢失 - 添加 chunk 清理注释说明:仅对旧版非插件架构 KB 有效 * fix(web): 修复检索结果长文本撑大容器导致查询按钮不可见 KBDetailDialog 的 main 容器添加 min-w-0 overflow-x-hidden, 限制 flex-1 子容器宽度,防止 Dify RAG 长文本撑出 Dialog 边界 * fix(rag): address code review issues for plugin architecture PR - Fix SQL injection in migration helpers by using bind parameters - Move numpy import to module level in vector/mgr.py - Improve path traversal validation using posixpath.normpath - Add call_rag_retrieve to connector, eliminating duplicate plugin_id parsing in kbmgr.py _retrieve - Normalize typing style to modern dict/list/None syntax Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(web): fix prettier formatting errors Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(rag): update embedding handling in RuntimeConnectionHandler - Renamed RAG_EMBED_DOCUMENTS and RAG_EMBED_QUERY actions to INVOKE_EMBEDDING for clarity. - Removed embed_documents and embed_query methods from RuntimeEmbeddingModel and RAGRuntimeService. - Integrated embedding model retrieval directly in the invoke_embedding method, improving error handling for missing models. - Updated the embedding invocation logic to streamline the process and enhance error reporting. * refactor(web): replace KnowledgeRetriever with RAGEngine across frontend and tests KnowledgeRetriever component type has been removed in favor of the new RAGEngine architecture. Update all remaining references in i18n locales, plugin component icon mappings, marketplace filter, and unit tests. Addresses reviewer notes from RockChinQ on PR #1967. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(rag): address critical bugs found in deep review - Fix path traversal bypass in runtime.py (check all path components for '..') - Use normalized path for file loading instead of raw user input - Change knowledge_bases from list to dict for O(1) lookup and race safety - Add rollback on KB creation failure (clean up DB + runtime on plugin error) - Add null check after KB update in knowledge service - Fix file extension parsing to use os.path.splitext instead of split('.') (handles multi-dot filenames like 'report.v2.pdf' correctly) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(rag): address remaining review issues across frontend and backend Frontend: - Fix KB delete: use async/await with error handling instead of fire-and-forget - Fix capabilities null check: add optional chaining to prevent crash - Add toast.error on KB info load failure instead of silent console.error - Replace hard-coded Chinese validation message with i18n key - Replace hard-coded English error messages in DynamicFormItemComponent with i18n - Optimize document polling: stop when all documents reach terminal state - Add i18n keys (fieldRequired, loadKnowledgeBaseFailed, deleteKnowledgeBaseFailed, getKnowledgeBaseListError) to all 4 locales Backend: - Fix KB delete atomicity: delete from DB first, then notify plugin - Add RAG engine plugin existence validation before creating KB Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(rag): fix ruff formatting in kbmgr.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Junyan Qin <rockchinq@gmail.com>
chore: correct sdk version to 0.3.0a1
Remove redundant `chunking_strategy` field and rename `custom_settings` to `creation_settings` to match the updated SDK entity definitions (langbot-plugin-sdk#36). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le creation_settings fields Remove embedding_model_uuid from MUTABLE_FIELDS to prevent post-creation modification via API. Add backend validation for creation_settings to preserve fields marked editable:false in the plugin's creation schema. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RockChinQ
reviewed
Feb 23, 2026
Comment on lines
13
to
14
| embedding_model_uuid = sqlalchemy.Column(sqlalchemy.String, default='') | ||
| top_k = sqlalchemy.Column(sqlalchemy.Integer, default=5) |
Member
There was a problem hiding this comment.
embedding model应该是改到动态表单里了;top_k你觉得还有必要单独出来吗?还是写到retrieval settings里?
Collaborator
Author
There was a problem hiding this comment.
已完成重构:
embedding_model_uuid和top_k已从独立列中移除embedding_model_uuid现在由插件通过creation_schema定义,存入creation_settings(创建后不可变)top_k现在由插件通过retrieval_schema定义,存入retrieval_settings(随时可改)- 移除了逐字段
editable概念,改为按 settings 分区控制可变性:creation_settings整体不可变,retrieval_settings整体可变 - SDK 侧同步清理了
RetrievalContext.top_k冗余字段,统一从retrieval_settings传递
Collaborator
Author
There was a problem hiding this comment.
已添加 retrieval_settings 列到 knowledge_bases 表,并加入 MUTABLE_FIELDS。现在 DB entity 中有 creation_settings(不可变)和 retrieval_settings(可变)两个 JSON 列,插件通过 creation_schema / retrieval_schema 分别定义对应字段。
…table retrieval_settings - Remove standalone embedding_model_uuid and top_k columns from KB entity - Add retrieval_settings column; update MUTABLE_FIELDS/CREATE_FIELDS accordingly - Merge migration logic into dbm019 (add retrieval_settings, migrate top_k and embedding_model_uuid into JSON settings, drop old columns on PostgreSQL) - Remove _filter_creation_settings and per-field editable concept - Frontend: creation_settings fields are all disabled when editing, retrieval_settings fields are always editable via a second DynamicFormComponent - Remove editable from IDynamicFormItemSchema, DynamicFormItemConfig - Clean up KBCardVO, KnowledgeBase API type, and localagent runner Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…_delete (#1997) Add functional metadata filter support across all 5 VDB backends using Chroma-style where syntax as the canonical format. Previously the filters parameter existed throughout the stack but was entirely ignored. - Add filter_utils.py with normalize_filter() and strip_unsupported_fields() - Implement filter in search() and add delete_by_filter() for all backends: Chroma/SeekDB (native passthrough), Qdrant (translated to models.Filter), Milvus (translated to expr string), pgvector (translated to SQLAlchemy conditions) - Milvus/pgvector limited to {text, file_id, chunk_uuid}; other fields logged and ignored - Replace delete_by_filter() NotImplementedError with backend delegation in mgr.py - Populate retrieval_context['filters'] from settings in kbmgr._retrieve() - Pass search_type/query_text/documents through handler and runtime service Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove numpy array conversion for query vectors; all VDB backends accept list[float] directly - Remove redundant get_or_create_collection call from upsert; backends handle collection creation internally in add_embeddings - Fix SeekDB to raise ValueError when vector dimension is unknown instead of defaulting to 384 - Use hybrid_search() for full-text and hybrid search modes in SeekDB, since pyseekdb's query() always requires embeddings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document text containing apostrophes (e.g. "don't", "it's") causes SQL syntax errors in OceanBase because single quotes were not in the escape table. Add single-quote escaping and apply the escape table to the documents parameter in add_embeddings(), not just metadata. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change single quote escaping from MySQL-style \' to standard SQL '' (doubled quote). The backslash escape is not recognized by OceanBase in NO_BACKSLASH_ESCAPES mode, causing SQL syntax errors when metadata text contains apostrophes (e.g. O'Shea in academic citations). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
retrieval_settings was not being passed from the service layer to RAGManager.create_knowledge_base(), causing retrieval schema fields (e.g. query_rewrite) to be lost on initial KB creation. They only took effect after a subsequent edit/update. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support conditional field visibility in plugin-defined forms via show_if rules (eq, neq, in operators). Fields can depend on values from the same form or cross-reference between creation and retrieval settings via externalDependentValues. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…stream Use send_file() instead of base64 encoding for returning file content in the GET_RAG_FILE_STREAM handler, avoiding memory issues with large files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ad UI (#2000) * feat(parser): add parser plugin integration and capability-aware upload UI Backend: add parser plugin API endpoints (list/invoke), connector and handler support for parser actions, and KB manager passthrough. Frontend: thread ragEngineCapabilities prop to FileUploadZone and use doc_parsing capability to conditionally show the RAG engine option in the parser selector. When no parser is available, show a warning prompting users to install a parser plugin. Update i18n: rename builtInParser to "Provided by RAG engine" and add noParserAvailable warning message in all 4 locales. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(parser): replace base64 with chunked file transfer and remove stale cache - Remove @alru_cache from list_parsers() and list_rag_engines() - Replace inline base64 file content with send_file/read_local_file chunked transfer pattern in parse_document and invoke_parser flows - Remove unused base64 import from kbmgr.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v4.9.0 Release Branch
RAG Engine Plugin Architecture (#1933)
将 RAG 能力从 LangBot 内置实现重构为插件化架构,主要变更:
rag_engine_plugin_id区分 RAG 引擎RAGEngine插件组件类型,第三方插件可提供自定义 RAG 实现creation_schema动态渲染external_knowledge_bases表,新增相关字段Other
langbot-pluginto 0.3.0 (chore: bump langbot-plugin to 0.3.0 #1992)