dsh-memo-ilife 0.1.0 → 0.2.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/dist/bridge.d.ts +11 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +34 -4
- package/dist/bridge.js.map +1 -1
- package/dist/client.js +331 -19
- package/dist/client.js.map +1 -1
- package/dist/contract.d.ts +34 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +35 -0
- package/dist/contract.js.map +1 -0
- package/dist/dsh-ctx.d.ts +116 -0
- package/dist/dsh-ctx.d.ts.map +1 -0
- package/dist/dsh-ctx.js +2 -0
- package/dist/dsh-ctx.js.map +1 -0
- package/dist/index.d.ts +7 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -7
- package/dist/index.js.map +1 -1
- package/dist/skill-provider.d.ts +22 -0
- package/dist/skill-provider.d.ts.map +1 -0
- package/dist/skill-provider.js +124 -0
- package/dist/skill-provider.js.map +1 -0
- package/dist/slot.d.ts +5 -0
- package/dist/slot.d.ts.map +1 -1
- package/dist/slot.js +5 -0
- package/dist/slot.js.map +1 -1
- package/package.json +16 -4
- package/dist/client.d.ts +0 -19
- package/dist/client.d.ts.map +0 -1
package/dist/bridge.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export declare class SkillBridgeError extends Error {
|
|
|
7
7
|
readonly code: 'missing-cli' | 'fetch-failed' | 'bad-json' | 'key-mismatch';
|
|
8
8
|
constructor(code: SkillBridgeError['code'], message: string);
|
|
9
9
|
}
|
|
10
|
+
/** 包内 CLI 相对路径(相对技能包根,与 SKILL_CLI 尾段一致)。 */
|
|
11
|
+
export declare const SKILL_CLI_REL: "dist/cli/cmd_read.js";
|
|
10
12
|
export declare function cliPath(): string;
|
|
11
13
|
export declare function assertCliPresent(path?: string): void;
|
|
12
14
|
/** host.call 侧处理函数:由 host 注册到 connection RPC,供面板调用。 */
|
|
@@ -15,6 +17,15 @@ export declare function handleHostCall(key: string, params?: Record<string, unkn
|
|
|
15
17
|
export declare function requestViaHost(host: {
|
|
16
18
|
call(method: string, args: unknown): Promise<unknown>;
|
|
17
19
|
}, key: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
20
|
+
/** spawn 超时毫秒:子进程超期未退即杀掉,转 fetch-failed,绝不无限挂起。
|
|
21
|
+
* #48 真机根因:Desktop 宿主的 process.execPath 是 Electron 二进制,直 spawn 会起 GUI 子进程永不退出。 */
|
|
22
|
+
export declare const SPAWN_TIMEOUT_MS: 20000;
|
|
23
|
+
/** node 可执行体解析(纯函数,execPath 可注入单测)。
|
|
24
|
+
* execPath 是 node 即直用;否则(Electron 宿主)沿用该二进制但加官方 ELECTRON_RUN_AS_NODE 语义当 node 用。 */
|
|
25
|
+
export declare function resolveNodeBin(execPath?: string): {
|
|
26
|
+
readonly bin: string;
|
|
27
|
+
readonly extraEnv: Record<string, string>;
|
|
28
|
+
};
|
|
18
29
|
/** 同步取数:spawn 技能 cmd_read,返回 envelope data(缺失阻断)。 */
|
|
19
30
|
export declare function readViaCli(key: string, params?: Record<string, unknown>): unknown;
|
|
20
31
|
//# sourceMappingURL=bridge.d.ts.map
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,aAAa,EAAG,kBAA2B,CAAC;AACzD,eAAO,MAAM,SAAS,EAAG,gDAAyD,CAAC;AACnF,eAAO,MAAM,gBAAgB,EAAG,iBAA0B,CAAC;AAC3D,eAAO,MAAM,eAAe,EAAG,eAAwB,CAAC;AAExD,eAAO,MAAM,oBAAoB,sJAC+B,CAAC;AAEjE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,UAAU,GAAG,cAAc,CAAC;gBAChE,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAK5D;AAMD,4CAA4C;AAC5C,eAAO,MAAM,aAAa,EAAG,sBAA+B,CAAC;AAe7D,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAOpD;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAEzF;AAED,oCAAoC;AACpC,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnK;AAED;kFACkF;AAClF,eAAO,MAAM,gBAAgB,EAAG,KAAe,CAAC;AAEhD;oFACoF;AACpF,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAyB,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAGvI;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAwBrF"}
|
package/dist/bridge.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { spawnSync } from 'node:child_process';
|
|
10
10
|
import { accessSync, constants } from 'node:fs';
|
|
11
|
+
import { createRequire } from 'node:module';
|
|
11
12
|
import { join, dirname } from 'node:path';
|
|
12
13
|
import { fileURLToPath } from 'node:url';
|
|
13
14
|
export const SKILL_PACKAGE = 'skill-memo-ilife';
|
|
@@ -26,8 +27,23 @@ export class SkillBridgeError extends Error {
|
|
|
26
27
|
function repoRoot() {
|
|
27
28
|
return join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
28
29
|
}
|
|
30
|
+
/** 包内 CLI 相对路径(相对技能包根,与 SKILL_CLI 尾段一致)。 */
|
|
31
|
+
export const SKILL_CLI_REL = 'dist/cli/cmd_read.js';
|
|
32
|
+
/** 按包名解析技能出口(#50 修法①之二,照抄 #48 卡路里样板):createRequire 定位技能包(SKILL_PACKAGE)
|
|
33
|
+
* 的 package.json,再拼包内 dist/cli/cmd_read.js。只读消费其 dist/CLI(spawn),
|
|
34
|
+
* 绝不 import 技能实现。包名解析失败回退单仓相对路径;两者皆无由 assertCliPresent
|
|
35
|
+
* 抛 missing-cli(缺失阻断不返空)。 */
|
|
36
|
+
function resolveSkillCli() {
|
|
37
|
+
try {
|
|
38
|
+
const pkgJson = createRequire(import.meta.url).resolve(SKILL_PACKAGE + '/package.json');
|
|
39
|
+
return join(dirname(pkgJson), SKILL_CLI_REL);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return join(repoRoot(), SKILL_CLI);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
29
45
|
export function cliPath() {
|
|
30
|
-
return
|
|
46
|
+
return resolveSkillCli();
|
|
31
47
|
}
|
|
32
48
|
export function assertCliPresent(path) {
|
|
33
49
|
const p = path ?? cliPath();
|
|
@@ -46,14 +62,28 @@ export function handleHostCall(key, params = {}) {
|
|
|
46
62
|
export function requestViaHost(host, key, params = {}) {
|
|
47
63
|
return host.call(HOST_CALL_METHOD, { key, params });
|
|
48
64
|
}
|
|
65
|
+
/** spawn 超时毫秒:子进程超期未退即杀掉,转 fetch-failed,绝不无限挂起。
|
|
66
|
+
* #48 真机根因:Desktop 宿主的 process.execPath 是 Electron 二进制,直 spawn 会起 GUI 子进程永不退出。 */
|
|
67
|
+
export const SPAWN_TIMEOUT_MS = 20_000;
|
|
68
|
+
/** node 可执行体解析(纯函数,execPath 可注入单测)。
|
|
69
|
+
* execPath 是 node 即直用;否则(Electron 宿主)沿用该二进制但加官方 ELECTRON_RUN_AS_NODE 语义当 node 用。 */
|
|
70
|
+
export function resolveNodeBin(execPath = process.execPath) {
|
|
71
|
+
if (/(^|[\\/])node(\.exe)?$/i.test(execPath))
|
|
72
|
+
return { bin: execPath, extraEnv: {} };
|
|
73
|
+
return { bin: execPath, extraEnv: { ELECTRON_RUN_AS_NODE: '1' } };
|
|
74
|
+
}
|
|
49
75
|
/** 同步取数:spawn 技能 cmd_read,返回 envelope data(缺失阻断)。 */
|
|
50
76
|
export function readViaCli(key, params = {}) {
|
|
51
77
|
const bin = cliPath();
|
|
52
78
|
assertCliPresent(bin);
|
|
53
|
-
const node =
|
|
54
|
-
const r = spawnSync(node, [bin, key, '--params', JSON.stringify(params)], { encoding: 'utf8' });
|
|
55
|
-
if (r.error)
|
|
79
|
+
const { bin: node, extraEnv } = resolveNodeBin();
|
|
80
|
+
const r = spawnSync(node, [bin, key, '--params', JSON.stringify(params)], { encoding: 'utf8', timeout: SPAWN_TIMEOUT_MS, env: { ...process.env, ...extraEnv } });
|
|
81
|
+
if (r.error) {
|
|
82
|
+
if (r.error?.code === 'ETIMEDOUT') {
|
|
83
|
+
throw new SkillBridgeError('fetch-failed', '出口超 ' + String(SPAWN_TIMEOUT_MS / 1000) + 's 未退,已杀掉(宿主非 node 时见 resolveNodeBin)');
|
|
84
|
+
}
|
|
56
85
|
throw new SkillBridgeError('fetch-failed', '出口 spawn 失败:' + r.error.message);
|
|
86
|
+
}
|
|
57
87
|
if (r.status !== 0) {
|
|
58
88
|
const tail = String(r.stderr ?? '').trim().split('\n').pop() ?? '';
|
|
59
89
|
throw new SkillBridgeError('fetch-failed', '出口非 0(' + String(r.status) + '):' + tail);
|
package/dist/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,aAAa,GAAG,kBAA2B,CAAC;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG,gDAAyD,CAAC;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAA0B,CAAC;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,eAAwB,CAAC;AAExD,MAAM,CAAC,MAAM,oBAAoB,GAC/B,8DAA8D,CAAC;AAEjE,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAA+D;IAC5E,YAAY,IAA8B,EAAE,OAAe;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -1,20 +1,332 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-memo-ilife",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __create = Object.create;
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
16
|
+
key = keys[i];
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
18
|
+
get: ((k) => from[k]).bind(null, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
25
|
+
value: mod,
|
|
26
|
+
enumerable: true
|
|
27
|
+
}) : target, mod));
|
|
28
|
+
//#endregion
|
|
29
|
+
let react = require("react");
|
|
30
|
+
react = __toESM(react, 1);
|
|
31
|
+
//#region src/contract.ts
|
|
32
|
+
/** dsh-memo-ilife 端口(port):DSH 世界与备忘录 hexagon 之间的契约。
|
|
33
|
+
*
|
|
34
|
+
* browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client
|
|
35
|
+
* 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。
|
|
36
|
+
* 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。
|
|
37
|
+
*/
|
|
38
|
+
const RPC_CHANNEL = "/ilife-memo";
|
|
39
|
+
const RPC_ENDPOINT_READ = "read";
|
|
40
|
+
/** 面板默认读键:memo.search 无参直读,空库安全(items []、total 0)。 */
|
|
41
|
+
const DEFAULT_READ_KEY = "memo.search";
|
|
42
|
+
/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */
|
|
43
|
+
function isRpcResult(raw) {
|
|
44
|
+
if (typeof raw !== "object" || raw === null) return false;
|
|
45
|
+
const ok = raw.ok;
|
|
46
|
+
return ok === true || ok === false;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/slot.ts
|
|
50
|
+
const SLOT_TITLE = "备忘录";
|
|
51
|
+
const PLUGIN = "dsh-memo-ilife";
|
|
52
|
+
const SKILL_PACKAGE = "skill-memo-ilife";
|
|
53
|
+
/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
|
|
54
|
+
* 发版 bump 时同步改这里(与 package.json 同值)。 */
|
|
55
|
+
const PLUGIN_VERSION = "0.2.0";
|
|
56
|
+
const SKILL_VERSION = "0.2.0";
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/settings.ts
|
|
59
|
+
/** 脚手架期唯一设置行:总开关(缺省启用,与官方关闭语义对齐)。 */
|
|
60
|
+
const SETTING_ROWS = [{
|
|
61
|
+
key: "enabled",
|
|
62
|
+
title: "备忘录面板启用",
|
|
63
|
+
control: "switch"
|
|
64
|
+
}];
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/client.ts
|
|
67
|
+
/** dsh-memo-ilife client 适配器(六边形:port=contract+dsh-ctx 镜像,adapter=本文件)。
|
|
68
|
+
*
|
|
69
|
+
* 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。
|
|
70
|
+
* 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。
|
|
71
|
+
* 注册两处(grill 定案,新术语见 CONTEXT.md):
|
|
72
|
+
* (a) 技能设置页 → 爱生活页签槽(总管声明的 children,各技能自研自家配置页);
|
|
73
|
+
* (b) 技能功能页 → sidebar槽(better-sidebar 服务,非 DSH slot;软依赖,
|
|
74
|
+
* 缺席即跳过,不断链。DSH右侧槽 + sidebar.footer.action 彻底出局,已删)。
|
|
75
|
+
* 有界重试例外依据(唯一允许的定时器):注册重试非数据轮询,照抄
|
|
76
|
+
* dsh-mattpocock-skills-deck/src/client/panelAssembly.js:100-108
|
|
77
|
+
* (betterSidebar 服务可能晚于本模块到达,最多 10 次、间隔 1000ms;卸载清理)。
|
|
78
|
+
* 只用 dsh-ctx 镜像内成员(slots.inject/register、connection.rpc.call 经闭包现取、
|
|
79
|
+
* betterSidebar 经 ctx.get 运行时取);取数只经 connection.rpc.call 进 host 通道;
|
|
80
|
+
* 缺席/错误纯条件渲染,不返空冒充。组件 React.createElement 手写,不引入 JSX。
|
|
81
|
+
*/
|
|
82
|
+
const inject = ["slots", "connection"];
|
|
83
|
+
/** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */
|
|
84
|
+
const S = {
|
|
85
|
+
card: {
|
|
86
|
+
padding: "12px 14px",
|
|
87
|
+
borderRadius: 10,
|
|
88
|
+
border: "1px solid var(--dsw-alias-border, rgba(128,128,128,.35))",
|
|
89
|
+
background: "var(--dsw-alias-bg-base, transparent)",
|
|
90
|
+
color: "var(--dsw-alias-label-primary, inherit)",
|
|
91
|
+
fontSize: 13,
|
|
92
|
+
lineHeight: 1.6
|
|
93
|
+
},
|
|
94
|
+
title: {
|
|
95
|
+
fontSize: 14,
|
|
96
|
+
fontWeight: 700,
|
|
97
|
+
marginBottom: 8
|
|
98
|
+
},
|
|
99
|
+
total: {
|
|
100
|
+
fontSize: 22,
|
|
101
|
+
fontWeight: 700,
|
|
102
|
+
margin: "2px 0 4px"
|
|
103
|
+
},
|
|
104
|
+
muted: {
|
|
105
|
+
color: "var(--dsw-alias-label-secondary, #9a9a9a)",
|
|
106
|
+
fontSize: 12
|
|
107
|
+
},
|
|
108
|
+
error: {
|
|
109
|
+
color: "var(--dsw-alias-state-error-primary, #ff6b6b)",
|
|
110
|
+
fontSize: 13
|
|
111
|
+
},
|
|
112
|
+
rows: {
|
|
113
|
+
marginTop: 8,
|
|
114
|
+
borderTop: "1px solid var(--dsw-alias-border, rgba(128,128,128,.25))",
|
|
115
|
+
paddingTop: 8
|
|
116
|
+
},
|
|
117
|
+
version: {
|
|
118
|
+
marginTop: 8,
|
|
119
|
+
paddingTop: 8,
|
|
120
|
+
borderTop: "1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))",
|
|
121
|
+
color: "var(--dsw-alias-label-tertiary, #8a8a8a)",
|
|
122
|
+
fontSize: 12
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
/** 版本行:插件与技能双版本号(用户要求:每技能设置页自报家门)。 */
|
|
126
|
+
function VersionLine() {
|
|
127
|
+
return react.createElement("div", { style: S.version }, `${PLUGIN} ${PLUGIN_VERSION} · ${SKILL_PACKAGE} ${SKILL_VERSION}`);
|
|
128
|
+
}
|
|
129
|
+
/** 数据态取值:有 total 显示 total,有值无 total 显示原值 JSON,空值返回 null(由调用方进错误态)。 */
|
|
130
|
+
function extractTotal(value) {
|
|
131
|
+
if (value === null || value === void 0) return null;
|
|
132
|
+
if (typeof value === "string") return value.length > 0 ? value : null;
|
|
133
|
+
if (typeof value === "object") {
|
|
134
|
+
const total = value.total;
|
|
135
|
+
if (total !== null && total !== void 0) return String(total);
|
|
136
|
+
try {
|
|
137
|
+
return JSON.stringify(value);
|
|
138
|
+
} catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return String(value);
|
|
143
|
+
}
|
|
144
|
+
/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */
|
|
145
|
+
const READ_TIMEOUT_MS = 2e4;
|
|
146
|
+
/** 自家赛跑超时(有界:settle 即清 timer;不依赖传输是否搭理 AbortSignal——Desktop 自研传输会忽略 signal)。
|
|
147
|
+
* 注释即 p10 有界重试门要的例外依据(文件内另有 clearTimeout/tries 上限/本注释三件套)。 */
|
|
148
|
+
function withTimeout(promise, ms) {
|
|
149
|
+
let timer;
|
|
150
|
+
const limit = new Promise((_, reject) => {
|
|
151
|
+
timer = setTimeout(() => {
|
|
152
|
+
timer = void 0;
|
|
153
|
+
const e = /* @__PURE__ */ new Error(`取数超时(${Math.round(ms / 1e3)}s):宿主未回,先查宿主日志与 DB 环境`);
|
|
154
|
+
e.name = "TimeoutError";
|
|
155
|
+
reject(e);
|
|
156
|
+
}, ms);
|
|
157
|
+
});
|
|
158
|
+
return Promise.race([promise.finally(() => {
|
|
159
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
160
|
+
}), limit]);
|
|
161
|
+
}
|
|
162
|
+
/** 单次读数(纯异步函数,无 hook;挂载期调用一次,无轮询)。 */
|
|
163
|
+
async function fetchRead(call, key, params) {
|
|
164
|
+
if (typeof call !== "function") return {
|
|
165
|
+
ok: false,
|
|
166
|
+
absent: true,
|
|
167
|
+
message: "宿主连接缺席:connection.rpc.call 不可用"
|
|
168
|
+
};
|
|
169
|
+
let result;
|
|
170
|
+
try {
|
|
171
|
+
const raw = await withTimeout(call("/api", RPC_CHANNEL.slice(1), {
|
|
172
|
+
method: RPC_ENDPOINT_READ,
|
|
173
|
+
payload: {
|
|
174
|
+
key,
|
|
175
|
+
params
|
|
176
|
+
}
|
|
177
|
+
}, AbortSignal.timeout(READ_TIMEOUT_MS)), READ_TIMEOUT_MS);
|
|
178
|
+
if (!isRpcResult(raw)) return {
|
|
179
|
+
ok: false,
|
|
180
|
+
absent: false,
|
|
181
|
+
message: "回执信封异常(非 ok 信封)"
|
|
182
|
+
};
|
|
183
|
+
result = raw;
|
|
184
|
+
} catch (e) {
|
|
185
|
+
if (e instanceof Error && e.name === "AbortError") return {
|
|
186
|
+
ok: false,
|
|
187
|
+
absent: false,
|
|
188
|
+
message: "取数超时(20s):宿主未回,先查宿主日志与 DB 环境"
|
|
189
|
+
};
|
|
190
|
+
return {
|
|
191
|
+
ok: false,
|
|
192
|
+
absent: false,
|
|
193
|
+
message: `取数失败:${e instanceof Error ? e.message : String(e)}`
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
if (!result.ok) {
|
|
197
|
+
const code = result.error?.code ?? "unknown";
|
|
198
|
+
const message = result.error?.message ?? "";
|
|
199
|
+
if (code === "missing-cli") return {
|
|
200
|
+
ok: false,
|
|
201
|
+
absent: true,
|
|
202
|
+
message: `技能出口缺席(missing-cli):${message}`
|
|
203
|
+
};
|
|
204
|
+
return {
|
|
205
|
+
ok: false,
|
|
206
|
+
absent: false,
|
|
207
|
+
message: `取数失败(${code}):${message}`
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const text = extractTotal(result.value);
|
|
211
|
+
if (text === null) return {
|
|
212
|
+
ok: false,
|
|
213
|
+
absent: false,
|
|
214
|
+
message: "取数为空(不冒充正常)"
|
|
215
|
+
};
|
|
216
|
+
return {
|
|
217
|
+
ok: true,
|
|
218
|
+
text
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** 技能功能页:sidebar槽里展开的干活区(查数调数,不管配置)。挂载期一次 RPC。 */
|
|
222
|
+
function MemoWork(props) {
|
|
223
|
+
const [state, setState] = react.useState({ kind: "loading" });
|
|
224
|
+
react.useEffect(() => {
|
|
225
|
+
let alive = true;
|
|
226
|
+
(async () => {
|
|
227
|
+
const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, {});
|
|
228
|
+
if (!alive) return;
|
|
229
|
+
if (r.ok) setState({
|
|
230
|
+
kind: "data",
|
|
231
|
+
total: r.text
|
|
232
|
+
});
|
|
233
|
+
else if (r.absent) setState({
|
|
234
|
+
kind: "absent",
|
|
235
|
+
message: r.message
|
|
236
|
+
});
|
|
237
|
+
else setState({
|
|
238
|
+
kind: "error",
|
|
239
|
+
message: r.message
|
|
240
|
+
});
|
|
241
|
+
})();
|
|
242
|
+
return () => {
|
|
243
|
+
alive = false;
|
|
244
|
+
};
|
|
245
|
+
}, [props.getCall]);
|
|
246
|
+
if (state.kind === "loading") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.muted }, "备忘录加载中…"));
|
|
247
|
+
if (state.kind === "data") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.title }, SLOT_TITLE), react.createElement("div", { style: S.total }, `total ${state.total}`), react.createElement(VersionLine, null));
|
|
248
|
+
return react.createElement("div", { style: S.card }, react.createElement("div", { style: state.kind === "absent" ? S.muted : S.error }, state.message), react.createElement(VersionLine, null));
|
|
249
|
+
}
|
|
250
|
+
function controlLabel(control) {
|
|
251
|
+
if (control === "switch") return "开关(缺省启用,只读)";
|
|
252
|
+
if (control === "text") return "文本(只读)";
|
|
253
|
+
if (control === "number") return "数字(只读)";
|
|
254
|
+
return `${control}(只读)`;
|
|
255
|
+
}
|
|
256
|
+
/** 技能设置页:爱生活页签条下的一页(只读设置行 + 状态读数,禁做假开关)。 */
|
|
257
|
+
function MemoConfig(props) {
|
|
258
|
+
const [state, setState] = react.useState({ kind: "loading" });
|
|
259
|
+
react.useEffect(() => {
|
|
260
|
+
let alive = true;
|
|
261
|
+
(async () => {
|
|
262
|
+
const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, {});
|
|
263
|
+
if (!alive) return;
|
|
264
|
+
if (r.ok) setState({
|
|
265
|
+
kind: "data",
|
|
266
|
+
total: r.text
|
|
267
|
+
});
|
|
268
|
+
else if (r.absent) setState({
|
|
269
|
+
kind: "absent",
|
|
270
|
+
message: r.message
|
|
271
|
+
});
|
|
272
|
+
else setState({
|
|
273
|
+
kind: "error",
|
|
274
|
+
message: r.message
|
|
275
|
+
});
|
|
276
|
+
})();
|
|
277
|
+
return () => {
|
|
278
|
+
alive = false;
|
|
279
|
+
};
|
|
280
|
+
}, [props.getCall]);
|
|
281
|
+
const status = state.kind === "loading" ? react.createElement("div", { style: S.muted }, "状态读取中…") : state.kind === "data" ? react.createElement("div", null, react.createElement("div", { style: S.title }, SLOT_TITLE), react.createElement("div", { style: S.total }, `total ${state.total}`)) : react.createElement("div", { style: state.kind === "absent" ? S.muted : S.error }, state.message);
|
|
282
|
+
return react.createElement("div", { style: S.card }, status, react.createElement("div", { style: S.rows }, SETTING_ROWS.map((row) => react.createElement("div", { key: row.key }, `${row.title} · ${controlLabel(row.control)}`))), react.createElement(VersionLine, null));
|
|
283
|
+
}
|
|
284
|
+
function apply(ctx) {
|
|
285
|
+
const getCall = () => ctx.connection?.rpc?.call ?? null;
|
|
286
|
+
ctx.slots.inject("ilife.config-tab", () => ctx.slots.register({
|
|
287
|
+
name: "ilife.config-tab",
|
|
288
|
+
id: "dsh-memo-ilife",
|
|
289
|
+
order: 70,
|
|
290
|
+
label: () => SLOT_TITLE
|
|
291
|
+
}, () => react.createElement(MemoConfig, { getCall })));
|
|
292
|
+
const ensureWorkTab = () => {
|
|
293
|
+
try {
|
|
294
|
+
const get = ctx.get;
|
|
295
|
+
const bs = typeof get === "function" ? get("betterSidebar") : void 0;
|
|
296
|
+
if (!bs || typeof bs.registerTab !== "function") return false;
|
|
297
|
+
const dispose = bs.registerTab({
|
|
298
|
+
id: "ilife-memo-ilife:work",
|
|
299
|
+
title: "备忘录",
|
|
300
|
+
order: 60,
|
|
301
|
+
single: true,
|
|
302
|
+
component: () => react.createElement(MemoWork, { getCall })
|
|
303
|
+
});
|
|
304
|
+
ctx.effect(() => () => {
|
|
305
|
+
try {
|
|
306
|
+
dispose();
|
|
307
|
+
} catch {}
|
|
308
|
+
}, "dsh-memo-ilife: sidebar work tab");
|
|
309
|
+
return true;
|
|
310
|
+
} catch {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
if (!ensureWorkTab()) {
|
|
315
|
+
let tries = 0;
|
|
316
|
+
const timer = setInterval(() => {
|
|
317
|
+
tries++;
|
|
318
|
+
if (ensureWorkTab() || tries >= 10) clearInterval(timer);
|
|
319
|
+
}, 1e3);
|
|
320
|
+
ctx.effect(() => () => {
|
|
321
|
+
clearInterval(timer);
|
|
322
|
+
}, "dsh-memo-ilife: sidebar work tab retry");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
exports.apply = apply;
|
|
327
|
+
exports.inject = inject;
|
|
328
|
+
return module.exports;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
20
332
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAC9C,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC;AAE9C,MAAM,UAAU,iBAAiB,CAAC,IAAc;IAC9C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAc,EAAE,SAAkB;IACjE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAgB,EAAE,GAAW,EAAE,SAAkC,EAAE;IACpG,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;AACtD,CAAC"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["React"],"sources":["../src/contract.ts","../src/slot.ts","../src/settings.ts","../src/client.ts"],"sourcesContent":["/** dsh-memo-ilife 端口(port):DSH 世界与备忘录 hexagon 之间的契约。\n *\n * browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client\n * 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。\n * 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。\n */\nexport const RPC_CHANNEL = '/ilife-memo' as const;\nexport const RPC_ENDPOINT_READ = 'read' as const;\n\n/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-memo-ilife SKILL.md)。 */\nexport interface ReadPayload {\n readonly key: string;\n readonly params: Record<string, unknown>;\n}\n\nexport interface RpcError {\n readonly code: string;\n readonly message: string;\n readonly details: Record<string, unknown>;\n}\n\nexport type RpcResult =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: RpcError };\n\nexport function ok(value: unknown): RpcResult {\n return { ok: true, value };\n}\n\nexport function fail(code: string, message: string): RpcResult {\n return { ok: false, error: { code, message, details: {} } };\n}\n\n/** 载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */\nexport function parseReadPayload(raw: unknown): ReadPayload | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const { key, params } = raw as { key?: unknown; params?: unknown };\n if (typeof key !== 'string' || key.length === 0) return null;\n if (typeof params !== 'object' || params === null || Array.isArray(params)) return null;\n return { key, params: params as Record<string, unknown> };\n}\n\n/** 面板默认读键:memo.search 无参直读,空库安全(items []、total 0)。 */\nexport const DEFAULT_READ_KEY = 'memo.search' as const;\n\n/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */\nexport function isRpcResult(raw: unknown): raw is RpcResult {\n if (typeof raw !== 'object' || raw === null) return false;\n const ok = (raw as { ok?: unknown }).ok;\n return ok === true || ok === false;\n}\n","/** dsh-memo-ilife 槽位描述(P10 脚手架,P3 #4 定案)。\n *\n * 写死槽位原生组件:id 命名空间 ilife:memo,order 70。\n * 注册与打开只走 registerTab/openTab 的路径导航;子页后缀(如 ilife:memo:*)\n * 只在主面板内导航,不占栏。缺席纯条件渲染,不轮询(本文件无定时器;\n * 有界重试归一由 base-render 拥有,单品不自建)。\n */\n\nexport const SKILL = 'memo' as const;\nexport const SLOT_ID = 'ilife:memo' as const;\nexport const SLOT_ORDER = 70 as const;\nexport const SLOT_TITLE = '备忘录' as const;\nexport const PLUGIN = 'dsh-memo-ilife' as const;\nexport const MANAGER_PLUGIN = 'dsh-life-pack' as const;\nexport const SKILL_PACKAGE = 'skill-memo-ilife' as const;\n\n/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。\n * 发版 bump 时同步改这里(与 package.json 同值)。 */\nexport const PLUGIN_VERSION = '0.2.0' as const;\nexport const SKILL_VERSION = '0.2.0' as const;\n\nexport interface SlotDescriptor {\n readonly skill: string;\n readonly slotId: string;\n readonly order: number;\n readonly title: string;\n readonly kind: 'page';\n}\n\nexport function slotDescriptor(): SlotDescriptor {\n return { skill: SKILL, slotId: SLOT_ID, order: SLOT_ORDER, title: SLOT_TITLE, kind: 'page' };\n}\n\n/** 写死原生组件描述(纯数据,无按需加载,无外嵌页)。 */\nexport const TAB_COMPONENT = { kind: 'native', name: 'MemoPanel' } as const;\n\nexport interface TabsPort {\n hasTabs(): boolean;\n registerTab(entry: { readonly id: string; readonly title: string; readonly order: number; readonly single: boolean; readonly component: unknown }): () => void;\n openTab(seed: { readonly type: string; readonly path: string }, scope?: { readonly sessionId?: string }): void;\n}\n\n/** 自注册:幂等(调用方持 disposer),失败返回 false 由调用方决定重试。 */\nexport function registerSingle(port: TabsPort): (() => void) | null {\n if (!port.hasTabs()) return null;\n return port.registerTab({ id: SLOT_ID, title: SLOT_TITLE, order: SLOT_ORDER, single: true, component: TAB_COMPONENT });\n}\n\n/** 内容型打开:path seed,折叠面板自动展开。 */\nexport function openSingle(port: TabsPort, sessionId?: string): void {\n if (!port.hasTabs()) return;\n port.openTab({ type: SLOT_ID, path: SLOT_ID }, sessionId ? { sessionId } : undefined);\n}\n","/** dsh-memo-ilife 设置页(P10 脚手架:设置页住单品包)。\n *\n * 一次 registerTab,两处呈现:边栏 + 号菜单多一项,DSH 设置页侧边卡片\n * 分区自动多一张小卡片(注册表驱动、无硬编码,开关缺省启用)。\n * 本文件只声明本单品自己的设置行;总管不声明设置(见 boundaries 断言)。\n */\n\nexport const SETTINGS_OWNER = 'dsh-memo-ilife' as const;\nexport const SETTINGS_SLOT = 'ilife:memo' as const;\n\nexport interface SettingRow {\n readonly key: string;\n readonly title: string;\n readonly control: 'switch' | 'text' | 'number';\n}\n\n/** 脚手架期唯一设置行:总开关(缺省启用,与官方关闭语义对齐)。 */\nexport const SETTING_ROWS: readonly SettingRow[] = [\n { key: 'enabled', title: '备忘录面板启用', control: 'switch' },\n];\n","/** dsh-memo-ilife client 适配器(六边形:port=contract+dsh-ctx 镜像,adapter=本文件)。\n *\n * 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。\n * 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。\n * 注册两处(grill 定案,新术语见 CONTEXT.md):\n * (a) 技能设置页 → 爱生活页签槽(总管声明的 children,各技能自研自家配置页);\n * (b) 技能功能页 → sidebar槽(better-sidebar 服务,非 DSH slot;软依赖,\n * 缺席即跳过,不断链。DSH右侧槽 + sidebar.footer.action 彻底出局,已删)。\n * 有界重试例外依据(唯一允许的定时器):注册重试非数据轮询,照抄\n * dsh-mattpocock-skills-deck/src/client/panelAssembly.js:100-108\n * (betterSidebar 服务可能晚于本模块到达,最多 10 次、间隔 1000ms;卸载清理)。\n * 只用 dsh-ctx 镜像内成员(slots.inject/register、connection.rpc.call 经闭包现取、\n * betterSidebar 经 ctx.get 运行时取);取数只经 connection.rpc.call 进 host 通道;\n * 缺席/错误纯条件渲染,不返空冒充。组件 React.createElement 手写,不引入 JSX。\n */\nimport * as React from 'react';\nimport { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, isRpcResult } from './contract.js';\nimport { SLOT_TITLE, PLUGIN, SKILL_PACKAGE, PLUGIN_VERSION, SKILL_VERSION } from './slot.js';\nimport { SETTING_ROWS } from './settings.js';\nimport type { ClientCtx, RpcCallResult } from './dsh-ctx.js';\n\nexport const inject = ['slots', 'connection'];\n\n/** 调用口取用器:每次取数时现取(connection 后到也不永久缺席)。 */\nexport type GetCall = () => unknown;\n\n/** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */\nconst S = {\n card: {\n padding: '12px 14px',\n borderRadius: 10,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.35))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13,\n lineHeight: 1.6,\n } as React.CSSProperties,\n title: { fontSize: 14, fontWeight: 700, marginBottom: 8 } as React.CSSProperties,\n total: { fontSize: 22, fontWeight: 700, margin: '2px 0 4px' } as React.CSSProperties,\n muted: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: 12 } as React.CSSProperties,\n error: { color: 'var(--dsw-alias-state-error-primary, #ff6b6b)', fontSize: 13 } as React.CSSProperties,\n rows: { marginTop: 8, borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))', paddingTop: 8 } as React.CSSProperties,\n version: {\n marginTop: 8,\n paddingTop: 8,\n borderTop: '1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))',\n color: 'var(--dsw-alias-label-tertiary, #8a8a8a)',\n fontSize: 12,\n } as React.CSSProperties,\n};\n\n/** 版本行:插件与技能双版本号(用户要求:每技能设置页自报家门)。 */\nfunction VersionLine(): React.ReactElement {\n return React.createElement('div', { style: S.version }, `${PLUGIN} ${PLUGIN_VERSION} · ${SKILL_PACKAGE} ${SKILL_VERSION}`);\n}\n\ntype PanelState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'data'; readonly total: string }\n | { readonly kind: 'absent'; readonly message: string }\n | { readonly kind: 'error'; readonly message: string };\n\n/** 数据态取值:有 total 显示 total,有值无 total 显示原值 JSON,空值返回 null(由调用方进错误态)。 */\nfunction extractTotal(value: unknown): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'string') return value.length > 0 ? value : null;\n if (typeof value === 'object') {\n const total = (value as { total?: unknown }).total;\n if (total !== null && total !== undefined) return String(total);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n }\n return String(value);\n}\n\ntype ReadOutcome =\n | { readonly ok: true; readonly text: string }\n | { readonly ok: false; readonly absent: boolean; readonly message: string };\n\n/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */\nconst READ_TIMEOUT_MS = 20_000 as const;\n\n/** 自家赛跑超时(有界:settle 即清 timer;不依赖传输是否搭理 AbortSignal——Desktop 自研传输会忽略 signal)。\n * 注释即 p10 有界重试门要的例外依据(文件内另有 clearTimeout/tries 上限/本注释三件套)。 */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const limit = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n timer = undefined;\n const e = new Error(`取数超时(${Math.round(ms / 1000)}s):宿主未回,先查宿主日志与 DB 环境`);\n e.name = 'TimeoutError';\n reject(e);\n }, ms);\n });\n return Promise.race([\n promise.finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n }),\n limit,\n ]);\n}\n\n/** 单次读数(纯异步函数,无 hook;挂载期调用一次,无轮询)。 */\nasync function fetchRead(call: unknown, key: string, params: Record<string, unknown>): Promise<ReadOutcome> {\n // extractRpc 同式守卫:非函数即缺席态。\n if (typeof call !== 'function') return { ok: false, absent: true, message: '宿主连接缺席:connection.rpc.call 不可用' };\n let result: RpcCallResult;\n try {\n // 防御纵深 + 自家超时双保险(AbortSignal 帮正规传输提前收工;race 保传输忽略 signal 时仍落字)。\n const raw: unknown = await withTimeout(\n // #80:走 DSH 公开的 /api 载体(host 侧为 connection.fetch.register 注册的 /api/ilife-memo)。\n call('/api', RPC_CHANNEL.slice(1), { method: RPC_ENDPOINT_READ, payload: { key, params } }, AbortSignal.timeout(READ_TIMEOUT_MS)),\n READ_TIMEOUT_MS,\n );\n if (!isRpcResult(raw)) return { ok: false, absent: false, message: '回执信封异常(非 ok 信封)' };\n result = raw;\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') return { ok: false, absent: false, message: '取数超时(20s):宿主未回,先查宿主日志与 DB 环境' };\n return { ok: false, absent: false, message: `取数失败:${e instanceof Error ? e.message : String(e)}` };\n }\n if (!result.ok) {\n const code = result.error?.code ?? 'unknown';\n const message = result.error?.message ?? '';\n if (code === 'missing-cli') return { ok: false, absent: true, message: `技能出口缺席(missing-cli):${message}` };\n return { ok: false, absent: false, message: `取数失败(${code}):${message}` };\n }\n const text = extractTotal(result.value);\n if (text === null) return { ok: false, absent: false, message: '取数为空(不冒充正常)' };\n return { ok: true, text };\n}\n\n/** 技能功能页:sidebar槽里展开的干活区(查数调数,不管配置)。挂载期一次 RPC。 */\nfunction MemoWork(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n void (async () => {\n const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, {});\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n if (state.kind === 'loading') {\n return React.createElement('div', { style: S.card }, React.createElement('div', { style: S.muted }, '备忘录加载中…'));\n }\n if (state.kind === 'data') {\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: S.title }, SLOT_TITLE),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n React.createElement(VersionLine, null),\n );\n }\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message),\n React.createElement(VersionLine, null),\n );\n}\n\nfunction controlLabel(control: string): string {\n if (control === 'switch') return '开关(缺省启用,只读)';\n if (control === 'text') return '文本(只读)';\n if (control === 'number') return '数字(只读)';\n return `${control}(只读)`;\n}\n\n/** 技能设置页:爱生活页签条下的一页(只读设置行 + 状态读数,禁做假开关)。 */\nfunction MemoConfig(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n void (async () => {\n const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, {});\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n const status =\n state.kind === 'loading'\n ? React.createElement('div', { style: S.muted }, '状态读取中…')\n : state.kind === 'data'\n ? React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.title }, SLOT_TITLE),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n )\n : React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message);\n return React.createElement(\n 'div',\n { style: S.card },\n status,\n React.createElement(\n 'div',\n { style: S.rows },\n SETTING_ROWS.map((row) =>\n React.createElement('div', { key: row.key }, `${row.title} · ${controlLabel(row.control)}`),\n ),\n ),\n React.createElement(VersionLine, null),\n );\n}\n\ninterface BetterSidebarService {\n registerTab(descriptor: {\n readonly id: string;\n readonly title: string | (() => string);\n readonly order?: number;\n readonly single?: boolean;\n readonly component: (props: unknown) => React.ReactElement | null;\n }): () => void;\n}\n\nexport function apply(ctx: ClientCtx): void {\n // 调用口取用器透传给组件(每次取数现取;非函数由组件判缺席)。\n const getCall: GetCall = () => ctx.connection?.rpc?.call ?? null;\n\n // (a) 技能设置页 → 爱生活页签槽(总管声明;总管缺席时 inject 等待,不断链)。\n ctx.slots.inject('ilife.config-tab', () =>\n ctx.slots.register(\n {\n name: 'ilife.config-tab',\n id: 'dsh-memo-ilife',\n order: 70,\n label: () => SLOT_TITLE,\n },\n () => React.createElement(MemoConfig, { getCall }),\n ),\n );\n\n // (b) 技能功能页 → sidebar槽(软依赖:betterSidebar 缺席即跳过)。\n const ensureWorkTab = (): boolean => {\n try {\n const get = ctx.get;\n const bs = (typeof get === 'function' ? get('betterSidebar') : undefined) as BetterSidebarService | undefined;\n if (!bs || typeof bs.registerTab !== 'function') return false;\n const dispose = bs.registerTab({\n id: 'ilife-memo-ilife:work',\n title: '备忘录',\n order: 60,\n single: true,\n component: () => React.createElement(MemoWork, { getCall }),\n });\n ctx.effect(() => () => {\n try {\n dispose();\n } catch {\n /* 卸载清理失败忽略 */\n }\n }, 'dsh-memo-ilife: sidebar work tab');\n return true;\n } catch {\n return false;\n }\n };\n if (!ensureWorkTab()) {\n let tries = 0;\n const timer = setInterval(() => {\n tries++;\n if (ensureWorkTab() || tries >= 10) clearInterval(timer);\n }, 1000);\n ctx.effect(() => () => {\n clearInterval(timer);\n }, 'dsh-memo-ilife: sidebar work tab retry');\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** dsh-memo-ilife 端口(port):DSH 世界与备忘录 hexagon 之间的契约。
|
|
2
|
+
*
|
|
3
|
+
* browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client
|
|
4
|
+
* 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。
|
|
5
|
+
* 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const RPC_CHANNEL: "/ilife-memo";
|
|
8
|
+
export declare const RPC_ENDPOINT_READ: "read";
|
|
9
|
+
/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-memo-ilife SKILL.md)。 */
|
|
10
|
+
export interface ReadPayload {
|
|
11
|
+
readonly key: string;
|
|
12
|
+
readonly params: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface RpcError {
|
|
15
|
+
readonly code: string;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
readonly details: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export type RpcResult = {
|
|
20
|
+
readonly ok: true;
|
|
21
|
+
readonly value: unknown;
|
|
22
|
+
} | {
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly error: RpcError;
|
|
25
|
+
};
|
|
26
|
+
export declare function ok(value: unknown): RpcResult;
|
|
27
|
+
export declare function fail(code: string, message: string): RpcResult;
|
|
28
|
+
/** 载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */
|
|
29
|
+
export declare function parseReadPayload(raw: unknown): ReadPayload | null;
|
|
30
|
+
/** 面板默认读键:memo.search 无参直读,空库安全(items []、total 0)。 */
|
|
31
|
+
export declare const DEFAULT_READ_KEY: "memo.search";
|
|
32
|
+
/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */
|
|
33
|
+
export declare function isRpcResult(raw: unknown): raw is RpcResult;
|
|
34
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAG,aAAsB,CAAC;AAClD,eAAO,MAAM,iBAAiB,EAAG,MAAe,CAAC;AAEjD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAErD,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAE5C;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAE7D;AAED,iDAAiD;AACjD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAMjE;AAED,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,EAAG,aAAsB,CAAC;AAEvD,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,SAAS,CAI1D"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** dsh-memo-ilife 端口(port):DSH 世界与备忘录 hexagon 之间的契约。
|
|
2
|
+
*
|
|
3
|
+
* browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client
|
|
4
|
+
* 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。
|
|
5
|
+
* 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。
|
|
6
|
+
*/
|
|
7
|
+
export const RPC_CHANNEL = '/ilife-memo';
|
|
8
|
+
export const RPC_ENDPOINT_READ = 'read';
|
|
9
|
+
export function ok(value) {
|
|
10
|
+
return { ok: true, value };
|
|
11
|
+
}
|
|
12
|
+
export function fail(code, message) {
|
|
13
|
+
return { ok: false, error: { code, message, details: {} } };
|
|
14
|
+
}
|
|
15
|
+
/** 载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */
|
|
16
|
+
export function parseReadPayload(raw) {
|
|
17
|
+
if (typeof raw !== 'object' || raw === null)
|
|
18
|
+
return null;
|
|
19
|
+
const { key, params } = raw;
|
|
20
|
+
if (typeof key !== 'string' || key.length === 0)
|
|
21
|
+
return null;
|
|
22
|
+
if (typeof params !== 'object' || params === null || Array.isArray(params))
|
|
23
|
+
return null;
|
|
24
|
+
return { key, params: params };
|
|
25
|
+
}
|
|
26
|
+
/** 面板默认读键:memo.search 无参直读,空库安全(items []、total 0)。 */
|
|
27
|
+
export const DEFAULT_READ_KEY = 'memo.search';
|
|
28
|
+
/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */
|
|
29
|
+
export function isRpcResult(raw) {
|
|
30
|
+
if (typeof raw !== 'object' || raw === null)
|
|
31
|
+
return false;
|
|
32
|
+
const ok = raw.ok;
|
|
33
|
+
return ok === true || ok === false;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,aAAsB,CAAC;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAe,CAAC;AAkBjD,MAAM,UAAU,EAAE,CAAC,KAAc;IAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,OAAe;IAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAA0C,CAAC;IACnE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACxF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAiC,EAAE,CAAC;AAC5D,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAsB,CAAC;AAEvD,iDAAiD;AACjD,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,EAAE,GAAI,GAAwB,CAAC,EAAE,CAAC;IACxC,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** DSH ctx 最小镜像:只含本仓实际使用的面(type-only,构建期擦除,零运行时)。
|
|
2
|
+
*
|
|
3
|
+
* 每条成员的用法出处见 docs/agents/dsh-client-contract.md(附源码路径+行)。
|
|
4
|
+
* 禁止加镜外成员:要用新能力,先在 cookbook 落出处,再加镜像。用 `import type` 引用本文件。
|
|
5
|
+
* skills 面出处见 cookbook §12(#56 卡路里样板,badge 同形;#150 记账/#218 大厨同形)。
|
|
6
|
+
*/
|
|
7
|
+
export interface SlotsRegisterOptions {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly id?: string;
|
|
10
|
+
readonly order?: number;
|
|
11
|
+
readonly label?: string | (() => string);
|
|
12
|
+
readonly locale?: string;
|
|
13
|
+
readonly inject?: () => Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface SlotsFace {
|
|
16
|
+
inject(key: string, callback: () => (() => void) | Iterable<() => void>): () => void;
|
|
17
|
+
register(options: SlotsRegisterOptions, component: unknown): () => void;
|
|
18
|
+
}
|
|
19
|
+
export type RpcCallResult = {
|
|
20
|
+
readonly ok: true;
|
|
21
|
+
readonly value: unknown;
|
|
22
|
+
} | {
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly error: {
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
readonly details: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export interface RpcCallFace {
|
|
31
|
+
(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<RpcCallResult>;
|
|
32
|
+
}
|
|
33
|
+
export interface ClientCtx {
|
|
34
|
+
readonly slots: SlotsFace;
|
|
35
|
+
readonly connection?: {
|
|
36
|
+
readonly rpc?: {
|
|
37
|
+
readonly call: RpcCallFace;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
effect(callback: () => ((() => void) | void), label?: string): () => void;
|
|
41
|
+
get?(name: string): unknown;
|
|
42
|
+
}
|
|
43
|
+
export type RpcHandler = (endpoint: string, payload: unknown, signal?: AbortSignal) => Promise<unknown>;
|
|
44
|
+
/** 打包技能提供方镜像(cookbook §12,badge 同形;type-only,零运行时)。
|
|
45
|
+
*
|
|
46
|
+
* 出处:`ctx.skills.registerProvider(create)`(`dsh-skill/lib/index.js:147`);
|
|
47
|
+
* candidate 校验红线见 `validateCandidate`(同文件 `:452`)——`provider` 须等于注册名、
|
|
48
|
+
* `description` 非空、`rank` 有限数;`get` 回定义须与候选同名(同文件 `:259`)。
|
|
49
|
+
*/
|
|
50
|
+
export interface SkillInvocationPolicy {
|
|
51
|
+
readonly modelInvocable: boolean;
|
|
52
|
+
readonly userInvocable: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface SkillCandidate {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly description: string;
|
|
57
|
+
readonly invocation: SkillInvocationPolicy;
|
|
58
|
+
readonly provider: string;
|
|
59
|
+
readonly source: string;
|
|
60
|
+
readonly rank: number;
|
|
61
|
+
readonly locator: unknown;
|
|
62
|
+
readonly resourceBase?: {
|
|
63
|
+
readonly kind: 'directory';
|
|
64
|
+
readonly path: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export interface SkillDefinition {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly description: string;
|
|
70
|
+
readonly invocation: SkillInvocationPolicy;
|
|
71
|
+
readonly provider: string;
|
|
72
|
+
readonly source: string;
|
|
73
|
+
readonly resourceBase?: {
|
|
74
|
+
readonly kind: 'directory';
|
|
75
|
+
readonly path: string;
|
|
76
|
+
};
|
|
77
|
+
readonly content: string;
|
|
78
|
+
}
|
|
79
|
+
export interface SkillProvider {
|
|
80
|
+
readonly name: string;
|
|
81
|
+
list(options?: unknown): Promise<readonly SkillCandidate[]>;
|
|
82
|
+
get(candidate: SkillCandidate, options?: unknown): Promise<SkillDefinition | undefined>;
|
|
83
|
+
}
|
|
84
|
+
export interface SkillsFace {
|
|
85
|
+
registerProvider(create: (control: {
|
|
86
|
+
readonly signal: AbortSignal;
|
|
87
|
+
invalidate(): void;
|
|
88
|
+
}) => SkillProvider): () => void;
|
|
89
|
+
}
|
|
90
|
+
/** 本插件用到的宿主面(apply 入参)。
|
|
91
|
+
*
|
|
92
|
+
* `connection` 面:#80 起本插件走的是 DSH 公开的 `/api` 载体 `ctx.connection.fetch.register`
|
|
93
|
+
* (见 `src/index.ts` 的拆雷注释与 `docs/agents/plugin-webserver-inject.md`),不再是早期脚手架的
|
|
94
|
+
* `connection.rpc.handle`。此前镜像一直停在旧那一版(复审 F 的 S3)——现照**实现**对齐;
|
|
95
|
+
* `rpc` 降为可选,因为 `contract.ts` 的信封仍按 RPC 语义命名(`RpcResult`/`RpcHandler`)。
|
|
96
|
+
*/
|
|
97
|
+
export interface ConnectionFetchRegisterOptions {
|
|
98
|
+
readonly path: string;
|
|
99
|
+
readonly methods?: readonly string[];
|
|
100
|
+
readonly requestBody?: string;
|
|
101
|
+
fetch(request: unknown): Promise<Response> | Response;
|
|
102
|
+
}
|
|
103
|
+
export interface HostCtx {
|
|
104
|
+
readonly connection: {
|
|
105
|
+
readonly fetch: {
|
|
106
|
+
register(options: ConnectionFetchRegisterOptions): () => void;
|
|
107
|
+
};
|
|
108
|
+
readonly rpc?: {
|
|
109
|
+
handle(channel: string, handler: RpcHandler): () => void;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
readonly skills: SkillsFace;
|
|
113
|
+
effect(callback: () => ((() => void) | void), label?: string): () => void;
|
|
114
|
+
readonly logger?: unknown;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=dsh-ctx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsh-ctx.d.ts","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"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"}
|
package/dist/dsh-ctx.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsh-ctx.js","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* 形态:cordis 插件(name/inject/apply)+ dsh.bundle.patch 装配行。
|
|
4
|
-
* 单品硬依赖总管(dependencies,非 peer,见 package.json);设置页住本包。
|
|
5
|
-
*/
|
|
1
|
+
import type { HostCtx } from './dsh-ctx.js';
|
|
6
2
|
export declare const name = "dsh-memo-ilife";
|
|
7
3
|
export declare const inject: readonly string[];
|
|
8
|
-
export declare function apply(
|
|
4
|
+
export declare function apply(ctx: HostCtx): void;
|
|
9
5
|
export { SKILL, SLOT_ID, SLOT_ORDER, SLOT_TITLE, PLUGIN, MANAGER_PLUGIN, slotDescriptor, TAB_COMPONENT, registerSingle, openSingle } from './slot.js';
|
|
10
6
|
export type { SlotDescriptor, TabsPort } from './slot.js';
|
|
11
7
|
export { SETTINGS_OWNER, SETTINGS_SLOT, SETTING_ROWS } from './settings.js';
|
|
12
8
|
export type { SettingRow } from './settings.js';
|
|
13
|
-
export { SKILL_PACKAGE, SKILL_CLI, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
|
|
14
|
-
export {
|
|
15
|
-
export type {
|
|
9
|
+
export { SKILL_PACKAGE, SKILL_CLI, SKILL_CLI_REL, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
|
|
10
|
+
export { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, ok, fail, parseReadPayload } from './contract.js';
|
|
11
|
+
export type { ReadPayload, RpcError, RpcResult } from './contract.js';
|
|
12
|
+
export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, parseSkillText, provider as skillProvider } from './skill-provider.js';
|
|
13
|
+
export type { SkillCandidate, SkillDefinition, SkillProvider, SkillInvocationPolicy, SkillsFace } from './dsh-ctx.js';
|
|
16
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,IAAI,mBAAmB,CAAC;AACrC,eAAO,MAAM,MAAM,EAAE,SAAS,MAAM,EAA0C,CAAC;AAqB/E,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAoDxC;AAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACtJ,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvM,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC7G,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAMtE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACrJ,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,106 @@
|
|
|
1
|
-
/** dsh-memo-ilife host
|
|
1
|
+
/** dsh-memo-ilife host 适配器(六边形:port=contract,adapter=本文件+bridge)。
|
|
2
2
|
*
|
|
3
|
-
* 形态:cordis 插件(name/inject/apply
|
|
3
|
+
* 形态:cordis 插件(name/inject/apply)。RPC 通道与信封由 contract 定义,
|
|
4
|
+
* apply 真注册通道,取数只经 bridge.readViaCli(spawn 技能 CLI),
|
|
5
|
+
* 从不 import 任何技能实现。
|
|
4
6
|
* 单品硬依赖总管(dependencies,非 peer,见 package.json);设置页住本包。
|
|
7
|
+
*
|
|
8
|
+
* #232:`inject` 加 `skills`,`apply` 注册**打包技能提供方**(见 skill-provider.ts)——
|
|
9
|
+
* DSH 里的 agent 由此知道有 `skill-memo-ilife` 这个技能(名+介绍,可按需读全文调 CLI)。
|
|
10
|
+
* 提供方是宿主按名去重的单例:重装配时退让(照 #56 卡路里/#150 记账/#218 大厨样板),他错重抛。
|
|
5
11
|
*/
|
|
12
|
+
import { PROVIDER_NAME, provider as skillProvider } from './skill-provider.js';
|
|
13
|
+
import { RPC_CHANNEL, RPC_ENDPOINT_READ, ok, fail, parseReadPayload } from './contract.js';
|
|
14
|
+
import { SkillBridgeError, readViaCli } from './bridge.js';
|
|
6
15
|
export const name = 'dsh-memo-ilife';
|
|
7
|
-
export const inject = [];
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
export const inject = ['connection', 'webServer', 'skills'];
|
|
17
|
+
/** RPC 处理函数:endpoint 分发 → 载荷校验 → readViaCli → 信封包装(companion rpc.ts 同形)。 */
|
|
18
|
+
const handleMemoRpc = async (endpoint, payload) => {
|
|
19
|
+
if (endpoint !== RPC_ENDPOINT_READ)
|
|
20
|
+
return fail('bad-request', `未知端点:${String(endpoint)}`);
|
|
21
|
+
const parsed = parseReadPayload(payload ?? {});
|
|
22
|
+
if (!parsed)
|
|
23
|
+
return fail('bad-request', '载荷须为 {key: string, params: object}');
|
|
24
|
+
try {
|
|
25
|
+
return ok(readViaCli(parsed.key, parsed.params));
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (e instanceof SkillBridgeError)
|
|
29
|
+
return fail(e.code, e.message);
|
|
30
|
+
return fail('internal', e instanceof Error ? e.message : String(e));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export function apply(ctx) {
|
|
34
|
+
const loggerSource = ctx?.logger;
|
|
35
|
+
const logger = (typeof loggerSource === 'function'
|
|
36
|
+
? loggerSource(name)
|
|
37
|
+
: loggerSource) ?? console;
|
|
38
|
+
// #232:注册打包技能提供方——agent 的技能表由此看得见 skill-memo-ilife(名+介绍)。
|
|
39
|
+
try {
|
|
40
|
+
ctx.skills.registerProvider(() => skillProvider);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// 提供方是宿主按名去重的单例:重装配时上一实例可能已注册,此时退让;他错重抛。
|
|
44
|
+
if (!String(error?.message ?? error).includes('already registered'))
|
|
45
|
+
throw error;
|
|
46
|
+
logger.warn?.('[dsh-memo-ilife] skill provider ' + PROVIDER_NAME + ' already registered by another instance; yielding');
|
|
47
|
+
}
|
|
48
|
+
// #80:迁移到 DSH 公开的 /api 载体(ctx.connection.fetch.register)。
|
|
49
|
+
// 旧写法 ctx.connection.rpc.handle() 会以 connection 服务自身的 Context 去调
|
|
50
|
+
// webServer.register 注册前缀路由,而那个 Context 没有 webServer 注入 → 装配期必抛
|
|
51
|
+
// cannot get property "webServer" without inject(实测:给本插件加 webServer 声明也无效)。
|
|
52
|
+
// 参考实现:@xmanrui/dsh-im 的 plugin-src/management-rpc.mjs(上游 503a24a 的改道)。
|
|
53
|
+
const conn = ctx.connection;
|
|
54
|
+
const reply = (rpcId, result) => Response.json({ type: 'server-response', rpcId, result });
|
|
55
|
+
try {
|
|
56
|
+
const dispose = conn.fetch.register({
|
|
57
|
+
path: '/api' + RPC_CHANNEL,
|
|
58
|
+
methods: ['POST'],
|
|
59
|
+
requestBody: 'buffered',
|
|
60
|
+
async fetch(request) {
|
|
61
|
+
if (request.method !== 'POST')
|
|
62
|
+
return new Response('method not allowed', { status: 405 });
|
|
63
|
+
let message;
|
|
64
|
+
try {
|
|
65
|
+
message = await request.json();
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return new Response('body is not JSON', { status: 400 });
|
|
69
|
+
}
|
|
70
|
+
const rpcId = typeof message?.rpcId === 'string' ? message.rpcId : 'invalid-request';
|
|
71
|
+
const call = message?.payload;
|
|
72
|
+
if (message?.type !== 'client-request' || typeof message.rpcId !== 'string'
|
|
73
|
+
|| message.method !== RPC_CHANNEL.slice(1) || !call || typeof call.method !== 'string'
|
|
74
|
+
|| !Object.hasOwn(call, 'payload')) {
|
|
75
|
+
return reply(rpcId, { ok: false, error: { code: 'gateway/bad-request', message: 'Invalid memo request.', details: {} } });
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
return reply(rpcId, await handleMemoRpc(call.method, call.payload));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return new Response('memo handler failed', { status: 500 });
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
ctx.effect(() => () => dispose(), 'dsh-memo-ilife: fetch route cleanup');
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// 通道是宿主共享单例:重装配时上一实例可能已注册,此时退让(照抄 companion),他错重抛。
|
|
89
|
+
if (/(duplicate prefix route|already registered)/.test(String(error?.message ?? error))) {
|
|
90
|
+
logger.warn?.('[dsh-memo-ilife] rpc channel ' + RPC_CHANNEL + ' already registered by another instance; yielding');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
10
95
|
}
|
|
11
96
|
export { SKILL, SLOT_ID, SLOT_ORDER, SLOT_TITLE, PLUGIN, MANAGER_PLUGIN, slotDescriptor, TAB_COMPONENT, registerSingle, openSingle } from './slot.js';
|
|
12
97
|
export { SETTINGS_OWNER, SETTINGS_SLOT, SETTING_ROWS } from './settings.js';
|
|
13
|
-
export { SKILL_PACKAGE, SKILL_CLI, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
|
|
14
|
-
export {
|
|
98
|
+
export { SKILL_PACKAGE, SKILL_CLI, SKILL_CLI_REL, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
|
|
99
|
+
export { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, ok, fail, parseReadPayload } from './contract.js';
|
|
100
|
+
// 宿主**不**导出 `./client.js` 的值也不引用它的类型(#218 拆雷):客户端产物是 **loader 工厂包**
|
|
101
|
+
// (`window.__ModuleLoader__.load({id, factory})` 的 CJS,由 tsdown 打),不是 ESM 模块——
|
|
102
|
+
// 宿主 `export … from './client.js'` 会让插件树在启动期报
|
|
103
|
+
// 「The requested module './client.js' does not provide an export named 'CLIENT_COMPONENT'」而整棵树起不来;
|
|
104
|
+
// 连 type-only 引用也会把 client.ts 拉进宿主 `tsc -b` 的编译程序,把 loader 工厂包覆写成裸 ESM。
|
|
105
|
+
export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, parseSkillText, provider as skillProvider } from './skill-provider.js';
|
|
15
106
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SkillProvider } from './dsh-ctx.js';
|
|
2
|
+
/** 注册表内的提供方名(bundling 插件;candidate.provider 须与此一致,否则校验抛)。 */
|
|
3
|
+
export declare const PROVIDER_NAME: "dsh-memo-ilife";
|
|
4
|
+
/** 技能名(与 `packages/skill-memo-ilife/SKILL.md` frontmatter `name` 同值,由 test 逐字锁)。 */
|
|
5
|
+
export declare const SKILL_NAME: "skill-memo-ilife";
|
|
6
|
+
/** 打包技能标准优先级(与宿主 `BUNDLED_SKILL_RANK` 同值,内联,零依赖)。 */
|
|
7
|
+
export declare const BUNDLED_SKILL_RANK: 600;
|
|
8
|
+
export declare const SKILL_FILE: "SKILL.md";
|
|
9
|
+
/** 按包名定位技能包根目录(安装态 `node_modules/skill-memo-ilife`,单仓 dev 态 workspace 链接)。 */
|
|
10
|
+
export declare function skillDir(): string;
|
|
11
|
+
interface ParsedSkill {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly description: string;
|
|
14
|
+
readonly body: string;
|
|
15
|
+
}
|
|
16
|
+
/** 最小 frontmatter 解析(宿主零依赖,不引 yaml;缺头/缺字段返回 null,由调用方按缺席记)。
|
|
17
|
+
* name 正则放行连字符(`skill-memo-ilife`)。 */
|
|
18
|
+
export declare function parseSkillText(text: string): ParsedSkill | null;
|
|
19
|
+
/** badge 同形 provider(`list` 给摘要,`get` 给全文;`get` 只认名,忽略 locator 外的候选字段)。 */
|
|
20
|
+
export declare const provider: SkillProvider;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=skill-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-provider.d.ts","sourceRoot":"","sources":["../src/skill-provider.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAmC,aAAa,EAAE,MAAM,cAAc,CAAC;AAGnF,6DAA6D;AAC7D,eAAO,MAAM,aAAa,EAAG,gBAAyB,CAAC;AAEvD,oFAAoF;AACpF,eAAO,MAAM,UAAU,EAAG,kBAA2B,CAAC;AAEtD,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,EAAG,GAAY,CAAC;AAE/C,eAAO,MAAM,UAAU,EAAG,UAAmB,CAAC;AAE9C,8EAA8E;AAC9E,wBAAgB,QAAQ,IAAI,MAAM,CAGjC;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;wCACwC;AACxC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAyB/D;AAqDD,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,aAItB,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** dsh-memo-ilife 打包技能提供方(#232 备忘录线,照 #150 记账/#218 大厨样板同形)。
|
|
2
|
+
*
|
|
3
|
+
* 形态对照 `dsh-skill-badge`(出处见 `docs/agents/dsh-client-contract.md` §12):
|
|
4
|
+
* cordis 侧 `inject` 加 `skills`(见 index.ts),本文件只提供 provider 对象,
|
|
5
|
+
* 由 `apply` 经 `ctx.skills.registerProvider(() => provider)` 注册。
|
|
6
|
+
*
|
|
7
|
+
* 单份 SKILL.md 按包名解析(`createRequire.resolve('skill-memo-ilife/package.json')`
|
|
8
|
+
* 再拼 `SKILL.md`,**不复制**,避免双份腐化;不走 `exports` 子路径,免补 `./SKILL.md` 导出);
|
|
9
|
+
* `name` 用 `skill-memo-ilife`(与 SKILL.md frontmatter 同值,描述取文件实测值,不在插件内硬编码第二份);
|
|
10
|
+
* `rank` 内联 600(宿主 `BUNDLED_SKILL_RANK` 同值,不从宿主 import,保持零依赖);
|
|
11
|
+
* `source` 为 `bundled`;`content` 取 frontmatter 后正文(filesystem `parseSkillFile` 同形)。
|
|
12
|
+
*
|
|
13
|
+
* 本文件只读消费技能包的 SKILL.md(文本),从不 import 任何技能实现。
|
|
14
|
+
*/
|
|
15
|
+
import { readFile } from 'node:fs/promises';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
import { SKILL_PACKAGE } from './bridge.js';
|
|
19
|
+
/** 注册表内的提供方名(bundling 插件;candidate.provider 须与此一致,否则校验抛)。 */
|
|
20
|
+
export const PROVIDER_NAME = 'dsh-memo-ilife';
|
|
21
|
+
/** 技能名(与 `packages/skill-memo-ilife/SKILL.md` frontmatter `name` 同值,由 test 逐字锁)。 */
|
|
22
|
+
export const SKILL_NAME = 'skill-memo-ilife';
|
|
23
|
+
/** 打包技能标准优先级(与宿主 `BUNDLED_SKILL_RANK` 同值,内联,零依赖)。 */
|
|
24
|
+
export const BUNDLED_SKILL_RANK = 600;
|
|
25
|
+
export const SKILL_FILE = 'SKILL.md';
|
|
26
|
+
/** 按包名定位技能包根目录(安装态 `node_modules/skill-memo-ilife`,单仓 dev 态 workspace 链接)。 */
|
|
27
|
+
export function skillDir() {
|
|
28
|
+
const pkgJson = createRequire(import.meta.url).resolve(SKILL_PACKAGE + '/package.json');
|
|
29
|
+
return dirname(pkgJson);
|
|
30
|
+
}
|
|
31
|
+
/** 最小 frontmatter 解析(宿主零依赖,不引 yaml;缺头/缺字段返回 null,由调用方按缺席记)。
|
|
32
|
+
* name 正则放行连字符(`skill-memo-ilife`)。 */
|
|
33
|
+
export function parseSkillText(text) {
|
|
34
|
+
const normalized = text.replace(/\r\n/g, '\n');
|
|
35
|
+
if (!normalized.startsWith('---\n'))
|
|
36
|
+
return null;
|
|
37
|
+
const lines = normalized.split('\n');
|
|
38
|
+
const end = lines.indexOf('---', 1);
|
|
39
|
+
if (end < 2)
|
|
40
|
+
return null;
|
|
41
|
+
const data = {};
|
|
42
|
+
for (const ln of lines.slice(1, end)) {
|
|
43
|
+
const m = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(ln);
|
|
44
|
+
if (!m)
|
|
45
|
+
return null;
|
|
46
|
+
let v = (m[2] ?? '').trim();
|
|
47
|
+
if (v.length >= 2 && ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))) {
|
|
48
|
+
v = v.slice(1, -1);
|
|
49
|
+
}
|
|
50
|
+
data[m[1]] = v;
|
|
51
|
+
}
|
|
52
|
+
const name = data['name'];
|
|
53
|
+
const description = data['description'];
|
|
54
|
+
if (!name || !description)
|
|
55
|
+
return null;
|
|
56
|
+
// name 正则**逐字对齐宿主**(`dsh-skill/lib/index.js:17` 的 `SKILL_NAME`)——不许比宿主宽一格。
|
|
57
|
+
// 宽一格的后果不是「这个技能坏了」:不合格候选会在宿主 `validateCandidate`(`dsh-skill/lib/index.js:360`,
|
|
58
|
+
// 该处无 try)抛出 → 一路冒到 `dsh-tool-skill/lib/index.js:207` 每次模型请求的 `ctx.skills.snapshot()`
|
|
59
|
+
// (该文件全文无 try/catch)→ **全机所有会话的技能目录一起塌**。插件与宿主口径不一致时,以宿主为准。
|
|
60
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name))
|
|
61
|
+
return null;
|
|
62
|
+
return { name, description, body: lines.slice(end + 1).join('\n').trim() };
|
|
63
|
+
}
|
|
64
|
+
async function loadSkill() {
|
|
65
|
+
let dir;
|
|
66
|
+
try {
|
|
67
|
+
dir = skillDir();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
let raw;
|
|
73
|
+
try {
|
|
74
|
+
raw = await readFile(join(dir, SKILL_FILE), 'utf8');
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const parsed = parseSkillText(raw);
|
|
80
|
+
if (!parsed)
|
|
81
|
+
return null;
|
|
82
|
+
return { dir, parsed };
|
|
83
|
+
}
|
|
84
|
+
async function listSkills() {
|
|
85
|
+
const loaded = await loadSkill();
|
|
86
|
+
if (!loaded)
|
|
87
|
+
return [];
|
|
88
|
+
return [
|
|
89
|
+
{
|
|
90
|
+
name: loaded.parsed.name,
|
|
91
|
+
description: loaded.parsed.description,
|
|
92
|
+
invocation: { modelInvocable: true, userInvocable: true },
|
|
93
|
+
provider: PROVIDER_NAME,
|
|
94
|
+
source: 'bundled',
|
|
95
|
+
resourceBase: { kind: 'directory', path: loaded.dir },
|
|
96
|
+
rank: BUNDLED_SKILL_RANK,
|
|
97
|
+
locator: { path: join(loaded.dir, SKILL_FILE) },
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
async function getSkill(candidate) {
|
|
102
|
+
const loaded = await loadSkill();
|
|
103
|
+
if (!loaded)
|
|
104
|
+
return undefined;
|
|
105
|
+
// 候选过期(注册后 SKILL.md 改名)按宿主契约失效,不抛。
|
|
106
|
+
if (!candidate || candidate.name !== loaded.parsed.name)
|
|
107
|
+
return undefined;
|
|
108
|
+
return {
|
|
109
|
+
name: loaded.parsed.name,
|
|
110
|
+
description: loaded.parsed.description,
|
|
111
|
+
invocation: { modelInvocable: true, userInvocable: true },
|
|
112
|
+
provider: PROVIDER_NAME,
|
|
113
|
+
source: 'bundled',
|
|
114
|
+
resourceBase: { kind: 'directory', path: loaded.dir },
|
|
115
|
+
content: loaded.parsed.body,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** badge 同形 provider(`list` 给摘要,`get` 给全文;`get` 只认名,忽略 locator 外的候选字段)。 */
|
|
119
|
+
export const provider = {
|
|
120
|
+
name: PROVIDER_NAME,
|
|
121
|
+
list: () => listSkills(),
|
|
122
|
+
get: (candidate) => getSkill(candidate),
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=skill-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-provider.js","sourceRoot":"","sources":["../src/skill-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAyB,CAAC;AAEvD,oFAAoF;AACpF,MAAM,CAAC,MAAM,UAAU,GAAG,kBAA2B,CAAC;AAEtD,qDAAqD;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAY,CAAC;AAE/C,MAAM,CAAC,MAAM,UAAU,GAAG,UAAmB,CAAC;AAE9C,8EAA8E;AAC9E,MAAM,UAAU,QAAQ;IACtB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,GAAG,eAAe,CAAC,CAAC;IACxF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAQD;wCACwC;AACxC,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACxG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAW,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACvC,2EAA2E;IAC3E,+EAA+E;IAC/E,sFAAsF;IACtF,4DAA4D;IAC5D,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,QAAQ,EAAE,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO;QACL;YACE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;YACxB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;YACtC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YACzD,QAAQ,EAAE,aAAa;YACvB,MAAM,EAAE,SAAS;YACjB,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE;YACrD,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE;SAChD;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,SAAyB;IAC/C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,mCAAmC;IACnC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC1E,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;QACxB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;QACtC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QACzD,QAAQ,EAAE,aAAa;QACvB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE;QACrD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;IACxB,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;CACxC,CAAC"}
|
package/dist/slot.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare const SLOT_ORDER: 70;
|
|
|
11
11
|
export declare const SLOT_TITLE: "\u5907\u5FD8\u5F55";
|
|
12
12
|
export declare const PLUGIN: "dsh-memo-ilife";
|
|
13
13
|
export declare const MANAGER_PLUGIN: "dsh-life-pack";
|
|
14
|
+
export declare const SKILL_PACKAGE: "skill-memo-ilife";
|
|
15
|
+
/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
|
|
16
|
+
* 发版 bump 时同步改这里(与 package.json 同值)。 */
|
|
17
|
+
export declare const PLUGIN_VERSION: "0.2.0";
|
|
18
|
+
export declare const SKILL_VERSION: "0.2.0";
|
|
14
19
|
export interface SlotDescriptor {
|
|
15
20
|
readonly skill: string;
|
|
16
21
|
readonly slotId: string;
|
package/dist/slot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,KAAK,EAAG,MAAe,CAAC;AACrC,eAAO,MAAM,OAAO,EAAG,YAAqB,CAAC;AAC7C,eAAO,MAAM,UAAU,EAAG,EAAW,CAAC;AACtC,eAAO,MAAM,UAAU,EAAG,oBAAc,CAAC;AACzC,eAAO,MAAM,MAAM,EAAG,gBAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,EAAG,eAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,KAAK,EAAG,MAAe,CAAC;AACrC,eAAO,MAAM,OAAO,EAAG,YAAqB,CAAC;AAC7C,eAAO,MAAM,UAAU,EAAG,EAAW,CAAC;AACtC,eAAO,MAAM,UAAU,EAAG,oBAAc,CAAC;AACzC,eAAO,MAAM,MAAM,EAAG,gBAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,EAAG,eAAwB,CAAC;AACvD,eAAO,MAAM,aAAa,EAAG,kBAA2B,CAAC;AAEzD;wCACwC;AACxC,eAAO,MAAM,cAAc,EAAG,OAAgB,CAAC;AAC/C,eAAO,MAAM,aAAa,EAAG,OAAgB,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,IAAI,cAAc,CAE/C;AAED,gCAAgC;AAChC,eAAO,MAAM,aAAa;;;CAAiD,CAAC;AAE5E,MAAM,WAAW,QAAQ;IACvB,OAAO,IAAI,OAAO,CAAC;IACnB,WAAW,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,IAAI,CAAC;IAC/J,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChH;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAGlE;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAGnE"}
|
package/dist/slot.js
CHANGED
|
@@ -11,6 +11,11 @@ export const SLOT_ORDER = 70;
|
|
|
11
11
|
export const SLOT_TITLE = '备忘录';
|
|
12
12
|
export const PLUGIN = 'dsh-memo-ilife';
|
|
13
13
|
export const MANAGER_PLUGIN = 'dsh-life-pack';
|
|
14
|
+
export const SKILL_PACKAGE = 'skill-memo-ilife';
|
|
15
|
+
/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
|
|
16
|
+
* 发版 bump 时同步改这里(与 package.json 同值)。 */
|
|
17
|
+
export const PLUGIN_VERSION = '0.2.0';
|
|
18
|
+
export const SKILL_VERSION = '0.2.0';
|
|
14
19
|
export function slotDescriptor() {
|
|
15
20
|
return { skill: SKILL, slotId: SLOT_ID, order: SLOT_ORDER, title: SLOT_TITLE, kind: 'page' };
|
|
16
21
|
}
|
package/dist/slot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.js","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAe,CAAC;AACrC,MAAM,CAAC,MAAM,OAAO,GAAG,YAAqB,CAAC;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,EAAW,CAAC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAc,CAAC;AACzC,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,eAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"slot.js","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAe,CAAC;AACrC,MAAM,CAAC,MAAM,OAAO,GAAG,YAAqB,CAAC;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,EAAW,CAAC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAc,CAAC;AACzC,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,eAAwB,CAAC;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,kBAA2B,CAAC;AAEzD;wCACwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,OAAgB,CAAC;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,OAAgB,CAAC;AAU9C,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/F,CAAC;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAW,CAAC;AAQ5E,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;AACzH,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,SAAkB;IAC3D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO;IAC5B,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACxF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-memo-ilife",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "爱生活单品插件 P10 脚手架:备忘录(ilife:memo order 70),硬依赖总管 dsh-life-pack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"node": ">=22.13"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"dsh-life-pack": "
|
|
28
|
+
"dsh-life-pack": "^0.2.0",
|
|
29
|
+
"skill-memo-ilife": "0.2.0"
|
|
29
30
|
},
|
|
30
31
|
"dsh": {
|
|
31
32
|
"bundle": {
|
|
@@ -33,11 +34,22 @@
|
|
|
33
34
|
},
|
|
34
35
|
"client": {
|
|
35
36
|
"platform": "web",
|
|
36
|
-
"inject": [
|
|
37
|
+
"inject": [
|
|
38
|
+
"@deepseek-ai/dsh-client-ui-slots",
|
|
39
|
+
"@deepseek-ai/dsh-client-connection"
|
|
40
|
+
]
|
|
37
41
|
}
|
|
38
42
|
},
|
|
39
43
|
"scripts": {
|
|
40
|
-
"build": "
|
|
44
|
+
"build": "npm run build:host && npm run build:client",
|
|
45
|
+
"build:host": "tsc -b",
|
|
46
|
+
"build:client": "tsdown",
|
|
47
|
+
"typecheck": "tsc -p tsconfig.client.json",
|
|
41
48
|
"test": "node --test test/smoke.test.mjs"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "19.2.18",
|
|
52
|
+
"react": "19.2.8",
|
|
53
|
+
"tsdown": "0.22.14"
|
|
42
54
|
}
|
|
43
55
|
}
|
package/dist/client.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/** dsh-memo-ilife 客户端存根(P10 脚手架)。
|
|
2
|
-
*
|
|
3
|
-
* 写死槽位原生组件,不做动态按需加载,不做外嵌页。
|
|
4
|
-
* 面板取数只经 host.call 进 host 桥(见 bridge.ts),不 import 技能实现。
|
|
5
|
-
* 缺席纯条件渲染,无轮询(本文件无任何定时器)。
|
|
6
|
-
*/
|
|
7
|
-
import type { TabsPort } from './slot.js';
|
|
8
|
-
export interface HostCaller {
|
|
9
|
-
call(method: string, args: unknown): Promise<unknown>;
|
|
10
|
-
}
|
|
11
|
-
export declare const CLIENT_COMPONENT: {
|
|
12
|
-
readonly kind: "native";
|
|
13
|
-
readonly name: "MemoPanel";
|
|
14
|
-
};
|
|
15
|
-
export declare const CLIENT_METHOD: "ilife.memo.read";
|
|
16
|
-
export declare function mountSingleClient(port: TabsPort): (() => void) | null;
|
|
17
|
-
export declare function openSingleClient(port: TabsPort, sessionId?: string): void;
|
|
18
|
-
export declare function requestReadViaHost(host: HostCaller, key: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
19
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,gBAAgB;;;CAAgB,CAAC;AAC9C,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAE9C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAErE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAExH"}
|