dsh-plugin-restart-notify 0.1.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/README.md +63 -0
- package/lib/client.js +110 -0
- package/lib/index.js +52 -0
- package/lib/types/client/index.d.ts +59 -0
- package/lib/types/client/locales.d.ts +14 -0
- package/lib/types/host/index.d.ts +39 -0
- package/lib/types/index.d.ts +9 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# dsh-plugin-restart-notify
|
|
2
|
+
|
|
3
|
+
检测到"**新构建已落地但服务器未重启**"时弹出**系统桌面通知**的 dsh web 插件(`dsh-plugin` 社区插件)。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- host 半(`src/host/`):检测 `.dsh-build/client-build-environment.json` 的写入时间晚于服务器启动时间 → 向页面注入 `__DSH_BUILD_STALE__`
|
|
8
|
+
- client 半:读到 stale 标志 → 弹出系统通知「检测到新构建,请手动重启 dsh web」
|
|
9
|
+
- 权限在用户首次交互时请求(浏览器要求手势);被拒则静默
|
|
10
|
+
|
|
11
|
+
## 组成
|
|
12
|
+
|
|
13
|
+
| 半 | 文件 | 职责 |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| host | `src/host/index.ts` | 构建记录检测 + `webserver/index-inject` 注入标志 |
|
|
16
|
+
| client | `src/client/index.ts` | 读标志 + 桌面通知 |
|
|
17
|
+
|
|
18
|
+
## 依赖
|
|
19
|
+
|
|
20
|
+
peer 依赖(npm 已发布):
|
|
21
|
+
- `@deepseek-ai/cordis`
|
|
22
|
+
- `@deepseek-ai/dsh-client-locale`
|
|
23
|
+
- `@deepseek-ai/dsh-client-runtime`
|
|
24
|
+
- `@deepseek-ai/dsh-client-ui-slots`
|
|
25
|
+
- `@deepseek-ai/dsh-host-webserver`(host 半的 index-inject 类型)
|
|
26
|
+
- `@deepseek-ai/schemastery`(host 半 Config schema)
|
|
27
|
+
|
|
28
|
+
## 构建
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pnpm install
|
|
32
|
+
pnpm run build
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
产物:`lib/index.js`(host 半)、`lib/client.js`(浏览器半)。
|
|
36
|
+
|
|
37
|
+
## 挂载
|
|
38
|
+
|
|
39
|
+
在 dsh profile 的 `cordis.patch.yml` 加行:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
- insert:
|
|
43
|
+
- id: restart-notify
|
|
44
|
+
name: dsh-plugin-restart-notify
|
|
45
|
+
config:
|
|
46
|
+
root: !!js process.env.DSH_REPO_ROOT # 指向仓库根(含 .dsh-build/client-build-environment.json)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`root` 配置必须指向仓库根目录(构建记录所在处)。安装包/无 checkout 场景没有构建记录,检测自然跳过。
|
|
50
|
+
|
|
51
|
+
## 发布
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
npm publish
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
GitHub 仓库添加 `dsh-plugin` 话题。
|
|
58
|
+
|
|
59
|
+
## 已知限制
|
|
60
|
+
|
|
61
|
+
- **仅源码 checkout 检测**:构建记录来自仓库根;无 checkout 则无信号
|
|
62
|
+
- **页面加载时静态读取**:标志只在启动时读取一次;需刷新页面触发
|
|
63
|
+
- **需要通知权限**:首次交互时请求;被拒则静默
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-plugin-restart-notify",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region src/client/locales.ts
|
|
8
|
+
/** `restartNotify` namespace dictionaries (the restart notification's copy). */
|
|
9
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
10
|
+
const zh = {
|
|
11
|
+
"notification.title": "检测到新构建",
|
|
12
|
+
"notification.body": "请手动重启 dsh web 并刷新页面以应用新构建。"
|
|
13
|
+
};
|
|
14
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
15
|
+
const en = {
|
|
16
|
+
"notification.title": "New build detected",
|
|
17
|
+
"notification.body": "Restart dsh web and refresh to apply the new build."
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/client/index.ts
|
|
21
|
+
/** Dictionary namespace owned by this plugin. */
|
|
22
|
+
const NS = "restartNotify";
|
|
23
|
+
/** The stale-build global injected by the plugin's host half. */
|
|
24
|
+
const BUILD_STALE_GLOBAL = "__DSH_BUILD_STALE__";
|
|
25
|
+
/** Required services: the locale seat (no slot — the notice is a notification, not UI). */
|
|
26
|
+
const inject = ["locale"];
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the browser Notification constructor, or undefined where absent.
|
|
29
|
+
* The returned surface adapts the constructor: `create` wraps `new
|
|
30
|
+
* Notification(title, options)`.
|
|
31
|
+
* @returns the Notification surface when available.
|
|
32
|
+
*/
|
|
33
|
+
function browserNotification() {
|
|
34
|
+
const ctor = globalThis.Notification;
|
|
35
|
+
if (typeof ctor !== "function") return void 0;
|
|
36
|
+
const native = ctor;
|
|
37
|
+
if (typeof native.permission !== "string" || typeof native.requestPermission !== "function") return;
|
|
38
|
+
return {
|
|
39
|
+
get permission() {
|
|
40
|
+
return native.permission;
|
|
41
|
+
},
|
|
42
|
+
requestPermission: () => native.requestPermission(),
|
|
43
|
+
create: (title, options) => new native(title, options)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Raise the restart notification through the browser Notification API.
|
|
48
|
+
* Permission must already be granted.
|
|
49
|
+
* @param api - the browser Notification surface.
|
|
50
|
+
* @param title - the notification title.
|
|
51
|
+
* @param body - the notification body.
|
|
52
|
+
*/
|
|
53
|
+
function notifyRestart(api, title, body) {
|
|
54
|
+
if (api.permission !== "granted") return;
|
|
55
|
+
api.create(title, { body });
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether the host flagged a stale build for this page load.
|
|
59
|
+
* @returns true when the host injected the stale-build flag.
|
|
60
|
+
*/
|
|
61
|
+
function buildIsStale() {
|
|
62
|
+
return globalThis[BUILD_STALE_GLOBAL] === true;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Client plugin body: when the host flags a stale build, request notification
|
|
66
|
+
* permission on the user's first interaction and raise the restart
|
|
67
|
+
* notification once granted.
|
|
68
|
+
* @param ctx - client root context.
|
|
69
|
+
*/
|
|
70
|
+
function apply(ctx) {
|
|
71
|
+
const locale = ctx.locale;
|
|
72
|
+
ctx.effect(() => locale.register(NS, {
|
|
73
|
+
zh,
|
|
74
|
+
en
|
|
75
|
+
}), "dsh-plugin-restart-notify: dictionaries");
|
|
76
|
+
if (!buildIsStale()) return;
|
|
77
|
+
const notify = browserNotification();
|
|
78
|
+
if (notify === void 0) return;
|
|
79
|
+
const t = locale.bind(NS);
|
|
80
|
+
const raise = () => {
|
|
81
|
+
if (notify.permission !== "granted") return;
|
|
82
|
+
notifyRestart(notify, t("notification.title"), t("notification.body"));
|
|
83
|
+
};
|
|
84
|
+
if (notify.permission === "granted") {
|
|
85
|
+
raise();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (notify.permission === "denied" || typeof document === "undefined") return;
|
|
89
|
+
const requestOnce = () => {
|
|
90
|
+
document.removeEventListener("pointerdown", requestOnce);
|
|
91
|
+
document.removeEventListener("keydown", requestOnce);
|
|
92
|
+
notify.requestPermission().then(() => {
|
|
93
|
+
raise();
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
document.addEventListener("pointerdown", requestOnce, { once: true });
|
|
97
|
+
document.addEventListener("keydown", requestOnce, { once: true });
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
exports.BUILD_STALE_GLOBAL = BUILD_STALE_GLOBAL;
|
|
101
|
+
exports.apply = apply;
|
|
102
|
+
exports.browserNotification = browserNotification;
|
|
103
|
+
exports.buildIsStale = buildIsStale;
|
|
104
|
+
exports.inject = inject;
|
|
105
|
+
exports.notifyRestart = notifyRestart;
|
|
106
|
+
return module.exports;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import z from "@deepseek-ai/schemastery";
|
|
4
|
+
//#region lib/types/host/index.js
|
|
5
|
+
/**
|
|
6
|
+
* Host half of dsh-plugin-restart-notify: detects when a rebuild landed that
|
|
7
|
+
* this running server has not loaded, and injects the `__DSH_BUILD_STALE__`
|
|
8
|
+
* global into the served index so the browser half can raise a restart
|
|
9
|
+
* notification. This replaces the harness-internal detection so the plugin
|
|
10
|
+
* is self-contained; install this package and add its host entry to the
|
|
11
|
+
* profile cordis.yml alongside the client row.
|
|
12
|
+
*/
|
|
13
|
+
/** Global the browser half reads to show the restart notice. */
|
|
14
|
+
const BUILD_STALE_GLOBAL = "__DSH_BUILD_STALE__";
|
|
15
|
+
/** Repository-relative build record written by every complete `pnpm run build`. */
|
|
16
|
+
const BUILD_RECORD_PATH = ".dsh-build/client-build-environment.json";
|
|
17
|
+
/** Services required: the web server's index injection seat. */
|
|
18
|
+
const inject = ["webServer"];
|
|
19
|
+
/** Validate the plugin config. */
|
|
20
|
+
const Config = z.object({ root: z.string() });
|
|
21
|
+
/**
|
|
22
|
+
* The index injection signaling a stale build: when the build record was
|
|
23
|
+
* written after this server started, a complete build landed on disk that
|
|
24
|
+
* this process has not loaded. Absent a record no injection is produced.
|
|
25
|
+
* @param root - repository root whose build record is consulted.
|
|
26
|
+
* @param startedAt - server start time in epoch milliseconds.
|
|
27
|
+
* @returns the global injection, or undefined when no stale build exists.
|
|
28
|
+
*/
|
|
29
|
+
function buildStaleInjection(root, startedAt) {
|
|
30
|
+
const recordPath = join(root, BUILD_RECORD_PATH);
|
|
31
|
+
if (!existsSync(recordPath)) return void 0;
|
|
32
|
+
return statSync(recordPath).mtimeMs > startedAt ? {
|
|
33
|
+
kind: "global",
|
|
34
|
+
name: BUILD_STALE_GLOBAL,
|
|
35
|
+
value: true
|
|
36
|
+
} : void 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Mount the stale-build detection: consult the build record against this
|
|
40
|
+
* process's start time and inject the flag on every served index.
|
|
41
|
+
* @param ctx - Host context carrying the webServer service.
|
|
42
|
+
* @param config - plugin config (repository root).
|
|
43
|
+
*/
|
|
44
|
+
function apply(ctx, config) {
|
|
45
|
+
const startedAt = Date.now();
|
|
46
|
+
ctx.on("webserver/index-inject", (table) => {
|
|
47
|
+
const stale = buildStaleInjection(config.root, startedAt);
|
|
48
|
+
if (stale !== void 0) table.push(stale);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { BUILD_STALE_GLOBAL, Config, apply, buildStaleInjection, inject };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restart-notify surface plugin, browser half: when the host flags a stale
|
|
3
|
+
* build (`window.__DSH_BUILD_STALE__`, injected by this plugin's host half),
|
|
4
|
+
* raise a system desktop notification telling the user to restart dsh web.
|
|
5
|
+
* Permission is requested on the user's first interaction (browsers require
|
|
6
|
+
* a gesture); a denied permission stays silent.
|
|
7
|
+
*/
|
|
8
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
9
|
+
import { type RestartNotifyKey } from './locales.js';
|
|
10
|
+
export type { RestartNotifyKey } from './locales.js';
|
|
11
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
12
|
+
interface LocaleNamespaceMap {
|
|
13
|
+
/** The restart notification copy. */
|
|
14
|
+
restartNotify: RestartNotifyKey;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** The stale-build global injected by the plugin's host half. */
|
|
18
|
+
export declare const BUILD_STALE_GLOBAL = "__DSH_BUILD_STALE__";
|
|
19
|
+
/** Required services: the locale seat (no slot — the notice is a notification, not UI). */
|
|
20
|
+
export declare const inject: string[];
|
|
21
|
+
/**
|
|
22
|
+
* The browser Notification surface narrowed to what this plugin uses, so
|
|
23
|
+
* tests can stub it and non-browser environments degrade silently.
|
|
24
|
+
*/
|
|
25
|
+
export interface NotificationApi {
|
|
26
|
+
readonly permission: NotificationPermission;
|
|
27
|
+
requestPermission(): Promise<NotificationPermission>;
|
|
28
|
+
create(title: string, options?: {
|
|
29
|
+
body?: string;
|
|
30
|
+
}): unknown;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the browser Notification constructor, or undefined where absent.
|
|
34
|
+
* The returned surface adapts the constructor: `create` wraps `new
|
|
35
|
+
* Notification(title, options)`.
|
|
36
|
+
* @returns the Notification surface when available.
|
|
37
|
+
*/
|
|
38
|
+
export declare function browserNotification(): NotificationApi | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Raise the restart notification through the browser Notification API.
|
|
41
|
+
* Permission must already be granted.
|
|
42
|
+
* @param api - the browser Notification surface.
|
|
43
|
+
* @param title - the notification title.
|
|
44
|
+
* @param body - the notification body.
|
|
45
|
+
*/
|
|
46
|
+
export declare function notifyRestart(api: NotificationApi, title: string, body: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the host flagged a stale build for this page load.
|
|
49
|
+
* @returns true when the host injected the stale-build flag.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildIsStale(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Client plugin body: when the host flags a stale build, request notification
|
|
54
|
+
* permission on the user's first interaction and raise the restart
|
|
55
|
+
* notification once granted.
|
|
56
|
+
* @param ctx - client root context.
|
|
57
|
+
*/
|
|
58
|
+
export declare function apply(ctx: ClientContext): void;
|
|
59
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** `restartNotify` namespace dictionaries (the restart notification's copy). */
|
|
2
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
3
|
+
export declare const zh: {
|
|
4
|
+
'notification.title': string;
|
|
5
|
+
'notification.body': string;
|
|
6
|
+
};
|
|
7
|
+
/** The restartNotify namespace key union. */
|
|
8
|
+
export type RestartNotifyKey = keyof typeof zh;
|
|
9
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
10
|
+
export declare const en: {
|
|
11
|
+
'notification.title': string;
|
|
12
|
+
'notification.body': string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host half of dsh-plugin-restart-notify: detects when a rebuild landed that
|
|
3
|
+
* this running server has not loaded, and injects the `__DSH_BUILD_STALE__`
|
|
4
|
+
* global into the served index so the browser half can raise a restart
|
|
5
|
+
* notification. This replaces the harness-internal detection so the plugin
|
|
6
|
+
* is self-contained; install this package and add its host entry to the
|
|
7
|
+
* profile cordis.yml alongside the client row.
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
10
|
+
import type { IndexInjection } from '@deepseek-ai/dsh-host-webserver';
|
|
11
|
+
import z from '@deepseek-ai/schemastery';
|
|
12
|
+
/** Global the browser half reads to show the restart notice. */
|
|
13
|
+
export declare const BUILD_STALE_GLOBAL = "__DSH_BUILD_STALE__";
|
|
14
|
+
/** Services required: the web server's index injection seat. */
|
|
15
|
+
export declare const inject: string[];
|
|
16
|
+
/** Plugin config: the repository root whose build record is consulted. */
|
|
17
|
+
export interface Config {
|
|
18
|
+
/** Absolute path of the repository root carrying `.dsh-build/client-build-environment.json`. */
|
|
19
|
+
root: string;
|
|
20
|
+
}
|
|
21
|
+
/** Validate the plugin config. */
|
|
22
|
+
export declare const Config: z<Config>;
|
|
23
|
+
/**
|
|
24
|
+
* The index injection signaling a stale build: when the build record was
|
|
25
|
+
* written after this server started, a complete build landed on disk that
|
|
26
|
+
* this process has not loaded. Absent a record no injection is produced.
|
|
27
|
+
* @param root - repository root whose build record is consulted.
|
|
28
|
+
* @param startedAt - server start time in epoch milliseconds.
|
|
29
|
+
* @returns the global injection, or undefined when no stale build exists.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildStaleInjection(root: string, startedAt: number): IndexInjection | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Mount the stale-build detection: consult the build record against this
|
|
34
|
+
* process's start time and inject the flag on every served index.
|
|
35
|
+
* @param ctx - Host context carrying the webServer service.
|
|
36
|
+
* @param config - plugin config (repository root).
|
|
37
|
+
*/
|
|
38
|
+
export declare function apply(ctx: Context, config: Config): void;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-plugin-restart-notify entry: the host half that detects a stale build
|
|
3
|
+
* and injects the flag the browser half reads. Mount this package's entry
|
|
4
|
+
* (named `restart-notify`) in the profile cordis.yml with a `root` config
|
|
5
|
+
* pointing at the repository root, and add the `dsh.client` row for the
|
|
6
|
+
* browser half.
|
|
7
|
+
*/
|
|
8
|
+
export { apply, inject, Config, buildStaleInjection, BUILD_STALE_GLOBAL } from './host/index.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-plugin-restart-notify",
|
|
3
|
+
"description": "Desktop notification for dsh web telling the user to restart after a rebuild the running server has not loaded",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./lib/types/index.d.ts",
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"types": "./lib/types/client/index.d.ts",
|
|
14
|
+
"default": "./lib/client.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"dsh": {
|
|
19
|
+
"client": {
|
|
20
|
+
"inject": [
|
|
21
|
+
"@deepseek-ai/dsh-client-locale"
|
|
22
|
+
],
|
|
23
|
+
"platform": "web"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json && node scripts/build-client.mjs",
|
|
28
|
+
"bundle": "node scripts/build-client.mjs",
|
|
29
|
+
"watch": "node scripts/build-client.mjs --watch"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
33
|
+
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
34
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
36
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
37
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
+
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"typescript": "^6.0.3",
|
|
50
|
+
"tsdown": "^0.22.2"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"lib/index.js",
|
|
54
|
+
"lib/client.js",
|
|
55
|
+
"lib/types/**/*.d.ts"
|
|
56
|
+
],
|
|
57
|
+
"keywords": ["dsh-plugin", "deepseek-harness", "restart", "notification"]
|
|
58
|
+
}
|