Skip to content

Commit 96fecc7

Browse files
committed
Add /plugins-list command
1 parent caf6a6e commit 96fecc7

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
## Unreleased
44

55
- Fix MCP server initialization crash (`String cannot be cast to IPersistentCollection`) when OAuth metadata endpoint returns a non-JSON or error response.
6-
- Add `plugins` config for loading external configuration from git repos or local paths.
6+
- Add `plugins` config for loading external configuration from git repos or local paths. #349
77
- Plugins can provide skills, MCP servers, agents, commands, hooks, rules, and arbitrary config overrides.
8+
- Add commands `/plugins-list` and `/plugins-add`.
89

910
## 0.110.3
1011

src/eca/features/commands.clj

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[eca.db :as db]
99
[eca.features.index :as f.index]
1010
[eca.features.login :as f.login]
11+
[eca.features.plugins :as f.plugins]
1112
[eca.features.prompt :as f.prompt]
1213
[eca.features.skills :as f.skills]
1314
[eca.features.tools.mcp :as f.mcp]
@@ -135,6 +136,10 @@
135136
{:name "subagents"
136137
:type :native
137138
:description "List available subagents and their configuration."
139+
:arguments []}
140+
{:name "plugins-list"
141+
:type :native
142+
:description "List available plugins from configured marketplaces."
138143
:arguments []}]
139144
custom-cmds (map (fn [custom]
140145
{:name (:name custom)
@@ -408,6 +413,27 @@
408413
"subagents" (let [msg (subagents-msg config)]
409414
{:type :chat-messages
410415
:chats {chat-id {:messages [{:role "system" :content [{:type :text :text msg}]}]}}})
416+
"plugins-list" (let [plugins-config (:plugins config)
417+
plugins (f.plugins/list-marketplace-plugins plugins-config)
418+
msg (if (seq plugins)
419+
(let [by-source (group-by :source-name plugins)]
420+
(reduce-kv
421+
(fn [s source-name source-plugins]
422+
(str s "**" source-name "** (`" (:source-url (first source-plugins)) "`)\n"
423+
(reduce
424+
(fn [s2 {:keys [name description installed?]}]
425+
(str s2 "- " name
426+
(when installed? "")
427+
(when description (str "" description))
428+
"\n"))
429+
""
430+
source-plugins)
431+
"\n"))
432+
"Plugins available:\n\n"
433+
by-source))
434+
"No plugin marketplaces configured. Add plugin sources to your config under the `plugins` key.")]
435+
{:type :chat-messages
436+
:chats {chat-id {:messages [{:role "system" :content [{:type :text :text msg}]}]}}})
411437

412438
;; else check if a custom command or skill
413439
(if-let [custom-command-prompt (get-custom-command command args custom-cmds)]

src/eca/features/plugins.clj

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@
294294
[plugins-config]
295295
(if (or (nil? plugins-config) (empty? plugins-config))
296296
empty-result
297-
(let [auto-install (get plugins-config :install [])
297+
(let [auto-install (get plugins-config "install" [])
298298
sources (parse-sources plugins-config)]
299299
(if (empty? auto-install)
300300
(do (logger/debug logger-tag "No plugins in install, skipping")
@@ -320,3 +320,23 @@
320320
(do (logger/info logger-tag "Loading plugin:" plugin-name "from" source-name)
321321
(discover-components plugin-dir))))]
322322
(merge-components components))))))
323+
324+
(defn list-marketplace-plugins
325+
"Lists all available plugins from configured marketplace sources.
326+
Returns a seq of {:name :source-name :source-url :description :installed?} maps."
327+
[plugins-config]
328+
(when (seq plugins-config)
329+
(let [installed-set (set (get plugins-config :install []))
330+
sources (parse-sources plugins-config)]
331+
(doall
332+
(for [[source-name source-url] sources
333+
:let [source-dir (resolve-source! source-url)]
334+
:when source-dir
335+
:let [marketplace (read-marketplace source-dir)]
336+
:when marketplace
337+
plugin marketplace]
338+
{:name (:name plugin)
339+
:description (:description plugin)
340+
:source-name source-name
341+
:source-url source-url
342+
:installed? (contains? installed-set (:name plugin))})))))

0 commit comments

Comments
 (0)