sigit-code 0.1.1__tar.gz → 1.0.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.
- sigit_code-1.0.0/.agents/skills/tool-calling/SKILL.md +290 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.github/workflows/ci.yml +4 -1
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.github/workflows/release-homebrew.yml +1 -1
- sigit_code-1.0.0/CHANGELOG.md +70 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/Cargo.lock +17 -16
- {sigit_code-0.1.1 → sigit_code-1.0.0}/Cargo.toml +5 -4
- {sigit_code-0.1.1 → sigit_code-1.0.0}/PKG-INFO +13 -19
- sigit_code-1.0.0/README.md +111 -0
- sigit_code-1.0.0/npm/README.md.tmpl +62 -0
- sigit_code-1.0.0/npm/sigit/README.md +106 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/pypi/README.md +12 -18
- sigit_code-1.0.0/src/chat.rs +1713 -0
- sigit_code-1.0.0/src/main.rs +1691 -0
- sigit_code-1.0.0/src/models.rs +196 -0
- sigit_code-1.0.0/src/setup.rs +750 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/src/tools.rs +472 -76
- sigit_code-0.1.1/.agents/skills/tool-calling/SKILL.md +0 -283
- sigit_code-0.1.1/README.md +0 -55
- sigit_code-0.1.1/npm/README.md.tmpl +0 -22
- sigit_code-0.1.1/npm/sigit/README.md +0 -85
- sigit_code-0.1.1/src/chat.rs +0 -1162
- sigit_code-0.1.1/src/main.rs +0 -527
- sigit_code-0.1.1/src/setup.rs +0 -89
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.agents/AGENTS.md +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.github/workflows/release-github.yml +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.github/workflows/release-npm.yml +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.github/workflows/release-pypi.yml +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.gitignore +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/.nvmrc +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/LICENSE +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/package-main.json.tmpl +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/package.json.tmpl +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/scripts/render-main-package.cjs +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/scripts/render-platform-package.cjs +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/sigit/.gitignore +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/sigit/package.json +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/sigit/src/index.ts +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/npm/sigit/tsconfig.json +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/pypi/pyproject.toml +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/pyproject.toml +0 -0
- {sigit_code-0.1.1 → sigit_code-1.0.0}/rust-toolchain.toml +0 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# Skill: Tool Calling in siGit Code
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
siGit Code supports **agentic tool calling** — the LLM invokes tools (read/write files, run commands, read websites) to operate on the user's codebase. This works in both **interactive TUI mode** and **ACP server mode** (Zed editor).
|
|
6
|
+
|
|
7
|
+
Tool calling spans three layers:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
siGit (agent loop + tool execution)
|
|
11
|
+
→ onde (ChatEngine with tool-aware API)
|
|
12
|
+
→ mistral.rs (model inference + tool call parsing)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Model Requirement
|
|
18
|
+
|
|
19
|
+
**Only Qwen 3 supports tool calling.** Qwen 2.5 does NOT — mistral.rs only has a parser for Qwen 3's `<tool_call>...</tool_call>` XML format.
|
|
20
|
+
|
|
21
|
+
| Model | Constructor | Size | Tool calling | Default |
|
|
22
|
+
|-------|-----------|------|:---:|:---:|
|
|
23
|
+
| Qwen 3 8B (Q4_K_M) | `GgufModelConfig::qwen3_8b()` | ~5 GB | ✅ | ✅ **default** |
|
|
24
|
+
| Qwen 3 4B (Q4_K_M) | `GgufModelConfig::qwen3_4b()` | ~2.7 GB | ✅ | |
|
|
25
|
+
| Qwen 3 1.7B (Q4_K_M) | `GgufModelConfig::qwen3_1_7b()` | ~1.3 GB | ✅ | |
|
|
26
|
+
| Qwen 2.5 Coder 3B | `GgufModelConfig::qwen25_coder_3b()` | ~1.93 GB | ❌ | |
|
|
27
|
+
| Qwen 2.5 Coder 1.5B | `GgufModelConfig::qwen25_coder_1_5b()` | ~941 MB | ❌ | |
|
|
28
|
+
|
|
29
|
+
siGit uses **Qwen 3 8B** by default with `max_tokens: 8192` (set in `main.rs` for both TUI and ACP modes).
|
|
30
|
+
|
|
31
|
+
### Why 8B over 4B
|
|
32
|
+
|
|
33
|
+
4B can't do `edit_file` reliably. It reads a file, then fails to reproduce the exact `old_text` it just saw. This spirals into 7+ retry rounds that burn through `max_tokens` on `<think>` blocks and return nothing. 8B is the smallest model that actually lands edits.
|
|
34
|
+
|
|
35
|
+
### bartowski GGUF naming convention
|
|
36
|
+
|
|
37
|
+
bartowski's repos use the publisher name as a prefix with an underscore:
|
|
38
|
+
|
|
39
|
+
| Constant | Value |
|
|
40
|
+
|----------|-------|
|
|
41
|
+
| `BARTOWSKI_QWEN3_8B_GGUF` | `"bartowski/Qwen_Qwen3-8B-GGUF"` |
|
|
42
|
+
| `QWEN3_8B_GGUF_FILE` | `"Qwen_Qwen3-8B-Q4_K_M.gguf"` |
|
|
43
|
+
| `BARTOWSKI_QWEN3_4B_GGUF` | `"bartowski/Qwen_Qwen3-4B-GGUF"` |
|
|
44
|
+
| `QWEN3_4B_GGUF_FILE` | `"Qwen_Qwen3-4B-Q4_K_M.gguf"` |
|
|
45
|
+
|
|
46
|
+
These constants live in `onde/src/inference/models.rs`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Tools (9 total)
|
|
51
|
+
|
|
52
|
+
Defined in `sigit/src/tools.rs` via `all_tools()`:
|
|
53
|
+
|
|
54
|
+
| # | Tool | Parameters | Behavior |
|
|
55
|
+
|---|------|-----------|----------|
|
|
56
|
+
| 1 | `read_file` | `path` | Reads file contents, truncates at 10,000 chars |
|
|
57
|
+
| 2 | `create_directory` | `path` | Creates directory and all parents |
|
|
58
|
+
| 3 | `list_directory` | `path` | Lists entries with `[DIR]`/`[FILE]` prefix, dirs first |
|
|
59
|
+
| 4 | `search_files` | `pattern`, `path` (optional) | Recursive regex search, max 50 matches |
|
|
60
|
+
| 5 | `read_website` | `url` | Fetches HTTP/HTTPS, strips HTML, returns text |
|
|
61
|
+
| 6 | `create_file` | `path`, `content` | Creates new file (fails if exists) |
|
|
62
|
+
| 7 | `edit_file` | `path`, `old_text`, `new_text` | Find-and-replace (must match exactly once) |
|
|
63
|
+
| 8 | `delete_file` | `path` | Deletes file or empty directory |
|
|
64
|
+
| 9 | `run_command` | `command`, `cwd` (optional) | Shell command with 120s timeout |
|
|
65
|
+
|
|
66
|
+
### Async handling
|
|
67
|
+
|
|
68
|
+
`execute_tool()` is `async`. Most tools run synchronously, except:
|
|
69
|
+
|
|
70
|
+
- **`read_website`** — uses `tokio::task::spawn_blocking` because `reqwest::blocking::Client` panics inside a tokio runtime ("Cannot start a runtime from within a runtime")
|
|
71
|
+
|
|
72
|
+
### Tool gating by model
|
|
73
|
+
|
|
74
|
+
In TUI mode, `run_inference_task()` takes a `tools_enabled: bool` parameter. When the model's `ModelOption.tool_calling` is `false` (Qwen 2.5), an empty tool list is passed so the model doesn't receive tool schemas it can't use.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Architecture
|
|
79
|
+
|
|
80
|
+
### Layer 1: mistral.rs (model-level)
|
|
81
|
+
|
|
82
|
+
- `RequestBuilder::set_tools(Vec<Tool>)` — attach tool definitions
|
|
83
|
+
- `RequestBuilder::set_tool_choice(ToolChoice::Auto)` — let model decide
|
|
84
|
+
- `QwenParser` detects `<tool_call>...</tool_call>` tags in output
|
|
85
|
+
- Grammar-constrained decoding forces valid JSON inside tool calls
|
|
86
|
+
- `<think>...</think>` reasoning is separated from tool calls by the reasoning parser
|
|
87
|
+
- Works identically for GGUF and full-precision models
|
|
88
|
+
|
|
89
|
+
### Layer 2: onde (engine-level)
|
|
90
|
+
|
|
91
|
+
#### Key types (`onde/src/inference/types.rs`)
|
|
92
|
+
|
|
93
|
+
| Type | Purpose |
|
|
94
|
+
|------|---------|
|
|
95
|
+
| `ToolDefinition` | `{ name, description, parameters_schema: String }` |
|
|
96
|
+
| `ToolCallRequest` | `{ id, function_name, arguments: String }` |
|
|
97
|
+
| `ToolResult` | `{ tool_call_id, content: String }` |
|
|
98
|
+
| `ToolAwareResult` | `{ text, tool_calls: Vec<ToolCallRequest>, duration_secs, ... }` |
|
|
99
|
+
|
|
100
|
+
#### Key methods (`onde/src/inference/engine.rs`)
|
|
101
|
+
|
|
102
|
+
| Method | Purpose |
|
|
103
|
+
|--------|---------|
|
|
104
|
+
| `send_message_with_tools(msg, &[ToolDefinition])` | Returns `ToolAwareResult` with possible tool calls |
|
|
105
|
+
| `send_tool_results(Vec<ToolResult>, Option<&[ToolDefinition]>)` | Feed results back; `None` forces text response |
|
|
106
|
+
|
|
107
|
+
#### Internal details
|
|
108
|
+
|
|
109
|
+
- `attach_tools()` converts `ToolDefinition` → mistral.rs `Tool`, sets `ToolChoice::Auto` and `strict: Some(true)`
|
|
110
|
+
- `parse_tool_calls()` extracts tool calls from `choice.message.tool_calls`, generates fallback IDs if empty
|
|
111
|
+
- `replay_history_with_tools()` uses `.enumerate()` for correct sequential `index` values
|
|
112
|
+
- Malformed `parameters_schema` JSON logs a warning instead of silently producing empty params
|
|
113
|
+
- Malformed tool call `arguments` JSON logs a warning for debugging
|
|
114
|
+
|
|
115
|
+
### Layer 3: siGit (agent-level)
|
|
116
|
+
|
|
117
|
+
#### ACP session handling (`src/main.rs`)
|
|
118
|
+
|
|
119
|
+
All session handlers (`load_session`, `fork_session`, `new_session`) do:
|
|
120
|
+
|
|
121
|
+
1. **Store `args.cwd`** in `session_cwd: Mutex<Option<PathBuf>>`
|
|
122
|
+
2. **`std::env::set_current_dir(&args.cwd)`** — so relative paths in tool calls resolve correctly
|
|
123
|
+
3. **`engine.clear_history()`** — siGit doesn't persist sessions
|
|
124
|
+
4. **`engine.push_history(ChatMessage::system(...))`** — injects: *"The user's project working directory is {cwd}. Always use absolute paths..."*
|
|
125
|
+
|
|
126
|
+
Without step 4, the model uses the process `cwd` (often `$HOME`) and creates files in the wrong directory.
|
|
127
|
+
|
|
128
|
+
#### ACP content block handling (`prompt()`)
|
|
129
|
+
|
|
130
|
+
The `prompt()` handler processes all ACP content block types:
|
|
131
|
+
|
|
132
|
+
- **`ContentBlock::Text`** — passed through as-is
|
|
133
|
+
- **`ContentBlock::Resource` (EmbeddedResource)** — `TextResourceContents` inlined as `--- {uri} ---\n{text}\n--- end ---`
|
|
134
|
+
- **`ContentBlock::ResourceLink`** — `file://` URIs are read from disk. **Line range fragments** like `#L207:219` are parsed: the `#` fragment is stripped from the path, and only lines 207–219 are extracted and sent to the model
|
|
135
|
+
|
|
136
|
+
Example: Zed sends `@ index.html (207:219)` as:
|
|
137
|
+
```
|
|
138
|
+
ResourceLink(name="index.html (207:219)", uri="file:///path/to/index.html#L207:219")
|
|
139
|
+
```
|
|
140
|
+
siGit parses this into path `/path/to/index.html` + lines 207–219.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## The Agentic Loop
|
|
145
|
+
|
|
146
|
+
Both ACP mode (`SiGitAgent::prompt()`) and TUI mode (`run_inference_task()`) implement:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
1. engine.send_message_with_tools(user_text, &tools) → ToolAwareResult
|
|
150
|
+
2. while result.tool_calls is non-empty AND round < MAX_TOOL_ROUNDS (10):
|
|
151
|
+
a. For each tool_call:
|
|
152
|
+
- Log: → tool_name(arguments)
|
|
153
|
+
- Execute: tools::execute_tool(name, arguments).await
|
|
154
|
+
- Log: ← N chars
|
|
155
|
+
- Collect ToolResult { tool_call_id, content }
|
|
156
|
+
b. Decide next_tools:
|
|
157
|
+
- round < MAX_TOOL_ROUNDS → Some(&tools) (allow more calls)
|
|
158
|
+
- else → None (force text response)
|
|
159
|
+
c. engine.send_tool_results(results, next_tools) → ToolAwareResult
|
|
160
|
+
3. Send final result.text to user
|
|
161
|
+
- Empty reply after tool rounds → log warning (ACP) or show error (TUI)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## System Prompt
|
|
167
|
+
|
|
168
|
+
The `SYSTEM_PROMPT` in `main.rs` (~122 lines) includes critical instructions:
|
|
169
|
+
|
|
170
|
+
- **Never tell the user to run commands** — use `run_command` tool instead
|
|
171
|
+
- **Can access websites** — use `read_website` tool (overrides RLHF refusal training)
|
|
172
|
+
- **Prefer absolute paths** in all tool arguments
|
|
173
|
+
- **Git operations** — always use `run_command` with absolute cwd
|
|
174
|
+
- **smbCloud domain knowledge** — auth boundaries, deploy flows, project structure
|
|
175
|
+
|
|
176
|
+
The session `cwd` is injected as a separate system message at session creation time (not part of the static prompt).
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Model Cache
|
|
181
|
+
|
|
182
|
+
Models are stored in the shared Onde App Group container on macOS:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
~/Library/Group Containers/group.com.ondeinference.apps/models/hub/
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`setup.rs` sets `HF_HOME` and `HF_HUB_CACHE` to point there at startup, so siGit reuses models downloaded by the Onde desktop app (and vice versa).
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Adding a New Tool
|
|
193
|
+
|
|
194
|
+
1. Add an `AgentTool` entry to `all_tools()` in `src/tools.rs`
|
|
195
|
+
2. Add a match arm to `execute_tool()` — use `spawn_blocking` if the implementation blocks
|
|
196
|
+
3. Write `exec_your_tool(arguments: &str) -> String`
|
|
197
|
+
4. Update `test_all_tools_count` test (currently expects 9)
|
|
198
|
+
|
|
199
|
+
No changes needed in onde or mistral.rs — tool definitions are passed dynamically.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Adding a New Model
|
|
204
|
+
|
|
205
|
+
1. **`onde/src/inference/models.rs`** — add `pub const` for repo ID and GGUF filename, add to `SUPPORTED_MODELS` array and `SUPPORTED_MODEL_INFO`
|
|
206
|
+
2. **`onde/src/inference/engine.rs`** — add `pub fn model_name() -> Self` constructor to `impl GgufModelConfig`
|
|
207
|
+
3. **`sigit/src/chat.rs`** — add `ModelOption` entry to `SIGIT_MODELS` with `tool_calling: true/false`
|
|
208
|
+
4. **`sigit/src/main.rs`** — update `run_interactive()` and `run_acp_server()` if changing the default
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Debugging
|
|
213
|
+
|
|
214
|
+
### Log locations
|
|
215
|
+
|
|
216
|
+
- **TUI mode:** `$TMPDIR/sigit.log` (e.g. `/var/folders/.../sigit.log`)
|
|
217
|
+
- **ACP mode (Zed):** `~/Library/Logs/Zed/Zed.log` — grep for `agent stderr:.*sigit`
|
|
218
|
+
|
|
219
|
+
### Key log patterns
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
# Model loaded successfully
|
|
223
|
+
ChatEngine: model Qwen 3 8B loaded in 6.9s
|
|
224
|
+
|
|
225
|
+
# Session cwd captured
|
|
226
|
+
load_session: id=..., cwd=/path/to/project, additional_directories=[...]
|
|
227
|
+
|
|
228
|
+
# Tool call parsed by mistral.rs
|
|
229
|
+
ChatEngine: tool inference END — 12.3s — tool_calls: 1
|
|
230
|
+
|
|
231
|
+
# Tool executed
|
|
232
|
+
→ read_file({"path":"/absolute/path/to/file.rs"})
|
|
233
|
+
← 6506 chars
|
|
234
|
+
|
|
235
|
+
# Tool result sent back
|
|
236
|
+
ChatEngine: tool results inference START — 1 results
|
|
237
|
+
|
|
238
|
+
# Model returned empty (exhausted max_tokens on thinking)
|
|
239
|
+
model returned empty reply after 7 tool round(s)
|
|
240
|
+
|
|
241
|
+
# ResourceLink received from Zed
|
|
242
|
+
block[1]: ResourceLink(name=index.html (207:219), uri=file:///path/to/index.html#L207:219)
|
|
243
|
+
|
|
244
|
+
# ResourceLink read failed (fragment not stripped — old bug, now fixed)
|
|
245
|
+
could not read ResourceLink file:///path/to/index.html#L207:219: No such file or directory
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Common issues
|
|
249
|
+
|
|
250
|
+
| Symptom | Cause | Fix |
|
|
251
|
+
|---------|-------|-----|
|
|
252
|
+
| Model says "I cannot access websites" | RLHF refusal override not in system prompt | System prompt now has CRITICAL block about `read_website` |
|
|
253
|
+
| `0 tool call(s)` for every prompt | Wrong model loaded (Qwen 2.5) | Check log for `loading GGUF model` — must be Qwen 3 |
|
|
254
|
+
| `edit_file` returns `← 161 chars` repeatedly | `old_text not found` — model can't match exact text | Use Qwen 3 8B (not 4B); consider line-based edit tool |
|
|
255
|
+
| Files created in wrong directory | `cwd` not captured from ACP session | Session handlers must call `set_current_dir` + `push_history` with cwd |
|
|
256
|
+
| `@ file.html (207:219)` context missing | `#L207:219` fragment not stripped from file path | `prompt()` now parses URI fragments and extracts line ranges |
|
|
257
|
+
| `read_website` panics/hangs | `reqwest::blocking` inside tokio runtime | `exec_read_website` wrapped in `spawn_blocking` |
|
|
258
|
+
| Empty reply after many tool rounds | Model exhausted `max_tokens` on `<think>` blocks | Set `max_tokens: 8192`; 8B model wastes fewer tokens on thinking |
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Cargo Dependency Note
|
|
263
|
+
|
|
264
|
+
For local development, `sigit/Cargo.toml` must use the path dependency:
|
|
265
|
+
|
|
266
|
+
```toml
|
|
267
|
+
onde = { path = "../onde" }
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
For CI/release, switch to the git dependency (after pushing Onde changes):
|
|
271
|
+
|
|
272
|
+
```toml
|
|
273
|
+
onde = { git = "https://github.com/ondeinference/onde", branch = "development" }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The `qwen3_8b()` constructor only exists in the local Onde SDK until it's pushed to the `development` branch.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## File Map
|
|
281
|
+
|
|
282
|
+
| File | What it does |
|
|
283
|
+
|------|-------------|
|
|
284
|
+
| `sigit/src/tools.rs` | 9 tool schemas (`all_tools()`), `execute_tool()` dispatch, all `exec_*` implementations |
|
|
285
|
+
| `sigit/src/main.rs` | `SYSTEM_PROMPT`, `SiGitAgent` struct with `session_cwd`, ACP session handlers (cwd + push_history), `prompt()` with content block parsing, model selection (`qwen3_8b`), `MAX_TOOL_ROUNDS` |
|
|
286
|
+
| `sigit/src/chat.rs` | `SIGIT_MODELS` array (4 models), `run_inference_task()` with `tools_enabled` gate, TUI tool loop |
|
|
287
|
+
| `sigit/src/setup.rs` | HF cache setup pointing to shared App Group container |
|
|
288
|
+
| `onde/src/inference/types.rs` | `ToolDefinition`, `ToolCallRequest`, `ToolResult`, `ToolAwareResult` |
|
|
289
|
+
| `onde/src/inference/engine.rs` | `send_message_with_tools()`, `send_tool_results()`, `attach_tools()`, `parse_tool_calls()`, `replay_history_with_tools()`, `GgufModelConfig::qwen3_8b()` |
|
|
290
|
+
| `onde/src/inference/models.rs` | Model constants and `SUPPORTED_MODELS` array |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0 — 2026
|
|
4
|
+
|
|
5
|
+
We've been running siGit in production across smbCloud codebases for a while now. It works. Time to call it 1.0.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
### The short version
|
|
10
|
+
|
|
11
|
+
siGit is a local coding agent. It runs a quantized LLM on your machine, talks to editors over ACP, and can read files, run commands, search the web, and write code — all without sending anything to a cloud API. You install it with cargo, pip, npm, or Homebrew. It just works.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### What's actually in here
|
|
16
|
+
|
|
17
|
+
**The editor integration** is the main thing. Zed and VSCode both pick it up as an ACP agent. Multi-turn sessions, tool calling, session forking, working directory context — all there. This was the original goal and it's solid.
|
|
18
|
+
|
|
19
|
+
**The terminal UI** is a bonus that turned out to be genuinely useful. Full-screen ratatui chat, streaming tokens with a blinking cursor, a thinking spinner while the model reasons, a model picker you can pull up mid-session. It runs on macOS and Linux. Windows gets the editor integration for now — TUI support there is on the list.
|
|
20
|
+
|
|
21
|
+
**Tool calling** is what makes it an agent instead of a chat window. The loop runs up to 10 rounds per message:
|
|
22
|
+
|
|
23
|
+
- `read_file` / `write_file` / `delete_file`
|
|
24
|
+
- `list_directory` / `search_files`
|
|
25
|
+
- `run_command` — shell commands with optional working directory
|
|
26
|
+
- `read_website` — fetches a URL and strips it to readable text
|
|
27
|
+
|
|
28
|
+
The model decides which tools to call, sees the results, and keeps going until it has something worth saying.
|
|
29
|
+
|
|
30
|
+
**Model support** is broader than we expected to ship at 1.0. Qwen 3 1.7B, 4B, 8B, and 14B. Qwen 2.5 1.5B and 3B. Qwen 2.5 Coder 1.5B, 3B, and 7B. DeepSeek Coder 6.7B. All GGUF, all pulled from HuggingFace on first run.
|
|
31
|
+
|
|
32
|
+
Qwen 3 is the interesting one. It uses extended thinking mode — the model reasons inside `<think>…</think>` blocks before answering. The TUI strips those out and renders them dimmed above the reply, so you can see what it was doing without it cluttering the conversation. The 8B is the default on desktop. Mobile defaults to 1.7B because iOS gives apps ~2–3 GB and we found out the hard way that 3B causes OOM on an iPhone 16e.
|
|
33
|
+
|
|
34
|
+
**The model picker** (`/models` in the TUI, or an agent config option in editors) shows what's cached locally, what's available to download, whether a model supports tool calling, and whether its local cache looks healthy. Switching models downloads and loads in the background — the UI stays alive the whole time with a progress bar.
|
|
35
|
+
|
|
36
|
+
**smbCloud context** is baked into the system prompt. siGit knows the difference between platform user flows and tenant app auth flows, how `Project` / `FrontendApp` / `AuthApp` / GresIQ fit together, that Next.js SSR deploys are not the generic git-push path, and what workspace patterns smbCloud repos tend to follow. Outside smbCloud it's a normal coding agent and doesn't push platform-specific advice where it doesn't belong.
|
|
37
|
+
|
|
38
|
+
**Distribution** ended up being more work than the software itself, honestly. Pre-built binaries for macOS (arm64 + x64), Linux (arm64 + x64), and Windows (arm64 + x64). Four install methods: `cargo install sigit`, `pip install sigit-code`, `npm install -g @smbcloud/sigit`, `brew install sigit`. Getting all of that working across CI, crates.io, PyPI, npm, and Homebrew is its own project.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
### What doesn't work yet
|
|
43
|
+
|
|
44
|
+
The Windows TUI. ACP/editor mode works fine on Windows — it's just the interactive terminal UI that's missing. The underlying issue is Unix-specific terminal handling we haven't abstracted yet.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### Changes since 0.1.2
|
|
49
|
+
|
|
50
|
+
- Qwen 3 14B support
|
|
51
|
+
- Qwen 3 `<think>` block parsing — strips and renders thinking content separately in the TUI
|
|
52
|
+
- Moved all TUI code into `#[cfg(unix)]` — this fixed a pile of dead-code errors on Windows CI that were blocking releases
|
|
53
|
+
- Live download progress bar during model switch, with cancellation (Ctrl+C mid-download works)
|
|
54
|
+
- Model download and loading progress shown in the Zed agent config panel
|
|
55
|
+
- Animated spinner during model switching
|
|
56
|
+
- Qwen 2.5 Coder 7B
|
|
57
|
+
- Available-for-download models shown in the picker, not just locally cached ones
|
|
58
|
+
- Model selection persists across restarts
|
|
59
|
+
- Session working directory support
|
|
60
|
+
- Model picker logic moved to a platform-independent module so it compiles on Windows even without the TUI
|
|
61
|
+
- `/models N` shortcut for picking a model by number directly
|
|
62
|
+
- `read_website` tool
|
|
63
|
+
- Better `read_file` handling and empty reply detection
|
|
64
|
+
- Async tool execution
|
|
65
|
+
- Fixed CI cross-compilation for macOS, iOS, Linux, and Windows
|
|
66
|
+
- npm, PyPI, and Homebrew distribution added
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
*© 2026 [smbCloud](https://smbcloud.xyz/) (Splitfire AB).*
|
|
@@ -741,9 +741,9 @@ dependencies = [
|
|
|
741
741
|
|
|
742
742
|
[[package]]
|
|
743
743
|
name = "cc"
|
|
744
|
-
version = "1.2.
|
|
744
|
+
version = "1.2.61"
|
|
745
745
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
746
|
-
checksum = "
|
|
746
|
+
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
|
|
747
747
|
dependencies = [
|
|
748
748
|
"find-msvc-tools",
|
|
749
749
|
"jobserver",
|
|
@@ -1264,9 +1264,9 @@ dependencies = [
|
|
|
1264
1264
|
|
|
1265
1265
|
[[package]]
|
|
1266
1266
|
name = "data-encoding"
|
|
1267
|
-
version = "2.
|
|
1267
|
+
version = "2.11.0"
|
|
1268
1268
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1269
|
-
checksum = "
|
|
1269
|
+
checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
|
|
1270
1270
|
|
|
1271
1271
|
[[package]]
|
|
1272
1272
|
name = "defmac"
|
|
@@ -3264,7 +3264,7 @@ dependencies = [
|
|
|
3264
3264
|
[[package]]
|
|
3265
3265
|
name = "mistralrs"
|
|
3266
3266
|
version = "0.8.1"
|
|
3267
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3267
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3268
3268
|
dependencies = [
|
|
3269
3269
|
"anyhow",
|
|
3270
3270
|
"candle-core",
|
|
@@ -3291,7 +3291,7 @@ dependencies = [
|
|
|
3291
3291
|
[[package]]
|
|
3292
3292
|
name = "mistralrs-audio"
|
|
3293
3293
|
version = "0.8.1"
|
|
3294
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3294
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3295
3295
|
dependencies = [
|
|
3296
3296
|
"anyhow",
|
|
3297
3297
|
"apodize",
|
|
@@ -3302,7 +3302,7 @@ dependencies = [
|
|
|
3302
3302
|
[[package]]
|
|
3303
3303
|
name = "mistralrs-core"
|
|
3304
3304
|
version = "0.8.1"
|
|
3305
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3305
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3306
3306
|
dependencies = [
|
|
3307
3307
|
"ahash",
|
|
3308
3308
|
"akin",
|
|
@@ -3399,7 +3399,7 @@ dependencies = [
|
|
|
3399
3399
|
[[package]]
|
|
3400
3400
|
name = "mistralrs-macros"
|
|
3401
3401
|
version = "0.8.1"
|
|
3402
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3402
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3403
3403
|
dependencies = [
|
|
3404
3404
|
"darling 0.23.0",
|
|
3405
3405
|
"proc-macro2",
|
|
@@ -3410,7 +3410,7 @@ dependencies = [
|
|
|
3410
3410
|
[[package]]
|
|
3411
3411
|
name = "mistralrs-mcp"
|
|
3412
3412
|
version = "0.8.1"
|
|
3413
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3413
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3414
3414
|
dependencies = [
|
|
3415
3415
|
"anyhow",
|
|
3416
3416
|
"async-trait",
|
|
@@ -3430,7 +3430,7 @@ dependencies = [
|
|
|
3430
3430
|
[[package]]
|
|
3431
3431
|
name = "mistralrs-paged-attn"
|
|
3432
3432
|
version = "0.8.1"
|
|
3433
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3433
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3434
3434
|
dependencies = [
|
|
3435
3435
|
"anyhow",
|
|
3436
3436
|
"candle-core",
|
|
@@ -3446,7 +3446,7 @@ dependencies = [
|
|
|
3446
3446
|
[[package]]
|
|
3447
3447
|
name = "mistralrs-quant"
|
|
3448
3448
|
version = "0.8.1"
|
|
3449
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3449
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3450
3450
|
dependencies = [
|
|
3451
3451
|
"byteorder",
|
|
3452
3452
|
"candle-core",
|
|
@@ -3475,7 +3475,7 @@ dependencies = [
|
|
|
3475
3475
|
[[package]]
|
|
3476
3476
|
name = "mistralrs-vision"
|
|
3477
3477
|
version = "0.8.1"
|
|
3478
|
-
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#
|
|
3478
|
+
source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#e53956bcd1b40c8221f79b919d78c1e496aba634"
|
|
3479
3479
|
dependencies = [
|
|
3480
3480
|
"candle-core",
|
|
3481
3481
|
"image",
|
|
@@ -3799,7 +3799,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
|
3799
3799
|
[[package]]
|
|
3800
3800
|
name = "onde"
|
|
3801
3801
|
version = "0.1.8"
|
|
3802
|
-
source = "git+https://github.com/ondeinference/onde?branch=development#
|
|
3802
|
+
source = "git+https://github.com/ondeinference/onde?branch=development#dfcc6ecfa74ac965af6c33ba0bd06d9cf241fc12"
|
|
3803
3803
|
dependencies = [
|
|
3804
3804
|
"anyhow",
|
|
3805
3805
|
"cc",
|
|
@@ -4807,9 +4807,9 @@ dependencies = [
|
|
|
4807
4807
|
|
|
4808
4808
|
[[package]]
|
|
4809
4809
|
name = "rustls-pki-types"
|
|
4810
|
-
version = "1.14.
|
|
4810
|
+
version = "1.14.1"
|
|
4811
4811
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4812
|
-
checksum = "
|
|
4812
|
+
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
|
|
4813
4813
|
dependencies = [
|
|
4814
4814
|
"web-time",
|
|
4815
4815
|
"zeroize",
|
|
@@ -5271,7 +5271,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
|
5271
5271
|
|
|
5272
5272
|
[[package]]
|
|
5273
5273
|
name = "sigit"
|
|
5274
|
-
version = "0.
|
|
5274
|
+
version = "1.0.0"
|
|
5275
5275
|
dependencies = [
|
|
5276
5276
|
"agent-client-protocol",
|
|
5277
5277
|
"anyhow",
|
|
@@ -5283,6 +5283,7 @@ dependencies = [
|
|
|
5283
5283
|
"onde",
|
|
5284
5284
|
"ratatui",
|
|
5285
5285
|
"regex",
|
|
5286
|
+
"reqwest 0.12.28",
|
|
5286
5287
|
"serde_json",
|
|
5287
5288
|
"tokio",
|
|
5288
5289
|
"tokio-util",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "sigit"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "1.0.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
description = "siGit Code — ACP-compatible AI coding agent for smbCloud platform."
|
|
6
6
|
documentation = "https://github.com/getsigit/sigit"
|
|
@@ -18,11 +18,11 @@ path = "src/main.rs"
|
|
|
18
18
|
|
|
19
19
|
[dependencies]
|
|
20
20
|
# ACP protocol SDK
|
|
21
|
-
agent-client-protocol = { version = "0.10.4", features = ["unstable_session_fork"] }
|
|
21
|
+
agent-client-protocol = { version = "0.10.4", features = ["unstable_session_fork", "unstable_session_additional_directories"] }
|
|
22
22
|
|
|
23
23
|
# Onde Inference engine (local LLM)
|
|
24
|
-
#
|
|
25
|
-
onde = { git = "https://github.com/ondeinference/onde", branch = "development" }
|
|
24
|
+
# onde = { path = "../onde" }
|
|
25
|
+
onde = { version = "0.1.8", git = "https://github.com/ondeinference/onde", branch = "development" }
|
|
26
26
|
|
|
27
27
|
# Async runtime
|
|
28
28
|
async-trait = "0.1"
|
|
@@ -41,4 +41,5 @@ log = "0.4"
|
|
|
41
41
|
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
|
|
42
42
|
serde_json = "1"
|
|
43
43
|
regex = "1"
|
|
44
|
+
reqwest = { version = "0.12", default-features = false, features = ["blocking", "rustls-tls"] }
|
|
44
45
|
uuid = { version = "1", features = ["v4"] }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sigit-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -25,11 +25,7 @@ Project-URL: Homepage, https://smbcloud.xyz
|
|
|
25
25
|
Project-URL: Issues, https://github.com/getsigit/sigit/issues
|
|
26
26
|
Project-URL: Repository, https://github.com/getsigit/sigit
|
|
27
27
|
|
|
28
|
-
<
|
|
29
|
-
<strong>siGit Code</strong>
|
|
30
|
-
</p>
|
|
31
|
-
|
|
32
|
-
<h1 align="center">sigit</h1>
|
|
28
|
+
<h1 align="center">siGit Code</h1>
|
|
33
29
|
|
|
34
30
|
<p align="center">
|
|
35
31
|
<strong>AI coding agent powered by local LLM via <a href="https://ondeinference.com">Onde Inference</a>.</strong><br>
|
|
@@ -37,10 +33,10 @@ Project-URL: Repository, https://github.com/getsigit/sigit
|
|
|
37
33
|
</p>
|
|
38
34
|
|
|
39
35
|
<p align="center">
|
|
40
|
-
<a href="https://smbcloud.xyz"><img src="https://img.shields.io/badge/smbcloud.xyz-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
|
|
41
36
|
<a href="https://pypi.org/project/sigit-code/"><img src="https://img.shields.io/pypi/v/sigit-code?style=flat-square&labelColor=17211D&color=235843" alt="PyPI"></a>
|
|
42
|
-
<a href="https://www.npmjs.com/package/@smbcloud/sigit"><img src="https://img.shields.io/npm/v/@smbcloud/sigit?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
|
|
43
37
|
<a href="https://crates.io/crates/sigit"><img src="https://img.shields.io/crates/v/sigit?style=flat-square&labelColor=17211D&color=235843" alt="Crates.io"></a>
|
|
38
|
+
<a href="https://www.npmjs.com/package/@smbcloud/sigit"><img src="https://img.shields.io/npm/v/@smbcloud/sigit?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
|
|
39
|
+
<a href="https://smbcloud.xyz"><img src="https://img.shields.io/badge/smbcloud.xyz-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
|
|
44
40
|
<a href="https://github.com/getsigit/sigit/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-235843?style=flat-square&labelColor=17211D" alt="License"></a>
|
|
45
41
|
</p>
|
|
46
42
|
|
|
@@ -50,8 +46,11 @@ Project-URL: Repository, https://github.com/getsigit/sigit
|
|
|
50
46
|
|
|
51
47
|
## Install
|
|
52
48
|
|
|
49
|
+
Use `pip` or `uv`:
|
|
50
|
+
|
|
53
51
|
```sh
|
|
54
52
|
pip install sigit-code
|
|
53
|
+
uvx --from sigit-code sigit
|
|
55
54
|
```
|
|
56
55
|
|
|
57
56
|
Installs the native `sigit` binary for your platform — no compiler, no Node.js, no runtime dependencies.
|
|
@@ -72,15 +71,10 @@ siGit works as an [ACP-compatible](https://github.com/nicobailon/agent-client-pr
|
|
|
72
71
|
|
|
73
72
|
```json
|
|
74
73
|
{
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
"binary": {
|
|
80
|
-
"path": "sigit",
|
|
81
|
-
"args": ["--acp"]
|
|
82
|
-
}
|
|
83
|
-
}
|
|
74
|
+
"agent_servers": {
|
|
75
|
+
"siGit Code": {
|
|
76
|
+
"type": "custom",
|
|
77
|
+
"command": "/absolute/path/to/sigit"
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
80
|
}
|
|
@@ -93,7 +87,7 @@ Then select **sigit** as your agent profile in the Zed assistant panel.
|
|
|
93
87
|
| Method | Command |
|
|
94
88
|
|--------|---------|
|
|
95
89
|
| npm | `npm install -g @smbcloud/sigit` |
|
|
96
|
-
| Homebrew | `brew
|
|
90
|
+
| Homebrew | `brew tap getsigit/tap && brew install sigit` |
|
|
97
91
|
| Cargo | `cargo install sigit` |
|
|
98
92
|
|
|
99
93
|
### From source
|
|
@@ -131,4 +125,4 @@ Licensed under **Apache 2.0**.
|
|
|
131
125
|
|
|
132
126
|
## Copyright
|
|
133
127
|
|
|
134
|
-
2026 smbCloud (Splitfire AB).
|
|
128
|
+
© 2026 [smbCloud](https://smbcloud.xyz/) (Splitfire AB).
|