dsh-cursor-subscription 0.5.7 → 0.6.1
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/AGENTS.md +43 -1
- package/README.md +11 -1
- package/README_zh.md +18 -2
- package/lib/client.js +725 -9
- package/lib/index.js +44 -5
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -32,6 +32,23 @@ Then ensure `dsh-cursor-subscription` is listed in the profile
|
|
|
32
32
|
`package.json` under `dsh.profile.bundles` (the `dsh plugin add` command does
|
|
33
33
|
this automatically for published packages).
|
|
34
34
|
|
|
35
|
+
pnpm (11+) applies a built-in 24-hour `minimumReleaseAge` supply-chain gate, so a
|
|
36
|
+
range such as `^0.5.0` never selects a version published within the last 24
|
|
37
|
+
hours. Right after a release, a plain `add` or `update` therefore falls back to
|
|
38
|
+
the newest release older than 24 hours — for a young package, the earliest
|
|
39
|
+
published version. Install the newest release by exempting this package by name
|
|
40
|
+
in the profile `pnpm-workspace.yaml`:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
minimumReleaseAgeExclude:
|
|
44
|
+
- dsh-cursor-subscription
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Requesting one version explicitly (`dsh plugin --profile web add
|
|
48
|
+
dsh-cursor-subscription@0.5.8`) also works: pnpm then appends that single
|
|
49
|
+
version to the same list. Do not set `minimumReleaseAge: 0` just to install this
|
|
50
|
+
plugin; that drops the protection for every package in the profile.
|
|
51
|
+
|
|
35
52
|
Update with `dsh plugin --profile web update dsh-cursor-subscription`.
|
|
36
53
|
Uninstall with `dsh plugin --profile web remove dsh-cursor-subscription`.
|
|
37
54
|
|
|
@@ -44,7 +61,9 @@ dsh --profile web --dump-config
|
|
|
44
61
|
|
|
45
62
|
Success requires:
|
|
46
63
|
|
|
47
|
-
1. The requested package version appears once.
|
|
64
|
+
1. The requested package version appears once. A version older than the one
|
|
65
|
+
requested means pnpm's 24-hour release-age gate resolved the range; see
|
|
66
|
+
Install.
|
|
48
67
|
2. `cursor-subscription` appears once in the composed config after install
|
|
49
68
|
or update, and is absent after uninstall.
|
|
50
69
|
3. No unrelated profile or plugin changed.
|
|
@@ -57,10 +76,33 @@ If the user authorizes a live check, restart DSH manually, open
|
|
|
57
76
|
explicitly requests a live check, run one simple chat message and confirm the
|
|
58
77
|
streamed reply appears in the conversation.
|
|
59
78
|
|
|
79
|
+
The section title carries the version of the installed build next to it. That
|
|
80
|
+
number comes from the plugin's own manifest over the account channel, so it
|
|
81
|
+
matches `dsh plugin --profile web list dsh-cursor-subscription --depth 0`; a
|
|
82
|
+
missing chip on a loaded panel means the version request failed, not that the
|
|
83
|
+
plugin is unloaded.
|
|
84
|
+
|
|
85
|
+
The panel also contributes languages: besides the built-in Simplified Chinese and
|
|
86
|
+
English, **Settings -> General -> Language** lists Traditional Chinese, Japanese,
|
|
87
|
+
Korean, Spanish, French, German, Italian, Brazilian Portuguese, Russian, and
|
|
88
|
+
Arabic, and the panel mirrors itself for Arabic. Those entries come from the
|
|
89
|
+
panel's own `ctx.locale.addLanguage` calls, so they only appear on a DSH whose
|
|
90
|
+
locale runtime supports language packs; elsewhere the panel silently stays
|
|
91
|
+
zh/en. A missing language in that list is a locale-runtime question, not a
|
|
92
|
+
plugin-load failure.
|
|
93
|
+
|
|
60
94
|
## Failure handling
|
|
61
95
|
|
|
62
96
|
- If the settings page reports "无法读取 Cursor 状态" the loopback RPC failed;
|
|
63
97
|
confirm the plugin bundle is listed once in the composed config.
|
|
98
|
+
- A boot failure reading `plugin tree failed to load: failed to apply loader
|
|
99
|
+
entry cursor-subscription ... cannot get property "webServer" without inject`
|
|
100
|
+
means a plugin build that mounted its account channel through
|
|
101
|
+
`connection.rpc.handle` ran against a DSH whose Connection plugin no longer
|
|
102
|
+
declares `webServer` (for example DSH 0.1.5-rc.1). Install version 0.5.8 or
|
|
103
|
+
later, whose channel mount passes an owner context that declares `webServer`.
|
|
104
|
+
Do not fix this by adding `webServer` to the plugin's own `inject`: the failing
|
|
105
|
+
read happens on the providing plugin's scope and stays broken.
|
|
64
106
|
- A "Cursor subscription is not signed in" error on a model call means the
|
|
65
107
|
credential store is empty; the user must complete the browser login flow.
|
|
66
108
|
- Cursor's Agent protocol is undocumented and changes; a transport or
|
package/README.md
CHANGED
|
@@ -12,10 +12,11 @@ Sign in to your Cursor account and use your Cursor subscription directly from De
|
|
|
12
12
|
- Store credentials in DSH's local credential store and refresh access tokens automatically.
|
|
13
13
|
- Discover models available to the current account dynamically through Cursor's `GetUsableModels`, with a built-in fallback list if discovery fails.
|
|
14
14
|
- Stream conversations with reasoning output, image attachments, and DSH tool calls.
|
|
15
|
-
- View sign-in status and token expiration in the settings page.
|
|
15
|
+
- View sign-in status and token expiration in the settings page, which labels itself with the installed build version.
|
|
16
16
|
- View and manually refresh subscription usage, including requests, Auto + Composer usage, other-model (API) usage, per-model spend, on-demand spend, and billing cycle.
|
|
17
17
|
- View and manually refresh the models available to the current account.
|
|
18
18
|
- Configure the per-run tool-round limit and HTTP retry count, interval, and status codes from the settings page.
|
|
19
|
+
- Read the settings page in Simplified Chinese, English, Traditional Chinese, Japanese, Korean, Spanish, French, German, Italian, Brazilian Portuguese, Russian, or Arabic. The panel mirrors itself for Arabic; contributed languages join DSH's own language picker under **Settings → General → Language** and fall back to English outside the panel.
|
|
19
20
|
|
|
20
21
|
## Installation
|
|
21
22
|
|
|
@@ -33,6 +34,13 @@ dsh --profile web --dump-config
|
|
|
33
34
|
|
|
34
35
|
The installed package list should contain exactly one `dsh-cursor-subscription`, and the composed configuration should contain exactly one `cursor-subscription` entry.
|
|
35
36
|
|
|
37
|
+
pnpm 11 and later ship a built-in 24-hour `minimumReleaseAge` gate, so a plain `add` never selects a version published within the last 24 hours. Right after a release, install it explicitly (`dsh plugin --profile web add dsh-cursor-subscription@0.5.8`) or exempt this package by name in the profile's `pnpm-workspace.yaml`:
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
minimumReleaseAgeExclude:
|
|
41
|
+
- dsh-cursor-subscription
|
|
42
|
+
```
|
|
43
|
+
|
|
36
44
|
### Local Development Installation
|
|
37
45
|
|
|
38
46
|
Run the following command in the profile directory, such as `%USERPROFILE%\.dsh\profiles\web`:
|
|
@@ -68,6 +76,8 @@ If DSH is running, restart it manually after installation or an update.
|
|
|
68
76
|
- **DSH still reports that you are signed out after sign-in:** Make sure the browser completed the entire authorization flow and redirected to the completion page. Polling waits for up to approximately 2.5 minutes.
|
|
69
77
|
- **The model list is empty:** `GetUsableModels` depends on the account type. If discovery fails, the plugin uses its built-in model list, and you can still enter a model name manually.
|
|
70
78
|
- **Requests return 401:** If the access token has expired and the refresh token is no longer valid, sign in again from the settings page.
|
|
79
|
+
- **DSH fails to start with `cannot get property "webServer" without inject`:** The installed DSH's Connection plugin does not declare `webServer`, which the older channel registration relied on. Install version 0.5.8 or later of this plugin.
|
|
80
|
+
- **A plain install picks an old version:** pnpm's built-in 24-hour `minimumReleaseAge` gate skips releases published within the last day. Install an explicit version or exempt this package by name; see the installation section.
|
|
71
81
|
- **The server protocol changed:** Cursor's Agent protocol is unpublished. If requests fail, check for a plugin update.
|
|
72
82
|
|
|
73
83
|
## Scope and Support
|
package/README_zh.md
CHANGED
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
- 登录凭据保存在本机 DSH credential 存储中,自动刷新访问令牌;
|
|
18
18
|
- 通过 Cursor 的 `GetUsableModels` 动态发现当前账户可用的模型(失败时回退到内置列表);
|
|
19
19
|
- 流式对话,支持思考过程(reasoning)、用户图片附件与 DSH 工具调用;
|
|
20
|
-
-
|
|
20
|
+
- 设置页可查看登录状态与令牌有效期,标题旁标出当前安装的插件版本号;
|
|
21
21
|
- 设置页可查询订阅用量(包含请求、Auto + Composer、其他模型占比、各模型消费、按需消费、账单周期)并手动刷新;
|
|
22
22
|
- 设置页可查看当前账户可用的模型列表并手动刷新;
|
|
23
|
-
- 可在设置页调整单次任务工具轮次上限,以及 HTTP
|
|
23
|
+
- 可在设置页调整单次任务工具轮次上限,以及 HTTP 重试次数、间隔和状态码;
|
|
24
|
+
- 设置页支持简体中文、英文、繁体中文、日语、韩语、西班牙语、法语、德语、意大利语、巴西葡萄牙语、俄语和阿拉伯语;阿拉伯语下界面自动镜像为从右到左。新增语言会注册进 DSH 的语言列表(**设置 → 通用 → 语言**),面板之外的其他界面回退到英文。
|
|
24
25
|
|
|
25
26
|
## 安装
|
|
26
27
|
|
|
@@ -39,6 +40,16 @@ dsh --profile web --dump-config
|
|
|
39
40
|
安装列表中应只有一个 `dsh-cursor-subscription`,配置中应只有一个
|
|
40
41
|
`cursor-subscription` 条目。
|
|
41
42
|
|
|
43
|
+
pnpm 11 及以后内置了 24 小时的 `minimumReleaseAge` 供应链防护:普通 `add`
|
|
44
|
+
不会选择 24 小时内发布的版本。刚发布完新版本时,请显式指定版本安装
|
|
45
|
+
(`dsh plugin --profile web add dsh-cursor-subscription@0.5.8`),或在 profile 的
|
|
46
|
+
`pnpm-workspace.yaml` 里按包名豁免:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
minimumReleaseAgeExclude:
|
|
50
|
+
- dsh-cursor-subscription
|
|
51
|
+
```
|
|
52
|
+
|
|
42
53
|
### 本地开发安装
|
|
43
54
|
|
|
44
55
|
在 profile 目录(如 `%USERPROFILE%\.dsh\profiles\web`)执行:
|
|
@@ -81,6 +92,11 @@ dsh plugin --profile web remove dsh-cursor-subscription # 卸载
|
|
|
81
92
|
- **模型列表为空**:`GetUsableModels` 依赖账户类型,失败时插件会使用内置模型列表,
|
|
82
93
|
仍可手动输入模型名。
|
|
83
94
|
- **请求报 401**:令牌过期且 refresh token 失效时,需要在设置页重新登录。
|
|
95
|
+
- **DSH 启动失败并报 `cannot get property "webServer" without inject`**:当前 DSH 的
|
|
96
|
+
Connection 插件不再自己声明 `webServer`,旧版插件注册账户通道时依赖了它。请安装
|
|
97
|
+
0.5.8 或更高版本的本插件。
|
|
98
|
+
- **普通安装装到的是旧版本**:pnpm 内置的 24 小时 `minimumReleaseAge` 防护会跳过
|
|
99
|
+
最近一天内发布的版本。请显式指定版本安装,或按包名豁免该包;见安装章节。
|
|
84
100
|
- **服务端协议变更**:Cursor 的 Agent 协议是未公开接口,若请求失败请检查插件更新。
|
|
85
101
|
|
|
86
102
|
## 边界与支持
|
package/lib/client.js
CHANGED
|
@@ -33,7 +33,6 @@ window.__ModuleLoader__.load({
|
|
|
33
33
|
usageRefreshing: "刷新中…",
|
|
34
34
|
usageNotSignedIn: "登录后可查看 Cursor 返回的用量。",
|
|
35
35
|
usageLoading: "正在读取用量…",
|
|
36
|
-
usageError: "无法读取用量",
|
|
37
36
|
usageUpdated: "更新于 {value}",
|
|
38
37
|
plan: "套餐",
|
|
39
38
|
unlimited: "不限额",
|
|
@@ -43,7 +42,6 @@ window.__ModuleLoader__.load({
|
|
|
43
42
|
autoUsage: "计划 Cursor 模型使用量",
|
|
44
43
|
otherModels: "计划其他模型使用量",
|
|
45
44
|
modelUsage: "模型用量",
|
|
46
|
-
spendUsed: "已消费 ${used}",
|
|
47
45
|
spendUsedOf: "已消费 ${used} / ${limit}",
|
|
48
46
|
billingCycle: "账单周期",
|
|
49
47
|
billingDaysLeft: "剩余 {value} 天",
|
|
@@ -54,7 +52,6 @@ window.__ModuleLoader__.load({
|
|
|
54
52
|
models: "模型列表",
|
|
55
53
|
modelsRefresh: "刷新模型列表",
|
|
56
54
|
modelsRefreshing: "刷新中…",
|
|
57
|
-
modelsEmpty: "暂无模型数据",
|
|
58
55
|
modelsCount: "{value} 个模型",
|
|
59
56
|
modelsLoading: "正在读取模型列表…",
|
|
60
57
|
runtimeSettings: "运行设置",
|
|
@@ -96,7 +93,6 @@ window.__ModuleLoader__.load({
|
|
|
96
93
|
usageRefreshing: "Refreshing…",
|
|
97
94
|
usageNotSignedIn: "Sign in to read usage reported by Cursor.",
|
|
98
95
|
usageLoading: "Reading usage…",
|
|
99
|
-
usageError: "Could not read usage",
|
|
100
96
|
usageUpdated: "Updated {value}",
|
|
101
97
|
plan: "Plan",
|
|
102
98
|
unlimited: "Unlimited",
|
|
@@ -106,11 +102,9 @@ window.__ModuleLoader__.load({
|
|
|
106
102
|
autoUsage: "Plan Cursor model usage",
|
|
107
103
|
otherModels: "Plan other model usage",
|
|
108
104
|
modelUsage: "Model usage",
|
|
109
|
-
spendUsed: "${used} spent",
|
|
110
105
|
spendUsedOf: "${used} / ${limit} spent",
|
|
111
106
|
billingCycle: "Billing cycle",
|
|
112
107
|
billingDaysLeft: "{value} days left",
|
|
113
|
-
planPercent: "Plan used {value}%",
|
|
114
108
|
autoPercent: "Plan Cursor models {value}%",
|
|
115
109
|
otherModelsPercent: "Plan other models {value}%",
|
|
116
110
|
otherModelsUnknown: "This usage value has not been read yet",
|
|
@@ -118,7 +112,6 @@ window.__ModuleLoader__.load({
|
|
|
118
112
|
models: "Models",
|
|
119
113
|
modelsRefresh: "Refresh models",
|
|
120
114
|
modelsRefreshing: "Refreshing…",
|
|
121
|
-
modelsEmpty: "No model data yet",
|
|
122
115
|
modelsCount: "{value} models",
|
|
123
116
|
modelsLoading: "Reading model list…",
|
|
124
117
|
runtimeSettings: "Runtime settings",
|
|
@@ -140,6 +133,647 @@ window.__ModuleLoader__.load({
|
|
|
140
133
|
settingsSaveFailed: "Could not save runtime settings.",
|
|
141
134
|
settingsInvalid: "Check the tool rounds, retry count, interval, and HTTP status codes.",
|
|
142
135
|
};
|
|
136
|
+
const zhHant = {
|
|
137
|
+
nav: "Cursor 訂閱",
|
|
138
|
+
title: "Cursor 訂閱",
|
|
139
|
+
connected: "已登入",
|
|
140
|
+
disconnected: "未登入",
|
|
141
|
+
accountLoading: "正在讀取帳戶狀態…",
|
|
142
|
+
login: "瀏覽器登入",
|
|
143
|
+
logout: "登出",
|
|
144
|
+
cancel: "取消",
|
|
145
|
+
openLogin: "開啟登入頁",
|
|
146
|
+
waiting: "正在等待登入完成…",
|
|
147
|
+
failed: "登入失敗,請重試。",
|
|
148
|
+
loadFailed: "無法讀取 Cursor 狀態。",
|
|
149
|
+
note: "在瀏覽器登入 Cursor 帳戶後,即可在模型選擇器中使用 Cursor 訂閱模型。登入資訊僅保存在本機,不會上傳。",
|
|
150
|
+
expiresAt: "權杖有效至 {value}",
|
|
151
|
+
usage: "訂閱用量",
|
|
152
|
+
usageRefresh: "重新整理",
|
|
153
|
+
usageRefreshing: "重新整理中…",
|
|
154
|
+
usageNotSignedIn: "登入後可查看 Cursor 回報的用量。",
|
|
155
|
+
usageLoading: "正在讀取用量…",
|
|
156
|
+
usageUpdated: "更新於 {value}",
|
|
157
|
+
plan: "方案",
|
|
158
|
+
unlimited: "不限額",
|
|
159
|
+
includedRequests: "包含請求",
|
|
160
|
+
requestsUsed: "已用 {used} / {limit} 次請求({pct}%)",
|
|
161
|
+
onDemandSpend: "隨用隨付支出",
|
|
162
|
+
autoUsage: "方案 Cursor 模型用量",
|
|
163
|
+
otherModels: "方案其他模型用量",
|
|
164
|
+
modelUsage: "模型用量",
|
|
165
|
+
spendUsedOf: "已消費 ${used} / ${limit}",
|
|
166
|
+
billingCycle: "帳單週期",
|
|
167
|
+
billingDaysLeft: "剩餘 {value} 天",
|
|
168
|
+
autoPercent: "方案 Cursor 模型 {value}%",
|
|
169
|
+
otherModelsPercent: "方案其他模型 {value}%",
|
|
170
|
+
otherModelsUnknown: "尚未讀取到該用量",
|
|
171
|
+
modelSpendPct: "{model} 已用 ${used}({pct}%)",
|
|
172
|
+
models: "模型清單",
|
|
173
|
+
modelsRefresh: "重新整理模型清單",
|
|
174
|
+
modelsRefreshing: "重新整理中…",
|
|
175
|
+
modelsCount: "{value} 個模型",
|
|
176
|
+
modelsLoading: "正在讀取模型清單…",
|
|
177
|
+
runtimeSettings: "執行設定",
|
|
178
|
+
runtimeSettingsNote: "設定會儲存到目前的 DSH profile,並從下一次 Cursor 請求開始生效。",
|
|
179
|
+
maxToolRounds: "最大工具輪次",
|
|
180
|
+
maxToolRoundsHint: "單次 Cursor 任務允許的工具輪次,超過後以 TOOL_LIMIT 終止。範圍 1–1000。",
|
|
181
|
+
retryCount: "重試次數",
|
|
182
|
+
retryCountHint: "符合狀態碼時允許的額外請求次數。預設 0(關閉),啟用後可能重複 Cursor 遠端模型請求或用量。範圍 0–10。",
|
|
183
|
+
retryInterval: "重試間隔(毫秒)",
|
|
184
|
+
retryIntervalHint: "每次 HTTP 重試前等待的固定時間。範圍 0–300000。",
|
|
185
|
+
retryStatuses: "重試 HTTP 狀態碼",
|
|
186
|
+
retryStatusesHint: "以逗號分隔,例如 408, 425, 429, 500, 502, 503, 504。",
|
|
187
|
+
saveSettings: "儲存設定",
|
|
188
|
+
savingSettings: "儲存中…",
|
|
189
|
+
reloadSettings: "重新載入",
|
|
190
|
+
loadingSettings: "載入中…",
|
|
191
|
+
settingsSaved: "設定已儲存。",
|
|
192
|
+
settingsLoadFailed: "無法讀取執行設定。",
|
|
193
|
+
settingsSaveFailed: "無法儲存執行設定。",
|
|
194
|
+
settingsInvalid: "請檢查工具輪次、重試次數、間隔和 HTTP 狀態碼。",
|
|
195
|
+
};
|
|
196
|
+
const ja = {
|
|
197
|
+
nav: "Cursor",
|
|
198
|
+
title: "Cursor サブスクリプション",
|
|
199
|
+
connected: "サインイン済み",
|
|
200
|
+
disconnected: "未サインイン",
|
|
201
|
+
accountLoading: "アカウント状態を読み込み中…",
|
|
202
|
+
login: "ブラウザーでサインイン",
|
|
203
|
+
logout: "サインアウト",
|
|
204
|
+
cancel: "キャンセル",
|
|
205
|
+
openLogin: "サインインページを開く",
|
|
206
|
+
waiting: "サインインの完了を待っています…",
|
|
207
|
+
failed: "サインインに失敗しました。もう一度お試しください。",
|
|
208
|
+
loadFailed: "Cursor の状態を読み取れませんでした。",
|
|
209
|
+
note: "ブラウザーで Cursor アカウントにサインインすると、モデル選択で Cursor サブスクリプションのモデルを利用できます。認証情報はこのマシン内にのみ保存されます。",
|
|
210
|
+
expiresAt: "トークン有効期限 {value}",
|
|
211
|
+
usage: "サブスクリプション使用量",
|
|
212
|
+
usageRefresh: "更新",
|
|
213
|
+
usageRefreshing: "更新中…",
|
|
214
|
+
usageNotSignedIn: "サインインすると Cursor が報告する使用量を確認できます。",
|
|
215
|
+
usageLoading: "使用量を読み込み中…",
|
|
216
|
+
usageUpdated: "{value} に更新",
|
|
217
|
+
plan: "プラン",
|
|
218
|
+
unlimited: "無制限",
|
|
219
|
+
includedRequests: "含まれるリクエスト",
|
|
220
|
+
requestsUsed: "{used} / {limit} リクエスト使用({pct}%)",
|
|
221
|
+
onDemandSpend: "オンデマンド利用額",
|
|
222
|
+
autoUsage: "プランの Cursor モデル使用量",
|
|
223
|
+
otherModels: "プランのその他モデル使用量",
|
|
224
|
+
modelUsage: "モデル使用量",
|
|
225
|
+
spendUsedOf: "${used} / ${limit} 使用",
|
|
226
|
+
billingCycle: "請求サイクル",
|
|
227
|
+
billingDaysLeft: "残り {value} 日",
|
|
228
|
+
autoPercent: "プランの Cursor モデル {value}%",
|
|
229
|
+
otherModelsPercent: "プランのその他モデル {value}%",
|
|
230
|
+
otherModelsUnknown: "この使用量はまだ取得していません",
|
|
231
|
+
modelSpendPct: "{model} ${used}({pct}%)",
|
|
232
|
+
models: "モデル",
|
|
233
|
+
modelsRefresh: "モデルを更新",
|
|
234
|
+
modelsRefreshing: "更新中…",
|
|
235
|
+
modelsCount: "{value} 個のモデル",
|
|
236
|
+
modelsLoading: "モデル一覧を読み込み中…",
|
|
237
|
+
runtimeSettings: "実行設定",
|
|
238
|
+
runtimeSettingsNote: "設定は現在の DSH profile に保存され、次回の Cursor リクエストから適用されます。",
|
|
239
|
+
maxToolRounds: "最大ツールラウンド",
|
|
240
|
+
maxToolRoundsHint: "1 回の Cursor タスクで許可されるツールラウンド数。超えると TOOL_LIMIT で終了します。範囲: 1〜1000。",
|
|
241
|
+
retryCount: "リトライ回数",
|
|
242
|
+
retryCountHint: "該当するステータスに対する追加リクエスト回数。既定 0(無効)。有効にすると Cursor のリモートモデル処理や使用量が重複する場合があります。範囲: 0〜10。",
|
|
243
|
+
retryInterval: "リトライ間隔(ミリ秒)",
|
|
244
|
+
retryIntervalHint: "各 HTTP リトライ前の固定待機時間。範囲: 0〜300000。",
|
|
245
|
+
retryStatuses: "リトライする HTTP ステータスコード",
|
|
246
|
+
retryStatusesHint: "カンマ区切り、例: 408, 425, 429, 500, 502, 503, 504。",
|
|
247
|
+
saveSettings: "設定を保存",
|
|
248
|
+
savingSettings: "保存中…",
|
|
249
|
+
reloadSettings: "再読み込み",
|
|
250
|
+
loadingSettings: "読み込み中…",
|
|
251
|
+
settingsSaved: "設定を保存しました。",
|
|
252
|
+
settingsLoadFailed: "実行設定を読み取れませんでした。",
|
|
253
|
+
settingsSaveFailed: "実行設定を保存できませんでした。",
|
|
254
|
+
settingsInvalid: "ツールラウンド、リトライ回数、間隔、HTTP ステータスコードを確認してください。",
|
|
255
|
+
};
|
|
256
|
+
const ko = {
|
|
257
|
+
nav: "Cursor",
|
|
258
|
+
title: "Cursor 구독",
|
|
259
|
+
connected: "로그인됨",
|
|
260
|
+
disconnected: "로그인하지 않음",
|
|
261
|
+
accountLoading: "계정 상태를 불러오는 중…",
|
|
262
|
+
login: "브라우저로 로그인",
|
|
263
|
+
logout: "로그아웃",
|
|
264
|
+
cancel: "취소",
|
|
265
|
+
openLogin: "로그인 페이지 열기",
|
|
266
|
+
waiting: "로그인 완료를 기다리는 중…",
|
|
267
|
+
failed: "로그인에 실패했습니다. 다시 시도하세요.",
|
|
268
|
+
loadFailed: "Cursor 상태를 읽을 수 없습니다.",
|
|
269
|
+
note: "브라우저에서 Cursor 계정으로 로그인하면 모델 선택기에서 Cursor 구독 모델을 사용할 수 있습니다. 자격 증명은 이 컴퓨터에만 저장됩니다.",
|
|
270
|
+
expiresAt: "토큰 만료 {value}",
|
|
271
|
+
usage: "구독 사용량",
|
|
272
|
+
usageRefresh: "새로 고침",
|
|
273
|
+
usageRefreshing: "새로 고치는 중…",
|
|
274
|
+
usageNotSignedIn: "로그인하면 Cursor가 보고하는 사용량을 볼 수 있습니다.",
|
|
275
|
+
usageLoading: "사용량을 불러오는 중…",
|
|
276
|
+
usageUpdated: "{value}에 업데이트",
|
|
277
|
+
plan: "플랜",
|
|
278
|
+
unlimited: "무제한",
|
|
279
|
+
includedRequests: "포함된 요청",
|
|
280
|
+
requestsUsed: "요청 {used} / {limit} 사용 ({pct}%)",
|
|
281
|
+
onDemandSpend: "종량제 지출",
|
|
282
|
+
autoUsage: "플랜 Cursor 모델 사용량",
|
|
283
|
+
otherModels: "플랜 기타 모델 사용량",
|
|
284
|
+
modelUsage: "모델 사용량",
|
|
285
|
+
spendUsedOf: "${used} / ${limit} 사용",
|
|
286
|
+
billingCycle: "결제 주기",
|
|
287
|
+
billingDaysLeft: "{value}일 남음",
|
|
288
|
+
autoPercent: "플랜 Cursor 모델 {value}%",
|
|
289
|
+
otherModelsPercent: "플랜 기타 모델 {value}%",
|
|
290
|
+
otherModelsUnknown: "이 사용량은 아직 읽지 않았습니다",
|
|
291
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
292
|
+
models: "모델",
|
|
293
|
+
modelsRefresh: "모델 새로 고침",
|
|
294
|
+
modelsRefreshing: "새로 고치는 중…",
|
|
295
|
+
modelsCount: "모델 {value}개",
|
|
296
|
+
modelsLoading: "모델 목록을 불러오는 중…",
|
|
297
|
+
runtimeSettings: "실행 설정",
|
|
298
|
+
runtimeSettingsNote: "설정은 현재 DSH profile에 저장되며 다음 Cursor 요청부터 적용됩니다.",
|
|
299
|
+
maxToolRounds: "최대 도구 라운드",
|
|
300
|
+
maxToolRoundsHint: "Cursor 작업 하나에서 허용되는 도구 라운드 수이며 초과하면 TOOL_LIMIT으로 종료됩니다. 범위: 1–1000.",
|
|
301
|
+
retryCount: "재시도 횟수",
|
|
302
|
+
retryCountHint: "일치하는 상태 코드에 대한 추가 요청 횟수. 기본값 0(해제). 사용하면 Cursor 원격 모델 작업이나 사용량이 중복될 수 있습니다. 범위: 0–10.",
|
|
303
|
+
retryInterval: "재시도 간격(ms)",
|
|
304
|
+
retryIntervalHint: "각 HTTP 재시도 전에 기다리는 고정 시간. 범위: 0–300000.",
|
|
305
|
+
retryStatuses: "재시도할 HTTP 상태 코드",
|
|
306
|
+
retryStatusesHint: "쉼표로 구분합니다. 예: 408, 425, 429, 500, 502, 503, 504.",
|
|
307
|
+
saveSettings: "설정 저장",
|
|
308
|
+
savingSettings: "저장 중…",
|
|
309
|
+
reloadSettings: "다시 불러오기",
|
|
310
|
+
loadingSettings: "불러오는 중…",
|
|
311
|
+
settingsSaved: "설정을 저장했습니다.",
|
|
312
|
+
settingsLoadFailed: "실행 설정을 읽을 수 없습니다.",
|
|
313
|
+
settingsSaveFailed: "실행 설정을 저장할 수 없습니다.",
|
|
314
|
+
settingsInvalid: "도구 라운드, 재시도 횟수, 간격, HTTP 상태 코드를 확인하세요.",
|
|
315
|
+
};
|
|
316
|
+
const es = {
|
|
317
|
+
nav: "Cursor",
|
|
318
|
+
title: "Suscripción a Cursor",
|
|
319
|
+
connected: "Sesión iniciada",
|
|
320
|
+
disconnected: "Sin sesión",
|
|
321
|
+
accountLoading: "Leyendo el estado de la cuenta…",
|
|
322
|
+
login: "Iniciar sesión en el navegador",
|
|
323
|
+
logout: "Cerrar sesión",
|
|
324
|
+
cancel: "Cancelar",
|
|
325
|
+
openLogin: "Abrir la página de inicio de sesión",
|
|
326
|
+
waiting: "Esperando a que termine el inicio de sesión…",
|
|
327
|
+
failed: "No se pudo iniciar sesión. Inténtalo de nuevo.",
|
|
328
|
+
loadFailed: "No se pudo leer el estado de Cursor.",
|
|
329
|
+
note: "Después de iniciar sesión con una cuenta de Cursor en el navegador, los modelos de la suscripción a Cursor estarán disponibles en el selector de modelos. Las credenciales permanecen en este equipo.",
|
|
330
|
+
expiresAt: "Token válido hasta {value}",
|
|
331
|
+
usage: "Uso de la suscripción",
|
|
332
|
+
usageRefresh: "Actualizar",
|
|
333
|
+
usageRefreshing: "Actualizando…",
|
|
334
|
+
usageNotSignedIn: "Inicia sesión para ver el uso que informa Cursor.",
|
|
335
|
+
usageLoading: "Leyendo el uso…",
|
|
336
|
+
usageUpdated: "Actualizado {value}",
|
|
337
|
+
plan: "Plan",
|
|
338
|
+
unlimited: "Ilimitado",
|
|
339
|
+
includedRequests: "Solicitudes incluidas",
|
|
340
|
+
requestsUsed: "{used} / {limit} solicitudes usadas ({pct}%)",
|
|
341
|
+
onDemandSpend: "Gasto bajo demanda",
|
|
342
|
+
autoUsage: "Uso de modelos Cursor del plan",
|
|
343
|
+
otherModels: "Uso de otros modelos del plan",
|
|
344
|
+
modelUsage: "Uso por modelo",
|
|
345
|
+
spendUsedOf: "${used} / ${limit} gastados",
|
|
346
|
+
billingCycle: "Ciclo de facturación",
|
|
347
|
+
billingDaysLeft: "Quedan {value} días",
|
|
348
|
+
autoPercent: "Modelos Cursor del plan {value}%",
|
|
349
|
+
otherModelsPercent: "Otros modelos del plan {value}%",
|
|
350
|
+
otherModelsUnknown: "Este valor de uso aún no se ha leído",
|
|
351
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
352
|
+
models: "Modelos",
|
|
353
|
+
modelsRefresh: "Actualizar modelos",
|
|
354
|
+
modelsRefreshing: "Actualizando…",
|
|
355
|
+
modelsCount: "{value} modelos",
|
|
356
|
+
modelsLoading: "Leyendo la lista de modelos…",
|
|
357
|
+
runtimeSettings: "Ajustes de ejecución",
|
|
358
|
+
runtimeSettingsNote: "Los ajustes se guardan en el profile de DSH actual y se aplican desde la siguiente solicitud a Cursor.",
|
|
359
|
+
maxToolRounds: "Rondas de herramientas máximas",
|
|
360
|
+
maxToolRoundsHint: "Rondas de herramientas permitidas en una tarea de Cursor antes de que TOOL_LIMIT la detenga. Rango: 1–1000.",
|
|
361
|
+
retryCount: "Número de reintentos",
|
|
362
|
+
retryCountHint: "Intentos adicionales para los estados coincidentes. Predeterminado: 0 (desactivado). Activar los reintentos puede repetir trabajo o uso del modelo remoto de Cursor. Rango: 0–10.",
|
|
363
|
+
retryInterval: "Intervalo de reintento (ms)",
|
|
364
|
+
retryIntervalHint: "Espera fija antes de cada reintento HTTP. Rango: 0–300000.",
|
|
365
|
+
retryStatuses: "Códigos de estado HTTP con reintento",
|
|
366
|
+
retryStatusesHint: "Separados por comas, por ejemplo: 408, 425, 429, 500, 502, 503, 504.",
|
|
367
|
+
saveSettings: "Guardar ajustes",
|
|
368
|
+
savingSettings: "Guardando…",
|
|
369
|
+
reloadSettings: "Recargar",
|
|
370
|
+
loadingSettings: "Cargando…",
|
|
371
|
+
settingsSaved: "Ajustes guardados.",
|
|
372
|
+
settingsLoadFailed: "No se pudieron leer los ajustes de ejecución.",
|
|
373
|
+
settingsSaveFailed: "No se pudieron guardar los ajustes de ejecución.",
|
|
374
|
+
settingsInvalid: "Comprueba las rondas de herramientas, los reintentos, el intervalo y los códigos de estado HTTP.",
|
|
375
|
+
};
|
|
376
|
+
const fr = {
|
|
377
|
+
nav: "Cursor",
|
|
378
|
+
title: "Abonnement Cursor",
|
|
379
|
+
connected: "Connecté",
|
|
380
|
+
disconnected: "Non connecté",
|
|
381
|
+
accountLoading: "Lecture de l'état du compte…",
|
|
382
|
+
login: "Se connecter via le navigateur",
|
|
383
|
+
logout: "Se déconnecter",
|
|
384
|
+
cancel: "Annuler",
|
|
385
|
+
openLogin: "Ouvrir la page de connexion",
|
|
386
|
+
waiting: "En attente de la fin de la connexion…",
|
|
387
|
+
failed: "Échec de la connexion. Réessayez.",
|
|
388
|
+
loadFailed: "Impossible de lire l'état de Cursor.",
|
|
389
|
+
note: "Après vous être connecté à un compte Cursor dans le navigateur, les modèles de l'abonnement Cursor apparaissent dans le sélecteur de modèles. Les identifiants restent sur cette machine.",
|
|
390
|
+
expiresAt: "Jeton valide jusqu'au {value}",
|
|
391
|
+
usage: "Utilisation de l'abonnement",
|
|
392
|
+
usageRefresh: "Actualiser",
|
|
393
|
+
usageRefreshing: "Actualisation…",
|
|
394
|
+
usageNotSignedIn: "Connectez-vous pour consulter l'utilisation signalée par Cursor.",
|
|
395
|
+
usageLoading: "Lecture de l'utilisation…",
|
|
396
|
+
usageUpdated: "Mis à jour {value}",
|
|
397
|
+
plan: "Forfait",
|
|
398
|
+
unlimited: "Illimité",
|
|
399
|
+
includedRequests: "Requêtes incluses",
|
|
400
|
+
requestsUsed: "{used} / {limit} requêtes utilisées ({pct} %)",
|
|
401
|
+
onDemandSpend: "Dépenses à la demande",
|
|
402
|
+
autoUsage: "Utilisation des modèles Cursor du forfait",
|
|
403
|
+
otherModels: "Utilisation des autres modèles du forfait",
|
|
404
|
+
modelUsage: "Utilisation par modèle",
|
|
405
|
+
spendUsedOf: "${used} / ${limit} dépensés",
|
|
406
|
+
billingCycle: "Cycle de facturation",
|
|
407
|
+
billingDaysLeft: "{value} jours restants",
|
|
408
|
+
autoPercent: "Modèles Cursor du forfait {value} %",
|
|
409
|
+
otherModelsPercent: "Autres modèles du forfait {value} %",
|
|
410
|
+
otherModelsUnknown: "Cette valeur d'utilisation n'a pas encore été lue",
|
|
411
|
+
modelSpendPct: "{model} ${used} ({pct} %)",
|
|
412
|
+
models: "Modèles",
|
|
413
|
+
modelsRefresh: "Actualiser les modèles",
|
|
414
|
+
modelsRefreshing: "Actualisation…",
|
|
415
|
+
modelsCount: "{value} modèles",
|
|
416
|
+
modelsLoading: "Lecture de la liste des modèles…",
|
|
417
|
+
runtimeSettings: "Paramètres d'exécution",
|
|
418
|
+
runtimeSettingsNote: "Les paramètres sont enregistrés dans le profile DSH actuel et s'appliquent à partir de la prochaine requête Cursor.",
|
|
419
|
+
maxToolRounds: "Nombre maximal de tours d'outils",
|
|
420
|
+
maxToolRoundsHint: "Tours d'outils autorisés dans une tâche Cursor avant l'arrêt par TOOL_LIMIT. Plage : 1–1000.",
|
|
421
|
+
retryCount: "Nombre de tentatives",
|
|
422
|
+
retryCountHint: "Tentatives supplémentaires pour les statuts correspondants. Par défaut : 0 (désactivé). Activer les tentatives peut répéter le travail ou l'utilisation du modèle Cursor distant. Plage : 0–10.",
|
|
423
|
+
retryInterval: "Intervalle de nouvelle tentative (ms)",
|
|
424
|
+
retryIntervalHint: "Délai fixe avant chaque nouvelle tentative HTTP. Plage : 0–300000.",
|
|
425
|
+
retryStatuses: "Codes d'état HTTP à réessayer",
|
|
426
|
+
retryStatusesHint: "Séparés par des virgules, par exemple : 408, 425, 429, 500, 502, 503, 504.",
|
|
427
|
+
saveSettings: "Enregistrer les paramètres",
|
|
428
|
+
savingSettings: "Enregistrement…",
|
|
429
|
+
reloadSettings: "Recharger",
|
|
430
|
+
loadingSettings: "Chargement…",
|
|
431
|
+
settingsSaved: "Paramètres enregistrés.",
|
|
432
|
+
settingsLoadFailed: "Impossible de lire les paramètres d'exécution.",
|
|
433
|
+
settingsSaveFailed: "Impossible d'enregistrer les paramètres d'exécution.",
|
|
434
|
+
settingsInvalid: "Vérifiez les tours d'outils, le nombre de tentatives, l'intervalle et les codes d'état HTTP.",
|
|
435
|
+
};
|
|
436
|
+
const de = {
|
|
437
|
+
nav: "Cursor",
|
|
438
|
+
title: "Cursor-Abonnement",
|
|
439
|
+
connected: "Angemeldet",
|
|
440
|
+
disconnected: "Nicht angemeldet",
|
|
441
|
+
accountLoading: "Kontostatus wird gelesen…",
|
|
442
|
+
login: "Im Browser anmelden",
|
|
443
|
+
logout: "Abmelden",
|
|
444
|
+
cancel: "Abbrechen",
|
|
445
|
+
openLogin: "Anmeldeseite öffnen",
|
|
446
|
+
waiting: "Warten auf den Abschluss der Anmeldung…",
|
|
447
|
+
failed: "Anmeldung fehlgeschlagen. Bitte erneut versuchen.",
|
|
448
|
+
loadFailed: "Cursor-Status konnte nicht gelesen werden.",
|
|
449
|
+
note: "Nach der Anmeldung mit einem Cursor-Konto im Browser stehen die Modelle des Cursor-Abonnements in der Modellauswahl bereit. Die Anmeldedaten bleiben auf diesem Rechner.",
|
|
450
|
+
expiresAt: "Token gültig bis {value}",
|
|
451
|
+
usage: "Abonnement-Nutzung",
|
|
452
|
+
usageRefresh: "Aktualisieren",
|
|
453
|
+
usageRefreshing: "Wird aktualisiert…",
|
|
454
|
+
usageNotSignedIn: "Melden Sie sich an, um die von Cursor gemeldete Nutzung zu sehen.",
|
|
455
|
+
usageLoading: "Nutzung wird gelesen…",
|
|
456
|
+
usageUpdated: "Aktualisiert {value}",
|
|
457
|
+
plan: "Tarif",
|
|
458
|
+
unlimited: "Unbegrenzt",
|
|
459
|
+
includedRequests: "Enthaltene Anfragen",
|
|
460
|
+
requestsUsed: "{used} / {limit} Anfragen verwendet ({pct} %)",
|
|
461
|
+
onDemandSpend: "Nutzungsabhängige Ausgaben",
|
|
462
|
+
autoUsage: "Cursor-Modellnutzung des Tarifs",
|
|
463
|
+
otherModels: "Nutzung anderer Modelle des Tarifs",
|
|
464
|
+
modelUsage: "Nutzung je Modell",
|
|
465
|
+
spendUsedOf: "${used} / ${limit} ausgegeben",
|
|
466
|
+
billingCycle: "Abrechnungszeitraum",
|
|
467
|
+
billingDaysLeft: "Noch {value} Tage",
|
|
468
|
+
autoPercent: "Cursor-Modelle des Tarifs {value} %",
|
|
469
|
+
otherModelsPercent: "Andere Modelle des Tarifs {value} %",
|
|
470
|
+
otherModelsUnknown: "Dieser Nutzungswert wurde noch nicht gelesen",
|
|
471
|
+
modelSpendPct: "{model} ${used} ({pct} %)",
|
|
472
|
+
models: "Modelle",
|
|
473
|
+
modelsRefresh: "Modelle aktualisieren",
|
|
474
|
+
modelsRefreshing: "Wird aktualisiert…",
|
|
475
|
+
modelsCount: "{value} Modelle",
|
|
476
|
+
modelsLoading: "Modellliste wird gelesen…",
|
|
477
|
+
runtimeSettings: "Laufzeiteinstellungen",
|
|
478
|
+
runtimeSettingsNote: "Einstellungen werden im aktuellen DSH-profile gespeichert und gelten ab der nächsten Cursor-Anfrage.",
|
|
479
|
+
maxToolRounds: "Maximale Tool-Runden",
|
|
480
|
+
maxToolRoundsHint: "Erlaubte Tool-Runden in einer Cursor-Aufgabe, bevor TOOL_LIMIT abbricht. Bereich: 1–1000.",
|
|
481
|
+
retryCount: "Anzahl der Wiederholungen",
|
|
482
|
+
retryCountHint: "Zusätzliche Versuche bei passenden Statuscodes. Standard: 0 (aus). Aktivierte Wiederholungen können Remote-Arbeit oder Nutzung des Cursor-Modells duplizieren. Bereich: 0–10.",
|
|
483
|
+
retryInterval: "Wiederholungsintervall (ms)",
|
|
484
|
+
retryIntervalHint: "Feste Wartezeit vor jedem HTTP-Wiederholungsversuch. Bereich: 0–300000.",
|
|
485
|
+
retryStatuses: "HTTP-Statuscodes für Wiederholung",
|
|
486
|
+
retryStatusesHint: "Kommagetrennt, zum Beispiel: 408, 425, 429, 500, 502, 503, 504.",
|
|
487
|
+
saveSettings: "Einstellungen speichern",
|
|
488
|
+
savingSettings: "Wird gespeichert…",
|
|
489
|
+
reloadSettings: "Neu laden",
|
|
490
|
+
loadingSettings: "Wird geladen…",
|
|
491
|
+
settingsSaved: "Einstellungen gespeichert.",
|
|
492
|
+
settingsLoadFailed: "Laufzeiteinstellungen konnten nicht gelesen werden.",
|
|
493
|
+
settingsSaveFailed: "Laufzeiteinstellungen konnten nicht gespeichert werden.",
|
|
494
|
+
settingsInvalid: "Prüfen Sie Tool-Runden, Anzahl der Wiederholungen, Intervall und HTTP-Statuscodes.",
|
|
495
|
+
};
|
|
496
|
+
const ru = {
|
|
497
|
+
nav: "Cursor",
|
|
498
|
+
title: "Подписка Cursor",
|
|
499
|
+
connected: "Вход выполнен",
|
|
500
|
+
disconnected: "Вход не выполнен",
|
|
501
|
+
accountLoading: "Чтение состояния аккаунта…",
|
|
502
|
+
login: "Войти через браузер",
|
|
503
|
+
logout: "Выйти",
|
|
504
|
+
cancel: "Отмена",
|
|
505
|
+
openLogin: "Открыть страницу входа",
|
|
506
|
+
waiting: "Ожидание завершения входа…",
|
|
507
|
+
failed: "Не удалось войти. Повторите попытку.",
|
|
508
|
+
loadFailed: "Не удалось прочитать состояние Cursor.",
|
|
509
|
+
note: "После входа в аккаунт Cursor в браузере модели подписки Cursor появятся в выборе моделей. Учётные данные остаются на этом компьютере.",
|
|
510
|
+
expiresAt: "Токен действителен до {value}",
|
|
511
|
+
usage: "Использование подписки",
|
|
512
|
+
usageRefresh: "Обновить",
|
|
513
|
+
usageRefreshing: "Обновление…",
|
|
514
|
+
usageNotSignedIn: "Войдите, чтобы увидеть использование, о котором сообщает Cursor.",
|
|
515
|
+
usageLoading: "Чтение использования…",
|
|
516
|
+
usageUpdated: "Обновлено {value}",
|
|
517
|
+
plan: "Тариф",
|
|
518
|
+
unlimited: "Без ограничений",
|
|
519
|
+
includedRequests: "Включённые запросы",
|
|
520
|
+
requestsUsed: "Использовано {used} / {limit} запросов ({pct}%)",
|
|
521
|
+
onDemandSpend: "Расходы по требованию",
|
|
522
|
+
autoUsage: "Использование моделей Cursor по тарифу",
|
|
523
|
+
otherModels: "Использование других моделей по тарифу",
|
|
524
|
+
modelUsage: "Использование по моделям",
|
|
525
|
+
spendUsedOf: "Потрачено ${used} / ${limit}",
|
|
526
|
+
billingCycle: "Расчётный период",
|
|
527
|
+
billingDaysLeft: "Осталось {value} дн.",
|
|
528
|
+
autoPercent: "Модели Cursor по тарифу {value}%",
|
|
529
|
+
otherModelsPercent: "Другие модели по тарифу {value}%",
|
|
530
|
+
otherModelsUnknown: "Это значение использования ещё не прочитано",
|
|
531
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
532
|
+
models: "Модели",
|
|
533
|
+
modelsRefresh: "Обновить модели",
|
|
534
|
+
modelsRefreshing: "Обновление…",
|
|
535
|
+
modelsCount: "Моделей: {value}",
|
|
536
|
+
modelsLoading: "Чтение списка моделей…",
|
|
537
|
+
runtimeSettings: "Параметры выполнения",
|
|
538
|
+
runtimeSettingsNote: "Параметры сохраняются в текущем profile DSH и применяются со следующего запроса к Cursor.",
|
|
539
|
+
maxToolRounds: "Максимум раундов инструментов",
|
|
540
|
+
maxToolRoundsHint: "Раунды инструментов, разрешённые в одной задаче Cursor, после чего срабатывает TOOL_LIMIT. Диапазон: 1–1000.",
|
|
541
|
+
retryCount: "Число повторов",
|
|
542
|
+
retryCountHint: "Дополнительные попытки для совпадающих статусов. По умолчанию: 0 (выключено). Включение повторов может продублировать работу удалённой модели Cursor или расход. Диапазон: 0–10.",
|
|
543
|
+
retryInterval: "Интервал повтора (мс)",
|
|
544
|
+
retryIntervalHint: "Фиксированная задержка перед каждым повтором HTTP. Диапазон: 0–300000.",
|
|
545
|
+
retryStatuses: "HTTP-статусы для повтора",
|
|
546
|
+
retryStatusesHint: "Через запятую, например: 408, 425, 429, 500, 502, 503, 504.",
|
|
547
|
+
saveSettings: "Сохранить параметры",
|
|
548
|
+
savingSettings: "Сохранение…",
|
|
549
|
+
reloadSettings: "Перезагрузить",
|
|
550
|
+
loadingSettings: "Загрузка…",
|
|
551
|
+
settingsSaved: "Параметры сохранены.",
|
|
552
|
+
settingsLoadFailed: "Не удалось прочитать параметры выполнения.",
|
|
553
|
+
settingsSaveFailed: "Не удалось сохранить параметры выполнения.",
|
|
554
|
+
settingsInvalid: "Проверьте раунды инструментов, число повторов, интервал и HTTP-статусы.",
|
|
555
|
+
};
|
|
556
|
+
const ptBr = {
|
|
557
|
+
nav: "Cursor",
|
|
558
|
+
title: "Assinatura do Cursor",
|
|
559
|
+
connected: "Conectado",
|
|
560
|
+
disconnected: "Não conectado",
|
|
561
|
+
accountLoading: "Lendo o status da conta…",
|
|
562
|
+
login: "Entrar pelo navegador",
|
|
563
|
+
logout: "Sair",
|
|
564
|
+
cancel: "Cancelar",
|
|
565
|
+
openLogin: "Abrir a página de login",
|
|
566
|
+
waiting: "Aguardando a conclusão do login…",
|
|
567
|
+
failed: "Falha no login. Tente novamente.",
|
|
568
|
+
loadFailed: "Não foi possível ler o estado do Cursor.",
|
|
569
|
+
note: "Depois de entrar com uma conta Cursor no navegador, os modelos da assinatura do Cursor ficam disponíveis no seletor de modelos. As credenciais permanecem neste computador.",
|
|
570
|
+
expiresAt: "Token válido até {value}",
|
|
571
|
+
usage: "Uso da assinatura",
|
|
572
|
+
usageRefresh: "Atualizar",
|
|
573
|
+
usageRefreshing: "Atualizando…",
|
|
574
|
+
usageNotSignedIn: "Entre para ver o uso informado pelo Cursor.",
|
|
575
|
+
usageLoading: "Lendo o uso…",
|
|
576
|
+
usageUpdated: "Atualizado em {value}",
|
|
577
|
+
plan: "Plano",
|
|
578
|
+
unlimited: "Ilimitado",
|
|
579
|
+
includedRequests: "Requisições incluídas",
|
|
580
|
+
requestsUsed: "{used} / {limit} requisições usadas ({pct}%)",
|
|
581
|
+
onDemandSpend: "Gasto sob demanda",
|
|
582
|
+
autoUsage: "Uso dos modelos Cursor do plano",
|
|
583
|
+
otherModels: "Uso de outros modelos do plano",
|
|
584
|
+
modelUsage: "Uso por modelo",
|
|
585
|
+
spendUsedOf: "${used} / ${limit} gastos",
|
|
586
|
+
billingCycle: "Ciclo de cobrança",
|
|
587
|
+
billingDaysLeft: "{value} dias restantes",
|
|
588
|
+
autoPercent: "Modelos Cursor do plano {value}%",
|
|
589
|
+
otherModelsPercent: "Outros modelos do plano {value}%",
|
|
590
|
+
otherModelsUnknown: "Este valor de uso ainda não foi lido",
|
|
591
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
592
|
+
models: "Modelos",
|
|
593
|
+
modelsRefresh: "Atualizar modelos",
|
|
594
|
+
modelsRefreshing: "Atualizando…",
|
|
595
|
+
modelsCount: "{value} modelos",
|
|
596
|
+
modelsLoading: "Lendo a lista de modelos…",
|
|
597
|
+
runtimeSettings: "Configurações de execução",
|
|
598
|
+
runtimeSettingsNote: "As configurações são salvas no profile do DSH atual e valem a partir da próxima requisição ao Cursor.",
|
|
599
|
+
maxToolRounds: "Máximo de rodadas de ferramentas",
|
|
600
|
+
maxToolRoundsHint: "Rodadas de ferramentas permitidas em uma tarefa do Cursor antes de o TOOL_LIMIT interromper. Faixa: 1–1000.",
|
|
601
|
+
retryCount: "Número de tentativas",
|
|
602
|
+
retryCountHint: "Tentativas adicionais para os status correspondentes. Padrão: 0 (desativado). Ativar tentativas pode repetir trabalho ou uso do modelo remoto do Cursor. Faixa: 0–10.",
|
|
603
|
+
retryInterval: "Intervalo entre tentativas (ms)",
|
|
604
|
+
retryIntervalHint: "Espera fixa antes de cada nova tentativa HTTP. Faixa: 0–300000.",
|
|
605
|
+
retryStatuses: "Códigos de status HTTP com nova tentativa",
|
|
606
|
+
retryStatusesHint: "Separados por vírgula, por exemplo: 408, 425, 429, 500, 502, 503, 504.",
|
|
607
|
+
saveSettings: "Salvar configurações",
|
|
608
|
+
savingSettings: "Salvando…",
|
|
609
|
+
reloadSettings: "Recarregar",
|
|
610
|
+
loadingSettings: "Carregando…",
|
|
611
|
+
settingsSaved: "Configurações salvas.",
|
|
612
|
+
settingsLoadFailed: "Não foi possível ler as configurações de execução.",
|
|
613
|
+
settingsSaveFailed: "Não foi possível salvar as configurações de execução.",
|
|
614
|
+
settingsInvalid: "Verifique as rodadas de ferramentas, o número de tentativas, o intervalo e os códigos de status HTTP.",
|
|
615
|
+
};
|
|
616
|
+
const it = {
|
|
617
|
+
nav: "Cursor",
|
|
618
|
+
title: "Abbonamento Cursor",
|
|
619
|
+
connected: "Connesso",
|
|
620
|
+
disconnected: "Non connesso",
|
|
621
|
+
accountLoading: "Lettura dello stato dell'account…",
|
|
622
|
+
login: "Accedi dal browser",
|
|
623
|
+
logout: "Esci",
|
|
624
|
+
cancel: "Annulla",
|
|
625
|
+
openLogin: "Apri la pagina di accesso",
|
|
626
|
+
waiting: "In attesa del completamento dell'accesso…",
|
|
627
|
+
failed: "Accesso non riuscito. Riprova.",
|
|
628
|
+
loadFailed: "Impossibile leggere lo stato di Cursor.",
|
|
629
|
+
note: "Dopo aver eseguito l'accesso con un account Cursor nel browser, i modelli dell'abbonamento Cursor saranno disponibili nel selettore dei modelli. Le credenziali restano su questo computer.",
|
|
630
|
+
expiresAt: "Token valido fino al {value}",
|
|
631
|
+
usage: "Utilizzo dell'abbonamento",
|
|
632
|
+
usageRefresh: "Aggiorna",
|
|
633
|
+
usageRefreshing: "Aggiornamento…",
|
|
634
|
+
usageNotSignedIn: "Accedi per vedere l'utilizzo comunicato da Cursor.",
|
|
635
|
+
usageLoading: "Lettura dell'utilizzo…",
|
|
636
|
+
usageUpdated: "Aggiornato {value}",
|
|
637
|
+
plan: "Piano",
|
|
638
|
+
unlimited: "Illimitato",
|
|
639
|
+
includedRequests: "Richieste incluse",
|
|
640
|
+
requestsUsed: "{used} / {limit} richieste usate ({pct}%)",
|
|
641
|
+
onDemandSpend: "Spesa on demand",
|
|
642
|
+
autoUsage: "Utilizzo dei modelli Cursor del piano",
|
|
643
|
+
otherModels: "Utilizzo degli altri modelli del piano",
|
|
644
|
+
modelUsage: "Utilizzo per modello",
|
|
645
|
+
spendUsedOf: "${used} / ${limit} spesi",
|
|
646
|
+
billingCycle: "Ciclo di fatturazione",
|
|
647
|
+
billingDaysLeft: "{value} giorni rimanenti",
|
|
648
|
+
autoPercent: "Modelli Cursor del piano {value}%",
|
|
649
|
+
otherModelsPercent: "Altri modelli del piano {value}%",
|
|
650
|
+
otherModelsUnknown: "Questo valore di utilizzo non è ancora stato letto",
|
|
651
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
652
|
+
models: "Modelli",
|
|
653
|
+
modelsRefresh: "Aggiorna i modelli",
|
|
654
|
+
modelsRefreshing: "Aggiornamento…",
|
|
655
|
+
modelsCount: "{value} modelli",
|
|
656
|
+
modelsLoading: "Lettura dell'elenco dei modelli…",
|
|
657
|
+
runtimeSettings: "Impostazioni di esecuzione",
|
|
658
|
+
runtimeSettingsNote: "Le impostazioni vengono salvate nel profile DSH corrente e si applicano dalla successiva richiesta a Cursor.",
|
|
659
|
+
maxToolRounds: "Numero massimo di round di strumenti",
|
|
660
|
+
maxToolRoundsHint: "Round di strumenti consentiti in un'attività Cursor prima che TOOL_LIMIT la interrompa. Intervallo: 1–1000.",
|
|
661
|
+
retryCount: "Numero di tentativi",
|
|
662
|
+
retryCountHint: "Tentativi aggiuntivi per gli stati corrispondenti. Predefinito: 0 (disattivato). Attivare i tentativi può ripetere lavoro o utilizzo del modello Cursor remoto. Intervallo: 0–10.",
|
|
663
|
+
retryInterval: "Intervallo tra tentativi (ms)",
|
|
664
|
+
retryIntervalHint: "Attesa fissa prima di ogni nuovo tentativo HTTP. Intervallo: 0–300000.",
|
|
665
|
+
retryStatuses: "Codici di stato HTTP da ritentare",
|
|
666
|
+
retryStatusesHint: "Separati da virgole, ad esempio: 408, 425, 429, 500, 502, 503, 504.",
|
|
667
|
+
saveSettings: "Salva impostazioni",
|
|
668
|
+
savingSettings: "Salvataggio…",
|
|
669
|
+
reloadSettings: "Ricarica",
|
|
670
|
+
loadingSettings: "Caricamento…",
|
|
671
|
+
settingsSaved: "Impostazioni salvate.",
|
|
672
|
+
settingsLoadFailed: "Impossibile leggere le impostazioni di esecuzione.",
|
|
673
|
+
settingsSaveFailed: "Impossibile salvare le impostazioni di esecuzione.",
|
|
674
|
+
settingsInvalid: "Controlla i round di strumenti, il numero di tentativi, l'intervallo e i codici di stato HTTP.",
|
|
675
|
+
};
|
|
676
|
+
const ar = {
|
|
677
|
+
nav: "Cursor",
|
|
678
|
+
title: "اشتراك Cursor",
|
|
679
|
+
connected: "تم تسجيل الدخول",
|
|
680
|
+
disconnected: "لم يتم تسجيل الدخول",
|
|
681
|
+
accountLoading: "جارٍ قراءة حالة الحساب…",
|
|
682
|
+
login: "تسجيل الدخول عبر المتصفح",
|
|
683
|
+
logout: "تسجيل الخروج",
|
|
684
|
+
cancel: "إلغاء",
|
|
685
|
+
openLogin: "فتح صفحة تسجيل الدخول",
|
|
686
|
+
waiting: "في انتظار اكتمال تسجيل الدخول…",
|
|
687
|
+
failed: "فشل تسجيل الدخول. حاول مرة أخرى.",
|
|
688
|
+
loadFailed: "تعذّر قراءة حالة Cursor.",
|
|
689
|
+
note: "بعد تسجيل الدخول بحساب Cursor في المتصفح، تصبح نماذج اشتراك Cursor متاحة في منتقي النماذج. تبقى بيانات الاعتماد على هذا الجهاز.",
|
|
690
|
+
expiresAt: "الرمز صالح حتى {value}",
|
|
691
|
+
usage: "استخدام الاشتراك",
|
|
692
|
+
usageRefresh: "تحديث",
|
|
693
|
+
usageRefreshing: "جارٍ التحديث…",
|
|
694
|
+
usageNotSignedIn: "سجّل الدخول لعرض الاستخدام الذي يبلّغ عنه Cursor.",
|
|
695
|
+
usageLoading: "جارٍ قراءة الاستخدام…",
|
|
696
|
+
usageUpdated: "حُدّث في {value}",
|
|
697
|
+
plan: "الخطة",
|
|
698
|
+
unlimited: "غير محدود",
|
|
699
|
+
includedRequests: "الطلبات المضمّنة",
|
|
700
|
+
requestsUsed: "استُخدم {used} / {limit} طلبًا ({pct}%)",
|
|
701
|
+
onDemandSpend: "الإنفاق عند الطلب",
|
|
702
|
+
autoUsage: "استخدام نماذج Cursor في الخطة",
|
|
703
|
+
otherModels: "استخدام النماذج الأخرى في الخطة",
|
|
704
|
+
modelUsage: "الاستخدام حسب النموذج",
|
|
705
|
+
spendUsedOf: "أُنفق ${used} / ${limit}",
|
|
706
|
+
billingCycle: "دورة الفوترة",
|
|
707
|
+
billingDaysLeft: "بقي {value} يومًا",
|
|
708
|
+
autoPercent: "نماذج Cursor في الخطة {value}%",
|
|
709
|
+
otherModelsPercent: "النماذج الأخرى في الخطة {value}%",
|
|
710
|
+
otherModelsUnknown: "لم تُقرأ قيمة الاستخدام هذه بعد",
|
|
711
|
+
modelSpendPct: "{model} ${used} ({pct}%)",
|
|
712
|
+
models: "النماذج",
|
|
713
|
+
modelsRefresh: "تحديث النماذج",
|
|
714
|
+
modelsRefreshing: "جارٍ التحديث…",
|
|
715
|
+
modelsCount: "{value} نموذجًا",
|
|
716
|
+
modelsLoading: "جارٍ قراءة قائمة النماذج…",
|
|
717
|
+
runtimeSettings: "إعدادات التشغيل",
|
|
718
|
+
runtimeSettingsNote: "تُحفظ الإعدادات في profile DSH الحالي وتُطبَّق بدءًا من طلب Cursor التالي.",
|
|
719
|
+
maxToolRounds: "الحد الأقصى لجولات الأدوات",
|
|
720
|
+
maxToolRoundsHint: "جولات الأدوات المسموح بها في مهمة Cursor واحدة قبل أن يوقفها TOOL_LIMIT. النطاق: 1–1000.",
|
|
721
|
+
retryCount: "عدد المحاولات",
|
|
722
|
+
retryCountHint: "محاولات إضافية لحالات الاستجابة المطابقة. الافتراضي: 0 (معطّل). قد يؤدي تفعيل المحاولات إلى تكرار عمل النموذج البعيد في Cursor أو استخدامه. النطاق: 0–10.",
|
|
723
|
+
retryInterval: "الفاصل بين المحاولات (مللي ثانية)",
|
|
724
|
+
retryIntervalHint: "انتظار ثابت قبل كل محاولة HTTP جديدة. النطاق: 0–300000.",
|
|
725
|
+
retryStatuses: "رموز حالة HTTP المُعاد المحاولة فيها",
|
|
726
|
+
retryStatusesHint: "مفصولة بفواصل، مثل: 408, 425, 429, 500, 502, 503, 504.",
|
|
727
|
+
saveSettings: "حفظ الإعدادات",
|
|
728
|
+
savingSettings: "جارٍ الحفظ…",
|
|
729
|
+
reloadSettings: "إعادة التحميل",
|
|
730
|
+
loadingSettings: "جارٍ التحميل…",
|
|
731
|
+
settingsSaved: "تم حفظ الإعدادات.",
|
|
732
|
+
settingsLoadFailed: "تعذّر قراءة إعدادات التشغيل.",
|
|
733
|
+
settingsSaveFailed: "تعذّر حفظ إعدادات التشغيل.",
|
|
734
|
+
settingsInvalid: "تحقق من جولات الأدوات وعدد المحاولات والفاصل ورموز حالة HTTP.",
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
/** Every dictionary carries the same key set as `en`; a test enforces it. */
|
|
738
|
+
const DICTIONARIES = {
|
|
739
|
+
zh,
|
|
740
|
+
en,
|
|
741
|
+
"zh-Hant": zhHant,
|
|
742
|
+
ja,
|
|
743
|
+
ko,
|
|
744
|
+
es,
|
|
745
|
+
fr,
|
|
746
|
+
de,
|
|
747
|
+
it,
|
|
748
|
+
"pt-BR": ptBr,
|
|
749
|
+
ru,
|
|
750
|
+
ar,
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Languages this panel contributes to the DSH catalog. DSH ships `zh` and
|
|
755
|
+
* `en` only, so every other language joins the shared catalog through
|
|
756
|
+
* `locale.addLanguage` and then appears in Settings -> General -> Language.
|
|
757
|
+
* Each one falls back to `en`, which keeps the rest of the DSH shell
|
|
758
|
+
* readable for a reader of a contributed language.
|
|
759
|
+
*/
|
|
760
|
+
const LANGUAGES = [
|
|
761
|
+
{ id: "zh-Hant", label: "繁體中文", fallback: "zh" },
|
|
762
|
+
{ id: "ja", label: "日本語", fallback: "en" },
|
|
763
|
+
{ id: "ko", label: "한국어", fallback: "en" },
|
|
764
|
+
{ id: "es", label: "Español", fallback: "en" },
|
|
765
|
+
{ id: "fr", label: "Français", fallback: "en" },
|
|
766
|
+
{ id: "de", label: "Deutsch", fallback: "en" },
|
|
767
|
+
{ id: "it", label: "Italiano", fallback: "en" },
|
|
768
|
+
{ id: "pt-BR", label: "Português (Brasil)", fallback: "en" },
|
|
769
|
+
{ id: "ru", label: "Русский", fallback: "en" },
|
|
770
|
+
{ id: "ar", label: "العربية", fallback: "en" },
|
|
771
|
+
];
|
|
772
|
+
|
|
773
|
+
/** Contributed locales written right to left; the panel mirrors for these. */
|
|
774
|
+
const RTL_LOCALES = new Set(["ar"]);
|
|
775
|
+
/** Marker the stylesheet keys the mirrored rules on. */
|
|
776
|
+
const RTL_ATTRIBUTE = "cursorSubscriptionRtl";
|
|
143
777
|
|
|
144
778
|
const STYLE = `
|
|
145
779
|
.cursorSubscription{display:flex;flex-direction:column;gap:10px;max-width:720px;color:var(--dsw-alias-label-primary);container-type:inline-size}
|
|
@@ -158,6 +792,7 @@ window.__ModuleLoader__.load({
|
|
|
158
792
|
.cursorSubscriptionFlow p{font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary)}
|
|
159
793
|
.cursorSubscriptionError{font-size:13px;line-height:20px;color:var(--dsw-alias-state-error-primary)}
|
|
160
794
|
.cursorSubscriptionNote{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
795
|
+
.cursorSubscriptionVersion{font:500 11px/17px ui-monospace,SFMono-Regular,Consolas,monospace;color:var(--dsw-alias-label-tertiary);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:1px 6px;direction:ltr}
|
|
161
796
|
.cursorSubscriptionFreshness{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
162
797
|
.cursorSubscriptionSectionHead{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
163
798
|
.cursorSubscriptionSectionTitle{display:flex;flex:1;min-width:0;flex-direction:column;gap:2px}
|
|
@@ -188,6 +823,10 @@ window.__ModuleLoader__.load({
|
|
|
188
823
|
.cursorSubscriptionFieldHint{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
189
824
|
.cursorSubscriptionSettingsFoot{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
|
|
190
825
|
.cursorSubscriptionSuccess{font-size:12px;line-height:18px;color:var(--dsw-alias-state-success-primary)}
|
|
826
|
+
html[data-cursor-subscription-rtl] .cursorSubscription{direction:rtl}
|
|
827
|
+
html[data-cursor-subscription-rtl] .cursorSubscriptionUsageRow progress{direction:rtl}
|
|
828
|
+
html[data-cursor-subscription-rtl] .cursorSubscriptionField input{direction:ltr;text-align:left}
|
|
829
|
+
html[data-cursor-subscription-rtl] .cursorSubscriptionModelChip{direction:ltr}
|
|
191
830
|
@container (max-width:520px){.cursorSubscriptionSettingsGrid{grid-template-columns:1fr}.cursorSubscriptionFieldWide{grid-column:auto}}
|
|
192
831
|
`;
|
|
193
832
|
|
|
@@ -195,6 +834,25 @@ window.__ModuleLoader__.load({
|
|
|
195
834
|
if (!response?.ok) throw new Error(response?.error?.message ?? "Cursor RPC failed");
|
|
196
835
|
return response.value;
|
|
197
836
|
};
|
|
837
|
+
/**
|
|
838
|
+
* Label one reported build version for the panel header.
|
|
839
|
+
* @param value - version string reported by the Host.
|
|
840
|
+
* @returns the `v`-prefixed label, or undefined when nothing usable was reported.
|
|
841
|
+
*/
|
|
842
|
+
const formatVersion = (value) => (typeof value === "string" && value.trim() !== "" ? `v${value.trim()}` : undefined);
|
|
843
|
+
/**
|
|
844
|
+
* Read the serving build's version through the account channel.
|
|
845
|
+
* @param rpc - connection RPC client bound to this panel.
|
|
846
|
+
* @returns the label, or undefined when the call fails or answers without a version.
|
|
847
|
+
*/
|
|
848
|
+
const readVersion = async (rpc) => {
|
|
849
|
+
try {
|
|
850
|
+
const response = await rpc.call(CHANNEL, "version", {});
|
|
851
|
+
return response?.ok ? formatVersion(response.value?.version) : undefined;
|
|
852
|
+
} catch {
|
|
853
|
+
return undefined;
|
|
854
|
+
}
|
|
855
|
+
};
|
|
198
856
|
const fill = (text, values) => Object.entries(values).reduce((next, [key, value]) => next.replace(`{${key}}`, String(value)), text);
|
|
199
857
|
const validDate = (value) => {
|
|
200
858
|
const date = new Date(value);
|
|
@@ -780,6 +1438,16 @@ window.__ModuleLoader__.load({
|
|
|
780
1438
|
const [account, setAccount] = react.useState();
|
|
781
1439
|
const [error, setError] = react.useState();
|
|
782
1440
|
const [resetKey, setResetKey] = react.useState(0);
|
|
1441
|
+
const [version, setVersion] = react.useState();
|
|
1442
|
+
react.useEffect(() => {
|
|
1443
|
+
let live = true;
|
|
1444
|
+
readVersion(rpc).then((label) => {
|
|
1445
|
+
if (live) setVersion(label);
|
|
1446
|
+
});
|
|
1447
|
+
return () => {
|
|
1448
|
+
live = false;
|
|
1449
|
+
};
|
|
1450
|
+
}, []);
|
|
783
1451
|
react.useEffect(() => {
|
|
784
1452
|
let live = true;
|
|
785
1453
|
rpc.call(CHANNEL, "status", {})
|
|
@@ -800,7 +1468,16 @@ window.__ModuleLoader__.load({
|
|
|
800
1468
|
children: [
|
|
801
1469
|
react_jsx_runtime.jsx("div", {
|
|
802
1470
|
className: "cursorSubscriptionHead",
|
|
803
|
-
children:
|
|
1471
|
+
children: [
|
|
1472
|
+
react_jsx_runtime.jsx("h2", { children: t("title") }),
|
|
1473
|
+
version === undefined
|
|
1474
|
+
? null
|
|
1475
|
+
: react_jsx_runtime.jsx("span", {
|
|
1476
|
+
className: "cursorSubscriptionVersion",
|
|
1477
|
+
title: `dsh-cursor-subscription ${version}`,
|
|
1478
|
+
children: version,
|
|
1479
|
+
}),
|
|
1480
|
+
],
|
|
804
1481
|
}),
|
|
805
1482
|
error === undefined
|
|
806
1483
|
? null
|
|
@@ -821,7 +1498,43 @@ window.__ModuleLoader__.load({
|
|
|
821
1498
|
}
|
|
822
1499
|
|
|
823
1500
|
function apply(ctx) {
|
|
824
|
-
ctx.effect(() => ctx.locale.register(NS,
|
|
1501
|
+
ctx.effect(() => ctx.locale.register(NS, DICTIONARIES), "cursor-subscription: copy");
|
|
1502
|
+
// Contribute the panel's extra languages to the shared catalog. A locale
|
|
1503
|
+
// id may already be owned by DSH itself or by another language pack: that
|
|
1504
|
+
// is not an error, the dictionary above simply joins the existing one. An
|
|
1505
|
+
// older locale runtime without language packs has no `addLanguage`, which
|
|
1506
|
+
// leaves the built-in zh/en panel in place instead of failing the client.
|
|
1507
|
+
ctx.effect(() => {
|
|
1508
|
+
const disposers = [];
|
|
1509
|
+
for (const language of LANGUAGES) {
|
|
1510
|
+
const taken = ctx.locale.getLocale().locales.some((entry) => entry.id === language.id);
|
|
1511
|
+
if (taken) continue;
|
|
1512
|
+
try {
|
|
1513
|
+
disposers.push(ctx.locale.addLanguage(language));
|
|
1514
|
+
} catch {
|
|
1515
|
+
/* an occupied id or an unavailable fallback leaves the panel working */
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return () => {
|
|
1519
|
+
for (const dispose of disposers) dispose();
|
|
1520
|
+
};
|
|
1521
|
+
}, "cursor-subscription: languages");
|
|
1522
|
+
// Mirror the panel while a right-to-left language is active. The marker
|
|
1523
|
+
// rides the document element so the stylesheet can scope it; nothing else
|
|
1524
|
+
// in the shell is affected.
|
|
1525
|
+
ctx.effect(() => {
|
|
1526
|
+
const root = document.documentElement;
|
|
1527
|
+
const sync = () => {
|
|
1528
|
+
if (RTL_LOCALES.has(ctx.locale.getLocale().active)) root.dataset[RTL_ATTRIBUTE] = "";
|
|
1529
|
+
else delete root.dataset[RTL_ATTRIBUTE];
|
|
1530
|
+
};
|
|
1531
|
+
sync();
|
|
1532
|
+
const off = ctx.locale.subscribe(sync);
|
|
1533
|
+
return () => {
|
|
1534
|
+
off();
|
|
1535
|
+
delete root.dataset[RTL_ATTRIBUTE];
|
|
1536
|
+
};
|
|
1537
|
+
}, "cursor-subscription: direction");
|
|
825
1538
|
ctx.effect(() => {
|
|
826
1539
|
const tag = document.createElement("style");
|
|
827
1540
|
tag.dataset.plugin = "dsh-cursor-subscription";
|
|
@@ -848,6 +1561,9 @@ window.__ModuleLoader__.load({
|
|
|
848
1561
|
//#endregion
|
|
849
1562
|
exports.apply = apply;
|
|
850
1563
|
exports.inject = inject;
|
|
1564
|
+
// Pure helpers the panel's tests pin; the DSH client module loader reads only apply/inject.
|
|
1565
|
+
exports.formatVersion = formatVersion;
|
|
1566
|
+
exports.readVersion = readVersion;
|
|
851
1567
|
return module.exports;
|
|
852
1568
|
},
|
|
853
1569
|
});
|
package/lib/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import z from "@deepseek-ai/schemastery";
|
|
|
17
17
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
18
18
|
import { ToolCallId, LlmAdapter, LlmError } from "@deepseek-ai/dsh-llm";
|
|
19
19
|
import { createHash, randomUUID } from "node:crypto";
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
20
21
|
import http2 from "node:http2";
|
|
21
22
|
import http from "node:http";
|
|
22
23
|
import https from "node:https";
|
|
@@ -24,6 +25,21 @@ import { spawn } from "node:child_process";
|
|
|
24
25
|
import { gunzipSync } from "node:zlib";
|
|
25
26
|
import { encodeValue, decodeValue, Reader, Writer } from "./proto.js";
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Read this package's own version from the manifest beside `lib/`.
|
|
30
|
+
* @returns the manifest version, or undefined when it cannot be read.
|
|
31
|
+
*/
|
|
32
|
+
function readVersion() {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
35
|
+
} catch {
|
|
36
|
+
/* An unreadable manifest leaves the version unknown instead of failing the plugin. */
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Build version the settings panel prints; undefined when the manifest is unreadable. */
|
|
41
|
+
export const VERSION = readVersion();
|
|
42
|
+
|
|
27
43
|
//#region native fetch
|
|
28
44
|
/**
|
|
29
45
|
* DSH web replaces the ambient `fetch` with an MCP `createFetchWithInit`
|
|
@@ -119,11 +135,13 @@ function makeResponse(status, res, data) {
|
|
|
119
135
|
|
|
120
136
|
//#region constants
|
|
121
137
|
export const name = "cursor-subscription";
|
|
122
|
-
export const inject = ["llm", "credentials", "connection"
|
|
138
|
+
export const inject = ["llm", "credentials", "connection"];
|
|
123
139
|
|
|
124
140
|
export const PROVIDER = "cursor-subscription";
|
|
125
141
|
export const CREDENTIAL_REF = credentialRef("CURSOR_SUBSCRIPTION_OAUTH");
|
|
126
142
|
export const CHANNEL = "/cursor-subscription";
|
|
143
|
+
/** Connection registry options: accept the account channel from loopback Hosts only. */
|
|
144
|
+
const LOOPBACK_RPC = Object.freeze({ authority: "loopback" });
|
|
127
145
|
|
|
128
146
|
export const CURSOR_BASE_URL = "https://api2.cursor.sh";
|
|
129
147
|
export const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
@@ -776,11 +794,15 @@ export function createCursorRpcHandler(coordinator, options = {}) {
|
|
|
776
794
|
const usageReader = options.usageReader;
|
|
777
795
|
const modelsProvider = options.modelsProvider;
|
|
778
796
|
const settingsController = options.settings;
|
|
797
|
+
const version = options.version ?? VERSION;
|
|
779
798
|
const publicError = (code, message) => ({ ok: false, error: { code, message, details: { issues: [] } } });
|
|
780
799
|
return async (endpoint, payload, signal) => {
|
|
781
800
|
try {
|
|
782
801
|
signal.throwIfAborted();
|
|
783
802
|
const input = asObject(payload);
|
|
803
|
+
// The panel labels itself with the build that is actually serving it, so the
|
|
804
|
+
// version never has to be duplicated into the browser bundle.
|
|
805
|
+
if (endpoint === "version") return ok({ version });
|
|
784
806
|
if (endpoint === "settings") return ok(settingsController.read());
|
|
785
807
|
if (endpoint === "settings/update") {
|
|
786
808
|
if (!Number.isSafeInteger(input.revision) || input.revision < 0) throw new Error("invalid Cursor settings revision");
|
|
@@ -2917,9 +2939,26 @@ export function apply(ctx, config = {}) {
|
|
|
2917
2939
|
modelsProvider: adapter,
|
|
2918
2940
|
settings: settingsController,
|
|
2919
2941
|
});
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2942
|
+
// Mount the loopback account channel through Connection. `rpc.handle`
|
|
2943
|
+
// registers the channel on the Context that reads the Connection service,
|
|
2944
|
+
// but resolves that Context's `webServer` through the providing plugin's own
|
|
2945
|
+
// scope, so it only works while the Connection plugin itself declares
|
|
2946
|
+
// `webServer`. @deepseek-ai/dsh-client-connection 0.1.5-rc.1 declares
|
|
2947
|
+
// `credentials` alone and mounts `/api` from a nested `webServer` Context, so
|
|
2948
|
+
// `rpc.handle` fails the entire plugin tree with
|
|
2949
|
+
// `cannot get property "webServer" without inject`. Calling the same registry
|
|
2950
|
+
// method Connection uses internally with an explicit owner Context that
|
|
2951
|
+
// declares `webServer` reuses Connection's envelope, trust fence, and browser
|
|
2952
|
+
// authentication, and keeps the route on this plugin's fiber. Fall back to
|
|
2953
|
+
// the public `rpc.handle` if that registry method ever disappears.
|
|
2954
|
+
ctx.inject(["connection", "webServer"], (webCtx) => {
|
|
2955
|
+
const connection = webCtx.connection;
|
|
2956
|
+
webCtx.effect(() => {
|
|
2957
|
+
if (typeof connection.register === "function") {
|
|
2958
|
+
return connection.register(webCtx, CHANNEL, handler, LOOPBACK_RPC);
|
|
2959
|
+
}
|
|
2960
|
+
return connection.rpc.handle(CHANNEL, handler, LOOPBACK_RPC);
|
|
2961
|
+
}, "cursor-subscription: loopback account RPC");
|
|
2962
|
+
});
|
|
2924
2963
|
}
|
|
2925
2964
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-cursor-subscription",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"packageManager": "pnpm@11.19.0",
|
|
5
5
|
"description": "Cursor subscription for DeepSeek Harness with browser login, token refresh, model discovery, and the Cursor Agent chat protocol",
|
|
6
6
|
"type": "module",
|