dsh-cite 0.2.0 → 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 stardustlc
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.en.md CHANGED
@@ -13,6 +13,10 @@ A DeepSeek Harness plugin for bibliographic references: query Crossref and forma
13
13
  | `cite_bibtex` | Generate a BibTeX entry | `doi`; `key` optional |
14
14
  | `cite_check` | Extract DOIs from text and validate them | `text`; `maxChecks` 1-50, default 10 |
15
15
 
16
+ ## Compatibility
17
+
18
+ Verified against `@deepseek-ai/dsh@0.1.1-rc.2` on 2026-08-26. Built for the cordis patch-bundle plugin model (`cordis.patch.yml` + `dsh.bundle.patch`). No runtime imports of `@deepseek-ai/*` internals.
19
+
16
20
  ## Install
17
21
 
18
22
  ```bash
@@ -20,3 +24,15 @@ dsh plugin --profile web add dsh-cite
20
24
  ```
21
25
 
22
26
  MIT
27
+
28
+ ## Uninstall
29
+
30
+ ```bash
31
+ dsh plugin --profile web remove dsh-cite
32
+ ```
33
+
34
+ Then restart the web service. To clean up fully, also remove the plugin entry from your profile `cordis.patch.yml` if you overrode it.
35
+
36
+ ## License
37
+
38
+ MIT (see [LICENSE](LICENSE))
package/README.md CHANGED
@@ -13,12 +13,25 @@ DeepSeek Harness 参考文献工具插件:通过 Crossref API 查询文献元
13
13
  | `cite_bibtex` | 生成 BibTeX 条目 | `doi` 必填;`key` 可选 |
14
14
  | `cite_check` | 从文本提取 DOI 并并发校验是否存在(并发 3,保持输入顺序) | `text` 必填;`maxChecks` 1-50 默认 10 |
15
15
 
16
+ ## 兼容性
17
+
18
+ 在 `@deepseek-ai/dsh@0.1.1-rc.2` 上验证(2026-08-26)。遵循 cordis 组合包补丁模型(`cordis.patch.yml` + `dsh.bundle.patch`),运行时不 import 任何 `@deepseek-ai/*` 内部模块。
19
+
16
20
  ## 安装
17
21
 
18
22
  ```bash
19
23
  dsh plugin --profile web add dsh-cite
20
24
  ```
21
25
 
26
+ ## 卸载
27
+
28
+ ```bash
29
+ dsh plugin --profile web remove dsh-cite
30
+ ```
31
+
32
+ 卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile `cordis.patch.yml` 中覆盖的插件行。
33
+
34
+
22
35
  ## 示例
23
36
 
24
37
  ```text
@@ -56,3 +69,6 @@ pnpm test # 构建 + 18 个测试
56
69
  ```
57
70
 
58
71
  MIT
72
+ ## License
73
+
74
+ MIT(见 [LICENSE](LICENSE))
package/lib/crossref.js CHANGED
@@ -135,7 +135,7 @@ export function extractDois(text) {
135
135
  const seen = new Set();
136
136
  const result = [];
137
137
  for (const match of text.match(pattern) ?? []) {
138
- const clean = match.replace(/[.,;]+$/, '').trim();
138
+ const clean = match.replace(/[.,;:)\]}'">]+$/, '').trim();
139
139
  if (seen.has(clean.toLowerCase()))
140
140
  continue;
141
141
  seen.add(clean.toLowerCase());
package/lib/format.js CHANGED
@@ -26,7 +26,7 @@ function initials(given) {
26
26
  }
27
27
  function apaName(author) {
28
28
  const family = author.family !== '' ? author.family : (author.name !== '' ? author.name : author.given);
29
- const initialsText = author.given !== '' ? initials(author.given) : (author.name !== '' ? initials(author.name.split(/[\s-]+/)[0] ?? '') : '');
29
+ const initialsText = author.given !== '' ? initials(author.given) : '';
30
30
  return initialsText !== '' ? family + ', ' + initialsText : family;
31
31
  }
32
32
  function mlaName(author, first) {
@@ -52,7 +52,9 @@ function apaAuthors(authors) {
52
52
  return names[0];
53
53
  if (names.length === 2)
54
54
  return names[0] + ', & ' + names[1];
55
- return names.slice(0, 19).join(', ') + ', ...';
55
+ if (names.length <= 20)
56
+ return names.slice(0, -1).join(', ') + ', & ' + names[names.length - 1];
57
+ return names.slice(0, 19).join(', ') + ', ... ' + names[names.length - 1];
56
58
  }
57
59
  function mlaAuthors(authors) {
58
60
  if (authors.length === 0)
@@ -201,7 +203,21 @@ export function buildCitation(work, style, lang = 'zh') {
201
203
  }
202
204
  }
203
205
  function escapeLatex(value) {
204
- return value.replace(/([{}])/g, '\\$1').replace(/&/g, '\\&').replace(/%/g, '\\%').replace(/\$/g, '\\$');
206
+ return value.replace(/[\\{}&%$#_~^]/g, (ch) => {
207
+ switch (ch) {
208
+ case '\\': return '\\textbackslash{}';
209
+ case '{': return '\\{';
210
+ case '}': return '\\}';
211
+ case '&': return '\\&';
212
+ case '%': return '\\%';
213
+ case '$': return '\\$';
214
+ case '#': return '\\#';
215
+ case '_': return '\\_';
216
+ case '~': return '\\textasciitilde{}';
217
+ case '^': return '\\textasciicircum{}';
218
+ default: return ch;
219
+ }
220
+ });
205
221
  }
206
222
  /** BibTeX 引用键只允许安全字符,空格/逗号/花括号等替换为下划线。 */
207
223
  function sanitizeBibtexKey(value) {
package/lib/index.d.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  import { type CiteConfig } from './config.js';
11
11
  import { type CiteToolDefinition } from './tools.js';
12
12
  /** cordis 服务注入:apply 里要用 ctx.tools。 */
13
+ export declare const name = "cite";
13
14
  export declare const inject: string[];
14
15
  export interface CitePluginContext {
15
16
  tools: {
package/lib/index.js CHANGED
@@ -10,6 +10,7 @@
10
10
  import { resolveConfig } from './config.js';
11
11
  import { buildCiteTools } from './tools.js';
12
12
  /** cordis 服务注入:apply 里要用 ctx.tools。 */
13
+ export const name = 'cite';
13
14
  export const inject = ['tools'];
14
15
  export function apply(ctx, config) {
15
16
  let cfg;
package/lib/tools.js CHANGED
@@ -207,5 +207,49 @@ export function buildCiteTools(cfg, fetchImpl) {
207
207
  },
208
208
  timeoutMs: cfg.timeoutMs * 3 + 5000,
209
209
  };
210
- return [citeLookup, citeFormat, citeBibtex, citeCheck];
210
+ const citeHealth = {
211
+ name: 'cite_health',
212
+ description: 'dsh-cite 自检:向 Crossref API 发一个最小请求验证连通性(rows=1),报告延迟。遇到问题时先运行本工具定位。',
213
+ parameters: compileParameters({}),
214
+ output: {
215
+ schema: { type: 'object', additionalProperties: true },
216
+ render: (_args, value) => {
217
+ const rec = (value ?? {});
218
+ const rawChecks = Array.isArray(rec.checks) ? rec.checks : [];
219
+ const checks = rawChecks.map((item) => (item ?? {}));
220
+ const lines = ['dsh-cite 自检' + (rec.ok === true ? ':正常。' : ':发现问题。')];
221
+ for (const c of checks) {
222
+ lines.push('- ' + c.name + ':' + (c.ok === true ? '✅' : '❌ ' + String(c.detail ?? '')));
223
+ }
224
+ return [{ type: 'text', text: lines.join('\n') }];
225
+ },
226
+ },
227
+ async execute() {
228
+ const checks = [];
229
+ let ok = true;
230
+ const startedAt = Date.now();
231
+ try {
232
+ const fetcher = fetchImpl ?? globalThis.fetch;
233
+ const response = await fetcher('https://api.crossref.org/works?rows=1&select=DOI', {
234
+ headers: { 'user-agent': cfg.userAgent },
235
+ signal: AbortSignal.timeout(Math.min(cfg.timeoutMs, 15000)),
236
+ });
237
+ if (response.ok) {
238
+ checks.push({ name: 'Crossref API', ok: true, detail: 'HTTP ' + response.status + ',' + (Date.now() - startedAt) + 'ms' });
239
+ }
240
+ else {
241
+ ok = false;
242
+ checks.push({ name: 'Crossref API', ok: false, detail: 'HTTP ' + response.status });
243
+ }
244
+ }
245
+ catch (error) {
246
+ ok = false;
247
+ checks.push({ name: 'Crossref API', ok: false, detail: (error instanceof Error ? error.message : String(error)) + '(网络需要特殊代理时请配置系统代理后重启)' });
248
+ }
249
+ checks.push({ name: '请求配置', ok: true, detail: 'timeoutMs=' + cfg.timeoutMs + ',UA 已配置' });
250
+ return { ok, plugin: 'dsh-cite', checks };
251
+ },
252
+ timeoutMs: Math.min(cfg.timeoutMs + 5000, 30000),
253
+ };
254
+ return [citeLookup, citeFormat, citeBibtex, citeCheck, citeHealth];
211
255
  }
package/package.json CHANGED
@@ -1,64 +1,63 @@
1
- {
2
- "name": "dsh-cite",
3
- "version": "0.2.0",
4
- "description": "DSH 参考文献工具插件:cite_lookup/cite_format/cite_bibtex/cite_check 四工具,Crossref 元数据查询(含 DOI 精确解析与并发校验),GB/T 7714 / APA / MLA / Chicago 格式化,零运行时依赖。",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "types": "lib/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./lib/index.d.ts",
11
- "default": "./lib/index.js"
12
- },
13
- "./cordis.patch.yml": "./cordis.patch.yml",
14
- "./package.json": "./package.json"
15
- },
16
- "files": [
17
- "lib",
18
- "cordis.patch.yml",
19
- "README.md",
20
- "README.en.md"
21
- ],
22
- "scripts": {
23
- "build": "tsc -p tsconfig.json",
24
- "prepare": "tsc -p tsconfig.json",
25
- "typecheck": "tsc -p tsconfig.json --noEmit",
26
- "test": "pnpm run build && node --test \"test/*.test.mjs\"",
27
- "prepublishOnly": "pnpm run build"
28
- },
29
- "dsh": {
30
- "bundle": {
31
- "patch": "./cordis.patch.yml"
32
- }
33
- },
34
- "keywords": [
35
- "dsh",
36
- "deepseek-harness",
37
- "plugin",
38
- "citation",
39
- "crossref",
40
- "gb-t-7714",
41
- "apa",
42
- "mla",
43
- "chicago",
44
- "dsh-plugin"
45
- ],
46
- "license": "MIT",
47
- "engines": {
48
- "node": ">=22.13"
49
- },
50
- "devDependencies": {
51
- "@types/node": "^24.0.0",
52
- "typescript": "^5.6.0"
53
- },
54
- "repository": {
55
- "type": "git",
56
- "url": "git+https://github.com/STARDUSTLC666/dsh-cite.git"
57
- },
58
- "bugs": {
59
- "url": "https://github.com/STARDUSTLC666/dsh-cite/issues"
60
- },
61
- "homepage": "https://github.com/STARDUSTLC666/dsh-cite#readme",
62
- "author": "stardustlc",
63
- "packageManager": "pnpm@11.7.0"
64
- }
1
+ {
2
+ "name": "dsh-cite",
3
+ "version": "0.3.0",
4
+ "description": "DSH 参考文献工具插件:cite_lookup/cite_format/cite_bibtex/cite_check 四工具,Crossref 元数据查询(含 DOI 精确解析与并发校验),GB/T 7714 / APA / MLA / Chicago 格式化,零运行时依赖。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./cordis.patch.yml": "./cordis.patch.yml",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "lib",
18
+ "cordis.patch.yml",
19
+ "README.md",
20
+ "README.en.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.json",
24
+ "typecheck": "tsc -p tsconfig.json --noEmit",
25
+ "test": "pnpm run build && node --test \"test/*.test.mjs\"",
26
+ "prepublishOnly": "pnpm run build"
27
+ },
28
+ "dsh": {
29
+ "bundle": {
30
+ "patch": "./cordis.patch.yml"
31
+ }
32
+ },
33
+ "keywords": [
34
+ "dsh",
35
+ "deepseek-harness",
36
+ "plugin",
37
+ "citation",
38
+ "crossref",
39
+ "gb-t-7714",
40
+ "apa",
41
+ "mla",
42
+ "chicago",
43
+ "dsh-plugin"
44
+ ],
45
+ "license": "MIT",
46
+ "engines": {
47
+ "node": ">=22"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^24.0.0",
51
+ "typescript": "^5.6.0"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/STARDUSTLC666/dsh-cite.git"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/STARDUSTLC666/dsh-cite/issues"
59
+ },
60
+ "homepage": "https://github.com/STARDUSTLC666/dsh-cite#readme",
61
+ "author": "stardustlc",
62
+ "packageManager": "pnpm@11.7.0"
63
+ }