@bittersmilezzz/dsh-asr-voice 0.3.3 → 0.4.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/cordis.patch.yml +6 -5
- package/lib/client.js +54 -24
- package/lib/client.js.map +1 -1
- package/lib/index.js +44 -15
- package/lib/index.js.map +1 -1
- package/lib/optimize.js +1 -1
- package/lib/optimize.js.map +1 -1
- package/lib/presets.js +2 -1
- package/lib/presets.js.map +1 -1
- package/lib/realtime-host.js +19 -1
- package/lib/realtime-host.js.map +1 -1
- package/lib/realtime-tts.js +49 -29
- package/lib/realtime-tts.js.map +1 -1
- package/lib/settings.js +4 -1
- package/lib/settings.js.map +1 -1
- package/lib/types/index.d.ts +17 -3
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/optimize.d.ts +8 -0
- package/lib/types/optimize.d.ts.map +1 -1
- package/lib/types/presets.d.ts +4 -1
- package/lib/types/presets.d.ts.map +1 -1
- package/lib/types/realtime-host.d.ts +4 -0
- package/lib/types/realtime-host.d.ts.map +1 -1
- package/lib/types/realtime-tts.d.ts.map +1 -1
- package/lib/types/settings.d.ts +24 -24
- package/lib/types/settings.d.ts.map +1 -1
- package/package.json +33 -28
package/cordis.patch.yml
CHANGED
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
# host 实时通道(realtime.provider 选 'builtin' 假 provider 或真云端预置)。
|
|
14
14
|
# - 提示词优化:本地启发式(zh/en 清洗)或可选 LLM 重写(optimize.mode 默认
|
|
15
15
|
# llm,走 DSH 当前所选模型的官方 LLM 通道,host 代理)。
|
|
16
|
-
# - 设置页卡片:「设置 → 插件 → 配置」→「语音输入」(
|
|
17
|
-
# key: asr-voice
|
|
16
|
+
# - 设置页卡片:「设置 → 插件 → 配置」→「语音输入」(plugins.bundle.config,
|
|
17
|
+
# key: asr-voice;配置 schema 是入口模块顶层导出的 Config,DSH 0.1.7 起
|
|
18
|
+
# profile-backed forms,entry id 即 namespace)。
|
|
18
19
|
# - API key 只进 **DSH 凭据服务**(预置引用名与官方 LLM 凭据同名),settings 与浏览器
|
|
19
20
|
# 都不持有密钥;音频与转写请求经 /api/asr-voice/* 私有 JSON 代理。纯 Node HTTP 实现,
|
|
20
21
|
# macOS / Windows 双平台。
|
|
21
22
|
#
|
|
22
|
-
# host inject 只列硬依赖(webServer/llm
|
|
23
|
-
#
|
|
24
|
-
# ctx.get 可选读取。client 侧
|
|
23
|
+
# host inject 只列硬依赖(webServer/llm);配置经函数插件第二参注入(DSH 0.1.7
|
|
24
|
+
# Config 契约),无需 inject settings;agentDefaultModel 在优化路由内
|
|
25
|
+
# ctx.get 可选读取。client 侧 configForms / locale / slots 是硬依赖(设置卡与
|
|
25
26
|
# 按钮座位必需),connection / sessions / remote.credentials 是可选 ctx.inject
|
|
26
27
|
# (缺失只让对应能力退化:密钥读写 / 回合打断,不影响挂载)。
|
|
27
28
|
# 注意:inject 项是 Cordis 服务名(非 entry id)。
|
package/lib/client.js
CHANGED
|
@@ -818,6 +818,9 @@ window.__ModuleLoader__.load({
|
|
|
818
818
|
}
|
|
819
819
|
.dshav-card:hover { border-color: var(--dsw-alias-label-dimmed); }
|
|
820
820
|
.dshav-card.dshav-card-open { background: var(--dsw-alias-bg-layer-2); border-color: var(--dsw-alias-label-dimmed);}
|
|
821
|
+
/* 插件详情页(view: 'page'):官方页面已画标题/外壳,卡片容器透明化、body 无分隔线。 */
|
|
822
|
+
.dshav-card.dshav-card-page { border: 0; background: none; }
|
|
823
|
+
.dshav-card.dshav-card-page:hover { border-color: transparent; }
|
|
821
824
|
.dshav-header {
|
|
822
825
|
width: 100%;
|
|
823
826
|
appearance: none;
|
|
@@ -846,6 +849,7 @@ window.__ModuleLoader__.load({
|
|
|
846
849
|
.dshav-chevron { flex: none; color: var(--dsw-alias-label-tertiary); transition: transform .16s;}
|
|
847
850
|
.dshav-chevron.dshav-open { transform: rotate(180deg); }
|
|
848
851
|
.dshav-body { border-top: 1px solid var(--dsw-alias-border-l2); margin: 0 16px; padding-bottom: 8px;}
|
|
852
|
+
.dshav-body.dshav-body-page { border-top: 0; margin: 0; padding-top: 0; }
|
|
849
853
|
.dshav-group { display: flex; flex-direction: column; }
|
|
850
854
|
/* 分组之间用与字段一致的分割线(官方 border-l2)。 */
|
|
851
855
|
.dshav-group + .dshav-group { border-top: 1px solid var(--dsw-alias-border-l2); }
|
|
@@ -1108,7 +1112,7 @@ window.__ModuleLoader__.load({
|
|
|
1108
1112
|
label: "内置模拟(开发)",
|
|
1109
1113
|
wssUrl: "",
|
|
1110
1114
|
defaultModel: "",
|
|
1111
|
-
keyPreset: "
|
|
1115
|
+
keyPreset: "",
|
|
1112
1116
|
hint: "I3/I4 开发态:host 用能量 VAD 假 provider 驱动整条管道,不花配额"
|
|
1113
1117
|
}, {
|
|
1114
1118
|
id: "dashscope-realtime",
|
|
@@ -1315,10 +1319,13 @@ window.__ModuleLoader__.load({
|
|
|
1315
1319
|
}
|
|
1316
1320
|
return false;
|
|
1317
1321
|
}
|
|
1318
|
-
/**
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
+
/**
|
|
1323
|
+
* 绑定 host Config form 并订阅:首次读取当前值,之后 form 变化回写本地快照并广播。
|
|
1324
|
+
* @param forms - configForms 服务(DSH 0.1.7 官方 ConfigForms,随 fiber 注入)。
|
|
1325
|
+
* @returns 订阅 disposer(随 fiber 清理)。
|
|
1326
|
+
*/
|
|
1327
|
+
function bindConfigScope(forms) {
|
|
1328
|
+
const scope = forms.get(ASR_VOICE_NS);
|
|
1322
1329
|
voiceScope = scope;
|
|
1323
1330
|
const applySnapshot = () => {
|
|
1324
1331
|
const value = scope.getSnapshot().value;
|
|
@@ -1372,7 +1379,7 @@ window.__ModuleLoader__.load({
|
|
|
1372
1379
|
tts,
|
|
1373
1380
|
ttsVoice,
|
|
1374
1381
|
hotkey,
|
|
1375
|
-
bargeIn,
|
|
1382
|
+
bargeIn: engine === "segmented" && bargeIn,
|
|
1376
1383
|
maxSessionMs,
|
|
1377
1384
|
language: source.language,
|
|
1378
1385
|
settleMs: turn.settleMs,
|
|
@@ -2108,8 +2115,8 @@ window.__ModuleLoader__.load({
|
|
|
2108
2115
|
behavior: "groupBehavior",
|
|
2109
2116
|
realtime: "groupRealtime"
|
|
2110
2117
|
};
|
|
2111
|
-
/**
|
|
2112
|
-
function VoiceSettingsCard({ t }) {
|
|
2118
|
+
/** 设置卡片:插件详情页按 view 渲染(summary 一行 / page 表单),兜底路径自绘折叠外壳。 */
|
|
2119
|
+
function VoiceSettingsCard({ t, view }) {
|
|
2113
2120
|
const version = useConfigVersion();
|
|
2114
2121
|
const [open, setOpen] = react.useState(false);
|
|
2115
2122
|
const [showAdvanced, setShowAdvanced] = react.useState(false);
|
|
@@ -2283,9 +2290,11 @@ window.__ModuleLoader__.load({
|
|
|
2283
2290
|
];
|
|
2284
2291
|
const needKey = keyState !== null && !keyState.configured && keyState.failure === null;
|
|
2285
2292
|
const keyNameMissing = presetById(provider.preset) === void 0 && provider.name.trim() === "";
|
|
2293
|
+
const pageView = view === "page";
|
|
2294
|
+
if (view === "summary") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t("cardCopy") });
|
|
2286
2295
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
2287
|
-
className: "dshav-card" + (open ? " dshav-card-open" : ""),
|
|
2288
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2296
|
+
className: "dshav-card" + (open || pageView ? " dshav-card-open" : "") + (pageView ? " dshav-card-page" : ""),
|
|
2297
|
+
children: [pageView ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2289
2298
|
type: "button",
|
|
2290
2299
|
className: "dshav-header",
|
|
2291
2300
|
"aria-expanded": open,
|
|
@@ -2314,8 +2323,8 @@ window.__ModuleLoader__.load({
|
|
|
2314
2323
|
strokeLinejoin: "round"
|
|
2315
2324
|
})
|
|
2316
2325
|
})]
|
|
2317
|
-
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2318
|
-
className: "dshav-body",
|
|
2326
|
+
}), open || pageView ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2327
|
+
className: "dshav-body" + (pageView ? " dshav-body-page" : ""),
|
|
2319
2328
|
children: [
|
|
2320
2329
|
!writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2321
2330
|
className: "dshav-field-hint",
|
|
@@ -2399,7 +2408,7 @@ window.__ModuleLoader__.load({
|
|
|
2399
2408
|
placeholder: keyState?.configured === true ? t("keyKeepPlaceholder") : t("keyPastePlaceholder"),
|
|
2400
2409
|
spellCheck: false,
|
|
2401
2410
|
autoComplete: "off",
|
|
2402
|
-
disabled: !writable || keyState?.writable === false,
|
|
2411
|
+
disabled: !writable || keyState === null || keyState?.writable === false,
|
|
2403
2412
|
onChange: (e) => setKeyInput(e.target.value)
|
|
2404
2413
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2405
2414
|
type: "button",
|
|
@@ -4894,6 +4903,7 @@ window.__ModuleLoader__.load({
|
|
|
4894
4903
|
headers: { accept: "text/event-stream" },
|
|
4895
4904
|
signal: controller.signal
|
|
4896
4905
|
});
|
|
4906
|
+
if (res.status === 409) return;
|
|
4897
4907
|
if (!res.ok || res.body === null) {
|
|
4898
4908
|
if (!disposed) onEvent({
|
|
4899
4909
|
type: "error",
|
|
@@ -6707,7 +6717,8 @@ window.__ModuleLoader__.load({
|
|
|
6707
6717
|
const sys = systemDict();
|
|
6708
6718
|
const title = chat.active ? chat.title : busy ? state === "recording" ? sys.recordingTitle : state === "transcribing" ? sys.transcribingTitle : sys.optimizingTitle : chat.enabled ? sys.micTitleHoldChat : sys.micTitle;
|
|
6709
6719
|
const ariaLabel = chat.active ? chat.ariaLabel : busy ? state === "recording" ? t("recordingTitle") : state === "transcribing" ? t("transcribingTitle") : t("optimizingTitle") : chat.enabled ? t("micTitleHoldChat") : t("micTitle");
|
|
6710
|
-
const
|
|
6720
|
+
const ariaKeyName = (spec) => spec.replace(/\bCtrl\b/gi, "Control").replace(/\bCmd\b/gi, "Meta").replace(/\bAlt\b/gi, "Alt");
|
|
6721
|
+
const shortcut = chat.enabled && config.realtime.hotkey !== "" ? ariaKeyName(config.realtime.hotkey) : config.behavior.hotkey !== "" ? ariaKeyName(config.behavior.hotkey) : void 0;
|
|
6711
6722
|
const chatStatus = chat.active || !busy && error === null && notice === null ? chat.status : null;
|
|
6712
6723
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6713
6724
|
className: "dshav-mic-wrap",
|
|
@@ -6848,6 +6859,20 @@ window.__ModuleLoader__.load({
|
|
|
6848
6859
|
if (e.key === "Escape") {
|
|
6849
6860
|
e.stopPropagation();
|
|
6850
6861
|
closePreview();
|
|
6862
|
+
return;
|
|
6863
|
+
}
|
|
6864
|
+
if (e.key !== "Tab") return;
|
|
6865
|
+
const focusables = e.currentTarget.querySelectorAll("button");
|
|
6866
|
+
if (focusables.length === 0) return;
|
|
6867
|
+
const first = focusables[0];
|
|
6868
|
+
const last = focusables[focusables.length - 1];
|
|
6869
|
+
const active = document.activeElement;
|
|
6870
|
+
if (e.shiftKey && (active === first || !e.currentTarget.contains(active))) {
|
|
6871
|
+
e.preventDefault();
|
|
6872
|
+
last.focus();
|
|
6873
|
+
} else if (!e.shiftKey && (active === last || !e.currentTarget.contains(active))) {
|
|
6874
|
+
e.preventDefault();
|
|
6875
|
+
first.focus();
|
|
6851
6876
|
}
|
|
6852
6877
|
},
|
|
6853
6878
|
children: [
|
|
@@ -6903,12 +6928,15 @@ window.__ModuleLoader__.load({
|
|
|
6903
6928
|
//#endregion
|
|
6904
6929
|
//#region src/client/index.ts
|
|
6905
6930
|
const NS = "asr-voice";
|
|
6906
|
-
/**
|
|
6907
|
-
|
|
6931
|
+
/** 包名(`plugins.bundle.config` 的 key:bundle 的 package name)。 */
|
|
6932
|
+
const PACKAGE_NAME = "@bittersmilezzz/dsh-asr-voice";
|
|
6933
|
+
/** 硬依赖:设置卡/配置读写必须的顶层服务(DSH 0.1.7 起 configForms 取代
|
|
6934
|
+
* settingsScope;必须硬依赖,否则卡片包在 scoped inject 里会因服务不可注入而
|
|
6935
|
+
* 永不注册——这正是此前设置卡消失的根因)。 */
|
|
6908
6936
|
const inject = [
|
|
6909
6937
|
"slots",
|
|
6910
6938
|
"locale",
|
|
6911
|
-
"
|
|
6939
|
+
"configForms"
|
|
6912
6940
|
];
|
|
6913
6941
|
/** 快捷键处理(按住说话 / 点击切换 / 实时对话进出),随 fiber 生命周期注册。 */
|
|
6914
6942
|
function applyHotkey() {
|
|
@@ -7022,19 +7050,21 @@ window.__ModuleLoader__.load({
|
|
|
7022
7050
|
const sessions = raw.sessions;
|
|
7023
7051
|
cancelTurn = (sessionId) => {
|
|
7024
7052
|
try {
|
|
7025
|
-
((sessions?.scope(sessionId))?.get("conversation"))?.cancel?.()
|
|
7053
|
+
((sessions?.scope(sessionId))?.get("conversation"))?.cancel?.().catch(() => {});
|
|
7026
7054
|
} catch {}
|
|
7027
7055
|
};
|
|
7028
7056
|
});
|
|
7029
7057
|
ctx.effect(applyHotkey, "asr-voice: hotkey");
|
|
7030
|
-
ctx.effect(() => bindConfigScope(ctx.
|
|
7031
|
-
ctx.slots.inject("
|
|
7032
|
-
name: "
|
|
7033
|
-
key:
|
|
7058
|
+
ctx.effect(() => bindConfigScope(ctx.configForms), "asr-voice: config form sync");
|
|
7059
|
+
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
|
|
7060
|
+
name: "plugins.bundle.config",
|
|
7061
|
+
key: PACKAGE_NAME,
|
|
7034
7062
|
locale: NS
|
|
7035
|
-
}, () => react_jsx_runtime.jsx(VoiceSettingsCard, {
|
|
7063
|
+
}, (props) => react_jsx_runtime.jsx(VoiceSettingsCard, {
|
|
7064
|
+
t,
|
|
7065
|
+
view: props?.view
|
|
7066
|
+
})));
|
|
7036
7067
|
ctx.inject([
|
|
7037
|
-
"settingsScope",
|
|
7038
7068
|
"connection",
|
|
7039
7069
|
"remote",
|
|
7040
7070
|
"remote.credentials"
|