Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:33:43.449Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

action_completion_provider.rs

138 lines · 4.6 KB · rust
1use collections::HashMap;
2use command_palette;
3use editor::{CompletionProvider, Editor};
4use fuzzy::StringMatchCandidate;
5use gpui::{Context, Entity, SharedString, Window};
6use language::{self, ToOffset};
7use project::{self, CompletionDisplayOptions};
8
9pub struct ActionCompletionProvider {
10    action_names: Vec<&'static str>,
11    humanized_names: HashMap<&'static str, SharedString>,
12}
13
14impl ActionCompletionProvider {
15    pub fn new(
16        action_names: Vec<&'static str>,
17        humanized_names: HashMap<&'static str, SharedString>,
18    ) -> Self {
19        Self {
20            action_names,
21            humanized_names,
22        }
23    }
24}
25
26impl CompletionProvider for ActionCompletionProvider {
27    fn completions(
28        &self,
29        buffer: &Entity<language::Buffer>,
30        buffer_position: language::Anchor,
31        _trigger: editor::CompletionContext,
32        _window: &mut Window,
33        cx: &mut Context<Editor>,
34    ) -> gpui::Task<anyhow::Result<Vec<project::CompletionResponse>>> {
35        let buffer = buffer.read(cx);
36        let mut count_back = 0;
37
38        for char in buffer.reversed_chars_at(buffer_position) {
39            if char.is_ascii_alphanumeric() || char == '_' || char == ':' {
40                count_back += 1;
41            } else {
42                break;
43            }
44        }
45
46        let start_anchor = buffer.anchor_before(
47            buffer_position
48                .to_offset(&buffer)
49                .saturating_sub(count_back),
50        );
51
52        let replace_range = start_anchor..buffer_position;
53        let snapshot = buffer.text_snapshot();
54        let query: String = snapshot.text_for_range(replace_range.clone()).collect();
55        let normalized_query = command_palette::normalize_action_query(&query);
56
57        let candidates: Vec<StringMatchCandidate> = self
58            .action_names
59            .iter()
60            .enumerate()
61            .map(|(ix, &name)| {
62                let humanized = self
63                    .humanized_names
64                    .get(name)
65                    .cloned()
66                    .unwrap_or_else(|| name.into());
67                StringMatchCandidate::new(ix, &humanized)
68            })
69            .collect();
70
71        let executor = cx.background_executor().clone();
72        let executor_for_fuzzy = executor.clone();
73        let action_names = self.action_names.clone();
74        let humanized_names = self.humanized_names.clone();
75
76        executor.spawn(async move {
77            let matches = fuzzy::match_strings(
78                &candidates,
79                &normalized_query,
80                true,
81                true,
82                action_names.len(),
83                &Default::default(),
84                executor_for_fuzzy,
85            )
86            .await;
87
88            let completions: Vec<project::Completion> = matches
89                .iter()
90                .take(50)
91                .map(|m| {
92                    let action_name = action_names[m.candidate_id];
93                    let humanized = humanized_names
94                        .get(action_name)
95                        .cloned()
96                        .unwrap_or_else(|| action_name.into());
97
98                    project::Completion {
99                        replace_range: replace_range.clone(),
100                        label: language::CodeLabel::plain(humanized.to_string(), None),
101                        new_text: action_name.to_string(),
102                        documentation: None,
103                        source: project::CompletionSource::Custom,
104                        icon_path: None,
105                        icon_color: None,
106                        match_start: None,
107                        snippet_deduplication_key: None,
108                        insert_text_mode: None,
109                        confirm: None,
110                        group: None,
111                    }
112                })
113                .collect();
114
115            Ok(vec![project::CompletionResponse {
116                completions,
117                display_options: CompletionDisplayOptions {
118                    dynamic_width: true,
119                },
120                is_incomplete: false,
121            }])
122        })
123    }
124
125    fn is_completion_trigger(
126        &self,
127        _buffer: &Entity<language::Buffer>,
128        _position: language::Anchor,
129        text: &str,
130        _trigger_in_words: bool,
131        _cx: &mut Context<Editor>,
132    ) -> bool {
133        text.chars().last().is_some_and(|last_char| {
134            last_char.is_ascii_alphanumeric() || last_char == '_' || last_char == ':'
135        })
136    }
137}
138
Served at tenant.openagents/omega Member data and write actions are omitted.