@adhdev/daemon-core 0.9.76-rc.5 → 0.9.76-rc.51
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/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
- package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
- package/dist/commands/cli-manager.d.ts +17 -4
- package/dist/commands/mesh-coordinator.d.ts +2 -0
- package/dist/commands/router.d.ts +11 -0
- package/dist/config/mesh-config.d.ts +3 -0
- package/dist/git/git-types.d.ts +1 -1
- package/dist/git/git-worktree.d.ts +64 -0
- package/dist/git/index.d.ts +2 -0
- package/dist/index.js +1398 -436
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1425 -467
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +1 -0
- package/dist/mesh/mesh-events.d.ts +9 -0
- package/dist/providers/chat-message-normalization.d.ts +11 -0
- package/dist/providers/cli-provider-instance.d.ts +3 -0
- package/dist/providers/provider-instance-manager.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +2 -0
- package/dist/repo-mesh-types.d.ts +13 -0
- package/dist/shared-types.d.ts +4 -0
- package/package.json +4 -5
- package/src/cli-adapters/provider-cli-adapter.ts +28 -7
- package/src/cli-adapters/provider-cli-runtime.ts +3 -2
- package/src/commands/chat-commands.ts +109 -8
- package/src/commands/cli-manager.ts +78 -5
- package/src/commands/handler.ts +13 -4
- package/src/commands/mesh-coordinator.ts +149 -6
- package/src/commands/router.d.ts +1 -0
- package/src/commands/router.ts +554 -34
- package/src/config/mesh-config.ts +23 -2
- package/src/git/git-commands.ts +5 -1
- package/src/git/git-types.ts +1 -0
- package/src/git/git-worktree.ts +214 -0
- package/src/git/index.ts +14 -0
- package/src/mesh/coordinator-prompt.ts +25 -10
- package/src/mesh/mesh-events.ts +109 -43
- package/src/providers/chat-message-normalization.ts +54 -0
- package/src/providers/cli-provider-instance.d.ts +2 -0
- package/src/providers/cli-provider-instance.ts +58 -7
- package/src/providers/provider-instance-manager.ts +20 -1
- package/src/providers/provider-instance.ts +2 -0
- package/src/repo-mesh-types.ts +15 -0
- package/src/shared-types.ts +4 -0
- package/src/status/builders.ts +17 -12
- package/src/status/reporter.ts +6 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { existsSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
3
|
import { createRequire } from 'node:module'
|
|
3
|
-
import
|
|
4
|
+
import * as os from 'node:os'
|
|
5
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path'
|
|
4
6
|
import type { ProviderModule, MeshCoordinatorMcpConfigFormat } from '../providers/contracts.js'
|
|
5
7
|
|
|
6
8
|
export interface MeshCoordinatorMcpServerLaunch {
|
|
@@ -32,6 +34,7 @@ export type MeshCoordinatorSetup =
|
|
|
32
34
|
|
|
33
35
|
export interface ResolveMeshCoordinatorSetupOptions {
|
|
34
36
|
provider?: ProviderModule | null
|
|
37
|
+
cliType?: string
|
|
35
38
|
meshId: string
|
|
36
39
|
workspace: string
|
|
37
40
|
adhdevMcpCommand?: string
|
|
@@ -41,6 +44,58 @@ export interface ResolveMeshCoordinatorSetupOptions {
|
|
|
41
44
|
|
|
42
45
|
const DEFAULT_SERVER_NAME = 'adhdev-mesh'
|
|
43
46
|
const DEFAULT_ADHDEV_MCP_COMMAND = 'adhdev-mcp'
|
|
47
|
+
const HERMES_CLI_TYPE = 'hermes-cli'
|
|
48
|
+
const HERMES_MCP_CONFIG_PATH = '~/.hermes/config.yaml'
|
|
49
|
+
|
|
50
|
+
function isHermesProvider(provider: ProviderModule | null | undefined, cliType?: string): boolean {
|
|
51
|
+
const type = cliType?.trim() || provider?.type?.trim() || ''
|
|
52
|
+
return type === HERMES_CLI_TYPE
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function resolveHermesMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetupOptions): MeshCoordinatorSetup {
|
|
56
|
+
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
57
|
+
meshId: options.meshId,
|
|
58
|
+
nodeExecutable: options.nodeExecutable,
|
|
59
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
60
|
+
})
|
|
61
|
+
if (!mcpServer) {
|
|
62
|
+
return {
|
|
63
|
+
kind: 'unsupported',
|
|
64
|
+
reason: 'Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode',
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace)
|
|
68
|
+
if (!configPath.trim()) {
|
|
69
|
+
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace)
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
kind: 'auto_import',
|
|
73
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
74
|
+
configPath,
|
|
75
|
+
configFormat: 'hermes_config_yaml',
|
|
76
|
+
mcpServer,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function createHermesManualMeshCoordinatorSetup(meshId: string, workspace: string): MeshCoordinatorSetup {
|
|
81
|
+
return {
|
|
82
|
+
kind: 'manual',
|
|
83
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
84
|
+
configFormat: 'hermes_config_yaml',
|
|
85
|
+
configPathCommand: HERMES_MCP_CONFIG_PATH,
|
|
86
|
+
requiresRestart: true,
|
|
87
|
+
instructions: 'Hermes CLI does not auto-import repo-local .mcp.json. Add this MCP server to Hermes config under mcp_servers, then start a fresh Hermes session.',
|
|
88
|
+
template: renderMeshCoordinatorTemplate(
|
|
89
|
+
'mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n',
|
|
90
|
+
{
|
|
91
|
+
meshId,
|
|
92
|
+
workspace,
|
|
93
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
94
|
+
adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND,
|
|
95
|
+
},
|
|
96
|
+
),
|
|
97
|
+
}
|
|
98
|
+
}
|
|
44
99
|
|
|
45
100
|
export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetupOptions): MeshCoordinatorSetup {
|
|
46
101
|
const { provider, meshId, workspace } = options
|
|
@@ -52,6 +107,10 @@ export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetup
|
|
|
52
107
|
}
|
|
53
108
|
}
|
|
54
109
|
|
|
110
|
+
if (isHermesProvider(provider, options.cliType)) {
|
|
111
|
+
return resolveHermesMeshCoordinatorSetup(options)
|
|
112
|
+
}
|
|
113
|
+
|
|
55
114
|
const mcpConfig = config.mcpConfig
|
|
56
115
|
if (!mcpConfig || mcpConfig.mode === 'none') {
|
|
57
116
|
return {
|
|
@@ -74,13 +133,13 @@ export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetup
|
|
|
74
133
|
if (!mcpServer) {
|
|
75
134
|
return {
|
|
76
135
|
kind: 'unsupported',
|
|
77
|
-
reason: 'Could not resolve the ADHDev MCP server entrypoint
|
|
136
|
+
reason: 'Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode',
|
|
78
137
|
}
|
|
79
138
|
}
|
|
80
139
|
return {
|
|
81
140
|
kind: 'auto_import',
|
|
82
141
|
serverName,
|
|
83
|
-
configPath:
|
|
142
|
+
configPath: resolveMcpConfigPath(path, workspace),
|
|
84
143
|
configFormat: mcpConfig.format,
|
|
85
144
|
mcpServer,
|
|
86
145
|
}
|
|
@@ -118,6 +177,14 @@ function renderMeshCoordinatorTemplate(template: string, values: Record<string,
|
|
|
118
177
|
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key: string) => values[key] || '')
|
|
119
178
|
}
|
|
120
179
|
|
|
180
|
+
function resolveMcpConfigPath(configPath: string, workspace: string): string {
|
|
181
|
+
const trimmed = configPath.trim()
|
|
182
|
+
if (trimmed === '~') return os.homedir()
|
|
183
|
+
if (trimmed.startsWith('~/')) return join(os.homedir(), trimmed.slice(2))
|
|
184
|
+
if (isAbsolute(trimmed)) return trimmed
|
|
185
|
+
return join(workspace, trimmed)
|
|
186
|
+
}
|
|
187
|
+
|
|
121
188
|
function resolveAdhdevMcpServerLaunch(options: {
|
|
122
189
|
meshId: string
|
|
123
190
|
nodeExecutable?: string
|
|
@@ -125,9 +192,85 @@ function resolveAdhdevMcpServerLaunch(options: {
|
|
|
125
192
|
}): MeshCoordinatorMcpServerLaunch | null {
|
|
126
193
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath)
|
|
127
194
|
if (!entryPath) return null
|
|
195
|
+
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable)
|
|
196
|
+
if (!nodeExecutable) return null
|
|
128
197
|
return {
|
|
129
|
-
command:
|
|
130
|
-
args: [entryPath, '--repo-mesh', options.meshId],
|
|
198
|
+
command: nodeExecutable,
|
|
199
|
+
args: [entryPath, '--mode', 'ipc', '--repo-mesh', options.meshId],
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function resolveMcpNodeExecutable(explicitExecutable?: string): string | null {
|
|
204
|
+
const explicit = explicitExecutable?.trim()
|
|
205
|
+
if (explicit) return explicit
|
|
206
|
+
|
|
207
|
+
const candidates: string[] = []
|
|
208
|
+
const addCandidate = (candidate?: string | null) => {
|
|
209
|
+
const trimmed = candidate?.trim()
|
|
210
|
+
if (!trimmed) return
|
|
211
|
+
const normalized = normalizeExistingPath(trimmed) || trimmed
|
|
212
|
+
if (!candidates.includes(normalized)) candidates.push(normalized)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE)
|
|
216
|
+
addCandidate(process.env.ADHDEV_NODE_EXECUTABLE)
|
|
217
|
+
addCandidate(process.env.npm_node_execpath)
|
|
218
|
+
addNodeCandidatesFromPath(process.env.PATH, addCandidate)
|
|
219
|
+
addNodeCandidatesFromNvm(os.homedir(), addCandidate)
|
|
220
|
+
addCandidate('/opt/homebrew/bin/node')
|
|
221
|
+
addCandidate('/usr/local/bin/node')
|
|
222
|
+
addCandidate('/usr/bin/node')
|
|
223
|
+
addCandidate(process.execPath)
|
|
224
|
+
|
|
225
|
+
for (const candidate of candidates) {
|
|
226
|
+
if (nodeRuntimeSupportsWebSocket(candidate)) return candidate
|
|
227
|
+
}
|
|
228
|
+
return null
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function addNodeCandidatesFromPath(pathValue: string | undefined, addCandidate: (candidate?: string | null) => void) {
|
|
232
|
+
for (const entry of (pathValue || '').split(':')) {
|
|
233
|
+
const dir = entry.trim()
|
|
234
|
+
if (!dir) continue
|
|
235
|
+
addCandidate(join(dir, 'node'))
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function addNodeCandidatesFromNvm(homeDir: string, addCandidate: (candidate?: string | null) => void) {
|
|
240
|
+
const versionsDir = join(homeDir, '.nvm', 'versions', 'node')
|
|
241
|
+
try {
|
|
242
|
+
const versionDirs = readdirSync(versionsDir, { withFileTypes: true })
|
|
243
|
+
.filter((entry) => entry.isDirectory())
|
|
244
|
+
.map((entry) => entry.name)
|
|
245
|
+
.sort(compareNodeVersionNamesDescending)
|
|
246
|
+
for (const versionDir of versionDirs) {
|
|
247
|
+
addCandidate(join(versionsDir, versionDir, 'bin', 'node'))
|
|
248
|
+
}
|
|
249
|
+
} catch {
|
|
250
|
+
// nvm is optional; PATH and process.execPath candidates still cover normal installs.
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function compareNodeVersionNamesDescending(a: string, b: string): number {
|
|
255
|
+
const parse = (value: string) => value.replace(/^v/, '').split('.').map((part) => Number.parseInt(part, 10) || 0)
|
|
256
|
+
const left = parse(a)
|
|
257
|
+
const right = parse(b)
|
|
258
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
259
|
+
const diff = (right[i] || 0) - (left[i] || 0)
|
|
260
|
+
if (diff !== 0) return diff
|
|
261
|
+
}
|
|
262
|
+
return b.localeCompare(a)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function nodeRuntimeSupportsWebSocket(nodeExecutable: string): boolean {
|
|
266
|
+
try {
|
|
267
|
+
execFileSync(nodeExecutable, ['-e', "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
|
|
268
|
+
stdio: 'ignore',
|
|
269
|
+
timeout: 3000,
|
|
270
|
+
})
|
|
271
|
+
return true
|
|
272
|
+
} catch {
|
|
273
|
+
return false
|
|
131
274
|
}
|
|
132
275
|
}
|
|
133
276
|
|
package/src/commands/router.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface SessionHostControlPlane {
|
|
|
21
21
|
}): Promise<any>;
|
|
22
22
|
listSessions(): Promise<any[]>;
|
|
23
23
|
stopSession(sessionId: string): Promise<any>;
|
|
24
|
+
deleteSession(sessionId: string, opts?: { force?: boolean }): Promise<any>;
|
|
24
25
|
resumeSession(sessionId: string): Promise<any>;
|
|
25
26
|
restartSession(sessionId: string): Promise<any>;
|
|
26
27
|
sendSignal(sessionId: string, signal: string): Promise<any>;
|