Compare commits
1 Commits
ex
...
active-tab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7983802d05 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -739,6 +739,8 @@ dependencies = [
|
||||
"assistant_tool",
|
||||
"chrono",
|
||||
"collections",
|
||||
"editor",
|
||||
"feature_flags",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"html_to_markdown",
|
||||
|
||||
@@ -451,6 +451,15 @@ fn supported_context_picker_modes(
|
||||
modes
|
||||
}
|
||||
|
||||
pub fn active_singleton_buffer_path(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
|
||||
let active_item = workspace.active_item(cx)?;
|
||||
|
||||
let editor = active_item.to_any().downcast::<Editor>().ok()?.read(cx);
|
||||
let buffer = editor.buffer().read(cx).as_singleton()?;
|
||||
|
||||
let path = buffer.read(cx).file()?.path().to_path_buf();
|
||||
Some(path)
|
||||
}
|
||||
fn recent_context_picker_entries(
|
||||
context_store: Entity<ContextStore>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
|
||||
@@ -21,6 +21,7 @@ use language_model::{
|
||||
};
|
||||
use project::git_store::{GitStore, GitStoreCheckpoint, RepositoryState};
|
||||
use project::{Project, Worktree};
|
||||
use workspace::Workspace;
|
||||
use prompt_store::{
|
||||
AssistantSystemPromptContext, PromptBuilder, RulesFile, WorktreeInfoForSystemPrompt,
|
||||
};
|
||||
@@ -31,6 +32,7 @@ use util::{ResultExt as _, TryFutureExt as _, maybe, post_inc};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::context::{AssistantContext, ContextId, format_context_as_string};
|
||||
use crate::context_picker::active_singleton_buffer_path;
|
||||
use crate::thread_store::{
|
||||
SerializedMessage, SerializedMessageSegment, SerializedThread, SerializedToolResult,
|
||||
SerializedToolUse,
|
||||
@@ -261,6 +263,7 @@ pub struct Thread {
|
||||
initial_project_snapshot: Shared<Task<Option<Arc<ProjectSnapshot>>>>,
|
||||
cumulative_token_usage: TokenUsage,
|
||||
feedback: Option<ThreadFeedback>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
}
|
||||
|
||||
impl Thread {
|
||||
@@ -268,6 +271,7 @@ impl Thread {
|
||||
project: Entity<Project>,
|
||||
tools: Arc<ToolWorkingSet>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -299,6 +303,7 @@ impl Thread {
|
||||
},
|
||||
cumulative_token_usage: TokenUsage::default(),
|
||||
feedback: None,
|
||||
workspace,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +313,7 @@ impl Thread {
|
||||
project: Entity<Project>,
|
||||
tools: Arc<ToolWorkingSet>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let next_message_id = MessageId(
|
||||
@@ -362,6 +368,7 @@ impl Thread {
|
||||
initial_project_snapshot: Task::ready(serialized.initial_project_snapshot).shared(),
|
||||
cumulative_token_usage: serialized.cumulative_token_usage,
|
||||
feedback: None,
|
||||
workspace,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,8 +836,15 @@ impl Thread {
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Try to get active tab path
|
||||
let active_tab_path = self.workspace
|
||||
.as_ref()
|
||||
.and_then(|weak_workspace| weak_workspace.upgrade())
|
||||
.and_then(|workspace| active_singleton_buffer_path(&workspace.read(cx), cx))
|
||||
.map(|path| path.to_string_lossy().to_string());
|
||||
|
||||
cx.spawn(async |_cx| {
|
||||
cx.spawn(async move |_cx| {
|
||||
let results = futures::future::join_all(tasks).await;
|
||||
let mut first_err = None;
|
||||
let worktrees = results
|
||||
@@ -842,7 +856,7 @@ impl Thread {
|
||||
worktree
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
(AssistantSystemPromptContext::new(worktrees), first_err)
|
||||
(AssistantSystemPromptContext::new(worktrees).with_active_tab_path(active_tab_path), first_err)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ impl ThreadStore {
|
||||
self.project.clone(),
|
||||
self.tools.clone(),
|
||||
self.prompt_builder.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
@@ -134,6 +135,7 @@ impl ThreadStore {
|
||||
this.project.clone(),
|
||||
this.tools.clone(),
|
||||
this.prompt_builder.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -16,6 +16,8 @@ anyhow.workspace = true
|
||||
assistant_tool.workspace = true
|
||||
chrono.workspace = true
|
||||
collections.workspace = true
|
||||
editor.workspace = true
|
||||
feature_flags.workspace = true
|
||||
futures.workspace = true
|
||||
gpui.workspace = true
|
||||
html_to_markdown.workspace = true
|
||||
@@ -31,6 +33,7 @@ serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
ui.workspace = true
|
||||
util.workspace = true
|
||||
workspace.workspace = true
|
||||
worktree.workspace = true
|
||||
open = { workspace = true }
|
||||
workspace-hack.workspace = true
|
||||
|
||||
58
crates/assistant_tools/src/active_tab_tool.rs
Normal file
58
crates/assistant_tools/src/active_tab_tool.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use assistant_tool::{ActionLog, Tool};
|
||||
use gpui::{App, Entity, Task};
|
||||
use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat};
|
||||
use project::Project;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ui::IconName;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct ActiveTabToolInput {}
|
||||
|
||||
pub struct ActiveTabTool;
|
||||
|
||||
impl Tool for ActiveTabTool {
|
||||
fn name(&self) -> String {
|
||||
"active-tab".into()
|
||||
}
|
||||
|
||||
fn needs_confirmation(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
include_str!("./active_tab_tool/description.md").into()
|
||||
}
|
||||
|
||||
fn icon(&self) -> IconName {
|
||||
IconName::Eye
|
||||
}
|
||||
|
||||
fn input_schema(&self, _format: LanguageModelToolSchemaFormat) -> serde_json::Value {
|
||||
let schema = schemars::schema_for!(ActiveTabToolInput);
|
||||
serde_json::to_value(&schema).unwrap()
|
||||
}
|
||||
|
||||
fn ui_text(&self, _input: &serde_json::Value) -> String {
|
||||
"Get active tabs".to_string()
|
||||
}
|
||||
|
||||
fn run(
|
||||
self: Arc<Self>,
|
||||
input: serde_json::Value,
|
||||
_messages: &[LanguageModelRequestMessage],
|
||||
_project: Entity<Project>,
|
||||
_action_log: Entity<ActionLog>,
|
||||
_cx: &mut App,
|
||||
) -> Task<Result<String>> {
|
||||
let _input = match serde_json::from_value::<ActiveTabToolInput>(input) {
|
||||
Ok(input) => input,
|
||||
Err(err) => return Task::ready(Err(anyhow!(err))),
|
||||
};
|
||||
|
||||
Task::ready(Ok("Active tab information would be shown here".to_string()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Returns the path of the user's currently active tab.
|
||||
@@ -1,3 +1,4 @@
|
||||
mod active_tab_tool;
|
||||
mod bash_tool;
|
||||
mod batch_tool;
|
||||
mod code_symbol_iter;
|
||||
@@ -23,6 +24,7 @@ mod thinking_tool;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use active_tab_tool::ActiveTabTool;
|
||||
use assistant_tool::ToolRegistry;
|
||||
use copy_path_tool::CopyPathTool;
|
||||
use gpui::App;
|
||||
@@ -51,6 +53,7 @@ pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut App) {
|
||||
assistant_tool::init(cx);
|
||||
|
||||
let registry = ToolRegistry::global(cx);
|
||||
registry.register_tool(ActiveTabTool);
|
||||
registry.register_tool(BashTool);
|
||||
registry.register_tool(BatchTool);
|
||||
registry.register_tool(CreateDirectoryTool);
|
||||
|
||||
@@ -548,15 +548,22 @@ pub fn into_anthropic(
|
||||
}
|
||||
}
|
||||
|
||||
// Create a StringOrContents value explicitly
|
||||
let system_value = if !system_message.is_empty() {
|
||||
Some({
|
||||
// Use String variant directly with a qualified path for clarity
|
||||
let string_variant = anthropic::StringOrContents::String(system_message);
|
||||
string_variant
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
anthropic::Request {
|
||||
model,
|
||||
messages: new_messages,
|
||||
max_tokens: max_output_tokens,
|
||||
system: if system_message.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(anthropic::StringOrContents::String(system_message))
|
||||
},
|
||||
system: system_value,
|
||||
thinking: if let AnthropicModelMode::Thinking { budget_tokens } = mode {
|
||||
Some(anthropic::Thinking::Enabled { budget_tokens })
|
||||
} else {
|
||||
|
||||
@@ -20,6 +20,7 @@ use util::ResultExt;
|
||||
pub struct AssistantSystemPromptContext {
|
||||
pub worktrees: Vec<WorktreeInfoForSystemPrompt>,
|
||||
pub has_rules: bool,
|
||||
pub active_tab_path: Option<String>,
|
||||
}
|
||||
|
||||
impl AssistantSystemPromptContext {
|
||||
@@ -30,8 +31,14 @@ impl AssistantSystemPromptContext {
|
||||
Self {
|
||||
worktrees,
|
||||
has_rules,
|
||||
active_tab_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_active_tab_path(mut self, path: Option<String>) -> Self {
|
||||
self.active_tab_path = path;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
||||
Reference in New Issue
Block a user