dsh-plugin-experts 0.1.0 → 0.1.2
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/dist/dsh-package.mjs +116 -0
- package/dist/host.js +4 -2
- package/package.json +3 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reaching an official Harness package from a third-party Host half.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists: `install_bundle` links a workspace directory into the
|
|
5
|
+
* profile, and Node resolves a plugin's bare-specifier imports from that
|
|
6
|
+
* directory's **realpath** — the user's source tree, far outside the dsh
|
|
7
|
+
* installation. So `import '@deepseek-ai/dsh-mcp-client'` fails with
|
|
8
|
+
* ERR_MODULE_NOT_FOUND even though the package is right there in the running
|
|
9
|
+
* app. Verified on 0.2.0-rc.2; see docs/PORTING-NOTES.md §9.
|
|
10
|
+
*
|
|
11
|
+
* The anchor order mirrors app-boot's own `resolveBundleDir`: the installation
|
|
12
|
+
* first, the profile second, so an in-box package is never shadowed by a
|
|
13
|
+
* profile-local copy. Resolution through the same anchor also means the import
|
|
14
|
+
* lands on the same absolute file the official rows use, so Node's module cache
|
|
15
|
+
* hands back the same instance rather than a second one.
|
|
16
|
+
*
|
|
17
|
+
* @module shared/dsh-package
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { createRequire } from 'node:module'
|
|
21
|
+
import { isAbsolute, join } from 'node:path'
|
|
22
|
+
import { pathToFileURL } from 'node:url'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Candidate resolution anchors, most authoritative first.
|
|
26
|
+
* @param {{ argv?: readonly string[], cwd?: string }} [options] - overrides for tests.
|
|
27
|
+
* @returns {string[]} absolute anchors suitable for `createRequire`.
|
|
28
|
+
*/
|
|
29
|
+
export function dshResolutionAnchors({ argv = process.argv, cwd = process.cwd() } = {}) {
|
|
30
|
+
const anchors = []
|
|
31
|
+
// The script the host process was started with lives inside the installation:
|
|
32
|
+
// <dsh home>/node_modules/@deepseek-ai/dsh-desktop-host/lib/index.js
|
|
33
|
+
if (typeof argv[1] === 'string' && isAbsolute(argv[1])) anchors.push(argv[1])
|
|
34
|
+
// The desktop host is additionally handed the dsh home as its first argument.
|
|
35
|
+
if (typeof argv[2] === 'string' && isAbsolute(argv[2])) anchors.push(join(argv[2], 'package.json'))
|
|
36
|
+
// Profile-local packages last, so they can never shadow the installation.
|
|
37
|
+
anchors.push(join(cwd, 'package.json'))
|
|
38
|
+
return [...new Set(anchors)]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Test seam: specifiers answered from memory instead of the installation.
|
|
43
|
+
*
|
|
44
|
+
* Offline verification runs a Host half's `apply()` outside DSH, where the
|
|
45
|
+
* installation does not exist. A feature that needs `storageDomain` or the MCP
|
|
46
|
+
* client would otherwise be unverifiable until it is installed — exactly the
|
|
47
|
+
* situation shared/host/route.mjs and the rest of the harness exist to avoid.
|
|
48
|
+
*
|
|
49
|
+
* This only substitutes *resolution*; the real anchor walk stays the default and
|
|
50
|
+
* is covered directly by tests/dsh-package.test.mjs.
|
|
51
|
+
*
|
|
52
|
+
* The map lives on `globalThis` under a symbol: the published bundle ships this
|
|
53
|
+
* file as its own module (`dist/dsh-package.mjs`), so a test process holds two
|
|
54
|
+
* instances of it — the repo copy and the bundle copy. Module-level state would
|
|
55
|
+
* split them, and stubs registered through the repo copy would silently stop
|
|
56
|
+
* resolving inside the bundle. One shared registry keeps every instance honest.
|
|
57
|
+
* @type {Map<string, Record<string, unknown>>}
|
|
58
|
+
*/
|
|
59
|
+
const STUBS_KEY = Symbol.for('dsh-skills:dsh-package-stubs')
|
|
60
|
+
const stubs = (globalThis[STUBS_KEY] ??= new Map())
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Answer one specifier from memory for the rest of this process.
|
|
64
|
+
* @param {string} specifier - package name to stub.
|
|
65
|
+
* @param {Record<string, unknown>} module - the module namespace to return.
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*/
|
|
68
|
+
export function setDshPackageStub(specifier, module) {
|
|
69
|
+
stubs.set(specifier, module)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Remove every stub. */
|
|
73
|
+
export function clearDshPackageStubs() {
|
|
74
|
+
stubs.clear()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Resolve an official package to its entry file.
|
|
79
|
+
* @param {string} specifier - the package name to resolve.
|
|
80
|
+
* @param {{ argv?: readonly string[], cwd?: string }} [options] - overrides for tests.
|
|
81
|
+
* @returns {string} absolute path of the resolved entry file.
|
|
82
|
+
* @throws {Error} with the anchors and codes tried when nothing resolves.
|
|
83
|
+
*/
|
|
84
|
+
export function resolveDshPackage(specifier, options = {}) {
|
|
85
|
+
if (stubs.has(specifier)) return `stub:${specifier}`
|
|
86
|
+
const tried = []
|
|
87
|
+
for (const anchor of dshResolutionAnchors(options)) {
|
|
88
|
+
try {
|
|
89
|
+
return createRequire(anchor).resolve(specifier)
|
|
90
|
+
} catch (error) {
|
|
91
|
+
tried.push(`${anchor} (${error?.code ?? error?.name ?? 'error'})`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(
|
|
95
|
+
`dsh-skills: cannot resolve ${JSON.stringify(specifier)} from the dsh installation or the profile.\n`
|
|
96
|
+
+ `Tried: ${tried.join(', ')}\n`
|
|
97
|
+
+ 'A Host half must not import an official package by bare specifier: Node resolves that from\n'
|
|
98
|
+
+ "this plugin's realpath, which is outside the installation. Use importDshPackage() instead.",
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Import an official package from the installation.
|
|
104
|
+
*
|
|
105
|
+
* Resolving to the same absolute file the official rows use means a second
|
|
106
|
+
* module instance is never created, which matters for plugins that coordinate
|
|
107
|
+
* through module-level state (for example mcp-client's `serverName` reservations).
|
|
108
|
+
* @param {string} specifier - the package name to import.
|
|
109
|
+
* @param {{ argv?: readonly string[], cwd?: string }} [options] - overrides for tests.
|
|
110
|
+
* @returns {Promise<Record<string, unknown>>} the imported module namespace.
|
|
111
|
+
*/
|
|
112
|
+
export async function importDshPackage(specifier, options) {
|
|
113
|
+
const stub = stubs.get(specifier)
|
|
114
|
+
if (stub !== undefined) return stub
|
|
115
|
+
return import(pathToFileURL(resolveDshPackage(specifier, options)).href)
|
|
116
|
+
}
|
package/dist/host.js
CHANGED
|
@@ -60,7 +60,8 @@ function dshResolutionAnchors({ argv = process.argv, cwd = process.cwd() } = {})
|
|
|
60
60
|
anchors.push(join(cwd, "package.json"));
|
|
61
61
|
return [...new Set(anchors)];
|
|
62
62
|
}
|
|
63
|
-
var
|
|
63
|
+
var STUBS_KEY = /* @__PURE__ */ Symbol.for("dsh-skills:dsh-package-stubs");
|
|
64
|
+
var stubs = globalThis[STUBS_KEY] ??= /* @__PURE__ */ new Map();
|
|
64
65
|
function resolveDshPackage(specifier, options = {}) {
|
|
65
66
|
if (stubs.has(specifier)) return `stub:${specifier}`;
|
|
66
67
|
const tried = [];
|
|
@@ -951,6 +952,7 @@ function registerExpertManagerSkill(ctx) {
|
|
|
951
952
|
}
|
|
952
953
|
|
|
953
954
|
// ../library/src/tools.js
|
|
955
|
+
import { importDshPackage as importDshPackage2 } from "./dsh-package.mjs";
|
|
954
956
|
function compileValue(node) {
|
|
955
957
|
if (node === null || typeof node !== "object") throw new Error("dsh-plugin-library: schema node must be an object");
|
|
956
958
|
if (node.type === "object") {
|
|
@@ -1003,7 +1005,7 @@ var cached2;
|
|
|
1003
1005
|
async function loadDefineTool() {
|
|
1004
1006
|
if (cached2 !== void 0) return cached2;
|
|
1005
1007
|
try {
|
|
1006
|
-
const mod = await
|
|
1008
|
+
const mod = await importDshPackage2("@deepseek-ai/dsh-tools");
|
|
1007
1009
|
if (typeof mod?.defineTool === "function") {
|
|
1008
1010
|
cached2 = mod.defineTool;
|
|
1009
1011
|
return cached2;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-experts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "可复用的专家角色:草稿、不可变的已发布修订,以及按会话采用。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/host.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": "./
|
|
8
|
+
".": "./dist/host.js",
|
|
9
9
|
"./client": "./dist/client.js",
|
|
10
10
|
"./package.json": "./package.json",
|
|
11
11
|
"./locale/*.json": "./locale/*.json"
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"dist/host.js",
|
|
32
32
|
"dist/client.js",
|
|
33
|
+
"dist/dsh-package.mjs",
|
|
33
34
|
"cordis.patch.yml",
|
|
34
35
|
"locale/*.json",
|
|
35
36
|
"resources/**/*",
|