@aipanel/provider-deepseek 1.2.0-beta.2 → 1.2.0-beta.3
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/es/dsh-install.d.ts +13 -8
- package/es/dsh-install.js +17 -14
- package/es/profile.d.ts +4 -4
- package/es/profile.js +14 -20
- package/es/provider.d.ts +0 -3
- package/es/provider.js +22 -14
- package/lib/dsh-install.cjs +21 -17
- package/lib/dsh-install.d.ts +13 -8
- package/lib/profile.cjs +13 -19
- package/lib/profile.d.ts +4 -4
- package/lib/provider.cjs +18 -11
- package/lib/provider.d.ts +0 -3
- package/package.json +3 -6
- package/dsh-plugin/dist/index.js +0 -110
package/es/dsh-install.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
export declare const DSH_CLIENT_PACKAGE = "@aipanel/dsh-client";
|
|
2
|
+
export declare const DSH_PLUGIN_PACKAGE = "@aipanel/dsh-plugin";
|
|
2
3
|
/**
|
|
3
|
-
* 是否为 dev workspace
|
|
4
|
-
* 生产安装的 provider 在 node_modules/@aipanel/provider-deepseek/ 下,上一级不是 dsh
|
|
4
|
+
* 是否为 dev workspace 且某 dsh 包产物就绪(存在 package.json 与产物文件)。
|
|
5
|
+
* 生产安装的 provider 在 node_modules/@aipanel/provider-deepseek/ 下,上一级不是 dsh-*,返回 null。
|
|
6
|
+
* @param metaUrl 调用方 import.meta.url(provider 源码 es/lib 的上一级是 packages/providers/deepseek)
|
|
7
|
+
* @param subdir dev 子目录名("dsh-client" | "dsh-plugin")
|
|
8
|
+
* @param distRel 产物相对路径(client 为 "lib/client.js",plugin 为 "dist/index.js")
|
|
5
9
|
*/
|
|
6
|
-
export declare function
|
|
10
|
+
export declare function resolveDevDshPackageSource(metaUrl: string, subdir: string, distRel: string): string | null;
|
|
7
11
|
/** dsh web profile 目录(固定 --profile web);home 未指定时回退 $DSH_HOME / ~/.dsh */
|
|
8
12
|
export declare function dshProfileDir(home?: string): string;
|
|
9
|
-
/** @aipanel/dsh
|
|
10
|
-
export declare function
|
|
13
|
+
/** 某 @aipanel/dsh-* 包在 profile 的 node_modules 中是否可解析 */
|
|
14
|
+
export declare function isDshPackageInstalled(profileDir: string, packageName: string): boolean;
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
* 确保某 @aipanel/dsh-* 包已安装且为最新(官方命令 dsh plugin add)。
|
|
13
17
|
* 每次启动都执行(不跳过已安装):dev 本地目录每次重装保证改代码生效,
|
|
14
|
-
* 生产 npm 包每次检查 registry 拉取最新版本。安装失败返回 false
|
|
18
|
+
* 生产 npm 包每次检查 registry 拉取最新版本。安装失败返回 false(不阻塞启动,
|
|
19
|
+
* 仅对应 overlay 行停用,如失去 chip 高亮 / 审查工具)。
|
|
15
20
|
*/
|
|
16
|
-
export declare function
|
|
21
|
+
export declare function ensureDshPackage(profileDir: string, packageName: string, target: string, home?: string): Promise<boolean>;
|
package/es/dsh-install.js
CHANGED
|
@@ -6,10 +6,14 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { createLogger } from "@aipanel/core/node";
|
|
7
7
|
const log = createLogger("DshInstall");
|
|
8
8
|
const DSH_CLIENT_PACKAGE = "@aipanel/dsh-client";
|
|
9
|
-
|
|
9
|
+
const DSH_PLUGIN_PACKAGE = "@aipanel/dsh-plugin";
|
|
10
|
+
function packageJsonIn(profileDir, packageName) {
|
|
11
|
+
return path.join(profileDir, "node_modules", ...packageName.split("/"), "package.json");
|
|
12
|
+
}
|
|
13
|
+
function resolveDevDshPackageSource(metaUrl, subdir, distRel) {
|
|
10
14
|
const here = path.dirname(fileURLToPath(metaUrl));
|
|
11
|
-
const devDir = path.resolve(here,
|
|
12
|
-
if (fs.existsSync(path.join(devDir, "package.json")) && fs.existsSync(path.join(devDir,
|
|
15
|
+
const devDir = path.resolve(here, `../${subdir}`);
|
|
16
|
+
if (fs.existsSync(path.join(devDir, "package.json")) && fs.existsSync(path.join(devDir, distRel))) {
|
|
13
17
|
return devDir;
|
|
14
18
|
}
|
|
15
19
|
return null;
|
|
@@ -18,12 +22,10 @@ function dshProfileDir(home) {
|
|
|
18
22
|
const resolved = home || process.env.DSH_HOME || path.join(os.homedir(), ".dsh");
|
|
19
23
|
return path.join(resolved, "profiles", "web");
|
|
20
24
|
}
|
|
21
|
-
function
|
|
22
|
-
return fs.existsSync(
|
|
23
|
-
path.join(profileDir, "node_modules", "@aipanel", "dsh-client", "package.json")
|
|
24
|
-
);
|
|
25
|
+
function isDshPackageInstalled(profileDir, packageName) {
|
|
26
|
+
return fs.existsSync(packageJsonIn(profileDir, packageName));
|
|
25
27
|
}
|
|
26
|
-
async function
|
|
28
|
+
async function ensureDshPackage(profileDir, packageName, target, home) {
|
|
27
29
|
try {
|
|
28
30
|
log.debug(`installing ${target} into dsh profile via dsh plugin add`);
|
|
29
31
|
await execa("dsh", ["plugin", "--profile", "web", "add", target], {
|
|
@@ -34,15 +36,15 @@ async function ensureDshClient(profileDir, target, home) {
|
|
|
34
36
|
...home ? { DSH_HOME: home } : {}
|
|
35
37
|
}
|
|
36
38
|
});
|
|
37
|
-
if (!
|
|
38
|
-
log.warn(`dsh plugin add finished but ${
|
|
39
|
+
if (!isDshPackageInstalled(profileDir, packageName)) {
|
|
40
|
+
log.warn(`dsh plugin add finished but ${packageName} is not resolvable`, {
|
|
39
41
|
profileDir
|
|
40
42
|
});
|
|
41
43
|
return false;
|
|
42
44
|
}
|
|
43
45
|
return true;
|
|
44
46
|
} catch (e) {
|
|
45
|
-
log.warn(`failed to install ${
|
|
47
|
+
log.warn(`failed to install ${packageName} via dsh plugin add`, {
|
|
46
48
|
target,
|
|
47
49
|
error: e instanceof Error ? e.message : String(e)
|
|
48
50
|
});
|
|
@@ -51,8 +53,9 @@ async function ensureDshClient(profileDir, target, home) {
|
|
|
51
53
|
}
|
|
52
54
|
export {
|
|
53
55
|
DSH_CLIENT_PACKAGE,
|
|
56
|
+
DSH_PLUGIN_PACKAGE,
|
|
54
57
|
dshProfileDir,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
ensureDshPackage,
|
|
59
|
+
isDshPackageInstalled,
|
|
60
|
+
resolveDevDshPackageSource
|
|
58
61
|
};
|
package/es/profile.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
export declare function buildDshOverlay(options: {
|
|
3
3
|
vitePort: number;
|
|
4
4
|
cwd: string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** host 插件(@aipanel/dsh-plugin)是否已被同步到 dsh profile;false 时停用该行,避免 fail-loud */
|
|
6
|
+
pluginAvailable?: boolean;
|
|
7
|
+
/** client 插件(@aipanel/dsh-client)是否可被 dsh 解析(provider 已同步到 dsh profile);false 时停用该行,避免 fail-loud */
|
|
7
8
|
clientAvailable?: boolean;
|
|
8
9
|
}): string;
|
|
9
|
-
/** 将 overlay 写入项目缓存目录(
|
|
10
|
-
* node_modules/.cache/opencode 惯例),不污染用户项目根目录。 */
|
|
10
|
+
/** 将 overlay 写入项目缓存目录(AIPANEL_CACHE_DIR 下按 provider 分二级目录),不污染用户项目根目录。 */
|
|
11
11
|
export declare function writeDshOverlay(workspaceCwd: string, overlay: string): string;
|
package/es/profile.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
import { MCP_API_PATH, createLogger } from "@aipanel/core/node";
|
|
3
|
+
import { AIPANEL_CACHE_DIR, MCP_API_PATH, createLogger } from "@aipanel/core/node";
|
|
5
4
|
const log = createLogger("DeepSeekProfile");
|
|
6
5
|
function buildDshOverlay(options) {
|
|
7
|
-
const { vitePort, cwd,
|
|
6
|
+
const { vitePort, cwd, pluginAvailable = true, clientAvailable = true } = options;
|
|
8
7
|
const mcpUrl = `http://127.0.0.1:${vitePort}${MCP_API_PATH}`;
|
|
9
8
|
const rows = [];
|
|
10
9
|
rows.push(
|
|
@@ -18,22 +17,17 @@ function buildDshOverlay(options) {
|
|
|
18
17
|
" headers: {}"
|
|
19
18
|
].join("\n")
|
|
20
19
|
);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
[
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
].join("\n")
|
|
33
|
-
);
|
|
34
|
-
} else {
|
|
35
|
-
log.debug("aipanel dsh-plugin dist not found, skipping host plugin row", { pluginDistPath });
|
|
36
|
-
}
|
|
20
|
+
rows.push(
|
|
21
|
+
[
|
|
22
|
+
" - id: aipanel",
|
|
23
|
+
" name: '@aipanel/dsh-plugin'",
|
|
24
|
+
...pluginAvailable ? [] : [" disabled: true"],
|
|
25
|
+
" inject: [tools, subprocess]",
|
|
26
|
+
" config:",
|
|
27
|
+
` cwd: ${JSON.stringify(cwd)}`,
|
|
28
|
+
" autoDiagnose: true"
|
|
29
|
+
].join("\n")
|
|
30
|
+
);
|
|
37
31
|
rows.push(
|
|
38
32
|
[
|
|
39
33
|
" - id: aipanel-client",
|
|
@@ -44,7 +38,7 @@ function buildDshOverlay(options) {
|
|
|
44
38
|
return ["- insert:", rows.join("\n"), ""].join("\n");
|
|
45
39
|
}
|
|
46
40
|
function writeDshOverlay(workspaceCwd, overlay) {
|
|
47
|
-
const dir = path.join(workspaceCwd,
|
|
41
|
+
const dir = path.join(workspaceCwd, AIPANEL_CACHE_DIR, "dsh");
|
|
48
42
|
fs.mkdirSync(dir, { recursive: true });
|
|
49
43
|
const file = path.join(dir, "dsh-overlay.cordis.yml");
|
|
50
44
|
fs.writeFileSync(file, overlay, "utf-8");
|
package/es/provider.d.ts
CHANGED
|
@@ -36,9 +36,6 @@ export declare class DeepSeekWebProvider implements WebProvider {
|
|
|
36
36
|
start(options: ProviderStartOptions): Promise<ProviderStartResult>;
|
|
37
37
|
/** 把 providerOptions 配置映射为 dsh settings 命名空间 patch(仅含用户显式配置项) */
|
|
38
38
|
private buildSettingsToApply;
|
|
39
|
-
/** 解析 aipanel dsh-plugin 的构建产物路径(存在才在 overlay 里注入插件行)。
|
|
40
|
-
* 注意用 fileURLToPath:URL.pathname 是 percent-encoded,中文路径下 existsSync 会误判不存在。 */
|
|
41
|
-
private resolvePluginDist;
|
|
42
39
|
stop(): Promise<void>;
|
|
43
40
|
killOrphans(): Promise<number>;
|
|
44
41
|
listSessions(projectDir: string): Promise<ChatSession[]>;
|
package/es/provider.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { createLogger } from "@aipanel/core/node";
|
|
6
5
|
import { DEFAULT_DEEPSEEK_PROVIDER_OPTIONS } from "./constants.js";
|
|
7
6
|
import { DSH_LOOPBACK_HOST, DSH_MUX_EVENTS_PATH, DSH_HOST_EVENTS_PATH } from "./constants.js";
|
|
@@ -11,10 +10,11 @@ import { startDeepSeekWeb } from "./deepseek-web.js";
|
|
|
11
10
|
import { buildDshOverlay, writeDshOverlay } from "./profile.js";
|
|
12
11
|
import { checkDeepSeekInstalled, getDeepSeekVersion, killOrphanDeepSeekProcesses } from "./system.js";
|
|
13
12
|
import {
|
|
13
|
+
DSH_CLIENT_PACKAGE,
|
|
14
|
+
DSH_PLUGIN_PACKAGE,
|
|
14
15
|
dshProfileDir,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
DSH_CLIENT_PACKAGE
|
|
16
|
+
ensureDshPackage,
|
|
17
|
+
resolveDevDshPackageSource
|
|
18
18
|
} from "./dsh-install.js";
|
|
19
19
|
const log = createLogger("DeepSeekWebProvider");
|
|
20
20
|
class DeepSeekWebProvider {
|
|
@@ -66,9 +66,11 @@ or run without installing:
|
|
|
66
66
|
cwd: options.cwd,
|
|
67
67
|
vitePort: options.vitePort
|
|
68
68
|
});
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
|
|
69
|
+
const profileDir = dshProfileDir(this.opts.home);
|
|
70
|
+
const devClientDir = resolveDevDshPackageSource(import.meta.url, "dsh-client", "lib/client.js");
|
|
71
|
+
const clientAvailable = await ensureDshPackage(
|
|
72
|
+
profileDir,
|
|
73
|
+
DSH_CLIENT_PACKAGE,
|
|
72
74
|
devClientDir ?? DSH_CLIENT_PACKAGE,
|
|
73
75
|
this.opts.home
|
|
74
76
|
);
|
|
@@ -77,10 +79,22 @@ or run without installing:
|
|
|
77
79
|
metaUrl: import.meta.url
|
|
78
80
|
});
|
|
79
81
|
}
|
|
82
|
+
const devPluginDir = resolveDevDshPackageSource(import.meta.url, "dsh-plugin", "dist/index.js");
|
|
83
|
+
const pluginAvailable = await ensureDshPackage(
|
|
84
|
+
profileDir,
|
|
85
|
+
DSH_PLUGIN_PACKAGE,
|
|
86
|
+
devPluginDir ?? DSH_PLUGIN_PACKAGE,
|
|
87
|
+
this.opts.home
|
|
88
|
+
);
|
|
89
|
+
if (!pluginAvailable) {
|
|
90
|
+
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics & auto-diagnose disabled", {
|
|
91
|
+
metaUrl: import.meta.url
|
|
92
|
+
});
|
|
93
|
+
}
|
|
80
94
|
const overlay = buildDshOverlay({
|
|
81
95
|
vitePort: options.vitePort,
|
|
82
96
|
cwd: options.cwd,
|
|
83
|
-
|
|
97
|
+
pluginAvailable,
|
|
84
98
|
clientAvailable
|
|
85
99
|
});
|
|
86
100
|
const patchPath = writeDshOverlay(options.cwd, overlay);
|
|
@@ -124,12 +138,6 @@ or run without installing:
|
|
|
124
138
|
}
|
|
125
139
|
return sections;
|
|
126
140
|
}
|
|
127
|
-
/** 解析 aipanel dsh-plugin 的构建产物路径(存在才在 overlay 里注入插件行)。
|
|
128
|
-
* 注意用 fileURLToPath:URL.pathname 是 percent-encoded,中文路径下 existsSync 会误判不存在。 */
|
|
129
|
-
resolvePluginDist() {
|
|
130
|
-
const fromHere = new URL("../dsh-plugin/dist/index.js", import.meta.url);
|
|
131
|
-
return fileURLToPath(fromHere);
|
|
132
|
-
}
|
|
133
141
|
async stop() {
|
|
134
142
|
if (this.process) {
|
|
135
143
|
log.debug("Killing dsh web process", { pid: this.process.pid });
|
package/lib/dsh-install.cjs
CHANGED
|
@@ -28,10 +28,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
28
28
|
var dsh_install_exports = {};
|
|
29
29
|
__export(dsh_install_exports, {
|
|
30
30
|
DSH_CLIENT_PACKAGE: () => DSH_CLIENT_PACKAGE,
|
|
31
|
+
DSH_PLUGIN_PACKAGE: () => DSH_PLUGIN_PACKAGE,
|
|
31
32
|
dshProfileDir: () => dshProfileDir,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
ensureDshPackage: () => ensureDshPackage,
|
|
34
|
+
isDshPackageInstalled: () => isDshPackageInstalled,
|
|
35
|
+
resolveDevDshPackageSource: () => resolveDevDshPackageSource
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(dsh_install_exports);
|
|
37
38
|
var import_node_fs = __toESM(require("node:fs"));
|
|
@@ -42,10 +43,14 @@ var import_node_url = require("node:url");
|
|
|
42
43
|
var import_node = require("@aipanel/core/node");
|
|
43
44
|
const log = (0, import_node.createLogger)("DshInstall");
|
|
44
45
|
const DSH_CLIENT_PACKAGE = "@aipanel/dsh-client";
|
|
45
|
-
|
|
46
|
+
const DSH_PLUGIN_PACKAGE = "@aipanel/dsh-plugin";
|
|
47
|
+
function packageJsonIn(profileDir, packageName) {
|
|
48
|
+
return import_node_path.default.join(profileDir, "node_modules", ...packageName.split("/"), "package.json");
|
|
49
|
+
}
|
|
50
|
+
function resolveDevDshPackageSource(metaUrl, subdir, distRel) {
|
|
46
51
|
const here = import_node_path.default.dirname((0, import_node_url.fileURLToPath)(metaUrl));
|
|
47
|
-
const devDir = import_node_path.default.resolve(here,
|
|
48
|
-
if (import_node_fs.default.existsSync(import_node_path.default.join(devDir, "package.json")) && import_node_fs.default.existsSync(import_node_path.default.join(devDir,
|
|
52
|
+
const devDir = import_node_path.default.resolve(here, `../${subdir}`);
|
|
53
|
+
if (import_node_fs.default.existsSync(import_node_path.default.join(devDir, "package.json")) && import_node_fs.default.existsSync(import_node_path.default.join(devDir, distRel))) {
|
|
49
54
|
return devDir;
|
|
50
55
|
}
|
|
51
56
|
return null;
|
|
@@ -54,12 +59,10 @@ function dshProfileDir(home) {
|
|
|
54
59
|
const resolved = home || process.env.DSH_HOME || import_node_path.default.join(import_node_os.default.homedir(), ".dsh");
|
|
55
60
|
return import_node_path.default.join(resolved, "profiles", "web");
|
|
56
61
|
}
|
|
57
|
-
function
|
|
58
|
-
return import_node_fs.default.existsSync(
|
|
59
|
-
import_node_path.default.join(profileDir, "node_modules", "@aipanel", "dsh-client", "package.json")
|
|
60
|
-
);
|
|
62
|
+
function isDshPackageInstalled(profileDir, packageName) {
|
|
63
|
+
return import_node_fs.default.existsSync(packageJsonIn(profileDir, packageName));
|
|
61
64
|
}
|
|
62
|
-
async function
|
|
65
|
+
async function ensureDshPackage(profileDir, packageName, target, home) {
|
|
63
66
|
try {
|
|
64
67
|
log.debug(`installing ${target} into dsh profile via dsh plugin add`);
|
|
65
68
|
await (0, import_execa.execa)("dsh", ["plugin", "--profile", "web", "add", target], {
|
|
@@ -70,15 +73,15 @@ async function ensureDshClient(profileDir, target, home) {
|
|
|
70
73
|
...home ? { DSH_HOME: home } : {}
|
|
71
74
|
}
|
|
72
75
|
});
|
|
73
|
-
if (!
|
|
74
|
-
log.warn(`dsh plugin add finished but ${
|
|
76
|
+
if (!isDshPackageInstalled(profileDir, packageName)) {
|
|
77
|
+
log.warn(`dsh plugin add finished but ${packageName} is not resolvable`, {
|
|
75
78
|
profileDir
|
|
76
79
|
});
|
|
77
80
|
return false;
|
|
78
81
|
}
|
|
79
82
|
return true;
|
|
80
83
|
} catch (e) {
|
|
81
|
-
log.warn(`failed to install ${
|
|
84
|
+
log.warn(`failed to install ${packageName} via dsh plugin add`, {
|
|
82
85
|
target,
|
|
83
86
|
error: e instanceof Error ? e.message : String(e)
|
|
84
87
|
});
|
|
@@ -88,8 +91,9 @@ async function ensureDshClient(profileDir, target, home) {
|
|
|
88
91
|
// Annotate the CommonJS export names for ESM import in node:
|
|
89
92
|
0 && (module.exports = {
|
|
90
93
|
DSH_CLIENT_PACKAGE,
|
|
94
|
+
DSH_PLUGIN_PACKAGE,
|
|
91
95
|
dshProfileDir,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
ensureDshPackage,
|
|
97
|
+
isDshPackageInstalled,
|
|
98
|
+
resolveDevDshPackageSource
|
|
95
99
|
});
|
package/lib/dsh-install.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
export declare const DSH_CLIENT_PACKAGE = "@aipanel/dsh-client";
|
|
2
|
+
export declare const DSH_PLUGIN_PACKAGE = "@aipanel/dsh-plugin";
|
|
2
3
|
/**
|
|
3
|
-
* 是否为 dev workspace
|
|
4
|
-
* 生产安装的 provider 在 node_modules/@aipanel/provider-deepseek/ 下,上一级不是 dsh
|
|
4
|
+
* 是否为 dev workspace 且某 dsh 包产物就绪(存在 package.json 与产物文件)。
|
|
5
|
+
* 生产安装的 provider 在 node_modules/@aipanel/provider-deepseek/ 下,上一级不是 dsh-*,返回 null。
|
|
6
|
+
* @param metaUrl 调用方 import.meta.url(provider 源码 es/lib 的上一级是 packages/providers/deepseek)
|
|
7
|
+
* @param subdir dev 子目录名("dsh-client" | "dsh-plugin")
|
|
8
|
+
* @param distRel 产物相对路径(client 为 "lib/client.js",plugin 为 "dist/index.js")
|
|
5
9
|
*/
|
|
6
|
-
export declare function
|
|
10
|
+
export declare function resolveDevDshPackageSource(metaUrl: string, subdir: string, distRel: string): string | null;
|
|
7
11
|
/** dsh web profile 目录(固定 --profile web);home 未指定时回退 $DSH_HOME / ~/.dsh */
|
|
8
12
|
export declare function dshProfileDir(home?: string): string;
|
|
9
|
-
/** @aipanel/dsh
|
|
10
|
-
export declare function
|
|
13
|
+
/** 某 @aipanel/dsh-* 包在 profile 的 node_modules 中是否可解析 */
|
|
14
|
+
export declare function isDshPackageInstalled(profileDir: string, packageName: string): boolean;
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
* 确保某 @aipanel/dsh-* 包已安装且为最新(官方命令 dsh plugin add)。
|
|
13
17
|
* 每次启动都执行(不跳过已安装):dev 本地目录每次重装保证改代码生效,
|
|
14
|
-
* 生产 npm 包每次检查 registry 拉取最新版本。安装失败返回 false
|
|
18
|
+
* 生产 npm 包每次检查 registry 拉取最新版本。安装失败返回 false(不阻塞启动,
|
|
19
|
+
* 仅对应 overlay 行停用,如失去 chip 高亮 / 审查工具)。
|
|
15
20
|
*/
|
|
16
|
-
export declare function
|
|
21
|
+
export declare function ensureDshPackage(profileDir: string, packageName: string, target: string, home?: string): Promise<boolean>;
|
package/lib/profile.cjs
CHANGED
|
@@ -33,11 +33,10 @@ __export(profile_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(profile_exports);
|
|
34
34
|
var import_fs = __toESM(require("fs"));
|
|
35
35
|
var import_path = __toESM(require("path"));
|
|
36
|
-
var import_url = require("url");
|
|
37
36
|
var import_node = require("@aipanel/core/node");
|
|
38
37
|
const log = (0, import_node.createLogger)("DeepSeekProfile");
|
|
39
38
|
function buildDshOverlay(options) {
|
|
40
|
-
const { vitePort, cwd,
|
|
39
|
+
const { vitePort, cwd, pluginAvailable = true, clientAvailable = true } = options;
|
|
41
40
|
const mcpUrl = `http://127.0.0.1:${vitePort}${import_node.MCP_API_PATH}`;
|
|
42
41
|
const rows = [];
|
|
43
42
|
rows.push(
|
|
@@ -51,22 +50,17 @@ function buildDshOverlay(options) {
|
|
|
51
50
|
" headers: {}"
|
|
52
51
|
].join("\n")
|
|
53
52
|
);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
[
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
].join("\n")
|
|
66
|
-
);
|
|
67
|
-
} else {
|
|
68
|
-
log.debug("aipanel dsh-plugin dist not found, skipping host plugin row", { pluginDistPath });
|
|
69
|
-
}
|
|
53
|
+
rows.push(
|
|
54
|
+
[
|
|
55
|
+
" - id: aipanel",
|
|
56
|
+
" name: '@aipanel/dsh-plugin'",
|
|
57
|
+
...pluginAvailable ? [] : [" disabled: true"],
|
|
58
|
+
" inject: [tools, subprocess]",
|
|
59
|
+
" config:",
|
|
60
|
+
` cwd: ${JSON.stringify(cwd)}`,
|
|
61
|
+
" autoDiagnose: true"
|
|
62
|
+
].join("\n")
|
|
63
|
+
);
|
|
70
64
|
rows.push(
|
|
71
65
|
[
|
|
72
66
|
" - id: aipanel-client",
|
|
@@ -77,7 +71,7 @@ function buildDshOverlay(options) {
|
|
|
77
71
|
return ["- insert:", rows.join("\n"), ""].join("\n");
|
|
78
72
|
}
|
|
79
73
|
function writeDshOverlay(workspaceCwd, overlay) {
|
|
80
|
-
const dir = import_path.default.join(workspaceCwd,
|
|
74
|
+
const dir = import_path.default.join(workspaceCwd, import_node.AIPANEL_CACHE_DIR, "dsh");
|
|
81
75
|
import_fs.default.mkdirSync(dir, { recursive: true });
|
|
82
76
|
const file = import_path.default.join(dir, "dsh-overlay.cordis.yml");
|
|
83
77
|
import_fs.default.writeFileSync(file, overlay, "utf-8");
|
package/lib/profile.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
export declare function buildDshOverlay(options: {
|
|
3
3
|
vitePort: number;
|
|
4
4
|
cwd: string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/** host 插件(@aipanel/dsh-plugin)是否已被同步到 dsh profile;false 时停用该行,避免 fail-loud */
|
|
6
|
+
pluginAvailable?: boolean;
|
|
7
|
+
/** client 插件(@aipanel/dsh-client)是否可被 dsh 解析(provider 已同步到 dsh profile);false 时停用该行,避免 fail-loud */
|
|
7
8
|
clientAvailable?: boolean;
|
|
8
9
|
}): string;
|
|
9
|
-
/** 将 overlay 写入项目缓存目录(
|
|
10
|
-
* node_modules/.cache/opencode 惯例),不污染用户项目根目录。 */
|
|
10
|
+
/** 将 overlay 写入项目缓存目录(AIPANEL_CACHE_DIR 下按 provider 分二级目录),不污染用户项目根目录。 */
|
|
11
11
|
export declare function writeDshOverlay(workspaceCwd: string, overlay: string): string;
|
package/lib/provider.cjs
CHANGED
|
@@ -23,7 +23,6 @@ __export(provider_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(provider_exports);
|
|
25
25
|
const import_meta = {};
|
|
26
|
-
var import_node_url = require("node:url");
|
|
27
26
|
var import_node = require("@aipanel/core/node");
|
|
28
27
|
var import_constants = require("./constants.cjs");
|
|
29
28
|
var import_constants2 = require("./constants.cjs");
|
|
@@ -83,9 +82,11 @@ or run without installing:
|
|
|
83
82
|
cwd: options.cwd,
|
|
84
83
|
vitePort: options.vitePort
|
|
85
84
|
});
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
85
|
+
const profileDir = (0, import_dsh_install.dshProfileDir)(this.opts.home);
|
|
86
|
+
const devClientDir = (0, import_dsh_install.resolveDevDshPackageSource)(import_meta.url, "dsh-client", "lib/client.js");
|
|
87
|
+
const clientAvailable = await (0, import_dsh_install.ensureDshPackage)(
|
|
88
|
+
profileDir,
|
|
89
|
+
import_dsh_install.DSH_CLIENT_PACKAGE,
|
|
89
90
|
devClientDir ?? import_dsh_install.DSH_CLIENT_PACKAGE,
|
|
90
91
|
this.opts.home
|
|
91
92
|
);
|
|
@@ -94,10 +95,22 @@ or run without installing:
|
|
|
94
95
|
metaUrl: import_meta.url
|
|
95
96
|
});
|
|
96
97
|
}
|
|
98
|
+
const devPluginDir = (0, import_dsh_install.resolveDevDshPackageSource)(import_meta.url, "dsh-plugin", "dist/index.js");
|
|
99
|
+
const pluginAvailable = await (0, import_dsh_install.ensureDshPackage)(
|
|
100
|
+
profileDir,
|
|
101
|
+
import_dsh_install.DSH_PLUGIN_PACKAGE,
|
|
102
|
+
devPluginDir ?? import_dsh_install.DSH_PLUGIN_PACKAGE,
|
|
103
|
+
this.opts.home
|
|
104
|
+
);
|
|
105
|
+
if (!pluginAvailable) {
|
|
106
|
+
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics & auto-diagnose disabled", {
|
|
107
|
+
metaUrl: import_meta.url
|
|
108
|
+
});
|
|
109
|
+
}
|
|
97
110
|
const overlay = (0, import_profile.buildDshOverlay)({
|
|
98
111
|
vitePort: options.vitePort,
|
|
99
112
|
cwd: options.cwd,
|
|
100
|
-
|
|
113
|
+
pluginAvailable,
|
|
101
114
|
clientAvailable
|
|
102
115
|
});
|
|
103
116
|
const patchPath = (0, import_profile.writeDshOverlay)(options.cwd, overlay);
|
|
@@ -141,12 +154,6 @@ or run without installing:
|
|
|
141
154
|
}
|
|
142
155
|
return sections;
|
|
143
156
|
}
|
|
144
|
-
/** 解析 aipanel dsh-plugin 的构建产物路径(存在才在 overlay 里注入插件行)。
|
|
145
|
-
* 注意用 fileURLToPath:URL.pathname 是 percent-encoded,中文路径下 existsSync 会误判不存在。 */
|
|
146
|
-
resolvePluginDist() {
|
|
147
|
-
const fromHere = new URL("../dsh-plugin/dist/index.js", import_meta.url);
|
|
148
|
-
return (0, import_node_url.fileURLToPath)(fromHere);
|
|
149
|
-
}
|
|
150
157
|
async stop() {
|
|
151
158
|
if (this.process) {
|
|
152
159
|
log.debug("Killing dsh web process", { pid: this.process.pid });
|
package/lib/provider.d.ts
CHANGED
|
@@ -36,9 +36,6 @@ export declare class DeepSeekWebProvider implements WebProvider {
|
|
|
36
36
|
start(options: ProviderStartOptions): Promise<ProviderStartResult>;
|
|
37
37
|
/** 把 providerOptions 配置映射为 dsh settings 命名空间 patch(仅含用户显式配置项) */
|
|
38
38
|
private buildSettingsToApply;
|
|
39
|
-
/** 解析 aipanel dsh-plugin 的构建产物路径(存在才在 overlay 里注入插件行)。
|
|
40
|
-
* 注意用 fileURLToPath:URL.pathname 是 percent-encoded,中文路径下 existsSync 会误判不存在。 */
|
|
41
|
-
private resolvePluginDist;
|
|
42
39
|
stop(): Promise<void>;
|
|
43
40
|
killOrphans(): Promise<number>;
|
|
44
41
|
listSessions(projectDir: string): Promise<ChatSession[]>;
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipanel/provider-deepseek",
|
|
3
|
-
"version": "1.2.0-beta.
|
|
3
|
+
"version": "1.2.0-beta.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.cjs",
|
|
6
6
|
"module": "es/index.js",
|
|
7
7
|
"types": "es/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
9
|
"es",
|
|
10
|
-
"lib"
|
|
11
|
-
"dsh-plugin/dist"
|
|
10
|
+
"lib"
|
|
12
11
|
],
|
|
13
12
|
"exports": {
|
|
14
13
|
".": {
|
|
@@ -22,10 +21,8 @@
|
|
|
22
21
|
"registry": "https://registry.npmjs.org/"
|
|
23
22
|
},
|
|
24
23
|
"dependencies": {
|
|
25
|
-
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
|
|
26
|
-
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
27
24
|
"execa": "^9.6.1",
|
|
28
|
-
"@aipanel/core": "1.2.0-beta.
|
|
25
|
+
"@aipanel/core": "1.2.0-beta.3"
|
|
29
26
|
},
|
|
30
27
|
"devDependencies": {
|
|
31
28
|
"esbuild": "^0.25.0"
|
package/dsh-plugin/dist/index.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// dsh-plugin/src/index.ts
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
defineTool
|
|
5
|
-
} from "@deepseek-ai/dsh-tools";
|
|
6
|
-
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
7
|
-
var name = "aipanel";
|
|
8
|
-
var inject = ["tools", "subprocess"];
|
|
9
|
-
var JS_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
10
|
-
".js",
|
|
11
|
-
".jsx",
|
|
12
|
-
".ts",
|
|
13
|
-
".tsx",
|
|
14
|
-
".mjs",
|
|
15
|
-
".cjs",
|
|
16
|
-
".mts",
|
|
17
|
-
".cts",
|
|
18
|
-
".vue"
|
|
19
|
-
]);
|
|
20
|
-
var MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "apply_patch"]);
|
|
21
|
-
var STDOUT_MAX_BYTES = 2e5;
|
|
22
|
-
var STDOUT_SPILL_MAX_BYTES = 2e6;
|
|
23
|
-
var STDERR_MAX_BYTES = 1e5;
|
|
24
|
-
var GRACE_MS = 3e4;
|
|
25
|
-
function apply(ctx, config = {}) {
|
|
26
|
-
const cwd = config.cwd ?? process.cwd();
|
|
27
|
-
const autoDiagnose = config.autoDiagnose ?? true;
|
|
28
|
-
const tools = ctx.tools;
|
|
29
|
-
const subprocess = ctx.subprocess;
|
|
30
|
-
async function collectOutput(argv, signal) {
|
|
31
|
-
try {
|
|
32
|
-
const exe = await subprocess.resolveExecutable("npx", void 0, signal);
|
|
33
|
-
const proc = subprocess.spawn({
|
|
34
|
-
argv: [exe, ...argv],
|
|
35
|
-
cwd,
|
|
36
|
-
stdio: {
|
|
37
|
-
stdin: "ignore",
|
|
38
|
-
stdout: { maxBytes: STDOUT_MAX_BYTES, spill: { maxBytes: STDOUT_SPILL_MAX_BYTES } },
|
|
39
|
-
stderr: { maxBytes: STDERR_MAX_BYTES }
|
|
40
|
-
},
|
|
41
|
-
graceMs: GRACE_MS,
|
|
42
|
-
signal
|
|
43
|
-
});
|
|
44
|
-
await proc.done;
|
|
45
|
-
return { text: proc.collected.stdout?.readFrom(0)?.text ?? "" };
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return { text: "", error: String(e) };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async function runDiagnostics(filePath, signal) {
|
|
51
|
-
const parts = [];
|
|
52
|
-
const tsc = await collectOutput(["tsc", "--noEmit", "--pretty", "false"], signal);
|
|
53
|
-
if (tsc.error) parts.push("## tsc\n\n(diagnostics skipped: " + tsc.error + ")");
|
|
54
|
-
else if (tsc.text.trim()) parts.push("## tsc\n\n" + tsc.text.trim());
|
|
55
|
-
const eslint = await collectOutput(["eslint", filePath, "--format", "compact"], signal);
|
|
56
|
-
if (eslint.text.trim()) parts.push("## eslint\n\n" + eslint.text.trim());
|
|
57
|
-
return parts.join("\n\n");
|
|
58
|
-
}
|
|
59
|
-
tools.register(
|
|
60
|
-
defineTool({
|
|
61
|
-
name: "run_diagnostics",
|
|
62
|
-
description: "Run ESLint and TypeScript type checks on filePath and report problems. Use after editing code to verify no lint/type errors before proceeding.",
|
|
63
|
-
parameters: {
|
|
64
|
-
filePath: {
|
|
65
|
-
type: "string",
|
|
66
|
-
required: true,
|
|
67
|
-
description: "Absolute or cwd-relative file path to diagnose"
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
output: {
|
|
71
|
-
schema: { type: "string" },
|
|
72
|
-
render: (_args, value) => [{ type: "text", text: value }]
|
|
73
|
-
},
|
|
74
|
-
async execute(args, exec) {
|
|
75
|
-
return runDiagnostics(path.resolve(cwd, args.filePath), exec.signal).catch(
|
|
76
|
-
(e) => "diagnostics failed: " + String(e)
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
);
|
|
81
|
-
ctx.on(
|
|
82
|
-
"tools/post-execute",
|
|
83
|
-
async (exec, result, next) => {
|
|
84
|
-
const decision = await next();
|
|
85
|
-
if (!autoDiagnose) return decision;
|
|
86
|
-
if (!MUTATING_TOOLS.has(exec.name)) return decision;
|
|
87
|
-
if (result.isError) return decision;
|
|
88
|
-
if (decision.kind !== "accept") return decision;
|
|
89
|
-
const filePath = exec.arguments?.filePath;
|
|
90
|
-
if (typeof filePath !== "string" || !filePath) return decision;
|
|
91
|
-
if (!JS_EXTENSIONS.has(path.extname(filePath))) return decision;
|
|
92
|
-
const diag = await runDiagnostics(path.resolve(cwd, filePath), exec.signal).catch(
|
|
93
|
-
() => "diagnostics unavailable"
|
|
94
|
-
);
|
|
95
|
-
const message = createUserMessage({
|
|
96
|
-
content: [
|
|
97
|
-
{ type: "text", text: `Auto diagnostics after ${exec.name} (${filePath}):
|
|
98
|
-
${diag}` }
|
|
99
|
-
],
|
|
100
|
-
source: { kind: "plugin", plugin: name }
|
|
101
|
-
});
|
|
102
|
-
return { kind: "accept", additionalContexts: [message] };
|
|
103
|
-
}
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
export {
|
|
107
|
-
apply,
|
|
108
|
-
inject,
|
|
109
|
-
name
|
|
110
|
-
};
|