dsh-neartoken 0.9.0 → 0.11.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 +10 -4
- package/lib/client.js +209 -75
- package/lib/client.js.map +1 -1
- package/lib/index.js +312 -36
- package/lib/types/client/api.d.ts +5 -0
- package/lib/types/client/locales.d.ts +14 -0
- package/lib/types/host/account.d.ts +38 -2
- package/lib/types/host/browser.d.ts +21 -0
- package/lib/types/host/images.d.ts +17 -4
- package/lib/types/host/routes.d.ts +5 -0
- package/lib/types/protocol.d.ts +29 -3
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
1. 装插件、重启 `dsh web`、硬刷新。
|
|
43
43
|
2. 打开 **设置 → NearToken**,点「连接 NearToken」。
|
|
44
44
|
3. 设置页显示确认码;点「打开浏览器确认」,在站点自己的页面登录(密码、2FA、passkey 都走站点原生流程)并批准。
|
|
45
|
+
这个按钮走 Host:页面自己 `window.open` 开出来的窗口会被困在承载页面的外壳里(Electron 桌面端会另开一个应用窗口、macOS 上甚至没有任何反应),所以由 Host 调平台启动器交给**系统默认浏览器**(macOS `open` / Windows `rundll32 url.dll,FileProtocolHandler` / Linux `xdg-open`)。地址固定取 Host 自己等待的那个,页面无法让 Host 打开任意 URL。
|
|
46
|
+
卡片同时把确认地址当作可选文字列出来(带「复制链接」按钮)—— 没有桌面环境的机器(远程、容器)启动器可能不存在,把地址贴进自己的浏览器即可。
|
|
45
47
|
4. 插件轮询到批准后自动完成:把站点为该插件铸造的 API key 写进 credentials 的 `NEARTOKEN_API_KEY`,并挂上 `neartoken` provider。
|
|
46
48
|
5. 「断开连接」删掉本地凭据、撤掉 provider,并调用站点的撤销端点。
|
|
47
49
|
6. 卡片下方的「模型白名单」勾选即自动保存 —— 未勾选的不再出现在模型选择器里,且当场生效(Host 用 `AdapterRegistrationHandle.replace()` 重新声明同一条路由,同步发布 `llm/adapters-updated`,浏览器重拉目录)。没设置过白名单时默认全部显示,「全部显示」清空白名单。
|
|
@@ -137,8 +139,11 @@
|
|
|
137
139
|
|
|
138
140
|
| 通道 | 判定 | 请求 | 响应 |
|
|
139
141
|
|---|---|---|---|
|
|
140
|
-
| `images` |
|
|
141
|
-
| `
|
|
142
|
+
| `images` | 声明含 `image-generation`(gpt-image 系) | `POST /v1/images/generations` | `data[0].b64_json` 或临时 `url` |
|
|
143
|
+
| `genai` | 声明含 `gemini`(nano-banana、`gemini-*-image`) | `POST /v1beta/models/<model>:generateContent` | `candidates[0].content.parts[].inlineData`(结构化) |
|
|
144
|
+
| `chat` | 其余(只有 `openai` 的,如 grok-imagine) | `POST /v1/chat/completions` | 回复文本里的 `data:image/...;base64,` 或图片链接 |
|
|
145
|
+
|
|
146
|
+
Gemini 系走原生 surface 而不是 openai 兼容层:同模型同提示词实测 **74 秒**(原生,返回 `inlineData`)对 **110 秒**(chat,返回 markdown data URL)。原生拿的是结构化字段,不用从文本里抠图,也不依赖网关的转换实现。
|
|
142
147
|
|
|
143
148
|
实测数据:`gpt-image-2.5-flare` 走促销分组 `#39` 约 43 秒返回 1.3 MB PNG(base64);`nano-banana-pro` 打 images 端点会被站点拒绝(`only imagen models are supported`),走 chat 才出图;`grok-imagine-image` 两条都通。拿到 bytes 后按 magic bytes 判格式(PNG/JPEG/WebP/GIF),再交给 attachment 服务落盘。
|
|
144
149
|
|
|
@@ -148,10 +153,11 @@
|
|
|
148
153
|
|
|
149
154
|
`images` 传工作区里的图片路径,工具读成 data URL 后按通道发送:
|
|
150
155
|
|
|
151
|
-
- **images 通道**:作为 `image`
|
|
156
|
+
- **images 通道**:作为 `image` 数组(data URL)发给 `/v1/images/generations`(站点 DTO 里没有可用的 `edits` 路由,参考图只能搭生成请求)
|
|
157
|
+
- **genai 通道**:作为 `inlineData` part 与提示词一起进 `contents[0].parts`
|
|
152
158
|
- **chat 通道**:作为 `image_url` content part 与提示词一起进 `messages`
|
|
153
159
|
|
|
154
|
-
实测(`nano-banana-pro` + 一张 2.1 MB 的 PNG 参考图):chat 通道 110
|
|
160
|
+
实测(`nano-banana-pro` + 一张 2.1 MB 的 PNG 参考图):chat 通道 110 秒出图返回 jpeg;同一模型单轮文生图走 genai 通道 74 秒返回 PNG。参考图在**发请求前**读盘并校验(存在、是普通文件、是 PNG/JPEG/WebP/GIF、≤ 20 MB),所以缺文件不会白花一次生成。
|
|
155
161
|
|
|
156
162
|
### 落盘
|
|
157
163
|
|
package/lib/client.js
CHANGED
|
@@ -10,7 +10,7 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
11
|
//#region src/protocol.ts
|
|
12
12
|
/**
|
|
13
|
-
* The wire vocabulary shared by the Host routes and the browser section:
|
|
13
|
+
* The wire vocabulary shared by the Host routes and the browser section: the
|
|
14
14
|
* route paths and the JSON each answers. Both build faces import this file, so
|
|
15
15
|
* a route rename cannot leave the browser calling a path the Host stopped
|
|
16
16
|
* serving.
|
|
@@ -27,6 +27,11 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
const AUTHORIZE_PATH = "/neartoken/authorize";
|
|
28
28
|
/** Abandon the authorization in progress. */
|
|
29
29
|
const CANCEL_PATH = "/neartoken/cancel";
|
|
30
|
+
/**
|
|
31
|
+
* Ask the Host to open the pending confirmation page in the user's own browser.
|
|
32
|
+
* The request carries no address: the Host opens the one it is waiting on.
|
|
33
|
+
*/
|
|
34
|
+
const OPEN_PATH = "/neartoken/open";
|
|
30
35
|
/** Forget the stored key and revoke it on the site. */
|
|
31
36
|
const LOGOUT_PATH = "/neartoken/logout";
|
|
32
37
|
/** Read the catalog beside the stored whitelist; POST a new whitelist. */
|
|
@@ -36,8 +41,8 @@ window.__ModuleLoader__.load({
|
|
|
36
41
|
//#endregion
|
|
37
42
|
//#region src/client/api.ts
|
|
38
43
|
/**
|
|
39
|
-
* The browser half of the settings-page carrier:
|
|
40
|
-
*
|
|
44
|
+
* The browser half of the settings-page carrier: same-origin calls to the Host
|
|
45
|
+
* routes declared in ../protocol.ts.
|
|
41
46
|
*
|
|
42
47
|
* @module
|
|
43
48
|
*/
|
|
@@ -73,6 +78,13 @@ window.__ModuleLoader__.load({
|
|
|
73
78
|
async cancel() {
|
|
74
79
|
await post(CANCEL_PATH);
|
|
75
80
|
},
|
|
81
|
+
async openBrowser() {
|
|
82
|
+
const response = await fetcher(OPEN_PATH, { method: "POST" });
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const refusal = await response.json().catch(() => ({ message: `HTTP ${String(response.status)}` }));
|
|
85
|
+
throw new Error(refusal.message ?? `HTTP ${String(response.status)}`);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
76
88
|
async signOut() {
|
|
77
89
|
await post(LOGOUT_PATH);
|
|
78
90
|
},
|
|
@@ -321,23 +333,23 @@ window.__ModuleLoader__.load({
|
|
|
321
333
|
document.head.appendChild(tag);
|
|
322
334
|
}
|
|
323
335
|
var group_tags_module_css_default = {
|
|
324
|
-
"toneOrange": "FotuUq_toneOrange",
|
|
325
336
|
"toneRose": "FotuUq_toneRose",
|
|
326
|
-
"tonePink": "FotuUq_tonePink",
|
|
327
337
|
"toneCyan": "FotuUq_toneCyan",
|
|
328
338
|
"toneTeal": "FotuUq_toneTeal",
|
|
329
|
-
"
|
|
330
|
-
"ratioBase": "FotuUq_ratioBase",
|
|
331
|
-
"tag": "FotuUq_tag",
|
|
332
|
-
"toneViolet": "FotuUq_toneViolet",
|
|
333
|
-
"toneSky": "FotuUq_toneSky",
|
|
339
|
+
"toneLime": "FotuUq_toneLime",
|
|
334
340
|
"toneFuchsia": "FotuUq_toneFuchsia",
|
|
341
|
+
"ratioPricey": "FotuUq_ratioPricey",
|
|
342
|
+
"toneEmerald": "FotuUq_toneEmerald",
|
|
343
|
+
"tag": "FotuUq_tag",
|
|
344
|
+
"toneOrange": "FotuUq_toneOrange",
|
|
335
345
|
"toneIndigo": "FotuUq_toneIndigo",
|
|
336
|
-
"ratioChip": "FotuUq_ratioChip",
|
|
337
346
|
"toneAmber": "FotuUq_toneAmber",
|
|
338
|
-
"
|
|
339
|
-
"
|
|
340
|
-
"
|
|
347
|
+
"toneViolet": "FotuUq_toneViolet",
|
|
348
|
+
"toneSky": "FotuUq_toneSky",
|
|
349
|
+
"tonePink": "FotuUq_tonePink",
|
|
350
|
+
"ratioCheap": "FotuUq_ratioCheap",
|
|
351
|
+
"ratioBase": "FotuUq_ratioBase",
|
|
352
|
+
"ratioChip": "FotuUq_ratioChip"
|
|
341
353
|
};
|
|
342
354
|
//#endregion
|
|
343
355
|
//#region src/client/group-tags.tsx
|
|
@@ -392,39 +404,39 @@ window.__ModuleLoader__.load({
|
|
|
392
404
|
document.head.appendChild(tag);
|
|
393
405
|
}
|
|
394
406
|
var ModelGroupSelect_module_css_default = {
|
|
407
|
+
"check": "_2pt-bW_check",
|
|
408
|
+
"optionActive": "_2pt-bW_optionActive",
|
|
409
|
+
"cellLabel": "_2pt-bW_cellLabel",
|
|
410
|
+
"root": "_2pt-bW_root",
|
|
411
|
+
"retry": "_2pt-bW_retry",
|
|
412
|
+
"groupName": "_2pt-bW_groupName",
|
|
395
413
|
"triggerIcon": "_2pt-bW_triggerIcon",
|
|
396
|
-
"modelOption": "_2pt-bW_modelOption",
|
|
397
|
-
"search": "_2pt-bW_search",
|
|
398
414
|
"toast": "_2pt-bW_toast",
|
|
399
|
-
"
|
|
400
|
-
"searchRow": "_2pt-bW_searchRow",
|
|
401
|
-
"searchClear": "_2pt-bW_searchClear",
|
|
402
|
-
"error": "_2pt-bW_error",
|
|
403
|
-
"cellValue": "_2pt-bW_cellValue",
|
|
404
|
-
"chevron": "_2pt-bW_chevron",
|
|
415
|
+
"warning": "_2pt-bW_warning",
|
|
405
416
|
"selected": "_2pt-bW_selected",
|
|
406
|
-
"check": "_2pt-bW_check",
|
|
407
|
-
"groupOptionLabel": "_2pt-bW_groupOptionLabel",
|
|
408
|
-
"triggerLabel": "_2pt-bW_triggerLabel",
|
|
409
|
-
"empty": "_2pt-bW_empty",
|
|
410
417
|
"optionCopy": "_2pt-bW_optionCopy",
|
|
411
|
-
"retry": "_2pt-bW_retry",
|
|
412
|
-
"optionActive": "_2pt-bW_optionActive",
|
|
413
|
-
"menu": "_2pt-bW_menu",
|
|
414
418
|
"option": "_2pt-bW_option",
|
|
415
|
-
"
|
|
419
|
+
"error": "_2pt-bW_error",
|
|
420
|
+
"cellValue": "_2pt-bW_cellValue",
|
|
421
|
+
"trigger": "_2pt-bW_trigger",
|
|
422
|
+
"menu": "_2pt-bW_menu",
|
|
416
423
|
"cellChevron": "_2pt-bW_cellChevron",
|
|
424
|
+
"optionTrailing": "_2pt-bW_optionTrailing",
|
|
425
|
+
"searchRow": "_2pt-bW_searchRow",
|
|
426
|
+
"chevron": "_2pt-bW_chevron",
|
|
427
|
+
"triggerLabel": "_2pt-bW_triggerLabel",
|
|
417
428
|
"status": "_2pt-bW_status",
|
|
418
|
-
"
|
|
429
|
+
"empty": "_2pt-bW_empty",
|
|
419
430
|
"triggerEffort": "_2pt-bW_triggerEffort",
|
|
420
|
-
"
|
|
421
|
-
"
|
|
422
|
-
"groupName": "_2pt-bW_groupName",
|
|
423
|
-
"cellLabel": "_2pt-bW_cellLabel",
|
|
431
|
+
"groupOptionLabel": "_2pt-bW_groupOptionLabel",
|
|
432
|
+
"modelOption": "_2pt-bW_modelOption",
|
|
424
433
|
"cell": "_2pt-bW_cell",
|
|
425
434
|
"modelName": "_2pt-bW_modelName",
|
|
426
|
-
"
|
|
427
|
-
"groupInline": "_2pt-bW_groupInline"
|
|
435
|
+
"groups": "_2pt-bW_groups",
|
|
436
|
+
"groupInline": "_2pt-bW_groupInline",
|
|
437
|
+
"search": "_2pt-bW_search",
|
|
438
|
+
"variantCount": "_2pt-bW_variantCount",
|
|
439
|
+
"searchClear": "_2pt-bW_searchClear"
|
|
428
440
|
};
|
|
429
441
|
//#endregion
|
|
430
442
|
//#region src/client/ModelGroupSelect.tsx
|
|
@@ -980,7 +992,7 @@ window.__ModuleLoader__.load({
|
|
|
980
992
|
}
|
|
981
993
|
//#endregion
|
|
982
994
|
//#region \0dsh-css:D:\Projects\deepseek-harness\dsh-neartoken\src\client\NearTokenSection.module.css.mjs
|
|
983
|
-
const css = "._02HI2q_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}._02HI2q_title{margin:0;font-size:16px;font-weight:500;line-height:24px}._02HI2q_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}._02HI2q_card{border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-settings-card-fill);border-radius:var(--dsw-radius-xl);flex-direction:column;gap:12px;padding:14px 16px;display:flex}._02HI2q_cardHead{align-items:baseline;gap:10px;display:flex}._02HI2q_name{font-size:15px;font-weight:500;line-height:22px}._02HI2q_handle{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._02HI2q_badge{background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-secondary);border-radius:999px;margin-left:auto;padding:2px 8px;font-size:12px;line-height:18px}._02HI2q_badgeOn{color:var(--dsw-alias-state-success-primary)}._02HI2q_facts{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover);grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:14px 18px;margin:0;padding:12px 14px;display:grid}._02HI2q_fact{flex-direction:column;gap:2px;display:flex}._02HI2q_factLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._02HI2q_factValue{font-variant-numeric:tabular-nums;letter-spacing:-.01em;color:var(--dsw-alias-label-primary);font-size:15px;font-weight:500;line-height:22px}._02HI2q_form{flex-direction:column;gap:10px;display:flex}._02HI2q_label{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}._02HI2q_codeRow{align-items:center;gap:10px;display:flex}._02HI2q_code{font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);letter-spacing:.08em;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);user-select:all;padding:4px 12px;font-size:18px;line-height:26px}._02HI2q_actions{align-items:center;gap:10px;display:flex}._02HI2q_button{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-button-elevated-fill);height:32px;color:var(--dsw-alias-label-primary);cursor:pointer;padding:0 14px;font-size:14px}._02HI2q_buttonPrimary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border-color:#0000}._02HI2q_button:disabled{opacity:.55;cursor:default}._02HI2q_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}._02HI2q_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._02HI2q_search{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-button-elevated-fill);height:32px;color:var(--dsw-alias-label-primary);padding:0 10px;font-size:14px}._02HI2q_search::placeholder{color:var(--dsw-alias-label-dimmed)}._02HI2q_toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._02HI2q_autosave{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:12px;line-height:18px}._02HI2q_list{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-md);flex-direction:column;max-height:320px;padding:4px;display:flex;overflow-y:auto}._02HI2q_row{border-radius:var(--dsw-radius-sm);cursor:pointer;align-items:baseline;gap:8px;padding:4px 6px;font-size:13px;line-height:20px;display:flex}._02HI2q_row:hover{background:var(--dsw-alias-interactive-bg-hover)}._02HI2q_row input{accent-color:var(--dsw-alias-button-primary-fill);align-self:center}._02HI2q_rowName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);flex:auto;overflow:hidden}._02HI2q_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;align-items:baseline;gap:8px;font-size:12px;display:flex}._02HI2q_rowRatio{color:var(--dsw-alias-label-secondary)}._02HI2q_tip{z-index:40;border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-settings-card-fill);pointer-events:none;flex-direction:column;gap:2px;width:280px;max-height:240px;padding:8px 10px;font-size:12px;line-height:18px;display:flex;position:fixed;overflow-y:auto;box-shadow:0 8px 24px #00000024}._02HI2q_tipTitle{color:var(--dsw-alias-label-tertiary)}._02HI2q_tipRow{justify-content:space-between;align-items:baseline;gap:10px;display:flex}._02HI2q_tipGroup{min-width:0;color:var(--dsw-alias-label-primary);align-items:center;gap:4px;display:flex;overflow:hidden}._02HI2q_tipGroupName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._02HI2q_select{border:1px solid var(--dsw-color-border-subtle,#0000001f);max-width:60%;color:inherit;font:inherit;background:0 0;border-radius:6px;margin-left:auto;padding:2px 6px;font-size:12px}._02HI2q_select:disabled{opacity:.5}._02HI2q_cardToggle{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:0;display:flex}._02HI2q_cardToggle:hover ._02HI2q_name{color:var(--dsw-alias-label-primary)}._02HI2q_count{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary);align-items:center;gap:8px;margin-left:auto;font-size:12px;line-height:18px;display:inline-flex}._02HI2q_countDot{background:var(--dsw-alias-label-dimmed);border-radius:50%;width:3px;height:3px}._02HI2q_countPicked{color:var(--dsw-alias-label-secondary)}._02HI2q_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .12s}._02HI2q_chevronOpen{transform:rotate(180deg)}";
|
|
995
|
+
const css = "._02HI2q_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}._02HI2q_title{margin:0;font-size:16px;font-weight:500;line-height:24px}._02HI2q_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}._02HI2q_card{border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-settings-card-fill);border-radius:var(--dsw-radius-xl);flex-direction:column;gap:12px;padding:14px 16px;display:flex}._02HI2q_cardHead{align-items:baseline;gap:10px;display:flex}._02HI2q_name{font-size:15px;font-weight:500;line-height:22px}._02HI2q_handle{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._02HI2q_badge{background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-secondary);border-radius:999px;margin-left:auto;padding:2px 8px;font-size:12px;line-height:18px}._02HI2q_badgeOn{color:var(--dsw-alias-state-success-primary)}._02HI2q_facts{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-interactive-bg-hover);grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:14px 18px;margin:0;padding:12px 14px;display:grid}._02HI2q_fact{flex-direction:column;gap:2px;display:flex}._02HI2q_factLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}._02HI2q_factValue{font-variant-numeric:tabular-nums;letter-spacing:-.01em;color:var(--dsw-alias-label-primary);font-size:15px;font-weight:500;line-height:22px}._02HI2q_voucherFact{grid-column:1/-1}._02HI2q_voucherList{flex-direction:column;gap:2px;margin:0;display:flex}._02HI2q_voucherRow{justify-content:space-between;align-items:baseline;gap:10px;font-size:13px;line-height:20px;display:flex}._02HI2q_voucherGroup{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._02HI2q_voucherAmount{color:var(--dsw-alias-state-success-primary);font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:500}._02HI2q_form{flex-direction:column;gap:10px;display:flex}._02HI2q_label{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}._02HI2q_codeRow{align-items:center;gap:10px;display:flex}._02HI2q_code{font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);letter-spacing:.08em;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);user-select:all;padding:4px 12px;font-size:18px;line-height:26px}._02HI2q_linkRow{flex-direction:column;gap:4px;display:flex}._02HI2q_linkLine{align-items:flex-start;gap:8px;display:flex}._02HI2q_link{min-width:0;font-family:var(--dsw-font-mono,ui-monospace, SFMono-Regular, Menlo, monospace);word-break:break-all;color:var(--dsw-alias-label-secondary);user-select:all;flex:auto;font-size:12px;line-height:18px}._02HI2q_actions{align-items:center;gap:10px;display:flex}._02HI2q_button{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-button-elevated-fill);height:32px;color:var(--dsw-alias-label-primary);cursor:pointer;padding:0 14px;font-size:14px}._02HI2q_buttonPrimary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border-color:#0000}._02HI2q_button:disabled{opacity:.55;cursor:default}._02HI2q_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}._02HI2q_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}._02HI2q_search{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-button-elevated-fill);height:32px;color:var(--dsw-alias-label-primary);padding:0 10px;font-size:14px}._02HI2q_search::placeholder{color:var(--dsw-alias-label-dimmed)}._02HI2q_toolbar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._02HI2q_autosave{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:12px;line-height:18px}._02HI2q_list{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-md);flex-direction:column;max-height:320px;padding:4px;display:flex;overflow-y:auto}._02HI2q_row{border-radius:var(--dsw-radius-sm);cursor:pointer;align-items:baseline;gap:8px;padding:4px 6px;font-size:13px;line-height:20px;display:flex}._02HI2q_row:hover{background:var(--dsw-alias-interactive-bg-hover)}._02HI2q_row input{accent-color:var(--dsw-alias-button-primary-fill);align-self:center}._02HI2q_rowName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);flex:auto;overflow:hidden}._02HI2q_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;align-items:baseline;gap:8px;font-size:12px;display:flex}._02HI2q_rowRatio{color:var(--dsw-alias-label-secondary)}._02HI2q_tip{z-index:40;border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-settings-card-fill);pointer-events:none;flex-direction:column;gap:2px;width:280px;max-height:240px;padding:8px 10px;font-size:12px;line-height:18px;display:flex;position:fixed;overflow-y:auto;box-shadow:0 8px 24px #00000024}._02HI2q_tipTitle{color:var(--dsw-alias-label-tertiary)}._02HI2q_tipRow{justify-content:space-between;align-items:baseline;gap:10px;display:flex}._02HI2q_tipGroup{min-width:0;color:var(--dsw-alias-label-primary);align-items:center;gap:4px;display:flex;overflow:hidden}._02HI2q_tipGroupName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._02HI2q_select{border:1px solid var(--dsw-color-border-subtle,#0000001f);max-width:60%;color:inherit;font:inherit;background:0 0;border-radius:6px;margin-left:auto;padding:2px 6px;font-size:12px}._02HI2q_select:disabled{opacity:.5}._02HI2q_cardToggle{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:0;display:flex}._02HI2q_cardToggle:hover ._02HI2q_name{color:var(--dsw-alias-label-primary)}._02HI2q_count{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary);align-items:center;gap:8px;margin-left:auto;font-size:12px;line-height:18px;display:inline-flex}._02HI2q_countDot{background:var(--dsw-alias-label-dimmed);border-radius:50%;width:3px;height:3px}._02HI2q_countPicked{color:var(--dsw-alias-label-secondary)}._02HI2q_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .12s}._02HI2q_chevronOpen{transform:rotate(180deg)}";
|
|
984
996
|
const tagId = "dsh-neartoken/NearTokenSection.module.css";
|
|
985
997
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
986
998
|
const tag = document.createElement("style");
|
|
@@ -990,48 +1002,56 @@ window.__ModuleLoader__.load({
|
|
|
990
1002
|
document.head.appendChild(tag);
|
|
991
1003
|
}
|
|
992
1004
|
var NearTokenSection_module_css_default = {
|
|
993
|
-
"chevron": "_02HI2q_chevron",
|
|
994
|
-
"rowMeta": "_02HI2q_rowMeta",
|
|
995
|
-
"rowRatio": "_02HI2q_rowRatio",
|
|
996
1005
|
"autosave": "_02HI2q_autosave",
|
|
997
|
-
"
|
|
1006
|
+
"card": "_02HI2q_card",
|
|
1007
|
+
"cardHead": "_02HI2q_cardHead",
|
|
998
1008
|
"handle": "_02HI2q_handle",
|
|
999
|
-
"
|
|
1009
|
+
"toolbar": "_02HI2q_toolbar",
|
|
1000
1010
|
"tipGroupName": "_02HI2q_tipGroupName",
|
|
1001
|
-
"
|
|
1002
|
-
"notice": "_02HI2q_notice",
|
|
1003
|
-
"fact": "_02HI2q_fact",
|
|
1004
|
-
"search": "_02HI2q_search",
|
|
1005
|
-
"row": "_02HI2q_row",
|
|
1006
|
-
"tipGroup": "_02HI2q_tipGroup",
|
|
1007
|
-
"label": "_02HI2q_label",
|
|
1008
|
-
"section": "_02HI2q_section",
|
|
1011
|
+
"count": "_02HI2q_count",
|
|
1009
1012
|
"select": "_02HI2q_select",
|
|
1013
|
+
"voucherAmount": "_02HI2q_voucherAmount",
|
|
1014
|
+
"rowName": "_02HI2q_rowName",
|
|
1015
|
+
"intro": "_02HI2q_intro",
|
|
1010
1016
|
"name": "_02HI2q_name",
|
|
1011
|
-
"
|
|
1012
|
-
"
|
|
1017
|
+
"rowMeta": "_02HI2q_rowMeta",
|
|
1018
|
+
"countDot": "_02HI2q_countDot",
|
|
1013
1019
|
"factValue": "_02HI2q_factValue",
|
|
1014
|
-
"
|
|
1015
|
-
"
|
|
1016
|
-
"
|
|
1017
|
-
"
|
|
1018
|
-
"cardHead": "_02HI2q_cardHead",
|
|
1019
|
-
"factLabel": "_02HI2q_factLabel",
|
|
1020
|
-
"list": "_02HI2q_list",
|
|
1021
|
-
"buttonPrimary": "_02HI2q_buttonPrimary",
|
|
1022
|
-
"intro": "_02HI2q_intro",
|
|
1023
|
-
"rowName": "_02HI2q_rowName",
|
|
1024
|
-
"toolbar": "_02HI2q_toolbar",
|
|
1025
|
-
"tipTitle": "_02HI2q_tipTitle",
|
|
1026
|
-
"title": "_02HI2q_title",
|
|
1020
|
+
"codeRow": "_02HI2q_codeRow",
|
|
1021
|
+
"link": "_02HI2q_link",
|
|
1022
|
+
"linkRow": "_02HI2q_linkRow",
|
|
1023
|
+
"voucherList": "_02HI2q_voucherList",
|
|
1027
1024
|
"actions": "_02HI2q_actions",
|
|
1028
|
-
"
|
|
1025
|
+
"row": "_02HI2q_row",
|
|
1026
|
+
"chevronOpen": "_02HI2q_chevronOpen",
|
|
1029
1027
|
"code": "_02HI2q_code",
|
|
1030
|
-
"
|
|
1031
|
-
"
|
|
1028
|
+
"title": "_02HI2q_title",
|
|
1029
|
+
"fact": "_02HI2q_fact",
|
|
1030
|
+
"list": "_02HI2q_list",
|
|
1031
|
+
"facts": "_02HI2q_facts",
|
|
1032
|
+
"buttonPrimary": "_02HI2q_buttonPrimary",
|
|
1033
|
+
"voucherFact": "_02HI2q_voucherFact",
|
|
1034
|
+
"search": "_02HI2q_search",
|
|
1035
|
+
"rowRatio": "_02HI2q_rowRatio",
|
|
1036
|
+
"hint": "_02HI2q_hint",
|
|
1037
|
+
"form": "_02HI2q_form",
|
|
1038
|
+
"badgeOn": "_02HI2q_badgeOn",
|
|
1039
|
+
"factLabel": "_02HI2q_factLabel",
|
|
1040
|
+
"voucherGroup": "_02HI2q_voucherGroup",
|
|
1041
|
+
"notice": "_02HI2q_notice",
|
|
1042
|
+
"label": "_02HI2q_label",
|
|
1032
1043
|
"tip": "_02HI2q_tip",
|
|
1044
|
+
"badge": "_02HI2q_badge",
|
|
1045
|
+
"tipTitle": "_02HI2q_tipTitle",
|
|
1046
|
+
"section": "_02HI2q_section",
|
|
1047
|
+
"tipRow": "_02HI2q_tipRow",
|
|
1048
|
+
"tipGroup": "_02HI2q_tipGroup",
|
|
1049
|
+
"chevron": "_02HI2q_chevron",
|
|
1033
1050
|
"countPicked": "_02HI2q_countPicked",
|
|
1034
|
-
"
|
|
1051
|
+
"linkLine": "_02HI2q_linkLine",
|
|
1052
|
+
"button": "_02HI2q_button",
|
|
1053
|
+
"cardToggle": "_02HI2q_cardToggle",
|
|
1054
|
+
"voucherRow": "_02HI2q_voucherRow"
|
|
1035
1055
|
};
|
|
1036
1056
|
//#endregion
|
|
1037
1057
|
//#region src/client/NearTokenSection.tsx
|
|
@@ -1046,8 +1066,15 @@ window.__ModuleLoader__.load({
|
|
|
1046
1066
|
*/
|
|
1047
1067
|
/** How often the page re-reads the Host while an authorization is pending. */
|
|
1048
1068
|
const PENDING_REFRESH_MS = 1500;
|
|
1069
|
+
/**
|
|
1070
|
+
* How often the page re-reads the Host while connected, so the card shows the
|
|
1071
|
+
* wallet numbers the Host re-reads at the same cadence.
|
|
1072
|
+
*/
|
|
1073
|
+
const CONNECTED_REFRESH_MS = 3e5;
|
|
1049
1074
|
/** How long a burst of checkbox clicks waits before one save is written. */
|
|
1050
1075
|
const AUTOSAVE_DELAY_MS = 400;
|
|
1076
|
+
/** How long the copy button acknowledges a copied address before resetting. */
|
|
1077
|
+
const COPIED_RESET_MS = 2e3;
|
|
1051
1078
|
/**
|
|
1052
1079
|
* Render the NearToken settings page.
|
|
1053
1080
|
* @param props - the injected route carrier and translate, plus slot owner props.
|
|
@@ -1057,6 +1084,8 @@ window.__ModuleLoader__.load({
|
|
|
1057
1084
|
const [status, setStatus] = (0, react.useState)(void 0);
|
|
1058
1085
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1059
1086
|
const [error, setError] = (0, react.useState)(void 0);
|
|
1087
|
+
/** Whether the confirmation address was just copied to the clipboard. */
|
|
1088
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
1060
1089
|
/** Re-read the Host state and publish it. */
|
|
1061
1090
|
const refresh = (0, react.useCallback)(async () => {
|
|
1062
1091
|
try {
|
|
@@ -1070,6 +1099,18 @@ window.__ModuleLoader__.load({
|
|
|
1070
1099
|
}, [refresh]);
|
|
1071
1100
|
const pendingCode = status?.pending?.userCode;
|
|
1072
1101
|
const waiting = pendingCode !== void 0;
|
|
1102
|
+
(0, react.useEffect)(() => {
|
|
1103
|
+
setCopied(false);
|
|
1104
|
+
}, [pendingCode]);
|
|
1105
|
+
(0, react.useEffect)(() => {
|
|
1106
|
+
if (!copied) return;
|
|
1107
|
+
const timer = setTimeout(() => {
|
|
1108
|
+
setCopied(false);
|
|
1109
|
+
}, COPIED_RESET_MS);
|
|
1110
|
+
return () => {
|
|
1111
|
+
clearTimeout(timer);
|
|
1112
|
+
};
|
|
1113
|
+
}, [copied]);
|
|
1073
1114
|
(0, react.useEffect)(() => {
|
|
1074
1115
|
if (!waiting) return;
|
|
1075
1116
|
const timer = setInterval(() => {
|
|
@@ -1083,6 +1124,16 @@ window.__ModuleLoader__.load({
|
|
|
1083
1124
|
pendingCode,
|
|
1084
1125
|
refresh
|
|
1085
1126
|
]);
|
|
1127
|
+
const connected = status?.configured === true;
|
|
1128
|
+
(0, react.useEffect)(() => {
|
|
1129
|
+
if (!connected) return;
|
|
1130
|
+
const timer = setInterval(() => {
|
|
1131
|
+
refresh();
|
|
1132
|
+
}, CONNECTED_REFRESH_MS);
|
|
1133
|
+
return () => {
|
|
1134
|
+
clearInterval(timer);
|
|
1135
|
+
};
|
|
1136
|
+
}, [connected, refresh]);
|
|
1086
1137
|
/** Run one Host call with the busy flag and the error channel wired. */
|
|
1087
1138
|
const run = (0, react.useCallback)(async (action) => {
|
|
1088
1139
|
setBusy(true);
|
|
@@ -1108,6 +1159,37 @@ window.__ModuleLoader__.load({
|
|
|
1108
1159
|
await refresh();
|
|
1109
1160
|
});
|
|
1110
1161
|
};
|
|
1162
|
+
/**
|
|
1163
|
+
* Hand the confirmation page to the user's own browser, through the Host: a
|
|
1164
|
+
* window the page opens stays inside the shell hosting it — a desktop build
|
|
1165
|
+
* shows another application window, and macOS may refuse outright. The
|
|
1166
|
+
* address is printed below as well, for a machine with no launcher at all.
|
|
1167
|
+
*/
|
|
1168
|
+
const openAddress = () => {
|
|
1169
|
+
(async () => {
|
|
1170
|
+
setError(void 0);
|
|
1171
|
+
try {
|
|
1172
|
+
await api.openBrowser();
|
|
1173
|
+
} catch (failure) {
|
|
1174
|
+
setError(t("account.openFailed", { message: messageOf(failure) }));
|
|
1175
|
+
}
|
|
1176
|
+
})();
|
|
1177
|
+
};
|
|
1178
|
+
/**
|
|
1179
|
+
* Copy the confirmation address, for a machine where nothing can be launched.
|
|
1180
|
+
*/
|
|
1181
|
+
const copyAddress = () => {
|
|
1182
|
+
const address = status?.pending?.verificationUriComplete;
|
|
1183
|
+
if (address === void 0) return;
|
|
1184
|
+
(async () => {
|
|
1185
|
+
try {
|
|
1186
|
+
await navigator.clipboard.writeText(address);
|
|
1187
|
+
setCopied(true);
|
|
1188
|
+
} catch {
|
|
1189
|
+
setError(t("account.copyFailed"));
|
|
1190
|
+
}
|
|
1191
|
+
})();
|
|
1192
|
+
};
|
|
1111
1193
|
const signOut = () => {
|
|
1112
1194
|
run(async () => {
|
|
1113
1195
|
await api.signOut();
|
|
@@ -1189,7 +1271,26 @@ window.__ModuleLoader__.load({
|
|
|
1189
1271
|
className: NearTokenSection_module_css_default.factValue,
|
|
1190
1272
|
children: status.tokenName
|
|
1191
1273
|
})]
|
|
1192
|
-
})
|
|
1274
|
+
}),
|
|
1275
|
+
account !== void 0 && (account.vouchers?.length ?? 0) > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1276
|
+
className: `${NearTokenSection_module_css_default.fact} ${NearTokenSection_module_css_default.voucherFact}`,
|
|
1277
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
|
|
1278
|
+
className: NearTokenSection_module_css_default.factLabel,
|
|
1279
|
+
children: t("account.vouchers")
|
|
1280
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
1281
|
+
className: NearTokenSection_module_css_default.voucherList,
|
|
1282
|
+
children: account.vouchers?.map((voucher) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1283
|
+
className: NearTokenSection_module_css_default.voucherRow,
|
|
1284
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1285
|
+
className: NearTokenSection_module_css_default.voucherGroup,
|
|
1286
|
+
children: voucher.group
|
|
1287
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1288
|
+
className: NearTokenSection_module_css_default.voucherAmount,
|
|
1289
|
+
children: voucher.amount
|
|
1290
|
+
})]
|
|
1291
|
+
}, `${voucher.groupId}:${voucher.group}`))
|
|
1292
|
+
})]
|
|
1293
|
+
}) : null
|
|
1193
1294
|
]
|
|
1194
1295
|
}),
|
|
1195
1296
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1255,9 +1356,7 @@ window.__ModuleLoader__.load({
|
|
|
1255
1356
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1256
1357
|
type: "button",
|
|
1257
1358
|
className: `${NearTokenSection_module_css_default.button} ${NearTokenSection_module_css_default.buttonPrimary}`,
|
|
1258
|
-
onClick:
|
|
1259
|
-
window.open(pending.verificationUriComplete, "_blank", "noopener,noreferrer");
|
|
1260
|
-
},
|
|
1359
|
+
onClick: openAddress,
|
|
1261
1360
|
children: t("account.openBrowser")
|
|
1262
1361
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1263
1362
|
type: "button",
|
|
@@ -1267,6 +1366,27 @@ window.__ModuleLoader__.load({
|
|
|
1267
1366
|
children: busy ? t("account.cancelling") : t("account.cancel")
|
|
1268
1367
|
})]
|
|
1269
1368
|
}),
|
|
1369
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1370
|
+
className: NearTokenSection_module_css_default.linkRow,
|
|
1371
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1372
|
+
className: NearTokenSection_module_css_default.label,
|
|
1373
|
+
children: t("account.manualLink")
|
|
1374
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1375
|
+
className: NearTokenSection_module_css_default.linkLine,
|
|
1376
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1377
|
+
className: NearTokenSection_module_css_default.link,
|
|
1378
|
+
href: pending.verificationUriComplete,
|
|
1379
|
+
target: "_blank",
|
|
1380
|
+
rel: "noopener noreferrer",
|
|
1381
|
+
children: pending.verificationUriComplete
|
|
1382
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1383
|
+
type: "button",
|
|
1384
|
+
className: NearTokenSection_module_css_default.button,
|
|
1385
|
+
onClick: copyAddress,
|
|
1386
|
+
children: copied ? t("account.copied") : t("account.copyLink")
|
|
1387
|
+
})]
|
|
1388
|
+
})]
|
|
1389
|
+
}),
|
|
1270
1390
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1271
1391
|
className: NearTokenSection_module_css_default.hint,
|
|
1272
1392
|
children: t("account.expiresIn", { minutes: String(minutes) })
|
|
@@ -1785,7 +1905,7 @@ window.__ModuleLoader__.load({
|
|
|
1785
1905
|
}),
|
|
1786
1906
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1787
1907
|
className: NearTokenSection_module_css_default.rowMeta,
|
|
1788
|
-
children: t(entry.channel === "images" ? "images.channel.images" : "images.channel.chat")
|
|
1908
|
+
children: t(entry.channel === "images" ? "images.channel.images" : entry.channel === "genai" ? "images.channel.genai" : "images.channel.chat")
|
|
1789
1909
|
})
|
|
1790
1910
|
]
|
|
1791
1911
|
}, entry.model))
|
|
@@ -1865,6 +1985,11 @@ window.__ModuleLoader__.load({
|
|
|
1865
1985
|
"account.waiting": "已发起授权,请在浏览器中确认。",
|
|
1866
1986
|
"account.userCode": "确认码",
|
|
1867
1987
|
"account.openBrowser": "打开浏览器确认",
|
|
1988
|
+
"account.manualLink": "打不开浏览器时,手动打开下面的地址:",
|
|
1989
|
+
"account.copyLink": "复制链接",
|
|
1990
|
+
"account.copied": "已复制",
|
|
1991
|
+
"account.copyFailed": "复制失败,请手动选中上面的链接复制。",
|
|
1992
|
+
"account.openFailed": "未能打开浏览器({message});请复制下面的地址,在自己的浏览器里访问。",
|
|
1868
1993
|
"account.expiresIn": "本次确认 {minutes} 分钟内有效",
|
|
1869
1994
|
"account.cancel": "取消",
|
|
1870
1995
|
"account.cancelling": "正在取消…",
|
|
@@ -1873,6 +1998,7 @@ window.__ModuleLoader__.load({
|
|
|
1873
1998
|
"account.group": "用户分组",
|
|
1874
1999
|
"account.balance": "剩余额度",
|
|
1875
2000
|
"account.used": "已用额度",
|
|
2001
|
+
"account.vouchers": "代金券",
|
|
1876
2002
|
"account.token": "API 令牌",
|
|
1877
2003
|
"account.signOut": "断开连接",
|
|
1878
2004
|
"account.signingOut": "正在断开…",
|
|
@@ -1904,6 +2030,7 @@ window.__ModuleLoader__.load({
|
|
|
1904
2030
|
"images.intro": "开启后模型可以调用 generate_image 工具生图。勾选要用的生图模型,并为每个模型指定走哪个分组(决定计费与可用性)。",
|
|
1905
2031
|
"images.enable": "启用 generate_image 工具",
|
|
1906
2032
|
"images.channel.images": "images 接口",
|
|
2033
|
+
"images.channel.genai": "gemini 接口",
|
|
1907
2034
|
"images.channel.chat": "chat 接口",
|
|
1908
2035
|
"images.save": "保存",
|
|
1909
2036
|
"images.saving": "正在保存…",
|
|
@@ -1949,6 +2076,11 @@ window.__ModuleLoader__.load({
|
|
|
1949
2076
|
"account.waiting": "Authorization started. Confirm it in your browser.",
|
|
1950
2077
|
"account.userCode": "Code",
|
|
1951
2078
|
"account.openBrowser": "Open browser to confirm",
|
|
2079
|
+
"account.manualLink": "If the browser does not open, open this address yourself:",
|
|
2080
|
+
"account.copyLink": "Copy link",
|
|
2081
|
+
"account.copied": "Copied",
|
|
2082
|
+
"account.copyFailed": "Could not copy; select the link above and copy it yourself.",
|
|
2083
|
+
"account.openFailed": "Could not open your browser ({message}); copy the address below and open it yourself.",
|
|
1952
2084
|
"account.expiresIn": "This confirmation is valid for {minutes} minutes",
|
|
1953
2085
|
"account.cancel": "Cancel",
|
|
1954
2086
|
"account.cancelling": "Cancelling…",
|
|
@@ -1957,6 +2089,7 @@ window.__ModuleLoader__.load({
|
|
|
1957
2089
|
"account.group": "Group",
|
|
1958
2090
|
"account.balance": "Balance",
|
|
1959
2091
|
"account.used": "Used",
|
|
2092
|
+
"account.vouchers": "Vouchers",
|
|
1960
2093
|
"account.token": "API token",
|
|
1961
2094
|
"account.signOut": "Disconnect",
|
|
1962
2095
|
"account.signingOut": "Disconnecting…",
|
|
@@ -1988,6 +2121,7 @@ window.__ModuleLoader__.load({
|
|
|
1988
2121
|
"images.intro": "Once on, the model can call the generate_image tool. Check the picture models you want and pick the group each one bills to.",
|
|
1989
2122
|
"images.enable": "Enable the generate_image tool",
|
|
1990
2123
|
"images.channel.images": "images endpoint",
|
|
2124
|
+
"images.channel.genai": "gemini endpoint",
|
|
1991
2125
|
"images.channel.chat": "chat endpoint",
|
|
1992
2126
|
"images.save": "Save",
|
|
1993
2127
|
"images.saving": "Saving…",
|