Removes the `skills` feature flag now that Skills are ready to ship to all users. Cleans up all `cx.has_flag::<SkillsFeatureFlag>()` gates across the agent, agent_ui, prompt_store, and title_bar crates, drops the now-unused `feature_flags` dependency from `prompt_store` and `title_bar`, and removes the dead `update_flags(true, vec!["skills"])` calls from the agent's skills tests. Closes AI-269 Release Notes: - Enabled Skills for all users. ---------
Unified · Split
| @@ -13688,7 +13688,6 @@ dependencies = [ · 13687 unmodified lines | ||
| 13688 | 13688 | "chrono", |
| 13689 | 13689 | "collections", |
| 13690 | 13690 | "db", |
| 13691 | − "feature_flags", | |
| 13692 | 13691 | "fs", |
| 13693 | 13692 | "futures 0.3.32", |
| 13694 | 13693 | "fuzzy", |
| @@ -18251,7 +18250,6 @@ dependencies = [ · 4556 unmodified lines | ||
| 18251 | 18250 | "client", |
| 18252 | 18251 | "cloud_api_types", |
| 18253 | 18252 | "db", |
| 18254 | − "feature_flags", | |
| 18255 | 18253 | "fs", |
| 18256 | 18254 | "git_ui", |
| 18257 | 18255 | "gpui", |
| @@ -38,7 +38,7 @@ use agent_skills::{ · 37 unmodified lines | ||
| 38 | 38 | use anyhow::{Context as _, Result, anyhow}; |
| 39 | 39 | use chrono::{DateTime, Utc}; |
| 40 | 40 | use collections::{HashMap, HashSet, IndexMap}; |
| 41 | −use feature_flags::{FeatureFlagAppExt as _, SkillsFeatureFlag}; | |
| 41 | + | |
| 42 | 42 | use fs::Fs; |
| 43 | 43 | use futures::channel::{mpsc, oneshot}; |
| 44 | 44 | use futures::future::Shared; |
| @@ -392,11 +392,11 @@ impl NativeAgent { · 347 unmodified lines | ||
| 392 | 392 | /// Kicks off a one-time scan of the global skills directory if one |
| 393 | 393 | /// isn't already in progress and a watch isn't already active. |
| 394 | 394 | /// |
| 395 | − /// Idempotent and cheap: returns immediately if the user lacks the | |
| 396 | − /// skills feature flag, or if a scan or watch is already running. | |
| 397 | − /// The expected callers are user-interaction events from the agent | |
| 398 | − /// panel (input focus, slash autocomplete, conversation submit); | |
| 399 | − /// firing this from any of them is equivalent and safe to repeat. | |
| 395 | + /// Idempotent and cheap: returns immediately if a scan or watch is | |
| 396 | + /// already running. The expected callers are user-interaction events | |
| 397 | + /// from the agent panel (input focus, slash autocomplete, conversation | |
| 398 | + /// submit); firing this from any of them is equivalent and safe to | |
| 399 | + /// repeat. | |
| 400 | 400 | /// |
| 401 | 401 | /// The scan itself runs detached on the foreground executor. If |
| 402 | 402 | /// `~/.agents/skills/` exists it transitions state to |
| @@ -405,9 +405,6 @@ impl NativeAgent { · 2 unmodified lines | ||
| 405 | 405 | /// next trigger retries (covering the case where the user creates |
| 406 | 406 | /// the directory after the first scan). |
| 407 | 407 | pub fn ensure_skills_scan_started(&mut self, cx: &mut Context<Self>) { |
| 408 | − if !cx.has_flag::<SkillsFeatureFlag>() { | |
| 409 | − return; | |
| 410 | − } | |
| 411 | 408 | if !matches!(self.skills_state, SkillsState::Idle) { |
| 412 | 409 | return; |
| 413 | 410 | } |
| @@ -598,12 +595,10 @@ impl NativeAgent { · 184 unmodified lines | ||
| 598 | 595 | // after the thread is constructed are still visible to the |
| 599 | 596 | // model — without this, the catalog and tool would drift out |
| 600 | 597 | // of sync until the session was reopened. |
| 601 | − if cx.has_flag::<SkillsFeatureFlag>() { | |
| 602 | − thread.add_tool(SkillTool::new( | |
| 603 | − skills_resolver_for_project(weak.clone(), project_id), | |
| 604 | − self.fs.clone(), | |
| 605 | − )); | |
| 606 | − } | |
| 598 | + thread.add_tool(SkillTool::new( | |
| 599 | + skills_resolver_for_project(weak.clone(), project_id), | |
| 600 | + self.fs.clone(), | |
| 601 | + )); | |
| 607 | 602 | }); |
| 608 | 603 | |
| 609 | 604 | let subscriptions = vec![ |
| @@ -822,12 +817,8 @@ impl NativeAgent { · 212 unmodified lines | ||
| 822 | 817 | }) |
| 823 | 818 | .collect::<Vec<_>>(); |
| 824 | 819 | |
| 825 | − // Skills are gated behind the "skills" feature flag. Without it we | |
| 826 | − // skip all on-disk lookups so users see no behavior change. | |
| 827 | − let skills_enabled = cx.has_flag::<SkillsFeatureFlag>(); | |
| 828 | − | |
| 829 | 820 | // Load global skills |
| 830 | − let global_skills_task = if skills_enabled { | |
| 821 | + let global_skills_task = { | |
| 831 | 822 | let global_skills_dir = global_skills_dir(); |
| 832 | 823 | let global_skills_fs = fs.clone(); |
| 833 | 824 | cx.background_spawn(async move { |
| @@ -838,8 +829,6 @@ impl NativeAgent { · 4 unmodified lines | ||
| 838 | 829 | ) |
| 839 | 830 | .await |
| 840 | 831 | }) |
| 841 | − } else { | |
| 842 | − Task::ready(Vec::new()) | |
| 843 | 832 | }; |
| 844 | 833 | |
| 845 | 834 | // Load project-local skills, but only from worktrees the user has |
| @@ -852,7 +841,7 @@ impl NativeAgent { · 6 unmodified lines | ||
| 852 | 841 | // worktrees pick up their skills without restarting. |
| 853 | 842 | let trusted_worktrees = TrustedWorktrees::try_get_global(cx); |
| 854 | 843 | let worktree_store = project.read(cx).worktree_store(); |
| 855 | − let project_skills_task = if skills_enabled { | |
| 844 | + let project_skills_task = { | |
| 856 | 845 | let project_skills_futures: Vec< |
| 857 | 846 | futures::future::BoxFuture<'static, Vec<Result<Skill, SkillLoadError>>>, |
| 858 | 847 | > = worktrees |
| @@ -897,8 +886,6 @@ impl NativeAgent { · 38 unmodified lines | ||
| 897 | 886 | }) |
| 898 | 887 | .collect(); |
| 899 | 888 | cx.background_spawn(async move { future::join_all(project_skills_futures).await }) |
| 900 | − } else { | |
| 901 | − Task::ready(Vec::new()) | |
| 902 | 889 | }; |
| 903 | 890 | let default_user_rules_task = if let Some(prompt_store) = prompt_store.as_ref() { |
| 904 | 891 | prompt_store.read_with(cx, |prompt_store, cx| { |
| @@ -1107,7 +1094,7 @@ impl NativeAgent { · 202 unmodified lines | ||
| 1107 | 1094 | &mut self, |
| 1108 | 1095 | project: Entity<Project>, |
| 1109 | 1096 | event: &project::Event, |
| 1110 | − cx: &mut Context<Self>, | |
| 1097 | + _cx: &mut Context<Self>, | |
| 1111 | 1098 | ) { |
| 1112 | 1099 | let project_id = project.entity_id(); |
| 1113 | 1100 | let Some(state) = self.projects.get_mut(&project_id) else { |
| @@ -1118,16 +1105,14 @@ impl NativeAgent { · 4 unmodified lines | ||
| 1118 | 1105 | state.project_context_needs_refresh.send(()).ok(); |
| 1119 | 1106 | } |
| 1120 | 1107 | project::Event::WorktreeUpdatedEntries(_, items) => { |
| 1121 | − let skills_enabled = cx.has_flag::<SkillsFeatureFlag>(); | |
| 1122 | 1108 | if items.iter().any(|(path, _, _)| { |
| 1123 | 1109 | let path_ref = path.as_ref(); |
| 1124 | 1110 | RULES_FILE_REL_PATHS |
| 1125 | 1111 | .iter() |
| 1126 | 1112 | .any(|rules_path| path_ref == rules_path.as_ref()) |
| 1127 | − || (skills_enabled | |
| 1128 | − && SKILLS_PREFIX | |
| 1129 | − .as_ref() | |
| 1130 | − .is_some_and(|prefix| path_ref.starts_with(prefix))) | |
| 1113 | + || SKILLS_PREFIX | |
| 1114 | + .as_ref() | |
| 1115 | + .is_some_and(|prefix| path_ref.starts_with(prefix)) | |
| 1131 | 1116 | }) { |
| 1132 | 1117 | state.project_context_needs_refresh.send(()).ok(); |
| 1133 | 1118 | } |
| @@ -3583,9 +3568,6 @@ mod internal_tests { · 2449 unmodified lines | ||
| 3583 | 3568 | #[gpui::test] |
| 3584 | 3569 | async fn test_global_skills_load_and_reload(cx: &mut TestAppContext) { |
| 3585 | 3570 | init_test(cx); |
| 3586 | − cx.update(|cx| { | |
| 3587 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 3588 | − }); | |
| 3589 | 3571 | let fs = FakeFs::new(cx.executor()); |
| 3590 | 3572 | let skills_dir = global_skills_dir(); |
| 3591 | 3573 | let initial_skill_dir = skills_dir.join("my-skill"); |
| @@ -3651,9 +3633,6 @@ mod internal_tests { · 59 unmodified lines | ||
| 3651 | 3633 | #[gpui::test] |
| 3652 | 3634 | async fn test_global_skills_dir_created_after_startup(cx: &mut TestAppContext) { |
| 3653 | 3635 | init_test(cx); |
| 3654 | − cx.update(|cx| { | |
| 3655 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 3656 | − }); | |
| 3657 | 3636 | let fs = FakeFs::new(cx.executor()); |
| 3658 | 3637 | let skills_dir = global_skills_dir(); |
| 3659 | 3638 | |
| @@ -3735,9 +3714,6 @@ mod internal_tests { · 75 unmodified lines | ||
| 3735 | 3714 | #[gpui::test] |
| 3736 | 3715 | async fn test_skills_added_after_session_visible_to_skill_tool(cx: &mut TestAppContext) { |
| 3737 | 3716 | init_test(cx); |
| 3738 | − cx.update(|cx| { | |
| 3739 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 3740 | − }); | |
| 3741 | 3717 | let fs = FakeFs::new(cx.executor()); |
| 3742 | 3718 | let skills_dir = global_skills_dir(); |
| 3743 | 3719 | |
| @@ -3879,9 +3855,6 @@ mod internal_tests { · 135 unmodified lines | ||
| 3879 | 3855 | #[gpui::test] |
| 3880 | 3856 | async fn test_subagent_skills_lookup_matches_parent(cx: &mut TestAppContext) { |
| 3881 | 3857 | init_test(cx); |
| 3882 | − cx.update(|cx| { | |
| 3883 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 3884 | − }); | |
| 3885 | 3858 | let fs = FakeFs::new(cx.executor()); |
| 3886 | 3859 | let skills_dir = global_skills_dir(); |
| 3887 | 3860 | let skill_dir = skills_dir.join("shared-skill"); |
| @@ -3982,9 +3955,6 @@ mod internal_tests { · 94 unmodified lines | ||
| 3982 | 3955 | #[gpui::test] |
| 3983 | 3956 | async fn test_skills_appear_as_available_skills(cx: &mut TestAppContext) { |
| 3984 | 3957 | init_test(cx); |
| 3985 | − cx.update(|cx| { | |
| 3986 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 3987 | − }); | |
| 3988 | 3958 | let fs = FakeFs::new(cx.executor()); |
| 3989 | 3959 | let skills_dir = global_skills_dir(); |
| 3990 | 3960 | |
| @@ -4087,7 +4057,6 @@ mod internal_tests { · 96 unmodified lines | ||
| 4087 | 4057 | |
| 4088 | 4058 | init_test(cx); |
| 4089 | 4059 | cx.update(|cx| { |
| 4090 | − cx.update_flags(true, vec!["skills".to_string()]); | |
| 4091 | 4060 | // The trust global isn't created by `init_test`. We need it |
| 4092 | 4061 | // for `Project::test_with_worktree_trust` to actually wire up |
| 4093 | 4062 | // trust tracking and for our subscription in |
| @@ -61,7 +61,7 @@ use collections::HashMap; · 60 unmodified lines | ||
| 61 | 61 | use editor::{Editor, MultiBuffer}; |
| 62 | 62 | use extension::ExtensionEvents; |
| 63 | 63 | use extension_host::ExtensionStore; |
| 64 | −use feature_flags::{FeatureFlagAppExt as _, SkillsFeatureFlag}; | |
| 64 | + | |
| 65 | 65 | use fs::Fs; |
| 66 | 66 | use gpui::{ |
| 67 | 67 | Action, Anchor, Animation, AnimationExt, AnyElement, App, AsyncWindowContext, ClipboardItem, |
| @@ -4714,12 +4714,6 @@ impl AgentPanel { · 4646 unmodified lines | ||
| 4714 | 4714 | .with_handle(self.agent_panel_menu_handle.clone()) |
| 4715 | 4715 | .menu({ |
| 4716 | 4716 | move |window, cx| { |
| 4717 | − // When the Skills feature flag is on, hide the legacy Rules menu entry. | |
| 4718 | − // The flag is read from a global store populated asynchronously, and | |
| 4719 | − // this menu builder runs on every open, so the latest resolved value is | |
| 4720 | − // reflected when the user clicks the ellipsis. | |
| 4721 | − let skills_enabled = cx.has_flag::<SkillsFeatureFlag>(); | |
| 4722 | − | |
| 4723 | 4717 | Some(ContextMenu::build(window, cx, |mut menu, _window, _| { |
| 4724 | 4718 | menu = menu.context(focus_handle.clone()); |
| 4725 | 4719 | |
| @@ -4756,10 +4750,6 @@ impl AgentPanel { · 30 unmodified lines | ||
| 4756 | 4750 | .action("Add Custom Server…", Box::new(AddContextServer)) |
| 4757 | 4751 | .separator(); |
| 4758 | 4752 | |
| 4759 | − if !skills_enabled { | |
| 4760 | − menu = menu.action("Rules", Box::new(OpenRulesLibrary::default())); | |
| 4761 | − } | |
| 4762 | − | |
| 4763 | 4753 | menu = menu.action("Profiles", Box::new(ManageProfiles::default())); |
| 4764 | 4754 | } |
| 4765 | 4755 | |
| @@ -43,7 +43,7 @@ use ::ui::IconName; · 42 unmodified lines | ||
| 43 | 43 | use agent_client_protocol::schema as acp; |
| 44 | 44 | use agent_settings::{AgentProfileId, AgentSettings}; |
| 45 | 45 | use command_palette_hooks::CommandPaletteFilter; |
| 46 | −use feature_flags::{FeatureFlagAppExt as _, SkillsFeatureFlag}; | |
| 46 | +use feature_flags::FeatureFlagAppExt as _; | |
| 47 | 47 | use fs::Fs; |
| 48 | 48 | use gpui::{ |
| 49 | 49 | Action, App, Context, Entity, ImageSource, Resource, SharedString, SharedUri, Window, actions, |
| @@ -560,21 +560,7 @@ pub fn init( · 510 unmodified lines | ||
| 560 | 560 | _: &zed_actions::agent::OpenRulesToSkillsMigrationInfo, |
| 561 | 561 | window: &mut Window, |
| 562 | 562 | cx: &mut Context<Workspace>| { |
| 563 | − // The banner is the only intended entry point and is | |
| 564 | − // gated on the skills flag, but dispatch from the | |
| 565 | − // command palette or a keybind is still possible — only | |
| 566 | − // open the explainer if the flag is enabled so it never | |
| 567 | − // surfaces outside its intended audience. | |
| 568 | − // | |
| 569 | − // Race note: `has_flag` returns false before server | |
| 570 | − // flags are received, so a dispatch during that brief | |
| 571 | − // window is a no-op even for users who genuinely have | |
| 572 | − // the flag. The banner itself has the same race — it | |
| 573 | − // stays hidden until flags arrive — so a user who can | |
| 574 | − // see the banner has, by definition, already passed it. | |
| 575 | − if cx.has_flag::<SkillsFeatureFlag>() { | |
| 576 | − crate::ui::RulesToSkillsModal::toggle(workspace, window, cx); | |
| 577 | − } | |
| 563 | + crate::ui::RulesToSkillsModal::toggle(workspace, window, cx); | |
| 578 | 564 | }, |
| 579 | 565 | ); |
| 580 | 566 | }) |
| @@ -608,10 +594,16 @@ pub fn init( · 27 unmodified lines | ||
| 608 | 594 | }) |
| 609 | 595 | .detach(); |
| 610 | 596 | |
| 611 | − // Once the `skills` feature flag has resolved, kick off the one-time | |
| 612 | − // migration of non-Default Rules to global Skills. Idempotent and | |
| 613 | − // self-gated on the flag, so it's safe to call on every flag-ready | |
| 614 | − // notification (and a no-op for users without the flag). | |
| 597 | + // Kick off the one-time migration of non-Default Rules to global | |
| 598 | + // Skills, deferred until server feature flags arrive. | |
| 599 | + // | |
| 600 | + // The migration itself is idempotent and no longer gated on a flag, | |
| 601 | + // but the deferral via `on_flags_ready` still matters: the migration | |
| 602 | + // writes to the on-disk `GlobalKeyValueStore`, which dispatches work | |
| 603 | + // on the `sqlezWorker` background thread. In `gpui::test` contexts, | |
| 604 | + // server flags are never received, so this callback never fires — | |
| 605 | + // which keeps that sqlite worker activity from racing with the | |
| 606 | + // `TestScheduler` and tripping its non-determinism panic. | |
| 615 | 607 | { |
| 616 | 608 | let fs = fs.clone(); |
| 617 | 609 | cx.on_flags_ready(move |_, cx| { |
| @@ -653,12 +645,6 @@ fn update_command_palette_filter(cx: &mut App) { · 35 unmodified lines | ||
| 653 | 645 | .edit_predictions |
| 654 | 646 | .provider; |
| 655 | 647 | |
| 656 | − // The Skills feature flag is loaded asynchronously, so this value may | |
| 657 | − // be `false` before flags resolve. `update_command_palette_filter` | |
| 658 | − // gets re-run from `cx.on_flags_ready` (see `init`), which means the | |
| 659 | − // filter is reapplied with the correct value once flags arrive. | |
| 660 | − let skills_enabled = cx.has_flag::<SkillsFeatureFlag>(); | |
| 661 | − | |
| 662 | 648 | CommandPaletteFilter::update_global(cx, |filter, _| { |
| 663 | 649 | use editor::actions::{ |
| 664 | 650 | AcceptEditPrediction, AcceptNextLineEditPrediction, AcceptNextWordEditPrediction, |
| @@ -726,12 +712,12 @@ fn update_command_palette_filter(cx: &mut App) { · 61 unmodified lines | ||
| 726 | 712 | filter.show_namespace("multi_workspace"); |
| 727 | 713 | } |
| 728 | 714 | |
| 729 | − // Hide `assistant: open rules library` when Skills are enabled — | |
| 730 | − // Rules are surfaced through the Skills UI in that case. Applied | |
| 731 | − // after the disable-ai / agent-enabled branches so it overrides | |
| 732 | − // the `show_namespace("assistant")` call above without affecting | |
| 733 | − // the rest of that namespace's actions. | |
| 734 | − if !disable_ai && skills_enabled { | |
| 715 | + // Hide `assistant: open rules library` — Rules are surfaced | |
| 716 | + // through the Skills UI now. Applied after the disable-ai / | |
| 717 | + // agent-enabled branches so it overrides the | |
| 718 | + // `show_namespace("assistant")` call above without affecting the | |
| 719 | + // rest of that namespace's actions. | |
| 720 | + if !disable_ai { | |
| 735 | 721 | filter.hide_action_types(&open_rules_library_action); |
| 736 | 722 | } else { |
| 737 | 723 | filter.show_action_types(open_rules_library_action.iter()); |
| @@ -123,15 +123,3 @@ impl FeatureFlag for AutoWatchFeatureFlag { · 122 unmodified lines | ||
| 123 | 123 | type Value = PresenceFlag; |
| 124 | 124 | } |
| 125 | 125 | register_feature_flag!(AutoWatchFeatureFlag); |
| 126 | − | |
| 127 | −pub struct SkillsFeatureFlag; | |
| 128 | − | |
| 129 | −impl FeatureFlag for SkillsFeatureFlag { | |
| 130 | − const NAME: &'static str = "skills"; | |
| 131 | − type Value = PresenceFlag; | |
| 132 | − | |
| 133 | − fn enabled_for_staff() -> bool { | |
| 134 | − true | |
| 135 | − } | |
| 136 | −} | |
| 137 | −register_feature_flag!(SkillsFeatureFlag); | |
| @@ -18,7 +18,7 @@ assets.workspace = true · 17 unmodified lines | ||
| 18 | 18 | chrono.workspace = true |
| 19 | 19 | collections.workspace = true |
| 20 | 20 | db.workspace = true |
| 21 | −feature_flags.workspace = true | |
| 21 | + | |
| 22 | 22 | fs.workspace = true |
| 23 | 23 | futures.workspace = true |
| 24 | 24 | fuzzy.workspace = true |
| @@ -24,14 +24,10 @@ · 23 unmodified lines | ||
| 24 | 24 | //! (still using Zed's shipped default content) are skipped so we don't |
| 25 | 25 | //! pollute AGENTS.md with text the user never wrote. |
| 26 | 26 | //! |
| 27 | −//! Both migrations are gated by: | |
| 28 | −//! | |
| 29 | −//! * the `skills` feature flag — users without it never have their Rules | |
| 30 | −//! touched in any way; | |
| 31 | −//! * a single global "migration already ran" flag persisted in | |
| 32 | −//! [`GlobalKeyValueStore`] — keyed by [`MIGRATION_DONE_KEY`], so a | |
| 33 | −//! shared home directory only gets populated once per machine even | |
| 34 | −//! across release channels. | |
| 27 | +//! Both migrations are gated by a single global "migration already ran" | |
| 28 | +//! flag persisted in [`GlobalKeyValueStore`] — keyed by | |
| 29 | +//! [`MIGRATION_DONE_KEY`], so a shared home directory only gets | |
| 30 | +//! populated once per machine even across release channels. | |
| 35 | 31 | //! |
| 36 | 32 | //! The migration is intentionally non-destructive: rule rows in the LMDB |
| 37 | 33 | //! database are left in place after the migration. That way users can |
| @@ -45,7 +41,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; · 7 unmodified lines | ||
| 45 | 41 | use agent_skills::{SKILL_FILE_NAME, global_skills_dir, slugify_skill_name}; |
| 46 | 42 | use anyhow::{Context as _, Result}; |
| 47 | 43 | use db::kvp::GlobalKeyValueStore; |
| 48 | −use feature_flags::{FeatureFlagAppExt as _, SkillsFeatureFlag}; | |
| 49 | 44 | use fs::Fs; |
| 50 | 45 | use gpui::{App, AsyncApp, Entity, TaskExt as _}; |
| 51 | 46 | use serde::{Deserialize, Serialize}; |
| @@ -151,13 +146,9 @@ static MIGRATION_TASK_SPAWNED: AtomicBool = AtomicBool::new(false); · 99 unmodified lines | ||
| 151 | 146 | /// Migrate non-Default user rules to global Skills, if not already done. |
| 152 | 147 | /// |
| 153 | 148 | /// Safe to call on every startup — short-circuits immediately when the |
| 154 | −/// migration has already run, when another invocation in this process | |
| 155 | −/// has already started it, or when the user doesn't have the `skills` | |
| 156 | −/// feature flag enabled. | |
| 149 | +/// migration has already run or when another invocation in this process | |
| 150 | +/// has already started it. | |
| 157 | 151 | pub fn migrate_rules_to_skills_if_needed(fs: Arc<dyn Fs>, cx: &mut App) { |
| 158 | − if !cx.has_flag::<SkillsFeatureFlag>() { | |
| 159 | − return; | |
| 160 | − } | |
| 161 | 152 | if migration_done() { |
| 162 | 153 | return; |
| 163 | 154 | } |
| @@ -40,7 +40,7 @@ chrono.workspace = true · 39 unmodified lines | ||
| 40 | 40 | client.workspace = true |
| 41 | 41 | cloud_api_types.workspace = true |
| 42 | 42 | db.workspace = true |
| 43 | −feature_flags.workspace = true | |
| 43 | + | |
| 44 | 44 | git_ui.workspace = true |
| 45 | 45 | gpui = { workspace = true, features = ["screen-capture"] } |
| 46 | 46 | icons.workspace = true |
| @@ -25,7 +25,6 @@ use auto_update::AutoUpdateStatus; · 24 unmodified lines | ||
| 25 | 25 | use call::ActiveCall; |
| 26 | 26 | use client::{Client, UserStore, zed_urls}; |
| 27 | 27 | use cloud_api_types::Plan; |
| 28 | −use feature_flags::{FeatureFlagAppExt as _, SkillsFeatureFlag}; | |
| 29 | 28 | |
| 30 | 29 | use gpui::{ |
| 31 | 30 | Action, Anchor, Animation, AnimationExt, AnyElement, App, Context, Element, Entity, Focusable, |
| @@ -469,7 +468,6 @@ impl TitleBar { · 437 unmodified lines | ||
| 469 | 468 | zed_actions::agent::OpenRulesToSkillsMigrationInfo.boxed_clone(), |
| 470 | 469 | cx, |
| 471 | 470 | ) |
| 472 | − .visible_when(|cx| cx.has_flag::<SkillsFeatureFlag>()) | |
| 473 | 471 | })); |
| 474 | 472 | |
| 475 | 473 | let mut this = Self { |