@lindengjian/codex-beacon 1.0.5
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 +30 -0
- package/app/CodexBeacon.app/Contents/Info.plist +36 -0
- package/app/CodexBeacon.app/Contents/MacOS/CodexBeacon +0 -0
- package/app/CodexBeacon.app/Contents/Resources/CodexBeacon.icns +0 -0
- package/app/CodexBeacon.app/Contents/_CodeSignature/CodeResources +128 -0
- package/bin/codex-beacon.mjs +75 -0
- package/lib/installer.mjs +120 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Codex Beacon npm installer
|
|
2
|
+
|
|
3
|
+
This package installs the native Codex Beacon app into `~/Applications` on an
|
|
4
|
+
Apple Silicon Mac running macOS 15 or later.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npx @lindengjian/codex-beacon install
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Or install the small command-line launcher globally:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install -g @lindengjian/codex-beacon
|
|
14
|
+
codex-beacon install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
codex-beacon open
|
|
21
|
+
codex-beacon doctor
|
|
22
|
+
codex-beacon uninstall
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`uninstall` removes only `~/Applications/CodexBeacon.app`. Before removal it
|
|
26
|
+
asks Beacon to unregister its login item and roll back the shared App Server
|
|
27
|
+
compatibility adapter that Beacon itself created.
|
|
28
|
+
|
|
29
|
+
The app remains ad-hoc signed and is not notarized. npm does not bypass macOS
|
|
30
|
+
security checks; follow the macOS prompt only when you trust the release.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>en</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>CodexBeacon</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>com.lindengjian.CodexBeacon</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleIconFile</key>
|
|
14
|
+
<string>CodexBeacon.icns</string>
|
|
15
|
+
<key>CFBundleName</key>
|
|
16
|
+
<string>Codex Beacon</string>
|
|
17
|
+
<key>CFBundlePackageType</key>
|
|
18
|
+
<string>APPL</string>
|
|
19
|
+
<key>CFBundleShortVersionString</key>
|
|
20
|
+
<string>1.0.5</string>
|
|
21
|
+
<key>CFBundleVersion</key>
|
|
22
|
+
<string>1.0.5</string>
|
|
23
|
+
<key>LSArchitecturePriority</key>
|
|
24
|
+
<array>
|
|
25
|
+
<string>arm64</string>
|
|
26
|
+
</array>
|
|
27
|
+
<key>LSMinimumSystemVersion</key>
|
|
28
|
+
<string>15.0</string>
|
|
29
|
+
<key>LSUIElement</key>
|
|
30
|
+
<true/>
|
|
31
|
+
<key>NSHighResolutionCapable</key>
|
|
32
|
+
<true/>
|
|
33
|
+
<key>NSPrincipalClass</key>
|
|
34
|
+
<string>NSApplication</string>
|
|
35
|
+
</dict>
|
|
36
|
+
</plist>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>files</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Resources/CodexBeacon.icns</key>
|
|
8
|
+
<data>
|
|
9
|
+
ARb+dgpuDExYp5sFia3uxkcaQd0=
|
|
10
|
+
</data>
|
|
11
|
+
</dict>
|
|
12
|
+
<key>files2</key>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>Resources/CodexBeacon.icns</key>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>hash2</key>
|
|
17
|
+
<data>
|
|
18
|
+
/rRUPUqqL36bgR9YaCgNtPZoEW5epmPMQHPsP/iHbUk=
|
|
19
|
+
</data>
|
|
20
|
+
</dict>
|
|
21
|
+
</dict>
|
|
22
|
+
<key>rules</key>
|
|
23
|
+
<dict>
|
|
24
|
+
<key>^Resources/</key>
|
|
25
|
+
<true/>
|
|
26
|
+
<key>^Resources/.*\.lproj/</key>
|
|
27
|
+
<dict>
|
|
28
|
+
<key>optional</key>
|
|
29
|
+
<true/>
|
|
30
|
+
<key>weight</key>
|
|
31
|
+
<real>1000</real>
|
|
32
|
+
</dict>
|
|
33
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
34
|
+
<dict>
|
|
35
|
+
<key>omit</key>
|
|
36
|
+
<true/>
|
|
37
|
+
<key>weight</key>
|
|
38
|
+
<real>1100</real>
|
|
39
|
+
</dict>
|
|
40
|
+
<key>^Resources/Base\.lproj/</key>
|
|
41
|
+
<dict>
|
|
42
|
+
<key>weight</key>
|
|
43
|
+
<real>1010</real>
|
|
44
|
+
</dict>
|
|
45
|
+
<key>^version.plist$</key>
|
|
46
|
+
<true/>
|
|
47
|
+
</dict>
|
|
48
|
+
<key>rules2</key>
|
|
49
|
+
<dict>
|
|
50
|
+
<key>.*\.dSYM($|/)</key>
|
|
51
|
+
<dict>
|
|
52
|
+
<key>weight</key>
|
|
53
|
+
<real>11</real>
|
|
54
|
+
</dict>
|
|
55
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
56
|
+
<dict>
|
|
57
|
+
<key>omit</key>
|
|
58
|
+
<true/>
|
|
59
|
+
<key>weight</key>
|
|
60
|
+
<real>2000</real>
|
|
61
|
+
</dict>
|
|
62
|
+
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
|
63
|
+
<dict>
|
|
64
|
+
<key>nested</key>
|
|
65
|
+
<true/>
|
|
66
|
+
<key>weight</key>
|
|
67
|
+
<real>10</real>
|
|
68
|
+
</dict>
|
|
69
|
+
<key>^.*</key>
|
|
70
|
+
<true/>
|
|
71
|
+
<key>^Info\.plist$</key>
|
|
72
|
+
<dict>
|
|
73
|
+
<key>omit</key>
|
|
74
|
+
<true/>
|
|
75
|
+
<key>weight</key>
|
|
76
|
+
<real>20</real>
|
|
77
|
+
</dict>
|
|
78
|
+
<key>^PkgInfo$</key>
|
|
79
|
+
<dict>
|
|
80
|
+
<key>omit</key>
|
|
81
|
+
<true/>
|
|
82
|
+
<key>weight</key>
|
|
83
|
+
<real>20</real>
|
|
84
|
+
</dict>
|
|
85
|
+
<key>^Resources/</key>
|
|
86
|
+
<dict>
|
|
87
|
+
<key>weight</key>
|
|
88
|
+
<real>20</real>
|
|
89
|
+
</dict>
|
|
90
|
+
<key>^Resources/.*\.lproj/</key>
|
|
91
|
+
<dict>
|
|
92
|
+
<key>optional</key>
|
|
93
|
+
<true/>
|
|
94
|
+
<key>weight</key>
|
|
95
|
+
<real>1000</real>
|
|
96
|
+
</dict>
|
|
97
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
98
|
+
<dict>
|
|
99
|
+
<key>omit</key>
|
|
100
|
+
<true/>
|
|
101
|
+
<key>weight</key>
|
|
102
|
+
<real>1100</real>
|
|
103
|
+
</dict>
|
|
104
|
+
<key>^Resources/Base\.lproj/</key>
|
|
105
|
+
<dict>
|
|
106
|
+
<key>weight</key>
|
|
107
|
+
<real>1010</real>
|
|
108
|
+
</dict>
|
|
109
|
+
<key>^[^/]+$</key>
|
|
110
|
+
<dict>
|
|
111
|
+
<key>nested</key>
|
|
112
|
+
<true/>
|
|
113
|
+
<key>weight</key>
|
|
114
|
+
<real>10</real>
|
|
115
|
+
</dict>
|
|
116
|
+
<key>^embedded\.provisionprofile$</key>
|
|
117
|
+
<dict>
|
|
118
|
+
<key>weight</key>
|
|
119
|
+
<real>20</real>
|
|
120
|
+
</dict>
|
|
121
|
+
<key>^version\.plist$</key>
|
|
122
|
+
<dict>
|
|
123
|
+
<key>weight</key>
|
|
124
|
+
<real>20</real>
|
|
125
|
+
</dict>
|
|
126
|
+
</dict>
|
|
127
|
+
</dict>
|
|
128
|
+
</plist>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
defaultInstalledApp,
|
|
8
|
+
doctor,
|
|
9
|
+
installApp,
|
|
10
|
+
openApp,
|
|
11
|
+
uninstallApp,
|
|
12
|
+
} from "../lib/installer.mjs";
|
|
13
|
+
|
|
14
|
+
const packageDirectory = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
15
|
+
const bundledApp = join(packageDirectory, "app", "CodexBeacon.app");
|
|
16
|
+
|
|
17
|
+
function printUsage() {
|
|
18
|
+
console.log(`Codex Beacon npm installer
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
codex-beacon install [--no-launch] Install to ~/Applications and open it
|
|
22
|
+
codex-beacon open Open the installed app
|
|
23
|
+
codex-beacon doctor Check platform, installation, and signature
|
|
24
|
+
codex-beacon uninstall Clean up Beacon-owned services and remove the app
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function run() {
|
|
29
|
+
const [command = "help", ...arguments_] = process.argv.slice(2);
|
|
30
|
+
|
|
31
|
+
switch (command) {
|
|
32
|
+
case "install": {
|
|
33
|
+
const installedApp = installApp({ bundledApp });
|
|
34
|
+
console.log(`Installed Codex Beacon at ${installedApp}`);
|
|
35
|
+
if (!arguments_.includes("--no-launch")) {
|
|
36
|
+
openApp(installedApp);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
case "open": {
|
|
41
|
+
const installedApp = defaultInstalledApp();
|
|
42
|
+
doctor({ installedApp });
|
|
43
|
+
openApp(installedApp);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
case "doctor": {
|
|
47
|
+
const installedApp = doctor();
|
|
48
|
+
console.log(`Codex Beacon is installed and its signature is valid: ${installedApp}`);
|
|
49
|
+
console.log("Open Beacon and use its integration diagnostic to verify Codex Desktop compatibility.");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
case "uninstall": {
|
|
53
|
+
if (uninstallApp({})) {
|
|
54
|
+
console.log("Removed Codex Beacon from ~/Applications.");
|
|
55
|
+
} else {
|
|
56
|
+
console.log("Codex Beacon is not installed in ~/Applications.");
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
case "help":
|
|
61
|
+
case "--help":
|
|
62
|
+
case "-h":
|
|
63
|
+
printUsage();
|
|
64
|
+
return;
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unknown command: ${command}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
run();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(`codex-beacon: ${error.message}`);
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cpSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
renameSync,
|
|
6
|
+
rmSync,
|
|
7
|
+
statSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { basename, dirname, join } from "node:path";
|
|
11
|
+
import { execFileSync } from "node:child_process";
|
|
12
|
+
|
|
13
|
+
export const applicationName = "CodexBeacon.app";
|
|
14
|
+
export const executableRelativePath = join("Contents", "MacOS", "CodexBeacon");
|
|
15
|
+
|
|
16
|
+
export function validatePlatform({ platform = process.platform, arch = process.arch } = {}) {
|
|
17
|
+
if (platform !== "darwin" || arch !== "arm64") {
|
|
18
|
+
throw new Error("Codex Beacon only supports macOS on Apple Silicon (darwin/arm64).");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function defaultApplicationsDirectory(homeDirectory = homedir()) {
|
|
23
|
+
return join(homeDirectory, "Applications");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function defaultInstalledApp(applicationsDirectory = defaultApplicationsDirectory()) {
|
|
27
|
+
return join(applicationsDirectory, applicationName);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function verifyApp(appPath) {
|
|
31
|
+
execFileSync("/usr/bin/codesign", ["--verify", "--strict", "--verbose=2", appPath], {
|
|
32
|
+
stdio: "inherit",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function openApp(appPath) {
|
|
37
|
+
execFileSync("/usr/bin/open", [appPath], { stdio: "inherit" });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function assertAppBundle(appPath, description) {
|
|
41
|
+
if (!existsSync(appPath) || !statSync(appPath).isDirectory()) {
|
|
42
|
+
throw new Error(`${description} is missing: ${appPath}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function replaceDirectory(source, destination) {
|
|
47
|
+
const parentDirectory = dirname(destination);
|
|
48
|
+
const stagingDirectory = join(parentDirectory, `.${basename(destination)}.install-${process.pid}`);
|
|
49
|
+
const backupDirectory = join(parentDirectory, `.${basename(destination)}.backup-${process.pid}`);
|
|
50
|
+
|
|
51
|
+
rmSync(stagingDirectory, { recursive: true, force: true });
|
|
52
|
+
rmSync(backupDirectory, { recursive: true, force: true });
|
|
53
|
+
cpSync(source, stagingDirectory, { recursive: true, preserveTimestamps: true });
|
|
54
|
+
|
|
55
|
+
const hadExistingInstallation = existsSync(destination);
|
|
56
|
+
if (hadExistingInstallation) {
|
|
57
|
+
renameSync(destination, backupDirectory);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
renameSync(stagingDirectory, destination);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (hadExistingInstallation && !existsSync(destination)) {
|
|
64
|
+
renameSync(backupDirectory, destination);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
} finally {
|
|
68
|
+
rmSync(stagingDirectory, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
rmSync(backupDirectory, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function installApp({
|
|
75
|
+
bundledApp,
|
|
76
|
+
applicationsDirectory = defaultApplicationsDirectory(),
|
|
77
|
+
platform = process.platform,
|
|
78
|
+
arch = process.arch,
|
|
79
|
+
verifyApp: verify = verifyApp,
|
|
80
|
+
}) {
|
|
81
|
+
validatePlatform({ platform, arch });
|
|
82
|
+
assertAppBundle(bundledApp, "The bundled Codex Beacon app");
|
|
83
|
+
verify(bundledApp);
|
|
84
|
+
mkdirSync(applicationsDirectory, { recursive: true });
|
|
85
|
+
|
|
86
|
+
const installedApp = defaultInstalledApp(applicationsDirectory);
|
|
87
|
+
replaceDirectory(bundledApp, installedApp);
|
|
88
|
+
return installedApp;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function uninstallApp({
|
|
92
|
+
installedApp = defaultInstalledApp(),
|
|
93
|
+
prepareForUninstall = (executable, commandArguments) =>
|
|
94
|
+
execFileSync(executable, commandArguments, { stdio: "inherit" }),
|
|
95
|
+
}) {
|
|
96
|
+
if (!existsSync(installedApp)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const executable = join(installedApp, executableRelativePath);
|
|
101
|
+
if (!existsSync(executable)) {
|
|
102
|
+
throw new Error(`The installed Codex Beacon app is incomplete: ${installedApp}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
prepareForUninstall(executable, ["--prepare-for-uninstall"]);
|
|
106
|
+
rmSync(installedApp, { recursive: true, force: false });
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function doctor({
|
|
111
|
+
installedApp = defaultInstalledApp(),
|
|
112
|
+
platform = process.platform,
|
|
113
|
+
arch = process.arch,
|
|
114
|
+
verifyApp: verify = verifyApp,
|
|
115
|
+
}) {
|
|
116
|
+
validatePlatform({ platform, arch });
|
|
117
|
+
assertAppBundle(installedApp, "Codex Beacon is not installed; run `codex-beacon install`");
|
|
118
|
+
verify(installedApp);
|
|
119
|
+
return installedApp;
|
|
120
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lindengjian/codex-beacon",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "Install Codex Beacon, a native macOS status companion for Codex Desktop.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"codex-beacon": "bin/codex-beacon.mjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"app",
|
|
13
|
+
"bin",
|
|
14
|
+
"lib",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"os": [
|
|
18
|
+
"darwin"
|
|
19
|
+
],
|
|
20
|
+
"cpu": [
|
|
21
|
+
"arm64"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "node --test test/*.test.mjs",
|
|
28
|
+
"prepack": "node scripts/prepare-package.mjs",
|
|
29
|
+
"pack:check": "npm pack --dry-run"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/lindengjian/CodexBeacon.git",
|
|
34
|
+
"directory": "npm"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/lindengjian/CodexBeacon#readme",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/lindengjian/CodexBeacon/issues"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|