illusion-code 0.2.6__tar.gz → 0.2.7__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.
Files changed (522) hide show
  1. {illusion_code-0.2.6 → illusion_code-0.2.7}/PKG-INFO +1 -1
  2. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/package-lock.json +2 -2
  3. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/package.json +1 -1
  4. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/ConversationView.tsx +6 -3
  5. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/version.ts +1 -1
  6. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/package-lock.json +2 -2
  7. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/package.json +1 -1
  8. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/App.tsx +97 -1
  9. illusion_code-0.2.7/frontend/web/src/components/ChatArea.tsx +428 -0
  10. illusion_code-0.2.7/frontend/web/src/components/MessageBubble.tsx +496 -0
  11. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/PromptInput.tsx +9 -0
  12. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/Sidebar.tsx +25 -11
  13. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/i18n.ts +34 -0
  14. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/index.css +118 -40
  15. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/version.ts +1 -1
  16. {illusion_code-0.2.6 → illusion_code-0.2.7}/pyproject.toml +1 -1
  17. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/__init__.py +1 -1
  18. illusion_code-0.2.6/frontend/web/src/components/ChatArea.tsx +0 -179
  19. illusion_code-0.2.6/frontend/web/src/components/MessageBubble.tsx +0 -277
  20. {illusion_code-0.2.6 → illusion_code-0.2.7}/.github/workflows/publish.yml +0 -0
  21. {illusion_code-0.2.6 → illusion_code-0.2.7}/.gitignore +0 -0
  22. {illusion_code-0.2.6 → illusion_code-0.2.7}/.python-version +0 -0
  23. {illusion_code-0.2.6 → illusion_code-0.2.7}/LICENSE +0 -0
  24. {illusion_code-0.2.6 → illusion_code-0.2.7}/README.md +0 -0
  25. {illusion_code-0.2.6 → illusion_code-0.2.7}/README.zh-CN.md +0 -0
  26. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/architecture.md +0 -0
  27. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/channels.md +0 -0
  28. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/commands.md +0 -0
  29. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/extensions.md +0 -0
  30. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/getting-started.md +0 -0
  31. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/introduction.md +0 -0
  32. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/project-files.md +0 -0
  33. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/en/settings.md +0 -0
  34. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/images/IllusionCode.png +0 -0
  35. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/images/image1.png +0 -0
  36. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/images/image2.png +0 -0
  37. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/architecture.md +0 -0
  38. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/channels.md +0 -0
  39. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/commands.md +0 -0
  40. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/extensions.md +0 -0
  41. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/getting-started.md +0 -0
  42. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/introduction.md +0 -0
  43. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/project-files.md +0 -0
  44. {illusion_code-0.2.6 → illusion_code-0.2.7}/docs/zh-CN/settings.md +0 -0
  45. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/build.mjs +0 -0
  46. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/App.tsx +0 -0
  47. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/CommandPicker.tsx +0 -0
  48. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/Composer.tsx +0 -0
  49. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/ComposerController.tsx +0 -0
  50. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/Footer.tsx +0 -0
  51. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/MarkdownContent.tsx +0 -0
  52. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/MarkdownTable.tsx +0 -0
  53. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/ModalHost.tsx +0 -0
  54. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/MultilineTextInput.tsx +0 -0
  55. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/PromptInput.tsx +0 -0
  56. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/QuestionNavigationBar.tsx +0 -0
  57. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/QuestionPreviewBox.tsx +0 -0
  58. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/SelectModal.tsx +0 -0
  59. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/SidePanel.tsx +0 -0
  60. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/Spinner.tsx +0 -0
  61. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/StatusBar.tsx +0 -0
  62. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/SwarmPanel.tsx +0 -0
  63. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/TodoPanel.tsx +0 -0
  64. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/ToolCallDisplay.tsx +0 -0
  65. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/TranscriptPane.tsx +0 -0
  66. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/components/WelcomeBanner.tsx +0 -0
  67. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/hooks/useAnimationFrame.ts +0 -0
  68. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/hooks/useBackendSession.ts +0 -0
  69. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/hooks/useBlink.ts +0 -0
  70. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/hooks/useQuestionState.ts +0 -0
  71. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/hooks/useTerminalSize.ts +0 -0
  72. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/i18n.ts +0 -0
  73. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/index.tsx +0 -0
  74. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/theme/ThemeContext.tsx +0 -0
  75. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/theme/builtinThemes.ts +0 -0
  76. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/ToolInterface.ts +0 -0
  77. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/AgentTool.ts +0 -0
  78. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/BashTool.ts +0 -0
  79. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/CronTool.ts +0 -0
  80. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/EditTool.ts +0 -0
  81. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/GenericTool.ts +0 -0
  82. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/LspTool.ts +0 -0
  83. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/McpTool.ts +0 -0
  84. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/NotebookTool.ts +0 -0
  85. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/PlanTool.ts +0 -0
  86. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/ReadTool.ts +0 -0
  87. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/SearchTool.ts +0 -0
  88. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/SkillTool.ts +0 -0
  89. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/TaskTool.ts +0 -0
  90. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/WebTool.ts +0 -0
  91. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/WorktreeTool.ts +0 -0
  92. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/implementations/WriteTool.ts +0 -0
  93. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/tools/registry.ts +0 -0
  94. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/types.ts +0 -0
  95. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/utils/markdown.ts +0 -0
  96. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/src/utils/thinking.ts +0 -0
  97. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/terminal/tsconfig.json +0 -0
  98. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/index.html +0 -0
  99. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/postcss.config.js +0 -0
  100. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/ErrorBoundary.tsx +0 -0
  101. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/ModalCard.tsx +0 -0
  102. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/RightPanel.tsx +0 -0
  103. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/TodoPanel.tsx +0 -0
  104. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/Toolbar.tsx +0 -0
  105. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/components/WelcomeScreen.tsx +0 -0
  106. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/hooks/useWebSocketSession.ts +0 -0
  107. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/main.tsx +0 -0
  108. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/remarkSuperscript.ts +0 -0
  109. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/types/protocol.ts +0 -0
  110. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/src/vite-env.d.ts +0 -0
  111. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/tailwind.config.js +0 -0
  112. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/tsconfig.json +0 -0
  113. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/tsconfig.node.json +0 -0
  114. {illusion_code-0.2.6 → illusion_code-0.2.7}/frontend/web/vite.config.ts +0 -0
  115. {illusion_code-0.2.6 → illusion_code-0.2.7}/scripts/build_frontend.py +0 -0
  116. {illusion_code-0.2.6 → illusion_code-0.2.7}/scripts/hatch_build.py +0 -0
  117. {illusion_code-0.2.6 → illusion_code-0.2.7}/scripts/publish.py +0 -0
  118. {illusion_code-0.2.6 → illusion_code-0.2.7}/scripts/sync_version.py +0 -0
  119. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/__main__.py +0 -0
  120. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/__init__.py +0 -0
  121. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/client.py +0 -0
  122. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/codex_client.py +0 -0
  123. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/compat.py +0 -0
  124. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/effort.py +0 -0
  125. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/errors.py +0 -0
  126. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/openai_client.py +0 -0
  127. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/provider.py +0 -0
  128. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/registry.py +0 -0
  129. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/api/usage.py +0 -0
  130. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/__init__.py +0 -0
  131. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/codex_oauth.py +0 -0
  132. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/copilot.py +0 -0
  133. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/external.py +0 -0
  134. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/flows.py +0 -0
  135. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/manager.py +0 -0
  136. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/auth/storage.py +0 -0
  137. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/bridge/__init__.py +0 -0
  138. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/bridge/manager.py +0 -0
  139. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/bridge/session_runner.py +0 -0
  140. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/bridge/types.py +0 -0
  141. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/bridge/work_secret.py +0 -0
  142. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/__init__.py +0 -0
  143. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/base.py +0 -0
  144. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/base_commands.py +0 -0
  145. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/config.py +0 -0
  146. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/__init__.py +0 -0
  147. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/adapter.py +0 -0
  148. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/commands.py +0 -0
  149. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/messaging.py +0 -0
  150. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/session_map.py +0 -0
  151. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/feishu/ws_client.py +0 -0
  152. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/pid.py +0 -0
  153. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/__init__.py +0 -0
  154. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/adapter.py +0 -0
  155. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/api.py +0 -0
  156. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/commands.py +0 -0
  157. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/session_map.py +0 -0
  158. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/qq/ws_client.py +0 -0
  159. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/serve.py +0 -0
  160. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/tools/__init__.py +0 -0
  161. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/tools/feishu_doc.py +0 -0
  162. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/tools/feishu_drive.py +0 -0
  163. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/weixin/__init__.py +0 -0
  164. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/weixin/adapter.py +0 -0
  165. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/weixin/commands.py +0 -0
  166. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/weixin/ilink_api.py +0 -0
  167. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/channels/weixin/session_map.py +0 -0
  168. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/cli.py +0 -0
  169. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/__init__.py +0 -0
  170. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/auth.py +0 -0
  171. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/bridge.py +0 -0
  172. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/context.py +0 -0
  173. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/git.py +0 -0
  174. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/helpers.py +0 -0
  175. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/__init__.py +0 -0
  176. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/analysis/__init__.py +0 -0
  177. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/analysis/architecture.py +0 -0
  178. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/analysis/conventions.py +0 -0
  179. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/analysis/dependencies.py +0 -0
  180. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/analysis/key_modules.py +0 -0
  181. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/extraction/__init__.py +0 -0
  182. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/extraction/lsp_symbols.py +0 -0
  183. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/extraction/readme.py +0 -0
  184. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/extraction/scanner.py +0 -0
  185. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/__init__.py +0 -0
  186. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/claudemd.py +0 -0
  187. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/illusionmd.py +0 -0
  188. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/memory_template.py +0 -0
  189. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/rules.py +0 -0
  190. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/generation/sections.py +0 -0
  191. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/orchestrator.py +0 -0
  192. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/init/types.py +0 -0
  193. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/mcp.py +0 -0
  194. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/memory.py +0 -0
  195. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/misc.py +0 -0
  196. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/model.py +0 -0
  197. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/plugin.py +0 -0
  198. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/registry.py +0 -0
  199. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/rules.py +0 -0
  200. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/sandbox.py +0 -0
  201. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/session.py +0 -0
  202. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/settings.py +0 -0
  203. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/commands/types.py +0 -0
  204. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/config/__init__.py +0 -0
  205. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/config/i18n.py +0 -0
  206. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/config/paths.py +0 -0
  207. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/config/plan_file.py +0 -0
  208. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/config/settings.py +0 -0
  209. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/coordinator/__init__.py +0 -0
  210. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/coordinator/agent_definitions.py +0 -0
  211. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/coordinator/coordinator_mode.py +0 -0
  212. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/__init__.py +0 -0
  213. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/cost_tracker.py +0 -0
  214. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/messages.py +0 -0
  215. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/query.py +0 -0
  216. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/query_engine.py +0 -0
  217. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/engine/stream_events.py +0 -0
  218. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/__init__.py +0 -0
  219. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/events.py +0 -0
  220. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/executor.py +0 -0
  221. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/hot_reload.py +0 -0
  222. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/loader.py +0 -0
  223. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/register_hooks.py +0 -0
  224. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/schemas.py +0 -0
  225. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/session_hooks.py +0 -0
  226. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/types.py +0 -0
  227. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/hooks/utils.py +0 -0
  228. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/mcp/__init__.py +0 -0
  229. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/mcp/client.py +0 -0
  230. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/mcp/config.py +0 -0
  231. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/mcp/types.py +0 -0
  232. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/__init__.py +0 -0
  233. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/manager.py +0 -0
  234. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/memdir.py +0 -0
  235. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/paths.py +0 -0
  236. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/scan.py +0 -0
  237. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/search.py +0 -0
  238. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/memory/types.py +0 -0
  239. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/output_styles/__init__.py +0 -0
  240. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/output_styles/loader.py +0 -0
  241. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/permissions/__init__.py +0 -0
  242. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/permissions/checker.py +0 -0
  243. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/permissions/loader.py +0 -0
  244. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/permissions/modes.py +0 -0
  245. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/permissions/schemas.py +0 -0
  246. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/platforms.py +0 -0
  247. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/__init__.py +0 -0
  248. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/installer.py +0 -0
  249. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/loader.py +0 -0
  250. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/options.py +0 -0
  251. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/schemas.py +0 -0
  252. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/plugins/types.py +0 -0
  253. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/prompts/__init__.py +0 -0
  254. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/prompts/claudemd.py +0 -0
  255. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/prompts/context.py +0 -0
  256. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/prompts/environment.py +0 -0
  257. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/prompts/system_prompt.py +0 -0
  258. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/__init__.py +0 -0
  259. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/adapter.py +0 -0
  260. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/platforms/__init__.py +0 -0
  261. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/platforms/base.py +0 -0
  262. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/platforms/linux.py +0 -0
  263. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/platforms/macos.py +0 -0
  264. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/platforms/windows.py +0 -0
  265. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/proxy/__init__.py +0 -0
  266. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/proxy/env_vars.py +0 -0
  267. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/runtime.py +0 -0
  268. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/symlink_protection.py +0 -0
  269. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/utils.py +0 -0
  270. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/sandbox/violation_store.py +0 -0
  271. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/__init__.py +0 -0
  272. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/__init__.py +0 -0
  273. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/auto_compact.py +0 -0
  274. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/compact_core.py +0 -0
  275. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/compact_prompt.py +0 -0
  276. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/constants.py +0 -0
  277. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/message_ops.py +0 -0
  278. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/microcompact.py +0 -0
  279. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/models.py +0 -0
  280. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/compact/token_utils.py +0 -0
  281. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/cron.py +0 -0
  282. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/cron_scheduler.py +0 -0
  283. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/file_history.py +0 -0
  284. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/lsp/__init__.py +0 -0
  285. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/lsp/client.py +0 -0
  286. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/lsp/config.py +0 -0
  287. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/lsp/manager.py +0 -0
  288. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/lsp/types.py +0 -0
  289. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/session_storage.py +0 -0
  290. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/services/token_estimation.py +0 -0
  291. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/__init__.py +0 -0
  292. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/__init__.py +0 -0
  293. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/batch.md +0 -0
  294. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/debug.md +0 -0
  295. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/loop.md +0 -0
  296. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/remember.md +0 -0
  297. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/simplify.md +0 -0
  298. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/skillify.md +0 -0
  299. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/stuck.md +0 -0
  300. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/update-config.md +0 -0
  301. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/bundled/content/verify.md +0 -0
  302. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/loader.py +0 -0
  303. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/registry.py +0 -0
  304. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/skills/types.py +0 -0
  305. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/state/__init__.py +0 -0
  306. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/state/app_state.py +0 -0
  307. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/state/store.py +0 -0
  308. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/__init__.py +0 -0
  309. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/agent_executor.py +0 -0
  310. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/in_process.py +0 -0
  311. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/subprocess_backend.py +0 -0
  312. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/team_helpers.py +0 -0
  313. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/types.py +0 -0
  314. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/swarm/worktree.py +0 -0
  315. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/__init__.py +0 -0
  316. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/local_agent_task.py +0 -0
  317. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/local_shell_task.py +0 -0
  318. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/manager.py +0 -0
  319. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/stop_task.py +0 -0
  320. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tasks/types.py +0 -0
  321. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/__init__.py +0 -0
  322. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/agent_tool.py +0 -0
  323. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/ask_user_question_tool.py +0 -0
  324. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/base.py +0 -0
  325. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/bash_tool.py +0 -0
  326. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/config_tool.py +0 -0
  327. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/cron_tool.py +0 -0
  328. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/enter_plan_mode_tool.py +0 -0
  329. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/enter_worktree_tool.py +0 -0
  330. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/exit_plan_mode_tool.py +0 -0
  331. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/exit_worktree_tool.py +0 -0
  332. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/file_edit_tool.py +0 -0
  333. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/file_read_tool.py +0 -0
  334. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/file_write_tool.py +0 -0
  335. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/glob_tool.py +0 -0
  336. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/grep_tool.py +0 -0
  337. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/list_mcp_resources_tool.py +0 -0
  338. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/lsp_formatters.py +0 -0
  339. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/lsp_schemas.py +0 -0
  340. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/lsp_tool.py +0 -0
  341. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/mcp_auth_tool.py +0 -0
  342. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/mcp_tool.py +0 -0
  343. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/notebook_edit_tool.py +0 -0
  344. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/powershell_tool.py +0 -0
  345. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/read_mcp_resource_tool.py +0 -0
  346. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/repl_tool.py +0 -0
  347. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/send_message_tool.py +0 -0
  348. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/shell_common.py +0 -0
  349. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/skill_tool.py +0 -0
  350. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/sleep_tool.py +0 -0
  351. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/structured_output_tool.py +0 -0
  352. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_create_tool.py +0 -0
  353. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_get_tool.py +0 -0
  354. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_list_tool.py +0 -0
  355. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_output_tool.py +0 -0
  356. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_stop_tool.py +0 -0
  357. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/task_update_tool.py +0 -0
  358. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/team_create_tool.py +0 -0
  359. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/team_delete_tool.py +0 -0
  360. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/todo_write_tool.py +0 -0
  361. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/tool_search_tool.py +0 -0
  362. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/web_fetch_tool.py +0 -0
  363. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/tools/web_search_tool.py +0 -0
  364. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/__init__.py +0 -0
  365. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/app.py +0 -0
  366. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/backend_host.py +0 -0
  367. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/input.py +0 -0
  368. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/output.py +0 -0
  369. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/permission_dialog.py +0 -0
  370. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/permission_store.py +0 -0
  371. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/protocol.py +0 -0
  372. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/react_launcher.py +0 -0
  373. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/runtime.py +0 -0
  374. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/textual_app.py +0 -0
  375. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/web/__init__.py +0 -0
  376. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/web/server.py +0 -0
  377. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/web/ws_host.py +0 -0
  378. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/ui/web/ws_web_api.py +0 -0
  379. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/utils/__init__.py +0 -0
  380. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/utils/atomic_write.py +0 -0
  381. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/utils/file_state_cache.py +0 -0
  382. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/utils/ripgrep.py +0 -0
  383. {illusion_code-0.2.6 → illusion_code-0.2.7}/src/illusion/utils/shell.py +0 -0
  384. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/__init__.py +0 -0
  385. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_anthropic_client.py +0 -0
  386. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_client.py +0 -0
  387. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_codex_client.py +0 -0
  388. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_effort.py +0 -0
  389. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_fallback/346/217/220/347/244/272.py" +0 -0
  390. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/api/test_openai_client.py +0 -0
  391. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/__init__.py +0 -0
  392. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/feishu/__init__.py +0 -0
  393. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/feishu/test_adapter.py +0 -0
  394. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/feishu/test_commands.py +0 -0
  395. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/feishu/test_session_map.py +0 -0
  396. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/test_base.py +0 -0
  397. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/test_base_commands.py +0 -0
  398. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/test_config.py +0 -0
  399. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/test_pid.py +0 -0
  400. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/test_tool_registration.py +0 -0
  401. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/tools/__init__.py +0 -0
  402. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/tools/test_feishu_doc.py +0 -0
  403. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/tools/test_feishu_drive.py +0 -0
  404. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/weixin/__init__.py +0 -0
  405. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/weixin/test_adapter.py +0 -0
  406. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/weixin/test_config.py +0 -0
  407. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/weixin/test_ilink_api.py +0 -0
  408. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/channels/weixin/test_session_map.py +0 -0
  409. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/init/__init__.py +0 -0
  410. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/init/test_claudemd.py +0 -0
  411. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/init/test_orchestrator.py +0 -0
  412. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/init/test_scanner.py +0 -0
  413. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/init/test_sections.py +0 -0
  414. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/commands/test_effort_command.py +0 -0
  415. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/config/test_i18n.py +0 -0
  416. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/config/test_settings.py +0 -0
  417. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/conftest.py +0 -0
  418. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/engine/test_query_engine.py +0 -0
  419. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/fixtures/fake_mcp_server.py +0 -0
  420. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/integration/test_effort_integration.py +0 -0
  421. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/services/lsp/test_lsp_client.py +0 -0
  422. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/services/lsp/test_lsp_config.py +0 -0
  423. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/services/lsp/test_lsp_manager.py +0 -0
  424. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/services/lsp/test_lsp_types.py +0 -0
  425. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_api/__init__.py +0 -0
  426. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_api/test_client.py +0 -0
  427. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_api/test_codex_client.py +0 -0
  428. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_api/test_compat.py +0 -0
  429. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_api/test_openai_client.py +0 -0
  430. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_auth/test_external.py +0 -0
  431. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_bridge/test_core.py +0 -0
  432. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_bridge/test_session_flow.py +0 -0
  433. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_commands/__init__.py +0 -0
  434. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_commands/test_cli.py +0 -0
  435. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_commands/test_command_flows.py +0 -0
  436. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_commands/test_registry.py +0 -0
  437. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_config/__init__.py +0 -0
  438. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_config/test_paths.py +0 -0
  439. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_config/test_settings.py +0 -0
  440. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_coordinator/test_agent_definitions.py +0 -0
  441. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_coordinator/test_coordinator_mode.py +0 -0
  442. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_engine/__init__.py +0 -0
  443. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_engine/test_media_block.py +0 -0
  444. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_engine/test_query_engine.py +0 -0
  445. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_engine/test_tool_result_media.py +0 -0
  446. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_hooks/__init__.py +0 -0
  447. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_hooks/test_executor.py +0 -0
  448. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_hooks/test_loader_permissions.py +0 -0
  449. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_hooks_skills_plugins_real.py +0 -0
  450. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_mcp/__init__.py +0 -0
  451. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_mcp/test_config_permissions.py +0 -0
  452. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_mcp/test_integration.py +0 -0
  453. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_mcp/test_stdio_flow.py +0 -0
  454. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_memory/__init__.py +0 -0
  455. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_memory/test_manager_permissions.py +0 -0
  456. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_memory/test_memdir.py +0 -0
  457. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_merged_prs_on_autoagent.py +0 -0
  458. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_permissions/__init__.py +0 -0
  459. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_permissions/test_checker.py +0 -0
  460. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_permissions/test_loader.py +0 -0
  461. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_permissions/test_project_permissions.py +0 -0
  462. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_platforms.py +0 -0
  463. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_plugins/__init__.py +0 -0
  464. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_plugins/test_lifecycle_flow.py +0 -0
  465. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_plugins/test_loader.py +0 -0
  466. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_plugins/test_loader_permissions.py +0 -0
  467. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_prompts/__init__.py +0 -0
  468. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_prompts/test_claudemd.py +0 -0
  469. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_prompts/test_claudemd_permissions.py +0 -0
  470. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_prompts/test_environment.py +0 -0
  471. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_prompts/test_system_prompt.py +0 -0
  472. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_qq_channel.py +0 -0
  473. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_real_large_tasks.py +0 -0
  474. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_adapter.py +0 -0
  475. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_config_schema.py +0 -0
  476. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_platform_linux.py +0 -0
  477. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_platform_macos.py +0 -0
  478. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_platform_windows.py +0 -0
  479. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_proxy_env_vars.py +0 -0
  480. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_runtime.py +0 -0
  481. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_symlink_protection.py +0 -0
  482. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_utils.py +0 -0
  483. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_sandbox/test_violation_store.py +0 -0
  484. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_scripts/test_sync_version.py +0 -0
  485. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_services/test_compact.py +0 -0
  486. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_services/test_cron.py +0 -0
  487. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_services/test_cron_scheduler.py +0 -0
  488. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_services/test_session_storage.py +0 -0
  489. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_skills/test_loader.py +0 -0
  490. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_skills/test_loader_permissions.py +0 -0
  491. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/__init__.py +0 -0
  492. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/test_agent_executor.py +0 -0
  493. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/test_imports.py +0 -0
  494. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/test_in_process.py +0 -0
  495. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/test_types.py +0 -0
  496. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_swarm/test_worktree.py +0 -0
  497. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tasks/test_manager.py +0 -0
  498. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/__init__.py +0 -0
  499. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_agent_tool.py +0 -0
  500. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_core_tools.py +0 -0
  501. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_file_read_media.py +0 -0
  502. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_glob_tool.py +0 -0
  503. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_grep_tool.py +0 -0
  504. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_integration.py +0 -0
  505. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_integration_flows.py +0 -0
  506. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_mcp_auth_tool.py +0 -0
  507. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_ripgrep.py +0 -0
  508. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_shell_common.py +0 -0
  509. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_task_tools.py +0 -0
  510. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_team_tools.py +0 -0
  511. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_tools/test_web_fetch_tool.py +0 -0
  512. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/__init__.py +0 -0
  513. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/test_modes.py +0 -0
  514. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/test_permission_store.py +0 -0
  515. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/test_react_backend.py +0 -0
  516. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/test_react_launcher.py +0 -0
  517. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_ui/test_textual_app.py +0 -0
  518. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_untested_features.py +0 -0
  519. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/test_utils/test_shell.py +0 -0
  520. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/ui/test_backend_host.py +0 -0
  521. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/ui/test_protocol_web.py +0 -0
  522. {illusion_code-0.2.6 → illusion_code-0.2.7}/tests/ui/test_web_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: illusion-code
3
- Version: 0.2.6
3
+ Version: 0.2.7
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.6",
3
+ "version": "0.2.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@illusion/terminal",
9
- "version": "0.2.6",
9
+ "version": "0.2.7",
10
10
  "dependencies": {
11
11
  "chalk": "^5.6.2",
12
12
  "ink": "^5.1.0",
@@ -24,5 +24,5 @@
24
24
  "tsx": "^4.19.2",
25
25
  "typescript": "^5.7.3"
26
26
  },
27
- "version": "0.2.6"
27
+ "version": "0.2.7"
28
28
  }
@@ -680,12 +680,15 @@ function wrapForPrefix(text: string, terminalWidth: number, prefix: string): str
680
680
  }
681
681
 
682
682
  function truncateToDisplayWidth(text: string, maxWidth: number): string {
683
- if (stringWidth(text) <= maxWidth) {
684
- return text;
683
+ // tab 替换为空格,因为 string-width 将 tab 算作1字符宽度,
684
+ // 但终端中 tab 会展开为多个空格,导致宽度计算偏小、截断不足
685
+ const expanded = text.replace(/\t/g, ' ');
686
+ if (stringWidth(expanded) <= maxWidth) {
687
+ return expanded;
685
688
  }
686
689
  let result = '';
687
690
  let width = 0;
688
- for (const ch of text) {
691
+ for (const ch of expanded) {
689
692
  const charWidth = stringWidth(ch);
690
693
  if (width + charWidth > Math.max(1, maxWidth - 1)) {
691
694
  break;
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  /** 当前版本号 */
9
- export const VERSION = '0.2.6';
9
+ export const VERSION = '0.2.7';
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@illusion/web",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@illusion/web",
9
- "version": "0.2.6",
9
+ "version": "0.2.7",
10
10
  "dependencies": {
11
11
  "highlight.js": "^11.11.0",
12
12
  "react": "^18.3.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illusion/web",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -53,6 +53,12 @@ export default function App() {
53
53
  // 内联选项状态
54
54
  const [inlineOptions, setInlineOptions] = useState<SelectRequestPayload | null>(null);
55
55
 
56
+ // 回退确认弹窗状态
57
+ const [rewindConfirm, setRewindConfirm] = useState<{ turns: number } | null>(null);
58
+ // 重新生成:存储待重发的 user 消息文本,rewind 完成后自动重发
59
+ const pendingRegenerateRef = useRef<string | null>(null);
60
+ const prevBusyRef = useRef(false);
61
+
56
62
  // Toast 状态
57
63
  const [toastMessage, setToastMessage] = useState<{ text: string; type: 'success' | 'error' | 'info' } | null>(null);
58
64
  const [toastExiting, setToastExiting] = useState(false);
@@ -231,6 +237,57 @@ export default function App() {
231
237
  /** 处理停止当前任务 */
232
238
  const handleStop = () => { session.sendRequest({ type: 'stop' }); };
233
239
 
240
+ /**
241
+ * 处理回退到指定轮次
242
+ *
243
+ * 由 ChatArea 中 user 消息的撤销按钮触发,弹出模式选择弹窗。
244
+ *
245
+ * @param turnsToRewind - 需要回退的轮次数
246
+ */
247
+ const handleRewindToTurn = useCallback((turnsToRewind: number) => {
248
+ setRewindConfirm({ turns: turnsToRewind });
249
+ }, []);
250
+
251
+ /**
252
+ * 确认回退 —— 根据用户选择的模式执行 /rewind N mode
253
+ *
254
+ * 通过 submit_line 通道(treat_as_text 缺省=false)直接走命令注册表,
255
+ * 绕过 web_query 的多步弹窗流程。
256
+ *
257
+ * @param mode - 回退模式:code / conversation / both
258
+ */
259
+ const handleConfirmRewind = useCallback((mode: string) => {
260
+ const turns = rewindConfirm?.turns ?? 1;
261
+ setRewindConfirm(null);
262
+ session.setBusyTrue();
263
+ session.sendRequest({ type: 'submit_line', line: `/rewind ${turns} ${mode}` });
264
+ }, [rewindConfirm, session]);
265
+
266
+ /**
267
+ * 处理重新生成
268
+ *
269
+ * 找到最后一条 user 消息文本,先 /rewind 1 both 回退一轮,
270
+ * rewind 完成后(busy→false)自动重发 user 消息。
271
+ */
272
+ const handleRegenerate = useCallback(() => {
273
+ const lastUserMsg = [...session.staticItems].reverse().find((i) => i.role === 'user' && !i.text.startsWith('/'));
274
+ if (!lastUserMsg) return;
275
+ pendingRegenerateRef.current = lastUserMsg.text;
276
+ session.setBusyTrue();
277
+ session.sendRequest({ type: 'submit_line', line: '/rewind 1 both' });
278
+ }, [session]);
279
+
280
+ // 监听 busy 状态变化:rewind 完成后自动重发 user 消息(重新生成)
281
+ useEffect(() => {
282
+ if (prevBusyRef.current && !session.busy && pendingRegenerateRef.current) {
283
+ const text = pendingRegenerateRef.current;
284
+ pendingRegenerateRef.current = null;
285
+ session.setBusyTrue();
286
+ session.sendRequest({ type: 'submit_line', line: text, treat_as_text: true });
287
+ }
288
+ prevBusyRef.current = session.busy;
289
+ }, [session.busy, session]);
290
+
234
291
  /** 处理新建会话 */
235
292
  const handleNewSession = () => {
236
293
  session.sendRequest({ type: 'web_new_session' });
@@ -345,7 +402,8 @@ export default function App() {
345
402
  streamingReasoning={session.streamingReasoning} pendingToolCalls={session.pendingToolCalls}
346
403
  busy={session.busy} connected={session.connected}
347
404
  modal={session.modal} onPermissionResponse={handlePermissionResponse}
348
- onQuestionResponse={handleQuestionResponse} restoringSessionId={session.restoringSessionId} />
405
+ onQuestionResponse={handleQuestionResponse} restoringSessionId={session.restoringSessionId}
406
+ onRewindToTurn={handleRewindToTurn} onRegenerate={handleRegenerate} />
349
407
  <PromptInput lang={lang} busy={session.busy} connected={session.connected}
350
408
  commands={session.commands} onSubmit={handleSubmit} onStop={handleStop}
351
409
  inlineOptions={inlineOptions} onInlineSelect={handleInlineSelect} onInlineClose={handleInlineClose} />
@@ -407,6 +465,44 @@ export default function App() {
407
465
  </div>
408
466
  )}
409
467
 
468
+ {/* 回退确认弹窗(选择回退范围) */}
469
+ {rewindConfirm && (
470
+ <div className="fixed inset-0 z-50 flex items-center justify-center">
471
+ <div className="absolute inset-0 bg-black/35 backdrop-blur-md animate-fade-in" onClick={() => setRewindConfirm(null)} />
472
+ <div className="relative glass-overlay rounded-2xl w-[380px] flex flex-col animate-scale-in modal-origin-center">
473
+ <div className="px-6 py-4 border-b border-border-light">
474
+ <h3 className="text-lg font-semibold text-content-primary">{t(lang, 'rewind_confirm_title')}</h3>
475
+ </div>
476
+ <div className="py-2 px-1">
477
+ {([
478
+ { mode: 'both', label: t(lang, 'rewind_both'), desc: t(lang, 'rewind_both_desc') },
479
+ { mode: 'conversation', label: t(lang, 'rewind_conversation'), desc: t(lang, 'rewind_conversation_desc') },
480
+ { mode: 'code', label: t(lang, 'rewind_code'), desc: t(lang, 'rewind_code_desc') },
481
+ ] as const).map((opt) => (
482
+ <button
483
+ key={opt.mode}
484
+ onClick={() => handleConfirmRewind(opt.mode)}
485
+ className="w-full text-left px-6 py-3 cursor-pointer glass-option-hover transition-colors rounded-lg flex items-center justify-between group"
486
+ >
487
+ <div>
488
+ <div className="text-sm font-medium text-content-primary">{opt.label}</div>
489
+ <div className="text-xs text-content-disabled mt-0.5">{opt.desc}</div>
490
+ </div>
491
+ <svg className="w-4 h-4 text-content-disabled opacity-0 group-hover:opacity-100 transition-opacity" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
492
+ <path d="M6 3l5 5-5 5" />
493
+ </svg>
494
+ </button>
495
+ ))}
496
+ </div>
497
+ <div className="px-6 py-4 border-t border-border-light flex justify-end">
498
+ <button onClick={() => setRewindConfirm(null)} className="px-4 py-2 text-sm text-content-secondary glass-option-hover rounded-lg transition-colors cursor-pointer border border-white/40">
499
+ {t(lang, 'cancel')}
500
+ </button>
501
+ </div>
502
+ </div>
503
+ </div>
504
+ )}
505
+
410
506
  {/* Toast 通知 */}
411
507
  {toastMessage && (
412
508
  <div
@@ -0,0 +1,428 @@
1
+ /**
2
+ * @fileoverview 聊天区域组件
3
+ *
4
+ * Web 前端的主要对话显示区域,负责:
5
+ * - 显示对话历史(按轮次分组)
6
+ * - 显示待处理的工具调用
7
+ * - 显示流式回复和思考过程
8
+ * - 显示权限确认和问答模态框
9
+ * - 自动滚动到底部
10
+ *
11
+ * @module ChatArea
12
+ */
13
+
14
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
+ import { t, type UiLanguage } from '../i18n';
16
+ import MessageBubble, { PendingToolBubble, StreamingBuffer, ReasoningContent } from './MessageBubble';
17
+ import WelcomeScreen from './WelcomeScreen';
18
+ import { PermissionCard, QuestionCard } from './ModalCard';
19
+ import type { TranscriptItem, PendingToolCall } from '../types/protocol';
20
+
21
+ /** 消息列表收缩阈值:超过此轮次时折叠更早的消息 */
22
+ const COLLAPSE_TURN_THRESHOLD = 5;
23
+ /** 判定"已在底部"的像素容差 */
24
+ const BOTTOM_THRESHOLD_PX = 80;
25
+
26
+ /**
27
+ * 将一轮对话的 items 拆分为三部分:
28
+ * - userItems:用户消息(始终可见)
29
+ * - thinkingItems:工具调用 + 中间 assistant 消息(归入"思考过程"可折叠区)
30
+ * - finalAssistant:最后一条含文本的 assistant 消息(始终可见,其 reasoning 归入思考区)
31
+ *
32
+ * @param items - 单轮转录项列表
33
+ * @returns 拆分结果
34
+ */
35
+ function splitTurnItems(items: TranscriptItem[]) {
36
+ const userItems: TranscriptItem[] = [];
37
+ const thinkingItems: TranscriptItem[] = [];
38
+ let finalAssistant: TranscriptItem | null = null;
39
+
40
+ // 找到最后一条有非空 text 的 assistant 消息作为"最终回复"
41
+ let lastAssistantIdx = -1;
42
+ for (let i = items.length - 1; i >= 0; i--) {
43
+ if (items[i]!.role === 'assistant' && items[i]!.text.trim()) {
44
+ lastAssistantIdx = i;
45
+ break;
46
+ }
47
+ }
48
+
49
+ for (let i = 0; i < items.length; i++) {
50
+ const item = items[i]!;
51
+ if (item.role === 'user') {
52
+ userItems.push(item);
53
+ } else if (i === lastAssistantIdx) {
54
+ finalAssistant = item;
55
+ } else {
56
+ thinkingItems.push(item);
57
+ }
58
+ }
59
+
60
+ return { userItems, thinkingItems, finalAssistant };
61
+ }
62
+
63
+ /**
64
+ * 思考过程折叠区组件
65
+ *
66
+ * 将一轮对话中的工具调用、中间 assistant 消息、最终 assistant 的 reasoning
67
+ * 统一收纳进一个可折叠的"思考过程"区域,减少历史消息的浏览器渲染负担。
68
+ *
69
+ * 流式输出阶段(autoExpand=true)自动展开,完成后自动折叠。
70
+ *
71
+ * @param props.thinkingItems - 工具调用 + 中间消息
72
+ * @param props.finalReasoning - 最终 assistant 的 reasoning 文本
73
+ * @param props.lang - UI 语言
74
+ * @param props.toolInputMap - 工具输入映射
75
+ * @param props.autoExpand - 是否自动展开(流式阶段)
76
+ */
77
+ function ThinkingProcessSection({
78
+ thinkingItems,
79
+ finalReasoning,
80
+ lang,
81
+ toolInputMap,
82
+ autoExpand,
83
+ onToggle,
84
+ }: {
85
+ thinkingItems: TranscriptItem[];
86
+ finalReasoning?: string;
87
+ lang: UiLanguage;
88
+ toolInputMap: Map<string, Record<string, unknown>>;
89
+ autoExpand: boolean;
90
+ onToggle?: () => void;
91
+ }) {
92
+ const [open, setOpen] = useState(autoExpand);
93
+ const prevAutoExpand = useRef(autoExpand);
94
+
95
+ // autoExpand 变化时(流式开始/结束)自动同步展开状态
96
+ if (autoExpand !== prevAutoExpand.current) {
97
+ prevAutoExpand.current = autoExpand;
98
+ setOpen(autoExpand);
99
+ }
100
+
101
+ const hasContent = thinkingItems.length > 0 || !!finalReasoning?.trim();
102
+ if (!hasContent) return null;
103
+
104
+ const stepCount = thinkingItems.length + (finalReasoning?.trim() ? 1 : 0);
105
+ const label = t(lang, 'thinking_process_count').replace('{count}', String(stepCount));
106
+
107
+ const handleToggle = () => {
108
+ setOpen(!open);
109
+ onToggle?.();
110
+ };
111
+
112
+ return (
113
+ <div className="my-1">
114
+ {autoExpand ? (
115
+ // 流式输出阶段:仅显示标题,不渲染可点击的折叠按钮,避免用户误操作
116
+ <div className="flex items-center gap-1.5 text-xs text-content-secondary py-1">
117
+ <svg className="w-3 h-3 rotate-90" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
118
+ <path d="M4.5 2.5L8 6L4.5 9.5" />
119
+ </svg>
120
+ <span className="font-medium">{label}</span>
121
+ </div>
122
+ ) : (
123
+ <button
124
+ onClick={handleToggle}
125
+ className="flex items-center gap-1.5 text-xs text-content-secondary hover:text-content-primary transition-colors py-1 cursor-pointer"
126
+ >
127
+ <svg
128
+ className={`w-3 h-3 transition-transform duration-150 ${open ? 'rotate-90' : ''}`}
129
+ viewBox="0 0 12 12"
130
+ fill="none"
131
+ stroke="currentColor"
132
+ strokeWidth="1.5"
133
+ strokeLinecap="round"
134
+ strokeLinejoin="round"
135
+ >
136
+ <path d="M4.5 2.5L8 6L4.5 9.5" />
137
+ </svg>
138
+ <span className="font-medium">{label}</span>
139
+ </button>
140
+ )}
141
+ {open && (
142
+ <div className="mt-1.5 animate-fade-in-up">
143
+ {thinkingItems.map((item, idx) => (
144
+ <MessageBubble key={idx} item={item} toolInputMap={toolInputMap} lang={lang} showActions={false} inlineReasoning />
145
+ ))}
146
+ {finalReasoning?.trim() && <ReasoningContent text={finalReasoning} />}
147
+ </div>
148
+ )}
149
+ </div>
150
+ );
151
+ }
152
+
153
+ /**
154
+ * 从 staticItems 中提取 tool_use_id → tool_input 映射
155
+ *
156
+ * @param items - 转录项列表
157
+ * @returns tool_use_id 到 tool_input 的映射
158
+ */
159
+ function buildToolInputMap(items: TranscriptItem[]): Map<string, Record<string, unknown>> {
160
+ const map = new Map<string, Record<string, unknown>>();
161
+ for (const item of items) {
162
+ if (item.role === 'tool' && item.tool_use_id && item.tool_input) {
163
+ map.set(item.tool_use_id, item.tool_input);
164
+ }
165
+ }
166
+ return map;
167
+ }
168
+
169
+ /**
170
+ * ChatArea 组件属性接口
171
+ */
172
+ interface ChatAreaProps {
173
+ /** 当前 UI 语言 */
174
+ lang: UiLanguage;
175
+ /** 静态转录项列表 */
176
+ staticItems: TranscriptItem[];
177
+ /** 助手回复缓冲区 */
178
+ assistantBuffer: string;
179
+ /** 流式推理文本 */
180
+ streamingReasoning: string;
181
+ /** 待处理的工具调用列表 */
182
+ pendingToolCalls: PendingToolCall[];
183
+ /** 是否忙碌 */
184
+ busy: boolean;
185
+ /** 是否已连接 */
186
+ connected: boolean;
187
+ /** 模态对话框配置 */
188
+ modal: Record<string, unknown> | null;
189
+ /** 权限响应回调 */
190
+ onPermissionResponse: (requestId: string, allowed: boolean, alwaysAllow: boolean, toolName: string) => void;
191
+ /** 问答响应回调 */
192
+ onQuestionResponse: (requestId: string, answer: string) => void;
193
+ /** 正在恢复的会话 ID(可选,非空时显示居中加载卡片覆盖转录区) */
194
+ restoringSessionId?: string | null;
195
+ /** 撤销到指定轮次回调(参数为待回退轮次数) */
196
+ onRewindToTurn?: (turnsToRewind: number) => void;
197
+ /** 重新生成回调(回退最后一轮并重发 user 消息) */
198
+ onRegenerate?: () => void;
199
+ }
200
+
201
+ /**
202
+ * 聊天区域组件
203
+ *
204
+ * Web 前端的主要对话显示区域。
205
+ *
206
+ * @param props - 组件属性
207
+ * @returns 返回聊天区域的 JSX 元素
208
+ */
209
+ export default function ChatArea({
210
+ lang, staticItems, assistantBuffer, streamingReasoning, pendingToolCalls, busy, connected,
211
+ modal, onPermissionResponse, onQuestionResponse, restoringSessionId, onRewindToTurn, onRegenerate,
212
+ }: ChatAreaProps) {
213
+ const scrollRef = useRef<HTMLDivElement>(null);
214
+ const [showScrollDown, setShowScrollDown] = useState(false);
215
+ const [expanded, setExpanded] = useState(false);
216
+ const userScrolledUpRef = useRef(false);
217
+
218
+ // 按用户消息分组为轮次(turn),每轮以用户消息开头
219
+ // 注意:hooks 必须在任何条件返回之前调用(React Rules of Hooks)
220
+ const turns = useMemo(() => {
221
+ const result: TranscriptItem[][] = [];
222
+ for (const item of staticItems) {
223
+ if (item.role === 'user' || result.length === 0) {
224
+ result.push([item]);
225
+ } else {
226
+ result[result.length - 1]!.push(item);
227
+ }
228
+ }
229
+ return result;
230
+ }, [staticItems]);
231
+
232
+ // 消息列表收缩:超过阈值时仅展示最新 N 轮,其余折叠
233
+ const { visibleTurns, hiddenCount } = useMemo(() => {
234
+ if (expanded || turns.length <= COLLAPSE_TURN_THRESHOLD) {
235
+ return { visibleTurns: turns, hiddenCount: 0 };
236
+ }
237
+ return {
238
+ visibleTurns: turns.slice(turns.length - COLLAPSE_TURN_THRESHOLD),
239
+ hiddenCount: turns.length - COLLAPSE_TURN_THRESHOLD,
240
+ };
241
+ }, [turns, expanded]);
242
+
243
+ // 计算可见轮次在原 turns 中的起始偏移
244
+ const turnOffset = turns.length - visibleTurns.length;
245
+
246
+ // tool_use_id → tool_input 映射,用于 tool_result 摘要显示
247
+ const toolInputMap = useMemo(() => buildToolInputMap(staticItems), [staticItems]);
248
+
249
+ /** 检查滚动容器是否在底部附近 */
250
+ const isNearBottom = useCallback(() => {
251
+ const el = scrollRef.current;
252
+ if (!el) return true;
253
+ const max = el.scrollHeight - el.clientHeight;
254
+ return el.scrollTop >= max - BOTTOM_THRESHOLD_PX;
255
+ }, []);
256
+
257
+ /** 滚动事件处理:跟踪用户是否手动上滑 */
258
+ const handleScroll = useCallback(() => {
259
+ const nearBottom = isNearBottom();
260
+ userScrolledUpRef.current = !nearBottom;
261
+ setShowScrollDown(!nearBottom && scrollRef.current ? scrollRef.current.scrollHeight - scrollRef.current.clientHeight > 200 : false);
262
+ }, [isNearBottom]);
263
+
264
+ /** 一键回到底部 */
265
+ const scrollToBottom = useCallback(() => {
266
+ const el = scrollRef.current;
267
+ if (!el) return;
268
+ el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
269
+ userScrolledUpRef.current = false;
270
+ setShowScrollDown(false);
271
+ }, []);
272
+
273
+ // 内容变化时自动滚动到底部(仅当用户未手动上滑时)
274
+ useEffect(() => {
275
+ if (userScrolledUpRef.current) return;
276
+ const el = scrollRef.current;
277
+ if (!el) return;
278
+ el.scrollTop = el.scrollHeight;
279
+ }, [staticItems, assistantBuffer, streamingReasoning, pendingToolCalls, modal]);
280
+
281
+ // 新会话或恢复后重置展开状态
282
+ useEffect(() => {
283
+ setExpanded(false);
284
+ userScrolledUpRef.current = false;
285
+ }, [staticItems.length === 0]);
286
+
287
+ const hasContent = staticItems.length > 0 || assistantBuffer || streamingReasoning || pendingToolCalls.length > 0 || !!modal;
288
+
289
+ // 会话恢复中:显示居中加载卡片,覆盖正常转录区
290
+ // 此条件返回在所有 hooks 之后,不违反 React Rules of Hooks
291
+ if (restoringSessionId) {
292
+ return (
293
+ <div className="flex-1 flex items-center justify-center">
294
+ <div className="flex flex-col items-center gap-3">
295
+ <svg className="animate-spin w-8 h-8 text-primary" viewBox="0 0 24 24" fill="none">
296
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
297
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
298
+ </svg>
299
+ <span className="text-sm text-content-secondary">{t(lang, 'restoring_session')}</span>
300
+ </div>
301
+ </div>
302
+ );
303
+ }
304
+
305
+ return (
306
+ <div className="flex-1 overflow-y-auto relative" ref={scrollRef} onScroll={handleScroll}>
307
+ {!connected && !hasContent && (
308
+ <div className="flex items-center justify-center h-full text-content-disabled text-sm font-medium">
309
+ {t(lang, 'connecting')}
310
+ </div>
311
+ )}
312
+ {connected && !hasContent && (
313
+ <WelcomeScreen lang={lang} />
314
+ )}
315
+
316
+ <div className="mx-auto max-w-5xl px-6 md:px-10 lg:px-16 py-6">
317
+ {/* 折叠的更早消息入口 */}
318
+ {hiddenCount > 0 && (
319
+ <div className="flex justify-center mb-6">
320
+ <button
321
+ onClick={() => setExpanded(true)}
322
+ className="px-4 py-2 text-sm text-content-secondary hover:text-content-primary glass-surface rounded-full transition-colors cursor-pointer hover:scale-105 active:scale-95"
323
+ >
324
+ {t(lang, 'show_earlier').replace('{count}', String(hiddenCount))}
325
+ </button>
326
+ </div>
327
+ )}
328
+
329
+ {visibleTurns.map((turn, visIdx) => {
330
+ const turnIdx = turnOffset + visIdx;
331
+ const isLastTurn = turnIdx === turns.length - 1;
332
+ const { userItems, thinkingItems, finalAssistant } = splitTurnItems(turn);
333
+ const autoExpand = busy && isLastTurn;
334
+ const turnsToRewind = turns.length - turnIdx;
335
+ return (
336
+ <div key={turnIdx} className={visIdx > 0 ? 'mt-12' : ''}>
337
+ {userItems.map((item, msgIdx) => (
338
+ <MessageBubble
339
+ key={`u-${turnIdx}-${msgIdx}`}
340
+ item={item}
341
+ lang={lang}
342
+ onRewind={onRewindToTurn ? () => onRewindToTurn(turnsToRewind) : undefined}
343
+ actionsDisabled={busy}
344
+ />
345
+ ))}
346
+ <ThinkingProcessSection
347
+ thinkingItems={thinkingItems}
348
+ finalReasoning={finalAssistant?.reasoning}
349
+ lang={lang}
350
+ toolInputMap={toolInputMap}
351
+ autoExpand={autoExpand}
352
+ onToggle={isLastTurn ? () => {
353
+ // 切换折叠后延迟滚动到底部,等待 DOM 更新完成
354
+ setTimeout(() => {
355
+ const el = scrollRef.current;
356
+ if (el) el.scrollTop = el.scrollHeight;
357
+ }, 0);
358
+ } : undefined}
359
+ />
360
+ {finalAssistant && (
361
+ <MessageBubble
362
+ key={`f-${turnIdx}`}
363
+ item={finalAssistant}
364
+ toolInputMap={toolInputMap}
365
+ lang={lang}
366
+ hideReasoning
367
+ onRegenerate={isLastTurn ? onRegenerate : undefined}
368
+ actionsDisabled={busy}
369
+ />
370
+ )}
371
+ </div>
372
+ );
373
+ })}
374
+ {pendingToolCalls.length > 0 && (
375
+ <div className={turns.length > 0 ? 'mt-4' : ''}>
376
+ {pendingToolCalls.map((call) => (
377
+ <PendingToolBubble key={call.tool_use_id} call={call} />
378
+ ))}
379
+ </div>
380
+ )}
381
+ {busy && !assistantBuffer && !streamingReasoning && pendingToolCalls.length === 0 && (
382
+ <div className={turns.length > 0 ? 'mt-4' : ''}>
383
+ <ThinkingIndicator lang={lang} />
384
+ </div>
385
+ )}
386
+ {busy && (assistantBuffer || streamingReasoning) && (
387
+ <div className={turns.length > 0 ? 'mt-4' : ''}>
388
+ <StreamingBuffer text={assistantBuffer} reasoning={streamingReasoning} />
389
+ </div>
390
+ )}
391
+ {modal?.kind === 'permission' && (
392
+ <PermissionCard modal={modal} lang={lang} onRespond={onPermissionResponse} />
393
+ )}
394
+ {modal?.kind === 'question' && (
395
+ <QuestionCard modal={modal} lang={lang} onRespond={onQuestionResponse} />
396
+ )}
397
+ </div>
398
+
399
+ {/* 一键回到底部浮动按钮 */}
400
+ {showScrollDown && (
401
+ <button
402
+ onClick={scrollToBottom}
403
+ className="fixed bottom-36 left-1/2 -translate-x-1/2 z-30 w-9 h-9 flex items-center justify-center rounded-full glass-surface text-content-secondary hover:text-content-primary shadow-lg transition-all duration-200 hover:scale-110 active:scale-95 cursor-pointer animate-fade-in-up"
404
+ title={t(lang, 'scroll_to_bottom')}
405
+ >
406
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
407
+ <path d="M12 5v14M5 12l7 7 7-7" />
408
+ </svg>
409
+ </button>
410
+ )}
411
+ </div>
412
+ );
413
+ }
414
+
415
+ function ThinkingIndicator({ lang }: { lang: UiLanguage }) {
416
+ return (
417
+ <div className="flex items-center gap-2.5 py-2">
418
+ <span className="flex gap-1">
419
+ <span className="w-1.5 h-1.5 rounded-full bg-primary animate-bounce" style={{ animationDelay: '0ms' }} />
420
+ <span className="w-1.5 h-1.5 rounded-full bg-primary animate-bounce" style={{ animationDelay: '150ms' }} />
421
+ <span className="w-1.5 h-1.5 rounded-full bg-primary animate-bounce" style={{ animationDelay: '300ms' }} />
422
+ </span>
423
+ <span className="text-xs text-content-secondary animate-pulse">
424
+ {t(lang, 'thinking')}
425
+ </span>
426
+ </div>
427
+ );
428
+ }