@dsh-enhanced/plugin-control-plane 0.1.4
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/LICENSE +21 -0
- package/README.md +63 -0
- package/bin/dsh-plugin-control.js +8 -0
- package/cordis.patch.yml +7 -0
- package/lib/catalog.d.ts +33 -0
- package/lib/catalog.d.ts.map +1 -0
- package/lib/catalog.js +183 -0
- package/lib/catalog.js.map +1 -0
- package/lib/cli.d.ts +2 -0
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +213 -0
- package/lib/cli.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -0
- package/lib/service.d.ts +32 -0
- package/lib/service.d.ts.map +1 -0
- package/lib/service.js +50 -0
- package/lib/service.js.map +1 -0
- package/lib/tools.d.ts +4 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +14 -0
- package/lib/tools.js.map +1 -0
- package/lib/version.d.ts +2 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +2 -0
- package/lib/version.js.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-enhanced contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @dsh-enhanced/plugin-control-plane
|
|
2
|
+
|
|
3
|
+
用于按能力发现、审批、隔离验证和原子启用 DSH bundle 的控制面。它把“Agent 发现缺口”与“修改正在运行的 profile / 源码”严格分开。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
dsh plugin --profile web add @dsh-enhanced/plugin-control-plane
|
|
9
|
+
dsh --profile web --dump-config
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 配置与使用
|
|
13
|
+
|
|
14
|
+
首次使用无需先下载目录:若默认路径 `~/.dsh/plugin-control/catalog.json` 不存在,运行时会使用包内的首方、只读、完整性固定目录(coding provider、health、heartbeat、event triggers、Memory/Wiki bridge、Lark 与 supervised evolution)。该目录固定到已发布的 npm `0.1.3` tarball,不是浮动的 latest 查询,也不会由 Agent 更新。
|
|
15
|
+
|
|
16
|
+
owner 可在默认路径放置自己的 catalog;它会完全取代首方目录。每条记录都需要精确 npm 版本、`sha512-...` 完整性、精确 DSH baseline、能力标签和权限摘要。`requires` 可声明必须一同启用的顶层 bundle,例如 Lark channel 的 Delivery 与 credential bundle:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"schemaVersion": 1,
|
|
21
|
+
"entries": [{
|
|
22
|
+
"id": "memory-wiki-bridge",
|
|
23
|
+
"capabilities": ["memory knowledge promotion"],
|
|
24
|
+
"package": "@dsh-enhanced/memory-wiki-bridge",
|
|
25
|
+
"version": "0.1.3",
|
|
26
|
+
"integrity": "sha512-REPLACE_WITH_NPM_DIST_INTEGRITY",
|
|
27
|
+
"requires": [],
|
|
28
|
+
"authorities": ["filesystem: DSH home only"],
|
|
29
|
+
"dshBaseline": "0.1.0-rc.8"
|
|
30
|
+
}]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Agent 可调用 `plugin_discover` 自动查找候选项,或用 `plugin_activation_plan` 生成**只读待审批计划**。两个工具都不会下载、安装、修改或重启任何东西。
|
|
35
|
+
|
|
36
|
+
owner 在审阅完整 package/version/integrity/authority 后,才可使用不向 Agent 注册的本地 CLI:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
dsh-plugin-control discover --capability 'knowledge promotion'
|
|
40
|
+
dsh-plugin-control approve --plan ~/.dsh/plugin-control/plans/plugin-....json --approved-by owner@example
|
|
41
|
+
dsh-plugin-control activate --plan ~/.dsh/plugin-control/plans/plugin-....json --dsh-home ~/.dsh
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`activate` 先核对当前 DSH 精确版本,再复制 profile 到隔离 staging profile,安装候选和全部 `requires` 的精确版本、核对 pnpm lock 中每个完整性、执行 `dsh --dump-config`,然后通过同一父目录内的 rename 原子替换目标 profile。替换后的最终组合校验失败会自动恢复原 profile;成功后仍由 owner 使用 `scripts/install/restart.sh` 重启常驻服务。
|
|
45
|
+
|
|
46
|
+
新建或修改插件绝不在生产 checkout 中进行:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
dsh-plugin-control scaffold --owner-approved --repository ../dsh-enhanced-feature-worktree --name my-plugin
|
|
50
|
+
dsh-plugin-control verify-worktree --owner-approved --repository ../dsh-enhanced-feature-worktree
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
两者只接受 linked Git worktree,创建要求干净 worktree;验证运行 `git diff --check` 与 `pnpm check`。之后仍需正常 code review、PR、发布和上述启用流程。
|
|
54
|
+
|
|
55
|
+
## 权限与数据
|
|
56
|
+
|
|
57
|
+
- 运行时 plugin 只读取 owner 配置的本地 catalog,并在 `statePath` 写入受限的待审批 plan;无网络、凭据、浏览器或子进程权限。
|
|
58
|
+
- 本地 CLI 的 `activate` 才会调用 `dsh`、复制/rename profile;它需要 owner 明确执行,且不暴露为 Agent tool。CLI 不读取或输出凭据。
|
|
59
|
+
- `scaffold` / `verify-worktree` 只在 owner 传入 `--owner-approved` 的 linked Git worktree 中运行 pnpm/git;它们不会改动主 checkout、生产 profile 或已发布包。
|
|
60
|
+
|
|
61
|
+
## 兼容性
|
|
62
|
+
|
|
63
|
+
See the repository [compatibility baseline](../../docs/compatibility.md).
|
package/cordis.patch.yml
ADDED
package/lib/catalog.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface CatalogEntry {
|
|
2
|
+
id: string;
|
|
3
|
+
capabilities: string[];
|
|
4
|
+
package: string;
|
|
5
|
+
version: string;
|
|
6
|
+
integrity: string;
|
|
7
|
+
/** Additional top-level bundles that must be installed with this candidate. */
|
|
8
|
+
requires: readonly CatalogPackage[];
|
|
9
|
+
authorities: string[];
|
|
10
|
+
dshBaseline: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CatalogPackage {
|
|
13
|
+
package: string;
|
|
14
|
+
version: string;
|
|
15
|
+
integrity: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CapabilityCatalog {
|
|
18
|
+
schemaVersion: 1;
|
|
19
|
+
entries: CatalogEntry[];
|
|
20
|
+
}
|
|
21
|
+
export declare function parseCatalog(value: unknown): CapabilityCatalog;
|
|
22
|
+
export declare function loadCatalog(path: string): Promise<CapabilityCatalog>;
|
|
23
|
+
/**
|
|
24
|
+
* Curated first-party candidates make a new core installation immediately
|
|
25
|
+
* useful without granting an Agent registry, network, or activation access.
|
|
26
|
+
* They deliberately remain pinned to a previously published, immutable npm
|
|
27
|
+
* release. An owner-created catalog at Config.catalogPath replaces this list.
|
|
28
|
+
*/
|
|
29
|
+
export declare const firstPartyCatalog: CapabilityCatalog;
|
|
30
|
+
export declare function loadCatalogWithFirstPartyFallback(path: string): Promise<CapabilityCatalog>;
|
|
31
|
+
export declare function discover(catalog: CapabilityCatalog, capability: string): CatalogEntry[];
|
|
32
|
+
export declare function candidateDigest(entry: CatalogEntry, profile: string): string;
|
|
33
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,+EAA+E;IAC/E,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAA;IACnC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAAG,aAAa,EAAE,CAAC,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE;AA8ChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAkB9D;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAI1E;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBA8E9B,CAAA;AAEF,wBAAsB,iCAAiC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAOhG;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAOvF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5E"}
|
package/lib/catalog.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
const idPattern = /^[a-z0-9][a-z0-9-]{0,63}$/u;
|
|
4
|
+
const packagePattern = /^@[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/u;
|
|
5
|
+
const versionPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?$/u;
|
|
6
|
+
const integrityPattern = /^sha512-[A-Za-z0-9+/=]+$/u;
|
|
7
|
+
function text(value, label) {
|
|
8
|
+
if (typeof value !== 'string' || value.normalize('NFC').trim() === '')
|
|
9
|
+
throw new Error(`plugin-control-plane: ${label} must be a non-empty string`);
|
|
10
|
+
return value.normalize('NFC').trim();
|
|
11
|
+
}
|
|
12
|
+
function textList(value, label) {
|
|
13
|
+
if (!Array.isArray(value) || value.length === 0 || value.some(item => typeof item !== 'string' || item.trim() === '')) {
|
|
14
|
+
throw new Error(`plugin-control-plane: ${label} must be a non-empty string array`);
|
|
15
|
+
}
|
|
16
|
+
return [...new Set(value.map(item => item.normalize('NFC').trim()))].sort();
|
|
17
|
+
}
|
|
18
|
+
function catalogPackage(value, label) {
|
|
19
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
20
|
+
throw new Error(`plugin-control-plane: ${label} must be an object`);
|
|
21
|
+
}
|
|
22
|
+
const item = value;
|
|
23
|
+
const packageName = text(item.package, `${label}.package`);
|
|
24
|
+
const version = text(item.version, `${label}.version`);
|
|
25
|
+
const integrity = text(item.integrity, `${label}.integrity`);
|
|
26
|
+
if (!packagePattern.test(packageName) || !versionPattern.test(version) || !integrityPattern.test(integrity)) {
|
|
27
|
+
throw new Error(`plugin-control-plane: ${label} must pin package, exact version, and sha512 integrity`);
|
|
28
|
+
}
|
|
29
|
+
return Object.freeze({ package: packageName, version, integrity });
|
|
30
|
+
}
|
|
31
|
+
function catalogRequirements(value, primary, label) {
|
|
32
|
+
if (value === undefined)
|
|
33
|
+
return Object.freeze([]);
|
|
34
|
+
if (!Array.isArray(value))
|
|
35
|
+
throw new Error(`plugin-control-plane: ${label}.requires must be an array`);
|
|
36
|
+
const seen = new Set([primary.package]);
|
|
37
|
+
const entries = value.map((raw, index) => {
|
|
38
|
+
const requirement = catalogPackage(raw, `${label}.requires[${index}]`);
|
|
39
|
+
if (seen.has(requirement.package))
|
|
40
|
+
throw new Error(`plugin-control-plane: ${label}.requires contains duplicate package ${requirement.package}`);
|
|
41
|
+
seen.add(requirement.package);
|
|
42
|
+
return requirement;
|
|
43
|
+
});
|
|
44
|
+
return Object.freeze(entries.sort((left, right) => left.package.localeCompare(right.package)));
|
|
45
|
+
}
|
|
46
|
+
export function parseCatalog(value) {
|
|
47
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
48
|
+
throw new Error('plugin-control-plane: catalog must be an object');
|
|
49
|
+
const input = value;
|
|
50
|
+
if (input.schemaVersion !== 1 || !Array.isArray(input.entries))
|
|
51
|
+
throw new Error('plugin-control-plane: unsupported catalog schema');
|
|
52
|
+
const seen = new Set();
|
|
53
|
+
const entries = input.entries.map(raw => {
|
|
54
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
55
|
+
throw new Error('plugin-control-plane: catalog entry must be an object');
|
|
56
|
+
const item = raw;
|
|
57
|
+
const id = text(item.id, 'entry id');
|
|
58
|
+
const primary = catalogPackage(item, id);
|
|
59
|
+
const baseline = text(item.dshBaseline, `${id}.dshBaseline`);
|
|
60
|
+
if (!idPattern.test(id) || seen.has(id))
|
|
61
|
+
throw new Error(`plugin-control-plane: invalid or duplicate entry id ${id}`);
|
|
62
|
+
if (!versionPattern.test(baseline))
|
|
63
|
+
throw new Error(`plugin-control-plane: entry ${id}.dshBaseline must be an exact DSH version`);
|
|
64
|
+
seen.add(id);
|
|
65
|
+
return Object.freeze({ id, ...primary, requires: catalogRequirements(item.requires, primary, id), dshBaseline: baseline,
|
|
66
|
+
capabilities: textList(item.capabilities, `${id}.capabilities`), authorities: textList(item.authorities, `${id}.authorities`) });
|
|
67
|
+
});
|
|
68
|
+
return Object.freeze({ schemaVersion: 1, entries: Object.freeze(entries) });
|
|
69
|
+
}
|
|
70
|
+
export async function loadCatalog(path) {
|
|
71
|
+
const source = await readFile(path, 'utf8');
|
|
72
|
+
if (Buffer.byteLength(source) > 1_048_576)
|
|
73
|
+
throw new Error('plugin-control-plane: catalog exceeds 1 MiB');
|
|
74
|
+
return parseCatalog(JSON.parse(source));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Curated first-party candidates make a new core installation immediately
|
|
78
|
+
* useful without granting an Agent registry, network, or activation access.
|
|
79
|
+
* They deliberately remain pinned to a previously published, immutable npm
|
|
80
|
+
* release. An owner-created catalog at Config.catalogPath replaces this list.
|
|
81
|
+
*/
|
|
82
|
+
export const firstPartyCatalog = parseCatalog({
|
|
83
|
+
schemaVersion: 1,
|
|
84
|
+
entries: [
|
|
85
|
+
{
|
|
86
|
+
id: 'coding-subscription-provider',
|
|
87
|
+
capabilities: ['coding agent', 'codex', 'claude code', 'cursor', 'grok'],
|
|
88
|
+
package: '@dsh-enhanced/coding-subscription-provider', version: '0.1.3',
|
|
89
|
+
integrity: 'sha512-LMyIzx2NJrK7+ExsoB049fkLi4rJncYBU8Mn56ssWNBoW+LqtuzlofymwBHL2In7UPwHG3V+7MxBE0MjkrWmlQ==',
|
|
90
|
+
authorities: ['filesystem: local coding-client credentials', 'subprocess: locally installed coding clients', 'network: configured provider route'],
|
|
91
|
+
dshBaseline: '0.1.0-rc.8',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'traex-acp-provider',
|
|
95
|
+
capabilities: ['coding agent', 'traex', 'acp', 'reasoning effort'],
|
|
96
|
+
package: '@dsh-enhanced/traex-acp-provider', version: '0.1.3',
|
|
97
|
+
integrity: 'sha512-qGoYNAcO/uNHw/WMzOTD6q3Z8hIC7HwMGrp996BrJGB5HpUayuz58oCjyYQQ+caREnb8vESS9DoaW5nOGpB9sA==',
|
|
98
|
+
authorities: ['subprocess: local TraeX ACP client', 'network: TraeX-managed provider route'],
|
|
99
|
+
dshBaseline: '0.1.0-rc.8',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'assistant-health',
|
|
103
|
+
capabilities: ['health', 'readiness', 'liveness', 'diagnostics'],
|
|
104
|
+
package: '@dsh-enhanced/assistant-health', version: '0.1.3',
|
|
105
|
+
integrity: 'sha512-GcNqvjjSul+jrx52dFzxsKASPXUeMDi+ia40DXXI77rZQaqWc6O49iOPCXkrbo43pbsZmCY5cpjb1zLtWLkuQA==',
|
|
106
|
+
authorities: ['read-only: mounted service health and diagnostics'],
|
|
107
|
+
dshBaseline: '0.1.0-rc.8',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: 'assistant-heartbeat',
|
|
111
|
+
capabilities: ['heartbeat', 'proactive check-in', 'active hours'],
|
|
112
|
+
package: '@dsh-enhanced/assistant-heartbeat', version: '0.1.3',
|
|
113
|
+
integrity: 'sha512-wXTOl2LAGg3fvnZ9rxiQTv6w8nxLsjODA74V5QipoYitm2hezx30obPQBWqEtpTym3dvC7AEVBTqgRLDWt+Ycw==',
|
|
114
|
+
authorities: ['persistent schedule state', 'agent invocation during configured active hours'],
|
|
115
|
+
dshBaseline: '0.1.0-rc.8',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'event-triggers',
|
|
119
|
+
capabilities: ['events', 'webhook', 'file watch', 'https polling'],
|
|
120
|
+
package: '@dsh-enhanced/event-triggers', version: '0.1.3',
|
|
121
|
+
integrity: 'sha512-iMl6zwuYwFpqLq0nIGW59mcQlDvu8370ex9FRtTW7WwW5Ab40Hk7cbHTJ2UpZQj0yEBi0lraVD0t7boXopfigg==',
|
|
122
|
+
authorities: ['filesystem: configured watched paths', 'network: configured HTTPS endpoints', 'network ingress: HMAC webhook endpoint'],
|
|
123
|
+
dshBaseline: '0.1.0-rc.8',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'memory-wiki-bridge',
|
|
127
|
+
capabilities: ['memory', 'wiki', 'knowledge promotion'],
|
|
128
|
+
package: '@dsh-enhanced/memory-wiki-bridge', version: '0.1.3',
|
|
129
|
+
integrity: 'sha512-vvsh72xDsxcyUZHT67T/nJgtN+h2uiXVG3ez+BovzFR/owFtLWjELbFZeV2TVvQJARRizcdEFqq6mIawCOovZw==',
|
|
130
|
+
authorities: ['filesystem: configured personal Wiki vault', 'persistent proposal state'],
|
|
131
|
+
dshBaseline: '0.1.0-rc.8',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'lark-assistant',
|
|
135
|
+
capabilities: ['lark', 'feishu', 'chat channel', 'resident assistant'],
|
|
136
|
+
package: '@dsh-enhanced/lark-channel', version: '0.1.3',
|
|
137
|
+
integrity: 'sha512-CWwxX1cW2PYldWz/p3+EMG1VRwu1EzKyFS984sMq/tzY0a1TGjgZsLNOn0EHq2hpwCBdZd861gnmmKTqF7nwng==',
|
|
138
|
+
requires: [
|
|
139
|
+
{ package: '@dsh-enhanced/assistant-delivery', version: '0.1.3', integrity: 'sha512-ZgPV8CYY0L5X7rUHG4b9/ulPlQi5PNnrDi8LPpTPj+y8Mc5oE7bbZQnKpniGkjEftmWK16GRlhx+A9Z00sYsTw==' },
|
|
140
|
+
{ package: '@dsh-enhanced/credentials-keychain', version: '0.1.3', integrity: 'sha512-g8OOFqnDwd0/SRldZmWN6f6FScD1llN+jdjRu4lLmZ1xdQ6nOacEGvUK4l1rCa89xNWkJVFdgQLuOC/e2VbDXw==' },
|
|
141
|
+
],
|
|
142
|
+
authorities: ['network: Lark WebSocket and API', 'credentials: OS keychain/secret store', 'resident process: current-user service'],
|
|
143
|
+
dshBaseline: '0.1.0-rc.8',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'supervised-evolution',
|
|
147
|
+
capabilities: ['supervised growth', 'evolution', 'behaviour guidance'],
|
|
148
|
+
package: '@dsh-enhanced/assistant-evolution', version: '0.1.3',
|
|
149
|
+
integrity: 'sha512-WeerqdqJuqUNqCPb/QtTuvF4amJ3YlS/mJ0QoUlqt5Bygso2nz6K4o2vDF4MaDaIhjpuCR0KTiqFLXXQHAEEEg==',
|
|
150
|
+
requires: [
|
|
151
|
+
{ package: '@dsh-enhanced/assistant-delivery', version: '0.1.3', integrity: 'sha512-ZgPV8CYY0L5X7rUHG4b9/ulPlQi5PNnrDi8LPpTPj+y8Mc5oE7bbZQnKpniGkjEftmWK16GRlhx+A9Z00sYsTw==' },
|
|
152
|
+
{ package: '@dsh-enhanced/credentials-keychain', version: '0.1.3', integrity: 'sha512-g8OOFqnDwd0/SRldZmWN6f6FScD1llN+jdjRu4lLmZ1xdQ6nOacEGvUK4l1rCa89xNWkJVFdgQLuOC/e2VbDXw==' },
|
|
153
|
+
{ package: '@dsh-enhanced/lark-channel', version: '0.1.3', integrity: 'sha512-CWwxX1cW2PYldWz/p3+EMG1VRwu1EzKyFS984sMq/tzY0a1TGjgZsLNOn0EHq2hpwCBdZd861gnmmKTqF7nwng==' },
|
|
154
|
+
{ package: '@dsh-enhanced/traex-acp-provider', version: '0.1.3', integrity: 'sha512-qGoYNAcO/uNHw/WMzOTD6q3Z8hIC7HwMGrp996BrJGB5HpUayuz58oCjyYQQ+caREnb8vESS9DoaW5nOGpB9sA==' },
|
|
155
|
+
],
|
|
156
|
+
authorities: ['network: Lark approval channel', 'credentials: OS keychain/secret store', 'subprocess: local TraeX ACP client', 'persistent guidance and approval state'],
|
|
157
|
+
dshBaseline: '0.1.0-rc.8',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
export async function loadCatalogWithFirstPartyFallback(path) {
|
|
162
|
+
try {
|
|
163
|
+
return await loadCatalog(path);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT')
|
|
167
|
+
return firstPartyCatalog;
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export function discover(catalog, capability) {
|
|
172
|
+
const terms = capability.normalize('NFC').toLocaleLowerCase('en-US').trim().split(/\s+/u).filter(Boolean);
|
|
173
|
+
if (terms.length === 0 || terms.length > 12)
|
|
174
|
+
throw new Error('plugin-control-plane: capability query must contain 1..12 terms');
|
|
175
|
+
return catalog.entries.filter(entry => {
|
|
176
|
+
const haystack = `${entry.id} ${entry.capabilities.join(' ')}`.toLocaleLowerCase('en-US');
|
|
177
|
+
return terms.every(term => haystack.includes(term));
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
export function candidateDigest(entry, profile) {
|
|
181
|
+
return createHash('sha256').update(JSON.stringify({ entry, profile })).digest('hex');
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
package/lib/cli.d.ts
ADDED
package/lib/cli.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsLA,wBAAsB,gBAAgB,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlF"}
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { cp, mkdir, readFile, rename, rm, stat, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { candidateDigest, discover, loadCatalogWithFirstPartyFallback, parseCatalog } from './catalog.js';
|
|
5
|
+
const profilePattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
|
|
6
|
+
const planIdPattern = /^plugin-[a-f0-9]{24}$/u;
|
|
7
|
+
const maxPlanLifetimeMs = 86_400_000;
|
|
8
|
+
function option(argv, name) {
|
|
9
|
+
const index = argv.indexOf(name);
|
|
10
|
+
const value = index === -1 ? undefined : argv[index + 1];
|
|
11
|
+
if (value === undefined || value.startsWith('--'))
|
|
12
|
+
throw new Error(`plugin-control-plane: ${name} is required`);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function optionalOption(argv, name) {
|
|
16
|
+
const index = argv.indexOf(name);
|
|
17
|
+
if (index === -1)
|
|
18
|
+
return undefined;
|
|
19
|
+
const value = argv[index + 1];
|
|
20
|
+
if (value === undefined || value.startsWith('--'))
|
|
21
|
+
throw new Error(`plugin-control-plane: ${name} requires a value`);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
function defaultCatalogPath() {
|
|
25
|
+
const dshHome = process.env.DSH_HOME ?? join(process.env.HOME ?? '', '.dsh');
|
|
26
|
+
if (!isAbsolute(dshHome))
|
|
27
|
+
throw new Error('plugin-control-plane: DSH_HOME must be absolute');
|
|
28
|
+
return join(dshHome, 'plugin-control', 'catalog.json');
|
|
29
|
+
}
|
|
30
|
+
function exactPackages(candidate) {
|
|
31
|
+
return [
|
|
32
|
+
{ package: candidate.package, version: candidate.version, integrity: candidate.integrity },
|
|
33
|
+
...candidate.requires,
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
function validApproval(value) {
|
|
37
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
38
|
+
return false;
|
|
39
|
+
const approval = value;
|
|
40
|
+
return typeof approval.principal === 'string' && approval.principal.normalize('NFC').trim() !== ''
|
|
41
|
+
&& approval.principal.length <= 256 && Number.isSafeInteger(approval.approvedAt);
|
|
42
|
+
}
|
|
43
|
+
async function atomicJsonWrite(path, value) {
|
|
44
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
45
|
+
const temporary = `${path}.tmp-${process.pid}-${Math.random().toString(16).slice(2)}`;
|
|
46
|
+
try {
|
|
47
|
+
await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
|
|
48
|
+
await rename(temporary, path);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await unlink(temporary).catch(() => undefined);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function run(command, args, cwd, env) {
|
|
55
|
+
const outcome = spawnSync(command, [...args], { cwd, env, encoding: 'utf8', maxBuffer: 1_048_576 });
|
|
56
|
+
if (outcome.status !== 0)
|
|
57
|
+
throw new Error(`plugin-control-plane: ${command} failed: ${(outcome.stderr || outcome.stdout || '').trim().slice(0, 1_000)}`);
|
|
58
|
+
return outcome.stdout;
|
|
59
|
+
}
|
|
60
|
+
async function planFromFile(path) {
|
|
61
|
+
const value = JSON.parse(await readFile(path, 'utf8'));
|
|
62
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
63
|
+
throw new Error('plugin-control-plane: invalid plan');
|
|
64
|
+
const plan = value;
|
|
65
|
+
const createdAt = plan.createdAt;
|
|
66
|
+
const expiresAt = plan.expiresAt;
|
|
67
|
+
if (plan.schemaVersion !== 1 || typeof plan.id !== 'string' || typeof plan.profile !== 'string'
|
|
68
|
+
|| typeof plan.digest !== 'string' || typeof createdAt !== 'number' || typeof expiresAt !== 'number'
|
|
69
|
+
|| !Number.isSafeInteger(createdAt) || !Number.isSafeInteger(expiresAt)) {
|
|
70
|
+
throw new Error('plugin-control-plane: invalid plan');
|
|
71
|
+
}
|
|
72
|
+
if (!planIdPattern.test(plan.id) || !profilePattern.test(plan.profile)
|
|
73
|
+
|| !/^[a-f0-9]{64}$/u.test(plan.digest)
|
|
74
|
+
|| expiresAt <= createdAt || expiresAt - createdAt > maxPlanLifetimeMs) {
|
|
75
|
+
throw new Error('plugin-control-plane: invalid plan');
|
|
76
|
+
}
|
|
77
|
+
const candidate = parseCatalog({ schemaVersion: 1, entries: [plan.candidate] }).entries[0];
|
|
78
|
+
if (candidate === undefined || candidateDigest(candidate, plan.profile) !== plan.digest)
|
|
79
|
+
throw new Error('plugin-control-plane: plan digest mismatch');
|
|
80
|
+
if (Date.now() > expiresAt)
|
|
81
|
+
throw new Error('plugin-control-plane: plan has expired');
|
|
82
|
+
if (plan.status !== 'pending-owner-approval' && plan.status !== 'owner-approved')
|
|
83
|
+
throw new Error('plugin-control-plane: invalid plan status');
|
|
84
|
+
if (plan.status === 'owner-approved' && !validApproval(plan.approval))
|
|
85
|
+
throw new Error('plugin-control-plane: invalid plan approval');
|
|
86
|
+
return {
|
|
87
|
+
schemaVersion: 1,
|
|
88
|
+
id: plan.id,
|
|
89
|
+
status: plan.status,
|
|
90
|
+
createdAt,
|
|
91
|
+
expiresAt,
|
|
92
|
+
profile: plan.profile,
|
|
93
|
+
candidate,
|
|
94
|
+
digest: plan.digest,
|
|
95
|
+
...(plan.approval === undefined ? {} : { approval: plan.approval }),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async function approve(argv) {
|
|
99
|
+
const path = resolve(option(argv, '--plan'));
|
|
100
|
+
const principal = option(argv, '--approved-by').normalize('NFC').trim();
|
|
101
|
+
if (principal === '' || principal.length > 256)
|
|
102
|
+
throw new Error('plugin-control-plane: invalid approving principal');
|
|
103
|
+
const plan = await planFromFile(path);
|
|
104
|
+
if (plan.status !== 'pending-owner-approval')
|
|
105
|
+
throw new Error('plugin-control-plane: plan is not pending approval');
|
|
106
|
+
const approved = { ...plan, status: 'owner-approved', approval: { principal, approvedAt: Date.now() } };
|
|
107
|
+
await atomicJsonWrite(path, approved);
|
|
108
|
+
process.stdout.write(`Approved ${approved.id}; activation remains a separate command.\n`);
|
|
109
|
+
}
|
|
110
|
+
async function activate(argv) {
|
|
111
|
+
const plan = await planFromFile(resolve(option(argv, '--plan')));
|
|
112
|
+
if (plan.status !== 'owner-approved' || plan.approval === undefined)
|
|
113
|
+
throw new Error('plugin-control-plane: owner approval is required');
|
|
114
|
+
const dshHome = resolve(option(argv, '--dsh-home'));
|
|
115
|
+
if (!isAbsolute(dshHome) || !profilePattern.test(plan.profile))
|
|
116
|
+
throw new Error('plugin-control-plane: invalid DSH home or profile');
|
|
117
|
+
const profilePath = join(dshHome, 'profiles', plan.profile);
|
|
118
|
+
const stageProfile = `stage-${plan.id.slice(-24)}`;
|
|
119
|
+
const stagePath = join(dshHome, 'profiles', stageProfile);
|
|
120
|
+
const backupPath = join(dshHome, 'profiles', `.${plan.profile}.plugin-backup-${plan.id.slice(-12)}`);
|
|
121
|
+
await rm(stagePath, { recursive: true, force: true });
|
|
122
|
+
await rm(backupPath, { recursive: true, force: true });
|
|
123
|
+
try {
|
|
124
|
+
try {
|
|
125
|
+
await stat(profilePath);
|
|
126
|
+
await cp(profilePath, stagePath, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (!(error instanceof Error) || !('code' in error) || error.code !== 'ENOENT')
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
const env = { ...process.env, DSH_HOME: dshHome };
|
|
133
|
+
const installedDshVersion = run('dsh', ['--version'], undefined, env).trim();
|
|
134
|
+
if (installedDshVersion !== plan.candidate.dshBaseline) {
|
|
135
|
+
throw new Error(`plugin-control-plane: candidate requires DSH ${plan.candidate.dshBaseline}, found ${installedDshVersion || 'unknown'}`);
|
|
136
|
+
}
|
|
137
|
+
const packages = exactPackages(plan.candidate);
|
|
138
|
+
run('dsh', ['plugin', '--profile', stageProfile, 'add', ...packages.map(item => `${item.package}@${item.version}`)], undefined, env);
|
|
139
|
+
const stagedLock = await readFile(join(stagePath, 'pnpm-lock.yaml'), 'utf8');
|
|
140
|
+
if (packages.some(item => !stagedLock.includes(item.integrity))) {
|
|
141
|
+
throw new Error('plugin-control-plane: staged lockfile integrity does not match the approved catalog');
|
|
142
|
+
}
|
|
143
|
+
run('dsh', ['--profile', stageProfile, '--dump-config'], undefined, env);
|
|
144
|
+
try {
|
|
145
|
+
await rename(profilePath, backupPath);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (!(error instanceof Error) || !('code' in error) || error.code !== 'ENOENT')
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
await rename(stagePath, profilePath);
|
|
152
|
+
try {
|
|
153
|
+
run('dsh', ['--profile', plan.profile, '--dump-config'], undefined, env);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
await rm(profilePath, { recursive: true, force: true });
|
|
157
|
+
await rename(backupPath, profilePath);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
await rm(backupPath, { recursive: true, force: true });
|
|
161
|
+
process.stdout.write(`Activated ${packages.map(item => `${item.package}@${item.version}`).join(', ')} atomically; restart the resident service with scripts/install/restart.sh ${plan.profile}.\n`);
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
await rm(stagePath, { recursive: true, force: true });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function scaffold(argv) {
|
|
168
|
+
if (!argv.includes('--owner-approved'))
|
|
169
|
+
throw new Error('plugin-control-plane: scaffold requires --owner-approved');
|
|
170
|
+
const repository = resolve(option(argv, '--repository'));
|
|
171
|
+
const name = option(argv, '--name');
|
|
172
|
+
const worktrees = run('git', ['worktree', 'list', '--porcelain'], repository).split('\n')
|
|
173
|
+
.filter(line => line.startsWith('worktree ')).map(line => resolve(line.slice('worktree '.length)));
|
|
174
|
+
if (worktrees.length < 2 || worktrees[0] === repository || !worktrees.includes(repository)) {
|
|
175
|
+
throw new Error('plugin-control-plane: source creation is allowed only in a linked Git worktree, never the primary checkout');
|
|
176
|
+
}
|
|
177
|
+
if (run('git', ['status', '--porcelain'], repository).trim() !== '')
|
|
178
|
+
throw new Error('plugin-control-plane: worktree must be clean before scaffolding');
|
|
179
|
+
run('pnpm', ['create:plugin', name], repository);
|
|
180
|
+
run('pnpm', 'check'.split(' '), repository);
|
|
181
|
+
process.stdout.write(`Scaffolded ${name} in an isolated clean worktree and completed pnpm check. Submit it for review/PR; it was not activated.\n`);
|
|
182
|
+
}
|
|
183
|
+
async function verifyWorktree(argv) {
|
|
184
|
+
if (!argv.includes('--owner-approved'))
|
|
185
|
+
throw new Error('plugin-control-plane: verify-worktree requires --owner-approved');
|
|
186
|
+
const repository = resolve(option(argv, '--repository'));
|
|
187
|
+
const worktrees = run('git', ['worktree', 'list', '--porcelain'], repository).split('\n')
|
|
188
|
+
.filter(line => line.startsWith('worktree ')).map(line => resolve(line.slice('worktree '.length)));
|
|
189
|
+
if (worktrees.length < 2 || worktrees[0] === repository || !worktrees.includes(repository)) {
|
|
190
|
+
throw new Error('plugin-control-plane: plugin modification verification is allowed only in a linked Git worktree');
|
|
191
|
+
}
|
|
192
|
+
run('git', ['diff', '--check'], repository);
|
|
193
|
+
run('pnpm', ['check'], repository);
|
|
194
|
+
process.stdout.write('Isolated worktree passed pnpm check. Review and submit a PR before publishing or activating it.\n');
|
|
195
|
+
}
|
|
196
|
+
export async function runPluginControl(argv = process.argv.slice(2)) {
|
|
197
|
+
const command = argv[0];
|
|
198
|
+
if (command === 'discover') {
|
|
199
|
+
const catalog = await loadCatalogWithFirstPartyFallback(resolve(optionalOption(argv, '--catalog') ?? defaultCatalogPath()));
|
|
200
|
+
process.stdout.write(`${JSON.stringify(discover(catalog, option(argv, '--capability')), null, 2)}\n`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (command === 'approve')
|
|
204
|
+
return approve(argv);
|
|
205
|
+
if (command === 'activate')
|
|
206
|
+
return activate(argv);
|
|
207
|
+
if (command === 'scaffold')
|
|
208
|
+
return scaffold(argv);
|
|
209
|
+
if (command === 'verify-worktree')
|
|
210
|
+
return verifyWorktree(argv);
|
|
211
|
+
throw new Error('Usage: dsh-plugin-control <discover|approve|activate|scaffold|verify-worktree> ...');
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=cli.js.map
|
package/lib/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC3F,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,iCAAiC,EAAE,YAAY,EAA0C,MAAM,cAAc,CAAA;AAOjJ,MAAM,cAAc,GAAG,oCAAoC,CAAA;AAC3D,MAAM,aAAa,GAAG,wBAAwB,CAAA;AAC9C,MAAM,iBAAiB,GAAG,UAAU,CAAA;AAEpC,SAAS,MAAM,CAAC,IAAuB,EAAE,IAAY;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,KAAK,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;IACxD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,cAAc,CAAC,CAAA;IAC/G,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAuB,EAAE,IAAY;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;IAC7B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,mBAAmB,CAAC,CAAA;IACpH,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,CAAA;IAC5E,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IAC5F,OAAO,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,cAAc,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,SAAuB;IAC5C,OAAO;QACL,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE;QAC1F,GAAG,SAAS,CAAC,QAAQ;KACtB,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrF,MAAM,QAAQ,GAAG,KAAsD,CAAA;IACvE,OAAO,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;WAC7F,QAAQ,CAAC,SAAS,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;AACpF,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,KAAc;IACzD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC5D,MAAM,SAAS,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACrF,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAChH,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;IAC/B,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAChD,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,OAAe,EAAE,IAAuB,EAAE,GAAY,EAAE,GAAuB;IAC1F,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAA;IACnG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,YAAY,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;IACxJ,OAAO,OAAO,CAAC,MAAM,CAAA;AACvB,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAA;IACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IAC9H,MAAM,IAAI,GAAG,KAAsB,CAAA;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;IAChC,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;WAC1F,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ;WACjG,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;WACjE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;WACpC,SAAS,IAAI,SAAS,IAAI,SAAS,GAAG,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC1F,IAAI,SAAS,KAAK,SAAS,IAAI,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IACtJ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;IACrF,IAAI,IAAI,CAAC,MAAM,KAAK,wBAAwB,IAAI,IAAI,CAAC,MAAM,KAAK,gBAAgB;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9I,IAAI,IAAI,CAAC,MAAM,KAAK,gBAAgB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IACrI,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS;QACT,SAAS;QACT,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS;QACT,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;KACpE,CAAA;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,IAAuB;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAA;IACvE,IAAI,SAAS,KAAK,EAAE,IAAI,SAAS,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACpH,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,wBAAwB;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACnH,MAAM,QAAQ,GAAS,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAA;IAC7G,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,QAAQ,CAAC,EAAE,4CAA4C,CAAC,CAAA;AAC3F,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAuB;IAC7C,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAChE,IAAI,IAAI,CAAC,MAAM,KAAK,gBAAgB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;IACxI,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAA;IACnD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACpI,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3D,MAAM,YAAY,GAAG,SAAS,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAA;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC,OAAO,kBAAkB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IACpG,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,IAAI,CAAC;QACH,IAAI,CAAC;YAAC,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAAC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YAC1H,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAA;QAC7F,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;QACjD,MAAM,mBAAmB,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;QAC5E,IAAI,mBAAmB,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,CAAC,SAAS,CAAC,WAAW,WAAW,mBAAmB,IAAI,SAAS,EAAE,CAAC,CAAA;QAC1I,CAAC;QACD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC9C,GAAG,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QACpI,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAA;QAC5E,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAA;QACxG,CAAC;QACD,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QACxE,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;QAAC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACpE,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAA;QAC7F,CAAC;QACD,MAAM,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;QACpC,IAAI,CAAC;YAAC,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAC9F,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACvD,MAAM,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;YACrC,MAAM,KAAK,CAAA;QACb,CAAC;QACD,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,6EAA6E,IAAI,CAAC,OAAO,KAAK,CAAC,CAAA;IACrM,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACvD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAuB;IAC7C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IACnH,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAA;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACnC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;SACtF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACpG,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,KAAK,CAAC,4GAA4G,CAAC,CAAA;IAC/H,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IACvJ,GAAG,CAAC,MAAM,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC,CAAA;IAChD,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAA;IAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,2GAA2G,CAAC,CAAA;AACrJ,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAuB;IACnD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IAC1H,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAA;IACxD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;SACtF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACpG,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAA;IACpH,CAAC;IACD,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,CAAA;IAC3C,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAA;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mGAAmG,CAAC,CAAA;AAC3H,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACvB,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,iCAAiC,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC,CAAA;QAC3H,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;QACrG,OAAM;IACR,CAAC;IACD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;IACjD,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;IACjD,IAAI,OAAO,KAAK,iBAAiB;QAAE,OAAO,cAAc,CAAC,IAAI,CAAC,CAAA;IAC9D,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAA;AACvG,CAAC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { PluginControlPlaneService, type Config } from './service.js';
|
|
3
|
+
import { version } from './version.js';
|
|
4
|
+
export declare const name = "dsh-enhanced-plugin-control-plane";
|
|
5
|
+
export { PluginControlPlaneService, version };
|
|
6
|
+
export { Config } from './service.js';
|
|
7
|
+
export * from './catalog.js';
|
|
8
|
+
export * from './service.js';
|
|
9
|
+
export declare function apply(ctx: Context, config: Config): void;
|
|
10
|
+
export default PluginControlPlaneService;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,yBAAyB,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,eAAO,MAAM,IAAI,sCAAsC,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAE5B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAExD;AAED,eAAe,yBAAyB,CAAA"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PluginControlPlaneService } from './service.js';
|
|
2
|
+
import { version } from './version.js';
|
|
3
|
+
export const name = 'dsh-enhanced-plugin-control-plane';
|
|
4
|
+
export { PluginControlPlaneService, version };
|
|
5
|
+
export { Config } from './service.js';
|
|
6
|
+
export * from './catalog.js';
|
|
7
|
+
export * from './service.js';
|
|
8
|
+
export function apply(ctx, config) {
|
|
9
|
+
new PluginControlPlaneService(ctx, config);
|
|
10
|
+
}
|
|
11
|
+
export default PluginControlPlaneService;
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAe,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,mCAAmC,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAE5B,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAc;IAChD,IAAI,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAC5C,CAAC;AAED,eAAe,yBAAyB,CAAA"}
|
package/lib/service.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
2
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
3
|
+
import { type CatalogEntry } from './catalog.js';
|
|
4
|
+
export interface Config {
|
|
5
|
+
catalogPath: string;
|
|
6
|
+
statePath: string;
|
|
7
|
+
proposalTtlMs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PluginActivationPlan {
|
|
10
|
+
schemaVersion: 1;
|
|
11
|
+
id: string;
|
|
12
|
+
status: 'pending-owner-approval';
|
|
13
|
+
createdAt: number;
|
|
14
|
+
expiresAt: number;
|
|
15
|
+
profile: string;
|
|
16
|
+
candidate: CatalogEntry;
|
|
17
|
+
digest: string;
|
|
18
|
+
}
|
|
19
|
+
declare module '@deepseek-ai/cordis' {
|
|
20
|
+
interface Context {
|
|
21
|
+
pluginControlPlane: PluginControlPlaneService;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export declare class PluginControlPlaneService extends Service {
|
|
25
|
+
static Config: Schema<Config>;
|
|
26
|
+
private readonly config;
|
|
27
|
+
constructor(ctx: Context, input: Config);
|
|
28
|
+
discover(capability: string): Promise<CatalogEntry[]>;
|
|
29
|
+
plan(candidateId: string, profile: string): Promise<PluginActivationPlan>;
|
|
30
|
+
}
|
|
31
|
+
export declare const Config: Schema<Config>;
|
|
32
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,EAAgE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAG9G,MAAM,WAAW,MAAM;IAAG,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE;AAM1F,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,wBAAwB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;IACpG,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CACzD;AAED,OAAO,QAAQ,qBAAqB,CAAC;IAAE,UAAU,OAAO;QAAG,kBAAkB,EAAE,yBAAyB,CAAA;KAAE;CAAE;AAE5G,qBAAa,yBAA0B,SAAQ,OAAO;IACpD,MAAM,CAAC,MAAM,iBAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAC7B,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;IAOjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIrD,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAqBhF;AAED,eAAO,MAAM,MAAM,gBAAS,CAAA"}
|
package/lib/service.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { mkdir, rename, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, join } from 'node:path';
|
|
3
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
4
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
5
|
+
import { candidateDigest, discover, loadCatalogWithFirstPartyFallback } from './catalog.js';
|
|
6
|
+
import { registerPluginControlTools } from './tools.js';
|
|
7
|
+
const schema = Schema.object({
|
|
8
|
+
catalogPath: Schema.string().required(), statePath: Schema.string().required(),
|
|
9
|
+
proposalTtlMs: Schema.number().step(1).min(60_000).max(86_400_000).default(900_000),
|
|
10
|
+
});
|
|
11
|
+
export class PluginControlPlaneService extends Service {
|
|
12
|
+
static Config = schema;
|
|
13
|
+
config;
|
|
14
|
+
constructor(ctx, input) {
|
|
15
|
+
super(ctx, 'pluginControlPlane');
|
|
16
|
+
this.config = schema(input);
|
|
17
|
+
if (!isAbsolute(this.config.catalogPath) || !isAbsolute(this.config.statePath))
|
|
18
|
+
throw new Error('plugin-control-plane: catalogPath and statePath must be absolute');
|
|
19
|
+
ctx.inject(['tools'], toolsCtx => registerPluginControlTools(toolsCtx, this));
|
|
20
|
+
}
|
|
21
|
+
async discover(capability) {
|
|
22
|
+
return discover(await loadCatalogWithFirstPartyFallback(this.config.catalogPath), capability);
|
|
23
|
+
}
|
|
24
|
+
async plan(candidateId, profile) {
|
|
25
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(profile))
|
|
26
|
+
throw new Error('plugin-control-plane: invalid profile');
|
|
27
|
+
const candidate = (await loadCatalogWithFirstPartyFallback(this.config.catalogPath)).entries.find(item => item.id === candidateId);
|
|
28
|
+
if (candidate === undefined)
|
|
29
|
+
throw new Error('plugin-control-plane: candidate not found');
|
|
30
|
+
const createdAt = Date.now();
|
|
31
|
+
const digest = candidateDigest(candidate, profile);
|
|
32
|
+
const plan = Object.freeze({ schemaVersion: 1, id: `plugin-${digest.slice(0, 24)}`,
|
|
33
|
+
status: 'pending-owner-approval', createdAt, expiresAt: createdAt + this.config.proposalTtlMs, profile, candidate, digest });
|
|
34
|
+
await mkdir(this.config.statePath, { recursive: true, mode: 0o700 });
|
|
35
|
+
const target = join(this.config.statePath, `${plan.id}.json`);
|
|
36
|
+
const temporary = `${target}.tmp-${process.pid}-${Math.random().toString(16).slice(2)}`;
|
|
37
|
+
try {
|
|
38
|
+
await writeFile(temporary, `${JSON.stringify(plan, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
|
|
39
|
+
await rename(temporary, target);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
// A failed write must not leave a plan that a later owner could mistake
|
|
43
|
+
// for an authenticated proposal. Missing files are benign here.
|
|
44
|
+
await unlink(temporary).catch(() => undefined);
|
|
45
|
+
}
|
|
46
|
+
return plan;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export const Config = schema;
|
|
50
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/lib/tools.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAE7D,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAWjG"}
|
package/lib/tools.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
2
|
+
export function registerPluginControlTools(ctx, service) {
|
|
3
|
+
ctx.tools.register(defineTool({ name: 'plugin_discover', description: 'Find signed-catalog plugin candidates by capability. Read-only; never installs anything.',
|
|
4
|
+
parameters: { capability: { type: 'string', required: true } },
|
|
5
|
+
output: { schema: { type: 'object', additionalProperties: false, properties: { candidates: { type: 'array', required: true, items: { type: 'object', additionalProperties: true, properties: {} } } } }, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }] },
|
|
6
|
+
async execute(args) { return { candidates: await service.discover(args.capability) }; },
|
|
7
|
+
}));
|
|
8
|
+
ctx.tools.register(defineTool({ name: 'plugin_activation_plan', description: 'Create an owner-approval plan for one exact catalog candidate. It never installs, edits, or reloads a production profile.',
|
|
9
|
+
parameters: { candidate_id: { type: 'string', required: true }, profile: { type: 'string', required: true } },
|
|
10
|
+
output: { schema: { type: 'object', additionalProperties: true, properties: {} }, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }] },
|
|
11
|
+
async execute(args) { return await service.plan(args.candidate_id, args.profile); },
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=tools.js.map
|
package/lib/tools.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGnD,MAAM,UAAU,0BAA0B,CAAC,GAAY,EAAE,OAAkC;IACzF,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,0FAA0F;QAC9J,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAC9D,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;QACpR,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAAW,CAAA,CAAC,CAAC;KAChG,CAAC,CAAC,CAAA;IACH,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,WAAW,EAAE,2HAA2H;QACtM,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAC7G,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;QAC7J,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAU,CAAA,CAAC,CAAC;KAC5F,CAAC,CAAC,CAAA;AACL,CAAC"}
|
package/lib/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAA"}
|
package/lib/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-enhanced/plugin-control-plane",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "A proposal-only capability catalog and isolated plugin activation control plane for DSH.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"types": "./lib/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"dsh-plugin-control": "./bin/dsh-plugin-control.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./lib/index.d.ts",
|
|
15
|
+
"default": "./lib/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin",
|
|
22
|
+
"lib",
|
|
23
|
+
"cordis.patch.yml",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/22-ai-00/dsh-enhanced.git",
|
|
36
|
+
"directory": "plugins/plugin-control-plane"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"deepseek",
|
|
40
|
+
"deepseek-harness",
|
|
41
|
+
"dsh-plugin"
|
|
42
|
+
],
|
|
43
|
+
"dsh": {
|
|
44
|
+
"bundle": {
|
|
45
|
+
"patch": "./cordis.patch.yml"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@deepseek-ai/schemastery": "3.18.1"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
53
|
+
"@deepseek-ai/dsh-tools": ">=0.1.0-rc.8 <0.2.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"@deepseek-ai/cordis": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@deepseek-ai/dsh-tools": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
65
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.8",
|
|
66
|
+
"@types/node": "22.20.0",
|
|
67
|
+
"typescript": "6.0.3",
|
|
68
|
+
"vitest": "4.1.8"
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"build": "tsc -p tsconfig.build.json",
|
|
72
|
+
"test": "vitest run",
|
|
73
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
74
|
+
}
|
|
75
|
+
}
|