sigit-code 1.7.4__tar.gz → 1.7.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.
Files changed (65) hide show
  1. {sigit_code-1.7.4 → sigit_code-1.7.6}/Cargo.lock +2 -2
  2. {sigit_code-1.7.4 → sigit_code-1.7.6}/Cargo.toml +2 -2
  3. {sigit_code-1.7.4 → sigit_code-1.7.6}/PKG-INFO +1 -1
  4. sigit_code-1.7.6/crates/cli/README.md +90 -0
  5. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/account.rs +4 -39
  6. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/backend.rs +27 -3
  7. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/chat.rs +27 -6
  8. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/headless.rs +9 -6
  9. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/main.rs +502 -130
  10. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/permissions.rs +3 -1
  11. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/provider.rs +11 -1
  12. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/tools.rs +350 -11
  13. sigit_code-1.7.6/crates/cli/tests/acp_cloud_reauth.rs +208 -0
  14. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_logout.rs +71 -0
  15. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_permissions.rs +73 -1
  16. sigit_code-1.7.4/crates/cli/README.md +0 -234
  17. {sigit_code-1.7.4 → sigit_code-1.7.6}/README.md +0 -0
  18. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/Cargo.toml +0 -0
  19. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/client_fs.rs +0 -0
  20. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/client_terminal.rs +0 -0
  21. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/commands.rs +0 -0
  22. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/frontmatter.rs +0 -0
  23. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/harness_markup.rs +0 -0
  24. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/hooks.rs +0 -0
  25. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/inline_tool_calls.rs +0 -0
  26. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/instructions.rs +0 -0
  27. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/mcp.rs +0 -0
  28. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/models.rs +0 -0
  29. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/program_status.rs +0 -0
  30. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/repetition.rs +0 -0
  31. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/session_store.rs +0 -0
  32. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/settings.rs +0 -0
  33. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/setup.rs +0 -0
  34. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/skills.rs +0 -0
  35. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/subagents.rs +0 -0
  36. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/src/workspace.rs +0 -0
  37. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_audio.rs +0 -0
  38. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_client_fs.rs +0 -0
  39. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_client_terminal.rs +0 -0
  40. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_concurrent_sessions.rs +0 -0
  41. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_elicitation.rs +0 -0
  42. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_embedded_context.rs +0 -0
  43. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_endpoint_errors.rs +0 -0
  44. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_error_codes.rs +0 -0
  45. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_harness_markup.rs +0 -0
  46. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_images.rs +0 -0
  47. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_multi_root.rs +0 -0
  48. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_session_list.rs +0 -0
  49. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_session_load.rs +0 -0
  50. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_stop_reasons.rs +0 -0
  51. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_tool_call_name.rs +0 -0
  52. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/acp_tool_stdin.rs +0 -0
  53. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/headless_mode.rs +0 -0
  54. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/cli/tests/version_flag.rs +0 -0
  55. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/Cargo.toml +0 -0
  56. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/README.md +0 -0
  57. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/assets/sign-in-logo.png +0 -0
  58. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/auth.rs +0 -0
  59. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/browser_auth.rs +0 -0
  60. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/credentials.rs +0 -0
  61. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/lib.rs +0 -0
  62. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/profile.rs +0 -0
  63. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/src/prompt.rs +0 -0
  64. {sigit_code-1.7.4 → sigit_code-1.7.6}/crates/sigit-agent/tests/embedded.rs +0 -0
  65. {sigit_code-1.7.4 → sigit_code-1.7.6}/pyproject.toml +0 -0
@@ -5945,7 +5945,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
5945
5945
 
5946
5946
  [[package]]
5947
5947
  name = "sigit"
5948
- version = "1.7.4"
5948
+ version = "1.7.6"
5949
5949
  dependencies = [
5950
5950
  "agent-client-protocol",
5951
5951
  "anyhow",
@@ -5976,7 +5976,7 @@ dependencies = [
5976
5976
 
5977
5977
  [[package]]
5978
5978
  name = "sigit-agent"
5979
- version = "1.7.4"
5979
+ version = "1.7.6"
5980
5980
  dependencies = [
5981
5981
  "agent-client-protocol",
5982
5982
  "anyhow",
@@ -3,7 +3,7 @@ resolver = "3"
3
3
  members = ["crates/cli", "crates/sigit-*"]
4
4
 
5
5
  [workspace.package]
6
- version = "1.7.4"
6
+ version = "1.7.6"
7
7
  edition = "2024"
8
8
  license = "Apache-2.0"
9
9
  repository = "https://github.com/getsigit/sigit"
@@ -16,7 +16,7 @@ authors = ["Seto Elkahfi <seto@sigit.si>", "paydii <193906237+paydii@users.norep
16
16
  # crates.io, so this resolves from the registry rather than the onde-ed checkout next door.
17
17
  ed-acp = { version = "1.3.0", default-features = false }
18
18
  ed-acp-testkit = "1.3.0"
19
- sigit-agent = { version = "1.7.4", default-features = false, path = "crates/sigit-agent" }
19
+ sigit-agent = { version = "1.7.6", default-features = false, path = "crates/sigit-agent" }
20
20
 
21
21
  # ACP protocol SDK
22
22
  agent-client-protocol = { version = "2.2", features = ["unstable_session_fork"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sigit-code
3
- Version: 1.7.4
3
+ Version: 1.7.6
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -0,0 +1,90 @@
1
+ <p align="center">
2
+ <img src="docs/assets/logo.png" alt="siGit Code" width="96">
3
+ </p>
4
+
5
+ <h1 align="center">siGit Code</h1>
6
+
7
+ <p align="center"><strong>The coding agent that runs where your code lives.</strong></p>
8
+ <p align="center">A modular on-device inference LLM coding agent. Core component of siGit Factory.</p>
9
+
10
+ <p align="center">
11
+ <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>
12
+ <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>
13
+ <a href="https://www.npmjs.com/package/@getsigit/sigit"><img src="https://img.shields.io/npm/v/@getsigit/sigit?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
14
+ <a href="https://snapcraft.io/sigit"><img src="https://snapcraft.io/sigit/badge.svg" alt="sigit"></a>
15
+ <a href="https://sigit.si/code"><img src="https://img.shields.io/badge/sigit.si%2Fcode-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
16
+ <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>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://www.nuget.org/packages/SiGit.Code"><img src="https://img.shields.io/nuget/v/SiGit.Code?style=flat-square&labelColor=17211D&color=235843&label=nuget" alt="NuGet"></a>
21
+ <a href="https://github.com/microsoft/winget-pkgs/tree/master/manifests/g/getSigit/siGitCode"><img src="https://img.shields.io/winget/v/getSigit.siGitCode?style=flat-square&labelColor=17211D&color=235843" alt="winget"></a>
22
+ <a href="https://marketplace.visualstudio.com/items?itemName=getsigit.sigit-code"><img src="https://img.shields.io/badge/VS%20Code-Marketplace-235843?style=flat-square&labelColor=17211D" alt="VS Code Marketplace"></a>
23
+ <a href="https://pypi.org/project/sigit-code/"><img src="https://img.shields.io/pypi/dm/sigit-code?style=flat-square&labelColor=17211D&color=235843&label=pypi%20downloads" alt="PyPI downloads"></a>
24
+ <a href="https://github.com/getsigit/sigit/releases"><img src="https://img.shields.io/github/v/release/getsigit/sigit?style=flat-square&labelColor=17211D&color=235843" alt="Release"></a>
25
+ <a href="https://github.com/getsigit/sigit/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/getsigit/sigit/ci.yml?style=flat-square&labelColor=17211D&label=ci" alt="CI"></a>
26
+ <a href="https://github.com/getsigit/sigit/releases"><img src="https://img.shields.io/github/downloads/getsigit/sigit/total?style=flat-square&labelColor=17211D&color=235843" alt="GitHub downloads"></a>
27
+ </p>
28
+
29
+ siGit Code runs on your machine and works in any codebase. Inference runs on-device by default through the [Onde Inference on-device inference SDK](https://ondeinference.com/sdk), or on siGit Code Cloud when you choose it. You need no API key to start, and it works with any editor that speaks the [Agent Client Protocol](https://agentclientprotocol.com). The agent is Apache-2.0. siGit Code Cloud and [siGit Factory](https://factory.sigit.si/) are the hosted, paid side.
30
+
31
+ ## Install
32
+
33
+ ```sh
34
+ cargo install sigit
35
+ brew tap getsigit/tap && brew trust --tap getsigit/tap && brew install sigit
36
+ npm install -g @getsigit/sigit
37
+ ```
38
+
39
+ More ways, including pip, NuGet, winget, Scoop and Linux packages, are in [docs/install.md](docs/install.md).
40
+
41
+ ## Get siGit anywhere
42
+
43
+ The command-line agent and the desktop and mobile app are separate products. Each cell links to where it ships.
44
+
45
+ | Desktop and mobile apps | macOS | Windows | Linux | iOS | Android |
46
+ |---|:-:|:-:|:-:|:-:|:-:|
47
+ | [App Store](https://apps.apple.com/app/id6753018849) | [✓](https://apps.apple.com/app/id6753018849) | | | [✓](https://apps.apple.com/app/id6753018849) | |
48
+ | [Google Play](https://play.google.com/store/apps/details?id=xyz.smbcloud.SiGit) | | | | | [✓](https://play.google.com/store/apps/details?id=xyz.smbcloud.SiGit) |
49
+ | [Microsoft Store](https://apps.microsoft.com/detail/9p69ph1k7nxx) | | [✓](https://apps.microsoft.com/detail/9p69ph1k7nxx) | | | |
50
+ | [Snap Store](https://snapcraft.io/sigit) | | | [✓](https://snapcraft.io/sigit) | | |
51
+ | [Direct download](https://getsigit.5mb.app/download) | [✓](https://getsigit.5mb.app/download) | [✓](https://getsigit.5mb.app/download) | [✓](https://getsigit.5mb.app/download) | | |
52
+
53
+ | Command line | macOS | Windows | Linux |
54
+ |---|:-:|:-:|:-:|
55
+ | [crates.io](https://crates.io/crates/sigit) | ✓ | ✓ | ✓ |
56
+ | [Homebrew](docs/install.md) | ✓ | | |
57
+ | [npm](https://www.npmjs.com/package/@getsigit/sigit) | ✓ | ✓ | ✓ |
58
+ | [PyPI and uv](https://pypi.org/project/sigit-code/) | ✓ | ✓ | ✓ |
59
+ | [NuGet](https://www.nuget.org/packages/SiGit.Code) | ✓ | ✓ | ✓ |
60
+ | [winget](docs/install.md) | | ✓ | |
61
+ | [Scoop](https://github.com/getsigit/scoop-bucket) | | ✓ | |
62
+ | [deb and rpm](https://github.com/getsigit/sigit/releases) | | | ✓ |
63
+
64
+ `sudo snap install sigit` installs the desktop app, not the terminal agent. The app currently uses siGit Code Cloud for inference, while the command line runs models on-device. Details are in [docs/distribution.md](docs/distribution.md).
65
+
66
+ Every channel, kept current: https://getsigit.5mb.app/
67
+
68
+ ## Use it your way
69
+
70
+ - **In your editor.** Any ACP client starts `sigit --acp`. See [ACP support](docs/acp.md).
71
+ - **In the terminal.** Run `sigit` for a full-screen chat UI. See [terminal mode](docs/terminal.md).
72
+ - **In scripts and CI.** `sigit run "<prompt>"` gives you JSONL events and exit codes. See [headless mode](docs/headless.md).
73
+
74
+ Setup guides for Zed, Xcode, VS Code and the JetBrains IDEs are in [docs/editors.md](docs/editors.md).
75
+
76
+ ## Docs
77
+
78
+ [Install](docs/install.md), [editors](docs/editors.md), [ACP](docs/acp.md), [terminal](docs/terminal.md), [headless](docs/headless.md), [hooks](docs/hooks.md), [MCP](docs/mcp.md), [telemetry](docs/telemetry.md), [distribution](docs/distribution.md). The index is [docs/README.md](docs/README.md).
79
+
80
+ ## Contributing
81
+
82
+ Issues and pull requests are welcome. Open one against `development`.
83
+
84
+ ## License
85
+
86
+ [Apache 2.0](https://github.com/getsigit/sigit/blob/main/LICENSE)
87
+
88
+ ## Copyright
89
+
90
+ © 2026 [siGit Code & Deploy](https://sigit.si).
@@ -27,7 +27,7 @@ fn api_base() -> String {
27
27
  // `serde_json::Value` rather than a struct because of the bare-string variant.
28
28
 
29
29
  #[derive(Debug, Deserialize)]
30
- struct MeResponse {
30
+ struct UserResponse {
31
31
  #[serde(default)]
32
32
  email: Option<String>,
33
33
  }
@@ -90,40 +90,6 @@ pub async fn authenticate(email: &str, password: &str) -> Result<String, String>
90
90
  Err(format!("sign-in failed: {message}"))
91
91
  }
92
92
 
93
- /// Verify that a usable session exists, confirming the stored token against the
94
- /// account API. Returns the signed-in email on success, or a human-readable
95
- /// reason it is not usable. Used by the ACP `authenticate` handler to answer the
96
- /// editor's auth gate.
97
- pub async fn verify_session() -> Result<String, String> {
98
- let Some(creds) = credentials::load() else {
99
- return Err("not signed in".to_string());
100
- };
101
-
102
- let url = format!("{}/api/v1/me", api_base().trim_end_matches('/'));
103
- let response = reqwest::Client::new()
104
- .get(&url)
105
- .bearer_auth(&creds.access_token)
106
- .send()
107
- .await
108
- .map_err(|error| format!("could not reach siGit Code Cloud: {error}"))?;
109
-
110
- if response.status().is_success() {
111
- let email = response
112
- .json::<MeResponse>()
113
- .await
114
- .ok()
115
- .and_then(|me| me.email)
116
- .or(creds.email)
117
- .unwrap_or_else(|| "(unknown)".to_string());
118
- Ok(email)
119
- } else {
120
- Err(format!(
121
- "session expired (HTTP {})",
122
- response.status().as_u16()
123
- ))
124
- }
125
- }
126
-
127
93
  /// Run an interactive sign-in against the terminal, prompting for email and a
128
94
  /// hidden password. Used by `sigit login`, which the editor launches in an
129
95
  /// embedded terminal for ACP terminal-based authentication. Returns the signed-in
@@ -166,11 +132,10 @@ pub async fn end_session() -> String {
166
132
  /// One-line description of the current session, verifying the token if reachable.
167
133
  pub async fn status_line() -> String {
168
134
  let Some(creds) = credentials::load() else {
169
- return "Not signed in. Use `/login <email> <password>` to use siGit Code Cloud."
170
- .to_string();
135
+ return "Not signed in. Use `/login` to use siGit Code Cloud.".to_string();
171
136
  };
172
137
 
173
- let url = format!("{}/api/v1/me", api_base().trim_end_matches('/'));
138
+ let url = format!("{}/api/v1/user", api_base().trim_end_matches('/'));
174
139
  match reqwest::Client::new()
175
140
  .get(&url)
176
141
  .bearer_auth(&creds.access_token)
@@ -179,7 +144,7 @@ pub async fn status_line() -> String {
179
144
  {
180
145
  Ok(response) if response.status().is_success() => {
181
146
  let email = response
182
- .json::<MeResponse>()
147
+ .json::<UserResponse>()
183
148
  .await
184
149
  .ok()
185
150
  .and_then(|me| me.email)
@@ -951,6 +951,9 @@ fn onde_result_to_turn(result: onde::inference::ToolAwareResult) -> TurnResult {
951
951
  pub struct OpenAiBackend {
952
952
  base_url: String,
953
953
  api_key: String,
954
+ /// Read the bearer from the stored session on each request instead of
955
+ /// using `api_key`; see `bearer`.
956
+ session_token: bool,
954
957
  model: String,
955
958
  http: reqwest::Client,
956
959
  /// The full message list sent on each request (system + turns + tool results).
@@ -985,6 +988,7 @@ impl OpenAiBackend {
985
988
  Self {
986
989
  base_url: base_url.into(),
987
990
  api_key: api_key.into(),
991
+ session_token: false,
988
992
  accepts_images: crate::provider::model_accepts_images(&model),
989
993
  accepts_audio: crate::provider::model_accepts_audio(&model),
990
994
  model,
@@ -994,6 +998,25 @@ impl OpenAiBackend {
994
998
  }
995
999
  }
996
1000
 
1001
+ /// Have the backend send the stored siGit Code Cloud session token as its
1002
+ /// bearer, read on every request. A token captured at build time goes
1003
+ /// stale when the user signs in as someone else; `api_key` is then only
1004
+ /// the fallback for a signed-out request.
1005
+ pub fn with_session_token(mut self, on: bool) -> Self {
1006
+ self.session_token = on;
1007
+ self
1008
+ }
1009
+
1010
+ /// The bearer for the next request.
1011
+ fn bearer(&self) -> String {
1012
+ if self.session_token
1013
+ && let Some(token) = crate::credentials::load_token()
1014
+ {
1015
+ return token;
1016
+ }
1017
+ self.api_key.clone()
1018
+ }
1019
+
997
1020
  fn tools_json(tools: &[ToolSpec]) -> Vec<serde_json::Value> {
998
1021
  tools
999
1022
  .iter()
@@ -1122,7 +1145,7 @@ impl OpenAiBackend {
1122
1145
  let mut response = self
1123
1146
  .http
1124
1147
  .post(&url)
1125
- .bearer_auth(&self.api_key)
1148
+ .bearer_auth(self.bearer())
1126
1149
  .json(&body)
1127
1150
  .send()
1128
1151
  .await
@@ -1144,7 +1167,7 @@ impl OpenAiBackend {
1144
1167
  response = self
1145
1168
  .http
1146
1169
  .post(&url)
1147
- .bearer_auth(&self.api_key)
1170
+ .bearer_auth(self.bearer())
1148
1171
  .json(&body)
1149
1172
  .send()
1150
1173
  .await
@@ -1193,7 +1216,7 @@ impl OpenAiBackend {
1193
1216
  let response = self
1194
1217
  .http
1195
1218
  .post(&url)
1196
- .bearer_auth(&self.api_key)
1219
+ .bearer_auth(self.bearer())
1197
1220
  .json(&body)
1198
1221
  .send()
1199
1222
  .await
@@ -1826,6 +1849,7 @@ impl InferenceBackend for OpenAiBackend {
1826
1849
  Some(Arc::new(Self {
1827
1850
  base_url: self.base_url.clone(),
1828
1851
  api_key: self.api_key.clone(),
1852
+ session_token: self.session_token,
1829
1853
  model: self.model.clone(),
1830
1854
  // The client is a handle on one connection pool; sharing it keeps
1831
1855
  // connections to the endpoint warm across sessions.
@@ -167,6 +167,13 @@ pub(crate) fn tool_title(name: &str, arguments_json: &str) -> String {
167
167
  str_arg("path")
168
168
  }
169
169
  "search_files" | "glob" => str_arg("pattern"),
170
+ "command_output" | "monitor_command" | "kill_command" => {
171
+ let id = args.as_ref().and_then(|a| a.get("task_id")?.as_u64());
172
+ id.map(|id| match crate::tools::background_task_command(id) {
173
+ Some(command) => format!("task {id} (`{command}`)"),
174
+ None => format!("task {id}"),
175
+ })
176
+ }
170
177
  _ => None,
171
178
  };
172
179
  (name.to_string(), summary)
@@ -3013,12 +3020,15 @@ mod tui {
3013
3020
  let system_prompt = crate::with_launch_context(
3014
3021
  &crate::system_prompt_for_model(true),
3015
3022
  );
3016
- app.backend = Arc::new(OpenAiBackend::new(
3017
- provider.base_url,
3018
- provider.api_key,
3019
- provider.model,
3020
- Some(system_prompt),
3021
- ));
3023
+ app.backend = Arc::new(
3024
+ OpenAiBackend::new(
3025
+ provider.base_url,
3026
+ provider.api_key,
3027
+ provider.model,
3028
+ Some(system_prompt),
3029
+ )
3030
+ .with_session_token(provider.session_token),
3031
+ );
3022
3032
  app.current_model_name = provider.display_name.clone();
3023
3033
  app.tool_calling = true;
3024
3034
  // Selecting a cloud tier puts us in cloud mode.
@@ -4142,6 +4152,17 @@ mod tests {
4142
4152
  );
4143
4153
  }
4144
4154
 
4155
+ #[test]
4156
+ fn tool_title_task_tools_name_the_task() {
4157
+ for name in ["command_output", "monitor_command", "kill_command"] {
4158
+ assert_eq!(
4159
+ tool_title(name, r#"{"task_id":999999}"#),
4160
+ format!("{name} · task 999999")
4161
+ );
4162
+ }
4163
+ assert_eq!(tool_title("monitor_command", "{}"), "monitor_command");
4164
+ }
4165
+
4145
4166
  #[test]
4146
4167
  fn tool_title_file_tools_show_the_path() {
4147
4168
  for name in [
@@ -349,12 +349,15 @@ pub async fn run(config: HeadlessConfig) -> i32 {
349
349
  &crate::workspace::additional_roots(),
350
350
  ));
351
351
 
352
- let backend: Arc<dyn InferenceBackend> = Arc::new(OpenAiBackend::new(
353
- cfg.base_url,
354
- cfg.api_key,
355
- cfg.model.clone(),
356
- Some(system_prompt),
357
- ));
352
+ let backend: Arc<dyn InferenceBackend> = Arc::new(
353
+ OpenAiBackend::new(
354
+ cfg.base_url,
355
+ cfg.api_key,
356
+ cfg.model.clone(),
357
+ Some(system_prompt),
358
+ )
359
+ .with_session_token(cfg.session_token),
360
+ );
358
361
 
359
362
  if config.resume {
360
363
  let Some(history) = session_store::load(&config.session_id) else {