opencode-qwen-cli-auth 2.2.8 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,31 +1,28 @@
1
1
  # opencode-qwen-cli-auth
2
- OAuth plugin for OpenCode that lets you use Qwen models with your Qwen account, without managing a DashScope API key directly.
3
2
 
4
- ## Scope
5
-
6
- - Uses OAuth Device Authorization Grant (RFC 8628) for sign-in.
7
- - Best suited for personal/dev workflows.
8
- - For production or commercial workloads, use DashScope API key auth instead:
9
- https://dashscope.console.aliyun.com/
3
+ OAuth plugin for [OpenCode](https://opencode.ai) to use Qwen for free via Qwen Account, compatible with the [qwen-code CLI](https://github.com/QwenLM/qwen-code) mechanism.
10
4
 
11
5
  ## Features
12
6
 
13
- - OAuth login through `opencode auth login`.
14
- - Automatic token refresh before expiration.
15
- - Dynamic API base URL from token `resource_url` with safe fallback.
16
- - Model normalization to `coder-model` for Qwen Portal API.
17
- - Optional prompt bridge behavior via `QWEN_MODE`.
18
- - Optional debug and request logging via environment variables.
7
+ - **OAuth 2.0 Device Authorization Grant** (RFC 8628) - login with your Qwen Account
8
+ - **No API key required** - utilize Qwen's free tier
9
+ - **Automatic token refresh** when expired
10
+ - **DashScope compatibility** - automatically injects required headers for the OAuth flow
11
+ - **Smart output token limit** - auto-caps tokens based on model (65K for coder-model, 8K for vision-model)
12
+ - **Retry & Fallback** - handles quota/rate limit errors with payload degradation mechanism
13
+ - **Logging & Debugging** - detailed debugging support via environment variables
14
+
15
+ ## Installation
19
16
 
20
- ## Requirements
17
+ ### Requirements
21
18
 
22
- - Qwen account
23
- - OpenCode
24
- - Node.js `>=20` (only required when building/testing from source)
19
+ - Node.js >= 20.0.0
20
+ - OpenCode with plugin support
21
+ - Qwen Account (free)
25
22
 
26
- ## Quick start
23
+ ### Add to OpenCode
27
24
 
28
- Add the plugin to your OpenCode config:
25
+ Configure in `opencode.json`:
29
26
 
30
27
  ```json
31
28
  {
@@ -35,128 +32,230 @@ Add the plugin to your OpenCode config:
35
32
  }
36
33
  ```
37
34
 
38
- Then sign in:
35
+ ### Login
39
36
 
40
37
  ```bash
41
38
  opencode auth login
42
39
  ```
43
40
 
44
- Choose `Qwen Code` -> `Qwen Code (qwen.ai OAuth)`.
41
+ Select provider **Qwen Code (qwen.ai OAuth)** and follow the instructions:
45
42
 
46
- ## Usage
43
+ 1. Open the URL displayed in the terminal
44
+ 2. Enter the provided code
45
+ 3. The plugin will automatically poll and save the token
47
46
 
48
- ```bash
49
- opencode run "create a hello world file" --model=qwen-code/coder-model
50
- opencode chat --model=qwen-code/coder-model
51
- ```
47
+ ## Supported Models
52
48
 
53
- Always keep the provider prefix `qwen-code/` in model configuration.
49
+ | Model | ID | Context | Max Output | Cost |
50
+ |-------|-----|---------|------------|---------|
51
+ | Qwen Coder (Qwen 3.5 Plus) | `coder-model` | 1M tokens | 65,536 tokens | Free |
52
+ | Qwen VL Plus (Vision) | `vision-model` | 128K tokens | 8,192 tokens | Free |
54
53
 
55
54
  ## Configuration
56
55
 
57
- ### `QWEN_MODE`
56
+ ### Environment Variables
58
57
 
59
- Resolution order:
58
+ | Variable | Description | Value |
59
+ |------|-------|---------|
60
+ | `QWEN_CLI_PATH` | Path to qwen CLI (for fallback) | Default: auto-detect |
61
+ | `QWEN_MODE` | Qwen mode toggle | `1`/`true` (default) |
62
+ | `DEBUG_QWEN_PLUGIN=1` | Enable debug logging | Optional |
63
+ | `ENABLE_PLUGIN_REQUEST_LOGGING=1` | Enable request logging to file | Optional |
64
+ | `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1` | Enable CLI fallback on quota error | Optional |
60
65
 
61
- 1. Environment variable `QWEN_MODE`
62
- 2. File `~/.opencode/qwen/auth-config.json`
63
- 3. Default value: `true`
66
+ ### Debug & Logging
64
67
 
65
- Example `~/.opencode/qwen/auth-config.json`:
68
+ ```bash
69
+ # Debug mode - logs to console
70
+ DEBUG_QWEN_PLUGIN=1 opencode run "hello" --model=qwen-code/coder-model
66
71
 
67
- ```json
68
- {
69
- "qwenMode": true
70
- }
72
+ # Request logging - saves detailed JSON files
73
+ ENABLE_PLUGIN_REQUEST_LOGGING=1 opencode run "hello" --model=qwen-code/coder-model
71
74
  ```
72
75
 
73
- Supported env values:
74
-
75
- - Enable: `QWEN_MODE=1` or `QWEN_MODE=true`
76
- - Disable: `QWEN_MODE=0` or `QWEN_MODE=false`
76
+ Log files are stored at: `~/.opencode/logs/qwen-plugin/`
77
77
 
78
- ## Logging and debug
78
+ ## How It Works
79
79
 
80
- - Enable debug logs:
80
+ ### OAuth Flow
81
81
 
82
- ```bash
83
- DEBUG_QWEN_PLUGIN=1 opencode run "your prompt"
82
+ ```
83
+ 1. OpenCode requests auth -> Plugin
84
+ 2. Plugin requests device code from Qwen OAuth Server
85
+ 3. Displays URL + code to user
86
+ 4. User opens URL and enters code to authorize
87
+ 5. Plugin polls token from Qwen OAuth Server
88
+ 6. Saves token and returns to OpenCode
89
+ 7. All API requests are injected with headers and sent to DashScope
84
90
  ```
85
91
 
86
- - Enable request logging to files:
92
+ ### Token Storage
87
93
 
88
- ```bash
89
- ENABLE_PLUGIN_REQUEST_LOGGING=1 opencode run "your prompt"
90
- ```
94
+ - **Location**: `~/.qwen/oauth_creds.json`
95
+ - **Format**: JSON with access_token, refresh_token, expiry_date, resource_url
96
+ - **Auto-refresh**: Triggered when less than 30 seconds to expiration
97
+ - **Lock mechanism**: Safe multi-process token refresh
91
98
 
92
- Log path: `~/.opencode/logs/qwen-plugin/`
99
+ ### Required Headers
93
100
 
94
- ## Local plugin data
101
+ The plugin automatically injects required headers for DashScope OAuth:
95
102
 
96
- - OAuth token: `~/.opencode/qwen/oauth_token.json`
97
- - Plugin config: `~/.opencode/qwen/auth-config.json`
98
- - Prompt cache: `~/.opencode/cache/`
103
+ ```
104
+ X-DashScope-AuthType: qwen-oauth
105
+ X-DashScope-CacheControl: enable
106
+ User-Agent: opencode-qwen-cli-auth/{version}
107
+ X-DashScope-UserAgent: opencode-qwen-cli-auth/{version}
108
+ ```
99
109
 
100
- ## Troubleshooting
110
+ ## Error Handling
101
111
 
102
- ### `Authentication required. Please run: opencode auth login`
112
+ ### Insufficient Quota
103
113
 
104
- Token is missing or refresh failed. Re-authenticate:
114
+ When hitting a `429 insufficient_quota` error, the plugin automatically:
105
115
 
106
- ```bash
107
- opencode auth login
108
- ```
116
+ 1. **Degrades payload** - removes tools, reduces max_tokens to 1024
117
+ 2. **Retries** - attempts request with degraded payload
118
+ 3. **CLI fallback** (optional) - invokes `qwen` CLI if `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1` is set
109
119
 
110
- ### Device authorization timed out
120
+ ### Token Expiration
111
121
 
112
- The device code expired or was not confirmed in time. Run `opencode auth login` again and confirm in the browser sooner.
122
+ - Automatically uses refresh token
123
+ - Retries up to 2 times for transient errors (timeout, network)
124
+ - Clears token and requests re-auth on 401/403
113
125
 
114
- ### `429` rate limit
126
+ ## Authentication Management
115
127
 
116
- The server is throttling requests. Reduce request frequency and retry later.
128
+ ### Check Status
117
129
 
118
- ### Wrong model behavior
130
+ ```bash
131
+ # View saved token
132
+ cat ~/.qwen/oauth_creds.json
133
+ ```
119
134
 
120
- Ensure your model is set correctly in OpenCode:
135
+ ### Remove Authentication
121
136
 
122
- ```yaml
123
- model: qwen-code/coder-model
137
+ **PowerShell:**
138
+ ```powershell
139
+ Remove-Item -Recurse -Force "$HOME/.opencode/qwen"
140
+ Remove-Item -Force "$HOME/.qwen/oauth_creds.json"
124
141
  ```
125
142
 
126
- ## Clear auth state
143
+ **Bash (Linux/macOS):**
144
+ ```bash
145
+ rm -rf ~/.opencode/qwen
146
+ rm ~/.qwen/oauth_creds.json
147
+ ```
127
148
 
128
- - macOS/Linux:
149
+ ### Manual Refresh
129
150
 
130
151
  ```bash
131
- rm -rf ~/.opencode/qwen/
152
+ # Clear old token and login again
153
+ opencode auth logout
154
+ opencode auth login
132
155
  ```
133
156
 
134
- - PowerShell:
157
+ ## Plugin Architecture
135
158
 
136
- ```powershell
137
- Remove-Item -Recurse -Force "$HOME/.opencode/qwen"
138
159
  ```
160
+ dist/
161
+ ├── index.js # Entry point, exports QwenAuthPlugin
162
+ ├── lib/
163
+ │ ├── auth/
164
+ │ │ ├── auth.js # OAuth flow: device code, poll token, refresh
165
+ │ │ └── browser.js # Browser opener utility
166
+ │ ├── config.js # Config paths, QWEN_MODE
167
+ │ ├── constants.js # Constants: OAuth endpoints, headers, errors
168
+ │ ├── logger.js # Logging utilities
169
+ │ └── types.js # TypeScript types
170
+ ```
171
+
172
+ ### Internal Hooks Used
173
+
174
+ | Hook | Purpose |
175
+ |------|----------|
176
+ | `auth.loader` | Provides apiKey, baseURL, custom fetch |
177
+ | `auth.methods.authorize` | Device Authorization OAuth flow |
178
+ | `config` | Registers provider and models |
179
+ | `chat.params` | Sets timeout, maxRetries, max_tokens limits |
180
+ | `chat.headers` | Injects DashScope headers |
181
+
182
+ ## Comparison with Previous Plugin
183
+
184
+ | Feature | Old Plugin | This Plugin |
185
+ |-----------|-----------|------------|
186
+ | OAuth Device Flow | ✓ | ✓ |
187
+ | Custom fetch layer | ✗ | ✓ |
188
+ | DashScope headers | ✗ | ✓ (auto-inject) |
189
+ | Output token capping | ✗ | ✓ |
190
+ | Quota degradation | ✗ | ✓ |
191
+ | CLI fallback | ✗ | ✓ (optional) |
192
+ | Multi-process lock | ✗ | ✓ |
193
+ | Legacy token migration | ✗ | ✓ |
194
+
195
+ ## Troubleshooting
196
+
197
+ ### Common Issues
198
+
199
+ **1. Persistent `insufficient_quota` errors**
200
+ - Your account may have exhausted the free tier quota
201
+ - Try deleting the token and logging in again
202
+ - Enable CLI fallback: `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1`
203
+
204
+ **2. OAuth timeout**
205
+ - Check network connection
206
+ - Increase timeout in config if needed
207
+ - View detailed logs with `DEBUG_QWEN_PLUGIN=1`
139
208
 
140
- Then log in again with `opencode auth login`.
209
+ **3. Cannot find qwen CLI**
210
+ - Install qwen-code: `npm install -g @qwen-code/qwen-code`
211
+ - Or set env var: `QWEN_CLI_PATH=/path/to/qwen`
212
+
213
+ **4. Token not saving**
214
+ - Check write permissions for `~/.qwen/` directory
215
+ - View logs with `ENABLE_PLUGIN_REQUEST_LOGGING=1`
141
216
 
142
217
  ## Development
143
218
 
219
+ ### Build
220
+
144
221
  ```bash
222
+ npm install
145
223
  npm run build
224
+ ```
225
+
226
+ ### Test
227
+
228
+ ```bash
229
+ npm test
230
+ ```
231
+
232
+ ### Type Check
233
+
234
+ ```bash
146
235
  npm run typecheck
147
- npm run test
148
- npm run lint
149
236
  ```
150
237
 
151
- ## Policy and links
238
+ ### Lint & Format
152
239
 
153
- - Terms of Service: https://qwen.ai/termsservice
154
- - Privacy Policy: https://qwen.ai/privacypolicy
155
- - Usage Policy: https://qwen.ai/usagepolicy
156
- - NPM: https://www.npmjs.com/package/opencode-qwen-cli-auth
157
- - Repository: https://github.com/TVD-00/opencode-qwen-cli-auth
158
- - Issues: https://github.com/TVD-00/opencode-qwen-cli-auth/issues
240
+ ```bash
241
+ npm run lint
242
+ npm run format
243
+ ```
159
244
 
160
245
  ## License
161
246
 
162
247
  MIT
248
+
249
+ ## Repository
250
+
251
+ - **Source**: https://github.com/TVD-00/opencode-qwen-cli-auth
252
+ - **Issues**: https://github.com/TVD-00/opencode-qwen-cli-auth/issues
253
+ - **NPM**: https://www.npmjs.com/package/opencode-qwen-cli-auth
254
+
255
+ ## Author
256
+
257
+ Geoff Hammond
258
+
259
+ ## Contributing
260
+
261
+ All contributions (PRs, issues, feedback) are welcome at the GitHub repository.
package/README.vi.md ADDED
@@ -0,0 +1,261 @@
1
+ # opencode-qwen-cli-auth
2
+
3
+ Plugin OAuth cho [OpenCode](https://opencode.ai) để sử dụng Qwen miễn phí thông qua Qwen Account, tương thích với cơ chế của [qwen-code CLI](https://github.com/QwenLM/qwen-code).
4
+
5
+ ## Tính năng
6
+
7
+ - **OAuth 2.0 Device Authorization Grant** (RFC 8628) - đăng nhập bằng Qwen Account
8
+ - **Không cần API key** - sử dụng free tier của Qwen
9
+ - **Tự động refresh token** khi hết hạn
10
+ - **Tương thích DashScope** - tự động inject headers cần thiết cho OAuth flow
11
+ - **Giới hạn output token thông minh** - tự động cap theo model (65K cho coder-model, 8K cho vision-model)
12
+ - **Retry & Fallback** - xử lý lỗi quota/rate limit với cơ chế degrade (giảm tải payload)
13
+ - **Logging & Debugging** - hỗ trợ debug chi tiết qua biến môi trường
14
+
15
+ ## Cài đặt
16
+
17
+ ### Yêu cầu
18
+
19
+ - Node.js >= 20.0.0
20
+ - OpenCode có hỗ trợ plugin
21
+ - Qwen Account (miễn phí)
22
+
23
+ ### Thêm vào OpenCode
24
+
25
+ Cấu hình trong file `opencode.json`:
26
+
27
+ ```json
28
+ {
29
+ "$schema": "https://opencode.ai/config.json",
30
+ "plugin": ["opencode-qwen-cli-auth"],
31
+ "model": "qwen-code/coder-model"
32
+ }
33
+ ```
34
+
35
+ ### Đăng nhập
36
+
37
+ ```bash
38
+ opencode auth login
39
+ ```
40
+
41
+ Chọn provider **Qwen Code (qwen.ai OAuth)** và làm theo hướng dẫn:
42
+
43
+ 1. Mở URL hiển thị trong terminal
44
+ 2. Nhập mã code được cung cấp
45
+ 3. Plugin sẽ tự động poll và lưu token
46
+
47
+ ## Models hỗ trợ
48
+
49
+ | Model | ID | Context | Max Output | Chi phí |
50
+ |-------|-----|---------|------------|---------|
51
+ | Qwen Coder (Qwen 3.5 Plus) | `coder-model` | 1M tokens | 65,536 tokens | Miễn phí |
52
+ | Qwen VL Plus (Vision) | `vision-model` | 128K tokens | 8,192 tokens | Miễn phí |
53
+
54
+ ## Cấu hình
55
+
56
+ ### Biến môi trường
57
+
58
+ | Biến | Mô tả | Giá trị |
59
+ |------|-------|---------|
60
+ | `QWEN_CLI_PATH` | Đường dẫn đến qwen CLI (cho fallback) | Mặc định: tự động tìm |
61
+ | `QWEN_MODE` | Bật/tắt Qwen mode | `1`/`true` (mặc định) |
62
+ | `DEBUG_QWEN_PLUGIN=1` | Bật debug logging | Tùy chọn |
63
+ | `ENABLE_PLUGIN_REQUEST_LOGGING=1` | Bật ghi log request ra file | Tùy chọn |
64
+ | `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1` | Bật tính năng gọi CLI khi hết quota | Tùy chọn |
65
+
66
+ ### Debug & Logging
67
+
68
+ ```bash
69
+ # Debug mode - in log ra console
70
+ DEBUG_QWEN_PLUGIN=1 opencode run "hello" --model=qwen-code/coder-model
71
+
72
+ # Request logging - lưu chi tiết vào file JSON
73
+ ENABLE_PLUGIN_REQUEST_LOGGING=1 opencode run "hello" --model=qwen-code/coder-model
74
+ ```
75
+
76
+ File log được lưu tại: `~/.opencode/logs/qwen-plugin/`
77
+
78
+ ## Cơ chế hoạt động
79
+
80
+ ### Luồng OAuth (OAuth Flow)
81
+
82
+ ```
83
+ 1. OpenCode yêu cầu xác thực -> Plugin
84
+ 2. Plugin xin cấp device code từ Qwen OAuth Server
85
+ 3. Hiển thị URL + code cho người dùng
86
+ 4. Người dùng mở URL và nhập code để ủy quyền
87
+ 5. Plugin liên tục gọi (poll) Qwen OAuth Server để lấy token
88
+ 6. Lưu token và trả về cho OpenCode
89
+ 7. Tất cả request API sẽ được đính kèm headers và gửi đến DashScope
90
+ ```
91
+
92
+ ### Lưu trữ Token
93
+
94
+ - **Vị trí**: `~/.qwen/oauth_creds.json`
95
+ - **Định dạng**: JSON chứa access_token, refresh_token, expiry_date, resource_url
96
+ - **Tự động refresh**: Kích hoạt khi token còn dưới 30 giây là hết hạn
97
+ - **Cơ chế khóa (Lock)**: Đảm bảo an toàn khi refresh token trong môi trường đa tiến trình (multi-process)
98
+
99
+ ### Headers Bắt buộc
100
+
101
+ Plugin tự động đính kèm các headers cần thiết cho DashScope OAuth:
102
+
103
+ ```
104
+ X-DashScope-AuthType: qwen-oauth
105
+ X-DashScope-CacheControl: enable
106
+ User-Agent: opencode-qwen-cli-auth/{version}
107
+ X-DashScope-UserAgent: opencode-qwen-cli-auth/{version}
108
+ ```
109
+
110
+ ## Xử lý lỗi
111
+
112
+ ### Hết Quota (Insufficient Quota)
113
+
114
+ Khi gặp lỗi `429 insufficient_quota`, plugin sẽ tự động:
115
+
116
+ 1. **Degrade payload** - loại bỏ mảng tools, giảm max_tokens xuống 1024
117
+ 2. **Retry** - thử gọi lại API với payload đã giảm tải
118
+ 3. **CLI fallback** (tùy chọn) - gọi `qwen` CLI nếu biến `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1` được bật
119
+
120
+ ### Token Hết Hạn
121
+
122
+ - Tự động sử dụng refresh token để lấy token mới
123
+ - Thử lại tối đa 2 lần đối với các lỗi tạm thời (timeout, lỗi mạng)
124
+ - Xóa token cũ và yêu cầu đăng nhập lại nếu nhận lỗi 401/403
125
+
126
+ ## Quản lý xác thực
127
+
128
+ ### Kiểm tra trạng thái
129
+
130
+ ```bash
131
+ # Xem token đang được lưu
132
+ cat ~/.qwen/oauth_creds.json
133
+ ```
134
+
135
+ ### Xóa xác thực
136
+
137
+ **PowerShell:**
138
+ ```powershell
139
+ Remove-Item -Recurse -Force "$HOME/.opencode/qwen"
140
+ Remove-Item -Force "$HOME/.qwen/oauth_creds.json"
141
+ ```
142
+
143
+ **Bash (Linux/macOS):**
144
+ ```bash
145
+ rm -rf ~/.opencode/qwen
146
+ rm ~/.qwen/oauth_creds.json
147
+ ```
148
+
149
+ ### Refresh thủ công
150
+
151
+ ```bash
152
+ # Xóa token cũ và đăng nhập lại
153
+ opencode auth logout
154
+ opencode auth login
155
+ ```
156
+
157
+ ## Kiến trúc Plugin
158
+
159
+ ```
160
+ dist/
161
+ ├── index.js # Entry point, exports QwenAuthPlugin
162
+ ├── lib/
163
+ │ ├── auth/
164
+ │ │ ├── auth.js # Luồng OAuth: device code, poll token, refresh
165
+ │ │ └── browser.js # Tiện ích mở trình duyệt
166
+ │ ├── config.js # Đường dẫn cấu hình, QWEN_MODE
167
+ │ ├── constants.js # Hằng số: OAuth endpoints, headers, mã lỗi
168
+ │ ├── logger.js # Tiện ích logging
169
+ │ └── types.js # Định nghĩa kiểu (TypeScript)
170
+ ```
171
+
172
+ ### Các Hook Sử Dụng
173
+
174
+ | Hook | Mục đích |
175
+ |------|----------|
176
+ | `auth.loader` | Cung cấp apiKey, baseURL, custom fetch |
177
+ | `auth.methods.authorize` | Thực hiện luồng Device Authorization OAuth |
178
+ | `config` | Đăng ký provider và models |
179
+ | `chat.params` | Thiết lập timeout, maxRetries, giới hạn max_tokens |
180
+ | `chat.headers` | Đính kèm các headers của DashScope |
181
+
182
+ ## So sánh với Plugin Cũ
183
+
184
+ | Tính năng | Plugin cũ | Plugin này |
185
+ |-----------|-----------|------------|
186
+ | OAuth Device Flow | ✓ | ✓ |
187
+ | Custom fetch layer | ✗ | ✓ |
188
+ | Headers của DashScope | ✗ | ✓ (tự động đính kèm) |
189
+ | Giới hạn Output token | ✗ | ✓ |
190
+ | Degradation khi hết quota| ✗ | ✓ |
191
+ | Fallback dùng CLI | ✗ | ✓ (tùy chọn) |
192
+ | Khóa đa tiến trình | ✗ | ✓ |
193
+ | Migrate token cũ | ✗ | ✓ |
194
+
195
+ ## Khắc phục sự cố (Troubleshooting)
196
+
197
+ ### Các lỗi thường gặp
198
+
199
+ **1. Bị lỗi `insufficient_quota` liên tục**
200
+ - Tài khoản của bạn có thể đã hết hạn mức miễn phí
201
+ - Hãy thử xóa token và đăng nhập lại
202
+ - Bật tính năng CLI fallback: `OPENCODE_QWEN_ENABLE_CLI_FALLBACK=1`
203
+
204
+ **2. OAuth timeout**
205
+ - Kiểm tra lại kết nối mạng
206
+ - Tăng timeout trong cấu hình nếu cần
207
+ - Xem log chi tiết bằng cách bật `DEBUG_QWEN_PLUGIN=1`
208
+
209
+ **3. Không tìm thấy qwen CLI**
210
+ - Cài đặt qwen-code: `npm install -g @qwen-code/qwen-code`
211
+ - Hoặc cấu hình biến: `QWEN_CLI_PATH=/path/to/qwen`
212
+
213
+ **4. Không lưu được token**
214
+ - Kiểm tra quyền ghi (write permissions) cho thư mục `~/.qwen/`
215
+ - Xem log bằng cách bật `ENABLE_PLUGIN_REQUEST_LOGGING=1`
216
+
217
+ ## Phát triển
218
+
219
+ ### Build
220
+
221
+ ```bash
222
+ npm install
223
+ npm run build
224
+ ```
225
+
226
+ ### Test
227
+
228
+ ```bash
229
+ npm test
230
+ ```
231
+
232
+ ### Type Check
233
+
234
+ ```bash
235
+ npm run typecheck
236
+ ```
237
+
238
+ ### Lint & Format
239
+
240
+ ```bash
241
+ npm run lint
242
+ npm run format
243
+ ```
244
+
245
+ ## Giấy phép (License)
246
+
247
+ MIT
248
+
249
+ ## Repository
250
+
251
+ - **Mã nguồn**: https://github.com/TVD-00/opencode-qwen-cli-auth
252
+ - **Báo lỗi (Issues)**: https://github.com/TVD-00/opencode-qwen-cli-auth/issues
253
+ - **NPM**: https://www.npmjs.com/package/opencode-qwen-cli-auth
254
+
255
+ ## Tác giả
256
+
257
+ Geoff Hammond
258
+
259
+ ## Đóng góp
260
+
261
+ Mọi sự đóng góp (PR, issue, feedback) đều được hoan nghênh tại GitHub repository.