Repository Analysis

nonebot/nonebot2

跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python

5.4 Low AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of nonebot/nonebot2, a Python project with 7,620 GitHub stars. SynthScan v2.0 examined 77,842 lines of code across 535 source files, recording 336 pattern matches distributed across 9 syntactic categories. The overall adjusted score of 5.4 places this repository in the Low AI signal band.

The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).

5.4
Adjusted Score
5.4
Raw Score
100%
Time Factor
2026-07-14
Last Push
7.6K
Stars
Python
Language
77.8K
Lines of Code
535
Files
336
Pattern Hits
2026-07-14
Scan Date
0.04
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.

Severity Breakdown

Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.

CRITICAL 0HIGH 24MEDIUM 3LOW 309

Directory Score Breakdown

This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.

Pattern Findings

The scanner identified 336 distinct pattern matches across 9 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.

Unused Imports186 hits · 169 pts
SeverityFileLineSnippetContext
LOWtests/conftest.py25CODE
LOWtests/plugins/plugin/__init__.py1CODE
LOWtests/plugins/nested/plugins/nested_subplugin.py1CODE
LOWnonebot/params.py33CODE
LOWnonebot/params.py34CODE
LOWnonebot/params.py35CODE
LOWnonebot/params.py36CODE
LOWnonebot/params.py37CODE
LOWnonebot/params.py38CODE
LOWnonebot/params.py39CODE
LOWnonebot/params.py40CODE
LOWnonebot/params.py42CODE
LOWnonebot/params.py43CODE
LOWnonebot/params.py44CODE
LOWnonebot/params.py45CODE
LOWnonebot/params.py46CODE
LOWnonebot/compat.py89CODE
LOWnonebot/compat.py90CODE
LOWnonebot/compat.py100CODE
LOWnonebot/compat.py306CODE
LOWnonebot/matcher.py10CODE
LOWnonebot/matcher.py11CODE
LOWnonebot/matcher.py12CODE
LOWnonebot/matcher.py13CODE
LOWnonebot/matcher.py14CODE
LOWnonebot/matcher.py15CODE
LOWnonebot/matcher.py16CODE
LOWnonebot/matcher.py17CODE
LOWnonebot/matcher.py18CODE
LOWnonebot/matcher.py19CODE
LOWnonebot/permission.py15CODE
LOWnonebot/permission.py17CODE
LOWnonebot/log.py27CODE
LOWnonebot/log.py27CODE
LOWnonebot/__init__.py52CODE
LOWnonebot/__init__.py340CODE
LOWnonebot/__init__.py341CODE
LOWnonebot/__init__.py342CODE
LOWnonebot/__init__.py343CODE
LOWnonebot/__init__.py344CODE
LOWnonebot/__init__.py346CODE
LOWnonebot/__init__.py347CODE
LOWnonebot/__init__.py348CODE
LOWnonebot/__init__.py349CODE
LOWnonebot/__init__.py350CODE
LOWnonebot/__init__.py351CODE
LOWnonebot/__init__.py352CODE
LOWnonebot/__init__.py353CODE
LOWnonebot/__init__.py354CODE
LOWnonebot/__init__.py355CODE
LOWnonebot/__init__.py356CODE
LOWnonebot/__init__.py357CODE
LOWnonebot/__init__.py358CODE
LOWnonebot/__init__.py359CODE
LOWnonebot/__init__.py360CODE
LOWnonebot/__init__.py361CODE
LOWnonebot/__init__.py362CODE
LOWnonebot/__init__.py363CODE
LOWnonebot/__init__.py364CODE
LOWnonebot/__init__.py365CODE
126 more matches not shown…
Cross-File Repetition24 hits · 120 pts
SeverityFileLineSnippetContext
HIGHwebsite/docs/developer/adapter-writing.md0根据平台事件的特性,转换平台 payload 为具体 event event 模型继承自 pydantic.basemodel,具体请参考 pydantic 文档STRING
HIGH…sioned_docs/version-2.5.0/developer/adapter-writing.md0根据平台事件的特性,转换平台 payload 为具体 event event 模型继承自 pydantic.basemodel,具体请参考 pydantic 文档STRING
HIGH…sioned_docs/version-2.4.4/developer/adapter-writing.md0根据平台事件的特性,转换平台 payload 为具体 event event 模型继承自 pydantic.basemodel,具体请参考 pydantic 文档STRING
HIGH…sioned_docs/version-2.4.3/developer/adapter-writing.md0根据平台事件的特性,转换平台 payload 为具体 event event 模型继承自 pydantic.basemodel,具体请参考 pydantic 文档STRING
HIGHwebsite/docs/best-practice/database/developer/README.md0first revision 迁移 id: xxxxxxxxxxxx 父迁移: 创建时间: 2006-01-02 15:04:05.999999STRING
HIGH…rsion-2.5.0/best-practice/database/developer/README.md0first revision 迁移 id: xxxxxxxxxxxx 父迁移: 创建时间: 2006-01-02 15:04:05.999999STRING
HIGH…rsion-2.4.4/best-practice/database/developer/README.md0first revision 迁移 id: xxxxxxxxxxxx 父迁移: 创建时间: 2006-01-02 15:04:05.999999STRING
HIGH…rsion-2.4.3/best-practice/database/developer/README.md0first revision 迁移 id: xxxxxxxxxxxx 父迁移: 创建时间: 2006-01-02 15:04:05.999999STRING
HIGHwebsite/docs/best-practice/alconna/command.md0output 以下是建议的输入: * <abc: int> * --help * -h * -sct * --shortcut * foo * barSTRING
HIGH…ed_docs/version-2.5.0/best-practice/alconna/command.md0output 以下是建议的输入: * <abc: int> * --help * -h * -sct * --shortcut * foo * barSTRING
HIGH…ed_docs/version-2.4.4/best-practice/alconna/command.md0output 以下是建议的输入: * <abc: int> * --help * -h * -sct * --shortcut * foo * barSTRING
HIGH…ed_docs/version-2.4.3/best-practice/alconna/command.md0output 以下是建议的输入: * <abc: int> * --help * -h * -sct * --shortcut * foo * barSTRING
HIGHwebsite/docs/best-practice/alconna/uniseg/segment.md0- 点击 action 类型的按钮时会触发一个关于 按钮回调 事件,该事件的 button 资源会包含上述 id - 点击 link 类型的按钮时会打开一个链接或者小程序,该链接的地址为 `url` - 点击 input 类型的按钮时会在用STRING
HIGH…/version-2.5.0/best-practice/alconna/uniseg/segment.md0- 点击 action 类型的按钮时会触发一个关于 按钮回调 事件,该事件的 button 资源会包含上述 id - 点击 link 类型的按钮时会打开一个链接或者小程序,该链接的地址为 `url` - 点击 input 类型的按钮时会在用STRING
HIGH…/version-2.4.4/best-practice/alconna/uniseg/segment.md0- 点击 action 类型的按钮时会触发一个关于 按钮回调 事件,该事件的 button 资源会包含上述 id - 点击 link 类型的按钮时会打开一个链接或者小程序,该链接的地址为 `url` - 点击 input 类型的按钮时会在用STRING
HIGH…/version-2.4.3/best-practice/alconna/uniseg/segment.md0- 点击 action 类型的按钮时会触发一个关于 按钮回调 事件,该事件的 button 资源会包含上述 id - 点击 link 类型的按钮时会打开一个链接或者小程序,该链接的地址为 `url` - 点击 input 类型的按钮时会在用STRING
HIGHwebsite/docs/best-practice/alconna/uniseg/segment.md0仅建议使用下列值:primary, secondary, success, warning, danger, info, link, grey, blue 此处规定 `grey` 与 `secondary` 等同, `blue` 与 `prSTRING
HIGH…/version-2.5.0/best-practice/alconna/uniseg/segment.md0仅建议使用下列值:primary, secondary, success, warning, danger, info, link, grey, blue 此处规定 `grey` 与 `secondary` 等同, `blue` 与 `prSTRING
HIGH…/version-2.4.4/best-practice/alconna/uniseg/segment.md0仅建议使用下列值:primary, secondary, success, warning, danger, info, link, grey, blue 此处规定 `grey` 与 `secondary` 等同, `blue` 与 `prSTRING
HIGH…/version-2.4.3/best-practice/alconna/uniseg/segment.md0仅建议使用下列值:primary, secondary, success, warning, danger, info, link, grey, blue 此处规定 `grey` 与 `secondary` 等同, `blue` 与 `prSTRING
HIGHwebsite/docs/best-practice/alconna/uniseg/segment.md0- admin: 仅管理者可操作 - all: 所有人可操作 - list[at]: 指定用户/身份组可操作STRING
HIGH…/version-2.5.0/best-practice/alconna/uniseg/segment.md0- admin: 仅管理者可操作 - all: 所有人可操作 - list[at]: 指定用户/身份组可操作STRING
HIGH…/version-2.4.4/best-practice/alconna/uniseg/segment.md0- admin: 仅管理者可操作 - all: 所有人可操作 - list[at]: 指定用户/身份组可操作STRING
HIGH…/version-2.4.3/best-practice/alconna/uniseg/segment.md0- admin: 仅管理者可操作 - all: 所有人可操作 - list[at]: 指定用户/身份组可操作STRING
Hyper-Verbose Identifiers51 hits · 51 pts
SeverityFileLineSnippetContext
LOWtests/test_utils.py56def test_generic_check_issubclass():CODE
LOWtests/test_utils.py72def test_is_coroutine_callable():CODE
LOWtests/test_utils.py118def test_is_async_gen_callable():CODE
LOWtests/test_driver.py602async def test_aiohttp_stream_request_skip_empty_chunk() -> None:CODE
LOWtests/test_driver.py683async def test_aiohttp_websocket_close_frame(msg_type: str) -> None:CODE
LOWtests/test_driver.py710def test_timeout_unset_vs_none():CODE
LOWtests/test_driver.py838async def test_websocket_client_timeout(driver: Driver, server_url: URL):CODE
LOWtests/test_driver.py890async def test_websocket_client_ping_timeout(driver: Driver, server_url: URL):CODE
LOWtests/test_driver.py933async def test_websocket_client_ping_interval(driver: Driver, server_url: URL):CODE
LOWtests/test_broadcast.py61async def test_event_preprocessor_ignore(app: App, monkeypatch: pytest.MonkeyPatch):CODE
LOWtests/test_broadcast.py91async def test_event_preprocessor_exception(CODE
LOWtests/test_broadcast.py168async def test_event_postprocessor_exception(CODE
LOWtests/test_broadcast.py242async def test_run_preprocessor_ignore(app: App, monkeypatch: pytest.MonkeyPatch):CODE
LOWtests/test_broadcast.py272async def test_run_preprocessor_exception(CODE
LOWtests/test_broadcast.py354async def test_run_postprocessor_exception(CODE
LOWtests/test_config.py117def test_config_without_delimiter():CODE
LOWtests/test_adapters/test_adapter.py84 def _fake_setup_websocket_server(setup: WebSocketServerSetup):CODE
LOWtests/test_adapters/test_adapter.py190async def test_adapter_websocket_client(driver: Driver):CODE
LOWtests/test_adapters/test_bot.py28async def test_bot_calling_api_hook_simple(app: App):CODE
LOWtests/test_adapters/test_bot.py54async def test_bot_calling_api_hook_mock(app: App):CODE
LOWtests/test_adapters/test_bot.py81async def test_bot_calling_api_hook_multi_mock(app: App):CODE
LOWtests/test_adapters/test_bot.py121async def test_bot_called_api_hook_simple(app: App):CODE
LOWtests/test_adapters/test_bot.py153async def test_bot_called_api_hook_mock(app: App):CODE
LOWtests/test_adapters/test_bot.py197async def test_bot_called_api_hook_multi_mock(app: App):CODE
LOWtests/test_adapters/test_template.py36def test_rich_template_message():CODE
LOWtests/test_plugin/test_get.py24def test_get_plugin_by_module_name():CODE
LOWtests/test_plugin/test_get.py49def test_get_available_plugin():CODE
LOWtests/test_plugin/test_get.py73def test_get_plugin_config_with_env(monkeypatch: pytest.MonkeyPatch):CODE
LOWtests/test_plugin/test_load.py155def test_require_not_declared():CODE
LOWtests/test_plugin/test_load.py190def test_inherit_supported_adapters_not_found():CODE
LOWtests/test_plugin/test_load.py264def test_inherit_supported_adapters_combine(CODE
LOWtests/plugins/param/param_arg.py31async def annotated_arg_prompt_result(key: Annotated[Any, ArgPromptResult()]) -> Any:CODE
LOWtests/test_matcher/test_matcher.py234async def test_default_permission_updater(app: App):CODE
LOWtests/test_matcher/test_matcher.py255async def test_user_permission_updater(app: App):CODE
LOWtests/test_matcher/test_matcher.py277async def test_custom_permission_updater(app: App):CODE
LOWnonebot/compat.py270 def __get_pydantic_core_schema__(CODE
LOWnonebot/message.py136def _handle_ignored_exception(CODE
LOWnonebot/message.py153async def _apply_event_preprocessors(CODE
LOWnonebot/message.py210async def _apply_event_postprocessors(CODE
LOWnonebot/message.py315async def _apply_run_postprocessors(CODE
LOWnonebot/plugin/__init__.py61def _module_name_to_plugin_name(module_name: str) -> str:CODE
LOWnonebot/plugin/__init__.py87def _module_name_to_plugin_id(CODE
LOWnonebot/plugin/__init__.py148def get_plugin_by_module_name(module_name: str) -> "Plugin | None":CODE
LOWnonebot/plugin/__init__.py169def get_available_plugin_names() -> set[str]:CODE
LOWnonebot/plugin/load.py219def inherit_supported_adapters(*names: str) -> set[str] | None:CODE
LOWnonebot/plugin/manager.py84 def _previous_controlled_modules(self) -> dict[str, str]:CODE
LOWnonebot/internal/rule.py79 def _handle_skipped_exception(CODE
LOWnonebot/internal/adapter/bot.py85 def _handle_mock_api_exception(CODE
LOWnonebot/internal/adapter/bot.py135 def _handle_mock_api_exception(CODE
LOWnonebot/internal/adapter/template.py18 def formatter_field_name_split(CODE
LOWnonebot/internal/matcher/matcher.py877 def _handle_special_exception(CODE
Excessive Try-Catch Wrapping39 hits · 39 pts
SeverityFileLineSnippetContext
LOWwebsite/docs/developer/adapter-writing.md73except Exception as e:CODE
LOWwebsite/docs/developer/adapter-writing.md174 except Exception as e:CODE
LOWwebsite/docs/developer/adapter-writing.md184 except Exception as e:CODE
LOWwebsite/docs/developer/adapter-writing.md310 except Exception as e:CODE
LOW…sioned_docs/version-2.5.0/developer/adapter-writing.md73except Exception as e:CODE
LOW…sioned_docs/version-2.5.0/developer/adapter-writing.md174 except Exception as e:CODE
LOW…sioned_docs/version-2.5.0/developer/adapter-writing.md184 except Exception as e:CODE
LOW…sioned_docs/version-2.5.0/developer/adapter-writing.md310 except Exception as e:CODE
LOW…sioned_docs/version-2.4.4/developer/adapter-writing.md73except Exception as e:CODE
LOW…sioned_docs/version-2.4.4/developer/adapter-writing.md174 except Exception as e:CODE
LOW…sioned_docs/version-2.4.4/developer/adapter-writing.md184 except Exception as e:CODE
LOW…sioned_docs/version-2.4.4/developer/adapter-writing.md310 except Exception as e:CODE
LOW…sioned_docs/version-2.4.3/developer/adapter-writing.md73except Exception as e:CODE
LOW…sioned_docs/version-2.4.3/developer/adapter-writing.md174 except Exception as e:CODE
LOW…sioned_docs/version-2.4.3/developer/adapter-writing.md184 except Exception as e:CODE
LOW…sioned_docs/version-2.4.3/developer/adapter-writing.md310 except Exception as e:CODE
LOWtests/test_driver.py216 except Exception as e:CODE
LOWnonebot/permission.py102 except Exception:CODE
LOWnonebot/__init__.py63except Exception: # pragma: no coverCODE
LOWnonebot/message.py396 except Exception as e:CODE
LOWnonebot/message.py406 except Exception as e:CODE
LOWnonebot/message.py462 except Exception as e:CODE
LOWnonebot/message.py557 except Exception as e:CODE
LOWnonebot/rule.py168 except Exception:CODE
LOWnonebot/rule.py223 except Exception:CODE
LOWnonebot/rule.py278 except Exception:CODE
LOWnonebot/rule.py328 except Exception:CODE
LOWnonebot/rule.py567 except Exception as e:CODE
LOWnonebot/rule.py687 except Exception:CODE
LOWnonebot/utils.py271 except Exception as e:CODE
LOWnonebot/plugins/single_session.py25 except Exception:CODE
LOWnonebot/plugin/manager.py196 except Exception as e:CODE
LOWnonebot/plugin/manager.py257 except Exception:CODE
LOWnonebot/internal/params.py308 except Exception as e:CODE
LOWnonebot/internal/permission.py139 except Exception:CODE
LOWnonebot/internal/adapter/bot.py129 except Exception as e:CODE
LOWnonebot/internal/matcher/matcher.py602 except Exception:CODE
LOWnonebot/internal/matcher/matcher.py628 except Exception:CODE
LOWnonebot/dependencies/utils.py46 except Exception as e:CODE
Deep Nesting19 hits · 19 pts
SeverityFileLineSnippetContext
LOWtests/fake_server.py82CODE
LOWtests/test_param.py793CODE
LOWnonebot/config.py133CODE
LOWnonebot/config.py142CODE
LOWnonebot/config.py183CODE
LOWnonebot/rule.py88CODE
LOWnonebot/utils.py154CODE
LOWnonebot/plugin/manager.py156CODE
LOWnonebot/internal/params.py571CODE
LOWnonebot/internal/params.py581CODE
LOWnonebot/internal/driver/model.py66CODE
LOWnonebot/internal/driver/model.py226CODE
LOWnonebot/internal/adapter/message.py108CODE
LOWnonebot/internal/adapter/message.py154CODE
LOWnonebot/internal/adapter/message.py254CODE
LOWnonebot/internal/adapter/template.py88CODE
LOWnonebot/internal/adapter/template.py121CODE
LOWnonebot/internal/matcher/matcher.py822CODE
LOWnonebot/dependencies/__init__.py120CODE
AI Structural Patterns6 hits · 6 pts
SeverityFileLineSnippetContext
LOWtests/conftest.py63CODE
LOWtests/utils.py76CODE
LOWtests/plugins/param/priority.py11CODE
LOWnonebot/plugin/on.py114CODE
LOWnonebot/internal/driver/model.py66CODE
LOWnonebot/internal/matcher/matcher.py195CODE
Modern Structural Boilerplate6 hits · 6 pts
SeverityFileLineSnippetContext
LOWnonebot/internal/params.py140 def set_result(self, result: Any) -> None:CODE
LOWnonebot/internal/params.py150 def set_exception(self, exception: BaseException) -> None:CODE
LOWnonebot/internal/matcher/matcher.py711 def set_receive(self, id: str, event: Event) -> None:CODE
LOWnonebot/internal/matcher/matcher.py742 def set_arg(self, key: str, message: Message) -> None:CODE
LOWnonebot/internal/matcher/matcher.py746 def set_target(self, target: str, cache: bool = True) -> None:CODE
LOWnonebot/internal/matcher/manager.py91 def set_provider(self, provider_class: type[MatcherProvider]) -> None:CODE
Dead Code3 hits · 6 pts
SeverityFileLineSnippetContext
MEDIUMnonebot/internal/driver/abstract.py274CODE
MEDIUMnonebot/internal/driver/abstract.py316CODE
MEDIUMnonebot/internal/driver/abstract.py340CODE
Over-Commented Block2 hits · 2 pts
SeverityFileLineSnippetContext
LOWwebsite/docusaurus.config.ts261 // exclude: [COMMENT
LOWwebsite/src/components/Paginate/index.tsx41 // (element: HTMLElement | null) => {COMMENT