chad-code 1.0.7__tar.gz → 1.0.8__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.
- {chad_code-1.0.7/src/chad_code.egg-info → chad_code-1.0.8}/PKG-INFO +21 -5
- {chad_code-1.0.7 → chad_code-1.0.8}/README.md +20 -4
- {chad_code-1.0.7 → chad_code-1.0.8}/pyproject.toml +9 -5
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/__init__.py +1 -1
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/speech.py +22 -1
- {chad_code-1.0.7 → chad_code-1.0.8/src/chad_code.egg-info}/PKG-INFO +21 -5
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_speech.py +18 -1
- {chad_code-1.0.7 → chad_code-1.0.8}/LICENSE +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/setup.cfg +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/agent.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/atif.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/base_engine.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/bench.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/cli.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/compaction.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/completion_engine.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/config.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/diag.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/engine.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/guardrails.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/ignore.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/levers.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/lsp.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/lspclient.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/lspservers.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/mcp.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/mcp_oauth.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/mlx_fastpath.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/mlx_qsdpa.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/LICENSE +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/__init__.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/alignment.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/attention.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/audio.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/cache.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/conformer.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/ctc.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/parakeet.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/rnnt.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/tokenizer.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/parakeet/utils.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/profiles.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/prompt.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/prove.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/render.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/repomap.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/serve.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/session.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/skills.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/symbols.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/syntaxgate.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/toolcall_parse.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/tools.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/tui.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad/validate.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad_code.egg-info/SOURCES.txt +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad_code.egg-info/dependency_links.txt +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad_code.egg-info/entry_points.txt +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad_code.egg-info/requires.txt +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/src/chad_code.egg-info/top_level.txt +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_agent.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_agent_e2e.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_agent_guards.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_atif.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_bench.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_cli.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_compact_notice.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_compaction.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_completion_engine.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_config.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_confirm_preview.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_done_audit.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_drift_warn.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_edit.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_edit_corruption.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_engine.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_engine_kvquant.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_engine_pld_hybrid.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_feel_pack.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_garble_invariant.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_gate.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_ignore.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_intent.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_lever_bite.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_levers.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_log_redaction.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_lsp.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_lsp_live.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_lspclient.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_mcp.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_mcp_oauth.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_mlx_fastpath.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_mlx_qsdpa.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_plan_review.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_prove.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_render.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_replace_lines.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_repomap.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_repomap_polyglot.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_serve.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_session.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_skills.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_speech_tui.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_subagent.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_symbols.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_syntaxgate.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_toolcall_parse.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_tools.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_tui.py +0 -0
- {chad_code-1.0.7 → chad_code-1.0.8}/tests/test_validate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chad-code
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/nathansutton/chad
|
|
@@ -139,6 +139,21 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
139
139
|
uv run chad -c # resume this directory's last conversation
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
**Optional extras.** Everything core is in the base install; two features are opt-in
|
|
143
|
+
because they pull deps not every install wants — `speech` (voice mode: a mic library,
|
|
144
|
+
no torch) and `highlight` (syntax colour in diffs/previews). An extra rides on the
|
|
145
|
+
**install spec**, not on a separate command, so how you add it depends on how you
|
|
146
|
+
installed chad:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
uv tool install --force 'chad-code[speech]' # add to an existing `uv tool` install
|
|
150
|
+
uvx --from 'chad-code[speech]' chad # one-off run, nothing installed
|
|
151
|
+
uv sync --extra speech # from a clone
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`/speech` in the TUI prints whichever of those matches your install, so you never have
|
|
155
|
+
to work it out from here.
|
|
156
|
+
|
|
142
157
|
**The model.** chad picks one for you by RAM and downloads it once into the shared Hugging
|
|
143
158
|
Face cache (`~/.cache/huggingface`, reused across every project). Override with
|
|
144
159
|
`--model 9b` / `--model 35b`, or `--model <repo or local dir>` for anything else.
|
|
@@ -164,8 +179,8 @@ re-downloads the model.
|
|
|
164
179
|
**Development.** `uv sync` once, then `uv run pytest -q` — the fast unit gate loads **no
|
|
165
180
|
model weights**, runs in seconds, and is what CI runs. Throughput on your own machine:
|
|
166
181
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)). LSP-precise
|
|
167
|
-
find-references / rename need
|
|
168
|
-
|
|
182
|
+
find-references / rename need no extra — chad fetches pyright via `uvx` on first use and
|
|
183
|
+
falls back to tree-sitter when a language server can't start.
|
|
169
184
|
|
|
170
185
|
## Interactive UX
|
|
171
186
|
|
|
@@ -191,8 +206,9 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
191
206
|
isn't clipped, and a personal word table (`~/.chad/speech_words.json`) teaches it your
|
|
192
207
|
identifiers — `{"pie test": "pytest"}`. Dictation cost is linear in take length, so a
|
|
193
208
|
long thought is fine; `/speech` off releases both the mic and the weights. Nothing
|
|
194
|
-
leaves the machine. Needs the `speech` extra
|
|
195
|
-
|
|
209
|
+
leaves the machine. Needs the `speech` extra — just a mic library; no torch, no numba
|
|
210
|
+
(see [Installing & upgrading](#installing--upgrading); on a `uv tool` install that's
|
|
211
|
+
`uv tool install --force 'chad-code[speech]'`).
|
|
196
212
|
|
|
197
213
|
**Usage.** `uv run chad --help` is the source of truth:
|
|
198
214
|
|
|
@@ -103,6 +103,21 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
103
103
|
uv run chad -c # resume this directory's last conversation
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
**Optional extras.** Everything core is in the base install; two features are opt-in
|
|
107
|
+
because they pull deps not every install wants — `speech` (voice mode: a mic library,
|
|
108
|
+
no torch) and `highlight` (syntax colour in diffs/previews). An extra rides on the
|
|
109
|
+
**install spec**, not on a separate command, so how you add it depends on how you
|
|
110
|
+
installed chad:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
uv tool install --force 'chad-code[speech]' # add to an existing `uv tool` install
|
|
114
|
+
uvx --from 'chad-code[speech]' chad # one-off run, nothing installed
|
|
115
|
+
uv sync --extra speech # from a clone
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`/speech` in the TUI prints whichever of those matches your install, so you never have
|
|
119
|
+
to work it out from here.
|
|
120
|
+
|
|
106
121
|
**The model.** chad picks one for you by RAM and downloads it once into the shared Hugging
|
|
107
122
|
Face cache (`~/.cache/huggingface`, reused across every project). Override with
|
|
108
123
|
`--model 9b` / `--model 35b`, or `--model <repo or local dir>` for anything else.
|
|
@@ -128,8 +143,8 @@ re-downloads the model.
|
|
|
128
143
|
**Development.** `uv sync` once, then `uv run pytest -q` — the fast unit gate loads **no
|
|
129
144
|
model weights**, runs in seconds, and is what CI runs. Throughput on your own machine:
|
|
130
145
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)). LSP-precise
|
|
131
|
-
find-references / rename need
|
|
132
|
-
|
|
146
|
+
find-references / rename need no extra — chad fetches pyright via `uvx` on first use and
|
|
147
|
+
falls back to tree-sitter when a language server can't start.
|
|
133
148
|
|
|
134
149
|
## Interactive UX
|
|
135
150
|
|
|
@@ -155,8 +170,9 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
155
170
|
isn't clipped, and a personal word table (`~/.chad/speech_words.json`) teaches it your
|
|
156
171
|
identifiers — `{"pie test": "pytest"}`. Dictation cost is linear in take length, so a
|
|
157
172
|
long thought is fine; `/speech` off releases both the mic and the weights. Nothing
|
|
158
|
-
leaves the machine. Needs the `speech` extra
|
|
159
|
-
|
|
173
|
+
leaves the machine. Needs the `speech` extra — just a mic library; no torch, no numba
|
|
174
|
+
(see [Installing & upgrading](#installing--upgrading); on a `uv tool` install that's
|
|
175
|
+
`uv tool install --force 'chad-code[speech]'`).
|
|
160
176
|
|
|
161
177
|
**Usage.** `uv run chad --help` is the source of truth:
|
|
162
178
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# import name, and command name are independent. `uvx chad-code` runs the alias
|
|
5
5
|
# script added under [project.scripts].
|
|
6
6
|
name = "chad-code"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.8"
|
|
8
8
|
description = "Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -72,11 +72,15 @@ dependencies = [
|
|
|
72
72
|
"mcp>=2,<3",
|
|
73
73
|
]
|
|
74
74
|
|
|
75
|
+
# Extras ride on the INSTALL SPEC, so the command depends on how chad was installed:
|
|
76
|
+
# `uv tool install --force 'chad-code[<extra>]'` (or `uvx --from 'chad-code[<extra>]' chad`)
|
|
77
|
+
# for a PyPI install, `uv sync --extra <extra>` only in a clone. speech.install_hint()
|
|
78
|
+
# derives the right one at runtime — keep it in step with any extra added here.
|
|
79
|
+
# NOTE: the PyPI distribution is `chad-code`; 'pip install chad' installs an unrelated
|
|
80
|
+
# squatted package.
|
|
81
|
+
#
|
|
75
82
|
# Optional syntax highlighting in diffs / confirm previews. Pure-Python,
|
|
76
83
|
# import-guarded in render.py: absent, output is byte-identical to the un-highlighted path.
|
|
77
|
-
# Install with `uv sync --extra highlight`.
|
|
78
|
-
# NOTE: no PyPI release exists; 'pip install chad' installs an unrelated squatted
|
|
79
|
-
# package. Document uv/git installs only.
|
|
80
84
|
[project.optional-dependencies]
|
|
81
85
|
highlight = ["pygments>=2.17"]
|
|
82
86
|
# Voice mode (/speech in the TUI): push-to-talk dictation via chad's vendored
|
|
@@ -85,7 +89,7 @@ highlight = ["pygments>=2.17"]
|
|
|
85
89
|
# `say`. All on-device, nothing leaves the machine. mlx/numpy/huggingface-hub
|
|
86
90
|
# are already core deps, so the extra adds only the mic (sounddevice/PortAudio).
|
|
87
91
|
# Optional and import-guarded in speech.py: absent, /speech prints the install
|
|
88
|
-
# hint and everything else is untouched.
|
|
92
|
+
# hint and everything else is untouched.
|
|
89
93
|
speech = [
|
|
90
94
|
"sounddevice>=0.5",
|
|
91
95
|
]
|
|
@@ -4,7 +4,7 @@ A flat collection of cooperating modules behind one console script (``chad``):
|
|
|
4
4
|
the inference engine, the tool layer, the agent loop, and the terminal UI.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "1.0.
|
|
7
|
+
__version__ = "1.0.8"
|
|
8
8
|
|
|
9
9
|
# chad sets no MLX_* runtime vars. MLX_METAL_FAST_SYNCH, MLX_MAX_OPS_PER_BUFFER
|
|
10
10
|
# and MLX_MAX_MB_PER_BUFFER were each measured end-to-end on the 35B and every
|
|
@@ -85,6 +85,27 @@ def model_cached() -> bool:
|
|
|
85
85
|
return False
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
def install_hint(extra: str = "speech", path: str | None = None) -> str:
|
|
89
|
+
"""The command that adds an optional extra to THIS install.
|
|
90
|
+
|
|
91
|
+
There is no single right answer: an extra attaches to the install SPEC for a
|
|
92
|
+
`uv tool`/`uvx` install and to `uv sync` only in a clone, so the one-line
|
|
93
|
+
hint /speech prints has to know which of those it's talking to — a clone-only
|
|
94
|
+
hint sends the (majority) PyPI user to a command that can't work. Keyed off
|
|
95
|
+
where this file physically lives, the one thing we can observe.
|
|
96
|
+
"""
|
|
97
|
+
here = os.path.realpath(path or __file__)
|
|
98
|
+
if f"{os.sep}uv{os.sep}tools{os.sep}" in here: # uv tool install
|
|
99
|
+
return f"uv tool install --force 'chad-code[{extra}]'"
|
|
100
|
+
# uvx's ephemeral env: hardlinked out of the uv cache (archive-v*/environments-v*).
|
|
101
|
+
if f"{os.sep}uv{os.sep}archive-" in here or f"{os.sep}uv{os.sep}environments-" in here:
|
|
102
|
+
return f"uvx --from 'chad-code[{extra}]' chad"
|
|
103
|
+
root = os.path.dirname(os.path.dirname(os.path.dirname(here))) # src/chad/x.py -> repo
|
|
104
|
+
if os.path.exists(os.path.join(root, "pyproject.toml")):
|
|
105
|
+
return f"uv sync --extra {extra}"
|
|
106
|
+
return f"uv pip install 'chad-code[{extra}]'" # a plain venv
|
|
107
|
+
|
|
108
|
+
|
|
88
109
|
def available():
|
|
89
110
|
"""(ok, reason). ok=False carries the one-line reason speech can't start —
|
|
90
111
|
surfaced verbatim by /speech, so it names the fix, not just the failure."""
|
|
@@ -102,7 +123,7 @@ def available():
|
|
|
102
123
|
missing.append("sounddevice")
|
|
103
124
|
if missing:
|
|
104
125
|
return False, (f"speech needs {' + '.join(missing)} — install with "
|
|
105
|
-
f"`
|
|
126
|
+
f"`{install_hint()}` (all local: Parakeet-on-MLX STT, "
|
|
106
127
|
f"macOS `say` TTS)")
|
|
107
128
|
return True, ""
|
|
108
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chad-code
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: Local MLX-backed, Claude-Code-style coding agent (Apple Silicon, Ornith 35B/9B)
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Repository, https://github.com/nathansutton/chad
|
|
@@ -139,6 +139,21 @@ uv run chad "add a --json flag to main.py and update the tests" # one-shot, he
|
|
|
139
139
|
uv run chad -c # resume this directory's last conversation
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
**Optional extras.** Everything core is in the base install; two features are opt-in
|
|
143
|
+
because they pull deps not every install wants — `speech` (voice mode: a mic library,
|
|
144
|
+
no torch) and `highlight` (syntax colour in diffs/previews). An extra rides on the
|
|
145
|
+
**install spec**, not on a separate command, so how you add it depends on how you
|
|
146
|
+
installed chad:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
uv tool install --force 'chad-code[speech]' # add to an existing `uv tool` install
|
|
150
|
+
uvx --from 'chad-code[speech]' chad # one-off run, nothing installed
|
|
151
|
+
uv sync --extra speech # from a clone
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`/speech` in the TUI prints whichever of those matches your install, so you never have
|
|
155
|
+
to work it out from here.
|
|
156
|
+
|
|
142
157
|
**The model.** chad picks one for you by RAM and downloads it once into the shared Hugging
|
|
143
158
|
Face cache (`~/.cache/huggingface`, reused across every project). Override with
|
|
144
159
|
`--model 9b` / `--model 35b`, or `--model <repo or local dir>` for anything else.
|
|
@@ -164,8 +179,8 @@ re-downloads the model.
|
|
|
164
179
|
**Development.** `uv sync` once, then `uv run pytest -q` — the fast unit gate loads **no
|
|
165
180
|
model weights**, runs in seconds, and is what CI runs. Throughput on your own machine:
|
|
166
181
|
`uv run chad-bench` (see [Throughput & performance](docs/benchmarks.md)). LSP-precise
|
|
167
|
-
find-references / rename need
|
|
168
|
-
|
|
182
|
+
find-references / rename need no extra — chad fetches pyright via `uvx` on first use and
|
|
183
|
+
falls back to tree-sitter when a language server can't start.
|
|
169
184
|
|
|
170
185
|
## Interactive UX
|
|
171
186
|
|
|
@@ -191,8 +206,9 @@ it chad uses the tree-sitter fallback automatically.
|
|
|
191
206
|
isn't clipped, and a personal word table (`~/.chad/speech_words.json`) teaches it your
|
|
192
207
|
identifiers — `{"pie test": "pytest"}`. Dictation cost is linear in take length, so a
|
|
193
208
|
long thought is fine; `/speech` off releases both the mic and the weights. Nothing
|
|
194
|
-
leaves the machine. Needs the `speech` extra
|
|
195
|
-
|
|
209
|
+
leaves the machine. Needs the `speech` extra — just a mic library; no torch, no numba
|
|
210
|
+
(see [Installing & upgrading](#installing--upgrading); on a `uv tool` install that's
|
|
211
|
+
`uv tool install --force 'chad-code[speech]'`).
|
|
196
212
|
|
|
197
213
|
**Usage.** `uv run chad --help` is the source of truth:
|
|
198
214
|
|
|
@@ -110,7 +110,24 @@ def test_available_reports_missing_deps_as_hint():
|
|
|
110
110
|
ok, reason = speech.available()
|
|
111
111
|
assert ok in (True, False)
|
|
112
112
|
if not ok:
|
|
113
|
-
assert "
|
|
113
|
+
assert "sounddevice" in reason and "speech" in reason
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_install_hint_matches_how_chad_was_installed():
|
|
117
|
+
# The hint is the whole fix, so it has to name the command that works for the
|
|
118
|
+
# reader: extras ride on the install spec for uvx/tool installs, on `uv sync`
|
|
119
|
+
# only in a clone. Paths are the real shapes uv produces.
|
|
120
|
+
h = speech.install_hint
|
|
121
|
+
assert h(path="/Users/x/.local/share/uv/tools/chad-code/lib/python3.13/"
|
|
122
|
+
"site-packages/chad/speech.py") == \
|
|
123
|
+
"uv tool install --force 'chad-code[speech]'"
|
|
124
|
+
assert h(path="/Users/x/.cache/uv/archive-v0/abc123/lib/python3.13/"
|
|
125
|
+
"site-packages/chad/speech.py") == "uvx --from 'chad-code[speech]' chad"
|
|
126
|
+
assert h(path="/Users/x/.local/share/uv/python/venv/lib/python3.13/"
|
|
127
|
+
"site-packages/chad/speech.py") == "uv pip install 'chad-code[speech]'"
|
|
128
|
+
# This test file IS a clone, so the live module resolves to the clone form.
|
|
129
|
+
assert speech.install_hint() == "uv sync --extra speech"
|
|
130
|
+
assert h("highlight") == "uv sync --extra highlight"
|
|
114
131
|
|
|
115
132
|
|
|
116
133
|
def test_collapse_repeats_kills_hallucination_loop():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|