@adhdev/daemon-core 0.9.2 → 0.9.4
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/commands/upgrade-helper.d.ts +21 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +97 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -15
- package/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +0 -5
- package/src/commands/upgrade-helper.ts +128 -9
- package/src/index.d.ts +2 -2
- package/src/index.ts +11 -2
package/package.json
CHANGED
|
@@ -1962,11 +1962,6 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1962
1962
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
1963
1963
|
}
|
|
1964
1964
|
}
|
|
1965
|
-
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || '');
|
|
1966
|
-
if (blockingModal || this.currentStatus === 'waiting_approval') {
|
|
1967
|
-
throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
|
|
1968
|
-
}
|
|
1969
|
-
|
|
1970
1965
|
this.isWaitingForResponse = true;
|
|
1971
1966
|
this.responseBuffer = '';
|
|
1972
1967
|
this.finishRetryCount = 0;
|
|
@@ -15,6 +15,18 @@ export interface DaemonUpgradeHelperPayload {
|
|
|
15
15
|
sessionHostAppName?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export interface CurrentGlobalInstallSurface {
|
|
19
|
+
npmExecutable: string;
|
|
20
|
+
packageRoot: string | null;
|
|
21
|
+
installPrefix: string | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface PinnedGlobalInstallCommand {
|
|
25
|
+
command: string;
|
|
26
|
+
args: string[];
|
|
27
|
+
surface: CurrentGlobalInstallSurface;
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
function getUpgradeLogPath(): string {
|
|
19
31
|
const home = os.homedir();
|
|
20
32
|
const dir = path.join(home, '.adhdev');
|
|
@@ -31,10 +43,107 @@ function appendUpgradeLog(message: string): void {
|
|
|
31
43
|
}
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
function
|
|
46
|
+
function resolveSiblingNpmExecutable(nodeExecutable: string): string {
|
|
47
|
+
const binDir = path.dirname(nodeExecutable);
|
|
48
|
+
const candidates = process.platform === 'win32'
|
|
49
|
+
? ['npm.cmd', 'npm.exe', 'npm']
|
|
50
|
+
: ['npm'];
|
|
51
|
+
for (const candidate of candidates) {
|
|
52
|
+
const candidatePath = path.join(binDir, candidate);
|
|
53
|
+
if (fs.existsSync(candidatePath)) {
|
|
54
|
+
return candidatePath;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
35
57
|
return 'npm';
|
|
36
58
|
}
|
|
37
59
|
|
|
60
|
+
function findCurrentPackageRoot(currentCliPath: string | undefined, packageName: string): string | null {
|
|
61
|
+
if (!currentCliPath) return null;
|
|
62
|
+
|
|
63
|
+
let resolvedPath = currentCliPath;
|
|
64
|
+
try {
|
|
65
|
+
resolvedPath = fs.realpathSync.native(currentCliPath);
|
|
66
|
+
} catch {
|
|
67
|
+
// keep the original path when realpath is unavailable
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let currentDir = resolvedPath;
|
|
71
|
+
try {
|
|
72
|
+
if (fs.statSync(resolvedPath).isFile()) {
|
|
73
|
+
currentDir = path.dirname(resolvedPath);
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
currentDir = path.dirname(resolvedPath);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
while (true) {
|
|
80
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
83
|
+
const parsed = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
84
|
+
if (parsed?.name === packageName) {
|
|
85
|
+
const normalized = currentDir.replace(/\\/g, '/');
|
|
86
|
+
return normalized.includes('/node_modules/') ? currentDir : null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// ignore malformed package metadata while scanning upward
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parentDir = path.dirname(currentDir);
|
|
94
|
+
if (parentDir === currentDir) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
currentDir = parentDir;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resolveInstallPrefixFromPackageRoot(packageRoot: string, packageName: string): string | null {
|
|
102
|
+
const nodeModulesDir = packageName.startsWith('@')
|
|
103
|
+
? path.dirname(path.dirname(packageRoot))
|
|
104
|
+
: path.dirname(packageRoot);
|
|
105
|
+
if (path.basename(nodeModulesDir) !== 'node_modules') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const maybeLibDir = path.dirname(nodeModulesDir);
|
|
110
|
+
if (path.basename(maybeLibDir) === 'lib') {
|
|
111
|
+
return path.dirname(maybeLibDir);
|
|
112
|
+
}
|
|
113
|
+
return maybeLibDir;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function resolveCurrentGlobalInstallSurface(options: {
|
|
117
|
+
packageName: string;
|
|
118
|
+
currentCliPath?: string;
|
|
119
|
+
nodeExecutable?: string;
|
|
120
|
+
}): CurrentGlobalInstallSurface {
|
|
121
|
+
const packageRoot = findCurrentPackageRoot(options.currentCliPath || process.argv[1], options.packageName);
|
|
122
|
+
return {
|
|
123
|
+
npmExecutable: resolveSiblingNpmExecutable(options.nodeExecutable || process.execPath),
|
|
124
|
+
packageRoot,
|
|
125
|
+
installPrefix: packageRoot ? resolveInstallPrefixFromPackageRoot(packageRoot, options.packageName) : null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function buildPinnedGlobalInstallCommand(options: {
|
|
130
|
+
packageName: string;
|
|
131
|
+
targetVersion: string;
|
|
132
|
+
currentCliPath?: string;
|
|
133
|
+
nodeExecutable?: string;
|
|
134
|
+
}): PinnedGlobalInstallCommand {
|
|
135
|
+
const surface = resolveCurrentGlobalInstallSurface(options);
|
|
136
|
+
const args = ['install', '-g', `${options.packageName}@${options.targetVersion || 'latest'}`, '--force'];
|
|
137
|
+
if (surface.installPrefix) {
|
|
138
|
+
args.push('--prefix', surface.installPrefix);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
command: surface.npmExecutable,
|
|
142
|
+
args,
|
|
143
|
+
surface,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
38
147
|
function getNpmExecOptions(): { shell: boolean } {
|
|
39
148
|
return { shell: process.platform === 'win32' };
|
|
40
149
|
}
|
|
@@ -107,11 +216,13 @@ function removeDaemonPidFile(): void {
|
|
|
107
216
|
}
|
|
108
217
|
}
|
|
109
218
|
|
|
110
|
-
function cleanupStaleGlobalInstallDirs(pkgName: string): void {
|
|
219
|
+
function cleanupStaleGlobalInstallDirs(pkgName: string, surface: CurrentGlobalInstallSurface): void {
|
|
111
220
|
const npmExecOpts = getNpmExecOptions();
|
|
112
|
-
const
|
|
221
|
+
const prefixArgs = surface.installPrefix ? ['--prefix', surface.installPrefix] : [];
|
|
222
|
+
const npmRoot = execFileSync(surface.npmExecutable, ['root', '-g', ...prefixArgs], { encoding: 'utf8', ...npmExecOpts }).trim();
|
|
113
223
|
if (!npmRoot) return;
|
|
114
|
-
const npmPrefix =
|
|
224
|
+
const npmPrefix = surface.installPrefix
|
|
225
|
+
|| execFileSync(surface.npmExecutable, ['prefix', '-g', ...prefixArgs], { encoding: 'utf8', ...npmExecOpts }).trim();
|
|
115
226
|
const binDir = process.platform === 'win32' ? npmPrefix : path.join(npmPrefix, 'bin');
|
|
116
227
|
const packageBaseName = pkgName.startsWith('@') ? pkgName.split('/')[1] : pkgName;
|
|
117
228
|
const binNames = new Set<string>([packageBaseName]);
|
|
@@ -138,7 +249,7 @@ function cleanupStaleGlobalInstallDirs(pkgName: string): void {
|
|
|
138
249
|
|
|
139
250
|
if (fs.existsSync(binDir)) {
|
|
140
251
|
for (const entry of fs.readdirSync(binDir)) {
|
|
141
|
-
if (!
|
|
252
|
+
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
142
253
|
fs.rmSync(path.join(binDir, entry), { recursive: true, force: true });
|
|
143
254
|
appendUpgradeLog(`Removed stale bin staging entry: ${path.join(binDir, entry)}`);
|
|
144
255
|
}
|
|
@@ -160,7 +271,15 @@ export function spawnDetachedDaemonUpgradeHelper(payload: DaemonUpgradeHelperPay
|
|
|
160
271
|
async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Promise<void> {
|
|
161
272
|
const restartArgv = Array.isArray(payload.restartArgv) ? payload.restartArgv : [];
|
|
162
273
|
const sessionHostAppName = payload.sessionHostAppName || process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';
|
|
274
|
+
const installCommand = buildPinnedGlobalInstallCommand({
|
|
275
|
+
packageName: payload.packageName,
|
|
276
|
+
targetVersion: payload.targetVersion,
|
|
277
|
+
});
|
|
163
278
|
appendUpgradeLog(`Upgrade helper started for ${payload.packageName}@${payload.targetVersion}`);
|
|
279
|
+
appendUpgradeLog(`Using npm executable: ${installCommand.command}`);
|
|
280
|
+
if (installCommand.surface.installPrefix) {
|
|
281
|
+
appendUpgradeLog(`Pinned install prefix: ${installCommand.surface.installPrefix}`);
|
|
282
|
+
}
|
|
164
283
|
|
|
165
284
|
if (Number.isFinite(payload.parentPid) && payload.parentPid > 0) {
|
|
166
285
|
appendUpgradeLog(`Waiting for parent pid ${payload.parentPid} to exit`);
|
|
@@ -169,13 +288,13 @@ async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Prom
|
|
|
169
288
|
|
|
170
289
|
stopSessionHostProcesses(sessionHostAppName);
|
|
171
290
|
removeDaemonPidFile();
|
|
172
|
-
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
291
|
+
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
173
292
|
|
|
174
293
|
const spec = `${payload.packageName}@${payload.targetVersion || 'latest'}`;
|
|
175
294
|
appendUpgradeLog(`Installing ${spec}`);
|
|
176
295
|
const installOutput = execFileSync(
|
|
177
|
-
|
|
178
|
-
|
|
296
|
+
installCommand.command,
|
|
297
|
+
installCommand.args,
|
|
179
298
|
{
|
|
180
299
|
encoding: 'utf8',
|
|
181
300
|
stdio: 'pipe',
|
|
@@ -192,7 +311,7 @@ async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Prom
|
|
|
192
311
|
// processes have exited.
|
|
193
312
|
if (process.platform === 'win32') {
|
|
194
313
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
195
|
-
cleanupStaleGlobalInstallDirs(payload.packageName);
|
|
314
|
+
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
196
315
|
appendUpgradeLog('Post-install staging cleanup complete');
|
|
197
316
|
}
|
|
198
317
|
|
package/src/index.d.ts
CHANGED
|
@@ -41,8 +41,8 @@ export { DaemonCommandHandler } from './commands/handler.js';
|
|
|
41
41
|
export type { CommandResult, CommandContext } from './commands/handler.js';
|
|
42
42
|
export { DaemonCommandRouter } from './commands/router.js';
|
|
43
43
|
export type { CommandRouterDeps, CommandRouterResult } from './commands/router.js';
|
|
44
|
-
export { maybeRunDaemonUpgradeHelperFromEnv, spawnDetachedDaemonUpgradeHelper } from './commands/upgrade-helper.js';
|
|
45
|
-
export type { DaemonUpgradeHelperPayload } from './commands/upgrade-helper.js';
|
|
44
|
+
export { maybeRunDaemonUpgradeHelperFromEnv, spawnDetachedDaemonUpgradeHelper, resolveCurrentGlobalInstallSurface, buildPinnedGlobalInstallCommand } from './commands/upgrade-helper.js';
|
|
45
|
+
export type { DaemonUpgradeHelperPayload, CurrentGlobalInstallSurface, PinnedGlobalInstallCommand } from './commands/upgrade-helper.js';
|
|
46
46
|
export { DaemonStatusReporter } from './status/reporter.js';
|
|
47
47
|
export { buildSessionEntries, findCdpManager, hasCdpManager, isCdpConnected } from './status/builders.js';
|
|
48
48
|
export { buildStatusSnapshot, buildMachineInfo } from './status/snapshot.js';
|
package/src/index.ts
CHANGED
|
@@ -137,8 +137,17 @@ export { DaemonCommandHandler } from './commands/handler.js';
|
|
|
137
137
|
export type { CommandResult, CommandContext } from './commands/handler.js';
|
|
138
138
|
export { DaemonCommandRouter } from './commands/router.js';
|
|
139
139
|
export type { CommandRouterDeps, CommandRouterResult } from './commands/router.js';
|
|
140
|
-
export {
|
|
141
|
-
|
|
140
|
+
export {
|
|
141
|
+
maybeRunDaemonUpgradeHelperFromEnv,
|
|
142
|
+
spawnDetachedDaemonUpgradeHelper,
|
|
143
|
+
resolveCurrentGlobalInstallSurface,
|
|
144
|
+
buildPinnedGlobalInstallCommand,
|
|
145
|
+
} from './commands/upgrade-helper.js';
|
|
146
|
+
export type {
|
|
147
|
+
DaemonUpgradeHelperPayload,
|
|
148
|
+
CurrentGlobalInstallSurface,
|
|
149
|
+
PinnedGlobalInstallCommand,
|
|
150
|
+
} from './commands/upgrade-helper.js';
|
|
142
151
|
|
|
143
152
|
// ── Status ──
|
|
144
153
|
export { DaemonStatusReporter } from './status/reporter.js';
|