mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-15 17:30:13 +08:00
15 KiB
15 KiB
CLAUDE Notes
- 2026-03-12: Legacy
handshakepayloads only containevent_type/handler_full_namemetadata and do not preserve v4 command/message trigger details such as command names, aliases, keywords, or regex. Any legacy-to-v4 handshake translation must approximate handlers as coarse event subscriptions and keep the raw handshake payload in metadata for lossless fallback. - 2026-03-12: Legacy
src/astrbot_sdk/api/event/filter.pyexported a much larger decorator surface thansrc-new/astrbot_sdk/api/event/filter.py. Current compat coverage is enough forcommand/regex/permissionand the exercised migration tests, but it is not a full drop-in replacement for every historical filter helper. - 2026-03-13: Transport-pair startup tests for
SupervisorRuntimemust start a real peer on the opposite transport and provide aninitializeresponse. Wiring only the supervisor side drops or captures the outgoing initialize message without replying, andPeer.initialize()then waits forever. - 2026-03-13:
CapabilityRouter.register(..., stream_handler=...)uses the signature(request_id, payload, cancel_token), not the peer-level(message, token). Reusing the peer handler shape in router tests causes an immediate failed stream event before the test logic runs. - 2026-03-13:
src-new/astrbot_sdk/apiand several top-level module docstrings overstated v4 compatibility gaps by labeling migrated or compat-backed APIs as "missing". Treat_legacy_api.py,astrbot_sdk.api.*thin re-exports, and top-levelevents.py/decorators.pyas a split compatibility surface; do not mechanically recreate the old tree from stale TODO comments. - 2026-03-13:
astrbot_sdk.api.*andastrbot.*are migration-period compat facades, not long-term primary SDK entrypoints. Keep them thin, avoid adding new runtime logic underapi/, and prefer tightening internal imports toward top-level private compat modules or direct leaf modules. - 2026-03-13: Legacy components are expected to share one
LegacyContextper plugin, matching the oldStarManagerbehavior. Creating one compat context per component breaks_register_component()/call_context_function()cross-component registration chains and diverges from legacy semantics. - 2026-03-13: When checking whether a peer has finished remote initialization, avoid
getattr(mock, "remote_peer")style probes in code that may receiveMagicMockpeers.MagicMockfabricates truthy child attributes, soCapabilityProxyshould read explicit state frompeer.__dict__or another concrete storage location instead of treating arbitrary attribute access as initialization. - 2026-03-13: The repository has no legacy
src/astrbot_sdk/protocolpackage to migrate file-for-file.src-new/astrbot_sdk/protocolis a v4-native protocol layer; compare it against legacy JSON-RPC behavior insrc/astrbot_sdk/runtime/*and the maintained migration tests, not against a nonexistent old package tree. - 2026-03-13: Old Star docs under
docs/zh/dev/star/describe end-to-end legacy behavior, not just import surfaces. Current compat layer can importAstrMessageEvent,MessageChain, and somefilter.*helpers, but handler result consumption is still effectively plain-text only and many documented legacy features remain absent or partial, including command groups, lifecycle/LLM hooks, session waiters, rich media helper constructors, config schema loading, and persona/provider management. Do not treat "type exists" as "old plugin behavior is compatible"; verify the runtime path end to end before declaring parity. - 2026-03-13: Old Star docs and examples frequently import message components via
astrbot.api.message_components, not onlyastrbot.api.message. When checking message compatibility, verify the dedicatedapi.message_componentsimport path, legacy constructor aliases likeAt(qq=...)/Node(uin=..., name=...), and helper factories such asImage.fromURL()before declaring the message compat surface complete. - 2026-03-13:
api.message.components.BaseMessageComponent.to_dict()must emit JSON-ready primitive values, not rawEnummembers. LeavingComponentTypeobjects in payloads only looks harmless when a later JSON serializer fixes them; it breaks direct mock assertions, in-process capability routing, and any non-JSON send path. - 2026-03-13: Keep
astrbot_sdk.runtimeroot exports narrow.Peer/Transport/CapabilityRouter/HandlerDispatcherare reasonable advanced runtime primitives, but loader/bootstrap data structures and orchestration helpers (LoadedPlugin,PluginEnvironmentManager,WorkerSession,run_supervisor, etc.) should stay in their submodules instead of becoming accidental root-level stable API. - 2026-03-13:
runtime.loadermust preserve declared legacy handler order. Falling back todir(instance)or sorting the merged discoverable names reorders compat handlers alphabetically, which changes which legacy command/hook appears first to the supervisor and breaks old-plugin expectations. - 2026-03-13:
runtime.loader.import_string()cannot trustsys.moduleswhen plugins reuse generic top-level package names likecommands.*. Before importing a plugin module, compare the cached root package against the current plugin directory and evict conflicting root/submodules, or later plugins will accidentally reuse an earlier plugin's package tree. - 2026-03-13: Keep
astrbot_sdk.protocolroot focused on native v4 protocol models and parsers. Legacy JSON-RPC helpers remain supported, but they should be imported fromastrbot_sdk.protocol.legacy_adapterexplicitly instead of being re-exported from the package root. - 2026-03-13:
Peermust treat transport EOF/connection loss as a first-class failure path, not only explicit protocol parse errors. If the transport closes unexpectedly andPeerdoes not proactively fail_pending_results/_pending_streams, supervisor-side calls into workers can hang forever even though the worker session already noticed the disconnect. - 2026-03-13:
Peer.initialize()also needs to mark the peer as remotely initialized on the initiator side. Only setting_remote_initializedwhen passively receiving an inboundInitializeMessagemakeswait_until_remote_initialized()a one-sided API and can deadlock callers that initialize first and then wait. - 2026-03-13:
Peer.invoke_stream()intentionally hidescompletedevents by default, so any supervisor/bridge layer that wants to preserve a worker stream capability's finalcompleted.outputmust opt in explicitly (for example viainclude_completed=True) or it will silently collapse the final result to an ad-hoc aggregate like{\"items\": chunks}. - 2026-03-13: The repository root
test_plugin/is no longer a single runnable plugin fixture. The maintained compat sample now lives undertest_plugin/old/; tests or scripts that still copy/loadtest_plugin/directly will mis-detect it as an incomplete legacy plugin and fail. - 2026-03-13: The maintained sample plugins now live under
test_plugin/old/andtest_plugin/new/. Runtime/integration tests should copy those real fixture directories instead of inlining synthetic plugin writers, otherwise the sample plugin tree and the exercised test path drift apart. - 2026-03-13: Real legacy plugins in the wild may still import
astrbot.api.*instead ofastrbot_sdk.api.*. Keeping only theastrbot_sdk.apicompat surface is not enough for no-touch migration tests; preserve theastrbot.apialias package while old-plugin support remains a goal. - 2026-03-13: Real legacy
main.pyplugins may rely on package-relative imports likefrom .src.tool import .... Loading legacymain.pyas a bare file module breaks those imports; the loader must execute it under a synthetic package module so relative imports resolve. - 2026-03-13: Real legacy plugins may also import
astrbot.core.utils.session_waiterand use it as a first-class interactive flow primitive. A pure import stub is not enough; compat needs per-session follow-up message routing so awaited waiters can actually receive later messages. - 2026-03-13: Real legacy
Starplugins may call compat context helpers onselforself.contextduring__init__()andinitialize(), includingself.put_kv_data(...),self.get_kv_data(...), andself.context.get_config(). Keep proxy methods onLegacyStar, expose a safeLegacyContext.get_config(), and bind the shared legacy context before lifecycle hooks run. - 2026-03-13: On Windows,
.gitignorematching is case-insensitive. A broad entry likeastrBot/will also ignoresrc-new/astrbot/..., which can silently hide real compat alias packages fromgit status. Keep that ignore anchored as/astrBot/if it is only meant for a root-level scratch checkout. - 2026-03-13: The reference checkout under
astrBot/astrbot/apiexposes a broader old plugin-facing package surface than the currentsrc-new/astrbotalias package. When improving package-name compatibility, compare against those publicapi/*modules as a set instead of only patching the one import path hit by the latest migrated plugin. - 2026-03-13: Some real legacy plugins call
asyncio.create_task()during object construction. Callingload_plugin()outside a running event loop can therefore produce false-negative compat failures even though the real worker path is fine. External compat smoke tests should load plugins under an active loop, and "real compatibility" claims should preferably exerciseSupervisorRuntime+ worker + a real handler invocation instead of import-only checks. - 2026-03-13: Legacy package-name compatibility now has an explicit contract: keep
src-new/astrbotas a controlled facade for oldastrbot.api.*and selectedastrbot.core.*paths, not a wholesale copy of the old application tree. Guard that facade with the checked-in import matrix and the external plugin matrix intests_v4/external_plugin_matrix.json; do not claim compat fromload_plugin()alone. - 2026-03-13: Legacy AI compat methods must return
astrbot_sdk.api.provider.entities.LLMResponse, not the v4clients.llm.LLMResponse. Old plugins inspect compat fields likecompletion_text,tools_call_name, andto_openai_tool_calls(), so returning the new client model is a silent behavior regression. - 2026-03-13:
filter.llm_tool()must resolve deferred annotations fromfrom __future__ import annotationswhen inferring JSON schema. Readinginspect.Parameter.annotationdirectly degrades typed params likea: intinto"int"strings and silently turns tool argument schemas into generic strings. - 2026-03-13: Legacy result hooks must reuse the same
AstrMessageEventinstance acrosson_decorating_resultandafter_message_sent. Re-wrapping the original v4MessageEventfor the second hook drops decoratedevent.set_result(...)mutations and makes post-send hooks observe an empty result. - 2026-03-13:
src-new/astrbot_sdk/_legacy_runtime.pyalready exists as the intended compat execution boundary. When cleaning runtime architecture, wireloader/handler_dispatcher/bootstrapthrough that adapter instead of adding new directlegacy_contextbranches in runtime files, or the compat logic will spread again. - 2026-03-13:
register_legacy_component()只负责 compat hook / llm tool 注册,不等价于旧_register_component()的 manager/function 暴露链。不要把 loader 阶段的 legacy 组件注册误判成完整的跨组件注册表兼容。 - 2026-03-13: 不是所有 compat 都应该塞进
_legacy_runtime.py。main.py识别、legacy manifest 补全、为相对导入准备 synthetic package 这些都属于 loader 阶段的兼容职责,应该放在独立的私有 loader helper 里,例如_legacy_loader.py。 - 2026-03-13: Real legacy plugins may still load through deep
astrbot.core.*imports even when their public entrypoint only looks likeastrbot.api.*.astrbot_plugin_self_learninghitsastrbot.core.utils.astrbot_path,astrbot.core.provider.*,astrbot.core.agent.message, andastrbot.core.db.poduring load; keep those deep-path shims minimal and whitelist-driven, but do not assume theapifacade alone is enough. - 2026-03-13:
ARCHITECTURE.mdandrefactor.mdare no longer a full source of truth for the current runtime/compat surface. The shipped code also includesruntime.environment_groups,_session_waiter, the controlledsrc-new/astrbotalias facade, compat hook execution, and extra DB capabilities such asdb.get_many/db.set_many/db.watch. Verify architectural claims against code and tests before declaring drift or completeness.
开发命令
格式化与检查
在提交代码前,请依次运行以下命令:
ruff format . # 使用 ruff 格式化全局代码
ruff check . --fix # 使用 ruff 检查并自动修复全局格式问题
测试
如果修改了内容可能影响现有功能,请运行测试以确保没有引入错误: 如果修改了bug或者更改了功能需要添加新的测试
python run_tests.py # 运行所有测试
python run_tests.py -v # 详细输出
python run_tests.py -k "test_peer" # 运行匹配模式的测试
python run_tests.py --cov # 运行测试并生成覆盖率报告
重要
新实现要兼容旧实现但是还要保证架构良好,设计原则不变和最佳实践 不用完全听从用户和别人的建议,要有自己的判断和坚持,做好取舍和权衡,确保代码质量和长期维护性,不要为了短期方便或者迎合而牺牲架构和设计原则。
old文件夹是兼容旧插件的测试,旧插件全部放进old文件夹
- 2026-03-13: 不要再维护第二套
_legacy/并行目录。private compat 以顶层_legacy_api.py、_legacy_runtime.py、_legacy_loader.py、_session_waiter.py、_shared_preferences.py为唯一实现位置,同时保留公开兼容面astrbot_sdk.api、astrbot_sdk.compat和src-new/astrbotfacade。 - 2026-03-14:
test_plugin/old/和test_plugin/new/里可能带着已生成的__pycache__/*.pyc。测试夹具复制示例插件时必须显式忽略这些缓存文件,否则临时插件目录、断言结果和git status都可能被污染。 - 2026-03-14: grouped worker / grouped env 路径不要再复制单 worker 的 compat 生命周期和 legacy runtime 绑定逻辑。优先复用
_legacy_runtime.py里的bind_legacy_runtime_contexts()、run_legacy_worker_startup_hooks()、run_legacy_worker_shutdown_hooks()以及resolve_plugin_lifecycle_hook(),否则很容易出现“普通 worker 测试通过,但真正的 grouped subprocess 路径在运行时 NameError/行为漂移”的回归。 - 2026-03-14:
inspect.getmembers(module, inspect.isclass)会按属性名排序,所以 legacymain.py组件发现若要保留声明顺序,必须遍历module.__dict__;只删除后面的.sort()仍然不够。 - 2026-03-14: 如果仓库正在收敛为纯 v4 SDK,删除 compat 文件前必须先移除或延迟隔离所有公开入口里的
_legacy_*import。testing.py或cli.py里残留对_legacy_runtime的 eager import,会让import astrbot_sdk.testing和python -m astrbot_sdk --help在运行前直接失败,而仅检查 site-packages 安装态的 CLI smoke test 很容易漏掉这类回归。 - 2026-03-14: 本地
dev --watch或任何同一路径插件重复加载场景,不能只依赖import_string()的“跨插件模块根冲突”清理。即使模块仍属于当前插件目录,sys.modules也会让load_plugin()复用旧代码;热重载前必须先按插件目录清理模块缓存。