illusion-code 0.2.10__tar.gz → 0.2.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {illusion_code-0.2.10 → illusion_code-0.2.11}/PKG-INFO +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/package-lock.json +2 -2
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/package.json +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/version.ts +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/package-lock.json +2 -2
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/package.json +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/version.ts +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/pyproject.toml +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/__init__.py +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/__init__.py +35 -78
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/config.py +17 -7
- illusion_code-0.2.11/src/illusion/channels/exit_handler.py +83 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/session_map.py +25 -15
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/adapter.py +39 -34
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/session_map.py +22 -12
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/ws_client.py +73 -18
- illusion_code-0.2.11/src/illusion/channels/registry.py +253 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/serve.py +117 -90
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/tools/feishu_doc.py +6 -6
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/tools/feishu_drive.py +9 -9
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/tools/media.py +5 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/weixin/ilink_api.py +93 -14
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/weixin/session_map.py +22 -12
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/cli.py +10 -51
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/session.py +2 -18
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/config/i18n.py +24 -4
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/__init__.py +1 -1
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/mcp/__init__.py +1 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/__init__.py +7 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/__init__.py +6 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/todo_sync.py +2 -2
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/runtime.py +1 -1
- illusion_code-0.2.11/tests/channels/test_exit_handler.py +192 -0
- illusion_code-0.2.11/tests/channels/test_registry.py +248 -0
- illusion_code-0.2.11/tests/channels/test_session_persist.py +72 -0
- illusion_code-0.2.11/tests/channels/test_supervise.py +71 -0
- illusion_code-0.2.11/tests/channels/weixin/test_ilink_retry.py +65 -0
- illusion_code-0.2.11/tests/test_cli_exit_handler.py +66 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_qq_streaming.py +2 -2
- {illusion_code-0.2.10 → illusion_code-0.2.11}/.github/workflows/publish.yml +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/.gitignore +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/.python-version +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/LICENSE +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/README.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/README.zh-CN.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/architecture.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/channels.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/commands.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/extensions.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/getting-started.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/introduction.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/project-files.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/en/settings.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/images/IllusionCode.png +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/images/image1.png +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/images/image2.png +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/architecture.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/channels.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/commands.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/extensions.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/getting-started.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/introduction.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/project-files.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/docs/zh-CN/settings.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/build.mjs +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/App.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/CommandPicker.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/Composer.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/ComposerController.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/ConversationView.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/Footer.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/MarkdownContent.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/MarkdownTable.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/ModalHost.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/MultilineTextInput.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/PromptInput.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/QuestionNavigationBar.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/QuestionPreviewBox.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/SelectModal.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/SidePanel.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/Spinner.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/StatusBar.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/SwarmPanel.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/TodoPanel.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/ToolCallDisplay.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/TranscriptPane.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/components/WelcomeBanner.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/hooks/useAnimationFrame.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/hooks/useBackendSession.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/hooks/useBlink.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/hooks/useQuestionState.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/hooks/useTerminalSize.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/i18n.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/index.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/theme/ThemeContext.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/theme/builtinThemes.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/ToolInterface.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/AgentTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/BashTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/CronTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/EditTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/GenericTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/LspTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/McpTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/NotebookTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/PlanTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/ReadTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/SearchTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/SkillTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/TaskTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/WebTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/WorktreeTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/implementations/WriteTool.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/tools/registry.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/types.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/utils/markdown.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/src/utils/thinking.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/terminal/tsconfig.json +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/index.html +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/postcss.config.js +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/App.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/ChatArea.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/ErrorBoundary.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/MessageBubble.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/ModalCard.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/PromptInput.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/RightPanel.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/Sidebar.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/TodoPanel.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/Toolbar.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/components/WelcomeScreen.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/hooks/useTheme.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/hooks/useWebSocketSession.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/i18n.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/index.css +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/main.tsx +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/remarkSuperscript.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/types/protocol.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/utils/toolDisplayName.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/src/vite-env.d.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/tailwind.config.js +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/tsconfig.json +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/tsconfig.node.json +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/frontend/web/vite.config.ts +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/scripts/build_frontend.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/scripts/hatch_build.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/scripts/publish.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/scripts/sync_version.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/__main__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/codex_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/compat.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/effort.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/errors.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/openai_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/provider.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/registry.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/api/usage.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/codex_oauth.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/copilot.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/external.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/flows.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/auth/storage.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/bridge/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/bridge/manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/bridge/session_runner.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/bridge/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/bridge/work_secret.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/base.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/base_commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/delivery.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/messaging.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/streaming.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/feishu/ws_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/pid.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/api.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/qq/streaming.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/tools/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/tools/cross_channel.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/weixin/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/weixin/adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/channels/weixin/commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/auth.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/bridge.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/context.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/git.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/helpers.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/analysis/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/analysis/architecture.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/analysis/conventions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/analysis/dependencies.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/analysis/key_modules.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/extraction/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/extraction/lsp_symbols.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/extraction/readme.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/extraction/scanner.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/claudemd.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/illusionmd.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/memory_template.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/rules.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/generation/sections.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/orchestrator.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/init/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/mcp.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/memory.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/misc.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/model.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/plugin.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/registry.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/rules.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/sandbox.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/settings.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/commands/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/config/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/config/paths.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/config/plan_file.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/config/settings.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/coordinator/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/coordinator/agent_definitions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/coordinator/coordinator_mode.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/cost_tracker.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/messages.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/query.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/query_engine.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/engine/stream_events.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/events.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/executor.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/hot_reload.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/register_hooks.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/schemas.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/session_hooks.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/hooks/utils.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/mcp/client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/mcp/config.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/mcp/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/memdir.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/paths.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/scan.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/search.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/memory/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/output_styles/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/output_styles/loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/permissions/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/permissions/checker.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/permissions/loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/permissions/modes.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/permissions/schemas.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/platforms.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/installer.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/options.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/schemas.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/plugins/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/channel_hints.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/claudemd.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/context.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/environment.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/prompts/system_prompt.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/platforms/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/platforms/base.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/platforms/linux.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/platforms/macos.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/platforms/windows.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/proxy/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/proxy/env_vars.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/runtime.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/symlink_protection.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/utils.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/sandbox/violation_store.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/auto_compact.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/compact_core.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/compact_prompt.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/constants.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/message_ops.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/microcompact.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/models.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/compact/token_utils.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/cron.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/cron_scheduler.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/file_history.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/lsp/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/lsp/client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/lsp/config.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/lsp/manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/lsp/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/session_storage.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/services/token_estimation.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/batch.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/debug.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/loop.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/remember.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/simplify.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/skillify.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/stuck.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/update-config.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/bundled/content/verify.md +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/registry.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/skills/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/state/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/state/app_state.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/state/store.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/agent_executor.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/in_process.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/subprocess_backend.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/team_helpers.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/swarm/worktree.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/local_agent_task.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/local_shell_task.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/stop_task.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tasks/types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/agent_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/ask_user_question_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/base.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/bash_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/config_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/cron_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/enter_plan_mode_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/enter_worktree_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/exit_plan_mode_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/exit_worktree_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/file_edit_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/file_read_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/file_write_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/glob_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/grep_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/list_mcp_resources_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/lsp_formatters.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/lsp_schemas.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/lsp_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/mcp_auth_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/mcp_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/notebook_edit_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/powershell_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/read_mcp_resource_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/repl_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/send_message_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/shell_common.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/skill_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/sleep_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/structured_output_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_create_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_get_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_list_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_output_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_stop_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/task_update_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/team_create_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/team_delete_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/todo_write_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/tool_search_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/web_fetch_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/tools/web_search_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/app.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/backend_host.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/input.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/output.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/permission_dialog.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/permission_store.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/protocol.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/react_launcher.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/textual_app.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/web/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/web/server.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/web/ws_host.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/ui/web/ws_web_api.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/utils/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/utils/atomic_write.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/utils/file_state_cache.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/utils/ripgrep.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/src/illusion/utils/shell.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_anthropic_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_codex_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_effort.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_fallback/346/217/220/347/244/272.py" +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/api/test_openai_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/feishu/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/feishu/test_adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/feishu/test_commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/feishu/test_session_map.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/test_base.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/test_base_commands.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/test_config.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/test_pid.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/test_tool_registration.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/tools/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/tools/test_feishu_doc.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/tools/test_feishu_drive.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/weixin/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/weixin/test_adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/weixin/test_config.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/weixin/test_ilink_api.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/channels/weixin/test_session_map.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/init/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/init/test_claudemd.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/init/test_orchestrator.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/init/test_scanner.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/init/test_sections.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/commands/test_effort_command.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/config/test_i18n.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/config/test_settings.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/conftest.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/engine/test_query_engine.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/fixtures/fake_mcp_server.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/integration/test_effort_integration.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/services/lsp/test_lsp_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/services/lsp/test_lsp_config.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/services/lsp/test_lsp_manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/services/lsp/test_lsp_types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_api/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_api/test_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_api/test_codex_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_api/test_compat.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_api/test_openai_client.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_auth/test_external.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_bridge/test_core.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_bridge/test_session_flow.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_commands/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_commands/test_cli.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_commands/test_command_flows.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_commands/test_registry.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_config/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_config/test_paths.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_config/test_settings.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_coordinator/test_agent_definitions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_coordinator/test_coordinator_mode.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_engine/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_engine/test_media_block.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_engine/test_query_engine.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_engine/test_tool_result_media.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_hooks/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_hooks/test_executor.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_hooks/test_loader_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_hooks_skills_plugins_real.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_mcp/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_mcp/test_config_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_mcp/test_integration.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_mcp/test_stdio_flow.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_memory/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_memory/test_manager_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_memory/test_memdir.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_merged_prs_on_autoagent.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_permissions/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_permissions/test_checker.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_permissions/test_loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_permissions/test_project_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_platforms.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_plugins/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_plugins/test_lifecycle_flow.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_plugins/test_loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_plugins/test_loader_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_prompts/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_prompts/test_claudemd.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_prompts/test_claudemd_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_prompts/test_environment.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_prompts/test_system_prompt.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_qq_channel.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_real_large_tasks.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_adapter.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_config_schema.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_platform_linux.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_platform_macos.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_platform_windows.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_proxy_env_vars.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_runtime.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_symlink_protection.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_utils.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_sandbox/test_violation_store.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_scripts/test_sync_version.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_services/test_compact.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_services/test_cron.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_services/test_cron_scheduler.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_services/test_session_storage.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_skills/test_loader.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_skills/test_loader_permissions.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/test_agent_executor.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/test_imports.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/test_in_process.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/test_types.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_swarm/test_worktree.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tasks/test_manager.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_agent_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_core_tools.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_file_read_media.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_glob_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_grep_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_integration.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_integration_flows.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_mcp_auth_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_ripgrep.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_shell_common.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_task_tools.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_team_tools.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_tools/test_web_fetch_tool.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/test_modes.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/test_permission_store.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/test_react_backend.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/test_react_launcher.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_ui/test_textual_app.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_untested_features.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/test_utils/test_shell.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/ui/test_backend_host.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/ui/test_protocol_web.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/ui/test_web_api.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/__init__.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_channel_hints.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_cross_channel.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_delivery.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_feishu_streaming.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_media_tools.py +0 -0
- {illusion_code-0.2.10 → illusion_code-0.2.11}/tests/unit/test_session_list_active.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: illusion-code
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: Open-source Python port of Claude Code - an AI-powered CLI coding assistant
|
|
5
5
|
Project-URL: Homepage, https://github.com/YunTaiHua/illusion-code
|
|
6
6
|
Project-URL: Repository, https://github.com/YunTaiHua/illusion-code
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@illusion/terminal",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@illusion/terminal",
|
|
9
|
-
"version": "0.2.
|
|
9
|
+
"version": "0.2.11",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"chalk": "^5.6.2",
|
|
12
12
|
"ink": "^5.1.0",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@illusion/web",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@illusion/web",
|
|
9
|
-
"version": "0.2.
|
|
9
|
+
"version": "0.2.11",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"highlight.js": "^11.11.0",
|
|
12
12
|
"react": "^18.3.1",
|
|
@@ -35,6 +35,8 @@ logger = logging.getLogger(__name__)
|
|
|
35
35
|
def _config_fingerprint(cfg: "ChannelsConfig") -> str:
|
|
36
36
|
"""计算渠道配置指纹(用于检测配置变更后重启守护进程)
|
|
37
37
|
|
|
38
|
+
遍历 ChannelRegistry,对每个已启用渠道调用其 fingerprint_factory 生成标识。
|
|
39
|
+
|
|
38
40
|
Args:
|
|
39
41
|
cfg: 渠道配置
|
|
40
42
|
|
|
@@ -44,14 +46,14 @@ def _config_fingerprint(cfg: "ChannelsConfig") -> str:
|
|
|
44
46
|
import hashlib
|
|
45
47
|
import json as _json
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
from illusion.channels.registry import ChannelRegistry
|
|
50
|
+
|
|
51
|
+
# 遍历 registry 调用各渠道的 fingerprint_factory
|
|
48
52
|
enabled_channels = []
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if cfg.qq.enabled:
|
|
54
|
-
enabled_channels.append(f"qq:{cfg.qq.app_id}:{cfg.qq.client_secret}")
|
|
53
|
+
for desc in ChannelRegistry.all_descriptors():
|
|
54
|
+
channel_cfg = getattr(cfg, desc.config_attr, None)
|
|
55
|
+
if channel_cfg is not None and channel_cfg.enabled:
|
|
56
|
+
enabled_channels.append(desc.fingerprint_factory(channel_cfg))
|
|
55
57
|
raw = _json.dumps(sorted(enabled_channels), ensure_ascii=False)
|
|
56
58
|
return hashlib.md5(raw.encode()).hexdigest()
|
|
57
59
|
|
|
@@ -318,23 +320,6 @@ class ChannelRunner:
|
|
|
318
320
|
Args:
|
|
319
321
|
msg: 入站消息
|
|
320
322
|
"""
|
|
321
|
-
# 检查 /delete 信号:先执行 /new(清所有会话+发确认),再处理消息
|
|
322
|
-
# 信号触发后直接 return,避免继续走 try_handle 处理 /new 命令
|
|
323
|
-
# 导致"已开启新的对话"反馈消息发送两次
|
|
324
|
-
if self.session_store.check_signal():
|
|
325
|
-
for path in self.session_store.data_dir.glob("*.json"):
|
|
326
|
-
try:
|
|
327
|
-
path.unlink()
|
|
328
|
-
except OSError:
|
|
329
|
-
pass
|
|
330
|
-
from illusion.config.i18n import t as _t
|
|
331
|
-
# 统一使用 cmd_new,避免渠道专属文案不一致
|
|
332
|
-
await self.channel.send_text(
|
|
333
|
-
msg.chat_id, _t("cmd_new"), reply_to=msg.message_id,
|
|
334
|
-
)
|
|
335
|
-
self.session_store.clear_signal()
|
|
336
|
-
return
|
|
337
|
-
|
|
338
323
|
# 1. 待回复的权限/询问——不加锁,让回复立即送达
|
|
339
324
|
# (agent turn 持锁等待回复时,下一条消息作为回复立即 set_result,
|
|
340
325
|
# 不会因锁阻塞导致 300s 超时)
|
|
@@ -398,27 +383,16 @@ class ChannelRunner:
|
|
|
398
383
|
def _get_command_handler(self) -> Any:
|
|
399
384
|
"""按渠道类型返回对应的斜杠命令处理器
|
|
400
385
|
|
|
386
|
+
遍历 ChannelRegistry,匹配 adapter_class 后调用 command_handler_factory。
|
|
387
|
+
|
|
401
388
|
Returns:
|
|
402
389
|
BaseCommandHandler 实例或 None(未知渠道)
|
|
403
390
|
"""
|
|
404
|
-
from illusion.channels.
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
from illusion.channels.weixin.adapter import WeixinChannel
|
|
410
|
-
from illusion.channels.weixin.commands import WeixinCommandHandler
|
|
411
|
-
if isinstance(self.channel, WeixinChannel):
|
|
412
|
-
return WeixinCommandHandler(self.channel, self.session_store)
|
|
413
|
-
except ImportError:
|
|
414
|
-
pass # 微信模块不可用时跳过
|
|
415
|
-
try:
|
|
416
|
-
from illusion.channels.qq.adapter import QQChannel
|
|
417
|
-
from illusion.channels.qq.commands import QQCommandHandler
|
|
418
|
-
if isinstance(self.channel, QQChannel):
|
|
419
|
-
return QQCommandHandler(self.channel, self.session_store)
|
|
420
|
-
except ImportError:
|
|
421
|
-
pass # QQ 模块不可用时跳过
|
|
391
|
+
from illusion.channels.registry import ChannelRegistry
|
|
392
|
+
|
|
393
|
+
for desc in ChannelRegistry.all_descriptors():
|
|
394
|
+
if isinstance(self.channel, desc.adapter_class):
|
|
395
|
+
return desc.command_handler_factory(self.channel, self.session_store)
|
|
422
396
|
return None
|
|
423
397
|
|
|
424
398
|
async def _handle_stop(self, msg: "InboundMessage") -> None:
|
|
@@ -547,6 +521,14 @@ class ChannelRunner:
|
|
|
547
521
|
key = self.session_store.build_session_key(msg)
|
|
548
522
|
session = self.session_store.get_or_create(key, msg.user_id, msg.chat_type)
|
|
549
523
|
|
|
524
|
+
# 提前落盘会话索引(仅当文件尚不存在时):确保 session_id 落盘,
|
|
525
|
+
# 这样进程崩溃后下次启动 get_or_create 能命中该会话记录接续,
|
|
526
|
+
# 而非新建会话。注意:绝不覆盖已有 messages(否则会清空历史)。
|
|
527
|
+
try:
|
|
528
|
+
self.session_store.ensure_indexed(session)
|
|
529
|
+
except Exception as exc: # noqa: BLE001
|
|
530
|
+
logger.warning("会话索引提前落盘失败: %s", exc)
|
|
531
|
+
|
|
550
532
|
# 检测渠道是否支持消息编辑(仅飞书支持卡片 patch)
|
|
551
533
|
from illusion.channels.feishu.adapter import FeishuChannel
|
|
552
534
|
from illusion.channels.qq.adapter import QQChannel
|
|
@@ -600,18 +582,12 @@ class ChannelRunner:
|
|
|
600
582
|
await streaming_controller.start()
|
|
601
583
|
elif qq_c2c_streaming and qq_channel is not None:
|
|
602
584
|
# QQ C2C:用 stream_messages API 流式(首次有文本时才启动)
|
|
603
|
-
# 确保 token
|
|
604
|
-
|
|
605
|
-
from illusion.channels.qq.api import ensure_token
|
|
606
|
-
qq_channel._token = await ensure_token(
|
|
607
|
-
qq_channel._session,
|
|
608
|
-
qq_channel.config.app_id,
|
|
609
|
-
qq_channel.config.client_secret,
|
|
610
|
-
)
|
|
585
|
+
# 确保 token 已获取(通过 _get_token,重连后自动刷新)
|
|
586
|
+
token = await qq_channel._get_token()
|
|
611
587
|
from illusion.channels.qq.streaming import QQStreamingController
|
|
612
588
|
qq_streaming_controller = QQStreamingController(
|
|
613
589
|
session=qq_channel._session,
|
|
614
|
-
token=
|
|
590
|
+
token=token,
|
|
615
591
|
openid=msg.chat_id,
|
|
616
592
|
msg_id=msg.message_id,
|
|
617
593
|
)
|
|
@@ -889,10 +865,8 @@ def _create_session_store(
|
|
|
889
865
|
) -> Any:
|
|
890
866
|
"""根据渠道类型创建对应的 SessionStore
|
|
891
867
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
微信 → WeixinSessionStore
|
|
895
|
-
未知 → FeishuSessionStore(向后兼容)
|
|
868
|
+
遍历 ChannelRegistry,匹配 adapter_class 后调用 session_store_factory。
|
|
869
|
+
未知渠道回退到 FeishuSessionStore(向后兼容)。
|
|
896
870
|
|
|
897
871
|
Args:
|
|
898
872
|
channel: 渠道实例
|
|
@@ -902,30 +876,13 @@ def _create_session_store(
|
|
|
902
876
|
Returns:
|
|
903
877
|
对应渠道的 SessionStore 实例
|
|
904
878
|
"""
|
|
905
|
-
from illusion.channels.
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
)
|
|
912
|
-
try:
|
|
913
|
-
from illusion.channels.qq.adapter import QQChannel
|
|
914
|
-
if isinstance(channel, QQChannel):
|
|
915
|
-
from illusion.channels.qq.session_map import QQSessionStore
|
|
916
|
-
return QQSessionStore(
|
|
917
|
-
data_dir=data_dir,
|
|
918
|
-
group_sessions_per_user=group_sessions_per_user,
|
|
879
|
+
from illusion.channels.registry import ChannelRegistry
|
|
880
|
+
|
|
881
|
+
for desc in ChannelRegistry.all_descriptors():
|
|
882
|
+
if isinstance(channel, desc.adapter_class):
|
|
883
|
+
return desc.session_store_factory(
|
|
884
|
+
channel, data_dir, group_sessions_per_user
|
|
919
885
|
)
|
|
920
|
-
except ImportError:
|
|
921
|
-
pass
|
|
922
|
-
try:
|
|
923
|
-
from illusion.channels.weixin.adapter import WeixinChannel
|
|
924
|
-
if isinstance(channel, WeixinChannel):
|
|
925
|
-
from illusion.channels.weixin.session_map import WeixinSessionStore
|
|
926
|
-
return WeixinSessionStore(data_dir=data_dir)
|
|
927
|
-
except ImportError:
|
|
928
|
-
pass
|
|
929
886
|
# 未知渠道回退到飞书(向后兼容)
|
|
930
887
|
from illusion.channels.feishu.session_map import FeishuSessionStore
|
|
931
888
|
return FeishuSessionStore(
|
|
@@ -161,24 +161,34 @@ class ChannelsConfig(BaseModel):
|
|
|
161
161
|
def has_enabled_channels(self) -> bool:
|
|
162
162
|
"""是否有任何已启用的渠道
|
|
163
163
|
|
|
164
|
+
遍历 ChannelRegistry 检查每个渠道的 enabled 字段。
|
|
165
|
+
|
|
164
166
|
Returns:
|
|
165
167
|
bool: 任一渠道 enabled 为 True 时返回 True
|
|
166
168
|
"""
|
|
167
|
-
|
|
169
|
+
from illusion.channels.registry import ChannelRegistry
|
|
170
|
+
|
|
171
|
+
for desc in ChannelRegistry.all_descriptors():
|
|
172
|
+
channel_cfg = getattr(self, desc.config_attr, None)
|
|
173
|
+
if channel_cfg is not None and channel_cfg.enabled:
|
|
174
|
+
return True
|
|
175
|
+
return False
|
|
168
176
|
|
|
169
177
|
def enabled_channel_names(self) -> list[str]:
|
|
170
178
|
"""返回所有已启用渠道的名称列表
|
|
171
179
|
|
|
180
|
+
遍历 ChannelRegistry 收集已启用渠道名。
|
|
181
|
+
|
|
172
182
|
Returns:
|
|
173
183
|
list[str]: 已启用渠道名列表
|
|
174
184
|
"""
|
|
185
|
+
from illusion.channels.registry import ChannelRegistry
|
|
186
|
+
|
|
175
187
|
names: list[str] = []
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if self.qq.enabled:
|
|
181
|
-
names.append("qq")
|
|
188
|
+
for desc in ChannelRegistry.all_descriptors():
|
|
189
|
+
channel_cfg = getattr(self, desc.config_attr, None)
|
|
190
|
+
if channel_cfg is not None and channel_cfg.enabled:
|
|
191
|
+
names.append(desc.name)
|
|
182
192
|
return names
|
|
183
193
|
|
|
184
194
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""共享退出处理器
|
|
2
|
+
==================
|
|
3
|
+
|
|
4
|
+
统一 Ctrl+C / 正常退出时的守护进程退出行为,消除 cli.py 中
|
|
5
|
+
main() 和 web_start() 重复的内联退出确认逻辑。
|
|
6
|
+
|
|
7
|
+
行为规则:
|
|
8
|
+
1. 守护进程未运行 → 直接返回(程序正常退出)
|
|
9
|
+
2. channels.json 无配置或无启用渠道 → 直接返回
|
|
10
|
+
3. 否则弹出确认提示:
|
|
11
|
+
- 输入 y/Y/yes/回车(空输入)→ 停止守护进程
|
|
12
|
+
- 输入期间再次 Ctrl+C(KeyboardInterrupt)→ 停止守护进程
|
|
13
|
+
- 其他任何输入 → 不停止(守护进程保留运行)
|
|
14
|
+
- EOF(非 TTY 环境,如管道)→ 不停止
|
|
15
|
+
|
|
16
|
+
函数说明:
|
|
17
|
+
- handle_daemon_exit_on_interrupt: 退出时调用,按上述规则处理
|
|
18
|
+
- _confirm_exit: 私有确认函数
|
|
19
|
+
|
|
20
|
+
使用示例:
|
|
21
|
+
>>> from illusion.channels.exit_handler import handle_daemon_exit_on_interrupt
|
|
22
|
+
>>> # 在 cli.py 的 finally 块中调用
|
|
23
|
+
>>> handle_daemon_exit_on_interrupt()
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from illusion.channels import (
|
|
28
|
+
is_channel_daemon_running,
|
|
29
|
+
stop_channel_daemon_by_pid,
|
|
30
|
+
)
|
|
31
|
+
from illusion.channels.config import load_channels_config
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def handle_daemon_exit_on_interrupt() -> None:
|
|
35
|
+
"""Ctrl+C 或正常退出时的守护进程退出处理
|
|
36
|
+
|
|
37
|
+
行为:
|
|
38
|
+
1. 守护进程未运行 → 直接返回(程序正常退出)
|
|
39
|
+
2. channels.json 无配置或无启用渠道 → 直接返回
|
|
40
|
+
3. 否则弹出确认提示:
|
|
41
|
+
- 输入 y/Y/yes/回车(空输入)→ 停止守护进程
|
|
42
|
+
- 输入期间再次 Ctrl+C(KeyboardInterrupt)→ 停止守护进程
|
|
43
|
+
- 其他任何输入 → 不停止(守护进程保留运行)
|
|
44
|
+
|
|
45
|
+
退出路径必须比正常路径更健壮:任何异常(如 channels.json 权限不足、
|
|
46
|
+
PID 文件读取失败)都不应破坏退出体验,静默吞掉并记日志。
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
if not is_channel_daemon_running():
|
|
50
|
+
return
|
|
51
|
+
cfg = load_channels_config()
|
|
52
|
+
if not cfg.has_enabled_channels():
|
|
53
|
+
return
|
|
54
|
+
if _confirm_exit():
|
|
55
|
+
stop_channel_daemon_by_pid()
|
|
56
|
+
except Exception: # noqa: BLE001
|
|
57
|
+
# 退出路径防御性兜底:避免配置文件异常/PID 读取失败等导致丑陋 traceback
|
|
58
|
+
import logging
|
|
59
|
+
logging.getLogger(__name__).debug("exit handler suppressed exception", exc_info=True)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _confirm_exit() -> bool:
|
|
63
|
+
"""确认是否退出守护进程
|
|
64
|
+
|
|
65
|
+
y/Y/yes/空回车/二次 Ctrl+C 均视为确认;
|
|
66
|
+
其他输入或 EOF 视为拒绝。
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
bool: True 表示确认停止守护进程
|
|
70
|
+
"""
|
|
71
|
+
from illusion.config.i18n import t
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
answer = input(t("channel_daemon_exit_prompt") + " ").strip()
|
|
75
|
+
return answer.lower() in ("", "y", "yes")
|
|
76
|
+
except KeyboardInterrupt:
|
|
77
|
+
# 再次 Ctrl+C = 确认退出。Windows 终端会回显 "^C" 到屏幕,
|
|
78
|
+
# 打印明确的确认信息让用户知道 Ctrl+C 已被正确处理
|
|
79
|
+
print()
|
|
80
|
+
print(t("channel_daemon_exit_confirmed"))
|
|
81
|
+
return True
|
|
82
|
+
except EOFError:
|
|
83
|
+
return False # 非 TTY 环境(如管道)默认不杀
|
|
@@ -98,21 +98,6 @@ class FeishuSessionStore:
|
|
|
98
98
|
safe = key.replace(":", "_").replace("/", "_") # 安全文件名
|
|
99
99
|
return self.data_dir / f"{safe}.json"
|
|
100
100
|
|
|
101
|
-
def check_signal(self) -> bool:
|
|
102
|
-
"""检查 /delete 信号文件是否存在
|
|
103
|
-
|
|
104
|
-
Returns:
|
|
105
|
-
bool: 信号存在返回 True
|
|
106
|
-
"""
|
|
107
|
-
return (self.data_dir / ".delete_signal").exists()
|
|
108
|
-
|
|
109
|
-
def clear_signal(self) -> None:
|
|
110
|
-
"""删除信号文件"""
|
|
111
|
-
try:
|
|
112
|
-
(self.data_dir / ".delete_signal").unlink()
|
|
113
|
-
except OSError:
|
|
114
|
-
pass
|
|
115
|
-
|
|
116
101
|
def get_or_create(self, key: str, user_id: str, chat_type: str) -> FeishuSession:
|
|
117
102
|
"""获取或创建会话
|
|
118
103
|
|
|
@@ -125,6 +110,10 @@ class FeishuSessionStore:
|
|
|
125
110
|
|
|
126
111
|
Returns:
|
|
127
112
|
FeishuSession: 会话状态
|
|
113
|
+
|
|
114
|
+
Note:
|
|
115
|
+
会话索引在 _run_agent 进入 agent turn 前即提前落盘,
|
|
116
|
+
保证进程崩溃后下次启动能接续同一 session_id。
|
|
128
117
|
"""
|
|
129
118
|
path = self._key_to_path(key)
|
|
130
119
|
if path.exists():
|
|
@@ -178,6 +167,27 @@ class FeishuSessionStore:
|
|
|
178
167
|
except FileNotFoundError:
|
|
179
168
|
pass # 已删除
|
|
180
169
|
|
|
170
|
+
def ensure_indexed(self, session: FeishuSession) -> None:
|
|
171
|
+
"""确保会话索引已落盘(仅当文件不存在时创建)
|
|
172
|
+
|
|
173
|
+
与 save 不同:本方法绝不覆盖已有 messages,只在文件尚不存在时
|
|
174
|
+
写入 session_id 等索引字段,供进程崩溃后接续使用。
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
session: 会话状态
|
|
178
|
+
"""
|
|
179
|
+
path = self._key_to_path(session.key)
|
|
180
|
+
if path.exists():
|
|
181
|
+
return # 已有记录,绝不覆盖(避免清空历史)
|
|
182
|
+
data = {
|
|
183
|
+
"session_id": session.session_id,
|
|
184
|
+
"messages": [],
|
|
185
|
+
"user_id": session.user_id,
|
|
186
|
+
"chat_type": session.chat_type,
|
|
187
|
+
"model": session.model,
|
|
188
|
+
}
|
|
189
|
+
atomic_write_text(path, json.dumps(data, ensure_ascii=False, indent=2))
|
|
190
|
+
|
|
181
191
|
def clear_by_session_id(self, session_id: str) -> bool:
|
|
182
192
|
"""按 session_id 删除会话文件(用于 /delete 命令跨渠道清理)
|
|
183
193
|
|
|
@@ -83,7 +83,10 @@ class QQChannel(Channel):
|
|
|
83
83
|
self._stop_event = asyncio.Event()
|
|
84
84
|
self._ws_client: Any = None # QQWSClient 实例
|
|
85
85
|
self._session: Any = None # aiohttp.ClientSession(发送用)
|
|
86
|
-
self._token
|
|
86
|
+
# 注意:不再缓存 self._token。每次 API 调用都通过 _get_token()
|
|
87
|
+
# 获取最新 token(内部有 _token_cache + 过期检查,不会重复请求)。
|
|
88
|
+
# 原因:WS 重连时 ws_client 会刷新 _token_cache,但旧的 self._token
|
|
89
|
+
# 不会更新,导致重连后发送消息用旧 token 报 "token not exist or expire"。
|
|
87
90
|
|
|
88
91
|
# bot 自身 openid(用于自回显检测)
|
|
89
92
|
self._bot_openid: str = ""
|
|
@@ -101,6 +104,22 @@ class QQChannel(Channel):
|
|
|
101
104
|
# markdown 支持(从配置读取,默认启用)
|
|
102
105
|
self._markdown_support: bool = getattr(config, "markdown_support", True)
|
|
103
106
|
|
|
107
|
+
async def _get_token(self) -> str:
|
|
108
|
+
"""获取有效的 QQ Bot access token
|
|
109
|
+
|
|
110
|
+
每次调用都经过 ensure_token(),内部有缓存+过期检查,
|
|
111
|
+
不会重复请求。WS 重连后 _token_cache 已刷新,此方法自动
|
|
112
|
+
返回新 token,无需手动同步。
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
str: 有效的 access token
|
|
116
|
+
"""
|
|
117
|
+
if not self._session:
|
|
118
|
+
raise RuntimeError("QQ adapter 未连接,无法获取 token")
|
|
119
|
+
return await ensure_token(
|
|
120
|
+
self._session, self.config.app_id, self.config.client_secret,
|
|
121
|
+
)
|
|
122
|
+
|
|
104
123
|
async def connect(self) -> None:
|
|
105
124
|
"""建立 WS 连接和 HTTP session"""
|
|
106
125
|
import aiohttp
|
|
@@ -130,12 +149,9 @@ class QQChannel(Channel):
|
|
|
130
149
|
if not self._session:
|
|
131
150
|
return
|
|
132
151
|
try:
|
|
133
|
-
|
|
134
|
-
self._token = await ensure_token(
|
|
135
|
-
self._session, self.config.app_id, self.config.client_secret,
|
|
136
|
-
)
|
|
152
|
+
token = await self._get_token()
|
|
137
153
|
from illusion.channels.qq.api import API_BASE
|
|
138
|
-
headers = {"Authorization": f"QQBot {
|
|
154
|
+
headers = {"Authorization": f"QQBot {token}"}
|
|
139
155
|
async with self._session.get(f"{API_BASE}/users/@me", headers=headers) as resp:
|
|
140
156
|
if resp.status == 200:
|
|
141
157
|
data = await resp.json()
|
|
@@ -447,11 +463,8 @@ class QQChannel(Channel):
|
|
|
447
463
|
if not self._session:
|
|
448
464
|
return ""
|
|
449
465
|
|
|
450
|
-
# 确保 token
|
|
451
|
-
|
|
452
|
-
self._token = await ensure_token(
|
|
453
|
-
self._session, self.config.app_id, self.config.client_secret,
|
|
454
|
-
)
|
|
466
|
+
# 确保 token 有效(每次调用,重连后自动获取新 token)
|
|
467
|
+
token = await self._get_token()
|
|
455
468
|
|
|
456
469
|
# 格式化(markdown 原样传递 or 剥离为纯文本)
|
|
457
470
|
formatted = self._format_message(text)
|
|
@@ -476,13 +489,13 @@ class QQChannel(Channel):
|
|
|
476
489
|
try:
|
|
477
490
|
if is_group:
|
|
478
491
|
await send_group_message(
|
|
479
|
-
self._session,
|
|
492
|
+
self._session, token, chat_id, chunk,
|
|
480
493
|
msg_id=reply_to,
|
|
481
494
|
markdown=use_markdown,
|
|
482
495
|
)
|
|
483
496
|
else:
|
|
484
497
|
await send_c2c_message(
|
|
485
|
-
self._session,
|
|
498
|
+
self._session, token, chat_id, chunk,
|
|
486
499
|
msg_id=reply_to or "",
|
|
487
500
|
markdown=use_markdown,
|
|
488
501
|
)
|
|
@@ -516,8 +529,9 @@ class QQChannel(Channel):
|
|
|
516
529
|
try:
|
|
517
530
|
from illusion.channels.qq.api import upload_file
|
|
518
531
|
is_group = self._chat_type_cache.get(chat_id) == "group"
|
|
532
|
+
token = await self._get_token()
|
|
519
533
|
await upload_file(
|
|
520
|
-
self._session,
|
|
534
|
+
self._session, token, chat_id, file_path,
|
|
521
535
|
is_group=is_group,
|
|
522
536
|
)
|
|
523
537
|
except Exception as exc: # noqa: BLE001
|
|
@@ -555,10 +569,7 @@ class QQChannel(Channel):
|
|
|
555
569
|
upload_file,
|
|
556
570
|
)
|
|
557
571
|
|
|
558
|
-
|
|
559
|
-
self._token = await ensure_token(
|
|
560
|
-
self._session, self.config.app_id, self.config.client_secret,
|
|
561
|
-
)
|
|
572
|
+
token = await self._get_token()
|
|
562
573
|
|
|
563
574
|
is_group = self._chat_type_cache.get(chat_id) == "group"
|
|
564
575
|
|
|
@@ -569,7 +580,7 @@ class QQChannel(Channel):
|
|
|
569
580
|
)
|
|
570
581
|
|
|
571
582
|
upload_resp = await upload_file(
|
|
572
|
-
self._session,
|
|
583
|
+
self._session, token, chat_id, image_path,
|
|
573
584
|
is_group=is_group,
|
|
574
585
|
file_type=MEDIA_TYPE_IMAGE,
|
|
575
586
|
)
|
|
@@ -578,7 +589,7 @@ class QQChannel(Channel):
|
|
|
578
589
|
raise RuntimeError(f"QQ 图片上传未返回 file_info: {upload_resp}")
|
|
579
590
|
|
|
580
591
|
msg_id = await send_media_message(
|
|
581
|
-
self._session,
|
|
592
|
+
self._session, token, chat_id, file_info,
|
|
582
593
|
is_group=is_group, msg_id=reply_to,
|
|
583
594
|
)
|
|
584
595
|
|
|
@@ -619,10 +630,7 @@ class QQChannel(Channel):
|
|
|
619
630
|
upload_file,
|
|
620
631
|
)
|
|
621
632
|
|
|
622
|
-
|
|
623
|
-
self._token = await ensure_token(
|
|
624
|
-
self._session, self.config.app_id, self.config.client_secret,
|
|
625
|
-
)
|
|
633
|
+
token = await self._get_token()
|
|
626
634
|
|
|
627
635
|
is_group = self._chat_type_cache.get(chat_id) == "group"
|
|
628
636
|
|
|
@@ -633,7 +641,7 @@ class QQChannel(Channel):
|
|
|
633
641
|
)
|
|
634
642
|
|
|
635
643
|
upload_resp = await upload_file(
|
|
636
|
-
self._session,
|
|
644
|
+
self._session, token, chat_id, file_path,
|
|
637
645
|
is_group=is_group,
|
|
638
646
|
file_type=MEDIA_TYPE_FILE,
|
|
639
647
|
)
|
|
@@ -642,7 +650,7 @@ class QQChannel(Channel):
|
|
|
642
650
|
raise RuntimeError(f"QQ 文件上传未返回 file_info: {upload_resp}")
|
|
643
651
|
|
|
644
652
|
msg_id = await send_media_message(
|
|
645
|
-
self._session,
|
|
653
|
+
self._session, token, chat_id, file_info,
|
|
646
654
|
is_group=is_group, msg_id=reply_to,
|
|
647
655
|
)
|
|
648
656
|
|
|
@@ -678,10 +686,7 @@ class QQChannel(Channel):
|
|
|
678
686
|
if not self._session:
|
|
679
687
|
raise NotImplementedError("QQ session 未初始化,无法下载附件")
|
|
680
688
|
|
|
681
|
-
|
|
682
|
-
self._token = await ensure_token(
|
|
683
|
-
self._session, self.config.app_id, self.config.client_secret,
|
|
684
|
-
)
|
|
689
|
+
token = await self._get_token()
|
|
685
690
|
|
|
686
691
|
# 优先使用 download_url(QQ 入站附件的临时 URL)
|
|
687
692
|
url_error: Exception | None = None
|
|
@@ -694,7 +699,7 @@ class QQChannel(Channel):
|
|
|
694
699
|
# 仅对 QQ 可信 CDN 域名附带 Authorization,避免 bot token 泄露到第三方 host
|
|
695
700
|
headers: dict[str, str] = {}
|
|
696
701
|
if _is_qq_cdn_url(url):
|
|
697
|
-
headers["Authorization"] = f"QQBot {
|
|
702
|
+
headers["Authorization"] = f"QQBot {token}"
|
|
698
703
|
else:
|
|
699
704
|
logger.warning(
|
|
700
705
|
"QQ 附件 URL 非 QQ CDN 域名,不带 Authorization: %s",
|
|
@@ -724,7 +729,7 @@ class QQChannel(Channel):
|
|
|
724
729
|
)
|
|
725
730
|
try:
|
|
726
731
|
data = await download_file(
|
|
727
|
-
self._session,
|
|
732
|
+
self._session, token, target_id,
|
|
728
733
|
attachment.file_key,
|
|
729
734
|
is_group=False,
|
|
730
735
|
)
|
|
@@ -758,8 +763,8 @@ class QQChannel(Channel):
|
|
|
758
763
|
|
|
759
764
|
try:
|
|
760
765
|
from illusion.channels.qq.api import send_typing
|
|
761
|
-
|
|
762
|
-
|
|
766
|
+
token = await self._get_token()
|
|
767
|
+
await send_typing(self._session, token, chat_id)
|
|
763
768
|
except Exception as exc: # noqa: BLE001
|
|
764
769
|
logger.debug("QQ 打字状态发送失败: %s", exc)
|
|
765
770
|
|