@adhdev/daemon-core 0.9.47 → 0.9.49
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-adapter-types.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +1 -0
- package/dist/commands/chat-commands.d.ts +9 -0
- package/dist/commands/upgrade-helper.d.ts +12 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +405 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +403 -29
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-script-results.d.ts +1 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapter-types.ts +1 -0
- package/src/cli-adapters/provider-cli-adapter.ts +82 -0
- package/src/cli-adapters/provider-cli-shared.ts +6 -1
- package/src/commands/chat-commands.ts +267 -2
- package/src/commands/cli-manager.ts +4 -1
- package/src/commands/handler.ts +1 -0
- package/src/commands/router.ts +5 -6
- package/src/commands/stream-commands.ts +5 -0
- package/src/commands/upgrade-helper.d.ts +26 -0
- package/src/commands/upgrade-helper.ts +63 -19
- package/src/detection/cli-detector.ts +5 -1
- package/src/index.d.ts +2 -2
- package/src/index.ts +10 -7
- package/src/launch.ts +2 -2
- package/src/providers/acp-provider-instance.ts +1 -0
- package/src/providers/cli-provider-instance.ts +5 -0
- package/src/providers/cli-script-results.ts +5 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFileSync } from 'child_process';
|
|
1
|
+
import { execFileSync, type ExecFileSyncOptions } from 'child_process';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as os from 'os';
|
|
@@ -17,16 +17,21 @@ export interface DaemonUpgradeHelperPayload {
|
|
|
17
17
|
|
|
18
18
|
export interface CurrentGlobalInstallSurface {
|
|
19
19
|
npmExecutable: string;
|
|
20
|
+
npmArgsPrefix?: string[];
|
|
20
21
|
packageRoot: string | null;
|
|
21
22
|
installPrefix: string | null;
|
|
23
|
+
execOptions?: NpmExecOptions;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export interface PinnedGlobalInstallCommand {
|
|
25
27
|
command: string;
|
|
26
28
|
args: string[];
|
|
27
29
|
surface: CurrentGlobalInstallSurface;
|
|
30
|
+
execOptions: NpmExecOptions;
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
export type NpmExecOptions = { shell: boolean; windowsHide?: boolean };
|
|
34
|
+
|
|
30
35
|
function getUpgradeLogPath(): string {
|
|
31
36
|
const home = os.homedir();
|
|
32
37
|
const dir = path.join(home, '.adhdev');
|
|
@@ -43,18 +48,32 @@ function appendUpgradeLog(message: string): void {
|
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
|
|
46
|
-
function
|
|
51
|
+
function resolveSiblingNpmInvocation(nodeExecutable: string, platform: NodeJS.Platform = process.platform): {
|
|
52
|
+
executable: string;
|
|
53
|
+
argsPrefix: string[];
|
|
54
|
+
execOptions: NpmExecOptions;
|
|
55
|
+
} {
|
|
47
56
|
const binDir = path.dirname(nodeExecutable);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
if (platform === 'win32') {
|
|
58
|
+
const npmCliPath = path.join(binDir, 'node_modules', 'npm', 'bin', 'npm-cli.js');
|
|
59
|
+
if (fs.existsSync(npmCliPath)) {
|
|
60
|
+
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform) };
|
|
61
|
+
}
|
|
62
|
+
for (const candidate of ['npm.exe', 'npm']) {
|
|
63
|
+
const candidatePath = path.join(binDir, candidate);
|
|
64
|
+
if (fs.existsSync(candidatePath)) {
|
|
65
|
+
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform) };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform) };
|
|
69
|
+
}
|
|
70
|
+
for (const candidate of ['npm']) {
|
|
52
71
|
const candidatePath = path.join(binDir, candidate);
|
|
53
72
|
if (fs.existsSync(candidatePath)) {
|
|
54
|
-
return candidatePath;
|
|
73
|
+
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform) };
|
|
55
74
|
}
|
|
56
75
|
}
|
|
57
|
-
return 'npm';
|
|
76
|
+
return { executable: 'npm', argsPrefix: [], execOptions: getNpmExecOptions(platform) };
|
|
58
77
|
}
|
|
59
78
|
|
|
60
79
|
function findCurrentPackageRoot(currentCliPath: string | undefined, packageName: string): string | null {
|
|
@@ -117,12 +136,16 @@ export function resolveCurrentGlobalInstallSurface(options: {
|
|
|
117
136
|
packageName: string;
|
|
118
137
|
currentCliPath?: string;
|
|
119
138
|
nodeExecutable?: string;
|
|
139
|
+
platform?: NodeJS.Platform;
|
|
120
140
|
}): CurrentGlobalInstallSurface {
|
|
121
141
|
const packageRoot = findCurrentPackageRoot(options.currentCliPath || process.argv[1], options.packageName);
|
|
142
|
+
const npmInvocation = resolveSiblingNpmInvocation(options.nodeExecutable || process.execPath, options.platform);
|
|
122
143
|
return {
|
|
123
|
-
npmExecutable:
|
|
144
|
+
npmExecutable: npmInvocation.executable,
|
|
145
|
+
npmArgsPrefix: npmInvocation.argsPrefix,
|
|
124
146
|
packageRoot,
|
|
125
147
|
installPrefix: packageRoot ? resolveInstallPrefixFromPackageRoot(packageRoot, options.packageName) : null,
|
|
148
|
+
execOptions: npmInvocation.execOptions,
|
|
126
149
|
};
|
|
127
150
|
}
|
|
128
151
|
|
|
@@ -131,9 +154,10 @@ export function buildPinnedGlobalInstallCommand(options: {
|
|
|
131
154
|
targetVersion: string;
|
|
132
155
|
currentCliPath?: string;
|
|
133
156
|
nodeExecutable?: string;
|
|
157
|
+
platform?: NodeJS.Platform;
|
|
134
158
|
}): PinnedGlobalInstallCommand {
|
|
135
159
|
const surface = resolveCurrentGlobalInstallSurface(options);
|
|
136
|
-
const args = ['install', '-g', `${options.packageName}@${options.targetVersion || 'latest'}`, '--force'];
|
|
160
|
+
const args = [...(surface.npmArgsPrefix || []), 'install', '-g', `${options.packageName}@${options.targetVersion || 'latest'}`, '--force'];
|
|
137
161
|
if (surface.installPrefix) {
|
|
138
162
|
args.push('--prefix', surface.installPrefix);
|
|
139
163
|
}
|
|
@@ -141,17 +165,38 @@ export function buildPinnedGlobalInstallCommand(options: {
|
|
|
141
165
|
command: surface.npmExecutable,
|
|
142
166
|
args,
|
|
143
167
|
surface,
|
|
168
|
+
execOptions: surface.execOptions || getNpmExecOptions(options.platform),
|
|
144
169
|
};
|
|
145
170
|
}
|
|
146
171
|
|
|
147
|
-
function getNpmExecOptions(
|
|
148
|
-
|
|
172
|
+
export function getNpmExecOptions(platform: NodeJS.Platform = process.platform): NpmExecOptions {
|
|
173
|
+
if (platform === 'win32') {
|
|
174
|
+
return { shell: false, windowsHide: true };
|
|
175
|
+
}
|
|
176
|
+
return { shell: false };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function execNpmCommandSync(
|
|
180
|
+
args: string[],
|
|
181
|
+
options: ExecFileSyncOptions = {},
|
|
182
|
+
surface?: Pick<CurrentGlobalInstallSurface, 'npmExecutable' | 'npmArgsPrefix' | 'execOptions'>,
|
|
183
|
+
): Buffer | string {
|
|
184
|
+
const execOptions = surface?.execOptions || getNpmExecOptions();
|
|
185
|
+
return execFileSync(
|
|
186
|
+
surface?.npmExecutable || 'npm',
|
|
187
|
+
[...(surface?.npmArgsPrefix || []), ...args],
|
|
188
|
+
{
|
|
189
|
+
...options,
|
|
190
|
+
...execOptions,
|
|
191
|
+
...(process.platform === 'win32' ? { windowsHide: true } : {}),
|
|
192
|
+
},
|
|
193
|
+
);
|
|
149
194
|
}
|
|
150
195
|
|
|
151
196
|
function killPid(pid: number): boolean {
|
|
152
197
|
try {
|
|
153
198
|
if (process.platform === 'win32') {
|
|
154
|
-
execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore' });
|
|
199
|
+
execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
|
|
155
200
|
} else {
|
|
156
201
|
process.kill(pid, 'SIGTERM');
|
|
157
202
|
}
|
|
@@ -170,7 +215,7 @@ function getWindowsProcessCommandLine(pid: number): string | null {
|
|
|
170
215
|
'-ExecutionPolicy', 'Bypass',
|
|
171
216
|
'-Command',
|
|
172
217
|
`(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`,
|
|
173
|
-
], { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
218
|
+
], { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
|
|
174
219
|
if (psOut) return psOut;
|
|
175
220
|
} catch {
|
|
176
221
|
// fall through to wmic fallback
|
|
@@ -179,7 +224,7 @@ function getWindowsProcessCommandLine(pid: number): string | null {
|
|
|
179
224
|
try {
|
|
180
225
|
const wmicOut = execFileSync('wmic', [
|
|
181
226
|
'process', 'where', pidFilter, 'get', 'CommandLine',
|
|
182
|
-
], { encoding: 'utf8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
227
|
+
], { encoding: 'utf8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
|
|
183
228
|
if (wmicOut) return wmicOut;
|
|
184
229
|
} catch {
|
|
185
230
|
// noop
|
|
@@ -249,12 +294,11 @@ function removeDaemonPidFile(): void {
|
|
|
249
294
|
}
|
|
250
295
|
|
|
251
296
|
function cleanupStaleGlobalInstallDirs(pkgName: string, surface: CurrentGlobalInstallSurface): void {
|
|
252
|
-
const npmExecOpts = getNpmExecOptions();
|
|
253
297
|
const prefixArgs = surface.installPrefix ? ['--prefix', surface.installPrefix] : [];
|
|
254
|
-
const npmRoot =
|
|
298
|
+
const npmRoot = String(execNpmCommandSync(['root', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
|
|
255
299
|
if (!npmRoot) return;
|
|
256
300
|
const npmPrefix = surface.installPrefix
|
|
257
|
-
||
|
|
301
|
+
|| String(execNpmCommandSync(['prefix', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
|
|
258
302
|
const binDir = process.platform === 'win32' ? npmPrefix : path.join(npmPrefix, 'bin');
|
|
259
303
|
const packageBaseName = pkgName.startsWith('@') ? pkgName.split('/')[1] : pkgName;
|
|
260
304
|
const binNames = new Set<string>([packageBaseName]);
|
|
@@ -331,7 +375,7 @@ async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Prom
|
|
|
331
375
|
encoding: 'utf8',
|
|
332
376
|
stdio: 'pipe',
|
|
333
377
|
maxBuffer: 20 * 1024 * 1024,
|
|
334
|
-
...
|
|
378
|
+
...installCommand.execOptions,
|
|
335
379
|
},
|
|
336
380
|
);
|
|
337
381
|
if (installOutput.trim()) {
|
|
@@ -60,7 +60,11 @@ function resolveCommandPath(command: string): string | null {
|
|
|
60
60
|
/** Run a shell command with timeout, returning stdout or null on failure */
|
|
61
61
|
function execAsync(cmd: string, timeoutMs = 5000): Promise<string | null> {
|
|
62
62
|
return new Promise((resolve) => {
|
|
63
|
-
const child = exec(cmd, {
|
|
63
|
+
const child = exec(cmd, {
|
|
64
|
+
encoding: 'utf-8',
|
|
65
|
+
timeout: timeoutMs,
|
|
66
|
+
...(process.platform === 'win32' ? { windowsHide: true } : {}),
|
|
67
|
+
}, (err, stdout) => {
|
|
64
68
|
if (err || !stdout?.trim()) {
|
|
65
69
|
resolve(null);
|
|
66
70
|
} else {
|
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, resolveCurrentGlobalInstallSurface, buildPinnedGlobalInstallCommand } from './commands/upgrade-helper.js';
|
|
45
|
-
export type { DaemonUpgradeHelperPayload, CurrentGlobalInstallSurface, PinnedGlobalInstallCommand } from './commands/upgrade-helper.js';
|
|
44
|
+
export { maybeRunDaemonUpgradeHelperFromEnv, spawnDetachedDaemonUpgradeHelper, resolveCurrentGlobalInstallSurface, buildPinnedGlobalInstallCommand, execNpmCommandSync, getNpmExecOptions } from './commands/upgrade-helper.js';
|
|
45
|
+
export type { DaemonUpgradeHelperPayload, CurrentGlobalInstallSurface, PinnedGlobalInstallCommand, NpmExecOptions } 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
|
@@ -140,15 +140,18 @@ export type { CommandResult, CommandContext } from './commands/handler.js';
|
|
|
140
140
|
export { DaemonCommandRouter } from './commands/router.js';
|
|
141
141
|
export type { CommandRouterDeps, CommandRouterResult } from './commands/router.js';
|
|
142
142
|
export {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
maybeRunDaemonUpgradeHelperFromEnv,
|
|
144
|
+
spawnDetachedDaemonUpgradeHelper,
|
|
145
|
+
resolveCurrentGlobalInstallSurface,
|
|
146
|
+
buildPinnedGlobalInstallCommand,
|
|
147
|
+
execNpmCommandSync,
|
|
148
|
+
getNpmExecOptions,
|
|
147
149
|
} from './commands/upgrade-helper.js';
|
|
148
150
|
export type {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
DaemonUpgradeHelperPayload,
|
|
152
|
+
CurrentGlobalInstallSurface,
|
|
153
|
+
PinnedGlobalInstallCommand,
|
|
154
|
+
NpmExecOptions,
|
|
152
155
|
} from './commands/upgrade-helper.js';
|
|
153
156
|
|
|
154
157
|
// ── Status ──
|
package/src/launch.ts
CHANGED
|
@@ -469,7 +469,7 @@ async function launchMacOS(ide: IDEInfo, port: number, workspace?: string, newWi
|
|
|
469
469
|
|
|
470
470
|
if (!useAppLauncher && ide.cliCommand) {
|
|
471
471
|
// CLI based execute
|
|
472
|
-
spawn(ide.cliCommand, args, { detached: true, stdio: 'ignore' }).unref();
|
|
472
|
+
spawn(ide.cliCommand, args, { detached: true, stdio: 'ignore', windowsHide: true }).unref();
|
|
473
473
|
} else if (appName) {
|
|
474
474
|
// Fallback to `open -a` when no CLI wrapper is available or the provider prefers it.
|
|
475
475
|
const openArgs = ['-a', appName, '--args', ...args];
|
|
@@ -509,7 +509,7 @@ async function launchLinux(ide: IDEInfo, port: number, workspace?: string, newWi
|
|
|
509
509
|
if (newWindow) args.push('--new-window');
|
|
510
510
|
if (workspace) args.push(workspace);
|
|
511
511
|
|
|
512
|
-
spawn(cli, args, { detached: true, stdio: 'ignore' }).unref();
|
|
512
|
+
spawn(cli, args, { detached: true, stdio: 'ignore', windowsHide: true }).unref();
|
|
513
513
|
}
|
|
514
514
|
|
|
515
515
|
export function getAvailableIdeIds(): string[] {
|
|
@@ -662,6 +662,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
662
662
|
env,
|
|
663
663
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
664
664
|
shell: spawnConfig.shell || false,
|
|
665
|
+
...(process.platform === 'win32' ? { windowsHide: true } : {}),
|
|
665
666
|
});
|
|
666
667
|
|
|
667
668
|
// stderr → log + auth failure detection
|
|
@@ -601,7 +601,12 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
601
601
|
if (cliCommand?.type === 'send_message' && cliCommand.text) {
|
|
602
602
|
await this.adapter.sendMessage(cliCommand.text);
|
|
603
603
|
} else if (cliCommand?.type === 'pty_write' && cliCommand.text) {
|
|
604
|
+
const enterCount = cliCommand.enterCount || 1;
|
|
604
605
|
await this.adapter.writeRaw(cliCommand.text + '\r');
|
|
606
|
+
for (let i = 1; i < enterCount; i += 1) {
|
|
607
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
608
|
+
await this.adapter.writeRaw('\r');
|
|
609
|
+
}
|
|
605
610
|
}
|
|
606
611
|
|
|
607
612
|
this.applyProviderResponse(parsed.payload, { phase: 'immediate' });
|
|
@@ -18,7 +18,7 @@ export function parseCliScriptResult(result: unknown): { success: boolean; paylo
|
|
|
18
18
|
return { success: true, payload: result }
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function getCliScriptCommand(payload: any): { type: string; text?: string } | null {
|
|
21
|
+
export function getCliScriptCommand(payload: any): { type: string; text?: string; enterCount?: number } | null {
|
|
22
22
|
if (!payload || typeof payload !== 'object') return null
|
|
23
23
|
|
|
24
24
|
if (typeof payload.sendMessage === 'string' && payload.sendMessage.trim()) {
|
|
@@ -35,5 +35,8 @@ export function getCliScriptCommand(payload: any): { type: string; text?: string
|
|
|
35
35
|
? command.message.trim()
|
|
36
36
|
: ''
|
|
37
37
|
if (!text) return null
|
|
38
|
-
|
|
38
|
+
const enterCount = Number.isInteger(command.enterCount) && command.enterCount > 0 && command.enterCount <= 5
|
|
39
|
+
? command.enterCount
|
|
40
|
+
: undefined
|
|
41
|
+
return { type: command.type, text, ...(enterCount ? { enterCount } : {}) }
|
|
39
42
|
}
|