mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
agent_ui: Add show thread metadata action (#54314)
This commit is contained in:
parent
72b41263f3
commit
c95b41c75a
2 changed files with 174 additions and 3 deletions
|
|
@ -34,8 +34,8 @@ use crate::thread_metadata_store::{ThreadId, ThreadMetadataStore};
|
|||
use crate::{
|
||||
AddContextServer, AgentDiffPane, ConversationView, CopyThreadToClipboard, Follow,
|
||||
InlineAssistant, LoadThreadFromClipboard, NewThread, OpenActiveThreadAsMarkdown, OpenAgentDiff,
|
||||
OpenHistory, ResetTrialEndUpsell, ResetTrialUpsell, ToggleNavigationMenu, ToggleNewThreadMenu,
|
||||
ToggleOptionsMenu,
|
||||
OpenHistory, ResetTrialEndUpsell, ResetTrialUpsell, ShowAllSidebarThreadMetadata,
|
||||
ShowThreadMetadata, ToggleNavigationMenu, ToggleNewThreadMenu, ToggleOptionsMenu,
|
||||
agent_configuration::{AgentConfiguration, AssistantConfigurationEvent},
|
||||
conversation_view::{AcpThreadViewEvent, ThreadView},
|
||||
ui::EndTrialUpsell,
|
||||
|
|
@ -50,10 +50,11 @@ use crate::{ThreadHistory, agent_connection_store::AgentConnectionStore};
|
|||
use agent_settings::AgentSettings;
|
||||
use ai_onboarding::AgentPanelOnboarding;
|
||||
use anyhow::{Context as _, Result};
|
||||
use chrono::{DateTime, Utc};
|
||||
use client::UserStore;
|
||||
use cloud_api_types::Plan;
|
||||
use collections::HashMap;
|
||||
use editor::Editor;
|
||||
use editor::{Editor, MultiBuffer};
|
||||
use extension::ExtensionEvents;
|
||||
use extension_host::ExtensionStore;
|
||||
use fs::Fs;
|
||||
|
|
@ -311,6 +312,24 @@ pub fn init(cx: &mut App) {
|
|||
});
|
||||
}
|
||||
})
|
||||
.register_action(|workspace, _: &ShowThreadMetadata, window, cx| {
|
||||
if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
|
||||
panel.update(cx, |panel, cx| {
|
||||
panel.show_thread_metadata(&ShowThreadMetadata, window, cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
.register_action(|workspace, _: &ShowAllSidebarThreadMetadata, window, cx| {
|
||||
if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
|
||||
panel.update(cx, |panel, cx| {
|
||||
panel.show_all_sidebar_thread_metadata(
|
||||
&ShowAllSidebarThreadMetadata,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.register_action(|workspace, action: &ReviewBranchDiff, window, cx| {
|
||||
let Some(panel) = workspace.panel::<AgentPanel>(cx) else {
|
||||
return;
|
||||
|
|
@ -588,6 +607,46 @@ fn build_conflicted_files_resolution_prompt(
|
|||
content
|
||||
}
|
||||
|
||||
fn format_timestamp_human(dt: &DateTime<Utc>) -> String {
|
||||
let now = Utc::now();
|
||||
let duration = now.signed_duration_since(*dt);
|
||||
|
||||
let relative = if duration.num_seconds() < 0 {
|
||||
"in the future".to_string()
|
||||
} else if duration.num_seconds() < 60 {
|
||||
let seconds = duration.num_seconds();
|
||||
format!("{seconds} seconds ago")
|
||||
} else if duration.num_minutes() < 60 {
|
||||
let minutes = duration.num_minutes();
|
||||
format!("{minutes} minutes ago")
|
||||
} else if duration.num_hours() < 24 {
|
||||
let hours = duration.num_hours();
|
||||
format!("{hours} hours ago")
|
||||
} else {
|
||||
let days = duration.num_days();
|
||||
format!("{days} days ago")
|
||||
};
|
||||
|
||||
format!("{} ({})", dt.to_rfc3339(), relative)
|
||||
}
|
||||
|
||||
/// Used for `dev: show thread metadata` action
|
||||
fn thread_metadata_to_debug_json(
|
||||
metadata: &crate::thread_metadata_store::ThreadMetadata,
|
||||
) -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"thread_id": metadata.thread_id,
|
||||
"session_id": metadata.session_id.as_ref().map(|s| s.0.to_string()),
|
||||
"agent_id": metadata.agent_id.0.to_string(),
|
||||
"title": metadata.title.as_ref().map(|t| t.to_string()),
|
||||
"updated_at": format_timestamp_human(&metadata.updated_at),
|
||||
"created_at": metadata.created_at.as_ref().map(format_timestamp_human),
|
||||
"interacted_at": metadata.interacted_at.as_ref().map(format_timestamp_human),
|
||||
"worktree_paths": format!("{:?}", metadata.worktree_paths),
|
||||
"archived": metadata.archived,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) struct AgentThread {
|
||||
conversation_view: Entity<ConversationView>,
|
||||
}
|
||||
|
|
@ -1873,6 +1932,108 @@ impl AgentPanel {
|
|||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn show_thread_metadata(
|
||||
&mut self,
|
||||
_: &ShowThreadMetadata,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(thread_id) = self.active_thread_id(cx) else {
|
||||
Self::show_deferred_toast(&self.workspace, "No active thread", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(store) = ThreadMetadataStore::try_global(cx) else {
|
||||
Self::show_deferred_toast(&self.workspace, "Thread metadata store not available", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(metadata) = store.read(cx).entry(thread_id).cloned() else {
|
||||
Self::show_deferred_toast(&self.workspace, "No metadata found for active thread", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
let json = thread_metadata_to_debug_json(&metadata);
|
||||
let text = serde_json::to_string_pretty(&json).unwrap_or_default();
|
||||
let title = format!("Thread Metadata: {}", metadata.display_title());
|
||||
|
||||
self.open_json_buffer(title, text, window, cx);
|
||||
}
|
||||
|
||||
fn show_all_sidebar_thread_metadata(
|
||||
&mut self,
|
||||
_: &ShowAllSidebarThreadMetadata,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(store) = ThreadMetadataStore::try_global(cx) else {
|
||||
Self::show_deferred_toast(&self.workspace, "Thread metadata store not available", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
let entries: Vec<serde_json::Value> = store
|
||||
.read(cx)
|
||||
.entries()
|
||||
.filter(|t| !t.archived)
|
||||
.map(thread_metadata_to_debug_json)
|
||||
.collect();
|
||||
|
||||
let json = serde_json::Value::Array(entries);
|
||||
let text = serde_json::to_string_pretty(&json).unwrap_or_default();
|
||||
|
||||
self.open_json_buffer("All Sidebar Thread Metadata".to_string(), text, window, cx);
|
||||
}
|
||||
|
||||
fn open_json_buffer(
|
||||
&self,
|
||||
title: String,
|
||||
text: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let json_language = self.language_registry.language_for_name("JSON");
|
||||
let project = self.project.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
|
||||
window
|
||||
.spawn(cx, async move |cx| {
|
||||
let json_language = json_language.await.ok();
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.create_buffer(json_language, false, cx)
|
||||
})
|
||||
.await?;
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_text(text, cx);
|
||||
buffer.set_capability(language::Capability::ReadWrite, cx);
|
||||
});
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let buffer =
|
||||
cx.new(|cx| MultiBuffer::singleton(buffer, cx).with_title(title.clone()));
|
||||
|
||||
workspace.add_item_to_active_pane(
|
||||
Box::new(cx.new(|cx| {
|
||||
let mut editor =
|
||||
Editor::for_multibuffer(buffer, Some(project.clone()), window, cx);
|
||||
editor.set_breadcrumb_header(title);
|
||||
editor.disable_mouse_wheel_zoom();
|
||||
editor
|
||||
})),
|
||||
None,
|
||||
true,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn handle_agent_configuration_event(
|
||||
&mut self,
|
||||
_entity: &Entity<AgentConfiguration>,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,16 @@ actions!(
|
|||
]
|
||||
);
|
||||
|
||||
actions!(
|
||||
dev,
|
||||
[
|
||||
/// Shows metadata for the currently active thread.
|
||||
ShowThreadMetadata,
|
||||
/// Shows metadata for all threads in the sidebar.
|
||||
ShowAllSidebarThreadMetadata,
|
||||
]
|
||||
);
|
||||
|
||||
/// Action to authorize a tool call with a specific permission option.
|
||||
/// This is used by the permission granularity dropdown to authorize tool calls.
|
||||
#[derive(Clone, PartialEq, Deserialize, JsonSchema, Action)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue