dsh-chime-sound 0.3.2 → 0.3.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.3 (2026-09-16)
4
+
5
+ - **`koffi` 改为运行时动态 `import()`**,不再在模块顶层静态引入。dsh 的插件加载器把「入口模块 import 失败」当作**整棵插件树启动失败**(`Cordis startup failed because these plugin(s) could not be resolved`),所以静态引入一个可选的原生 FFI 包会把「没声音」升级成「profile 起不来」。现在 koffi 解析失败只以降级处理(`warn` + 诊断日志留痕),插件本体照常加载,其它插件也不受影响。
6
+ - **非 Windows 平台提前 `return`**:原先只发一条 warn 就继续往下走,于是仍会订阅 `session/event`、每个回合读一次 wav、再在 Win32 绑定处抛错被吞掉,并周期性重报服务缺失。现在平台门控在最前面直接返回,这些噪音消失。
7
+ - 版本号 `0.3.3`;`dsh-plugin.json` 的 `version` 同步。
8
+
3
9
  ## 0.3.2 (2026-09-13)
4
10
 
5
11
  - 文档:README 顶部加 CI 状态徽章;发布章节写明走 npm 可信发布(OIDC),仓库内不存放令牌
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  **English** · [中文](README.zh.md)
6
6
 
7
+ Built for [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI).
8
+
7
9
  Notification sounds for dsh-tui (originally named dsh-notice-sound, renamed on 2026-09-07).
8
10
 
9
11
  - **Triggers:** the agent calling `ask_user_question` (`session/event` `tool/call` — a nudge to come back and answer) and a reply finishing (`session/event` `turn/end`; agent-loop emits this once per turn, while `assistant/message` fires on every tool step and is deliberately not used). Both distinguish a focused from an unfocused terminal.
package/README.zh.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  **中文** · [English](README.md)
6
6
 
7
+ 为 [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI) 构建。
8
+
7
9
  dsh-tui 提示音效插件(原名 dsh-notice-sound,2026-09-07 更名)。
8
10
 
9
11
  - 触发:代理调用询问模块 `ask_user_question`(`session/event` `tool/call`,提醒用户回来回答问题)与回复完成(`session/event` `turn/end`,agent-loop 每回合仅发一次;`assistant/message` 会随每个工具步骤多次触发,不采用),并区分终端聚焦 / 未聚焦。
package/dsh-plugin.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifestVersion": "0.15",
4
4
  "id": "com.dsh-tui.chime",
5
5
  "name": "chime",
6
- "version": "0.3.2",
6
+ "version": "0.3.3",
7
7
  "facets": {
8
8
  "host": {
9
9
  "entry": "lib/index.js",
package/lib/index.js CHANGED
@@ -44,7 +44,6 @@ import { fileURLToPath } from 'node:url';
44
44
  import { appendFileSync, readFileSync } from 'node:fs';
45
45
  import { homedir } from 'node:os';
46
46
  import z from '@deepseek-ai/schemastery';
47
- import koffi from 'koffi';
48
47
  import { scaleWav } from './wav.js';
49
48
 
50
49
  const HERE = dirname(fileURLToPath(import.meta.url));
@@ -118,10 +117,20 @@ const RETRY_LIMIT = 60; // ~24s of service readiness attempts
118
117
  const POOL_SIZE = 8;
119
118
  const POOL_COOLDOWN_MS = 5000;
120
119
 
120
+ /**
121
+ * koffi, resolved by a RUNTIME import in `apply()` — deliberately not a static
122
+ * one. The loader treats a failed entry import as a whole-tree boot failure
123
+ * (`assertEntriesLoaded` → "Cordis startup failed"), so a module-scope import
124
+ * of an optional native FFI package would turn "no sound" into "the profile
125
+ * does not start".
126
+ */
127
+ let koffi = null;
128
+
121
129
  /** Lazy, shared Win32 bindings (koffi). */
122
130
  let win32 = null;
123
131
  function loadWin32() {
124
132
  if (win32 === null) {
133
+ if (koffi === null) throw new Error('koffi is not loaded (runtime import failed, or this is not a Win32 host)');
125
134
  const pvoid = koffi.pointer('void');
126
135
  const api = (lib, name, result, args) => lib.func('__stdcall', name, result, args);
127
136
  const user32 = koffi.load('user32.dll');
@@ -232,13 +241,26 @@ function registerSection(sections) {
232
241
  * this plugin, never the boot. Message events come from the session/event
233
242
  * bus (no Component identity required — see module header).
234
243
  */
235
- export function apply(ctx, config) {
244
+ export async function apply(ctx, config) {
236
245
  diag('apply started');
246
+ // TUI-RUN-001: the plugin is Win32-only (winmm/user32 via koffi). The
247
+ // platform gate runs FIRST and RETURNS: on a platform that can never play,
248
+ // subscribing to session/event would only produce retry noise.
237
249
  if (process.platform !== 'win32') {
238
- // TUI-RUN-001: the plugin is Win32-only (winmm/user32 via koffi); on
239
- // other platforms it degrades to a no-op — never a boot failure.
240
250
  diag(`platform=${process.platform}: sounds disabled (Win32-only)`);
241
251
  ctx.logger.warn(`chime: Win32-only plugin (winmm/user32); notification sounds will not play on ${process.platform}`);
252
+ return;
253
+ }
254
+ // Runtime import, not a module-scope one: a missing koffi must degrade this
255
+ // plugin, never fail the whole plugin tree (see the note on `koffi` above).
256
+ try {
257
+ koffi = (await import('koffi')).default;
258
+ }
259
+ catch (error) {
260
+ const reason = error instanceof Error ? error.message : String(error);
261
+ diag(`koffi import failed: ${reason}`);
262
+ ctx.logger.warn(`chime: could not load koffi (${reason}); notification sounds are disabled`);
263
+ return;
242
264
  }
243
265
  ctx.effect(function* () {
244
266
  let scope = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-chime-sound",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Notification sounds for dsh-tui: distinct tones for conversation done / user question, focused vs unfocused terminal, 9 selectable sound groups, master volume 0-150% in 5% steps, settings section, zh/en",
5
5
  "license": "MIT",
6
6
  "type": "module",