@adhdev/daemon-core 0.9.82-rc.318 → 0.9.82-rc.319
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-runtime.d.ts +34 -0
- package/dist/detection/ide-detector.d.ts +13 -0
- package/dist/detection/win32-ide-version.d.ts +37 -0
- package/dist/index.js +1100 -956
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1120 -976
- package/dist/index.mjs.map +1 -1
- package/dist/providers/spec/adapter.d.ts +10 -0
- package/dist/providers/working-dir.d.ts +17 -0
- package/package.json +2 -2
- package/src/cli-adapters/provider-cli-runtime.ts +54 -7
- package/src/detection/ide-detector.ts +31 -2
- package/src/detection/win32-ide-version.ts +106 -0
- package/src/mesh/mesh-events-coordinator.ts +124 -22
- package/src/providers/acp-provider-instance.ts +4 -3
- package/src/providers/cli-provider-instance.ts +5 -4
- package/src/providers/spec/adapter.ts +14 -1
- package/src/providers/spec/fsm-driver.ts +29 -8
- package/src/providers/version-archive.ts +28 -6
- package/src/providers/working-dir.ts +23 -0
|
@@ -22,6 +22,7 @@ import * as fs from 'node:fs';
|
|
|
22
22
|
import * as os from 'node:os';
|
|
23
23
|
import * as path from 'node:path';
|
|
24
24
|
import { TerminalAdapter, type TerminalAdapterOpts } from './adapter.js';
|
|
25
|
+
import { resolveCliSpawnPlanFromParts } from '../../cli-adapters/provider-cli-runtime.js';
|
|
25
26
|
import type { PtyTransportFactory } from '../../cli-adapters/pty-transport.js';
|
|
26
27
|
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from '@adhdev/session-host-core';
|
|
27
28
|
import {
|
|
@@ -389,15 +390,35 @@ export class FsmDriver implements ISpecDriver {
|
|
|
389
390
|
}
|
|
390
391
|
|
|
391
392
|
private buildAdapterOpts(): TerminalAdapterOpts {
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
// Single-source spawn resolution: route the spec's binary/args/env
|
|
394
|
+
// through the SAME planner the legacy ProviderCliAdapter uses
|
|
395
|
+
// (resolveCliSpawnPlanFromParts). This gives the spec/FSM path
|
|
396
|
+
// findBinary (PATH + npm-global / Node-dir fallback so an off-PATH
|
|
397
|
+
// `codex`/`claude` resolves), `{{workingDir}}` token substitution, shell
|
|
398
|
+
// wrapping for script-shims / non-absolute / non-native binaries, and a
|
|
399
|
+
// sanitized env with TERMINAL_CWD — none of which it had when it passed
|
|
400
|
+
// `this.spec.binary` straight to the PTY.
|
|
401
|
+
const cols = this.opts.cols ?? DEFAULT_SESSION_HOST_COLS;
|
|
402
|
+
const rows = this.opts.rows ?? DEFAULT_SESSION_HOST_ROWS;
|
|
403
|
+
const plan = resolveCliSpawnPlanFromParts({
|
|
404
|
+
command: this.spec.binary,
|
|
405
|
+
baseArgs: this.spec.spawn_args ?? [],
|
|
406
|
+
baseEnv: this.spec.env ?? {},
|
|
407
|
+
workingDir: this.opts.workingDir,
|
|
408
|
+
extraArgs: this.opts.extraCliArgs ?? [],
|
|
409
|
+
extraEnv: this.opts.extraEnv ?? {},
|
|
410
|
+
geometry: { cols, rows },
|
|
411
|
+
});
|
|
394
412
|
return {
|
|
395
|
-
binary:
|
|
396
|
-
args:
|
|
397
|
-
cwd:
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
413
|
+
binary: plan.shellCmd,
|
|
414
|
+
args: plan.shellArgs,
|
|
415
|
+
cwd: plan.ptyOptions.cwd,
|
|
416
|
+
// plan.ptyOptions.env is already a complete, sanitized environment —
|
|
417
|
+
// pass it verbatim, do not overlay process.env (see envIsComplete).
|
|
418
|
+
env: plan.ptyOptions.env,
|
|
419
|
+
envIsComplete: true,
|
|
420
|
+
cols,
|
|
421
|
+
rows,
|
|
401
422
|
transportFactory: this.opts.transportFactory,
|
|
402
423
|
};
|
|
403
424
|
}
|
|
@@ -16,6 +16,7 @@ import * as os from 'os';
|
|
|
16
16
|
import { platform } from 'os';
|
|
17
17
|
import type { ProviderLoader } from './provider-loader.js';
|
|
18
18
|
import type { ProviderModule } from './contracts.js';
|
|
19
|
+
import { isKnownWin32GuiExe, readWin32IdeVersionFromDisk } from '../detection/win32-ide-version.js';
|
|
19
20
|
|
|
20
21
|
// ─── Types ──────────────────────────────────────
|
|
21
22
|
|
|
@@ -226,6 +227,10 @@ export async function detectAllVersions(
|
|
|
226
227
|
): Promise<ProviderVersionInfo[]> {
|
|
227
228
|
const results: ProviderVersionInfo[] = [];
|
|
228
229
|
const currentOs = platform() as string;
|
|
230
|
+
// Map of provider type → GUI exe names (win32), used to refuse spawning a
|
|
231
|
+
// GUI executable for version detection (which would boot the IDE window).
|
|
232
|
+
const win32ProcessNames: Record<string, string[]> =
|
|
233
|
+
typeof loader.getWinProcessNames === 'function' ? loader.getWinProcessNames() : {};
|
|
229
234
|
|
|
230
235
|
for (const provider of loader.getAll()) {
|
|
231
236
|
const info: ProviderVersionInfo = {
|
|
@@ -258,12 +263,29 @@ export async function detectAllVersions(
|
|
|
258
263
|
info.path = appPath || null;
|
|
259
264
|
info.binary = resolvedBin || null;
|
|
260
265
|
|
|
261
|
-
// Version
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
266
|
+
// Version detection for IDEs must avoid spawning the GUI executable.
|
|
267
|
+
// On Windows the resolved binary is frequently the GUI Electron exe
|
|
268
|
+
// (case-insensitive FS), and `<exe> --version` boots the IDE window.
|
|
269
|
+
// Strategy (all spawn-free where possible):
|
|
270
|
+
// 1. win32: read bundled product.json/package.json next to the exe.
|
|
271
|
+
// 2. darwin: read Info.plist via PlistBuddy (read-only).
|
|
272
|
+
// 3. Fallback to `<bin> --version` ONLY when the binary is not a
|
|
273
|
+
// known GUI exe — the safety-net guard (#4).
|
|
274
|
+
if (currentOs === 'win32') {
|
|
275
|
+
info.version = readWin32IdeVersionFromDisk(resolvedBin || appPath || '');
|
|
276
|
+
if (!info.version && resolvedBin && !isKnownWin32GuiExe(resolvedBin, win32ProcessNames)) {
|
|
277
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
278
|
+
}
|
|
279
|
+
} else if (currentOs === 'darwin') {
|
|
280
|
+
if (appPath) info.version = await getMacAppVersion(appPath);
|
|
281
|
+
if (!info.version && resolvedBin) {
|
|
282
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
// linux and others: bundled CLI wrappers are real CLIs, safe to exec.
|
|
286
|
+
if (resolvedBin) {
|
|
287
|
+
info.version = await getVersion(resolvedBin, versionCommand);
|
|
288
|
+
}
|
|
267
289
|
}
|
|
268
290
|
|
|
269
291
|
} else if (provider.category === 'cli' || provider.category === 'acp') {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* working-dir — shared helpers for deriving display names from a session's
|
|
3
|
+
* working directory. Used by CLI/ACP provider instances to build session/tab
|
|
4
|
+
* titles.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* OS-aware basename of a working directory path.
|
|
9
|
+
*
|
|
10
|
+
* Splits on BOTH POSIX (`/`) and Windows (`\`) separators so a win32 path like
|
|
11
|
+
* `D:\gh\adhdev-cloud` resolves to `adhdev-cloud` even when the daemon's own
|
|
12
|
+
* `path.basename` is POSIX-only — and a path that mixes separators still works.
|
|
13
|
+
* Trailing separators and root-only paths fall back to `'session'`, matching
|
|
14
|
+
* the historical `.split('/').filter(Boolean).pop() || 'session'` behavior.
|
|
15
|
+
*
|
|
16
|
+
* Mirrors the web dashboard's `getWorkspaceName` (`ws.split(/[/\\]/)`).
|
|
17
|
+
*/
|
|
18
|
+
export function workingDirBasename(p: string): string {
|
|
19
|
+
return (p || '')
|
|
20
|
+
.split(/[\\/]/)
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.pop() || 'session';
|
|
23
|
+
}
|