sigit-code 1.6.4__tar.gz → 1.6.6__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.6.4 → sigit_code-1.6.6}/.agents/AGENTS.md +42 -2
- {sigit_code-1.6.4 → sigit_code-1.6.6}/AGENTS.md +42 -2
- {sigit_code-1.6.4 → sigit_code-1.6.6}/CHANGELOG.md +113 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/CLAUDE.md +42 -2
- {sigit_code-1.6.4 → sigit_code-1.6.6}/Cargo.lock +305 -126
- {sigit_code-1.6.4 → sigit_code-1.6.6}/Cargo.toml +7 -4
- {sigit_code-1.6.4 → sigit_code-1.6.6}/PKG-INFO +1 -1
- {sigit_code-1.6.4 → sigit_code-1.6.6}/README.md +30 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/backend.rs +484 -80
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/chat.rs +28 -7
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/client_fs.rs +3 -2
- sigit_code-1.6.6/src/client_terminal.rs +468 -0
- sigit_code-1.6.6/src/harness_markup.rs +381 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/headless.rs +49 -22
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/main.rs +837 -146
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/mcp.rs +140 -739
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/provider.rs +18 -0
- sigit_code-1.6.6/src/repetition.rs +221 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/tools.rs +539 -110
- sigit_code-1.6.6/tests/acp_audio.rs +310 -0
- sigit_code-1.6.6/tests/acp_client_terminal.rs +504 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_concurrent_sessions.rs +150 -3
- sigit_code-1.6.6/tests/acp_embedded_context.rs +274 -0
- sigit_code-1.6.6/tests/acp_harness_markup.rs +270 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_permissions.rs +154 -1
- sigit_code-1.6.6/tests/acp_tool_call_name.rs +277 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/branding/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.agents/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.cargo/config.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/branding/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.claude/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/ci.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-aur.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-crates.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-github.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-homebrew.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-npm.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-nuget.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-pypi.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-scoop.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.github/workflows/release-winget.yml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.gitignore +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.nvmrc +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.sigit/code-cloud-agent/config.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.sigit/code-review/config.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/.sigit/factory/config.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/LICENSE +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/docs/headless.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/docs/hooks.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/docs/mcp.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/examples/settings-with-hooks.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/examples/skills/README.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/examples/skills/commit-message/SKILL.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/README.md.tmpl +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/package-compat.json.tmpl +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/package-main.json.tmpl +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/package.json.tmpl +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/scripts/render-main-package.cjs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/scripts/render-platform-package.cjs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/sigit/.gitignore +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/sigit/README.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/sigit/package.json +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/sigit/src/index.ts +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/npm/sigit/tsconfig.json +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/nuget/.gitignore +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/nuget/sigit/Program.cs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/nuget/sigit/README.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/nuget/sigit/SiGit.Code.csproj +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/aur/PKGBUILD.in +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/nfpm.yaml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/windows/check-static-crt.ps1 +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/winget/getSigit.siGitCode.installer.yaml.in +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/winget/getSigit.siGitCode.locale.en-US.yaml.in +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/packaging/winget/getSigit.siGitCode.yaml.in +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/pypi/README.md +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/pypi/pyproject.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/pyproject.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/rust-toolchain.toml +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/account.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/browser_auth.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/commands.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/credentials.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/frontmatter.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/hooks.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/inline_tool_calls.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/instructions.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/models.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/permissions.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/session_store.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/settings.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/setup.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/skills.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/subagents.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/src/workspace.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_client_fs.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_endpoint_errors.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_images.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_logout.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_multi_root.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_session_list.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_session_load.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_stop_reasons.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/acp_tool_stdin.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/headless_mode.rs +0 -0
- {sigit_code-1.6.4 → sigit_code-1.6.6}/tests/version_flag.rs +0 -0
|
@@ -152,6 +152,19 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
152
152
|
well-formed ones. A block that doesn't parse (or never closes) is dropped from both the reply
|
|
153
153
|
and history, and `OpenAiBackend::complete` retries once with a note telling the model the call
|
|
154
154
|
didn't run. Leaving the raw block in history makes the model invent `<function_results>` later.
|
|
155
|
+
What that scanner lets through then goes through `src/harness_markup.rs`, which removes
|
|
156
|
+
markup the model makes up in the harness's shape (issue #122): a `<system_warning>`-style
|
|
157
|
+
block (any `system_*`/`system-*` tag) is dropped whole, from the reply and the history, and
|
|
158
|
+
other underscore-named tags like `<Option_Picker>` lose the tags but keep their text. Code is
|
|
159
|
+
never touched, and an opening tag only counts at the start of a line, since prose writes
|
|
160
|
+
placeholders like `<repo_url>` the same way. It has to run after the inline-call scanner,
|
|
161
|
+
because `<tool_call>` matches its underscore rule.
|
|
162
|
+
`src/repetition.rs` guards the same stream against a reply that degenerates into a loop over a
|
|
163
|
+
tiny vocabulary (issue #123): a window of 200 words with at most 40 distinct ones, fenced code
|
|
164
|
+
excepted, makes `consume_stream` stop reading, truncate the text to where the loop began (so
|
|
165
|
+
history never holds the junk), tell the user, and finish with `FinishReason::Repetition`
|
|
166
|
+
(`EndTurn` in ACP). `complete` then retries once with `REPETITION_RETRY`, like the malformed
|
|
167
|
+
tool call retry. Only the streaming path is guarded; `consume_json` and `LocalBackend` are not.
|
|
155
168
|
Image attachments: ACP fixes `promptCapabilities.image` for the whole connection, while the
|
|
156
169
|
model can change on any turn, so the capability is always advertised and the decision is made
|
|
157
170
|
per prompt. `InferenceBackend::accepts_images` answers for the active model (on-device: no;
|
|
@@ -163,6 +176,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
163
176
|
when its model cannot read them, which is what makes a mid-thread switch to a text-only tier
|
|
164
177
|
safe. Read history text through `backend::message_text`, never `content.as_str()`.
|
|
165
178
|
`IMAGE_TIERS` mirrors onde-cloud's `IMAGE_CANDIDATES`; update both together.
|
|
179
|
+
Audio attachments take the same path (`promptCapabilities.audio`, `accepts_audio`,
|
|
180
|
+
`audio_for_turn`, `without_audio`), sent as OpenAI `input_audio` parts. No cloud tier
|
|
181
|
+
takes audio, because onde-cloud drops `input_audio` parts when it parses a request, so
|
|
182
|
+
`provider::model_accepts_audio` says no for every `onde-*` id and yes for a user's own
|
|
183
|
+
endpoint. If onde-cloud ever routes audio, give it a tier table like `IMAGE_TIERS`.
|
|
166
184
|
- **`src/provider.rs`** — decides *which* backend serves inference. Resolution order, first match
|
|
167
185
|
wins: (1) override via `OPENAI_BASE_URL`+`OPENAI_API_KEY` or active profile in
|
|
168
186
|
`~/.config/sigit/providers.toml`; (2) siGit Code Cloud when logged in; (3) on-device.
|
|
@@ -330,7 +348,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
330
348
|
`execute_tool_impl` asks `route_for` before it dispatches `read_file`, `create_file`,
|
|
331
349
|
`edit_file` or `multi_edit`. Each of those tools is split into a parse step and a pure
|
|
332
350
|
render/apply step (`ReadFileCall`, `CreateFileCall`, `EditCall`) that the disk path and the
|
|
333
|
-
client path share, so the model gets the same result text either way. The
|
|
351
|
+
client path share, so the model gets the same result text either way. The writing tools also
|
|
352
|
+
hand back the file before and after (`tools::FileChange`, via `execute_tool_with_change`), which
|
|
353
|
+
`handle_prompt` sends as ACP `diff` content ahead of the result text. A permission request for
|
|
354
|
+
one of them carries the same diff, worked out by `preview_file_change` without writing anything
|
|
355
|
+
and before the workspace is released, since a relative path resolves against the session's cwd. The two capabilities are
|
|
334
356
|
independent: a client that only reads still gets its edits written to disk. The disk is the
|
|
335
357
|
fallback throughout: nothing is registered in the TUI or headless modes, a path outside the
|
|
336
358
|
session's roots is not routed, and a request the client fails or leaves unanswered for 30
|
|
@@ -338,6 +360,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
338
360
|
inside a spawned prompt turn, never from `handle_initialize` itself (deadlock, same as
|
|
339
361
|
permission requests). Existence checks and `create_file`'s parent directories still use the
|
|
340
362
|
disk. `SIGIT_CLIENT_FS=off` turns the routing off. Covered by `tests/acp_client_fs.rs`.
|
|
363
|
+
- **`src/client_terminal.rs`** — `run_command` in the ACP client's terminal. A client that
|
|
364
|
+
advertises `terminal` in `initialize` runs a foreground command itself (`terminal/create`, with
|
|
365
|
+
the platform shell as `command` and the whole command line as one argument), and
|
|
366
|
+
`exec_run_command_via_client` embeds the terminal in the tool call as `terminal` content, so the
|
|
367
|
+
user watches the output live and can stop the command from the editor. The seam is
|
|
368
|
+
`client_fs`'s: `handle_initialize` registers `AcpClientTerminal`, and `execute_tool_impl` asks
|
|
369
|
+
`client_terminal_route` before the blocking path. Embedding needs the tool call's id, which is
|
|
370
|
+
why `execute_tool_with_change` takes one. What `run_command` promises stays put: the 120 s
|
|
371
|
+
timeout ends in `terminal/kill`, the output is capped, and `CommitWatch` still amends the
|
|
372
|
+
co-author trailer, checking HEAD on disk before and after. Background commands stay local
|
|
373
|
+
(`command_output` and `kill_command` read their pipes), and so does a command whose directory
|
|
374
|
+
is outside the session's roots, since nothing says the editor's machine can see it. A
|
|
375
|
+
`terminal/create` the client fails means nothing ran, so the command runs locally; a failure
|
|
376
|
+
after that is reported as the tool's error instead, because running it again could repeat its
|
|
377
|
+
effects. The finished card keeps the terminal and drops the result text, which still goes out
|
|
378
|
+
as `raw_output`. `SIGIT_CLIENT_TERMINAL=off` turns the routing off. Covered by
|
|
379
|
+
`tests/acp_client_terminal.rs`.
|
|
341
380
|
- **`src/chat.rs`** — the Unix-only ratatui TUI. Loading-spinner phase then chat; uses
|
|
342
381
|
`tokio::select!` to multiplex terminal events with streaming tokens.
|
|
343
382
|
- **`src/headless.rs`** — non-interactive `sigit run` execution for scripts, CI, and Factory
|
|
@@ -407,7 +446,8 @@ verbosity with `RUST_LOG`.
|
|
|
407
446
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
408
447
|
`SIGIT_MODEL`, `SIGIT_MAX_TOOL_ROUNDS` (1 to 500, default 24; the tool-round cap of a
|
|
409
448
|
headless run or an ACP prompt turn), `SIGIT_MCP` (`off` disables MCP), `SIGIT_CLIENT_FS` (`off` keeps the file tools on disk even when the
|
|
410
|
-
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `
|
|
449
|
+
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `SIGIT_CLIENT_TERMINAL` (`off` runs
|
|
450
|
+
`run_command` locally even when the ACP client offers a terminal), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
411
451
|
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
412
452
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
413
453
|
mutating tools; the escape hatch for clients without permission-request support),
|
|
@@ -152,6 +152,19 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
152
152
|
well-formed ones. A block that doesn't parse (or never closes) is dropped from both the reply
|
|
153
153
|
and history, and `OpenAiBackend::complete` retries once with a note telling the model the call
|
|
154
154
|
didn't run. Leaving the raw block in history makes the model invent `<function_results>` later.
|
|
155
|
+
What that scanner lets through then goes through `src/harness_markup.rs`, which removes
|
|
156
|
+
markup the model makes up in the harness's shape (issue #122): a `<system_warning>`-style
|
|
157
|
+
block (any `system_*`/`system-*` tag) is dropped whole, from the reply and the history, and
|
|
158
|
+
other underscore-named tags like `<Option_Picker>` lose the tags but keep their text. Code is
|
|
159
|
+
never touched, and an opening tag only counts at the start of a line, since prose writes
|
|
160
|
+
placeholders like `<repo_url>` the same way. It has to run after the inline-call scanner,
|
|
161
|
+
because `<tool_call>` matches its underscore rule.
|
|
162
|
+
`src/repetition.rs` guards the same stream against a reply that degenerates into a loop over a
|
|
163
|
+
tiny vocabulary (issue #123): a window of 200 words with at most 40 distinct ones, fenced code
|
|
164
|
+
excepted, makes `consume_stream` stop reading, truncate the text to where the loop began (so
|
|
165
|
+
history never holds the junk), tell the user, and finish with `FinishReason::Repetition`
|
|
166
|
+
(`EndTurn` in ACP). `complete` then retries once with `REPETITION_RETRY`, like the malformed
|
|
167
|
+
tool call retry. Only the streaming path is guarded; `consume_json` and `LocalBackend` are not.
|
|
155
168
|
Image attachments: ACP fixes `promptCapabilities.image` for the whole connection, while the
|
|
156
169
|
model can change on any turn, so the capability is always advertised and the decision is made
|
|
157
170
|
per prompt. `InferenceBackend::accepts_images` answers for the active model (on-device: no;
|
|
@@ -163,6 +176,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
163
176
|
when its model cannot read them, which is what makes a mid-thread switch to a text-only tier
|
|
164
177
|
safe. Read history text through `backend::message_text`, never `content.as_str()`.
|
|
165
178
|
`IMAGE_TIERS` mirrors onde-cloud's `IMAGE_CANDIDATES`; update both together.
|
|
179
|
+
Audio attachments take the same path (`promptCapabilities.audio`, `accepts_audio`,
|
|
180
|
+
`audio_for_turn`, `without_audio`), sent as OpenAI `input_audio` parts. No cloud tier
|
|
181
|
+
takes audio, because onde-cloud drops `input_audio` parts when it parses a request, so
|
|
182
|
+
`provider::model_accepts_audio` says no for every `onde-*` id and yes for a user's own
|
|
183
|
+
endpoint. If onde-cloud ever routes audio, give it a tier table like `IMAGE_TIERS`.
|
|
166
184
|
- **`src/provider.rs`** — decides *which* backend serves inference. Resolution order, first match
|
|
167
185
|
wins: (1) override via `OPENAI_BASE_URL`+`OPENAI_API_KEY` or active profile in
|
|
168
186
|
`~/.config/sigit/providers.toml`; (2) siGit Code Cloud when logged in; (3) on-device.
|
|
@@ -330,7 +348,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
330
348
|
`execute_tool_impl` asks `route_for` before it dispatches `read_file`, `create_file`,
|
|
331
349
|
`edit_file` or `multi_edit`. Each of those tools is split into a parse step and a pure
|
|
332
350
|
render/apply step (`ReadFileCall`, `CreateFileCall`, `EditCall`) that the disk path and the
|
|
333
|
-
client path share, so the model gets the same result text either way. The
|
|
351
|
+
client path share, so the model gets the same result text either way. The writing tools also
|
|
352
|
+
hand back the file before and after (`tools::FileChange`, via `execute_tool_with_change`), which
|
|
353
|
+
`handle_prompt` sends as ACP `diff` content ahead of the result text. A permission request for
|
|
354
|
+
one of them carries the same diff, worked out by `preview_file_change` without writing anything
|
|
355
|
+
and before the workspace is released, since a relative path resolves against the session's cwd. The two capabilities are
|
|
334
356
|
independent: a client that only reads still gets its edits written to disk. The disk is the
|
|
335
357
|
fallback throughout: nothing is registered in the TUI or headless modes, a path outside the
|
|
336
358
|
session's roots is not routed, and a request the client fails or leaves unanswered for 30
|
|
@@ -338,6 +360,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
338
360
|
inside a spawned prompt turn, never from `handle_initialize` itself (deadlock, same as
|
|
339
361
|
permission requests). Existence checks and `create_file`'s parent directories still use the
|
|
340
362
|
disk. `SIGIT_CLIENT_FS=off` turns the routing off. Covered by `tests/acp_client_fs.rs`.
|
|
363
|
+
- **`src/client_terminal.rs`** — `run_command` in the ACP client's terminal. A client that
|
|
364
|
+
advertises `terminal` in `initialize` runs a foreground command itself (`terminal/create`, with
|
|
365
|
+
the platform shell as `command` and the whole command line as one argument), and
|
|
366
|
+
`exec_run_command_via_client` embeds the terminal in the tool call as `terminal` content, so the
|
|
367
|
+
user watches the output live and can stop the command from the editor. The seam is
|
|
368
|
+
`client_fs`'s: `handle_initialize` registers `AcpClientTerminal`, and `execute_tool_impl` asks
|
|
369
|
+
`client_terminal_route` before the blocking path. Embedding needs the tool call's id, which is
|
|
370
|
+
why `execute_tool_with_change` takes one. What `run_command` promises stays put: the 120 s
|
|
371
|
+
timeout ends in `terminal/kill`, the output is capped, and `CommitWatch` still amends the
|
|
372
|
+
co-author trailer, checking HEAD on disk before and after. Background commands stay local
|
|
373
|
+
(`command_output` and `kill_command` read their pipes), and so does a command whose directory
|
|
374
|
+
is outside the session's roots, since nothing says the editor's machine can see it. A
|
|
375
|
+
`terminal/create` the client fails means nothing ran, so the command runs locally; a failure
|
|
376
|
+
after that is reported as the tool's error instead, because running it again could repeat its
|
|
377
|
+
effects. The finished card keeps the terminal and drops the result text, which still goes out
|
|
378
|
+
as `raw_output`. `SIGIT_CLIENT_TERMINAL=off` turns the routing off. Covered by
|
|
379
|
+
`tests/acp_client_terminal.rs`.
|
|
341
380
|
- **`src/chat.rs`** — the Unix-only ratatui TUI. Loading-spinner phase then chat; uses
|
|
342
381
|
`tokio::select!` to multiplex terminal events with streaming tokens.
|
|
343
382
|
- **`src/headless.rs`** — non-interactive `sigit run` execution for scripts, CI, and Factory
|
|
@@ -407,7 +446,8 @@ verbosity with `RUST_LOG`.
|
|
|
407
446
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
408
447
|
`SIGIT_MODEL`, `SIGIT_MAX_TOOL_ROUNDS` (1 to 500, default 24; the tool-round cap of a
|
|
409
448
|
headless run or an ACP prompt turn), `SIGIT_MCP` (`off` disables MCP), `SIGIT_CLIENT_FS` (`off` keeps the file tools on disk even when the
|
|
410
|
-
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `
|
|
449
|
+
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `SIGIT_CLIENT_TERMINAL` (`off` runs
|
|
450
|
+
`run_command` locally even when the ACP client offers a terminal), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
411
451
|
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
412
452
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
413
453
|
mutating tools; the escape hatch for clients without permission-request support),
|
|
@@ -1,5 +1,118 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 1.6.6
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **A tool call carries its programmatic tool name.** The `tool_call` an editor
|
|
10
|
+
gets for a running tool now includes `name` (`read_file`, `run_command`,
|
|
11
|
+
`mcp__…`) next to the human title, sent on the first report of the call only
|
|
12
|
+
as the protocol asks. A client can tell a command from a file edit without
|
|
13
|
+
parsing the title, and a replayed thread from `session/load` carries the same
|
|
14
|
+
name (#196).
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **MCP runs on `rmcp`, the official Rust SDK, through `ed-mcp`.** siGit Code's
|
|
19
|
+
own JSON-RPC client for stdio and Streamable HTTP servers (about 600 lines)
|
|
20
|
+
is gone; `ed-mcp` is the layer every Onde agent shares. `mcp.toml`, the
|
|
21
|
+
baked-in `sigit` and `smbcloud` servers, tool names and `/mcp` are unchanged.
|
|
22
|
+
An HTTP server that stops answering is now reconnected and the call retried
|
|
23
|
+
once for any failure but a timeout, not only on a 404.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **A reply that degenerates into a repetition loop is cut off.** After a tool
|
|
28
|
+
call, a model could fall into thousands of words from a tiny vocabulary
|
|
29
|
+
(`find: list: check: get: …`) with no tool call and no end, and the junk went
|
|
30
|
+
into history for the next turn. siGit Code now watches a streamed reply for a
|
|
31
|
+
window of 200 words with very few distinct ones (code blocks excepted), stops
|
|
32
|
+
reading, keeps only the text before the loop, tells you it stopped, and asks
|
|
33
|
+
the model once to make its call or answer briefly (#123).
|
|
34
|
+
- **A linked selection written as `L10-L20` or `L10` reads just those lines.**
|
|
35
|
+
siGit Code read the line range of a `resource_link` only as `L10:20` or
|
|
36
|
+
`L10-20`, so `L10-L20` (the GitHub style) and a single line `L10` sent the
|
|
37
|
+
whole file instead of the selection. It now reads the same forms Zed's own
|
|
38
|
+
mention parser does, and a range that starts at line 0 or runs backwards
|
|
39
|
+
counts as no range.
|
|
40
|
+
|
|
41
|
+
## 1.6.5
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **An `@file` mention can carry unsaved edits.** siGit Code now advertises
|
|
46
|
+
`promptCapabilities.embeddedContext`, so a client can put a resource's
|
|
47
|
+
contents in the prompt instead of sending a link to it. Before, a client
|
|
48
|
+
that follows the spec only sent `resource_link`, and siGit Code read the
|
|
49
|
+
file from disk, missing whatever the user had not saved yet (#141).
|
|
50
|
+
- **A prompt can carry audio.** siGit Code now advertises
|
|
51
|
+
`promptCapabilities.audio` and sends an attached clip to the model as an
|
|
52
|
+
OpenAI `input_audio` part. It works the way image attachments do: a model on
|
|
53
|
+
an endpoint you configure yourself gets the clip and decides for itself,
|
|
54
|
+
while siGit Code Cloud tiers and on-device models, none of which take audio
|
|
55
|
+
today, get a note in its place and the editor says the clip was left out
|
|
56
|
+
(#143).
|
|
57
|
+
- **The README says what telemetry is sent.** A new Telemetry section covers
|
|
58
|
+
the model-timing events Onde Inference can report for on-device models,
|
|
59
|
+
what they leave out, and how to turn them off with `ONDE_DISABLE_PULSE=1`.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **A turn that cannot get its session back stops.** A turn on an HTTP backend
|
|
64
|
+
gives up the process-wide working directory while it waits and reinstalls
|
|
65
|
+
its session before a tool runs. If the reinstall failed, the turn logged a
|
|
66
|
+
warning and carried on in whichever directory was current. Nothing makes it
|
|
67
|
+
fail today, since a close waits for the turn, but the turn now ends as
|
|
68
|
+
cancelled instead of depending on that.
|
|
69
|
+
- **Dependencies match the rest of the Onde stack.** Onde 1.2.2 to 1.3.1,
|
|
70
|
+
reqwest 0.12 to 0.13 and ratatui 0.29 to 0.30, the versions Ed, OndeCode and
|
|
71
|
+
SplitFire Agent use. ratatui is built with only its crossterm backend, which
|
|
72
|
+
drops the second copy of crossterm (0.28) from the build.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- **Tags a model makes up no longer show in the reply.** After a long run of
|
|
77
|
+
tool rounds, a model could start writing markup that looked like it came
|
|
78
|
+
from siGit Code: a `<system_warning>` block telling the user the previous
|
|
79
|
+
turn was injected and should be ignored, or a question wrapped in
|
|
80
|
+
`<Option_Picker>`. Neither tag means anything to siGit Code or the editor,
|
|
81
|
+
so both rendered as raw text. A `system_*` block is now dropped from the
|
|
82
|
+
reply and from the history, and other made-up tags are removed while the
|
|
83
|
+
text inside them stays. Code blocks are left alone. The system prompt also
|
|
84
|
+
tells the model to write plain Markdown and to list choices as plain text
|
|
85
|
+
(#122).
|
|
86
|
+
- **Closing a thread that is waiting at a permission prompt no longer hangs.**
|
|
87
|
+
`session/close` cancels the session's running turn and waits for it to end,
|
|
88
|
+
but a turn stopped at a permission prompt only went on when the client
|
|
89
|
+
answered the request. A client that closed the thread without answering
|
|
90
|
+
left the close, and every later request for that thread, waiting for good.
|
|
91
|
+
The same held for `session/cancel` with a client that did not send the
|
|
92
|
+
cancelled outcome the protocol asks for. The permission wait now ends on
|
|
93
|
+
the cancellation as well, and an approval that arrives after the turn was
|
|
94
|
+
cancelled runs nothing.
|
|
95
|
+
|
|
96
|
+
- **A closed thread no longer leaves its request lock behind.** The process
|
|
97
|
+
kept one lock per session id for as long as it ran, for closed threads and
|
|
98
|
+
for ids no session ever had. The entry now goes with the last request that
|
|
99
|
+
used it.
|
|
100
|
+
|
|
101
|
+
- **A tool call that did not run no longer shows as completed.** When policy
|
|
102
|
+
or plan mode denied a call, when the user picked Deny at the permission
|
|
103
|
+
prompt, or when the repeat guard skipped a call the model made three times,
|
|
104
|
+
the editor's card still ended `completed`. Those cards now end `failed`, the
|
|
105
|
+
same way a call cancelled at the prompt already did. A call denied at the
|
|
106
|
+
prompt also gets its own title back instead of keeping the permission
|
|
107
|
+
request's (#139).
|
|
108
|
+
|
|
109
|
+
- **On-device inference no longer panics on some non-English text.** siGit Code
|
|
110
|
+
now builds on Onde 1.3.1, which fixes a panic when a message longer than 100
|
|
111
|
+
bytes had a multi-byte character (an accented letter, CJK, or an emoji) at
|
|
112
|
+
byte 100. Onde 1.3 also reports Pulse events for streaming inference, which
|
|
113
|
+
is the path on-device turns take, so those turns are now reported alongside
|
|
114
|
+
model loads. `ONDE_DISABLE_PULSE=1` turns Pulse off.
|
|
115
|
+
|
|
3
116
|
## 1.6.4
|
|
4
117
|
|
|
5
118
|
### Added
|
|
@@ -152,6 +152,19 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
152
152
|
well-formed ones. A block that doesn't parse (or never closes) is dropped from both the reply
|
|
153
153
|
and history, and `OpenAiBackend::complete` retries once with a note telling the model the call
|
|
154
154
|
didn't run. Leaving the raw block in history makes the model invent `<function_results>` later.
|
|
155
|
+
What that scanner lets through then goes through `src/harness_markup.rs`, which removes
|
|
156
|
+
markup the model makes up in the harness's shape (issue #122): a `<system_warning>`-style
|
|
157
|
+
block (any `system_*`/`system-*` tag) is dropped whole, from the reply and the history, and
|
|
158
|
+
other underscore-named tags like `<Option_Picker>` lose the tags but keep their text. Code is
|
|
159
|
+
never touched, and an opening tag only counts at the start of a line, since prose writes
|
|
160
|
+
placeholders like `<repo_url>` the same way. It has to run after the inline-call scanner,
|
|
161
|
+
because `<tool_call>` matches its underscore rule.
|
|
162
|
+
`src/repetition.rs` guards the same stream against a reply that degenerates into a loop over a
|
|
163
|
+
tiny vocabulary (issue #123): a window of 200 words with at most 40 distinct ones, fenced code
|
|
164
|
+
excepted, makes `consume_stream` stop reading, truncate the text to where the loop began (so
|
|
165
|
+
history never holds the junk), tell the user, and finish with `FinishReason::Repetition`
|
|
166
|
+
(`EndTurn` in ACP). `complete` then retries once with `REPETITION_RETRY`, like the malformed
|
|
167
|
+
tool call retry. Only the streaming path is guarded; `consume_json` and `LocalBackend` are not.
|
|
155
168
|
Image attachments: ACP fixes `promptCapabilities.image` for the whole connection, while the
|
|
156
169
|
model can change on any turn, so the capability is always advertised and the decision is made
|
|
157
170
|
per prompt. `InferenceBackend::accepts_images` answers for the active model (on-device: no;
|
|
@@ -163,6 +176,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
163
176
|
when its model cannot read them, which is what makes a mid-thread switch to a text-only tier
|
|
164
177
|
safe. Read history text through `backend::message_text`, never `content.as_str()`.
|
|
165
178
|
`IMAGE_TIERS` mirrors onde-cloud's `IMAGE_CANDIDATES`; update both together.
|
|
179
|
+
Audio attachments take the same path (`promptCapabilities.audio`, `accepts_audio`,
|
|
180
|
+
`audio_for_turn`, `without_audio`), sent as OpenAI `input_audio` parts. No cloud tier
|
|
181
|
+
takes audio, because onde-cloud drops `input_audio` parts when it parses a request, so
|
|
182
|
+
`provider::model_accepts_audio` says no for every `onde-*` id and yes for a user's own
|
|
183
|
+
endpoint. If onde-cloud ever routes audio, give it a tier table like `IMAGE_TIERS`.
|
|
166
184
|
- **`src/provider.rs`** — decides *which* backend serves inference. Resolution order, first match
|
|
167
185
|
wins: (1) override via `OPENAI_BASE_URL`+`OPENAI_API_KEY` or active profile in
|
|
168
186
|
`~/.config/sigit/providers.toml`; (2) siGit Code Cloud when logged in; (3) on-device.
|
|
@@ -330,7 +348,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
330
348
|
`execute_tool_impl` asks `route_for` before it dispatches `read_file`, `create_file`,
|
|
331
349
|
`edit_file` or `multi_edit`. Each of those tools is split into a parse step and a pure
|
|
332
350
|
render/apply step (`ReadFileCall`, `CreateFileCall`, `EditCall`) that the disk path and the
|
|
333
|
-
client path share, so the model gets the same result text either way. The
|
|
351
|
+
client path share, so the model gets the same result text either way. The writing tools also
|
|
352
|
+
hand back the file before and after (`tools::FileChange`, via `execute_tool_with_change`), which
|
|
353
|
+
`handle_prompt` sends as ACP `diff` content ahead of the result text. A permission request for
|
|
354
|
+
one of them carries the same diff, worked out by `preview_file_change` without writing anything
|
|
355
|
+
and before the workspace is released, since a relative path resolves against the session's cwd. The two capabilities are
|
|
334
356
|
independent: a client that only reads still gets its edits written to disk. The disk is the
|
|
335
357
|
fallback throughout: nothing is registered in the TUI or headless modes, a path outside the
|
|
336
358
|
session's roots is not routed, and a request the client fails or leaves unanswered for 30
|
|
@@ -338,6 +360,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
338
360
|
inside a spawned prompt turn, never from `handle_initialize` itself (deadlock, same as
|
|
339
361
|
permission requests). Existence checks and `create_file`'s parent directories still use the
|
|
340
362
|
disk. `SIGIT_CLIENT_FS=off` turns the routing off. Covered by `tests/acp_client_fs.rs`.
|
|
363
|
+
- **`src/client_terminal.rs`** — `run_command` in the ACP client's terminal. A client that
|
|
364
|
+
advertises `terminal` in `initialize` runs a foreground command itself (`terminal/create`, with
|
|
365
|
+
the platform shell as `command` and the whole command line as one argument), and
|
|
366
|
+
`exec_run_command_via_client` embeds the terminal in the tool call as `terminal` content, so the
|
|
367
|
+
user watches the output live and can stop the command from the editor. The seam is
|
|
368
|
+
`client_fs`'s: `handle_initialize` registers `AcpClientTerminal`, and `execute_tool_impl` asks
|
|
369
|
+
`client_terminal_route` before the blocking path. Embedding needs the tool call's id, which is
|
|
370
|
+
why `execute_tool_with_change` takes one. What `run_command` promises stays put: the 120 s
|
|
371
|
+
timeout ends in `terminal/kill`, the output is capped, and `CommitWatch` still amends the
|
|
372
|
+
co-author trailer, checking HEAD on disk before and after. Background commands stay local
|
|
373
|
+
(`command_output` and `kill_command` read their pipes), and so does a command whose directory
|
|
374
|
+
is outside the session's roots, since nothing says the editor's machine can see it. A
|
|
375
|
+
`terminal/create` the client fails means nothing ran, so the command runs locally; a failure
|
|
376
|
+
after that is reported as the tool's error instead, because running it again could repeat its
|
|
377
|
+
effects. The finished card keeps the terminal and drops the result text, which still goes out
|
|
378
|
+
as `raw_output`. `SIGIT_CLIENT_TERMINAL=off` turns the routing off. Covered by
|
|
379
|
+
`tests/acp_client_terminal.rs`.
|
|
341
380
|
- **`src/chat.rs`** — the Unix-only ratatui TUI. Loading-spinner phase then chat; uses
|
|
342
381
|
`tokio::select!` to multiplex terminal events with streaming tokens.
|
|
343
382
|
- **`src/headless.rs`** — non-interactive `sigit run` execution for scripts, CI, and Factory
|
|
@@ -407,7 +446,8 @@ verbosity with `RUST_LOG`.
|
|
|
407
446
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
408
447
|
`SIGIT_MODEL`, `SIGIT_MAX_TOOL_ROUNDS` (1 to 500, default 24; the tool-round cap of a
|
|
409
448
|
headless run or an ACP prompt turn), `SIGIT_MCP` (`off` disables MCP), `SIGIT_CLIENT_FS` (`off` keeps the file tools on disk even when the
|
|
410
|
-
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `
|
|
449
|
+
ACP client offers `fs/read_text_file` / `fs/write_text_file`), `SIGIT_CLIENT_TERMINAL` (`off` runs
|
|
450
|
+
`run_command` locally even when the ACP client offers a terminal), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
411
451
|
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
412
452
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
413
453
|
mutating tools; the escape hatch for clients without permission-request support),
|