sigit-code 1.6.6__tar.gz → 1.6.7__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.6 → sigit_code-1.6.7}/.agents/AGENTS.md +5 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/AGENTS.md +5 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/CHANGELOG.md +12 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/CLAUDE.md +5 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/Cargo.lock +1 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/Cargo.toml +1 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/PKG-INFO +1 -1
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/main.rs +138 -15
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_audio.rs +45 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/branding/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.agents/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.cargo/config.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/branding/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.claude/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/ci.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-aur.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-crates.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-github.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-homebrew.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-npm.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-nuget.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-pypi.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-scoop.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.github/workflows/release-winget.yml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.gitignore +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.nvmrc +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.sigit/code-cloud-agent/config.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.sigit/code-review/config.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/.sigit/factory/config.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/LICENSE +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/README.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/docs/headless.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/docs/hooks.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/docs/mcp.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/examples/settings-with-hooks.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/examples/skills/README.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/examples/skills/commit-message/SKILL.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/README.md.tmpl +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/package-compat.json.tmpl +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/package-main.json.tmpl +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/package.json.tmpl +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/scripts/render-main-package.cjs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/scripts/render-platform-package.cjs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/sigit/.gitignore +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/sigit/README.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/sigit/package.json +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/sigit/src/index.ts +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/npm/sigit/tsconfig.json +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/nuget/.gitignore +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/nuget/sigit/Program.cs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/nuget/sigit/README.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/nuget/sigit/SiGit.Code.csproj +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/aur/PKGBUILD.in +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/nfpm.yaml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/windows/check-static-crt.ps1 +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/winget/getSigit.siGitCode.installer.yaml.in +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/winget/getSigit.siGitCode.locale.en-US.yaml.in +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/winget/getSigit.siGitCode.yaml.in +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/pypi/README.md +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/pypi/pyproject.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/pyproject.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/rust-toolchain.toml +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/account.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/backend.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/browser_auth.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/chat.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/client_fs.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/client_terminal.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/commands.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/credentials.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/frontmatter.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/harness_markup.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/headless.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/hooks.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/inline_tool_calls.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/instructions.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/mcp.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/models.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/permissions.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/provider.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/repetition.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/session_store.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/settings.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/setup.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/skills.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/subagents.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/tools.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/src/workspace.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_client_fs.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_client_terminal.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_concurrent_sessions.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_embedded_context.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_endpoint_errors.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_harness_markup.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_images.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_logout.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_multi_root.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_permissions.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_session_list.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_session_load.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_stop_reasons.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_tool_call_name.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/acp_tool_stdin.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/headless_mode.rs +0 -0
- {sigit_code-1.6.6 → sigit_code-1.6.7}/tests/version_flag.rs +0 -0
|
@@ -310,7 +310,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
310
310
|
conversation); lifecycle and config handlers hold it throughout, and `handle_prompt` holds it
|
|
311
311
|
through a `WorkspaceHold` that it releases while waiting on an HTTP endpoint or a permission
|
|
312
312
|
answer and retakes (reinstalling its session via `resume_workspace`) before any tool runs. An
|
|
313
|
-
on-device turn never releases it. Take the session lock first, never the other way round.
|
|
313
|
+
on-device turn never releases it. Take the session lock first, never the other way round. A turn registers its `PromptCancellation` at
|
|
314
|
+
the top of `handle_prompt`, before it waits on either lock, and a `PromptRegistration`
|
|
315
|
+
guard clears it on every return, so a `session/cancel` that arrives while the turn
|
|
316
|
+
is still queued, switching threads, loading a model or running a slash command ends
|
|
317
|
+
it as `cancelled`. The checks sit after each of those waits. Tool
|
|
314
318
|
execution, subagents included, still runs one session at a time.
|
|
315
319
|
- **`src/instructions.rs`** — project instruction files, the always-on counterpart to skills.
|
|
316
320
|
Reads `AGENTS.md` (the cross-tool [agents.md](https://agents.md) standard) and `CLAUDE.md`,
|
|
@@ -310,7 +310,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
310
310
|
conversation); lifecycle and config handlers hold it throughout, and `handle_prompt` holds it
|
|
311
311
|
through a `WorkspaceHold` that it releases while waiting on an HTTP endpoint or a permission
|
|
312
312
|
answer and retakes (reinstalling its session via `resume_workspace`) before any tool runs. An
|
|
313
|
-
on-device turn never releases it. Take the session lock first, never the other way round.
|
|
313
|
+
on-device turn never releases it. Take the session lock first, never the other way round. A turn registers its `PromptCancellation` at
|
|
314
|
+
the top of `handle_prompt`, before it waits on either lock, and a `PromptRegistration`
|
|
315
|
+
guard clears it on every return, so a `session/cancel` that arrives while the turn
|
|
316
|
+
is still queued, switching threads, loading a model or running a slash command ends
|
|
317
|
+
it as `cancelled`. The checks sit after each of those waits. Tool
|
|
314
318
|
execution, subagents included, still runs one session at a time.
|
|
315
319
|
- **`src/instructions.rs`** — project instruction files, the always-on counterpart to skills.
|
|
316
320
|
Reads `AGENTS.md` (the cross-tool [agents.md](https://agents.md) standard) and `CLAUDE.md`,
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.6.7
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **A cancel that arrives before the turn starts is no longer lost.** A prompt
|
|
8
|
+
now registers for `session/cancel` as soon as it begins, not once it reaches
|
|
9
|
+
inference. A cancel that lands while the turn is queued on the workspace,
|
|
10
|
+
switching threads, loading a model, or running a slash command ends it with
|
|
11
|
+
`cancelled` instead of `end_turn`.
|
|
12
|
+
- **A prompt that is only audio is answered.** A clip with no text or image used
|
|
13
|
+
to end the turn at once with nothing sent to the model, even though the agent
|
|
14
|
+
advertises audio.
|
|
4
15
|
|
|
5
16
|
## 1.6.6
|
|
6
17
|
|
|
@@ -310,7 +310,11 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
310
310
|
conversation); lifecycle and config handlers hold it throughout, and `handle_prompt` holds it
|
|
311
311
|
through a `WorkspaceHold` that it releases while waiting on an HTTP endpoint or a permission
|
|
312
312
|
answer and retakes (reinstalling its session via `resume_workspace`) before any tool runs. An
|
|
313
|
-
on-device turn never releases it. Take the session lock first, never the other way round.
|
|
313
|
+
on-device turn never releases it. Take the session lock first, never the other way round. A turn registers its `PromptCancellation` at
|
|
314
|
+
the top of `handle_prompt`, before it waits on either lock, and a `PromptRegistration`
|
|
315
|
+
guard clears it on every return, so a `session/cancel` that arrives while the turn
|
|
316
|
+
is still queued, switching threads, loading a model or running a slash command ends
|
|
317
|
+
it as `cancelled`. The checks sit after each of those waits. Tool
|
|
314
318
|
execution, subagents included, still runs one session at a time.
|
|
315
319
|
- **`src/instructions.rs`** — project instruction files, the always-on counterpart to skills.
|
|
316
320
|
Reads `AGENTS.md` (the cross-tool [agents.md](https://agents.md) standard) and `CLAUDE.md`,
|
|
@@ -465,6 +465,21 @@ impl PromptCancellation {
|
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
+
/// Removes a turn's cancellation from the agent's registry when the turn ends,
|
|
469
|
+
/// whichever way it returns.
|
|
470
|
+
struct PromptRegistration<'a> {
|
|
471
|
+
agent: &'a SiGitAgent,
|
|
472
|
+
session_id: SessionId,
|
|
473
|
+
cancellation: Arc<PromptCancellation>,
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
impl Drop for PromptRegistration<'_> {
|
|
477
|
+
fn drop(&mut self) {
|
|
478
|
+
self.agent
|
|
479
|
+
.finish_prompt(&self.session_id, &self.cancellation);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
468
483
|
enum DrainTurnError {
|
|
469
484
|
Backend(backend::BackendError),
|
|
470
485
|
Cancelled,
|
|
@@ -3063,10 +3078,31 @@ impl SiGitAgent {
|
|
|
3063
3078
|
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
3064
3079
|
}
|
|
3065
3080
|
|
|
3081
|
+
// Registered before anything that can wait, so a `session/cancel` that
|
|
3082
|
+
// lands while this turn is still queued on the workspace, switching
|
|
3083
|
+
// sessions or loading a model is seen. The session lock is held, so the
|
|
3084
|
+
// slot can only be this turn's. The guard clears it on every return.
|
|
3085
|
+
let cancellation = Arc::new(PromptCancellation::default());
|
|
3086
|
+
self.prompt_cancellations
|
|
3087
|
+
.lock()
|
|
3088
|
+
.unwrap()
|
|
3089
|
+
.insert(session_id.to_string(), Arc::clone(&cancellation));
|
|
3090
|
+
let _registration = PromptRegistration {
|
|
3091
|
+
agent: self,
|
|
3092
|
+
session_id: session_id.clone(),
|
|
3093
|
+
cancellation: Arc::clone(&cancellation),
|
|
3094
|
+
};
|
|
3095
|
+
|
|
3066
3096
|
// Everything below (slash commands included) acts on the live session,
|
|
3067
3097
|
// so it has to be this one. Resource links are read relative to its cwd.
|
|
3068
3098
|
let mut workspace = WorkspaceHold::acquire(&self.workspace_lock).await;
|
|
3099
|
+
if cancellation.cancelled.load(Ordering::Acquire) {
|
|
3100
|
+
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
3101
|
+
}
|
|
3069
3102
|
self.activate_session(&session_id).await?;
|
|
3103
|
+
if cancellation.cancelled.load(Ordering::Acquire) {
|
|
3104
|
+
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
3105
|
+
}
|
|
3070
3106
|
|
|
3071
3107
|
// log every block so we can debug @ references and file context
|
|
3072
3108
|
for (i, block) in args.prompt.iter().enumerate() {
|
|
@@ -3204,7 +3240,7 @@ impl SiGitAgent {
|
|
|
3204
3240
|
|
|
3205
3241
|
let user_text = parts.join("\n");
|
|
3206
3242
|
|
|
3207
|
-
if user_text.trim().is_empty() && images.is_empty() {
|
|
3243
|
+
if user_text.trim().is_empty() && images.is_empty() && audio.is_empty() {
|
|
3208
3244
|
return Ok(PromptResponse::new(StopReason::EndTurn));
|
|
3209
3245
|
}
|
|
3210
3246
|
|
|
@@ -3230,17 +3266,18 @@ impl SiGitAgent {
|
|
|
3230
3266
|
match commands::resolve_command(&command) {
|
|
3231
3267
|
Some(custom) => commands::render(&custom.body, argument.as_deref()),
|
|
3232
3268
|
None => {
|
|
3233
|
-
return
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3269
|
+
return self
|
|
3270
|
+
.run_slash(
|
|
3271
|
+
cx,
|
|
3272
|
+
session_id,
|
|
3273
|
+
SlashCommand::Unknown(command, argument),
|
|
3274
|
+
&cancellation,
|
|
3275
|
+
)
|
|
3276
|
+
.await;
|
|
3240
3277
|
}
|
|
3241
3278
|
}
|
|
3242
3279
|
}
|
|
3243
|
-
Some(command) => return
|
|
3280
|
+
Some(command) => return self.run_slash(cx, session_id, command, &cancellation).await,
|
|
3244
3281
|
None => user_text,
|
|
3245
3282
|
};
|
|
3246
3283
|
|
|
@@ -3267,7 +3304,12 @@ impl SiGitAgent {
|
|
|
3267
3304
|
{
|
|
3268
3305
|
if self.auto_load_local_model {
|
|
3269
3306
|
self.start_startup_model_load_if_needed();
|
|
3270
|
-
|
|
3307
|
+
tokio::select! {
|
|
3308
|
+
ready = self.await_model_ready(cx, &session_id) => ready?,
|
|
3309
|
+
() = cancellation.cancelled() => {
|
|
3310
|
+
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3271
3313
|
} else {
|
|
3272
3314
|
self.send_assistant_message(
|
|
3273
3315
|
cx,
|
|
@@ -3280,11 +3322,9 @@ impl SiGitAgent {
|
|
|
3280
3322
|
}
|
|
3281
3323
|
}
|
|
3282
3324
|
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
.unwrap()
|
|
3287
|
-
.insert(session_id.to_string(), Arc::clone(&cancellation));
|
|
3325
|
+
if cancellation.cancelled.load(Ordering::Acquire) {
|
|
3326
|
+
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
3327
|
+
}
|
|
3288
3328
|
|
|
3289
3329
|
// ── tool-calling loop ────────────────────────────────────────────
|
|
3290
3330
|
// send message → execute any tool calls → feed results back
|
|
@@ -3987,6 +4027,24 @@ impl SiGitAgent {
|
|
|
3987
4027
|
}
|
|
3988
4028
|
}
|
|
3989
4029
|
|
|
4030
|
+
/// Run a built-in slash command as a turn. A `session/cancel` ends it with
|
|
4031
|
+
/// `Cancelled`; only `/compact` and `/load` take long enough to notice.
|
|
4032
|
+
async fn run_slash(
|
|
4033
|
+
&self,
|
|
4034
|
+
cx: &ConnectionTo<Client>,
|
|
4035
|
+
session_id: SessionId,
|
|
4036
|
+
command: SlashCommand,
|
|
4037
|
+
cancellation: &PromptCancellation,
|
|
4038
|
+
) -> agent_client_protocol::Result<PromptResponse> {
|
|
4039
|
+
if cancellation.cancelled.load(Ordering::Acquire) {
|
|
4040
|
+
return Ok(PromptResponse::new(StopReason::Cancelled));
|
|
4041
|
+
}
|
|
4042
|
+
tokio::select! {
|
|
4043
|
+
response = exec_slash_acp(self, cx, session_id, command) => response,
|
|
4044
|
+
() = cancellation.cancelled() => Ok(PromptResponse::new(StopReason::Cancelled)),
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
|
|
3990
4048
|
fn finish_prompt(&self, session_id: &SessionId, cancellation: &Arc<PromptCancellation>) {
|
|
3991
4049
|
let key = session_id.to_string();
|
|
3992
4050
|
let mut active = self.prompt_cancellations.lock().unwrap();
|
|
@@ -6406,6 +6464,71 @@ mod tests {
|
|
|
6406
6464
|
assert!(agent.active_session.lock().unwrap().is_none());
|
|
6407
6465
|
}
|
|
6408
6466
|
|
|
6467
|
+
#[tokio::test]
|
|
6468
|
+
async fn a_turn_leaves_no_cancellation_behind_however_it_returns() {
|
|
6469
|
+
let agent = SiGitAgent::new(
|
|
6470
|
+
Arc::new(ChatEngine::new()),
|
|
6471
|
+
default_local_model_config(),
|
|
6472
|
+
Arc::new(AtomicBool::new(true)),
|
|
6473
|
+
Arc::new(AtomicBool::new(false)),
|
|
6474
|
+
Arc::new(std::sync::Mutex::new(None)),
|
|
6475
|
+
false,
|
|
6476
|
+
false,
|
|
6477
|
+
);
|
|
6478
|
+
let session_id = SessionId::new("early");
|
|
6479
|
+
let turn = Arc::new(PromptCancellation::default());
|
|
6480
|
+
agent
|
|
6481
|
+
.prompt_cancellations
|
|
6482
|
+
.lock()
|
|
6483
|
+
.unwrap()
|
|
6484
|
+
.insert("early".into(), Arc::clone(&turn));
|
|
6485
|
+
let registration = PromptRegistration {
|
|
6486
|
+
agent: &agent,
|
|
6487
|
+
session_id: session_id.clone(),
|
|
6488
|
+
cancellation: Arc::clone(&turn),
|
|
6489
|
+
};
|
|
6490
|
+
|
|
6491
|
+
// A cancel that arrives before the turn reaches inference is recorded
|
|
6492
|
+
// and stays visible to every check the turn makes afterwards.
|
|
6493
|
+
agent
|
|
6494
|
+
.handle_cancel(CancelNotification::new(session_id.clone()))
|
|
6495
|
+
.await
|
|
6496
|
+
.unwrap();
|
|
6497
|
+
assert!(turn.cancelled.load(Ordering::Acquire));
|
|
6498
|
+
tokio::time::timeout(std::time::Duration::from_millis(50), turn.cancelled())
|
|
6499
|
+
.await
|
|
6500
|
+
.expect("a pre-cancelled turn must resolve at once");
|
|
6501
|
+
|
|
6502
|
+
drop(registration);
|
|
6503
|
+
assert!(agent.prompt_cancellations.lock().unwrap().is_empty());
|
|
6504
|
+
}
|
|
6505
|
+
|
|
6506
|
+
#[tokio::test]
|
|
6507
|
+
async fn a_finished_turn_does_not_remove_its_successors_cancellation() {
|
|
6508
|
+
let agent = SiGitAgent::new(
|
|
6509
|
+
Arc::new(ChatEngine::new()),
|
|
6510
|
+
default_local_model_config(),
|
|
6511
|
+
Arc::new(AtomicBool::new(true)),
|
|
6512
|
+
Arc::new(AtomicBool::new(false)),
|
|
6513
|
+
Arc::new(std::sync::Mutex::new(None)),
|
|
6514
|
+
false,
|
|
6515
|
+
false,
|
|
6516
|
+
);
|
|
6517
|
+
let old = Arc::new(PromptCancellation::default());
|
|
6518
|
+
let new = Arc::new(PromptCancellation::default());
|
|
6519
|
+
agent
|
|
6520
|
+
.prompt_cancellations
|
|
6521
|
+
.lock()
|
|
6522
|
+
.unwrap()
|
|
6523
|
+
.insert("s".into(), Arc::clone(&new));
|
|
6524
|
+
drop(PromptRegistration {
|
|
6525
|
+
agent: &agent,
|
|
6526
|
+
session_id: SessionId::new("s"),
|
|
6527
|
+
cancellation: old,
|
|
6528
|
+
});
|
|
6529
|
+
assert!(agent.prompt_cancellations.lock().unwrap().contains_key("s"));
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6409
6532
|
#[tokio::test]
|
|
6410
6533
|
async fn cancel_signals_only_the_matching_active_prompt() {
|
|
6411
6534
|
let agent = SiGitAgent::new(
|
|
@@ -308,3 +308,48 @@ fn a_cloud_tier_gets_the_text_and_the_user_is_told() {
|
|
|
308
308
|
"the user must be told the clip was left out: {updates}"
|
|
309
309
|
);
|
|
310
310
|
}
|
|
311
|
+
|
|
312
|
+
#[test]
|
|
313
|
+
fn an_audio_only_prompt_reaches_the_endpoint() {
|
|
314
|
+
let endpoint = start_fake_endpoint(vec![sse_text("heard it")]);
|
|
315
|
+
let scratch = std::env::temp_dir().join(format!("sigit_acp_audio_only_{}", std::process::id()));
|
|
316
|
+
let config_dir = scratch.join("config");
|
|
317
|
+
let project = scratch.join("project");
|
|
318
|
+
std::fs::create_dir_all(&config_dir).unwrap();
|
|
319
|
+
std::fs::create_dir_all(&project).unwrap();
|
|
320
|
+
|
|
321
|
+
let mut agent = spawn_agent(endpoint.port, &config_dir, "scripted-audio-model");
|
|
322
|
+
let id = agent.request(
|
|
323
|
+
"initialize",
|
|
324
|
+
json!({"protocolVersion": 1, "clientCapabilities": {}}),
|
|
325
|
+
);
|
|
326
|
+
agent.wait_for_response(id);
|
|
327
|
+
let id = agent.request("session/new", json!({"cwd": project, "mcpServers": []}));
|
|
328
|
+
let session_id = agent.wait_for_response(id)["result"]["sessionId"]
|
|
329
|
+
.as_str()
|
|
330
|
+
.expect("session id")
|
|
331
|
+
.to_string();
|
|
332
|
+
|
|
333
|
+
let id = agent.request(
|
|
334
|
+
"session/prompt",
|
|
335
|
+
json!({
|
|
336
|
+
"sessionId": session_id,
|
|
337
|
+
"prompt": [{"type": "audio", "mimeType": "audio/wav", "data": CLIP}],
|
|
338
|
+
}),
|
|
339
|
+
);
|
|
340
|
+
let response = agent.wait_for_response(id);
|
|
341
|
+
assert_eq!(response["result"]["stopReason"], "end_turn");
|
|
342
|
+
|
|
343
|
+
let requests = endpoint.requests.lock().unwrap();
|
|
344
|
+
let request = requests
|
|
345
|
+
.first()
|
|
346
|
+
.expect("a clip with no text is still a prompt, so the endpoint must see it");
|
|
347
|
+
assert!(
|
|
348
|
+
request.to_string().contains(CLIP),
|
|
349
|
+
"the clip must reach the endpoint: {request}"
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
drop(requests);
|
|
353
|
+
drop(agent);
|
|
354
|
+
let _ = std::fs::remove_dir_all(&scratch);
|
|
355
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sigit_code-1.6.6 → sigit_code-1.6.7}/packaging/winget/getSigit.siGitCode.locale.en-US.yaml.in
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|