Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions frontend/src-tauri/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const MAPLE_GOOSE_PERMISSION_CONFIG: &str = r#"user:
never_allow: []
"#;
const RUN_SHUTDOWN_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
const DEFAULT_AGENT_SESSION_TITLE: &str = "New agent session";
const DEFAULT_AGENT_SESSION_TITLE: &str = "New task";
const DEFAULT_MCP_TIMEOUT_SECONDS: u64 = 300;
const MAX_AGENT_SESSION_TITLE_CHARS: usize = 80;
const MAX_AGENT_ERROR_CHARS: usize = 1_200;
Expand All @@ -84,7 +84,7 @@ fn validate_session_model_lock(
return Ok(());
}
Err(format!(
"This Agent session is locked to model {persisted_model}. Start a new session to use {requested_model}."
"This task is locked to model {persisted_model}. Start a new task to use {requested_model}."
))
}

Expand Down Expand Up @@ -1026,7 +1026,7 @@ pub async fn agent_create_session(
let session = session_manager
.create_session(root.clone(), title, SessionType::User, permission_mode)
.await
.map_err(|e| format!("Failed to create Goose session: {e}"))?;
.map_err(|e| format!("Failed to create Agent task: {e}"))?;

permission_modes
.lock()
Expand Down Expand Up @@ -1109,7 +1109,7 @@ pub async fn agent_list_sessions(
let mut sessions = session_manager
.list_all_sessions()
.await
.map_err(|e| format!("Failed to list Goose sessions: {e}"))?
.map_err(|e| format!("Failed to list Agent tasks: {e}"))?
.into_iter()
.filter(|session| {
if let Some(root) = filter_root.as_ref() {
Expand Down Expand Up @@ -1148,11 +1148,11 @@ pub async fn agent_load_session(
let session = session_manager
.get_session(&session_id, true)
.await
.map_err(|e| format!("Failed to load Goose session: {e}"))?;
.map_err(|e| format!("Failed to load Agent task: {e}"))?;
let conversation = session
.conversation
.as_ref()
.ok_or_else(|| "Goose session history was not loaded".to_string())?;
.ok_or_else(|| "Agent task history was not loaded".to_string())?;
let timeline = conversation_to_timeline_items(conversation);
let timeline =
overlay_live_timeline(&state.live_timelines, &session_id, conversation, timeline).await;
Expand Down Expand Up @@ -1188,7 +1188,7 @@ pub async fn agent_list_session_mcp_servers(
let session = session_manager
.get_session(session_id.trim(), false)
.await
.map_err(|error| format!("Failed to load Goose session: {error}"))?;
.map_err(|error| format!("Failed to load Agent task: {error}"))?;
let configured = normalize_mcp_servers(
load_agent_config_inner(&app_handle, &user_id)
.map_err(|error| format!("Failed to load MCP servers: {error}"))?
Expand All @@ -1212,7 +1212,7 @@ pub async fn agent_set_session_mcp_server_enabled(
let session_id = request.session_id.trim().to_string();
let requested_key = goose::config::extensions::name_to_key(request.name.trim());
if session_id.is_empty() {
return Err("Agent session ID cannot be empty".to_string());
return Err("Agent task ID cannot be empty".to_string());
}
if requested_key.is_empty() || requested_key == "developer" {
return Err("That MCP server cannot be changed".to_string());
Expand Down Expand Up @@ -1240,7 +1240,7 @@ pub async fn agent_set_session_mcp_server_enabled(
let session = session_manager
.get_session(&session_id, false)
.await
.map_err(|error| format!("Failed to load Goose session: {error}"))?;
.map_err(|error| format!("Failed to load Agent task: {error}"))?;
let session_mcp_keys = session_mcp_extension_keys(&session);
let manager_result = agent_manager
.get_or_create_agent_with_runtime_context(
Expand Down Expand Up @@ -1300,13 +1300,13 @@ pub async fn agent_set_session_mcp_server_enabled(
agent
.persist_extension_state(&session_id)
.await
.map_err(|error| format!("Failed to save MCP session state: {error}"))?;
.map_err(|error| format!("Failed to save task MCP settings: {error}"))?;
}

let refreshed = session_manager
.get_session(&session_id, false)
.await
.map_err(|error| format!("Failed to reload Goose session: {error}"))?;
.map_err(|error| format!("Failed to reload Agent task: {error}"))?;
Ok(session_mcp_servers(&configured, &refreshed))
}

Expand All @@ -1323,7 +1323,7 @@ pub async fn agent_delete_session(
ensure_account_generation(&state, &account_scope, generation).await?;
let session_id = session_id.trim().to_string();
if session_id.is_empty() {
return Err("Agent session ID cannot be empty".to_string());
return Err("Agent task ID cannot be empty".to_string());
}

let _session_lifecycle_guard = state.session_lifecycle.lock().await;
Expand All @@ -1333,7 +1333,7 @@ pub async fn agent_delete_session(
Some(current) => {
ensure_runtime_account(current, &account_scope)?;
if has_active_session_run(&current.active_runs, &session_id) {
return Err("Stop the running agent before deleting this chat".to_string());
return Err("Stop the running agent before deleting this task".to_string());
}
(
Some(Arc::clone(&current.agent_manager)),
Expand Down Expand Up @@ -1375,11 +1375,11 @@ async fn delete_persisted_agent_session(
session_manager
.get_session(session_id, false)
.await
.map_err(|e| format!("Failed to find Goose session {session_id}: {e}"))?;
.map_err(|e| format!("Failed to find Agent task {session_id}: {e}"))?;
session_manager
.delete_session(session_id)
.await
.map_err(|e| format!("Failed to delete Goose session {session_id}: {e}"))?;
.map_err(|e| format!("Failed to delete Agent task {session_id}: {e}"))?;

live_timelines.lock().await.remove(session_id);
pending_permissions
Expand Down Expand Up @@ -1411,15 +1411,15 @@ async fn rollback_cancelled_agent_turn(
let session = session_manager
.get_session(session_id, false)
.await
.map_err(|error| format!("Failed to inspect cancelled Agent session: {error}"))?;
.map_err(|error| format!("Failed to inspect cancelled Agent task: {error}"))?;
if !session.user_set_name {
session_manager
.update(session_id)
.system_generated_name(title.clone())
.apply()
.await
.map_err(|error| {
format!("Failed to restore cancelled Agent session title: {error}")
format!("Failed to restore cancelled Agent task title: {error}")
})?;
}
}
Expand Down Expand Up @@ -1492,7 +1492,7 @@ pub async fn agent_send_message(
agent_manager
.try_register_cancel_token(&request.session_id, cancel_token.clone())
.await
.map_err(|e| format!("Agent session is already running: {e}"))?;
.map_err(|e| format!("Agent task is already running: {e}"))?;

// A rejected or delayed send must not be able to change a live policy that
// the mode command already made authoritative. Seed only sessions that do
Expand All @@ -1510,7 +1510,7 @@ pub async fn agent_send_message(
let mut session = session_manager
.get_session(&request.session_id, true)
.await
.map_err(|e| format!("Failed to load Goose session: {e}"))?;
.map_err(|e| format!("Failed to load Agent task: {e}"))?;
validate_session_model_lock(
session.message_count,
session
Expand All @@ -1534,11 +1534,11 @@ pub async fn agent_send_message(
.system_generated_name(prompt_title)
.apply()
.await
.map_err(|e| format!("Failed to name Agent session: {e}"))?;
.map_err(|e| format!("Failed to name Agent task: {e}"))?;
session = session_manager
.get_session(&session.id, false)
.await
.map_err(|e| format!("Failed to load named Goose session: {e}"))?;
.map_err(|e| format!("Failed to load named Agent task: {e}"))?;
emit_agent_event(
&app_handle,
AgentEventEnvelope {
Expand Down Expand Up @@ -1820,7 +1820,7 @@ pub async fn agent_set_permission_mode(

let session_id = request.session_id.trim().to_string();
if session_id.is_empty() {
return Err("Agent permission mode update requires a session ID".to_string());
return Err("Agent permission mode update requires a task ID".to_string());
}
let goose_mode = parse_user_permission_mode(&request.mode)?;
let (agent_manager, session_manager, permission_modes) = {
Expand Down Expand Up @@ -1986,12 +1986,12 @@ pub async fn agent_permission_respond(
ensure_runtime_account(current, &account_scope)?;
let session_id = response.session_id.trim().to_string();
if session_id.is_empty() {
return Err("Agent permission response requires a session ID".to_string());
return Err("Agent permission response requires a task ID".to_string());
}
let key = (session_id.clone(), response.request_id.clone());
if !state.pending_permissions.lock().await.contains_key(&key) {
return Err(format!(
"No pending Agent Mode permission request found for {} in session {}",
"No pending Agent Mode permission request found for {} in task {}",
response.request_id, session_id
));
}
Expand Down Expand Up @@ -2325,7 +2325,7 @@ async fn run_agent_prompt(run: AgentPromptRun) -> Result<AgentPromptOutcome, Str
let updated_session = session_manager
.get_session(&session_id, false)
.await
.map_err(|e| format!("Failed to load updated Goose session: {e}"))?;
.map_err(|e| format!("Failed to load updated Agent task: {e}"))?;
let working_dir = updated_session.working_dir.clone();
emit_agent_event(
&app_handle,
Expand Down Expand Up @@ -2608,7 +2608,7 @@ async fn configure_session_agent(
goose::execution::manager::RuntimeContext::default(),
)
.await
.map_err(|e| format!("Failed to get Goose agent for session {}: {e}", session.id))?;
.map_err(|e| format!("Failed to load Agent for task {}: {e}", session.id))?;
let agent = manager_result.agent;
let mcp_errors = mcp_connection_errors(manager_result.extension_results, &session_mcp_keys);
let provider = goose::providers::create_with_working_dir(
Expand Down Expand Up @@ -4846,7 +4846,7 @@ mod tests {
assert!(validate_session_model_lock(3, Some("glm-5-2"), "glm-5-2").is_ok());
let error = validate_session_model_lock(3, Some("glm-5-2"), "gemma4-31b").unwrap_err();
assert!(error.contains("locked to model glm-5-2"));
assert!(error.contains("Start a new session"));
assert!(error.contains("Start a new task"));
}

#[tokio::test]
Expand Down
39 changes: 21 additions & 18 deletions frontend/src/components/AgentMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ export function AgentMode({ userId }: { userId: string }) {
}, [projectRoot, visibleProjectRoots]);
const activeSessionTitle = useMemo(() => {
const activeSession = sessions.find((session) => session.id === activeSessionId);
return activeSession ? sessionTitle(activeSession) : "Agent session";
return activeSession ? sessionTitle(activeSession) : "New task";
}, [activeSessionId, sessions]);
const activeRunId = activeSessionId ? (activeRunsBySession[activeSessionId] ?? null) : null;
const activePendingSendKey = activeSessionId || NEW_SESSION_PENDING_KEY;
Expand Down Expand Up @@ -1234,7 +1234,7 @@ export function AgentMode({ userId }: { userId: string }) {
if (!sessionId) {
const detail = await agentRuntimeService.createSession(userId, {
projectRoot,
title: "New agent session",
title: "New task",
model: model || DEFAULT_MODEL,
mode: selectedModeRef.current,
mcpServerNames: selectedNewChatMcpServerNames
Expand Down Expand Up @@ -1294,7 +1294,7 @@ export function AgentMode({ userId }: { userId: string }) {
}
return await agentRuntimeService.createSession(userId, {
projectRoot,
title: "New agent session",
title: "New task",
model: model || DEFAULT_MODEL,
mode: selectedModeRef.current,
mcpServerNames: selectedNewChatMcpServerNames
Expand Down Expand Up @@ -1364,7 +1364,7 @@ export function AgentMode({ userId }: { userId: string }) {
return { detail, timelineRevision };
}
}
throw new Error("This Agent session is still updating. Try selecting it again shortly.");
throw new Error("This task is still updating. Try selecting it again shortly.");
});
const { detail, timelineRevision } = loaded;
if (
Expand All @@ -1381,7 +1381,7 @@ export function AgentMode({ userId }: { userId: string }) {
// that case leave the previous chat intact instead of overwriting the
// newer timeline with a stale snapshot.
if (!replaceSessionTimeline(detail.session.id, detail.timeline, timelineRevision)) {
throw new Error("This Agent session changed while loading. Try selecting it again.");
throw new Error("This task changed while loading. Try selecting it again.");
}

// Commit the selected session and all of its settings together. Until
Expand Down Expand Up @@ -1604,7 +1604,7 @@ export function AgentMode({ userId }: { userId: string }) {
async (item: AgentTimelineItem, decision: AgentPermissionDecision) => {
const sessionId = activeSessionIdRef.current;
try {
if (!sessionId) throw new Error("No active Agent session for this permission request");
if (!sessionId) throw new Error("No active task for this permission request");
await agentRuntimeService.respondToPermission(
userId,
sessionId,
Expand Down Expand Up @@ -1892,6 +1892,7 @@ export function AgentMode({ userId }: { userId: string }) {
onSessionSelect={(sessionId) => void loadSession(sessionId)}
/>
}
onNewItem={areAgentSettingsLocked ? undefined : () => void createSession()}
onToggle={toggleSidebar}
/>

Expand All @@ -1902,7 +1903,8 @@ export function AgentMode({ userId }: { userId: string }) {
if (!open) setSessionToDelete(null);
}}
chatTitle={sessionTitle(sessionToDelete)}
description={`This will delete "${sessionTitle(sessionToDelete)}" from Agent Mode. This action cannot be undone.`}
itemLabel="task"
description={`This will permanently delete the task "${sessionTitle(sessionToDelete)}". This action cannot be undone.`}
onConfirm={() => void deleteSession(sessionToDelete.id)}
/>
) : null}
Expand Down Expand Up @@ -1931,6 +1933,7 @@ export function AgentMode({ userId }: { userId: string }) {
title={activeSessionTitle}
isSidebarOpen={isSidebarOpen}
onNewChat={() => void createSession()}
newItemLabel="New Task"
/>
) : null}

Expand All @@ -1944,7 +1947,7 @@ export function AgentMode({ userId }: { userId: string }) {
<p className="mt-0.5 text-xs text-muted-foreground">
Maple cannot verify that this existing Local OpenAI Proxy key belongs to the
signed-in account. This can happen once after upgrading from an older Agent Mode
build. Your chats remain available; replace the saved local setup before sending
build. Your tasks remain available; replace the saved local setup before sending
another message. The existing backend key will remain in API Management.
</p>
</div>
Expand Down Expand Up @@ -2629,9 +2632,7 @@ function AgentSidebarContent({
size="icon"
className="h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground"
onClick={() => toggleProjectCollapsed(root.path)}
aria-label={
isCollapsed ? "Expand project sessions" : "Collapse project sessions"
}
aria-label={isCollapsed ? "Expand project tasks" : "Collapse project tasks"}
>
{isCollapsed ? (
<ChevronRight className="h-4 w-4" />
Expand All @@ -2648,7 +2649,7 @@ function AgentSidebarContent({
className="h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground"
onClick={onCreateSession}
disabled={disabled || !projectRoot}
aria-label="New agent session"
aria-label="New Task"
>
<MessageSquarePlus className="h-4 w-4" />
</Button>
Expand All @@ -2659,7 +2660,7 @@ function AgentSidebarContent({
<div className="mt-2 w-full space-y-2 pl-6">
{projectSessions.length === 0 ? (
isActive ? (
<p className="py-1 text-xs text-muted-foreground/75">No sessions yet</p>
<p className="py-1 text-xs text-muted-foreground/75">No tasks yet</p>
) : null
) : (
projectSessions.map((session) => {
Expand Down Expand Up @@ -2726,7 +2727,7 @@ function AgentSidebarContent({
event.preventDefault();
event.stopPropagation();
}}
aria-label={`Open chat menu for ${title}`}
aria-label={`Open task menu for ${title}`}
>
<MoreHorizontal
className="h-4 w-4"
Expand All @@ -2743,7 +2744,9 @@ function AgentSidebarContent({
className="mr-2 h-4 w-4"
strokeWidth={SIDEBAR_ICON_STROKE}
/>
{isRunning ? "Stop Agent Before Deleting" : "Delete Chat"}
{isRunning
? "Stop Agent Before Deleting Task"
: "Delete Task"}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down Expand Up @@ -2788,10 +2791,10 @@ function AgentSidebarContent({

<div className="mt-7">
<p className="mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
Chats
Tasks
</p>
<p className="text-xs text-muted-foreground/75">
Folderless agent chats are not available yet.
Folderless Agent tasks are not available yet.
</p>
</div>
</>
Expand Down Expand Up @@ -3751,7 +3754,7 @@ function permissionRequestId(item: AgentTimelineItem): string {
}

function sessionTitle(session: AgentSessionSummary): string {
return session.title || "Agent session";
return session.title || "New task";
}

function toolTitle(item: AgentTimelineItem): string {
Expand Down
Loading
Loading