codexunlimit 0.1.0-web.13 → 0.1.0-web.16
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 +97 -79
- package/cli.mjs +2 -110
- package/codex-desktop.ps1 +85 -0
- package/package.json +32 -14
- package/runtime.mjs +1 -0
- package/shared-ZNBXOIRW.mjs +1 -0
- package/web/app.js +1 -154
- package/web/privacy.html +1 -0
- package/web/style.css +5 -0
- package/account-pool.mjs +0 -161
- package/app.mjs +0 -161
- package/codex-account-client.mjs +0 -53
- package/config.mjs +0 -224
- package/doctor.mjs +0 -20
- package/image-http.mjs +0 -22
- package/io.mjs +0 -5
- package/license-client.mjs +0 -153
- package/product.mjs +0 -5
- package/protocol.mjs +0 -28
- package/quota.mjs +0 -34
- package/relay.mjs +0 -156
- package/state.mjs +0 -33
- package/updates.mjs +0 -47
- package/web/markdown.js +0 -15
- package/web/messages.js +0 -68
- package/web/pool-ui.js +0 -53
- package/web/stream.js +0 -25
- package/web/updates.js +0 -26
- package/windows.mjs +0 -53
package/README.md
CHANGED
|
@@ -1,82 +1,100 @@
|
|
|
1
|
-
# Codex Unlimit ·
|
|
2
|
-
|
|
3
|
-
Cài một gói trên Windows hoặc macOS,
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
codexunlimit
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
npm
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
# Codex Unlimit · Thiết lập nhanh trong terminal
|
|
2
|
+
|
|
3
|
+
Cài một gói trên Windows hoặc macOS, nhập key trong terminal và bắt đầu dùng Codex. Hỗ trợ Node.js 22 từ 22.15.0, hoặc Node.js 24 trở lên.
|
|
4
|
+
|
|
5
|
+
## Key từ nhà cung cấp · web.16
|
|
6
|
+
|
|
7
|
+
Cài và nhập key như bình thường. Với key do reseller cung cấp, liên hệ người bán để được hỗ trợ hoặc gia hạn. Mục Quyền riêng tư có sẵn trên máy; cập nhật bằng `npm i -g codexunlimit`. Key mua trực tiếp trên website vẫn dùng các liên kết quản lý hiện có.
|
|
8
|
+
|
|
9
|
+
## Nhập key và áp dụng ngay trong terminal · web.15
|
|
10
|
+
|
|
11
|
+
Lần đầu chạy `codexunlimit` trong PowerShell hoặc Terminal, ứng dụng tự mở luồng thiết lập. Nhập key ở ô ẩn; nếu đã đăng nhập ChatGPT trong Codex, chỉ cần lưu công việc rồi xác nhận áp dụng. Chương trình sao lưu cấu hình, bật kết nối và yêu cầu Codex đóng/mở lại. Không tự mở web trong luồng này.
|
|
12
|
+
|
|
13
|
+
Nếu chưa đăng nhập ChatGPT, Codex được mở để bạn đăng nhập; quay lại terminal và nhấn Enter để tiếp tục. Không nhập mật khẩu ChatGPT tại đây. Có thể hủy bằng Ctrl+C hoặc q; các bước đã lưu được giữ. Một thao tác đóng/mở đã gửi có thể vẫn hoàn tất.
|
|
14
|
+
|
|
15
|
+
Chạy lại thiết lập bằng `codexunlimit setup`. Mở trang quản lý, chat và quota sau bằng `codexunlimit web`. Lệnh `setup` cần terminal tương tác và không nhận key qua tham số hay pipe. Không tự bật khởi động cùng máy; tùy chọn đó vẫn ở khay/cài đặt.
|
|
16
|
+
|
|
17
|
+
## Thiết lập Codex trên trang web · web.14
|
|
18
|
+
|
|
19
|
+
Trang chủ ưu tiên nhập key, kết nối tài khoản ChatGPT và áp dụng cấu hình Codex. Các bước còn thiếu hoặc cấu hình bị thay đổi được hiển thị ngay trên trang. Hoàn tất key và tài khoản, lưu công việc đang làm rồi chọn **Cấu hình & mở lại Codex**. Có thể bỏ chọn tự mở lại để chỉ lưu cấu hình.
|
|
20
|
+
|
|
21
|
+
Các nút **Mở Codex**, **Mở lại Codex** và **Đóng Codex** điều khiển ứng dụng desktop được nhận diện trên máy; không đóng Codex CLI hoặc extension. Khi Codex chưa chấp nhận đóng, ứng dụng dừng thao tác và hướng dẫn xử lý, không ép tắt. Nếu không tìm thấy ứng dụng hoặc hệ điều hành chưa hỗ trợ, lưu cấu hình rồi mở lại Codex thủ công. **Tắt kết nối Codex Unlimit** khôi phục cấu hình gốc, kể cả khi key đã hết hạn. Chat trên web vẫn ở mục **Trò chuyện**.
|
|
22
|
+
|
|
23
|
+
## Sửa thông báo kích hoạt · web.13
|
|
24
|
+
|
|
25
|
+
Phân biệt lỗi ngày giờ máy khách, phản hồi xác thực không hợp lệ và key bị máy chủ từ chối. Khi admin đã ghi nhận kích hoạt nhưng máy khách báo lỗi ngày giờ, đồng bộ lại ngày giờ tự động, khởi động lại Codex Unlimit và nhập lại cùng key. Kích hoạt lại trên cùng thiết bị với dữ liệu ứng dụng còn nguyên không tăng số thiết bị hay tính lại thời hạn. Key hết hạn hoặc bị thu hồi thật vẫn bị chặn.
|
|
26
|
+
|
|
27
|
+
## Cài và thiết lập
|
|
28
|
+
|
|
29
|
+
Mở PowerShell (Windows) hoặc Terminal (macOS/Linux). Cài và bắt đầu thiết lập bằng hai dòng:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm i -g codexunlimit
|
|
33
|
+
codexunlimit
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Lần đầu, nhập key ngay trong terminal theo hướng dẫn. Khi được hỏi, lưu công việc rồi nhấn Enter để đồng ý kết nối, lưu cấu hình và mở lại Codex. Nếu máy chưa hỗ trợ mở lại tự động, terminal báo rõ bước cần làm thủ công. Web local là tùy chọn: chạy `codexunlimit web` khi muốn xem trạng thái hoặc chat.
|
|
37
|
+
|
|
38
|
+
Trên Windows, có thể dùng `npm.cmd` và `codexunlimit.cmd` nếu PowerShell chặn file `.ps1`.
|
|
39
|
+
|
|
40
|
+
Trang cài đặt công bố nguồn đang có hiệu lực. Khi gói chính thức trên npmjs đã được xác nhận tại đó, có thể dùng `npm i -g codexunlimit` hoặc thêm `@0.1.0-web.8` để cố định phiên bản. URL sản phẩm vẫn là phương án dự phòng. Không coi tên trần trên registry là chính thức trước thông báo xuất bản. Gói không có hook cài đặt tự chạy. Cần Node/npm có sẵn; không tải/chạy PowerShell từ web hay yêu cầu bộ cài .exe riêng. Kiểm tra môi trường bằng `codexunlimit doctor` (hoặc `--json`); lệnh không đọc token ChatGPT.
|
|
41
|
+
|
|
42
|
+
## Ảnh và độ ổn định · web.7
|
|
43
|
+
|
|
44
|
+
Công cụ ImageGen gốc của Codex có thể gửi tạo/sửa ảnh qua `/v1/images/generations` và `/v1/images/edits` (cũng hỗ trợ đường dẫn không có `/v1`). Ảnh không đi qua luồng xử lý văn bản/SSE. Tài khoản đã chọn được giữ cho từng request; gateway không tự tạo lại ảnh hoặc đổi tài khoản khi upstream lỗi. Quyền tạo ảnh và quota vẫn do tài khoản upstream quyết định. Đây không phải nút tạo ảnh mới trong chat local và không phải API key OpenAI công khai.
|
|
45
|
+
|
|
46
|
+
Lỗi mạng khi gia hạn lease tạm thời trả 503/429, không tự kết luận key hết hạn. Lease còn hạn vẫn được dùng trong khi thử gia hạn; lease hết hạn không được dùng để vượt kiểm tra. Server từ chối/thu hồi thật vẫn có hiệu lực. Phản hồi HTML từ proxy được đổi thành lỗi JSON ngắn, có hướng dẫn chờ, không tự gửi lại request tốn quota.
|
|
47
|
+
|
|
48
|
+
Trước khi cập nhật, hoàn tất tác vụ, cài lại bằng lệnh npm đang công bố rồi chạy `codexunlimit restart`. Khởi động lại theo cách này giữ cấu hình kết nối, key/pool/hội thoại. Nếu npm báo file đang được dùng, chọn **Dừng để cập nhật** trong ứng dụng rồi cài lại. Với bản từ URL riêng chưa có công bố npmjs, không dùng `npm update -g codexunlimit` theo tên trần.
|
|
49
|
+
|
|
50
|
+
Nếu đã dùng bộ cài quản lý trước đây, không cần cài chồng: dùng `codexunlimit update` của bộ cài đó. Muốn chuyển hẳn sang npm, chuẩn bị Node/npm trước, gỡ bộ cài cũ bằng lệnh `uninstall` của nó (giữ dữ liệu), rồi cài npm. Tránh để hai launcher cùng tên trong PATH khiến mở nhầm phiên bản.
|
|
51
|
+
|
|
52
|
+
## Tài khoản, quota và Markdown
|
|
53
|
+
|
|
54
|
+
Mở **Tài khoản & quota** trong trang local để xem mức sử dụng 5 giờ/1 tuần, thời điểm reset và lần cập nhật của từng tài khoản. Nút **Cập nhật quota** đọc hạn mức qua công cụ đăng nhập Codex, không gửi tin nhắn. Phản hồi chat/Codex cũng cập nhật số liệu local và bảng quota admin/khách online hiện có. Nếu chưa có dữ liệu hoặc dữ liệu đã cũ, giao diện ghi rõ; không suy thành 0%.
|
|
55
|
+
|
|
56
|
+
Chọn **Thêm tài khoản**, đồng ý sử dụng phiên và mở trang đăng nhập OpenAI. Có thể dùng đăng nhập bằng mã nếu cần. Mỗi tài khoản có phiên riêng, tối đa 10 tài khoản lưu thêm; không thay đổi phiên gốc trong Codex. Sau lần đăng nhập đầu, chọn **Dùng tài khoản này** hoặc chọn ở đầu trang chat. Lựa chọn áp dụng cho yêu cầu mới; yêu cầu đang chạy giữ tài khoản ban đầu. Khi hết quota, ứng dụng báo giới hạn và không tự gửi lại qua tài khoản khác.
|
|
57
|
+
|
|
58
|
+
Phiên trong pool được mã hóa bằng AES-GCM với khóa rút từ khóa thiết bị. Trên Windows, khóa thiết bị được bảo vệ bằng DPAPI của người dùng. Công cụ Codex chỉ dùng file phiên tạm trong thư mục riêng khi đăng nhập/làm mới và file được xóa khi tác vụ kết thúc. Token không được trả cho trang web, không ghi log và không gửi về server quản lý; yêu cầu xử lý vẫn gửi access token cần thiết qua gateway như trước. Tài khoản gốc được liên kết chỉ cung cấp access token tạm thời để đọc quota, không sao chép/luân chuyển refresh token của Codex gốc.
|
|
59
|
+
|
|
60
|
+
Gói npm tự cài thêm `@openai/codex` 0.166.0 cùng binary đúng hệ điều hành và `markdown-it` 15.0.3. Cần kết nối npm registry khi cài; không dùng `--omit=optional` vì sẽ thiếu binary đăng nhập. Dung lượng tải thực tế bao gồm các dependency, không chỉ file `.tgz` của Codex Unlimit.
|
|
61
|
+
|
|
62
|
+
Câu trả lời chat hỗ trợ Markdown khi nhận từng phần và khi mở lại lịch sử: tiêu đề, chữ đậm/nghiêng, danh sách, trích dẫn, bảng, liên kết và khối mã có nút sao chép. HTML thô không được thực thi, liên kết script bị chặn và ảnh bên ngoài không tự tải.
|
|
63
|
+
|
|
64
|
+
## Khay Windows và tắt ứng dụng
|
|
65
|
+
|
|
66
|
+
Từ web.5, biểu tượng CU xuất hiện trong khay Windows khi ứng dụng chạy; có thể nằm trong dấu mũi tên lên ở thanh tác vụ. Nhấp đúp để mở trang, nhấp phải để chọn **Mở Codex Unlimit**, **Khởi động cùng Windows**, **Khởi động lại**, hoặc **Tắt ứng dụng**. Tự khởi động mặc định tắt; khi bật, chỉ chạy nền trong khay, không mở trình duyệt.
|
|
67
|
+
|
|
68
|
+
**Cài đặt & hỗ trợ → Ứng dụng trên máy** cũng có công tắc khởi động cùng Windows, nút hiện lại biểu tượng khay, hướng dẫn cập nhật và nút tắt. Đóng tab không dừng dịch vụ. **Tắt ứng dụng** hoặc `codexunlimit stop` khôi phục cấu hình Codex do bản này quản lý trước khi dừng, giữ key và dữ liệu. Nếu cấu hình bị bên khác chỉnh sửa, thao tác dừng sẽ báo rõ xung đột thay vì ghi đè.
|
|
69
|
+
|
|
70
|
+
`codexunlimit startup on` / `codexunlimit startup off` bật/tắt shortcut trong Startup của tài khoản Windows hiện tại; không cần quyền quản trị. `codexunlimit restart` khởi động lại. macOS/Linux vẫn dùng lệnh mở và tắt; bản này chưa có khay hay tự khởi động cho hai nền tảng đó.
|
|
71
|
+
|
|
72
|
+
## Cập nhật và xử lý kết nối
|
|
73
|
+
|
|
74
|
+
Cài gói mới rồi chạy `codexunlimit`: CLI xác minh phiên web đang chạy bằng khóa điều khiển của cùng thư mục dữ liệu, dừng phiên khác phiên bản và mở bản mới. Giữ cấu hình, key và dữ liệu trong lần chuyển này. Không dừng dịch vụ lạ đang chiếm cổng. Với web.1 chưa có giao thức xác minh phiên, chạy `codexunlimit stop` trước. Bản native cũ cần khôi phục kết nối và thoát từ chính bản đó.
|
|
75
|
+
|
|
76
|
+
**Dừng để cập nhật** trong phần mở rộng của cài đặt sẽ giữ cấu hình nhưng dừng dịch vụ; Codex tạm thời mất kết nối cho tới khi mở bản mới. Gỡ ứng dụng: tắt **Khởi động cùng Windows**, chọn **Tắt ứng dụng**, rồi chạy `npm uninstall -g codexunlimit`. Dữ liệu riêng vẫn được giữ.
|
|
77
|
+
|
|
78
|
+
Khi không kết nối được, chọn **Kiểm tra kết nối**. Trang phân biệt key, tài khoản và cấu hình; profile riêng, cấu hình native, quyền ghi và bản sao khôi phục hỏng có hướng xử lý cụ thể. Nếu Codex đã reset cấu hình về trực tiếp, **Kết nối lại với Codex** tạo lại kết nối và sao lưu cấu hình hiện tại. Không tự sửa cấu hình đang được ứng dụng khác quản lý.
|
|
79
|
+
|
|
80
|
+
## Dữ liệu và tương thích
|
|
81
|
+
|
|
82
|
+
- Cổng local mặc định `18457`. Để được hỗ trợ hoặc gia hạn, liên hệ nơi đã cung cấp key cho bạn.
|
|
83
|
+
- Dữ liệu web ở `%LOCALAPPDATA%/CodexunlimitWeb` trên Windows, `~/Library/Application Support/CodexunlimitWeb` trên macOS. Khóa thiết bị dùng DPAPI trên Windows; file riêng tư theo quyền người dùng trên macOS/Linux.
|
|
84
|
+
- Lịch sử chat ở trình duyệt này, tối đa 30 cuộc / 100 tin mỗi cuộc. Khi gửi tin, nội dung và mã truy cập đi qua dịch vụ Codex Unlimit; server không lưu nội dung chat hoặc mã truy cập. Refresh token do Codex quản lý.
|
|
85
|
+
- Gói web dùng kích hoạt thiết bị riêng. Nếu chuyển từ native, khôi phục kết nối và dừng bản native trước; quản trị viên có thể giải phóng slot cũ. Không tự chuyển khóa Keychain/DPAPI từ ứng dụng native.
|
|
86
|
+
- Chat sử dụng phiên ChatGPT từ Codex; khi hết phiên, đăng nhập lại trong Codex. Chưa có đăng nhập ChatGPT độc lập trong web.
|
|
87
|
+
- Không yêu cầu Authenticode hoặc Apple Developer ID để chạy gói Node; xác minh license và chữ ký request vẫn thực hiện. Policy luôn ở server.
|
|
88
|
+
|
|
89
|
+
## Kiểm tra / đóng gói từ repository
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npm run start:local
|
|
93
|
+
npm run pack:local
|
|
94
|
+
npm test
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`pack:local` chỉ đóng gói thư mục connector theo allowlist; không lấy mã server/engine hoặc dữ liệu vận hành. Package đang private để tránh phát hành nhầm lên npm. Sau khi được phân phối, khách có thể cài trực tiếp từ URL gói tải; không cần public server source.
|
|
80
98
|
|
|
81
99
|
### Kiểm tra phiên bản và cập nhật
|
|
82
100
|
|
package/cli.mjs
CHANGED
|
@@ -1,110 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import crypto from 'node:crypto';
|
|
6
|
-
import {spawn} from 'node:child_process';
|
|
7
|
-
import {fileURLToPath} from 'node:url';
|
|
8
|
-
import {ClientState} from './state.mjs';
|
|
9
|
-
import {LicenseClient} from './license-client.mjs';
|
|
10
|
-
import {createConnector} from './relay.mjs';
|
|
11
|
-
import {createLocalApp,createBrowserTicket,readCodexAccount} from './app.mjs';
|
|
12
|
-
import {AccountPool} from './account-pool.mjs';
|
|
13
|
-
import {DEFAULT_PORT,VERSION} from './product.mjs';
|
|
14
|
-
import {unsyncCodex,migrateCodexTransport} from './config.mjs';
|
|
15
|
-
import {createWindowsIntegration} from './windows.mjs';
|
|
16
|
-
import {errors} from './web/messages.js';
|
|
17
|
-
import {diagnoseRuntime} from './doctor.mjs';
|
|
18
|
-
|
|
19
|
-
const args=process.argv.slice(2),command=args[0]&&!args[0].startsWith('--')?args[0]:'open';
|
|
20
|
-
function option(name,fallback){const i=args.indexOf(name);if(i<0)return fallback;if(!args[i+1]||args[i+1].startsWith('--'))throw Error('Thiếu giá trị cho '+name);return args[i+1];}
|
|
21
|
-
const home=path.resolve(option('--home',process.platform==='win32'?path.join(process.env.LOCALAPPDATA??path.join(os.homedir(),'AppData/Local'),'CodexunlimitWeb'):process.platform==='darwin'?path.join(os.homedir(),'Library/Application Support/CodexunlimitWeb'):path.join(os.homedir(),'.local/share/codexunlimit')));
|
|
22
|
-
async function main(){
|
|
23
|
-
if(args.includes('--version')){console.log(VERSION);return;}
|
|
24
|
-
if(command==='doctor'){
|
|
25
|
-
const result=await diagnoseRuntime();if(args.includes('--json'))console.log(JSON.stringify(result));else{for(const check of result.checks)console.log((check.ok?'OK ':'THIẾU ')+check.name+(check.version?' '+check.version:''));console.log(result.ok?'Môi trường đã sẵn sàng. Key/tài khoản được kiểm tra trong ứng dụng.':'Cài lại gói npm, giữ dependency tùy chọn. Không cần xóa key, đăng xuất ChatGPT hoặc reset thiết bị.');}if(!result.ok)process.exitCode=1;return;
|
|
26
|
-
}
|
|
27
|
-
if(args.includes('--help')){console.log('Codex Unlimit\n codexunlimit diagnostics Xuất log kết nối đã loại thông tin riêng tư\n codexunlimit doctor Kiểm tra Node, SQLite và Codex runtime\n codexunlimit Mở ứng dụng và khay Windows\n codexunlimit stop Khôi phục kết nối Codex và tắt ứng dụng\n codexunlimit restart Khởi động lại bằng bản đã cài mới nhất\n codexunlimit startup on Tự mở trong khay khi đăng nhập Windows\n codexunlimit startup off Tắt khởi động cùng Windows\n codexunlimit --no-open Chạy nền, không mở trình duyệt\n --no-tray Không mở khay (dành cho kiểm thử)\n --home <thư mục> Dữ liệu riêng\n --port <số cổng> Cổng cho lần cài đầu');return;}
|
|
28
|
-
if(!['open','serve','stop','restart','startup','diagnostics'].includes(command))throw Error('Lệnh chưa đúng. Xem codexunlimit --help');
|
|
29
|
-
const state=new ClientState(home);let serving=false;
|
|
30
|
-
try{
|
|
31
|
-
if(command==='diagnostics'){console.log(JSON.stringify({version:VERSION,requests:state.diagnostics()},null,2));return;}
|
|
32
|
-
const port=Number(option('--port',DEFAULT_PORT));if(!Number.isInteger(port)||port<1024||port>65535)throw Error('Cổng cần nằm trong khoảng 1024–65535.');
|
|
33
|
-
state.initialize({port,codexHome:state.get('codex_home')??process.env.CODEX_HOME??path.join(os.homedir(),'.codex')});
|
|
34
|
-
const desktop=createWindowsIntegration(state);
|
|
35
|
-
if(command==='startup'){
|
|
36
|
-
if(!['on','off'].includes(args[1]))throw Error('Dùng codexunlimit startup on hoặc codexunlimit startup off.');
|
|
37
|
-
await desktop.setStartup(args[1]==='on');console.log(args[1]==='on'?'Đã bật khởi động cùng Windows.':'Đã tắt khởi động cùng Windows.');return;
|
|
38
|
-
}
|
|
39
|
-
const base='http://127.0.0.1:'+state.settings.get('relay.port');
|
|
40
|
-
async function health(){try{const r=await fetch(base+'/healthz',{signal:AbortSignal.timeout(1000)});return await r.json();}catch{return null;}}
|
|
41
|
-
async function ownInstance(){
|
|
42
|
-
const nonce=crypto.randomBytes(24).toString('hex'),expected=crypto.createHmac('sha256',state.get('control_token')).update('cu-instance:'+nonce).digest('hex');
|
|
43
|
-
const response=await fetch(base+'/control/identity',{headers:{'x-cu-nonce':nonce},signal:AbortSignal.timeout(1500)});
|
|
44
|
-
const value=await response.json();if(value.proof!==expected)throw Error('Cổng đang chạy một phiên khác. Dừng bản cũ trước hoặc chọn cổng khác.');
|
|
45
|
-
}
|
|
46
|
-
if(command==='serve'){
|
|
47
|
-
const license=new LicenseClient(state);
|
|
48
|
-
const pool=new AccountPool(state,{privateKey:license.device.privateKey,defaultAccount:()=>readCodexAccount(state)});
|
|
49
|
-
const server=createConnector(state,{license,pool,localApp:createLocalApp(state,{license,desktop,pool,onStop:shutdown}),prepareStop:mode=>{if(mode==='exit')unsyncCodex(state);},onStop:shutdown});
|
|
50
|
-
let stopping=false;
|
|
51
|
-
function shutdown(){if(stopping)return;stopping=true;server.close(async()=>{try{await pool.close();}finally{state.close();process.exit(0);}});server.closeIdleConnections();setTimeout(()=>server.closeAllConnections(),1500).unref();}
|
|
52
|
-
server.listen(state.settings.get('relay.port'),'127.0.0.1');await new Promise((resolve,reject)=>{server.once('listening',resolve);server.once('error',reject);});
|
|
53
|
-
try{migrateCodexTransport(state);}catch(error){console.error(errors[error.message]??errors.operation_failed);}
|
|
54
|
-
serving=true;process.once('SIGINT',shutdown);process.once('SIGTERM',shutdown);
|
|
55
|
-
if(desktop.status().startup)desktop.setStartup(true).catch(()=>console.error(errors.startup_update_failed));
|
|
56
|
-
if(process.platform==='win32'&&!args.includes('--no-tray'))desktop.showTray().catch(()=>console.error(errors.tray_unavailable));
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
let existing=await health();
|
|
60
|
-
if(existing&&(existing.service!=='codexunlimit-connector'||existing.mode!=='desktop'))throw Error('Cổng đang được ứng dụng khác sử dụng. Hãy chọn --port khác với --home riêng.');
|
|
61
|
-
// Compatibility for customers who installed the update before stopping web.1.
|
|
62
|
-
if(existing&&!(command==='stop'&&existing.version==='0.1.0-web.1'))await ownInstance();
|
|
63
|
-
async function stopInstance(mode){
|
|
64
|
-
if(mode==='exit')unsyncCodex(state);
|
|
65
|
-
if(!existing)return;
|
|
66
|
-
const response=await fetch(base+'/control/stop',{method:'POST',headers:{'x-cu-control':state.get('control_token'),'x-cu-stop-mode':mode},signal:AbortSignal.timeout(5000)});
|
|
67
|
-
if(!response.ok)throw Error('Chưa tắt được phiên đang chạy. Mở Cài đặt & hỗ trợ để kiểm tra kết nối.');
|
|
68
|
-
for(let attempt=0;attempt<50;attempt++){
|
|
69
|
-
if(!await health()){existing=null;return;}
|
|
70
|
-
await new Promise(resolve=>setTimeout(resolve,100));
|
|
71
|
-
}
|
|
72
|
-
throw Error('Phiên cũ chưa tắt hoàn toàn. Chờ một lát rồi mở lại Codex Unlimit.');
|
|
73
|
-
}
|
|
74
|
-
if(command==='stop'){await stopInstance('exit');console.log('Codex Unlimit đã tắt. Kết nối Codex đã được khôi phục.');return;}
|
|
75
|
-
if(existing&&(command==='restart'||existing.version!==VERSION)){
|
|
76
|
-
console.log('Đang khởi động lại Codex Unlimit '+VERSION+'…');await stopInstance('update');
|
|
77
|
-
}
|
|
78
|
-
if(existing){const page=await fetch(base+'/app/',{signal:AbortSignal.timeout(2000)});if(!page.ok)throw Error('Bản cũ đang chạy. Dừng Codex Unlimit cũ trước khi mở phiên bản web.');}
|
|
79
|
-
else{
|
|
80
|
-
const logs=path.join(home,'logs');fs.mkdirSync(logs,{recursive:true,mode:0o700});
|
|
81
|
-
const output=fs.openSync(path.join(logs,'web.log'),'a',0o600);
|
|
82
|
-
const child=spawn(process.execPath,[fileURLToPath(import.meta.url),'serve','--home',home,...(args.includes('--no-tray')?['--no-tray']:[])],{detached:true,windowsHide:true,stdio:['ignore',output,output]});
|
|
83
|
-
let launchError=false;child.once('error',()=>{launchError=true;});
|
|
84
|
-
child.unref();fs.closeSync(output);
|
|
85
|
-
for(let i=0;i<100;i++){existing=await health();if(existing||launchError)break;await new Promise(r=>setTimeout(r,150));}
|
|
86
|
-
if(!existing)throw Error('Chưa mở được dịch vụ. Xem '+path.join(logs,'web.log'));
|
|
87
|
-
await ownInstance();
|
|
88
|
-
}
|
|
89
|
-
const url=base+'/app/#ticket='+createBrowserTicket(state);
|
|
90
|
-
console.log('Codex Unlimit đang chạy trên máy của bạn.\n'+url+'\nGiữ đường dẫn này riêng tư; liên kết mở trang có hiệu lực 2 phút.');
|
|
91
|
-
if(!args.includes('--no-open')){
|
|
92
|
-
// Keep the complete local URL (including its ticket) out of shell source.
|
|
93
|
-
const windows=process.platform==='win32';
|
|
94
|
-
const exe=windows?path.join(process.env.SystemRoot??'C:/Windows','System32/WindowsPowerShell/v1.0/powershell.exe'):process.platform==='darwin'?'open':'xdg-open';
|
|
95
|
-
const launchArgs=windows?['-NoProfile','-NonInteractive','-WindowStyle','Hidden','-Command',"$ErrorActionPreference='Stop'; Start-Process -FilePath $env:CU_BROWSER_URL"]:[url];
|
|
96
|
-
try{
|
|
97
|
-
await new Promise((resolve,reject)=>{
|
|
98
|
-
const child=spawn(exe,launchArgs,{windowsHide:true,stdio:'ignore',env:{...process.env,CU_BROWSER_URL:url}});
|
|
99
|
-
const timeout=setTimeout(()=>{child.kill();reject(Error('browser_open_timeout'));},15000);
|
|
100
|
-
child.once('error',error=>{clearTimeout(timeout);reject(error);});
|
|
101
|
-
child.once('exit',code=>{clearTimeout(timeout);code===0?resolve():reject(Error('browser_open_failed'));});
|
|
102
|
-
});
|
|
103
|
-
}catch{
|
|
104
|
-
console.error('Không tự mở được trình duyệt. Sao chép đường dẫn local ở trên vào trình duyệt.');
|
|
105
|
-
process.exitCode=1;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}finally{if(!serving)state.close();}
|
|
109
|
-
}
|
|
110
|
-
main().catch(error=>{console.error(errors[error.message]??error.message);process.exitCode=1;});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const _0x1e23ac=_0xe915;function _0xe915(_0x5aaee6,_0x5e74bb){_0x5aaee6=_0x5aaee6-0x12f;const _0x395d1f=_0x395d();let _0xe915b8=_0x395d1f[_0x5aaee6];if(_0xe915['bNHwgB']===undefined){var _0x382ff3=function(_0xf34559){const _0x32dd2c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x247922='',_0x500dae='';for(let _0x3b0f06=0x0,_0x144f37,_0x3cbec3,_0x32209d=0x0;_0x3cbec3=_0xf34559['charAt'](_0x32209d++);~_0x3cbec3&&(_0x144f37=_0x3b0f06%0x4?_0x144f37*0x40+_0x3cbec3:_0x3cbec3,_0x3b0f06++%0x4)?_0x247922+=String['fromCharCode'](0xff&_0x144f37>>(-0x2*_0x3b0f06&0x6)):0x0){_0x3cbec3=_0x32dd2c['indexOf'](_0x3cbec3);}for(let _0x16289e=0x0,_0x4f3d9f=_0x247922['length'];_0x16289e<_0x4f3d9f;_0x16289e++){_0x500dae+='%'+('00'+_0x247922['charCodeAt'](_0x16289e)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x500dae);};_0xe915['RgmGCm']=_0x382ff3,_0xe915['YNJwVH']={},_0xe915['bNHwgB']=!![];}const _0x42eca2=_0x395d1f[0x0];_0xe915['lNFIQe']!==_0x42eca2&&(_0xe915['YNJwVH']={},_0xe915['lNFIQe']=_0x42eca2);const _0x2adcb6=_0xe915['YNJwVH'][_0x5aaee6];return _0x2adcb6===undefined?(_0xe915b8=_0xe915['RgmGCm'](_0xe915b8),_0xe915['YNJwVH'][_0x5aaee6]=_0xe915b8):_0xe915b8=_0x2adcb6,_0xe915b8;}(function(_0x48550b,_0x44160d){const _0x120438=_0xe915,_0x2854df=_0x48550b();while(!![]){try{const _0x8e3e09=-parseInt(_0x120438(0x149))/0x1*(parseInt(_0x120438(0x190))/0x2)+parseInt(_0x120438(0x180))/0x3*(-parseInt(_0x120438(0x142))/0x4)+parseInt(_0x120438(0x191))/0x5*(-parseInt(_0x120438(0x178))/0x6)+parseInt(_0x120438(0x155))/0x7+parseInt(_0x120438(0x19b))/0x8+-parseInt(_0x120438(0x18b))/0x9+parseInt(_0x120438(0x1a2))/0xa;if(_0x8e3e09===_0x44160d)break;else _0x2854df['push'](_0x2854df['shift']());}catch(_0x5a2113){_0x2854df['push'](_0x2854df['shift']());}}}(_0x395d,0x3a478));import{B as _0x500dae,C as _0x3b0f06,D as _0x144f37,E as _0x3cbec3,H as _0x32209d,I as _0x16289e,J as _0x4f3d9f,Q as _0x1c57ef,R as _0x283333,S as _0x5add7e,T as _0x3825b5,U as _0x40b90e,V as _0x42fb73,W as _0x30c456,X,Y as _0x165d1c,a as _0x2eb830,c as _0x41f46d,f as _0x196643,s as _0x3f000b,x as _0x3c3dd7}from'./shared-ZNBXOIRW.mjs';import _0x299dd9 from'node:fs';import _0x2b4aad from'node:path';import _0x2427e6 from'node:os';import _0x3d807e from'node:crypto';import{spawn as _0xe58d0f}from'node:child_process';import{fileURLToPath as _0x10224d}from'node:url';function _0x395d(){const _0x12259a=['C3rHCNr1Ca','CMvSyxKUCg9YDa','Bw9Kzq','t0SGica','BwTKAxjtEw5J','mJq3own2u1PPAW','zxHPDa','Aw5JBhvKzxm','ue9tva','u3LZDgvTmZiVv2LUzg93C1bVD2vYu2HLBgWVDJeUmc9WB3DLCNnOzwXSlMv4zq','zgvZA3rVCa','C3rKAw4','jevYCM9Yqwn0Aw9UuhjLzMvYzw5Jzt0Nu3rVCcC7ifn0yxj0lvbYB2nLC3mGluzPBgvqyxrOicrLBNy6q1vFqLjpv1nfuL9vuKW','Bg9NCW','XjbHBMCGA2JHU59Pimsr4BUzBMCGBog6OwKGq29KzxGGvw5SAw1PDca','C2XPy2u','zgLHz25VC3rPy3m','mtqXmJa4ovjrwgnWqq','ls1UBY1VCgvU','q29KzxGGvw5SAw1PDcdeKwfUzYbJAog6OxKGDhldQM4GBCoHEsbJ4BUNysbI4BQHBI4k','ANnVBG','DgvYBwLUywXFC2v0DxbFDhr5x3jLCxvPCMvK','u0Lhvevstq','yxjNDG','CgXHDgzVCM0','Bg9N','BwvZC2fNzq','y29KzxHFAg9Tzq','q2JgSgeGBEg7NYdeKCAW4BUJyYbK4BUly2GGDUg7Ps4GwgvTia','mc4XlJaTD2vIlJe','XjddOYbI4BQTDcbRAog7N2KGXjhHU5LUzYbJW7LUzYbxAw5KB3DZlG','C3rHDhvZ','lvDPBMrVD1n0EwXL','l2fWCc8JDgLJA2v0pq','l2nVBNrYB2WVC3rVCa','y29UDhjVBf90B2TLBG','z2v0','lu5VBKLUDgvYywn0AxzL','C2vYDMLJzq','qZOVv2LUzg93CW','zxjYB3i','C2v0u3rHCNr1Ca','C3rHCNrZv2L0Aa','BgLZDgvUAw5N','ugHPW6PUigpfQsbJAmAWysb04BQVDcbOB8oGBIb0B8oGBI4Gq2JHU50GBEg7MxqGBmoHDcbY4BUtAsbT4BUFigZHUQfPienVzgv4ifvUBgLTAxqU','zxHLy1bHDgG','cKDP4BUVimsrXRdHU51UzYbK4BQRBIbUW6b5ihjPW6PUzYb0XRa7igXPW6PUigVHUR90ig3HU58GDhjHBMCGy8oZigHP4BUhDsbS4BUXyYaYihbOW7P0lG','zgfYD2LU','u0Lhsu5u','y29KzxH1BMXPBwL0lwnVBM5Ly3rVCG','BgLJzw5Zzs5Hy3rPDMf0Aw9U','CMvZB2X2zq','nti4wufgyxj1','C3rVCa','q29KzxGGvw5SAw1PDaOGignVzgv4Dw5SAw1PDcbKAwfNBM9ZDgLJCYaGicbyDEg6PxqGBg9NigVHUR90ig7HU5fPimsrW6mGBg/HUQfPihrOW7rUzYb0Aw4GCMNdQM5NihtgSaOGignVzgv4Dw5SAw1PDcbKB2n0B3iGicaGicaGicblAEg7G20GDhjHie5VzguSifnrtgL0zsb2W6aGq29KzxGGCNvUDgLTzqOGignVzgv4Dw5SAw1PDcaGicaGicaGicaGicaGicbuAgNHUR90igZHUQ1Wig5Oyw5Oiog7NYbS4BQNBIdeKEg6P3u7ig3HU58GDhjHBMCGCxxHUQnUigZdVsbRAgKGXjhdOYb4B25NcIaGy29KzxH1BMXPBwL0ihnLDhvWicaGicaGicaGie5O4BQTCcbRzxKG4BQPBIWGy+g6PxuGAmoSBMGGDSoGig3HU58GBog6OwKGq29KzxGGDhjVBMCGDgvYBwLUywWkicbJB2rLEhvUBgLTAxqGD2vIicaGicaGicaGicaGtEg7NYdHU6LUzYbK4BULBMCGD2vIihBdOcbRAgf5ifDPBMrVD3mkicbJB2rLEhvUBgLTAxqGC3rVCcaGicaGicaGicaGs2JdTgKGCgJHU6vJigVHUR90ig7HU5fPienVzgv4ihBdOcb04BQVDcdHU6LUzYbK4BULBMCkicbJB2rLEhvUBgLTAxqGCMvZDgfYDcaGicaGicaGs2JHU59Pimsr4BUzBMCGBog6OwKGyUg6Sw5NiglHUQnUimsrW6mGy8oGAsbT4BUBAsbUAog6PxqkicbJB2rLEhvUBgLTAxqGC3rHCNr1CcbVBIaGicaGvog7SsbT4BUFihrYB25NigTOyxKGA2HPimsrXinUzYbUAog6RxaGv2LUzg93CWOGignVzgv4Dw5SAw1PDcbZDgfYDhvWig9MzIaGicbu4BQVDcbRAog7N2KGXjhHU5LUzYbJW7LUzYbxAw5KB3DZcIaGy29KzxH1BMXPBwL0ic0TBM8TB3bLBIaGicaGienO4BQHEsbU4BUbBIWGA2JdTg5Nig3HU58GDhldRg5Oigr1EEg7H3qkicaTlw5VlxrYyxKGicaGicaGicaGicaGicaGicaGs2JdTg5Nig3HU58GA2HHEsaOzmoGBMGGy2HVigTP4BUdBsb0Aog7RsKkicaTlwHVBwuGphrOXRaGBEg7Pwm+icaGicaGicaGicaGrog7RYbSAEg7H3uGCMNdQM5NcIaGls1WB3j0idXZ4BUrigpHU5vUzZ4GicaGicaGicaGicbd4BUvBMCGy2HVigZHUQDUigpdOgKGXjhHUQD1','y29KzxGUCMvZDgfYDef0','y2XVC2vbBgXdB25Uzwn0Aw9UCW','ChjPDMf0zuTLEq','DMvYC2LVBG','lunVBw1HBMq','odm4otjbC05Tr2i','lu5VuhjVzMLSzq','Aw5PDgLHBgL6zq','DhjHEv91BMf2ywLSywjSzq','BgLZDgvU','y2XVC2vjzgXLq29UBMvJDgLVBNm','tog7H25OignOXRbHimsrW7PUzY4GwgvTignVzgv4Dw5SAw1PDcaTlwHLBha','B3bLBLn5BMm','y2fUy2vSBgvK','C29Tzq','y2f0y2G','mJG2mdC0vMLwDgnX','tCo0Asb0CSAW4BUDBMCGXjhdOYbZ4BQ1BIbZW6bUzY4Gs2v5l3tdOgKGA2HV4BQJBIdeKCAW4BUJyYbRAEg7G20GDhjHihrYB25Niog7Qw5NigtHU6vUzY4','l2fWCc8','CMfUzg9TqNL0zxm','uxxHUQnUigZdVsb2W6aGA2NHU4nTihrYysbZyxu6ignVzgv4Dw5SAw1PDcb3zwi','mte4r3Lcturb','mJe0mJvWCunXt1G','q29KzxH1BMXPBwL0v2vI','ChjVB2y','CMvZDgfYDa','DxbKyxrL','BMfTzq','DgLTzw91Da','BM93','B3bLCMf0Aw9Ux2zHAwXLza','l2HLywX0AhO','mta4nZy5nK5zrvj0Ca','zg9JDg9Y','C2v0Dxa','XjddOYb04BQVDcbRAog7N2KGXjhHU5LUzYbJW7LUzYbxAw5KB3DZlG','B25Jzq','Ag9TzwrPCG','C2LNBMfS','ntK1otCWmgHwBMf4ua','y3uTAw5ZDgfUy2u6','yNjVD3nLCL9VCgvUx3rPBwvVDxq','yNjVD3nLCL9VCgvUx2zHAwXLza','AxnuvfK','AM9PBG','q+g7Lw5Nimsryw5NignO4BQHEsbT4BUzDcbWAgNdQM4GA2JdOwmUietHU6TUzYbI4BQJBIbJXAKGDhlgSog7M2mGAg/HURDJignO4BUnBIbJ4BUvBMCGA2JdOwmU','C2v0DgLUz3m','C3rYAw5NAwz5','D2LUmZi','C2vYDMu','AwDUB3jL','yxnZAwDU','C2HHmJu2','ls1WB3j0','tgLICMfYEs9bChbSAwnHDgLVBIbtDxbWB3j0l0nVzgv4Dw5SAw1PDfDLyG','l2nVBNrYB2WVAwrLBNrPDhK','D2vI','s2JdTg5NihrYDxNHU4fUigTLEsb2W6bVigtdSM5NigZHU4DUAc4Gq2JHUQf5ignVzgv4Dw5SAw1PDcbZzxr1CcdeKEg7GYbUAog6RxaGA2v5iog6Qw4U','y2XVC2u','q2JgSgeGDog6R3qGXjhgSog7O2mGCgHPW6PUimsryw5NignO4BQHEs4GtEg7NYbdW6bPimsr4BQ3DcaMigJHU5CGDhlHU6mGXjhHU4mGA2NHU4nTihrYysbR4BQ/DcbU4BUrAs4','y3jLyxrLsg1HyW','zgLNzxn0','s2JdTg5NihtHU7eGBEg7NYdeKCAW4BUJyYb0CSoSBMGGzhv54BUhDc4Gu2fVignOW6LWimsrXRdHU51UzYbK4BQRBIbSB2nHBcdHU58GDhldQM4GDSoGBYb0CSoSBMGGzhv54BUhDc4','q8oGAsbS4BQHAsbNW7nPig5WBsWGz2NHU68GzgvWzw5Kzw5JEsb0W7L5ignO4BUnBI4Gs2JdTg5NigpHUQDUihJdS2eGA2v5lcdeKCsdBMCGEhxHUQv0ienOyxrhufqGAg/HURDJihjLC2v0ihrOAEg6V3qGyUg7IY4','ls1UBY10CMf5','B3bLBG','D2vIlMXVzW','y29TCgXLDgvK','DgvYBwLUywXFC2v0DxbFy2fUy2vSBgvK','zxHPDenVzgu','Dg9tDhjPBMC','Dw5Yzwy','sgLKzgvU','y29UzMLNDxjLza','Agv4','y29Kzq','zgv2AwnL','ls1OB21L','B2zM','mJbZu05Mt3a','lMXVy2fSl3nOyxjLl2nVzgv4Dw5SAw1PDa'];_0x395d=function(){return _0x12259a;};return _0x395d();}var n=process[_0x1e23ac(0x15b)][_0x1e23ac(0x153)](0x2),E=n[0x0]&&!n[0x0]['startsWith']('--')?n[0x0]:null,l=E===_0x1e23ac(0x1b3)?_0x1e23ac(0x134):E??_0x1e23ac(0x134),J=!!(process[_0x1e23ac(0x14f)][_0x1e23ac(0x1a6)]&&process['stdout'][_0x1e23ac(0x1a6)]);function Q(_0x2def04,_0x4d7c3d){let _0x2978a7=n['indexOf'](_0x2def04);if(_0x2978a7<0x0)return _0x4d7c3d;if(!n[_0x2978a7+0x1]||n[_0x2978a7+0x1]['startsWith']('--'))throw Error('Thi\u1EBFu\x20gi\xE1\x20tr\u1ECB\x20cho\x20'+_0x2def04);return n[_0x2978a7+0x1];}var _=_0x2b4aad[_0x1e23ac(0x177)](Q('--home',process[_0x1e23ac(0x15c)]===_0x1e23ac(0x1ab)?_0x2b4aad[_0x1e23ac(0x1a7)](process.env.LOCALAPPDATA??_0x2b4aad[_0x1e23ac(0x1a7)](_0x2427e6[_0x1e23ac(0x1a0)](),'AppData/Local'),_0x1e23ac(0x192)):process[_0x1e23ac(0x15c)]==='darwin'?_0x2b4aad[_0x1e23ac(0x1a7)](_0x2427e6[_0x1e23ac(0x1a0)](),_0x1e23ac(0x1b1)):_0x2b4aad[_0x1e23ac(0x1a7)](_0x2427e6['homedir'](),_0x1e23ac(0x143))));async function V(){const _0xcda1c2=_0x1e23ac;if(n['includes']('--version')){console[_0xcda1c2(0x15d)](_0x2eb830);return;}if(l===_0xcda1c2(0x19c)){let _0x59d824=await _0x3825b5();if(n[_0xcda1c2(0x14b)]('--json'))console[_0xcda1c2(0x15d)](JSON[_0xcda1c2(0x1aa)](_0x59d824));else{for(let _0x2290cd of _0x59d824['checks'])console['log']((_0x2290cd['ok']?_0xcda1c2(0x147):'THI\u1EBEU\x20')+_0x2290cd[_0xcda1c2(0x196)]+(_0x2290cd[_0xcda1c2(0x17e)]?'\x20'+_0x2290cd[_0xcda1c2(0x17e)]:''));console['log'](_0x59d824['ok']?_0xcda1c2(0x18c):_0xcda1c2(0x132));}_0x59d824['ok']||(process['exitCode']=0x1);return;}if(n[_0xcda1c2(0x14b)]('--help')){console[_0xcda1c2(0x15d)](_0xcda1c2(0x17a));return;}if(n[_0xcda1c2(0x189)](_0xfe297c=>/^--(?:key|activation-key)(?:=|$)/['test'](_0xfe297c)))throw Error(_0xcda1c2(0x1b4));if(l===_0xcda1c2(0x19d)&&!J)throw Object[_0xcda1c2(0x1ae)](Error('terminal_setup_tty_required'),{'code':_0xcda1c2(0x159)});if(![_0xcda1c2(0x134),'setup',_0xcda1c2(0x1ac),_0xcda1c2(0x179),_0xcda1c2(0x194),_0xcda1c2(0x144),_0xcda1c2(0x154)][_0xcda1c2(0x14b)](l))throw Error(_0xcda1c2(0x186));let _0x38d185=new _0x196643(_),_0x55f57d=!0x1;try{if(l==='diagnostics'){console[_0xcda1c2(0x15d)](JSON[_0xcda1c2(0x1aa)]({'version':_0x2eb830,'requests':_0x38d185['diagnostics']()},null,0x2));return;}let _0x30090c=Number(Q(_0xcda1c2(0x1b0),0x4819));if(!Number['isInteger'](_0x30090c)||_0x30090c<0x400||_0x30090c>0xffff)throw Error('C\u1ED5ng\x20c\u1EA7n\x20n\u1EB1m\x20trong\x20kho\u1EA3ng\x201024\u201365535.');_0x38d185[_0xcda1c2(0x182)]({'port':_0x30090c,'codexHome':_0x38d185[_0xcda1c2(0x168)](_0xcda1c2(0x15f))??process.env.CODEX_HOME??_0x2b4aad[_0xcda1c2(0x1a7)](_0x2427e6[_0xcda1c2(0x1a0)](),'.codex')});let _0x224a6e=_0x42fb73({'command':l,'explicitCommand':!!E,'interactive':J,'noOpen':n[_0xcda1c2(0x14b)](_0xcda1c2(0x156)),'activated':!!_0x38d185[_0xcda1c2(0x168)](_0xcda1c2(0x176)),'connected':!!_0x38d185['get']('web.connected'),'configured':_0x3b0f06(_0x38d185)[_0xcda1c2(0x13c)],'restartRequired':!!_0x38d185['get'](_0xcda1c2(0x17b))}),_0x297cbb=_0x283333(_0x38d185);if(l===_0xcda1c2(0x144)){if(!['on',_0xcda1c2(0x141)][_0xcda1c2(0x14b)](n[0x1]))throw Error('D\xF9ng\x20codexunlimit\x20startup\x20on\x20ho\u1EB7c\x20codexunlimit\x20startup\x20off.');await _0x297cbb[_0xcda1c2(0x16d)](n[0x1]==='on'),console[_0xcda1c2(0x15d)](n[0x1]==='on'?_0xcda1c2(0x162):_0xcda1c2(0x19e));return;}let _0x3d1d59='http://127.0.0.1:'+_0x38d185['settings'][_0xcda1c2(0x168)]('relay.port');async function _0x55e1de(){const _0x5e060d=_0xcda1c2;try{return await(await fetch(_0x3d1d59+_0x5e060d(0x19a),{'signal':AbortSignal['timeout'](0x3e8)}))[_0x5e060d(0x158)]();}catch{return null;}}async function _0x2498db(){const _0x48628a=_0xcda1c2;let _0x11c363=_0x3d807e[_0x48628a(0x18e)](0x18)[_0x48628a(0x139)]('hex'),_0x3b487d=_0x3d807e[_0x48628a(0x12f)](_0x48628a(0x1af),_0x38d185[_0x48628a(0x168)](_0x48628a(0x167)))[_0x48628a(0x195)](_0x48628a(0x1a3)+_0x11c363)[_0x48628a(0x130)](_0x48628a(0x13d));if((await(await fetch(_0x3d1d59+_0x48628a(0x1b2),{'headers':{'x-cu-nonce':_0x11c363},'signal':AbortSignal[_0x48628a(0x197)](0x5dc)}))[_0x48628a(0x158)]())[_0x48628a(0x193)]!==_0x3b487d)throw Error(_0x48628a(0x1a8));}if(l===_0xcda1c2(0x1ac)){let _0x95a60e=function(){const _0x511ded=_0xcda1c2;_0x16402a||(_0x16402a=!0x0,_0x4c9af6[_0x511ded(0x1b5)](async()=>{const _0x2201c3=_0x511ded;try{await _0x4b8b2a['close']();}finally{_0x38d185[_0x2201c3(0x1b5)](),process[_0x2201c3(0x14a)](0x0);}}),_0x4c9af6[_0x511ded(0x185)](),setTimeout(()=>_0x4c9af6[_0x511ded(0x17c)](),0x5dc)[_0x511ded(0x13a)]());},_0x2b9e13=new _0x3f000b(_0x38d185),_0x4b8b2a=new _0x1c57ef(_0x38d185,{'privateKey':_0x2b9e13[_0xcda1c2(0x13f)][_0xcda1c2(0x17d)],'defaultAccount':()=>_0x16289e(_0x38d185)}),_0x4c9af6=_0x3c3dd7(_0x38d185,{'license':_0x2b9e13,'pool':_0x4b8b2a,'localApp':_0x4f3d9f(_0x38d185,{'license':_0x2b9e13,'desktop':_0x297cbb,'pool':_0x4b8b2a,'codexDesktop':_0x5add7e(),'onStop':_0x95a60e}),'prepareStop':_0x24370b=>{_0x24370b==='exit'&&_0x500dae(_0x38d185);},'onStop':_0x95a60e}),_0x16402a=!0x1;_0x4c9af6[_0xcda1c2(0x184)](_0x38d185[_0xcda1c2(0x1a9)][_0xcda1c2(0x168)](_0xcda1c2(0x145)),'127.0.0.1'),await new Promise((_0x4c9240,_0x477836)=>{const _0x519189=_0xcda1c2;_0x4c9af6[_0x519189(0x19f)](_0x519189(0x16f),_0x4c9240),_0x4c9af6[_0x519189(0x19f)](_0x519189(0x16c),_0x477836);});try{_0x144f37(_0x38d185);}catch(_0x32788d){console[_0xcda1c2(0x16c)](_0x3cbec3[_0x32788d['message']]??_0x3cbec3[_0xcda1c2(0x199)]);}_0x55f57d=!0x0,process[_0xcda1c2(0x19f)](_0xcda1c2(0x174),_0x95a60e),process[_0xcda1c2(0x19f)](_0xcda1c2(0x15a),_0x95a60e),_0x297cbb[_0xcda1c2(0x163)]()[_0xcda1c2(0x144)]&&_0x297cbb[_0xcda1c2(0x16d)](!0x0)[_0xcda1c2(0x18a)](()=>console[_0xcda1c2(0x16c)](_0x3cbec3['startup_update_failed'])),process[_0xcda1c2(0x15c)]==='win32'&&!n[_0xcda1c2(0x14b)](_0xcda1c2(0x133))&&_0x297cbb['showTray']()['catch'](()=>console[_0xcda1c2(0x16c)](_0x3cbec3[_0xcda1c2(0x183)]));return;}let _0xaa72=await _0x55e1de();if(_0xaa72&&(_0xaa72[_0xcda1c2(0x16a)]!==_0xcda1c2(0x175)||_0xaa72[_0xcda1c2(0x146)]!==_0xcda1c2(0x14e)))throw Error('C\u1ED5ng\x20\u0111ang\x20\u0111\u01B0\u1EE3c\x20\u1EE9ng\x20d\u1EE5ng\x20kh\xE1c\x20s\u1EED\x20d\u1EE5ng.\x20H\xE3y\x20ch\u1ECDn\x20--port\x20kh\xE1c\x20v\u1EDBi\x20--home\x20ri\xEAng.');_0xaa72&&!(l==='stop'&&_0xaa72[_0xcda1c2(0x17e)]===_0xcda1c2(0x161))&&await _0x2498db();async function _0x486db8(_0x40bcad){const _0x24d367=_0xcda1c2;if(_0x40bcad===_0x24d367(0x14a)&&_0x500dae(_0x38d185),!_0xaa72)return;if(!(await fetch(_0x3d1d59+_0x24d367(0x166),{'method':_0x24d367(0x14c),'headers':{'x-cu-control':_0x38d185[_0x24d367(0x168)](_0x24d367(0x167)),'x-cu-stop-mode':_0x40bcad},'signal':AbortSignal['timeout'](0x1388)}))['ok'])throw Error(_0x24d367(0x1b6));for(let _0x1451a0=0x0;_0x1451a0<0x32;_0x1451a0++){if(!await _0x55e1de()){_0xaa72=null;return;}await new Promise(_0x4e1709=>setTimeout(_0x4e1709,0x64));}throw Error(_0x24d367(0x170));}if(l===_0xcda1c2(0x179)){await _0x486db8(_0xcda1c2(0x14a)),console[_0xcda1c2(0x15d)]('Codex\x20Unlimit\x20\u0111\xE3\x20t\u1EAFt.\x20K\u1EBFt\x20n\u1ED1i\x20Codex\x20\u0111\xE3\x20\u0111\u01B0\u1EE3c\x20kh\xF4i\x20ph\u1EE5c.');return;}if(_0xaa72&&(l===_0xcda1c2(0x194)||_0xaa72[_0xcda1c2(0x17e)]!==_0x2eb830)&&(console[_0xcda1c2(0x15d)](_0xcda1c2(0x152)+_0x2eb830+'\u2026'),await _0x486db8(_0xcda1c2(0x195))),_0xaa72){if(!(await fetch(_0x3d1d59+_0xcda1c2(0x18d),{'signal':AbortSignal[_0xcda1c2(0x197)](0x7d0)}))['ok'])throw Error('B\u1EA3n\x20c\u0169\x20\u0111ang\x20ch\u1EA1y.\x20D\u1EEBng\x20Codex\x20Unlimit\x20c\u0169\x20tr\u01B0\u1EDBc\x20khi\x20m\u1EDF\x20phi\xEAn\x20b\u1EA3n\x20web.');}else{let _0x185114=_0x2b4aad[_0xcda1c2(0x1a7)](_,_0xcda1c2(0x151));_0x299dd9[_0xcda1c2(0x148)](_0x185114,{'recursive':!0x0,'mode':0x1c0});let _0x3d5d29=_0x299dd9[_0xcda1c2(0x187)](_0x2b4aad[_0xcda1c2(0x1a7)](_0x185114,_0xcda1c2(0x135)),'a',0x180),_0x359f7a=_0xe58d0f(process[_0xcda1c2(0x171)],[_0x10224d(import.meta.url),_0xcda1c2(0x1ac),_0xcda1c2(0x140),_,...n[_0xcda1c2(0x14b)](_0xcda1c2(0x133))?['--no-tray']:[]],{'detached':!0x0,'windowsHide':!0x0,'stdio':[_0xcda1c2(0x1ad),_0x3d5d29,_0x3d5d29]}),_0x51542c=!0x1;_0x359f7a['once'](_0xcda1c2(0x16c),()=>{_0x51542c=!0x0;}),_0x359f7a[_0xcda1c2(0x13a)](),_0x299dd9['closeSync'](_0x3d5d29);for(let _0x325432=0x0;_0x325432<0x64&&(_0xaa72=await _0x55e1de(),!(_0xaa72||_0x51542c));_0x325432++)await new Promise(_0x4a0147=>setTimeout(_0x4a0147,0x96));if(!_0xaa72)throw Error(_0xcda1c2(0x160)+_0x2b4aad['join'](_0x185114,_0xcda1c2(0x135)));await _0x2498db();}if(_0x224a6e){let _0x3a5512=_0x30c456();try{let _0x1f62ba=await X({'base':_0x3d1d59,'ticket':_0x32209d(_0x38d185),'signal':_0x3a5512[_0xcda1c2(0x1a1)]}),_0xf60f97=await _0x165d1c({'api':_0x1f62ba,'ui':_0x3a5512});_0xf60f97[_0xcda1c2(0x136)]?_0x38d185['set']('setup.completedAt',Date[_0xcda1c2(0x198)]()):_0xf60f97[_0xcda1c2(0x188)]||(process['exitCode']=0x2);}finally{_0x3a5512[_0xcda1c2(0x1b5)]();}return;}let _0x78e8ca=_0x3d1d59+_0xcda1c2(0x165)+_0x32209d(_0x38d185);if(console[_0xcda1c2(0x15d)](_0xcda1c2(0x157)+_0x78e8ca+_0xcda1c2(0x172)),!n[_0xcda1c2(0x14b)](_0xcda1c2(0x156))){let _0xa49ecc=process[_0xcda1c2(0x15c)]===_0xcda1c2(0x1ab),_0x3bff72=_0xa49ecc?_0x2b4aad[_0xcda1c2(0x1a7)](process.env.SystemRoot??_0xcda1c2(0x16b),_0xcda1c2(0x14d)):process[_0xcda1c2(0x15c)]===_0xcda1c2(0x173)?_0xcda1c2(0x134):'xdg-open',_0x56c3a5=_0xa49ecc?[_0xcda1c2(0x181),_0xcda1c2(0x169),_0xcda1c2(0x164),_0xcda1c2(0x13b),_0xcda1c2(0x17f),_0xcda1c2(0x150)]:[_0x78e8ca];try{await new Promise((_0x3a71a3,_0x25e2aa)=>{const _0x3b9b53=_0xcda1c2;let _0x21002d=_0xe58d0f(_0x3bff72,_0x56c3a5,{'windowsHide':!0x0,'stdio':'ignore','env':{...process.env,'CU_BROWSER_URL':_0x78e8ca}}),_0xe74f99=setTimeout(()=>{const _0x43cd24=_0xe915;_0x21002d['kill'](),_0x25e2aa(Error(_0x43cd24(0x1a4)));},0x3a98);_0x21002d[_0x3b9b53(0x19f)](_0x3b9b53(0x16c),_0x4e7714=>{clearTimeout(_0xe74f99),_0x25e2aa(_0x4e7714);}),_0x21002d[_0x3b9b53(0x19f)](_0x3b9b53(0x14a),_0x2d4f30=>{const _0x4b9b5d=_0x3b9b53;clearTimeout(_0xe74f99),_0x2d4f30===0x0?_0x3a71a3():_0x25e2aa(Error(_0x4b9b5d(0x1a5)));});});}catch{console[_0xcda1c2(0x16c)](_0xcda1c2(0x131)),process[_0xcda1c2(0x138)]=0x1;}}}finally{_0x55f57d||_0x38d185['close']();}}V()['catch'](_0x517ada=>{const _0x407faa=_0x1e23ac;console['error'](_0x517ada['code']?_0x40b90e(_0x517ada):_0x3cbec3[_0x517ada[_0x407faa(0x15e)]]??_0x517ada['message']),(l===_0x407faa(0x19d)||_0x517ada[_0x407faa(0x13e)]?.[_0x407faa(0x16e)]('terminal_'))&&console[_0x407faa(0x16c)](_0x407faa(0x18f)),process[_0x407faa(0x138)]=_0x517ada[_0x407faa(0x13e)]===_0x407faa(0x137)?0x82:0x1;});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
$ErrorActionPreference = 'Stop'
|
|
2
|
+
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
|
|
3
|
+
$sessionId = (Get-Process -Id $PID).SessionId
|
|
4
|
+
function Get-DesktopProcesses {
|
|
5
|
+
@(Get-Process -Name ChatGPT,Codex -ErrorAction SilentlyContinue | Where-Object { $_.SessionId -eq $sessionId -and $_.Path })
|
|
6
|
+
}
|
|
7
|
+
function Store-Target([string]$folder) {
|
|
8
|
+
try {
|
|
9
|
+
$manifest = New-Object System.Xml.XmlDocument
|
|
10
|
+
$manifest.XmlResolver = $null
|
|
11
|
+
$manifest.Load((Join-Path $folder 'AppxManifest.xml'))
|
|
12
|
+
if ($manifest.Package.Identity.Name -ne 'OpenAI.Codex') { return $null }
|
|
13
|
+
$application = @($manifest.Package.Applications.Application | Where-Object { $_.Executable -match '(^|[\\/])(ChatGPT|Codex)\.exe$' }) | Select-Object -First 1
|
|
14
|
+
if (!$application -or $application.Id -notmatch '^[A-Za-z0-9._-]+$') { return $null }
|
|
15
|
+
$executable = [IO.Path]::GetFullPath((Join-Path $folder $application.Executable))
|
|
16
|
+
if (!$executable.StartsWith($folder.TrimEnd('\') + '\',[StringComparison]::OrdinalIgnoreCase) -or !(Test-Path -LiteralPath $executable -PathType Leaf)) { return $null }
|
|
17
|
+
$publisher = (Split-Path $folder -Leaf).Split('_')[-1]
|
|
18
|
+
if ($publisher -notmatch '^[a-z0-9]+$') { return $null }
|
|
19
|
+
return @{ executable=$executable; appId=('OpenAI.Codex_' + $publisher + '!' + $application.Id) }
|
|
20
|
+
} catch { return $null }
|
|
21
|
+
}
|
|
22
|
+
function Find-Desktop {
|
|
23
|
+
foreach ($process in (Get-DesktopProcesses)) {
|
|
24
|
+
$prefix = [regex]::Escape((Join-Path $env:ProgramFiles 'WindowsApps'))
|
|
25
|
+
if ($process.Path -match ('^(' + $prefix + '\\OpenAI\.Codex_[^\\]+)\\app\\(?:ChatGPT|Codex)\.exe$')) {
|
|
26
|
+
$target = Store-Target $Matches[1]
|
|
27
|
+
if ($target) { return $target }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
foreach ($package in @(Get-AppxPackage -Name OpenAI.Codex -ErrorAction SilentlyContinue)) {
|
|
31
|
+
$target = Store-Target $package.InstallLocation
|
|
32
|
+
if ($target) { return $target }
|
|
33
|
+
}
|
|
34
|
+
foreach ($candidate in @((Join-Path $env:LOCALAPPDATA 'Programs\Codex\Codex.exe'),(Join-Path $env:LOCALAPPDATA 'OpenAI\Codex\Codex.exe'),(Join-Path $env:ProgramFiles 'Codex\Codex.exe'))) {
|
|
35
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return @{executable=[IO.Path]::GetFullPath($candidate)} }
|
|
36
|
+
}
|
|
37
|
+
return $null
|
|
38
|
+
}
|
|
39
|
+
function Matching-Processes($target) {
|
|
40
|
+
@(Get-DesktopProcesses | Where-Object { [string]::Equals($_.Path,$target.executable,[StringComparison]::OrdinalIgnoreCase) })
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
$request = [Console]::In.ReadToEnd() | ConvertFrom-Json
|
|
44
|
+
if ($request.action -notin @('status','open','stop')) { throw 'codex_app_invalid_action' }
|
|
45
|
+
$target = Find-Desktop
|
|
46
|
+
if (!$target) {
|
|
47
|
+
if ($request.action -ne 'status') { throw 'codex_app_not_found' }
|
|
48
|
+
@{supported=$true;installed=$false;running=$false} | ConvertTo-Json -Compress
|
|
49
|
+
exit 0
|
|
50
|
+
}
|
|
51
|
+
if ($request.action -eq 'stop') {
|
|
52
|
+
$processes = @(Matching-Processes $target)
|
|
53
|
+
if ($processes.Count -gt 0) {
|
|
54
|
+
$windows = @($processes | Where-Object { $_.MainWindowHandle -ne 0 })
|
|
55
|
+
if ($windows.Count -eq 0) { throw 'codex_app_close_pending' }
|
|
56
|
+
foreach ($process in $windows) { if (!$process.CloseMainWindow()) { throw 'codex_app_close_pending' } }
|
|
57
|
+
$deadline = [DateTime]::UtcNow.AddSeconds(15)
|
|
58
|
+
while (@(Matching-Processes $target).Count -gt 0) {
|
|
59
|
+
if ([DateTime]::UtcNow -ge $deadline) { throw 'codex_app_close_pending' }
|
|
60
|
+
Start-Sleep -Milliseconds 250
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if ($request.action -eq 'open') {
|
|
65
|
+
if ($target.appId) {
|
|
66
|
+
Start-Process -FilePath (Join-Path $env:WINDIR 'explorer.exe') -ArgumentList ('shell:AppsFolder\' + $target.appId) -WindowStyle Hidden
|
|
67
|
+
} else {
|
|
68
|
+
# This is the interactive desktop application explicitly requested by its user.
|
|
69
|
+
Start-Process -FilePath $target.executable -WindowStyle Normal
|
|
70
|
+
}
|
|
71
|
+
$deadline = [DateTime]::UtcNow.AddSeconds(15)
|
|
72
|
+
while (@(Matching-Processes $target).Count -eq 0) {
|
|
73
|
+
if ([DateTime]::UtcNow -ge $deadline) { throw 'codex_app_open_failed' }
|
|
74
|
+
Start-Sleep -Milliseconds 250
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
$processes = @(Matching-Processes $target)
|
|
78
|
+
$result = @{supported=$true;installed=$true;running=($processes.Count -gt 0)}
|
|
79
|
+
if ($processes.Count -gt 0) { $first = $processes | Sort-Object StartTime | Select-Object -First 1; $result.startedAt=([DateTimeOffset]$first.StartTime).ToUnixTimeMilliseconds() }
|
|
80
|
+
$result | ConvertTo-Json -Compress
|
|
81
|
+
} catch {
|
|
82
|
+
$code = $_.Exception.Message
|
|
83
|
+
if ($code -notmatch '^codex_app_[a-z_]+$') { $code = 'codex_app_unavailable' }
|
|
84
|
+
@{error=$code} | ConvertTo-Json -Compress
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "codexunlimit",
|
|
3
|
-
"version": "0.1.0-web.
|
|
4
|
-
"private": false,
|
|
5
|
-
"description": "Codex Unlimit — trò chuyện và quản lý kết nối trên máy của bạn",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"license": "UNLICENSED",
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "codexunlimit",
|
|
3
|
+
"version": "0.1.0-web.16",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Codex Unlimit — trò chuyện và quản lý kết nối trên máy của bạn",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"registry": "https://registry.npmjs.org",
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": "^22.15.0 || >=24.0.0"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"codexunlimit": "cli.mjs"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@openai/codex": "0.166.0",
|
|
20
|
+
"markdown-it": "15.0.3"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"cli.mjs",
|
|
24
|
+
"runtime.mjs",
|
|
25
|
+
"shared-ZNBXOIRW.mjs",
|
|
26
|
+
"codex-desktop.ps1",
|
|
27
|
+
"device.ps1",
|
|
28
|
+
"windows.ps1",
|
|
29
|
+
"web/",
|
|
30
|
+
"README.md"
|
|
31
|
+
]
|
|
32
|
+
}
|
package/runtime.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(_0x4211ae,_0x4b94ca){const _0x20e60a=_0x5203,_0x392109=_0x4211ae();while(!![]){try{const _0x4a33fb=-parseInt(_0x20e60a(0x1b1))/0x1+-parseInt(_0x20e60a(0x1c3))/0x2*(parseInt(_0x20e60a(0x1c5))/0x3)+-parseInt(_0x20e60a(0x1a7))/0x4*(-parseInt(_0x20e60a(0x1c9))/0x5)+-parseInt(_0x20e60a(0x1bd))/0x6*(parseInt(_0x20e60a(0x1af))/0x7)+parseInt(_0x20e60a(0x1c7))/0x8*(-parseInt(_0x20e60a(0x1a3))/0x9)+parseInt(_0x20e60a(0x1bc))/0xa*(-parseInt(_0x20e60a(0x1bf))/0xb)+parseInt(_0x20e60a(0x1a9))/0xc;if(_0x4a33fb===_0x4b94ca)break;else _0x392109['push'](_0x392109['shift']());}catch(_0x2f3fd7){_0x392109['push'](_0x392109['shift']());}}}(_0x42e2,0x89e67));function _0x5203(_0x5dadf8,_0x4e653e){_0x5dadf8=_0x5dadf8-0x1a1;const _0x42e280=_0x42e2();let _0x520396=_0x42e280[_0x5dadf8];if(_0x5203['EPDUEo']===undefined){var _0x3956a3=function(_0x4d8f5b){const _0x49e57e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x183bb6='',_0x2728e8='';for(let _0x5d2712=0x0,_0x28b5b9,_0x2b06e2,_0x478ea2=0x0;_0x2b06e2=_0x4d8f5b['charAt'](_0x478ea2++);~_0x2b06e2&&(_0x28b5b9=_0x5d2712%0x4?_0x28b5b9*0x40+_0x2b06e2:_0x2b06e2,_0x5d2712++%0x4)?_0x183bb6+=String['fromCharCode'](0xff&_0x28b5b9>>(-0x2*_0x5d2712&0x6)):0x0){_0x2b06e2=_0x49e57e['indexOf'](_0x2b06e2);}for(let _0x20ef21=0x0,_0x1033ef=_0x183bb6['length'];_0x20ef21<_0x1033ef;_0x20ef21++){_0x2728e8+='%'+('00'+_0x183bb6['charCodeAt'](_0x20ef21)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2728e8);};_0x5203['xZHdEC']=_0x3956a3,_0x5203['ZuqGEB']={},_0x5203['EPDUEo']=!![];}const _0x1e89ff=_0x42e280[0x0];_0x5203['zhPEpd']!==_0x1e89ff&&(_0x5203['ZuqGEB']={},_0x5203['zhPEpd']=_0x1e89ff);const _0xf1378a=_0x5203['ZuqGEB'][_0x5dadf8];return _0xf1378a===undefined?(_0x520396=_0x5203['xZHdEC'](_0x520396),_0x5203['ZuqGEB'][_0x5dadf8]=_0x520396):_0x520396=_0xf1378a,_0x520396;}function _0x42e2(){const _0x28aaf1=['CMvZCg9UC2uUB3v0Chv0x3rLEhqUzgvSDge','DhjPBq','mti2AgzHwvnK','w0rptKvD','mJa2mZfKqNPlu3e','CMvZCg9UC2uUzMfPBgvK','otuXmK1sEgnqBq','zMLSDgvY','mtiWnJu2nvrssKvfDG','BgvUz3rO','CgfYC2u','ugJHUQnUigJHU5nPiglHU4SGz2NdOw4GXjfV4BQHBI4GqUg6Ow4Gy8oZihrO4BUdigFHU61PigZHUQfPihrPBIbUAog6R24U','ndu4mvL2CMPiAG','C3rHCNrZv2L0Aa','CMvZCg9UC2uUy29TCgXLDgvK','B3v0Chv0x3rLEhq','ogzSweXyva','zgvSDge','mZCZotaZndrcDg9pz0i','q2JgSgeGBMJHUQ1UimsrXRdHU6nJig7HU5LPigr1BMCGDhlHUQmGBog7NwKUieJdO3KGDgJHU60GBog6OwKU','DhjPBvn0yxj0','y2fUy2vS','y29UDgvUDa','C2XPy2u','ntiXntCWBuXPB3vz','zMXHDe1HCa','mZe5mtm4B0rksMrO','AM9PBG','BwfW','yNL0zuXLBMD0Aa','C3rYAw5N','CMvWBgfJzq','zgvJB2rL','DhLWzq','y2f0y2G','CMvHza','ugJHUQnUigJHU5nPigTOW7rUzYbO4BUJCcbS4BUhlG','otmWotu5mgfnzgDeDa','nJbmvMDWBwu','B3v0Chv0','mtfvwxbMtuK','C3bSAxq'];_0x42e2=function(){return _0x28aaf1;};return _0x42e2();}import{A as _0x2728e8,B as _0x5d2712,C as _0x28b5b9,D as _0x2b06e2,E as _0x478ea2,F as _0x20ef21,G as _0x1033ef,H as _0x423277,I as _0x383b00,J as _0x2b257b,K as _0x3167db,L as _0x5af592,M as _0x404ced,N as _0x12759b,O as _0x3cad3c,P as _0x4a669a,Q as _0x39fa84,R as _0x393059,S as _0x20b7b8,T as _0x1e21ec,U as _0x2e4548,V as _0x1ed652,W as _0x2f7296,X as _0x30a9ac,Y as _0x2fd18d,a as _0x2b4981,b as _0x55281e,c as _0xaa27e8,d as _0x5d5b9f,e as _0x24b528,f as _0x5f44b5,g as _0xeb121c,h as _0x465107,i as _0x28623f,j as _0xaedafc,k as _0x237e40,l as _0x57b301,m as _0x6e8c1d,n as _0x8b913f,o as _0x6d187c,p as _0x12645d,q as _0x431a53,r as _0x209c87,s as _0x4e091f,t as _0x3ae4d5,u as _0x207450,v as _0x1046d6,w as _0x130edb,x as _0x58b00c,y as _0x37bae4,z as _0x506e11}from'./shared-ZNBXOIRW.mjs';async function mt(_0x23de76,_0x43cb02,{maxText:_0x2b6ac7=0x3e800,maxBytes:_0x167e2=0x4*0x400*0x400}={}){const _0x335f66=_0x5203;let _0x1d1a46=_0x23de76['getReader'](),_0x4ff989=new TextDecoder(),_0x824b2b='',_0x11187b=!0x1,_0x1abda0='',_0x173833=0x0,_0x1a6758=()=>Error('C\xE2u\x20tr\u1EA3\x20l\u1EDDi\x20qu\xE1\x20d\xE0i.\x20H\xE3y\x20chia\x20y\xEAu\x20c\u1EA7u\x20th\xE0nh\x20c\xE1c\x20ph\u1EA7n\x20nh\u1ECF\x20h\u01A1n.');function _0x1004b5(_0x5a3700){const _0x2e3b07=_0x5203;let _0xbcf00a=_0x5a3700[_0x2e3b07(0x1c0)]('\x0a')[_0x2e3b07(0x1c8)](_0x171411=>_0x171411[_0x2e3b07(0x1a4)]('data:'))[_0x2e3b07(0x1b3)](_0x38d8ea=>_0x38d8ea[_0x2e3b07(0x1ae)](0x5)[_0x2e3b07(0x1ab)]())[_0x2e3b07(0x1b2)]('\x0a');if(!_0xbcf00a||_0xbcf00a===_0x2e3b07(0x1c4))return;let _0x3af0f3;try{_0x3af0f3=JSON[_0x2e3b07(0x1a1)](_0xbcf00a);}catch{throw Error(_0x2e3b07(0x1a2));}if(_0x3af0f3[_0x2e3b07(0x1b8)]===_0x2e3b07(0x1c1)){if(typeof _0x3af0f3[_0x2e3b07(0x1a8)]!=_0x2e3b07(0x1b5))throw Error(_0x2e3b07(0x1bb));if(_0x1abda0[_0x2e3b07(0x1ca)]+_0x3af0f3[_0x2e3b07(0x1a8)][_0x2e3b07(0x1ca)]>_0x2b6ac7)throw _0x1a6758();_0x1abda0+=_0x3af0f3[_0x2e3b07(0x1a8)],_0x43cb02(_0x1abda0);}if(_0x3af0f3[_0x2e3b07(0x1b8)]===_0x2e3b07(0x1a5)&&(_0x11187b=!0x0,!_0x1abda0)){if(_0x1abda0=(_0x3af0f3['response']?.[_0x2e3b07(0x1be)]??[])[_0x2e3b07(0x1b0)](_0x54eac9=>_0x54eac9[_0x2e3b07(0x1ad)]??[])['filter'](_0x14c3bf=>_0x14c3bf[_0x2e3b07(0x1b8)]===_0x2e3b07(0x1a6))[_0x2e3b07(0x1b3)](_0x11beef=>_0x11beef['text'])[_0x2e3b07(0x1b2)](''),_0x1abda0[_0x2e3b07(0x1ca)]>_0x2b6ac7)throw _0x1a6758();_0x43cb02(_0x1abda0);}if(['error',_0x2e3b07(0x1c6),'response.incomplete']['includes'](_0x3af0f3[_0x2e3b07(0x1b8)]))throw Error('Ch\u01B0a\x20ho\xE0n\x20t\u1EA5t\x20c\xE2u\x20tr\u1EA3\x20l\u1EDDi.\x20Vui\x20l\xF2ng\x20th\u1EED\x20l\u1EA1i.');}try{for(;;){let {value:_0x59111c,done:_0x52253}=await _0x1d1a46[_0x335f66(0x1ba)]();if(_0x173833+=_0x59111c?.[_0x335f66(0x1b4)]??0x0,_0x173833>_0x167e2)throw _0x1a6758();_0x824b2b+=_0x4ff989[_0x335f66(0x1b7)](_0x59111c,{'stream':!_0x52253})[_0x335f66(0x1b6)](/\r\n/g,'\x0a'),_0x824b2b=_0x824b2b[_0x335f66(0x1b6)](/\r\n/g,'\x0a');let _0x566494;for(;!_0x11187b&&(_0x566494=_0x824b2b['indexOf']('\x0a\x0a'))>=0x0;)_0x1004b5(_0x824b2b[_0x335f66(0x1ae)](0x0,_0x566494)),_0x824b2b=_0x824b2b['slice'](_0x566494+0x2);if(_0x824b2b[_0x335f66(0x1ca)]>0x2*0x400*0x400)throw Error('Ph\u1EA3n\x20h\u1ED3i\x20qu\xE1\x20d\xE0i.\x20H\xE3y\x20th\u1EED\x20m\u1ED9t\x20y\xEAu\x20c\u1EA7u\x20ng\u1EAFn\x20h\u01A1n.');if(_0x52253||_0x11187b)break;}if(!_0x11187b&&_0x824b2b[_0x335f66(0x1c2)]()&&_0x1004b5(_0x824b2b),!_0x11187b)throw Error('K\u1EBFt\x20n\u1ED1i\x20b\u1ECB\x20gi\xE1n\x20\u0111o\u1EA1n\x20tr\u01B0\u1EDBc\x20khi\x20ho\xE0n\x20t\u1EA5t.');if(!_0x1abda0)throw Error(_0x335f66(0x1aa));return _0x1abda0;}finally{await _0x1d1a46[_0x335f66(0x1ac)]()[_0x335f66(0x1b9)](()=>{}),_0x1d1a46['releaseLock']();}}export{_0x39fa84 as AccountPool,_0x5f44b5 as ClientState,_0x5af592 as CodexAccountClient,_0xaa27e8 as DEFAULT_PORT,_0x5d5b9f as LICENSE_ORIGIN,_0x24b528 as LICENSE_PUBLIC_KEY,_0x4e091f as LicenseClient,_0x4a669a as LocalQuota,_0x55281e as PRODUCT,_0x2b4981 as VERSION,_0x404ced as accountIdentity,_0x6d187c as boundedJson,_0x28b5b9 as codexConnection,_0x3167db as codexExecutable,_0x20ef21 as compareVersions,_0x423277 as createBrowserTicket,_0x20b7b8 as createCodexDesktop,_0x58b00c as createConnector,_0x2b257b as createLocalApp,_0x2f7296 as createTerminalPrompter,_0x30a9ac as createTerminalSetupClient,_0x1033ef as createUpdateChecker,_0x393059 as createWindowsIntegration,_0x1e21ec as diagnoseRuntime,_0x478ea2 as errors,_0x1046d6 as gatewayRequest,_0xeb121c as hash,_0x12759b as headerWindows,_0x207450 as imageRequest,_0x3ae4d5 as isImageRoute,_0x431a53 as loadDevice,_0x12645d as machineIdentity,_0x37bae4 as managedConfig,_0x2b06e2 as migrateCodexTransport,_0x57b301 as proofText,_0x465107 as publicText,_0x3cad3c as rateLimitWindows,_0x383b00 as readCodexAccount,_0x28623f as readPublic,mt as readResponseStream,_0x209c87 as requestLicense,_0x506e11 as restoreConfig,_0x2fd18d as runTerminalSetup,_0x1ed652 as shouldRunTerminalSetup,_0xaedafc as signEnvelope,_0x6e8c1d as signProof,_0x130edb as signedHeaders,_0x2728e8 as syncCodex,_0x2e4548 as terminalSetupMessage,_0x5d2712 as unsyncCodex,_0x237e40 as verifyEnvelope,_0x8b913f as verifyProof};
|