@ailuntz/minilink 0.9.5 → 0.9.7

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 CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  需 Node.js ≥22.16,并已安装 Desktop。
17
17
 
18
- macOS / Windows / Linux:
18
+ macOS:
19
19
 
20
20
  ```sh
21
21
  npm install -g @ailuntz/minilink --allow-scripts=@ailuntz/minilink
@@ -26,6 +26,8 @@ minilink on
26
26
 
27
27
  npm 11 默认可能跳过全局包的安装脚本;上面的单次许可让 MiniLink 完成 Desktop 接入,不会永久允许其他包的脚本。
28
28
 
29
+ Windows / Linux 的模型路由和 Desktop 连接已通过手动启动桥验证;当前 npm 包的自动安装脚本仅实现 macOS,不能使用上述命令完成 Windows / Linux 的桌面接入。
30
+
29
31
  ## 命令
30
32
 
31
33
  | 命令 | 用途 |
@@ -37,7 +39,7 @@ npm 11 默认可能跳过全局包的安装脚本;上面的单次许可让 Min
37
39
 
38
40
  通过 `minilink link` 保存选择后,完全退出并重开 Desktop。
39
41
 
40
- macOS 上 `off` 会让后续启动直接使用 Desktop 自带的 Codex;`on` 会重新接入 MiniLink。已打开的 Desktop 需要完全退出并重开,才会切换启动方式。MiniLink 会在每次启动时重新查找 Desktop 自带的 Codex,兼容旧版 `Resources/codex` 和新版 `Resources/codex-cli/bin/codex` 布局。
42
+ macOS 上 `off` 会让后续启动直接使用 Desktop 自带的 Codex;`on` 会重新接入 MiniLink。已打开的 Desktop 需要完全退出并重开,才会切换启动方式。MiniLink 使用 ChatGPT 当前内置的 `Resources/codex-cli/CodexCLI.app/Contents/MacOS/codex`。
41
43
 
42
44
  ## 配置
43
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ailuntz/minilink",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "description": "Use your Codex profiles in the Desktop model menu.",
5
5
  "type": "module",
6
6
  "license": "MIT AND Apache-2.0",
package/src/config.mjs CHANGED
@@ -63,22 +63,12 @@ export function discoverProfiles(home = codexHome()) {
63
63
  return routes;
64
64
  }
65
65
 
66
- export const bundledCodexPaths = [
67
- 'codex-cli/bin/codex',
68
- 'codex-cli/CodexCLI.app/Contents/MacOS/codex',
69
- 'codex'
70
- ];
71
-
72
- export function bundledCodex(app) {
73
- for (const relative of bundledCodexPaths) {
74
- const candidate = join(app, 'Contents/Resources', relative);
75
- try { accessSync(candidate, constants.X_OK); return candidate; } catch {}
76
- }
77
- return null;
78
- }
66
+ export const bundledCodexRelativePath = 'Contents/Resources/codex-cli/CodexCLI.app/Contents/MacOS/codex';
67
+ export const bundledCodex = app => join(app, bundledCodexRelativePath);
79
68
 
80
69
  export function findApp() {
81
- return [process.env.CODEX_DESKTOP_APP, '/Applications/ChatGPT.app', '/Applications/Codex.app', join(homedir(), 'Applications/ChatGPT.app'), join(homedir(), 'Applications/Codex.app')].filter(Boolean).find(p => bundledCodex(p));
70
+ const app = process.env.CODEX_DESKTOP_APP || '/Applications/ChatGPT.app';
71
+ try { accessSync(bundledCodex(app), constants.X_OK); return app; } catch { return null; }
82
72
  }
83
73
 
84
74
  export function resolveRealCodex(selfPath) {
package/src/install.mjs CHANGED
@@ -5,7 +5,7 @@ import { execFileSync } from 'node:child_process';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { activeRuns } from './runtime.mjs';
7
7
  import { legacyInstallation } from './legacy.mjs';
8
- import { atomicJSON, configPath, codexHome, resolveRealCodex, readConfig, bundledCodexPaths } from './config.mjs';
8
+ import { atomicJSON, configPath, codexHome, readConfig, bundledCodexRelativePath } from './config.mjs';
9
9
 
10
10
  const label = 'com.ailuntz.minilink';
11
11
  export const installRoot = () => join(homedir(), '.local/share/minilink');
@@ -42,7 +42,7 @@ function atomicFile(path, text, mode) {
42
42
 
43
43
  // Each installation has its own files: active Desktop processes keep their
44
44
  // original modules and picker assets while the next launch uses the new copy.
45
- export function install({ root = installRoot(), plist = defaultPlist(), source = sourceRoot, home = codexHome(), config = configPath(), node = process.execPath, npm = process.env.npm_execpath, prefix = process.env.npm_config_prefix, run = launchctl, legacy = root === installRoot() ? legacyInstallation() : null, realCodex = resolveRealCodex(join(source, 'bin/minilink.mjs')) } = {}) {
45
+ export function install({ root = installRoot(), plist = defaultPlist(), source = sourceRoot, home = codexHome(), config = configPath(), node = process.execPath, npm = process.env.npm_execpath, prefix = process.env.npm_config_prefix, run = launchctl, legacy = root === installRoot() ? legacyInstallation() : null } = {}) {
46
46
  if (process.platform !== 'darwin') throw new Error('Desktop 接入目前仅支持 macOS。');
47
47
  const previous = installation(root), wrapper = join(root, 'minilink');
48
48
  if (existsSync(plist) && !previous) throw new Error('同名 LaunchAgent 已存在且不属于本次安装。');
@@ -76,10 +76,8 @@ export function install({ root = installRoot(), plist = defaultPlist(), source =
76
76
  if (JSON.parse(readFileSync(join(dependency, 'package.json'), 'utf8')).name !== 'smol-toml') throw new Error('smol-toml 依赖路径无效。');
77
77
  cpSync(dependency, join(runtime, 'node_modules/smol-toml'), { recursive: true });
78
78
  const state = { version: 2, source, runtime, wrapper, node, npm: npm || previous?.npm, prefix: prefix || previous?.prefix, codexHome: home, configPath: config, previousEnv: previous?.previousEnv || legacy?.state.previousEnv || null, installedAt: new Date().toISOString() };
79
- // The small fallback also serves Desktop instances that inherited the old
80
- // launch environment before npm uninstall removed the integration.
81
- const fallbackApps = ['/Applications/ChatGPT.app', '/Applications/Codex.app', join(homedir(), 'Applications/ChatGPT.app'), join(homedir(), 'Applications/Codex.app')];
82
- const fallback = `if [ ! -f ${shellQuote(stateFile)} ]; then\n if [ -n "$MINILINK_REAL_CODEX" ] && [ -x "$MINILINK_REAL_CODEX" ]; then exec "$MINILINK_REAL_CODEX" "$@"; fi\n for app in "$CODEX_DESKTOP_APP" ${fallbackApps.map(shellQuote).join(' ')}; do\n [ -n "$app" ] || continue\n for rel in ${bundledCodexPaths.map(shellQuote).join(' ')}; do\n candidate="$app/Contents/Resources/$rel"\n if [ -x "$candidate" ]; then exec "$candidate" "$@"; fi\n done\n done\n exec ${shellQuote(realCodex)} "$@"\nfi`;
79
+ // A Desktop process can retain this launcher after npm removes the state.
80
+ const fallback = `if [ ! -f ${shellQuote(stateFile)} ]; then\n exec "\${CODEX_DESKTOP_APP:-/Applications/ChatGPT.app}/${bundledCodexRelativePath}" "$@"\nfi`;
83
81
  atomicFile(wrapper, `#!/bin/sh\n${fallback}\nexport CODEX_HOME=${shellQuote(home)}\nexport MINILINK_CONFIG=${shellQuote(config)}\nexec ${shellQuote(node)} ${shellQuote(join(runtime, 'bin/minilink.mjs'))} "$@"\n`, 0o755);
84
82
  atomicFile(activate, `#!/bin/sh\nexec ${shellQuote(node)} ${shellQuote(join(runtime, 'src/lifecycle.mjs'))}\n`, 0o700);
85
83
  mkdirSync(dirname(plist), { recursive: true });