jarvis-agent 0.1.0__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 (108) hide show
  1. jarvis_agent-0.1.0/PKG-INFO +49 -0
  2. jarvis_agent-0.1.0/README.md +289 -0
  3. jarvis_agent-0.1.0/agent/__init__.py +3 -0
  4. jarvis_agent-0.1.0/agent/acp.py +183 -0
  5. jarvis_agent-0.1.0/agent/config/__init__.py +5 -0
  6. jarvis_agent-0.1.0/agent/config/migrations.py +195 -0
  7. jarvis_agent-0.1.0/agent/config/settings.py +561 -0
  8. jarvis_agent-0.1.0/agent/core/__init__.py +24 -0
  9. jarvis_agent-0.1.0/agent/core/compactor.py +484 -0
  10. jarvis_agent-0.1.0/agent/core/context.py +79 -0
  11. jarvis_agent-0.1.0/agent/core/diag.py +213 -0
  12. jarvis_agent-0.1.0/agent/core/file_state.py +81 -0
  13. jarvis_agent-0.1.0/agent/core/holidays.py +236 -0
  14. jarvis_agent-0.1.0/agent/core/hooks.py +315 -0
  15. jarvis_agent-0.1.0/agent/core/mailbox.py +488 -0
  16. jarvis_agent-0.1.0/agent/core/mcp_client.py +397 -0
  17. jarvis_agent-0.1.0/agent/core/memory.py +319 -0
  18. jarvis_agent-0.1.0/agent/core/message.py +136 -0
  19. jarvis_agent-0.1.0/agent/core/monitor.py +312 -0
  20. jarvis_agent-0.1.0/agent/core/orchestrator.py +370 -0
  21. jarvis_agent-0.1.0/agent/core/query_loop.py +584 -0
  22. jarvis_agent-0.1.0/agent/core/recovery.py +203 -0
  23. jarvis_agent-0.1.0/agent/core/result.py +103 -0
  24. jarvis_agent-0.1.0/agent/core/scheduler.py +333 -0
  25. jarvis_agent-0.1.0/agent/core/skills.py +175 -0
  26. jarvis_agent-0.1.0/agent/core/subagent.py +442 -0
  27. jarvis_agent-0.1.0/agent/core/task_list.py +567 -0
  28. jarvis_agent-0.1.0/agent/core/team.py +510 -0
  29. jarvis_agent-0.1.0/agent/core/teammate.py +457 -0
  30. jarvis_agent-0.1.0/agent/core/tool.py +450 -0
  31. jarvis_agent-0.1.0/agent/core/vision_watcher.py +482 -0
  32. jarvis_agent-0.1.0/agent/daemon/__init__.py +23 -0
  33. jarvis_agent-0.1.0/agent/daemon/autostart.py +863 -0
  34. jarvis_agent-0.1.0/agent/daemon/daemon.py +1206 -0
  35. jarvis_agent-0.1.0/agent/daemon/voice_state.py +111 -0
  36. jarvis_agent-0.1.0/agent/llm/__init__.py +32 -0
  37. jarvis_agent-0.1.0/agent/llm/anthropic_provider.py +267 -0
  38. jarvis_agent-0.1.0/agent/llm/base.py +148 -0
  39. jarvis_agent-0.1.0/agent/llm/dashscope_provider.py +414 -0
  40. jarvis_agent-0.1.0/agent/llm/mock.py +114 -0
  41. jarvis_agent-0.1.0/agent/llm/openai_provider.py +399 -0
  42. jarvis_agent-0.1.0/agent/lsp/__init__.py +11 -0
  43. jarvis_agent-0.1.0/agent/lsp/client.py +344 -0
  44. jarvis_agent-0.1.0/agent/lsp/manager.py +276 -0
  45. jarvis_agent-0.1.0/agent/main.py +2321 -0
  46. jarvis_agent-0.1.0/agent/permissions/__init__.py +27 -0
  47. jarvis_agent-0.1.0/agent/permissions/checker.py +224 -0
  48. jarvis_agent-0.1.0/agent/permissions/modes.py +44 -0
  49. jarvis_agent-0.1.0/agent/permissions/path_guard.py +95 -0
  50. jarvis_agent-0.1.0/agent/permissions/rules.py +166 -0
  51. jarvis_agent-0.1.0/agent/permissions/shell_classifier.py +144 -0
  52. jarvis_agent-0.1.0/agent/prompts/__init__.py +5 -0
  53. jarvis_agent-0.1.0/agent/prompts/system.py +422 -0
  54. jarvis_agent-0.1.0/agent/tools/__init__.py +82 -0
  55. jarvis_agent-0.1.0/agent/tools/ask_user.py +68 -0
  56. jarvis_agent-0.1.0/agent/tools/base.py +49 -0
  57. jarvis_agent-0.1.0/agent/tools/bash.py +133 -0
  58. jarvis_agent-0.1.0/agent/tools/browser.py +572 -0
  59. jarvis_agent-0.1.0/agent/tools/camera.py +337 -0
  60. jarvis_agent-0.1.0/agent/tools/enter_plan.py +66 -0
  61. jarvis_agent-0.1.0/agent/tools/exit_plan.py +116 -0
  62. jarvis_agent-0.1.0/agent/tools/file_edit.py +107 -0
  63. jarvis_agent-0.1.0/agent/tools/file_read.py +106 -0
  64. jarvis_agent-0.1.0/agent/tools/file_write.py +85 -0
  65. jarvis_agent-0.1.0/agent/tools/glob.py +77 -0
  66. jarvis_agent-0.1.0/agent/tools/grep.py +111 -0
  67. jarvis_agent-0.1.0/agent/tools/keyboard.py +266 -0
  68. jarvis_agent-0.1.0/agent/tools/lsp_tool.py +443 -0
  69. jarvis_agent-0.1.0/agent/tools/mcp_tool.py +81 -0
  70. jarvis_agent-0.1.0/agent/tools/mouse.py +257 -0
  71. jarvis_agent-0.1.0/agent/tools/schedule_tool.py +267 -0
  72. jarvis_agent-0.1.0/agent/tools/screen.py +227 -0
  73. jarvis_agent-0.1.0/agent/tools/send_message.py +242 -0
  74. jarvis_agent-0.1.0/agent/tools/subagent_tool.py +288 -0
  75. jarvis_agent-0.1.0/agent/tools/task_create.py +71 -0
  76. jarvis_agent-0.1.0/agent/tools/task_get.py +52 -0
  77. jarvis_agent-0.1.0/agent/tools/task_list.py +60 -0
  78. jarvis_agent-0.1.0/agent/tools/task_stop.py +70 -0
  79. jarvis_agent-0.1.0/agent/tools/task_update.py +131 -0
  80. jarvis_agent-0.1.0/agent/tools/team_create.py +87 -0
  81. jarvis_agent-0.1.0/agent/tools/team_delete.py +66 -0
  82. jarvis_agent-0.1.0/agent/tools/todo.py +102 -0
  83. jarvis_agent-0.1.0/agent/tools/vision_tools.py +221 -0
  84. jarvis_agent-0.1.0/agent/tools/web.py +404 -0
  85. jarvis_agent-0.1.0/agent/tools/window.py +328 -0
  86. jarvis_agent-0.1.0/agent/ui/__init__.py +10 -0
  87. jarvis_agent-0.1.0/agent/ui/boot_animation.py +497 -0
  88. jarvis_agent-0.1.0/agent/ui/cli.py +808 -0
  89. jarvis_agent-0.1.0/agent/ui/markdown_renderer.py +223 -0
  90. jarvis_agent-0.1.0/agent/ui/model_picker.py +287 -0
  91. jarvis_agent-0.1.0/agent/ui/session_picker.py +212 -0
  92. jarvis_agent-0.1.0/agent/ui/terminal_picker.py +469 -0
  93. jarvis_agent-0.1.0/agent/voice/__init__.py +18 -0
  94. jarvis_agent-0.1.0/agent/voice/audio.py +49 -0
  95. jarvis_agent-0.1.0/agent/voice/stream_tts.py +399 -0
  96. jarvis_agent-0.1.0/agent/voice/stt.py +822 -0
  97. jarvis_agent-0.1.0/agent/voice/tts.py +359 -0
  98. jarvis_agent-0.1.0/agent/voice/voice_loop.py +916 -0
  99. jarvis_agent-0.1.0/jarvis_agent.egg-info/PKG-INFO +49 -0
  100. jarvis_agent-0.1.0/jarvis_agent.egg-info/SOURCES.txt +106 -0
  101. jarvis_agent-0.1.0/jarvis_agent.egg-info/dependency_links.txt +1 -0
  102. jarvis_agent-0.1.0/jarvis_agent.egg-info/entry_points.txt +2 -0
  103. jarvis_agent-0.1.0/jarvis_agent.egg-info/requires.txt +63 -0
  104. jarvis_agent-0.1.0/jarvis_agent.egg-info/top_level.txt +1 -0
  105. jarvis_agent-0.1.0/pyproject.toml +93 -0
  106. jarvis_agent-0.1.0/setup.cfg +4 -0
  107. jarvis_agent-0.1.0/tests/test_permissions.py +57 -0
  108. jarvis_agent-0.1.0/tests/test_query_loop.py +119 -0
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.4
2
+ Name: jarvis-agent
3
+ Version: 0.1.0
4
+ Summary: J.A.R.V.I.S — Personal computer AI agent, referencing core architecture design from mainstream AI Coding Agents, rewritten in Python
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: anthropic>=0.39.0
7
+ Requires-Dist: openai>=1.50.0
8
+ Requires-Dist: pydantic>=2.7.0
9
+ Requires-Dist: pydantic-settings>=2.3.0
10
+ Requires-Dist: rich>=13.7.0
11
+ Requires-Dist: prompt_toolkit>=3.0.0
12
+ Requires-Dist: pyyaml>=6.0
13
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
14
+ Provides-Extra: gui
15
+ Requires-Dist: pyautogui>=0.9.54; extra == "gui"
16
+ Requires-Dist: pillow>=10.0.0; extra == "gui"
17
+ Requires-Dist: pywinauto>=0.6.9; sys_platform == "win32" and extra == "gui"
18
+ Requires-Dist: pygetwindow>=0.0.9; sys_platform != "linux" and extra == "gui"
19
+ Provides-Extra: browser
20
+ Requires-Dist: playwright>=1.40.0; extra == "browser"
21
+ Provides-Extra: mcp
22
+ Requires-Dist: mcp>=1.0.0; extra == "mcp"
23
+ Provides-Extra: camera
24
+ Requires-Dist: opencv-python>=4.8.0; extra == "camera"
25
+ Provides-Extra: vision
26
+ Requires-Dist: mediapipe>=0.10.14; extra == "vision"
27
+ Requires-Dist: opencv-python>=4.8.0; extra == "vision"
28
+ Requires-Dist: paddleocr>=2.7.0; extra == "vision"
29
+ Provides-Extra: voice
30
+ Requires-Dist: dashscope>=1.20.0; extra == "voice"
31
+ Requires-Dist: pyaudio>=0.2.14; extra == "voice"
32
+ Provides-Extra: daemon
33
+ Requires-Dist: pystray>=0.19.0; extra == "daemon"
34
+ Requires-Dist: pywin32>=227; sys_platform == "win32" and extra == "daemon"
35
+ Requires-Dist: keyboard>=0.13.0; sys_platform != "darwin" and extra == "daemon"
36
+ Requires-Dist: pillow>=10.0.0; extra == "daemon"
37
+ Requires-Dist: psutil>=5.9.0; extra == "daemon"
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
40
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
41
+ Requires-Dist: ruff>=0.5.0; extra == "dev"
42
+ Provides-Extra: all
43
+ Requires-Dist: jarvis-agent[gui]; extra == "all"
44
+ Requires-Dist: jarvis-agent[browser]; extra == "all"
45
+ Requires-Dist: jarvis-agent[mcp]; extra == "all"
46
+ Requires-Dist: jarvis-agent[camera]; extra == "all"
47
+ Requires-Dist: jarvis-agent[vision]; extra == "all"
48
+ Requires-Dist: jarvis-agent[voice]; extra == "all"
49
+ Requires-Dist: jarvis-agent[daemon]; extra == "all"
@@ -0,0 +1,289 @@
1
+ <div align="center">
2
+ <pre>
3
+ ██ ▄████▄ █████▄ ██ ██ ██ ▄█████
4
+ ██ ██▄▄██ ██▄▄██▄ ██▄▄██ ██ ▀▀▀▄▄▄
5
+ ████▀ ██ ██ ██ ██ ▀██▀ ██ █████▀
6
+ </pre>
7
+ </div>
8
+
9
+ # J.A.R.V.I.S
10
+
11
+ > **J**ust **A** **R**ather **V**ery **I**ntelligent **S**ystem
12
+ >
13
+ > 「随时为您效劳,先生。」
14
+
15
+ 这是一个为个人电脑打造的 AI Agent —— 能像《钢铁侠》里的贾维斯一样与你对话、帮你操作电脑、常驻后台听你召唤、能听会说。它的工具协议、权限系统、编排模型、MCP 集成、上下文压缩等核心思想有着现代 AI Agent 的最佳实践,实现语言、交互方式和产品形态都围绕「个人电脑助手」设计,把「终端原生、工具驱动、可扩展」的智能助手带到你自己的个人电脑系统中。
16
+
17
+ ## 平台支持
18
+
19
+ | 功能 | Windows | macOS | Linux |
20
+ |---|---|---|---|
21
+ | REPL 对话 + 文件/命令工具 | ✅ | ✅ | ✅ |
22
+ | LLM Provider(OpenAI / Anthropic / DashScope) | ✅ | ✅ | ✅ |
23
+ | MCP 集成 / 会话记忆 / 上下文压缩 | ✅ | ✅ | ✅ |
24
+ | Rich 终端 UI + 启动动画 | ✅ | ✅ | ✅ |
25
+ | 语音 TTS / STT(`/voice`) | ✅ | ✅ | ✅ |
26
+ | 鼠标 / 键盘 / 截屏(pyautogui) | ✅ | ✅¹ | ✅² |
27
+ | 摄像头 / 视觉监控 | ✅ | ✅ | ✅ |
28
+ | `--daemon` 后台常驻模式 | ✅ | ✅ | ⚠️ 前台运行³ |
29
+ | 开机自启 | ✅ Startup | ✅ LaunchAgent | ❌ 手动 systemd |
30
+ | 桌面快捷方式 | ✅ .lnk | ✅ .command | ✅ .desktop |
31
+ | 全局热键 | ✅ | ❌ | ⚠️ 需 root |
32
+
33
+ > ¹ macOS 需在「系统设置 → 隐私与安全 → 辅助功能」中授权终端/Python
34
+ > ² Linux 鼠标键盘操作需 DISPLAY 环境变量(X11/Wayland 桌面环境)
35
+ > ³ Linux 上 `--daemon` 会以前台模式运行(无法后台分离),功能完整
36
+
37
+ ## 安装
38
+
39
+ ### 从 PyPI 安装(推荐)
40
+
41
+ ```bash
42
+ # 一键安装全功能(语音 + GUI + daemon + MCP + 浏览器 + 摄像头/视觉)
43
+ pip install "jarvis-agent[all]"
44
+
45
+ # 仅安装核心对话功能
46
+ pip install jarvis-agent
47
+ ```
48
+
49
+ ### 从 GitHub 安装
50
+
51
+ ```bash
52
+ # 克隆仓库
53
+ git clone https://github.com/yourname/J.A.R.V.I.S.git
54
+ cd J.A.R.V.I.S/jarvis
55
+
56
+ # 安装核心包(开发模式)
57
+ pip install -e .
58
+
59
+ # 开发模式全功能
60
+ pip install -e ".[all]"
61
+ ```
62
+
63
+ ### 用 uv 安装(更快)
64
+
65
+ [uv](https://docs.astral.sh/uv/) 是 Rust 编写的高性能 Python 包管理器,推荐新用户尝试:
66
+
67
+ ```bash
68
+ # 作为全局工具安装
69
+ uv tool install "jarvis-agent[all]"
70
+
71
+ # 之后直接用
72
+ jarvis
73
+ ```
74
+
75
+ ### 安装可选功能
76
+
77
+ jarvis 将不同能力拆分为可选依赖组,按需安装:
78
+
79
+ | 依赖组 | 功能 |
80
+ |---|---|
81
+ | `gui` | 鼠标/键盘/截屏/窗口管理 |
82
+ | `browser` | 浏览器自动化(Playwright) |
83
+ | `mcp` | MCP 工具集成 |
84
+ | `camera` | 摄像头拍照 |
85
+ | `vision` | 实时视觉监控 + OCR |
86
+ | `voice` | 语音对话(TTS + STT) |
87
+ | `daemon` | 后台常驻/托盘/热键/开机自启 |
88
+ | `all` | 上面全部 |
89
+
90
+ ```bash
91
+ # 一键安装全部功能(推荐)
92
+ pip install "jarvis-agent[all]"
93
+
94
+ # 或按需安装
95
+ pip install "jarvis-agent[voice]" # 语音对话
96
+ pip install "jarvis-agent[gui]" # 鼠标/键盘/截屏
97
+ pip install "jarvis-agent[daemon]" # 后台常驻模式
98
+ pip install "jarvis-agent[mcp]" # MCP 工具集成
99
+ pip install "jarvis-agent[camera,vision]" # 摄像头/视觉监控
100
+ pip install "jarvis-agent[browser]" # 浏览器自动化
101
+ pip install playwright && playwright install chromium # 浏览器需要额外安装 Chromium
102
+ ```
103
+
104
+ ### 平台系统依赖
105
+
106
+ **macOS**:
107
+
108
+ ```bash
109
+ brew install portaudio # pyaudio 编译依赖(语音功能必需)
110
+ # 系统设置 → 隐私与安全 → 辅助功能 → 允许终端/Python(GUI 操作必需)
111
+ # 系统设置 → 隐私与安全 → 麦克风 → 允许终端/Python(语音输入必需)
112
+ ```
113
+
114
+ **Linux (Ubuntu/Debian)**:
115
+
116
+ ```bash
117
+ sudo apt install portaudio19-dev python3-pyaudio # 语音功能
118
+ sudo apt install libgtk-3-dev libnotify-dev # 系统托盘(pystray)
119
+ sudo apt install python3-tk # pyautogui 截屏依赖
120
+ # 全局热键需要 root 权限: sudo jarvis --daemon
121
+ ```
122
+
123
+ **Linux (Fedora/RHEL)**:
124
+
125
+ ```bash
126
+ sudo dnf install portaudio-devel gtk3-devel
127
+ ```
128
+
129
+ **Windows**: 无需额外系统依赖,直接 `pip install` 即可。
130
+
131
+ ## 快速开始
132
+
133
+ ```bash
134
+ # 默认接阿里云 DashScope(qwen3.7-plus,多模态视觉模型)
135
+ export DASHSCOPE_API_KEY=sk-xxx
136
+ jarvis
137
+ ```
138
+
139
+ > Windows PowerShell 用 `$env:DASHSCOPE_API_KEY = "sk-xxx"` 设置环境变量。
140
+
141
+ 默认配置在 `configs/settings.toml`,环境变量 `JARVIS_*` 和 CLI 参数可覆盖。
142
+ API Key 识别优先级:`DASHSCOPE_API_KEY` > `ANTHROPIC_API_KEY` > `OPENAI_API_KEY` > `JARVIS_API_KEY`。
143
+
144
+ ### 模型管理(`/models`)
145
+
146
+ 内置 qwen 系列模型开箱即用,也支持添加自定义模型(DeepSeek / Claude / GPT 等):
147
+
148
+ - `/models` — 交互式模型列表,↑↓ 选择、Enter 切换、空格管理配置
149
+ - `/model <name>` — 快速切换到指定模型
150
+ - 内置模型可按空格键修改接口类型 / API Key / 模型类型(多模态 or 纯文本),保存为自定义覆盖配置
151
+ - 自定义模型支持编辑和删除,配置持久化到 `~/.jarvis/settings.toml`
152
+ - 接口类型支持:**OpenAI 兼容** / **Anthropic 兼容** / **DashScope SDK**(qwen 原生协议,支持 `MultiModalConversation` 和 `Generation` 双端点)
153
+
154
+ ## 目录结构
155
+
156
+ ```
157
+ agent/
158
+ ├── core/ # 核心:Tool 协议、QueryLoop、Orchestrator、上下文压缩、
159
+ │ # 会话记忆、Skill 系统、MCP 客户端、子代理、调度器
160
+ ├── permissions/ # 五层权限系统:规则、校验、路径守护、命令分类
161
+ ├── tools/ # 内置工具(30+):bash / 文件 / glob / grep / todo / ask_user +
162
+ │ # GUI(鼠标/键盘/屏幕/窗口/浏览器)+ 摄像头 / 视觉监控 +
163
+ │ # MCP 代理 / 子代理 / 日程 / 系统监控
164
+ ├── llm/ # LLM 抽象层:base + openai_provider + anthropic_provider + dashscope_provider
165
+ ├── ui/ # Rich 终端 UI + 启动动画 + prompt_toolkit 补全
166
+ ├── prompts/ # 系统提示组装
167
+ ├── config/ # 配置加载(TOML 多源合并 + 环境变量覆盖 + 用户级覆盖)
168
+ ├── voice/ # 语音引擎:TTS(CosyVoice)+ STT(Qwen3-ASR / Paraformer 双后端)+ /voice 闭环
169
+ ├── daemon/ # 常驻模式:后台守护 + 全局热键 + 系统托盘 + 开机自启
170
+ └── memory/ # 会话 / 记忆持久化
171
+ ```
172
+
173
+ ## REPL 命令
174
+
175
+ 启动后输入 `/` 自动弹出命令列表(Tab 补全):
176
+
177
+ | 命令 | 说明 |
178
+ |---|---|
179
+ | `/help` `/h` | 查看所有命令帮助 |
180
+ | `/exit` `/quit` | 退出贾维斯 |
181
+ | `/mode <m>` | 切换权限模式(default / plan / accept_edits / yolo)|
182
+ | `/model` | 交互式模型选择 |
183
+ | `/model <name>` | 直接切换到指定模型 |
184
+ | `/models` | 管理模型列表(添加 / 编辑 / 删除) |
185
+ | `/think` | 开关深度思考模式(ReAct 思维链) |
186
+ | `/voice` `/talk` | 进入语音对话模式 |
187
+ | `/say <text>` | TTS 语音朗读 |
188
+ | `/listen` `/mic` | 录音识别成文字 |
189
+ | `/save [name]` | 保存当前会话 |
190
+ | `/load <name>` `/resume <n>` | 加载已保存会话 |
191
+ | `/sessions` | 列出所有已保存会话 |
192
+ | `/memory` | 查看长期记忆文件 |
193
+ | `/skills` | 列出已加载技能包 |
194
+ | `/mcp` | 查看 MCP server 连接状态 |
195
+ | `/tools` | 列出所有可用工具 |
196
+ | `/reset` `/clear` | 清空对话历史 |
197
+ | `/compact` | 手动压缩上下文 |
198
+
199
+ ## 深度思考(ReAct 思维链)
200
+
201
+ 启用后,模型在每次回复前先输出 `reasoning_content`(思考过程),再进行正式回复或工具调用,形成完整的 **Think → Act → Observe** ReAct 循环。
202
+
203
+ - 思考内容在终端显示为「💭 思考过程」暗色面板,不干扰正式回复输出
204
+ - 配置:`configs/settings.toml` 中 `enable_thinking = true` / `thinking_budget = 2000`
205
+ - 运行时开关:`/think on` / `/think off`
206
+ - 环境变量关闭:`JARVIS_ENABLE_THINKING=0`
207
+
208
+ ## 语音对话(`/voice`)
209
+
210
+ 进入语音对话模式后,形成 **STT → LLM → TTS** 闭环:
211
+
212
+ - **语音输入**:Qwen3-ASR 流式识别(WebSocket),支持中英文
213
+ - **语音输出**:CosyVoice TTS 自然语音合成
214
+ - **打断机制**:ESC 打断当前回复,LLM 意图识别退出(说"退下")
215
+ - **思考模式**:语音模式下思考内容显示在终端面板,不进入 TTS 朗读
216
+ - **markdown 清洗**:自动过滤代码块 / 表格 / 链接等不适合朗读的内容
217
+
218
+ ## 常驻模式(贾维斯形态)
219
+
220
+ ```bash
221
+ jarvis --daemon # 后台启动,自动进入语音对话
222
+ ```
223
+
224
+ **跨平台行为**:
225
+
226
+ | 平台 | 后台分离方式 | 说明 |
227
+ |---|---|---|
228
+ | Windows | `pythonw.exe` + `DETACHED_PROCESS` | 无窗口进程,关闭终端不影响 |
229
+ | macOS | `start_new_session=True` | 新会话脱离终端,关闭 Terminal.app 不影响 |
230
+ | Linux | 不支持后台分离 | 以前台模式运行(功能完整,关闭终端即退出) |
231
+
232
+ 启动后系统托盘出现蓝色同心圆图标。默认自动进入语音对话模式——说「退下」进待机,说「贾维斯」唤醒。
233
+
234
+ **托盘菜单(右键):**
235
+
236
+ | 菜单项 | 行为 |
237
+ |---|---|
238
+ | 语音对话 | 唤起语音对话模式 |
239
+ | 文本对话 | 弹出终端窗口运行完整 REPL(自动恢复上次会话) |
240
+ | 退出贾维斯 | 立即终止守护进程 |
241
+
242
+ > 文本对话弹窗:Windows 用 Git Bash / CMD,macOS 用 Terminal.app,Linux 用 gnome-terminal / xterm。
243
+
244
+ ### 开机自启 / 桌面快捷方式
245
+
246
+ ```bash
247
+ python -m agent.daemon.autostart install # 安装开机自启
248
+ python -m agent.daemon.autostart uninstall # 卸载开机自启
249
+ python -m agent.daemon.autostart status # 查看状态
250
+
251
+ python -m agent.daemon.autostart desktop # 创建桌面快捷方式
252
+ python -m agent.daemon.autostart desktop-uninstall # 删除桌面快捷方式
253
+ ```
254
+
255
+ | 平台 | 开机自启 | 桌面快捷方式 |
256
+ |---|---|---|
257
+ | Windows | Startup 文件夹 .lnk | .lnk(指向 VBS 无窗口启动) |
258
+ | macOS | LaunchAgent plist(`launchctl load`) | .command(Terminal.app 打开) |
259
+ | Linux | 不支持(提示手动 systemd) | .desktop 文件 |
260
+
261
+ ### 其他启动方式
262
+
263
+ | 方式 | 说明 |
264
+ |---|---|
265
+ | `jarvis` | 前台 REPL 模式(带启动动画) |
266
+ | `jarvis --with-tray` | 前台 REPL + 托盘图标 |
267
+ | `jarvis --daemon` | 后台常驻模式(Windows/macOS 后台分离,Linux 前台运行) |
268
+
269
+ ### 会话恢复
270
+
271
+ 异常退出时下次启动自动提示恢复上次会话(对话历史 + 工作目录)。文本对话窗口也会自动恢复。
272
+
273
+ ## 可选依赖
274
+
275
+ GUI 工具(鼠标 / 键盘 / 屏幕 / 窗口)未安装时自动跳过,不影响基础功能:
276
+
277
+ ```bash
278
+ pip install -e ".[gui]" # 鼠标/键盘/截屏
279
+ pip install -e ".[browser]" && playwright install chromium # 浏览器自动化
280
+ ```
281
+
282
+ ## 开发路线
283
+
284
+ - [x] 阶段 1:最小可用 Agent(对话 + 文件 + 命令 + 五层权限)
285
+ - [x] 阶段 2:电脑操作能力(GUI + 多模态视觉 + 浏览器自动化 + 摄像头拍照)
286
+ - [x] 阶段 3:实时语音(TTS + STT + /voice 闭环 + 打断)
287
+ - [x] 阶段 4:记忆与生态(会话持久化 / 长期记忆 / MCP 接入 / 上下文压缩 / Skill 系统)
288
+ - [x] 阶段 5:贾维斯形态(daemon 常驻 + 全局热键 + 系统托盘 + 开机自启 + 子代理 + 主动感知 + 视觉监控)
289
+ - [x] 阶段 6:跨平台适配(Windows / macOS / Linux)
@@ -0,0 +1,3 @@
1
+ """jarvis: 个人电脑 AI Agent(J.A.R.V.I.S.),借鉴 Claude Code 架构思想用 Python 重写"""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,183 @@
1
+ """ACP (Agent Client Protocol) stdio transport.
2
+
3
+ cc-connect 通过 ACP 协议桥接贾维斯到 IM 平台(飞书/钉钉/微信)。
4
+ 此模块实现 ACP agent 端的最小必要方法,通过 stdin/stdout 通信。
5
+
6
+ 协议:JSON-RPC 2.0 over stdio, 每行一条消息,\n 分隔。
7
+ 参考:https://agentclientprotocol.com/protocol/v1/overview
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import sys
14
+ from typing import Any
15
+
16
+
17
+ PROTOCOL_VERSION = "0.1"
18
+
19
+
20
+ class ACPServer:
21
+ """ACP stdio server。处理 initialize / session/new / session/prompt。"""
22
+
23
+ def __init__(self):
24
+ self._session_id = "jarvis-session"
25
+ self._initialized = False
26
+ self._pending_req_id: int | str | None = None
27
+
28
+ # ---- public API ----
29
+
30
+ def run(self) -> None:
31
+ """阻塞式主循环:读 stdin,逐条处理 JSON-RPC。"""
32
+ for line in sys.stdin:
33
+ line = line.strip()
34
+ if not line:
35
+ continue
36
+ try:
37
+ msg = json.loads(line)
38
+ except json.JSONDecodeError:
39
+ continue
40
+ self._dispatch(msg)
41
+
42
+ # ---- dispatch ----
43
+
44
+ def _dispatch(self, msg: dict[str, Any]) -> None:
45
+ method = msg.get("method", "")
46
+ req_id = msg.get("id")
47
+
48
+ if method == "initialize":
49
+ self._handle_initialize(req_id, msg.get("params", {}))
50
+ elif method == "session/new":
51
+ self._handle_session_new(req_id)
52
+ elif method == "session/prompt":
53
+ self._handle_prompt(req_id, msg.get("params", {}))
54
+ elif method == "session/cancel":
55
+ self._send_result(req_id, {})
56
+ else:
57
+ self._send_error(req_id, -32601, f"未知方法: {method}")
58
+
59
+ # ---- handlers ----
60
+
61
+ def _handle_initialize(self, req_id: Any, params: dict) -> None:
62
+ self._send_result(req_id, {
63
+ "protocolVersion": 1, # cc-connect 要求整数类型
64
+ "agentInfo": {"name": "jarvis", "version": "0.1"},
65
+ "capabilities": {},
66
+ })
67
+ self._initialized = True
68
+
69
+ def _handle_session_new(self, req_id: Any) -> None:
70
+ if not self._initialized:
71
+ self._send_error(req_id, -32000, "未初始化")
72
+ return
73
+ self._send_result(req_id, {"sessionId": self._session_id})
74
+
75
+ def _handle_prompt(self, req_id: Any, params: dict) -> None:
76
+ if not self._initialized:
77
+ self._send_error(req_id, -32000, "未初始化")
78
+ return
79
+
80
+ prompt = params.get("prompt", [])
81
+ text = ""
82
+ for p in prompt:
83
+ if isinstance(p, dict) and p.get("type") == "text":
84
+ text += p.get("text", "")
85
+
86
+ if not text:
87
+ self._send_result(req_id, {"stopReason": "end_turn"})
88
+ return
89
+
90
+ self._pending_req_id = req_id
91
+ # 回调交给外部 agent 循环
92
+ self._on_prompt(text, self._notify_update, self._finish_prompt)
93
+
94
+ # ---- callbacks for agent ----
95
+
96
+ def _on_prompt(self, text: str, on_update, on_finish):
97
+ """子类覆盖此方法实现 agent 逻辑。"""
98
+ on_update("thought", f"收到消息: {text}")
99
+ on_finish("end_turn")
100
+
101
+ # ---- send helpers ----
102
+
103
+ def _notify_update(self, update_type: str, text: str) -> None:
104
+ """发送 session/update 通知(思考/回复文本)。"""
105
+ content_type = "thought" if update_type == "thought" else "text"
106
+ self._write({
107
+ "jsonrpc": "2.0",
108
+ "method": "session/update",
109
+ "params": {
110
+ "sessionId": self._session_id,
111
+ "update": {
112
+ "type": "agent_message_chunk",
113
+ "content": {"type": content_type, "text": text},
114
+ },
115
+ },
116
+ })
117
+
118
+ def _finish_prompt(self, stop_reason: str = "end_turn") -> None:
119
+ """完成本轮 prompt,发送 result。"""
120
+ if self._pending_req_id is not None:
121
+ self._send_result(self._pending_req_id, {"stopReason": stop_reason})
122
+ self._pending_req_id = None
123
+
124
+ def _send_result(self, req_id: Any, result: Any) -> None:
125
+ if req_id is None:
126
+ return # 通知消息无 id,不回复
127
+ self._write({"jsonrpc": "2.0", "id": req_id, "result": result})
128
+
129
+ def _send_error(self, req_id: Any, code: int, message: str) -> None:
130
+ if req_id is None:
131
+ return
132
+ self._write({"jsonrpc": "2.0", "id": req_id, "error": {"code": code, "message": message}})
133
+
134
+ def _write(self, msg: dict) -> None:
135
+ sys.stdout.write(json.dumps(msg, ensure_ascii=False) + "\n")
136
+ sys.stdout.flush()
137
+
138
+
139
+ class JarvisACP(ACPServer):
140
+ """贾维斯 ACP 适配器:把 stdin JSON-RPC 转成 QueryLoop 调用。"""
141
+
142
+ def __init__(self, settings, provider, loop, ctx, messages):
143
+ super().__init__()
144
+ self._settings = settings
145
+ self._provider = provider
146
+ self._loop = loop
147
+ self._ctx = ctx
148
+ self._messages = messages
149
+ self._session_id = "jarvis-" + str(id(self))[:8]
150
+
151
+ def _on_prompt(self, text: str, on_update, on_finish):
152
+ """执行 agent 循环,思考/文本通过 on_update 推给 cc-connect。"""
153
+ try:
154
+ # 装配 UI 回调:输出走 ACP 通知
155
+ class _ACPUI:
156
+ verbose = False
157
+
158
+ def info(self, *a, **kw):
159
+ pass
160
+
161
+ def warn(self, *a, **kw):
162
+ pass
163
+
164
+ def error(self, *a, **kw):
165
+ pass
166
+
167
+ def assistant_text(self, t):
168
+ on_update("text", t)
169
+
170
+ def assistant_thinking(self, t):
171
+ on_update("thought", t)
172
+
173
+ self._ctx.ui = _ACPUI()
174
+ self._ctx.on_assistant_text = None
175
+
176
+ import asyncio
177
+ asyncio.get_event_loop().run_until_complete(
178
+ self._loop.run(text, self._ctx)
179
+ )
180
+ on_finish("end_turn")
181
+ except Exception as e:
182
+ on_update("thought", f"[错误] {e}")
183
+ on_finish("error")
@@ -0,0 +1,5 @@
1
+ """配置层。"""
2
+
3
+ from agent.config.settings import Settings, load_settings
4
+
5
+ __all__ = ["Settings", "load_settings"]