substrate-setup 0.3.0__tar.gz → 0.4.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.
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/.gitignore +77 -77
- substrate_setup-0.4.0/CHANGELOG.md +38 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/PKG-INFO +56 -12
- substrate_setup-0.4.0/README.md +90 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/pyproject.toml +80 -63
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/scripts/lint_no_app_import.sh +10 -10
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/scripts/regenerate_fallback_catalog.py +68 -68
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/__init__.py +6 -6
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/__main__.py +5 -5
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/__init__.py +24 -24
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/aider.py +409 -393
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/base.py +69 -56
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/claude_code.py +355 -339
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/codex.py +369 -345
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/continue_dev.py +298 -282
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/cursor.py +111 -94
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/agents/hermes.py +520 -504
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/backup.py +32 -32
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/catalog.py +115 -115
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/cli.py +249 -249
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/credentials.py +82 -82
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/data/fallback_catalog.json +343 -343
- substrate_setup-0.4.0/substrate_setup/env_persist.py +242 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/substrate_setup/markers.py +27 -27
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_aider.py +390 -364
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_claude_code.py +290 -262
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_codex.py +366 -278
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_continue_dev.py +283 -257
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_cursor.py +161 -111
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/test_hermes.py +630 -606
- substrate_setup-0.4.0/tests/conftest.py +37 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_backup.py +38 -38
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_catalog.py +95 -95
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_cli.py +287 -226
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_credentials.py +80 -80
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_e2e.py +152 -152
- substrate_setup-0.4.0/tests/test_env_persist.py +210 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/test_markers.py +45 -45
- substrate_setup-0.4.0/uv.lock +866 -0
- substrate_setup-0.3.0/README.md +0 -51
- substrate_setup-0.3.0/tests/conftest.py +0 -19
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/__init__.py +0 -0
- {substrate_setup-0.3.0 → substrate_setup-0.4.0}/tests/agents/__init__.py +0 -0
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
# Secrets
|
|
2
|
-
.env
|
|
3
|
-
.env.local
|
|
4
|
-
.env.*.local
|
|
5
|
-
*.secret
|
|
6
|
-
secrets/
|
|
7
|
-
credentials.txt
|
|
8
|
-
credentials.*.txt
|
|
9
|
-
|
|
10
|
-
# Python
|
|
11
|
-
__pycache__/
|
|
12
|
-
*.py[cod]
|
|
13
|
-
*$py.class
|
|
14
|
-
*.so
|
|
15
|
-
.Python
|
|
16
|
-
.venv/
|
|
17
|
-
venv/
|
|
18
|
-
env/
|
|
19
|
-
.pytest_cache/
|
|
20
|
-
.mypy_cache/
|
|
21
|
-
.ruff_cache/
|
|
22
|
-
*.egg-info/
|
|
23
|
-
dist/
|
|
24
|
-
build/
|
|
25
|
-
|
|
26
|
-
# Node / Next.js
|
|
27
|
-
node_modules/
|
|
28
|
-
.next/
|
|
29
|
-
.vercel/
|
|
30
|
-
.turbo/
|
|
31
|
-
|
|
32
|
-
# CodeGraph (local-only code knowledge graph index)
|
|
33
|
-
.codegraph/
|
|
34
|
-
out/
|
|
35
|
-
*.tsbuildinfo
|
|
36
|
-
.npm/
|
|
37
|
-
.yarn/
|
|
38
|
-
|
|
39
|
-
# IDE
|
|
40
|
-
.vscode/
|
|
41
|
-
.idea/
|
|
42
|
-
*.swp
|
|
43
|
-
*.swo
|
|
44
|
-
|
|
45
|
-
# OS
|
|
46
|
-
.DS_Store
|
|
47
|
-
Thumbs.db
|
|
48
|
-
desktop.ini
|
|
49
|
-
|
|
50
|
-
# Logs
|
|
51
|
-
*.log
|
|
52
|
-
logs/
|
|
53
|
-
|
|
54
|
-
# Local databases
|
|
55
|
-
*.db
|
|
56
|
-
*.sqlite
|
|
57
|
-
*.sqlite3
|
|
58
|
-
|
|
59
|
-
# Editors
|
|
60
|
-
*~
|
|
61
|
-
.#*
|
|
62
|
-
|
|
63
|
-
# Coverage
|
|
64
|
-
.coverage
|
|
65
|
-
htmlcov/
|
|
66
|
-
coverage.xml
|
|
67
|
-
*.cover
|
|
68
|
-
|
|
69
|
-
# Claude Code project state (if any project-local)
|
|
70
|
-
.claude/
|
|
71
|
-
|
|
72
|
-
# Misc
|
|
73
|
-
*.bak
|
|
74
|
-
*.tmp
|
|
75
|
-
|
|
76
|
-
# brainstorming companion working dir
|
|
77
|
-
.superpowers/
|
|
1
|
+
# Secrets
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
.env.*.local
|
|
5
|
+
*.secret
|
|
6
|
+
secrets/
|
|
7
|
+
credentials.txt
|
|
8
|
+
credentials.*.txt
|
|
9
|
+
|
|
10
|
+
# Python
|
|
11
|
+
__pycache__/
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
*.so
|
|
15
|
+
.Python
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.ruff_cache/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
dist/
|
|
24
|
+
build/
|
|
25
|
+
|
|
26
|
+
# Node / Next.js
|
|
27
|
+
node_modules/
|
|
28
|
+
.next/
|
|
29
|
+
.vercel/
|
|
30
|
+
.turbo/
|
|
31
|
+
|
|
32
|
+
# CodeGraph (local-only code knowledge graph index)
|
|
33
|
+
.codegraph/
|
|
34
|
+
out/
|
|
35
|
+
*.tsbuildinfo
|
|
36
|
+
.npm/
|
|
37
|
+
.yarn/
|
|
38
|
+
|
|
39
|
+
# IDE
|
|
40
|
+
.vscode/
|
|
41
|
+
.idea/
|
|
42
|
+
*.swp
|
|
43
|
+
*.swo
|
|
44
|
+
|
|
45
|
+
# OS
|
|
46
|
+
.DS_Store
|
|
47
|
+
Thumbs.db
|
|
48
|
+
desktop.ini
|
|
49
|
+
|
|
50
|
+
# Logs
|
|
51
|
+
*.log
|
|
52
|
+
logs/
|
|
53
|
+
|
|
54
|
+
# Local databases
|
|
55
|
+
*.db
|
|
56
|
+
*.sqlite
|
|
57
|
+
*.sqlite3
|
|
58
|
+
|
|
59
|
+
# Editors
|
|
60
|
+
*~
|
|
61
|
+
.#*
|
|
62
|
+
|
|
63
|
+
# Coverage
|
|
64
|
+
.coverage
|
|
65
|
+
htmlcov/
|
|
66
|
+
coverage.xml
|
|
67
|
+
*.cover
|
|
68
|
+
|
|
69
|
+
# Claude Code project state (if any project-local)
|
|
70
|
+
.claude/
|
|
71
|
+
|
|
72
|
+
# Misc
|
|
73
|
+
*.bak
|
|
74
|
+
*.tmp
|
|
75
|
+
|
|
76
|
+
# brainstorming companion working dir
|
|
77
|
+
.superpowers/
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.0 — 2026-05-30
|
|
4
|
+
|
|
5
|
+
- Lower the supported Python floor from **3.12 to 3.8**. Nothing in the tool
|
|
6
|
+
actually required 3.12 — the gate was conservative. `pip install
|
|
7
|
+
substrate-setup` now works on Anaconda's default 3.9 and other older
|
|
8
|
+
interpreters, no `uv`/`pipx` workaround needed.
|
|
9
|
+
- `enum.StrEnum` (3.11+) imports natively on 3.11+ with a minimal
|
|
10
|
+
`(str, Enum)` backport on older interpreters.
|
|
11
|
+
- The `tomllib` → `tomli` fallback is now `sys.version_info`-gated, and
|
|
12
|
+
`tomli` is a declared dependency (`python_version < '3.11'`) — previously
|
|
13
|
+
the fallback path had no dependency backing it and would have failed.
|
|
14
|
+
- `tomli-w` lower bound relaxed `1.2 → 1.0` so 3.8 resolves.
|
|
15
|
+
- No CLI or config-schema changes — pure compatibility widening. The
|
|
16
|
+
test/type tooling still requires 3.9+ (`pytest-httpx`/`mypy` dropped 3.8);
|
|
17
|
+
end users on 3.8 are unaffected.
|
|
18
|
+
|
|
19
|
+
## 0.3.1 — 2026-05-24
|
|
20
|
+
|
|
21
|
+
- Persist `SUBSTRATE_API_KEY` automatically during `configure`:
|
|
22
|
+
on Windows, writes `HKCU\Environment\SUBSTRATE_API_KEY` via `winreg`
|
|
23
|
+
+ `WM_SETTINGCHANGE` broadcast — visible to GUI agents (Codex Desktop)
|
|
24
|
+
on next launch without the user editing rc files or restarting their
|
|
25
|
+
session. On macOS / Linux, appends a marker-fenced `export` block (or
|
|
26
|
+
fish-syntax `set -gx` for fish users) to the user's shell rc. Re-runs
|
|
27
|
+
collapse stale blocks idempotently — the rc never grows on repeated
|
|
28
|
+
configures.
|
|
29
|
+
- Codex adapter now prints a one-line Windows Defender exclusion command
|
|
30
|
+
to eliminate SmartScreen prompts on per-action helper binary spawns.
|
|
31
|
+
Informational only — substrate-setup never elevates itself.
|
|
32
|
+
- Adapters surface env-persistence failures with a clear `WARNING:`
|
|
33
|
+
prefix + manual fallback hint so users notice when the convenience
|
|
34
|
+
step fails but the config file itself was written successfully.
|
|
35
|
+
- Codex adapter drops the stale "/v1/responses NOT YET STARTED" warning
|
|
36
|
+
— Phase 2 shipped on 2026-05-24.
|
|
37
|
+
- No config schema changes from 0.3.0. Upgrade cleanly via
|
|
38
|
+
`uv tool install --force substrate-setup` (or pipx).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: substrate-setup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: One-shot local configurator for coding agents against a Substrate gateway
|
|
5
5
|
Project-URL: Homepage, https://github.com/FrankXiaA/substrate-solutions
|
|
6
6
|
Project-URL: Source, https://github.com/FrankXiaA/substrate-solutions/tree/main/substrate-api/substrate_setup
|
|
@@ -14,16 +14,21 @@ Classifier: Intended Audience :: Developers
|
|
|
14
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
22
|
Classifier: Topic :: Software Development :: Code Generators
|
|
19
23
|
Classifier: Topic :: Utilities
|
|
20
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.8
|
|
21
25
|
Requires-Dist: httpx>=0.27
|
|
22
26
|
Requires-Dist: ruamel-yaml>=0.18
|
|
23
|
-
Requires-Dist: tomli-w>=1.
|
|
27
|
+
Requires-Dist: tomli-w>=1.0
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
24
29
|
Provides-Extra: dev
|
|
25
30
|
Requires-Dist: mypy<2,>=1.13; extra == 'dev'
|
|
26
|
-
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-httpx>=0.30; (python_version >= '3.9') and extra == 'dev'
|
|
27
32
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
28
33
|
Requires-Dist: ruff<1,>=0.7; extra == 'dev'
|
|
29
34
|
Description-Content-Type: text/markdown
|
|
@@ -34,10 +39,16 @@ One-shot configurator that points local coding agents at a Substrate gateway.
|
|
|
34
39
|
|
|
35
40
|
## Install
|
|
36
41
|
|
|
37
|
-
`substrate-setup`
|
|
42
|
+
`substrate-setup` runs on **Python 3.8 or newer** — including Anaconda's default 3.9 and the system Python on older Linux/macOS boxes. Plain `pip` works:
|
|
38
43
|
|
|
39
44
|
```bash
|
|
40
|
-
|
|
45
|
+
pip install substrate-setup
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you'd rather keep the tool in its own isolated environment (recommended, so it can't clash with a project's dependencies), use `uv` or `pipx`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Option A — uv (also downloads a Python for the tool if needed)
|
|
41
52
|
uv tool install substrate-setup
|
|
42
53
|
|
|
43
54
|
# Option B — pipx
|
|
@@ -52,19 +63,24 @@ curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
|
|
|
52
63
|
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
53
64
|
```
|
|
54
65
|
|
|
55
|
-
> **Why not `pip install substrate-setup`?** It works only if the `pip` on your PATH is bound to a Python 3.12+ interpreter. Anaconda's default `pip` (Python 3.9) is the common pitfall — PyPI hides every release from it with `Requires-Python >=3.12` and the error message is unhelpful. `uv` and `pipx` both create an isolated 3.12 venv for the tool, so they sidestep the issue entirely.
|
|
56
|
-
|
|
57
66
|
## Use
|
|
58
67
|
|
|
59
68
|
```bash
|
|
60
|
-
export SUBSTRATE_API_KEY="sk-substrate-..." # or be prompted
|
|
61
|
-
|
|
62
69
|
substrate-setup configure # detect installed agents and wire them up
|
|
63
70
|
substrate-setup verify # read-only: confirm everything points at the gateway
|
|
64
71
|
substrate-setup remove # strip the substrate-managed entries
|
|
65
72
|
substrate-setup --help
|
|
66
73
|
```
|
|
67
74
|
|
|
75
|
+
### After running configure
|
|
76
|
+
|
|
77
|
+
`substrate-setup configure` writes the API key for you automatically. On Windows it lands in `HKCU\Environment\SUBSTRATE_API_KEY` (visible to Codex Desktop and other GUI agents on next launch). On macOS / Linux it lands in your shell rc (`~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish` depending on `$SHELL`) inside a marker-fenced block — re-running configure replaces the block in place, no duplicates.
|
|
78
|
+
|
|
79
|
+
You should not need to set `SUBSTRATE_API_KEY` by hand. If auto-persistence fails (the printed message will say `API key WARNING: …`), you can set it manually:
|
|
80
|
+
|
|
81
|
+
- **Windows:** `[Environment]::SetEnvironmentVariable("SUBSTRATE_API_KEY", "<your-key>", "User")` then re-launch the agent.
|
|
82
|
+
- **macOS / Linux:** add `export SUBSTRATE_API_KEY=<your-key>` to your shell rc and `source` it.
|
|
83
|
+
|
|
68
84
|
Supported agents: `hermes`, `cursor`, `aider`, `continue`, `claude-code`, `codex`.
|
|
69
85
|
|
|
70
86
|
Subset with `--agents-only hermes,aider`. Preview without writing: `--dry-run`. Override the gateway base URL: `--base-url https://your-gateway.example.com`.
|
|
@@ -77,5 +93,33 @@ Subset with `--agents-only hermes,aider`. Preview without writing: `--dry-run`.
|
|
|
77
93
|
| `cursor` | Walkthrough printed after configure — copy the base URL, key, and model ids into Cursor's Settings → Models. |
|
|
78
94
|
| `aider` | `~/.aider.model.metadata.json` written with one entry per chat-capable Substrate model. Use `--model openai/<id>` to switch. |
|
|
79
95
|
| `continue` | All chat-capable Substrate models written as separate `models:` entries in `~/.continue/config.yaml`. |
|
|
80
|
-
| `claude-code` | `~/.claude/settings.json` env block (`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`). The `/model` picker stays opus/sonnet/haiku — use `claude --model openai/<id>` for any other Substrate model.
|
|
81
|
-
| `codex` | `~/.codex/config.toml` `[model_providers.substrate]` block with `wire_api = "responses"`.
|
|
96
|
+
| `claude-code` | `~/.claude/settings.json` env block (`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`). The `/model` picker stays opus/sonnet/haiku — use `claude --model openai/<id>` for any other Substrate model. Requires Substrate's `/v1/messages` endpoint — shipped in gateway Phase 1. |
|
|
97
|
+
| `codex` | `~/.codex/config.toml` `[model_providers.substrate]` block with `wire_api = "responses"`. API key is auto-persisted (see above). Requires Substrate's `/v1/responses` endpoint — shipped in gateway Phase 2. |
|
|
98
|
+
|
|
99
|
+
### Heads-up: tool calling on Gemini 3.1 Pro Preview
|
|
100
|
+
|
|
101
|
+
If your CLI agent (Hermes, Aider, etc.) uses tool calling against
|
|
102
|
+
`google/gemini-3.1-pro-preview`, expect occasional misses (~20-30% of
|
|
103
|
+
attempts). All other Substrate models hit ≥95% reliability for tool calls.
|
|
104
|
+
|
|
105
|
+
## Troubleshooting
|
|
106
|
+
|
|
107
|
+
### Windows: Defender SmartScreen prompts on every Codex click
|
|
108
|
+
|
|
109
|
+
Codex Desktop spawns helper binaries (`codex-command-runner.exe`,
|
|
110
|
+
`node_repl.exe`) per UI action. With `sandbox = "elevated"` in
|
|
111
|
+
`~/.codex/config.toml`, each spawn triggers Windows Defender
|
|
112
|
+
SmartScreen, prompting you on every click until the Codex install
|
|
113
|
+
directory is whitelisted.
|
|
114
|
+
|
|
115
|
+
One-time fix — open an **Administrator** PowerShell window and run:
|
|
116
|
+
|
|
117
|
+
```powershell
|
|
118
|
+
Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\OpenAI\Codex"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
This excludes Codex's binaries from real-time scanning. Reverse with
|
|
122
|
+
`Remove-MpPreference -ExclusionPath "$env:LOCALAPPDATA\OpenAI\Codex"`.
|
|
123
|
+
|
|
124
|
+
`substrate-setup configure --agents-only codex` also prints this
|
|
125
|
+
command at the end of its walkthrough on Windows.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# substrate-setup
|
|
2
|
+
|
|
3
|
+
One-shot configurator that points local coding agents at a Substrate gateway.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
`substrate-setup` runs on **Python 3.8 or newer** — including Anaconda's default 3.9 and the system Python on older Linux/macOS boxes. Plain `pip` works:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install substrate-setup
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If you'd rather keep the tool in its own isolated environment (recommended, so it can't clash with a project's dependencies), use `uv` or `pipx`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Option A — uv (also downloads a Python for the tool if needed)
|
|
17
|
+
uv tool install substrate-setup
|
|
18
|
+
|
|
19
|
+
# Option B — pipx
|
|
20
|
+
pipx install substrate-setup
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Don't have `uv`? Install it once with:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
|
|
27
|
+
# or on Windows:
|
|
28
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Use
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
substrate-setup configure # detect installed agents and wire them up
|
|
35
|
+
substrate-setup verify # read-only: confirm everything points at the gateway
|
|
36
|
+
substrate-setup remove # strip the substrate-managed entries
|
|
37
|
+
substrate-setup --help
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### After running configure
|
|
41
|
+
|
|
42
|
+
`substrate-setup configure` writes the API key for you automatically. On Windows it lands in `HKCU\Environment\SUBSTRATE_API_KEY` (visible to Codex Desktop and other GUI agents on next launch). On macOS / Linux it lands in your shell rc (`~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish` depending on `$SHELL`) inside a marker-fenced block — re-running configure replaces the block in place, no duplicates.
|
|
43
|
+
|
|
44
|
+
You should not need to set `SUBSTRATE_API_KEY` by hand. If auto-persistence fails (the printed message will say `API key WARNING: …`), you can set it manually:
|
|
45
|
+
|
|
46
|
+
- **Windows:** `[Environment]::SetEnvironmentVariable("SUBSTRATE_API_KEY", "<your-key>", "User")` then re-launch the agent.
|
|
47
|
+
- **macOS / Linux:** add `export SUBSTRATE_API_KEY=<your-key>` to your shell rc and `source` it.
|
|
48
|
+
|
|
49
|
+
Supported agents: `hermes`, `cursor`, `aider`, `continue`, `claude-code`, `codex`.
|
|
50
|
+
|
|
51
|
+
Subset with `--agents-only hermes,aider`. Preview without writing: `--dry-run`. Override the gateway base URL: `--base-url https://your-gateway.example.com`.
|
|
52
|
+
|
|
53
|
+
### Per-agent catalog UX (0.3.0+)
|
|
54
|
+
|
|
55
|
+
| Agent | How it learns about Substrate's models |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `hermes` | Live URL fetch via `model_catalog.providers.substrate.url`. Picker shows all chat-capable Substrate models, refreshed on Hermes' 24h TTL. |
|
|
58
|
+
| `cursor` | Walkthrough printed after configure — copy the base URL, key, and model ids into Cursor's Settings → Models. |
|
|
59
|
+
| `aider` | `~/.aider.model.metadata.json` written with one entry per chat-capable Substrate model. Use `--model openai/<id>` to switch. |
|
|
60
|
+
| `continue` | All chat-capable Substrate models written as separate `models:` entries in `~/.continue/config.yaml`. |
|
|
61
|
+
| `claude-code` | `~/.claude/settings.json` env block (`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`). The `/model` picker stays opus/sonnet/haiku — use `claude --model openai/<id>` for any other Substrate model. Requires Substrate's `/v1/messages` endpoint — shipped in gateway Phase 1. |
|
|
62
|
+
| `codex` | `~/.codex/config.toml` `[model_providers.substrate]` block with `wire_api = "responses"`. API key is auto-persisted (see above). Requires Substrate's `/v1/responses` endpoint — shipped in gateway Phase 2. |
|
|
63
|
+
|
|
64
|
+
### Heads-up: tool calling on Gemini 3.1 Pro Preview
|
|
65
|
+
|
|
66
|
+
If your CLI agent (Hermes, Aider, etc.) uses tool calling against
|
|
67
|
+
`google/gemini-3.1-pro-preview`, expect occasional misses (~20-30% of
|
|
68
|
+
attempts). All other Substrate models hit ≥95% reliability for tool calls.
|
|
69
|
+
|
|
70
|
+
## Troubleshooting
|
|
71
|
+
|
|
72
|
+
### Windows: Defender SmartScreen prompts on every Codex click
|
|
73
|
+
|
|
74
|
+
Codex Desktop spawns helper binaries (`codex-command-runner.exe`,
|
|
75
|
+
`node_repl.exe`) per UI action. With `sandbox = "elevated"` in
|
|
76
|
+
`~/.codex/config.toml`, each spawn triggers Windows Defender
|
|
77
|
+
SmartScreen, prompting you on every click until the Codex install
|
|
78
|
+
directory is whitelisted.
|
|
79
|
+
|
|
80
|
+
One-time fix — open an **Administrator** PowerShell window and run:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\OpenAI\Codex"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This excludes Codex's binaries from real-time scanning. Reverse with
|
|
87
|
+
`Remove-MpPreference -ExclusionPath "$env:LOCALAPPDATA\OpenAI\Codex"`.
|
|
88
|
+
|
|
89
|
+
`substrate-setup configure --agents-only codex` also prints this
|
|
90
|
+
command at the end of its walkthrough on Windows.
|
|
@@ -1,63 +1,80 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["hatchling"]
|
|
3
|
-
build-backend = "hatchling.build"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "substrate-setup"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "One-shot local configurator for coding agents against a Substrate gateway"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
11
|
-
authors = [{ name = "Substrate Solutions" }]
|
|
12
|
-
license = { text = "MIT" }
|
|
13
|
-
keywords = ["substrate", "llm", "gateway", "aider", "continue", "hermes", "openai-compatible"]
|
|
14
|
-
classifiers = [
|
|
15
|
-
"Development Status :: 4 - Beta",
|
|
16
|
-
"Environment :: Console",
|
|
17
|
-
"Intended Audience :: Developers",
|
|
18
|
-
"License :: OSI Approved :: MIT License",
|
|
19
|
-
"Operating System :: OS Independent",
|
|
20
|
-
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
-
"Programming Language :: Python :: 3.
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
[project.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
[
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "substrate-setup"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "One-shot local configurator for coding agents against a Substrate gateway"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
authors = [{ name = "Substrate Solutions" }]
|
|
12
|
+
license = { text = "MIT" }
|
|
13
|
+
keywords = ["substrate", "llm", "gateway", "aider", "continue", "hermes", "openai-compatible"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Code Generators",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"httpx>=0.27",
|
|
31
|
+
"ruamel.yaml>=0.18",
|
|
32
|
+
"tomli-w>=1.0",
|
|
33
|
+
# Reading TOML (codex config, credentials probe) uses the stdlib
|
|
34
|
+
# ``tomllib`` on 3.11+; older interpreters fall back to the ``tomli``
|
|
35
|
+
# backport. See ``credentials.py`` / ``agents/codex.py`` import guards.
|
|
36
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/FrankXiaA/substrate-solutions"
|
|
41
|
+
Source = "https://github.com/FrankXiaA/substrate-solutions/tree/main/substrate-api/substrate_setup"
|
|
42
|
+
Issues = "https://github.com/FrankXiaA/substrate-solutions/issues"
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
# Runtime floor is Python 3.8, but the test/type tooling needs 3.9+
|
|
46
|
+
# (pytest-httpx>=0.30 and modern mypy both dropped 3.8). Developing/testing
|
|
47
|
+
# the package therefore requires 3.9+; end users on 3.8 are unaffected.
|
|
48
|
+
dev = [
|
|
49
|
+
"pytest>=8.0",
|
|
50
|
+
"pytest-httpx>=0.30; python_version >= '3.9'",
|
|
51
|
+
"ruff>=0.7,<1",
|
|
52
|
+
"mypy>=1.13,<2",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.scripts]
|
|
56
|
+
substrate-setup = "substrate_setup.cli:main"
|
|
57
|
+
|
|
58
|
+
[tool.hatch.build.targets.wheel]
|
|
59
|
+
packages = ["substrate_setup"]
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
target-version = "py38"
|
|
66
|
+
|
|
67
|
+
[tool.mypy]
|
|
68
|
+
# Lowest version mypy itself supports as an analysis target; the package's
|
|
69
|
+
# runtime floor is 3.8 (see requires-python). 3.8-only breakage is caught by
|
|
70
|
+
# the test suite + import smoke, not the type checker.
|
|
71
|
+
python_version = "3.9"
|
|
72
|
+
strict = true
|
|
73
|
+
ignore_missing_imports = true
|
|
74
|
+
packages = ["substrate_setup"]
|
|
75
|
+
|
|
76
|
+
[[tool.mypy.overrides]]
|
|
77
|
+
module = "tests.*"
|
|
78
|
+
disallow_untyped_defs = false
|
|
79
|
+
disallow_incomplete_defs = false
|
|
80
|
+
check_untyped_defs = false
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# CI lint: substrate_setup/ MUST NOT import anything from app/.
|
|
3
|
-
# The two packages share a source tree, not a dependency graph.
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
PKG_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
6
|
-
if grep -RIn --include='*.py' '^from app\b\|^import app\b' "$PKG_DIR/substrate_setup"; then
|
|
7
|
-
echo "ERROR: substrate_setup/ must not import from app/. See package boundary rule in spec."
|
|
8
|
-
exit 1
|
|
9
|
-
fi
|
|
10
|
-
echo "OK: no app/ imports in substrate_setup/"
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# CI lint: substrate_setup/ MUST NOT import anything from app/.
|
|
3
|
+
# The two packages share a source tree, not a dependency graph.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
PKG_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
6
|
+
if grep -RIn --include='*.py' '^from app\b\|^import app\b' "$PKG_DIR/substrate_setup"; then
|
|
7
|
+
echo "ERROR: substrate_setup/ must not import from app/. See package boundary rule in spec."
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
echo "OK: no app/ imports in substrate_setup/"
|