impel-cli 0.11.1 → 0.11.2
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 +5 -2
- package/package.json +1 -1
- package/src/apps.js +139 -5
package/README.md
CHANGED
|
@@ -703,8 +703,11 @@ a stable, unique bundle identifier and gateway configuration:
|
|
|
703
703
|
to the authenticated aggregate Claude subscription pool exposed by the Impel
|
|
704
704
|
gateway.
|
|
705
705
|
- Impel ChatGPT wraps an APFS-cloned official app while preserving the nested
|
|
706
|
-
OpenAI-signed bundle and executable.
|
|
707
|
-
|
|
706
|
+
OpenAI-signed bundle and executable. A wrapper-owned startup preload pins
|
|
707
|
+
Electron's application name before the native menu is created, so macOS
|
|
708
|
+
shows `Impel ChatGPT (<org>)` without changing OpenAI's signed code. Its outer
|
|
709
|
+
resource root contains the narrowly patched renderer ASAR used at runtime.
|
|
710
|
+
The wrapper sets `CODEX_HOME`,
|
|
708
711
|
passes a separate Chromium `--user-data-dir`, and writes its provider config
|
|
709
712
|
and model catalog below `~/.config/impel/apps/tenants/<org>/chatgpt`. It also supplies a
|
|
710
713
|
process-scoped, Codex-compatible wrapper around the Impel PAT so native
|
package/package.json
CHANGED
package/src/apps.js
CHANGED
|
@@ -193,6 +193,7 @@ export function bundleIsCurrent(status) {
|
|
|
193
193
|
compatibility.vendorSignaturesPreserved === true
|
|
194
194
|
&& compatibility.resourceRoot === CHATGPT_RESOURCE_ROOT
|
|
195
195
|
&& compatibility.patches?.fastModeForGatewayAuth > 0
|
|
196
|
+
&& compatibility.patches?.tenantDisplayNamePreload === 1
|
|
196
197
|
)),
|
|
197
198
|
);
|
|
198
199
|
}
|
|
@@ -1060,6 +1061,11 @@ function writeVendoredChatGPTBundle(paths, vendorPath, gatewayUrl) {
|
|
|
1060
1061
|
vendoredChatGPTLauncher(paths, vendorBundleName, executableName, gatewayUrl),
|
|
1061
1062
|
0o755,
|
|
1062
1063
|
);
|
|
1064
|
+
writeAtomic(
|
|
1065
|
+
path.join(staging, "Contents", "Resources", "impel-chatgpt-preload.cjs"),
|
|
1066
|
+
vendoredChatGPTDisplayNamePreload(),
|
|
1067
|
+
0o644,
|
|
1068
|
+
);
|
|
1063
1069
|
writeAtomic(path.join(staging, "Contents", "Resources", "impel-compatibility.json"), JSON.stringify({
|
|
1064
1070
|
schemaVersion: 2,
|
|
1065
1071
|
cliVersion: CLI_VERSION,
|
|
@@ -1070,7 +1076,11 @@ function writeVendoredChatGPTBundle(paths, vendorPath, gatewayUrl) {
|
|
|
1070
1076
|
profileRoot: paths.chatgpt.root,
|
|
1071
1077
|
codexHome: paths.chatgpt.codexHome,
|
|
1072
1078
|
browserData: paths.chatgpt.browserData,
|
|
1073
|
-
patches: {
|
|
1079
|
+
patches: {
|
|
1080
|
+
fastModeForGatewayAuth: fastModePatchCount,
|
|
1081
|
+
desktopAPIForGatewayAuth: 0,
|
|
1082
|
+
tenantDisplayNamePreload: 1,
|
|
1083
|
+
},
|
|
1074
1084
|
vendorSignaturesPreserved: true,
|
|
1075
1085
|
resourceRoot: CHATGPT_RESOURCE_ROOT,
|
|
1076
1086
|
asarHeaderSha256: asarHash,
|
|
@@ -1384,14 +1394,138 @@ unset TOKEN
|
|
|
1384
1394
|
secure_codex_home
|
|
1385
1395
|
BROWSER_DATA=${shellQuote(paths.chatgpt.browserData)}
|
|
1386
1396
|
mkdir -p "$BROWSER_DATA"
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
#
|
|
1397
|
+
export IMPEL_APP_DISPLAY_NAME=${shellQuote(paths.chatgpt.displayName)}
|
|
1398
|
+
PRELOAD="$HERE/../Resources/impel-chatgpt-preload.cjs"
|
|
1399
|
+
export NODE_OPTIONS="--require=\\\"$PRELOAD\\\""
|
|
1400
|
+
# Electron resolves resources from the Impel wrapper when the nested app is
|
|
1401
|
+
# executed directly. The wrapper exposes the vendor resource tree there while
|
|
1402
|
+
# preserving the nested OpenAI-signed executable and bundle. The startup
|
|
1403
|
+
# preload pins Electron's application name before its native menu is created.
|
|
1391
1404
|
exec "$VENDOR_APP/Contents/MacOS/${executableName}" --user-data-dir="$BROWSER_DATA" "$@"
|
|
1392
1405
|
`;
|
|
1393
1406
|
}
|
|
1394
1407
|
|
|
1408
|
+
function vendoredChatGPTDisplayNamePreload() {
|
|
1409
|
+
return `"use strict";
|
|
1410
|
+
|
|
1411
|
+
const displayName = process.env.IMPEL_APP_DISPLAY_NAME;
|
|
1412
|
+
if (process.type === "browser" && displayName) {
|
|
1413
|
+
const Module = require("node:module");
|
|
1414
|
+
const path = require("node:path");
|
|
1415
|
+
const load = Module._load;
|
|
1416
|
+
let objc;
|
|
1417
|
+
let appKit;
|
|
1418
|
+
let launchServicesNamed = false;
|
|
1419
|
+
let activationPolicyRefreshed = false;
|
|
1420
|
+
|
|
1421
|
+
const loadNativeBridge = () => {
|
|
1422
|
+
objc ||= require(path.join(
|
|
1423
|
+
process.resourcesPath,
|
|
1424
|
+
"app.asar.unpacked/node_modules/objc-js/dist/index.js",
|
|
1425
|
+
));
|
|
1426
|
+
appKit ||= new objc.NobjcLibrary("/System/Library/Frameworks/AppKit.framework/AppKit");
|
|
1427
|
+
return { objc, appKit };
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
const setLaunchServicesApplicationName = () => {
|
|
1431
|
+
if (launchServicesNamed) return;
|
|
1432
|
+
try {
|
|
1433
|
+
const native = loadNativeBridge();
|
|
1434
|
+
new native.objc.NobjcLibrary(
|
|
1435
|
+
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices",
|
|
1436
|
+
);
|
|
1437
|
+
const title = native.appKit.NSString.stringWithUTF8String$(displayName);
|
|
1438
|
+
const info = native.appKit.NSMutableDictionary.dictionaryWithDictionary$(
|
|
1439
|
+
native.appKit.NSBundle.mainBundle().infoDictionary(),
|
|
1440
|
+
);
|
|
1441
|
+
for (const key of ["CFBundleName", "CFBundleDisplayName"]) {
|
|
1442
|
+
info.setObject$forKey$(title, native.appKit.NSString.stringWithUTF8String$(key));
|
|
1443
|
+
}
|
|
1444
|
+
native.objc.callFunction(
|
|
1445
|
+
"_LSSetApplicationLaunchServicesServerConnectionStatus",
|
|
1446
|
+
{ returns: "v", args: ["Q", "@"] },
|
|
1447
|
+
0,
|
|
1448
|
+
null,
|
|
1449
|
+
);
|
|
1450
|
+
const checked = native.objc.callFunction(
|
|
1451
|
+
"_LSApplicationCheckIn",
|
|
1452
|
+
{ returns: "@", args: ["i", "@"] },
|
|
1453
|
+
-2,
|
|
1454
|
+
info,
|
|
1455
|
+
);
|
|
1456
|
+
const asn = native.objc.callFunction("_LSGetCurrentApplicationASN", { returns: "@" });
|
|
1457
|
+
if (!checked || !asn) return;
|
|
1458
|
+
const status = native.objc.callFunction(
|
|
1459
|
+
"_LSSetApplicationInformationItem",
|
|
1460
|
+
{ returns: "i", args: ["i", "@", "@", "@", "@"] },
|
|
1461
|
+
-2,
|
|
1462
|
+
asn,
|
|
1463
|
+
native.appKit.NSString.stringWithUTF8String$("LSDisplayName"),
|
|
1464
|
+
title,
|
|
1465
|
+
null,
|
|
1466
|
+
);
|
|
1467
|
+
launchServicesNamed = status === 0;
|
|
1468
|
+
} catch {
|
|
1469
|
+
// Keep the signed vendor app usable if LaunchServices changes this
|
|
1470
|
+
// private-but-established process-title API in a future macOS release.
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
|
|
1474
|
+
const setNativeApplicationMenuTitle = () => {
|
|
1475
|
+
try {
|
|
1476
|
+
const native = loadNativeBridge();
|
|
1477
|
+
const title = native.appKit.NSString.stringWithUTF8String$(displayName);
|
|
1478
|
+
native.appKit.NSProcessInfo.processInfo().setProcessName$(title);
|
|
1479
|
+
const application = native.appKit.NSApplication.sharedApplication();
|
|
1480
|
+
application.setAccessibilityTitle$(title);
|
|
1481
|
+
const menu = application.mainMenu();
|
|
1482
|
+
if (menu && menu.numberOfItems() > 0) {
|
|
1483
|
+
const item = menu.itemAtIndex$(0);
|
|
1484
|
+
item.setTitle$(title);
|
|
1485
|
+
item.setAccessibilityTitle$(title);
|
|
1486
|
+
item.setAccessibilityLabel$(title);
|
|
1487
|
+
}
|
|
1488
|
+
} catch {
|
|
1489
|
+
// The OpenAI-signed native bridge is version-specific. Leave the app
|
|
1490
|
+
// usable if a future vendor build removes it; compatibility metadata
|
|
1491
|
+
// will force the next CLI version to rebuild the wrapper.
|
|
1492
|
+
}
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
Module._load = function (request) {
|
|
1496
|
+
const loaded = load.apply(this, arguments);
|
|
1497
|
+
if (request === "electron" && loaded?.app) {
|
|
1498
|
+
Module._load = load;
|
|
1499
|
+
const setName = loaded.app.setName.bind(loaded.app);
|
|
1500
|
+
setName(displayName);
|
|
1501
|
+
loaded.app.setName = () => setName(displayName);
|
|
1502
|
+
setLaunchServicesApplicationName();
|
|
1503
|
+
setNativeApplicationMenuTitle();
|
|
1504
|
+
const setApplicationMenu = loaded.Menu.setApplicationMenu.bind(loaded.Menu);
|
|
1505
|
+
loaded.Menu.setApplicationMenu = (menu) => {
|
|
1506
|
+
const result = setApplicationMenu(menu);
|
|
1507
|
+
setNativeApplicationMenuTitle();
|
|
1508
|
+
if (!activationPolicyRefreshed) {
|
|
1509
|
+
activationPolicyRefreshed = true;
|
|
1510
|
+
loaded.app.setActivationPolicy("accessory");
|
|
1511
|
+
setTimeout(() => {
|
|
1512
|
+
loaded.app.setActivationPolicy("regular");
|
|
1513
|
+
launchServicesNamed = false;
|
|
1514
|
+
setLaunchServicesApplicationName();
|
|
1515
|
+
setApplicationMenu(menu);
|
|
1516
|
+
setNativeApplicationMenuTitle();
|
|
1517
|
+
}, 0);
|
|
1518
|
+
}
|
|
1519
|
+
setTimeout(setNativeApplicationMenuTitle, 0);
|
|
1520
|
+
return result;
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
return loaded;
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
`;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1395
1529
|
function signVendoredApp(bundle, vendorExecutable, label) {
|
|
1396
1530
|
if (process.platform !== "darwin" || !isMachO(vendorExecutable)) return;
|
|
1397
1531
|
spawnSync("/usr/bin/xattr", ["-dr", "com.apple.quarantine", bundle], { stdio: "ignore" });
|