@walkhi/code-relax 0.1.0-beta.50 → 0.1.0-beta.59

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.
Files changed (101) hide show
  1. package/README.md +105 -105
  2. package/dist/bin/cleanup-accounts.mjs +63 -63
  3. package/dist/bin/codex-remote.mjs +403 -403
  4. package/dist/bin/publish-android-release.mjs +63 -63
  5. package/dist/bin/release-upload-server.mjs +190 -190
  6. package/dist/bin/set-relay-admin-password.mjs +11 -0
  7. package/dist/build-platform.json +1 -1
  8. package/dist/get-shared-service-url.ps1 +14 -14
  9. package/dist/shared/code-browser.cjs +159 -159
  10. package/dist/shared/file-changes.cjs +31 -31
  11. package/dist/shared/file-citations.cjs +117 -117
  12. package/dist/shared/file-mentions.cjs +92 -92
  13. package/dist/shared/message-delivery.cjs +115 -115
  14. package/dist/shared/p2p-file-channel.cjs +87 -87
  15. package/dist/shared/release-version.cjs +31 -0
  16. package/dist/shared/server-requests.cjs +311 -311
  17. package/dist/shared/timeline-sync.cjs +173 -173
  18. package/dist/skills/code-relax/SKILL.md +22 -22
  19. package/dist/src/bounded-process-log.mjs +63 -63
  20. package/dist/src/celsius-client.mjs +107 -107
  21. package/dist/src/dots-approval-timeline.mjs +99 -99
  22. package/dist/src/dots-avatar.mjs +42 -42
  23. package/dist/src/dots-chat-projection.mjs +50 -50
  24. package/dist/src/dots-chat-server.mjs +483 -483
  25. package/dist/src/dots-message-images.mjs +319 -319
  26. package/dist/src/dots-profile.mjs +77 -77
  27. package/dist/src/dots-room-activity.mjs +172 -172
  28. package/dist/src/dots-room-client.mjs +137 -135
  29. package/dist/src/dots-room-projection.mjs +94 -94
  30. package/dist/src/dots-schedules.mjs +66 -66
  31. package/dist/src/dots-summary-tasks.mjs +32 -32
  32. package/dist/src/dots-task-catalog.mjs +430 -430
  33. package/dist/src/file-transfer-range.mjs +22 -22
  34. package/dist/src/file-upload-session.mjs +146 -130
  35. package/dist/src/hosted-history-app-server.mjs +103 -103
  36. package/dist/src/hosted-history-cache.mjs +113 -113
  37. package/dist/src/lan-socket-server.mjs +338 -266
  38. package/dist/src/managed-app-server.mjs +373 -373
  39. package/dist/src/managed-endpoint.mjs +25 -25
  40. package/dist/src/message-upload-files.mjs +109 -109
  41. package/dist/src/onboarding.mjs +12 -12
  42. package/dist/src/platform/README.md +1 -1
  43. package/dist/src/platform/codex-protocol.mjs +46 -46
  44. package/dist/src/platform/desktop-project-store.mjs +219 -208
  45. package/dist/src/platform/linux/desktop-host.mjs +87 -87
  46. package/dist/src/platform/linux/process.mjs +53 -53
  47. package/dist/src/platform/linux/system.mjs +50 -50
  48. package/dist/src/platform/linux/user-environment.mjs +9 -9
  49. package/dist/src/platform/macos/codex-runtime.mjs +125 -125
  50. package/dist/src/platform/macos/desktop-host.mjs +86 -86
  51. package/dist/src/platform/macos/user-environment.mjs +9 -9
  52. package/dist/src/platform/native-package.mjs +58 -58
  53. package/dist/src/platform/windows/activate-desktop.ps1 +49 -49
  54. package/dist/src/platform/windows/codex-runtime.mjs +215 -215
  55. package/dist/src/platform/windows/credential-store.mjs +27 -27
  56. package/dist/src/platform/windows/credential-store.ps1 +49 -49
  57. package/dist/src/platform/windows/desktop-host.mjs +65 -65
  58. package/dist/src/platform/windows/desktop-info.ps1 +38 -38
  59. package/dist/src/platform/windows/desktop-project-registration.mjs +4 -4
  60. package/dist/src/platform/windows/desktop-shortcuts.ps1 +14 -14
  61. package/dist/src/platform/windows/dots-profile.mjs +49 -49
  62. package/dist/src/platform/windows/launch-worker.mjs +41 -41
  63. package/dist/src/platform/windows/project-locations.mjs +16 -16
  64. package/dist/src/platform/windows/service-host.mjs +35 -35
  65. package/dist/src/platform/windows/user-environment.mjs +52 -52
  66. package/dist/src/project-management.mjs +58 -58
  67. package/dist/src/runtime-discovery.mjs +47 -47
  68. package/dist/src/self-relay/account-cleanup.mjs +30 -30
  69. package/dist/src/self-relay/admin-auth.mjs +59 -0
  70. package/dist/src/self-relay/admin-login-page.mjs +7 -0
  71. package/dist/src/self-relay/admin-page.mjs +87 -80
  72. package/dist/src/self-relay/admin-server.mjs +49 -18
  73. package/dist/src/self-relay/admin-style.mjs +58 -14
  74. package/dist/src/self-relay/admin-workstations-page.mjs +95 -0
  75. package/dist/src/self-relay/admin-workstations.mjs +143 -0
  76. package/dist/src/self-relay/connection-reporting.mjs +38 -0
  77. package/dist/src/self-relay/connector.mjs +444 -439
  78. package/dist/src/self-relay/demo.mjs +31 -31
  79. package/dist/src/self-relay/diagnostics.mjs +54 -54
  80. package/dist/src/self-relay/email-accounts.mjs +183 -183
  81. package/dist/src/self-relay/file-wire.mjs +13 -13
  82. package/dist/src/self-relay/lifecycle.mjs +11 -0
  83. package/dist/src/self-relay/p2p-probe.mjs +168 -168
  84. package/dist/src/self-relay/phone-connections.mjs +55 -0
  85. package/dist/src/self-relay/privacy-page.mjs +26 -26
  86. package/dist/src/self-relay/public-releases.mjs +67 -67
  87. package/dist/src/self-relay/rtc-file-bridge.mjs +46 -41
  88. package/dist/src/self-relay/server.mjs +63 -3
  89. package/dist/src/self-relay/usage-meter.mjs +141 -141
  90. package/dist/src/server.mjs +23 -9
  91. package/dist/src/service-doctor.mjs +148 -148
  92. package/dist/src/service-install.mjs +97 -97
  93. package/dist/src/service-lifecycle.mjs +139 -139
  94. package/dist/src/service-update.mjs +6 -3
  95. package/dist/src/shared-app-server.mjs +683 -666
  96. package/dist/src/shared-catalog.mjs +132 -132
  97. package/dist/src/shared-thread-stream.mjs +165 -165
  98. package/dist/src/usage-reset.mjs +17 -17
  99. package/dist/src/workstation-downloads.mjs +120 -120
  100. package/package.json +4 -4
  101. package/tools/postinstall.mjs +186 -186
@@ -1,86 +1,86 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { startBackground } from '../../background-process.mjs';
4
- import { systemRequest } from './system.mjs';
5
- import { assertPlainPath } from '../../skill-install.mjs';
6
- import { setTimeout as delay } from 'node:timers/promises';
7
- import { runtimePaths } from '../runtime-paths.mjs';
8
- import { readRecord } from '../../service-lifecycle.mjs';
9
- export { residentStartup } from './resident-startup.mjs';
10
-
11
- import { managedEndpointUrl, readManagedEndpoint } from '../../managed-endpoint.mjs';
12
- export function createDesktopHost({ request = systemRequest, wait = delay, now = Date.now, timeout = 10000,
13
- stateRoot = () => runtimePaths().stateRoot, fingerprint = file => {
14
- const stat = fs.statSync(path.join(file, 'Contents/Info.plist'));
15
- return `${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;
16
- } } = {}) {
17
- return {
18
- desktopIntegration: true,
19
- async inspect() {
20
- const url = readManagedEndpoint(stateRoot());
21
- const info = await request({ operation: 'desktop-info', url });
22
- return { ...info, managedUrl: url, desktopIdentity: info.desktop ? `${info.desktop}:${info.version}:${info.build}:${fingerprint(info.desktop)}` : null };
23
- },
24
- process: pid => request({ operation: 'process', pid }),
25
- ownsListener: (expected, url) => request({ operation: 'owns-listener', expected, url }),
26
- start: startBackground,
27
- async stop(pid, expected) {
28
- if (!expected || expected.pid !== pid) throw new Error('停止内核前缺少进程身份,未结束任何进程。');
29
- return request({ operation: 'stop', expected });
30
- },
31
- async sharedServiceUrl() {
32
- const info = await this.inspect();
33
- return info.connectedToManagedServer ? info.managedUrl : '';
34
- },
35
- async startDesktop(bundlePath, environment) {
36
- const managedUrl = managedEndpointUrl(environment.CODEX_APP_SERVER_WS_URL);
37
- if (!managedUrl || managedUrl !== readManagedEndpoint(stateRoot())) throw new Error('Desktop 内核地址与工作站不一致。');
38
- const runtime = readRecord(path.join(stateRoot(), 'codex-runtime.json'));
39
- const codexHome = environment.CODEX_HOME || runtime?.codexHome;
40
- if (!codexHome || !path.isAbsolute(codexHome)) throw new Error('缺少已选内核的 CODEX_HOME,请先运行 relax setup。');
41
- const info = await this.inspect();
42
- if (info.running) throw new Error('Desktop 仍在运行,未创建第二个实例。');
43
- if (info.desktop !== bundlePath) throw new Error('Codex Desktop 安装位置已变化,请重新检查。');
44
- return request({ operation: 'desktop-start', bundlePath,
45
- environment: { CODEX_HOME: codexHome, CODEX_APP_SERVER_WS_URL: managedUrl } });
46
- },
47
- async closeDesktop(bundlePath) {
48
- const info = await this.inspect();
49
- if (!info.running) return;
50
- if (info.desktop !== bundlePath || !info.process) throw new Error('Desktop 进程身份已变化,未请求退出。');
51
- await request({ operation: 'desktop-close', bundlePath, expected: info.process });
52
- const deadline = now() + timeout;
53
- while ((await this.inspect()).running) {
54
- if (now() >= deadline) throw new Error('Desktop 尚未正常退出,请在 Mac 上处理未保存内容后重试;未强制结束进程。');
55
- await wait(200);
56
- }
57
- },
58
- async desktopReady() {
59
- const info = await this.inspect();
60
- return info.running && info.finishedLaunching && info.connectedToManagedServer;
61
- },
62
- async prepareKernelRestart() {
63
- const info = await this.inspect();
64
- if (!info.running || !info.connectedToManagedServer) return null;
65
- await this.closeDesktop(info.desktop);
66
- return info.desktop;
67
- },
68
- async resumeAfterKernelRestart(bundlePath, environment) {
69
- if (!bundlePath) return;
70
- await this.startDesktop(bundlePath, environment);
71
- const deadline = now() + 30000;
72
- while (!await this.desktopReady()) {
73
- if (now() >= deadline) throw new Error('内核已就绪,但 Mac Desktop 尚未重新接入。');
74
- await wait(500);
75
- }
76
- },
77
- ready: async url => { try { return (await fetch(url, { signal: AbortSignal.timeout(1000) })).ok; } catch { return false; } },
78
- };
79
- }
80
- export const desktopHost = createDesktopHost();
81
- export async function resolveStateRoot(stateRoot) {
82
- assertPlainPath(stateRoot);
83
- fs.mkdirSync(stateRoot, { recursive: true, mode: 0o700 });
84
- return fs.realpathSync(stateRoot);
85
- }
86
- export async function removeDesktopShortcut() { return { removed: false, reason: 'not-used-on-macos' }; }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { startBackground } from '../../background-process.mjs';
4
+ import { systemRequest } from './system.mjs';
5
+ import { assertPlainPath } from '../../skill-install.mjs';
6
+ import { setTimeout as delay } from 'node:timers/promises';
7
+ import { runtimePaths } from '../runtime-paths.mjs';
8
+ import { readRecord } from '../../service-lifecycle.mjs';
9
+ export { residentStartup } from './resident-startup.mjs';
10
+
11
+ import { managedEndpointUrl, readManagedEndpoint } from '../../managed-endpoint.mjs';
12
+ export function createDesktopHost({ request = systemRequest, wait = delay, now = Date.now, timeout = 10000,
13
+ stateRoot = () => runtimePaths().stateRoot, fingerprint = file => {
14
+ const stat = fs.statSync(path.join(file, 'Contents/Info.plist'));
15
+ return `${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;
16
+ } } = {}) {
17
+ return {
18
+ desktopIntegration: true,
19
+ async inspect() {
20
+ const url = readManagedEndpoint(stateRoot());
21
+ const info = await request({ operation: 'desktop-info', url });
22
+ return { ...info, managedUrl: url, desktopIdentity: info.desktop ? `${info.desktop}:${info.version}:${info.build}:${fingerprint(info.desktop)}` : null };
23
+ },
24
+ process: pid => request({ operation: 'process', pid }),
25
+ ownsListener: (expected, url) => request({ operation: 'owns-listener', expected, url }),
26
+ start: startBackground,
27
+ async stop(pid, expected) {
28
+ if (!expected || expected.pid !== pid) throw new Error('停止内核前缺少进程身份,未结束任何进程。');
29
+ return request({ operation: 'stop', expected });
30
+ },
31
+ async sharedServiceUrl() {
32
+ const info = await this.inspect();
33
+ return info.connectedToManagedServer ? info.managedUrl : '';
34
+ },
35
+ async startDesktop(bundlePath, environment) {
36
+ const managedUrl = managedEndpointUrl(environment.CODEX_APP_SERVER_WS_URL);
37
+ if (!managedUrl || managedUrl !== readManagedEndpoint(stateRoot())) throw new Error('Desktop 内核地址与工作站不一致。');
38
+ const runtime = readRecord(path.join(stateRoot(), 'codex-runtime.json'));
39
+ const codexHome = environment.CODEX_HOME || runtime?.codexHome;
40
+ if (!codexHome || !path.isAbsolute(codexHome)) throw new Error('缺少已选内核的 CODEX_HOME,请先运行 relax setup。');
41
+ const info = await this.inspect();
42
+ if (info.running) throw new Error('Desktop 仍在运行,未创建第二个实例。');
43
+ if (info.desktop !== bundlePath) throw new Error('Codex Desktop 安装位置已变化,请重新检查。');
44
+ return request({ operation: 'desktop-start', bundlePath,
45
+ environment: { CODEX_HOME: codexHome, CODEX_APP_SERVER_WS_URL: managedUrl } });
46
+ },
47
+ async closeDesktop(bundlePath) {
48
+ const info = await this.inspect();
49
+ if (!info.running) return;
50
+ if (info.desktop !== bundlePath || !info.process) throw new Error('Desktop 进程身份已变化,未请求退出。');
51
+ await request({ operation: 'desktop-close', bundlePath, expected: info.process });
52
+ const deadline = now() + timeout;
53
+ while ((await this.inspect()).running) {
54
+ if (now() >= deadline) throw new Error('Desktop 尚未正常退出,请在 Mac 上处理未保存内容后重试;未强制结束进程。');
55
+ await wait(200);
56
+ }
57
+ },
58
+ async desktopReady() {
59
+ const info = await this.inspect();
60
+ return info.running && info.finishedLaunching && info.connectedToManagedServer;
61
+ },
62
+ async prepareKernelRestart() {
63
+ const info = await this.inspect();
64
+ if (!info.running || !info.connectedToManagedServer) return null;
65
+ await this.closeDesktop(info.desktop);
66
+ return info.desktop;
67
+ },
68
+ async resumeAfterKernelRestart(bundlePath, environment) {
69
+ if (!bundlePath) return;
70
+ await this.startDesktop(bundlePath, environment);
71
+ const deadline = now() + 30000;
72
+ while (!await this.desktopReady()) {
73
+ if (now() >= deadline) throw new Error('内核已就绪,但 Mac Desktop 尚未重新接入。');
74
+ await wait(500);
75
+ }
76
+ },
77
+ ready: async url => { try { return (await fetch(url, { signal: AbortSignal.timeout(1000) })).ok; } catch { return false; } },
78
+ };
79
+ }
80
+ export const desktopHost = createDesktopHost();
81
+ export async function resolveStateRoot(stateRoot) {
82
+ assertPlainPath(stateRoot);
83
+ fs.mkdirSync(stateRoot, { recursive: true, mode: 0o700 });
84
+ return fs.realpathSync(stateRoot);
85
+ }
86
+ export async function removeDesktopShortcut() { return { removed: false, reason: 'not-used-on-macos' }; }
@@ -1,9 +1,9 @@
1
- import { managedEndpointUrl } from '../../managed-endpoint.mjs';
2
- // Launch Services receives these settings for one new application instance.
3
- // Do not mutate shell profiles or the login session's global environment.
4
- export async function configureManagedEnvironment(stateRoot, url) {
5
- if (!managedEndpointUrl(url)) throw new Error('未确认 Codex 内核地址。');
6
- return { configured: true, changed: false, owned: false, persistent: false,
7
- scope: 'application-launch', value: url };
8
- }
9
- export async function clearManagedEnvironment() { return { removed: false, preserved: false, reason: 'application-launch-only' }; }
1
+ import { managedEndpointUrl } from '../../managed-endpoint.mjs';
2
+ // Launch Services receives these settings for one new application instance.
3
+ // Do not mutate shell profiles or the login session's global environment.
4
+ export async function configureManagedEnvironment(stateRoot, url) {
5
+ if (!managedEndpointUrl(url)) throw new Error('未确认 Codex 内核地址。');
6
+ return { configured: true, changed: false, owned: false, persistent: false,
7
+ scope: 'application-launch', value: url };
8
+ }
9
+ export async function clearManagedEnvironment() { return { removed: false, preserved: false, reason: 'application-launch-only' }; }
@@ -1,58 +1,58 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { createRequire } from 'node:module';
4
-
5
- export const nativeTargets = Object.freeze({
6
- 'win32-x64': { packageName: '@walkhi/code-relax-native-win32-x64', file: 'desktop-helper/CodeRelaxDesktop.exe' },
7
- 'darwin-arm64': { packageName: '@walkhi/code-relax-native-darwin-arm64', file: 'macos-host/CodeRelaxHost' },
8
- 'darwin-x64': { packageName: '@walkhi/code-relax-native-darwin-x64', file: 'macos-host/CodeRelaxHost' },
9
- 'linux-x64': { packageName: null, file: null },
10
- 'linux-arm64': { packageName: null, file: null },
11
- });
12
-
13
- const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, ''));
14
-
15
- // Native dependencies are selected by npm's os/cpu filters. Materialize only
16
- // this platform's helper before setup touches the installed workstation.
17
- export function prepareNativePackage(packageRoot, { platform = process.platform, arch = process.arch } = {}) {
18
- const target = nativeTargets[`${platform}-${arch}`];
19
- if (!target) throw new Error(`尚不支持此工作站平台:${platform}-${arch}。`);
20
- const marker = path.join(packageRoot, 'dist/build-platform.json');
21
- const build = readJson(marker);
22
- if (!target.file) {
23
- const pkg = readJson(path.join(packageRoot, 'package.json'));
24
- if (!(build.platform === platform && build.arch === arch)
25
- && !(build.layout === 'npm-platform-packages' && build.version === pkg.version))
26
- throw new Error('安装包构建与当前系统、架构或版本不匹配,请重新安装。');
27
- // Linux adapters use Node/procfs and the session's Secret Service. There is
28
- // no private native helper to download; sharp/RTC select their own binaries.
29
- fs.writeFileSync(marker, JSON.stringify({ platform, arch, version: pkg.version }));
30
- return { platform, arch, materialized: false };
31
- }
32
- const destination = path.join(packageRoot, 'dist/native', target.file);
33
- if (build.platform === platform && build.arch === arch) {
34
- if (!fs.statSync(destination).isFile()) throw new Error('安装包缺少当前平台原生组件,请重新安装。');
35
- return { platform, arch, materialized: false };
36
- }
37
- const pkg = readJson(path.join(packageRoot, 'package.json'));
38
- if (build.layout !== 'npm-platform-packages' || build.version !== pkg.version)
39
- throw new Error('安装包构建与当前系统、架构或版本不匹配,请重新安装。');
40
- let manifest;
41
- try { manifest = createRequire(path.join(packageRoot, 'package.json')).resolve(`${target.packageName}/package.json`); }
42
- catch (error) {
43
- if (error.code !== 'MODULE_NOT_FOUND') throw error;
44
- throw new Error(`缺少 ${target.packageName}@${pkg.version};请勿省略 optional 依赖,使用 npm install -g @walkhi/code-relax@${pkg.version} --include=optional --allow-scripts=@walkhi/code-relax --foreground-scripts 重新安装。`);
45
- }
46
- const native = readJson(manifest);
47
- if (native.name !== target.packageName || native.version !== pkg.version
48
- || native.os?.length !== 1 || native.os[0] !== platform || native.cpu?.length !== 1 || native.cpu[0] !== arch)
49
- throw new Error('原生组件包的系统、架构或版本不匹配,未更新工作站。');
50
- const source = path.join(path.dirname(manifest), 'native', target.file);
51
- if (!fs.statSync(source).isFile()) throw new Error('平台包缺少原生组件,未更新工作站。');
52
- fs.mkdirSync(path.dirname(destination), { recursive: true });
53
- fs.copyFileSync(source, destination);
54
- if (platform === 'darwin') fs.chmodSync(destination, 0o755);
55
- // Only commit the selected platform after the component has been copied.
56
- fs.writeFileSync(marker, JSON.stringify({ platform, arch, version: pkg.version }));
57
- return { platform, arch, packageName: native.name, materialized: true };
58
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+
5
+ export const nativeTargets = Object.freeze({
6
+ 'win32-x64': { packageName: '@walkhi/code-relax-native-win32-x64', file: 'desktop-helper/CodeRelaxDesktop.exe' },
7
+ 'darwin-arm64': { packageName: '@walkhi/code-relax-native-darwin-arm64', file: 'macos-host/CodeRelaxHost' },
8
+ 'darwin-x64': { packageName: '@walkhi/code-relax-native-darwin-x64', file: 'macos-host/CodeRelaxHost' },
9
+ 'linux-x64': { packageName: null, file: null },
10
+ 'linux-arm64': { packageName: null, file: null },
11
+ });
12
+
13
+ const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, ''));
14
+
15
+ // Native dependencies are selected by npm's os/cpu filters. Materialize only
16
+ // this platform's helper before setup touches the installed workstation.
17
+ export function prepareNativePackage(packageRoot, { platform = process.platform, arch = process.arch } = {}) {
18
+ const target = nativeTargets[`${platform}-${arch}`];
19
+ if (!target) throw new Error(`尚不支持此工作站平台:${platform}-${arch}。`);
20
+ const marker = path.join(packageRoot, 'dist/build-platform.json');
21
+ const build = readJson(marker);
22
+ if (!target.file) {
23
+ const pkg = readJson(path.join(packageRoot, 'package.json'));
24
+ if (!(build.platform === platform && build.arch === arch)
25
+ && !(build.layout === 'npm-platform-packages' && build.version === pkg.version))
26
+ throw new Error('安装包构建与当前系统、架构或版本不匹配,请重新安装。');
27
+ // Linux adapters use Node/procfs and the session's Secret Service. There is
28
+ // no private native helper to download; sharp/RTC select their own binaries.
29
+ fs.writeFileSync(marker, JSON.stringify({ platform, arch, version: pkg.version }));
30
+ return { platform, arch, materialized: false };
31
+ }
32
+ const destination = path.join(packageRoot, 'dist/native', target.file);
33
+ if (build.platform === platform && build.arch === arch) {
34
+ if (!fs.statSync(destination).isFile()) throw new Error('安装包缺少当前平台原生组件,请重新安装。');
35
+ return { platform, arch, materialized: false };
36
+ }
37
+ const pkg = readJson(path.join(packageRoot, 'package.json'));
38
+ if (build.layout !== 'npm-platform-packages' || build.version !== pkg.version)
39
+ throw new Error('安装包构建与当前系统、架构或版本不匹配,请重新安装。');
40
+ let manifest;
41
+ try { manifest = createRequire(path.join(packageRoot, 'package.json')).resolve(`${target.packageName}/package.json`); }
42
+ catch (error) {
43
+ if (error.code !== 'MODULE_NOT_FOUND') throw error;
44
+ throw new Error(`缺少 ${target.packageName}@${pkg.version};请勿省略 optional 依赖,使用 npm install -g @walkhi/code-relax@${pkg.version} --include=optional --allow-scripts=@walkhi/code-relax --foreground-scripts 重新安装。`);
45
+ }
46
+ const native = readJson(manifest);
47
+ if (native.name !== target.packageName || native.version !== pkg.version
48
+ || native.os?.length !== 1 || native.os[0] !== platform || native.cpu?.length !== 1 || native.cpu[0] !== arch)
49
+ throw new Error('原生组件包的系统、架构或版本不匹配,未更新工作站。');
50
+ const source = path.join(path.dirname(manifest), 'native', target.file);
51
+ if (!fs.statSync(source).isFile()) throw new Error('平台包缺少原生组件,未更新工作站。');
52
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
53
+ fs.copyFileSync(source, destination);
54
+ if (platform === 'darwin') fs.chmodSync(destination, 0o755);
55
+ // Only commit the selected platform after the component has been copied.
56
+ fs.writeFileSync(marker, JSON.stringify({ platform, arch, version: pkg.version }));
57
+ return { platform, arch, packageName: native.name, materialized: true };
58
+ }
@@ -1,49 +1,49 @@
1
- param(
2
- [Parameter(Mandatory=$true)][string]$Executable,
3
- [Parameter(Mandatory=$true)][string]$AppServerUrl
4
- )
5
- $ErrorActionPreference = 'Stop'
6
- [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
7
- if ($AppServerUrl -cnotmatch '^ws://127\.0\.0\.1:([1-9][0-9]{0,4})\z' -or [int]$Matches[1] -gt 65535) { throw 'Invalid managed app-server URL.' }
8
- $package = Get-AppxPackage OpenAI.Codex | Select-Object -First 1
9
- if (-not $package -or $Executable -ne (Join-Path $package.InstallLocation 'app/ChatGPT.exe')) {
10
- throw 'Desktop executable identity changed; activation stopped.'
11
- }
12
- # Packaged activation uses the user's environment, not the worker's env block.
13
- # Installation already owns and broadcasts this setting. Do not silently launch
14
- # a separate app-server if it has been removed or changed since installation.
15
- if ([Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_WS_URL', 'User') -ne $AppServerUrl) {
16
- throw 'Desktop app-server environment differs from the workstation; run relax setup to repair it.'
17
- }
18
- if ([Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_FORCE_CLI', 'User') -eq '1' -or
19
- [Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_FORCE_CLI', 'Machine') -eq '1') {
20
- throw 'CODEX_APP_SERVER_FORCE_CLI=1 prevents Desktop from connecting to the workstation.'
21
- }
22
- # Activate the registered application so Windows supplies its MSIX identity.
23
- # Never spawn ChatGPT.exe through the hidden-console broker: a bootstrap failure
24
- # can leave a windowless Electron singleton blocking subsequent taskbar launches.
25
- Add-Type -TypeDefinition @'
26
- using System;
27
- using System.Runtime.InteropServices;
28
- namespace CodeRelax {
29
- [ComImport, Guid("2e941141-7f97-4756-ba1d-9decde894a3d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
30
- interface IApplicationActivationManager {
31
- void ActivateApplication([MarshalAs(UnmanagedType.LPWStr)] string appId,
32
- [MarshalAs(UnmanagedType.LPWStr)] string arguments, uint options, out uint processId);
33
- void ActivateForFile([MarshalAs(UnmanagedType.LPWStr)] string appId, IntPtr items,
34
- [MarshalAs(UnmanagedType.LPWStr)] string verb, out uint processId);
35
- void ActivateForProtocol([MarshalAs(UnmanagedType.LPWStr)] string appId, IntPtr items, out uint processId);
36
- }
37
- public static class DesktopActivation {
38
- public static uint Activate(string appId) {
39
- object instance = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")));
40
- try {
41
- uint processId;
42
- ((IApplicationActivationManager)instance).ActivateApplication(appId, "", 2, out processId);
43
- return processId;
44
- } finally { Marshal.ReleaseComObject(instance); }
45
- }
46
- }
47
- }
48
- '@
49
- [CodeRelax.DesktopActivation]::Activate($package.PackageFamilyName + '!App')
1
+ param(
2
+ [Parameter(Mandatory=$true)][string]$Executable,
3
+ [Parameter(Mandatory=$true)][string]$AppServerUrl
4
+ )
5
+ $ErrorActionPreference = 'Stop'
6
+ [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
7
+ if ($AppServerUrl -cnotmatch '^ws://127\.0\.0\.1:([1-9][0-9]{0,4})\z' -or [int]$Matches[1] -gt 65535) { throw 'Invalid managed app-server URL.' }
8
+ $package = Get-AppxPackage OpenAI.Codex | Select-Object -First 1
9
+ if (-not $package -or $Executable -ne (Join-Path $package.InstallLocation 'app/ChatGPT.exe')) {
10
+ throw 'Desktop executable identity changed; activation stopped.'
11
+ }
12
+ # Packaged activation uses the user's environment, not the worker's env block.
13
+ # Installation already owns and broadcasts this setting. Do not silently launch
14
+ # a separate app-server if it has been removed or changed since installation.
15
+ if ([Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_WS_URL', 'User') -ne $AppServerUrl) {
16
+ throw 'Desktop app-server environment differs from the workstation; run relax setup to repair it.'
17
+ }
18
+ if ([Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_FORCE_CLI', 'User') -eq '1' -or
19
+ [Environment]::GetEnvironmentVariable('CODEX_APP_SERVER_FORCE_CLI', 'Machine') -eq '1') {
20
+ throw 'CODEX_APP_SERVER_FORCE_CLI=1 prevents Desktop from connecting to the workstation.'
21
+ }
22
+ # Activate the registered application so Windows supplies its MSIX identity.
23
+ # Never spawn ChatGPT.exe through the hidden-console broker: a bootstrap failure
24
+ # can leave a windowless Electron singleton blocking subsequent taskbar launches.
25
+ Add-Type -TypeDefinition @'
26
+ using System;
27
+ using System.Runtime.InteropServices;
28
+ namespace CodeRelax {
29
+ [ComImport, Guid("2e941141-7f97-4756-ba1d-9decde894a3d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
30
+ interface IApplicationActivationManager {
31
+ void ActivateApplication([MarshalAs(UnmanagedType.LPWStr)] string appId,
32
+ [MarshalAs(UnmanagedType.LPWStr)] string arguments, uint options, out uint processId);
33
+ void ActivateForFile([MarshalAs(UnmanagedType.LPWStr)] string appId, IntPtr items,
34
+ [MarshalAs(UnmanagedType.LPWStr)] string verb, out uint processId);
35
+ void ActivateForProtocol([MarshalAs(UnmanagedType.LPWStr)] string appId, IntPtr items, out uint processId);
36
+ }
37
+ public static class DesktopActivation {
38
+ public static uint Activate(string appId) {
39
+ object instance = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")));
40
+ try {
41
+ uint processId;
42
+ ((IApplicationActivationManager)instance).ActivateApplication(appId, "", 2, out processId);
43
+ return processId;
44
+ } finally { Marshal.ReleaseComObject(instance); }
45
+ }
46
+ }
47
+ }
48
+ '@
49
+ [CodeRelax.DesktopActivation]::Activate($package.PackageFamilyName + '!App')