@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/host.js
CHANGED
|
@@ -117,33 +117,22 @@ var require_companion = __commonJS({
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
// src/host.ts
|
|
120
|
-
var
|
|
120
|
+
var import_node_process5 = __toESM(require("node:process"));
|
|
121
121
|
|
|
122
122
|
// src/host-runtime.ts
|
|
123
|
-
var
|
|
123
|
+
var import_node_process4 = __toESM(require("node:process"));
|
|
124
124
|
|
|
125
125
|
// src/codex-host.ts
|
|
126
|
-
var
|
|
127
|
-
var import_node_child_process2 = require("node:child_process");
|
|
126
|
+
var import_node_process3 = __toESM(require("node:process"));
|
|
128
127
|
var import_node_readline = __toESM(require("node:readline"));
|
|
129
|
-
var
|
|
128
|
+
var import_companion5 = __toESM(require_companion());
|
|
130
129
|
|
|
131
130
|
// src/constants.ts
|
|
132
|
-
var import_node_os = __toESM(require("node:os"));
|
|
133
131
|
var import_node_path = __toESM(require("node:path"));
|
|
134
132
|
var import_companion = __toESM(require_companion());
|
|
135
|
-
var DEXLY_COMPANION_VERSION = true ? "0.1.
|
|
133
|
+
var DEXLY_COMPANION_VERSION = true ? "0.1.3" : packageJson.version;
|
|
136
134
|
var DEXLY_COMPANION_DESCRIPTION = "Dexly native bridge for Codex";
|
|
137
135
|
var DEXLY_COMPANION_METADATA_FILE_NAME = "install-metadata.json";
|
|
138
|
-
function defaultInstallRoot(homeDir = import_node_os.default.homedir()) {
|
|
139
|
-
return import_node_path.default.join(homeDir, "Library", "Application Support", "Dexly", "companion");
|
|
140
|
-
}
|
|
141
|
-
function defaultChromeHostManifestDir(homeDir = import_node_os.default.homedir()) {
|
|
142
|
-
return import_node_path.default.join(homeDir, "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
143
|
-
}
|
|
144
|
-
function defaultChromeAllowedOrigins() {
|
|
145
|
-
return [...import_companion.DEXLY_FIXED_ALLOWED_ORIGINS];
|
|
146
|
-
}
|
|
147
136
|
function currentInstallPath(installRoot) {
|
|
148
137
|
return import_node_path.default.join(installRoot, "current");
|
|
149
138
|
}
|
|
@@ -153,11 +142,8 @@ function installMetadataPath(installRoot) {
|
|
|
153
142
|
function installedHostScriptPath(installRoot) {
|
|
154
143
|
return import_node_path.default.join(currentInstallPath(installRoot), "dist", "host.js");
|
|
155
144
|
}
|
|
156
|
-
function installedHostLauncherPath(installRoot) {
|
|
157
|
-
return import_node_path.default.join(currentInstallPath(installRoot), "bin",
|
|
158
|
-
}
|
|
159
|
-
function installedHostManifestPath(manifestDir) {
|
|
160
|
-
return import_node_path.default.join(manifestDir, `${import_companion.DEXLY_COMPANION_HOST_NAME}.json`);
|
|
145
|
+
function installedHostLauncherPath(installRoot, platform = process.platform) {
|
|
146
|
+
return import_node_path.default.join(currentInstallPath(installRoot), "bin", resolveLauncherFileName(platform));
|
|
161
147
|
}
|
|
162
148
|
function buildChromeHostManifest(hostPath, allowedOrigins) {
|
|
163
149
|
return {
|
|
@@ -168,9 +154,12 @@ function buildChromeHostManifest(hostPath, allowedOrigins) {
|
|
|
168
154
|
allowed_origins: allowedOrigins
|
|
169
155
|
};
|
|
170
156
|
}
|
|
157
|
+
function resolveLauncherFileName(platform) {
|
|
158
|
+
return platform === "win32" ? "dexly-companion-host.cmd" : "dexly-companion-host";
|
|
159
|
+
}
|
|
171
160
|
|
|
172
161
|
// src/management.ts
|
|
173
|
-
var
|
|
162
|
+
var import_companion4 = __toESM(require_companion());
|
|
174
163
|
|
|
175
164
|
// src/install-metadata.ts
|
|
176
165
|
var import_promises = require("node:fs/promises");
|
|
@@ -233,14 +222,171 @@ async function saveInstallMetadata(installRoot, metadata) {
|
|
|
233
222
|
|
|
234
223
|
// src/install.ts
|
|
235
224
|
var import_promises2 = require("node:fs/promises");
|
|
236
|
-
var
|
|
225
|
+
var import_node_path4 = __toESM(require("node:path"));
|
|
237
226
|
|
|
238
|
-
// src/
|
|
227
|
+
// src/platform.ts
|
|
228
|
+
var import_node_os = __toESM(require("node:os"));
|
|
239
229
|
var import_node_path2 = __toESM(require("node:path"));
|
|
240
230
|
var import_node_process = __toESM(require("node:process"));
|
|
231
|
+
var import_companion3 = __toESM(require_companion());
|
|
232
|
+
function assertSupportedPlatform(platform = import_node_process.default.platform) {
|
|
233
|
+
switch (platform) {
|
|
234
|
+
case "darwin":
|
|
235
|
+
case "linux":
|
|
236
|
+
case "win32":
|
|
237
|
+
return platform;
|
|
238
|
+
default:
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Dexly Companion currently supports macOS, Windows, and Linux only. Unsupported platform: ${platform}.`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function defaultChromeAllowedOrigins() {
|
|
245
|
+
return [...import_companion3.DEXLY_FIXED_ALLOWED_ORIGINS];
|
|
246
|
+
}
|
|
247
|
+
function defaultInstallRoot(options = {}) {
|
|
248
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
249
|
+
const homeDir = options.homeDir ?? import_node_os.default.homedir();
|
|
250
|
+
const env = options.env ?? import_node_process.default.env;
|
|
251
|
+
switch (platform) {
|
|
252
|
+
case "darwin":
|
|
253
|
+
return import_node_path2.default.join(homeDir, "Library", "Application Support", "Dexly", "companion");
|
|
254
|
+
case "linux": {
|
|
255
|
+
const dataHome = env.XDG_DATA_HOME?.trim() || import_node_path2.default.join(homeDir, ".local", "share");
|
|
256
|
+
return import_node_path2.default.join(dataHome, "Dexly", "companion");
|
|
257
|
+
}
|
|
258
|
+
case "win32": {
|
|
259
|
+
const localAppData = env.LOCALAPPDATA?.trim() || import_node_path2.default.join(homeDir, "AppData", "Local");
|
|
260
|
+
return import_node_path2.default.join(localAppData, "Dexly", "companion");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function resolveChromeHostRegistration(options = {}) {
|
|
265
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
266
|
+
const homeDir = options.homeDir ?? import_node_os.default.homedir();
|
|
267
|
+
const env = options.env ?? import_node_process.default.env;
|
|
268
|
+
const installRoot = options.installRoot ?? defaultInstallRoot({
|
|
269
|
+
platform,
|
|
270
|
+
homeDir,
|
|
271
|
+
env
|
|
272
|
+
});
|
|
273
|
+
const manifestPath = options.manifestDir ? import_node_path2.default.join(options.manifestDir, `${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`) : defaultChromeManifestPath({
|
|
274
|
+
platform,
|
|
275
|
+
homeDir,
|
|
276
|
+
env,
|
|
277
|
+
installRoot
|
|
278
|
+
});
|
|
279
|
+
if (platform === "win32") {
|
|
280
|
+
return {
|
|
281
|
+
kind: "windows-registry",
|
|
282
|
+
manifestPath,
|
|
283
|
+
allowedOrigins: defaultChromeAllowedOrigins(),
|
|
284
|
+
registryKey: options.windowsRegistryKey ?? `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${import_companion3.DEXLY_COMPANION_HOST_NAME}`
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
kind: "manifest-file",
|
|
289
|
+
manifestPath,
|
|
290
|
+
allowedOrigins: defaultChromeAllowedOrigins(),
|
|
291
|
+
registryKey: null
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function resolvePlatformLayout(options = {}) {
|
|
295
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
296
|
+
const installRoot = options.installRoot ?? defaultInstallRoot(options);
|
|
297
|
+
return {
|
|
298
|
+
platform,
|
|
299
|
+
installRoot,
|
|
300
|
+
activationStrategy: platform === "win32" ? "copy" : "symlink",
|
|
301
|
+
launcherKind: platform === "win32" ? "windows-cmd" : "posix",
|
|
302
|
+
launcherFileName: platform === "win32" ? "dexly-companion-host.cmd" : "dexly-companion-host",
|
|
303
|
+
hostRegistration: resolveChromeHostRegistration({
|
|
304
|
+
...options,
|
|
305
|
+
platform,
|
|
306
|
+
installRoot
|
|
307
|
+
})
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function defaultLauncherPathEntries(platform = import_node_process.default.platform, env = import_node_process.default.env) {
|
|
311
|
+
switch (assertSupportedPlatform(platform)) {
|
|
312
|
+
case "darwin":
|
|
313
|
+
return ["/usr/local/bin", "/opt/homebrew/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
314
|
+
case "linux":
|
|
315
|
+
return ["/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
316
|
+
case "win32": {
|
|
317
|
+
const systemRoot = env.SystemRoot?.trim() || "C:\\Windows";
|
|
318
|
+
return [import_node_path2.default.join(systemRoot, "System32"), systemRoot];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function renderHostLauncher(options) {
|
|
323
|
+
const platform = assertSupportedPlatform(options.platform);
|
|
324
|
+
const pathEntries = [
|
|
325
|
+
import_node_path2.default.dirname(options.nodePath),
|
|
326
|
+
options.codexPath ? import_node_path2.default.dirname(options.codexPath) : null,
|
|
327
|
+
...defaultLauncherPathEntries(platform, options.env ?? import_node_process.default.env)
|
|
328
|
+
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
329
|
+
if (platform === "win32") {
|
|
330
|
+
const lines2 = [
|
|
331
|
+
"@echo off",
|
|
332
|
+
"setlocal",
|
|
333
|
+
`set "PATH=${toBatchLiteral(pathEntries.join(import_node_path2.default.delimiter))};%PATH%"`,
|
|
334
|
+
options.codexPath ? `set "DEXLY_COMPANION_CODEX_PATH=${toBatchLiteral(options.codexPath)}"` : null,
|
|
335
|
+
`set "DEXLY_COMPANION_NODE_PATH=${toBatchLiteral(options.nodePath)}"`,
|
|
336
|
+
`set "DEXLY_COMPANION_HOST_SCRIPT=${toBatchLiteral(options.hostScriptPath)}"`,
|
|
337
|
+
'"%DEXLY_COMPANION_NODE_PATH%" "%DEXLY_COMPANION_HOST_SCRIPT%" %*'
|
|
338
|
+
].filter((line) => typeof line === "string");
|
|
339
|
+
return `${lines2.join("\r\n")}\r
|
|
340
|
+
`;
|
|
341
|
+
}
|
|
342
|
+
const lines = [
|
|
343
|
+
"#!/bin/sh",
|
|
344
|
+
"set -eu",
|
|
345
|
+
`export PATH=${toShellLiteral(pathEntries.join(import_node_path2.default.delimiter))}`,
|
|
346
|
+
options.codexPath ? `export DEXLY_COMPANION_CODEX_PATH=${toShellLiteral(options.codexPath)}` : null,
|
|
347
|
+
`exec ${toShellLiteral(options.nodePath)} ${toShellLiteral(options.hostScriptPath)} "$@"`
|
|
348
|
+
].filter((line) => typeof line === "string");
|
|
349
|
+
return `${lines.join("\n")}
|
|
350
|
+
`;
|
|
351
|
+
}
|
|
352
|
+
function defaultChromeManifestPath(options) {
|
|
353
|
+
switch (options.platform) {
|
|
354
|
+
case "darwin":
|
|
355
|
+
return import_node_path2.default.join(
|
|
356
|
+
options.homeDir,
|
|
357
|
+
"Library",
|
|
358
|
+
"Application Support",
|
|
359
|
+
"Google",
|
|
360
|
+
"Chrome",
|
|
361
|
+
"NativeMessagingHosts",
|
|
362
|
+
`${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`
|
|
363
|
+
);
|
|
364
|
+
case "linux": {
|
|
365
|
+
const configHome = options.env.XDG_CONFIG_HOME?.trim() || import_node_path2.default.join(options.homeDir, ".config");
|
|
366
|
+
return import_node_path2.default.join(
|
|
367
|
+
configHome,
|
|
368
|
+
"google-chrome",
|
|
369
|
+
"NativeMessagingHosts",
|
|
370
|
+
`${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
case "win32":
|
|
374
|
+
return import_node_path2.default.join(options.installRoot, "native-host", `${import_companion3.DEXLY_COMPANION_HOST_NAME}.json`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function toShellLiteral(value) {
|
|
378
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
379
|
+
}
|
|
380
|
+
function toBatchLiteral(value) {
|
|
381
|
+
return value.replace(/%/g, "%%").replace(/"/g, '""');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/tooling.ts
|
|
385
|
+
var import_node_path3 = __toESM(require("node:path"));
|
|
386
|
+
var import_node_process2 = __toESM(require("node:process"));
|
|
241
387
|
var import_node_child_process = require("node:child_process");
|
|
242
388
|
function detectToolPaths() {
|
|
243
|
-
const nodePath =
|
|
389
|
+
const nodePath = import_node_process2.default.execPath;
|
|
244
390
|
const npmPath = resolveExecutablePath("npm") ?? "npm";
|
|
245
391
|
const codexPath = resolveExecutablePath("codex");
|
|
246
392
|
return {
|
|
@@ -249,40 +395,38 @@ function detectToolPaths() {
|
|
|
249
395
|
codexPath
|
|
250
396
|
};
|
|
251
397
|
}
|
|
252
|
-
function resolveExecutablePath(command, env =
|
|
253
|
-
const
|
|
398
|
+
function resolveExecutablePath(command, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
399
|
+
const lookupCommand = platform === "win32" ? "where" : "which";
|
|
400
|
+
const result = (0, import_node_child_process.spawnSync)(lookupCommand, [command], {
|
|
254
401
|
encoding: "utf8",
|
|
255
402
|
env
|
|
256
403
|
});
|
|
257
|
-
if (result.status !== 0) {
|
|
404
|
+
if (result.error || result.status !== 0) {
|
|
258
405
|
return null;
|
|
259
406
|
}
|
|
260
|
-
const executablePath = result.stdout.trim();
|
|
261
|
-
return executablePath
|
|
407
|
+
const executablePath = result.stdout.split(/\r?\n/).map((value) => value.trim()).find((value) => value.length > 0);
|
|
408
|
+
return executablePath ?? null;
|
|
262
409
|
}
|
|
263
|
-
function buildToolEnv(toolPaths, extraPaths = []) {
|
|
410
|
+
function buildToolEnv(toolPaths, extraPaths = [], platform = import_node_process2.default.platform) {
|
|
411
|
+
const supportedPlatform = assertSupportedPlatform(platform);
|
|
412
|
+
const pathSeparator = supportedPlatform === "win32" ? ";" : ":";
|
|
264
413
|
const pathEntries = [
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
toolPaths.codexPath ?
|
|
414
|
+
import_node_path3.default.dirname(toolPaths.nodePath),
|
|
415
|
+
import_node_path3.default.dirname(toolPaths.npmPath),
|
|
416
|
+
toolPaths.codexPath ? import_node_path3.default.dirname(toolPaths.codexPath) : null,
|
|
268
417
|
...extraPaths,
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"/usr/bin",
|
|
272
|
-
"/bin",
|
|
273
|
-
"/usr/sbin",
|
|
274
|
-
"/sbin",
|
|
275
|
-
import_node_process.default.env.PATH ?? null
|
|
418
|
+
...defaultLauncherPathEntries(supportedPlatform, import_node_process2.default.env),
|
|
419
|
+
import_node_process2.default.env.PATH ?? null
|
|
276
420
|
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
277
421
|
return {
|
|
278
|
-
...
|
|
279
|
-
PATH: pathEntries.join(
|
|
422
|
+
...import_node_process2.default.env,
|
|
423
|
+
PATH: pathEntries.join(pathSeparator),
|
|
280
424
|
...toolPaths.codexPath ? { DEXLY_COMPANION_CODEX_PATH: toolPaths.codexPath } : {}
|
|
281
425
|
};
|
|
282
426
|
}
|
|
283
427
|
async function runCommand(command, args, options = {}) {
|
|
284
428
|
return await new Promise((resolve, reject) => {
|
|
285
|
-
const child = (
|
|
429
|
+
const child = spawnManaged(command, args, {
|
|
286
430
|
cwd: options.cwd,
|
|
287
431
|
env: options.env,
|
|
288
432
|
stdio: "pipe"
|
|
@@ -310,8 +454,8 @@ async function runCommand(command, args, options = {}) {
|
|
|
310
454
|
});
|
|
311
455
|
});
|
|
312
456
|
}
|
|
313
|
-
function resolveCodexVersion(codexCommand =
|
|
314
|
-
const result = (
|
|
457
|
+
function resolveCodexVersion(codexCommand = import_node_process2.default.env.DEXLY_COMPANION_CODEX_PATH ?? "codex", env = import_node_process2.default.env) {
|
|
458
|
+
const result = spawnManagedSync(codexCommand, ["--version"], {
|
|
315
459
|
encoding: "utf8",
|
|
316
460
|
env
|
|
317
461
|
});
|
|
@@ -320,8 +464,8 @@ function resolveCodexVersion(codexCommand = import_node_process.default.env.DEXL
|
|
|
320
464
|
}
|
|
321
465
|
return result.stdout.trim() || null;
|
|
322
466
|
}
|
|
323
|
-
function resolveNpmGlobalBinDir(npmPath, env =
|
|
324
|
-
const result = (
|
|
467
|
+
function resolveNpmGlobalBinDir(npmPath, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
468
|
+
const result = spawnManagedSync(npmPath, ["config", "get", "prefix"], {
|
|
325
469
|
encoding: "utf8",
|
|
326
470
|
env
|
|
327
471
|
});
|
|
@@ -329,76 +473,151 @@ function resolveNpmGlobalBinDir(npmPath, env = import_node_process.default.env)
|
|
|
329
473
|
return null;
|
|
330
474
|
}
|
|
331
475
|
const prefix = result.stdout.trim();
|
|
332
|
-
|
|
476
|
+
if (prefix.length === 0) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
return npmGlobalBinDirFromPrefix(prefix, platform);
|
|
480
|
+
}
|
|
481
|
+
function spawnManaged(command, args, options = {}) {
|
|
482
|
+
const invocation = buildSpawnInvocation(command, args, options.env);
|
|
483
|
+
return (0, import_node_child_process.spawn)(invocation.command, invocation.args, {
|
|
484
|
+
...options,
|
|
485
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
function spawnManagedSync(command, args, options = {}) {
|
|
489
|
+
const invocation = buildSpawnInvocation(command, args, options.env);
|
|
490
|
+
return (0, import_node_child_process.spawnSync)(invocation.command, invocation.args, {
|
|
491
|
+
...options,
|
|
492
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function buildSpawnInvocation(command, args, env = import_node_process2.default.env, platform = import_node_process2.default.platform) {
|
|
496
|
+
if (platform !== "win32" || !isWindowsCommandScript(command, platform)) {
|
|
497
|
+
return {
|
|
498
|
+
command,
|
|
499
|
+
args
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
return {
|
|
503
|
+
command: resolveWindowsCommandShell(env),
|
|
504
|
+
args: ["/d", "/s", "/c", quoteWindowsCommand([command, ...args])],
|
|
505
|
+
windowsVerbatimArguments: false
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function isWindowsCommandScript(command, platform = import_node_process2.default.platform) {
|
|
509
|
+
if (platform !== "win32") {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
const normalized = command.trim().toLowerCase();
|
|
513
|
+
return normalized.endsWith(".cmd") || normalized.endsWith(".bat");
|
|
514
|
+
}
|
|
515
|
+
function resolveWindowsCommandShell(env = import_node_process2.default.env) {
|
|
516
|
+
const comSpec = env.ComSpec?.trim();
|
|
517
|
+
if (comSpec) {
|
|
518
|
+
return comSpec;
|
|
519
|
+
}
|
|
520
|
+
const systemRoot = env.SystemRoot?.trim() || "C:\\Windows";
|
|
521
|
+
return import_node_path3.default.join(systemRoot, "System32", "cmd.exe");
|
|
522
|
+
}
|
|
523
|
+
function quoteWindowsCommand(parts) {
|
|
524
|
+
return parts.map(quoteWindowsArgument).join(" ");
|
|
525
|
+
}
|
|
526
|
+
function quoteWindowsArgument(value) {
|
|
527
|
+
if (value.length === 0) {
|
|
528
|
+
return '""';
|
|
529
|
+
}
|
|
530
|
+
if (!/[ \t"&()^<>|]/.test(value)) {
|
|
531
|
+
return value;
|
|
532
|
+
}
|
|
533
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
534
|
+
}
|
|
535
|
+
function npmGlobalBinDirFromPrefix(prefix, platform = import_node_process2.default.platform) {
|
|
536
|
+
return platform === "win32" ? prefix : import_node_path3.default.join(prefix, "bin");
|
|
333
537
|
}
|
|
334
538
|
|
|
335
539
|
// src/install.ts
|
|
336
|
-
async function rewriteCurrentLauncher(installRoot, toolPaths) {
|
|
337
|
-
const
|
|
338
|
-
|
|
540
|
+
async function rewriteCurrentLauncher(installRoot, toolPaths, options = {}) {
|
|
541
|
+
const layout = resolvePlatformLayout({
|
|
542
|
+
installRoot,
|
|
543
|
+
platform: options.platform
|
|
544
|
+
});
|
|
545
|
+
const launcherPath = installedHostLauncherPath(installRoot, layout.platform);
|
|
546
|
+
await (0, import_promises2.mkdir)(import_node_path4.default.dirname(launcherPath), { recursive: true });
|
|
339
547
|
await (0, import_promises2.writeFile)(
|
|
340
548
|
launcherPath,
|
|
341
549
|
renderHostLauncher({
|
|
550
|
+
platform: layout.platform,
|
|
342
551
|
nodePath: toolPaths.nodePath,
|
|
343
552
|
hostScriptPath: installedHostScriptPath(installRoot),
|
|
344
553
|
codexPath: toolPaths.codexPath
|
|
345
554
|
}),
|
|
346
555
|
"utf8"
|
|
347
556
|
);
|
|
348
|
-
await (
|
|
557
|
+
await chmodIfSupported(layout.platform, launcherPath);
|
|
349
558
|
return launcherPath;
|
|
350
559
|
}
|
|
351
|
-
async function
|
|
352
|
-
const
|
|
353
|
-
|
|
560
|
+
async function ensureChromeHostRegistration(installRoot, options = {}) {
|
|
561
|
+
const layout = resolvePlatformLayout({
|
|
562
|
+
installRoot,
|
|
563
|
+
platform: options.platform,
|
|
564
|
+
manifestDir: options.manifestDir,
|
|
565
|
+
windowsRegistryKey: options.windowsRegistryKey
|
|
566
|
+
});
|
|
567
|
+
const manifestPath = layout.hostRegistration.manifestPath;
|
|
568
|
+
await (0, import_promises2.mkdir)(import_node_path4.default.dirname(manifestPath), { recursive: true });
|
|
354
569
|
await (0, import_promises2.writeFile)(
|
|
355
570
|
manifestPath,
|
|
356
|
-
`${JSON.stringify(
|
|
571
|
+
`${JSON.stringify(
|
|
572
|
+
buildChromeHostManifest(installedHostLauncherPath(installRoot, layout.platform), layout.hostRegistration.allowedOrigins),
|
|
573
|
+
null,
|
|
574
|
+
2
|
|
575
|
+
)}
|
|
357
576
|
`,
|
|
358
577
|
"utf8"
|
|
359
578
|
);
|
|
579
|
+
if (layout.hostRegistration.kind === "windows-registry" && layout.hostRegistration.registryKey) {
|
|
580
|
+
await (options.registryWriter ?? writeWindowsRegistryManifestPath)(
|
|
581
|
+
layout.hostRegistration.registryKey,
|
|
582
|
+
manifestPath
|
|
583
|
+
);
|
|
584
|
+
}
|
|
360
585
|
return manifestPath;
|
|
361
586
|
}
|
|
362
|
-
function
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
"/opt/homebrew/bin",
|
|
368
|
-
"/usr/bin",
|
|
369
|
-
"/bin",
|
|
370
|
-
"/usr/sbin",
|
|
371
|
-
"/sbin"
|
|
372
|
-
].filter((entry, index, entries) => typeof entry === "string" && entries.indexOf(entry) === index);
|
|
373
|
-
const lines = [
|
|
374
|
-
"#!/bin/sh",
|
|
375
|
-
"set -eu",
|
|
376
|
-
`export PATH=${toShellLiteral(pathEntries.join(":"))}`,
|
|
377
|
-
options.codexPath ? `export DEXLY_COMPANION_CODEX_PATH=${toShellLiteral(options.codexPath)}` : null,
|
|
378
|
-
`exec ${toShellLiteral(options.nodePath)} ${toShellLiteral(options.hostScriptPath)} "$@"`
|
|
379
|
-
].filter((line) => typeof line === "string");
|
|
380
|
-
return `${lines.join("\n")}
|
|
381
|
-
`;
|
|
587
|
+
async function chmodIfSupported(platform, targetPath) {
|
|
588
|
+
if (platform === "win32") {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
await (0, import_promises2.chmod)(targetPath, 493);
|
|
382
592
|
}
|
|
383
|
-
function
|
|
384
|
-
|
|
593
|
+
async function writeWindowsRegistryManifestPath(registryKey, manifestPath) {
|
|
594
|
+
await runCommand("reg.exe", [
|
|
595
|
+
"add",
|
|
596
|
+
registryKey,
|
|
597
|
+
"/ve",
|
|
598
|
+
"/t",
|
|
599
|
+
"REG_SZ",
|
|
600
|
+
"/d",
|
|
601
|
+
manifestPath,
|
|
602
|
+
"/f"
|
|
603
|
+
]);
|
|
385
604
|
}
|
|
386
605
|
|
|
387
606
|
// src/management.ts
|
|
388
607
|
async function upgradeInstalledCompanion(options) {
|
|
389
|
-
const installRoot = options.installRoot ?? defaultInstallRoot();
|
|
608
|
+
const installRoot = options.installRoot ?? defaultInstallRoot({ platform: options.platform });
|
|
390
609
|
const metadata = await loadInstallMetadata(installRoot);
|
|
391
610
|
if (!metadata) {
|
|
392
611
|
throw new Error("Dexly Companion install metadata is missing. Reinstall Dexly Companion first.");
|
|
393
612
|
}
|
|
394
613
|
const specifier = options.version?.trim() ? options.version.trim() : options.distTag.trim();
|
|
395
|
-
const targetSpecifier = `${
|
|
396
|
-
const env = buildToolEnv(metadata.tools);
|
|
614
|
+
const targetSpecifier = `${import_companion4.DEXLY_COMPANION_PACKAGE_NAME}@${specifier}`;
|
|
615
|
+
const env = buildToolEnv(metadata.tools, [], options.platform);
|
|
397
616
|
await runCommand(metadata.tools.npmPath, [
|
|
398
617
|
"exec",
|
|
399
618
|
"--yes",
|
|
400
619
|
`--package=${targetSpecifier}`,
|
|
401
|
-
|
|
620
|
+
import_companion4.DEXLY_COMPANION_EXECUTABLE_NAME,
|
|
402
621
|
"install",
|
|
403
622
|
"--channel",
|
|
404
623
|
options.distTag
|
|
@@ -414,15 +633,14 @@ async function upgradeInstalledCompanion(options) {
|
|
|
414
633
|
};
|
|
415
634
|
}
|
|
416
635
|
async function installCodexWithCompanion(options) {
|
|
417
|
-
const installRoot = options?.installRoot ?? defaultInstallRoot();
|
|
418
|
-
const manifestDir = options?.manifestDir ?? defaultChromeHostManifestDir();
|
|
636
|
+
const installRoot = options?.installRoot ?? defaultInstallRoot({ platform: options?.platform });
|
|
419
637
|
const existingMetadata = await loadInstallMetadata(installRoot);
|
|
420
638
|
const toolPaths = existingMetadata?.tools ?? detectToolPaths();
|
|
421
|
-
const env = buildToolEnv(toolPaths);
|
|
639
|
+
const env = buildToolEnv(toolPaths, [], options?.platform);
|
|
422
640
|
await runCommand(toolPaths.npmPath, ["install", "-g", "@openai/codex"], { env });
|
|
423
|
-
const globalBinDir = resolveNpmGlobalBinDir(toolPaths.npmPath, env);
|
|
424
|
-
const nextEnv = buildToolEnv(toolPaths, globalBinDir ? [globalBinDir] : []);
|
|
425
|
-
const codexPath = resolveExecutablePath("codex", nextEnv);
|
|
641
|
+
const globalBinDir = resolveNpmGlobalBinDir(toolPaths.npmPath, env, options?.platform);
|
|
642
|
+
const nextEnv = buildToolEnv(toolPaths, globalBinDir ? [globalBinDir] : [], options?.platform);
|
|
643
|
+
const codexPath = resolveExecutablePath("codex", nextEnv, options?.platform);
|
|
426
644
|
const codexVersion = resolveCodexVersion(codexPath ?? void 0, nextEnv);
|
|
427
645
|
if (!codexPath || !codexVersion) {
|
|
428
646
|
throw new Error("Codex install completed, but Dexly Companion could not resolve the installed codex binary.");
|
|
@@ -431,8 +649,12 @@ async function installCodexWithCompanion(options) {
|
|
|
431
649
|
...toolPaths,
|
|
432
650
|
codexPath
|
|
433
651
|
};
|
|
434
|
-
await rewriteCurrentLauncher(installRoot, nextToolPaths);
|
|
435
|
-
await
|
|
652
|
+
await rewriteCurrentLauncher(installRoot, nextToolPaths, { platform: options?.platform });
|
|
653
|
+
await ensureChromeHostRegistration(installRoot, {
|
|
654
|
+
platform: options?.platform,
|
|
655
|
+
manifestDir: options?.manifestDir,
|
|
656
|
+
windowsRegistryKey: options?.windowsRegistryKey
|
|
657
|
+
});
|
|
436
658
|
if (existingMetadata) {
|
|
437
659
|
await saveInstallMetadata(installRoot, {
|
|
438
660
|
...existingMetadata,
|
|
@@ -443,7 +665,7 @@ async function installCodexWithCompanion(options) {
|
|
|
443
665
|
return {
|
|
444
666
|
codexPath,
|
|
445
667
|
codexVersion,
|
|
446
|
-
installCommand:
|
|
668
|
+
installCommand: import_companion4.DEXLY_CODEX_INSTALL_COMMAND
|
|
447
669
|
};
|
|
448
670
|
}
|
|
449
671
|
|
|
@@ -461,9 +683,9 @@ var DexlyNativeHost = class {
|
|
|
461
683
|
stderrLines = [];
|
|
462
684
|
constructor(options) {
|
|
463
685
|
this.send = options.send;
|
|
464
|
-
this.spawnProcess = options.spawnProcess ??
|
|
465
|
-
this.spawnProcessSync = options.spawnProcessSync ??
|
|
466
|
-
this.codexCommand = options.codexCommand ??
|
|
686
|
+
this.spawnProcess = options.spawnProcess ?? ((command, args, spawnOptions) => spawnManaged(command, [...args], spawnOptions));
|
|
687
|
+
this.spawnProcessSync = options.spawnProcessSync ?? ((command, args, spawnOptions) => spawnManagedSync(command, [...args], spawnOptions));
|
|
688
|
+
this.codexCommand = options.codexCommand ?? import_node_process3.default.env.DEXLY_COMPANION_CODEX_PATH ?? "codex";
|
|
467
689
|
this.requestProcessExit = options.requestProcessExit ?? null;
|
|
468
690
|
}
|
|
469
691
|
async handleMessage(message) {
|
|
@@ -723,7 +945,7 @@ var DexlyNativeHost = class {
|
|
|
723
945
|
null,
|
|
724
946
|
null,
|
|
725
947
|
"codex_not_connected",
|
|
726
|
-
`${
|
|
948
|
+
`${import_companion5.DEXLY_COMPANION_DISPLAY_NAME} is not connected to Codex app-server.`
|
|
727
949
|
));
|
|
728
950
|
return;
|
|
729
951
|
}
|
|
@@ -813,19 +1035,19 @@ function writeNativeMessage(output, message) {
|
|
|
813
1035
|
// src/host-runtime.ts
|
|
814
1036
|
async function runNativeHost() {
|
|
815
1037
|
const host = new DexlyNativeHost({
|
|
816
|
-
send: (message) => writeNativeMessage(
|
|
1038
|
+
send: (message) => writeNativeMessage(import_node_process4.default.stdout, message),
|
|
817
1039
|
requestProcessExit: () => {
|
|
818
|
-
setTimeout(() =>
|
|
1040
|
+
setTimeout(() => import_node_process4.default.exit(0), 25);
|
|
819
1041
|
}
|
|
820
1042
|
});
|
|
821
|
-
|
|
1043
|
+
import_node_process4.default.stdout.on("error", (error) => {
|
|
822
1044
|
if ("code" in error && error.code === "EPIPE") {
|
|
823
|
-
void host.close().finally(() =>
|
|
1045
|
+
void host.close().finally(() => import_node_process4.default.exit(0));
|
|
824
1046
|
}
|
|
825
1047
|
});
|
|
826
|
-
const detachReader = createNativeMessageReader(
|
|
1048
|
+
const detachReader = createNativeMessageReader(import_node_process4.default.stdin, (message) => {
|
|
827
1049
|
void host.handleMessage(message).catch((error) => {
|
|
828
|
-
writeNativeMessage(
|
|
1050
|
+
writeNativeMessage(import_node_process4.default.stdout, {
|
|
829
1051
|
kind: "host/error",
|
|
830
1052
|
action: null,
|
|
831
1053
|
requestId: null,
|
|
@@ -838,21 +1060,21 @@ async function runNativeHost() {
|
|
|
838
1060
|
detachReader();
|
|
839
1061
|
await host.close();
|
|
840
1062
|
};
|
|
841
|
-
|
|
842
|
-
void shutdown().finally(() =>
|
|
1063
|
+
import_node_process4.default.stdin.on("end", () => {
|
|
1064
|
+
void shutdown().finally(() => import_node_process4.default.exit(0));
|
|
843
1065
|
});
|
|
844
|
-
|
|
845
|
-
void shutdown().finally(() =>
|
|
1066
|
+
import_node_process4.default.on("SIGINT", () => {
|
|
1067
|
+
void shutdown().finally(() => import_node_process4.default.exit(0));
|
|
846
1068
|
});
|
|
847
|
-
|
|
848
|
-
void shutdown().finally(() =>
|
|
1069
|
+
import_node_process4.default.on("SIGTERM", () => {
|
|
1070
|
+
void shutdown().finally(() => import_node_process4.default.exit(0));
|
|
849
1071
|
});
|
|
850
1072
|
}
|
|
851
1073
|
|
|
852
1074
|
// src/host.ts
|
|
853
1075
|
void runNativeHost().catch((error) => {
|
|
854
1076
|
const message = error instanceof Error ? error.message : "Dexly Companion host failed.";
|
|
855
|
-
|
|
1077
|
+
import_node_process5.default.stderr.write(`${message}
|
|
856
1078
|
`);
|
|
857
|
-
|
|
1079
|
+
import_node_process5.default.exit(1);
|
|
858
1080
|
});
|