Skip to content

Commit 706b49d

Browse files
committed
Merge development into main for v1.7.0 release
2 parents aecaa16 + 90fbffd commit 706b49d

86 files changed

Lines changed: 4805 additions & 814 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/AGENTS.md‎

Lines changed: 123 additions & 48 deletions
Large diffs are not rendered by default.

‎.agents/skills/agent-client-protocol/SKILL.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Spec: https://agentclientprotocol.com
2626
> protocol (`Agent.v2()`, `V2ConnectionTo`) sits behind the `unstable_protocol_v2`
2727
> feature and siGit does not enable it.
2828
29-
siGit's entire ACP server lives in `src/main.rs` (`run_acp_server`, the
29+
siGit's entire ACP server lives in `crates/cli/src/main.rs` (`run_acp_server`, the
3030
`SiGitAgent` struct, and its `handle_*` methods). Read it alongside this skill.
3131

3232
---
@@ -202,11 +202,12 @@ the connection and the agent anymore. Don't reintroduce the mpsc forwarder patte
202202
| `NewSessionRequest` | `handle_new_session` | sets cwd, resets history, advertises commands + config options |
203203
| `LoadSessionRequest` | `handle_load_session` | like new_session; gated by `load_session(true)` capability |
204204
| `ForkSessionRequest` | `handle_fork_session` | gated by `unstable_session_fork` + `SessionForkCapabilities` |
205-
| `ListSessionsRequest` | `handle_list_sessions` | the editor's "Import Threads" picker; gated by `SessionListCapabilities` |
205+
| `ListSessionsRequest` | `handle_list_sessions` | the editor's "Import Threads" picker; gated by `SessionListCapabilities`; paged with `cursor` / `nextCursor` |
206206
| `PromptRequest` | `handle_prompt` | the turn: parse blocks → slash commands or tool-calling loop |
207207
| `SetSessionConfigOptionRequest` | `handle_set_session_config_option` | the Zed model picker — switches/downloads models |
208208
| `SetSessionModeRequest` | `handle_set_session_mode` | legacy mode selector; same Manual/Auto/Plan state as the Permissions config option |
209209
| `CancelNotification` | `handle_cancel` | notification, no response |
210+
| `$/cancel_request` | `responder.cancellation()` | not a registered handler: the SDK tracks it per request, and the prompt and `authenticate` closures read the marker |
210211

211212
Everything else is left to the SDK default (method not found).
212213

@@ -594,14 +595,14 @@ Editor Agent
594595

595596
## Where to look in the code
596597

597-
Everything ACP lives in `src/main.rs`:
598+
Everything ACP lives in `crates/cli/src/main.rs`:
598599

599600
- `run_acp_server` — builder wiring + transport.
600601
- `SiGitAgent` + `handle_*` — the handlers.
601602
- `build_model_config_options` / `resolve_model_config` — picker.
602603
- `parse_slash` / `exec_slash_acp` — slash commands.
603604
- `handle_response` — the `Responder` helper.
604605

605-
`src/backend.rs` holds the `InferenceBackend` trait (`LocalBackend` /
606-
`OpenAiBackend`) used by `handle_prompt`'s tool-calling loop; `src/tools.rs`
606+
`crates/cli/src/backend.rs` holds the `InferenceBackend` trait (`LocalBackend` /
607+
`OpenAiBackend`) used by `handle_prompt`'s tool-calling loop; `crates/cli/src/tools.rs`
607608
defines the agent tools and `execute_tool`.

‎.agents/skills/run-sigit/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ tmux kill-session -t sigit
9494
## Run (human path)
9595

9696
```bash
97-
cargo run # stdin is your TTY → launches the TUI
97+
cargo run -p sigit # stdin is your TTY → launches the TUI
9898
```
9999

100100
A full-screen chat opens; type a message or `/help`, Ctrl+C to quit. Useless

‎.agents/skills/sigit-code-release/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ Use this skill when preparing a release for this repository.
1717
## Working approach
1818

1919
1. Read the files that define the release version and distribution metadata before proposing any changes.
20-
2. Treat `Cargo.toml` as the primary release version source for the Rust crate and the PyPI package in this repository.
20+
2. Treat `[workspace.package].version` in the root `Cargo.toml` as the primary release version source for the Rust crate and the PyPI package in this repository.
2121
3. Check how the release workflows rewrite or derive versions before editing checked-in npm or Python metadata.
2222
4. Prefer targeted verification commands that match CI or packaging workflows already present in the repository.
2323
5. Report blockers clearly: failed checks, version mismatches, missing changelog entries, or unpublished packaging changes.
2424

2525
## Repo-specific release rules
2626

27-
- Bump the crate version in `Cargo.toml`.
27+
- Bump `[workspace.package].version` in the root `Cargo.toml`; every workspace crate inherits it.
2828
- Update the root `sigit` package entry in `Cargo.lock` when the crate version changes.
2929
- Add or update the top changelog entry in `CHANGELOG.md` for the release being cut.
3030
- Do not treat `npm/sigit/package.json` `0.0.0-dev` as a bug by default. The npm release workflow rewrites it at publish time using `npm/scripts/render-main-package.cjs` and the release tag.
3131
- Every npm package publishes twice, under `@getsigit` and under `@smbcloud`. `@smbcloud` is the pre-1.5.5 name, mirrored so an install predating the rename keeps updating; `@getsigit` is canonical and is what the README, the Homebrew tap, and the ACP registry entry point at. All fourteen names (two base packages, twelve platform packages) publish over OIDC and each needs its own Trusted Publisher on npm pointing at `release-npm.yml`.
3232
- The scope is a render-time argument, not a second copy of the packaging: `render-platform-package.cjs` takes it as a fifth argument, and the base package picks it up from `package-main.json.tmpl` versus `package-compat.json.tmpl`. `npm/sigit/src/index.ts` is built once and shipped under both names — it reads its own `package.json` at runtime to decide which scope to resolve the platform binary from, and prints the migration notice only when it finds itself running as `@smbcloud/sigit`.
33-
- Do not add a hardcoded version to `pypi/pyproject.toml` for normal releases. PyPI uses `maturin` with `dynamic = ["version"]` and derives the published package version from `Cargo.toml`.
33+
- Do not add a hardcoded version to `pypi/pyproject.toml` for normal releases. PyPI uses `maturin` with `dynamic = ["version"]` and derives the published package version from `crates/cli/Cargo.toml`, which inherits the workspace version.
3434
- Release workflows are tag-driven. `release-github.yml`, `release-npm.yml`, `release-pypi.yml`, `release-crates.yml`, `release-homebrew.yml`, `release-nuget.yml`, and `release-mcp-registry.yml` all derive `RELEASE_VERSION` from a `v*.*.*` tag or a manually supplied tag input.
3535
- The crate is published to crates.io (`release-crates.yml`) and the Homebrew tap is updated (`release-homebrew.yml`) as part of the tag-driven flow. Per the siGit release flow, Homebrew is auto-triggered — do not dispatch it manually.
3636
- `release-github.yml` builds the binaries, attaches them (plus a `.deb`/`.rpm` per Linux target built with nfpm from `packaging/nfpm.yaml`) to the GitHub release, then dispatches `release-homebrew`, `release-scoop`, `release-winget`, and `release-aur`. A dispatch failure in any one of those four is logged as a warning, not a hard failure — an unconfigured channel doesn't block the rest of the release. `release-nuget.yml` and `release-mcp-registry.yml`, by contrast, are tag-triggered directly like the other language-registry workflows, not dispatched from `release-github.yml`.

‎.agents/skills/tool-calling/SKILL.md‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Tool calling spans these layers:
1313

1414
```
1515
siGit (agent loop + tool execution)
16-
→ InferenceBackend (src/backend.rs — LocalBackend or OpenAiBackend/cloud)
16+
→ InferenceBackend (crates/cli/src/backend.rs — LocalBackend or OpenAiBackend/cloud)
1717
→ onde ChatEngine (tool-aware API) ── for LocalBackend
1818
→ mistral.rs (model inference + tool call parsing)
1919
└ OpenAI-compatible HTTP endpoint ── for OpenAiBackend (siGit Code Cloud)
@@ -31,7 +31,7 @@ a remote OpenAI-compatible endpoint (the siGit Code Cloud tiers). Both implement
3131
Tool calling needs a model mistral.rs has a tool-call parser for. The supported
3232
set is the **Qwen 3 family** (`<tool_call>...</tool_call>` XML) plus **Qwen 2.5
3333
Coder 7B**. Plain Qwen 2.5 and the smaller Qwen 2.5 Coder variants do NOT support
34-
tool calling. The authoritative list is `is_tool_calling()` in `src/models.rs`.
34+
tool calling. The authoritative list is `is_tool_calling()` in `crates/cli/src/models.rs`.
3535

3636
| Model | Constructor | Size | Tool calling |
3737
|-------|-----------|------|:---:|
@@ -54,7 +54,7 @@ fallback. Users pick a tool-calling model via the `/models` picker.
5454

5555
### max_tokens
5656

57-
`max_tokens_for()` in `src/models.rs` gives tool-calling models **4096** tokens
57+
`max_tokens_for()` in `crates/cli/src/models.rs` gives tool-calling models **4096** tokens
5858
and non-tool models **512** (tool models need headroom because `<think>` blocks
5959
eat the budget). The TUI startup load in `run_interactive` overrides this to
6060
**8192**. Don't assume a single value.
@@ -139,7 +139,7 @@ In ACP mode, `handle_prompt` currently always passes the full tool set (`agent_t
139139
| `send_message_with_tools(msg, &[ToolDefinition])` | Returns `ToolAwareResult` with possible tool calls |
140140
| `send_tool_results(Vec<ToolResult>, Option<&[ToolDefinition]>)` | Feed results back; `None` forces text response |
141141

142-
#### Layer 2.5: the `InferenceBackend` abstraction (`src/backend.rs`)
142+
#### Layer 2.5: the `InferenceBackend` abstraction (`crates/cli/src/backend.rs`)
143143

144144
siGit doesn't call the engine directly from the agent loop — it goes through the
145145
`InferenceBackend` trait so on-device and cloud inference share one code path:
@@ -155,7 +155,7 @@ siGit doesn't call the engine directly from the agent loop — it goes through t
155155
`handle_prompt` snapshots `self.backend.lock().await.clone()` once per turn so a
156156
mid-turn model/tier switch can't split the conversation across backends. When
157157
`backend.is_remote()` it skips the local model load + readiness wait. Cloud tiers
158-
(`fast`, `balanced`, `large`) come from `src/provider.rs` and are sign-in gated.
158+
(`fast`, `balanced`, `large`) come from `crates/cli/src/provider.rs` and are sign-in gated.
159159

160160
#### Internal details
161161

@@ -167,7 +167,7 @@ mid-turn model/tier switch can't split the conversation across backends. When
167167

168168
### Layer 3: siGit (agent-level)
169169

170-
#### ACP session handling (`src/main.rs`)
170+
#### ACP session handling (`crates/cli/src/main.rs`)
171171

172172
All session handlers (`load_session`, `fork_session`, `new_session`) do:
173173

@@ -252,7 +252,7 @@ Models are stored in the shared Onde App Group container on macOS:
252252

253253
## Adding a New Tool
254254

255-
1. Add an `AgentTool` entry to `all_tools()` in `src/tools.rs`
255+
1. Add an `AgentTool` entry to `all_tools()` in `crates/cli/src/tools.rs`
256256
2. Add a match arm to `execute_tool()` — use `spawn_blocking` if the implementation blocks
257257
3. Write `exec_your_tool(arguments: &str) -> String`
258258
4. Update `test_all_tools_count` test (currently expects 9)

‎.github/workflows/release-crates.yml‎

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,51 @@ jobs:
5555
with:
5656
key: crates-publish
5757

58-
- name: Check whether version already exists on crates.io
58+
# sigit depends on sigit-agent, so the library goes first, each behind its own
59+
# "already published" check: a re-run publishes only what is missing.
60+
- name: Check whether sigit-agent already exists on crates.io
61+
id: agent-check
62+
shell: bash
63+
run: |
64+
VERSION=$(cargo metadata --no-deps --format-version 1 | \
65+
python3 -c "import sys,json; pkgs=json.load(sys.stdin)['packages']; \
66+
print(next(p['version'] for p in pkgs if p['name']=='sigit-agent'))")
67+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
68+
69+
# crates.io answers 403 to requests without a descriptive
70+
# User-Agent, so curl's default one makes this look like a 404 and
71+
# the publish below runs into "crate already exists on the index".
72+
# Branch on the status code rather than on curl's exit status, so an
73+
# answer we do not understand stops the job instead of quietly
74+
# degrading into that same failure.
75+
# Retry first, so a timeout or a 5xx costs a few seconds instead of
76+
# the whole release.
77+
STATUS=$(curl -sS -o /dev/null -w '%{http_code}' \
78+
--retry 3 --retry-delay 2 --retry-all-errors \
79+
-H "User-Agent: ${GITHUB_REPOSITORY} release workflow (https://github.com/${GITHUB_REPOSITORY})" \
80+
"https://crates.io/api/v1/crates/sigit-agent/${VERSION}")
81+
82+
case "$STATUS" in
83+
200)
84+
echo "sigit-agent ${VERSION} already exists on crates.io, skipping publish"
85+
echo "exists=true" >> "$GITHUB_OUTPUT"
86+
;;
87+
404)
88+
echo "exists=false" >> "$GITHUB_OUTPUT"
89+
;;
90+
*)
91+
echo "Unexpected ${STATUS} from crates.io while checking whether sigit-agent ${VERSION} is published" >&2
92+
exit 1
93+
;;
94+
esac
95+
96+
- name: Publish sigit-agent to crates.io
97+
if: steps.agent-check.outputs.exists != 'true'
98+
env:
99+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
100+
run: cargo publish --locked -p sigit-agent
101+
102+
- name: Check whether sigit already exists on crates.io
59103
id: crates-check
60104
shell: bash
61105
run: |
@@ -91,8 +135,8 @@ jobs:
91135
;;
92136
esac
93137
94-
- name: Publish to crates.io
138+
- name: Publish sigit to crates.io
95139
if: steps.crates-check.outputs.exists != 'true'
96140
env:
97141
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
98-
run: cargo publish --locked
142+
run: cargo publish --locked -p sigit

‎.github/workflows/release-github.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494

9595
- name: Build binary
9696
shell: bash
97-
run: cargo build --locked --release --target ${{ matrix.target }}
97+
run: cargo build --locked --release -p sigit --target ${{ matrix.target }}
9898

9999
- name: Check Windows binary has no VC++ runtime dependency
100100
if: contains(matrix.target, 'windows')

‎.github/workflows/release-homebrew.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ jobs:
8181
8282
# Homebrew formula for siGit Code (\`sigit\` binary).
8383
class Sigit < Formula
84-
desc 'AI coding agent powered by local LLM via Onde Inference'
85-
homepage 'https://github.com/getsigit/sigit'
84+
desc 'A modular local inference LLM coding agent. Core component of siGit Factory.'
85+
homepage 'https://sigit.si/code'
8686
version '${VERSION}'
8787
license 'Apache-2.0'
8888

‎.github/workflows/release-npm.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101

102102
- name: Build binary
103103
shell: bash
104-
run: cargo build --locked --release --target ${{ matrix.build.TARGET }}
104+
run: cargo build --locked --release -p sigit --target ${{ matrix.build.TARGET }}
105105

106106
- name: Install Node
107107
uses: actions/setup-node@v6

‎.github/workflows/release-nuget.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ jobs:
9090

9191
- name: Build binary
9292
shell: bash
93-
run: cargo build --locked --release --target ${{ matrix.build.TARGET }}
93+
run: cargo build --locked --release -p sigit --target ${{ matrix.build.TARGET }}
9494

9595
- name: Prepare artifact
9696
shell: bash

0 commit comments

Comments
 (0)