@dexlyai/dexly 0.1.2 → 0.1.3
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/README.md +4 -2
- package/dist/cli.js +611 -299
- package/dist/host.js +332 -110
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -117,29 +117,21 @@ var require_companion = __commonJS({
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
// src/cli.ts
|
|
120
|
-
var
|
|
120
|
+
var import_node_path5 = __toESM(require("node:path"));
|
|
121
121
|
var import_node_process5 = __toESM(require("node:process"));
|
|
122
|
-
var
|
|
122
|
+
var import_companion7 = __toESM(require_companion());
|
|
123
123
|
|
|
124
124
|
// src/doctor.ts
|
|
125
|
-
var
|
|
126
|
-
var import_node_child_process = require("node:child_process");
|
|
125
|
+
var import_promises2 = require("node:fs/promises");
|
|
127
126
|
var import_node_events = require("node:events");
|
|
128
|
-
var
|
|
127
|
+
var import_companion4 = __toESM(require_companion());
|
|
129
128
|
|
|
130
129
|
// src/constants.ts
|
|
131
|
-
var import_node_os = __toESM(require("node:os"));
|
|
132
130
|
var import_node_path = __toESM(require("node:path"));
|
|
133
131
|
var import_companion = __toESM(require_companion());
|
|
134
|
-
var DEXLY_COMPANION_VERSION = true ? "0.1.
|
|
132
|
+
var DEXLY_COMPANION_VERSION = true ? "0.1.3" : packageJson.version;
|
|
135
133
|
var DEXLY_COMPANION_DESCRIPTION = "Dexly native bridge for Codex";
|
|
136
134
|
var DEXLY_COMPANION_METADATA_FILE_NAME = "install-metadata.json";
|
|
137
|
-
function defaultInstallRoot(homeDir = import_node_os.default.homedir()) {
|
|
138
|
-
return import_node_path.default.join(homeDir, "Library", "Application Support", "Dexly", "companion");
|
|
139
|
-
}
|
|
140
|
-
function defaultChromeHostManifestDir(homeDir = import_node_os.default.homedir()) {
|
|
141
|
-
return import_node_path.default.join(homeDir, "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
142
|
-
}
|
|
143
135
|
function defaultChromeAllowedOrigins() {
|
|
144
136
|
return [...import_companion.DEXLY_FIXED_ALLOWED_ORIGINS];
|
|
145
137
|
}
|
|
@@ -158,8 +150,8 @@ function versionInstallPath(installRoot, version) {
|
|
|
158
150
|
function installedHostScriptPath(installRoot) {
|
|
159
151
|
return import_node_path.default.join(currentInstallPath(installRoot), "dist", "host.js");
|
|
160
152
|
}
|
|
161
|
-
function installedHostLauncherPath(installRoot) {
|
|
162
|
-
return import_node_path.default.join(currentInstallPath(installRoot), "bin",
|
|
153
|
+
function installedHostLauncherPath(installRoot, platform = process.platform) {
|
|
154
|
+
return import_node_path.default.join(currentInstallPath(installRoot), "bin", resolveLauncherFileName(platform));
|
|
163
155
|
}
|
|
164
156
|
function versionedCliPath(versionRoot) {
|
|
165
157
|
return import_node_path.default.join(versionRoot, "dist", "cli.js");
|
|
@@ -167,15 +159,12 @@ function versionedCliPath(versionRoot) {
|
|
|
167
159
|
function versionedHostScriptPath(versionRoot) {
|
|
168
160
|
return import_node_path.default.join(versionRoot, "dist", "host.js");
|
|
169
161
|
}
|
|
170
|
-
function versionedHostLauncherPath(versionRoot) {
|
|
171
|
-
return import_node_path.default.join(versionRoot, "bin",
|
|
162
|
+
function versionedHostLauncherPath(versionRoot, platform = process.platform) {
|
|
163
|
+
return import_node_path.default.join(versionRoot, "bin", resolveLauncherFileName(platform));
|
|
172
164
|
}
|
|
173
165
|
function versionedPackageJsonPath(versionRoot) {
|
|
174
166
|
return import_node_path.default.join(versionRoot, "package.json");
|
|
175
167
|
}
|
|
176
|
-
function installedHostManifestPath(manifestDir) {
|
|
177
|
-
return import_node_path.default.join(manifestDir, `${import_companion.DEXLY_COMPANION_HOST_NAME}.json`);
|
|
178
|
-
}
|
|
179
168
|
function buildChromeHostManifest(hostPath, allowedOrigins) {
|
|
180
169
|
return {
|
|
181
170
|
name: import_companion.DEXLY_COMPANION_HOST_NAME,
|
|
@@ -185,6 +174,68 @@ function buildChromeHostManifest(hostPath, allowedOrigins) {
|
|
|
185
174
|
allowed_origins: allowedOrigins
|
|
186
175
|
};
|
|
187
176
|
}
|
|
177
|
+
function resolveLauncherFileName(platform) {
|
|
178
|
+
return platform === "win32" ? "dexly-companion-host.cmd" : "dexly-companion-host";
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/install-metadata.ts
|
|
182
|
+
var import_promises = require("node:fs/promises");
|
|
183
|
+
var import_companion2 = __toESM(require_companion());
|
|
184
|
+
function normalizeString(value) {
|
|
185
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
186
|
+
}
|
|
187
|
+
function normalizeToolPaths(value) {
|
|
188
|
+
if (!value || typeof value !== "object") {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const candidate = value;
|
|
192
|
+
const nodePath = normalizeString(candidate.nodePath);
|
|
193
|
+
const npmPath = normalizeString(candidate.npmPath);
|
|
194
|
+
if (!nodePath || !npmPath) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
nodePath,
|
|
199
|
+
npmPath,
|
|
200
|
+
codexPath: normalizeString(candidate.codexPath)
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async function loadInstallMetadata(installRoot) {
|
|
204
|
+
try {
|
|
205
|
+
const raw = await (0, import_promises.readFile)(installMetadataPath(installRoot), "utf8");
|
|
206
|
+
const parsed = JSON.parse(raw);
|
|
207
|
+
const tools = normalizeToolPaths(parsed.tools);
|
|
208
|
+
const currentVersion = normalizeString(parsed.currentVersion);
|
|
209
|
+
const installedAt = normalizeString(parsed.installedAt);
|
|
210
|
+
const updatedAt = normalizeString(parsed.updatedAt);
|
|
211
|
+
if (!tools || !currentVersion || !installedAt || !updatedAt) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const knownGoodVersions = Array.isArray(parsed.knownGoodVersions) ? parsed.knownGoodVersions.filter((value) => typeof value === "string" && value.trim().length > 0) : [currentVersion];
|
|
215
|
+
return {
|
|
216
|
+
schemaVersion: 1,
|
|
217
|
+
packageName: import_companion2.DEXLY_COMPANION_PACKAGE_NAME,
|
|
218
|
+
executableName: import_companion2.DEXLY_COMPANION_EXECUTABLE_NAME,
|
|
219
|
+
currentVersion,
|
|
220
|
+
previousVersion: normalizeString(parsed.previousVersion),
|
|
221
|
+
knownGoodVersions: knownGoodVersions.length > 0 ? knownGoodVersions : [currentVersion],
|
|
222
|
+
currentChannel: normalizeString(parsed.currentChannel),
|
|
223
|
+
installedAt,
|
|
224
|
+
updatedAt,
|
|
225
|
+
tools
|
|
226
|
+
};
|
|
227
|
+
} catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async function saveInstallMetadata(installRoot, metadata) {
|
|
232
|
+
await (0, import_promises.writeFile)(
|
|
233
|
+
installMetadataPath(installRoot),
|
|
234
|
+
`${JSON.stringify(metadata, null, 2)}
|
|
235
|
+
`,
|
|
236
|
+
"utf8"
|
|
237
|
+
);
|
|
238
|
+
}
|
|
188
239
|
|
|
189
240
|
// src/native-protocol.ts
|
|
190
241
|
var import_node_buffer = require("node:buffer");
|
|
@@ -223,33 +274,352 @@ function writeNativeMessage(output, message) {
|
|
|
223
274
|
output.write(encodeNativeMessage(message));
|
|
224
275
|
}
|
|
225
276
|
|
|
277
|
+
// src/platform.ts
|
|
278
|
+
var import_node_os = __toESM(require("node:os"));
|
|
279
|
+
var import_node_path2 = __toESM(require("node:path"));
|
|
280
|
+
var import_node_process = __toESM(require("node:process"));
|
|
281
|
+
var import_companion3 = __toESM(require_companion());
|
|
282
|
+
function assertSupportedPlatform(platform = import_node_process.default.platform) {
|
|
283
|
+
switch (platform) {
|
|
284
|
+
case "darwin":
|
|
285
|
+
case "linux":
|
|
286
|
+
case "win32":
|
|
287
|
+
return platform;
|
|
288
|
+
default:
|
|
289
|
+
throw new Error(
|
|
290
|
+
`Dexly Companion currently supports macOS, Windows, and Linux only. Unsupported platform: ${platform}.`
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function describePlatform(platform = import_node_process.default.platform) {
|
|
295
|
+
switch (platform) {
|
|
296
|
+
case "darwin":
|
|
297
|
+
return "macOS";
|
|
298
|
+
case "linux":
|
|
299
|
+
return "Linux";
|
|
300
|
+
case "win32":
|
|
301
|
+
return "Windows";
|
|
302
|
+
default:
|
|
303
|
+
return platform;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function defaultChromeAllowedOrigins2() {
|
|
307
|
+
return [...import_companion3.DEXLY_FIXED_ALLOWED_ORIGINS];
|
|
308
|
+
}
|
|
309
|
+
function defaultInstallRoot(options = {}) {
|
|
310
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
311
|
+
const homeDir = options.homeDir ?? import_node_os.default.homedir();
|
|
312
|
+
const env = options.env ?? import_node_process.default.env;
|
|
313
|
+
switch (platform) {
|
|
314
|
+
case "darwin":
|
|
315
|
+
return import_node_path2.default.join(homeDir, "Library", "Application Support", "Dexly", "companion");
|
|
316
|
+
case "linux": {
|
|
317
|
+
const dataHome = env.XDG_DATA_HOME?.trim() || import_node_path2.default.join(homeDir, ".local", "share");
|
|
318
|
+
return import_node_path2.default.join(dataHome, "Dexly", "companion");
|
|
319
|
+
}
|
|
320
|
+
case "win32": {
|
|
321
|
+
const localAppData = env.LOCALAPPDATA?.trim() || import_node_path2.default.join(homeDir, "AppData", "Local");
|
|
322
|
+
return import_node_path2.default.join(localAppData, "Dexly", "companion");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function resolveChromeHostRegistration(options = {}) {
|
|
327
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
328
|
+
const homeDir = options.homeDir ?? import_node_os.default.homedir();
|
|
329
|
+
const env = options.env ?? import_node_process.default.env;
|
|
330
|
+
const installRoot = options.installRoot ?? defaultInstallRoot({
|
|
331
|
+
platform,
|
|
332
|
+
homeDir,
|
|
333
|
+
env
|
|
334
|
+
});
|
|
335
|
+
const manifestPath = options.manifestDir ? import_node_path2.default.join(options.manifestDir, `${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`) : defaultChromeManifestPath({
|
|
336
|
+
platform,
|
|
337
|
+
homeDir,
|
|
338
|
+
env,
|
|
339
|
+
installRoot
|
|
340
|
+
});
|
|
341
|
+
if (platform === "win32") {
|
|
342
|
+
return {
|
|
343
|
+
kind: "windows-registry",
|
|
344
|
+
manifestPath,
|
|
345
|
+
allowedOrigins: defaultChromeAllowedOrigins2(),
|
|
346
|
+
registryKey: options.windowsRegistryKey ?? `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${import_companion3.DEXLY_COMPANION_HOST_NAME}`
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
kind: "manifest-file",
|
|
351
|
+
manifestPath,
|
|
352
|
+
allowedOrigins: defaultChromeAllowedOrigins2(),
|
|
353
|
+
registryKey: null
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function resolvePlatformLayout(options = {}) {
|
|
357
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
358
|
+
const installRoot = options.installRoot ?? defaultInstallRoot(options);
|
|
359
|
+
return {
|
|
360
|
+
platform,
|
|
361
|
+
installRoot,
|
|
362
|
+
activationStrategy: platform === "win32" ? "copy" : "symlink",
|
|
363
|
+
launcherKind: platform === "win32" ? "windows-cmd" : "posix",
|
|
364
|
+
launcherFileName: platform === "win32" ? "dexly-companion-host.cmd" : "dexly-companion-host",
|
|
365
|
+
hostRegistration: resolveChromeHostRegistration({
|
|
366
|
+
...options,
|
|
367
|
+
platform,
|
|
368
|
+
installRoot
|
|
369
|
+
})
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function defaultLauncherPathEntries(platform = import_node_process.default.platform, env = import_node_process.default.env) {
|
|
373
|
+
switch (assertSupportedPlatform(platform)) {
|
|
374
|
+
case "darwin":
|
|
375
|
+
return ["/usr/local/bin", "/opt/homebrew/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
376
|
+
case "linux":
|
|
377
|
+
return ["/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
378
|
+
case "win32": {
|
|
379
|
+
const systemRoot = env.SystemRoot?.trim() || "C:\\Windows";
|
|
380
|
+
return [import_node_path2.default.join(systemRoot, "System32"), systemRoot];
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function renderHostLauncher(options) {
|
|
385
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
386
|
+
const pathEntries = [
|
|
387
|
+
import_node_path2.default.dirname(options.nodePath),
|
|
388
|
+
options.codexPath ? import_node_path2.default.dirname(options.codexPath) : null,
|
|
389
|
+
...defaultLauncherPathEntries(platform, options.env ?? import_node_process.default.env)
|
|
390
|
+
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
391
|
+
if (platform === "win32") {
|
|
392
|
+
const lines2 = [
|
|
393
|
+
"@echo off",
|
|
394
|
+
"setlocal",
|
|
395
|
+
`set "PATH=${toBatchLiteral(pathEntries.join(import_node_path2.default.delimiter))};%PATH%"`,
|
|
396
|
+
options.codexPath ? `set "DEXLY_COMPANION_CODEX_PATH=${toBatchLiteral(options.codexPath)}"` : null,
|
|
397
|
+
`set "DEXLY_COMPANION_NODE_PATH=${toBatchLiteral(options.nodePath)}"`,
|
|
398
|
+
`set "DEXLY_COMPANION_HOST_SCRIPT=${toBatchLiteral(options.hostScriptPath)}"`,
|
|
399
|
+
'"%DEXLY_COMPANION_NODE_PATH%" "%DEXLY_COMPANION_HOST_SCRIPT%" %*'
|
|
400
|
+
].filter((line) => typeof line === "string");
|
|
401
|
+
return `${lines2.join("\r\n")}\r
|
|
402
|
+
`;
|
|
403
|
+
}
|
|
404
|
+
const lines = [
|
|
405
|
+
"#!/bin/sh",
|
|
406
|
+
"set -eu",
|
|
407
|
+
`export PATH=${toShellLiteral(pathEntries.join(import_node_path2.default.delimiter))}`,
|
|
408
|
+
options.codexPath ? `export DEXLY_COMPANION_CODEX_PATH=${toShellLiteral(options.codexPath)}` : null,
|
|
409
|
+
`exec ${toShellLiteral(options.nodePath)} ${toShellLiteral(options.hostScriptPath)} "$@"`
|
|
410
|
+
].filter((line) => typeof line === "string");
|
|
411
|
+
return `${lines.join("\n")}
|
|
412
|
+
`;
|
|
413
|
+
}
|
|
414
|
+
function defaultChromeManifestPath(options) {
|
|
415
|
+
switch (options.platform) {
|
|
416
|
+
case "darwin":
|
|
417
|
+
return import_node_path2.default.join(
|
|
418
|
+
options.homeDir,
|
|
419
|
+
"Library",
|
|
420
|
+
"Application Support",
|
|
421
|
+
"Google",
|
|
422
|
+
"Chrome",
|
|
423
|
+
"NativeMessagingHosts",
|
|
424
|
+
`${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`
|
|
425
|
+
);
|
|
426
|
+
case "linux": {
|
|
427
|
+
const configHome = options.env.XDG_CONFIG_HOME?.trim() || import_node_path2.default.join(options.homeDir, ".config");
|
|
428
|
+
return import_node_path2.default.join(
|
|
429
|
+
configHome,
|
|
430
|
+
"google-chrome",
|
|
431
|
+
"NativeMessagingHosts",
|
|
432
|
+
`${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
case "win32":
|
|
436
|
+
return import_node_path2.default.join(options.installRoot, "native-host", `${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function toShellLiteral(value) {
|
|
440
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
441
|
+
}
|
|
442
|
+
function toBatchLiteral(value) {
|
|
443
|
+
return value.replace(/%/g, "%%").replace(/"/g, '""');
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// src/tooling.ts
|
|
447
|
+
var import_node_path3 = __toESM(require("node:path"));
|
|
448
|
+
var import_node_process2 = __toESM(require("node:process"));
|
|
449
|
+
var import_node_child_process = require("node:child_process");
|
|
450
|
+
function detectToolPaths() {
|
|
451
|
+
const nodePath = import_node_process2.default.execPath;
|
|
452
|
+
const npmPath = resolveExecutablePath("npm") ?? "npm";
|
|
453
|
+
const codexPath = resolveExecutablePath("codex");
|
|
454
|
+
return {
|
|
455
|
+
nodePath,
|
|
456
|
+
npmPath,
|
|
457
|
+
codexPath
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function resolveExecutablePath(command, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
461
|
+
const lookupCommand = platform === "win32" ? "where" : "which";
|
|
462
|
+
const result = (0, import_node_child_process.spawnSync)(lookupCommand, [command], {
|
|
463
|
+
encoding: "utf8",
|
|
464
|
+
env
|
|
465
|
+
});
|
|
466
|
+
if (result.error || result.status !== 0) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
const executablePath = result.stdout.split(/\r?\n/).map((value) => value.trim()).find((value) => value.length > 0);
|
|
470
|
+
return executablePath ?? null;
|
|
471
|
+
}
|
|
472
|
+
function buildToolEnv(toolPaths, extraPaths = [], platform = import_node_process2.default.platform) {
|
|
473
|
+
const supportedPlatform = assertSupportedPlatform(platform);
|
|
474
|
+
const pathSeparator = supportedPlatform === "win32" ? ";" : ":";
|
|
475
|
+
const pathEntries = [
|
|
476
|
+
import_node_path3.default.dirname(toolPaths.nodePath),
|
|
477
|
+
import_node_path3.default.dirname(toolPaths.npmPath),
|
|
478
|
+
toolPaths.codexPath ? import_node_path3.default.dirname(toolPaths.codexPath) : null,
|
|
479
|
+
...extraPaths,
|
|
480
|
+
...defaultLauncherPathEntries(supportedPlatform, import_node_process2.default.env),
|
|
481
|
+
import_node_process2.default.env.PATH ?? null
|
|
482
|
+
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
483
|
+
return {
|
|
484
|
+
...import_node_process2.default.env,
|
|
485
|
+
PATH: pathEntries.join(pathSeparator),
|
|
486
|
+
...toolPaths.codexPath ? { DEXLY_COMPANION_CODEX_PATH: toolPaths.codexPath } : {}
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
async function runCommand(command, args, options = {}) {
|
|
490
|
+
return await new Promise((resolve, reject) => {
|
|
491
|
+
const child = spawnManaged(command, args, {
|
|
492
|
+
cwd: options.cwd,
|
|
493
|
+
env: options.env,
|
|
494
|
+
stdio: "pipe"
|
|
495
|
+
});
|
|
496
|
+
let stdout = "";
|
|
497
|
+
let stderr = "";
|
|
498
|
+
child.stdout.on("data", (chunk) => {
|
|
499
|
+
stdout += (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString("utf8");
|
|
500
|
+
});
|
|
501
|
+
child.stderr.on("data", (chunk) => {
|
|
502
|
+
stderr += (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString("utf8");
|
|
503
|
+
});
|
|
504
|
+
child.once("error", (error) => {
|
|
505
|
+
reject(error);
|
|
506
|
+
});
|
|
507
|
+
child.once("exit", (code, signal) => {
|
|
508
|
+
if (code === 0) {
|
|
509
|
+
resolve({ stdout, stderr });
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const detail = stderr.trim() || stdout.trim();
|
|
513
|
+
reject(new Error(
|
|
514
|
+
detail.length > 0 ? `${command} ${args.join(" ")} failed (${code ?? signal ?? "unknown"}): ${detail}` : `${command} ${args.join(" ")} failed (${code ?? signal ?? "unknown"}).`
|
|
515
|
+
));
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function resolveCodexVersion(codexCommand = import_node_process2.default.env.DEXLY_COMPANION_CODEX_PATH ?? "codex", env = import_node_process2.default.env) {
|
|
520
|
+
const result = spawnManagedSync(codexCommand, ["--version"], {
|
|
521
|
+
encoding: "utf8",
|
|
522
|
+
env
|
|
523
|
+
});
|
|
524
|
+
if (result.error || result.status !== 0) {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
return result.stdout.trim() || null;
|
|
528
|
+
}
|
|
529
|
+
function resolveNpmGlobalBinDir(npmPath, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
530
|
+
const result = spawnManagedSync(npmPath, ["config", "get", "prefix"], {
|
|
531
|
+
encoding: "utf8",
|
|
532
|
+
env
|
|
533
|
+
});
|
|
534
|
+
if (result.error || result.status !== 0) {
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
const prefix = result.stdout.trim();
|
|
538
|
+
if (prefix.length === 0) {
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
return npmGlobalBinDirFromPrefix(prefix, platform);
|
|
542
|
+
}
|
|
543
|
+
function spawnManaged(command, args, options = {}) {
|
|
544
|
+
const invocation = buildSpawnInvocation(command, args, options.env);
|
|
545
|
+
return (0, import_node_child_process.spawn)(invocation.command, invocation.args, {
|
|
546
|
+
...options,
|
|
547
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
function spawnManagedSync(command, args, options = {}) {
|
|
551
|
+
const invocation = buildSpawnInvocation(command, args, options.env);
|
|
552
|
+
return (0, import_node_child_process.spawnSync)(invocation.command, invocation.args, {
|
|
553
|
+
...options,
|
|
554
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
function buildSpawnInvocation(command, args, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
558
|
+
if (platform !== "win32" || !isWindowsCommandScript(command, platform)) {
|
|
559
|
+
return {
|
|
560
|
+
command,
|
|
561
|
+
args
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
return {
|
|
565
|
+
command: resolveWindowsCommandShell(env),
|
|
566
|
+
args: ["/d", "/s", "/c", quoteWindowsCommand([command, ...args])],
|
|
567
|
+
windowsVerbatimArguments: false
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
function isWindowsCommandScript(command, platform = import_node_process2.default.platform) {
|
|
571
|
+
if (platform !== "win32") {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
const normalized = command.trim().toLowerCase();
|
|
575
|
+
return normalized.endsWith(".cmd") || normalized.endsWith(".bat");
|
|
576
|
+
}
|
|
577
|
+
function resolveWindowsCommandShell(env = import_node_process2.default.env) {
|
|
578
|
+
const comSpec = env.ComSpec?.trim();
|
|
579
|
+
if (comSpec) {
|
|
580
|
+
return comSpec;
|
|
581
|
+
}
|
|
582
|
+
const systemRoot = env.SystemRoot?.trim() || "C:\\Windows";
|
|
583
|
+
return import_node_path3.default.join(systemRoot, "System32", "cmd.exe");
|
|
584
|
+
}
|
|
585
|
+
function quoteWindowsCommand(parts) {
|
|
586
|
+
return parts.map(quoteWindowsArgument).join(" ");
|
|
587
|
+
}
|
|
588
|
+
function quoteWindowsArgument(value) {
|
|
589
|
+
if (value.length === 0) {
|
|
590
|
+
return '""';
|
|
591
|
+
}
|
|
592
|
+
if (!/[ \t"&()^<>|]/.test(value)) {
|
|
593
|
+
return value;
|
|
594
|
+
}
|
|
595
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
596
|
+
}
|
|
597
|
+
function npmGlobalBinDirFromPrefix(prefix, platform = import_node_process2.default.platform) {
|
|
598
|
+
return platform === "win32" ? prefix : import_node_path3.default.join(prefix, "bin");
|
|
599
|
+
}
|
|
600
|
+
|
|
226
601
|
// src/doctor.ts
|
|
227
|
-
async function runDoctor(options) {
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
const manifestPath =
|
|
231
|
-
const hostLauncherPath = installedHostLauncherPath(installRoot);
|
|
602
|
+
async function runDoctor(options = {}) {
|
|
603
|
+
const layout = resolvePlatformLayout(options);
|
|
604
|
+
const installRoot = layout.installRoot;
|
|
605
|
+
const manifestPath = layout.hostRegistration.manifestPath;
|
|
606
|
+
const hostLauncherPath = installedHostLauncherPath(installRoot, layout.platform);
|
|
232
607
|
const hostScriptPath = installedHostScriptPath(installRoot);
|
|
233
608
|
const metadataPath = installMetadataPath(installRoot);
|
|
234
609
|
const checks = [];
|
|
235
610
|
checks.push({
|
|
236
611
|
label: "platform",
|
|
237
|
-
ok:
|
|
238
|
-
detail:
|
|
612
|
+
ok: true,
|
|
613
|
+
detail: `${describePlatform(layout.platform)} supported.`
|
|
239
614
|
});
|
|
615
|
+
checks.push(await checkHostRegistration(layout.hostRegistration, options.registryReader));
|
|
240
616
|
checks.push(await checkPath("host launcher", hostLauncherPath));
|
|
241
617
|
checks.push(await checkPath("host bundle", hostScriptPath));
|
|
242
618
|
checks.push(await checkPath("install metadata", metadataPath));
|
|
243
619
|
checks.push(await checkPath("native host manifest", manifestPath));
|
|
244
|
-
|
|
245
|
-
checks.push(
|
|
246
|
-
checks.push(await
|
|
247
|
-
const codexVersion = resolveCodexVersion();
|
|
248
|
-
checks.push({
|
|
249
|
-
label: "codex",
|
|
250
|
-
ok: codexVersion != null,
|
|
251
|
-
detail: codexVersion ?? "Codex CLI not found in PATH."
|
|
252
|
-
});
|
|
620
|
+
checks.push(await checkHostManifest(manifestPath, hostLauncherPath));
|
|
621
|
+
checks.push(await checkNativeHostRuntime(layout.hostRegistration, options.registryReader));
|
|
622
|
+
checks.push(await checkCodexAvailability(installRoot, layout.platform));
|
|
253
623
|
return {
|
|
254
624
|
ok: checks.every((check) => check.ok),
|
|
255
625
|
checks
|
|
@@ -257,7 +627,7 @@ async function runDoctor(options) {
|
|
|
257
627
|
}
|
|
258
628
|
async function checkPath(label, filePath) {
|
|
259
629
|
try {
|
|
260
|
-
await (0,
|
|
630
|
+
await (0, import_promises2.access)(filePath);
|
|
261
631
|
return {
|
|
262
632
|
label,
|
|
263
633
|
ok: true,
|
|
@@ -271,16 +641,39 @@ async function checkPath(label, filePath) {
|
|
|
271
641
|
};
|
|
272
642
|
}
|
|
273
643
|
}
|
|
644
|
+
async function checkHostRegistration(registration, registryReader) {
|
|
645
|
+
if (registration.kind === "manifest-file") {
|
|
646
|
+
return {
|
|
647
|
+
label: "native host registration",
|
|
648
|
+
ok: true,
|
|
649
|
+
detail: registration.manifestPath
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
const registeredManifestPath = await (registryReader ?? readWindowsRegistryManifestPath)(registration.registryKey ?? "");
|
|
653
|
+
if (!registeredManifestPath) {
|
|
654
|
+
return {
|
|
655
|
+
label: "native host registration",
|
|
656
|
+
ok: false,
|
|
657
|
+
detail: `Chrome registry key is missing or empty: ${registration.registryKey}`
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
const ok = registeredManifestPath === registration.manifestPath;
|
|
661
|
+
return {
|
|
662
|
+
label: "native host registration",
|
|
663
|
+
ok,
|
|
664
|
+
detail: ok ? `Registry points to ${registeredManifestPath}` : `Registry points to ${registeredManifestPath}, expected ${registration.manifestPath}`
|
|
665
|
+
};
|
|
666
|
+
}
|
|
274
667
|
async function checkHostManifest(filePath, expectedHostPath) {
|
|
275
668
|
try {
|
|
276
|
-
const raw = await (0,
|
|
669
|
+
const raw = await (0, import_promises2.readFile)(filePath, "utf8");
|
|
277
670
|
const manifest = JSON.parse(raw);
|
|
278
671
|
const allowedOrigins = Array.isArray(manifest.allowed_origins) ? manifest.allowed_origins.filter((value) => typeof value === "string") : [];
|
|
279
|
-
const ok = manifest.name ===
|
|
672
|
+
const ok = manifest.name === import_companion4.DEXLY_COMPANION_HOST_NAME && typeof manifest.path === "string" && manifest.path === expectedHostPath && import_companion4.DEXLY_FIXED_ALLOWED_ORIGINS.every((origin) => allowedOrigins.includes(origin));
|
|
280
673
|
return {
|
|
281
674
|
label: "manifest contents",
|
|
282
675
|
ok,
|
|
283
|
-
detail: ok ? `Native host manifest is valid, points to ${expectedHostPath}, and includes ${
|
|
676
|
+
detail: ok ? `Native host manifest is valid, points to ${expectedHostPath}, and includes ${import_companion4.DEXLY_FIXED_ALLOWED_ORIGINS.join(", ")}` : "Native host manifest is missing the expected name, expected launcher path, or one of Dexly's fixed extension origins."
|
|
284
677
|
};
|
|
285
678
|
} catch (error) {
|
|
286
679
|
return {
|
|
@@ -290,10 +683,18 @@ async function checkHostManifest(filePath, expectedHostPath) {
|
|
|
290
683
|
};
|
|
291
684
|
}
|
|
292
685
|
}
|
|
293
|
-
async function checkNativeHostRuntime(
|
|
294
|
-
const defaultOrigin = `chrome-extension://${
|
|
686
|
+
async function checkNativeHostRuntime(registration, registryReader) {
|
|
687
|
+
const defaultOrigin = `chrome-extension://${import_companion4.DEXLY_DEV_EXTENSION_ID}/`;
|
|
688
|
+
const registeredManifestPath = registration.kind === "windows-registry" ? await (registryReader ?? readWindowsRegistryManifestPath)(registration.registryKey ?? "") : registration.manifestPath;
|
|
689
|
+
if (!registeredManifestPath) {
|
|
690
|
+
return {
|
|
691
|
+
label: "native host runtime",
|
|
692
|
+
ok: false,
|
|
693
|
+
detail: "Dexly Companion could not resolve the registered native host manifest path."
|
|
694
|
+
};
|
|
695
|
+
}
|
|
295
696
|
try {
|
|
296
|
-
const raw = await (0,
|
|
697
|
+
const raw = await (0, import_promises2.readFile)(registeredManifestPath, "utf8");
|
|
297
698
|
const manifest = JSON.parse(raw);
|
|
298
699
|
if (typeof manifest.path !== "string" || manifest.path.length === 0) {
|
|
299
700
|
return {
|
|
@@ -332,8 +733,32 @@ async function checkNativeHostRuntime(manifestPath) {
|
|
|
332
733
|
};
|
|
333
734
|
}
|
|
334
735
|
}
|
|
736
|
+
async function checkCodexAvailability(installRoot, platform) {
|
|
737
|
+
const metadata = await loadInstallMetadata(installRoot);
|
|
738
|
+
const env = metadata ? buildToolEnv(metadata.tools, [], platform) : process.env;
|
|
739
|
+
const codexVersion = metadata ? resolveCodexVersion(metadata.tools.codexPath ?? void 0, env) : resolveCodexVersion(void 0, env);
|
|
740
|
+
if (codexVersion) {
|
|
741
|
+
return {
|
|
742
|
+
label: "codex",
|
|
743
|
+
ok: true,
|
|
744
|
+
detail: codexVersion
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
if (metadata?.tools.codexPath) {
|
|
748
|
+
return {
|
|
749
|
+
label: "codex",
|
|
750
|
+
ok: false,
|
|
751
|
+
detail: `Codex CLI was not available via stored install metadata (${metadata.tools.codexPath}).`
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
return {
|
|
755
|
+
label: "codex",
|
|
756
|
+
ok: false,
|
|
757
|
+
detail: "Codex CLI not found in stored install metadata or PATH."
|
|
758
|
+
};
|
|
759
|
+
}
|
|
335
760
|
async function runHostHealthCheck(hostPath, origin) {
|
|
336
|
-
const child = (
|
|
761
|
+
const child = spawnManaged(hostPath, [origin], {
|
|
337
762
|
stdio: ["pipe", "pipe", "pipe"]
|
|
338
763
|
});
|
|
339
764
|
const parser = new NativeMessageParser();
|
|
@@ -345,8 +770,8 @@ async function runHostHealthCheck(hostPath, origin) {
|
|
|
345
770
|
}, 3e3);
|
|
346
771
|
const cleanup = () => {
|
|
347
772
|
clearTimeout(timeout);
|
|
348
|
-
child.stdout
|
|
349
|
-
child.stderr
|
|
773
|
+
child.stdout?.off("data", handleStdout);
|
|
774
|
+
child.stderr?.off("data", handleStderr);
|
|
350
775
|
child.off("error", handleError);
|
|
351
776
|
child.off("exit", handleExit);
|
|
352
777
|
};
|
|
@@ -375,19 +800,19 @@ async function runHostHealthCheck(hostPath, origin) {
|
|
|
375
800
|
stderrTail ? `Dexly Companion exited before replying (code ${code ?? "null"}, signal ${signal ?? "null"}): ${stderrTail}` : `Dexly Companion exited before replying (code ${code ?? "null"}, signal ${signal ?? "null"}).`
|
|
376
801
|
));
|
|
377
802
|
};
|
|
378
|
-
child.stdout
|
|
379
|
-
child.stderr
|
|
803
|
+
child.stdout?.on("data", handleStdout);
|
|
804
|
+
child.stderr?.on("data", handleStderr);
|
|
380
805
|
child.once("error", handleError);
|
|
381
806
|
child.once("exit", handleExit);
|
|
382
807
|
});
|
|
383
|
-
child.stdin
|
|
808
|
+
child.stdin?.write(
|
|
384
809
|
encodeNativeMessage({
|
|
385
810
|
kind: "host/health",
|
|
386
811
|
requestId: "doctor-health"
|
|
387
812
|
})
|
|
388
813
|
);
|
|
389
814
|
const response = await messagePromise;
|
|
390
|
-
child.stdin
|
|
815
|
+
child.stdin?.end();
|
|
391
816
|
await Promise.race([
|
|
392
817
|
(0, import_node_events.once)(child, "exit"),
|
|
393
818
|
new Promise((resolve) => setTimeout(resolve, 250))
|
|
@@ -397,14 +822,21 @@ async function runHostHealthCheck(hostPath, origin) {
|
|
|
397
822
|
child.kill();
|
|
398
823
|
}
|
|
399
824
|
}
|
|
400
|
-
function
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
|
|
825
|
+
async function readWindowsRegistryManifestPath(registryKey) {
|
|
826
|
+
if (!registryKey.trim()) {
|
|
827
|
+
return null;
|
|
828
|
+
}
|
|
829
|
+
try {
|
|
830
|
+
const result = await runCommand("reg.exe", ["query", registryKey, "/ve"]);
|
|
831
|
+
const match = result.stdout.split(/\r?\n/).map((line) => line.trim()).find((line) => line.includes("REG_SZ"));
|
|
832
|
+
if (!match) {
|
|
833
|
+
return null;
|
|
834
|
+
}
|
|
835
|
+
const [, value] = match.split(/REG_SZ/i);
|
|
836
|
+
return value?.trim() || null;
|
|
837
|
+
} catch {
|
|
405
838
|
return null;
|
|
406
839
|
}
|
|
407
|
-
return result.stdout.trim() || null;
|
|
408
840
|
}
|
|
409
841
|
|
|
410
842
|
// src/host-runtime.ts
|
|
@@ -412,220 +844,62 @@ var import_node_process4 = __toESM(require("node:process"));
|
|
|
412
844
|
|
|
413
845
|
// src/codex-host.ts
|
|
414
846
|
var import_node_process3 = __toESM(require("node:process"));
|
|
415
|
-
var import_node_child_process3 = require("node:child_process");
|
|
416
847
|
var import_node_readline = __toESM(require("node:readline"));
|
|
417
|
-
var
|
|
848
|
+
var import_companion6 = __toESM(require_companion());
|
|
418
849
|
|
|
419
850
|
// src/management.ts
|
|
420
851
|
var import_promises4 = require("node:fs/promises");
|
|
421
|
-
var
|
|
422
|
-
|
|
423
|
-
// src/install-metadata.ts
|
|
424
|
-
var import_promises2 = require("node:fs/promises");
|
|
425
|
-
var import_companion3 = __toESM(require_companion());
|
|
426
|
-
function normalizeString(value) {
|
|
427
|
-
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
428
|
-
}
|
|
429
|
-
function normalizeToolPaths(value) {
|
|
430
|
-
if (!value || typeof value !== "object") {
|
|
431
|
-
return null;
|
|
432
|
-
}
|
|
433
|
-
const candidate = value;
|
|
434
|
-
const nodePath = normalizeString(candidate.nodePath);
|
|
435
|
-
const npmPath = normalizeString(candidate.npmPath);
|
|
436
|
-
if (!nodePath || !npmPath) {
|
|
437
|
-
return null;
|
|
438
|
-
}
|
|
439
|
-
return {
|
|
440
|
-
nodePath,
|
|
441
|
-
npmPath,
|
|
442
|
-
codexPath: normalizeString(candidate.codexPath)
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
async function loadInstallMetadata(installRoot) {
|
|
446
|
-
try {
|
|
447
|
-
const raw = await (0, import_promises2.readFile)(installMetadataPath(installRoot), "utf8");
|
|
448
|
-
const parsed = JSON.parse(raw);
|
|
449
|
-
const tools = normalizeToolPaths(parsed.tools);
|
|
450
|
-
const currentVersion = normalizeString(parsed.currentVersion);
|
|
451
|
-
const installedAt = normalizeString(parsed.installedAt);
|
|
452
|
-
const updatedAt = normalizeString(parsed.updatedAt);
|
|
453
|
-
if (!tools || !currentVersion || !installedAt || !updatedAt) {
|
|
454
|
-
return null;
|
|
455
|
-
}
|
|
456
|
-
const knownGoodVersions = Array.isArray(parsed.knownGoodVersions) ? parsed.knownGoodVersions.filter((value) => typeof value === "string" && value.trim().length > 0) : [currentVersion];
|
|
457
|
-
return {
|
|
458
|
-
schemaVersion: 1,
|
|
459
|
-
packageName: import_companion3.DEXLY_COMPANION_PACKAGE_NAME,
|
|
460
|
-
executableName: import_companion3.DEXLY_COMPANION_EXECUTABLE_NAME,
|
|
461
|
-
currentVersion,
|
|
462
|
-
previousVersion: normalizeString(parsed.previousVersion),
|
|
463
|
-
knownGoodVersions: knownGoodVersions.length > 0 ? knownGoodVersions : [currentVersion],
|
|
464
|
-
currentChannel: normalizeString(parsed.currentChannel),
|
|
465
|
-
installedAt,
|
|
466
|
-
updatedAt,
|
|
467
|
-
tools
|
|
468
|
-
};
|
|
469
|
-
} catch {
|
|
470
|
-
return null;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
async function saveInstallMetadata(installRoot, metadata) {
|
|
474
|
-
await (0, import_promises2.writeFile)(
|
|
475
|
-
installMetadataPath(installRoot),
|
|
476
|
-
`${JSON.stringify(metadata, null, 2)}
|
|
477
|
-
`,
|
|
478
|
-
"utf8"
|
|
479
|
-
);
|
|
480
|
-
}
|
|
852
|
+
var import_companion5 = __toESM(require_companion());
|
|
481
853
|
|
|
482
854
|
// src/install.ts
|
|
483
855
|
var import_promises3 = require("node:fs/promises");
|
|
484
|
-
var
|
|
485
|
-
var import_node_process2 = __toESM(require("node:process"));
|
|
486
|
-
|
|
487
|
-
// src/tooling.ts
|
|
488
|
-
var import_node_path2 = __toESM(require("node:path"));
|
|
489
|
-
var import_node_process = __toESM(require("node:process"));
|
|
490
|
-
var import_node_child_process2 = require("node:child_process");
|
|
491
|
-
function detectToolPaths() {
|
|
492
|
-
const nodePath = import_node_process.default.execPath;
|
|
493
|
-
const npmPath = resolveExecutablePath("npm") ?? "npm";
|
|
494
|
-
const codexPath = resolveExecutablePath("codex");
|
|
495
|
-
return {
|
|
496
|
-
nodePath,
|
|
497
|
-
npmPath,
|
|
498
|
-
codexPath
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
function resolveExecutablePath(command, env = import_node_process.default.env) {
|
|
502
|
-
const result = (0, import_node_child_process2.spawnSync)("which", [command], {
|
|
503
|
-
encoding: "utf8",
|
|
504
|
-
env
|
|
505
|
-
});
|
|
506
|
-
if (result.status !== 0) {
|
|
507
|
-
return null;
|
|
508
|
-
}
|
|
509
|
-
const executablePath = result.stdout.trim();
|
|
510
|
-
return executablePath.length > 0 ? executablePath : null;
|
|
511
|
-
}
|
|
512
|
-
function buildToolEnv(toolPaths, extraPaths = []) {
|
|
513
|
-
const pathEntries = [
|
|
514
|
-
import_node_path2.default.dirname(toolPaths.nodePath),
|
|
515
|
-
import_node_path2.default.dirname(toolPaths.npmPath),
|
|
516
|
-
toolPaths.codexPath ? import_node_path2.default.dirname(toolPaths.codexPath) : null,
|
|
517
|
-
...extraPaths,
|
|
518
|
-
"/usr/local/bin",
|
|
519
|
-
"/opt/homebrew/bin",
|
|
520
|
-
"/usr/bin",
|
|
521
|
-
"/bin",
|
|
522
|
-
"/usr/sbin",
|
|
523
|
-
"/sbin",
|
|
524
|
-
import_node_process.default.env.PATH ?? null
|
|
525
|
-
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
526
|
-
return {
|
|
527
|
-
...import_node_process.default.env,
|
|
528
|
-
PATH: pathEntries.join(":"),
|
|
529
|
-
...toolPaths.codexPath ? { DEXLY_COMPANION_CODEX_PATH: toolPaths.codexPath } : {}
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
async function runCommand(command, args, options = {}) {
|
|
533
|
-
return await new Promise((resolve, reject) => {
|
|
534
|
-
const child = (0, import_node_child_process2.spawn)(command, args, {
|
|
535
|
-
cwd: options.cwd,
|
|
536
|
-
env: options.env,
|
|
537
|
-
stdio: "pipe"
|
|
538
|
-
});
|
|
539
|
-
let stdout = "";
|
|
540
|
-
let stderr = "";
|
|
541
|
-
child.stdout.on("data", (chunk) => {
|
|
542
|
-
stdout += (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString("utf8");
|
|
543
|
-
});
|
|
544
|
-
child.stderr.on("data", (chunk) => {
|
|
545
|
-
stderr += (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString("utf8");
|
|
546
|
-
});
|
|
547
|
-
child.once("error", (error) => {
|
|
548
|
-
reject(error);
|
|
549
|
-
});
|
|
550
|
-
child.once("exit", (code, signal) => {
|
|
551
|
-
if (code === 0) {
|
|
552
|
-
resolve({ stdout, stderr });
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
const detail = stderr.trim() || stdout.trim();
|
|
556
|
-
reject(new Error(
|
|
557
|
-
detail.length > 0 ? `${command} ${args.join(" ")} failed (${code ?? signal ?? "unknown"}): ${detail}` : `${command} ${args.join(" ")} failed (${code ?? signal ?? "unknown"}).`
|
|
558
|
-
));
|
|
559
|
-
});
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
function resolveCodexVersion2(codexCommand = import_node_process.default.env.DEXLY_COMPANION_CODEX_PATH ?? "codex", env = import_node_process.default.env) {
|
|
563
|
-
const result = (0, import_node_child_process2.spawnSync)(codexCommand, ["--version"], {
|
|
564
|
-
encoding: "utf8",
|
|
565
|
-
env
|
|
566
|
-
});
|
|
567
|
-
if (result.error || result.status !== 0) {
|
|
568
|
-
return null;
|
|
569
|
-
}
|
|
570
|
-
return result.stdout.trim() || null;
|
|
571
|
-
}
|
|
572
|
-
function resolveNpmGlobalBinDir(npmPath, env = import_node_process.default.env) {
|
|
573
|
-
const result = (0, import_node_child_process2.spawnSync)(npmPath, ["config", "get", "prefix"], {
|
|
574
|
-
encoding: "utf8",
|
|
575
|
-
env
|
|
576
|
-
});
|
|
577
|
-
if (result.error || result.status !== 0) {
|
|
578
|
-
return null;
|
|
579
|
-
}
|
|
580
|
-
const prefix = result.stdout.trim();
|
|
581
|
-
return prefix.length > 0 ? import_node_path2.default.join(prefix, "bin") : null;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
// src/install.ts
|
|
856
|
+
var import_node_path4 = __toESM(require("node:path"));
|
|
585
857
|
async function installCompanion(options) {
|
|
586
|
-
if (import_node_process2.default.platform !== "darwin") {
|
|
587
|
-
throw new Error("Dexly Companion phase one currently supports macOS only.");
|
|
588
|
-
}
|
|
589
858
|
await assertInstallablePackageExists(options.sourcePackageDir);
|
|
590
|
-
const
|
|
591
|
-
const
|
|
592
|
-
const manifestPath =
|
|
593
|
-
const hostPath = installedHostLauncherPath(installRoot);
|
|
859
|
+
const layout = resolvePlatformLayout(options);
|
|
860
|
+
const installRoot = layout.installRoot;
|
|
861
|
+
const manifestPath = layout.hostRegistration.manifestPath;
|
|
862
|
+
const hostPath = installedHostLauncherPath(installRoot, layout.platform);
|
|
594
863
|
const allowedOrigins = defaultChromeAllowedOrigins();
|
|
595
864
|
const toolPaths = options.toolPaths ?? detectToolPaths();
|
|
596
|
-
const sourceDistDir =
|
|
597
|
-
const sourcePackageJsonPath =
|
|
865
|
+
const sourceDistDir = import_node_path4.default.join(options.sourcePackageDir, "dist");
|
|
866
|
+
const sourcePackageJsonPath = import_node_path4.default.join(options.sourcePackageDir, "package.json");
|
|
598
867
|
const installVersion = await readInstallPackageVersion(sourcePackageJsonPath);
|
|
599
868
|
const versionRoot = versionInstallPath(installRoot, installVersion);
|
|
600
869
|
const stagingVersionRoot = `${versionRoot}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
601
870
|
await (0, import_promises3.mkdir)(versionStorePath(installRoot), { recursive: true });
|
|
602
871
|
await (0, import_promises3.rm)(stagingVersionRoot, { recursive: true, force: true });
|
|
603
872
|
try {
|
|
604
|
-
await (0, import_promises3.mkdir)(
|
|
605
|
-
await (0, import_promises3.cp)(sourceDistDir,
|
|
873
|
+
await (0, import_promises3.mkdir)(import_node_path4.default.join(stagingVersionRoot, "dist"), { recursive: true });
|
|
874
|
+
await (0, import_promises3.cp)(sourceDistDir, import_node_path4.default.join(stagingVersionRoot, "dist"), { recursive: true });
|
|
606
875
|
await (0, import_promises3.copyFile)(sourcePackageJsonPath, versionedPackageJsonPath(stagingVersionRoot));
|
|
607
|
-
await (
|
|
608
|
-
await (
|
|
609
|
-
await (0, import_promises3.mkdir)(
|
|
876
|
+
await chmodIfSupported(layout.platform, versionedCliPath(stagingVersionRoot));
|
|
877
|
+
await chmodIfSupported(layout.platform, versionedHostScriptPath(stagingVersionRoot));
|
|
878
|
+
await (0, import_promises3.mkdir)(import_node_path4.default.dirname(versionedHostLauncherPath(stagingVersionRoot, layout.platform)), { recursive: true });
|
|
610
879
|
await (0, import_promises3.writeFile)(
|
|
611
|
-
versionedHostLauncherPath(stagingVersionRoot),
|
|
880
|
+
versionedHostLauncherPath(stagingVersionRoot, layout.platform),
|
|
612
881
|
renderHostLauncher({
|
|
882
|
+
platform: layout.platform,
|
|
613
883
|
nodePath: toolPaths.nodePath,
|
|
614
884
|
hostScriptPath: installedHostScriptPath(installRoot),
|
|
615
885
|
codexPath: toolPaths.codexPath
|
|
616
886
|
}),
|
|
617
887
|
"utf8"
|
|
618
888
|
);
|
|
619
|
-
await (
|
|
889
|
+
await chmodIfSupported(layout.platform, versionedHostLauncherPath(stagingVersionRoot, layout.platform));
|
|
620
890
|
await (0, import_promises3.rm)(versionRoot, { recursive: true, force: true });
|
|
621
891
|
await (0, import_promises3.rename)(stagingVersionRoot, versionRoot);
|
|
622
892
|
} catch (error) {
|
|
623
893
|
await (0, import_promises3.rm)(stagingVersionRoot, { recursive: true, force: true }).catch(() => void 0);
|
|
624
894
|
throw error;
|
|
625
895
|
}
|
|
626
|
-
await activateInstalledVersion(installRoot, installVersion);
|
|
627
|
-
await rewriteCurrentLauncher(installRoot, toolPaths);
|
|
628
|
-
await
|
|
896
|
+
await activateInstalledVersion(installRoot, installVersion, { platform: layout.platform });
|
|
897
|
+
await rewriteCurrentLauncher(installRoot, toolPaths, { platform: layout.platform });
|
|
898
|
+
await ensureChromeHostRegistration(installRoot, {
|
|
899
|
+
...options,
|
|
900
|
+
platform: layout.platform,
|
|
901
|
+
registryWriter: options.registryWriter
|
|
902
|
+
});
|
|
629
903
|
const existingMetadata = await loadInstallMetadata(installRoot);
|
|
630
904
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
631
905
|
const metadata = {
|
|
@@ -651,13 +925,30 @@ async function installCompanion(options) {
|
|
|
651
925
|
hostPath,
|
|
652
926
|
allowedOrigins,
|
|
653
927
|
version: installVersion,
|
|
654
|
-
metadataPath:
|
|
928
|
+
metadataPath: import_node_path4.default.join(installRoot, "install-metadata.json")
|
|
655
929
|
};
|
|
656
930
|
}
|
|
657
|
-
async function activateInstalledVersion(installRoot, version) {
|
|
931
|
+
async function activateInstalledVersion(installRoot, version, options = {}) {
|
|
932
|
+
const layout = resolvePlatformLayout({
|
|
933
|
+
installRoot,
|
|
934
|
+
platform: options.platform
|
|
935
|
+
});
|
|
658
936
|
const currentPath = currentInstallPath(installRoot);
|
|
937
|
+
const versionPath = versionInstallPath(installRoot, version);
|
|
938
|
+
if (layout.activationStrategy === "copy") {
|
|
939
|
+
const stagingCurrentPath = `${currentPath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
940
|
+
await (0, import_promises3.rm)(stagingCurrentPath, { recursive: true, force: true });
|
|
941
|
+
await (0, import_promises3.cp)(versionPath, stagingCurrentPath, { recursive: true });
|
|
942
|
+
try {
|
|
943
|
+
await (0, import_promises3.rename)(stagingCurrentPath, currentPath);
|
|
944
|
+
} catch {
|
|
945
|
+
await (0, import_promises3.rm)(currentPath, { recursive: true, force: true });
|
|
946
|
+
await (0, import_promises3.rename)(stagingCurrentPath, currentPath);
|
|
947
|
+
}
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
659
950
|
const tempLinkPath = `${currentPath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
660
|
-
const targetPath =
|
|
951
|
+
const targetPath = import_node_path4.default.join("versions", version);
|
|
661
952
|
await (0, import_promises3.mkdir)(installRoot, { recursive: true });
|
|
662
953
|
await (0, import_promises3.rm)(tempLinkPath, { recursive: true, force: true });
|
|
663
954
|
await (0, import_promises3.symlink)(targetPath, tempLinkPath);
|
|
@@ -668,30 +959,51 @@ async function activateInstalledVersion(installRoot, version) {
|
|
|
668
959
|
await (0, import_promises3.rename)(tempLinkPath, currentPath);
|
|
669
960
|
}
|
|
670
961
|
}
|
|
671
|
-
async function rewriteCurrentLauncher(installRoot, toolPaths) {
|
|
672
|
-
const
|
|
673
|
-
|
|
962
|
+
async function rewriteCurrentLauncher(installRoot, toolPaths, options = {}) {
|
|
963
|
+
const layout = resolvePlatformLayout({
|
|
964
|
+
installRoot,
|
|
965
|
+
platform: options.platform
|
|
966
|
+
});
|
|
967
|
+
const launcherPath = installedHostLauncherPath(installRoot, layout.platform);
|
|
968
|
+
await (0, import_promises3.mkdir)(import_node_path4.default.dirname(launcherPath), { recursive: true });
|
|
674
969
|
await (0, import_promises3.writeFile)(
|
|
675
970
|
launcherPath,
|
|
676
971
|
renderHostLauncher({
|
|
972
|
+
platform: layout.platform,
|
|
677
973
|
nodePath: toolPaths.nodePath,
|
|
678
974
|
hostScriptPath: installedHostScriptPath(installRoot),
|
|
679
975
|
codexPath: toolPaths.codexPath
|
|
680
976
|
}),
|
|
681
977
|
"utf8"
|
|
682
978
|
);
|
|
683
|
-
await (
|
|
979
|
+
await chmodIfSupported(layout.platform, launcherPath);
|
|
684
980
|
return launcherPath;
|
|
685
981
|
}
|
|
686
|
-
async function
|
|
687
|
-
const
|
|
688
|
-
|
|
982
|
+
async function ensureChromeHostRegistration(installRoot, options = {}) {
|
|
983
|
+
const layout = resolvePlatformLayout({
|
|
984
|
+
installRoot,
|
|
985
|
+
platform: options.platform,
|
|
986
|
+
manifestDir: options.manifestDir,
|
|
987
|
+
windowsRegistryKey: options.windowsRegistryKey
|
|
988
|
+
});
|
|
989
|
+
const manifestPath = layout.hostRegistration.manifestPath;
|
|
990
|
+
await (0, import_promises3.mkdir)(import_node_path4.default.dirname(manifestPath), { recursive: true });
|
|
689
991
|
await (0, import_promises3.writeFile)(
|
|
690
992
|
manifestPath,
|
|
691
|
-
`${JSON.stringify(
|
|
993
|
+
`${JSON.stringify(
|
|
994
|
+
buildChromeHostManifest(installedHostLauncherPath(installRoot, layout.platform), layout.hostRegistration.allowedOrigins),
|
|
995
|
+
null,
|
|
996
|
+
2
|
|
997
|
+
)}
|
|
692
998
|
`,
|
|
693
999
|
"utf8"
|
|
694
1000
|
);
|
|
1001
|
+
if (layout.hostRegistration.kind === "windows-registry" && layout.hostRegistration.registryKey) {
|
|
1002
|
+
await (options.registryWriter ?? writeWindowsRegistryManifestPath)(
|
|
1003
|
+
layout.hostRegistration.registryKey,
|
|
1004
|
+
manifestPath
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
695
1007
|
return manifestPath;
|
|
696
1008
|
}
|
|
697
1009
|
async function pruneVersionStore(installRoot, keepVersions) {
|
|
@@ -702,14 +1014,14 @@ async function pruneVersionStore(installRoot, keepVersions) {
|
|
|
702
1014
|
if (keep.has(entry)) {
|
|
703
1015
|
return;
|
|
704
1016
|
}
|
|
705
|
-
await (0, import_promises3.rm)(
|
|
1017
|
+
await (0, import_promises3.rm)(import_node_path4.default.join(versionsPath, entry), { recursive: true, force: true });
|
|
706
1018
|
}));
|
|
707
1019
|
}
|
|
708
1020
|
async function assertInstallablePackageExists(sourcePackageDir) {
|
|
709
1021
|
const requiredPaths = [
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
1022
|
+
import_node_path4.default.join(sourcePackageDir, "dist", "cli.js"),
|
|
1023
|
+
import_node_path4.default.join(sourcePackageDir, "dist", "host.js"),
|
|
1024
|
+
import_node_path4.default.join(sourcePackageDir, "package.json")
|
|
713
1025
|
];
|
|
714
1026
|
for (const filePath of requiredPaths) {
|
|
715
1027
|
try {
|
|
@@ -728,29 +1040,23 @@ async function readInstallPackageVersion(packageJsonPath) {
|
|
|
728
1040
|
}
|
|
729
1041
|
return packageJson.version.trim();
|
|
730
1042
|
}
|
|
731
|
-
function
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
"/opt/homebrew/bin",
|
|
737
|
-
"/usr/bin",
|
|
738
|
-
"/bin",
|
|
739
|
-
"/usr/sbin",
|
|
740
|
-
"/sbin"
|
|
741
|
-
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
742
|
-
const lines = [
|
|
743
|
-
"#!/bin/sh",
|
|
744
|
-
"set -eu",
|
|
745
|
-
`export PATH=${toShellLiteral(pathEntries.join(":"))}`,
|
|
746
|
-
options.codexPath ? `export DEXLY_COMPANION_CODEX_PATH=${toShellLiteral(options.codexPath)}` : null,
|
|
747
|
-
`exec ${toShellLiteral(options.nodePath)} ${toShellLiteral(options.hostScriptPath)} "$@"`
|
|
748
|
-
].filter((line) => typeof line === "string");
|
|
749
|
-
return `${lines.join("\n")}
|
|
750
|
-
`;
|
|
1043
|
+
async function chmodIfSupported(platform, targetPath) {
|
|
1044
|
+
if (platform === "win32") {
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
await (0, import_promises3.chmod)(targetPath, 493);
|
|
751
1048
|
}
|
|
752
|
-
function
|
|
753
|
-
|
|
1049
|
+
async function writeWindowsRegistryManifestPath(registryKey, manifestPath) {
|
|
1050
|
+
await runCommand("reg.exe", [
|
|
1051
|
+
"add",
|
|
1052
|
+
registryKey,
|
|
1053
|
+
"/ve",
|
|
1054
|
+
"/t",
|
|
1055
|
+
"REG_SZ",
|
|
1056
|
+
"/d",
|
|
1057
|
+
manifestPath,
|
|
1058
|
+
"/f"
|
|
1059
|
+
]);
|
|
754
1060
|
}
|
|
755
1061
|
|
|
756
1062
|
// src/management.ts
|
|
@@ -771,19 +1077,19 @@ function nextMetadata(metadata, nextVersion, channel) {
|
|
|
771
1077
|
};
|
|
772
1078
|
}
|
|
773
1079
|
async function upgradeInstalledCompanion(options) {
|
|
774
|
-
const installRoot = options.installRoot ?? defaultInstallRoot();
|
|
1080
|
+
const installRoot = options.installRoot ?? defaultInstallRoot({ platform: options.platform });
|
|
775
1081
|
const metadata = await loadInstallMetadata(installRoot);
|
|
776
1082
|
if (!metadata) {
|
|
777
1083
|
throw new Error("Dexly Companion install metadata is missing. Reinstall Dexly Companion first.");
|
|
778
1084
|
}
|
|
779
1085
|
const specifier = options.version?.trim() ? options.version.trim() : options.distTag.trim();
|
|
780
|
-
const targetSpecifier = `${
|
|
781
|
-
const env = buildToolEnv(metadata.tools);
|
|
1086
|
+
const targetSpecifier = `${import_companion5.DEXLY_COMPANION_PACKAGE_NAME}@${specifier}`;
|
|
1087
|
+
const env = buildToolEnv(metadata.tools, [], options.platform);
|
|
782
1088
|
await runCommand(metadata.tools.npmPath, [
|
|
783
1089
|
"exec",
|
|
784
1090
|
"--yes",
|
|
785
1091
|
`--package=${targetSpecifier}`,
|
|
786
|
-
|
|
1092
|
+
import_companion5.DEXLY_COMPANION_EXECUTABLE_NAME,
|
|
787
1093
|
"install",
|
|
788
1094
|
"--channel",
|
|
789
1095
|
options.distTag
|
|
@@ -799,8 +1105,7 @@ async function upgradeInstalledCompanion(options) {
|
|
|
799
1105
|
};
|
|
800
1106
|
}
|
|
801
1107
|
async function rollbackInstalledCompanion(options) {
|
|
802
|
-
const installRoot = options?.installRoot ?? defaultInstallRoot();
|
|
803
|
-
const manifestDir = options?.manifestDir ?? defaultChromeHostManifestDir();
|
|
1108
|
+
const installRoot = options?.installRoot ?? defaultInstallRoot({ platform: options?.platform });
|
|
804
1109
|
const metadata = await loadInstallMetadata(installRoot);
|
|
805
1110
|
if (!metadata) {
|
|
806
1111
|
throw new Error("Dexly Companion install metadata is missing. Reinstall Dexly Companion first.");
|
|
@@ -810,9 +1115,13 @@ async function rollbackInstalledCompanion(options) {
|
|
|
810
1115
|
throw new Error("Dexly Companion does not have a previous known-good version to roll back to.");
|
|
811
1116
|
}
|
|
812
1117
|
await (0, import_promises4.access)(versionInstallPath(installRoot, previousVersion));
|
|
813
|
-
await activateInstalledVersion(installRoot, previousVersion);
|
|
814
|
-
await rewriteCurrentLauncher(installRoot, metadata.tools);
|
|
815
|
-
await
|
|
1118
|
+
await activateInstalledVersion(installRoot, previousVersion, { platform: options?.platform });
|
|
1119
|
+
await rewriteCurrentLauncher(installRoot, metadata.tools, { platform: options?.platform });
|
|
1120
|
+
await ensureChromeHostRegistration(installRoot, {
|
|
1121
|
+
platform: options?.platform,
|
|
1122
|
+
manifestDir: options?.manifestDir,
|
|
1123
|
+
windowsRegistryKey: options?.windowsRegistryKey
|
|
1124
|
+
});
|
|
816
1125
|
const next = nextMetadata(metadata, previousVersion, metadata.currentChannel);
|
|
817
1126
|
next.previousVersion = metadata.currentVersion;
|
|
818
1127
|
await saveInstallMetadata(installRoot, next);
|
|
@@ -822,16 +1131,15 @@ async function rollbackInstalledCompanion(options) {
|
|
|
822
1131
|
};
|
|
823
1132
|
}
|
|
824
1133
|
async function installCodexWithCompanion(options) {
|
|
825
|
-
const installRoot = options?.installRoot ?? defaultInstallRoot();
|
|
826
|
-
const manifestDir = options?.manifestDir ?? defaultChromeHostManifestDir();
|
|
1134
|
+
const installRoot = options?.installRoot ?? defaultInstallRoot({ platform: options?.platform });
|
|
827
1135
|
const existingMetadata = await loadInstallMetadata(installRoot);
|
|
828
1136
|
const toolPaths = existingMetadata?.tools ?? detectToolPaths();
|
|
829
|
-
const env = buildToolEnv(toolPaths);
|
|
1137
|
+
const env = buildToolEnv(toolPaths, [], options?.platform);
|
|
830
1138
|
await runCommand(toolPaths.npmPath, ["install", "-g", "@openai/codex"], { env });
|
|
831
|
-
const globalBinDir = resolveNpmGlobalBinDir(toolPaths.npmPath, env);
|
|
832
|
-
const nextEnv = buildToolEnv(toolPaths, globalBinDir ? [globalBinDir] : []);
|
|
833
|
-
const codexPath = resolveExecutablePath("codex", nextEnv);
|
|
834
|
-
const codexVersion =
|
|
1139
|
+
const globalBinDir = resolveNpmGlobalBinDir(toolPaths.npmPath, env, options?.platform);
|
|
1140
|
+
const nextEnv = buildToolEnv(toolPaths, globalBinDir ? [globalBinDir] : [], options?.platform);
|
|
1141
|
+
const codexPath = resolveExecutablePath("codex", nextEnv, options?.platform);
|
|
1142
|
+
const codexVersion = resolveCodexVersion(codexPath ?? void 0, nextEnv);
|
|
835
1143
|
if (!codexPath || !codexVersion) {
|
|
836
1144
|
throw new Error("Codex install completed, but Dexly Companion could not resolve the installed codex binary.");
|
|
837
1145
|
}
|
|
@@ -839,8 +1147,12 @@ async function installCodexWithCompanion(options) {
|
|
|
839
1147
|
...toolPaths,
|
|
840
1148
|
codexPath
|
|
841
1149
|
};
|
|
842
|
-
await rewriteCurrentLauncher(installRoot, nextToolPaths);
|
|
843
|
-
await
|
|
1150
|
+
await rewriteCurrentLauncher(installRoot, nextToolPaths, { platform: options?.platform });
|
|
1151
|
+
await ensureChromeHostRegistration(installRoot, {
|
|
1152
|
+
platform: options?.platform,
|
|
1153
|
+
manifestDir: options?.manifestDir,
|
|
1154
|
+
windowsRegistryKey: options?.windowsRegistryKey
|
|
1155
|
+
});
|
|
844
1156
|
if (existingMetadata) {
|
|
845
1157
|
await saveInstallMetadata(installRoot, {
|
|
846
1158
|
...existingMetadata,
|
|
@@ -851,7 +1163,7 @@ async function installCodexWithCompanion(options) {
|
|
|
851
1163
|
return {
|
|
852
1164
|
codexPath,
|
|
853
1165
|
codexVersion,
|
|
854
|
-
installCommand:
|
|
1166
|
+
installCommand: import_companion5.DEXLY_CODEX_INSTALL_COMMAND
|
|
855
1167
|
};
|
|
856
1168
|
}
|
|
857
1169
|
|
|
@@ -869,8 +1181,8 @@ var DexlyNativeHost = class {
|
|
|
869
1181
|
stderrLines = [];
|
|
870
1182
|
constructor(options) {
|
|
871
1183
|
this.send = options.send;
|
|
872
|
-
this.spawnProcess = options.spawnProcess ??
|
|
873
|
-
this.spawnProcessSync = options.spawnProcessSync ??
|
|
1184
|
+
this.spawnProcess = options.spawnProcess ?? ((command, args, spawnOptions) => spawnManaged(command, [...args], spawnOptions));
|
|
1185
|
+
this.spawnProcessSync = options.spawnProcessSync ?? ((command, args, spawnOptions) => spawnManagedSync(command, [...args], spawnOptions));
|
|
874
1186
|
this.codexCommand = options.codexCommand ?? import_node_process3.default.env.DEXLY_COMPANION_CODEX_PATH ?? "codex";
|
|
875
1187
|
this.requestProcessExit = options.requestProcessExit ?? null;
|
|
876
1188
|
}
|
|
@@ -1131,7 +1443,7 @@ var DexlyNativeHost = class {
|
|
|
1131
1443
|
null,
|
|
1132
1444
|
null,
|
|
1133
1445
|
"codex_not_connected",
|
|
1134
|
-
`${
|
|
1446
|
+
`${import_companion6.DEXLY_COMPANION_DISPLAY_NAME} is not connected to Codex app-server.`
|
|
1135
1447
|
));
|
|
1136
1448
|
return;
|
|
1137
1449
|
}
|
|
@@ -1266,7 +1578,7 @@ async function runHost() {
|
|
|
1266
1578
|
async function runInstall(args) {
|
|
1267
1579
|
const parsed = parseArgs(args);
|
|
1268
1580
|
const result = await installCompanion({
|
|
1269
|
-
sourcePackageDir:
|
|
1581
|
+
sourcePackageDir: import_node_path5.default.resolve(__dirname, ".."),
|
|
1270
1582
|
installRoot: parsed.installRoot,
|
|
1271
1583
|
manifestDir: parsed.manifestDir,
|
|
1272
1584
|
channel: parsed.channel
|
|
@@ -1294,7 +1606,7 @@ async function runDoctorCommand(args) {
|
|
|
1294
1606
|
}
|
|
1295
1607
|
if (!result.ok) {
|
|
1296
1608
|
import_node_process5.default.stdout.write(`
|
|
1297
|
-
If Dexly Companion is missing, run ${
|
|
1609
|
+
If Dexly Companion is missing, run ${import_companion7.DEXLY_COMPANION_INSTALL_COMMAND}.
|
|
1298
1610
|
`);
|
|
1299
1611
|
import_node_process5.default.exitCode = 1;
|
|
1300
1612
|
}
|