mini-coder 0.5.12 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/plugins.ts DELETED
@@ -1,183 +0,0 @@
1
- /**
2
- * Plugin loader and lifecycle management.
3
- *
4
- * Plugins extend mini-coder with additional tools and system prompt context.
5
- * They are declared in a config file and loaded as modules at startup.
6
- * Each plugin's `init` is called once, and `destroy` (if present) is called
7
- * on shutdown.
8
- *
9
- * @module
10
- */
11
-
12
- import { existsSync, readFileSync } from "node:fs";
13
- import { resolve } from "node:path";
14
- import type { Message, Tool } from "@mariozechner/pi-ai";
15
- import type { ToolHandler } from "./agent.ts";
16
- import type { Theme } from "./theme.ts";
17
-
18
- // ---------------------------------------------------------------------------
19
- // Types
20
- // ---------------------------------------------------------------------------
21
-
22
- /**
23
- * Context provided to plugins during initialization.
24
- *
25
- * Gives plugins read-only access to the agent's environment without
26
- * exposing internal implementation details.
27
- */
28
- export interface AgentContext {
29
- /** The working directory. */
30
- cwd: string;
31
- /** Read-only access to the current session's messages. */
32
- messages: readonly Message[];
33
- /** The app data directory (`~/.config/mini-coder/`). */
34
- dataDir: string;
35
- }
36
-
37
- /**
38
- * Result returned by a plugin's `init` function.
39
- *
40
- * Contains any additional tools the agent should register and/or
41
- * context to append to the system prompt.
42
- */
43
- export interface PluginResult {
44
- /** Additional tool definitions to register with the model. */
45
- tools?: Tool[];
46
- /** Tool name → handler map for the tools above. */
47
- toolHandlers?: Map<string, ToolHandler>;
48
- /** Additional context to append to the system prompt. */
49
- systemPromptSuffix?: string;
50
- /** Partial theme override — merged on top of the default theme. */
51
- theme?: Partial<Theme>;
52
- }
53
-
54
- /**
55
- * The interface a plugin module must implement.
56
- *
57
- * A plugin is a module that exports a conforming object. It is loaded
58
- * dynamically from a path or package name declared in the config file.
59
- */
60
- export interface Plugin {
61
- /** Human-readable plugin name. */
62
- name: string;
63
- /** Brief description of what the plugin provides. */
64
- description: string;
65
- /** Called once at startup. Returns tools to register and/or context to add. */
66
- init(
67
- agent: AgentContext,
68
- config?: Record<string, unknown>,
69
- ): Promise<PluginResult>;
70
- /** Called on shutdown for cleanup. */
71
- destroy?(): Promise<void>;
72
- }
73
-
74
- /** A single entry in the plugins config file. */
75
- export interface PluginEntry {
76
- /** Plugin name (for display and error messages). */
77
- name: string;
78
- /** Module path or package name to import. */
79
- module: string;
80
- /** Optional configuration passed to the plugin's `init`. */
81
- config?: Record<string, unknown>;
82
- }
83
-
84
- /** A loaded and initialized plugin with its result. */
85
- export interface LoadedPlugin {
86
- /** The plugin entry from config. */
87
- entry: PluginEntry;
88
- /** The plugin module instance. */
89
- plugin: Plugin;
90
- /** The result from calling `init`. */
91
- result: PluginResult;
92
- }
93
-
94
- // ---------------------------------------------------------------------------
95
- // Config loading
96
- // ---------------------------------------------------------------------------
97
-
98
- /**
99
- * Load plugin entries from the config file.
100
- *
101
- * Reads and parses the plugins config file. Returns an empty array if
102
- * the file does not exist or contains no plugins.
103
- *
104
- * @param configPath - Path to the plugins config file (e.g. `~/.config/mini-coder/plugins.json`).
105
- * @returns Array of {@link PluginEntry} records.
106
- */
107
- export function loadPluginConfig(configPath: string): PluginEntry[] {
108
- if (!existsSync(configPath)) return [];
109
-
110
- const raw = readFileSync(configPath, "utf-8");
111
- const parsed = JSON.parse(raw) as { plugins?: PluginEntry[] };
112
- return parsed.plugins ?? [];
113
- }
114
-
115
- // ---------------------------------------------------------------------------
116
- // Plugin lifecycle
117
- // ---------------------------------------------------------------------------
118
-
119
- /**
120
- * Load and initialize all plugins from config entries.
121
- *
122
- * Imports each plugin module, calls its `init` with the agent context,
123
- * and collects the results. Plugins that fail to load or initialize are
124
- * skipped with a warning (logged via `onError`).
125
- *
126
- * @param entries - Plugin entries from the config file.
127
- * @param context - The agent context to pass to each plugin.
128
- * @param onError - Callback for plugin load/init errors.
129
- * @returns Array of successfully loaded plugins.
130
- */
131
- export async function initPlugins(
132
- entries: PluginEntry[],
133
- context: AgentContext,
134
- onError?: (entry: PluginEntry, error: Error) => void,
135
- ): Promise<LoadedPlugin[]> {
136
- const loaded: LoadedPlugin[] = [];
137
-
138
- for (const entry of entries) {
139
- try {
140
- const modulePath = resolve(entry.module);
141
- const mod = (await import(modulePath)) as { default?: Plugin } & Plugin;
142
- const plugin = mod.default ?? mod;
143
-
144
- if (typeof plugin.init !== "function") {
145
- throw new Error(
146
- `Plugin "${entry.name}" does not export an init function`,
147
- );
148
- }
149
-
150
- const result = await plugin.init(context, entry.config);
151
- loaded.push({ entry, plugin, result });
152
- } catch (err) {
153
- onError?.(entry, err instanceof Error ? err : new Error(String(err)));
154
- }
155
- }
156
-
157
- return loaded;
158
- }
159
-
160
- /**
161
- * Destroy all loaded plugins.
162
- *
163
- * Calls `destroy` on each plugin that implements it. Errors during
164
- * destruction are passed to `onError` — destruction continues for
165
- * remaining plugins regardless.
166
- *
167
- * @param plugins - The loaded plugins to destroy.
168
- * @param onError - Callback for destruction errors.
169
- */
170
- export async function destroyPlugins(
171
- plugins: LoadedPlugin[],
172
- onError?: (entry: PluginEntry, error: Error) => void,
173
- ): Promise<void> {
174
- for (const { entry, plugin } of plugins) {
175
- if (typeof plugin.destroy === "function") {
176
- try {
177
- await plugin.destroy();
178
- } catch (err) {
179
- onError?.(entry, err instanceof Error ? err : new Error(String(err)));
180
- }
181
- }
182
- }
183
- }