@adhdev/daemon-core 0.9.76-rc.12 → 0.9.76-rc.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/dist/index.js +67 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/mesh-coordinator.ts +80 -3
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
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
4
|
import * as os from 'node:os'
|
|
4
5
|
import { dirname, isAbsolute, join, resolve } from 'node:path'
|
|
@@ -75,7 +76,7 @@ export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetup
|
|
|
75
76
|
if (!mcpServer) {
|
|
76
77
|
return {
|
|
77
78
|
kind: 'unsupported',
|
|
78
|
-
reason: 'Could not resolve the ADHDev MCP server entrypoint
|
|
79
|
+
reason: 'Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode',
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
return {
|
|
@@ -134,12 +135,88 @@ function resolveAdhdevMcpServerLaunch(options: {
|
|
|
134
135
|
}): MeshCoordinatorMcpServerLaunch | null {
|
|
135
136
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath)
|
|
136
137
|
if (!entryPath) return null
|
|
138
|
+
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable)
|
|
139
|
+
if (!nodeExecutable) return null
|
|
137
140
|
return {
|
|
138
|
-
command:
|
|
141
|
+
command: nodeExecutable,
|
|
139
142
|
args: [entryPath, '--mode', 'ipc', '--repo-mesh', options.meshId],
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
|
|
146
|
+
function resolveMcpNodeExecutable(explicitExecutable?: string): string | null {
|
|
147
|
+
const explicit = explicitExecutable?.trim()
|
|
148
|
+
if (explicit) return explicit
|
|
149
|
+
|
|
150
|
+
const candidates: string[] = []
|
|
151
|
+
const addCandidate = (candidate?: string | null) => {
|
|
152
|
+
const trimmed = candidate?.trim()
|
|
153
|
+
if (!trimmed) return
|
|
154
|
+
const normalized = normalizeExistingPath(trimmed) || trimmed
|
|
155
|
+
if (!candidates.includes(normalized)) candidates.push(normalized)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE)
|
|
159
|
+
addCandidate(process.env.ADHDEV_NODE_EXECUTABLE)
|
|
160
|
+
addCandidate(process.env.npm_node_execpath)
|
|
161
|
+
addNodeCandidatesFromPath(process.env.PATH, addCandidate)
|
|
162
|
+
addNodeCandidatesFromNvm(os.homedir(), addCandidate)
|
|
163
|
+
addCandidate('/opt/homebrew/bin/node')
|
|
164
|
+
addCandidate('/usr/local/bin/node')
|
|
165
|
+
addCandidate('/usr/bin/node')
|
|
166
|
+
addCandidate(process.execPath)
|
|
167
|
+
|
|
168
|
+
for (const candidate of candidates) {
|
|
169
|
+
if (nodeRuntimeSupportsWebSocket(candidate)) return candidate
|
|
170
|
+
}
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function addNodeCandidatesFromPath(pathValue: string | undefined, addCandidate: (candidate?: string | null) => void) {
|
|
175
|
+
for (const entry of (pathValue || '').split(':')) {
|
|
176
|
+
const dir = entry.trim()
|
|
177
|
+
if (!dir) continue
|
|
178
|
+
addCandidate(join(dir, 'node'))
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function addNodeCandidatesFromNvm(homeDir: string, addCandidate: (candidate?: string | null) => void) {
|
|
183
|
+
const versionsDir = join(homeDir, '.nvm', 'versions', 'node')
|
|
184
|
+
try {
|
|
185
|
+
const versionDirs = readdirSync(versionsDir, { withFileTypes: true })
|
|
186
|
+
.filter((entry) => entry.isDirectory())
|
|
187
|
+
.map((entry) => entry.name)
|
|
188
|
+
.sort(compareNodeVersionNamesDescending)
|
|
189
|
+
for (const versionDir of versionDirs) {
|
|
190
|
+
addCandidate(join(versionsDir, versionDir, 'bin', 'node'))
|
|
191
|
+
}
|
|
192
|
+
} catch {
|
|
193
|
+
// nvm is optional; PATH and process.execPath candidates still cover normal installs.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function compareNodeVersionNamesDescending(a: string, b: string): number {
|
|
198
|
+
const parse = (value: string) => value.replace(/^v/, '').split('.').map((part) => Number.parseInt(part, 10) || 0)
|
|
199
|
+
const left = parse(a)
|
|
200
|
+
const right = parse(b)
|
|
201
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
202
|
+
const diff = (right[i] || 0) - (left[i] || 0)
|
|
203
|
+
if (diff !== 0) return diff
|
|
204
|
+
}
|
|
205
|
+
return b.localeCompare(a)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function nodeRuntimeSupportsWebSocket(nodeExecutable: string): boolean {
|
|
209
|
+
try {
|
|
210
|
+
execFileSync(nodeExecutable, ['-e', "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
|
|
211
|
+
stdio: 'ignore',
|
|
212
|
+
timeout: 3000,
|
|
213
|
+
})
|
|
214
|
+
return true
|
|
215
|
+
} catch {
|
|
216
|
+
return false
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
143
220
|
function resolveAdhdevMcpEntryPath(explicitPath?: string): string | null {
|
|
144
221
|
const explicit = explicitPath?.trim()
|
|
145
222
|
if (explicit) return normalizeExistingPath(explicit) || explicit
|