@telosmaylx/dsh-session-notify 0.1.7 → 0.1.9
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 +583 -570
- package/lib/client.js +188 -48
- package/lib/core.js +103 -1
- package/lib/index.js +45 -9
- package/package.json +70 -70
package/lib/core.js
CHANGED
|
@@ -25,6 +25,96 @@ function tableFor(language) {
|
|
|
25
25
|
return LABELS[language] || LABELS.zh
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* 各语言默认推送标题(按结束原因差异化)。
|
|
30
|
+
* 优先级:titleTemplates[kind] > titleTemplate(全局模板)> 本表。
|
|
31
|
+
*/
|
|
32
|
+
const DEFAULT_TITLES = {
|
|
33
|
+
zh: { completed: '任务已完成', aborted: '任务已中止', blocked: '任务被阻塞', error: '任务出错', 'max-tokens': '任务达到输出上限' },
|
|
34
|
+
'zh-tw': { completed: '任務已完成', aborted: '任務已中止', blocked: '任務被阻塞', error: '任務出錯', 'max-tokens': '任務達到輸出上限' },
|
|
35
|
+
en: { completed: 'Task completed', aborted: 'Task aborted', blocked: 'Task blocked', error: 'Task failed', 'max-tokens': 'Task hit the output cap' },
|
|
36
|
+
ja: { completed: 'タスク完了', aborted: 'タスク中止', blocked: 'タスクがブロックされました', error: 'タスクエラー', 'max-tokens': '出力上限に到達' },
|
|
37
|
+
ko: { completed: '작업 완료', aborted: '작업 중단됨', blocked: '작업 차단됨', error: '작업 오류', 'max-tokens': '출력 한도 도달' },
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 渲染某原因的实际推送标题:
|
|
42
|
+
* titleTemplates[kind](按原因定制)> titleTemplate(全局模板)> DEFAULT_TITLES[lang][kind]。
|
|
43
|
+
* 模板支持 {title} 占位符(会话标题,缺失为空);渲染后为空时回退默认标题。
|
|
44
|
+
* @param {string} kind
|
|
45
|
+
* @param {{ language?: string; titleTemplate?: string; titleTemplates?: Record<string, string> }} opts
|
|
46
|
+
* @param {string} [titleValue]
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
export function renderTitle(kind, opts = {}, titleValue = '') {
|
|
50
|
+
const language = LABELS[opts.language] ? opts.language : 'zh'
|
|
51
|
+
const per = (opts.titleTemplates && typeof opts.titleTemplates[kind] === 'string' && opts.titleTemplates[kind].trim() !== '') ? opts.titleTemplates[kind] : ''
|
|
52
|
+
const global = typeof opts.titleTemplate === 'string' && opts.titleTemplate.trim() !== '' ? opts.titleTemplate : ''
|
|
53
|
+
const fallback = (DEFAULT_TITLES[language] && DEFAULT_TITLES[language][kind]) || DEFAULT_TITLES.zh[kind] || '任务已完成'
|
|
54
|
+
const tpl = per || global || fallback
|
|
55
|
+
const out = String(tpl).replaceAll('{title}', titleValue).trim()
|
|
56
|
+
return out || fallback
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 各语言默认正文句式(templates 留空时的回退文案)。
|
|
61
|
+
* 按 reason 差异化表达,避免清一色「(用时 X,消耗 Y)」:
|
|
62
|
+
* - completed:括号紧凑式;aborted/blocked:句号拆句;error:错误详情前置;
|
|
63
|
+
* - max-tokens:句号拆句 + 建议;generic:兜底。
|
|
64
|
+
* 标签内嵌会话标题:{titleBlock}(带语言引号;无标题时为空块,自动退回「会话已完成」)。
|
|
65
|
+
* 其他占位符:{errBlock} 错误详情块(含分隔符,无错误为空)、{dur} 用时、{use} 消耗。
|
|
66
|
+
* 仅当用时与消耗都有数据时启用;数据不全回退到 buildNotice 的 parts 拼接逻辑(自动省略缺失项)。
|
|
67
|
+
*/
|
|
68
|
+
const DEFAULT_PHRASES = {
|
|
69
|
+
zh: {
|
|
70
|
+
completed: '会话{titleBlock}已完成(用时 {dur},消耗 {use})。',
|
|
71
|
+
aborted: '会话{titleBlock}已中止。用时 {dur},消耗 {use}。',
|
|
72
|
+
blocked: '会话{titleBlock}被阻塞。用时 {dur},消耗 {use}。',
|
|
73
|
+
error: '会话{titleBlock}出错{errBlock}(用时 {dur},消耗 {use})。',
|
|
74
|
+
'max-tokens': '会话{titleBlock}达到输出上限。用时 {dur},消耗 {use},建议拆分任务后重试。',
|
|
75
|
+
generic: '会话{titleBlock}已结束。用时 {dur},消耗 {use}。',
|
|
76
|
+
},
|
|
77
|
+
'zh-tw': {
|
|
78
|
+
completed: '會話{titleBlock}已完成(用時 {dur},消耗 {use})。',
|
|
79
|
+
aborted: '會話{titleBlock}已中止。用時 {dur},消耗 {use}。',
|
|
80
|
+
blocked: '會話{titleBlock}被阻塞。用時 {dur},消耗 {use}。',
|
|
81
|
+
error: '會話{titleBlock}出錯{errBlock}(用時 {dur},消耗 {use})。',
|
|
82
|
+
'max-tokens': '會話{titleBlock}達到輸出上限。用時 {dur},消耗 {use},建議拆分任務後重試。',
|
|
83
|
+
generic: '會話{titleBlock}已結束。用時 {dur},消耗 {use}。',
|
|
84
|
+
},
|
|
85
|
+
en: {
|
|
86
|
+
completed: 'Session {titleBlock} completed (took {dur}, used {use}).',
|
|
87
|
+
aborted: 'Session {titleBlock} aborted. Took {dur}, used {use}.',
|
|
88
|
+
blocked: 'Session {titleBlock} blocked. Took {dur}, used {use}.',
|
|
89
|
+
error: 'Session {titleBlock} failed{errBlock} (took {dur}, used {use}).',
|
|
90
|
+
'max-tokens': 'Session {titleBlock} hit the output-token cap. Took {dur}, used {use} — consider splitting the task.',
|
|
91
|
+
generic: 'Session {titleBlock} ended. Took {dur}, used {use}.',
|
|
92
|
+
},
|
|
93
|
+
ja: {
|
|
94
|
+
completed: 'セッション{titleBlock}完了(所要 {dur}、消費 {use})。',
|
|
95
|
+
aborted: 'セッション{titleBlock}中止。所要 {dur}、消費 {use}。',
|
|
96
|
+
blocked: 'セッション{titleBlock}がブロックされました。所要 {dur}、消費 {use}。',
|
|
97
|
+
error: 'セッション{titleBlock}エラー{errBlock}(所要 {dur}、消費 {use})。',
|
|
98
|
+
'max-tokens': 'セッション{titleBlock}が出力トークン上限に到達。所要 {dur}、消費 {use}。タスクの分割をおすすめします。',
|
|
99
|
+
generic: 'セッション{titleBlock}終了。所要 {dur}、消費 {use}。',
|
|
100
|
+
},
|
|
101
|
+
ko: {
|
|
102
|
+
completed: '세션{titleBlock} 완료(소요 {dur}, 소모 {use})。',
|
|
103
|
+
aborted: '세션{titleBlock} 중단됨. 소요 {dur}, 소모 {use}.',
|
|
104
|
+
blocked: '세션{titleBlock} 차단됨. 소요 {dur}, 소모 {use}.',
|
|
105
|
+
error: '세션{titleBlock} 오류{errBlock}(소요 {dur}, 소모 {use}).',
|
|
106
|
+
'max-tokens': '세션{titleBlock} 출력 한도 도달. 소요 {dur}, 소모 {use} — 작업 분할을 권장합니다.',
|
|
107
|
+
generic: '세션{titleBlock} 종료. 소요 {dur}, 소모 {use}.',
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** 会话标题块:带语言引号(zh/zh-tw/ja/ko「」,en ");无标题返回空块。 */
|
|
112
|
+
function titleValueBlock(language, titleValue) {
|
|
113
|
+
const v = typeof titleValue === 'string' ? titleValue.trim() : ''
|
|
114
|
+
if (!v) return ''
|
|
115
|
+
return language === 'en' ? `"${v}"` : `「${v}」`
|
|
116
|
+
}
|
|
117
|
+
|
|
28
118
|
/**
|
|
29
119
|
* 按语言取 reason 标签。
|
|
30
120
|
* @param {string} kind
|
|
@@ -218,6 +308,7 @@ export function buildNotice(kind, reasonData, { startedAt, endedAt, usage = null
|
|
|
218
308
|
const templates = custom.templates ?? {}
|
|
219
309
|
const label = labelFor(kind, language)
|
|
220
310
|
const detail = detailFor(reasonData, language)
|
|
311
|
+
const errText = plainError(reasonData)
|
|
221
312
|
let summary = `${label}${detail}`
|
|
222
313
|
const durationLine = includeDuration ? formatDuration(endedAt - startedAt, language) : null
|
|
223
314
|
const usageLine = includeUsage ? summarizeUsage(usage, language) : null
|
|
@@ -229,6 +320,7 @@ export function buildNotice(kind, reasonData, { startedAt, endedAt, usage = null
|
|
|
229
320
|
if (usageLine) parts.push(`${L.use} ${usageLine}`)
|
|
230
321
|
const suffix = parts.length ? `(${parts.join(',')})` : ''
|
|
231
322
|
const template = templates[kind]
|
|
323
|
+
const phraseTpl = (DEFAULT_PHRASES[language] && DEFAULT_PHRASES[language][kind]) || (DEFAULT_PHRASES[language] && DEFAULT_PHRASES[language].generic) || ''
|
|
232
324
|
let text
|
|
233
325
|
if (typeof template === 'string' && template.trim() !== '') {
|
|
234
326
|
// 自定义模板:占位符替换,保持 summary 与正文一致的语义
|
|
@@ -236,11 +328,21 @@ export function buildNotice(kind, reasonData, { startedAt, endedAt, usage = null
|
|
|
236
328
|
label,
|
|
237
329
|
duration: durationLine ?? '',
|
|
238
330
|
usage: usageLine ?? '',
|
|
239
|
-
error:
|
|
331
|
+
error: errText || 'none', // 无报错时显示 none,而非空串
|
|
240
332
|
cache: cacheLine,
|
|
241
333
|
tps: tpsLine,
|
|
242
334
|
title: typeof titleValue === 'string' ? titleValue : '',
|
|
243
335
|
})
|
|
336
|
+
} else if (durationLine && usageLine && phraseTpl) {
|
|
337
|
+
// 默认句式(用时+消耗都有时启用,按 reason 差异化表达)
|
|
338
|
+
const errBlock = errText ? L.sep + errText : ''
|
|
339
|
+
const titleBlock = titleValueBlock(language, titleValue)
|
|
340
|
+
text = phraseTpl
|
|
341
|
+
.replaceAll('{label}', label)
|
|
342
|
+
.replaceAll('{titleBlock}', titleBlock)
|
|
343
|
+
.replaceAll('{errBlock}', errBlock)
|
|
344
|
+
.replaceAll('{dur}', durationLine)
|
|
345
|
+
.replaceAll('{use}', usageLine)
|
|
244
346
|
} else if (language === 'en') {
|
|
245
347
|
text = `${summary}${suffix ? ` (${parts.join(', ')}).` : '.'}`
|
|
246
348
|
} else if (language === 'ja') {
|
package/lib/index.js
CHANGED
|
@@ -36,7 +36,7 @@ import { appendFileSync } from 'node:fs'
|
|
|
36
36
|
import { join } from 'node:path'
|
|
37
37
|
import { homedir } from 'node:os'
|
|
38
38
|
import { createRequire } from 'node:module'
|
|
39
|
-
import { createTurnTracker, buildNotice, isSubagentSession, officialCacheRate, officialTps } from './core.js?v=1' // v=1: 缓存破坏——HMR 重载按 URL 键控
|
|
39
|
+
import { createTurnTracker, buildNotice, isSubagentSession, officialCacheRate, officialTps, renderTitle } from './core.js?v=1' // v=1: 缓存破坏——HMR 重载按 URL 键控
|
|
40
40
|
|
|
41
41
|
/** Cordis loader 诊断用插件名。 */
|
|
42
42
|
export const name = 'session-complete-notify'
|
|
@@ -73,7 +73,9 @@ const DEFAULT_OPTIONS = {
|
|
|
73
73
|
const DEFAULT_SETTINGS = {
|
|
74
74
|
language: 'zh',
|
|
75
75
|
templates: { completed: '', error: '', aborted: '', blocked: '', 'max-tokens': '' },
|
|
76
|
-
titleTemplate: '',
|
|
76
|
+
titleTemplate: '', // 空 = 未自定义全局标题,各原因使用语言默认标题(如「任务已完成」「任务出错」)
|
|
77
|
+
/** 按原因定制推送标题(空 = 用 titleTemplate 或语言默认标题)。 */
|
|
78
|
+
titleTemplates: { completed: '', error: '', aborted: '', blocked: '', 'max-tokens': '' },
|
|
77
79
|
includeDuration: true,
|
|
78
80
|
includeUsage: true,
|
|
79
81
|
skipSubagents: true,
|
|
@@ -89,10 +91,16 @@ function sanitizeSettings(raw) {
|
|
|
89
91
|
for (const key of Object.keys(templates)) {
|
|
90
92
|
if (typeof templatesRaw[key] === 'string') templates[key] = templatesRaw[key]
|
|
91
93
|
}
|
|
94
|
+
const titlesRaw = src.titleTemplates && typeof src.titleTemplates === 'object' ? src.titleTemplates : {}
|
|
95
|
+
const titleTemplates = { ...DEFAULT_SETTINGS.titleTemplates }
|
|
96
|
+
for (const key of Object.keys(titleTemplates)) {
|
|
97
|
+
if (typeof titlesRaw[key] === 'string') titleTemplates[key] = titlesRaw[key]
|
|
98
|
+
}
|
|
92
99
|
return {
|
|
93
100
|
language: ['zh', 'zh-tw', 'en', 'ja', 'ko'].includes(src.language) ? src.language : 'zh',
|
|
94
101
|
templates,
|
|
95
102
|
titleTemplate: typeof src.titleTemplate === 'string' ? src.titleTemplate : '',
|
|
103
|
+
titleTemplates,
|
|
96
104
|
includeDuration: typeof src.includeDuration === 'boolean' ? src.includeDuration : true,
|
|
97
105
|
includeUsage: typeof src.includeUsage === 'boolean' ? src.includeUsage : true,
|
|
98
106
|
skipSubagents: typeof src.skipSubagents === 'boolean' ? src.skipSubagents : true,
|
|
@@ -130,6 +138,13 @@ export function apply(ctx, config = {}) {
|
|
|
130
138
|
'max-tokens': Schema.string().default(''),
|
|
131
139
|
}),
|
|
132
140
|
titleTemplate: Schema.string().default(''),
|
|
141
|
+
titleTemplates: Schema.object({
|
|
142
|
+
completed: Schema.string().default(''),
|
|
143
|
+
error: Schema.string().default(''),
|
|
144
|
+
aborted: Schema.string().default(''),
|
|
145
|
+
blocked: Schema.string().default(''),
|
|
146
|
+
'max-tokens': Schema.string().default(''),
|
|
147
|
+
}),
|
|
133
148
|
includeDuration: Schema.boolean().default(true),
|
|
134
149
|
includeUsage: Schema.boolean().default(true),
|
|
135
150
|
skipSubagents: Schema.boolean().default(true),
|
|
@@ -196,17 +211,23 @@ export function apply(ctx, config = {}) {
|
|
|
196
211
|
try {
|
|
197
212
|
rootRegistry.register({
|
|
198
213
|
key: SETTINGS_NS,
|
|
199
|
-
|
|
200
|
-
|
|
214
|
+
// 投影值:{ kind: 结束原因, text: 系统消息全文, title: 该原因的推送标题(host 已渲染,含 {title} 替换)}
|
|
215
|
+
schema: z.object({ kind: z.string(), text: z.string(), title: z.string() }),
|
|
216
|
+
init: () => ({ kind: '', text: '', title: '' }),
|
|
201
217
|
apply: (state, event) => {
|
|
202
218
|
if (event.type !== 'user/message') return state
|
|
203
219
|
const src = event.data?.source ?? {}
|
|
204
220
|
if (src.kind !== 'plugin' || src.plugin !== PLUGIN_ID) return state
|
|
205
221
|
const text = ((event.data?.content ?? []).map((b) => b?.text ?? '')).join('').trim()
|
|
206
|
-
|
|
222
|
+
if (!text) return state
|
|
223
|
+
return {
|
|
224
|
+
kind: typeof src.reasonKind === 'string' ? src.reasonKind : state.kind,
|
|
225
|
+
text,
|
|
226
|
+
title: typeof src.titleText === 'string' && src.titleText ? src.titleText : state.title,
|
|
227
|
+
}
|
|
207
228
|
},
|
|
208
229
|
view: (state) => state,
|
|
209
|
-
stateVersion:
|
|
230
|
+
stateVersion: 2, // 投影值从 string 升级为对象(kind/text/title)
|
|
210
231
|
})
|
|
211
232
|
fileLog('session-projections unit registered (key=session-complete-notify)')
|
|
212
233
|
} catch (err) {
|
|
@@ -250,6 +271,12 @@ export function apply(ctx, config = {}) {
|
|
|
250
271
|
} catch (projErr) {
|
|
251
272
|
warn(ctx, `投影快照读取失败: ${projErr?.message ?? projErr}`)
|
|
252
273
|
}
|
|
274
|
+
// 标题投影缺失时从会话自身兜底(header.title / title),确保默认文案能内嵌会话标题
|
|
275
|
+
if (!titleValue) {
|
|
276
|
+
const h = session?.header ?? {}
|
|
277
|
+
titleValue = (typeof h.title === 'string' && h.title.trim()) ? h.title
|
|
278
|
+
: (typeof session?.title === 'string' && session.title.trim()) ? session.title : ''
|
|
279
|
+
}
|
|
253
280
|
const notice = buildNotice(kind, event.data.reason, {
|
|
254
281
|
...state,
|
|
255
282
|
includeDuration: true, // 标签即开关:{duration} 插了才显示
|
|
@@ -258,6 +285,8 @@ export function apply(ctx, config = {}) {
|
|
|
258
285
|
tpsValue,
|
|
259
286
|
titleValue,
|
|
260
287
|
}, { language: settings.language, templates: settings.templates })
|
|
288
|
+
// 推送标题按原因渲染:titleTemplates[kind] > titleTemplate > 语言默认(如「任务已完成」)
|
|
289
|
+
const title = renderTitle(kind, { language: settings.language, titleTemplate: settings.titleTemplate, titleTemplates: settings.titleTemplates }, titleValue)
|
|
261
290
|
// 边界约束:session/event 观察者回调运行在 turn/end 那次 append 的
|
|
262
291
|
// 发布边界之内(dsh-session 在 dispatch 前 set entry.appending,
|
|
263
292
|
// finally 中复位),此时同步 append 会被拒绝:
|
|
@@ -265,7 +294,7 @@ export function apply(ctx, config = {}) {
|
|
|
265
294
|
// 推迟到微任务——微任务队列在本次同步栈(含 finally 复位)之后才跑。
|
|
266
295
|
queueMicrotask(() => {
|
|
267
296
|
if (disposed) return // 卸载窗口内已调度的微任务:fiber 已拆除,跳过追加
|
|
268
|
-
appendNotice(ctx, session, notice)
|
|
297
|
+
appendNotice(ctx, session, notice, kind, title)
|
|
269
298
|
})
|
|
270
299
|
return
|
|
271
300
|
}
|
|
@@ -290,7 +319,7 @@ export function apply(ctx, config = {}) {
|
|
|
290
319
|
}
|
|
291
320
|
|
|
292
321
|
/** 把系统消息追加进会话日志(失败只记日志,绝不抛出破坏 event 火线)。 */
|
|
293
|
-
function appendNotice(ctx, session, notice) {
|
|
322
|
+
function appendNotice(ctx, session, notice, kind, title) {
|
|
294
323
|
try {
|
|
295
324
|
session.append(
|
|
296
325
|
'user/message',
|
|
@@ -298,7 +327,14 @@ function appendNotice(ctx, session, notice) {
|
|
|
298
327
|
id: newId(),
|
|
299
328
|
role: 'user',
|
|
300
329
|
content: [{ type: 'text', text: notice.text }],
|
|
301
|
-
source: {
|
|
330
|
+
source: {
|
|
331
|
+
kind: 'plugin',
|
|
332
|
+
plugin: PLUGIN_ID,
|
|
333
|
+
form: 'notice',
|
|
334
|
+
summary: notice.summary,
|
|
335
|
+
reasonKind: typeof kind === 'string' ? kind : '', // 投影 apply 取用
|
|
336
|
+
titleText: typeof title === 'string' ? title : '', // 投影 apply 取用(host 渲染好的推送标题)
|
|
337
|
+
},
|
|
302
338
|
},
|
|
303
339
|
{ surfaceOp: 'append' },
|
|
304
340
|
)
|
package/package.json
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@telosmaylx/dsh-session-notify",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "DSH session completion notifier: appends a plugin system message to the session log on turn/end and pushes browser notifications (Web Notification + toast), with a fully customizable official settings panel (presets, 5-language templates, cache-hit rate & tok/s from official projections).",
|
|
5
|
-
"private": false,
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./lib/index.js",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"default": "./lib/index.js"
|
|
11
|
-
},
|
|
12
|
-
"./client": {
|
|
13
|
-
"default": "./lib/client.js"
|
|
14
|
-
},
|
|
15
|
-
"./core": {
|
|
16
|
-
"default": "./lib/core.js"
|
|
17
|
-
},
|
|
18
|
-
"./package.json": "./package.json"
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"lib",
|
|
22
|
-
"scripts",
|
|
23
|
-
"cordis.patch.yml",
|
|
24
|
-
"README.md",
|
|
25
|
-
"LICENSE"
|
|
26
|
-
],
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
29
|
-
},
|
|
30
|
-
"keywords": [
|
|
31
|
-
"deepseek-harness",
|
|
32
|
-
"dsh",
|
|
33
|
-
"dsh-plugin",
|
|
34
|
-
"session-notify",
|
|
35
|
-
"notification",
|
|
36
|
-
"completion-reminder",
|
|
37
|
-
"agent"
|
|
38
|
-
],
|
|
39
|
-
"author": "dsh-session-notify contributors",
|
|
40
|
-
"license": "MIT",
|
|
41
|
-
"repository": {
|
|
42
|
-
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/TelosmaYLX/dsh-session-notify.git"
|
|
44
|
-
},
|
|
45
|
-
"homepage": "https://github.com/TelosmaYLX/dsh-session-notify#readme",
|
|
46
|
-
"bugs": {
|
|
47
|
-
"url": "https://github.com/TelosmaYLX/dsh-session-notify/issues"
|
|
48
|
-
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"cordis": ">=4.0.0-rc <5"
|
|
51
|
-
},
|
|
52
|
-
"engines": {
|
|
53
|
-
"node": ">=22"
|
|
54
|
-
},
|
|
55
|
-
"dsh": {
|
|
56
|
-
"bundle": {
|
|
57
|
-
"patch": "./cordis.patch.yml"
|
|
58
|
-
},
|
|
59
|
-
"client": {
|
|
60
|
-
"inject": [
|
|
61
|
-
"@deepseek-ai/dsh-client-runtime"
|
|
62
|
-
],
|
|
63
|
-
"platform": "web"
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
"scripts": {
|
|
67
|
-
"build": "bash scripts/build.sh || node --check lib/index.js && node --check lib/core.js && node --check lib/client.js",
|
|
68
|
-
"prepublishOnly": "node --check lib/index.js && node --check lib/core.js && node --check lib/client.js"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@telosmaylx/dsh-session-notify",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "DSH session completion notifier: appends a plugin system message to the session log on turn/end and pushes browser notifications (Web Notification + toast), with a fully customizable official settings panel (presets, 5-language templates, cache-hit rate & tok/s from official projections).",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"default": "./lib/client.js"
|
|
14
|
+
},
|
|
15
|
+
"./core": {
|
|
16
|
+
"default": "./lib/core.js"
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"lib",
|
|
22
|
+
"scripts",
|
|
23
|
+
"cordis.patch.yml",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"deepseek-harness",
|
|
32
|
+
"dsh",
|
|
33
|
+
"dsh-plugin",
|
|
34
|
+
"session-notify",
|
|
35
|
+
"notification",
|
|
36
|
+
"completion-reminder",
|
|
37
|
+
"agent"
|
|
38
|
+
],
|
|
39
|
+
"author": "dsh-session-notify contributors",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/TelosmaYLX/dsh-session-notify.git"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/TelosmaYLX/dsh-session-notify#readme",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/TelosmaYLX/dsh-session-notify/issues"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"cordis": ">=4.0.0-rc <5"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=22"
|
|
54
|
+
},
|
|
55
|
+
"dsh": {
|
|
56
|
+
"bundle": {
|
|
57
|
+
"patch": "./cordis.patch.yml"
|
|
58
|
+
},
|
|
59
|
+
"client": {
|
|
60
|
+
"inject": [
|
|
61
|
+
"@deepseek-ai/dsh-client-runtime"
|
|
62
|
+
],
|
|
63
|
+
"platform": "web"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "bash scripts/build.sh || node --check lib/index.js && node --check lib/core.js && node --check lib/client.js",
|
|
68
|
+
"prepublishOnly": "node --check lib/index.js && node --check lib/core.js && node --check lib/client.js"
|
|
69
|
+
}
|
|
70
|
+
}
|