@liangjiehappy/dsh-plugin-mj7 0.0.0-stage → 0.1.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/README.md CHANGED
@@ -1,3 +1,46 @@
1
- # Temporary Holding Version
1
+ # dsh-plugin-mj7
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Read-only mj7.cn data tools for DeepSeek Harness: standards/product search, HS lookup, Incoterms, trade documents, and CNY FX rates.
4
+
5
+ 中文说明见 [README.zh-CN.md](README.zh-CN.md).
6
+
7
+ ## Tools
8
+
9
+ | Tool | Purpose |
10
+ |---|---|
11
+ | `mj7_search` | Search standards, materials and industrial products by keyword |
12
+ | `mj7_hot` | Hot categories on mj7.cn |
13
+ | `mj7_hs` | Look up standards related to an HS code |
14
+ | `mj7_terms` | Incoterms responsibilities |
15
+ | `mj7_docs` | Export/trade document checklist |
16
+ | `mj7_fx` | CNY FX rates (default USD) |
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ dsh plugin --profile web add @liangjiehappy/dsh-plugin-mj7
22
+ ```
23
+
24
+ ## Config
25
+
26
+ ```yaml
27
+ - insert:
28
+ - id: dsh-plugin-mj7
29
+ name: "@liangjiehappy/dsh-plugin-mj7"
30
+ config:
31
+ baseUrl: "https://www.mj7.cn"
32
+ ```
33
+
34
+ Zero-config works; the default base URL is `https://www.mj7.cn`.
35
+
36
+ ## Permissions
37
+
38
+ - Outbound HTTPS GET to `www.mj7.cn` only (configurable `baseUrl`)
39
+ - No file reads or writes, no credential access, no shell
40
+ - Read-only: no login, no orders, no writes
41
+
42
+ ## Limitations
43
+
44
+ - Depends on public mj7.cn APIs (`/api/search`, `/api/hot`, `/api/hs`, `/api/terms`, `/api/docs`, `/api/fx`)
45
+ - API changes can break a tool; failures surface the real HTTP error
46
+ - Results are summaries with filters; open the site for full content
@@ -0,0 +1,46 @@
1
+ # dsh-plugin-mj7
2
+
3
+ 模极社(mj7.cn)只读数据插件:在 DSH 里查标准、产品、HS 关联、贸易术语、单证和汇率。
4
+
5
+ English docs: [README.md](README.md).
6
+
7
+ ## 工具
8
+
9
+ | 工具 | 作用 |
10
+ |---|---|
11
+ | `mj7_search` | 关键词搜索标准/产品/材料 |
12
+ | `mj7_hot` | 热门品类 |
13
+ | `mj7_hs` | HS 编码联想标准 |
14
+ | `mj7_terms` | Incoterms 术语 |
15
+ | `mj7_docs` | 外贸单证清单 |
16
+ | `mj7_fx` | 人民币汇率 |
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ dsh plugin --profile web add @liangjiehappy/dsh-plugin-mj7
22
+ ```
23
+
24
+ ## 配置
25
+
26
+ ```yaml
27
+ - insert:
28
+ - id: dsh-plugin-mj7
29
+ name: "@liangjiehappy/dsh-plugin-mj7"
30
+ config:
31
+ baseUrl: "https://www.mj7.cn"
32
+ ```
33
+
34
+ 零配置可用,默认 https://www.mj7.cn。
35
+
36
+ ## 权限声明
37
+
38
+ - 只对 `www.mj7.cn` 发 HTTPS GET(可配置 baseUrl)
39
+ - 不读写文件、不读凭证、不执行 shell
40
+ - 只读:不登录、不下单、不写数据
41
+
42
+ ## 限制
43
+
44
+ - 依赖 mj7.cn 公开 API(`/api/search`、`/api/hot`、`/api/hs`、`/api/terms`、`/api/docs`、`/api/fx`)
45
+ - API 变更可能导致工具失败;失败会返回真实 HTTP 错误
46
+ - 结果只做摘要与筛选,完整内容请打开站内页面
@@ -0,0 +1,5 @@
1
+ - insert:
2
+ - id: dsh-plugin-mj7
3
+ name: "@liangjiehappy/dsh-plugin-mj7"
4
+ config:
5
+ baseUrl: "https://www.mj7.cn"
package/lib/core.js ADDED
@@ -0,0 +1,71 @@
1
+ // dsh-plugin-mj7 · 纯函数:URL 构造与 API 结果摘要(无副作用、不依赖网络)
2
+ export const DEFAULT_BASE = 'https://www.mj7.cn'
3
+
4
+ export function normalizeBase(base) {
5
+ const b = (base || DEFAULT_BASE).trim().replace(/\/+$/, '')
6
+ if (!/^https?:\/\//i.test(b)) throw new Error('baseUrl 必须以 http(s):// 开头')
7
+ return b
8
+ }
9
+
10
+ export function buildUrl(base, path, params = {}) {
11
+ const u = new URL(path, base + '/')
12
+ for (const [k, v] of Object.entries(params)) {
13
+ if (v !== undefined && v !== null && v !== '') u.searchParams.set(k, String(v))
14
+ }
15
+ return u.toString()
16
+ }
17
+
18
+ export function asLimit(n, def = 6, max = 50) {
19
+ const v = Number(n)
20
+ if (!Number.isFinite(v) || v <= 0) return def
21
+ return Math.min(Math.floor(v), max)
22
+ }
23
+
24
+ function pickItem(it) {
25
+ const out = {}
26
+ for (const k of ['id', 'standard_no', 'org', 'title', 'title_cn', '_title', 'name', 'code', 'cn', 'en', 'url', 'type']) {
27
+ if (it && it[k] !== undefined) out[k] = it[k]
28
+ }
29
+ return out
30
+ }
31
+
32
+ export function summarizeSearch(json, limit = 6) {
33
+ if (!json || json.code !== 200) throw new Error((json && json.msg) || 'mj7 search 失败')
34
+ const groups = (json.groups || []).map((g) => ({
35
+ key: g.key,
36
+ name: g.name,
37
+ total: g.total,
38
+ items: (g.items || []).slice(0, limit).map(pickItem),
39
+ }))
40
+ return { total: json.total ?? 0, kw: json.kw || '', groups }
41
+ }
42
+
43
+ export function summarizeHot(json, limit = 30) {
44
+ if (!json || json.code !== 200) throw new Error((json && json.msg) || 'mj7 hot 失败')
45
+ return { items: (json.items || []).slice(0, limit) }
46
+ }
47
+
48
+ export function summarizeHs(json, limit = 10) {
49
+ if (!json || json.code !== 200) throw new Error((json && json.msg) || 'mj7 hs 失败')
50
+ return {
51
+ hs: json.hs || '',
52
+ chapter: json.chapter || '',
53
+ total: (json.data || []).length,
54
+ items: (json.data || []).slice(0, limit).map(pickItem),
55
+ }
56
+ }
57
+
58
+ export function summarizeList(json, limit = 10) {
59
+ if (!json || json.code !== 200) throw new Error((json && json.msg) || 'mj7 查询失败')
60
+ return {
61
+ total: json.total ?? (json.data || []).length,
62
+ items: (json.data || []).slice(0, limit),
63
+ }
64
+ }
65
+
66
+ export function summarizeFx(json, currency = 'USD') {
67
+ if (!json || json.code !== 200) throw new Error((json && json.msg) || 'mj7 fx 失败')
68
+ const cur = String(currency || 'USD').toUpperCase()
69
+ const rates = json.rates || {}
70
+ return { base: json.base || 'CNY', currency: cur, rate: rates[cur] ?? null, rates }
71
+ }
package/lib/index.js ADDED
@@ -0,0 +1,97 @@
1
+ // dsh-plugin-mj7 · 模极社 mj7.cn 只读数据工具
2
+ import { defineTool } from '@deepseek-ai/dsh-tools'
3
+ import {
4
+ buildUrl, normalizeBase, asLimit, summarizeSearch, summarizeHot,
5
+ summarizeHs, summarizeList, summarizeFx,
6
+ } from './core.js'
7
+
8
+ export const name = 'dsh-plugin-mj7'
9
+ export const inject = ['tools']
10
+
11
+ const text = (value) => [{ type: 'text', text: JSON.stringify(value, null, 2) }]
12
+ const headers = { 'user-agent': 'dsh-plugin-mj7/0.1', accept: 'application/json' }
13
+
14
+ export function apply(ctx, config = {}) {
15
+ const base = normalizeBase(config.baseUrl)
16
+
17
+ async function getJson(path, params, signal) {
18
+ const r = await fetch(buildUrl(base, path, params), { headers, signal })
19
+ if (!r.ok) throw new Error(`mj7 API HTTP ${r.status} (${path})`)
20
+ return r.json()
21
+ }
22
+
23
+ ctx.tools.register(defineTool({
24
+ name: 'mj7_search',
25
+ description: '搜索模极社(mj7.cn):标准、产品、材料。返回总数与分组摘要,含站内详情标识。',
26
+ parameters: {
27
+ kw: { type: 'string', required: true, description: '关键词,如“法兰”“ISO 4703”' },
28
+ limit: { type: 'number', description: '每组返回条数,默认 6' },
29
+ },
30
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
31
+ isConcurrencySafe: () => true,
32
+ async execute(args, exec) {
33
+ const json = await getJson('/api/search', { kw: args.kw }, exec.signal)
34
+ return summarizeSearch(json, asLimit(args.limit))
35
+ },
36
+ }))
37
+
38
+ ctx.tools.register(defineTool({
39
+ name: 'mj7_hot',
40
+ description: '模极社热门品类/关键词列表。',
41
+ parameters: {},
42
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
43
+ isConcurrencySafe: () => true,
44
+ async execute(_args, exec) {
45
+ return summarizeHot(await getJson('/api/hot', {}, exec.signal))
46
+ },
47
+ }))
48
+
49
+ ctx.tools.register(defineTool({
50
+ name: 'mj7_hs',
51
+ description: '按 HS 编码联想相关标准(mj7.cn HS 检索)。',
52
+ parameters: {
53
+ code: { type: 'string', required: true, description: 'HS 编码,如 73181500' },
54
+ limit: { type: 'number', description: '返回条数,默认 10' },
55
+ },
56
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
57
+ isConcurrencySafe: () => true,
58
+ async execute(args, exec) {
59
+ const json = await getJson('/api/hs', { code: args.code }, exec.signal)
60
+ return summarizeHs(json, asLimit(args.limit, 10))
61
+ },
62
+ }))
63
+
64
+ ctx.tools.register(defineTool({
65
+ name: 'mj7_terms',
66
+ description: '查 Incoterms 贸易术语(EXW/FOB/CIF 等)的责任划分。',
67
+ parameters: { q: { type: 'string', description: '关键词,留空返回全部' } },
68
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
69
+ isConcurrencySafe: () => true,
70
+ async execute(args, exec) {
71
+ return summarizeList(await getJson('/api/terms', { q: args.q || '' }, exec.signal), 10)
72
+ },
73
+ }))
74
+
75
+ ctx.tools.register(defineTool({
76
+ name: 'mj7_docs',
77
+ description: '查外贸单证清单(商业发票、装箱单、原产地证等)。',
78
+ parameters: { q: { type: 'string', description: '关键词,留空返回全部' } },
79
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
80
+ isConcurrencySafe: () => true,
81
+ async execute(args, exec) {
82
+ return summarizeList(await getJson('/api/docs', { q: args.q || '' }, exec.signal), 10)
83
+ },
84
+ }))
85
+
86
+ ctx.tools.register(defineTool({
87
+ name: 'mj7_fx',
88
+ description: '查人民币汇率(基准 CNY,默认 USD)。',
89
+ parameters: { currency: { type: 'string', description: '目标币种,默认 USD' } },
90
+ output: { schema: { type: 'json' }, render: (_a, v) => text(v) },
91
+ isConcurrencySafe: () => true,
92
+ async execute(args, exec) {
93
+ return summarizeFx(await getJson('/api/fx', { from: (args.currency || 'USD') }, exec.signal),
94
+ args.currency || 'USD')
95
+ },
96
+ }))
97
+ }
package/package.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "@liangjiehappy/dsh-plugin-mj7",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "模极社 mj7.cn 只读数据工具:标准/产品搜索、HS 联想、Incoterms、贸易单证、人民币汇率。只访问 www.mj7.cn。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "files": [
8
+ "lib",
9
+ "cordis.patch.yml",
10
+ "README.md",
11
+ "README.zh-CN.md"
12
+ ],
13
+ "dsh": {
14
+ "bundle": {
15
+ "patch": "./cordis.patch.yml"
16
+ }
17
+ },
18
+ "engines": {
19
+ "dsh": ">=0.2.0"
20
+ },
21
+ "peerDependencies": {
22
+ "@deepseek-ai/cordis": "*",
23
+ "@deepseek-ai/dsh-tools": "*"
24
+ },
25
+ "keywords": [
26
+ "deepseek-harness",
27
+ "dsh",
28
+ "dsh-plugin",
29
+ "mj7",
30
+ "standards",
31
+ "manufacturing",
32
+ "trade"
33
+ ],
34
+ "license": "MIT",
35
+ "scripts": {
36
+ "test": "node --test"
37
+ }
38
+ }