dsh-neartoken 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
  |---|---|
25
25
  | `src/index.ts` | 配置 schema、按凭据现状挂载 provider、装配其余模块 |
26
26
  | `src/host/account.ts` | RFC 8628 形状的设备授权:发起、按 interval 轮询、把 key 写进 credentials |
27
- | `src/host/routes.ts` | 设置页调用的同源路由(状态 / 授权 / 取消 / 断开 / 模型白名单) |
27
+ | `src/host/routes.ts` | 设置页调用的同源路由(状态 / 余额立即刷新 / 授权 / 取消 / 断开 / 模型白名单 / 生图设置) |
28
28
  | `src/host/whitelist.ts` | 白名单读写在插件自身 Config 的 `enabledModels`(volatile),存 profile patch |
29
29
  | `src/host/pricing.ts` | 拉 `/api/pricing`,展开成 `"<组>::<模型>"` 路由,过滤出能聊的模型 |
30
30
  | `src/host/model-caps.ts` | 一个模型能不能聊、上下文窗口多大、可选的推理等级(只读站点声明,不存模型表) |
@@ -196,7 +196,7 @@ Gemini 系走原生 surface 而不是 openai 兼容层:同模型同提示词
196
196
  - `-c` 后缀是站点自己的约定(带该后缀的模型工具调用不可靠):站点声明了端点类型时插件按声明提供,声明里没有它就不会出现;没有声明时按名字隐藏它的无后缀孪生之外的变体。
197
197
  - 站点上新但还没在后台填能力的模型:只要声明了端点类型就会提供,容量走 `defaultContextWindow`,模态按纯文本、没有推理档位(除非在 `modelOverrides` 里写明)。这不是 bug,是「站点是唯一真源」的直接后果——补能力请去后台填,不必等插件发版。
198
198
  - pricing 加载失败时沿用上一次成功的结果,从未成功过则目录为空(失败不写缓存,下次调用会重试)。
199
- - 账号卡片不自动刷新:数字只来自授权那一刻 grant 里的 `user`(站点的 dashboard 接口认浏览器会话,不认本插件持有的 relay key),落盘到 profile 下的 `neartoken-account.json`,重启后从文件恢复。之后余额变化不会反映,需要重新连接一次。
199
+ - 账号卡片的钱是**两次读**拼接的:授权那一刻 grant 里的 `user` 给出身份事实,余额/已用/代金券则来自站点 `/api/dsh/device/wallet`——Host 每 5 分钟读一次,页面在余额旁另有**立即刷新**按钮(`POST /neartoken/refresh`,读完后把同一份状态回给页面),所以不必重连也能看到新数字。落盘到 profile 下的 `neartoken-account.json` 只作重启回退。站点若没有该端点或读不到,卡片保留上一次的数字、不会清空。代金券为空时卡片给一句去「邀请计划」(站点 `/wallet` 页)领免费代金券的提示。
200
200
  - 白名单按裸模型名过滤:勾掉某模型会把它的所有分组一起隐藏;某个正在使用的模型被勾掉后,会话里已选中的 id 仍在,但选择器里不再列出它。
201
201
  - 白名单写入走 DSH 的 Settings:profile 里该行只保留 volatile 字段,所以别把 `baseURL` 等非 volatile 字段写进**同一个 profile 行**(会在此后第一次保存白名单时被 Settings 的 strip 规则清掉)。
202
202
  - 生图一次一张;`size` 对 images 通道只是建议,上游常忽略(实测不传 size 时 gpt-image-2.5-flare 出 1536x1024)。
package/lib/client.js CHANGED
@@ -23,6 +23,12 @@ window.__ModuleLoader__.load({
23
23
  */
24
24
  /** State read by the settings page before it draws, and while it waits. */
25
25
  const STATUS_PATH = "/neartoken/status";
26
+ /**
27
+ * Re-read the wallet right now, then answer with the same state `STATUS_PATH`
28
+ * reads. The Host already refreshes on its own cadence; this is the page asking
29
+ * for that read early, and the answer carries the fresh numbers.
30
+ */
31
+ const REFRESH_PATH = "/neartoken/refresh";
26
32
  /** Start a device authorization (the Host then polls the site). */
27
33
  const AUTHORIZE_PATH = "/neartoken/authorize";
28
34
  /** Abandon the authorization in progress. */
@@ -72,6 +78,9 @@ window.__ModuleLoader__.load({
72
78
  async status() {
73
79
  return await jsonOf(await fetcher(STATUS_PATH, { headers: { accept: "application/json" } }));
74
80
  },
81
+ async refreshAccount() {
82
+ return await post(REFRESH_PATH);
83
+ },
75
84
  async begin() {
76
85
  return await post(AUTHORIZE_PATH);
77
86
  },
@@ -333,22 +342,22 @@ window.__ModuleLoader__.load({
333
342
  document.head.appendChild(tag);
334
343
  }
335
344
  var group_tags_module_css_default = {
336
- "toneViolet": "FotuUq_toneViolet",
337
- "toneEmerald": "FotuUq_toneEmerald",
338
- "toneOrange": "FotuUq_toneOrange",
339
- "toneRose": "FotuUq_toneRose",
340
- "toneTeal": "FotuUq_toneTeal",
341
- "ratioBase": "FotuUq_ratioBase",
342
345
  "toneCyan": "FotuUq_toneCyan",
346
+ "toneRose": "FotuUq_toneRose",
347
+ "tonePink": "FotuUq_tonePink",
348
+ "ratioChip": "FotuUq_ratioChip",
349
+ "toneLime": "FotuUq_toneLime",
343
350
  "ratioCheap": "FotuUq_ratioCheap",
351
+ "toneOrange": "FotuUq_toneOrange",
352
+ "toneEmerald": "FotuUq_toneEmerald",
353
+ "ratioBase": "FotuUq_ratioBase",
354
+ "toneAmber": "FotuUq_toneAmber",
355
+ "toneTeal": "FotuUq_toneTeal",
356
+ "tag": "FotuUq_tag",
344
357
  "toneSky": "FotuUq_toneSky",
345
358
  "toneIndigo": "FotuUq_toneIndigo",
346
- "tag": "FotuUq_tag",
347
- "toneLime": "FotuUq_toneLime",
348
359
  "ratioPricey": "FotuUq_ratioPricey",
349
- "tonePink": "FotuUq_tonePink",
350
- "toneAmber": "FotuUq_toneAmber",
351
- "ratioChip": "FotuUq_ratioChip",
360
+ "toneViolet": "FotuUq_toneViolet",
352
361
  "toneFuchsia": "FotuUq_toneFuchsia"
353
362
  };
354
363
  //#endregion
@@ -404,39 +413,39 @@ window.__ModuleLoader__.load({
404
413
  document.head.appendChild(tag);
405
414
  }
406
415
  var ModelGroupSelect_module_css_default = {
407
- "triggerEffort": "_2pt-bW_triggerEffort",
408
- "check": "_2pt-bW_check",
416
+ "option": "_2pt-bW_option",
417
+ "selected": "_2pt-bW_selected",
409
418
  "trigger": "_2pt-bW_trigger",
410
419
  "searchClear": "_2pt-bW_searchClear",
411
- "search": "_2pt-bW_search",
412
- "cell": "_2pt-bW_cell",
413
- "triggerLabel": "_2pt-bW_triggerLabel",
414
- "modelOption": "_2pt-bW_modelOption",
420
+ "warning": "_2pt-bW_warning",
421
+ "optionCopy": "_2pt-bW_optionCopy",
422
+ "menu": "_2pt-bW_menu",
415
423
  "optionActive": "_2pt-bW_optionActive",
424
+ "cellLabel": "_2pt-bW_cellLabel",
425
+ "error": "_2pt-bW_error",
426
+ "optionTrailing": "_2pt-bW_optionTrailing",
427
+ "cellValue": "_2pt-bW_cellValue",
416
428
  "groups": "_2pt-bW_groups",
429
+ "root": "_2pt-bW_root",
430
+ "triggerIcon": "_2pt-bW_triggerIcon",
417
431
  "groupOptionLabel": "_2pt-bW_groupOptionLabel",
418
- "status": "_2pt-bW_status",
432
+ "triggerLabel": "_2pt-bW_triggerLabel",
433
+ "triggerEffort": "_2pt-bW_triggerEffort",
434
+ "groupInline": "_2pt-bW_groupInline",
419
435
  "empty": "_2pt-bW_empty",
420
436
  "searchRow": "_2pt-bW_searchRow",
421
- "menu": "_2pt-bW_menu",
422
- "root": "_2pt-bW_root",
423
- "toast": "_2pt-bW_toast",
424
- "cellChevron": "_2pt-bW_cellChevron",
425
- "option": "_2pt-bW_option",
426
437
  "groupName": "_2pt-bW_groupName",
427
- "optionTrailing": "_2pt-bW_optionTrailing",
428
- "retry": "_2pt-bW_retry",
438
+ "modelOption": "_2pt-bW_modelOption",
429
439
  "chevron": "_2pt-bW_chevron",
430
- "selected": "_2pt-bW_selected",
431
- "optionCopy": "_2pt-bW_optionCopy",
432
- "cellLabel": "_2pt-bW_cellLabel",
433
- "error": "_2pt-bW_error",
440
+ "status": "_2pt-bW_status",
441
+ "retry": "_2pt-bW_retry",
442
+ "search": "_2pt-bW_search",
434
443
  "modelName": "_2pt-bW_modelName",
435
444
  "variantCount": "_2pt-bW_variantCount",
436
- "triggerIcon": "_2pt-bW_triggerIcon",
437
- "cellValue": "_2pt-bW_cellValue",
438
- "warning": "_2pt-bW_warning",
439
- "groupInline": "_2pt-bW_groupInline"
445
+ "check": "_2pt-bW_check",
446
+ "cell": "_2pt-bW_cell",
447
+ "cellChevron": "_2pt-bW_cellChevron",
448
+ "toast": "_2pt-bW_toast"
440
449
  };
441
450
  //#endregion
442
451
  //#region src/client/ModelGroupSelect.tsx
@@ -992,7 +1001,7 @@ window.__ModuleLoader__.load({
992
1001
  }
993
1002
  //#endregion
994
1003
  //#region \0dsh-css:D:\Projects\deepseek-harness\dsh-neartoken\src\client\NearTokenSection.module.css.mjs
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)}";
1004
+ 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_valueRow{align-items:center;gap:6px;display:flex}._02HI2q_refresh{border-radius:var(--dsw-radius-sm);width:22px;height:22px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0;display:inline-flex}._02HI2q_refresh:hover:not(:disabled){background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary)}._02HI2q_refresh:disabled{opacity:.55;cursor:default}._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_voucherEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:20px}._02HI2q_invite{color:var(--dsw-alias-label-primary);text-underline-offset:2px;text-decoration:underline}._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)}";
996
1005
  const tagId = "dsh-neartoken/NearTokenSection.module.css";
997
1006
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
998
1007
  const tag = document.createElement("style");
@@ -1002,56 +1011,60 @@ window.__ModuleLoader__.load({
1002
1011
  document.head.appendChild(tag);
1003
1012
  }
1004
1013
  var NearTokenSection_module_css_default = {
1005
- "factValue": "_02HI2q_factValue",
1006
- "code": "_02HI2q_code",
1007
- "button": "_02HI2q_button",
1008
- "voucherRow": "_02HI2q_voucherRow",
1009
- "row": "_02HI2q_row",
1010
- "form": "_02HI2q_form",
1011
- "count": "_02HI2q_count",
1012
- "label": "_02HI2q_label",
1014
+ "tip": "_02HI2q_tip",
1015
+ "search": "_02HI2q_search",
1013
1016
  "linkLine": "_02HI2q_linkLine",
1014
- "fact": "_02HI2q_fact",
1015
- "voucherAmount": "_02HI2q_voucherAmount",
1016
- "autosave": "_02HI2q_autosave",
1017
- "rowRatio": "_02HI2q_rowRatio",
1018
- "title": "_02HI2q_title",
1019
- "tipTitle": "_02HI2q_tipTitle",
1017
+ "buttonPrimary": "_02HI2q_buttonPrimary",
1020
1018
  "select": "_02HI2q_select",
1021
- "factLabel": "_02HI2q_factLabel",
1022
- "cardToggle": "_02HI2q_cardToggle",
1023
- "card": "_02HI2q_card",
1024
- "hint": "_02HI2q_hint",
1025
- "link": "_02HI2q_link",
1026
- "list": "_02HI2q_list",
1019
+ "voucherFact": "_02HI2q_voucherFact",
1020
+ "linkRow": "_02HI2q_linkRow",
1027
1021
  "cardHead": "_02HI2q_cardHead",
1022
+ "voucherList": "_02HI2q_voucherList",
1023
+ "section": "_02HI2q_section",
1024
+ "valueRow": "_02HI2q_valueRow",
1025
+ "badge": "_02HI2q_badge",
1026
+ "tipTitle": "_02HI2q_tipTitle",
1027
+ "voucherRow": "_02HI2q_voucherRow",
1028
+ "name": "_02HI2q_name",
1028
1029
  "handle": "_02HI2q_handle",
1029
- "linkRow": "_02HI2q_linkRow",
1030
- "buttonPrimary": "_02HI2q_buttonPrimary",
1030
+ "factLabel": "_02HI2q_factLabel",
1031
+ "voucherAmount": "_02HI2q_voucherAmount",
1031
1032
  "notice": "_02HI2q_notice",
1032
- "intro": "_02HI2q_intro",
1033
- "rowMeta": "_02HI2q_rowMeta",
1034
- "tipRow": "_02HI2q_tipRow",
1035
- "tipGroupName": "_02HI2q_tipGroupName",
1036
- "facts": "_02HI2q_facts",
1037
1033
  "countPicked": "_02HI2q_countPicked",
1038
- "voucherFact": "_02HI2q_voucherFact",
1039
- "section": "_02HI2q_section",
1040
- "voucherGroup": "_02HI2q_voucherGroup",
1041
- "tipGroup": "_02HI2q_tipGroup",
1042
- "tip": "_02HI2q_tip",
1043
1034
  "chevron": "_02HI2q_chevron",
1035
+ "hint": "_02HI2q_hint",
1036
+ "tipRow": "_02HI2q_tipRow",
1037
+ "label": "_02HI2q_label",
1038
+ "invite": "_02HI2q_invite",
1039
+ "link": "_02HI2q_link",
1040
+ "actions": "_02HI2q_actions",
1041
+ "cardToggle": "_02HI2q_cardToggle",
1044
1042
  "chevronOpen": "_02HI2q_chevronOpen",
1043
+ "refresh": "_02HI2q_refresh",
1044
+ "code": "_02HI2q_code",
1045
+ "intro": "_02HI2q_intro",
1046
+ "fact": "_02HI2q_fact",
1047
+ "factValue": "_02HI2q_factValue",
1048
+ "voucherGroup": "_02HI2q_voucherGroup",
1049
+ "voucherEmpty": "_02HI2q_voucherEmpty",
1050
+ "button": "_02HI2q_button",
1045
1051
  "toolbar": "_02HI2q_toolbar",
1046
- "actions": "_02HI2q_actions",
1052
+ "autosave": "_02HI2q_autosave",
1047
1053
  "rowName": "_02HI2q_rowName",
1048
- "badge": "_02HI2q_badge",
1049
- "voucherList": "_02HI2q_voucherList",
1050
- "search": "_02HI2q_search",
1051
- "countDot": "_02HI2q_countDot",
1052
- "codeRow": "_02HI2q_codeRow",
1054
+ "rowRatio": "_02HI2q_rowRatio",
1055
+ "card": "_02HI2q_card",
1056
+ "row": "_02HI2q_row",
1057
+ "tipGroup": "_02HI2q_tipGroup",
1053
1058
  "badgeOn": "_02HI2q_badgeOn",
1054
- "name": "_02HI2q_name"
1059
+ "codeRow": "_02HI2q_codeRow",
1060
+ "title": "_02HI2q_title",
1061
+ "facts": "_02HI2q_facts",
1062
+ "count": "_02HI2q_count",
1063
+ "list": "_02HI2q_list",
1064
+ "tipGroupName": "_02HI2q_tipGroupName",
1065
+ "countDot": "_02HI2q_countDot",
1066
+ "form": "_02HI2q_form",
1067
+ "rowMeta": "_02HI2q_rowMeta"
1055
1068
  };
1056
1069
  //#endregion
1057
1070
  //#region src/client/NearTokenSection.tsx
@@ -1083,6 +1096,11 @@ window.__ModuleLoader__.load({
1083
1096
  function NearTokenSection({ api, t }) {
1084
1097
  const [status, setStatus] = (0, react.useState)(void 0);
1085
1098
  const [busy, setBusy] = (0, react.useState)(false);
1099
+ /**
1100
+ * Whether the card's money facts are being re-read right now. Kept apart from
1101
+ * `busy`: a balance read must not disable the buttons beside it.
1102
+ */
1103
+ const [walletBusy, setWalletBusy] = (0, react.useState)(false);
1086
1104
  const [error, setError] = (0, react.useState)(void 0);
1087
1105
  /** Whether the confirmation address was just copied to the clipboard. */
1088
1106
  const [copied, setCopied] = (0, react.useState)(false);
@@ -1196,8 +1214,26 @@ window.__ModuleLoader__.load({
1196
1214
  await refresh();
1197
1215
  });
1198
1216
  };
1217
+ /**
1218
+ * Ask the Host to re-read the wallet now, and publish the state it answers
1219
+ * with: the same read the Host runs on its own cadence, taken early.
1220
+ */
1221
+ const refreshWallet = () => {
1222
+ (async () => {
1223
+ setWalletBusy(true);
1224
+ setError(void 0);
1225
+ try {
1226
+ setStatus(await api.refreshAccount());
1227
+ } catch (failure) {
1228
+ setError(t("account.failed", { message: messageOf(failure) }));
1229
+ } finally {
1230
+ setWalletBusy(false);
1231
+ }
1232
+ })();
1233
+ };
1199
1234
  const account = status?.account;
1200
1235
  const pending = status?.pending;
1236
+ const [vouchersBefore = "", vouchersAfter = ""] = t("account.vouchersEmpty").split("{link}");
1201
1237
  const minutes = pending === void 0 ? 0 : Math.max(1, Math.round((pending.expiresAt - Date.now()) / 6e4));
1202
1238
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1203
1239
  className: NearTokenSection_module_css_default.section,
@@ -1247,9 +1283,17 @@ window.__ModuleLoader__.load({
1247
1283
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
1248
1284
  className: NearTokenSection_module_css_default.factLabel,
1249
1285
  children: t("account.balance")
1250
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
1251
- className: NearTokenSection_module_css_default.factValue,
1252
- children: account?.balance ?? "—"
1286
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dd", {
1287
+ className: `${NearTokenSection_module_css_default.factValue} ${NearTokenSection_module_css_default.valueRow}`,
1288
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: account?.balance ?? "—" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1289
+ type: "button",
1290
+ className: NearTokenSection_module_css_default.refresh,
1291
+ disabled: walletBusy,
1292
+ onClick: refreshWallet,
1293
+ title: walletBusy ? t("account.refreshing") : t("account.refresh"),
1294
+ "aria-label": walletBusy ? t("account.refreshing") : t("account.refresh"),
1295
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineRegular, { size: 13 })
1296
+ })]
1253
1297
  })]
1254
1298
  }),
1255
1299
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1290,6 +1334,25 @@ window.__ModuleLoader__.load({
1290
1334
  })]
1291
1335
  }, `${voucher.groupId}:${voucher.group}`))
1292
1336
  })]
1337
+ }) : account !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1338
+ className: `${NearTokenSection_module_css_default.fact} ${NearTokenSection_module_css_default.voucherFact}`,
1339
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
1340
+ className: NearTokenSection_module_css_default.factLabel,
1341
+ children: t("account.vouchers")
1342
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dd", {
1343
+ className: NearTokenSection_module_css_default.voucherEmpty,
1344
+ children: [
1345
+ vouchersBefore,
1346
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1347
+ className: NearTokenSection_module_css_default.invite,
1348
+ href: `${status.baseURL}/wallet`,
1349
+ target: "_blank",
1350
+ rel: "noreferrer",
1351
+ children: t("account.vouchersInvite")
1352
+ }),
1353
+ vouchersAfter
1354
+ ]
1355
+ })]
1293
1356
  }) : null
1294
1357
  ]
1295
1358
  }),
@@ -1999,6 +2062,10 @@ window.__ModuleLoader__.load({
1999
2062
  "account.balance": "剩余额度",
2000
2063
  "account.used": "已用额度",
2001
2064
  "account.vouchers": "代金券",
2065
+ "account.vouchersEmpty": "你还没有代金券,你可以通过{link}获得免费代金券",
2066
+ "account.vouchersInvite": "邀请计划",
2067
+ "account.refresh": "刷新余额",
2068
+ "account.refreshing": "正在刷新…",
2002
2069
  "account.token": "API 令牌",
2003
2070
  "account.signOut": "断开连接",
2004
2071
  "account.signingOut": "正在断开…",
@@ -2090,6 +2157,10 @@ window.__ModuleLoader__.load({
2090
2157
  "account.balance": "Balance",
2091
2158
  "account.used": "Used",
2092
2159
  "account.vouchers": "Vouchers",
2160
+ "account.vouchersEmpty": "You have no vouchers yet. Get free vouchers through the {link}.",
2161
+ "account.vouchersInvite": "referral program",
2162
+ "account.refresh": "Refresh balance",
2163
+ "account.refreshing": "Refreshing…",
2093
2164
  "account.token": "API token",
2094
2165
  "account.signOut": "Disconnect",
2095
2166
  "account.signingOut": "Disconnecting…",
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["css","useSyncExternalStore","useState","useRef","useId","useMemo","css","IconDataOutlineRegular","StateDot","IconChevronDownOutlineRegular","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","MenuGroup","IconCheckOutlineRegular","useState","useCallback","css","useRef","IconChevronDownOutlineRegular"],"sources":["../src/protocol.ts","../src/client/api.ts","../src/client/groups.ts","../src/client/group-tags.tsx","../src/client/ModelGroupSelect.tsx","../src/client/NearTokenSection.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * The wire vocabulary shared by the Host routes and the browser section: the\n * route paths and the JSON each answers. Both build faces import this file, so\n * a route rename cannot leave the browser calling a path the Host stopped\n * serving.\n *\n * Nothing here carries a password: the plugin never collects site credentials.\n * A connection is authorized by the site's own device-authorization flow, in\n * the user's browser — the Host only polls its result.\n *\n * @module\n */\n\n/** State read by the settings page before it draws, and while it waits. */\nexport const STATUS_PATH = '/neartoken/status'\n/** Start a device authorization (the Host then polls the site). */\nexport const AUTHORIZE_PATH = '/neartoken/authorize'\n/** Abandon the authorization in progress. */\nexport const CANCEL_PATH = '/neartoken/cancel'\n/**\n * Ask the Host to open the pending confirmation page in the user's own browser.\n * The request carries no address: the Host opens the one it is waiting on.\n */\nexport const OPEN_PATH = '/neartoken/open'\n/** Forget the stored key and revoke it on the site. */\nexport const LOGOUT_PATH = '/neartoken/logout'\n/** Read the catalog beside the stored whitelist; POST a new whitelist. */\nexport const MODELS_PATH = '/neartoken/models'\n/** Read the picture models and the image-generation setting; POST one change to it. */\nexport const IMAGES_PATH = '/neartoken/images'\n\n/**\n * One group voucher the wallet carries: a balance that can only pay for its\n * own group. Amounts arrive as raw quota and are shown in the site's own\n * display currency, like every other money figure on the card.\n */\nexport interface NearTokenVoucher {\n /** Group name exactly as the site publishes it, badge prefixes included. */\n readonly group: string\n /** The group's stable id, as the site's group registry numbers it. */\n readonly groupId: number\n /** Remaining voucher balance, formatted in the site's display currency. */\n readonly amount: string\n}\n\n/** One account's facts, as the settings card shows them. */\nexport interface NearTokenAccountSummary {\n /** The dashboard user name. */\n readonly username: string\n /** The display name when the site set one, otherwise the user name. */\n readonly displayName: string\n /** The user's own group, which is the default group a request routes by. */\n readonly group: string\n /** Remaining quota, formatted in the site's own display currency. */\n readonly balance: string\n /** Quota already spent, formatted the same way. */\n readonly used: string\n /**\n * The per-group vouchers of the last wallet read, absent until one answered.\n * A grant does not carry them; they arrive with the first wallet refresh.\n */\n readonly vouchers?: readonly NearTokenVoucher[]\n}\n\n/** One authorization the human must finish in their browser. */\nexport interface NearTokenPendingAuthorization {\n /** The short code the site shows on its confirmation page. */\n readonly userCode: string\n /** The page to open; carries no code of its own. */\n readonly verificationUri: string\n /** The same page with the code prefilled. */\n readonly verificationUriComplete: string\n /** When this attempt stops being valid, as epoch milliseconds. */\n readonly expiresAt: number\n}\n\n/** The `GET /neartoken/status` answer. */\nexport interface NearTokenStatus {\n /** Whether an API key is stored, i.e. whether the provider route is mounted. */\n readonly configured: boolean\n /** Site root the plugin talks to. */\n readonly baseURL: string\n /** Name of the token the site created for this plugin. */\n readonly tokenName: string\n /** Account facts, absent until a connection obtained them. */\n readonly account?: NearTokenAccountSummary\n /** The authorization in progress, while one is running. */\n readonly pending?: NearTokenPendingAuthorization\n /** Why the last attempt ended without a key, until the next one starts. */\n readonly error?: string\n}\n\n/** One group's offering of a model, as the whitelist list shows it. */\nexport interface NearTokenModelGroup {\n /** Group name exactly as the site publishes it, badge prefixes included. */\n readonly group: string\n /** The group's multiplier caption (`0.4x`), absent when the site published none. */\n readonly ratio?: string\n}\n\n/** One model the whitelist can show or hide. */\nexport interface NearTokenModelEntry {\n /** Bare model name: the whitelist key, and what the site's API takes. */\n readonly model: string\n /** Every group offering this model, in catalog order. */\n readonly groups: readonly NearTokenModelGroup[]\n /**\n * The cheapest multiplier among those groups, when the site published one.\n * The list shows it beside the group count; the per-group detail stays in\n * the hover panel.\n */\n readonly minRatio?: number\n}\n\n/** The `GET /neartoken/models` answer. */\nexport interface NearTokenModelsState {\n /** Every model the site offers, in catalog order. */\n readonly models: readonly NearTokenModelEntry[]\n /** The stored whitelist; empty means no whitelist, so every model is shown. */\n readonly enabled: readonly string[]\n}\n\n/** The `POST /neartoken/models` request body. */\nexport interface NearTokenModelsPatch {\n /** Model names to keep visible; an empty list restores the whole catalog. */\n readonly enabled: readonly string[]\n}\n\n/** The `POST /neartoken/authorize` answer. */\nexport type BeginAuthorizationOutcome =\n | { readonly status: 'pending'; readonly pending: NearTokenPendingAuthorization }\n | { readonly status: 'failed'; readonly message: string }\n\n/**\n * Which request shape one picture model speaks: the images endpoint, Gemini's\n * own generateContent, or a chat completion.\n */\nexport type NearTokenImageChannel = 'images' | 'genai' | 'chat'\n\n/** One picture model the image-generation setting can enable. */\nexport interface NearTokenImageModelEntry {\n /** Bare model name, as the site's API takes it. */\n readonly model: string\n /** The request shape this model answers. */\n readonly channel: NearTokenImageChannel\n /** Every group offering this model, in catalog order. */\n readonly groups: readonly NearTokenModelGroup[]\n /** The cheapest multiplier among those groups, when the site published one. */\n readonly minRatio?: number\n}\n\n/** The `GET /neartoken/images` answer. */\nexport interface NearTokenImagesState {\n /** Whether the `generate_image` tool is mounted for this profile. */\n readonly enabled: boolean\n /** Every picture model the site offers, in catalog order. */\n readonly models: readonly NearTokenImageModelEntry[]\n /** The enabled models and the group each one routes through; empty means the tool has no model to call. */\n readonly selection: Readonly<Record<string, string>>\n}\n\n/** The `POST /neartoken/images` request body. */\nexport interface NearTokenImagesPatch {\n /** Whether the tool should be mounted. */\n readonly enabled: boolean\n /** Bare model name to the group name it must route through. */\n readonly models: Readonly<Record<string, string>>\n}\n\n","/**\n * The browser half of the settings-page carrier: same-origin calls to the Host\n * routes declared in ../protocol.ts.\n *\n * @module\n */\nimport {\n AUTHORIZE_PATH, CANCEL_PATH, IMAGES_PATH, LOGOUT_PATH, MODELS_PATH, OPEN_PATH, STATUS_PATH,\n} from '../protocol.ts'\nimport type {\n BeginAuthorizationOutcome, NearTokenImagesPatch, NearTokenImagesState, NearTokenModelsPatch,\n NearTokenModelsState, NearTokenStatus,\n} from '../protocol.ts'\n\n/** The HTTP carrier, injectable so the section's behavior is testable. */\nexport type Fetch = (input: string, init?: RequestInit) => Promise<Response>\n\n/** What the section calls. */\nexport interface NearTokenApi {\n /** Read the key state, the account card, and any authorization in progress. */\n status(): Promise<NearTokenStatus>\n /** Start a device authorization; the Host polls the site from then on. */\n begin(): Promise<BeginAuthorizationOutcome>\n /** Abandon the authorization in progress. */\n cancel(): Promise<void>\n /**\n * Hand the pending confirmation page to the user's own browser. The page\n * cannot do that itself: a window it opens stays inside the shell hosting it.\n */\n openBrowser(): Promise<void>\n /** Forget the stored key and revoke it on the site. */\n signOut(): Promise<void>\n /** Read the site's model catalog beside the stored whitelist. */\n models(): Promise<NearTokenModelsState>\n /** Save a whitelist; an empty list shows every model again. */\n saveModels(enabled: readonly string[]): Promise<void>\n /** Read the picture models beside the stored image-generation setting. */\n images(): Promise<NearTokenImagesState>\n /** Save the image-generation setting: the tool's switch and one group per enabled model. */\n saveImages(patch: NearTokenImagesPatch): Promise<void>\n}\n\n/**\n * Read one JSON answer, turning an HTTP refusal into a thrown error.\n * @param response - the pending response.\n * @returns the parsed body.\n * @throws {Error} when the route answered a non-2xx status.\n */\nasync function jsonOf<T>(response: Response): Promise<T> {\n if (!response.ok) throw new Error(`HTTP ${String(response.status)}`)\n return await response.json() as T\n}\n\n/**\n * Build the carrier.\n * @param fetcher - HTTP carrier; defaults to the page's own fetch.\n * @returns the section's four calls.\n */\nexport function createNearTokenApi(fetcher: Fetch = (input, init) => fetch(input, init)): NearTokenApi {\n /** POST one empty JSON body and read its JSON answer. */\n const post = async <T>(path: string): Promise<T> => jsonOf<T>(await fetcher(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n }))\n return {\n async status() {\n return await jsonOf<NearTokenStatus>(await fetcher(STATUS_PATH, { headers: { accept: 'application/json' } }))\n },\n async begin() {\n return await post<BeginAuthorizationOutcome>(AUTHORIZE_PATH)\n },\n async cancel() {\n await post<unknown>(CANCEL_PATH)\n },\n async openBrowser() {\n // No body: the Host opens the page it is already waiting on, so this route\n // can never be asked to launch an arbitrary address.\n const response = await fetcher(OPEN_PATH, { method: 'POST' })\n if (!response.ok) {\n // The Host names why the platform launcher did not run; that reason is\n // what the reader needs, not a status code.\n const refusal = await response.json().catch(() => ({ message: `HTTP ${String(response.status)}` })) as { message?: string }\n throw new Error(refusal.message ?? `HTTP ${String(response.status)}`)\n }\n },\n async signOut() {\n await post<unknown>(LOGOUT_PATH)\n },\n async models() {\n return await jsonOf<NearTokenModelsState>(await fetcher(MODELS_PATH, { headers: { accept: 'application/json' } }))\n },\n async saveModels(enabled) {\n await jsonOf<unknown>(await fetcher(MODELS_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ enabled } satisfies NearTokenModelsPatch),\n }))\n },\n async images() {\n return await jsonOf<NearTokenImagesState>(await fetcher(IMAGES_PATH, { headers: { accept: 'application/json' } }))\n },\n async saveImages(patch) {\n const response = await fetcher(IMAGES_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n })\n if (!response.ok) {\n // The Host refuses a selection its catalog does not have; its message\n // names the reason, so the page shows that rather than a status code.\n const refusal = await response.json().catch(() => ({ message: `HTTP ${String(response.status)}` })) as { message?: string }\n throw new Error(refusal.message ?? `HTTP ${String(response.status)}`)\n }\n },\n }\n}\n","/**\n * The group dimension, folded out of catalog names.\n *\n * The NearToken provider (this plugin's own host half) expands the site's\n * `/api/pricing` into one catalog model per (group, model) pair, named\n * `\"<model> @ <group>\"`. The picker folds those back into one row per model\n * and turns the group into its own selectable level.\n *\n * Group names carry a badge convention on the site: a run of bracketed tags\n * before the group's own name (`[低价][反重力] Claude`). Those render as\n * colored capsules; the ratio comes through the catalog entry's description\n * (`分组倍率 0.4x`).\n *\n * Prototype scope: the provider allowlist and the name separator are\n * hardcoded. They become Config fields once the shape settles.\n */\n\n/** Providers whose catalog names carry a group suffix. */\nexport const GROUPED_PROVIDERS: readonly string[] = ['neartoken']\n\n/**\n * Capsule tone of one group badge. Tier tags keep a fixed hue so a long list\n * reads at a glance; any other tag takes a hue derived from its own text.\n */\nexport type BadgeTone =\n | 'rose' | 'emerald' | 'violet' | 'sky' | 'amber' | 'cyan'\n | 'fuchsia' | 'indigo' | 'teal' | 'lime' | 'orange' | 'pink'\n\n/** Tags that carry a tier meaning, with the hue the site gives each of them. */\nconst KNOWN_TAG_TONES: Record<string, BadgeTone> = {\n 满血: 'rose',\n 低价: 'emerald',\n 神秘: 'violet',\n 官Key: 'sky',\n 官key: 'sky',\n 可蒸馏: 'amber',\n 反重力: 'cyan',\n 生图: 'fuchsia',\n AIS: 'indigo',\n 稳定: 'teal',\n}\n\n/** Hues used by tags with no tier meaning, spread out so neighbours differ. */\nconst FALLBACK_TONES: readonly BadgeTone[] = [\n 'sky', 'amber', 'cyan', 'fuchsia', 'indigo', 'teal',\n 'lime', 'orange', 'pink', 'emerald', 'violet', 'rose',\n]\n\n/**\n * @param tag - one bracketed tag's text.\n * @returns a stable bucket for hue selection.\n */\nfunction hashTag(tag: string): number {\n let hash = 0\n for (const char of tag) hash = (hash * 31 + (char.codePointAt(0) ?? 0)) % 100_003\n return hash\n}\n\n/** One capsule rendered before the group's own name. */\nexport interface GroupBadge {\n readonly text: string\n readonly tone: BadgeTone\n}\n\n/** One group label split into its badge capsules and its own name. */\nexport interface ParsedGroup {\n readonly badges: readonly GroupBadge[]\n readonly label: string\n}\n\n/** Separator between a model name and its group suffix in the catalog name. */\nconst GROUP_SEPARATOR = ' @ '\n\n/**\n * Split one catalog name into the model's own name and the optional group.\n * @param name - the catalog model name, e.g. `glm-5.3 @ [低价][满血] 国模`.\n * @returns the model name without the suffix, plus the group when present.\n */\nexport function splitModelName(name: string): { model: string; group?: string } {\n const at = name.lastIndexOf(GROUP_SEPARATOR)\n if (at <= 0) return { model: name }\n const group = name.slice(at + GROUP_SEPARATOR.length).trim()\n const model = name.slice(0, at).trim()\n if (model === '' || group === '') return { model: name }\n return { model, group }\n}\n\n/**\n * Parse one group name's bracketed badge prefix.\n * @param name - the raw group name, e.g. `[低价][反重力] Claude`.\n * @returns the badge capsules (in order) and the group's own name.\n */\nexport function parseGroupLabel(name: string): ParsedGroup {\n const badges: GroupBadge[] = []\n let rest = name\n while (rest.startsWith('[')) {\n const end = rest.indexOf(']')\n if (end <= 1) break\n badges.push(badgeOf(rest.slice(1, end)))\n rest = rest.slice(end + 1)\n }\n return { badges, label: rest.trim() }\n}\n\n/**\n * @param text - one bracketed badge's text.\n * @returns the capsule tone that text renders in.\n */\nfunction badgeOf(text: string): GroupBadge {\n const known = KNOWN_TAG_TONES[text.trim()]\n if (known !== undefined) return { text, tone: known }\n return { text, tone: FALLBACK_TONES[hashTag(text) % FALLBACK_TONES.length] ?? 'sky' }\n}\n\n/**\n * The capitals each vendor writes its own family name with.\n *\n * The catalog publishes ids in lowercase only, so the display name has to put\n * them back: GPT and GLM are acronyms, DeepSeek is camel case, MiniMax and MiMo\n * keep an inner capital, and the `xhigh` effort is spelled `XHigh` everywhere\n * else in the product.\n */\nconst BRAND_SPELLING: Readonly<Record<string, string>> = {\n gpt: 'GPT',\n glm: 'GLM',\n deepseek: 'DeepSeek',\n minimax: 'MiniMax',\n mimo: 'MiMo',\n xhigh: 'XHigh',\n tts: 'TTS',\n}\n\n/**\n * Render a model name the way the pickers show it: hyphens become separators\n * and every word is capitalized, so `claude-opus-5-c` reads `Claude Opus 5 C`.\n * A vendor's own spelling wins over that rule (`gpt-5.5` reads `GPT 5.5`).\n *\n * The trailing `-c` stays a word on purpose: the site pairs every such model\n * with a twin that lacks the suffix (`claude-opus-5` beside `claude-opus-5-c`),\n * so dropping it from the display would leave two different models with the\n * same name. {@link isCodingUnfriendly} is what tells the reader which one it\n * is looking at.\n * @param model - a bare model name.\n * @returns the display name.\n */\nexport function displayModelName(model: string): string {\n return model\n .split('-')\n .filter(part => part.length > 0)\n .map(part => BRAND_SPELLING[part.toLowerCase()] ?? part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ')\n}\n\n/**\n * Read the group ratio out of the host-provided catalog description.\n * @param description - the catalog entry's description (`分组倍率 0.4x`).\n * @returns the ratio caption, or undefined when the entry carries none.\n */\nexport function ratioOf(description: string | undefined): string | undefined {\n if (description === undefined) return undefined\n const match = description.match(/([\\d.]+)x/)\n return match === null ? undefined : `${match[1]}x`\n}\n\n/**\n * @param provider - a catalog provider id.\n * @returns whether this provider's model names carry group suffixes.\n */\nexport function isGroupedProvider(provider: string): boolean {\n return GROUPED_PROVIDERS.includes(provider)\n}\n\n/** One group's take on a model: the exact catalog entry that routes it. */\nexport interface ModelVariant<M> {\n readonly provider: string\n readonly group?: string\n readonly model: M\n}\n\n/** One model row: the display name plus every group that offers it. */\nexport interface ModelOption<M> {\n /** Fold key: the model name without its group suffix. */\n readonly key: string\n /** Displayed model name. */\n readonly label: string\n readonly variants: readonly ModelVariant<M>[]\n}\n\n/**\n * Fold one provider's models into rows, one per model name.\n *\n * A provider outside {@link GROUPED_PROVIDERS} keeps a 1:1 mapping (no suffix\n * parsing), so its rows behave exactly like the built-in picker's.\n * @param provider - the catalog provider id.\n * @param models - that provider's catalog models, in catalog order.\n * @returns one option per distinct model name, in first-seen order.\n */\nexport function foldModels<M extends { readonly id: string; readonly name: string }>(\n provider: string, models: readonly M[],\n): ModelOption<M>[] {\n const grouped = isGroupedProvider(provider)\n const byKey = new Map<string, { label: string; variants: ModelVariant<M>[] }>()\n for (const model of models) {\n const { model: label, group } = grouped ? splitModelName(model.name) : { model: model.name, group: undefined }\n const key = grouped ? label : model.id\n const row = byKey.get(key)\n const variant: ModelVariant<M> = { provider, model, ...group === undefined ? {} : { group } }\n if (row === undefined) byKey.set(key, { label, variants: [variant] })\n else row.variants.push(variant)\n }\n return [...byKey].map(([key, row]) => ({ key, label: row.label, variants: row.variants }))\n}\n\n/**\n * Pick the variant a model row should route to.\n * @param option - the row being chosen.\n * @param preferredProvider - the currently selected provider, kept when it offers the model.\n * @param preferredGroup - the currently selected group, kept when that provider offers it.\n * @returns the variant to submit.\n */\nexport function chooseVariant<M>(\n option: ModelOption<M>, preferredProvider: string | undefined, preferredGroup: string | undefined,\n): ModelVariant<M> | undefined {\n const local = option.variants.filter(variant => variant.provider === preferredProvider)\n const pool = local.length > 0 ? local : option.variants\n return pool.find(variant => variant.group === preferredGroup) ?? pool[0]\n}\n","/**\n * The site's group vocabulary, rendered the way the site renders it: a group\n * name's leading tags become colour-coded capsules, its multiplier becomes a\n * capsule that reads green below the base price, and a model the site marks\n * with a `-c` suffix carries a note.\n *\n * Both surfaces that show groups — the settings page's whitelist and the\n * composer's model seat — share these so one group never looks like two\n * different things in the same product.\n */\nimport type { BadgeTone } from './groups.ts'\nimport css from './group-tags.module.css'\n\n/** CSS Module class carrying each tone's hue, kept parallel to {@link BadgeTone}. */\nconst TONE_CLASS: Record<BadgeTone, string> = {\n rose: css.toneRose,\n emerald: css.toneEmerald,\n violet: css.toneViolet,\n sky: css.toneSky,\n amber: css.toneAmber,\n cyan: css.toneCyan,\n fuchsia: css.toneFuchsia,\n indigo: css.toneIndigo,\n teal: css.toneTeal,\n lime: css.toneLime,\n orange: css.toneOrange,\n pink: css.tonePink,\n}\n\n/** One bracketed group tag as a coloured capsule. */\nexport function GroupTag(props: { text: string; tone: BadgeTone }) {\n return <span className={css.tag + ' ' + TONE_CLASS[props.tone]}>{props.text}</span>\n}\n\n/**\n * One group's multiplier as a capsule.\n * @param props - the multiplier caption the catalog carried (`0.3x`).\n * @returns the capsule, toned by whether it beats the base price.\n */\nexport function RatioChip(props: { ratio: string }) {\n const value = Number.parseFloat(props.ratio)\n let tone = css.ratioBase\n if (Number.isFinite(value)) {\n if (value < 1) tone = css.ratioCheap\n else if (value > 1) tone = css.ratioPricey\n }\n return <span className={css.ratioChip + ' ' + tone}>{props.ratio}</span>\n}\n","/**\n * ModelGroupSelect: a drop-in replacement for the composer's model seat\n * ('conversation.input.model') that adds a THIRD level between the model and\n * the reasoning effort.\n *\n * The root menu is a row triple — Model / Group / Effort — where the Group row\n * appears only while the selected model comes from a provider whose catalog\n * names carry a group suffix (see groups.ts). The trigger states all three:\n * \"GLM 5.3 · Zhang · high\".\n *\n * Registered at priority -1, one step below the built-in seat, so the shipped\n * picker stays untouched and simply does not render.\n */\nimport { MenuGroup, MenuSurface, Input } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore,\n type CSSProperties, type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport type { ModelReasoningEffort, ModelSelection } from '@deepseek-ai/dsh-api-remotes/client'\nimport {\n IconCheckOutlineRegular, IconChevronDownOutlineRegular, IconChevronRightOutlineRegular,\n IconCloseFillRegular, IconDataOutlineRegular, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ModelGroupSelectInjected } from './slots.ts'\nimport type { ModelCatalogModel } from '@deepseek-ai/dsh-api-session-controller/types'\nimport {\n chooseVariant, displayModelName, foldModels, isGroupedProvider, parseGroupLabel, ratioOf,\n type ModelOption, type ModelVariant,\n} from './groups.ts'\nimport { GroupTag, RatioChip } from './group-tags.tsx'\nimport css from './ModelGroupSelect.module.css'\n\n/** Which pane the dropdown shows: the three-row root or one drilled-in list. */\ntype Pane = 'root' | 'model' | 'group' | 'effort'\n\n/** Unplaced portal card: hidden but laid out at a fixed origin so offset sizes are real. */\nconst MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }\n\n/** One provider's folded rows. */\ninterface ProviderRows<M> {\n readonly id: string\n readonly name: string\n readonly options: readonly ModelOption<M>[]\n}\n\n/** Provider display order: account first, official next, then catalog order. */\nfunction providerRank(id: string): number {\n return id === 'deepseek-account' ? 0 : id === 'deepseek-official' ? 1 : 2\n}\n\n/**\n * Case-insensitive containment filter for the model search.\n * @param label - the row's display name.\n * @param query - the trimmed search text; empty keeps every row.\n * @returns whether the row stays visible.\n */\nfunction matchesQuery(label: string, query: string): boolean {\n return query === '' || label.toLowerCase().includes(query.toLowerCase())\n}\n\n/**\n * Keep the effort the user already picked when the new model offers it.\n * @param model - the catalog model the selection will route to.\n * @param previous - the effort in use before the switch.\n * @returns the effort to submit, or undefined for a model without reasoning.\n */\nfunction effortFor(model: ModelCatalogModel, previous: string | undefined): string | undefined {\n const reasoning = model.reasoning\n if (reasoning === undefined) return undefined\n if (previous !== undefined && reasoning.efforts.some(level => level.id === previous)) return previous\n return reasoning.defaultEffort\n}\n\n/**\n * Render the composer model seat with the group level.\n * @param props - owner share (locked) + injected directory face + the locale seat.\n * @returns the trigger and, while open, the three-level menu.\n */\nexport function ModelGroupSelect(\n { locked, available, directory, load, select, t }:\n ModelGroupSelectInjected & Pick<PropsRuntime<'conversation.input.model'>, 'locked'> & PropsLocale<'modelGroups'>,\n) {\n const state = useSyncExternalStore(\n fn => directory.subscribe(fn),\n () => directory.getSnapshot(),\n )\n const [open, setOpen] = useState(false)\n const [pane, setPane] = useState<Pane>('root')\n const [query, setQuery] = useState('')\n const [highlighted, setHighlighted] = useState(0)\n const [toast, setToast] = useState<string | null>(null)\n const rootRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const searchRef = useRef<HTMLInputElement | null>(null)\n const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n\n const accountName = t('provider.account')\n const providers = useMemo<ProviderRows<ModelCatalogModel>[]>(() => state.groups\n .map(group => ({\n id: group.id,\n name: group.id === 'deepseek-account' ? accountName : group.name,\n options: foldModels(group.id, group.models),\n }))\n .toSorted((left, right) => providerRank(left.id) - providerRank(right.id)), [state.groups, accountName])\n\n const current = state.current\n const located = useMemo(() => {\n for (const provider of providers) {\n for (const option of provider.options) {\n for (const variant of option.variants) {\n if (variant.provider === current?.provider && variant.model.id === current.model) {\n return { provider, option, variant }\n }\n }\n }\n }\n return undefined\n }, [providers, current])\n\n const reasoning = located?.variant.model.reasoning\n const effectiveEffort = current?.reasoningEffort ?? reasoning?.defaultEffort\n const effortLabel = located === undefined\n ? undefined\n : reasoning === undefined\n ? state.retainedEffort\n : effectiveEffort === undefined\n ? t('effort.providerDefault')\n : reasoning.efforts.find((level: ModelReasoningEffort) => level.id === effectiveEffort)?.name ?? effectiveEffort\n\n const currentGroup = located?.variant.group\n const groupChoices = useMemo(() => located === undefined || currentGroup === undefined\n ? []\n : located.option.variants.filter(variant => variant.provider === located.provider.id\n && variant.group !== undefined), [located, currentGroup])\n\n const filteredProviders = useMemo(() => {\n const trimmed = query.trim()\n return providers\n .map(provider => ({\n ...provider,\n options: provider.options.filter(option => matchesQuery(option.label, trimmed)),\n }))\n .filter(provider => provider.options.length > 0)\n }, [providers, query])\n\n const visibleOptions = useMemo(() => filteredProviders.flatMap(provider =>\n provider.options.map(option => ({ provider, option }))), [filteredProviders])\n const showSearch = providers.reduce((total, provider) => total + provider.options.length, 0) > 4\n const activeIndex = Math.min(highlighted, Math.max(0, visibleOptions.length - 1))\n const { pending } = state\n const busy = pending !== null\n const waiting = located === undefined && state.status === 'loading'\n\n const show = (): void => {\n triggerRef.current?.focus()\n setQuery('')\n setHighlighted(0)\n setPane(located === undefined ? 'model' : 'root')\n setOpen(true)\n load()\n }\n\n const close = (restoreFocus = false): void => {\n setOpen(false)\n setPane('root')\n if (restoreFocus) queueMicrotask(() => { triggerRef.current?.focus() })\n }\n\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: MouseEvent): void => {\n if (rootRef.current?.contains(event.target as Node) === true) return\n if (menuRef.current?.contains(event.target as Node) === true) return\n setOpen(false)\n setPane('root')\n }\n document.addEventListener('mousedown', closeOutside)\n return () => { document.removeEventListener('mousedown', closeOutside) }\n }, [open])\n\n useLayoutEffect(() => {\n if (!available || !open) { setMenuPos(null); return }\n const place = (): void => {\n const rect = triggerRef.current?.getBoundingClientRect()\n if (rect === undefined) return\n const MARGIN = 12\n const width = menuRef.current?.offsetWidth ?? 0\n const height = menuRef.current?.offsetHeight ?? 0\n let x = rect.right - width\n let y = rect.top - 8 - height\n if (width > 0) x = Math.min(Math.max(x, MARGIN), window.innerWidth - width - MARGIN)\n if (height > 0) y = Math.min(Math.max(y, MARGIN), window.innerHeight - height - MARGIN)\n setMenuPos({ left: x, top: y })\n }\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n return () => {\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [available, open, pane, state, query])\n\n useLayoutEffect(() => {\n if (open && pane === 'model' && showSearch) searchRef.current?.focus()\n }, [open, pane, showSearch])\n\n if (!available) return null\n\n const settle = (result: Awaited<ReturnType<ModelGroupSelectInjected['select']>>): void => {\n if (result === undefined) return\n if (result.ok) {\n setOpen(false)\n setPane('root')\n return\n }\n const { error } = result\n setToast(error.code === 'session/writer-held'\n ? t('error.sessionInUse')\n : t('error.action', { message: `${error.code}: ${error.message}` }))\n }\n\n const submit = (selection: ModelSelection): void => {\n triggerRef.current?.focus()\n void select(selection).then(settle)\n }\n\n const chooseOption = (option: ModelOption<ModelCatalogModel>): void => {\n const variant = chooseVariant(option, current?.provider, currentGroup)\n if (variant === undefined) return\n if (current?.provider === variant.provider && current.model === variant.model.id) {\n close(true)\n return\n }\n const effort = effortFor(variant.model, effectiveEffort)\n submit({\n provider: variant.provider,\n model: variant.model.id,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const chooseGroup = (variant: ModelVariant<ModelCatalogModel>): void => {\n if (current === null) return\n if (variant.model.id === current.model) {\n close(true)\n return\n }\n const effort = effortFor(variant.model, effectiveEffort)\n submit({\n provider: variant.provider,\n model: variant.model.id,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const chooseEffort = (effort: string | undefined): void => {\n if (current === null) return\n if (effectiveEffort === effort) {\n close(true)\n return\n }\n submit({\n provider: current.provider,\n model: current.model,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n if (event.nativeEvent.isComposing) return\n if (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== 'root' && located !== undefined) setPane('root')\n else close(true)\n return\n }\n if (!open || pane !== 'root') return\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault()\n setPane('root')\n }\n }\n\n // Only this plugin's own provider gets the rewritten name: every other\n // provider's models are the application's own catalog entries, so the seat\n // must keep showing them exactly as the built-in seat does. The group is a\n // routing dimension and is never spelled out here.\n const ownProvider = located !== undefined && isGroupedProvider(located.provider.id)\n const modelLabel = waiting\n ? t('trigger.loading')\n : located === undefined\n ? t('trigger.fallback')\n : ownProvider\n ? `${displayModelName(located.option.label)} @ ${located.provider.name}`\n : located.option.label\n const triggerParts = [modelLabel, effortLabel].filter(part => part !== undefined && part !== '')\n const triggerLabel = triggerParts.join(' · ')\n const triggerAria = waiting\n ? t('trigger.loading')\n : located === undefined\n ? t('trigger.selectAria')\n : t('trigger.aria', { model: modelLabel })\n\n let optionIndex = 0\n\n return (\n <div ref={rootRef} className={css.root} onKeyDown={onKeyDown}>\n <button\n ref={triggerRef}\n type=\"button\"\n className={css.trigger}\n aria-label={triggerAria}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? `${id}-menu` : undefined}\n title={triggerLabel}\n aria-busy={busy}\n disabled={locked}\n onClick={() => { if (open) close(true); else show() }}\n >\n <IconDataOutlineRegular className={css.triggerIcon} size={16} />\n <span className={css.triggerLabel}>{modelLabel}</span>\n {effortLabel !== undefined && <span className={css.triggerEffort}>{effortLabel}</span>}\n {busy\n ? <StateDot state=\"ongoing\" />\n : <IconChevronDownOutlineRegular className={css.chevron} />}\n </button>\n\n {open && createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={css.menu}\n style={menuPos ?? MEASURE_STYLE}\n role={pane === 'model' || pane === 'group' ? 'group' : 'menu'}\n aria-label={t('menu.aria')}\n aria-busy={state.status === 'loading' || busy}\n >\n {pane === 'root' && (\n <>\n <button type=\"button\" role=\"menuitem\" className={css.cell} onClick={() => { setPane('model') }}>\n <span className={css.cellLabel}>{t('menu.model')}</span>\n <span className={css.cellValue}>{modelLabel}</span>\n <IconChevronRightOutlineRegular className={css.cellChevron} />\n </button>\n {currentGroup !== undefined && (\n <button\n type=\"button\"\n role=\"menuitem\"\n className={css.cell}\n disabled={groupChoices.length < 2}\n onClick={() => { setPane('group') }}\n >\n <span className={css.cellLabel}>{t('menu.group')}</span>\n <span className={css.cellValue}>\n <GroupInline group={currentGroup} description={located?.variant.model.description} showRatio />\n </span>\n {groupChoices.length > 1 && <IconChevronRightOutlineRegular className={css.cellChevron} />}\n </button>\n )}\n {reasoning !== undefined && (\n <button type=\"button\" role=\"menuitem\" className={css.cell} onClick={() => { setPane('effort') }}>\n <span className={css.cellLabel}>{t('menu.effort')}</span>\n <span className={css.cellValue}>{effortLabel}</span>\n <IconChevronRightOutlineRegular className={css.cellChevron} />\n </button>\n )}\n </>\n )}\n\n {pane === 'model' && (\n <>\n {showSearch && (\n <div className={css.searchRow}>\n <Input\n ref={searchRef}\n className={css.search}\n type=\"text\"\n role=\"searchbox\"\n aria-label={t('search.placeholder')}\n placeholder={t('search.placeholder')}\n value={query}\n readOnly={busy}\n onChange={(event) => { setQuery(event.target.value); setHighlighted(0) }}\n />\n {query !== '' && (\n <button\n type=\"button\"\n className={css.searchClear}\n aria-label={t('search.clear')}\n disabled={busy}\n onClick={() => { setQuery(''); searchRef.current?.focus() }}\n >\n <IconCloseFillRegular />\n </button>\n )}\n </div>\n )}\n {state.status === 'loading' && <div className={css.status}>{t('status.loading')}</div>}\n {state.error !== null && (\n <div className={css.error}>\n <span>{t('error.action', { message: state.error })}</span>\n <button type=\"button\" className={css.retry} onClick={load}>{t('action.reload')}</button>\n </div>\n )}\n {state.failures.map(failure => (\n <div className={css.warning} key={failure.id}>\n <span>{t('warning.groupLoad', { name: failure.id === 'deepseek-account' ? accountName : failure.name, message: failure.message })}</span>\n <button type=\"button\" className={css.retry} onClick={load}>{t('action.reload')}</button>\n </div>\n ))}\n <div className={css.groups} role=\"menu\" aria-label={t('menu.model')} hidden={filteredProviders.length === 0}>\n {filteredProviders.map(provider => (\n <MenuGroup key={provider.id} label={provider.name}>\n {provider.options.map(option => {\n const index = optionIndex++\n const isCurrent = located !== undefined && located.option.key === option.key\n && located.provider.id === provider.id\n const groups = option.variants.filter(variant => variant.group !== undefined)\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isCurrent}\n id={`${id}-model-${index}`}\n tabIndex={showSearch ? -1 : 0}\n onFocus={() => { setHighlighted(index) }}\n data-highlighted={index === activeIndex ? '' : undefined}\n className={css.option + ' ' + css.modelOption + ' ' + (index === activeIndex ? css.optionActive : '')}\n key={option.key}\n title={option.label}\n disabled={busy}\n onMouseMove={() => { setHighlighted(index) }}\n onClick={() => { chooseOption(option) }}\n >\n <span className={css.optionCopy}>\n <span className={css.modelName}>\n {isGroupedProvider(provider.id) ? displayModelName(option.label) : option.label}\n </span>\n\n </span>\n <span className={css.optionTrailing}>\n {groups.length > 1 && <span className={css.variantCount}>{groups.length}</span>}\n <span className={css.check}>\n {isCurrent ? <IconCheckOutlineRegular /> : null}\n </span>\n </span>\n </button>\n )\n })}\n </MenuGroup>\n ))}\n </div>\n {state.status === 'ready' && filteredProviders.length === 0 && (\n <div className={css.empty} role=\"status\">\n {t(providers.length === 0 ? 'empty.models' : 'search.empty')}\n </div>\n )}\n </>\n )}\n\n {pane === 'group' && (\n <>\n {groupChoices.length === 0\n ? <div className={css.empty}>{t('empty.groups')}</div>\n : groupChoices.map((variant) => {\n const isCurrent = variant.model.id === current?.model\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isCurrent}\n className={css.option + (isCurrent ? ' ' + css.selected : '')}\n key={variant.model.id}\n disabled={busy}\n onClick={() => { chooseGroup(variant) }}\n >\n <span className={css.optionCopy}>\n <span className={css.groupOptionLabel}>\n <GroupInline group={variant.group ?? ''} description={variant.model.description} showRatio />\n </span>\n </span>\n <span className={css.check}>\n {isCurrent ? <IconCheckOutlineRegular /> : null}\n </span>\n </button>\n )\n })}\n </>\n )}\n\n {pane === 'effort' && (\n <>\n {(reasoning?.efforts.length ?? 0) === 0\n ? <div className={css.empty}>{t('empty.efforts')}</div>\n : [\n ...reasoning?.defaultEffort === undefined\n ? [{ id: undefined as string | undefined, name: t('effort.providerDefault') }]\n : [],\n ...(reasoning?.efforts ?? []).map((level: ModelReasoningEffort) => ({ id: level.id as string | undefined, name: level.name })),\n ].map(level => (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={effectiveEffort === level.id}\n className={css.option + (effectiveEffort === level.id ? ' ' + css.selected : '')}\n key={level.id ?? 'provider-default'}\n disabled={busy}\n onClick={() => { chooseEffort(level.id) }}\n >\n <span className={css.optionCopy}>\n <span className={css.modelName}>{level.name}</span>\n </span>\n <span className={css.check}>\n {effectiveEffort === level.id ? <IconCheckOutlineRegular /> : null}\n </span>\n </button>\n ))}\n </>\n )}\n </MenuSurface>,\n document.body,\n )}\n {toast !== null && <div className={css.toast} role=\"status\">{toast}</div>}\n </div>\n )\n}\n\n/**\n * One group's inline rendering: badge capsules, its own name, and optionally the\n * ratio badge.\n * @param props - the group key, its hardcoded style, and whether to show the ratio.\n * @returns the inline group value.\n */\nfunction GroupInline(\n { group, description, showRatio = false }: { group: string; description?: string; showRatio?: boolean },\n) {\n const { badges, label } = parseGroupLabel(group)\n const ratio = showRatio ? ratioOf(description) : undefined\n return (\n <span className={css.groupInline}>\n {badges.map(badge => <GroupTag key={badge.text} text={badge.text} tone={badge.tone} />)}\n <span className={css.groupName}>{label}</span>\n {ratio !== undefined && <RatioChip ratio={ratio} />}\n </span>\n )\n}\n\n\n","/**\n * The NearToken settings page: connect the plugin to the site's account through\n * the site's own device-authorization flow, show whose account is connected, and\n * disconnect.\n *\n * The page never asks for a password. It shows the short code the site issued,\n * offers the site's confirmation page, and re-reads the Host while the Host polls\n * — the key and the provider insertion both happen on the Host side of a grant.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { IconChevronDownOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {\n NearTokenImageModelEntry, NearTokenImagesState, NearTokenModelEntry, NearTokenModelsState, NearTokenStatus,\n} from '../protocol.ts'\nimport type { NearTokenApi } from './api.ts'\nimport { parseGroupLabel } from './groups.ts'\nimport { GroupTag, RatioChip } from './group-tags.tsx'\nimport type { GroupKey } from './locales.ts'\nimport css from './NearTokenSection.module.css'\n\n/** How often the page re-reads the Host while an authorization is pending. */\nconst PENDING_REFRESH_MS = 1_500\n\n/**\n * How often the page re-reads the Host while connected, so the card shows the\n * wallet numbers the Host re-reads at the same cadence.\n */\nconst CONNECTED_REFRESH_MS = 300_000\n\n/** How long a burst of checkbox clicks waits before one save is written. */\nconst AUTOSAVE_DELAY_MS = 400\n\n/** How long the copy button acknowledges a copied address before resetting. */\nconst COPIED_RESET_MS = 2_000\n\n/** What this section receives from its registration. */\nexport interface NearTokenSectionInjected {\n /** The Host's four routes. */\n api: NearTokenApi\n /** Bound translate for this plugin's dictionary. */\n t: (key: GroupKey, vars?: Record<string, string>) => string\n}\n\n/** Full component props: the section owner share plus this section's injected face. */\nexport type NearTokenSectionProps = PropsRuntime<'settings.section'> & NearTokenSectionInjected\n\n/**\n * Render the NearToken settings page.\n * @param props - the injected route carrier and translate, plus slot owner props.\n * @returns the section element tree.\n */\nexport function NearTokenSection({ api, t }: NearTokenSectionProps) {\n const [status, setStatus] = useState<NearTokenStatus | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n /** Whether the confirmation address was just copied to the clipboard. */\n const [copied, setCopied] = useState(false)\n\n /** Re-read the Host state and publish it. */\n const refresh = useCallback(async (): Promise<void> => {\n try {\n setStatus(await api.status())\n } catch (failure: unknown) {\n setError(t('account.failed', { message: messageOf(failure) }))\n }\n }, [api, t])\n\n // The page opens on whatever the Host already knows, so a reload neither\n // restarts a pending authorization nor forgets a finished one.\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n const pendingCode = status?.pending?.userCode\n const waiting = pendingCode !== undefined\n // A new attempt offers a new address, so the copy acknowledgement starts over.\n useEffect(() => { setCopied(false) }, [pendingCode])\n useEffect(() => {\n if (!copied) return\n const timer = setTimeout(() => { setCopied(false) }, COPIED_RESET_MS)\n return () => { clearTimeout(timer) }\n }, [copied])\n // While the Host polls the site, the page polls the Host: the grant, the\n // refusal, and the expiry all arrive as a changed status.\n useEffect(() => {\n if (!waiting) return\n const timer = setInterval(() => { void refresh() }, PENDING_REFRESH_MS)\n return () => { clearInterval(timer) }\n }, [waiting, pendingCode, refresh])\n\n // While connected, the Host refreshes the wallet on its own cadence; the\n // page re-reads the status at the same rate so those numbers reach the card.\n const connected = status?.configured === true\n useEffect(() => {\n if (!connected) return\n const timer = setInterval(() => { void refresh() }, CONNECTED_REFRESH_MS)\n return () => { clearInterval(timer) }\n }, [connected, refresh])\n\n /** Run one Host call with the busy flag and the error channel wired. */\n const run = useCallback(async (action: () => Promise<void>): Promise<void> => {\n setBusy(true)\n setError(undefined)\n try {\n await action()\n } catch (failure: unknown) {\n setError(t('account.failed', { message: messageOf(failure) }))\n } finally {\n setBusy(false)\n }\n }, [t])\n\n const connect = (): void => {\n void run(async () => {\n const outcome = await api.begin()\n if (outcome.status === 'failed') setError(t('account.failed', { message: outcome.message }))\n await refresh()\n })\n }\n const cancel = (): void => {\n void run(async () => {\n await api.cancel()\n await refresh()\n })\n }\n\n /**\n * Hand the confirmation page to the user's own browser, through the Host: a\n * window the page opens stays inside the shell hosting it — a desktop build\n * shows another application window, and macOS may refuse outright. The\n * address is printed below as well, for a machine with no launcher at all.\n */\n const openAddress = (): void => {\n void (async (): Promise<void> => {\n setError(undefined)\n try {\n await api.openBrowser()\n } catch (failure: unknown) {\n setError(t('account.openFailed', { message: messageOf(failure) }))\n }\n })()\n }\n\n /**\n * Copy the confirmation address, for a machine where nothing can be launched.\n */\n const copyAddress = (): void => {\n const address = status?.pending?.verificationUriComplete\n if (address === undefined) return\n void (async (): Promise<void> => {\n try {\n await navigator.clipboard.writeText(address)\n setCopied(true)\n } catch {\n setError(t('account.copyFailed'))\n }\n })()\n }\n const signOut = (): void => {\n void run(async () => {\n await api.signOut()\n await refresh()\n })\n }\n\n const account = status?.account\n const pending = status?.pending\n const minutes = pending === undefined ? 0 : Math.max(1, Math.round((pending.expiresAt - Date.now()) / 60_000))\n return (\n <div className={css.section}>\n <h2 className={css.title}>{t('account.title')}</h2>\n {status === undefined\n ? <p className={css.hint}>{t('account.loading')}</p>\n : status.configured\n ? (\n <section className={css.card}>\n <div className={css.cardHead}>\n <span className={css.name}>{account?.displayName ?? 'NearToken'}</span>\n {account === undefined ? null : <span className={css.handle}>@{account.username}</span>}\n <span className={`${css.badge} ${css.badgeOn}`}>{t('account.connected')}</span>\n </div>\n <dl className={css.facts}>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.group')}</dt>\n <dd className={css.factValue}>{account?.group ?? '—'}</dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.balance')}</dt>\n <dd className={css.factValue}>{account?.balance ?? '—'}</dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.used')}</dt>\n <dd className={css.factValue}>{account?.used ?? '—'}</dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.token')}</dt>\n <dd className={css.factValue}>{status.tokenName}</dd>\n </div>\n {account !== undefined && (account.vouchers?.length ?? 0) > 0\n ? (\n <div className={`${css.fact} ${css.voucherFact}`}>\n <dt className={css.factLabel}>{t('account.vouchers')}</dt>\n <dd className={css.voucherList}>\n {account.vouchers?.map(voucher => (\n <span key={`${voucher.groupId}:${voucher.group}`} className={css.voucherRow}>\n <span className={css.voucherGroup}>{voucher.group}</span>\n <span className={css.voucherAmount}>{voucher.amount}</span>\n </span>\n ))}\n </dd>\n </div>\n )\n : null}\n </dl>\n <div className={css.actions}>\n <button type=\"button\" className={css.button} disabled={busy} onClick={signOut}>\n {busy ? t('account.signingOut') : t('account.signOut')}\n </button>\n </div>\n </section>\n )\n : (\n <section className={css.card}>\n <div className={css.cardHead}>\n <span className={css.name}>{t('account.title')}</span>\n <span className={css.badge}>{t('account.disconnected')}</span>\n </div>\n <p className={css.hint}>{t('account.site')}:{status.baseURL}</p>\n {pending === undefined\n ? (\n <div className={css.actions}>\n <button\n type=\"button\" className={`${css.button} ${css.buttonPrimary}`} disabled={busy} onClick={connect}\n >\n {busy ? t('account.connecting') : t('account.connect')}\n </button>\n </div>\n )\n : (\n <div className={css.form}>\n <p className={css.hint}>{t('account.waiting')}</p>\n <div className={css.codeRow}>\n <span className={css.label}>{t('account.userCode')}</span>\n <code className={css.code}>{pending.userCode}</code>\n </div>\n <div className={css.actions}>\n <button\n type=\"button\" className={`${css.button} ${css.buttonPrimary}`}\n onClick={openAddress}\n >\n {t('account.openBrowser')}\n </button>\n <button type=\"button\" className={css.button} disabled={busy} onClick={cancel}>\n {busy ? t('account.cancelling') : t('account.cancel')}\n </button>\n </div>\n {/* Some platforms (macOS among them) let the automatic\n browser launch do nothing, so the address is also handed\n over as selectable text that can be copied by hand. */}\n <div className={css.linkRow}>\n <span className={css.label}>{t('account.manualLink')}</span>\n <div className={css.linkLine}>\n <a\n className={css.link} href={pending.verificationUriComplete}\n target=\"_blank\" rel=\"noopener noreferrer\"\n >\n {pending.verificationUriComplete}\n </a>\n <button type=\"button\" className={css.button} onClick={copyAddress}>\n {copied ? t('account.copied') : t('account.copyLink')}\n </button>\n </div>\n </div>\n <p className={css.hint}>{t('account.expiresIn', { minutes: String(minutes) })}</p>\n </div>\n )}\n </section>\n )}\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n {status?.error === undefined ? null : <p className={css.notice}>{t('account.failed', { message: status.error })}</p>}\n {status?.configured === true ? <ModelWhitelist api={api} t={t} /> : null}\n {status?.configured === true ? <ImageGeneration api={api} t={t} /> : null}\n </div>\n )\n}\n\n/**\n * The model whitelist block: which of the site's models the provider keeps in\n * the model picker, edited through the same-origin models carrier.\n *\n * An empty stored list means \"no whitelist\", so the boxes start all checked —\n * that is what the picker currently shows. Saving an empty list is refused\n * here, because it would read as the same \"no whitelist\" state; \"Show all\"\n * (which saves exactly that) is the explicit way back to the whole catalog.\n * @param props - the injected route carrier and translate.\n * @returns the whitelist block.\n */\nfunction ModelWhitelist({ api, t }: NearTokenSectionInjected) {\n const [state, setState] = useState<NearTokenModelsState | undefined>(undefined)\n const [selected, setSelected] = useState<ReadonlySet<string>>(new Set())\n const [query, setQuery] = useState('')\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n const [saved, setSaved] = useState(false)\n /** Why the last edit could not be applied; cleared by the next one. */\n const [notice, setNotice] = useState<string | undefined>(undefined)\n /** Whether the list itself is showing; the card opens collapsed. */\n const [open, setOpen] = useState(false)\n /** The queued save, while a burst of clicks is still settling. */\n const pending = useRef<number | undefined>(undefined)\n // The row whose group detail is showing, positioned in viewport coordinates:\n // the list scrolls, so the panel must escape its clip box rather than live in\n // the row's flow.\n const [tip, setTip] = useState<{ entry: NearTokenModelEntry; top: number; left: number } | undefined>(undefined)\n\n /** Publish one host answer: the boxes show the stored list, or all when none is stored. */\n const adopt = useCallback((next: NearTokenModelsState): void => {\n setState(next)\n setSelected(new Set(next.enabled.length === 0 ? next.models.map(entry => entry.model) : next.enabled))\n }, [])\n\n const load = useCallback(async (): Promise<void> => {\n try {\n adopt(await api.models())\n } catch (failure: unknown) {\n setError(t('whitelist.failed', { message: messageOf(failure) }))\n }\n }, [adopt, api, t])\n\n useEffect(() => { void load() }, [load])\n\n const models = state?.models ?? []\n const needle = query.trim().toLowerCase()\n const visible = needle === ''\n ? models\n : models.filter(entry => entry.model.toLowerCase().includes(needle))\n\n /** Cancel the pending save, if one is queued. */\n const cancelPending = useCallback((): void => {\n if (pending.current === undefined) return\n window.clearTimeout(pending.current)\n pending.current = undefined\n }, [])\n\n // A queued save must not outlive the page it belongs to.\n useEffect(() => cancelPending, [cancelPending])\n\n /**\n * Apply an edit to the boxes and queue one save.\n *\n * The list is stored as it is edited — there is no Save button to forget —\n * so the delay only coalesces a burst of clicks into one profile write.\n */\n const edit = (next: ReadonlySet<string>): void => {\n setSaved(false)\n setNotice(undefined)\n setSelected(next)\n cancelPending()\n // Catalog order, not click order: the stored list reads like the picker.\n const enabled = models.filter(entry => next.has(entry.model)).map(entry => entry.model)\n pending.current = window.setTimeout(() => {\n pending.current = undefined\n void persist(enabled)\n }, AUTOSAVE_DELAY_MS)\n }\n\n const toggle = (model: string): void => {\n const next = new Set(selected)\n if (next.has(model)) next.delete(model)\n else next.add(model)\n // An empty list means \"no whitelist\", i.e. show everything — the opposite\n // of what unchecking the last box asks for.\n if (next.size === 0) {\n setNotice(t('whitelist.keepOne'))\n return\n }\n edit(next)\n }\n /** Show one row's groups just below it, above it when there is no room. */\n const showTip = (entry: NearTokenModelEntry, anchor: HTMLElement): void => {\n const rect = anchor.getBoundingClientRect()\n const height = Math.min(240, 34 + entry.groups.length * 20)\n const below = rect.bottom + 6\n setTip({\n entry,\n top: below + height > window.innerHeight ? Math.max(12, rect.top - height - 6) : below,\n left: Math.max(12, Math.min(rect.left + 24, window.innerWidth - 292)),\n })\n }\n const checkVisible = (): void => {\n edit(new Set([...selected, ...visible.map(entry => entry.model)]))\n }\n /**\n * Empty the boxes the filter is showing.\n *\n * An emptied selection cannot be saved as such: an empty stored list means\n * \"no whitelist\", i.e. show every model, which is the opposite of the click.\n * So the boxes empty at once and the saved list is left alone; the next check\n * box saves the set the user actually wants, and \"Show all\" is the way back.\n */\n const uncheckVisible = (): void => {\n const hidden = new Set(visible.map(entry => entry.model))\n const next = new Set([...selected].filter(model => !hidden.has(model)))\n if (next.size > 0) {\n edit(next)\n return\n }\n cancelPending()\n setSaved(false)\n setSelected(next)\n setNotice(t('whitelist.cleared'))\n }\n\n /**\n * Write one list to the Host, which re-declares the provider route so the\n * model picker refetches without a page reload.\n * @param enabled - the model names to keep visible; empty restores everything.\n */\n const persist = useCallback(async (enabled: readonly string[]): Promise<void> => {\n setSaving(true)\n setError(undefined)\n try {\n await api.saveModels(enabled)\n setSaved(true)\n } catch (failure: unknown) {\n setError(t('whitelist.failed', { message: messageOf(failure) }))\n } finally {\n setSaving(false)\n }\n }, [api, t])\n\n /** Restore the whole catalog: nothing hidden, nothing stored. */\n const showEverything = (): void => {\n cancelPending()\n setSelected(new Set(models.map(entry => entry.model)))\n void persist([])\n }\n\n return (\n <section className={css.card}>\n <button\n type=\"button\"\n className={css.cardToggle}\n aria-expanded={open}\n aria-label={t(open ? 'card.collapse' : 'card.expand')}\n onClick={() => { setOpen((current) => !current) }}\n >\n <span className={css.name}>{t('whitelist.title')}</span>\n <span className={css.count}>\n <span className={css.countTotal}>{t('whitelist.count', { total: String(models.length) })}</span>\n <span className={css.countDot} aria-hidden=\"true\" />\n <span className={css.countPicked}>{t('whitelist.picked', { selected: String(selected.size) })}</span>\n </span>\n <IconChevronDownOutlineRegular\n className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron}\n size={14}\n />\n </button>\n {!open ? null : <>\n <p className={css.intro}>{t('whitelist.intro')}</p>\n {state === undefined\n ? (error === undefined ? <p className={css.hint}>{t('whitelist.loading')}</p> : null)\n : (\n <div className={css.form}>\n <input\n className={css.search}\n type=\"search\"\n value={query}\n placeholder={t('whitelist.search')}\n aria-label={t('whitelist.search')}\n onChange={(event) => { setQuery(event.target.value) }}\n />\n <div className={css.toolbar}>\n <button type=\"button\" className={css.button} disabled={saving || visible.length === 0} onClick={checkVisible}>\n {t('whitelist.selectAll')}\n </button>\n <button type=\"button\" className={css.button} disabled={saving || visible.length === 0} onClick={uncheckVisible}>\n {t('whitelist.clear')}\n </button>\n <button type=\"button\" className={css.button} disabled={saving} onClick={showEverything}>\n {t('whitelist.reset')}\n </button>\n <span className={css.autosave} aria-live=\"polite\">\n {saving ? t('whitelist.saving') : saved ? t('whitelist.autoSaved') : ''}\n </span>\n </div>\n {models.length === 0\n ? <p className={css.hint}>{t('whitelist.empty')}</p>\n : (\n <div className={css.list} onScroll={() => { setTip(undefined) }}>\n {visible.length === 0\n ? <p className={css.hint}>{t('whitelist.noMatch')}</p>\n : visible.map(entry => (\n <label\n key={entry.model}\n className={css.row}\n onMouseEnter={(event) => { showTip(entry, event.currentTarget) }}\n onMouseLeave={() => { setTip(undefined) }}\n >\n <input\n type=\"checkbox\"\n checked={selected.has(entry.model)}\n onChange={() => { toggle(entry.model) }}\n />\n <span className={css.rowName}>{entry.model}</span>\n <span className={css.rowMeta}>\n {entry.groups.length === 0 ? null : (\n <span>{t('whitelist.groupsCount', { count: String(entry.groups.length) })}</span>\n )}\n {entry.minRatio === undefined ? null : (\n <>\n <span className={css.rowRatio}>{t('whitelist.minRatio')}</span>\n <RatioChip ratio={String(entry.minRatio) + 'x'} />\n </>\n )}\n </span>\n </label>\n ))}\n {tip === undefined ? null : (\n <div className={css.tip} style={{ top: tip.top, left: tip.left }} role=\"tooltip\">\n <span className={css.tipTitle}>{t('whitelist.groupsTitle')}</span>\n {tip.entry.groups.map(group => {\n const parsed = parseGroupLabel(group.group)\n return (\n <span key={group.group} className={css.tipRow}>\n <span className={css.tipGroup}>\n {parsed.badges.map(badge => (\n <GroupTag key={badge.text} text={badge.text} tone={badge.tone} />\n ))}\n <span className={css.tipGroupName}>{parsed.label}</span>\n </span>\n {group.ratio === undefined ? null : <RatioChip ratio={group.ratio} />}\n </span>\n )\n })}\n </div>\n )}\n </div>\n )}\n <p className={css.hint}>{t('whitelist.hint')}</p>\n {notice === undefined ? null : <p className={css.notice}>{notice}</p>}\n </div>\n )}\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n </>}\n </section>\n )\n}\n\n/**\n * The image-generation card: the `generate_image` tool's switch and, per picture\n * model, the group its requests route through.\n *\n * Unlike the whitelist this block saves on a button, not on every click: the two\n * members describe one setting, and a group choice made before the model is\n * checked would otherwise be written as nothing.\n * @param props - the injected route carrier and translate.\n * @returns the image-generation block.\n */\nfunction ImageGeneration({ api, t }: NearTokenSectionInjected) {\n const [state, setState] = useState<NearTokenImagesState | undefined>(undefined)\n const [enabled, setEnabled] = useState(false)\n const [selection, setSelection] = useState<Readonly<Record<string, string>>>({})\n const [busy, setBusy] = useState(false)\n const [dirty, setDirty] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n const [saved, setSaved] = useState(false)\n /** Whether the controls are showing; the card opens collapsed. */\n const [open, setOpen] = useState(false)\n\n /** Publish one host answer into the controls. */\n const adopt = useCallback((next: NearTokenImagesState): void => {\n setState(next)\n setEnabled(next.enabled)\n setSelection({ ...next.selection })\n setDirty(false)\n }, [])\n\n const load = useCallback(async (): Promise<void> => {\n try {\n adopt(await api.images())\n } catch (failure: unknown) {\n setError(t('images.failed', { message: messageOf(failure) }))\n }\n }, [adopt, api, t])\n\n useEffect(() => { void load() }, [load])\n\n const models = state?.models ?? []\n const enabledCount = Object.keys(selection).length\n\n /** Check or uncheck one model; the first group of a newly checked model is its route. */\n const toggle = (model: string, groups: NearTokenImageModelEntry['groups']): void => {\n setSaved(false)\n setDirty(true)\n setSelection((current) => {\n if (current[model] !== undefined) {\n const next = { ...current }\n delete next[model]\n return next\n }\n const first = groups[0]?.group\n return first === undefined ? current : { ...current, [model]: first }\n })\n }\n\n const chooseGroup = (model: string, group: string): void => {\n setSaved(false)\n setDirty(true)\n setSelection(current => ({ ...current, [model]: group }))\n }\n\n const save = async (): Promise<void> => {\n setBusy(true)\n setError(undefined)\n setSaved(false)\n try {\n await api.saveImages({ enabled, models: selection })\n setSaved(true)\n setDirty(false)\n } catch (failure: unknown) {\n setError(t('images.failed', { message: messageOf(failure) }))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <section className={css.card}>\n <button\n type=\"button\"\n className={css.cardToggle}\n aria-expanded={open}\n aria-label={t(open ? 'card.collapse' : 'card.expand')}\n onClick={() => { setOpen((current) => !current) }}\n >\n <span className={css.name}>{t('images.title')}</span>\n <span className={css.count}>\n <span className={css.countTotal}>{t('images.count', { total: String(models.length) })}</span>\n <span className={css.countDot} aria-hidden=\"true\" />\n <span className={css.countPicked}>{t('images.picked', { selected: String(enabledCount) })}</span>\n </span>\n <IconChevronDownOutlineRegular\n className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron}\n size={14}\n />\n </button>\n {!open ? null : <>\n <p className={css.intro}>{t('images.intro')}</p>\n {state === undefined\n ? (error === undefined ? <p className={css.hint}>{t('images.loading')}</p> : null)\n : (\n <div className={css.form}>\n <label className={css.row}>\n <input\n type=\"checkbox\"\n checked={enabled}\n onChange={(event) => { setSaved(false); setDirty(true); setEnabled(event.target.checked) }}\n />\n <span className={css.rowName}>{t('images.enable')}</span>\n </label>\n {models.length === 0\n ? <p className={css.hint}>{t('images.empty')}</p>\n : (\n <div className={css.list}>\n {models.map(entry => (\n <label key={entry.model} className={css.row}>\n <input\n type=\"checkbox\"\n checked={selection[entry.model] !== undefined}\n onChange={() => { toggle(entry.model, entry.groups) }}\n />\n <span className={css.rowName}>{entry.model}</span>\n <select\n className={css.select}\n aria-label={t('images.groupAria', { model: entry.model })}\n disabled={selection[entry.model] === undefined}\n value={selection[entry.model] ?? entry.groups[0]?.group ?? ''}\n onChange={(event) => { chooseGroup(entry.model, event.target.value) }}\n >\n {entry.groups.map(group => (\n <option key={group.group} value={group.group}>\n {group.group}{group.ratio === undefined ? '' : ` · ${group.ratio}`}\n </option>\n ))}\n </select>\n <span className={css.rowMeta}>\n {t(entry.channel === 'images'\n ? 'images.channel.images'\n : entry.channel === 'genai' ? 'images.channel.genai' : 'images.channel.chat')}\n </span>\n </label>\n ))}\n </div>\n )}\n <div className={css.toolbar}>\n <button type=\"button\" className={css.button} disabled={busy || !dirty} onClick={() => { void save() }}>\n {busy ? t('images.saving') : t('images.save')}\n </button>\n <span className={css.autosave} aria-live=\"polite\">\n {dirty ? t('images.dirty') : saved ? t('images.saved') : ''}\n </span>\n </div>\n <p className={css.hint}>{t('images.hint')}</p>\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n </div>\n )}\n </>}\n </section>\n )\n}\n\n/**\n * Render one thrown value as the message the page shows.\n * @param error - whatever the call threw.\n * @returns the error's message, or its text.\n */\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}","/**\n * `modelGroups` namespace dictionaries. Copy mirrors the built-in model seat so\n * the two readings of the same control stay identical; only the group keys are\n * new.\n */\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'provider.account': 'DeepSeek 账号',\n 'trigger.fallback': '请选择模型',\n 'trigger.loading': '正在加载模型…',\n 'trigger.selectAria': '请选择模型',\n 'trigger.aria': '选择模型,当前 {model}',\n 'trigger.ariaEffort': '选择模型,当前 {model},推理等级 {effort}',\n 'menu.aria': '模型、分组与推理等级',\n 'menu.model': '模型',\n 'menu.group': '分组',\n 'menu.effort': '推理等级',\n 'effort.providerDefault': 'Default',\n 'status.loading': '正在刷新模型列表…',\n 'error.action': '模型操作失败:{message}',\n 'error.sessionInUse': '当前会话已被占用,可能是其他正在运行的 DSH 导致的(如其他 dsh web、桌面端),请退出其他正在运行的 DSH 后重试。',\n 'action.reload': '重新加载',\n 'warning.groupLoad': '{name} 加载失败:{message}',\n 'search.placeholder': '搜索模型…',\n 'search.clear': '清除搜索',\n 'search.empty': '没有匹配的模型。',\n 'empty.models': '暂无可用模型',\n 'empty.groups': '当前模型没有其它分组。',\n 'empty.efforts': '当前模型未提供推理等级。',\n 'account.nav': 'NearToken',\n 'account.title': 'NearToken 账号',\n 'account.site': '站点',\n 'account.connect': '连接 NearToken',\n 'account.connecting': '正在发起…',\n 'account.waiting': '已发起授权,请在浏览器中确认。',\n 'account.userCode': '确认码',\n 'account.openBrowser': '打开浏览器确认',\n 'account.manualLink': '打不开浏览器时,手动打开下面的地址:',\n 'account.copyLink': '复制链接',\n 'account.copied': '已复制',\n 'account.copyFailed': '复制失败,请手动选中上面的链接复制。',\n 'account.openFailed': '未能打开浏览器({message});请复制下面的地址,在自己的浏览器里访问。',\n 'account.expiresIn': '本次确认 {minutes} 分钟内有效',\n 'account.cancel': '取消',\n 'account.cancelling': '正在取消…',\n 'account.connected': '已接入',\n 'account.disconnected': '未连接',\n 'account.group': '用户分组',\n 'account.balance': '剩余额度',\n 'account.used': '已用额度',\n 'account.vouchers': '代金券',\n 'account.token': 'API 令牌',\n 'account.signOut': '断开连接',\n 'account.signingOut': '正在断开…',\n 'account.loading': '正在读取连接状态…',\n 'account.failed': '操作失败:{message}',\n 'whitelist.title': '模型白名单',\n 'whitelist.intro': '勾选要出现在 DSH 模型选择器里的模型;未勾选的不会出现。白名单写在插件配置里,重启后依然生效。',\n 'whitelist.loading': '正在读取模型清单…',\n 'whitelist.failed': '模型白名单操作失败:{message}',\n 'whitelist.search': '搜索模型…',\n 'whitelist.noMatch': '没有匹配的模型。',\n 'whitelist.empty': '站点没有返回任何模型。',\n 'whitelist.count': '{total} 个模型',\n 'whitelist.picked': '已选 {selected}',\n 'card.expand': '展开',\n 'card.collapse': '收起',\n 'whitelist.groupsCount': '{count} 个分组',\n 'whitelist.minRatio': '最低',\n 'whitelist.groupsTitle': '可用分组',\n 'whitelist.selectAll': '全选',\n 'whitelist.clear': '清空',\n 'whitelist.reset': '全部显示',\n 'whitelist.saving': '正在保存…',\n 'whitelist.autoSaved': '已自动保存,模型选择器已刷新',\n 'whitelist.hint': '勾选即自动保存;没勾选的不会出现在模型选择器里。「全部显示」会清空白名单。',\n 'whitelist.keepOne': '至少要保留一个模型;想放开全部请点「全部显示」。',\n 'whitelist.cleared': '已清空勾选;勾选要显示的模型后会立即保存。',\n 'images.title': '图像生成',\n 'images.intro': '开启后模型可以调用 generate_image 工具生图。勾选要用的生图模型,并为每个模型指定走哪个分组(决定计费与可用性)。',\n 'images.enable': '启用 generate_image 工具',\n 'images.channel.images': 'images 接口',\n 'images.channel.genai': 'gemini 接口',\n 'images.channel.chat': 'chat 接口',\n 'images.save': '保存',\n 'images.saving': '正在保存…',\n 'images.saved': '已保存,工具已按新设置生效',\n 'images.dirty': '有未保存的改动',\n 'images.hint': '生图一次约 20-60 秒;不勾选的模型模型看不到也调不到。改完记得点保存。',\n 'images.failed': '图像生成设置失败:{message}',\n 'images.empty': '站点没有返回任何生图模型。',\n 'images.loading': '正在读取生图模型…',\n 'images.count': '{total} 个生图模型',\n 'images.picked': '已启用 {selected}',\n 'images.groupAria': '{model} 使用的分组',\n} satisfies Record<string, string>\n\n/** The dictionary key union. */\nexport type GroupKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'provider.account': 'DeepSeek Account',\n 'trigger.fallback': 'Select model',\n 'trigger.loading': 'Loading models…',\n 'trigger.selectAria': 'Select model',\n 'trigger.aria': 'Select model, current {model}',\n 'trigger.ariaEffort': 'Select model, current {model}, reasoning effort {effort}',\n 'menu.aria': 'Model, group, and reasoning effort',\n 'menu.model': 'Model',\n 'menu.group': 'Group',\n 'menu.effort': 'Effort',\n 'effort.providerDefault': 'Default',\n 'status.loading': 'Refreshing model list…',\n 'error.action': 'Model operation failed: {message}',\n 'error.sessionInUse': 'This session is already in use, possibly by another running DSH instance (such as dsh web or the desktop app). Quit other running DSH instances and try again.',\n 'action.reload': 'Reload',\n 'warning.groupLoad': '{name} failed to load: {message}',\n 'search.placeholder': 'Search models…',\n 'search.clear': 'Clear search',\n 'search.empty': 'No matching models.',\n 'empty.models': 'No models available.',\n 'empty.groups': 'This model offers no other group.',\n 'empty.efforts': 'This model provides no reasoning effort levels.',\n 'account.nav': 'NearToken',\n 'account.title': 'NearToken account',\n 'account.site': 'Site',\n 'account.connect': 'Connect NearToken',\n 'account.connecting': 'Starting…',\n 'account.waiting': 'Authorization started. Confirm it in your browser.',\n 'account.userCode': 'Code',\n 'account.openBrowser': 'Open browser to confirm',\n 'account.manualLink': 'If the browser does not open, open this address yourself:',\n 'account.copyLink': 'Copy link',\n 'account.copied': 'Copied',\n 'account.copyFailed': 'Could not copy; select the link above and copy it yourself.',\n 'account.openFailed': 'Could not open your browser ({message}); copy the address below and open it yourself.',\n 'account.expiresIn': 'This confirmation is valid for {minutes} minutes',\n 'account.cancel': 'Cancel',\n 'account.cancelling': 'Cancelling…',\n 'account.connected': 'Connected',\n 'account.disconnected': 'Not connected',\n 'account.group': 'Group',\n 'account.balance': 'Balance',\n 'account.used': 'Used',\n 'account.vouchers': 'Vouchers',\n 'account.token': 'API token',\n 'account.signOut': 'Disconnect',\n 'account.signingOut': 'Disconnecting…',\n 'account.loading': 'Reading connection state…',\n 'account.failed': 'Failed: {message}',\n 'whitelist.title': 'Model whitelist',\n 'whitelist.intro': 'Check the models that should appear in the DSH model picker; unchecked models stay hidden. The list is stored in the plugin configuration and survives a restart.',\n 'whitelist.loading': 'Reading the model list…',\n 'whitelist.failed': 'Model whitelist failed: {message}',\n 'whitelist.search': 'Search models…',\n 'whitelist.noMatch': 'No matching models.',\n 'whitelist.empty': 'The site returned no models.',\n 'whitelist.count': '{total} models',\n 'whitelist.picked': '{selected} selected',\n 'card.expand': 'Expand',\n 'card.collapse': 'Collapse',\n 'whitelist.groupsCount': '{count} groups',\n 'whitelist.minRatio': 'from',\n 'whitelist.groupsTitle': 'Available groups',\n 'whitelist.selectAll': 'Check all',\n 'whitelist.clear': 'Clear',\n 'whitelist.reset': 'Show all',\n 'whitelist.saving': 'Saving…',\n 'whitelist.autoSaved': 'Saved; the model picker has been refreshed',\n 'whitelist.hint': 'Every change saves itself; unchecked models stay out of the picker. \"Show all\" clears the whitelist.',\n 'whitelist.keepOne': 'Keep at least one model; use \"Show all\" to offer everything again.',\n 'whitelist.cleared': 'Boxes cleared; checking a model saves the list you want.',\n 'images.title': 'Image generation',\n '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.',\n 'images.enable': 'Enable the generate_image tool',\n 'images.channel.images': 'images endpoint',\n 'images.channel.genai': 'gemini endpoint',\n 'images.channel.chat': 'chat endpoint',\n 'images.save': 'Save',\n 'images.saving': 'Saving…',\n 'images.saved': 'Saved; the tool now runs with these settings',\n 'images.dirty': 'Unsaved changes',\n 'images.hint': 'One picture takes 20-60 seconds; an unchecked model is invisible to the model and cannot be called. Remember to save.',\n 'images.failed': 'Image generation settings failed: {message}',\n 'images.empty': 'The site returned no picture models.',\n 'images.loading': 'Reading the picture models…',\n 'images.count': '{total} picture models',\n 'images.picked': '{selected} enabled',\n 'images.groupAria': 'Group used by {model}',\n} satisfies Record<GroupKey, string>\n","/**\n * NearToken provider plugin, browser half. Registers two surfaces: the NearToken\n * settings page (sign in, account facts, sign out) and a replacement for the\n * composer's model seat at priority -1, so the slot's lowest-priority\n * registration renders and the shipped picker stays in place without drawing.\n *\n * The seat shares the SAME per-session directory the built-in picker uses\n * (`ctx.modelDirectories`), so selection state, pending markers, the /model\n * popup, and Session persistence are unaffected: this plugin only changes what\n * the control looks like and adds the group level on top of it.\n *\n * The seat's declared child ('conversation.input.model.label') is owned by the\n * shipped registration, so this one declares none and renders catalog names\n * directly.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\n// Type-only: the carrier types and the ctx.modelDirectories / ctx.remote merges.\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui-conversation SlotMap merge (the input.model seat).\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { ModelSelection } from '@deepseek-ai/dsh-api-session-controller/types'\n// Type-only: pulls the settings shell's SlotMap merge ('settings.section').\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { createNearTokenApi } from './api.ts'\nimport { ModelGroupSelect } from './ModelGroupSelect.tsx'\nimport { NearTokenSection, type NearTokenSectionInjected } from './NearTokenSection.tsx'\nimport { en, zh, type GroupKey } from './locales.ts'\nimport type { ModelGroupSelectInjected } from './slots.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** The replacement model seat's copy. */\n modelGroups: GroupKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nconst NS = 'modelGroups'\n\n/** Required services: the slot registry, locale, sessions, and the directory service. */\nexport const inject = ['slots', 'locale', 'sessions', 'remote', 'remote.session']\n\n/**\n * Client plugin body: register the dictionaries, add the NearToken settings page,\n * then shadow the composer model seat over the shared model directory.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-neartoken-provider: dictionaries')\n // One carrier for the page's whole life: the registration closure hands the\n // same object back on every render, so the section's load effect runs once.\n const api = createNearTokenApi()\n const t = ctx.locale.bind(NS) as NearTokenSectionInjected['t']\n // The near-token page sits between the account page (-10) and the general\n // page (0): both answer \"who am I signed in as\".\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'neartoken',\n order: -5,\n label: () => t('account.nav'),\n locale: NS,\n inject: (): NearTokenSectionInjected => ({ api, t }),\n }, NearTokenSection))\n\n ctx.inject(['slots', 'modelDirectories'], (scope: ClientContext) => {\n const models = scope.modelDirectories\n const sessions = scope.sessions\n scope.slots.inject('conversation.input.model', () => scope.slots.register({\n name: 'conversation.input.model',\n // Shipped seat registers at the default priority 0; lower renders.\n priority: -1,\n locale: NS,\n inject: (sessionId): ModelGroupSelectInjected => {\n const directory = models.directoryFor(sessionId)\n const available = sessions.subagentAddress(sessionId) === undefined\n return {\n available,\n directory: directory.store,\n load: () => {\n if (available) directory.load().catch(() => { /* surfaced on the store */ })\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection)\n : Promise.resolve(undefined),\n }\n },\n }, ModelGroupSelect))\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["css","useSyncExternalStore","useState","useRef","useId","useMemo","css","IconDataOutlineRegular","StateDot","IconChevronDownOutlineRegular","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","MenuGroup","IconCheckOutlineRegular","useState","useCallback","css","IconRefreshOutlineRegular","useRef","IconChevronDownOutlineRegular"],"sources":["../src/protocol.ts","../src/client/api.ts","../src/client/groups.ts","../src/client/group-tags.tsx","../src/client/ModelGroupSelect.tsx","../src/client/NearTokenSection.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * The wire vocabulary shared by the Host routes and the browser section: the\n * route paths and the JSON each answers. Both build faces import this file, so\n * a route rename cannot leave the browser calling a path the Host stopped\n * serving.\n *\n * Nothing here carries a password: the plugin never collects site credentials.\n * A connection is authorized by the site's own device-authorization flow, in\n * the user's browser — the Host only polls its result.\n *\n * @module\n */\n\n/** State read by the settings page before it draws, and while it waits. */\nexport const STATUS_PATH = '/neartoken/status'\n/**\n * Re-read the wallet right now, then answer with the same state `STATUS_PATH`\n * reads. The Host already refreshes on its own cadence; this is the page asking\n * for that read early, and the answer carries the fresh numbers.\n */\nexport const REFRESH_PATH = '/neartoken/refresh'\n/** Start a device authorization (the Host then polls the site). */\nexport const AUTHORIZE_PATH = '/neartoken/authorize'\n/** Abandon the authorization in progress. */\nexport const CANCEL_PATH = '/neartoken/cancel'\n/**\n * Ask the Host to open the pending confirmation page in the user's own browser.\n * The request carries no address: the Host opens the one it is waiting on.\n */\nexport const OPEN_PATH = '/neartoken/open'\n/** Forget the stored key and revoke it on the site. */\nexport const LOGOUT_PATH = '/neartoken/logout'\n/** Read the catalog beside the stored whitelist; POST a new whitelist. */\nexport const MODELS_PATH = '/neartoken/models'\n/** Read the picture models and the image-generation setting; POST one change to it. */\nexport const IMAGES_PATH = '/neartoken/images'\n\n/**\n * One group voucher the wallet carries: a balance that can only pay for its\n * own group. Amounts arrive as raw quota and are shown in the site's own\n * display currency, like every other money figure on the card.\n */\nexport interface NearTokenVoucher {\n /** Group name exactly as the site publishes it, badge prefixes included. */\n readonly group: string\n /** The group's stable id, as the site's group registry numbers it. */\n readonly groupId: number\n /** Remaining voucher balance, formatted in the site's display currency. */\n readonly amount: string\n}\n\n/** One account's facts, as the settings card shows them. */\nexport interface NearTokenAccountSummary {\n /** The dashboard user name. */\n readonly username: string\n /** The display name when the site set one, otherwise the user name. */\n readonly displayName: string\n /** The user's own group, which is the default group a request routes by. */\n readonly group: string\n /** Remaining quota, formatted in the site's own display currency. */\n readonly balance: string\n /** Quota already spent, formatted the same way. */\n readonly used: string\n /**\n * The per-group vouchers of the last wallet read, absent until one answered.\n * A grant does not carry them; they arrive with the first wallet refresh.\n */\n readonly vouchers?: readonly NearTokenVoucher[]\n}\n\n/** One authorization the human must finish in their browser. */\nexport interface NearTokenPendingAuthorization {\n /** The short code the site shows on its confirmation page. */\n readonly userCode: string\n /** The page to open; carries no code of its own. */\n readonly verificationUri: string\n /** The same page with the code prefilled. */\n readonly verificationUriComplete: string\n /** When this attempt stops being valid, as epoch milliseconds. */\n readonly expiresAt: number\n}\n\n/** The `GET /neartoken/status` answer. */\nexport interface NearTokenStatus {\n /** Whether an API key is stored, i.e. whether the provider route is mounted. */\n readonly configured: boolean\n /** Site root the plugin talks to. */\n readonly baseURL: string\n /** Name of the token the site created for this plugin. */\n readonly tokenName: string\n /** Account facts, absent until a connection obtained them. */\n readonly account?: NearTokenAccountSummary\n /** The authorization in progress, while one is running. */\n readonly pending?: NearTokenPendingAuthorization\n /** Why the last attempt ended without a key, until the next one starts. */\n readonly error?: string\n}\n\n/** One group's offering of a model, as the whitelist list shows it. */\nexport interface NearTokenModelGroup {\n /** Group name exactly as the site publishes it, badge prefixes included. */\n readonly group: string\n /** The group's multiplier caption (`0.4x`), absent when the site published none. */\n readonly ratio?: string\n}\n\n/** One model the whitelist can show or hide. */\nexport interface NearTokenModelEntry {\n /** Bare model name: the whitelist key, and what the site's API takes. */\n readonly model: string\n /** Every group offering this model, in catalog order. */\n readonly groups: readonly NearTokenModelGroup[]\n /**\n * The cheapest multiplier among those groups, when the site published one.\n * The list shows it beside the group count; the per-group detail stays in\n * the hover panel.\n */\n readonly minRatio?: number\n}\n\n/** The `GET /neartoken/models` answer. */\nexport interface NearTokenModelsState {\n /** Every model the site offers, in catalog order. */\n readonly models: readonly NearTokenModelEntry[]\n /** The stored whitelist; empty means no whitelist, so every model is shown. */\n readonly enabled: readonly string[]\n}\n\n/** The `POST /neartoken/models` request body. */\nexport interface NearTokenModelsPatch {\n /** Model names to keep visible; an empty list restores the whole catalog. */\n readonly enabled: readonly string[]\n}\n\n/** The `POST /neartoken/authorize` answer. */\nexport type BeginAuthorizationOutcome =\n | { readonly status: 'pending'; readonly pending: NearTokenPendingAuthorization }\n | { readonly status: 'failed'; readonly message: string }\n\n/**\n * Which request shape one picture model speaks: the images endpoint, Gemini's\n * own generateContent, or a chat completion.\n */\nexport type NearTokenImageChannel = 'images' | 'genai' | 'chat'\n\n/** One picture model the image-generation setting can enable. */\nexport interface NearTokenImageModelEntry {\n /** Bare model name, as the site's API takes it. */\n readonly model: string\n /** The request shape this model answers. */\n readonly channel: NearTokenImageChannel\n /** Every group offering this model, in catalog order. */\n readonly groups: readonly NearTokenModelGroup[]\n /** The cheapest multiplier among those groups, when the site published one. */\n readonly minRatio?: number\n}\n\n/** The `GET /neartoken/images` answer. */\nexport interface NearTokenImagesState {\n /** Whether the `generate_image` tool is mounted for this profile. */\n readonly enabled: boolean\n /** Every picture model the site offers, in catalog order. */\n readonly models: readonly NearTokenImageModelEntry[]\n /** The enabled models and the group each one routes through; empty means the tool has no model to call. */\n readonly selection: Readonly<Record<string, string>>\n}\n\n/** The `POST /neartoken/images` request body. */\nexport interface NearTokenImagesPatch {\n /** Whether the tool should be mounted. */\n readonly enabled: boolean\n /** Bare model name to the group name it must route through. */\n readonly models: Readonly<Record<string, string>>\n}\n\n","/**\n * The browser half of the settings-page carrier: same-origin calls to the Host\n * routes declared in ../protocol.ts.\n *\n * @module\n */\nimport {\n AUTHORIZE_PATH, CANCEL_PATH, IMAGES_PATH, LOGOUT_PATH, MODELS_PATH, OPEN_PATH, REFRESH_PATH, STATUS_PATH,\n} from '../protocol.ts'\nimport type {\n BeginAuthorizationOutcome, NearTokenImagesPatch, NearTokenImagesState, NearTokenModelsPatch,\n NearTokenModelsState, NearTokenStatus,\n} from '../protocol.ts'\n\n/** The HTTP carrier, injectable so the section's behavior is testable. */\nexport type Fetch = (input: string, init?: RequestInit) => Promise<Response>\n\n/** What the section calls. */\nexport interface NearTokenApi {\n /** Read the key state, the account card, and any authorization in progress. */\n status(): Promise<NearTokenStatus>\n /**\n * Re-read the wallet now and answer with the fresh state. The Host already\n * refreshes on its own cadence; this asks for that read early, so the card\n * shows money facts newer than the last poll.\n */\n refreshAccount(): Promise<NearTokenStatus>\n /** Start a device authorization; the Host polls the site from then on. */\n begin(): Promise<BeginAuthorizationOutcome>\n /** Abandon the authorization in progress. */\n cancel(): Promise<void>\n /**\n * Hand the pending confirmation page to the user's own browser. The page\n * cannot do that itself: a window it opens stays inside the shell hosting it.\n */\n openBrowser(): Promise<void>\n /** Forget the stored key and revoke it on the site. */\n signOut(): Promise<void>\n /** Read the site's model catalog beside the stored whitelist. */\n models(): Promise<NearTokenModelsState>\n /** Save a whitelist; an empty list shows every model again. */\n saveModels(enabled: readonly string[]): Promise<void>\n /** Read the picture models beside the stored image-generation setting. */\n images(): Promise<NearTokenImagesState>\n /** Save the image-generation setting: the tool's switch and one group per enabled model. */\n saveImages(patch: NearTokenImagesPatch): Promise<void>\n}\n\n/**\n * Read one JSON answer, turning an HTTP refusal into a thrown error.\n * @param response - the pending response.\n * @returns the parsed body.\n * @throws {Error} when the route answered a non-2xx status.\n */\nasync function jsonOf<T>(response: Response): Promise<T> {\n if (!response.ok) throw new Error(`HTTP ${String(response.status)}`)\n return await response.json() as T\n}\n\n/**\n * Build the carrier.\n * @param fetcher - HTTP carrier; defaults to the page's own fetch.\n * @returns the section's four calls.\n */\nexport function createNearTokenApi(fetcher: Fetch = (input, init) => fetch(input, init)): NearTokenApi {\n /** POST one empty JSON body and read its JSON answer. */\n const post = async <T>(path: string): Promise<T> => jsonOf<T>(await fetcher(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n }))\n return {\n async status() {\n return await jsonOf<NearTokenStatus>(await fetcher(STATUS_PATH, { headers: { accept: 'application/json' } }))\n },\n async refreshAccount() {\n return await post<NearTokenStatus>(REFRESH_PATH)\n },\n async begin() {\n return await post<BeginAuthorizationOutcome>(AUTHORIZE_PATH)\n },\n async cancel() {\n await post<unknown>(CANCEL_PATH)\n },\n async openBrowser() {\n // No body: the Host opens the page it is already waiting on, so this route\n // can never be asked to launch an arbitrary address.\n const response = await fetcher(OPEN_PATH, { method: 'POST' })\n if (!response.ok) {\n // The Host names why the platform launcher did not run; that reason is\n // what the reader needs, not a status code.\n const refusal = await response.json().catch(() => ({ message: `HTTP ${String(response.status)}` })) as { message?: string }\n throw new Error(refusal.message ?? `HTTP ${String(response.status)}`)\n }\n },\n async signOut() {\n await post<unknown>(LOGOUT_PATH)\n },\n async models() {\n return await jsonOf<NearTokenModelsState>(await fetcher(MODELS_PATH, { headers: { accept: 'application/json' } }))\n },\n async saveModels(enabled) {\n await jsonOf<unknown>(await fetcher(MODELS_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ enabled } satisfies NearTokenModelsPatch),\n }))\n },\n async images() {\n return await jsonOf<NearTokenImagesState>(await fetcher(IMAGES_PATH, { headers: { accept: 'application/json' } }))\n },\n async saveImages(patch) {\n const response = await fetcher(IMAGES_PATH, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n })\n if (!response.ok) {\n // The Host refuses a selection its catalog does not have; its message\n // names the reason, so the page shows that rather than a status code.\n const refusal = await response.json().catch(() => ({ message: `HTTP ${String(response.status)}` })) as { message?: string }\n throw new Error(refusal.message ?? `HTTP ${String(response.status)}`)\n }\n },\n }\n}\n","/**\n * The group dimension, folded out of catalog names.\n *\n * The NearToken provider (this plugin's own host half) expands the site's\n * `/api/pricing` into one catalog model per (group, model) pair, named\n * `\"<model> @ <group>\"`. The picker folds those back into one row per model\n * and turns the group into its own selectable level.\n *\n * Group names carry a badge convention on the site: a run of bracketed tags\n * before the group's own name (`[低价][反重力] Claude`). Those render as\n * colored capsules; the ratio comes through the catalog entry's description\n * (`分组倍率 0.4x`).\n *\n * Prototype scope: the provider allowlist and the name separator are\n * hardcoded. They become Config fields once the shape settles.\n */\n\n/** Providers whose catalog names carry a group suffix. */\nexport const GROUPED_PROVIDERS: readonly string[] = ['neartoken']\n\n/**\n * Capsule tone of one group badge. Tier tags keep a fixed hue so a long list\n * reads at a glance; any other tag takes a hue derived from its own text.\n */\nexport type BadgeTone =\n | 'rose' | 'emerald' | 'violet' | 'sky' | 'amber' | 'cyan'\n | 'fuchsia' | 'indigo' | 'teal' | 'lime' | 'orange' | 'pink'\n\n/** Tags that carry a tier meaning, with the hue the site gives each of them. */\nconst KNOWN_TAG_TONES: Record<string, BadgeTone> = {\n 满血: 'rose',\n 低价: 'emerald',\n 神秘: 'violet',\n 官Key: 'sky',\n 官key: 'sky',\n 可蒸馏: 'amber',\n 反重力: 'cyan',\n 生图: 'fuchsia',\n AIS: 'indigo',\n 稳定: 'teal',\n}\n\n/** Hues used by tags with no tier meaning, spread out so neighbours differ. */\nconst FALLBACK_TONES: readonly BadgeTone[] = [\n 'sky', 'amber', 'cyan', 'fuchsia', 'indigo', 'teal',\n 'lime', 'orange', 'pink', 'emerald', 'violet', 'rose',\n]\n\n/**\n * @param tag - one bracketed tag's text.\n * @returns a stable bucket for hue selection.\n */\nfunction hashTag(tag: string): number {\n let hash = 0\n for (const char of tag) hash = (hash * 31 + (char.codePointAt(0) ?? 0)) % 100_003\n return hash\n}\n\n/** One capsule rendered before the group's own name. */\nexport interface GroupBadge {\n readonly text: string\n readonly tone: BadgeTone\n}\n\n/** One group label split into its badge capsules and its own name. */\nexport interface ParsedGroup {\n readonly badges: readonly GroupBadge[]\n readonly label: string\n}\n\n/** Separator between a model name and its group suffix in the catalog name. */\nconst GROUP_SEPARATOR = ' @ '\n\n/**\n * Split one catalog name into the model's own name and the optional group.\n * @param name - the catalog model name, e.g. `glm-5.3 @ [低价][满血] 国模`.\n * @returns the model name without the suffix, plus the group when present.\n */\nexport function splitModelName(name: string): { model: string; group?: string } {\n const at = name.lastIndexOf(GROUP_SEPARATOR)\n if (at <= 0) return { model: name }\n const group = name.slice(at + GROUP_SEPARATOR.length).trim()\n const model = name.slice(0, at).trim()\n if (model === '' || group === '') return { model: name }\n return { model, group }\n}\n\n/**\n * Parse one group name's bracketed badge prefix.\n * @param name - the raw group name, e.g. `[低价][反重力] Claude`.\n * @returns the badge capsules (in order) and the group's own name.\n */\nexport function parseGroupLabel(name: string): ParsedGroup {\n const badges: GroupBadge[] = []\n let rest = name\n while (rest.startsWith('[')) {\n const end = rest.indexOf(']')\n if (end <= 1) break\n badges.push(badgeOf(rest.slice(1, end)))\n rest = rest.slice(end + 1)\n }\n return { badges, label: rest.trim() }\n}\n\n/**\n * @param text - one bracketed badge's text.\n * @returns the capsule tone that text renders in.\n */\nfunction badgeOf(text: string): GroupBadge {\n const known = KNOWN_TAG_TONES[text.trim()]\n if (known !== undefined) return { text, tone: known }\n return { text, tone: FALLBACK_TONES[hashTag(text) % FALLBACK_TONES.length] ?? 'sky' }\n}\n\n/**\n * The capitals each vendor writes its own family name with.\n *\n * The catalog publishes ids in lowercase only, so the display name has to put\n * them back: GPT and GLM are acronyms, DeepSeek is camel case, MiniMax and MiMo\n * keep an inner capital, and the `xhigh` effort is spelled `XHigh` everywhere\n * else in the product.\n */\nconst BRAND_SPELLING: Readonly<Record<string, string>> = {\n gpt: 'GPT',\n glm: 'GLM',\n deepseek: 'DeepSeek',\n minimax: 'MiniMax',\n mimo: 'MiMo',\n xhigh: 'XHigh',\n tts: 'TTS',\n}\n\n/**\n * Render a model name the way the pickers show it: hyphens become separators\n * and every word is capitalized, so `claude-opus-5-c` reads `Claude Opus 5 C`.\n * A vendor's own spelling wins over that rule (`gpt-5.5` reads `GPT 5.5`).\n *\n * The trailing `-c` stays a word on purpose: the site pairs every such model\n * with a twin that lacks the suffix (`claude-opus-5` beside `claude-opus-5-c`),\n * so dropping it from the display would leave two different models with the\n * same name. {@link isCodingUnfriendly} is what tells the reader which one it\n * is looking at.\n * @param model - a bare model name.\n * @returns the display name.\n */\nexport function displayModelName(model: string): string {\n return model\n .split('-')\n .filter(part => part.length > 0)\n .map(part => BRAND_SPELLING[part.toLowerCase()] ?? part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ')\n}\n\n/**\n * Read the group ratio out of the host-provided catalog description.\n * @param description - the catalog entry's description (`分组倍率 0.4x`).\n * @returns the ratio caption, or undefined when the entry carries none.\n */\nexport function ratioOf(description: string | undefined): string | undefined {\n if (description === undefined) return undefined\n const match = description.match(/([\\d.]+)x/)\n return match === null ? undefined : `${match[1]}x`\n}\n\n/**\n * @param provider - a catalog provider id.\n * @returns whether this provider's model names carry group suffixes.\n */\nexport function isGroupedProvider(provider: string): boolean {\n return GROUPED_PROVIDERS.includes(provider)\n}\n\n/** One group's take on a model: the exact catalog entry that routes it. */\nexport interface ModelVariant<M> {\n readonly provider: string\n readonly group?: string\n readonly model: M\n}\n\n/** One model row: the display name plus every group that offers it. */\nexport interface ModelOption<M> {\n /** Fold key: the model name without its group suffix. */\n readonly key: string\n /** Displayed model name. */\n readonly label: string\n readonly variants: readonly ModelVariant<M>[]\n}\n\n/**\n * Fold one provider's models into rows, one per model name.\n *\n * A provider outside {@link GROUPED_PROVIDERS} keeps a 1:1 mapping (no suffix\n * parsing), so its rows behave exactly like the built-in picker's.\n * @param provider - the catalog provider id.\n * @param models - that provider's catalog models, in catalog order.\n * @returns one option per distinct model name, in first-seen order.\n */\nexport function foldModels<M extends { readonly id: string; readonly name: string }>(\n provider: string, models: readonly M[],\n): ModelOption<M>[] {\n const grouped = isGroupedProvider(provider)\n const byKey = new Map<string, { label: string; variants: ModelVariant<M>[] }>()\n for (const model of models) {\n const { model: label, group } = grouped ? splitModelName(model.name) : { model: model.name, group: undefined }\n const key = grouped ? label : model.id\n const row = byKey.get(key)\n const variant: ModelVariant<M> = { provider, model, ...group === undefined ? {} : { group } }\n if (row === undefined) byKey.set(key, { label, variants: [variant] })\n else row.variants.push(variant)\n }\n return [...byKey].map(([key, row]) => ({ key, label: row.label, variants: row.variants }))\n}\n\n/**\n * Pick the variant a model row should route to.\n * @param option - the row being chosen.\n * @param preferredProvider - the currently selected provider, kept when it offers the model.\n * @param preferredGroup - the currently selected group, kept when that provider offers it.\n * @returns the variant to submit.\n */\nexport function chooseVariant<M>(\n option: ModelOption<M>, preferredProvider: string | undefined, preferredGroup: string | undefined,\n): ModelVariant<M> | undefined {\n const local = option.variants.filter(variant => variant.provider === preferredProvider)\n const pool = local.length > 0 ? local : option.variants\n return pool.find(variant => variant.group === preferredGroup) ?? pool[0]\n}\n","/**\n * The site's group vocabulary, rendered the way the site renders it: a group\n * name's leading tags become colour-coded capsules, its multiplier becomes a\n * capsule that reads green below the base price, and a model the site marks\n * with a `-c` suffix carries a note.\n *\n * Both surfaces that show groups — the settings page's whitelist and the\n * composer's model seat — share these so one group never looks like two\n * different things in the same product.\n */\nimport type { BadgeTone } from './groups.ts'\nimport css from './group-tags.module.css'\n\n/** CSS Module class carrying each tone's hue, kept parallel to {@link BadgeTone}. */\nconst TONE_CLASS: Record<BadgeTone, string> = {\n rose: css.toneRose,\n emerald: css.toneEmerald,\n violet: css.toneViolet,\n sky: css.toneSky,\n amber: css.toneAmber,\n cyan: css.toneCyan,\n fuchsia: css.toneFuchsia,\n indigo: css.toneIndigo,\n teal: css.toneTeal,\n lime: css.toneLime,\n orange: css.toneOrange,\n pink: css.tonePink,\n}\n\n/** One bracketed group tag as a coloured capsule. */\nexport function GroupTag(props: { text: string; tone: BadgeTone }) {\n return <span className={css.tag + ' ' + TONE_CLASS[props.tone]}>{props.text}</span>\n}\n\n/**\n * One group's multiplier as a capsule.\n * @param props - the multiplier caption the catalog carried (`0.3x`).\n * @returns the capsule, toned by whether it beats the base price.\n */\nexport function RatioChip(props: { ratio: string }) {\n const value = Number.parseFloat(props.ratio)\n let tone = css.ratioBase\n if (Number.isFinite(value)) {\n if (value < 1) tone = css.ratioCheap\n else if (value > 1) tone = css.ratioPricey\n }\n return <span className={css.ratioChip + ' ' + tone}>{props.ratio}</span>\n}\n","/**\n * ModelGroupSelect: a drop-in replacement for the composer's model seat\n * ('conversation.input.model') that adds a THIRD level between the model and\n * the reasoning effort.\n *\n * The root menu is a row triple — Model / Group / Effort — where the Group row\n * appears only while the selected model comes from a provider whose catalog\n * names carry a group suffix (see groups.ts). The trigger states all three:\n * \"GLM 5.3 · Zhang · high\".\n *\n * Registered at priority -1, one step below the built-in seat, so the shipped\n * picker stays untouched and simply does not render.\n */\nimport { MenuGroup, MenuSurface, Input } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore,\n type CSSProperties, type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport type { ModelReasoningEffort, ModelSelection } from '@deepseek-ai/dsh-api-remotes/client'\nimport {\n IconCheckOutlineRegular, IconChevronDownOutlineRegular, IconChevronRightOutlineRegular,\n IconCloseFillRegular, IconDataOutlineRegular, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ModelGroupSelectInjected } from './slots.ts'\nimport type { ModelCatalogModel } from '@deepseek-ai/dsh-api-session-controller/types'\nimport {\n chooseVariant, displayModelName, foldModels, isGroupedProvider, parseGroupLabel, ratioOf,\n type ModelOption, type ModelVariant,\n} from './groups.ts'\nimport { GroupTag, RatioChip } from './group-tags.tsx'\nimport css from './ModelGroupSelect.module.css'\n\n/** Which pane the dropdown shows: the three-row root or one drilled-in list. */\ntype Pane = 'root' | 'model' | 'group' | 'effort'\n\n/** Unplaced portal card: hidden but laid out at a fixed origin so offset sizes are real. */\nconst MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }\n\n/** One provider's folded rows. */\ninterface ProviderRows<M> {\n readonly id: string\n readonly name: string\n readonly options: readonly ModelOption<M>[]\n}\n\n/** Provider display order: account first, official next, then catalog order. */\nfunction providerRank(id: string): number {\n return id === 'deepseek-account' ? 0 : id === 'deepseek-official' ? 1 : 2\n}\n\n/**\n * Case-insensitive containment filter for the model search.\n * @param label - the row's display name.\n * @param query - the trimmed search text; empty keeps every row.\n * @returns whether the row stays visible.\n */\nfunction matchesQuery(label: string, query: string): boolean {\n return query === '' || label.toLowerCase().includes(query.toLowerCase())\n}\n\n/**\n * Keep the effort the user already picked when the new model offers it.\n * @param model - the catalog model the selection will route to.\n * @param previous - the effort in use before the switch.\n * @returns the effort to submit, or undefined for a model without reasoning.\n */\nfunction effortFor(model: ModelCatalogModel, previous: string | undefined): string | undefined {\n const reasoning = model.reasoning\n if (reasoning === undefined) return undefined\n if (previous !== undefined && reasoning.efforts.some(level => level.id === previous)) return previous\n return reasoning.defaultEffort\n}\n\n/**\n * Render the composer model seat with the group level.\n * @param props - owner share (locked) + injected directory face + the locale seat.\n * @returns the trigger and, while open, the three-level menu.\n */\nexport function ModelGroupSelect(\n { locked, available, directory, load, select, t }:\n ModelGroupSelectInjected & Pick<PropsRuntime<'conversation.input.model'>, 'locked'> & PropsLocale<'modelGroups'>,\n) {\n const state = useSyncExternalStore(\n fn => directory.subscribe(fn),\n () => directory.getSnapshot(),\n )\n const [open, setOpen] = useState(false)\n const [pane, setPane] = useState<Pane>('root')\n const [query, setQuery] = useState('')\n const [highlighted, setHighlighted] = useState(0)\n const [toast, setToast] = useState<string | null>(null)\n const rootRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const searchRef = useRef<HTMLInputElement | null>(null)\n const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n\n const accountName = t('provider.account')\n const providers = useMemo<ProviderRows<ModelCatalogModel>[]>(() => state.groups\n .map(group => ({\n id: group.id,\n name: group.id === 'deepseek-account' ? accountName : group.name,\n options: foldModels(group.id, group.models),\n }))\n .toSorted((left, right) => providerRank(left.id) - providerRank(right.id)), [state.groups, accountName])\n\n const current = state.current\n const located = useMemo(() => {\n for (const provider of providers) {\n for (const option of provider.options) {\n for (const variant of option.variants) {\n if (variant.provider === current?.provider && variant.model.id === current.model) {\n return { provider, option, variant }\n }\n }\n }\n }\n return undefined\n }, [providers, current])\n\n const reasoning = located?.variant.model.reasoning\n const effectiveEffort = current?.reasoningEffort ?? reasoning?.defaultEffort\n const effortLabel = located === undefined\n ? undefined\n : reasoning === undefined\n ? state.retainedEffort\n : effectiveEffort === undefined\n ? t('effort.providerDefault')\n : reasoning.efforts.find((level: ModelReasoningEffort) => level.id === effectiveEffort)?.name ?? effectiveEffort\n\n const currentGroup = located?.variant.group\n const groupChoices = useMemo(() => located === undefined || currentGroup === undefined\n ? []\n : located.option.variants.filter(variant => variant.provider === located.provider.id\n && variant.group !== undefined), [located, currentGroup])\n\n const filteredProviders = useMemo(() => {\n const trimmed = query.trim()\n return providers\n .map(provider => ({\n ...provider,\n options: provider.options.filter(option => matchesQuery(option.label, trimmed)),\n }))\n .filter(provider => provider.options.length > 0)\n }, [providers, query])\n\n const visibleOptions = useMemo(() => filteredProviders.flatMap(provider =>\n provider.options.map(option => ({ provider, option }))), [filteredProviders])\n const showSearch = providers.reduce((total, provider) => total + provider.options.length, 0) > 4\n const activeIndex = Math.min(highlighted, Math.max(0, visibleOptions.length - 1))\n const { pending } = state\n const busy = pending !== null\n const waiting = located === undefined && state.status === 'loading'\n\n const show = (): void => {\n triggerRef.current?.focus()\n setQuery('')\n setHighlighted(0)\n setPane(located === undefined ? 'model' : 'root')\n setOpen(true)\n load()\n }\n\n const close = (restoreFocus = false): void => {\n setOpen(false)\n setPane('root')\n if (restoreFocus) queueMicrotask(() => { triggerRef.current?.focus() })\n }\n\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: MouseEvent): void => {\n if (rootRef.current?.contains(event.target as Node) === true) return\n if (menuRef.current?.contains(event.target as Node) === true) return\n setOpen(false)\n setPane('root')\n }\n document.addEventListener('mousedown', closeOutside)\n return () => { document.removeEventListener('mousedown', closeOutside) }\n }, [open])\n\n useLayoutEffect(() => {\n if (!available || !open) { setMenuPos(null); return }\n const place = (): void => {\n const rect = triggerRef.current?.getBoundingClientRect()\n if (rect === undefined) return\n const MARGIN = 12\n const width = menuRef.current?.offsetWidth ?? 0\n const height = menuRef.current?.offsetHeight ?? 0\n let x = rect.right - width\n let y = rect.top - 8 - height\n if (width > 0) x = Math.min(Math.max(x, MARGIN), window.innerWidth - width - MARGIN)\n if (height > 0) y = Math.min(Math.max(y, MARGIN), window.innerHeight - height - MARGIN)\n setMenuPos({ left: x, top: y })\n }\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n return () => {\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [available, open, pane, state, query])\n\n useLayoutEffect(() => {\n if (open && pane === 'model' && showSearch) searchRef.current?.focus()\n }, [open, pane, showSearch])\n\n if (!available) return null\n\n const settle = (result: Awaited<ReturnType<ModelGroupSelectInjected['select']>>): void => {\n if (result === undefined) return\n if (result.ok) {\n setOpen(false)\n setPane('root')\n return\n }\n const { error } = result\n setToast(error.code === 'session/writer-held'\n ? t('error.sessionInUse')\n : t('error.action', { message: `${error.code}: ${error.message}` }))\n }\n\n const submit = (selection: ModelSelection): void => {\n triggerRef.current?.focus()\n void select(selection).then(settle)\n }\n\n const chooseOption = (option: ModelOption<ModelCatalogModel>): void => {\n const variant = chooseVariant(option, current?.provider, currentGroup)\n if (variant === undefined) return\n if (current?.provider === variant.provider && current.model === variant.model.id) {\n close(true)\n return\n }\n const effort = effortFor(variant.model, effectiveEffort)\n submit({\n provider: variant.provider,\n model: variant.model.id,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const chooseGroup = (variant: ModelVariant<ModelCatalogModel>): void => {\n if (current === null) return\n if (variant.model.id === current.model) {\n close(true)\n return\n }\n const effort = effortFor(variant.model, effectiveEffort)\n submit({\n provider: variant.provider,\n model: variant.model.id,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const chooseEffort = (effort: string | undefined): void => {\n if (current === null) return\n if (effectiveEffort === effort) {\n close(true)\n return\n }\n submit({\n provider: current.provider,\n model: current.model,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n })\n }\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n if (event.nativeEvent.isComposing) return\n if (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== 'root' && located !== undefined) setPane('root')\n else close(true)\n return\n }\n if (!open || pane !== 'root') return\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault()\n setPane('root')\n }\n }\n\n // Only this plugin's own provider gets the rewritten name: every other\n // provider's models are the application's own catalog entries, so the seat\n // must keep showing them exactly as the built-in seat does. The group is a\n // routing dimension and is never spelled out here.\n const ownProvider = located !== undefined && isGroupedProvider(located.provider.id)\n const modelLabel = waiting\n ? t('trigger.loading')\n : located === undefined\n ? t('trigger.fallback')\n : ownProvider\n ? `${displayModelName(located.option.label)} @ ${located.provider.name}`\n : located.option.label\n const triggerParts = [modelLabel, effortLabel].filter(part => part !== undefined && part !== '')\n const triggerLabel = triggerParts.join(' · ')\n const triggerAria = waiting\n ? t('trigger.loading')\n : located === undefined\n ? t('trigger.selectAria')\n : t('trigger.aria', { model: modelLabel })\n\n let optionIndex = 0\n\n return (\n <div ref={rootRef} className={css.root} onKeyDown={onKeyDown}>\n <button\n ref={triggerRef}\n type=\"button\"\n className={css.trigger}\n aria-label={triggerAria}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? `${id}-menu` : undefined}\n title={triggerLabel}\n aria-busy={busy}\n disabled={locked}\n onClick={() => { if (open) close(true); else show() }}\n >\n <IconDataOutlineRegular className={css.triggerIcon} size={16} />\n <span className={css.triggerLabel}>{modelLabel}</span>\n {effortLabel !== undefined && <span className={css.triggerEffort}>{effortLabel}</span>}\n {busy\n ? <StateDot state=\"ongoing\" />\n : <IconChevronDownOutlineRegular className={css.chevron} />}\n </button>\n\n {open && createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={css.menu}\n style={menuPos ?? MEASURE_STYLE}\n role={pane === 'model' || pane === 'group' ? 'group' : 'menu'}\n aria-label={t('menu.aria')}\n aria-busy={state.status === 'loading' || busy}\n >\n {pane === 'root' && (\n <>\n <button type=\"button\" role=\"menuitem\" className={css.cell} onClick={() => { setPane('model') }}>\n <span className={css.cellLabel}>{t('menu.model')}</span>\n <span className={css.cellValue}>{modelLabel}</span>\n <IconChevronRightOutlineRegular className={css.cellChevron} />\n </button>\n {currentGroup !== undefined && (\n <button\n type=\"button\"\n role=\"menuitem\"\n className={css.cell}\n disabled={groupChoices.length < 2}\n onClick={() => { setPane('group') }}\n >\n <span className={css.cellLabel}>{t('menu.group')}</span>\n <span className={css.cellValue}>\n <GroupInline group={currentGroup} description={located?.variant.model.description} showRatio />\n </span>\n {groupChoices.length > 1 && <IconChevronRightOutlineRegular className={css.cellChevron} />}\n </button>\n )}\n {reasoning !== undefined && (\n <button type=\"button\" role=\"menuitem\" className={css.cell} onClick={() => { setPane('effort') }}>\n <span className={css.cellLabel}>{t('menu.effort')}</span>\n <span className={css.cellValue}>{effortLabel}</span>\n <IconChevronRightOutlineRegular className={css.cellChevron} />\n </button>\n )}\n </>\n )}\n\n {pane === 'model' && (\n <>\n {showSearch && (\n <div className={css.searchRow}>\n <Input\n ref={searchRef}\n className={css.search}\n type=\"text\"\n role=\"searchbox\"\n aria-label={t('search.placeholder')}\n placeholder={t('search.placeholder')}\n value={query}\n readOnly={busy}\n onChange={(event) => { setQuery(event.target.value); setHighlighted(0) }}\n />\n {query !== '' && (\n <button\n type=\"button\"\n className={css.searchClear}\n aria-label={t('search.clear')}\n disabled={busy}\n onClick={() => { setQuery(''); searchRef.current?.focus() }}\n >\n <IconCloseFillRegular />\n </button>\n )}\n </div>\n )}\n {state.status === 'loading' && <div className={css.status}>{t('status.loading')}</div>}\n {state.error !== null && (\n <div className={css.error}>\n <span>{t('error.action', { message: state.error })}</span>\n <button type=\"button\" className={css.retry} onClick={load}>{t('action.reload')}</button>\n </div>\n )}\n {state.failures.map(failure => (\n <div className={css.warning} key={failure.id}>\n <span>{t('warning.groupLoad', { name: failure.id === 'deepseek-account' ? accountName : failure.name, message: failure.message })}</span>\n <button type=\"button\" className={css.retry} onClick={load}>{t('action.reload')}</button>\n </div>\n ))}\n <div className={css.groups} role=\"menu\" aria-label={t('menu.model')} hidden={filteredProviders.length === 0}>\n {filteredProviders.map(provider => (\n <MenuGroup key={provider.id} label={provider.name}>\n {provider.options.map(option => {\n const index = optionIndex++\n const isCurrent = located !== undefined && located.option.key === option.key\n && located.provider.id === provider.id\n const groups = option.variants.filter(variant => variant.group !== undefined)\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isCurrent}\n id={`${id}-model-${index}`}\n tabIndex={showSearch ? -1 : 0}\n onFocus={() => { setHighlighted(index) }}\n data-highlighted={index === activeIndex ? '' : undefined}\n className={css.option + ' ' + css.modelOption + ' ' + (index === activeIndex ? css.optionActive : '')}\n key={option.key}\n title={option.label}\n disabled={busy}\n onMouseMove={() => { setHighlighted(index) }}\n onClick={() => { chooseOption(option) }}\n >\n <span className={css.optionCopy}>\n <span className={css.modelName}>\n {isGroupedProvider(provider.id) ? displayModelName(option.label) : option.label}\n </span>\n\n </span>\n <span className={css.optionTrailing}>\n {groups.length > 1 && <span className={css.variantCount}>{groups.length}</span>}\n <span className={css.check}>\n {isCurrent ? <IconCheckOutlineRegular /> : null}\n </span>\n </span>\n </button>\n )\n })}\n </MenuGroup>\n ))}\n </div>\n {state.status === 'ready' && filteredProviders.length === 0 && (\n <div className={css.empty} role=\"status\">\n {t(providers.length === 0 ? 'empty.models' : 'search.empty')}\n </div>\n )}\n </>\n )}\n\n {pane === 'group' && (\n <>\n {groupChoices.length === 0\n ? <div className={css.empty}>{t('empty.groups')}</div>\n : groupChoices.map((variant) => {\n const isCurrent = variant.model.id === current?.model\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={isCurrent}\n className={css.option + (isCurrent ? ' ' + css.selected : '')}\n key={variant.model.id}\n disabled={busy}\n onClick={() => { chooseGroup(variant) }}\n >\n <span className={css.optionCopy}>\n <span className={css.groupOptionLabel}>\n <GroupInline group={variant.group ?? ''} description={variant.model.description} showRatio />\n </span>\n </span>\n <span className={css.check}>\n {isCurrent ? <IconCheckOutlineRegular /> : null}\n </span>\n </button>\n )\n })}\n </>\n )}\n\n {pane === 'effort' && (\n <>\n {(reasoning?.efforts.length ?? 0) === 0\n ? <div className={css.empty}>{t('empty.efforts')}</div>\n : [\n ...reasoning?.defaultEffort === undefined\n ? [{ id: undefined as string | undefined, name: t('effort.providerDefault') }]\n : [],\n ...(reasoning?.efforts ?? []).map((level: ModelReasoningEffort) => ({ id: level.id as string | undefined, name: level.name })),\n ].map(level => (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={effectiveEffort === level.id}\n className={css.option + (effectiveEffort === level.id ? ' ' + css.selected : '')}\n key={level.id ?? 'provider-default'}\n disabled={busy}\n onClick={() => { chooseEffort(level.id) }}\n >\n <span className={css.optionCopy}>\n <span className={css.modelName}>{level.name}</span>\n </span>\n <span className={css.check}>\n {effectiveEffort === level.id ? <IconCheckOutlineRegular /> : null}\n </span>\n </button>\n ))}\n </>\n )}\n </MenuSurface>,\n document.body,\n )}\n {toast !== null && <div className={css.toast} role=\"status\">{toast}</div>}\n </div>\n )\n}\n\n/**\n * One group's inline rendering: badge capsules, its own name, and optionally the\n * ratio badge.\n * @param props - the group key, its hardcoded style, and whether to show the ratio.\n * @returns the inline group value.\n */\nfunction GroupInline(\n { group, description, showRatio = false }: { group: string; description?: string; showRatio?: boolean },\n) {\n const { badges, label } = parseGroupLabel(group)\n const ratio = showRatio ? ratioOf(description) : undefined\n return (\n <span className={css.groupInline}>\n {badges.map(badge => <GroupTag key={badge.text} text={badge.text} tone={badge.tone} />)}\n <span className={css.groupName}>{label}</span>\n {ratio !== undefined && <RatioChip ratio={ratio} />}\n </span>\n )\n}\n\n\n","/**\n * The NearToken settings page: connect the plugin to the site's account through\n * the site's own device-authorization flow, show whose account is connected, and\n * disconnect.\n *\n * The page never asks for a password. It shows the short code the site issued,\n * offers the site's confirmation page, and re-reads the Host while the Host polls\n * — the key and the provider insertion both happen on the Host side of a grant.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { IconChevronDownOutlineRegular, IconRefreshOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {\n NearTokenImageModelEntry, NearTokenImagesState, NearTokenModelEntry, NearTokenModelsState, NearTokenStatus,\n} from '../protocol.ts'\nimport type { NearTokenApi } from './api.ts'\nimport { parseGroupLabel } from './groups.ts'\nimport { GroupTag, RatioChip } from './group-tags.tsx'\nimport type { GroupKey } from './locales.ts'\nimport css from './NearTokenSection.module.css'\n\n/** How often the page re-reads the Host while an authorization is pending. */\nconst PENDING_REFRESH_MS = 1_500\n\n/**\n * How often the page re-reads the Host while connected, so the card shows the\n * wallet numbers the Host re-reads at the same cadence.\n */\nconst CONNECTED_REFRESH_MS = 300_000\n\n/** How long a burst of checkbox clicks waits before one save is written. */\nconst AUTOSAVE_DELAY_MS = 400\n\n/** How long the copy button acknowledges a copied address before resetting. */\nconst COPIED_RESET_MS = 2_000\n\n/** What this section receives from its registration. */\nexport interface NearTokenSectionInjected {\n /** The Host's four routes. */\n api: NearTokenApi\n /** Bound translate for this plugin's dictionary. */\n t: (key: GroupKey, vars?: Record<string, string>) => string\n}\n\n/** Full component props: the section owner share plus this section's injected face. */\nexport type NearTokenSectionProps = PropsRuntime<'settings.section'> & NearTokenSectionInjected\n\n/**\n * Render the NearToken settings page.\n * @param props - the injected route carrier and translate, plus slot owner props.\n * @returns the section element tree.\n */\nexport function NearTokenSection({ api, t }: NearTokenSectionProps) {\n const [status, setStatus] = useState<NearTokenStatus | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n /**\n * Whether the card's money facts are being re-read right now. Kept apart from\n * `busy`: a balance read must not disable the buttons beside it.\n */\n const [walletBusy, setWalletBusy] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n /** Whether the confirmation address was just copied to the clipboard. */\n const [copied, setCopied] = useState(false)\n\n /** Re-read the Host state and publish it. */\n const refresh = useCallback(async (): Promise<void> => {\n try {\n setStatus(await api.status())\n } catch (failure: unknown) {\n setError(t('account.failed', { message: messageOf(failure) }))\n }\n }, [api, t])\n\n // The page opens on whatever the Host already knows, so a reload neither\n // restarts a pending authorization nor forgets a finished one.\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n const pendingCode = status?.pending?.userCode\n const waiting = pendingCode !== undefined\n // A new attempt offers a new address, so the copy acknowledgement starts over.\n useEffect(() => { setCopied(false) }, [pendingCode])\n useEffect(() => {\n if (!copied) return\n const timer = setTimeout(() => { setCopied(false) }, COPIED_RESET_MS)\n return () => { clearTimeout(timer) }\n }, [copied])\n // While the Host polls the site, the page polls the Host: the grant, the\n // refusal, and the expiry all arrive as a changed status.\n useEffect(() => {\n if (!waiting) return\n const timer = setInterval(() => { void refresh() }, PENDING_REFRESH_MS)\n return () => { clearInterval(timer) }\n }, [waiting, pendingCode, refresh])\n\n // While connected, the Host refreshes the wallet on its own cadence; the\n // page re-reads the status at the same rate so those numbers reach the card.\n const connected = status?.configured === true\n useEffect(() => {\n if (!connected) return\n const timer = setInterval(() => { void refresh() }, CONNECTED_REFRESH_MS)\n return () => { clearInterval(timer) }\n }, [connected, refresh])\n\n /** Run one Host call with the busy flag and the error channel wired. */\n const run = useCallback(async (action: () => Promise<void>): Promise<void> => {\n setBusy(true)\n setError(undefined)\n try {\n await action()\n } catch (failure: unknown) {\n setError(t('account.failed', { message: messageOf(failure) }))\n } finally {\n setBusy(false)\n }\n }, [t])\n\n const connect = (): void => {\n void run(async () => {\n const outcome = await api.begin()\n if (outcome.status === 'failed') setError(t('account.failed', { message: outcome.message }))\n await refresh()\n })\n }\n const cancel = (): void => {\n void run(async () => {\n await api.cancel()\n await refresh()\n })\n }\n\n /**\n * Hand the confirmation page to the user's own browser, through the Host: a\n * window the page opens stays inside the shell hosting it — a desktop build\n * shows another application window, and macOS may refuse outright. The\n * address is printed below as well, for a machine with no launcher at all.\n */\n const openAddress = (): void => {\n void (async (): Promise<void> => {\n setError(undefined)\n try {\n await api.openBrowser()\n } catch (failure: unknown) {\n setError(t('account.openFailed', { message: messageOf(failure) }))\n }\n })()\n }\n\n /**\n * Copy the confirmation address, for a machine where nothing can be launched.\n */\n const copyAddress = (): void => {\n const address = status?.pending?.verificationUriComplete\n if (address === undefined) return\n void (async (): Promise<void> => {\n try {\n await navigator.clipboard.writeText(address)\n setCopied(true)\n } catch {\n setError(t('account.copyFailed'))\n }\n })()\n }\n const signOut = (): void => {\n void run(async () => {\n await api.signOut()\n await refresh()\n })\n }\n\n /**\n * Ask the Host to re-read the wallet now, and publish the state it answers\n * with: the same read the Host runs on its own cadence, taken early.\n */\n const refreshWallet = (): void => {\n void (async (): Promise<void> => {\n setWalletBusy(true)\n setError(undefined)\n try {\n setStatus(await api.refreshAccount())\n } catch (failure: unknown) {\n setError(t('account.failed', { message: messageOf(failure) }))\n } finally {\n setWalletBusy(false)\n }\n })()\n }\n\n const account = status?.account\n const pending = status?.pending\n // The empty-voucher sentence owns the link position, so a language that puts\n // it elsewhere only edits its own dictionary entry.\n const [vouchersBefore = '', vouchersAfter = ''] = t('account.vouchersEmpty').split('{link}')\n const minutes = pending === undefined ? 0 : Math.max(1, Math.round((pending.expiresAt - Date.now()) / 60_000))\n return (\n <div className={css.section}>\n <h2 className={css.title}>{t('account.title')}</h2>\n {status === undefined\n ? <p className={css.hint}>{t('account.loading')}</p>\n : status.configured\n ? (\n <section className={css.card}>\n <div className={css.cardHead}>\n <span className={css.name}>{account?.displayName ?? 'NearToken'}</span>\n {account === undefined ? null : <span className={css.handle}>@{account.username}</span>}\n <span className={`${css.badge} ${css.badgeOn}`}>{t('account.connected')}</span>\n </div>\n <dl className={css.facts}>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.group')}</dt>\n <dd className={css.factValue}>{account?.group ?? '—'}</dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.balance')}</dt>\n <dd className={`${css.factValue} ${css.valueRow}`}>\n <span>{account?.balance ?? '—'}</span>\n <button\n type=\"button\"\n className={css.refresh}\n disabled={walletBusy}\n onClick={refreshWallet}\n title={walletBusy ? t('account.refreshing') : t('account.refresh')}\n aria-label={walletBusy ? t('account.refreshing') : t('account.refresh')}\n >\n <IconRefreshOutlineRegular size={13} />\n </button>\n </dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.used')}</dt>\n <dd className={css.factValue}>{account?.used ?? '—'}</dd>\n </div>\n <div className={css.fact}>\n <dt className={css.factLabel}>{t('account.token')}</dt>\n <dd className={css.factValue}>{status.tokenName}</dd>\n </div>\n {account !== undefined && (account.vouchers?.length ?? 0) > 0\n ? (\n <div className={`${css.fact} ${css.voucherFact}`}>\n <dt className={css.factLabel}>{t('account.vouchers')}</dt>\n <dd className={css.voucherList}>\n {account.vouchers?.map(voucher => (\n <span key={`${voucher.groupId}:${voucher.group}`} className={css.voucherRow}>\n <span className={css.voucherGroup}>{voucher.group}</span>\n <span className={css.voucherAmount}>{voucher.amount}</span>\n </span>\n ))}\n </dd>\n </div>\n )\n : account !== undefined\n ? (\n <div className={`${css.fact} ${css.voucherFact}`}>\n <dt className={css.factLabel}>{t('account.vouchers')}</dt>\n <dd className={css.voucherEmpty}>\n {vouchersBefore}\n <a className={css.invite} href={`${status.baseURL}/wallet`} target=\"_blank\" rel=\"noreferrer\">\n {t('account.vouchersInvite')}\n </a>\n {vouchersAfter}\n </dd>\n </div>\n )\n : null}\n </dl>\n <div className={css.actions}>\n <button type=\"button\" className={css.button} disabled={busy} onClick={signOut}>\n {busy ? t('account.signingOut') : t('account.signOut')}\n </button>\n </div>\n </section>\n )\n : (\n <section className={css.card}>\n <div className={css.cardHead}>\n <span className={css.name}>{t('account.title')}</span>\n <span className={css.badge}>{t('account.disconnected')}</span>\n </div>\n <p className={css.hint}>{t('account.site')}:{status.baseURL}</p>\n {pending === undefined\n ? (\n <div className={css.actions}>\n <button\n type=\"button\" className={`${css.button} ${css.buttonPrimary}`} disabled={busy} onClick={connect}\n >\n {busy ? t('account.connecting') : t('account.connect')}\n </button>\n </div>\n )\n : (\n <div className={css.form}>\n <p className={css.hint}>{t('account.waiting')}</p>\n <div className={css.codeRow}>\n <span className={css.label}>{t('account.userCode')}</span>\n <code className={css.code}>{pending.userCode}</code>\n </div>\n <div className={css.actions}>\n <button\n type=\"button\" className={`${css.button} ${css.buttonPrimary}`}\n onClick={openAddress}\n >\n {t('account.openBrowser')}\n </button>\n <button type=\"button\" className={css.button} disabled={busy} onClick={cancel}>\n {busy ? t('account.cancelling') : t('account.cancel')}\n </button>\n </div>\n {/* Some platforms (macOS among them) let the automatic\n browser launch do nothing, so the address is also handed\n over as selectable text that can be copied by hand. */}\n <div className={css.linkRow}>\n <span className={css.label}>{t('account.manualLink')}</span>\n <div className={css.linkLine}>\n <a\n className={css.link} href={pending.verificationUriComplete}\n target=\"_blank\" rel=\"noopener noreferrer\"\n >\n {pending.verificationUriComplete}\n </a>\n <button type=\"button\" className={css.button} onClick={copyAddress}>\n {copied ? t('account.copied') : t('account.copyLink')}\n </button>\n </div>\n </div>\n <p className={css.hint}>{t('account.expiresIn', { minutes: String(minutes) })}</p>\n </div>\n )}\n </section>\n )}\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n {status?.error === undefined ? null : <p className={css.notice}>{t('account.failed', { message: status.error })}</p>}\n {status?.configured === true ? <ModelWhitelist api={api} t={t} /> : null}\n {status?.configured === true ? <ImageGeneration api={api} t={t} /> : null}\n </div>\n )\n}\n\n/**\n * The model whitelist block: which of the site's models the provider keeps in\n * the model picker, edited through the same-origin models carrier.\n *\n * An empty stored list means \"no whitelist\", so the boxes start all checked —\n * that is what the picker currently shows. Saving an empty list is refused\n * here, because it would read as the same \"no whitelist\" state; \"Show all\"\n * (which saves exactly that) is the explicit way back to the whole catalog.\n * @param props - the injected route carrier and translate.\n * @returns the whitelist block.\n */\nfunction ModelWhitelist({ api, t }: NearTokenSectionInjected) {\n const [state, setState] = useState<NearTokenModelsState | undefined>(undefined)\n const [selected, setSelected] = useState<ReadonlySet<string>>(new Set())\n const [query, setQuery] = useState('')\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n const [saved, setSaved] = useState(false)\n /** Why the last edit could not be applied; cleared by the next one. */\n const [notice, setNotice] = useState<string | undefined>(undefined)\n /** Whether the list itself is showing; the card opens collapsed. */\n const [open, setOpen] = useState(false)\n /** The queued save, while a burst of clicks is still settling. */\n const pending = useRef<number | undefined>(undefined)\n // The row whose group detail is showing, positioned in viewport coordinates:\n // the list scrolls, so the panel must escape its clip box rather than live in\n // the row's flow.\n const [tip, setTip] = useState<{ entry: NearTokenModelEntry; top: number; left: number } | undefined>(undefined)\n\n /** Publish one host answer: the boxes show the stored list, or all when none is stored. */\n const adopt = useCallback((next: NearTokenModelsState): void => {\n setState(next)\n setSelected(new Set(next.enabled.length === 0 ? next.models.map(entry => entry.model) : next.enabled))\n }, [])\n\n const load = useCallback(async (): Promise<void> => {\n try {\n adopt(await api.models())\n } catch (failure: unknown) {\n setError(t('whitelist.failed', { message: messageOf(failure) }))\n }\n }, [adopt, api, t])\n\n useEffect(() => { void load() }, [load])\n\n const models = state?.models ?? []\n const needle = query.trim().toLowerCase()\n const visible = needle === ''\n ? models\n : models.filter(entry => entry.model.toLowerCase().includes(needle))\n\n /** Cancel the pending save, if one is queued. */\n const cancelPending = useCallback((): void => {\n if (pending.current === undefined) return\n window.clearTimeout(pending.current)\n pending.current = undefined\n }, [])\n\n // A queued save must not outlive the page it belongs to.\n useEffect(() => cancelPending, [cancelPending])\n\n /**\n * Apply an edit to the boxes and queue one save.\n *\n * The list is stored as it is edited — there is no Save button to forget —\n * so the delay only coalesces a burst of clicks into one profile write.\n */\n const edit = (next: ReadonlySet<string>): void => {\n setSaved(false)\n setNotice(undefined)\n setSelected(next)\n cancelPending()\n // Catalog order, not click order: the stored list reads like the picker.\n const enabled = models.filter(entry => next.has(entry.model)).map(entry => entry.model)\n pending.current = window.setTimeout(() => {\n pending.current = undefined\n void persist(enabled)\n }, AUTOSAVE_DELAY_MS)\n }\n\n const toggle = (model: string): void => {\n const next = new Set(selected)\n if (next.has(model)) next.delete(model)\n else next.add(model)\n // An empty list means \"no whitelist\", i.e. show everything — the opposite\n // of what unchecking the last box asks for.\n if (next.size === 0) {\n setNotice(t('whitelist.keepOne'))\n return\n }\n edit(next)\n }\n /** Show one row's groups just below it, above it when there is no room. */\n const showTip = (entry: NearTokenModelEntry, anchor: HTMLElement): void => {\n const rect = anchor.getBoundingClientRect()\n const height = Math.min(240, 34 + entry.groups.length * 20)\n const below = rect.bottom + 6\n setTip({\n entry,\n top: below + height > window.innerHeight ? Math.max(12, rect.top - height - 6) : below,\n left: Math.max(12, Math.min(rect.left + 24, window.innerWidth - 292)),\n })\n }\n const checkVisible = (): void => {\n edit(new Set([...selected, ...visible.map(entry => entry.model)]))\n }\n /**\n * Empty the boxes the filter is showing.\n *\n * An emptied selection cannot be saved as such: an empty stored list means\n * \"no whitelist\", i.e. show every model, which is the opposite of the click.\n * So the boxes empty at once and the saved list is left alone; the next check\n * box saves the set the user actually wants, and \"Show all\" is the way back.\n */\n const uncheckVisible = (): void => {\n const hidden = new Set(visible.map(entry => entry.model))\n const next = new Set([...selected].filter(model => !hidden.has(model)))\n if (next.size > 0) {\n edit(next)\n return\n }\n cancelPending()\n setSaved(false)\n setSelected(next)\n setNotice(t('whitelist.cleared'))\n }\n\n /**\n * Write one list to the Host, which re-declares the provider route so the\n * model picker refetches without a page reload.\n * @param enabled - the model names to keep visible; empty restores everything.\n */\n const persist = useCallback(async (enabled: readonly string[]): Promise<void> => {\n setSaving(true)\n setError(undefined)\n try {\n await api.saveModels(enabled)\n setSaved(true)\n } catch (failure: unknown) {\n setError(t('whitelist.failed', { message: messageOf(failure) }))\n } finally {\n setSaving(false)\n }\n }, [api, t])\n\n /** Restore the whole catalog: nothing hidden, nothing stored. */\n const showEverything = (): void => {\n cancelPending()\n setSelected(new Set(models.map(entry => entry.model)))\n void persist([])\n }\n\n return (\n <section className={css.card}>\n <button\n type=\"button\"\n className={css.cardToggle}\n aria-expanded={open}\n aria-label={t(open ? 'card.collapse' : 'card.expand')}\n onClick={() => { setOpen((current) => !current) }}\n >\n <span className={css.name}>{t('whitelist.title')}</span>\n <span className={css.count}>\n <span className={css.countTotal}>{t('whitelist.count', { total: String(models.length) })}</span>\n <span className={css.countDot} aria-hidden=\"true\" />\n <span className={css.countPicked}>{t('whitelist.picked', { selected: String(selected.size) })}</span>\n </span>\n <IconChevronDownOutlineRegular\n className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron}\n size={14}\n />\n </button>\n {!open ? null : <>\n <p className={css.intro}>{t('whitelist.intro')}</p>\n {state === undefined\n ? (error === undefined ? <p className={css.hint}>{t('whitelist.loading')}</p> : null)\n : (\n <div className={css.form}>\n <input\n className={css.search}\n type=\"search\"\n value={query}\n placeholder={t('whitelist.search')}\n aria-label={t('whitelist.search')}\n onChange={(event) => { setQuery(event.target.value) }}\n />\n <div className={css.toolbar}>\n <button type=\"button\" className={css.button} disabled={saving || visible.length === 0} onClick={checkVisible}>\n {t('whitelist.selectAll')}\n </button>\n <button type=\"button\" className={css.button} disabled={saving || visible.length === 0} onClick={uncheckVisible}>\n {t('whitelist.clear')}\n </button>\n <button type=\"button\" className={css.button} disabled={saving} onClick={showEverything}>\n {t('whitelist.reset')}\n </button>\n <span className={css.autosave} aria-live=\"polite\">\n {saving ? t('whitelist.saving') : saved ? t('whitelist.autoSaved') : ''}\n </span>\n </div>\n {models.length === 0\n ? <p className={css.hint}>{t('whitelist.empty')}</p>\n : (\n <div className={css.list} onScroll={() => { setTip(undefined) }}>\n {visible.length === 0\n ? <p className={css.hint}>{t('whitelist.noMatch')}</p>\n : visible.map(entry => (\n <label\n key={entry.model}\n className={css.row}\n onMouseEnter={(event) => { showTip(entry, event.currentTarget) }}\n onMouseLeave={() => { setTip(undefined) }}\n >\n <input\n type=\"checkbox\"\n checked={selected.has(entry.model)}\n onChange={() => { toggle(entry.model) }}\n />\n <span className={css.rowName}>{entry.model}</span>\n <span className={css.rowMeta}>\n {entry.groups.length === 0 ? null : (\n <span>{t('whitelist.groupsCount', { count: String(entry.groups.length) })}</span>\n )}\n {entry.minRatio === undefined ? null : (\n <>\n <span className={css.rowRatio}>{t('whitelist.minRatio')}</span>\n <RatioChip ratio={String(entry.minRatio) + 'x'} />\n </>\n )}\n </span>\n </label>\n ))}\n {tip === undefined ? null : (\n <div className={css.tip} style={{ top: tip.top, left: tip.left }} role=\"tooltip\">\n <span className={css.tipTitle}>{t('whitelist.groupsTitle')}</span>\n {tip.entry.groups.map(group => {\n const parsed = parseGroupLabel(group.group)\n return (\n <span key={group.group} className={css.tipRow}>\n <span className={css.tipGroup}>\n {parsed.badges.map(badge => (\n <GroupTag key={badge.text} text={badge.text} tone={badge.tone} />\n ))}\n <span className={css.tipGroupName}>{parsed.label}</span>\n </span>\n {group.ratio === undefined ? null : <RatioChip ratio={group.ratio} />}\n </span>\n )\n })}\n </div>\n )}\n </div>\n )}\n <p className={css.hint}>{t('whitelist.hint')}</p>\n {notice === undefined ? null : <p className={css.notice}>{notice}</p>}\n </div>\n )}\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n </>}\n </section>\n )\n}\n\n/**\n * The image-generation card: the `generate_image` tool's switch and, per picture\n * model, the group its requests route through.\n *\n * Unlike the whitelist this block saves on a button, not on every click: the two\n * members describe one setting, and a group choice made before the model is\n * checked would otherwise be written as nothing.\n * @param props - the injected route carrier and translate.\n * @returns the image-generation block.\n */\nfunction ImageGeneration({ api, t }: NearTokenSectionInjected) {\n const [state, setState] = useState<NearTokenImagesState | undefined>(undefined)\n const [enabled, setEnabled] = useState(false)\n const [selection, setSelection] = useState<Readonly<Record<string, string>>>({})\n const [busy, setBusy] = useState(false)\n const [dirty, setDirty] = useState(false)\n const [error, setError] = useState<string | undefined>(undefined)\n const [saved, setSaved] = useState(false)\n /** Whether the controls are showing; the card opens collapsed. */\n const [open, setOpen] = useState(false)\n\n /** Publish one host answer into the controls. */\n const adopt = useCallback((next: NearTokenImagesState): void => {\n setState(next)\n setEnabled(next.enabled)\n setSelection({ ...next.selection })\n setDirty(false)\n }, [])\n\n const load = useCallback(async (): Promise<void> => {\n try {\n adopt(await api.images())\n } catch (failure: unknown) {\n setError(t('images.failed', { message: messageOf(failure) }))\n }\n }, [adopt, api, t])\n\n useEffect(() => { void load() }, [load])\n\n const models = state?.models ?? []\n const enabledCount = Object.keys(selection).length\n\n /** Check or uncheck one model; the first group of a newly checked model is its route. */\n const toggle = (model: string, groups: NearTokenImageModelEntry['groups']): void => {\n setSaved(false)\n setDirty(true)\n setSelection((current) => {\n if (current[model] !== undefined) {\n const next = { ...current }\n delete next[model]\n return next\n }\n const first = groups[0]?.group\n return first === undefined ? current : { ...current, [model]: first }\n })\n }\n\n const chooseGroup = (model: string, group: string): void => {\n setSaved(false)\n setDirty(true)\n setSelection(current => ({ ...current, [model]: group }))\n }\n\n const save = async (): Promise<void> => {\n setBusy(true)\n setError(undefined)\n setSaved(false)\n try {\n await api.saveImages({ enabled, models: selection })\n setSaved(true)\n setDirty(false)\n } catch (failure: unknown) {\n setError(t('images.failed', { message: messageOf(failure) }))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <section className={css.card}>\n <button\n type=\"button\"\n className={css.cardToggle}\n aria-expanded={open}\n aria-label={t(open ? 'card.collapse' : 'card.expand')}\n onClick={() => { setOpen((current) => !current) }}\n >\n <span className={css.name}>{t('images.title')}</span>\n <span className={css.count}>\n <span className={css.countTotal}>{t('images.count', { total: String(models.length) })}</span>\n <span className={css.countDot} aria-hidden=\"true\" />\n <span className={css.countPicked}>{t('images.picked', { selected: String(enabledCount) })}</span>\n </span>\n <IconChevronDownOutlineRegular\n className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron}\n size={14}\n />\n </button>\n {!open ? null : <>\n <p className={css.intro}>{t('images.intro')}</p>\n {state === undefined\n ? (error === undefined ? <p className={css.hint}>{t('images.loading')}</p> : null)\n : (\n <div className={css.form}>\n <label className={css.row}>\n <input\n type=\"checkbox\"\n checked={enabled}\n onChange={(event) => { setSaved(false); setDirty(true); setEnabled(event.target.checked) }}\n />\n <span className={css.rowName}>{t('images.enable')}</span>\n </label>\n {models.length === 0\n ? <p className={css.hint}>{t('images.empty')}</p>\n : (\n <div className={css.list}>\n {models.map(entry => (\n <label key={entry.model} className={css.row}>\n <input\n type=\"checkbox\"\n checked={selection[entry.model] !== undefined}\n onChange={() => { toggle(entry.model, entry.groups) }}\n />\n <span className={css.rowName}>{entry.model}</span>\n <select\n className={css.select}\n aria-label={t('images.groupAria', { model: entry.model })}\n disabled={selection[entry.model] === undefined}\n value={selection[entry.model] ?? entry.groups[0]?.group ?? ''}\n onChange={(event) => { chooseGroup(entry.model, event.target.value) }}\n >\n {entry.groups.map(group => (\n <option key={group.group} value={group.group}>\n {group.group}{group.ratio === undefined ? '' : ` · ${group.ratio}`}\n </option>\n ))}\n </select>\n <span className={css.rowMeta}>\n {t(entry.channel === 'images'\n ? 'images.channel.images'\n : entry.channel === 'genai' ? 'images.channel.genai' : 'images.channel.chat')}\n </span>\n </label>\n ))}\n </div>\n )}\n <div className={css.toolbar}>\n <button type=\"button\" className={css.button} disabled={busy || !dirty} onClick={() => { void save() }}>\n {busy ? t('images.saving') : t('images.save')}\n </button>\n <span className={css.autosave} aria-live=\"polite\">\n {dirty ? t('images.dirty') : saved ? t('images.saved') : ''}\n </span>\n </div>\n <p className={css.hint}>{t('images.hint')}</p>\n {error === undefined ? null : <p className={css.notice}>{error}</p>}\n </div>\n )}\n </>}\n </section>\n )\n}\n\n/**\n * Render one thrown value as the message the page shows.\n * @param error - whatever the call threw.\n * @returns the error's message, or its text.\n */\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}","/**\n * `modelGroups` namespace dictionaries. Copy mirrors the built-in model seat so\n * the two readings of the same control stay identical; only the group keys are\n * new.\n */\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'provider.account': 'DeepSeek 账号',\n 'trigger.fallback': '请选择模型',\n 'trigger.loading': '正在加载模型…',\n 'trigger.selectAria': '请选择模型',\n 'trigger.aria': '选择模型,当前 {model}',\n 'trigger.ariaEffort': '选择模型,当前 {model},推理等级 {effort}',\n 'menu.aria': '模型、分组与推理等级',\n 'menu.model': '模型',\n 'menu.group': '分组',\n 'menu.effort': '推理等级',\n 'effort.providerDefault': 'Default',\n 'status.loading': '正在刷新模型列表…',\n 'error.action': '模型操作失败:{message}',\n 'error.sessionInUse': '当前会话已被占用,可能是其他正在运行的 DSH 导致的(如其他 dsh web、桌面端),请退出其他正在运行的 DSH 后重试。',\n 'action.reload': '重新加载',\n 'warning.groupLoad': '{name} 加载失败:{message}',\n 'search.placeholder': '搜索模型…',\n 'search.clear': '清除搜索',\n 'search.empty': '没有匹配的模型。',\n 'empty.models': '暂无可用模型',\n 'empty.groups': '当前模型没有其它分组。',\n 'empty.efforts': '当前模型未提供推理等级。',\n 'account.nav': 'NearToken',\n 'account.title': 'NearToken 账号',\n 'account.site': '站点',\n 'account.connect': '连接 NearToken',\n 'account.connecting': '正在发起…',\n 'account.waiting': '已发起授权,请在浏览器中确认。',\n 'account.userCode': '确认码',\n 'account.openBrowser': '打开浏览器确认',\n 'account.manualLink': '打不开浏览器时,手动打开下面的地址:',\n 'account.copyLink': '复制链接',\n 'account.copied': '已复制',\n 'account.copyFailed': '复制失败,请手动选中上面的链接复制。',\n 'account.openFailed': '未能打开浏览器({message});请复制下面的地址,在自己的浏览器里访问。',\n 'account.expiresIn': '本次确认 {minutes} 分钟内有效',\n 'account.cancel': '取消',\n 'account.cancelling': '正在取消…',\n 'account.connected': '已接入',\n 'account.disconnected': '未连接',\n 'account.group': '用户分组',\n 'account.balance': '剩余额度',\n 'account.used': '已用额度',\n 'account.vouchers': '代金券',\n 'account.vouchersEmpty': '你还没有代金券,你可以通过{link}获得免费代金券',\n 'account.vouchersInvite': '邀请计划',\n 'account.refresh': '刷新余额',\n 'account.refreshing': '正在刷新…',\n 'account.token': 'API 令牌',\n 'account.signOut': '断开连接',\n 'account.signingOut': '正在断开…',\n 'account.loading': '正在读取连接状态…',\n 'account.failed': '操作失败:{message}',\n 'whitelist.title': '模型白名单',\n 'whitelist.intro': '勾选要出现在 DSH 模型选择器里的模型;未勾选的不会出现。白名单写在插件配置里,重启后依然生效。',\n 'whitelist.loading': '正在读取模型清单…',\n 'whitelist.failed': '模型白名单操作失败:{message}',\n 'whitelist.search': '搜索模型…',\n 'whitelist.noMatch': '没有匹配的模型。',\n 'whitelist.empty': '站点没有返回任何模型。',\n 'whitelist.count': '{total} 个模型',\n 'whitelist.picked': '已选 {selected}',\n 'card.expand': '展开',\n 'card.collapse': '收起',\n 'whitelist.groupsCount': '{count} 个分组',\n 'whitelist.minRatio': '最低',\n 'whitelist.groupsTitle': '可用分组',\n 'whitelist.selectAll': '全选',\n 'whitelist.clear': '清空',\n 'whitelist.reset': '全部显示',\n 'whitelist.saving': '正在保存…',\n 'whitelist.autoSaved': '已自动保存,模型选择器已刷新',\n 'whitelist.hint': '勾选即自动保存;没勾选的不会出现在模型选择器里。「全部显示」会清空白名单。',\n 'whitelist.keepOne': '至少要保留一个模型;想放开全部请点「全部显示」。',\n 'whitelist.cleared': '已清空勾选;勾选要显示的模型后会立即保存。',\n 'images.title': '图像生成',\n 'images.intro': '开启后模型可以调用 generate_image 工具生图。勾选要用的生图模型,并为每个模型指定走哪个分组(决定计费与可用性)。',\n 'images.enable': '启用 generate_image 工具',\n 'images.channel.images': 'images 接口',\n 'images.channel.genai': 'gemini 接口',\n 'images.channel.chat': 'chat 接口',\n 'images.save': '保存',\n 'images.saving': '正在保存…',\n 'images.saved': '已保存,工具已按新设置生效',\n 'images.dirty': '有未保存的改动',\n 'images.hint': '生图一次约 20-60 秒;不勾选的模型模型看不到也调不到。改完记得点保存。',\n 'images.failed': '图像生成设置失败:{message}',\n 'images.empty': '站点没有返回任何生图模型。',\n 'images.loading': '正在读取生图模型…',\n 'images.count': '{total} 个生图模型',\n 'images.picked': '已启用 {selected}',\n 'images.groupAria': '{model} 使用的分组',\n} satisfies Record<string, string>\n\n/** The dictionary key union. */\nexport type GroupKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'provider.account': 'DeepSeek Account',\n 'trigger.fallback': 'Select model',\n 'trigger.loading': 'Loading models…',\n 'trigger.selectAria': 'Select model',\n 'trigger.aria': 'Select model, current {model}',\n 'trigger.ariaEffort': 'Select model, current {model}, reasoning effort {effort}',\n 'menu.aria': 'Model, group, and reasoning effort',\n 'menu.model': 'Model',\n 'menu.group': 'Group',\n 'menu.effort': 'Effort',\n 'effort.providerDefault': 'Default',\n 'status.loading': 'Refreshing model list…',\n 'error.action': 'Model operation failed: {message}',\n 'error.sessionInUse': 'This session is already in use, possibly by another running DSH instance (such as dsh web or the desktop app). Quit other running DSH instances and try again.',\n 'action.reload': 'Reload',\n 'warning.groupLoad': '{name} failed to load: {message}',\n 'search.placeholder': 'Search models…',\n 'search.clear': 'Clear search',\n 'search.empty': 'No matching models.',\n 'empty.models': 'No models available.',\n 'empty.groups': 'This model offers no other group.',\n 'empty.efforts': 'This model provides no reasoning effort levels.',\n 'account.nav': 'NearToken',\n 'account.title': 'NearToken account',\n 'account.site': 'Site',\n 'account.connect': 'Connect NearToken',\n 'account.connecting': 'Starting…',\n 'account.waiting': 'Authorization started. Confirm it in your browser.',\n 'account.userCode': 'Code',\n 'account.openBrowser': 'Open browser to confirm',\n 'account.manualLink': 'If the browser does not open, open this address yourself:',\n 'account.copyLink': 'Copy link',\n 'account.copied': 'Copied',\n 'account.copyFailed': 'Could not copy; select the link above and copy it yourself.',\n 'account.openFailed': 'Could not open your browser ({message}); copy the address below and open it yourself.',\n 'account.expiresIn': 'This confirmation is valid for {minutes} minutes',\n 'account.cancel': 'Cancel',\n 'account.cancelling': 'Cancelling…',\n 'account.connected': 'Connected',\n 'account.disconnected': 'Not connected',\n 'account.group': 'Group',\n 'account.balance': 'Balance',\n 'account.used': 'Used',\n 'account.vouchers': 'Vouchers',\n 'account.vouchersEmpty': 'You have no vouchers yet. Get free vouchers through the {link}.',\n 'account.vouchersInvite': 'referral program',\n 'account.refresh': 'Refresh balance',\n 'account.refreshing': 'Refreshing…',\n 'account.token': 'API token',\n 'account.signOut': 'Disconnect',\n 'account.signingOut': 'Disconnecting…',\n 'account.loading': 'Reading connection state…',\n 'account.failed': 'Failed: {message}',\n 'whitelist.title': 'Model whitelist',\n 'whitelist.intro': 'Check the models that should appear in the DSH model picker; unchecked models stay hidden. The list is stored in the plugin configuration and survives a restart.',\n 'whitelist.loading': 'Reading the model list…',\n 'whitelist.failed': 'Model whitelist failed: {message}',\n 'whitelist.search': 'Search models…',\n 'whitelist.noMatch': 'No matching models.',\n 'whitelist.empty': 'The site returned no models.',\n 'whitelist.count': '{total} models',\n 'whitelist.picked': '{selected} selected',\n 'card.expand': 'Expand',\n 'card.collapse': 'Collapse',\n 'whitelist.groupsCount': '{count} groups',\n 'whitelist.minRatio': 'from',\n 'whitelist.groupsTitle': 'Available groups',\n 'whitelist.selectAll': 'Check all',\n 'whitelist.clear': 'Clear',\n 'whitelist.reset': 'Show all',\n 'whitelist.saving': 'Saving…',\n 'whitelist.autoSaved': 'Saved; the model picker has been refreshed',\n 'whitelist.hint': 'Every change saves itself; unchecked models stay out of the picker. \"Show all\" clears the whitelist.',\n 'whitelist.keepOne': 'Keep at least one model; use \"Show all\" to offer everything again.',\n 'whitelist.cleared': 'Boxes cleared; checking a model saves the list you want.',\n 'images.title': 'Image generation',\n '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.',\n 'images.enable': 'Enable the generate_image tool',\n 'images.channel.images': 'images endpoint',\n 'images.channel.genai': 'gemini endpoint',\n 'images.channel.chat': 'chat endpoint',\n 'images.save': 'Save',\n 'images.saving': 'Saving…',\n 'images.saved': 'Saved; the tool now runs with these settings',\n 'images.dirty': 'Unsaved changes',\n 'images.hint': 'One picture takes 20-60 seconds; an unchecked model is invisible to the model and cannot be called. Remember to save.',\n 'images.failed': 'Image generation settings failed: {message}',\n 'images.empty': 'The site returned no picture models.',\n 'images.loading': 'Reading the picture models…',\n 'images.count': '{total} picture models',\n 'images.picked': '{selected} enabled',\n 'images.groupAria': 'Group used by {model}',\n} satisfies Record<GroupKey, string>\n","/**\n * NearToken provider plugin, browser half. Registers two surfaces: the NearToken\n * settings page (sign in, account facts, sign out) and a replacement for the\n * composer's model seat at priority -1, so the slot's lowest-priority\n * registration renders and the shipped picker stays in place without drawing.\n *\n * The seat shares the SAME per-session directory the built-in picker uses\n * (`ctx.modelDirectories`), so selection state, pending markers, the /model\n * popup, and Session persistence are unaffected: this plugin only changes what\n * the control looks like and adds the group level on top of it.\n *\n * The seat's declared child ('conversation.input.model.label') is owned by the\n * shipped registration, so this one declares none and renders catalog names\n * directly.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\n// Type-only: the carrier types and the ctx.modelDirectories / ctx.remote merges.\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui-conversation SlotMap merge (the input.model seat).\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { ModelSelection } from '@deepseek-ai/dsh-api-session-controller/types'\n// Type-only: pulls the settings shell's SlotMap merge ('settings.section').\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { createNearTokenApi } from './api.ts'\nimport { ModelGroupSelect } from './ModelGroupSelect.tsx'\nimport { NearTokenSection, type NearTokenSectionInjected } from './NearTokenSection.tsx'\nimport { en, zh, type GroupKey } from './locales.ts'\nimport type { ModelGroupSelectInjected } from './slots.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** The replacement model seat's copy. */\n modelGroups: GroupKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nconst NS = 'modelGroups'\n\n/** Required services: the slot registry, locale, sessions, and the directory service. */\nexport const inject = ['slots', 'locale', 'sessions', 'remote', 'remote.session']\n\n/**\n * Client plugin body: register the dictionaries, add the NearToken settings page,\n * then shadow the composer model seat over the shared model directory.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-neartoken-provider: dictionaries')\n // One carrier for the page's whole life: the registration closure hands the\n // same object back on every render, so the section's load effect runs once.\n const api = createNearTokenApi()\n const t = ctx.locale.bind(NS) as NearTokenSectionInjected['t']\n // The near-token page sits between the account page (-10) and the general\n // page (0): both answer \"who am I signed in as\".\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'neartoken',\n order: -5,\n label: () => t('account.nav'),\n locale: NS,\n inject: (): NearTokenSectionInjected => ({ api, t }),\n }, NearTokenSection))\n\n ctx.inject(['slots', 'modelDirectories'], (scope: ClientContext) => {\n const models = scope.modelDirectories\n const sessions = scope.sessions\n scope.slots.inject('conversation.input.model', () => scope.slots.register({\n name: 'conversation.input.model',\n // Shipped seat registers at the default priority 0; lower renders.\n priority: -1,\n locale: NS,\n inject: (sessionId): ModelGroupSelectInjected => {\n const directory = models.directoryFor(sessionId)\n const available = sessions.subagentAddress(sessionId) === undefined\n return {\n available,\n directory: directory.store,\n load: () => {\n if (available) directory.load().catch(() => { /* surfaced on the store */ })\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection)\n : Promise.resolve(undefined),\n }\n },\n }, ModelGroupSelect))\n })\n}\n"],"mappings":"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"}
package/lib/index.js CHANGED
@@ -4019,6 +4019,12 @@ async function openInSystemBrowser(address, platform = process.platform, launche
4019
4019
  */
4020
4020
  /** State read by the settings page before it draws, and while it waits. */
4021
4021
  const STATUS_PATH = "/neartoken/status";
4022
+ /**
4023
+ * Re-read the wallet right now, then answer with the same state `STATUS_PATH`
4024
+ * reads. The Host already refreshes on its own cadence; this is the page asking
4025
+ * for that read early, and the answer carries the fresh numbers.
4026
+ */
4027
+ const REFRESH_PATH = "/neartoken/refresh";
4022
4028
  /** Start a device authorization (the Host then polls the site). */
4023
4029
  const AUTHORIZE_PATH = "/neartoken/authorize";
4024
4030
  /** Abandon the authorization in progress. */
@@ -4057,6 +4063,20 @@ function registerNearTokenRoutes(ctx, deps) {
4057
4063
  sendJson(res, 200, await deps.account.status());
4058
4064
  }
4059
4065
  }), `neartoken: GET ${STATUS_PATH}`);
4066
+ ctx.effect(() => ctx.webServer.register({
4067
+ kind: "exact",
4068
+ path: REFRESH_PATH,
4069
+ handler: async (req, res) => {
4070
+ if (rejected(ctx, req, res)) return;
4071
+ if (req.method !== "POST") {
4072
+ sendMethodNotAllowed(res, "POST");
4073
+ return;
4074
+ }
4075
+ req.resume();
4076
+ await deps.account.refreshWallet();
4077
+ sendJson(res, 200, await deps.account.status());
4078
+ }
4079
+ }), `neartoken: POST ${REFRESH_PATH}`);
4060
4080
  ctx.effect(() => ctx.webServer.register({
4061
4081
  kind: "exact",
4062
4082
  path: AUTHORIZE_PATH,
@@ -5,6 +5,12 @@ export type Fetch = (input: string, init?: RequestInit) => Promise<Response>;
5
5
  export interface NearTokenApi {
6
6
  /** Read the key state, the account card, and any authorization in progress. */
7
7
  status(): Promise<NearTokenStatus>;
8
+ /**
9
+ * Re-read the wallet now and answer with the fresh state. The Host already
10
+ * refreshes on its own cadence; this asks for that read early, so the card
11
+ * shows money facts newer than the last poll.
12
+ */
13
+ refreshAccount(): Promise<NearTokenStatus>;
8
14
  /** Start a device authorization; the Host polls the site from then on. */
9
15
  begin(): Promise<BeginAuthorizationOutcome>;
10
16
  /** Abandon the authorization in progress. */
@@ -49,6 +49,10 @@ export declare const zh: {
49
49
  'account.balance': string;
50
50
  'account.used': string;
51
51
  'account.vouchers': string;
52
+ 'account.vouchersEmpty': string;
53
+ 'account.vouchersInvite': string;
54
+ 'account.refresh': string;
55
+ 'account.refreshing': string;
52
56
  'account.token': string;
53
57
  'account.signOut': string;
54
58
  'account.signingOut': string;
@@ -142,6 +146,10 @@ export declare const en: {
142
146
  'account.balance': string;
143
147
  'account.used': string;
144
148
  'account.vouchers': string;
149
+ 'account.vouchersEmpty': string;
150
+ 'account.vouchersInvite': string;
151
+ 'account.refresh': string;
152
+ 'account.refreshing': string;
145
153
  'account.token': string;
146
154
  'account.signOut': string;
147
155
  'account.signingOut': string;
@@ -12,6 +12,12 @@
12
12
  */
13
13
  /** State read by the settings page before it draws, and while it waits. */
14
14
  export declare const STATUS_PATH = "/neartoken/status";
15
+ /**
16
+ * Re-read the wallet right now, then answer with the same state `STATUS_PATH`
17
+ * reads. The Host already refreshes on its own cadence; this is the page asking
18
+ * for that read early, and the answer carries the fresh numbers.
19
+ */
20
+ export declare const REFRESH_PATH = "/neartoken/refresh";
15
21
  /** Start a device authorization (the Host then polls the site). */
16
22
  export declare const AUTHORIZE_PATH = "/neartoken/authorize";
17
23
  /** Abandon the authorization in progress. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-neartoken",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },