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/BENCHMARK.md +15 -316
- package/PROGRESS.md +3 -3
- package/README.md +54 -21
- package/benchmark-baseline.sh +15 -0
- package/bun.lock +265 -90
- package/package.json +8 -7
- package/skills-lock.json +15 -0
- package/src/agent.ts +526 -13
- package/src/assistant-output.ts +73 -0
- package/src/cli.ts +2 -1
- package/src/delegation.ts +238 -0
- package/src/headless.ts +90 -44
- package/src/index.ts +267 -102
- package/src/input.ts +13 -1
- package/src/mcp.ts +609 -0
- package/src/prompt.ts +11 -13
- package/src/session-message.ts +57 -65
- package/src/session.ts +389 -42
- package/src/settings.ts +199 -7
- package/src/skills.ts +12 -3
- package/src/submit.ts +24 -2
- package/src/theme.ts +186 -3
- package/src/tool-common.ts +2 -0
- package/src/tool-delegate.ts +125 -0
- package/src/tool-shell.ts +190 -8
- package/src/tools.ts +335 -6
- package/src/ui/agent.ts +10 -0
- package/src/ui/commands.test.ts +525 -10
- package/src/ui/commands.ts +224 -8
- package/src/ui/conversation.test.ts +252 -27
- package/src/ui/conversation.ts +468 -390
- package/src/ui/help.ts +27 -11
- package/src/ui.ts +230 -75
- package/src/plugins.ts +0 -183
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
|
-
}
|