@miphamai/cli 0.6.5 → 0.6.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miphamai/cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Mipham Code — Multi-model open-core intelligent coding terminal by MiphamAI",
5
5
  "keywords": [
6
6
  "ai",
package/src/index.tsx CHANGED
@@ -9,9 +9,11 @@ import { QueryEngine } from './core/engine'
9
9
  import { SessionStore } from './core/session-store'
10
10
  import { SkillsLoader } from './skills/loader'
11
11
  import { PluginManager } from './plugin/plugin-manager'
12
+ import { loadPlugins } from './plugin/plugin-loader'
12
13
  import { createToolRegistry } from './tools'
13
14
  import { McpClient } from './mcp/client'
14
15
  import { registerMcpServerTools } from './mcp/registry'
16
+ import { AgentRegistry } from './agent/agent-registry'
15
17
  import { HookEngine } from './core/hooks'
16
18
  import { ArtifactServer } from './artifacts/server'
17
19
  import { ARTIFACTS_DIR, ARTIFACT_PORT, MIPHAM_DIR } from './shared/constants'
@@ -142,6 +144,22 @@ export async function runApp(options: RunOptions): Promise<void> {
142
144
  engine.setArtifactServer(artifactServer)
143
145
  engine.setAgentViewManager(agentViewManager)
144
146
  engine.setSkillsLoader(skillsLoader)
147
+
148
+ // Initialize agent registry and load plugin agents/skills/MCP/hooks
149
+ const agentRegistry = new AgentRegistry()
150
+ agentRegistry.loadUserAgents()
151
+ agentRegistry.loadProjectAgents(process.cwd())
152
+ engine.setAgentRegistry(agentRegistry)
153
+
154
+ loadPlugins(
155
+ pluginManager,
156
+ agentRegistry,
157
+ skillsLoader,
158
+ hookEngine,
159
+ McpClient.getInstance(),
160
+ tools,
161
+ )
162
+
145
163
  engine.setupContextSummarizer()
146
164
 
147
165
  // Auto-save session on exit
@@ -1,36 +1,105 @@
1
- import type { PluginManager } from './plugin-manager'
2
1
  import { join } from 'node:path'
3
- import { existsSync } from 'node:fs'
2
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
3
+ import type { PluginManager } from './plugin-manager'
4
+ import type { AgentRegistry } from '../agent/agent-registry'
5
+ import type { SkillsLoader } from '../skills/loader'
6
+ import type { HookEngine } from '../core/hooks'
7
+ import type { McpClient } from '../mcp/client'
8
+ import { registerMcpServerTools } from '../mcp/registry'
9
+ import type { McpServerConfig, ToolDefinition, HookDefinition } from '../shared/types'
4
10
 
11
+ /**
12
+ * Activate all enabled plugins — load their agents, skills, MCP servers, and hooks.
13
+ *
14
+ * Called once at startup after the core subsystems (agent registry, skills loader,
15
+ * hook engine, MCP client, tool registry) are initialized.
16
+ */
5
17
  export function loadPlugins(
6
18
  pluginManager: PluginManager,
7
- engine: unknown,
8
- skillsLoader: unknown,
19
+ agentRegistry: AgentRegistry,
20
+ skillsLoader: SkillsLoader,
21
+ hookEngine: HookEngine,
22
+ mcpClient: McpClient,
23
+ toolsMap: Map<string, ToolDefinition>,
9
24
  ): void {
10
25
  for (const plugin of pluginManager.getEnabled()) {
11
- // Load custom agents
26
+ // ── Custom agents ──
12
27
  const agentsDir = join(plugin.path, 'agents')
13
28
  if (existsSync(agentsDir)) {
14
- // → register with AgentRegistry
29
+ try {
30
+ agentRegistry.loadDirectory(agentsDir, 'user')
31
+ } catch (err) {
32
+ process.stderr.write(
33
+ `[plugin] Failed to load agents from "${plugin.name}": ${String(err)}\n`,
34
+ )
35
+ }
15
36
  }
16
37
 
17
- // Load custom skills
38
+ // ── Custom skills ──
18
39
  const skillsDir = join(plugin.path, 'skills')
19
40
  if (existsSync(skillsDir)) {
20
- // → register with SkillsLoader
41
+ try {
42
+ skillsLoader.loadExternal([skillsDir])
43
+ } catch (err) {
44
+ process.stderr.write(
45
+ `[plugin] Failed to load skills from "${plugin.name}": ${String(err)}\n`,
46
+ )
47
+ }
21
48
  }
22
49
 
23
- // Load MCP servers
50
+ // ── MCP servers ──
24
51
  const mcpDir = join(plugin.path, 'mcp-servers')
25
52
  if (existsSync(mcpDir)) {
26
- // → register MCP configs
53
+ try {
54
+ const entries = readdirSync(mcpDir)
55
+ for (const entry of entries) {
56
+ if (!entry.endsWith('.json')) continue
57
+ try {
58
+ const raw = readFileSync(join(mcpDir, entry), 'utf-8')
59
+ const cfg = JSON.parse(raw) as McpServerConfig
60
+ if (cfg.name && cfg.command) {
61
+ mcpClient
62
+ .connect(cfg)
63
+ .then(() => {
64
+ const count = registerMcpServerTools(cfg.name, toolsMap)
65
+ if (count > 0) {
66
+ process.stderr.write(
67
+ `[plugin] "${plugin.name}": registered ${count} MCP tools from "${cfg.name}"\n`,
68
+ )
69
+ }
70
+ })
71
+ .catch((err: unknown) => {
72
+ process.stderr.write(
73
+ `[plugin] Failed to connect MCP "${cfg.name}" from "${plugin.name}": ${String(err)}\n`,
74
+ )
75
+ })
76
+ }
77
+ } catch {
78
+ // skip unparseable MCP config files
79
+ }
80
+ }
81
+ } catch (err) {
82
+ process.stderr.write(
83
+ `[plugin] Failed to load MCP configs from "${plugin.name}": ${String(err)}\n`,
84
+ )
85
+ }
27
86
  }
28
87
 
29
- // Load hooks
30
- // → parse plugin.json hooks → register with HookEngine
88
+ // ── Hooks from plugin.json ──
89
+ try {
90
+ const manifestPath = join(plugin.path, 'plugin.json')
91
+ if (existsSync(manifestPath)) {
92
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'))
93
+ if (manifest.hooks && Array.isArray(manifest.hooks)) {
94
+ for (const hook of manifest.hooks as HookDefinition[]) {
95
+ if (hook.event) {
96
+ hookEngine.register(hook)
97
+ }
98
+ }
99
+ }
100
+ }
101
+ } catch (err) {
102
+ process.stderr.write(`[plugin] Failed to load hooks from "${plugin.name}": ${String(err)}\n`)
103
+ }
31
104
  }
32
-
33
- // Suppress unused parameter warnings — these are wiring stubs for future phases
34
- void engine
35
- void skillsLoader
36
105
  }
package/src/ui/app.tsx CHANGED
@@ -97,10 +97,14 @@ export function App({
97
97
 
98
98
  // Initialize agent registry (one-time, on mount)
99
99
  useMemo(() => {
100
- const agentRegistry = new AgentRegistry()
101
- agentRegistry.loadUserAgents()
102
- agentRegistry.loadProjectAgents(process.cwd())
103
- engine.setAgentRegistry(agentRegistry)
100
+ // Agent registry may already be initialized in index.tsx (for plugin loading).
101
+ // Only create a fresh one if not already set on the engine.
102
+ if (!engine.getAgentRegistry()) {
103
+ const agentRegistry = new AgentRegistry()
104
+ agentRegistry.loadUserAgents()
105
+ agentRegistry.loadProjectAgents(process.cwd())
106
+ engine.setAgentRegistry(agentRegistry)
107
+ }
104
108
  }, [])
105
109
 
106
110
  const mkCtx = useCallback(