Skip to content
Closed
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
13 changes: 6 additions & 7 deletions apps/maple-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,11 @@ the embedded transport.
Enabling an integration sets a device-local default for new tasks. Existing
tasks keep their frozen integration choice and expose CUA as an independent
per-task switch in the composer. A task that never chose a backend adopts the
device default only when it can actually run it. A detected standalone
CuaDriver, which Maple looks for on macOS only, remains a legacy-compatible
backend until the user explicitly sets up the built-in one;
Maple does not install or update it, start or stop its daemon, or alter another
client's configuration. Custom STDIO and Streamable HTTP MCP servers remain
account configuration that may roam between devices.
device default only when it can actually run it. Maple no longer looks for a
separately installed CuaDriver application: a task saved with its stdio entry
loses that entry on its next run, and a device setting that selected it reads
as not set up. Custom STDIO and Streamable HTTP MCP servers remain account
configuration that may roam between devices.

The embedded design, migration rules, privacy boundary, and preview limits are
documented in [`docs/embedded-cua.md`](docs/embedded-cua.md).
Expand Down Expand Up @@ -463,7 +462,7 @@ shows unpackaged builds; packaged Dev and Prod append `maple-agent-dev` and
| `<config>/agent/accounts/<scope>/goose/config/skills/` | Skills the account's tasks can load, including the delegation skills Maple installs while any external agent is enabled. |
| `<config>/agent/goose-runtime/` | Goose process configuration. |
| `<local data>/auth.json` | Sign-in credentials (mode 0600). Device-local; never in a roaming profile. |
| `<local data>/agent/accounts/<scope>/integrations.json` | Per-account defaults and validated launch details for integrations detected on this device. |
| `<local data>/agent/accounts/<scope>/integrations.json` | Per-account defaults for the integrations on this device. |
| `<local data>/agent/accounts/<scope>/goose/data/sessions/sessions.db` | Goose session history and usage ledger (SQLite, WAL). |
| `<local data>/agent/accounts/<scope>/tool_summaries.db` | Model-written one-line summaries of tool calls (SQLite, WAL). |
| `<local data>/agent/accounts/<scope>/attachments/` | Image attachments. |
Expand Down
1 change: 0 additions & 1 deletion apps/maple-agent/app/src/ui/chat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ fn draft_mcp_rows(
description: card.description.clone(),
transport: match card.backend {
Some(AgentIntegrationBackend::Embedded) => "embedded",
Some(AgentIntegrationBackend::External) => "stdio",
None => "unconfigured",
}
.to_string(),
Expand Down
7 changes: 3 additions & 4 deletions apps/maple-agent/app/src/ui/chat/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2525,7 +2525,6 @@ mod state_tests {
availability,
backend,
version: None,
standalone_version: None,
permissions: None,
setup_available: false,
enabled_for_new_tasks,
Expand Down Expand Up @@ -2610,7 +2609,7 @@ mod state_tests {
assert_eq!(rows[1].display_name, "CODEX");

// Without a stored CUA choice the row is unconfigured and off; an
// external backend that is not installed is on but unavailable.
// embedded choice whose grants are missing is on but unavailable.
let rows = draft_mcp_rows(
Vec::new(),
&[integration_card(
Expand All @@ -2628,12 +2627,12 @@ mod state_tests {
&[integration_card(
"cua-driver",
AgentIntegrationAvailability::SetupRequired,
Some(AgentIntegrationBackend::External),
Some(AgentIntegrationBackend::Embedded),
true,
)],
);
assert!(rows[0].enabled && !rows[0].available);
assert_eq!(rows[0].transport, "stdio");
assert_eq!(rows[0].transport, "embedded");
// No catalog at all: the servers alone, as before.
let rows = draft_mcp_rows(vec![mcp_server("docs", false)], &[]);
assert_eq!(rows.len(), 1);
Expand Down
61 changes: 11 additions & 50 deletions apps/maple-agent/app/src/ui/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2402,15 +2402,7 @@ impl SettingsScreen {
|| SettingsTarget::IntegrationSetup(integration.id.clone()),
pill_button(
format!("integration-setup-{}", integration.id),
if matches!(
&integration.backend,
Some(AgentIntegrationBackend::External)
) || integration.standalone_version.is_some()
{
"Set up built-in"
} else {
"Set up"
},
"Set up",
false,
cx.listener(move |this, _event, _window, cx| {
this.setup_integration(&id, cx);
Expand Down Expand Up @@ -2723,16 +2715,7 @@ fn integration_can_enable(integration: &AgentIntegration) -> bool {
);
}

match integration.backend {
Some(AgentIntegrationBackend::Embedded) => {
cua_permissions_ready(integration.permissions.as_ref())
}
Some(AgentIntegrationBackend::External) => integration.standalone_version.is_some(),
None => {
cua_permissions_ready(integration.permissions.as_ref())
|| integration.standalone_version.is_some()
}
}
cua_permissions_ready(integration.permissions.as_ref())
}

fn integration_can_toggle(integration: &AgentIntegration) -> bool {
Expand All @@ -2746,11 +2729,7 @@ fn integration_can_setup(integration: &AgentIntegration) -> bool {
integration.availability,
AgentIntegrationAvailability::NotDetected
)
&& (!cua_permissions_ready(integration.permissions.as_ref())
|| matches!(
&integration.backend,
Some(AgentIntegrationBackend::External)
))
&& !cua_permissions_ready(integration.permissions.as_ref())
}

fn integration_availability(integration: &AgentIntegration) -> (&'static str, u32) {
Expand All @@ -2768,9 +2747,7 @@ fn integration_availability(integration: &AgentIntegration) -> (&'static str, u3
match &integration.availability {
AgentIntegrationAvailability::NotDetected => ("Not detected", theme::text_muted()),
AgentIntegrationAvailability::Available if is_cua_driver(&integration.id) => {
if cua_permissions_ready(integration.permissions.as_ref())
|| integration.standalone_version.is_some()
{
if cua_permissions_ready(integration.permissions.as_ref()) {
("Ready", theme::status_success())
} else {
("Available", theme::status_success())
Expand All @@ -2791,16 +2768,8 @@ fn integration_setup_notice(permissions: &AgentIntegrationPermissions) -> Option
Some(format!("{}: {guidance}", missing.label()))
}

fn cua_backend_label(integration: &AgentIntegration) -> &'static str {
match integration.backend {
Some(AgentIntegrationBackend::External) => "Standalone driver",
None if integration.standalone_version.is_some()
&& !cua_permissions_ready(integration.permissions.as_ref()) =>
{
"Standalone detected"
}
Some(AgentIntegrationBackend::Embedded) | None => "Built into Maple",
}
fn cua_backend_label(_integration: &AgentIntegration) -> &'static str {
"Built into Maple"
}

fn integration_status_badge(label: &'static str, color: u32) -> Div {
Expand Down Expand Up @@ -3161,7 +3130,6 @@ mod tests {
detail: None,
permissions: Some(macos_permissions(ready, ready)),
setup_available: true,
standalone_version: None,
backend: Some(AgentIntegrationBackend::Embedded),
}
}
Expand Down Expand Up @@ -3263,18 +3231,11 @@ mod tests {
assert!(integration_is_visible(&claude_needs_setup));
assert!(!integration_can_enable(&claude_needs_setup));

let mut external = integration(AgentIntegrationAvailability::Available, true);
external.backend = Some(AgentIntegrationBackend::External);
external.permissions = Some(macos_permissions(false, false));
external.standalone_version = Some("0.23.2".to_string());
assert!(integration_can_toggle(&external));
assert!(integration_can_setup(&external));

// A separately installed driver must not make an embedded selection
// enableable after Maple's own grants have been revoked. The setup
// action is the only route back to a ready embedded backend.
let mut revoked_embedded = external.clone();
revoked_embedded.backend = Some(AgentIntegrationBackend::Embedded);
// An embedded selection is not enableable after Maple's own grants
// have been revoked. The setup action is the only route back to a
// ready embedded backend.
let mut revoked_embedded = integration(AgentIntegrationAvailability::Available, true);
revoked_embedded.permissions = Some(macos_permissions(false, false));
revoked_embedded.enabled_for_new_tasks = false;
assert!(!integration_can_enable(&revoked_embedded));
assert!(!integration_can_toggle(&revoked_embedded));
Expand Down
4 changes: 1 addition & 3 deletions apps/maple-agent/app/src/ui/settings/navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,7 @@ mod tests {
),
),
setup_available: true,
standalone_version: Some("0.23.2".to_string()),
backend: Some(maple_agent::agent::AgentIntegrationBackend::External),
backend: Some(maple_agent::agent::AgentIntegrationBackend::Embedded),
},
// An undetected integration contributes no focus target.
maple_agent::agent::AgentIntegration {
Expand All @@ -714,7 +713,6 @@ mod tests {
detail: None,
permissions: None,
setup_available: false,
standalone_version: None,
backend: None,
},
]);
Expand Down
Loading
Loading