dsh-pighub 0.0.0-stage → 0.0.1
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 +65 -2
- package/cordis.patch.yml +10 -0
- package/lib/index.js +76 -0
- package/package.json +48 -4
- package/test/smoke.mjs +93 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 positer
|
|
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
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-pighub
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**PigHub(猪猪库调研项目)的 DeepSeek Harness 插件——当前是 0.0.1 占位版。**
|
|
4
|
+
|
|
5
|
+
占位版只做三件事:占住 npm 包名 `dsh-pighub`、用一个最小 bundle 证明 DSH 装配链是对的、注册一个只读工具 `pighub_about` 让「装了且能调用」当场可验。
|
|
6
|
+
它**不联网、不下载、不缓存、不内嵌任何猪图或猪名数据**。
|
|
7
|
+
|
|
8
|
+
## 为什么先发布占位版
|
|
9
|
+
|
|
10
|
+
npm 包名只有**发布**才锁定,仓库、README、issue 都不能占位。而 `dsh-pighub` 目前在 registry 上无人占用(`npm view dsh-pighub` → 404),所以先发一个诚实的最小包把名字钉住,再谈功能。
|
|
11
|
+
真实功能的门槛不是代码,是**数据来源**:上游 PigHub 的图片与文案没有任何数据许可(GitHub `NOASSERTION`,按「保留全部权利」理解),把数据打进公开 npm 包就是再分发。占位版因此选择「零数据」。
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-pighub # 官方装配入口(写 profile 的 bundles,重启生效)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
或从源码目录装(未发布前的等价路径):
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add ./dsh-pighub
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
装好后工具表里会多出 `pighub_about`,它返回本插件的版本、阶段、上游署名与数据许可立场。
|
|
26
|
+
|
|
27
|
+
## 结构与契约
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
dsh-pighub/
|
|
31
|
+
├── package.json # dsh.bundle.patch → ./cordis.patch.yml(bundle 声明的唯一入口)
|
|
32
|
+
├── cordis.patch.yml # 一行 insert:id: dsh-pighub, name: dsh-pighub
|
|
33
|
+
├── lib/index.js # export name / inject / apply;注册 pighub_about
|
|
34
|
+
├── test/smoke.mjs # 离线冒烟:模拟宿主 ctx,断言导出/注册/回收/工具输出
|
|
35
|
+
├── docs/DSH-PLUGIN-PUBLIC-FORM.md # 调研:DSH 插件的公开形式与发布通道
|
|
36
|
+
├── README.md
|
|
37
|
+
└── LICENSE
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
DSH 插件的公共形态只有一条主链:**npm 包 + `package.json` 的 `dsh.bundle.patch` + 一张补丁层 + 一个 ESM 入口**。完整调研(官方与社区一手来源、字段逐项核对、三种分发通道、以及本包为什么这样写)见 [docs/DSH-PLUGIN-PUBLIC-FORM.md](./docs/DSH-PLUGIN-PUBLIC-FORM.md)。
|
|
41
|
+
|
|
42
|
+
## 验证
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npm test # = node test/smoke.mjs,12 项断言;同时是 prepublishOnly
|
|
46
|
+
npm pack --dry-run # 看发布内容(应只含 lib / cordis.patch.yml / README / LICENSE / test)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
冒烟测试不启动 DSH:它按宿主的用法调用一次 `apply(ctx)`,断言只注册了 `pighub_about`、注册被 `ctx.effect` 包住(可回收)、工具输出是稳定 JSON、且代码里的版本号与 `package.json` 一致。
|
|
50
|
+
|
|
51
|
+
## Roadmap(都未实现)
|
|
52
|
+
|
|
53
|
+
1. **先定数据来源**:自建数据(自制猪图/自写文案)或取得上游书面授权;二者之外不做数据类工具。
|
|
54
|
+
2. 之后才谈工具面:随机猪图、按名检索、今日猪猪。
|
|
55
|
+
3. 若要出图,再谈是否加 `dsh.client` 前端半(设置卡片 / 图片面板)——声明 `dsh.client` 后要单独构建浏览器产物(`lib/client.js`),占位版刻意不带。
|
|
56
|
+
|
|
57
|
+
## 许可
|
|
58
|
+
|
|
59
|
+
- **本插件代码**:MIT(见 [LICENSE](./LICENSE))。
|
|
60
|
+
- **上游 PigHub 数据**:未声明许可;本包不包含、不再分发任何上游素材。MIT 只覆盖这里的插件代码,不覆盖任何猪图或猪名文案。
|
|
61
|
+
|
|
62
|
+
## 状态
|
|
63
|
+
|
|
64
|
+
- 版本:0.0.1 占位版,唯一工具 `pighub_about`(只读自述)
|
|
65
|
+
- 数据:无。网络:无。
|
|
66
|
+
- 项目主目录:[../README.md](../README.md)(PigHub 调研档案)
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dsh-pighub 的 bundle 层:只插一行。
|
|
2
|
+
#
|
|
3
|
+
# 这一行是「已安装」的全部含义——Loader 读 package.json 的 dsh.bundle.patch,
|
|
4
|
+
# 把这里的内容追加到 profile 的装配链末尾,于是 name 指向的包被 import,
|
|
5
|
+
# 它的 apply(ctx) 才被执行。行 id 独立于包名,删包时按 id 回滚。
|
|
6
|
+
#
|
|
7
|
+
# name 必须是**包名**(Node 解析),不能写成源码相对路径。
|
|
8
|
+
- insert:
|
|
9
|
+
- id: dsh-pighub
|
|
10
|
+
name: dsh-pighub
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-pighub — 猪猪库 PigHub 的 DeepSeek Harness 插件(0.0.1 占位版)。
|
|
3
|
+
*
|
|
4
|
+
* 这个版本只做三件事,且只做这三件:
|
|
5
|
+
*
|
|
6
|
+
* 1. 占住 npm 包名 `dsh-pighub`(名字只有发布才锁定);
|
|
7
|
+
* 2. 用一个最小 bundle 证明装配链是对的(package.json 的 dsh.bundle.patch
|
|
8
|
+
* → cordis.patch.yml 的一行 insert → 本文件的 apply);
|
|
9
|
+
* 3. 注册一个只读工具 `pighub_about`,让「插件已装、能调用」可被当场验证。
|
|
10
|
+
*
|
|
11
|
+
* 它**不**做:不联网、不下载、不缓存、不内嵌任何猪图或猪名数据。上游 PigHub
|
|
12
|
+
* 的图片与文案没有任何数据许可(GitHub NOASSERTION → 默认保留全部权利),
|
|
13
|
+
* 把数据塞进一个公开 npm 包就是再分发,不是这个占位版有权做的事。真实能力的
|
|
14
|
+
* 设计见 README 的 roadmap,落地前必须先解决数据来源与许可。
|
|
15
|
+
*
|
|
16
|
+
* 契约(与宿主 loader 对齐,参考同机在跑的生产插件):
|
|
17
|
+
* - `export const name` —— Loader 行的身份;
|
|
18
|
+
* - `export const inject` —— 声明依赖的服务,这里只需要 tools;
|
|
19
|
+
* - `export function apply(ctx)` —— 注册能力的唯一入口。
|
|
20
|
+
*
|
|
21
|
+
* 资源注册一律包在 `ctx.effect` 里:宿主热重载/卸载时靠它回收,否则工具会
|
|
22
|
+
* 变成僵尸残留在工具表里(同生态插件踩过的坑)。
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** 与 package.json 的 name 必须一致;test/smoke.mjs 会断言两者相同。 */
|
|
26
|
+
export const name = 'dsh-pighub';
|
|
27
|
+
|
|
28
|
+
/** 只需要工具表;本版本不碰 LLM、会话、web 路由、文件系统。 */
|
|
29
|
+
export const inject = ['tools'];
|
|
30
|
+
|
|
31
|
+
/** 与 package.json 的 version 必须一致;test/smoke.mjs 会断言两者相同。 */
|
|
32
|
+
const VERSION = '0.0.1';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* `pighub_about` 的回答是一条**自述**,不是数据查询:它描述的正是本插件此刻
|
|
36
|
+
* 的状态与立场,所以永远不需要网络,也不会因为上游下架而说谎。
|
|
37
|
+
*
|
|
38
|
+
* 冻结成常量,是因为它必须逐字段可预测——调用者拿它做健康检查与署名核对。
|
|
39
|
+
*/
|
|
40
|
+
const ABOUT = Object.freeze({
|
|
41
|
+
ok: true,
|
|
42
|
+
plugin: name,
|
|
43
|
+
version: VERSION,
|
|
44
|
+
stage: 'placeholder',
|
|
45
|
+
purpose: '预留包名 + 验证 bundle 装配 + 提供一个可调用的只读自述工具',
|
|
46
|
+
upstream: {
|
|
47
|
+
project: 'PigHub',
|
|
48
|
+
what: 'QQ 猪猪生态的开源数据调研项目(1,361 张图索引快照,2026-11-12)',
|
|
49
|
+
dataLicense: '上游未声明数据许可(NOASSERTION,按保留全部权利理解)',
|
|
50
|
+
redistributed: false,
|
|
51
|
+
},
|
|
52
|
+
bundledData: null,
|
|
53
|
+
tools: ['pighub_about'],
|
|
54
|
+
roadmap: [
|
|
55
|
+
'确定合法数据来源(自建 / 上游书面授权),再谈工具面',
|
|
56
|
+
'候选工具:随机猪图、按名检索、今日猪猪——都取决于数据来源能否落地',
|
|
57
|
+
],
|
|
58
|
+
notice: '占位版不联网、不读写本地数据、无副作用;真实能力尚未实现。',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {any} ctx 宿主 Cordis 上下文:需要 `tools.register` 与 `effect`。
|
|
63
|
+
*/
|
|
64
|
+
export function apply(ctx) {
|
|
65
|
+
ctx.effect(
|
|
66
|
+
() =>
|
|
67
|
+
ctx.tools.register({
|
|
68
|
+
name: 'pighub_about',
|
|
69
|
+
description:
|
|
70
|
+
'读取 dsh-pighub 占位版的自述:版本 / 阶段 / 上游署名 / 数据许可立场;不联网、不读数据集、无副作用。 Read what the dsh-pighub placeholder is: version, stage, upstream attribution, data-licence position. No network, no dataset, no side effects.',
|
|
71
|
+
parameters: { type: 'object', properties: {}, additionalProperties: false },
|
|
72
|
+
execute: async () => ABOUT,
|
|
73
|
+
}),
|
|
74
|
+
'pighub-about-tool',
|
|
75
|
+
);
|
|
76
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-pighub",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "猪猪库 PigHub 的 DeepSeek Harness 插件——占位版(0.0.1):预留包名、验证 bundle 装配、注册一个只读的 pighub_about 工具;不内嵌、不下载、不缓存任何猪图。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./lib/index.js",
|
|
9
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"lib",
|
|
14
|
+
"cordis.patch.yml",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"test"
|
|
18
|
+
],
|
|
19
|
+
"dsh": {
|
|
20
|
+
"bundle": {
|
|
21
|
+
"patch": "./cordis.patch.yml"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"dsh",
|
|
26
|
+
"dsh-plugin",
|
|
27
|
+
"deepseek-harness",
|
|
28
|
+
"deepseek",
|
|
29
|
+
"cordis",
|
|
30
|
+
"pighub",
|
|
31
|
+
"pig",
|
|
32
|
+
"dataset"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22.12.0"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "node test/smoke.mjs",
|
|
39
|
+
"prepublishOnly": "node test/smoke.mjs"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"author": {
|
|
43
|
+
"name": "positer"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org/",
|
|
48
|
+
"tag": "latest"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/test/smoke.mjs
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 离线冒烟测试:不启动 DSH,直接按宿主的用法调用一次 apply。
|
|
3
|
+
*
|
|
4
|
+
* 它验证的是「装配契约」而不是「功能」——占位版的功能就是那句自述:
|
|
5
|
+
*
|
|
6
|
+
* 1. 导出齐全(name / inject / apply),且 name 与 package.json 一致;
|
|
7
|
+
* 2. apply 之后工具表里确实多了 pighub_about,且只有它一个;
|
|
8
|
+
* 3. 注册被包在 ctx.effect 里(effect 返回的 disposer 能回收);
|
|
9
|
+
* 4. execute 的返回是一个稳定的 JSON 对象,参数 schema 封闭。
|
|
10
|
+
*
|
|
11
|
+
* 任何一条不成立就非零退出——prepublishOnly 跑的就是它,坏包发不出去。
|
|
12
|
+
*/
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
|
|
17
|
+
const here = new URL('.', import.meta.url);
|
|
18
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', here), 'utf8'));
|
|
19
|
+
const plugin = await import(new URL('../lib/index.js', here).href);
|
|
20
|
+
|
|
21
|
+
let passed = 0;
|
|
22
|
+
const check = (label, fn) => {
|
|
23
|
+
fn();
|
|
24
|
+
passed += 1;
|
|
25
|
+
console.log('PASS ' + label);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// —— 1. 导出契约 ——
|
|
29
|
+
check('导出 name / inject / apply', () => {
|
|
30
|
+
assert.equal(typeof plugin.name, 'string');
|
|
31
|
+
assert.ok(Array.isArray(plugin.inject));
|
|
32
|
+
assert.equal(typeof plugin.apply, 'function');
|
|
33
|
+
});
|
|
34
|
+
check('name 与 package.json 的 name 一致', () => assert.equal(plugin.name, pkg.name));
|
|
35
|
+
check('inject 只声明 tools', () => assert.deepEqual(plugin.inject, ['tools']));
|
|
36
|
+
check('package.json 声明了 bundle 补丁', () =>
|
|
37
|
+
assert.equal(pkg.dsh?.bundle?.patch, './cordis.patch.yml'));
|
|
38
|
+
check('package.json 导出 cordis.patch.yml', () =>
|
|
39
|
+
assert.equal(pkg.exports?.['./cordis.patch.yml'], './cordis.patch.yml'));
|
|
40
|
+
|
|
41
|
+
// —— 2. 模拟宿主上下文 ——
|
|
42
|
+
const registered = new Map();
|
|
43
|
+
const disposers = [];
|
|
44
|
+
const ctx = {
|
|
45
|
+
effect(fn, label) {
|
|
46
|
+
const dispose = fn();
|
|
47
|
+
disposers.push({ label, dispose });
|
|
48
|
+
return dispose;
|
|
49
|
+
},
|
|
50
|
+
tools: {
|
|
51
|
+
register(definition) {
|
|
52
|
+
assert.ok(!registered.has(definition.name), '重复注册: ' + definition.name);
|
|
53
|
+
registered.set(definition.name, definition);
|
|
54
|
+
return () => registered.delete(definition.name);
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
plugin.apply(ctx);
|
|
60
|
+
|
|
61
|
+
check('apply 后注册了且仅注册了 pighub_about', () =>
|
|
62
|
+
assert.deepEqual([...registered.keys()], ['pighub_about']));
|
|
63
|
+
check('注册被包在 ctx.effect 里(可回收)', () => {
|
|
64
|
+
assert.equal(disposers.length, 1);
|
|
65
|
+
assert.equal(disposers[0].label, 'pighub-about-tool');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// —— 3. 工具定义与调用 ——
|
|
69
|
+
const tool = registered.get('pighub_about');
|
|
70
|
+
check('参数 schema 是封闭的空对象', () => {
|
|
71
|
+
assert.equal(tool.parameters.type, 'object');
|
|
72
|
+
assert.deepEqual(tool.parameters.properties, {});
|
|
73
|
+
assert.equal(tool.parameters.additionalProperties, false);
|
|
74
|
+
});
|
|
75
|
+
check('工具描述非空', () => assert.ok(tool.description.length > 20));
|
|
76
|
+
|
|
77
|
+
const answer = await tool.execute({}, {});
|
|
78
|
+
check('execute 返回冻结的自述对象', () => {
|
|
79
|
+
assert.equal(answer.ok, true);
|
|
80
|
+
assert.equal(answer.plugin, pkg.name);
|
|
81
|
+
assert.equal(answer.version, pkg.version, '代码版本与 package.json 不一致');
|
|
82
|
+
assert.equal(answer.stage, 'placeholder');
|
|
83
|
+
assert.deepEqual(answer.tools, ['pighub_about']);
|
|
84
|
+
assert.equal(answer.bundledData, null);
|
|
85
|
+
});
|
|
86
|
+
check('自述可无损 JSON 往返', () => assert.deepEqual(JSON.parse(JSON.stringify(answer)), answer));
|
|
87
|
+
|
|
88
|
+
// —— 4. 回收 ——
|
|
89
|
+
disposers[0].dispose();
|
|
90
|
+
check('disposer 之后工具表清空', () => assert.equal(registered.size, 0));
|
|
91
|
+
|
|
92
|
+
console.log('\n' + passed + ' PASS / 0 FAIL — ' + pkg.name + '@' + pkg.version);
|
|
93
|
+
console.log('entry: ' + fileURLToPath(new URL('../lib/index.js', here)));
|