sia-foundry 0.1.4__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.
- sia_foundry-0.1.4/LICENSE +21 -0
- sia_foundry-0.1.4/MANIFEST.in +6 -0
- sia_foundry-0.1.4/PKG-INFO +373 -0
- sia_foundry-0.1.4/README.md +342 -0
- sia_foundry-0.1.4/_build_backend.py +92 -0
- sia_foundry-0.1.4/pyproject.toml +72 -0
- sia_foundry-0.1.4/setup.cfg +4 -0
- sia_foundry-0.1.4/sia_cli/__init__.py +1 -0
- sia_foundry-0.1.4/sia_cli/__main__.py +401 -0
- sia_foundry-0.1.4/sia_cli/browser_auth.py +180 -0
- sia_foundry-0.1.4/sia_cli/channel.py +444 -0
- sia_foundry-0.1.4/sia_cli/client.py +215 -0
- sia_foundry-0.1.4/sia_cli/commands/__init__.py +0 -0
- sia_foundry-0.1.4/sia_cli/commands/env.py +158 -0
- sia_foundry-0.1.4/sia_cli/commands/eval_run.py +191 -0
- sia_foundry-0.1.4/sia_cli/commands/evals.py +223 -0
- sia_foundry-0.1.4/sia_cli/commands/failures.py +94 -0
- sia_foundry-0.1.4/sia_cli/commands/fix.py +446 -0
- sia_foundry-0.1.4/sia_cli/commands/improve.py +214 -0
- sia_foundry-0.1.4/sia_cli/commands/init.py +265 -0
- sia_foundry-0.1.4/sia_cli/commands/permissions.py +127 -0
- sia_foundry-0.1.4/sia_cli/commands/status.py +160 -0
- sia_foundry-0.1.4/sia_cli/commands/traces.py +123 -0
- sia_foundry-0.1.4/sia_cli/config.py +255 -0
- sia_foundry-0.1.4/sia_cli/context.py +154 -0
- sia_foundry-0.1.4/sia_cli/dotenv.py +91 -0
- sia_foundry-0.1.4/sia_cli/errors.py +10 -0
- sia_foundry-0.1.4/sia_cli/eval_exec.py +429 -0
- sia_foundry-0.1.4/sia_cli/eval_preview.py +101 -0
- sia_foundry-0.1.4/sia_cli/harbor.py +244 -0
- sia_foundry-0.1.4/sia_cli/otlp_receiver.py +138 -0
- sia_foundry-0.1.4/sia_cli/patches.py +165 -0
- sia_foundry-0.1.4/sia_cli/planner.py +179 -0
- sia_foundry-0.1.4/sia_cli/pyenv.py +86 -0
- sia_foundry-0.1.4/sia_cli/render.py +37 -0
- sia_foundry-0.1.4/sia_cli/repl.py +105 -0
- sia_foundry-0.1.4/sia_cli/settings.py +355 -0
- sia_foundry-0.1.4/sia_cli/source.py +197 -0
- sia_foundry-0.1.4/sia_cli/tools.py +307 -0
- sia_foundry-0.1.4/sia_cli/traces.py +186 -0
- sia_foundry-0.1.4/sia_cli/ui/__init__.py +36 -0
- sia_foundry-0.1.4/sia_cli/ui/activity.py +218 -0
- sia_foundry-0.1.4/sia_cli/ui/core.py +183 -0
- sia_foundry-0.1.4/sia_cli/ui/live.py +217 -0
- sia_foundry-0.1.4/sia_cli/ui/logfile.py +111 -0
- sia_foundry-0.1.4/sia_cli/ui/mode.py +80 -0
- sia_foundry-0.1.4/sia_cli/ui/prompt.py +141 -0
- sia_foundry-0.1.4/sia_cli/ui/theme.py +131 -0
- sia_foundry-0.1.4/sia_cli/ui/widgets.py +75 -0
- sia_foundry-0.1.4/sia_cli/versioning.py +100 -0
- sia_foundry-0.1.4/sia_cli/workspace.py +766 -0
- sia_foundry-0.1.4/sia_engine_shared/__init__.py +23 -0
- sia_foundry-0.1.4/sia_engine_shared/backoff.py +27 -0
- sia_foundry-0.1.4/sia_engine_shared/channel.py +101 -0
- sia_foundry-0.1.4/sia_engine_shared/coding_agent.py +65 -0
- sia_foundry-0.1.4/sia_engine_shared/hashing.py +21 -0
- sia_foundry-0.1.4/sia_engine_shared/parse.py +84 -0
- sia_foundry-0.1.4/sia_engine_shared/patches.py +206 -0
- sia_foundry-0.1.4/sia_engine_shared/paths.py +19 -0
- sia_foundry-0.1.4/sia_engine_shared/policy.py +1239 -0
- sia_foundry-0.1.4/sia_engine_shared/traces.py +124 -0
- sia_foundry-0.1.4/sia_engine_shared/types.py +177 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/PKG-INFO +373 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/SOURCES.txt +98 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/dependency_links.txt +1 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/entry_points.txt +2 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/requires.txt +9 -0
- sia_foundry-0.1.4/sia_foundry.egg-info/top_level.txt +2 -0
- sia_foundry-0.1.4/tests/test_await_job.py +175 -0
- sia_foundry-0.1.4/tests/test_browser_auth.py +135 -0
- sia_foundry-0.1.4/tests/test_channel_attach.py +164 -0
- sia_foundry-0.1.4/tests/test_channel_environment.py +289 -0
- sia_foundry-0.1.4/tests/test_channel_steps.py +200 -0
- sia_foundry-0.1.4/tests/test_cli_surface.py +129 -0
- sia_foundry-0.1.4/tests/test_dotenv.py +179 -0
- sia_foundry-0.1.4/tests/test_e2e.py +572 -0
- sia_foundry-0.1.4/tests/test_eval_exec.py +200 -0
- sia_foundry-0.1.4/tests/test_eval_preview.py +37 -0
- sia_foundry-0.1.4/tests/test_eval_run.py +77 -0
- sia_foundry-0.1.4/tests/test_fix_repair.py +223 -0
- sia_foundry-0.1.4/tests/test_fix_staleness.py +77 -0
- sia_foundry-0.1.4/tests/test_harbor.py +185 -0
- sia_foundry-0.1.4/tests/test_improve_advance.py +58 -0
- sia_foundry-0.1.4/tests/test_improve_e2e.py +345 -0
- sia_foundry-0.1.4/tests/test_live.py +305 -0
- sia_foundry-0.1.4/tests/test_patches.py +242 -0
- sia_foundry-0.1.4/tests/test_permissions_cmd.py +204 -0
- sia_foundry-0.1.4/tests/test_phase.py +189 -0
- sia_foundry-0.1.4/tests/test_prompt_collapse.py +213 -0
- sia_foundry-0.1.4/tests/test_provenance.py +92 -0
- sia_foundry-0.1.4/tests/test_pyenv.py +45 -0
- sia_foundry-0.1.4/tests/test_settings.py +377 -0
- sia_foundry-0.1.4/tests/test_source.py +152 -0
- sia_foundry-0.1.4/tests/test_tool_channel.py +551 -0
- sia_foundry-0.1.4/tests/test_traces.py +151 -0
- sia_foundry-0.1.4/tests/test_ui.py +350 -0
- sia_foundry-0.1.4/tests/test_ui_logs.py +133 -0
- sia_foundry-0.1.4/tests/test_versioning.py +118 -0
- sia_foundry-0.1.4/tests/test_versioning_e2e.py +121 -0
- sia_foundry-0.1.4/tests/test_workspace.py +850 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hexo AI
|
|
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,6 @@
|
|
|
1
|
+
# The build backend has to be inside the sdist, or building a wheel from the
|
|
2
|
+
# published sdist fails with `No module named '_build_backend'` — pip unpacks
|
|
3
|
+
# the sdist and calls the backend named in pyproject.toml, which by then is
|
|
4
|
+
# the only copy there is. Nothing else pulls a root-level module into an
|
|
5
|
+
# sdist, so it is named here.
|
|
6
|
+
include _build_backend.py
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sia-foundry
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: SIA Foundry CLI — improve a locally checked-out agent
|
|
5
|
+
Author-email: Hexo AI <team@19bits.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://sia.hexo.ai
|
|
8
|
+
Project-URL: Documentation, https://sia.hexo.ai
|
|
9
|
+
Keywords: sia,foundry,agents,evals,llm,cli
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
18
|
+
Classifier: Topic :: Software Development :: Testing
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: httpx>=0.27
|
|
23
|
+
Requires-Dist: rich>=13.0
|
|
24
|
+
Requires-Dist: PyYAML>=6.0
|
|
25
|
+
Requires-Dist: websockets>=13.0
|
|
26
|
+
Requires-Dist: harbor>=0.22
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# `sia` — the SIA Foundry CLI
|
|
33
|
+
|
|
34
|
+
Improve an AI agent you already have checked out. Point `sia` at your repo and
|
|
35
|
+
it generates an eval set from your code, runs your real agent against it,
|
|
36
|
+
collects traces, diagnoses what is going wrong, and writes patches you review
|
|
37
|
+
before they touch your working tree.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
sia improve --max-cost 5.00
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install sia-foundry # or: uv tool install sia-foundry, pipx install sia-foundry
|
|
47
|
+
sia --version
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
One package, and there is no second one to name. The policy that decides what
|
|
51
|
+
a server-sent tool call may do to your repo is a single piece of code shared
|
|
52
|
+
by both ends of the channel, not two copies that drift, and it ships inside
|
|
53
|
+
this wheel as `sia_engine_shared`. The backend installs those same files from
|
|
54
|
+
the repo rather than from here, so it never has to pull the CLI in to get
|
|
55
|
+
them. The proprietary `sia-engine` package (prompt engineering,
|
|
56
|
+
orchestration) is a separate, backend-only distribution — never installed
|
|
57
|
+
here.
|
|
58
|
+
|
|
59
|
+
It also pulls in [Harbor](https://pypi.org/project/harbor/), the sandbox
|
|
60
|
+
runner that `sia envs generate` and `sia evals run` shell out to. That is the
|
|
61
|
+
bulk of the install; it needs a Docker daemon at runtime, and the rest of the
|
|
62
|
+
CLI degrades gracefully without one.
|
|
63
|
+
|
|
64
|
+
Sign in through your browser — no password in the terminal:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
sia login # opens your browser, finishes on its own
|
|
68
|
+
sia login --device # prints a code, for SSH and containers
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Each login is named after the machine it came from and can be revoked from
|
|
72
|
+
**Devices** in the web app.
|
|
73
|
+
|
|
74
|
+
Requires Python 3.12+. Dependencies: `httpx`, `rich`, `PyYAML`, `websockets`,
|
|
75
|
+
`harbor`.
|
|
76
|
+
|
|
77
|
+
## Getting started
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd ~/code/my-agent
|
|
81
|
+
sia login --foundry https://sia.hexo.ai
|
|
82
|
+
sia init
|
|
83
|
+
sia status
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`sia init` registers the project, detects how to run your agent, writes
|
|
87
|
+
`.sia/config.toml`, and gitignores the derived artifacts.
|
|
88
|
+
|
|
89
|
+
Then run the loop:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
sia evals generate # read the source, synthesize an eval set
|
|
93
|
+
sia evals run # execute your agent, collect traces
|
|
94
|
+
sia failures detect # cluster what went wrong
|
|
95
|
+
sia fixes propose # write unified diffs
|
|
96
|
+
sia fixes apply p1 # review the diff, then land it
|
|
97
|
+
sia evals run # confirm the fix
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`sia` with no arguments opens an interactive shell (`/status`, `/evals`,
|
|
101
|
+
`/help`).
|
|
102
|
+
|
|
103
|
+
## How your agent gets invoked
|
|
104
|
+
|
|
105
|
+
`sia evals run` executes on **your** machine — it needs your databases,
|
|
106
|
+
credentials and local services. Tell it how in `.sia/config.toml`:
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[agent]
|
|
110
|
+
kind = "command" # command | http | python
|
|
111
|
+
cmd = "python3 -m myagent"
|
|
112
|
+
timeout_s = 120
|
|
113
|
+
concurrency = 4
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- **`command`** — a subprocess. Receives `{"input": "...", "case_id": "..."}`
|
|
117
|
+
as JSON on stdin; write `{"output": "..."}` to stdout. Bare text on stdout
|
|
118
|
+
works too, so a script that just prints its answer needs no wrapper.
|
|
119
|
+
`SIA_CASE_ID` is in the environment.
|
|
120
|
+
- **`http`** — `url = "http://localhost:8080/chat"`. Receives a POST with
|
|
121
|
+
`{"input", "case_id"}`; accepts `{"output": ...}` or an OpenAI
|
|
122
|
+
chat-completions body.
|
|
123
|
+
- **`python`** — `entrypoint = "myagent.main:run"`. Imported from the repo
|
|
124
|
+
root and called with the input string. Sync or async.
|
|
125
|
+
|
|
126
|
+
A case that crashes or times out is recorded as a failed case, not raised —
|
|
127
|
+
a broken agent is usually the thing you are investigating.
|
|
128
|
+
|
|
129
|
+
## Where the three inputs come from
|
|
130
|
+
|
|
131
|
+
Every SIA endpoint takes some combination of **source code**, an **eval set**
|
|
132
|
+
and **traces**.
|
|
133
|
+
|
|
134
|
+
**Source code** is your working tree. In a git repo `sia` uses `git ls-files`,
|
|
135
|
+
so `.gitignore` is honored exactly; add a `.siaignore` for anything else you
|
|
136
|
+
want held back. Tune `[source] include/exclude/max_files/max_bytes` in the
|
|
137
|
+
config. Only the selected files are uploaded; every path in the repo is sent as
|
|
138
|
+
a manifest so SIA knows what exists.
|
|
139
|
+
|
|
140
|
+
**The eval set** is a file in your repo: `.sia/evals/default.yaml`. Generate it
|
|
141
|
+
with `sia evals generate`, edit it by hand, review it in pull requests. It is
|
|
142
|
+
tracked in git on purpose — it is a test asset.
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
version: 1
|
|
146
|
+
name: default
|
|
147
|
+
cases:
|
|
148
|
+
- id: c1
|
|
149
|
+
input: where is order 5?
|
|
150
|
+
expected_behavior: asks for a customer id before searching
|
|
151
|
+
category: tool-use
|
|
152
|
+
tags: [orders]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Traces** arrive three ways:
|
|
156
|
+
|
|
157
|
+
1. `sia evals run` emits them itself. Zero setup.
|
|
158
|
+
2. `sia traces collect` runs a local OTLP receiver. Point an
|
|
159
|
+
already-instrumented agent at it:
|
|
160
|
+
```bash
|
|
161
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
162
|
+
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
|
|
163
|
+
```
|
|
164
|
+
(JSON encoding only — that is what keeps protobuf out of the install.)
|
|
165
|
+
3. `sia traces pull` fetches what the SIA inference gateway captured. Set
|
|
166
|
+
`[traces] gateway_url` and point your agent's LLM client at it; every call
|
|
167
|
+
is then traced with no instrumentation at all.
|
|
168
|
+
|
|
169
|
+
The `sia traces` group is unlisted — it works, but it is not in `sia --help`
|
|
170
|
+
or the command reference, because ways 1 and 3 need no command at all.
|
|
171
|
+
|
|
172
|
+
Spans are normalized to the OpenTelemetry GenAI conventions (`gen_ai.*`), so
|
|
173
|
+
OpenInference and OTel SDK output map in untranslated.
|
|
174
|
+
|
|
175
|
+
## Where things run
|
|
176
|
+
|
|
177
|
+
Reasoning is centralized on the Foundry API; execution stays where your agent
|
|
178
|
+
lives.
|
|
179
|
+
|
|
180
|
+
| Endpoint | Runs | Command |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| `generate_evals` | server | `sia evals generate` |
|
|
183
|
+
| `generate_evals_from_traces` | server | `sia evals generate --from-traces` |
|
|
184
|
+
| `generate_environment` | server | `sia envs generate` |
|
|
185
|
+
| `generate_environment_from_traces` | server | `sia envs generate --from-traces` |
|
|
186
|
+
| `run_eval` | **local** | `sia evals run` |
|
|
187
|
+
| `detect_failures` | server | `sia failures detect` |
|
|
188
|
+
| `propose_fix` | server | `sia fixes propose` |
|
|
189
|
+
| `apply_fix` | **local** | `sia fixes apply` |
|
|
190
|
+
|
|
191
|
+
Server-side calls upload the filtered source bundle, the eval set and the
|
|
192
|
+
traces. Judging also happens server-side, so the CLI never needs model
|
|
193
|
+
credentials.
|
|
194
|
+
|
|
195
|
+
## Letting SIA into the repo
|
|
196
|
+
|
|
197
|
+
Your working tree reaches Foundry over a **tool channel**: a WebSocket carrying
|
|
198
|
+
one tool call at a time. While it is open, SIA can read your files, edit them,
|
|
199
|
+
and run commands here — the same things a coding agent does locally, except the
|
|
200
|
+
model runs on the server and your code never leaves the machine.
|
|
201
|
+
|
|
202
|
+
The running step says which side it is blocked on, and for how long — the model
|
|
203
|
+
thinking on the server, or a tool call on this machine:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
⠙ job 22 server 3.0s waiting on model · 3.0s
|
|
207
|
+
⠼ job 22 server 5.9s running Bash cd . && python3 -c "import sys…
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Both clocks matter: the step's, and this wait's. The same transitions are
|
|
211
|
+
timestamped into `.sia/logs/<invocation>.log`, so a run that felt slow can be
|
|
212
|
+
read back afterwards and blamed on the right side.
|
|
213
|
+
|
|
214
|
+
**The commands that need it open it themselves.** `sia improve`,
|
|
215
|
+
`sia envs generate`, `sia evals generate`, `sia failures detect` and
|
|
216
|
+
`sia fixes propose` all attach when they start and detach when they finish, so
|
|
217
|
+
there is no daemon to remember:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
sia improve --max-cost 5.00
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
lending my-agent for this command
|
|
225
|
+
✓ Improve run #7 started
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
This is what makes `sia envs generate` able to *prove* a container works rather
|
|
229
|
+
than guess: the coding agent runs `harbor run -n 1 --env docker` against your
|
|
230
|
+
Docker, with your dependencies.
|
|
231
|
+
|
|
232
|
+
While one command holds the channel, another started alongside it uses that
|
|
233
|
+
session as-is rather than opening a second. The server keeps a single session
|
|
234
|
+
per project, so nothing connects behind its back and evicts it.
|
|
235
|
+
|
|
236
|
+
Every tool call is checked on **your** side before it runs:
|
|
237
|
+
|
|
238
|
+
| Tool | Policy |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `Read`, `Glob` | always allowed, confined to the repo |
|
|
241
|
+
| `Write`, `Edit` | repo only — `..`, `~`, absolute paths and symlinks out are refused |
|
|
242
|
+
| `Bash` | allowlisted (`harbor`, `docker`, `python`, `pytest`, `pip`, read-only `git`, …); anything else asks you first, showing the command |
|
|
243
|
+
|
|
244
|
+
A refusal goes back to the model as a tool error, so it adapts instead of
|
|
245
|
+
failing the run. Nothing about this is configurable from the server. Only
|
|
246
|
+
non-allowlisted `Bash` ever prompts; when a command owns the channel itself, the
|
|
247
|
+
streaming job log pauses for the question rather than scrolling it away.
|
|
248
|
+
|
|
249
|
+
The question shows the command in full, then collapses to a single line once
|
|
250
|
+
you answer — `✓ allowed Bash: rm -rf traces (5 lines)` — so a multi-line script
|
|
251
|
+
does not stay in your scrollback. Both the question and the answer are written
|
|
252
|
+
to `.sia/logs/<invocation>.log` in full.
|
|
253
|
+
|
|
254
|
+
The built-in list is `harbor`, `docker`, `python`, `pytest`, `pip`, read-only
|
|
255
|
+
`git`, `ls`, `cat`, `head`, `tail`, `wc`, `jq`, `grep`, `rg`, `find`, `sort`,
|
|
256
|
+
`uniq`. Pipelines of those are fine — every stage is checked, so `cat x | sh`
|
|
257
|
+
asks about `sh`, not about the pipe.
|
|
258
|
+
|
|
259
|
+
Being prompted repeatedly means the list is missing something this repo needs.
|
|
260
|
+
Name it, rather than turning the gate off:
|
|
261
|
+
|
|
262
|
+
```toml
|
|
263
|
+
[engine]
|
|
264
|
+
allow_commands = ["awk", "sqlite3"]
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Names, not patterns. Allowing a command does not allow what it is chained to:
|
|
268
|
+
`awk … && rm -rf ~` still asks, as does anything with `;`, `&&`, backticks,
|
|
269
|
+
`$(…)` or a redirect out of the repo.
|
|
270
|
+
|
|
271
|
+
To skip prompts entirely on a repo you are deliberately handing over, pass `-y`
|
|
272
|
+
for one command (`sia improve -y`, `sia fixes propose -y`) or set
|
|
273
|
+
`[engine] trust = "full"` for the project.
|
|
274
|
+
|
|
275
|
+
## The loop
|
|
276
|
+
|
|
277
|
+
`sia improve` runs detect → fix repeatedly until it stops paying off, instead of
|
|
278
|
+
you driving each step. It lends the repo for as long as it runs:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
sia improve --max-cost 5.00
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
It stops on the first of: no failures left, no fix proposed, the cost/accuracy
|
|
285
|
+
frontier not moving for two rounds, the budget, or the round limit — and says
|
|
286
|
+
which.
|
|
287
|
+
|
|
288
|
+
**The budget is in dollars, not tokens.** The coding turns are the expensive
|
|
289
|
+
part of a round and carry no eval tokens at all, so a token ceiling would bound
|
|
290
|
+
the cheap half and let the dear half run free.
|
|
291
|
+
|
|
292
|
+
Each round is a separate job. If the server restarts mid-round the run is
|
|
293
|
+
**parked**, not resumed — re-running a round that already spent money is worse
|
|
294
|
+
than stopping and asking — and `sia improve resume` picks it up at the round
|
|
295
|
+
boundary. `sia improve cancel` stops it after the current round rather than
|
|
296
|
+
tearing down a half-applied patch.
|
|
297
|
+
|
|
298
|
+
Patches are never applied for you: the loop proposes, and `sia fixes apply` is
|
|
299
|
+
still the gate.
|
|
300
|
+
|
|
301
|
+
## Patch safety
|
|
302
|
+
|
|
303
|
+
`propose_fix` returns unified diffs plus the SHA of every file each diff was
|
|
304
|
+
generated against. `sia fixes apply` refuses if the working tree has moved on
|
|
305
|
+
since — the check, not the diff format, is what makes server-side patch
|
|
306
|
+
generation safe. Override with `--force` if you know better; undo with
|
|
307
|
+
`sia fixes revert <id>`.
|
|
308
|
+
|
|
309
|
+
Patches are applied all-or-nothing: a hunk that fails on the third file leaves
|
|
310
|
+
the first two untouched. A patch that would leave every file byte-identical is
|
|
311
|
+
rejected rather than reported as applied.
|
|
312
|
+
|
|
313
|
+
## Environments (harbor tasks)
|
|
314
|
+
|
|
315
|
+
`sia envs generate` builds containerized tasks under `.sia/env/<name>/` so eval
|
|
316
|
+
cases can run reproducibly: seeded state, pinned dependencies, and a
|
|
317
|
+
`tests/verify.py` that exits non-zero on failure. `sia envs validate --build`
|
|
318
|
+
docker-builds each one.
|
|
319
|
+
|
|
320
|
+
## Command reference
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
sia init [path] [--from URL] [--name N] [--foundry URL] [--gateway URL] [--force]
|
|
324
|
+
sia login [--foundry URL] [--device]
|
|
325
|
+
sia logout [--foundry URL]
|
|
326
|
+
sia status
|
|
327
|
+
|
|
328
|
+
sia evals generate [--from-traces] [-n N] [--name NAME]
|
|
329
|
+
sia evals run [--no-harbor] [--concurrency N]
|
|
330
|
+
sia evals results
|
|
331
|
+
sia evals list | show <case-id>
|
|
332
|
+
|
|
333
|
+
sia envs generate [--from-traces] [-n N]
|
|
334
|
+
sia envs list | validate [--build]
|
|
335
|
+
|
|
336
|
+
sia failures detect | list | show <failure-id>
|
|
337
|
+
|
|
338
|
+
sia fixes propose
|
|
339
|
+
sia fixes apply [patch-id|all] [-y] [--force]
|
|
340
|
+
sia fixes revert <patch-id>
|
|
341
|
+
sia fixes list | show <patch-id>
|
|
342
|
+
|
|
343
|
+
sia # interactive shell
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Workspace layout
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
.sia/
|
|
350
|
+
config.toml # committed
|
|
351
|
+
evals/default.yaml # committed — a review artifact
|
|
352
|
+
env/<task>/ # committed
|
|
353
|
+
state.json # gitignored
|
|
354
|
+
traces/*.jsonl # gitignored
|
|
355
|
+
runs/*.json # gitignored
|
|
356
|
+
failures/*.json # gitignored
|
|
357
|
+
patches/*.json # gitignored
|
|
358
|
+
plans/*.json # gitignored
|
|
359
|
+
~/.sia/credentials.json # API tokens, keyed by Foundry URL, chmod 600
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Override the credentials path with `SIA_CREDENTIALS`, or supply a token
|
|
363
|
+
directly with `SIA_TOKEN`.
|
|
364
|
+
|
|
365
|
+
## Tests
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
cd cli && python -m pytest
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The end-to-end tests boot the real Foundry API in-process and drive the CLI
|
|
372
|
+
through the whole loop against a toy agent, with the model faked and no API
|
|
373
|
+
keys required.
|