illusion-code 0.1.0__py3-none-any.whl

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 (214) hide show
  1. illusion/__init__.py +24 -0
  2. illusion/__main__.py +15 -0
  3. illusion/_frontend/dist/index.mjs +39208 -0
  4. illusion/_frontend/package.json +27 -0
  5. illusion/_frontend/src/App.tsx +624 -0
  6. illusion/_frontend/src/components/CommandPicker.tsx +98 -0
  7. illusion/_frontend/src/components/Composer.tsx +55 -0
  8. illusion/_frontend/src/components/ComposerController.tsx +128 -0
  9. illusion/_frontend/src/components/ConversationView.tsx +750 -0
  10. illusion/_frontend/src/components/Footer.tsx +25 -0
  11. illusion/_frontend/src/components/MarkdownContent.tsx +537 -0
  12. illusion/_frontend/src/components/MarkdownTable.tsx +245 -0
  13. illusion/_frontend/src/components/ModalHost.tsx +425 -0
  14. illusion/_frontend/src/components/MultilineTextInput.tsx +250 -0
  15. illusion/_frontend/src/components/PromptInput.tsx +64 -0
  16. illusion/_frontend/src/components/SelectModal.tsx +78 -0
  17. illusion/_frontend/src/components/SidePanel.tsx +175 -0
  18. illusion/_frontend/src/components/Spinner.tsx +77 -0
  19. illusion/_frontend/src/components/StatusBar.tsx +142 -0
  20. illusion/_frontend/src/components/SwarmPanel.tsx +141 -0
  21. illusion/_frontend/src/components/TodoPanel.tsx +126 -0
  22. illusion/_frontend/src/components/ToolCallDisplay.tsx +202 -0
  23. illusion/_frontend/src/components/TranscriptPane.tsx +79 -0
  24. illusion/_frontend/src/components/WelcomeBanner.tsx +37 -0
  25. illusion/_frontend/src/hooks/useBackendSession.ts +468 -0
  26. illusion/_frontend/src/hooks/useTerminalSize.ts +9 -0
  27. illusion/_frontend/src/i18n.ts +78 -0
  28. illusion/_frontend/src/index.tsx +42 -0
  29. illusion/_frontend/src/theme/ThemeContext.tsx +19 -0
  30. illusion/_frontend/src/theme/builtinThemes.ts +89 -0
  31. illusion/_frontend/src/types.ts +110 -0
  32. illusion/_frontend/src/utils/markdown.ts +33 -0
  33. illusion/_frontend/src/utils/thinking.ts +191 -0
  34. illusion/_frontend/tsconfig.json +13 -0
  35. illusion/_web_dist/assets/index-BseIw-ik.css +10 -0
  36. illusion/_web_dist/assets/index-C_0ZWMuW.js +82 -0
  37. illusion/_web_dist/index.html +16 -0
  38. illusion/api/__init__.py +36 -0
  39. illusion/api/client.py +568 -0
  40. illusion/api/codex_client.py +563 -0
  41. illusion/api/compat.py +138 -0
  42. illusion/api/effort.py +128 -0
  43. illusion/api/errors.py +57 -0
  44. illusion/api/openai_client.py +819 -0
  45. illusion/api/provider.py +148 -0
  46. illusion/api/registry.py +479 -0
  47. illusion/api/usage.py +45 -0
  48. illusion/auth/__init__.py +50 -0
  49. illusion/auth/copilot.py +419 -0
  50. illusion/auth/external.py +612 -0
  51. illusion/auth/flows.py +58 -0
  52. illusion/auth/manager.py +214 -0
  53. illusion/auth/storage.py +372 -0
  54. illusion/bridge/__init__.py +38 -0
  55. illusion/bridge/manager.py +190 -0
  56. illusion/bridge/session_runner.py +84 -0
  57. illusion/bridge/types.py +113 -0
  58. illusion/bridge/work_secret.py +131 -0
  59. illusion/cli.py +1228 -0
  60. illusion/commands/__init__.py +32 -0
  61. illusion/commands/registry.py +1934 -0
  62. illusion/config/__init__.py +39 -0
  63. illusion/config/i18n.py +522 -0
  64. illusion/config/paths.py +259 -0
  65. illusion/config/settings.py +564 -0
  66. illusion/coordinator/__init__.py +41 -0
  67. illusion/coordinator/agent_definitions.py +1093 -0
  68. illusion/coordinator/coordinator_mode.py +127 -0
  69. illusion/engine/__init__.py +95 -0
  70. illusion/engine/cost_tracker.py +55 -0
  71. illusion/engine/messages.py +369 -0
  72. illusion/engine/query.py +632 -0
  73. illusion/engine/query_engine.py +343 -0
  74. illusion/engine/stream_events.py +169 -0
  75. illusion/hooks/__init__.py +67 -0
  76. illusion/hooks/events.py +43 -0
  77. illusion/hooks/executor.py +397 -0
  78. illusion/hooks/hot_reload.py +74 -0
  79. illusion/hooks/loader.py +133 -0
  80. illusion/hooks/schemas.py +121 -0
  81. illusion/hooks/types.py +86 -0
  82. illusion/mcp/__init__.py +104 -0
  83. illusion/mcp/client.py +377 -0
  84. illusion/mcp/config.py +140 -0
  85. illusion/mcp/types.py +175 -0
  86. illusion/memory/__init__.py +36 -0
  87. illusion/memory/manager.py +94 -0
  88. illusion/memory/memdir.py +58 -0
  89. illusion/memory/paths.py +57 -0
  90. illusion/memory/scan.py +120 -0
  91. illusion/memory/search.py +83 -0
  92. illusion/memory/types.py +43 -0
  93. illusion/output_styles/__init__.py +15 -0
  94. illusion/output_styles/loader.py +64 -0
  95. illusion/permissions/__init__.py +39 -0
  96. illusion/permissions/checker.py +174 -0
  97. illusion/permissions/modes.py +38 -0
  98. illusion/platforms.py +148 -0
  99. illusion/plugins/__init__.py +71 -0
  100. illusion/plugins/bundled/__init__.py +0 -0
  101. illusion/plugins/installer.py +59 -0
  102. illusion/plugins/loader.py +301 -0
  103. illusion/plugins/schemas.py +51 -0
  104. illusion/plugins/types.py +56 -0
  105. illusion/prompts/__init__.py +29 -0
  106. illusion/prompts/claudemd.py +74 -0
  107. illusion/prompts/context.py +187 -0
  108. illusion/prompts/environment.py +189 -0
  109. illusion/prompts/system_prompt.py +155 -0
  110. illusion/py.typed +0 -0
  111. illusion/sandbox/__init__.py +29 -0
  112. illusion/sandbox/adapter.py +174 -0
  113. illusion/services/__init__.py +59 -0
  114. illusion/services/compact/__init__.py +1015 -0
  115. illusion/services/cron.py +338 -0
  116. illusion/services/cron_scheduler.py +715 -0
  117. illusion/services/file_history.py +258 -0
  118. illusion/services/lsp/__init__.py +455 -0
  119. illusion/services/session_storage.py +237 -0
  120. illusion/services/token_estimation.py +72 -0
  121. illusion/skills/__init__.py +60 -0
  122. illusion/skills/bundled/__init__.py +110 -0
  123. illusion/skills/bundled/content/batch.md +86 -0
  124. illusion/skills/bundled/content/coding-guidelines.md +70 -0
  125. illusion/skills/bundled/content/debug.md +38 -0
  126. illusion/skills/bundled/content/loop.md +82 -0
  127. illusion/skills/bundled/content/remember.md +105 -0
  128. illusion/skills/bundled/content/simplify.md +53 -0
  129. illusion/skills/bundled/content/skillify.md +113 -0
  130. illusion/skills/bundled/content/stuck.md +54 -0
  131. illusion/skills/bundled/content/update-config.md +329 -0
  132. illusion/skills/bundled/content/verify.md +74 -0
  133. illusion/skills/loader.py +219 -0
  134. illusion/skills/registry.py +40 -0
  135. illusion/skills/types.py +24 -0
  136. illusion/state/__init__.py +18 -0
  137. illusion/state/app_state.py +67 -0
  138. illusion/state/store.py +93 -0
  139. illusion/swarm/__init__.py +71 -0
  140. illusion/swarm/agent_executor.py +857 -0
  141. illusion/swarm/in_process.py +259 -0
  142. illusion/swarm/subprocess_backend.py +136 -0
  143. illusion/swarm/team_helpers.py +123 -0
  144. illusion/swarm/types.py +159 -0
  145. illusion/swarm/worktree.py +347 -0
  146. illusion/tasks/__init__.py +33 -0
  147. illusion/tasks/local_agent_task.py +42 -0
  148. illusion/tasks/local_shell_task.py +27 -0
  149. illusion/tasks/manager.py +377 -0
  150. illusion/tasks/stop_task.py +21 -0
  151. illusion/tasks/types.py +88 -0
  152. illusion/tools/__init__.py +126 -0
  153. illusion/tools/agent_tool.py +388 -0
  154. illusion/tools/ask_user_question_tool.py +186 -0
  155. illusion/tools/base.py +149 -0
  156. illusion/tools/bash_tool.py +413 -0
  157. illusion/tools/config_tool.py +90 -0
  158. illusion/tools/cron_tool.py +473 -0
  159. illusion/tools/enter_plan_mode_tool.py +147 -0
  160. illusion/tools/enter_worktree_tool.py +188 -0
  161. illusion/tools/exit_plan_mode_tool.py +69 -0
  162. illusion/tools/exit_worktree_tool.py +225 -0
  163. illusion/tools/file_edit_tool.py +283 -0
  164. illusion/tools/file_read_tool.py +294 -0
  165. illusion/tools/file_write_tool.py +184 -0
  166. illusion/tools/glob_tool.py +165 -0
  167. illusion/tools/grep_tool.py +190 -0
  168. illusion/tools/list_mcp_resources_tool.py +80 -0
  169. illusion/tools/lsp_tool.py +333 -0
  170. illusion/tools/mcp_auth_tool.py +100 -0
  171. illusion/tools/mcp_tool.py +75 -0
  172. illusion/tools/notebook_edit_tool.py +242 -0
  173. illusion/tools/powershell_tool.py +334 -0
  174. illusion/tools/read_mcp_resource_tool.py +63 -0
  175. illusion/tools/repl_tool.py +100 -0
  176. illusion/tools/send_message_tool.py +112 -0
  177. illusion/tools/shell_common.py +187 -0
  178. illusion/tools/skill_tool.py +86 -0
  179. illusion/tools/sleep_tool.py +62 -0
  180. illusion/tools/structured_output_tool.py +58 -0
  181. illusion/tools/task_create_tool.py +98 -0
  182. illusion/tools/task_get_tool.py +94 -0
  183. illusion/tools/task_list_tool.py +94 -0
  184. illusion/tools/task_output_tool.py +55 -0
  185. illusion/tools/task_stop_tool.py +52 -0
  186. illusion/tools/task_update_tool.py +224 -0
  187. illusion/tools/team_create_tool.py +236 -0
  188. illusion/tools/team_delete_tool.py +104 -0
  189. illusion/tools/todo_write_tool.py +198 -0
  190. illusion/tools/tool_search_tool.py +156 -0
  191. illusion/tools/web_fetch_tool.py +264 -0
  192. illusion/tools/web_search_tool.py +186 -0
  193. illusion/ui/__init__.py +23 -0
  194. illusion/ui/app.py +258 -0
  195. illusion/ui/backend_host.py +1180 -0
  196. illusion/ui/input.py +86 -0
  197. illusion/ui/output.py +363 -0
  198. illusion/ui/permission_dialog.py +47 -0
  199. illusion/ui/permission_store.py +99 -0
  200. illusion/ui/protocol.py +384 -0
  201. illusion/ui/react_launcher.py +280 -0
  202. illusion/ui/runtime.py +787 -0
  203. illusion/ui/textual_app.py +603 -0
  204. illusion/ui/web/__init__.py +10 -0
  205. illusion/ui/web/server.py +87 -0
  206. illusion/ui/web/ws_host.py +1197 -0
  207. illusion/utils/__init__.py +0 -0
  208. illusion/utils/ripgrep.py +299 -0
  209. illusion/utils/shell.py +248 -0
  210. illusion_code-0.1.0.dist-info/METADATA +1159 -0
  211. illusion_code-0.1.0.dist-info/RECORD +214 -0
  212. illusion_code-0.1.0.dist-info/WHEEL +4 -0
  213. illusion_code-0.1.0.dist-info/entry_points.txt +2 -0
  214. illusion_code-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import {Box, Text} from 'ink';
3
+
4
+ import {useTheme} from '../theme/ThemeContext.js';
5
+
6
+ const MAX_VISIBLE = 6;
7
+
8
+ type CommandPickerMode = 'hints' | 'result';
9
+
10
+ type CommandPickerProps = {
11
+ hints?: string[];
12
+ selectedIndex?: number;
13
+ totalCommands?: number;
14
+ /** 结果模式:显示指令执行结果 */
15
+ mode?: CommandPickerMode;
16
+ result?: string;
17
+ resultType?: 'success' | 'error' | 'info';
18
+ };
19
+
20
+ export function CommandPicker({
21
+ hints,
22
+ selectedIndex,
23
+ mode = 'hints',
24
+ result,
25
+ }: CommandPickerProps): React.JSX.Element | null {
26
+ const theme = useTheme();
27
+
28
+ // 结果模式:显示指令执行结果
29
+ if (mode === 'result' && result) {
30
+ const lines = result.split('\n');
31
+ const displayLines = lines.slice(0, MAX_VISIBLE);
32
+
33
+ return (
34
+ <Box flexDirection="column" marginTop={1} borderStyle="round" borderColor={theme.colors.illusion} paddingX={1}>
35
+ {displayLines.map((line, i) => (
36
+ <Text key={i} color={theme.colors.illusion}>{line}</Text>
37
+ ))}
38
+ {lines.length > MAX_VISIBLE ? (
39
+ <Text color={theme.colors.illusion} dimColor>
40
+ {' '}... +{lines.length - MAX_VISIBLE} more lines
41
+ </Text>
42
+ ) : null}
43
+ <Text dimColor>
44
+ <Text color={theme.colors.muted}>esc</Text> dismiss
45
+ <Text> {theme.icons.middleDot} </Text>
46
+ <Text color={theme.colors.muted}>ctrl+o</Text> show full
47
+ </Text>
48
+ </Box>
49
+ );
50
+ }
51
+
52
+ // 提示模式:显示命令提示列表
53
+ if (!hints || hints.length === 0) {
54
+ return null;
55
+ }
56
+
57
+ const safeSelectedIndex = selectedIndex ?? 0;
58
+ const startIndex = Math.max(
59
+ 0,
60
+ Math.min(
61
+ safeSelectedIndex - Math.floor(MAX_VISIBLE / 2),
62
+ hints.length - MAX_VISIBLE,
63
+ ),
64
+ );
65
+ const endIndex = Math.min(startIndex + MAX_VISIBLE, hints.length);
66
+ const visible = hints.slice(startIndex, endIndex);
67
+
68
+ return (
69
+ <Box flexDirection="column" marginTop={1}>
70
+ {visible.map((hint, vi) => {
71
+ const actualIndex = startIndex + vi;
72
+ const isSelected = actualIndex === safeSelectedIndex;
73
+ return (
74
+ <Box key={hint}>
75
+ <Text color={isSelected ? theme.colors.suggestion : theme.colors.muted}>
76
+ {isSelected ? `${theme.icons.pointer} ` : ' '}
77
+ </Text>
78
+ <Text color={isSelected ? theme.colors.suggestion : undefined} bold={isSelected} dimColor={!isSelected}>
79
+ {hint}
80
+ </Text>
81
+ {isSelected ? <Text dimColor>{' [enter]'}</Text> : null}
82
+ </Box>
83
+ );
84
+ })}
85
+ <Box marginTop={0}>
86
+ <Text dimColor>
87
+ <Text color={theme.colors.muted}>↑↓</Text> navigate
88
+ <Text> {theme.icons.middleDot} </Text>
89
+ <Text color={theme.colors.muted}>↵</Text> select
90
+ <Text> {theme.icons.middleDot} </Text>
91
+ <Text color={theme.colors.muted}>tab</Text> complete
92
+ <Text> {theme.icons.middleDot} </Text>
93
+ <Text color={theme.colors.muted}>esc</Text> dismiss
94
+ </Text>
95
+ </Box>
96
+ </Box>
97
+ );
98
+ }
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import {Box, Text} from 'ink';
3
+ import TextInput from 'ink-text-input';
4
+
5
+ import {useTheme} from '../theme/ThemeContext.js';
6
+
7
+ function sanitizeInput(value: string): string {
8
+ return value
9
+ .replace(/[\r\n]+/g, ' ')
10
+ .replace(/\s+/g, ' ')
11
+ .trim();
12
+ }
13
+
14
+ export function Composer({
15
+ busy,
16
+ input,
17
+ setInput,
18
+ onSubmit,
19
+ historyIndex,
20
+ }: {
21
+ busy: boolean;
22
+ input: string;
23
+ setInput: (value: string) => void;
24
+ onSubmit: (value: string) => void;
25
+ historyIndex: number;
26
+ }): React.JSX.Element {
27
+ const theme = useTheme();
28
+
29
+ return (
30
+ <Box flexDirection="column" marginTop={1}>
31
+ <Box borderStyle="round" borderColor={busy ? theme.colors.warning : theme.colors.success} paddingX={1}>
32
+ <Text color={busy ? theme.colors.warning : theme.colors.success} bold>
33
+ {busy ? theme.icons.inProgress : theme.icons.completed}{' '}
34
+ </Text>
35
+ <Text color={busy ? theme.colors.warning : theme.colors.success} bold>
36
+ {busy ? 'busy' : 'ready'}
37
+ </Text>
38
+ <Text> </Text>
39
+ <TextInput
40
+ value={input}
41
+ onChange={(value) => setInput(sanitizeInput(value))}
42
+ onSubmit={onSubmit}
43
+ />
44
+ </Box>
45
+ <Box marginTop={1}>
46
+ <Text dimColor>
47
+ <Text color={theme.colors.muted}>enter</Text>=submit{' '}
48
+ <Text color={theme.colors.muted}>tab</Text>=complete{' '}
49
+ <Text color={theme.colors.muted}>ctrl-p/ctrl-n</Text>=history{' '}
50
+ <Text color={theme.colors.muted}>history_index</Text>={String(historyIndex)}
51
+ </Text>
52
+ </Box>
53
+ </Box>
54
+ );
55
+ }
@@ -0,0 +1,128 @@
1
+ import React, {useEffect, useMemo, useState} from 'react';
2
+ import {useInput} from 'ink';
3
+
4
+ import type {UiLanguage} from '../i18n.js';
5
+ import type {TodoItemSnapshot} from '../types.js';
6
+ import {CommandPicker} from './CommandPicker.js';
7
+ import {PromptInput} from './PromptInput.js';
8
+
9
+ export function ComposerController({
10
+ commands,
11
+ busy,
12
+ disabled,
13
+ language,
14
+ todoItems,
15
+ toolName,
16
+ onSubmit,
17
+ }: {
18
+ commands: string[];
19
+ busy: boolean;
20
+ disabled: boolean;
21
+ language: UiLanguage;
22
+ todoItems: TodoItemSnapshot[];
23
+ toolName?: string;
24
+ onSubmit: (value: string) => void;
25
+ }): React.JSX.Element | null {
26
+ const [input, setInput] = useState('');
27
+ const [pickerIndex, setPickerIndex] = useState(0);
28
+ const [localBusy, setLocalBusy] = useState(false);
29
+
30
+ const commandHints = useMemo(() => {
31
+ if (!input.startsWith('/')) {
32
+ return [] as string[];
33
+ }
34
+ const value = input.trimEnd();
35
+ if (!value) {
36
+ return [] as string[];
37
+ }
38
+ const matches = commands.filter((cmd) => cmd.startsWith(value));
39
+ if (value === '/') {
40
+ const preferred = ['/language'];
41
+ const boosted = preferred.filter((cmd) => matches.includes(cmd));
42
+ const rest = matches.filter((cmd) => !preferred.includes(cmd));
43
+ return [...boosted, ...rest];
44
+ }
45
+ return matches;
46
+ }, [commands, input]);
47
+
48
+ const showPicker = !disabled && input.startsWith('/') && commandHints.length > 0;
49
+ const effectiveBusy = busy || localBusy;
50
+
51
+ useEffect(() => {
52
+ setPickerIndex(0);
53
+ }, [showPicker, commandHints.length, input]);
54
+
55
+ useEffect(() => {
56
+ if (!busy) {
57
+ setLocalBusy(false);
58
+ }
59
+ }, [busy]);
60
+
61
+ useInput((chunk, key) => {
62
+ if (disabled) {
63
+ return;
64
+ }
65
+
66
+ if (showPicker) {
67
+ if (key.upArrow) {
68
+ setPickerIndex((i) => Math.max(0, i - 1));
69
+ return;
70
+ }
71
+ if (key.downArrow) {
72
+ setPickerIndex((i) => Math.min(commandHints.length - 1, i + 1));
73
+ return;
74
+ }
75
+ if (key.return) {
76
+ const selected = commandHints[pickerIndex];
77
+ if (selected) {
78
+ setLocalBusy(true);
79
+ setInput('');
80
+ onSubmit(selected);
81
+ }
82
+ return;
83
+ }
84
+ if (key.tab) {
85
+ const selected = commandHints[pickerIndex];
86
+ if (selected) {
87
+ setInput(selected + ' ');
88
+ }
89
+ return;
90
+ }
91
+ if (key.escape) {
92
+ setInput('');
93
+ return;
94
+ }
95
+ }
96
+
97
+ if (!showPicker && (key.upArrow || key.downArrow)) {
98
+ return;
99
+ }
100
+ });
101
+
102
+ if (disabled || effectiveBusy) {
103
+ return null;
104
+ }
105
+
106
+ return (
107
+ <>
108
+ {showPicker ? <CommandPicker hints={commandHints} selectedIndex={pickerIndex} totalCommands={commands.length} /> : null}
109
+ <PromptInput
110
+ busy={effectiveBusy}
111
+ input={input}
112
+ setInput={setInput}
113
+ onSubmit={(value) => {
114
+ if (!value.trim() || disabled) {
115
+ return;
116
+ }
117
+ setLocalBusy(true);
118
+ onSubmit(value);
119
+ setInput('');
120
+ }}
121
+ toolName={toolName}
122
+ suppressSubmit={showPicker}
123
+ language={language}
124
+ todoItems={todoItems}
125
+ />
126
+ </>
127
+ );
128
+ }