@senguoyun/dsh-arkme 0.1.82 → 0.1.84

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.
Files changed (108) hide show
  1. package/docs/ai-points-implementation.md +43 -0
  2. package/docs/interwoven-compact-summary-regression-2026-09-28.md +35 -0
  3. package/docs/interwoven-original-read-receipt-regression-2026-09-28.md +50 -0
  4. package/docs/personal-detail-consistency-regression-2026-09-28.md +40 -0
  5. package/docs/recognized-speaker-directory-backend-handoff-2026-09-28.md +157 -0
  6. package/docs/recognized-speaker-entry-and-visits.md +47 -0
  7. package/docs/recognized-speaker-presence-delivery.md +51 -0
  8. package/docs/recognized-speaker-sorting.md +30 -0
  9. package/docs/send-to-self-roles-cross-client-api-handoff-2026-09-27.md +9 -0
  10. package/lib/client.js +3358 -1946
  11. package/lib/client.js.map +1 -1
  12. package/lib/harness-model-client.js +168 -38
  13. package/lib/harness-native-selection-client.js +92 -1
  14. package/lib/harness-sidebar-client.js +31 -0
  15. package/lib/index.js +347 -132
  16. package/lib/persistent-extension.js +1 -1
  17. package/lib/{persistent-runtime-DV9Hme-U.js → persistent-runtime-CuKplHIv.js} +607 -303
  18. package/lib/sdk.js +31 -0
  19. package/lib/types/ai-points.d.ts +61 -0
  20. package/lib/types/ai-points.d.ts.map +1 -0
  21. package/lib/types/arkme-service.d.ts +11 -1
  22. package/lib/types/arkme-service.d.ts.map +1 -1
  23. package/lib/types/billing-gateway.d.ts.map +1 -1
  24. package/lib/types/client/ArkmeAccountUsage.d.ts +1 -3
  25. package/lib/types/client/ArkmeAccountUsage.d.ts.map +1 -1
  26. package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
  27. package/lib/types/client/ArkmeBillingSettings.d.ts +3 -2
  28. package/lib/types/client/ArkmeBillingSettings.d.ts.map +1 -1
  29. package/lib/types/client/ArkmeDataManagementSettings.d.ts.map +1 -1
  30. package/lib/types/client/ArkmeDocumentComposerInput.d.ts.map +1 -1
  31. package/lib/types/client/ArkmeEmojiPicker.d.ts.map +1 -1
  32. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts +12 -0
  33. package/lib/types/client/ArkmeInterwovenReadReceipt.d.ts.map +1 -0
  34. package/lib/types/client/ArkmeModelPricing.d.ts +9 -0
  35. package/lib/types/client/ArkmeModelPricing.d.ts.map +1 -0
  36. package/lib/types/client/ArkmeModelSelect.d.ts.map +1 -1
  37. package/lib/types/client/ArkmeNoteDetails.d.ts.map +1 -1
  38. package/lib/types/client/ArkmePointsConsumption.d.ts +5 -0
  39. package/lib/types/client/ArkmePointsConsumption.d.ts.map +1 -0
  40. package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts +6 -2
  41. package/lib/types/client/ArkmeRecognizedSpeakersSurface.d.ts.map +1 -1
  42. package/lib/types/client/ArkmeRecordingSurface.d.ts.map +1 -1
  43. package/lib/types/client/ArkmeRelatedQuickNotes.d.ts.map +1 -1
  44. package/lib/types/client/ArkmeSidebar.d.ts.map +1 -1
  45. package/lib/types/client/ArkoModelMenu.d.ts.map +1 -1
  46. package/lib/types/client/api.d.ts +1 -1
  47. package/lib/types/client/api.d.ts.map +1 -1
  48. package/lib/types/client/interwoven-moments.d.ts.map +1 -1
  49. package/lib/types/client/interwoven-read-receipt-store.d.ts +32 -0
  50. package/lib/types/client/interwoven-read-receipt-store.d.ts.map +1 -0
  51. package/lib/types/client/locales/actions-en.d.ts.map +1 -1
  52. package/lib/types/client/locales/dynamic-en.d.ts.map +1 -1
  53. package/lib/types/client/locales/en.d.ts.map +1 -1
  54. package/lib/types/client/reaction-preview-store.d.ts +1 -0
  55. package/lib/types/client/reaction-preview-store.d.ts.map +1 -1
  56. package/lib/types/client/recognized-speaker-directory.d.ts +36 -0
  57. package/lib/types/client/recognized-speaker-directory.d.ts.map +1 -0
  58. package/lib/types/client/recognized-speaker-order.d.ts +28 -0
  59. package/lib/types/client/recognized-speaker-order.d.ts.map +1 -0
  60. package/lib/types/client/recognized-speaker-tracker.d.ts +33 -0
  61. package/lib/types/client/recognized-speaker-tracker.d.ts.map +1 -0
  62. package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts +12 -0
  63. package/lib/types/client/recordings/RecognizedSpeakerEntry.d.ts.map +1 -0
  64. package/lib/types/client/recordings/SpeakerSelfGuide.d.ts +8 -0
  65. package/lib/types/client/recordings/SpeakerSelfGuide.d.ts.map +1 -0
  66. package/lib/types/client/recordings/recording-speaker-options-store.d.ts.map +1 -1
  67. package/lib/types/client/self-role-presentation.d.ts +6 -1
  68. package/lib/types/client/self-role-presentation.d.ts.map +1 -1
  69. package/lib/types/client/use-personal-extension-parents.d.ts +4 -0
  70. package/lib/types/client/use-personal-extension-parents.d.ts.map +1 -0
  71. package/lib/types/host-api.d.ts.map +1 -1
  72. package/lib/types/index.d.ts.map +1 -1
  73. package/lib/types/managed-ai/adapter.d.ts +2 -1
  74. package/lib/types/managed-ai/adapter.d.ts.map +1 -1
  75. package/lib/types/managed-ai/operation.d.ts +17 -0
  76. package/lib/types/managed-ai/operation.d.ts.map +1 -0
  77. package/lib/types/managed-ai/transport.d.ts +1 -0
  78. package/lib/types/managed-ai/transport.d.ts.map +1 -1
  79. package/lib/types/record-extension-tree.d.ts +2 -0
  80. package/lib/types/record-extension-tree.d.ts.map +1 -1
  81. package/lib/types/sdk/index.d.ts +14 -0
  82. package/lib/types/sdk/index.d.ts.map +1 -1
  83. package/lib/types/services/ai-points-service.d.ts +13 -0
  84. package/lib/types/services/ai-points-service.d.ts.map +1 -0
  85. package/lib/types/services/arko-service.d.ts.map +1 -1
  86. package/lib/types/services/chat-service.d.ts +9 -1
  87. package/lib/types/services/chat-service.d.ts.map +1 -1
  88. package/lib/types/services/interwoven-service.d.ts +3 -1
  89. package/lib/types/services/interwoven-service.d.ts.map +1 -1
  90. package/lib/types/services/recording-service.d.ts +2 -5
  91. package/lib/types/services/recording-service.d.ts.map +1 -1
  92. package/lib/types/services/unmarked-speaker-service.d.ts.map +1 -1
  93. package/lib/types/tools/business/account/ai-points.d.ts +4 -0
  94. package/lib/types/tools/business/account/ai-points.d.ts.map +1 -0
  95. package/lib/types/tools/business/account/index.d.ts.map +1 -1
  96. package/lib/types/tools/business/recordings/index.d.ts +1 -1
  97. package/lib/types/tools/business/recordings/index.d.ts.map +1 -1
  98. package/lib/types/tools/business/recordings/speaker-presence.d.ts +2 -0
  99. package/lib/types/tools/business/recordings/speaker-presence.d.ts.map +1 -0
  100. package/lib/types/tools/ports/profile.d.ts +3 -0
  101. package/lib/types/tools/ports/profile.d.ts.map +1 -1
  102. package/lib/types/tools/ports/recordings.d.ts +4 -0
  103. package/lib/types/tools/ports/recordings.d.ts.map +1 -1
  104. package/lib/types/types.d.ts +33 -8
  105. package/lib/types/types.d.ts.map +1 -1
  106. package/package.json +5 -5
  107. package/lib/types/recording-speaker-presence.d.ts +0 -28
  108. package/lib/types/recording-speaker-presence.d.ts.map +0 -1
@@ -9,6 +9,12 @@ window.__ModuleLoader__.load({
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  Object.fromEntries(`
11
11
  个人世界|Personal world
12
+ 说话人排序|Sort speakers
13
+ 经常出现|Most frequent
14
+ 最近出现|Most recent
15
+ 正在补齐说话人列表,排序仍在更新…|Loading the remaining speakers. Order is still updating…
16
+ 列表尚未完整,当前仅对已加载的说话人排序和搜索。|The list is incomplete. Sorting and search cover loaded speakers only.
17
+ 显示更多说话人|Show more speakers
12
18
  语音通话邀请|Voice call invitation
13
19
  视频通话邀请|Video call invitation
14
20
  公开快记|Public note
@@ -154,7 +160,7 @@ Agent · 内容由 AI 生成,仅供参考|Agent · AI-generated content; verif
154
160
  当前运行的任务预先占用的余额,任务完成后将返还剩余余额。|Credit reserved for running tasks. Unused credit is released when tasks finish.
155
161
  充值|Add credit
156
162
  余额充值|Add credit
157
- 充值后可在 DSH 会话中通过 Arkme 调用 AI 模型|Use prepaid credit to access AI models through Arkme in DSH.
163
+ APP 与 Arkme 3.0 共用积分,充值到账后即可使用|AI points are shared between the app and Arkme 3.0, and available once credited.
158
164
  当前余额|Current balance
159
165
  刷新|Refresh
160
166
  充值套餐|Credit packages
@@ -588,6 +594,7 @@ AI智能体|AI agent
588
594
  群聊名称|Group name
589
595
  最新|Latest
590
596
  部分历史附件暂不可用|Some earlier attachments are unavailable
597
+ 附件暂不可用|Attachment unavailable
591
598
  正在加载编辑记录…|Loading edit history…
592
599
  暂无编辑记录|No edit history
593
600
  重新加载历史附件|Reload earlier attachments
@@ -1631,6 +1638,14 @@ Bot 已移出群聊|Bot removed from the group
1631
1638
  {v0}人|{v0} people
1632
1639
  正在读取群 Bot…|Loading group Bots…
1633
1640
  Bot 列表加载失败,点击重试|Could not load Bots. Click to retry
1641
+ 新识别 {v0} 个|{v0} newly identified
1642
+ 识别我的声音|Identify my voice
1643
+ 你的声纹正在处理中|Your voiceprint is being processed
1644
+ 已录入声纹,暂未在录音中匹配到你|Voiceprint enrolled. No match found in your recordings yet.
1645
+ 还没有标记你的声音|Your voice has not been labeled yet
1646
+ 打开你的录音,点击说话人名称并选择自己;请先试听确认。|Open your recording, listen to confirm, then click the speaker name and select yourself.
1647
+ 从录音中标记我|Label myself in a recording
1648
+ 管理声纹|Manage voiceprint
1634
1649
  `.trim().split("\n").map((line) => {
1635
1650
  const index = line.indexOf("|");
1636
1651
  return [line.slice(0, index), line.slice(index + 1)];
@@ -1897,6 +1912,51 @@ Arkme 用户 {v0}|Arkme user {v0}
1897
1912
  {v0};录音仍保留在本机,可重试或下载|{v0}; recording remains on this device. Retry or download it.
1898
1913
  参与者: {v0}|Participants: {v0}
1899
1914
  说话人 {v0}|Speaker {v0}
1915
+
1916
+ AI 额度|AI allowance
1917
+ 积分|points
1918
+ 赠送积分|Granted points
1919
+ 充值积分|Purchased points
1920
+ 赠送积分到期时间|Grant expires
1921
+ 任务进行中暂占|Reserved by running tasks:
1922
+ 积分,结束后返还未用部分|points; unused points return when the task finishes
1923
+ 赠送 {v0} · 充值 {v1}|Granted {v0} · Purchased {v1}
1924
+ DSH 对话|DSH chat
1925
+ AI 调用|AI usage
1926
+ (赠送)| (Gift)
1927
+ (充值)| (Purchased)
1928
+ (赠送 {v0} · 充值 {v1})| (Gift {v0} · Purchased {v1})
1929
+ 消费记录|Spending history
1930
+ 模型调用|Model usage
1931
+ 附加服务|Additional service
1932
+ 消费月份|Spending month
1933
+ 该月消费|Spent in selected month
1934
+ 该月暂无积分消费|No point spending in selected month
1935
+ 暂时无法读取|Could not load
1936
+ 暂时无法读取消费明细。|Spending details could not be loaded.
1937
+ 输入 Token|Input tokens
1938
+ 输出 Token|Output tokens
1939
+ 缓存命中|Cache hit
1940
+ 缓存未命中|Cache miss
1941
+ 加载失败,已有明细已保留。|Loading failed. Existing entries have been kept.
1942
+ 积分充值|Buy points
1943
+ 可用积分|Available points
1944
+ 预占积分|Reserved points
1945
+ 预占积分说明|About reserved points
1946
+ 当前运行的任务预先占用的积分,任务完成后将返还未用积分。|Running tasks reserve points. Unused points return when the task finishes.
1947
+ 正在加载积分…|Loading points…
1948
+ 积分读取失败,点击重试|Points could not be loaded. Click to retry.
1949
+ 积分加载中…|Loading points…
1950
+ 积分读取失败|Points could not be loaded
1951
+ 积分到账中,到账后会自动刷新可用积分。|Your points are being credited. Available points will refresh automatically.
1952
+ 已到账,正在刷新可用积分|Credited. Refreshing available points…
1953
+ 可用积分已刷新:|Available points refreshed:
1954
+ 积分暂未刷新:|Points have not refreshed:
1955
+ 刷新积分|Refresh points
1956
+ AI 额度 {v0}|AI allowance {v0}
1957
+ AI 额度充值流程|AI point purchase
1958
+ 次调用|calls
1959
+ 按用量扣积分 · 计费说明|Usage-based points · Pricing details
1900
1960
  `.trim().split("\n").map((line) => {
1901
1961
  const p = line.indexOf("|");
1902
1962
  return [line.slice(0, p), line.slice(p + 1)];
@@ -1920,7 +1980,32 @@ Arkme 用户 {v0}|Arkme user {v0}
1920
1980
  const translated = source;
1921
1981
  return values === void 0 ? translated : translated.replace(/\{(\w+)\}/g, (match, key) => Object.prototype.hasOwnProperty.call(values, key) ? String(values[key]) : match);
1922
1982
  }
1923
- const arkmeIntlLocale = () => "zh-CN";
1983
+ //#endregion
1984
+ //#region src/ai-points.ts
1985
+ function pointsUnits(value) {
1986
+ if (!/^(?:0|[1-9]\d*)(?:\.\d{1,7})?$/.test(value)) throw new TypeError("Invalid exact AI points");
1987
+ const [whole = "0", fraction = ""] = value.split(".");
1988
+ const units = BigInt(whole) * 10000000n + BigInt(fraction.padEnd(7, "0"));
1989
+ if (units > 9223372036854775807n) throw new TypeError("AI points exceed accounting range");
1990
+ return units;
1991
+ }
1992
+ /** Display floors only; a rounded label can never overpromise spendable points. */
1993
+ function formatAiPoints(value) {
1994
+ const units = pointsUnits(value);
1995
+ if (units > 0n && units < 100000n) return "< 0.01";
1996
+ const hundredths = units / 100000n;
1997
+ const whole = (hundredths / 100n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1998
+ const fraction = (hundredths % 100n).toString().padStart(2, "0").replace(/0+$/, "");
1999
+ return fraction ? `${whole}.${fraction}` : whole;
2000
+ }
2001
+ /** Existing recharge values retain their nano-CNY meaning: ¥1 = 100 points. */
2002
+ function nanoCnyToPoints(value) {
2003
+ if (!/^(?:0|[1-9]\d*)$/.test(value)) throw new TypeError("Invalid nano-CNY");
2004
+ const units = BigInt(value);
2005
+ const whole = units / 10000000n;
2006
+ const fraction = (units % 10000000n).toString().padStart(7, "0").replace(/0+$/, "");
2007
+ return fraction ? `${whole}.${fraction}` : whole.toString();
2008
+ }
1924
2009
  //#endregion
1925
2010
  //#region src/client/arkme-billing.css?inline
1926
2011
  var arkme_billing_default = ".arkme-billing-modal-host {\n background: none;\n border: 0;\n width: 100%;\n max-width: none;\n height: 100%;\n max-height: none;\n margin: 0;\n padding: 0;\n position: fixed;\n inset: 0;\n}\n\n.arkme-billing-modal-host::backdrop {\n background: none;\n}\n\n.arkme-billing-backdrop {\n z-index: 120;\n backdrop-filter: blur(3px);\n background: #181b223d;\n place-items: center;\n padding: 28px;\n display: grid;\n position: fixed;\n inset: 0;\n}\n\n.arkme-billing-recharge-dialog, .arkme-billing-payment-dialog {\n color: #20232c;\n background: #fff;\n border: 1px solid #dedfe3;\n border-radius: 20px;\n width: min(620px, 100%);\n max-height: min(720px, 100vh - 56px);\n overflow-y: auto;\n box-shadow: 0 24px 72px #191c232e;\n}\n\n.arkme-billing-payment-dialog {\n width: min(420px, 100%);\n}\n\n.arkme-billing-dialog-header {\n border-bottom: 1px solid #ececef;\n justify-content: space-between;\n align-items: flex-start;\n gap: 18px;\n min-height: 78px;\n padding: 20px 22px 16px;\n display: flex;\n}\n\n.arkme-billing-dialog-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n line-height: 25px;\n}\n\n.arkme-billing-dialog-header p {\n overflow-wrap: anywhere;\n color: #8a8e96;\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-dialog-header > button {\n color: #777c85;\n width: 32px;\n height: 32px;\n font: inherit;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 9px;\n flex: none;\n place-items: center;\n font-size: 22px;\n display: grid;\n}\n\n.arkme-billing-dialog-header > button:hover {\n color: #20232c;\n background: #f3f3f5;\n}\n\n.arkme-billing-dialog-body {\n padding: 18px 22px 22px;\n}\n\n.arkme-billing-dialog-balance {\n border-bottom: 1px solid #ececef;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n column-gap: 12px;\n min-height: 48px;\n padding: 0 2px 16px;\n display: grid;\n}\n\n.arkme-billing-dialog-balance > span {\n color: #8a8e96;\n grid-column: 1;\n font-size: 11px;\n line-height: 16px;\n}\n\n.arkme-billing-dialog-balance > strong {\n grid-column: 1;\n font-size: 22px;\n font-weight: 600;\n line-height: 28px;\n}\n\n.arkme-billing-dialog-balance > button, .arkme-billing-error > button {\n color: #626772;\n height: 30px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 9px;\n grid-area: 1 / 2 / span 2;\n padding: 0 12px;\n font-size: 11px;\n}\n\n.arkme-billing-products-section, .arkme-billing-payment-section {\n padding-top: 17px;\n}\n\n.arkme-billing-products-section h3, .arkme-billing-payment-section h3 {\n color: #747984;\n margin: 0 0 11px;\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n\n.arkme-billing-product-grid {\n width: 100%;\n}\n\n.arkme-billing-product-grid > button {\n color: #20232c;\n min-width: 0;\n min-height: 62px;\n font: inherit;\n text-align: left;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 11px;\n align-content: center;\n gap: 4px;\n padding: 9px 11px;\n display: grid;\n}\n\n.arkme-billing-product-grid > button:hover {\n background: #f8f8f9;\n border-color: #cfd2d8;\n}\n\n.arkme-billing-product-grid > button.is-selected {\n border-color: #75839e;\n box-shadow: 0 0 0 1px #75839e;\n}\n\n.arkme-billing-product-grid > button > span {\n white-space: nowrap;\n text-overflow: ellipsis;\n font-size: 12px;\n font-weight: 500;\n line-height: 17px;\n overflow: hidden;\n}\n\n.arkme-billing-product-grid > button > strong {\n font-size: 14px;\n font-weight: 600;\n line-height: 19px;\n}\n\n.arkme-billing-payment-actions {\n flex-wrap: wrap;\n gap: 10px;\n display: flex;\n}\n\n.arkme-billing-payment-actions > button {\n color: #333842;\n min-width: 154px;\n height: 38px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 10px;\n justify-content: center;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.arkme-billing-payment-actions > button:hover {\n background: #f7f7f8;\n border-color: #cfd3da;\n}\n\n.arkme-billing-payment-actions > button:disabled, .arkme-billing-product-grid > button:disabled {\n opacity: .48;\n cursor: default;\n}\n\n.arkme-billing-platform-icon {\n flex: none;\n width: 18px;\n height: 18px;\n}\n\n.arkme-billing-platform-icon.is-alipay {\n color: #1677ff;\n}\n\n.arkme-billing-platform-icon.is-wechat {\n color: #07c160;\n}\n\n.arkme-billing-state {\n color: #858992;\n margin: 12px 0 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-error {\n color: #b54841;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n margin-top: 10px;\n font-size: 12px;\n line-height: 18px;\n display: flex;\n}\n\n.arkme-billing-error.is-purchase {\n justify-content: flex-start;\n}\n\n.arkme-billing-payment-content {\n text-align: center;\n justify-items: center;\n gap: 10px;\n padding: 28px 24px 18px;\n display: grid;\n}\n\n.arkme-billing-payment-content > .arkme-billing-platform-icon {\n width: 38px;\n height: 38px;\n margin-bottom: 4px;\n}\n\n.arkme-billing-payment-content > img {\n border-radius: 10px;\n width: 210px;\n height: 210px;\n}\n\n.arkme-billing-payment-content > strong {\n font-size: 14px;\n font-weight: 600;\n line-height: 21px;\n}\n\n.arkme-billing-payment-content > p {\n color: #858992;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.arkme-billing-payment-content.is-paid > strong {\n color: #16794f;\n font-size: 18px;\n line-height: 25px;\n}\n\n.arkme-billing-payment-content.is-paid > .arkme-billing-error {\n justify-content: center;\n}\n\n.arkme-billing-payment-content.is-crediting > strong {\n color: #335f9e;\n}\n\n.arkme-billing-dialog-actions {\n flex-wrap: wrap;\n justify-content: center;\n gap: 9px;\n padding: 0 22px 20px;\n display: flex;\n}\n\n.arkme-billing-dialog-actions > button, .arkme-billing-primary-action {\n color: #3c424d;\n height: 34px;\n font: inherit;\n cursor: pointer;\n background: #fff;\n border: 1px solid #dfe1e5;\n border-radius: 9px;\n padding: 0 14px;\n font-size: 12px;\n}\n\n.arkme-billing-dialog-actions > .arkme-billing-primary-action, .arkme-billing-payment-content > .arkme-billing-primary-action {\n color: #fff;\n background: #20232d;\n border-color: #20232d;\n}\n";
@@ -2154,11 +2239,42 @@ Arkme 用户 {v0}|Arkme user {v0}
2154
2239
  this.route = route;
2155
2240
  this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
2156
2241
  }
2242
+ /** Account-scoped marked speaker candidates; refs can be used only with this provider/account. */
2243
+ async recordingSpeakerCandidates(signal) {
2244
+ await this.requireSpeakerPresence(signal);
2245
+ return await this.call("recordings.speaker.options", {}, signal);
2246
+ }
2247
+ async recordingSpeakerPresence(signal) {
2248
+ await this.requireSpeakerPresence(signal);
2249
+ return await this.call("recordings.speaker.presence", {}, signal);
2250
+ }
2251
+ async recordingSpeakerMembers(speakerRef, options = {}) {
2252
+ if (speakerRef.trim() === "") throw new TypeError("speakerRef is required");
2253
+ await this.requireSpeakerPresence(options.signal);
2254
+ return await this.call("recordings.speaker.members", {
2255
+ speakerRef,
2256
+ ...options.expectedVersion === void 0 ? {} : { expectedVersion: options.expectedVersion }
2257
+ }, options.signal);
2258
+ }
2259
+ async requireSpeakerPresence(signal) {
2260
+ if ((await this.capabilities(signal)).features.speakerPresence !== true) throw new Error("当前 Provider 不支持全历史说话人统计");
2261
+ }
2157
2262
  async capabilities(signal) {
2158
2263
  const capabilities = await this.call("provider.capabilities", void 0, signal);
2159
2264
  if (capabilities.contractVersion !== 1) throw new Error(`Unsupported Arkme provider contract version ${String(capabilities.contractVersion)}`);
2160
2265
  return capabilities;
2161
2266
  }
2267
+ async aiPointsAccount(expectedAccountScope, signal) {
2268
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
2269
+ return this.call("account.points.query", { expectedAccountScope }, signal);
2270
+ }
2271
+ async aiPointsConsumption(expectedAccountScope, query, signal) {
2272
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
2273
+ return this.call("account.points.consumption", {
2274
+ expectedAccountScope,
2275
+ ...query
2276
+ }, signal);
2277
+ }
2162
2278
  async state(signal) {
2163
2279
  return await this.call("provider.state", void 0, signal);
2164
2280
  }
@@ -6355,18 +6471,14 @@ Arkme 用户 {v0}|Arkme user {v0}
6355
6471
  function formatArkmeBillingPrice(priceMinor, _currency) {
6356
6472
  return `¥${(priceMinor / 100).toFixed(2)}`;
6357
6473
  }
6358
- function formatArkmeNanoCny(value) {
6359
- if (!/^(?:0|[1-9]\d*)$/.test(value)) return "—";
6360
- const roundedCents = (BigInt(value) + 5000000n) / 10000000n;
6361
- const whole = roundedCents / 100n;
6362
- const fraction = (roundedCents % 100n).toString().padStart(2, "0");
6363
- return `¥${whole.toLocaleString(arkmeIntlLocale())}.${fraction}`;
6474
+ function formatArkmePoints(value) {
6475
+ return `${formatAiPoints(nanoCnyToPoints(value))} ${tr("积分")}`;
6364
6476
  }
6365
6477
  function errorMessage(error) {
6366
6478
  return error instanceof Error && error.message.trim() !== "" ? error.message : String(error);
6367
6479
  }
6368
6480
  function ArkmeBalanceSettingsRowView(props) {
6369
- const description = props.quotaState.kind === "ready" ? formatArkmeNanoCny(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? "正在加载余额…" : "余额读取失败,点击重试";
6481
+ const description = props.quotaState.kind === "ready" ? formatArkmePoints(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? "正在加载积分…" : "积分读取失败,点击重试";
6370
6482
  const reservedNanoCny = props.quotaState.kind === "ready" ? props.quotaState.quota.reservedNanoCny : void 0;
6371
6483
  const showReserved = reservedNanoCny !== void 0 && /^(?:0|[1-9]\d*)$/.test(reservedNanoCny) && BigInt(reservedNanoCny) > 0n;
6372
6484
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -6375,7 +6487,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6375
6487
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6376
6488
  type: "button",
6377
6489
  className: "arkme-redesign-balance-main",
6378
- "aria-label": tr("账户余额 {v0}", { v0: description }),
6490
+ "aria-label": tr("AI 额度 {v0}", { v0: description }),
6379
6491
  onClick: props.onOpen,
6380
6492
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: description })
6381
6493
  }),
@@ -6384,21 +6496,21 @@ Arkme 用户 {v0}|Arkme user {v0}
6384
6496
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6385
6497
  className: "arkme-redesign-reserved-title",
6386
6498
  children: [
6387
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr("预占余额") }),
6499
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr("预占积分") }),
6388
6500
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6389
6501
  className: "arkme-redesign-reserved-help",
6390
6502
  tabIndex: 0,
6391
- "aria-label": tr("预占余额说明"),
6503
+ "aria-label": tr("预占积分说明"),
6392
6504
  "aria-describedby": "arkme-reserved-balance-tooltip",
6393
6505
  children: "?"
6394
6506
  }),
6395
6507
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6396
6508
  id: "arkme-reserved-balance-tooltip",
6397
6509
  role: "tooltip",
6398
- children: tr("当前运行的任务预先占用的余额,任务完成后将返还剩余余额。")
6510
+ children: tr("当前运行的任务预先占用的积分,任务完成后将返还未用积分。")
6399
6511
  })
6400
6512
  ]
6401
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: formatArkmeNanoCny(reservedNanoCny) })]
6513
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: formatArkmePoints(reservedNanoCny) })]
6402
6514
  }),
6403
6515
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6404
6516
  type: "button",
@@ -6445,11 +6557,11 @@ Arkme 用户 {v0}|Arkme user {v0}
6445
6557
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6446
6558
  role: "dialog",
6447
6559
  "aria-modal": "true",
6448
- "aria-label": tr("余额充值"),
6560
+ "aria-label": tr("积分充值"),
6449
6561
  className: "arkme-billing-recharge-dialog",
6450
6562
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
6451
6563
  className: "arkme-billing-dialog-header",
6452
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: tr("余额充值") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("充值后可在 DSH 会话中通过 Arkme 调用 AI 模型") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6564
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: tr("积分充值") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("APP 与 Arkme 3.0 共用积分,充值到账后即可使用") })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6453
6565
  type: "button",
6454
6566
  "aria-label": tr("关闭充值弹窗"),
6455
6567
  onClick: props.onClose,
@@ -6461,8 +6573,8 @@ Arkme 用户 {v0}|Arkme user {v0}
6461
6573
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6462
6574
  className: "arkme-billing-dialog-balance",
6463
6575
  children: [
6464
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr("当前余额") }),
6465
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.quotaState.kind === "ready" ? formatArkmeNanoCny(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? tr("正在加载…") : "读取失败" }),
6576
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tr("可用积分") }),
6577
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.quotaState.kind === "ready" ? formatArkmePoints(props.quotaState.quota.availableNanoCny) : props.quotaState.kind === "loading" ? tr("正在加载…") : "读取失败" }),
6466
6578
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6467
6579
  type: "button",
6468
6580
  onClick: props.onRefreshQuota,
@@ -6506,10 +6618,10 @@ Arkme 用户 {v0}|Arkme user {v0}
6506
6618
  role: "radio",
6507
6619
  "aria-checked": product.productId === props.selectedProductId,
6508
6620
  className: product.productId === props.selectedProductId ? "is-selected" : "",
6509
- title: product.title,
6621
+ title: `${formatArkmePoints(product.creditNanoCny)} · ${formatArkmeBillingPrice(product.priceMinor, product.currency)}`,
6510
6622
  disabled: creating,
6511
6623
  onClick: () => props.onSelectProduct(product.productId),
6512
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: product.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatArkmeBillingPrice(product.priceMinor, product.currency) })]
6624
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatArkmePoints(product.creditNanoCny) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatArkmeBillingPrice(product.priceMinor, product.currency) })]
6513
6625
  }, product.productId))
6514
6626
  })
6515
6627
  ]
@@ -6552,7 +6664,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6552
6664
  const paymentAction = screen === "pending" ? props.order.paymentAction : void 0;
6553
6665
  const qrDataUrl = paymentAction?.type === "display_qr" ? billingQrDataUrl(paymentAction.qrContent) : "";
6554
6666
  const openUrl = paymentAction?.type === "open_url" ? paymentAction.url : "";
6555
- const paidAmount = formatArkmeBillingPrice(props.order.amountMinor, props.order.currency);
6667
+ const paidAmount = formatArkmePoints(props.order.creditNanoCny);
6556
6668
  const statusProblem = props.statusError !== "" && (screen === "pending" || screen === "crediting");
6557
6669
  const title = statusProblem ? "正在确认支付" : screen === "crediting" ? "支付已确认" : screen === "pending" ? "完成支付" : screen === "paid" ? "支付成功" : screen === "expired" ? "支付未完成" : "订单状态";
6558
6670
  (0, react.useEffect)(() => {
@@ -6637,19 +6749,19 @@ Arkme 用户 {v0}|Arkme user {v0}
6637
6749
  " ",
6638
6750
  countdownText(props.order.expiresAtMillis - props.nowMillis)
6639
6751
  ] }),
6640
- !statusProblem && screen === "crediting" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr("支付已确认,无需重复支付") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("余额到账中,到账后会自动刷新当前余额。") })] }),
6752
+ !statusProblem && screen === "crediting" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr("支付已确认,无需重复支付") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("积分到账中,到账后会自动刷新可用积分。") })] }),
6641
6753
  screen === "paid" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6642
6754
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
6643
6755
  paidAmount,
6644
6756
  " ",
6645
6757
  tr("已到账")
6646
6758
  ] }),
6647
- props.quotaState.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("已到账,正在刷新当前余额") }),
6648
- props.quotaState.kind === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [tr("当前余额已刷新:"), formatArkmeNanoCny(props.quotaState.quota.availableNanoCny)] }),
6759
+ props.quotaState.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: tr("已到账,正在刷新可用积分") }),
6760
+ props.quotaState.kind === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [tr("可用积分已刷新:"), formatArkmePoints(props.quotaState.quota.availableNanoCny)] }),
6649
6761
  props.quotaState.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
6650
6762
  className: "arkme-billing-error",
6651
6763
  role: "alert",
6652
- children: [tr("余额暂未刷新:"), props.quotaState.message]
6764
+ children: [tr("积分暂未刷新:"), props.quotaState.message]
6653
6765
  })
6654
6766
  ] }),
6655
6767
  screen === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: tr("支付凭据已过期,请重新生成。") }),
@@ -6674,7 +6786,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6674
6786
  screen === "paid" && props.quotaState.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6675
6787
  type: "button",
6676
6788
  onClick: props.onRefreshQuota,
6677
- children: tr("刷新余额")
6789
+ children: tr("刷新积分")
6678
6790
  }),
6679
6791
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6680
6792
  type: "button",
@@ -6715,7 +6827,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6715
6827
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
6716
6828
  ref,
6717
6829
  className: "arkme-billing-modal-host",
6718
- "aria-label": tr("AI 余额充值流程"),
6830
+ "aria-label": tr("AI 额度充值流程"),
6719
6831
  onCancel: (event) => {
6720
6832
  event.preventDefault();
6721
6833
  event.stopPropagation();
@@ -6724,7 +6836,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6724
6836
  children
6725
6837
  });
6726
6838
  }
6727
- function ArkmeBillingSettings({ active = true, renderTrigger, modal = false } = {}) {
6839
+ function ArkmeBillingSettings({ active = true, renderTrigger, modal = false, onCreditsChanged } = {}) {
6728
6840
  useArkmeLocale();
6729
6841
  const [open, setOpen] = (0, react.useState)(false);
6730
6842
  const [quotaState, setQuotaState] = (0, react.useState)({ kind: "loading" });
@@ -6833,7 +6945,10 @@ Arkme 用户 {v0}|Arkme user {v0}
6833
6945
  setOrderStatusRetryable(false);
6834
6946
  setOrderStatusRetryInMillis(void 0);
6835
6947
  checkoutAttemptRef.current = checkoutAttemptAfterOrder(checkoutAttemptRef.current, latest.status);
6836
- if (latest.status === "paid") loadQuota();
6948
+ if (latest.status === "paid") {
6949
+ loadQuota();
6950
+ onCreditsChanged?.();
6951
+ }
6837
6952
  },
6838
6953
  onError: (error, retry) => {
6839
6954
  setOrderStatusError(errorMessage(error));
@@ -6847,7 +6962,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6847
6962
  });
6848
6963
  pollerRef.current = poller;
6849
6964
  poller.start(nextOrder.orderId, nextOrder.expiresAtMillis, nextOrder.pollIntervalMillis, nextOrder.status);
6850
- }, [loadQuota]);
6965
+ }, [loadQuota, onCreditsChanged]);
6851
6966
  const createPayment = (0, react.useCallback)(async (paymentMethod, forceNew = false) => {
6852
6967
  if (productsState.kind !== "ready") return;
6853
6968
  const product = productsState.products.find((item) => item.enabled && item.productId === selectedProductIdRef.current);
@@ -6865,8 +6980,10 @@ Arkme 用户 {v0}|Arkme user {v0}
6865
6980
  setNowMillis(Date.now());
6866
6981
  activateBillingPaymentAction(nextOrder.paymentAction, openPaymentUrl);
6867
6982
  setOrder(nextOrder);
6868
- if (nextOrder.status === "paid") loadQuota();
6869
- else startPolling(nextOrder);
6983
+ if (nextOrder.status === "paid") {
6984
+ loadQuota();
6985
+ onCreditsChanged?.();
6986
+ } else startPolling(nextOrder);
6870
6987
  } catch (error) {
6871
6988
  setPurchaseError(errorMessage(error));
6872
6989
  } finally {
@@ -6874,6 +6991,7 @@ Arkme 用户 {v0}|Arkme user {v0}
6874
6991
  }
6875
6992
  }, [
6876
6993
  loadQuota,
6994
+ onCreditsChanged,
6877
6995
  openPaymentUrl,
6878
6996
  productsState,
6879
6997
  startPolling
@@ -6998,8 +7116,19 @@ Arkme 用户 {v0}|Arkme user {v0}
6998
7116
  ] });
6999
7117
  }
7000
7118
  //#endregion
7119
+ //#region src/client/ArkmeModelPricing.tsx
7120
+ /** One disclosure per menu keeps pricing available without repeating it in every row. */
7121
+ function ArkmeModelPricing({ models }) {
7122
+ const pricedModels = models.filter((model) => model.description);
7123
+ if (pricedModels.length === 0) return null;
7124
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
7125
+ className: "arkme-model-price",
7126
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: tr("按用量扣积分 · 计费说明") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", { children: pricedModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: model.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: model.description })] }, model.id)) })]
7127
+ });
7128
+ }
7129
+ //#endregion
7001
7130
  //#region src/client/arkme-model-select.css?inline
7002
- var arkme_model_select_default = ".arkme-model-select {\n min-width: 0;\n font-family: inherit;\n position: relative;\n}\n\n.arkme-model-select button {\n font: inherit;\n cursor: pointer;\n}\n\n.arkme-model-select button:disabled {\n opacity: .5;\n cursor: default;\n}\n\n.arkme-model-select button:focus-visible {\n outline-offset: -2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-trigger {\n max-width: min(360px, 45vw);\n height: 28px;\n color: var(--dsw-alias-label-secondary, #626772);\n background: none;\n border: 0;\n border-radius: 14px;\n align-items: center;\n gap: 5px;\n padding: 0 8px;\n display: flex;\n font-size: 13px !important;\n}\n\n.arkme-model-trigger > span:first-child {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.arkme-model-trigger small {\n flex-shrink: 0;\n}\n\n.arkme-model-menu {\n z-index: 30;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n background: var(--dsw-specific-menu, #fff);\n width: max-content;\n min-width: min(280px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(400px, 100vh - 96px);\n color: var(--dsw-alias-label-primary, #20232c);\n border-radius: 12px;\n padding: 5px;\n position: absolute;\n bottom: calc(100% + 8px);\n right: 0;\n overflow-y: auto;\n box-shadow: 0 8px 30px #0002;\n}\n\n.arkme-model-group-heading {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 7px 9px 4px;\n font-size: 12px;\n display: flex;\n}\n\n.arkme-model-balance-actions {\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n.arkme-model-balance-actions button {\n color: #3478e5;\n white-space: nowrap;\n background: none;\n border: 0;\n padding: 2px 0;\n}\n\n.arkme-model-balance-actions button:hover {\n text-decoration: underline;\n}\n\n.arkme-model-option {\n width: 100%;\n min-height: 38px;\n color: inherit;\n text-align: left;\n background: none;\n border: 0;\n border-radius: 8px;\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 8px 10px;\n display: flex;\n font-size: 14px !important;\n}\n\n.arkme-model-option:hover, .arkme-model-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover, #f3f4f6);\n}\n\n.arkme-model-option > span:first-child {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n.arkme-model-option small {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n font-size: 12px;\n display: block;\n}\n\n.arkme-model-status, .arkme-model-error {\n padding: 8px 10px;\n font-size: 12px;\n}\n\n.arkme-model-error {\n color: var(--dsw-alias-state-error-primary, #b54841);\n}\n\n.arkme-model-error button {\n color: inherit;\n background: none;\n border: 0;\n text-decoration: underline;\n}\n";
7131
+ var arkme_model_select_default = ".arkme-model-select {\n min-width: 0;\n font-family: inherit;\n position: relative;\n}\n\n.arkme-model-select button {\n font: inherit;\n cursor: pointer;\n}\n\n.arkme-model-select button:disabled {\n opacity: .5;\n cursor: default;\n}\n\n.arkme-model-select button:focus-visible {\n outline-offset: -2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-trigger {\n max-width: min(360px, 45vw);\n height: 28px;\n color: var(--dsw-alias-label-secondary, #626772);\n background: none;\n border: 0;\n border-radius: 14px;\n align-items: center;\n gap: 5px;\n padding: 0 8px;\n display: flex;\n font-size: 13px !important;\n}\n\n.arkme-model-trigger > span:first-child {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.arkme-model-trigger small {\n flex-shrink: 0;\n}\n\n.arkme-model-menu {\n z-index: 30;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n background: var(--dsw-specific-menu, #fff);\n width: max-content;\n min-width: min(280px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(400px, 100vh - 96px);\n color: var(--dsw-alias-label-primary, #20232c);\n border-radius: 12px;\n padding: 5px;\n position: absolute;\n bottom: calc(100% + 8px);\n right: 0;\n overflow-y: auto;\n box-shadow: 0 8px 30px #0002;\n}\n\n.arkme-model-group-heading {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 7px 9px 4px;\n font-size: 12px;\n display: flex;\n}\n\n.arkme-model-balance-actions {\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n.arkme-model-balance-actions button {\n color: #3478e5;\n white-space: nowrap;\n background: none;\n border: 0;\n padding: 2px 0;\n}\n\n.arkme-model-balance-actions button:hover {\n text-decoration: underline;\n}\n\n.arkme-model-option {\n width: 100%;\n min-height: 38px;\n color: inherit;\n text-align: left;\n background: none;\n border: 0;\n border-radius: 8px;\n justify-content: space-between;\n align-items: center;\n gap: 18px;\n padding: 8px 10px;\n display: flex;\n font-size: 14px !important;\n}\n\n.arkme-model-option:hover, .arkme-model-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover, #f3f4f6);\n}\n\n.arkme-model-option > span:first-child {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n.arkme-model-option small {\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n font-size: 12px;\n display: block;\n}\n\n.arkme-model-status, .arkme-model-error {\n padding: 8px 10px;\n font-size: 12px;\n}\n\n.arkme-model-error {\n color: var(--dsw-alias-state-error-primary, #b54841);\n}\n\n.arkme-model-error button {\n color: inherit;\n background: none;\n border: 0;\n text-decoration: underline;\n}\n\n.arkme-model-price {\n border-top: 1px solid var(--dsw-alias-border-inverted, #e8e8eb);\n color: var(--dsw-alias-label-tertiary, #8a8e96);\n margin-top: 4px;\n padding: 10px;\n font-size: 12px;\n}\n\n.arkme-model-price summary {\n cursor: pointer;\n}\n\n.arkme-model-price summary:focus-visible {\n outline-offset: 2px;\n outline: 2px solid #3578e5;\n}\n\n.arkme-model-price dl {\n overflow-wrap: anywhere;\n margin: 0;\n line-height: 1.6;\n}\n\n.arkme-model-price dl > div {\n margin-top: 10px;\n}\n\n.arkme-model-price dt {\n color: var(--dsw-alias-label-primary, #20232c);\n}\n\n.arkme-model-price dd {\n margin: 2px 0 0;\n}\n";
7003
7132
  //#endregion
7004
7133
  //#region src/client/ArkmeModelSelect.tsx
7005
7134
  function ArkmeModelSelect({ directory, locked, available }) {
@@ -7052,7 +7181,7 @@ Arkme 用户 {v0}|Arkme user {v0}
7052
7181
  "Home",
7053
7182
  "End"
7054
7183
  ].includes(event.key)) return;
7055
- const items = [...root.current?.querySelectorAll("[role=\"menu\"] button:not(:disabled)") ?? []];
7184
+ const items = [...root.current?.querySelectorAll("[role=\"menu\"] button:not(:disabled), [role=\"menu\"] summary") ?? []];
7056
7185
  if (items.length === 0) return;
7057
7186
  event.preventDefault();
7058
7187
  const current = items.indexOf(document.activeElement);
@@ -7159,7 +7288,7 @@ Arkme 用户 {v0}|Arkme user {v0}
7159
7288
  id: `${id}-${provider.id}`,
7160
7289
  children: [provider.id === "arkme-managed" ? "Arkme" : provider.name, provider.id === "arkme-managed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7161
7290
  "aria-live": "polite",
7162
- children: [" · ", quotaState.kind === "ready" ? formatArkmeNanoCny(quotaState.quota.availableNanoCny) : quotaState.kind === "loading" ? "余额加载中…" : "余额读取失败"]
7291
+ children: [" · ", quotaState.kind === "ready" ? formatArkmePoints(quotaState.quota.availableNanoCny) : quotaState.kind === "loading" ? "积分加载中…" : "积分读取失败"]
7163
7292
  })]
7164
7293
  }), provider.id === "arkme-managed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7165
7294
  className: "arkme-model-balance-actions",
@@ -7178,7 +7307,7 @@ Arkme 用户 {v0}|Arkme user {v0}
7178
7307
  })]
7179
7308
  }), provider.models.map((item) => {
7180
7309
  const selected = state.current?.provider === provider.id && state.current.model === item.id;
7181
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7310
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7182
7311
  type: "button",
7183
7312
  role: "menuitemradio",
7184
7313
  className: "arkme-model-option",
@@ -7188,13 +7317,14 @@ Arkme 用户 {v0}|Arkme user {v0}
7188
7317
  provider: provider.id,
7189
7318
  model: item.id
7190
7319
  }),
7191
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [item.name, item.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: item.description })] }), selected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7320
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [item.name, provider.id !== "arkme-managed" && item.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: item.description })] }), selected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7192
7321
  "aria-hidden": true,
7193
7322
  children: "✓"
7194
7323
  })]
7195
- }, item.id);
7324
+ }) }, item.id);
7196
7325
  })]
7197
7326
  }, provider.id)),
7327
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeModelPricing, { models: state.groups.filter((provider) => provider.id === "arkme-managed").flatMap((provider) => provider.models) }),
7198
7328
  state.status === "ready" && state.groups.every((item) => item.models.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7199
7329
  className: "arkme-model-status",
7200
7330
  children: tr("暂无可用模型")
@@ -274,11 +274,42 @@ window.__ModuleLoader__.load({
274
274
  this.route = route;
275
275
  this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
276
276
  }
277
+ /** Account-scoped marked speaker candidates; refs can be used only with this provider/account. */
278
+ async recordingSpeakerCandidates(signal) {
279
+ await this.requireSpeakerPresence(signal);
280
+ return await this.call("recordings.speaker.options", {}, signal);
281
+ }
282
+ async recordingSpeakerPresence(signal) {
283
+ await this.requireSpeakerPresence(signal);
284
+ return await this.call("recordings.speaker.presence", {}, signal);
285
+ }
286
+ async recordingSpeakerMembers(speakerRef, options = {}) {
287
+ if (speakerRef.trim() === "") throw new TypeError("speakerRef is required");
288
+ await this.requireSpeakerPresence(options.signal);
289
+ return await this.call("recordings.speaker.members", {
290
+ speakerRef,
291
+ ...options.expectedVersion === void 0 ? {} : { expectedVersion: options.expectedVersion }
292
+ }, options.signal);
293
+ }
294
+ async requireSpeakerPresence(signal) {
295
+ if ((await this.capabilities(signal)).features.speakerPresence !== true) throw new Error("当前 Provider 不支持全历史说话人统计");
296
+ }
277
297
  async capabilities(signal) {
278
298
  const capabilities = await this.call("provider.capabilities", void 0, signal);
279
299
  if (capabilities.contractVersion !== 1) throw new Error(`Unsupported Arkme provider contract version ${String(capabilities.contractVersion)}`);
280
300
  return capabilities;
281
301
  }
302
+ async aiPointsAccount(expectedAccountScope, signal) {
303
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
304
+ return this.call("account.points.query", { expectedAccountScope }, signal);
305
+ }
306
+ async aiPointsConsumption(expectedAccountScope, query, signal) {
307
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
308
+ return this.call("account.points.consumption", {
309
+ expectedAccountScope,
310
+ ...query
311
+ }, signal);
312
+ }
282
313
  async state(signal) {
283
314
  return await this.call("provider.state", void 0, signal);
284
315
  }
@@ -2408,6 +2439,12 @@ window.__ModuleLoader__.load({
2408
2439
  }
2409
2440
  Object.fromEntries(`
2410
2441
  个人世界|Personal world
2442
+ 说话人排序|Sort speakers
2443
+ 经常出现|Most frequent
2444
+ 最近出现|Most recent
2445
+ 正在补齐说话人列表,排序仍在更新…|Loading the remaining speakers. Order is still updating…
2446
+ 列表尚未完整,当前仅对已加载的说话人排序和搜索。|The list is incomplete. Sorting and search cover loaded speakers only.
2447
+ 显示更多说话人|Show more speakers
2411
2448
  语音通话邀请|Voice call invitation
2412
2449
  视频通话邀请|Video call invitation
2413
2450
  公开快记|Public note
@@ -2553,7 +2590,7 @@ Agent · 内容由 AI 生成,仅供参考|Agent · AI-generated content; verif
2553
2590
  当前运行的任务预先占用的余额,任务完成后将返还剩余余额。|Credit reserved for running tasks. Unused credit is released when tasks finish.
2554
2591
  充值|Add credit
2555
2592
  余额充值|Add credit
2556
- 充值后可在 DSH 会话中通过 Arkme 调用 AI 模型|Use prepaid credit to access AI models through Arkme in DSH.
2593
+ APP 与 Arkme 3.0 共用积分,充值到账后即可使用|AI points are shared between the app and Arkme 3.0, and available once credited.
2557
2594
  当前余额|Current balance
2558
2595
  刷新|Refresh
2559
2596
  充值套餐|Credit packages
@@ -2987,6 +3024,7 @@ AI智能体|AI agent
2987
3024
  群聊名称|Group name
2988
3025
  最新|Latest
2989
3026
  部分历史附件暂不可用|Some earlier attachments are unavailable
3027
+ 附件暂不可用|Attachment unavailable
2990
3028
  正在加载编辑记录…|Loading edit history…
2991
3029
  暂无编辑记录|No edit history
2992
3030
  重新加载历史附件|Reload earlier attachments
@@ -4030,6 +4068,14 @@ Bot 已移出群聊|Bot removed from the group
4030
4068
  {v0}人|{v0} people
4031
4069
  正在读取群 Bot…|Loading group Bots…
4032
4070
  Bot 列表加载失败,点击重试|Could not load Bots. Click to retry
4071
+ 新识别 {v0} 个|{v0} newly identified
4072
+ 识别我的声音|Identify my voice
4073
+ 你的声纹正在处理中|Your voiceprint is being processed
4074
+ 已录入声纹,暂未在录音中匹配到你|Voiceprint enrolled. No match found in your recordings yet.
4075
+ 还没有标记你的声音|Your voice has not been labeled yet
4076
+ 打开你的录音,点击说话人名称并选择自己;请先试听确认。|Open your recording, listen to confirm, then click the speaker name and select yourself.
4077
+ 从录音中标记我|Label myself in a recording
4078
+ 管理声纹|Manage voiceprint
4033
4079
  `.trim().split("\n").map((line) => {
4034
4080
  const index = line.indexOf("|");
4035
4081
  return [line.slice(0, index), line.slice(index + 1)];
@@ -4296,6 +4342,51 @@ Arkme 用户 {v0}|Arkme user {v0}
4296
4342
  {v0};录音仍保留在本机,可重试或下载|{v0}; recording remains on this device. Retry or download it.
4297
4343
  参与者: {v0}|Participants: {v0}
4298
4344
  说话人 {v0}|Speaker {v0}
4345
+
4346
+ AI 额度|AI allowance
4347
+ 积分|points
4348
+ 赠送积分|Granted points
4349
+ 充值积分|Purchased points
4350
+ 赠送积分到期时间|Grant expires
4351
+ 任务进行中暂占|Reserved by running tasks:
4352
+ 积分,结束后返还未用部分|points; unused points return when the task finishes
4353
+ 赠送 {v0} · 充值 {v1}|Granted {v0} · Purchased {v1}
4354
+ DSH 对话|DSH chat
4355
+ AI 调用|AI usage
4356
+ (赠送)| (Gift)
4357
+ (充值)| (Purchased)
4358
+ (赠送 {v0} · 充值 {v1})| (Gift {v0} · Purchased {v1})
4359
+ 消费记录|Spending history
4360
+ 模型调用|Model usage
4361
+ 附加服务|Additional service
4362
+ 消费月份|Spending month
4363
+ 该月消费|Spent in selected month
4364
+ 该月暂无积分消费|No point spending in selected month
4365
+ 暂时无法读取|Could not load
4366
+ 暂时无法读取消费明细。|Spending details could not be loaded.
4367
+ 输入 Token|Input tokens
4368
+ 输出 Token|Output tokens
4369
+ 缓存命中|Cache hit
4370
+ 缓存未命中|Cache miss
4371
+ 加载失败,已有明细已保留。|Loading failed. Existing entries have been kept.
4372
+ 积分充值|Buy points
4373
+ 可用积分|Available points
4374
+ 预占积分|Reserved points
4375
+ 预占积分说明|About reserved points
4376
+ 当前运行的任务预先占用的积分,任务完成后将返还未用积分。|Running tasks reserve points. Unused points return when the task finishes.
4377
+ 正在加载积分…|Loading points…
4378
+ 积分读取失败,点击重试|Points could not be loaded. Click to retry.
4379
+ 积分加载中…|Loading points…
4380
+ 积分读取失败|Points could not be loaded
4381
+ 积分到账中,到账后会自动刷新可用积分。|Your points are being credited. Available points will refresh automatically.
4382
+ 已到账,正在刷新可用积分|Credited. Refreshing available points…
4383
+ 可用积分已刷新:|Available points refreshed:
4384
+ 积分暂未刷新:|Points have not refreshed:
4385
+ 刷新积分|Refresh points
4386
+ AI 额度 {v0}|AI allowance {v0}
4387
+ AI 额度充值流程|AI point purchase
4388
+ 次调用|calls
4389
+ 按用量扣积分 · 计费说明|Usage-based points · Pricing details
4299
4390
  `.trim().split("\n").map((line) => {
4300
4391
  const p = line.indexOf("|");
4301
4392
  return [line.slice(0, p), line.slice(p + 1)];
@@ -216,11 +216,42 @@ window.__ModuleLoader__.load({
216
216
  this.route = route;
217
217
  this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
218
218
  }
219
+ /** Account-scoped marked speaker candidates; refs can be used only with this provider/account. */
220
+ async recordingSpeakerCandidates(signal) {
221
+ await this.requireSpeakerPresence(signal);
222
+ return await this.call("recordings.speaker.options", {}, signal);
223
+ }
224
+ async recordingSpeakerPresence(signal) {
225
+ await this.requireSpeakerPresence(signal);
226
+ return await this.call("recordings.speaker.presence", {}, signal);
227
+ }
228
+ async recordingSpeakerMembers(speakerRef, options = {}) {
229
+ if (speakerRef.trim() === "") throw new TypeError("speakerRef is required");
230
+ await this.requireSpeakerPresence(options.signal);
231
+ return await this.call("recordings.speaker.members", {
232
+ speakerRef,
233
+ ...options.expectedVersion === void 0 ? {} : { expectedVersion: options.expectedVersion }
234
+ }, options.signal);
235
+ }
236
+ async requireSpeakerPresence(signal) {
237
+ if ((await this.capabilities(signal)).features.speakerPresence !== true) throw new Error("当前 Provider 不支持全历史说话人统计");
238
+ }
219
239
  async capabilities(signal) {
220
240
  const capabilities = await this.call("provider.capabilities", void 0, signal);
221
241
  if (capabilities.contractVersion !== 1) throw new Error(`Unsupported Arkme provider contract version ${String(capabilities.contractVersion)}`);
222
242
  return capabilities;
223
243
  }
244
+ async aiPointsAccount(expectedAccountScope, signal) {
245
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
246
+ return this.call("account.points.query", { expectedAccountScope }, signal);
247
+ }
248
+ async aiPointsConsumption(expectedAccountScope, query, signal) {
249
+ if ((await this.capabilities(signal)).features.aiPoints !== true) throw new Error("当前 Provider 不支持 AI 积分");
250
+ return this.call("account.points.consumption", {
251
+ expectedAccountScope,
252
+ ...query
253
+ }, signal);
254
+ }
224
255
  async state(signal) {
225
256
  return await this.call("provider.state", void 0, signal);
226
257
  }