dsh-kaomoji 0.1.0 → 0.1.2

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
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/lang/zh-CN/
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.2] - 2026-09-10
11
+
12
+ ### Changed
13
+
14
+ - `auto` 模式的适用范围明确包含日常推荐、购物建议和实用 how-to 回答:这类
15
+ 对话式回答同样会带一个颜文字,只有纯代码、正式技术交付和高风险内容跳过。
16
+
17
+ ## [0.1.1] - 2026-09-10
18
+
19
+ ### Added
20
+
21
+ - 设置 RPC 默认信任范围改为 `trusted-host`:本机与 Host 声明的受信主机(如 Tailscale
22
+ 组网的服务器)都能保存设置;可用 `settingsAuthority: loopback` 收紧回仅本机。
23
+ - 设置卡片会显示 RPC 失败原因(来源不受信任 / Host 未加载 / 保存失败),不再静默只读。
24
+ - `auto` 模式改为更积极地输出颜文字:友好的寒暄、闲聊、共情类回复都会带一个。
25
+
26
+ ### Fixed
27
+
28
+ - 远程(Tailscale / 局域网)页面打开设置卡片时只能看、不能改的问题。
29
+
10
30
  ## [0.1.0] - 2026-09-09
11
31
 
12
32
  ### Added
package/README.en.md CHANGED
@@ -26,7 +26,7 @@ largest Japanese kaomoji sites.
26
26
  instead of inventing malformed faces.
27
27
  - **12 mood buckets** — happy, love, sad, cry, angry, surprised, confused,
28
28
  shy, playful, encourage, thanks, sorry.
29
- - **Three frequency modes** — `auto` (default), `frequent`, `off`.
29
+ - **Three frequency modes** — `auto` (default; greetings, casual chat, recommendations and empathetic replies get one), `frequent`, `off`.
30
30
  - **Placement control** — `inline` after the mood-matching sentence (default)
31
31
  or `end` of the reply.
32
32
  - **Visual settings card** under Settings → General, saved live without a restart.
@@ -62,12 +62,12 @@ Node.js `^22.19.0 || >=24.0.0`, pnpm 11.
62
62
  ```powershell
63
63
  cd "$env:USERPROFILE\.dsh\profiles\web"
64
64
 
65
- # Option A: install straight from GitHub (works today)
66
- dsh plugin --profile web add github:TianJie52009/dsh-kaomoji
67
-
68
- # Option B: install from npm (after the package is published)
65
+ # Option A: install from npm (recommended)
69
66
  dsh plugin --profile web add dsh-kaomoji
70
67
 
68
+ # Option B: install straight from GitHub (no npm release needed)
69
+ dsh plugin --profile web add github:TianJie52009/dsh-kaomoji
70
+
71
71
  # Local development build
72
72
  pnpm add file:C:\path\to\dsh-kaomoji
73
73
  ```
@@ -102,15 +102,25 @@ Example `cordis.patch.yml`:
102
102
 
103
103
  | Key | Type | Default | Description |
104
104
  | --- | --- | --- | --- |
105
- | `mode` | `'off' \| 'auto' \| 'frequent'` | `'auto'` | `off` disables; `auto` uses kaomoji only when helpful; `frequent` adds one to every conversational reply (code-only/formal replies excluded) |
105
+ | `mode` | `'off' \| 'auto' \| 'frequent'` | `'auto'` | `off` disables; `auto` adds one to greetings, casual chat, recommendations and empathetic replies; `frequent` adds one to every conversational reply (code-only/formal replies excluded) |
106
106
  | `placement` | `'inline' \| 'end'` | `'inline'` | Put the kaomoji after the best-matching sentence, or at the reply end |
107
107
  | `maxPerTurn` | `number` (1–5) | `1` | Max kaomoji per reply |
108
108
  | `customPrompt` | `string` | `''` | Extra style/scene guidance; cannot change mode, whitelist or limits |
109
109
  | `settingsFile` | `string` | `~/.dsh/dsh-kaomoji.json` | (advanced) user-settings file path |
110
+ | `settingsAuthority` | `'trusted-host' \| 'loopback'` | `'trusted-host'` | Settings RPC trust scope: by default the local Host plus declared trusted hosts (Tailscale/LAN) may write; set `loopback` to restrict to the local machine |
110
111
 
111
112
  Card edits take effect immediately; deployment-default edits in
112
113
  `cordis.patch.yml` require a dsh restart.
113
114
 
115
+ ### Remote access (Tailscale / LAN)
116
+
117
+ - If the dsh page is reachable remotely, the Host already trusts that origin;
118
+ with the default `settingsAuthority: trusted-host` the General card can save
119
+ settings from the remote session.
120
+ - If the card reports that the origin is not trusted, add the host to the
121
+ server’s `trustedHosts` (dsh-client-connection) or temporarily switch to
122
+ `settingsAuthority: loopback` and edit on the server itself.
123
+
114
124
  ## Kaomoji library & attribution
115
125
 
116
126
  The built-in library lives in [`data/catalog.json`](./data/catalog.json), with a
@@ -196,6 +206,14 @@ npm publish --access public --registry https://registry.npmjs.org
196
206
 
197
207
  ## FAQ
198
208
 
209
+ - **No kaomoji in replies?** Check, in order: (1) the Host half is mounted —
210
+ `dsh plugin --profile web add dsh-kaomoji` writes both `dependencies` and
211
+ `dsh.profile.bundles`; a bare `pnpm add` only loads the client card, so
212
+ re-install with the dsh CLI or add the `insert` row to `cordis.patch.yml`
213
+ and restart (the log should show `[dsh-kaomoji] 已挂载(mode=...)`);
214
+ (2) the mode — `auto` only fires on friendly/casual/empathetic replies, use
215
+ `frequent` for one per conversational reply; (3) the settings card status —
216
+ “Host not loaded” / “origin not trusted” also means the guidance is absent.
199
217
  - **Why does the model sometimes skip kaomoji in `auto` mode?** That is by
200
218
  design. Only `frequent` requires one per conversational reply.
201
219
  - **Can I use kaomoji outside the whitelist?** Yes — put the exact string in
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  - **纯提示词方案**:不截断、不改写模型流,也不额外调用模型,稳定且对 KV 缓存友好。
18
18
  - **白名单防乱码**:模型只会从词库中逐字符复制颜文字,不会凭印象拼出坏字符。
19
19
  - **情绪分桶**:内置 12 个情绪分类(开心 / 心动 / 难过 / 大哭 / 生气 / 惊讶 / 困惑 / 害羞 / 俏皮 / 鼓励 / 感谢 / 道歉),并随规则给出可用样例。
20
- - **三种频率模式**:`auto`(智能点缀,默认)/ `frequent`(每条对话回复都带)/ `off`(关闭)。
20
+ - **三种频率模式**:`auto`(智能:寒暄/闲聊/推荐建议/共情回复都会带一个,默认)/ `frequent`(每条对话回复都带)/ `off`(关闭)。
21
21
  - **放置位置可选**:贴在情绪最贴切的句子后(`inline`,默认)或固定在回复末尾(`end`)。
22
22
  - **可视化配置卡片**:卡片位于「设置 → 通用设置」,保存即生效、无需重启。
23
23
  - **零第三方运行时依赖**:只用 dsh 自带的 `systemPrompt` 服务与 Node 标准库。
@@ -59,7 +59,18 @@
59
59
  - Node.js `^22.19.0 || >=24.0.0`
60
60
  - pnpm 11(dsh 默认使用 pnpm)
61
61
 
62
- ### 方式一:从 GitHub 直装(现在就能用)
62
+ ### 方式一:从 npm 安装(推荐)
63
+
64
+ 包已发布到 npm,直接安装即可,dsh CLI 会自动把插件加入 `dsh.profile.bundles`:
65
+
66
+ ```powershell
67
+ cd "$env:USERPROFILE\.dsh\profiles\web"
68
+ dsh plugin --profile web add dsh-kaomoji
69
+ ```
70
+
71
+ > 包刚发布的 24 小时内,如果对方的 pnpm 开启了「新包安全期」,裸名安装可能暂时解析不到;这种情况可先用下面的 GitHub 方式安装。
72
+
73
+ ### 方式二:从 GitHub 直装(无需等 npm)
63
74
 
64
75
  无需等 npm 发布,dsh CLI 支持直接装 GitHub 仓库:
65
76
 
@@ -74,15 +85,10 @@ cd "$env:USERPROFILE\.dsh\profiles\web"
74
85
  pnpm add github:TianJie52009/dsh-kaomoji
75
86
  ```
76
87
 
77
- ### 方式二:从 npm 安装(包发布后)
88
+ ### 方式三:本地开发版
78
89
 
79
90
  ```powershell
80
- cd "$env:USERPROFILE\.dsh\profiles\web"
81
-
82
- # dsh CLI 会自动把插件加入 dsh.profile.bundles
83
- dsh plugin --profile web add dsh-kaomoji
84
-
85
- # 本地开发版:先把仓库 clone/解压到本地,再把路径换成该目录
91
+ # 先把仓库 clone/解压到本地,再把路径换成该目录
86
92
  pnpm add file:C:\path\to\dsh-kaomoji
87
93
  ```
88
94
 
@@ -112,14 +118,20 @@ pnpm add file:C:\path\to\dsh-kaomoji
112
118
 
113
119
  | 配置项 | 类型 | 默认值 | 说明 |
114
120
  | --- | --- | --- | --- |
115
- | `mode` | `'off' \| 'auto' \| 'frequent'` | `'auto'` | `off` 关闭;`auto` 只在确有助益时使用;`frequent` 每条对话回复都带一个(纯代码 / 正式技术交付除外) |
121
+ | `mode` | `'off' \| 'auto' \| 'frequent'` | `'auto'` | `off` 关闭;`auto` 寒暄/闲聊/推荐建议/共情回复都会带一个;`frequent` 每条对话回复都带一个(两者都跳过纯代码 / 正式技术交付) |
116
122
  | `placement` | `'inline' \| 'end'` | `'inline'` | 放在情绪最贴切的句子/短段后,或固定在回复末尾 |
117
123
  | `maxPerTurn` | `number`(1–5) | `1` | 每条回复最多允许的颜文字数量 |
118
124
  | `customPrompt` | `string` | `''` | 附加风格/场景说明;不能改变模式、白名单或数量上限 |
119
125
  | `settingsFile` | `string` | `~/.dsh/dsh-kaomoji.json` | (进阶)用户设置持久化文件路径 |
126
+ | `settingsAuthority` | `'trusted-host' \| 'loopback'` | `'trusted-host'` | 设置 RPC 信任范围:默认允许本机与 Host 声明的受信主机(Tailscale/局域网)保存设置;改成 `loopback` 则仅本机可改 |
120
127
 
121
128
  卡片里的修改即时写入用户层并热生效;修改 `cordis.patch.yml` 的部署默认值后需重启 dsh。
122
129
 
130
+ ### 远程访问(Tailscale / 局域网)
131
+
132
+ - 只要能正常远程打开 dsh 页面,说明 Host 已信任该来源;默认 `settingsAuthority: trusted-host` 下,通用设置卡片可以直接修改并保存。
133
+ - 如果卡片提示「当前来源不在 Host 的信任列表里」,说明服务端 `@deepseek-ai/dsh-client-connection` 没有把该域名/IP 加进 `trustedHosts`;先在服务端配置受信主机,或临时改用 `settingsAuthority: loopback` 并到服务器本机编辑。
134
+
123
135
  ## 词库来源与许可
124
136
 
125
137
  内置词库见 [`data/catalog.json`](./data/catalog.json),每个分类都标注了 kaomojiya.org 对应的来源页:
@@ -199,6 +211,22 @@ npm publish --access public --registry https://registry.npmjs.org
199
211
 
200
212
  ## FAQ
201
213
 
214
+ ### 回答里没有颜文字?
215
+
216
+ 按顺序检查:
217
+
218
+ 1. **Host 半是否真的挂载了**:`dsh plugin --profile web add dsh-kaomoji` 会把插件同时写进 `dependencies` 和 `dsh.profile.bundles`;如果只用 `pnpm add` 手动装,client 卡片会出现但 Host 不会注入提示词。重新用 dsh CLI 安装一次,或在 profile 的 `cordis.patch.yml` 里补:
219
+
220
+ ```yaml
221
+ - insert:
222
+ - id: dsh-kaomoji
223
+ name: dsh-kaomoji
224
+ ```
225
+
226
+ 然后重启 dsh,日志里应出现 `[dsh-kaomoji] 已挂载(mode=...)`。
227
+ 2. **确认模式**:默认 `auto` 只在友好/闲聊/共情等场景使用;想要每条对话回复都带,在通用设置卡片切到「高频」,或在 `cordis.patch.yml` 写 `mode: frequent`。
228
+ 3. **看设置卡片状态**:卡片提示「Host 未加载」或「来源不受信任」时,提示词也不会注入,先按上面的步骤修好挂载/信任。
229
+
202
230
  ### 为什么模型偶尔没有加颜文字?
203
231
 
204
232
  `auto` 模式本来就不要求每回合使用;只有 `frequent` 才要求「对话回复都带一个」。如果 `frequent` 下仍经常漏掉,多半是回复被模型判为纯代码/正式交付,或上下文里其它 persona 指令更强势——可用 `customPrompt` 再强调一次。
package/lib/client.js CHANGED
@@ -56,7 +56,7 @@ window.__ModuleLoader__.load({
56
56
  "mode.off": "关闭",
57
57
  "mode.off.desc": "不使用颜文字",
58
58
  "mode.auto": "智能",
59
- "mode.auto.desc": "适合表达友好、共情或俏皮情绪时自然使用",
59
+ "mode.auto.desc": "寒暄、闲聊、推荐建议、共情回复都会带一个",
60
60
  "mode.frequent": "高频",
61
61
  "mode.frequent.desc": "每条对话回复都带一个(纯代码/正式交付除外)",
62
62
  "field.placement": "放置位置",
@@ -69,7 +69,8 @@ window.__ModuleLoader__.load({
69
69
  "action.reset": "恢复默认",
70
70
  "status.loading": "正在读取设置…",
71
71
  "status.saved": "已保存,下一次回复生效。",
72
- "status.unsupported": "设置仅在 Host 本机(loopback)页面可修改。",
72
+ "status.unsupported": "Host 未加载颜文字插件或该来源不被信任,无法保存设置。",
73
+ "status.forbidden": "当前来源不在 Host 的信任列表里,无法保存设置。",
73
74
  "status.error": "保存失败,请重试。",
74
75
  };
75
76
 
@@ -80,7 +81,7 @@ window.__ModuleLoader__.load({
80
81
  "mode.off": "Off",
81
82
  "mode.off.desc": "No kaomoji",
82
83
  "mode.auto": "Smart",
83
- "mode.auto.desc": "Use naturally when a friendly, empathetic, or playful mood fits",
84
+ "mode.auto.desc": "Greetings, casual chat, recommendations and empathetic replies get one",
84
85
  "mode.frequent": "Frequent",
85
86
  "mode.frequent.desc": "One kaomoji in every conversational reply (code-only/formal excluded)",
86
87
  "field.placement": "Placement",
@@ -93,7 +94,8 @@ window.__ModuleLoader__.load({
93
94
  "action.reset": "Reset to defaults",
94
95
  "status.loading": "Loading settings…",
95
96
  "status.saved": "Saved — applies to the next reply.",
96
- "status.unsupported": "Settings can only be changed on the Host’s local (loopback) page.",
97
+ "status.unsupported": "The Host did not load the kaomoji plugin, or this origin is not trusted.",
98
+ "status.forbidden": "This origin is not in the Host trust list, so settings cannot be saved.",
97
99
  "status.error": "Save failed, please retry.",
98
100
  };
99
101
 
@@ -211,12 +213,12 @@ window.__ModuleLoader__.load({
211
213
  * 轻量快照 store(getSnapshot/subscribe),slot runtime 会把它包装成
212
214
  * useKaomoji(selector) hook。所有写操作都串行经过 loopback RPC。
213
215
  */
214
- function createSettingsStore(rpc, isLoopback) {
216
+ function createSettingsStore(rpc) {
215
217
  let snapshot = {
216
- status: isLoopback ? "loading" : "unavailable",
218
+ status: "loading",
217
219
  settings: cloneSettings(DEFAULT_SETTINGS),
218
220
  revision: undefined,
219
- writable: Boolean(isLoopback),
221
+ writable: true,
220
222
  saveError: null,
221
223
  justSaved: false,
222
224
  };
@@ -238,16 +240,24 @@ window.__ModuleLoader__.load({
238
240
  return task;
239
241
  };
240
242
 
243
+ const fail = (code) => {
244
+ publish({
245
+ status: "unavailable",
246
+ writable: false,
247
+ saveError: code,
248
+ justSaved: false,
249
+ });
250
+ };
251
+
241
252
  const callRpc = async (endpoint, payload) => {
242
- if (!isLoopback) {
243
- publish({ status: "unavailable", saveError: null });
244
- return undefined;
245
- }
246
253
  try {
247
254
  const result = await rpc.call(RPC_CHANNEL, endpoint, payload);
248
- return result && result.ok === true ? result.value : undefined;
249
- } catch {
250
- return undefined;
255
+ if (result && result.ok === true) return { value: result.value };
256
+ const code = result && result.error && result.error.code;
257
+ return { error: code === "forbidden" ? "forbidden" : "rejected" };
258
+ } catch (error) {
259
+ const message = String((error && error.message) || error || "");
260
+ return { error: /403|forbidden/i.test(message) ? "forbidden" : "unreachable" };
251
261
  }
252
262
  };
253
263
 
@@ -258,11 +268,12 @@ window.__ModuleLoader__.load({
258
268
  return () => listeners.delete(listener);
259
269
  },
260
270
  async refresh() {
261
- const value = await callRpc("get", {});
262
- if (value === undefined) {
263
- if (isLoopback) publish({ status: "ready", saveError: "load" });
271
+ const result = await callRpc("get", {});
272
+ if (result.error !== undefined) {
273
+ fail(result.error === "forbidden" ? "forbidden" : "load");
264
274
  return;
265
275
  }
276
+ const value = result.value;
266
277
  publish({
267
278
  status: "ready",
268
279
  settings: normalizeSettings(value.settings),
@@ -272,6 +283,7 @@ window.__ModuleLoader__.load({
272
283
  });
273
284
  },
274
285
  patch(field) {
286
+ if (!snapshot.writable) return Promise.resolve();
275
287
  const next = normalizeSettings({ ...snapshot.settings, ...field });
276
288
  publish({
277
289
  status: "ready",
@@ -280,14 +292,15 @@ window.__ModuleLoader__.load({
280
292
  justSaved: false,
281
293
  });
282
294
  return enqueue(async () => {
283
- const value = await callRpc("save", {
295
+ const result = await callRpc("save", {
284
296
  settings: next,
285
297
  expectedRevision: snapshot.revision,
286
298
  });
287
- if (value === undefined) {
288
- publish({ saveError: "save", justSaved: false });
299
+ if (result.error !== undefined) {
300
+ fail(result.error === "forbidden" ? "forbidden" : "save");
289
301
  return;
290
302
  }
303
+ const value = result.value;
291
304
  publish({
292
305
  settings: normalizeSettings(value.settings),
293
306
  revision: value.revision,
@@ -299,13 +312,14 @@ window.__ModuleLoader__.load({
299
312
  });
300
313
  },
301
314
  async reset() {
302
- if (!isLoopback) return;
315
+ if (!snapshot.writable) return;
303
316
  publish({ saveError: null, justSaved: false });
304
- const value = await callRpc("reset", { expectedRevision: snapshot.revision });
305
- if (value === undefined) {
306
- publish({ saveError: "save", justSaved: false });
317
+ const result = await callRpc("reset", { expectedRevision: snapshot.revision });
318
+ if (result.error !== undefined) {
319
+ fail(result.error === "forbidden" ? "forbidden" : "save");
307
320
  return;
308
321
  }
322
+ const value = result.value;
309
323
  publish({
310
324
  settings: normalizeSettings(value.settings),
311
325
  revision: value.revision,
@@ -332,7 +346,9 @@ window.__ModuleLoader__.load({
332
346
  }, [settings.customPrompt]);
333
347
 
334
348
  const statusText = state.saveError
335
- ? t("status.error")
349
+ ? state.saveError === "forbidden"
350
+ ? t("status.forbidden")
351
+ : t("status.error")
336
352
  : state.status === "loading"
337
353
  ? t("status.loading")
338
354
  : !state.writable
@@ -466,7 +482,7 @@ window.__ModuleLoader__.load({
466
482
  "dsh-kaomoji: dictionaries",
467
483
  );
468
484
  const connection = ctx.get("connection");
469
- const controller = createSettingsStore(connection.rpc, connection.isLoopback);
485
+ const controller = createSettingsStore(connection.rpc);
470
486
  void controller.refresh();
471
487
 
472
488
  ctx.effect(() => {
package/lib/index.js CHANGED
@@ -30,6 +30,8 @@ export const SETTINGS_FILE_SCHEMA_VERSION = 1;
30
30
 
31
31
  export const MODES = ["off", "auto", "frequent"];
32
32
  export const PLACEMENTS = ["inline", "end"];
33
+ /** 设置 RPC 的信任范围:trusted-host = 本机 + 服务端声明的受信主机(如 Tailscale)。 */
34
+ export const SETTINGS_AUTHORITIES = ["trusted-host", "loopback"];
33
35
 
34
36
  export const DEFAULT_CONFIG = Object.freeze({
35
37
  /** off=关闭;auto=智能(确实有助于表达才用);frequent=高频(每条对话回复都带)。 */
@@ -144,8 +146,9 @@ export function buildGuidance(config) {
144
146
 
145
147
  const modeLines = {
146
148
  auto: [
147
- "Use a Japanese kaomoji only when it genuinely improves a friendly, empathetic, playful, or warm reply.",
148
- "One per reply is usually enough; never force one, and never replace real content with it.",
149
+ "Most conversational replies should include one fitting kaomoji — greetings, casual chat, empathy, everyday recommendations or shopping advice, and practical how-to answers.",
150
+ "Skip it only when the reply is purely code, a formal/technical deliverable, or serious/high-stakes content.",
151
+ "One per reply is usually enough; never replace real content with it.",
149
152
  ],
150
153
  frequent: [
151
154
  "In every conversational reply — except code-only output, formal/technical deliverables, or tool calls — include one fitting kaomoji.",
@@ -203,6 +206,11 @@ function cloneSettings(settings) {
203
206
  return { ...settings, customPrompt: settings.customPrompt };
204
207
  }
205
208
 
209
+ /** 设置 RPC 的信任范围;未显式配置时用 trusted-host(本机 + 服务端声明的受信主机)。 */
210
+ function resolveAuthority(config) {
211
+ return config?.settingsAuthority === "loopback" ? "loopback" : "trusted-host";
212
+ }
213
+
206
214
  function defaultSettingsFile(config) {
207
215
  if (typeof config?.settingsFile === "string" && config.settingsFile.trim() !== "") {
208
216
  return resolve(config.settingsFile);
@@ -362,6 +370,7 @@ function createSettingsRpcHandler(ctx, settingsFile, getState, commit) {
362
370
  export function apply(ctx, config = {}) {
363
371
  const baseSettings = normalizeConfig(config);
364
372
  const settingsFile = defaultSettingsFile(config);
373
+ const authority = resolveAuthority(config);
365
374
  const stored = loadSettingsDocument(settingsFile);
366
375
 
367
376
  // currentSettings = 用户层(~/.dsh/dsh-kaomoji.json)覆盖部署默认值后的实时设置。
@@ -406,14 +415,14 @@ export function apply(ctx, config = {}) {
406
415
  connectionCtx.effect(
407
416
  () =>
408
417
  connectionCtx.connection.rpc.handle(SETTINGS_RPC_CHANNEL, handler, {
409
- authority: "loopback",
418
+ authority,
410
419
  }),
411
420
  "dsh-kaomoji: settings rpc",
412
421
  );
413
422
  });
414
423
 
415
424
  ctx.logger?.info?.(
416
- `[dsh-kaomoji] 已挂载(mode=${currentSettings.mode}, placement=${currentSettings.placement}, settingsFile=${settingsFile})`,
425
+ `[dsh-kaomoji] 已挂载(mode=${currentSettings.mode}, placement=${currentSettings.placement}, authority=${authority}, settingsFile=${settingsFile})`,
417
426
  );
418
427
  }
419
428
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-kaomoji",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Add mood-aware Japanese kaomoji to DeepSeek Harness (dsh) replies; prompt-injection plugin with a curated library from kaomojiya.org.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",