@aiwayds/dsh-mcp-adapter 0.1.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/README.md +90 -0
- package/README.zh.md +82 -0
- package/cordis.patch.yml +33 -0
- package/lib/index.d.ts +342 -0
- package/lib/index.js +623 -0
- package/lib/index.js.map +1 -0
- package/package.json +46 -0
- package/scripts/link-dsh-closure.mjs +91 -0
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aiwayds/dsh-mcp-adapter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "dsh plugin: token-efficient prompt-side shim for the official MCP client — folds mcp__* tool schemas out of every assembled prompt and exposes two constant meta-tools (mcp_list / mcp_call) instead",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22.19.0"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"lib",
|
|
14
|
+
"scripts",
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"README.md",
|
|
17
|
+
"README.zh.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"link-closure": "node scripts/link-dsh-closure.mjs",
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"check": "tsc --noEmit -p tsconfig.json",
|
|
23
|
+
"precheck": "node scripts/link-dsh-closure.mjs",
|
|
24
|
+
"pretest": "npm run build",
|
|
25
|
+
"test": "node --test test/*.test.mjs"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^24.0.0",
|
|
29
|
+
"typescript": "~5.9.0"
|
|
30
|
+
},
|
|
31
|
+
"dsh": {
|
|
32
|
+
"bundle": {
|
|
33
|
+
"patch": "./cordis.patch.yml"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"author": "fan56",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/fan56/dsh-mcp-adapter.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/fan56/dsh-mcp-adapter",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"registry": "https://registry.npmjs.org/"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postinstall linker: point every `node_modules/@deepseek-ai/*` entry at the
|
|
3
|
+
* global dsh closure.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: dsh-tui-pi is a plugin that runs *inside* the installed
|
|
6
|
+
* dsh CLI, and its source imports the `@deepseek-ai/*` packages (cordis,
|
|
7
|
+
* dsh-session, dsh-settings, schemastery, …). Those packages are **not**
|
|
8
|
+
* resolvable from the public npm registry in a usable way (their rc.6
|
|
9
|
+
* versions live only in the dsh install's own node_modules), so the repo
|
|
10
|
+
* resolves them from the *global dsh closure* —
|
|
11
|
+
* `$(realpath $(which dsh))/node_modules/@deepseek-ai` — via plain symlinks.
|
|
12
|
+
*
|
|
13
|
+
* The contract: ALL `@deepseek-ai/*` resolve to that single closure instance,
|
|
14
|
+
* so there is exactly one `@deepseek-ai/cordis` in the type graph. Declaring
|
|
15
|
+
* any of them in package.json made `pnpm install` create a second local copy
|
|
16
|
+
* in `.pnpm`, which broke the cordis `declare module` augmentation
|
|
17
|
+
* (`Property 'settings' does not exist on type 'Context'`), so they must stay
|
|
18
|
+
* *undeclared*. pnpm then treats the closure links as extraneous — and, as
|
|
19
|
+
* it prunes entries it once managed, the links can still disappear after an
|
|
20
|
+
* install. This script re-creates them on every `pnpm install` (postinstall).
|
|
21
|
+
*
|
|
22
|
+
* It is a no-op (exit 0) when no global dsh install is found — a dev machine
|
|
23
|
+
* without dsh simply cannot typecheck against dsh types.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { execFileSync } from 'node:child_process'
|
|
27
|
+
import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, symlinkSync } from 'node:fs'
|
|
28
|
+
import { dirname, join } from 'node:path'
|
|
29
|
+
import { fileURLToPath } from 'node:url'
|
|
30
|
+
|
|
31
|
+
const repoRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
32
|
+
// Guard: this postinstall is a dev-machine convenience for THIS repo. A
|
|
33
|
+
// published tarball carries scripts/ but no src/, and must never touch a
|
|
34
|
+
// consumer's node_modules (it would delete their @deepseek-ai packages and
|
|
35
|
+
// replace them with symlinks into their global dsh closure). pnpm ≥10 blocks
|
|
36
|
+
// dependency lifecycle scripts by default, but npm would run this — exit
|
|
37
|
+
// silently outside the repo.
|
|
38
|
+
if (!existsSync(join(repoRoot, 'src'))) {
|
|
39
|
+
process.exit(0)
|
|
40
|
+
}
|
|
41
|
+
const scopeDir = join(repoRoot, 'node_modules', '@deepseek-ai')
|
|
42
|
+
|
|
43
|
+
/** The global dsh package's own `node_modules/@deepseek-ai` closure dir. */
|
|
44
|
+
function findDshClosure() {
|
|
45
|
+
// 1) Follow the `dsh` bin — the most faithful pointer to the installed CLI
|
|
46
|
+
// (`/opt/homebrew/bin/dsh` → …/lib/bin.js → pkg dir → its node_modules).
|
|
47
|
+
try {
|
|
48
|
+
const bin = execFileSync('which', ['dsh'], { encoding: 'utf8' }).trim()
|
|
49
|
+
if (bin !== '') {
|
|
50
|
+
const real = realpathSync(bin)
|
|
51
|
+
const closure = join(dirname(dirname(real)), 'node_modules', '@deepseek-ai')
|
|
52
|
+
if (existsSync(join(closure, 'cordis'))) return closure
|
|
53
|
+
}
|
|
54
|
+
} catch { /* dsh not on PATH */ }
|
|
55
|
+
// 2) Fall back to the global node_modules root — the dsh package's own
|
|
56
|
+
// nested closure (what current npm produces for a global install).
|
|
57
|
+
try {
|
|
58
|
+
const root = execFileSync('npm', ['root', '-g'], { encoding: 'utf8' }).trim()
|
|
59
|
+
const nested = join(root, '@deepseek-ai', 'dsh', 'node_modules', '@deepseek-ai')
|
|
60
|
+
if (existsSync(join(nested, 'cordis'))) return nested
|
|
61
|
+
// 3) Last resort: npm's flat global layout, where dsh's @deepseek-ai/*
|
|
62
|
+
// deps are hoisted straight into <npm root -g>/@deepseek-ai next to
|
|
63
|
+
// the dsh package itself.
|
|
64
|
+
const flat = join(root, '@deepseek-ai')
|
|
65
|
+
if (existsSync(join(flat, 'cordis'))) return flat
|
|
66
|
+
} catch { /* npm unavailable */ }
|
|
67
|
+
return undefined
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const closure = findDshClosure()
|
|
71
|
+
if (closure === undefined) {
|
|
72
|
+
console.warn('[link-dsh-closure] global dsh not found — skipping @deepseek-ai links (dev without dsh)')
|
|
73
|
+
process.exit(0)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
mkdirSync(scopeDir, { recursive: true })
|
|
77
|
+
let linked = 0
|
|
78
|
+
for (const name of readdirSync(closure)) {
|
|
79
|
+
const target = join(scopeDir, name)
|
|
80
|
+
const source = join(closure, name)
|
|
81
|
+
try {
|
|
82
|
+
// Replace any existing entry (stale symlink, or a local .pnpm copy a
|
|
83
|
+
// previous install created) with the closure link.
|
|
84
|
+
rmSync(target, { recursive: true, force: true })
|
|
85
|
+
symlinkSync(source, target, 'junction')
|
|
86
|
+
linked++
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.warn(`[link-dsh-closure] failed to link ${name}: ${(error instanceof Error ? error.message : String(error))}`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log(`[link-dsh-closure] linked ${linked} @deepseek-ai/* packages from ${closure}`)
|