Skip to content

Commit 2af5ee6

Browse files
committed
chore: fix conflict with upstream
2 parents 4956741 + d4e9350 commit 2af5ee6

Some content is hidden

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

42 files changed

+2549
-776
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build-scripts/build.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ def build_macos_desktop_app(
248248

249249
info("Building tauri config")
250250
tauri_config_path = pathlib.Path(DESKTOP_PACKAGE_PATH) / "build-config.json"
251-
tauri_config_path.write_text(macos_tauri_config(cli_path=cli_path, chat_path=chat_path, pty_path=pty_path, target=target))
251+
tauri_config_path.write_text(
252+
macos_tauri_config(cli_path=cli_path, chat_path=chat_path, pty_path=pty_path, target=target)
253+
)
252254

253255
info("Building", DESKTOP_PACKAGE_NAME)
254256

@@ -394,13 +396,14 @@ def sign_and_rebundle_macos(app_path: pathlib.Path, dmg_path: pathlib.Path, sign
394396
info("Done signing!!")
395397

396398

397-
def build_linux_minimal(cli_path: pathlib.Path, pty_path: pathlib.Path):
399+
def build_linux_minimal(cli_path: pathlib.Path, pty_path: pathlib.Path, chat_path: pathlib.Path):
398400
"""
399401
Creates tar.gz, tar.xz, tar.zst, and zip archives under `BUILD_DIR`.
400402
401403
Each archive has the following structure:
402404
- archive/bin/q
403405
- archive/bin/qterm
406+
- archive/bin/qchat
404407
- archive/install.sh
405408
- archive/README
406409
- archive/BUILD-INFO
@@ -431,6 +434,7 @@ def build_linux_minimal(cli_path: pathlib.Path, pty_path: pathlib.Path):
431434

432435
shutil.copy2(cli_path, archive_bin_path / CLI_BINARY_NAME)
433436
shutil.copy2(pty_path, archive_bin_path / PTY_BINARY_NAME)
437+
shutil.copy2(chat_path, archive_bin_path / CHAT_BINARY_NAME)
434438

435439
signer = load_gpg_signer()
436440

@@ -708,7 +712,7 @@ def copy_extension(extension_uuid, extension_dir_name):
708712
cwd=DESKTOP_PACKAGE_PATH,
709713
env={**os.environ, **rust_env(release=release, variant=Variant.FULL), "BUILD_DIR": BUILD_DIR},
710714
)
711-
desktop_path = pathlib.Path(f'target/{target}/{"release" if release else "debug"}/{DESKTOP_BINARY_NAME}')
715+
desktop_path = pathlib.Path(f"target/{target}/{'release' if release else 'debug'}/{DESKTOP_BINARY_NAME}")
712716

713717
deb_resources = LinuxDebResources(
714718
cli_path=cli_path,
@@ -732,7 +736,7 @@ def copy_extension(extension_uuid, extension_dir_name):
732736
# Determine architecture suffix based on the target triple
733737
arch_suffix = "aarch64" if "aarch64" in target else "amd64"
734738
info(f"Using architecture suffix: {arch_suffix} for target: {target}")
735-
739+
736740
bundle_name = f"{tauri_product_name()}_{version()}_{arch_suffix}"
737741
target_subdir = "release" if release else "debug"
738742
bundle_grandparent_path = f"target/{target}/{target_subdir}/bundle"
@@ -917,7 +921,7 @@ def build(
917921
)
918922
build_output[variant] = BinaryPaths(cli_path=cli_path, pty_path=pty_path)
919923
else:
920-
build_linux_minimal(cli_path=cli_path, pty_path=pty_path)
924+
build_linux_minimal(cli_path=cli_path, pty_path=pty_path, chat_path=chat_path)
921925
build_output[variant] = BinaryPaths(cli_path=cli_path, pty_path=pty_path)
922926

923927
return build_output

build-scripts/signing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def cd_signer_request(method: str, path: str, data: str | None = None):
5757
response = requests.request(method=method, url=url, headers=dict(request.headers), data=data)
5858
info(f"CDSigner Request ({url}): {response.status_code}")
5959
if response.status_code == 429:
60-
warn(f"Too many requests, backing off for {2 ** i} seconds")
60+
warn(f"Too many requests, backing off for {2**i} seconds")
6161
time.sleep(2**i)
6262
continue
6363
return response

crates/chat-cli/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ bstr = "1.12.0"
4545
bytes = "1.10.1"
4646
camino = { version = "1.1.3", features = ["serde1"] }
4747
cfg-if = "1.0.0"
48-
chrono = { version = "0.4.41", default-features = false, features = ["std"] }
4948
clap = { version = "4.5.32", features = [
5049
"deprecated",
5150
"derive",

crates/chat-cli/src/api_client/clients/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl Client {
5555
.http_client(crate::aws_common::http_client::client())
5656
.interceptor(OptOutInterceptor::new(database))
5757
.interceptor(UserAgentOverrideInterceptor::new())
58-
.bearer_token_resolver(BearerResolver::new(database).await?)
58+
.bearer_token_resolver(BearerResolver)
5959
.app_name(app_name())
6060
.endpoint_url(endpoint.url())
6161
.build();

crates/chat-cli/src/api_client/clients/streaming_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl StreamingClient {
9090
.http_client(crate::aws_common::http_client::client())
9191
.interceptor(OptOutInterceptor::new(database))
9292
.interceptor(UserAgentOverrideInterceptor::new())
93-
.bearer_token_resolver(BearerResolver::new(database).await?)
93+
.bearer_token_resolver(BearerResolver)
9494
.app_name(app_name())
9595
.endpoint_url(endpoint.url())
9696
.stalled_stream_protection(stalled_stream_protection_config())

crates/chat-cli/src/auth/builder_id.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -518,17 +518,7 @@ pub async fn logout(database: &mut Database) -> Result<(), AuthError> {
518518
}
519519

520520
#[derive(Debug, Clone)]
521-
pub struct BearerResolver {
522-
token: Option<BuilderIdToken>,
523-
}
524-
525-
impl BearerResolver {
526-
pub async fn new(database: &mut Database) -> Result<Self, AuthError> {
527-
Ok(Self {
528-
token: BuilderIdToken::load(database).await?,
529-
})
530-
}
531-
}
521+
pub struct BearerResolver;
532522

533523
impl ResolveIdentity for BearerResolver {
534524
fn resolve_identity<'a>(
@@ -537,7 +527,8 @@ impl ResolveIdentity for BearerResolver {
537527
_config_bag: &'a ConfigBag,
538528
) -> IdentityFuture<'a> {
539529
IdentityFuture::new_boxed(Box::pin(async {
540-
match &self.token {
530+
let database = Database::new().await?;
531+
match BuilderIdToken::load(&database).await? {
541532
Some(token) => Ok(Identity::new(
542533
Token::new(token.access_token.0.clone(), Some(token.expires_at.into())),
543534
Some(token.expires_at.into()),

crates/chat-cli/src/cli/chat/cli.rs

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
use clap::Parser;
1+
use std::collections::HashMap;
2+
3+
use clap::{
4+
Args,
5+
Parser,
6+
Subcommand,
7+
ValueEnum,
8+
};
29

310
#[derive(Debug, Clone, PartialEq, Eq, Default, Parser)]
411
pub struct Chat {
@@ -10,6 +17,9 @@ pub struct Chat {
1017
/// prompt requests permissions to use a tool, unless --trust-all-tools is also used.
1118
#[arg(long)]
1219
pub no_interactive: bool,
20+
/// Resumes the previous conversation from this directory.
21+
#[arg(short, long)]
22+
pub resume: bool,
1323
/// The first question to ask
1424
pub input: Option<String>,
1525
/// Context profile to use
@@ -23,3 +33,127 @@ pub struct Chat {
2333
#[arg(long, value_delimiter = ',', value_name = "TOOL_NAMES")]
2434
pub trust_tools: Option<Vec<String>>,
2535
}
36+
37+
#[derive(Debug, Clone, PartialEq, Eq, Subcommand)]
38+
pub enum Mcp {
39+
/// Add or replace a configured server
40+
Add(McpAdd),
41+
/// Remove a server from the MCP configuration
42+
#[command(alias = "rm")]
43+
Remove(McpRemove),
44+
/// List configured servers
45+
List(McpList),
46+
/// Import a server configuration from another file
47+
Import(McpImport),
48+
/// Get the status of a configured server
49+
Status {
50+
#[arg(long)]
51+
name: String,
52+
},
53+
}
54+
55+
#[derive(Debug, Clone, PartialEq, Eq, Args)]
56+
pub struct McpAdd {
57+
/// Name for the server
58+
#[arg(long)]
59+
pub name: String,
60+
/// The command used to launch the server
61+
#[arg(long)]
62+
pub command: String,
63+
/// Where to add the server to. For profile scope, the name of the profile must specified with
64+
/// --profile.
65+
#[arg(long, value_enum)]
66+
pub scope: Option<Scope>,
67+
/// Name of the profile to add the server config to. Not compatible with workspace scope or
68+
/// global scope.
69+
#[arg(long)]
70+
pub profile: Option<String>,
71+
/// Environment variables to use when launching the server
72+
#[arg(long, value_parser = parse_env_vars)]
73+
pub env: Vec<HashMap<String, String>>,
74+
/// Server launch timeout, in milliseconds
75+
#[arg(long)]
76+
pub timeout: Option<u64>,
77+
/// Overwrite an existing server with the same name
78+
#[arg(long, default_value_t = false)]
79+
pub force: bool,
80+
}
81+
82+
#[derive(Debug, Clone, PartialEq, Eq, Args)]
83+
pub struct McpRemove {
84+
#[arg(long)]
85+
pub name: String,
86+
#[arg(long, value_enum)]
87+
pub scope: Option<Scope>,
88+
#[arg(long)]
89+
pub profile: Option<String>,
90+
}
91+
92+
#[derive(Debug, Clone, PartialEq, Eq, Args)]
93+
pub struct McpList {
94+
#[arg(value_enum)]
95+
pub scope: Option<Scope>,
96+
#[arg(long)]
97+
pub profile: Option<String>,
98+
}
99+
100+
#[derive(Debug, Clone, PartialEq, Eq, Args)]
101+
pub struct McpImport {
102+
#[arg(long)]
103+
pub file: String,
104+
#[arg(value_enum)]
105+
pub scope: Option<Scope>,
106+
#[arg(long)]
107+
pub profile: Option<String>,
108+
/// Overwrite an existing server with the same name
109+
#[arg(long, default_value_t = false)]
110+
pub force: bool,
111+
}
112+
113+
#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueEnum)]
114+
pub enum Scope {
115+
Workspace,
116+
Profile,
117+
Global,
118+
}
119+
120+
impl std::fmt::Display for Scope {
121+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122+
match self {
123+
Scope::Workspace => write!(f, "workspace"),
124+
Scope::Profile => write!(f, "profile"),
125+
Scope::Global => write!(f, "global"),
126+
}
127+
}
128+
}
129+
130+
#[derive(Debug)]
131+
struct EnvVarParseError(String);
132+
133+
impl std::fmt::Display for EnvVarParseError {
134+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135+
write!(f, "Failed to parse environment variables: {}", self.0)
136+
}
137+
}
138+
139+
impl std::error::Error for EnvVarParseError {}
140+
141+
fn parse_env_vars(arg: &str) -> Result<HashMap<String, String>, EnvVarParseError> {
142+
let mut vars = HashMap::new();
143+
144+
for pair in arg.split(",") {
145+
match pair.split_once('=') {
146+
Some((key, value)) => {
147+
vars.insert(key.trim().to_string(), value.trim().to_string());
148+
},
149+
None => {
150+
return Err(EnvVarParseError(format!(
151+
"Invalid environment variable '{}'. Expected 'name=value'",
152+
pair
153+
)));
154+
},
155+
}
156+
}
157+
158+
Ok(vars)
159+
}

crates/chat-cli/src/cli/chat/command.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ pub enum Command {
5151
subcommand: Option<PromptsSubcommand>,
5252
},
5353
Usage,
54-
Import {
54+
Load {
5555
path: String,
5656
},
57-
Export {
57+
Save {
5858
path: String,
5959
force: bool,
6060
},
@@ -818,15 +818,15 @@ impl Command {
818818
}
819819
},
820820
"usage" => Self::Usage,
821-
"import" => {
821+
"load" => {
822822
let Some(path) = parts.get(1) else {
823823
return Err("path is required".to_string());
824824
};
825-
Self::Import {
825+
Self::Load {
826826
path: (*path).to_string(),
827827
}
828828
},
829-
"export" => {
829+
"save" => {
830830
let force = parts.contains(&"-f") || parts.contains(&"--force");
831831
let Some(path) = parts.get(1) else {
832832
return Err("path is required".to_string());
@@ -835,7 +835,7 @@ impl Command {
835835
if !path.ends_with(".json") {
836836
path.push_str(".json");
837837
}
838-
Self::Export { path, force }
838+
Self::Save { path, force }
839839
},
840840
unknown_command => {
841841
let looks_like_path = {

crates/chat-cli/src/cli/chat/consts.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ pub const MAX_CURRENT_WORKING_DIRECTORY_LEN: usize = 256;
77
/// Limit to send the number of messages as part of chat.
88
pub const MAX_CONVERSATION_STATE_HISTORY_LEN: usize = 250;
99

10-
pub const MAX_TOOL_RESPONSE_SIZE: usize = 800_000;
10+
/// Actual service limit is 800_000
11+
pub const MAX_TOOL_RESPONSE_SIZE: usize = 600_000;
1112

12-
/// TODO: Use this to gracefully handle user message sizes.
13-
#[allow(dead_code)]
13+
/// Actual service limit is 600_000
1414
pub const MAX_USER_MESSAGE_SIZE: usize = 600_000;
1515

1616
/// In tokens

crates/chat-cli/src/cli/chat/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub struct ContextManager {
5959
/// Context configuration for the current profile.
6060
pub profile_config: ContextConfig,
6161

62+
#[serde(skip)]
6263
pub hook_executor: HookExecutor,
6364
}
6465

@@ -128,6 +129,13 @@ impl ContextManager {
128129
Ok(())
129130
}
130131

132+
/// Reloads the global and profile config from disk.
133+
pub async fn reload_config(&mut self) -> Result<()> {
134+
self.global_config = load_global_config(&self.ctx).await?;
135+
self.profile_config = load_profile_config(&self.ctx, &self.current_profile).await?;
136+
Ok(())
137+
}
138+
131139
/// Add paths to the context configuration.
132140
///
133141
/// # Arguments

0 commit comments

Comments
 (0)