@walkhi/code-relax 0.1.0-beta.30 → 0.1.0-beta.31
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 +95 -89
- package/dist/bin/cleanup-accounts.mjs +63 -63
- package/dist/bin/codex-remote.mjs +374 -367
- package/dist/bin/manage-relay-admin.mjs +20 -20
- package/dist/bin/migrate-relay-db.mjs +109 -109
- package/dist/bin/publish-android-release.mjs +62 -58
- package/dist/bin/self-relay-admin.mjs +8 -8
- package/dist/bin/self-relay-demo.mjs +33 -33
- package/dist/bin/self-relay-server.mjs +66 -66
- package/dist/build-platform.json +1 -1
- package/dist/get-lan-networks.ps1 +40 -40
- package/dist/get-shared-service-url.ps1 +6 -6
- package/dist/shared/app-server-events.cjs +422 -412
- package/dist/shared/code-browser.cjs +159 -159
- package/dist/shared/file-changes.cjs +31 -31
- package/dist/shared/file-citations.cjs +117 -117
- package/dist/shared/file-mentions.cjs +92 -92
- package/dist/shared/message-delivery.cjs +54 -54
- package/dist/shared/p2p-data-channel.cjs +72 -72
- package/dist/shared/p2p-diagnostics.cjs +28 -28
- package/dist/shared/p2p-file-channel.cjs +74 -74
- package/dist/shared/plan-pricing.cjs +32 -32
- package/dist/shared/question-attention.cjs +40 -0
- package/dist/shared/server-requests.cjs +219 -219
- package/dist/shared/timeline-sync.cjs +173 -173
- package/dist/skills/code-relax/SKILL.md +22 -22
- package/dist/src/archived-threads.mjs +22 -0
- package/dist/src/background-process.mjs +18 -18
- package/dist/src/bounded-process-log.mjs +63 -63
- package/dist/src/celsius-client.mjs +107 -107
- package/dist/src/code-browser.mjs +100 -100
- package/dist/src/desktop-launcher.mjs +46 -46
- package/dist/src/dots-approval-timeline.mjs +99 -99
- package/dist/src/dots-avatar.mjs +42 -42
- package/dist/src/dots-chat-projection.mjs +50 -50
- package/dist/src/dots-chat-server.mjs +461 -461
- package/dist/src/dots-message-images.mjs +319 -319
- package/dist/src/dots-profile.mjs +77 -77
- package/dist/src/dots-room-activity.mjs +94 -94
- package/dist/src/dots-room-client.mjs +135 -135
- package/dist/src/dots-room-projection.mjs +94 -94
- package/dist/src/dots-schedules.mjs +66 -66
- package/dist/src/dots-summary-tasks.mjs +32 -32
- package/dist/src/dots-task-catalog.mjs +430 -430
- package/dist/src/dots-task-files.mjs +52 -52
- package/dist/src/execution-health.mjs +26 -26
- package/dist/src/file-transfer-range.mjs +22 -22
- package/dist/src/file-upload-session.mjs +130 -130
- package/dist/src/hosted-history-app-server.mjs +103 -103
- package/dist/src/hosted-history-cache.mjs +113 -113
- package/dist/src/lan-socket-server.mjs +265 -263
- package/dist/src/managed-app-server.mjs +244 -244
- package/dist/src/message-images.mjs +9 -9
- package/dist/src/message-upload-files.mjs +74 -74
- package/dist/src/onboarding.mjs +12 -12
- package/dist/src/plan-pricing.mjs +47 -47
- package/dist/src/platform/README.md +12 -12
- package/dist/src/platform/codex-protocol.mjs +46 -46
- package/dist/src/platform/codex-runtime.mjs +3 -3
- package/dist/src/platform/credential-store.mjs +3 -3
- package/dist/src/platform/desktop-host.mjs +3 -3
- package/dist/src/platform/desktop-project-registration.mjs +3 -3
- package/dist/src/platform/desktop-project-store.mjs +208 -149
- package/dist/src/platform/file-opener.mjs +9 -0
- package/dist/src/platform/linux/README.md +3 -3
- package/dist/src/platform/linux/codex-runtime.mjs +56 -0
- package/dist/src/platform/linux/credential-store.mjs +28 -0
- package/dist/src/platform/linux/desktop-host.mjs +83 -0
- package/dist/src/platform/linux/desktop-installation.mjs +36 -0
- package/dist/src/platform/linux/desktop-project-registration.mjs +11 -0
- package/dist/src/platform/linux/network-info.mjs +11 -0
- package/dist/src/platform/linux/process.mjs +42 -0
- package/dist/src/platform/linux/project-locations.mjs +17 -0
- package/dist/src/platform/linux/resident-startup.mjs +52 -0
- package/dist/src/platform/linux/retained-runtime.mjs +76 -0
- package/dist/src/platform/linux/service-host.mjs +18 -0
- package/dist/src/platform/linux/system.mjs +49 -0
- package/dist/src/platform/linux/user-environment.mjs +7 -0
- package/dist/src/platform/macos/README.md +3 -3
- package/dist/src/platform/macos/codex-runtime.mjs +125 -125
- package/dist/src/platform/macos/credential-store.mjs +10 -10
- package/dist/src/platform/macos/desktop-host.mjs +82 -82
- package/dist/src/platform/macos/desktop-project-registration.mjs +11 -10
- package/dist/src/platform/macos/network-info.mjs +8 -28
- package/dist/src/platform/macos/project-locations.mjs +8 -8
- package/dist/src/platform/macos/resident-startup.mjs +84 -84
- package/dist/src/platform/macos/retained-runtime.mjs +127 -127
- package/dist/src/platform/macos/service-host.mjs +18 -18
- package/dist/src/platform/macos/system.mjs +29 -29
- package/dist/src/platform/macos/user-environment.mjs +7 -7
- package/dist/src/platform/native-package.mjs +58 -46
- package/dist/src/platform/network-info.mjs +3 -3
- package/dist/src/platform/path-identity.mjs +5 -5
- package/dist/src/platform/posix/network-candidates.mjs +23 -0
- package/dist/src/platform/posix/runtime-paths.mjs +25 -25
- package/dist/src/platform/project-locations.mjs +3 -3
- package/dist/src/platform/runtime-paths.mjs +8 -8
- package/dist/src/platform/select.mjs +5 -5
- package/dist/src/platform/service-host.mjs +3 -3
- package/dist/src/platform/user-environment.mjs +3 -3
- package/dist/src/platform/windows/IsolatedProcess.cs +79 -79
- package/dist/src/platform/windows/activate-desktop.ps1 +48 -48
- package/dist/src/platform/windows/background-process.mjs +30 -30
- package/dist/src/platform/windows/codex-runtime.mjs +215 -215
- package/dist/src/platform/windows/credential-store.mjs +27 -27
- package/dist/src/platform/windows/credential-store.ps1 +49 -49
- package/dist/src/platform/windows/desktop-helper.mjs +179 -179
- package/dist/src/platform/windows/desktop-host.mjs +58 -58
- package/dist/src/platform/windows/desktop-info.ps1 +14 -14
- package/dist/src/platform/windows/desktop-project-registration.mjs +4 -4
- package/dist/src/platform/windows/desktop-runtime.ps1 +10 -10
- package/dist/src/platform/windows/desktop-shortcuts.ps1 +21 -21
- package/dist/src/platform/windows/dots-profile.mjs +49 -49
- package/dist/src/platform/windows/launch-worker.mjs +41 -41
- package/dist/src/platform/windows/network-info.mjs +34 -34
- package/dist/src/platform/windows/project-locations.mjs +16 -16
- package/dist/src/platform/windows/resident-start.js +20 -20
- package/dist/src/platform/windows/resident-start.ps1 +7 -7
- package/dist/src/platform/windows/resident-startup.ps1 +83 -83
- package/dist/src/platform/windows/resolve-state-root.ps1 +14 -14
- package/dist/src/platform/windows/runtime-paths.mjs +20 -20
- package/dist/src/platform/windows/rustdesk-video-probe.mjs +167 -167
- package/dist/src/platform/windows/service-host.mjs +31 -31
- package/dist/src/platform/windows/start-hidden-console.ps1 +49 -49
- package/dist/src/platform/windows/stop-desktop.ps1 +22 -22
- package/dist/src/platform/windows/user-environment.mjs +50 -50
- package/dist/src/platform/windows/user-environment.ps1 +41 -41
- package/dist/src/project-archive.mjs +30 -0
- package/dist/src/project-create.mjs +121 -119
- package/dist/src/project-management.mjs +59 -69
- package/dist/src/project-remove.mjs +55 -0
- package/dist/src/project-update.mjs +56 -0
- package/dist/src/runtime-discovery.mjs +47 -47
- package/dist/src/self-relay/account-cleanup.mjs +30 -30
- package/dist/src/self-relay/account-connections.mjs +52 -52
- package/dist/src/self-relay/admin-cloud.mjs +101 -101
- package/dist/src/self-relay/admin-page.mjs +80 -80
- package/dist/src/self-relay/admin-server.mjs +74 -74
- package/dist/src/self-relay/admin-state.mjs +127 -127
- package/dist/src/self-relay/admin-style.mjs +14 -14
- package/dist/src/self-relay/android-releases.mjs +61 -61
- package/dist/src/self-relay/client.mjs +61 -61
- package/dist/src/self-relay/connector.mjs +439 -438
- package/dist/src/self-relay/debug-allowlist.mjs +33 -33
- package/dist/src/self-relay/demo.mjs +37 -37
- package/dist/src/self-relay/device-info.mjs +27 -0
- package/dist/src/self-relay/device-store.mjs +92 -84
- package/dist/src/self-relay/diagnostics.mjs +54 -54
- package/dist/src/self-relay/email-accounts.mjs +183 -183
- package/dist/src/self-relay/file-wire.mjs +13 -13
- package/dist/src/self-relay/lan-authorizations.mjs +71 -42
- package/dist/src/self-relay/lifecycle.mjs +264 -250
- package/dist/src/self-relay/long-pairing.mjs +40 -40
- package/dist/src/self-relay/mysql-state.mjs +118 -105
- package/dist/src/self-relay/p2p-probe.mjs +159 -159
- package/dist/src/self-relay/privacy-page.mjs +26 -26
- package/dist/src/self-relay/public-releases.mjs +34 -0
- package/dist/src/self-relay/rtc-file-bridge.mjs +41 -41
- package/dist/src/self-relay/server.mjs +1006 -932
- package/dist/src/self-relay/usage-daily.mjs +55 -55
- package/dist/src/self-relay/usage-meter.mjs +141 -141
- package/dist/src/self-relay/windows-route-helper.mjs +75 -75
- package/dist/src/self-relay/wire.mjs +36 -36
- package/dist/src/server.mjs +1861 -1778
- package/dist/src/service-control.mjs +82 -82
- package/dist/src/service-doctor.mjs +110 -110
- package/dist/src/service-health.mjs +33 -33
- package/dist/src/service-install.mjs +91 -91
- package/dist/src/service-lifecycle.mjs +138 -138
- package/dist/src/service-restart.mjs +81 -81
- package/dist/src/shared-app-server.mjs +615 -611
- package/dist/src/shared-catalog.mjs +132 -132
- package/dist/src/shared-recovery.mjs +146 -146
- package/dist/src/shared-thread-stream.mjs +164 -164
- package/dist/src/skill-install.mjs +51 -51
- package/dist/src/thread-title-generation.mjs +150 -150
- package/dist/src/turn-model-history.mjs +47 -47
- package/dist/src/usage-reset.mjs +17 -17
- package/dist/src/workstation-downloads.mjs +120 -120
- package/dist/tools/rtc-route-helper.ps1 +99 -99
- package/dist/tools/start-rtc-route-helper.ps1 +15 -15
- package/dist/web/vendor/markdown-it.LICENSE.txt +22 -22
- package/dist/web/vendor/markdown-it.umd.min.js +13 -13
- package/package.json +7 -6
- package/tools/postinstall.mjs +127 -127
|
@@ -1,367 +1,374 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { phonePairingSteps, desktopSetupSteps, pairingDisplayText } from '../src/onboarding.mjs';
|
|
3
|
-
import { lifecycle, readRecord, writeRecord } from '../src/service-lifecycle.mjs';
|
|
4
|
-
import { runtimePaths } from '../src/platform/runtime-paths.mjs';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
pair
|
|
34
|
-
pair
|
|
35
|
-
pair-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
desktop-helper
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
--
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
throw new Error('
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
throw new Error('
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (!
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
throw new Error('Codex
|
|
147
|
-
}
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
result
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
await
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
let
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
installed.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
installed.
|
|
339
|
-
installed.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { phonePairingSteps, desktopSetupSteps, pairingDisplayText } from '../src/onboarding.mjs';
|
|
3
|
+
import { lifecycle, readRecord, writeRecord } from '../src/service-lifecycle.mjs';
|
|
4
|
+
import { runtimePaths } from '../src/platform/runtime-paths.mjs';
|
|
5
|
+
import { openFile } from '../src/platform/file-opener.mjs';
|
|
6
|
+
import * as host from '../src/platform/service-host.mjs';
|
|
7
|
+
import { installService, uninstallService, packageRoot } from '../src/service-install.mjs';
|
|
8
|
+
import { installSkill, removeSkill, inspectSkill } from '../src/skill-install.mjs';
|
|
9
|
+
import { doctor, formatDoctorOutput } from '../src/service-doctor.mjs';
|
|
10
|
+
import { launchDesktop } from '../src/desktop-launcher.mjs';
|
|
11
|
+
import { desktopHost, removeDesktopShortcut, residentStartup, resolveStateRoot } from '../src/platform/desktop-host.mjs';
|
|
12
|
+
import { selfRelay } from '../src/self-relay/lifecycle.mjs';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { executableKey } from '../src/platform/path-identity.mjs';
|
|
16
|
+
import fs from 'node:fs';
|
|
17
|
+
import { spawn } from 'node:child_process';
|
|
18
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
19
|
+
import { requestRecovery, recoveryWarning } from '../src/shared-recovery.mjs';
|
|
20
|
+
import { configureManagedEnvironment, clearManagedEnvironment } from '../src/platform/user-environment.mjs';
|
|
21
|
+
import { resolveCodexRuntime } from '../src/platform/codex-runtime.mjs';
|
|
22
|
+
import { controlRequest } from '../src/service-control.mjs';
|
|
23
|
+
import { processAlive } from '../src/background-process.mjs';
|
|
24
|
+
import { prepareNativePackage } from '../src/platform/native-package.mjs';
|
|
25
|
+
import { managedAppServerUrl } from '../src/managed-app-server.mjs';
|
|
26
|
+
import { readDotsTasks } from '../src/dots-task-catalog.mjs';
|
|
27
|
+
import { installDesktopHelper, desktopHelperStatus, removeDesktopHelper } from '../src/platform/windows/desktop-helper.mjs';
|
|
28
|
+
|
|
29
|
+
const help = `Code Relax(Windows / macOS / Linux)
|
|
30
|
+
用法:relax <命令>
|
|
31
|
+
常用指令:
|
|
32
|
+
start 启动或复用桌面服务和 Codex 内核,并恢复已配置的 Code Relax 中继
|
|
33
|
+
pair 启动或复用桌面服务,并打开一次性配对二维码
|
|
34
|
+
pair --expires <带时区的截止时间> 创建本工作站可重复使用的长期二维码
|
|
35
|
+
pair-list 查看本工作站长期邀请的 ID 和截止时间
|
|
36
|
+
pair-revoke <邀请ID> 废止本工作站指定长期邀请
|
|
37
|
+
devices 查看本工作站配对授权及最后连接时间
|
|
38
|
+
device-revoke <授权ID> --confirm 撤销指定配对授权
|
|
39
|
+
dots-tasks 读取当前 ChatGPT 账号的 Dots 委派任务与最近轮次状态
|
|
40
|
+
维护指令:
|
|
41
|
+
setup 部署并启动桌面服务、Codex 内核和登录自启动;安全配置 Desktop 后续接入
|
|
42
|
+
setup --desktop-helper (Windows)同时安装受保护的桌面操作辅助服务,首次需要工作站 UAC 授权
|
|
43
|
+
desktop-helper-install (Windows)单独安装桌面操作辅助服务,保持现有桌面服务和 Codex 内核
|
|
44
|
+
desktop-helper-status (Windows)查看桌面操作辅助服务状态
|
|
45
|
+
desktop-helper-remove (Windows)移除桌面操作辅助服务,需要工作站 UAC 授权
|
|
46
|
+
doctor 简单检查工作站是否正常
|
|
47
|
+
diag 输出详细诊断报告,供客服或技术人员排查
|
|
48
|
+
kernel-restart --confirm 重启 Codex 内核并启用已选更新;等待新内核就绪
|
|
49
|
+
desktop-recover --confirm 重新打开 Desktop 并接入 Codex 内核;不强制重启已有内核
|
|
50
|
+
uninstall 停止并移除固定目录服务和本包 Skill,清理自有 Desktop 环境变量,保留其他配置与附件
|
|
51
|
+
默认监听 0.0.0.0,移动端与电脑需在同一受信任局域网。
|
|
52
|
+
--json 仅供安装脚本等程序调用。`;
|
|
53
|
+
|
|
54
|
+
function currentNodeExecutable() {
|
|
55
|
+
const link = process.env.NVM_SYMLINK && path.join(process.env.NVM_SYMLINK, 'node.exe');
|
|
56
|
+
if (link && fs.existsSync(link)) {
|
|
57
|
+
try {
|
|
58
|
+
if (fs.realpathSync(link).toLowerCase() === fs.realpathSync(process.execPath).toLowerCase()) return link;
|
|
59
|
+
} catch {}
|
|
60
|
+
}
|
|
61
|
+
return process.execPath;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function main() {
|
|
65
|
+
const [command, ...flags] = process.argv.slice(2);
|
|
66
|
+
if (!command || command === '--help' || command === '-h') {
|
|
67
|
+
console.log(help);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const options = flags.filter(flag => flag !== '--json');
|
|
71
|
+
const longPair = command === 'pair' && options.length === 2 && options[0] === '--expires';
|
|
72
|
+
const revokeInvite = command === 'pair-revoke' && options.length === 1 && /^[\w-]{16,128}$/.test(options[0]);
|
|
73
|
+
const revokeDevice = command === 'device-revoke' && options.length === 2 && /^[\w-]{16,128}$/.test(options[0]) && options[1] === '--confirm';
|
|
74
|
+
if (!['kernel-restart', 'desktop-recover', 'setup', 'doctor', 'diag', 'uninstall', 'start', 'pair', 'pair-list', 'pair-revoke', 'devices', 'device-revoke', 'dots-tasks', 'desktop-helper-install', 'desktop-helper-status', 'desktop-helper-remove'].includes(command)
|
|
75
|
+
|| (!longPair && !revokeInvite && !revokeDevice && (['pair-revoke', 'device-revoke'].includes(command) || options.some(flag => !((['kernel-restart', 'desktop-recover'].includes(command) && flag === '--confirm') || (command === 'setup' && flag === '--desktop-helper')))))) {
|
|
76
|
+
throw new Error('无效命令或参数。使用 --help 查看用法。');
|
|
77
|
+
}
|
|
78
|
+
const inviteExpires = longPair ? Date.parse(options[1]) : undefined;
|
|
79
|
+
if (longPair && (!/(Z|[+-]\d{2}:\d{2})$/.test(options[1]) || !Number.isSafeInteger(inviteExpires) || inviteExpires <= Date.now())) {
|
|
80
|
+
throw new Error('截止时间必须在未来且含时区,例如 2026-11-01T00:00:00+08:00。');
|
|
81
|
+
}
|
|
82
|
+
if (!['win32', 'darwin', 'linux'].includes(process.platform)) throw new Error('工作站目前支持 Windows、macOS 和 Linux。');
|
|
83
|
+
if (process.platform !== 'win32' && (command.startsWith('desktop-helper-') || options.includes('--desktop-helper')))
|
|
84
|
+
throw new Error('此平台不提供远程桌面画面、鼠标和键盘控制。');
|
|
85
|
+
if (command === 'desktop-recover' && desktopHost.desktopIntegration === false)
|
|
86
|
+
throw new Error('此平台的 Codex Desktop 自动接入尚未支持。');
|
|
87
|
+
const json = flags.includes('--json');
|
|
88
|
+
if (['desktop-helper-install', 'desktop-helper-status', 'desktop-helper-remove'].includes(command)) {
|
|
89
|
+
const result = command === 'desktop-helper-install' ? await installDesktopHelper() : command === 'desktop-helper-remove' ? await removeDesktopHelper() : await desktopHelperStatus();
|
|
90
|
+
console.log(json ? JSON.stringify(result) : result.removed ? '桌面操作辅助服务已移除。' : result.running ? '桌面操作辅助服务已就绪,手机可按需获取画面并确认点击。' : '桌面操作辅助服务尚未就绪,请运行 relax desktop-helper-install。');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (command === 'dots-tasks') {
|
|
94
|
+
const result = await readDotsTasks(managedAppServerUrl);
|
|
95
|
+
const statuses = { completed: '完成', inProgress: '进行中', failed: '失败', interrupted: '已中断' };
|
|
96
|
+
console.log(json ? JSON.stringify(result) : result.tasks.length
|
|
97
|
+
? result.tasks.map(task => `${task.title || task.id} — ${statuses[task.latestTurn?.status] || task.status || '暂无轮次'}\n${task.cwd || ''}`).join('\n\n')
|
|
98
|
+
: '当前账号没有未归档的 Dots 委派任务。');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const paths = runtimePaths();
|
|
102
|
+
const { stateRoot, serviceRoot } = paths;
|
|
103
|
+
const installedEntry = path.join(serviceRoot, 'dist/bin/codex-remote.mjs');
|
|
104
|
+
const installationPath = path.join(serviceRoot, 'installation.json');
|
|
105
|
+
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number);
|
|
106
|
+
const currentNodeSupported = nodeMajor > 22 || (nodeMajor === 22 && nodeMinor >= 12);
|
|
107
|
+
const installed = executableKey(fileURLToPath(import.meta.url)) === executableKey(installedEntry);
|
|
108
|
+
const installation = readRecord(installationPath);
|
|
109
|
+
if (installation?.nodeExecutable && !fs.existsSync(installation.nodeExecutable) && currentNodeSupported
|
|
110
|
+
&& ['start', 'pair', 'doctor'].includes(command)) {
|
|
111
|
+
writeRecord(installationPath, { ...installation, nodeExecutable: currentNodeExecutable() });
|
|
112
|
+
}
|
|
113
|
+
if (['kernel-restart', 'desktop-recover', 'start', 'pair', 'pair-list', 'pair-revoke', 'devices', 'device-revoke'].includes(command) && !installed) {
|
|
114
|
+
if (!fs.existsSync(installedEntry)) throw new Error('尚未部署服务,请先执行 relax setup。');
|
|
115
|
+
const executable = readRecord(installationPath)?.nodeExecutable;
|
|
116
|
+
if (!executable || !fs.existsSync(executable)) throw new Error('安装时选用的 Node 不存在,请重新执行 relax setup。');
|
|
117
|
+
const child = spawn(executable, [installedEntry, command, ...flags], { stdio: 'inherit', windowsHide: true });
|
|
118
|
+
const code = await new Promise((resolve, reject) => { child.once('error', reject); child.once('exit', resolve); });
|
|
119
|
+
process.exitCode = code ?? 1;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const service = lifecycle({ stateRoot, host });
|
|
123
|
+
const ensureAutostart = async () => {
|
|
124
|
+
const currentInstallation = readRecord(installationPath);
|
|
125
|
+
if (!currentInstallation?.nodeExecutable) throw new Error('请先执行 setup。');
|
|
126
|
+
const startup = { serviceRoot, nodeExecutable: currentInstallation.nodeExecutable };
|
|
127
|
+
const current = await residentStartup(startup, 'status');
|
|
128
|
+
if (current.enabled) return { ...current, repaired: false };
|
|
129
|
+
const result = await residentStartup(startup, 'enable');
|
|
130
|
+
return { ...result, repaired: true };
|
|
131
|
+
};
|
|
132
|
+
if (command === 'kernel-restart') {
|
|
133
|
+
if (!flags.includes('--confirm')) {
|
|
134
|
+
throw new Error('重启会立即结束当前 Codex 内核,正在运行的任务、待审批和未确认结果可能中断;恢复后不会自动重发。使用 --confirm 确认。');
|
|
135
|
+
}
|
|
136
|
+
const previous = await service.status();
|
|
137
|
+
if (!previous.running) throw new Error('桌面服务尚未运行,请先执行 relax start。');
|
|
138
|
+
await service.restartManagedAppServer(true);
|
|
139
|
+
const deadline = Date.now() + 60_000;
|
|
140
|
+
let current = await service.status();
|
|
141
|
+
while (current.managedAppServer?.restart?.status === 'running' && Date.now() < deadline) {
|
|
142
|
+
await delay(250);
|
|
143
|
+
current = await service.status();
|
|
144
|
+
}
|
|
145
|
+
if (current.managedAppServer?.restart?.status === 'failed') {
|
|
146
|
+
throw new Error(current.managedAppServer.restart.error || 'Codex 内核重启失败。');
|
|
147
|
+
}
|
|
148
|
+
if (!current.running || current.managedAppServer?.state !== 'ready'
|
|
149
|
+
|| current.managedAppServer?.restart?.status !== 'completed') {
|
|
150
|
+
throw new Error('Codex 内核未在 60 秒内完成重启,请运行 relax doctor 查看状态。');
|
|
151
|
+
}
|
|
152
|
+
if (previous.managedAppServer?.updatePending && current.managedAppServer.updatePending) {
|
|
153
|
+
throw new Error('Codex 内核已重启,但更新仍未应用;请运行 relax doctor 查看状态。');
|
|
154
|
+
}
|
|
155
|
+
const result = { status: 'completed', message: previous.managedAppServer?.updatePending
|
|
156
|
+
? 'Codex 内核已重启并应用更新。' : 'Codex 内核已重启。',
|
|
157
|
+
previousVersion: previous.managedAppServer?.version || null,
|
|
158
|
+
version: current.managedAppServer.version || null,
|
|
159
|
+
selectedVersion: current.managedAppServer.selectedVersion || null,
|
|
160
|
+
updateApplied: previous.managedAppServer?.updatePending === true,
|
|
161
|
+
updatePending: current.managedAppServer.updatePending === true,
|
|
162
|
+
pid: current.managedAppServer.pid || null,
|
|
163
|
+
executionReady: current.execution?.ready === true };
|
|
164
|
+
console.log(json ? JSON.stringify(result) : `${result.message}\n版本:${result.version || '未知'}\n执行状态:${result.executionReady ? '已就绪' : '正在恢复'}`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (command === 'desktop-recover') {
|
|
168
|
+
if (!flags.includes('--confirm')) throw new Error(recoveryWarning + ' 使用 --confirm 确认。');
|
|
169
|
+
const result = await requestRecovery(stateRoot, { confirmed: true });
|
|
170
|
+
console.log(json ? JSON.stringify(result) : `${result.message || result.status}${result.error ? '\n' + result.error : ''}\n${result.operationId || ''}`.trim());
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (command === 'devices' || command === 'device-revoke') {
|
|
174
|
+
const result = await selfRelay(command === 'devices' ? 'devices-list' : 'device-revoke', stateRoot,
|
|
175
|
+
command === 'device-revoke' ? { id: options[0], confirmed: true } : undefined);
|
|
176
|
+
console.log(json ? JSON.stringify(result) : result.displayText); return;
|
|
177
|
+
}
|
|
178
|
+
if (command === 'pair-list' || command === 'pair-revoke') {
|
|
179
|
+
const result = await selfRelay(command === 'pair-list' ? 'invite-list' : 'invite-revoke', stateRoot,
|
|
180
|
+
command === 'pair-revoke' ? { id: options[0] } : undefined);
|
|
181
|
+
console.log(json ? JSON.stringify(result) : result.displayText);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (command === 'pair') {
|
|
185
|
+
await ensureAutostart();
|
|
186
|
+
let bridge = await service.status();
|
|
187
|
+
if (!bridge.running) {
|
|
188
|
+
await service.start();
|
|
189
|
+
bridge = await service.status();
|
|
190
|
+
}
|
|
191
|
+
if (!bridge.running) throw new Error('Code Relax 工作站服务未能启动。');
|
|
192
|
+
if (longPair) await selfRelay('relay-start', stateRoot);
|
|
193
|
+
const result = await selfRelay(longPair ? 'invite-create' : 'relay-pair', stateRoot, longPair ? { expires: inviteExpires } : undefined);
|
|
194
|
+
if (!json && result.qrPath) {
|
|
195
|
+
openFile(result.qrPath);
|
|
196
|
+
}
|
|
197
|
+
console.log(json ? JSON.stringify(result) : `配对二维码已生成。\n${result.displayText}\n二维码文件:${result.qrPath}`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (command === 'doctor' || command === 'diag') {
|
|
201
|
+
const result = await doctor({ paths, host, service, ensureAutostart, diagnostics: command === 'diag' });
|
|
202
|
+
console.log(json ? JSON.stringify(result) : formatDoctorOutput(result, command === 'diag'));
|
|
203
|
+
if (!result.ready) process.exitCode = 1;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (command === 'uninstall') {
|
|
207
|
+
const desktopHelper = process.platform === 'win32' ? await removeDesktopHelper() : { removed: false, supported: false };
|
|
208
|
+
const skill = inspectSkill();
|
|
209
|
+
let environment;
|
|
210
|
+
const result = await uninstallService(paths, service, async () => {
|
|
211
|
+
environment = await clearManagedEnvironment(stateRoot);
|
|
212
|
+
const installation = readRecord(path.join(serviceRoot, 'installation.json'));
|
|
213
|
+
if (installation?.nodeExecutable) await removeDesktopShortcut({ serviceRoot, nodeExecutable: installation.nodeExecutable });
|
|
214
|
+
if (installation?.nodeExecutable) await residentStartup({ serviceRoot, nodeExecutable: installation.nodeExecutable }, 'disable');
|
|
215
|
+
});
|
|
216
|
+
result.environment = environment;
|
|
217
|
+
result.desktopHelper = desktopHelper;
|
|
218
|
+
result.skill = skill.managed ? removeSkill() : { removed: false, message: '未移除自定义或未安装的 Skill。' };
|
|
219
|
+
result.message = process.platform !== 'win32'
|
|
220
|
+
? '固定目录服务已卸载;配置、附件、钥匙串凭据和可能仍在执行任务的 Codex 内核已保留。'
|
|
221
|
+
: environment?.preserved
|
|
222
|
+
? '固定目录服务已卸载;检测到用户自定义的 CODEX_APP_SERVER_WS_URL,已保留。配置、附件和可能仍在执行任务的 app-server 也已保留;重启电脑可结束该进程。npm 命令入口可再用 npm uninstall -g @walkhi/code-relax 移除。'
|
|
223
|
+
: '固定目录服务已卸载;Code Relax 设置的 app-server 环境变量已清理,其他配置、附件和可能仍在执行任务的 app-server 已保留;重启电脑可结束该进程。npm 命令入口可再用 npm uninstall -g @walkhi/code-relax 移除。';
|
|
224
|
+
console.log(json ? JSON.stringify(result) : `${result.message}\n${result.skill.message}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (command === 'setup') {
|
|
228
|
+
prepareNativePackage(packageRoot(path.dirname(fileURLToPath(import.meta.url))));
|
|
229
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
230
|
+
if (major < 22 || (major === 22 && minor < 12)) throw new Error('需要 Node >=22.12。');
|
|
231
|
+
const physicalStateRoot = await resolveStateRoot(stateRoot);
|
|
232
|
+
// Preserve the effective package view; never replace a newer file already in it.
|
|
233
|
+
for (const name of ['bridge-config.json', 'bridge-session.json', 'bridge-startup-context.json',
|
|
234
|
+
'self-relay-config.json', 'self-relay-session.json', 'lan-device-authorizations.json',
|
|
235
|
+
'managed-app-server.json', 'managed-environment.json', 'shared-recovery.json', 'shared-recovery.lock']) {
|
|
236
|
+
const source = path.join(stateRoot, name), target = path.join(physicalStateRoot, name);
|
|
237
|
+
if (fs.existsSync(source) && !fs.existsSync(target)) fs.copyFileSync(source, target, fs.constants.COPYFILE_EXCL);
|
|
238
|
+
}
|
|
239
|
+
const hadInstalledService = fs.existsSync(path.join(serviceRoot, 'installation.json'));
|
|
240
|
+
const previousInstallation = readRecord(path.join(serviceRoot, 'installation.json'));
|
|
241
|
+
if (previousInstallation?.nodeExecutable) await removeDesktopShortcut({ serviceRoot, nodeExecutable: previousInstallation.nodeExecutable });
|
|
242
|
+
const desktopBeforeSetup = desktopHost.desktopIntegration === false ? { running: false, desktop: null } : await desktopHost.inspect();
|
|
243
|
+
const runtime = await resolveCodexRuntime(physicalStateRoot, { refresh: true });
|
|
244
|
+
const desktopNeedsAttach = desktopBeforeSetup.running && !await host.sharedServiceUrl();
|
|
245
|
+
const previous = hadInstalledService ? await service.status() : { processRunning: false };
|
|
246
|
+
const legacyRelaySession = readRecord(path.join(stateRoot, 'self-relay-session.json'));
|
|
247
|
+
const previousRelay = legacyRelaySession ? await controlRequest(legacyRelaySession) : await selfRelay('relay-status', stateRoot);
|
|
248
|
+
const resumeAfterUpdate = previous.processRunning || previousRelay.running;
|
|
249
|
+
const executable = currentNodeExecutable();
|
|
250
|
+
const startInstalled = async () => {
|
|
251
|
+
const entry = path.join(serviceRoot, 'dist/bin/codex-remote.mjs');
|
|
252
|
+
const child = spawn(executable, [entry, 'start', '--json'], { windowsHide: true, stdio: ['ignore', 'ignore', 'pipe'] });
|
|
253
|
+
let errors = '';
|
|
254
|
+
child.stderr.on('data', chunk => { errors += chunk; });
|
|
255
|
+
const code = await new Promise((resolve, reject) => { child.once('error', reject); child.once('exit', resolve); });
|
|
256
|
+
if (code) {
|
|
257
|
+
try { await selfRelay('relay-stop', stateRoot); } catch {}
|
|
258
|
+
try { await service.stop(); } catch {}
|
|
259
|
+
throw new Error(errors.trim().replace(/^(?:Code Relax:)+/u, '') || '桌面服务启动失败');
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
let stoppedForUpdate = false;
|
|
263
|
+
const installed = await installService(packageRoot(path.dirname(fileURLToPath(import.meta.url))), serviceRoot, executable, physicalStateRoot, {
|
|
264
|
+
beforeActivate: async () => {
|
|
265
|
+
if (desktopNeedsAttach) await desktopHost.closeDesktop(desktopBeforeSetup.desktop);
|
|
266
|
+
stoppedForUpdate = resumeAfterUpdate;
|
|
267
|
+
if (previousRelay.running && legacyRelaySession) {
|
|
268
|
+
await controlRequest(legacyRelaySession, 'POST');
|
|
269
|
+
const deadline = Date.now() + 10000;
|
|
270
|
+
while (processAlive(legacyRelaySession.pid)) {
|
|
271
|
+
if (Date.now() >= deadline) throw new Error('旧中继进程未在 10 秒内退出。');
|
|
272
|
+
await delay(100);
|
|
273
|
+
}
|
|
274
|
+
} else if (previousRelay.running) await selfRelay('relay-stop', stateRoot);
|
|
275
|
+
if (previous.processRunning) await service.stop();
|
|
276
|
+
},
|
|
277
|
+
verifyActivation: async () => { await startInstalled(); },
|
|
278
|
+
restoreActivation: async () => { if (stoppedForUpdate) await startInstalled(); },
|
|
279
|
+
});
|
|
280
|
+
const autostart = await residentStartup(installed, 'enable');
|
|
281
|
+
const deadline = Date.now() + 35_000;
|
|
282
|
+
let bridge = await service.status();
|
|
283
|
+
while (bridge.running && !['ready', 'failed'].includes(bridge.managedAppServer?.state) && Date.now() < deadline) {
|
|
284
|
+
await delay(250);
|
|
285
|
+
bridge = await service.status();
|
|
286
|
+
}
|
|
287
|
+
if (!bridge.running || bridge.managedAppServer?.state !== 'ready') {
|
|
288
|
+
throw new Error(bridge.managedAppServer?.error || '桌面服务已安装,但 Codex 内核未就绪;未写入 Desktop 环境变量。');
|
|
289
|
+
}
|
|
290
|
+
const environment = desktopBeforeSetup.desktop
|
|
291
|
+
? await configureManagedEnvironment(physicalStateRoot) : { configured: false, reason: desktopHost.desktopIntegration === false ? 'desktop-integration-unsupported' : 'desktop-not-installed' };
|
|
292
|
+
let managedAppServerMigrated = false;
|
|
293
|
+
const managedAppServerMigration = {
|
|
294
|
+
required: bridge.managedAppServer.launcherRestartRequired === true,
|
|
295
|
+
restarted: false,
|
|
296
|
+
previousPid: bridge.managedAppServer.pid || null,
|
|
297
|
+
};
|
|
298
|
+
let desktopRestarted = false;
|
|
299
|
+
let desktopRestartReason = null;
|
|
300
|
+
if (managedAppServerMigration.required) {
|
|
301
|
+
const desktopInfo = desktopHost.desktopIntegration === false ? { running: false } : await desktopHost.inspect();
|
|
302
|
+
const desktopAttached = desktopInfo.running
|
|
303
|
+
&& (bridge.desktop?.attachedToManagedServer === true || Boolean(await host.sharedServiceUrl()));
|
|
304
|
+
if (desktopAttached) await desktopHost.closeDesktop(desktopInfo.desktop);
|
|
305
|
+
await service.restartManagedAppServer();
|
|
306
|
+
const migrationDeadline = Date.now() + 40_000;
|
|
307
|
+
do {
|
|
308
|
+
await delay(250);
|
|
309
|
+
bridge = await service.status();
|
|
310
|
+
if (bridge.managedAppServer?.restart?.status === 'failed') {
|
|
311
|
+
throw new Error(bridge.managedAppServer.restart.error || 'Codex 内核启动链迁移失败。');
|
|
312
|
+
}
|
|
313
|
+
} while (Date.now() < migrationDeadline && (!bridge.running || bridge.managedAppServer?.state !== 'ready' || bridge.managedAppServer.launcherRestartRequired));
|
|
314
|
+
if (!bridge.running || bridge.managedAppServer?.state !== 'ready' || bridge.managedAppServer.launcherRestartRequired) {
|
|
315
|
+
throw new Error('Codex 内核未在 40 秒内完成启动链迁移。');
|
|
316
|
+
}
|
|
317
|
+
managedAppServerMigrated = true;
|
|
318
|
+
managedAppServerMigration.restarted = true;
|
|
319
|
+
if (desktopAttached) {
|
|
320
|
+
await launchDesktop({ stateRoot: physicalStateRoot, host: desktopHost });
|
|
321
|
+
desktopRestarted = true;
|
|
322
|
+
desktopRestartReason = 'app-server-migration';
|
|
323
|
+
bridge = await service.status();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const skill = installSkill(path.join(serviceRoot, 'dist/skills/code-relax/SKILL.md'));
|
|
327
|
+
if (desktopNeedsAttach && !desktopRestarted) {
|
|
328
|
+
const currentDesktop = await desktopHost.inspect();
|
|
329
|
+
if (currentDesktop.running) await desktopHost.closeDesktop(currentDesktop.desktop);
|
|
330
|
+
await launchDesktop({ stateRoot: physicalStateRoot, host: desktopHost });
|
|
331
|
+
desktopRestarted = true;
|
|
332
|
+
desktopRestartReason = 'attach-managed-server';
|
|
333
|
+
bridge = await service.status();
|
|
334
|
+
}
|
|
335
|
+
installed.autostart = autostart;
|
|
336
|
+
installed.skill = skill;
|
|
337
|
+
installed.restarted = resumeAfterUpdate;
|
|
338
|
+
installed.environment = environment;
|
|
339
|
+
installed.managedAppServer = bridge.managedAppServer;
|
|
340
|
+
installed.codexRuntime = runtime;
|
|
341
|
+
installed.managedAppServerMigrated = managedAppServerMigrated;
|
|
342
|
+
installed.managedAppServerMigration = { ...managedAppServerMigration,
|
|
343
|
+
currentPid: bridge.managedAppServer.pid || null,
|
|
344
|
+
launcherRevision: bridge.managedAppServer.launcherRevision ?? null };
|
|
345
|
+
installed.desktopRestarted = desktopRestarted;
|
|
346
|
+
installed.desktopRestartReason = desktopRestartReason;
|
|
347
|
+
if (options.includes('--desktop-helper')) installed.desktopHelper = await installDesktopHelper();
|
|
348
|
+
const migrationText = managedAppServerMigrated ? 'Codex 内核已更新并重启;请检查安装前正在进行的任务。\n' : '';
|
|
349
|
+
const displayText = `Code Relax ${installed.version} 安装成功。\n${migrationText}${desktopSetupSteps.join('\n')}`;
|
|
350
|
+
console.log(json ? JSON.stringify({ ...installed, nextSteps: desktopSetupSteps, displayText }) : displayText);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (!json && command === 'start') console.log('正在检查电脑连接并准备桌面服务…');
|
|
354
|
+
await ensureAutostart();
|
|
355
|
+
const result = await service[command]();
|
|
356
|
+
const { accessUrl, qrPath: _legacyQrPath, ...metadata } = result;
|
|
357
|
+
let relay;
|
|
358
|
+
if (fs.existsSync(path.join(stateRoot, 'self-relay-config.json'))) relay = await selfRelay('relay-status', stateRoot);
|
|
359
|
+
const nextSteps = phonePairingSteps(metadata.transportMode, relay?.paired === true);
|
|
360
|
+
const displayText = pairingDisplayText(nextSteps);
|
|
361
|
+
const output = { ...metadata, ...(relay ? { relayConnected: relay.relayConnected,
|
|
362
|
+
paired: relay.paired, clientCount: relay.clientCount, ...(relay.qrPath ? { qrPath: relay.qrPath, expiresAt: relay.expiresAt } : {}) } : {}),
|
|
363
|
+
nextSteps, displayText, mode: 'lan', listenAddress: '0.0.0.0', address: new URL(accessUrl).host };
|
|
364
|
+
if (json) console.log(JSON.stringify(output));
|
|
365
|
+
else {
|
|
366
|
+
if (relay?.qrPath) console.log(`配对二维码:${relay.qrPath}`);
|
|
367
|
+
console.log(displayText);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
main().catch(error => {
|
|
372
|
+
console.error(`Code Relax:${error.message}`);
|
|
373
|
+
process.exitCode = 1;
|
|
374
|
+
});
|