@adhdev/daemon-core 0.9.82-rc.363 → 0.9.82-rc.365

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.
@@ -0,0 +1,163 @@
1
+ /**
2
+ * RF-ROUTER MED family — IDE lifecycle + provider/IDE detection commands.
3
+ *
4
+ * stop_ide, restart_ide, launch_ide, detect_provider, detect_ides. launch_ide
5
+ * spawns the IDE, connects CDP, registers extension providers and refreshes
6
+ * detection. restart_ide stops (with kill) then launches.
7
+ *
8
+ * launch_ide self-recursion: the original case bodies for restart_session
9
+ * (cli-agent family) and restart_ide re-entered `executeDaemonCommand('launch_ide')`.
10
+ * Lifting the launch_ide body into the module-level `launchIde(ctx, args)` helper
11
+ * lets those handlers invoke the launch directly (ctx.launchIde) without recursing
12
+ * back through the registry, while the launch_ide handler simply delegates to it.
13
+ */
14
+ import { DaemonCdpManager } from '../../cdp/manager.js';
15
+ import { registerExtensionProviders } from '../../cdp/setup.js';
16
+ import { launchWithCdp } from '../../launch.js';
17
+ import { loadConfig } from '../../config/config.js';
18
+ import { loadState, saveState } from '../../config/state-store.js';
19
+ import { resolveIdeLaunchWorkspace } from '../../config/workspaces.js';
20
+ import { appendRecentActivity } from '../../config/recent-activity.js';
21
+ import { detectIDEs } from '../../detection/ide-detector.js';
22
+ import { detectCLI } from '../../detection/cli-detector.js';
23
+ import { LOG } from '../../logging/logger.js';
24
+ import type { CommandRouterResult } from '../router.js';
25
+ import type { MedFamilyContext, MedFamilyHandler } from './types.js';
26
+
27
+ /**
28
+ * IDE launch + CDP connect. Lifted verbatim from the original `launch_ide` switch
29
+ * case so restart_session / restart_ide can call it directly instead of recursing
30
+ * through executeDaemonCommand. Reads the router's CDP managers and detection
31
+ * caches via ctx.deps.
32
+ */
33
+ export async function launchIde(ctx: MedFamilyContext, args: any): Promise<CommandRouterResult> {
34
+ const ideKey = args?.ideId || args?.ideType;
35
+ const resolvedWorkspace = resolveIdeLaunchWorkspace(
36
+ {
37
+ workspace: args?.workspace,
38
+ workspaceId: args?.workspaceId,
39
+ useDefaultWorkspace: args?.useDefaultWorkspace,
40
+ },
41
+ loadConfig(),
42
+ );
43
+ const launchArgs = {
44
+ ideId: ideKey,
45
+ workspace: resolvedWorkspace,
46
+ newWindow: args?.newWindow,
47
+ };
48
+ LOG.info('LaunchIDE', `target=${ideKey || 'auto'}`);
49
+ const result = await launchWithCdp(launchArgs);
50
+
51
+ if (result.success && result.port && result.ideId && !ctx.deps.cdpManagers.has(result.ideId)) {
52
+ const logFn = ctx.deps.getCdpLogFn
53
+ ? ctx.deps.getCdpLogFn(result.ideId)
54
+ : LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
55
+ const provider = ctx.deps.providerLoader.getMeta(result.ideId);
56
+ const manager = new DaemonCdpManager(result.port, logFn, undefined, provider?.targetFilter);
57
+ const connected = await manager.connect();
58
+ if (connected) {
59
+ // Register active extension providers for this IDE in CDP manager
60
+ registerExtensionProviders(ctx.deps.providerLoader, manager, result.ideId);
61
+ ctx.deps.cdpManagers.set(result.ideId, manager);
62
+ LOG.info('CDP', `Connected: ${result.ideId} (port ${result.port})`);
63
+ LOG.info('CDP', `${ctx.deps.cdpManagers.size} IDE(s) connected`);
64
+
65
+ // Notify consumer (e.g. setupIdeInstance)
66
+ ctx.deps.onCdpManagerCreated?.(result.ideId, manager);
67
+ }
68
+ }
69
+ ctx.deps.onIdeConnected?.();
70
+ try {
71
+ const results = await detectIDEs(ctx.deps.providerLoader);
72
+ ctx.deps.detectedIdes.value = results;
73
+ ctx.deps.providerLoader.setIdeDetectionResults(results, true);
74
+ } catch { /* ignore detection refresh errors */ }
75
+ if (result.success && resolvedWorkspace) {
76
+ try {
77
+ const next = appendRecentActivity(loadState(), {
78
+ kind: 'ide',
79
+ providerType: result.ideId || ideKey,
80
+ providerName: result.ideId || ideKey,
81
+ workspace: resolvedWorkspace,
82
+ title: result.ideId || ideKey,
83
+ });
84
+ saveState(next);
85
+ } catch { /* ignore activity persist errors */ }
86
+ } else if (result.success && (result.ideId || ideKey)) {
87
+ try {
88
+ saveState(appendRecentActivity(loadState(), {
89
+ kind: 'ide',
90
+ providerType: result.ideId || ideKey,
91
+ providerName: result.ideId || ideKey,
92
+ title: result.ideId || ideKey,
93
+ }));
94
+ } catch { /* ignore activity persist errors */ }
95
+ }
96
+ return { ...result };
97
+ }
98
+
99
+ export const ideHandlers: Record<string, MedFamilyHandler> = {
100
+ // ─── IDE stop ───
101
+ stop_ide: async (ctx: MedFamilyContext, args: any) => {
102
+ const ideType = args?.ideType;
103
+ if (!ideType) throw new Error('ideType required');
104
+ const killProcess = args?.killProcess !== false; // default true
105
+ await ctx.stopIde(ideType, killProcess);
106
+ try {
107
+ const results = await detectIDEs(ctx.deps.providerLoader);
108
+ ctx.deps.detectedIdes.value = results;
109
+ ctx.deps.providerLoader.setIdeDetectionResults(results, true);
110
+ } catch { /* ignore detection refresh errors */ }
111
+ return { success: true, ideType, stopped: true, processKilled: killProcess };
112
+ },
113
+
114
+ // ─── IDE restart ───
115
+ restart_ide: async (ctx: MedFamilyContext, args: any) => {
116
+ const ideType = args?.ideType;
117
+ if (!ideType) throw new Error('ideType required');
118
+ await ctx.stopIde(ideType, true); // always kill process on restart
119
+ const launchResult = await ctx.launchIde({ ideType, enableCdp: true, workspace: args?.workspace });
120
+ return { success: true, ideType, restarted: true, launch: launchResult };
121
+ },
122
+
123
+ // ─── IDE launch + CDP connect ───
124
+ launch_ide: async (ctx: MedFamilyContext, args: any) => {
125
+ return launchIde(ctx, args);
126
+ },
127
+
128
+ // ─── Detect providers ───
129
+ detect_provider: async (ctx: MedFamilyContext, args: any) => {
130
+ const providerType = typeof args?.providerType === 'string' ? args.providerType.trim() : '';
131
+ if (!providerType) return { success: false, error: 'providerType is required' };
132
+ const normalizedType = ctx.deps.providerLoader.resolveAlias(providerType);
133
+ const provider = ctx.deps.providerLoader.getByAlias(providerType);
134
+ if (!provider) return { success: false, error: `Provider not found: ${providerType}` };
135
+ if (provider.category !== 'cli' && provider.category !== 'acp') {
136
+ return { success: false, error: `Provider detection is only supported for CLI/ACP providers: ${providerType}` };
137
+ }
138
+ if (!ctx.deps.providerLoader.isMachineProviderEnabled(normalizedType)) {
139
+ return { success: false, error: `Provider is disabled on this machine: ${providerType}` };
140
+ }
141
+ const detected = await detectCLI(normalizedType, ctx.deps.providerLoader, { includeVersion: false });
142
+ ctx.deps.providerLoader.setCliDetectionResults([{
143
+ id: normalizedType,
144
+ installed: !!detected,
145
+ path: detected?.path,
146
+ }], false);
147
+ ctx.deps.onStatusChange?.();
148
+ return {
149
+ success: true,
150
+ providerType: normalizedType,
151
+ detected: !!detected,
152
+ path: detected?.path || null,
153
+ };
154
+ },
155
+
156
+ // ─── Detect IDEs ───
157
+ detect_ides: async (ctx: MedFamilyContext, _args: any) => {
158
+ const results = await detectIDEs(ctx.deps.providerLoader);
159
+ ctx.deps.detectedIdes.value = results;
160
+ ctx.deps.providerLoader.setIdeDetectionResults(results, true);
161
+ return { success: true, detectedInfo: results };
162
+ },
163
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * RF-ROUTER MED family — command registry.
3
+ *
4
+ * Aggregates the medium-coupling command handlers extracted from
5
+ * DaemonCommandRouter.executeDaemonCommand into a single cmd → handler map. The
6
+ * router consults this registry after the LOW-family registry and before its
7
+ * switch (registry hit → return the handler result; miss → fall through to the
8
+ * remaining switch / CommandHandler delegation), so the facade and dispatch
9
+ * semantics are unchanged.
10
+ *
11
+ * MED handlers differ from LOW handlers in that they need router-private
12
+ * collaborators (mesh resolution, owner gating, inline-cache mutation, worktree /
13
+ * session cleanup, refine job starters, IDE launch). The router binds those onto
14
+ * MedFamilyContext at dispatch — see types.ts.
15
+ */
16
+ import { cliAgentHandlers } from './cli-agent.js';
17
+ import { ideHandlers } from './ide.js';
18
+ import { meshCrudHandlers } from './mesh-crud.js';
19
+ import { meshHostPairingHandlers } from './mesh-host-pairing.js';
20
+ import { meshQueueHandlers } from './mesh-queue.js';
21
+ import { fastForwardHandlers } from './fast-forward.js';
22
+ import type { MedFamilyRegistry } from './types.js';
23
+
24
+ export type { MedFamilyContext, MedFamilyHandler, MedFamilyRegistry } from './types.js';
25
+
26
+ export const medFamilyRegistry: MedFamilyRegistry = new Map(
27
+ Object.entries({
28
+ ...cliAgentHandlers,
29
+ ...ideHandlers,
30
+ ...meshCrudHandlers,
31
+ ...meshHostPairingHandlers,
32
+ ...meshQueueHandlers,
33
+ ...fastForwardHandlers,
34
+ }),
35
+ );