spark-agent 0.9.6__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 (174) hide show
  1. spark_agent-0.9.6/LICENSE +21 -0
  2. spark_agent-0.9.6/PKG-INFO +199 -0
  3. spark_agent-0.9.6/README.md +145 -0
  4. spark_agent-0.9.6/pyproject.toml +129 -0
  5. spark_agent-0.9.6/setup.cfg +4 -0
  6. spark_agent-0.9.6/src/spark/__init__.py +14 -0
  7. spark_agent-0.9.6/src/spark/__main__.py +4 -0
  8. spark_agent-0.9.6/src/spark/agents.py +184 -0
  9. spark_agent-0.9.6/src/spark/asyncutil.py +55 -0
  10. spark_agent-0.9.6/src/spark/cli.py +820 -0
  11. spark_agent-0.9.6/src/spark/config.py +813 -0
  12. spark_agent-0.9.6/src/spark/core/__init__.py +3 -0
  13. spark_agent-0.9.6/src/spark/core/checkpoints.py +429 -0
  14. spark_agent-0.9.6/src/spark/core/compact.py +497 -0
  15. spark_agent-0.9.6/src/spark/core/context.py +335 -0
  16. spark_agent-0.9.6/src/spark/core/context_profile.py +139 -0
  17. spark_agent-0.9.6/src/spark/core/graph.py +381 -0
  18. spark_agent-0.9.6/src/spark/core/loop.py +1135 -0
  19. spark_agent-0.9.6/src/spark/core/tokens.py +40 -0
  20. spark_agent-0.9.6/src/spark/desktop.py +127 -0
  21. spark_agent-0.9.6/src/spark/edit/__init__.py +48 -0
  22. spark_agent-0.9.6/src/spark/edit/ast_check.py +109 -0
  23. spark_agent-0.9.6/src/spark/edit/core.py +248 -0
  24. spark_agent-0.9.6/src/spark/edit/tool.py +148 -0
  25. spark_agent-0.9.6/src/spark/errors.py +10 -0
  26. spark_agent-0.9.6/src/spark/evals/__init__.py +21 -0
  27. spark_agent-0.9.6/src/spark/evals/__main__.py +64 -0
  28. spark_agent-0.9.6/src/spark/evals/data/swe_lite_real_subset.json +74 -0
  29. spark_agent-0.9.6/src/spark/evals/download_real.py +59 -0
  30. spark_agent-0.9.6/src/spark/evals/harness.py +413 -0
  31. spark_agent-0.9.6/src/spark/evals/scenarios.py +246 -0
  32. spark_agent-0.9.6/src/spark/git_memory.py +293 -0
  33. spark_agent-0.9.6/src/spark/hooks.py +147 -0
  34. spark_agent-0.9.6/src/spark/mcp_expose.py +108 -0
  35. spark_agent-0.9.6/src/spark/mcp_registry.py +429 -0
  36. spark_agent-0.9.6/src/spark/memory/__init__.py +0 -0
  37. spark_agent-0.9.6/src/spark/memory/extractor.py +265 -0
  38. spark_agent-0.9.6/src/spark/memory/llm.py +108 -0
  39. spark_agent-0.9.6/src/spark/memory/service.py +443 -0
  40. spark_agent-0.9.6/src/spark/memory/store.py +851 -0
  41. spark_agent-0.9.6/src/spark/model_catalog.py +161 -0
  42. spark_agent-0.9.6/src/spark/models.py +74 -0
  43. spark_agent-0.9.6/src/spark/onboard.py +320 -0
  44. spark_agent-0.9.6/src/spark/otel.py +93 -0
  45. spark_agent-0.9.6/src/spark/platform_compat.py +23 -0
  46. spark_agent-0.9.6/src/spark/policy.py +261 -0
  47. spark_agent-0.9.6/src/spark/prompts/system.md +33 -0
  48. spark_agent-0.9.6/src/spark/providers/__init__.py +19 -0
  49. spark_agent-0.9.6/src/spark/providers/base.py +14 -0
  50. spark_agent-0.9.6/src/spark/providers/factory.py +43 -0
  51. spark_agent-0.9.6/src/spark/providers/mock.py +55 -0
  52. spark_agent-0.9.6/src/spark/providers/openai_compat.py +453 -0
  53. spark_agent-0.9.6/src/spark/providers/probe.py +188 -0
  54. spark_agent-0.9.6/src/spark/providers/routing.py +347 -0
  55. spark_agent-0.9.6/src/spark/pty/__init__.py +307 -0
  56. spark_agent-0.9.6/src/spark/repo_map.py +288 -0
  57. spark_agent-0.9.6/src/spark/sandbox.py +273 -0
  58. spark_agent-0.9.6/src/spark/sanitize.py +104 -0
  59. spark_agent-0.9.6/src/spark/skills.py +103 -0
  60. spark_agent-0.9.6/src/spark/slash.py +159 -0
  61. spark_agent-0.9.6/src/spark/store.py +771 -0
  62. spark_agent-0.9.6/src/spark/structured.py +168 -0
  63. spark_agent-0.9.6/src/spark/tools/__init__.py +3 -0
  64. spark_agent-0.9.6/src/spark/tools/_common.py +16 -0
  65. spark_agent-0.9.6/src/spark/tools/bg.py +310 -0
  66. spark_agent-0.9.6/src/spark/tools/diagnostics.py +149 -0
  67. spark_agent-0.9.6/src/spark/tools/fs.py +249 -0
  68. spark_agent-0.9.6/src/spark/tools/gitops.py +379 -0
  69. spark_agent-0.9.6/src/spark/tools/mcp_bridge.py +427 -0
  70. spark_agent-0.9.6/src/spark/tools/notebook.py +123 -0
  71. spark_agent-0.9.6/src/spark/tools/registry.py +537 -0
  72. spark_agent-0.9.6/src/spark/tools/search.py +269 -0
  73. spark_agent-0.9.6/src/spark/tools/shell.py +297 -0
  74. spark_agent-0.9.6/src/spark/tools/untrusted.py +44 -0
  75. spark_agent-0.9.6/src/spark/tools/web.py +246 -0
  76. spark_agent-0.9.6/src/spark/tui/__init__.py +3 -0
  77. spark_agent-0.9.6/src/spark/tui/app.py +584 -0
  78. spark_agent-0.9.6/src/spark/tui/welcome.py +126 -0
  79. spark_agent-0.9.6/src/spark/web/__init__.py +3 -0
  80. spark_agent-0.9.6/src/spark/web/_handlers.py +862 -0
  81. spark_agent-0.9.6/src/spark/web/_httpbase.py +26 -0
  82. spark_agent-0.9.6/src/spark/web/_routing.py +12 -0
  83. spark_agent-0.9.6/src/spark/web/api_spec.py +162 -0
  84. spark_agent-0.9.6/src/spark/web/dist/assets/SettingsModal-C3YLub9B.js +4 -0
  85. spark_agent-0.9.6/src/spark/web/dist/assets/highlight-CBGBLn5w.js +5 -0
  86. spark_agent-0.9.6/src/spark/web/dist/assets/index-DG4oXX01.js +42 -0
  87. spark_agent-0.9.6/src/spark/web/dist/assets/index-SPHoMi93.css +1 -0
  88. spark_agent-0.9.6/src/spark/web/dist/assets/markdown-CnxUTuzz.js +29 -0
  89. spark_agent-0.9.6/src/spark/web/dist/assets/react-DyzINgAZ.js +9 -0
  90. spark_agent-0.9.6/src/spark/web/dist/favicon.svg +17 -0
  91. spark_agent-0.9.6/src/spark/web/dist/index.html +29 -0
  92. spark_agent-0.9.6/src/spark/web/index.html +253 -0
  93. spark_agent-0.9.6/src/spark/web/pty_api.py +162 -0
  94. spark_agent-0.9.6/src/spark/web/routes.py +543 -0
  95. spark_agent-0.9.6/src/spark/web/server.py +134 -0
  96. spark_agent-0.9.6/src/spark/web/sse.py +263 -0
  97. spark_agent-0.9.6/src/spark/web/state.py +363 -0
  98. spark_agent-0.9.6/src/spark/web/utils.py +175 -0
  99. spark_agent-0.9.6/src/spark_agent.egg-info/PKG-INFO +199 -0
  100. spark_agent-0.9.6/src/spark_agent.egg-info/SOURCES.txt +172 -0
  101. spark_agent-0.9.6/src/spark_agent.egg-info/dependency_links.txt +1 -0
  102. spark_agent-0.9.6/src/spark_agent.egg-info/entry_points.txt +2 -0
  103. spark_agent-0.9.6/src/spark_agent.egg-info/requires.txt +43 -0
  104. spark_agent-0.9.6/src/spark_agent.egg-info/top_level.txt +1 -0
  105. spark_agent-0.9.6/tests/test_acl_predicate.py +53 -0
  106. spark_agent-0.9.6/tests/test_adversarial_security.py +464 -0
  107. spark_agent-0.9.6/tests/test_approval_and_ssrf.py +160 -0
  108. spark_agent-0.9.6/tests/test_checkpoints.py +130 -0
  109. spark_agent-0.9.6/tests/test_cli_onboarding.py +234 -0
  110. spark_agent-0.9.6/tests/test_compaction.py +148 -0
  111. spark_agent-0.9.6/tests/test_config_acl.py +72 -0
  112. spark_agent-0.9.6/tests/test_config_provenance.py +106 -0
  113. spark_agent-0.9.6/tests/test_context.py +148 -0
  114. spark_agent-0.9.6/tests/test_desktop.py +40 -0
  115. spark_agent-0.9.6/tests/test_e2e_pipeline.py +334 -0
  116. spark_agent-0.9.6/tests/test_e2e_server.py +338 -0
  117. spark_agent-0.9.6/tests/test_exec.py +25 -0
  118. spark_agent-0.9.6/tests/test_git_bg_persist.py +194 -0
  119. spark_agent-0.9.6/tests/test_graph_routing.py +142 -0
  120. spark_agent-0.9.6/tests/test_hooks.py +158 -0
  121. spark_agent-0.9.6/tests/test_hooks_extended.py +146 -0
  122. spark_agent-0.9.6/tests/test_langgraph_path.py +172 -0
  123. spark_agent-0.9.6/tests/test_loop.py +88 -0
  124. spark_agent-0.9.6/tests/test_mcp.py +82 -0
  125. spark_agent-0.9.6/tests/test_mcp_bridge_boundary.py +231 -0
  126. spark_agent-0.9.6/tests/test_mcp_expose.py +54 -0
  127. spark_agent-0.9.6/tests/test_memory.py +249 -0
  128. spark_agent-0.9.6/tests/test_memory_store_boundary.py +338 -0
  129. spark_agent-0.9.6/tests/test_msg_ops.py +85 -0
  130. spark_agent-0.9.6/tests/test_p0_fixes.py +154 -0
  131. spark_agent-0.9.6/tests/test_p0_repo_map.py +63 -0
  132. spark_agent-0.9.6/tests/test_p0_telemetry.py +109 -0
  133. spark_agent-0.9.6/tests/test_p0_untrusted_sandbox.py +92 -0
  134. spark_agent-0.9.6/tests/test_p1_01_instructor.py +202 -0
  135. spark_agent-0.9.6/tests/test_p1_02_searchreplace.py +259 -0
  136. spark_agent-0.9.6/tests/test_p1_03_testcmd.py +254 -0
  137. spark_agent-0.9.6/tests/test_p1_04_declsubagent.py +315 -0
  138. spark_agent-0.9.6/tests/test_p1_05_pty.py +154 -0
  139. spark_agent-0.9.6/tests/test_p1_06_evals.py +141 -0
  140. spark_agent-0.9.6/tests/test_p1_07_mcp_registry.py +320 -0
  141. spark_agent-0.9.6/tests/test_p1_08_gitmemory.py +220 -0
  142. spark_agent-0.9.6/tests/test_p1_09_security.py +179 -0
  143. spark_agent-0.9.6/tests/test_p1_10_routing.py +242 -0
  144. spark_agent-0.9.6/tests/test_p1_capabilities.py +229 -0
  145. spark_agent-0.9.6/tests/test_p1_fixes.py +490 -0
  146. spark_agent-0.9.6/tests/test_p1_model_catalog.py +68 -0
  147. spark_agent-0.9.6/tests/test_p1_provider_resilience.py +153 -0
  148. spark_agent-0.9.6/tests/test_p2_context_profile.py +65 -0
  149. spark_agent-0.9.6/tests/test_p2_mcp_resources_prompts.py +77 -0
  150. spark_agent-0.9.6/tests/test_perf_bounds.py +304 -0
  151. spark_agent-0.9.6/tests/test_policy.py +83 -0
  152. spark_agent-0.9.6/tests/test_probe.py +78 -0
  153. spark_agent-0.9.6/tests/test_prompt_cache.py +99 -0
  154. spark_agent-0.9.6/tests/test_provider_config.py +63 -0
  155. spark_agent-0.9.6/tests/test_pty.py +105 -0
  156. spark_agent-0.9.6/tests/test_pty_http.py +131 -0
  157. spark_agent-0.9.6/tests/test_registry_scope.py +72 -0
  158. spark_agent-0.9.6/tests/test_reliability.py +198 -0
  159. spark_agent-0.9.6/tests/test_sandbox.py +18 -0
  160. spark_agent-0.9.6/tests/test_sandbox_policy.py +205 -0
  161. spark_agent-0.9.6/tests/test_sanitize.py +115 -0
  162. spark_agent-0.9.6/tests/test_search_web.py +90 -0
  163. spark_agent-0.9.6/tests/test_settings_api.py +180 -0
  164. spark_agent-0.9.6/tests/test_skills.py +90 -0
  165. spark_agent-0.9.6/tests/test_store.py +32 -0
  166. spark_agent-0.9.6/tests/test_store_fork.py +35 -0
  167. spark_agent-0.9.6/tests/test_task_notebook.py +146 -0
  168. spark_agent-0.9.6/tests/test_tools.py +63 -0
  169. spark_agent-0.9.6/tests/test_tui_welcome.py +199 -0
  170. spark_agent-0.9.6/tests/test_user_journeys.py +284 -0
  171. spark_agent-0.9.6/tests/test_web_port.py +32 -0
  172. spark_agent-0.9.6/tests/test_web_sse.py +262 -0
  173. spark_agent-0.9.6/tests/test_wildcard_permission.py +212 -0
  174. spark_agent-0.9.6/tests/test_worktree.py +141 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 badhope
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: spark-agent
3
+ Version: 0.9.6
4
+ Summary: Spark [Ember] — local-first coding agent with a Codex-style loop
5
+ License: MIT
6
+ Keywords: ai,agent,coding,local-first,llm,chatbot
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Classifier: Topic :: Software Development :: Code Generators
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: chromadb>=1.0
19
+ Requires-Dist: instructor<2.0,>=1.4
20
+ Requires-Dist: litellm<2.0,>=1.0
21
+ Requires-Dist: llama-index-core<1.0,>=0.12
22
+ Requires-Dist: llama-index-llms-openai-like<1.0,>=0.3
23
+ Requires-Dist: httpx<1.0,>=0.27
24
+ Requires-Dist: langgraph<1.0,>=0.3
25
+ Requires-Dist: langgraph-checkpoint-sqlite<3.0,>=2.0
26
+ Requires-Dist: mcp<2.0,>=1.0; python_version >= "3.10"
27
+ Requires-Dist: pydantic<3.0,>=2.7
28
+ Requires-Dist: pydantic-settings<3.0,>=2.0
29
+ Requires-Dist: textual<1.0,>=0.80
30
+ Requires-Dist: tomlkit<1.0,>=0.13
31
+ Requires-Dist: tree-sitter<0.27,>=0.25
32
+ Requires-Dist: tree-sitter-javascript<0.26,>=0.23
33
+ Requires-Dist: tree-sitter-python<0.26,>=0.23
34
+ Requires-Dist: tree-sitter-typescript<0.24,>=0.23
35
+ Requires-Dist: typer<1.0,>=0.12
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest>=8.0; extra == "dev"
38
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
39
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
40
+ Requires-Dist: ruff>=0.7; extra == "dev"
41
+ Requires-Dist: import-linter>=2.0; extra == "dev"
42
+ Requires-Dist: mypy>=1.11; extra == "dev"
43
+ Requires-Dist: bandit>=1.7; extra == "dev"
44
+ Requires-Dist: pre-commit>=3.6; extra == "dev"
45
+ Provides-Extra: telemetry
46
+ Requires-Dist: opentelemetry-api>=1.28; extra == "telemetry"
47
+ Requires-Dist: opentelemetry-sdk>=1.28; extra == "telemetry"
48
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.28; extra == "telemetry"
49
+ Provides-Extra: pty
50
+ Requires-Dist: ptyprocess>=0.7; sys_platform != "win32" and extra == "pty"
51
+ Provides-Extra: desktop
52
+ Requires-Dist: pywebview>=5.0; extra == "desktop"
53
+ Dynamic: license-file
54
+
55
+ > 🌐 [English](README.md) | [中文](README_zh.md)
56
+
57
+ # Spark — Local-first AI Coding Agent
58
+
59
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
60
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-brightgreen.svg)](https://www.python.org/)
61
+ [![Node 18+](https://img.shields.io/badge/node-18%2B-339933.svg)](https://nodejs.org/)
62
+
63
+ **Code stays with you. Keys stay with you.** A self-hosted AI coding assistant that runs entirely on your machine — zero privacy leaks, full control.
64
+
65
+ ## Core Values
66
+
67
+ 🔒 **Privacy First** — All code, conversation, and memory data stay entirely local. No third-party servers involved.
68
+ ⚡ **Four Form Factors** — Web UI, native desktop window, terminal TUI, and scriptable CLI.
69
+ 🧠 **Persistent Memory** — A vector memory store that remembers your project preferences, naming conventions, and workflow habits.
70
+ 🔬 **Four-Level Sandbox** — From read-only analysis to full access, tunable by risk profile.
71
+ ⏮️ **Checkpoint & Rollback** — Workspace snapshots plus conversation restore — jump to any previous state like Git.
72
+
73
+ ## Preview
74
+
75
+ ### Chat · driven by a real model
76
+
77
+ > SSE streaming, Markdown code blocks, expandable tool-call cards, live context-usage meter.
78
+ > This is a real session: the model read `pyproject.toml` and summarized the project — the `read_file` card shows ✓ Completed.
79
+
80
+ ![Chat](assets/screenshots/01-chat.png)
81
+
82
+ ### English UI · one-click switch
83
+
84
+ > Built-in Chinese/English localization (Settings → Display → Language). Here the model chained
85
+ > `read_file` + `glob` to survey the repo — both tool calls show Completed.
86
+
87
+ ![English UI](assets/screenshots/00-chat-en.png)
88
+
89
+ ### Settings · models and profiles
90
+
91
+ > 8 built-in presets (DeepSeek / Qwen / GLM / Kimi / Doubao / Agnes / Ollama / custom),
92
+ > multiple saved model profiles with one-click switching, a `Test connection` probe, and three reasoning-effort levels.
93
+
94
+ ![Settings · Model](assets/screenshots/02-settings-model.png)
95
+
96
+ ### Settings · permissions and sandbox
97
+
98
+ > Four access levels: sandbox-only / workspace (recommended) / full-access / unrestricted,
99
+ > each with an explicit behavior description. The protected-path list is user-editable and defaults to
100
+ > `/etc`, `/root/.spark` and Spark's own source tree.
101
+
102
+ ![Settings · Permissions](assets/screenshots/03-settings-permissions.png)
103
+
104
+ ### Settings · display and customization
105
+
106
+ > Light/dark/system theme, six display toggles (thinking / tools / plan card / context usage /
107
+ > session keywords / notices), and a **fully customizable system prompt** (empty = built-in default).
108
+
109
+ ![Settings · Display](assets/screenshots/04-settings-display.png)
110
+
111
+ ### File viewer · syntax highlighting
112
+
113
+ > Browse the workdir tree and preview files with line numbers and highlight.js syntax highlighting
114
+ > (including correct coloring of multi-line tokens), file sizes, and graceful handling of binary/oversized files.
115
+
116
+ ![File viewer](assets/screenshots/05-file-viewer.png)
117
+
118
+ ### Windows EXE · no install required
119
+
120
+ > Packaged with PyInstaller as a single executable (`dist/spark.exe`) — double-click to run, no Python needed.
121
+ > Shown here: the model really invoked `run_shell`, read back the output `42`, and reported the exit code correctly.
122
+
123
+ ![EXE run](assets/screenshots/06-exe-tool-call.png)
124
+
125
+ ## Quick Start
126
+
127
+ ```bash
128
+ git clone https://gitcode.com/badhope/spark # 或 GitHub: https://github.com/badhope/spark
129
+ cd spark && python3 -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
130
+ pip install -e ".[dev]"
131
+ spark web --workdir /your/project
132
+ ```
133
+
134
+ Open the printed address in your browser. **Without an API key Spark starts in demo mode (mock);
135
+ paste a key into the web settings and it switches to the real model immediately — no restart.**
136
+
137
+ Windows users can also build a portable EXE (Python 3.11+):
138
+
139
+ ```powershell
140
+ powershell -ExecutionPolicy Bypass -File scripts/build-windows.ps1
141
+ dist\spark\spark.exe web # or just double-click dist\spark.exe
142
+ ```
143
+
144
+ ## Four Form Factors
145
+
146
+ | Form | Command | Use case |
147
+ |------|---------|----------|
148
+ | Web UI | `spark web` | Everyday chat, file viewer, terminal, execution graph (auto-picks a free port) |
149
+ | Desktop | `spark desktop` | Native window via pywebview, bound to loopback |
150
+ | Terminal TUI | `spark` | Pure terminal environments, remote SSH |
151
+ | CLI / scripts | `spark exec "task"` | Automation, CI, piping |
152
+ | MCP server | `spark mcp-serve` | Expose every built-in tool to other MCP clients |
153
+
154
+ ## Feature Overview
155
+
156
+ | Category | Features |
157
+ |----------|----------|
158
+ | Chat | SSE streaming, Markdown code blocks, image attachments, reasoning stream display |
159
+ | Tools | File read/write, apply_edit with AST syntax gate, grep/glob, shell, background jobs, Jupyter, web search/fetch, full Git suite, worktrees |
160
+ | Planning | Multi-step plans (PlanCard visualization), parallel sub-agent delegation (up to 4), declarative sub-agents (`.claude/agents/*.md`) |
161
+ | Approval | Six approval modes (incl. plan-only / approve-plan), `[[permissions]]` wildcard rule engine, three-way approval dialog |
162
+ | Permissions | Four-level sandbox, protected paths, credential-path protection, token-level shell checks, MCP least-privilege allowlists |
163
+ | Memory | AGENTS.md injection, vector long-term memory (embeddings + optional reranker), auto-extraction, web-based management |
164
+ | Persistence | Sessions, checkpoint rollback (works without git), hot config reload, token usage stats |
165
+ | Models | Any OpenAI-compatible endpoint, local Ollama, multi-profile switching, `spark test` probe |
166
+ | Extension | MCP client (stdio/SSE/HTTP + OAuth), MCP registry search (with China-availability ratings), project skills `.spark/skills/`, lifecycle hooks |
167
+ | UI | Chinese/English, light/dark themes, command palette (Ctrl+K), file viewer, built-in terminal, web reader, execution graph, checkpoint panel |
168
+
169
+ ## Architecture
170
+
171
+ ![Architecture Overview](docs/assets/architecture.svg)
172
+
173
+ Detailed architecture → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
174
+
175
+ ## Platform Requirements
176
+
177
+ - Python 3.11+
178
+ - Node.js 18+ (frontend development only; the bundled frontend ships prebuilt)
179
+ - Any OpenAI-compatible API (DeepSeek, OpenAI, Ollama, Azure, Agnes, Unisound, SenseNova, …)
180
+ - Windows / macOS / Linux (one-click EXE build on Windows)
181
+
182
+ ## Documentation
183
+
184
+ | Document | Contents |
185
+ |----------|----------|
186
+ | [docs/INSTALL.md](docs/INSTALL.md) | Install & packaging (incl. Windows EXE) |
187
+ | [docs/CONFIGURATION.md](docs/CONFIGURATION.md) | Configuration reference (config.toml / env vars / API overview) |
188
+ | [docs/API.md](docs/API.md) | HTTP API and SSE event protocol |
189
+ | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Architecture notes |
190
+ | [docs/competitive-comparison.md](docs/competitive-comparison.md) | Feature comparison vs Qoder / ZCode / opencode / Codex CLI |
191
+
192
+ ## Community
193
+
194
+ - Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
195
+ - Issue Tracker: use the **Issues** tab of this repository
196
+
197
+ ---
198
+
199
+ **License:** MIT · **Author:** badhope · **Built with ❤️ in Shenzhen**
@@ -0,0 +1,145 @@
1
+ > 🌐 [English](README.md) | [中文](README_zh.md)
2
+
3
+ # Spark — Local-first AI Coding Agent
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-brightgreen.svg)](https://www.python.org/)
7
+ [![Node 18+](https://img.shields.io/badge/node-18%2B-339933.svg)](https://nodejs.org/)
8
+
9
+ **Code stays with you. Keys stay with you.** A self-hosted AI coding assistant that runs entirely on your machine — zero privacy leaks, full control.
10
+
11
+ ## Core Values
12
+
13
+ 🔒 **Privacy First** — All code, conversation, and memory data stay entirely local. No third-party servers involved.
14
+ ⚡ **Four Form Factors** — Web UI, native desktop window, terminal TUI, and scriptable CLI.
15
+ 🧠 **Persistent Memory** — A vector memory store that remembers your project preferences, naming conventions, and workflow habits.
16
+ 🔬 **Four-Level Sandbox** — From read-only analysis to full access, tunable by risk profile.
17
+ ⏮️ **Checkpoint & Rollback** — Workspace snapshots plus conversation restore — jump to any previous state like Git.
18
+
19
+ ## Preview
20
+
21
+ ### Chat · driven by a real model
22
+
23
+ > SSE streaming, Markdown code blocks, expandable tool-call cards, live context-usage meter.
24
+ > This is a real session: the model read `pyproject.toml` and summarized the project — the `read_file` card shows ✓ Completed.
25
+
26
+ ![Chat](assets/screenshots/01-chat.png)
27
+
28
+ ### English UI · one-click switch
29
+
30
+ > Built-in Chinese/English localization (Settings → Display → Language). Here the model chained
31
+ > `read_file` + `glob` to survey the repo — both tool calls show Completed.
32
+
33
+ ![English UI](assets/screenshots/00-chat-en.png)
34
+
35
+ ### Settings · models and profiles
36
+
37
+ > 8 built-in presets (DeepSeek / Qwen / GLM / Kimi / Doubao / Agnes / Ollama / custom),
38
+ > multiple saved model profiles with one-click switching, a `Test connection` probe, and three reasoning-effort levels.
39
+
40
+ ![Settings · Model](assets/screenshots/02-settings-model.png)
41
+
42
+ ### Settings · permissions and sandbox
43
+
44
+ > Four access levels: sandbox-only / workspace (recommended) / full-access / unrestricted,
45
+ > each with an explicit behavior description. The protected-path list is user-editable and defaults to
46
+ > `/etc`, `/root/.spark` and Spark's own source tree.
47
+
48
+ ![Settings · Permissions](assets/screenshots/03-settings-permissions.png)
49
+
50
+ ### Settings · display and customization
51
+
52
+ > Light/dark/system theme, six display toggles (thinking / tools / plan card / context usage /
53
+ > session keywords / notices), and a **fully customizable system prompt** (empty = built-in default).
54
+
55
+ ![Settings · Display](assets/screenshots/04-settings-display.png)
56
+
57
+ ### File viewer · syntax highlighting
58
+
59
+ > Browse the workdir tree and preview files with line numbers and highlight.js syntax highlighting
60
+ > (including correct coloring of multi-line tokens), file sizes, and graceful handling of binary/oversized files.
61
+
62
+ ![File viewer](assets/screenshots/05-file-viewer.png)
63
+
64
+ ### Windows EXE · no install required
65
+
66
+ > Packaged with PyInstaller as a single executable (`dist/spark.exe`) — double-click to run, no Python needed.
67
+ > Shown here: the model really invoked `run_shell`, read back the output `42`, and reported the exit code correctly.
68
+
69
+ ![EXE run](assets/screenshots/06-exe-tool-call.png)
70
+
71
+ ## Quick Start
72
+
73
+ ```bash
74
+ git clone https://gitcode.com/badhope/spark # 或 GitHub: https://github.com/badhope/spark
75
+ cd spark && python3 -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
76
+ pip install -e ".[dev]"
77
+ spark web --workdir /your/project
78
+ ```
79
+
80
+ Open the printed address in your browser. **Without an API key Spark starts in demo mode (mock);
81
+ paste a key into the web settings and it switches to the real model immediately — no restart.**
82
+
83
+ Windows users can also build a portable EXE (Python 3.11+):
84
+
85
+ ```powershell
86
+ powershell -ExecutionPolicy Bypass -File scripts/build-windows.ps1
87
+ dist\spark\spark.exe web # or just double-click dist\spark.exe
88
+ ```
89
+
90
+ ## Four Form Factors
91
+
92
+ | Form | Command | Use case |
93
+ |------|---------|----------|
94
+ | Web UI | `spark web` | Everyday chat, file viewer, terminal, execution graph (auto-picks a free port) |
95
+ | Desktop | `spark desktop` | Native window via pywebview, bound to loopback |
96
+ | Terminal TUI | `spark` | Pure terminal environments, remote SSH |
97
+ | CLI / scripts | `spark exec "task"` | Automation, CI, piping |
98
+ | MCP server | `spark mcp-serve` | Expose every built-in tool to other MCP clients |
99
+
100
+ ## Feature Overview
101
+
102
+ | Category | Features |
103
+ |----------|----------|
104
+ | Chat | SSE streaming, Markdown code blocks, image attachments, reasoning stream display |
105
+ | Tools | File read/write, apply_edit with AST syntax gate, grep/glob, shell, background jobs, Jupyter, web search/fetch, full Git suite, worktrees |
106
+ | Planning | Multi-step plans (PlanCard visualization), parallel sub-agent delegation (up to 4), declarative sub-agents (`.claude/agents/*.md`) |
107
+ | Approval | Six approval modes (incl. plan-only / approve-plan), `[[permissions]]` wildcard rule engine, three-way approval dialog |
108
+ | Permissions | Four-level sandbox, protected paths, credential-path protection, token-level shell checks, MCP least-privilege allowlists |
109
+ | Memory | AGENTS.md injection, vector long-term memory (embeddings + optional reranker), auto-extraction, web-based management |
110
+ | Persistence | Sessions, checkpoint rollback (works without git), hot config reload, token usage stats |
111
+ | Models | Any OpenAI-compatible endpoint, local Ollama, multi-profile switching, `spark test` probe |
112
+ | Extension | MCP client (stdio/SSE/HTTP + OAuth), MCP registry search (with China-availability ratings), project skills `.spark/skills/`, lifecycle hooks |
113
+ | UI | Chinese/English, light/dark themes, command palette (Ctrl+K), file viewer, built-in terminal, web reader, execution graph, checkpoint panel |
114
+
115
+ ## Architecture
116
+
117
+ ![Architecture Overview](docs/assets/architecture.svg)
118
+
119
+ Detailed architecture → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
120
+
121
+ ## Platform Requirements
122
+
123
+ - Python 3.11+
124
+ - Node.js 18+ (frontend development only; the bundled frontend ships prebuilt)
125
+ - Any OpenAI-compatible API (DeepSeek, OpenAI, Ollama, Azure, Agnes, Unisound, SenseNova, …)
126
+ - Windows / macOS / Linux (one-click EXE build on Windows)
127
+
128
+ ## Documentation
129
+
130
+ | Document | Contents |
131
+ |----------|----------|
132
+ | [docs/INSTALL.md](docs/INSTALL.md) | Install & packaging (incl. Windows EXE) |
133
+ | [docs/CONFIGURATION.md](docs/CONFIGURATION.md) | Configuration reference (config.toml / env vars / API overview) |
134
+ | [docs/API.md](docs/API.md) | HTTP API and SSE event protocol |
135
+ | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Architecture notes |
136
+ | [docs/competitive-comparison.md](docs/competitive-comparison.md) | Feature comparison vs Qoder / ZCode / opencode / Codex CLI |
137
+
138
+ ## Community
139
+
140
+ - Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
141
+ - Issue Tracker: use the **Issues** tab of this repository
142
+
143
+ ---
144
+
145
+ **License:** MIT · **Author:** badhope · **Built with ❤️ in Shenzhen**
@@ -0,0 +1,129 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "spark-agent"
7
+ version = "0.9.6"
8
+ description = "Spark [Ember] — local-first coding agent with a Codex-style loop"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ keywords = ["ai", "agent", "coding", "local-first", "llm", "chatbot"]
12
+ requires-python = ">=3.11"
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
21
+ "Topic :: Software Development :: Code Generators",
22
+ ]
23
+ dependencies = [
24
+ "chromadb>=1.0",
25
+ "instructor>=1.4,<2.0",
26
+ "litellm>=1.0,<2.0",
27
+ "llama-index-core>=0.12,<1.0",
28
+ "llama-index-llms-openai-like>=0.3,<1.0",
29
+ "httpx>=0.27,<1.0",
30
+ "langgraph>=0.3,<1.0",
31
+ "langgraph-checkpoint-sqlite>=2.0,<3.0",
32
+ "mcp>=1.0,<2.0; python_version>=\"3.10\"",
33
+ "pydantic>=2.7,<3.0",
34
+ "pydantic-settings>=2.0,<3.0",
35
+ "textual>=0.80,<1.0",
36
+ "tomlkit>=0.13,<1.0",
37
+ "tree-sitter>=0.25,<0.27",
38
+ "tree-sitter-javascript>=0.23,<0.26",
39
+ "tree-sitter-python>=0.23,<0.26",
40
+ "tree-sitter-typescript>=0.23,<0.24",
41
+ "typer>=0.12,<1.0",
42
+ ]
43
+
44
+ [project.optional-dependencies]
45
+ dev = [
46
+ "pytest>=8.0",
47
+ "pytest-asyncio>=0.23",
48
+ "pytest-cov>=4.1",
49
+ "ruff>=0.7",
50
+ "import-linter>=2.0",
51
+ "mypy>=1.11",
52
+ "bandit>=1.7",
53
+ "pre-commit>=3.6",
54
+ ]
55
+ # P0-9: 观测(Langfuse 自托管 = OTLP 端点,spark 直接接入 OTLP 即可)
56
+ telemetry = [
57
+ "opentelemetry-api>=1.28",
58
+ "opentelemetry-sdk>=1.28",
59
+ "opentelemetry-exporter-otlp-proto-grpc>=1.28",
60
+ ]
61
+ # P1-5: 内置终端(真实 PTY)。Windows 不支持(需 winpty/ConPTY),
62
+ # 故用环境标记排除;未安装时 spark.pty 可导入但 PtyManager() 给出清晰报错。
63
+ pty = [
64
+ "ptyprocess>=0.7; sys_platform != 'win32'",
65
+ ]
66
+ desktop = [
67
+ "pywebview>=5.0",
68
+ ]
69
+
70
+ [project.scripts]
71
+ spark = "spark.cli:app"
72
+
73
+ [tool.setuptools.packages.find]
74
+ where = ["src"]
75
+
76
+ [tool.setuptools.package-data]
77
+ spark = ["prompts/*.md", "web/*.html", "web/dist/*", "web/dist/assets/*", "evals/data/*.json"]
78
+
79
+ [tool.pytest.ini_options]
80
+ asyncio_mode = "auto"
81
+ testpaths = ["tests"]
82
+ pythonpath = ["src"]
83
+
84
+ [tool.ruff]
85
+ line-length = 100
86
+ target-version = "py311"
87
+
88
+ [tool.ruff.lint]
89
+ select = [
90
+ "E4", # pycodestyle import errors
91
+ "E7", # pycodestyle statement errors
92
+ "E9", # pycodestyle runtime errors
93
+ "F", # pyflakes
94
+ "I001", # import sorting
95
+ ]
96
+ ignore = []
97
+
98
+ [tool.ruff.lint.per-file-ignores]
99
+ # search.py deliberately defers pydantic/spark imports to avoid a circular
100
+ # import at module load time.
101
+ "src/spark/tools/search.py" = ["E402"]
102
+ # 以下文件中 logger = logging.getLogger(__name__) 紧跟在 __future__ 与 stdlib
103
+ # 导入之后、第三方/本地导入之前,避免 E402 噪音。
104
+ "src/spark/core/graph.py" = ["E402"]
105
+ "src/spark/memory/service.py" = ["E402"]
106
+ "src/spark/tools/shell.py" = ["E402"]
107
+ "src/spark/tui/app.py" = ["E402"]
108
+ # routes.py 保持 import-light:pty 写路径在 _POST_HANDLERS 定义后就近懒加载,
109
+ # 不为 import 排序把 pty 依赖提到模块顶部。
110
+ "src/spark/web/routes.py" = ["E402", "I001"]
111
+
112
+ [tool.mypy]
113
+ python_version = "3.11"
114
+ ignore_missing_imports = true
115
+ warn_unused_ignores = false
116
+ warn_return_any = false
117
+ check_untyped_defs = false
118
+
119
+ [[tool.mypy.overrides]]
120
+ module = [
121
+ "chromadb.*",
122
+ "llama_index.*",
123
+ "langgraph.*",
124
+ "litellm.*",
125
+ "textual.*",
126
+ "typer.*",
127
+ ]
128
+ ignore_missing_imports = true
129
+ follow_imports = "skip"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,14 @@
1
+ """Spark — local-first AI coding agent."""
2
+
3
+ import os
4
+
5
+ # Skip LiteLLM's model-cost-map fetch from raw.githubusercontent.com, which is
6
+ # unreachable from mainland China and burns ~9s of connection retries on every
7
+ # process start. The bundled local map ships in the wheel; users can opt back
8
+ # into remote refreshes by setting the variable to False explicitly.
9
+ # Must run before the first litellm import anywhere in the package (litellm
10
+ # reads this variable at import time), so it lives at the package root —
11
+ # every entry point (cli/web/desktop) imports spark first.
12
+ os.environ.setdefault("LITELLM_LOCAL_MODEL_COST_MAP", "True")
13
+
14
+ __version__ = "0.9.6"
@@ -0,0 +1,4 @@
1
+ from spark.cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()