@aipanel/provider-deepseek 1.2.8 → 1.2.10
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/api.d.ts +0 -5
- package/es/api.js +30 -83
- package/es/constants.d.ts +0 -9
- package/es/constants.js +1 -10
- package/es/index.d.ts +1 -2
- package/es/index.js +0 -2
- package/es/profile.d.ts +14 -4
- package/es/profile.js +19 -6
- package/es/provider.d.ts +6 -7
- package/es/provider.js +11 -42
- package/es/system.d.ts +3 -3
- package/es/system.js +9 -164
- package/lib/api.cjs +29 -82
- package/lib/api.d.ts +0 -5
- package/lib/constants.cjs +2 -12
- package/lib/constants.d.ts +0 -9
- package/lib/index.cjs +0 -3
- package/lib/index.d.ts +1 -2
- package/lib/profile.cjs +19 -6
- package/lib/profile.d.ts +14 -4
- package/lib/provider.cjs +11 -42
- package/lib/provider.d.ts +6 -7
- package/lib/system.cjs +8 -163
- package/lib/system.d.ts +3 -3
- package/package.json +2 -2
- package/es/bridge-script.d.ts +0 -13
- package/es/bridge-script.js +0 -195
- package/lib/bridge-script.cjs +0 -218
- package/lib/bridge-script.d.ts +0 -13
package/es/system.js
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const installed = code === 0;
|
|
11
|
-
timer.end(installed ? "\u2713 dsh is installed" : "\u274C dsh not found");
|
|
12
|
-
resolve(installed);
|
|
13
|
-
});
|
|
14
|
-
proc.on("error", (err) => {
|
|
15
|
-
log.debug("Failed to check dsh installation", { error: err.message });
|
|
16
|
-
timer.end("\u274C Check failed");
|
|
17
|
-
resolve(false);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
1
|
+
import { checkCliInstalled, getCliVersion, killOrphanCliProcesses } from "@aipanel/core/node";
|
|
2
|
+
function checkDeepSeekInstalled() {
|
|
3
|
+
return checkCliInstalled("dsh");
|
|
4
|
+
}
|
|
5
|
+
function getDeepSeekVersion() {
|
|
6
|
+
return getCliVersion("dsh");
|
|
7
|
+
}
|
|
8
|
+
function killOrphanDeepSeekProcesses() {
|
|
9
|
+
return killOrphanCliProcesses("dsh", { match: "dsh", winName: "node.exe", label: "dsh" });
|
|
20
10
|
}
|
|
21
11
|
const MIN_DSH_VERSION = "0.1.2-rc.1";
|
|
22
12
|
function parseDshVersion(version) {
|
|
@@ -57,151 +47,6 @@ function isDeepSeekVersionAtLeast(version, minimum = MIN_DSH_VERSION) {
|
|
|
57
47
|
}
|
|
58
48
|
return true;
|
|
59
49
|
}
|
|
60
|
-
function getDeepSeekVersion() {
|
|
61
|
-
return new Promise((resolve) => {
|
|
62
|
-
const proc = spawn("dsh", ["--version"], { stdio: "pipe", shell: true });
|
|
63
|
-
let output = "";
|
|
64
|
-
proc.stdout?.on("data", (data) => {
|
|
65
|
-
output += data.toString();
|
|
66
|
-
});
|
|
67
|
-
proc.on("close", (code) => {
|
|
68
|
-
if (code === 0 && output.trim()) {
|
|
69
|
-
resolve(output.trim());
|
|
70
|
-
} else {
|
|
71
|
-
resolve(null);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
proc.on("error", () => {
|
|
75
|
-
resolve(null);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
const KILL_ORPHAN_TIMEOUT = 5e3;
|
|
80
|
-
async function killOrphanDeepSeekProcesses() {
|
|
81
|
-
const timer = log.timer("killOrphanDeepSeekProcesses");
|
|
82
|
-
log.debug("Looking for orphan dsh processes (PPID=1)");
|
|
83
|
-
return new Promise((resolve) => {
|
|
84
|
-
let settled = false;
|
|
85
|
-
const done = (count) => {
|
|
86
|
-
if (settled) return;
|
|
87
|
-
settled = true;
|
|
88
|
-
resolve(count);
|
|
89
|
-
};
|
|
90
|
-
const timeout = setTimeout(() => {
|
|
91
|
-
log.warn("Kill orphan processes timed out, skipping");
|
|
92
|
-
timer.end("\u26A0 Timeout, skipped");
|
|
93
|
-
done(0);
|
|
94
|
-
}, KILL_ORPHAN_TIMEOUT);
|
|
95
|
-
const wrappedResolve = (count) => {
|
|
96
|
-
clearTimeout(timeout);
|
|
97
|
-
done(count);
|
|
98
|
-
};
|
|
99
|
-
if (process.platform === "win32") {
|
|
100
|
-
killOrphanProcessesOnWindows(wrappedResolve, timer);
|
|
101
|
-
} else {
|
|
102
|
-
killOrphanProcessesOnUnix(wrappedResolve, timer);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
function killOrphanProcessesOnWindows(resolve, timer) {
|
|
107
|
-
log.debug("Using Windows method to find orphan processes");
|
|
108
|
-
const proc = spawn(
|
|
109
|
-
"wmic",
|
|
110
|
-
["process", "where", 'name="node.exe"', "get", "processid,parentprocessid,commandline"],
|
|
111
|
-
{ stdio: "pipe" }
|
|
112
|
-
);
|
|
113
|
-
let output = "";
|
|
114
|
-
proc.stdout?.on("data", (data) => {
|
|
115
|
-
output += data.toString();
|
|
116
|
-
});
|
|
117
|
-
proc.on("close", () => {
|
|
118
|
-
const pidsToKill = [];
|
|
119
|
-
output.split("\n").forEach((rawLine) => {
|
|
120
|
-
const line = rawLine.trim();
|
|
121
|
-
if (!line.includes("dsh")) return;
|
|
122
|
-
const parts = line.trim().split(/\s+/);
|
|
123
|
-
if (parts.length >= 2) {
|
|
124
|
-
const ppid = parts[0];
|
|
125
|
-
const pid = parts[1];
|
|
126
|
-
if (ppid === "1" && pid && !isNaN(Number(pid))) {
|
|
127
|
-
pidsToKill.push(pid);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
if (pidsToKill.length > 0) {
|
|
132
|
-
log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
|
|
133
|
-
let killedCount = 0;
|
|
134
|
-
let completedCount = 0;
|
|
135
|
-
pidsToKill.forEach((pid) => {
|
|
136
|
-
const killProc = spawn("taskkill", ["/F", "/PID", pid], { stdio: "ignore" });
|
|
137
|
-
killProc.on("close", (code) => {
|
|
138
|
-
completedCount++;
|
|
139
|
-
if (code === 0) killedCount++;
|
|
140
|
-
if (completedCount === pidsToKill.length) {
|
|
141
|
-
timer.end(`\u2713 Killed ${killedCount} orphan processes`);
|
|
142
|
-
resolve(killedCount);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
} else {
|
|
147
|
-
log.debug("No orphan processes found");
|
|
148
|
-
timer.end("No orphan processes found");
|
|
149
|
-
resolve(0);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
proc.on("error", (err) => {
|
|
153
|
-
log.debug("Failed to find orphan processes", { error: err.message });
|
|
154
|
-
timer.end("\u274C Failed to find orphan processes");
|
|
155
|
-
resolve(0);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
function killOrphanProcessesOnUnix(resolve, timer) {
|
|
159
|
-
log.debug("Using Unix method to find orphan processes");
|
|
160
|
-
const proc = spawn("ps", ["-e", "-o", "pid,ppid,args"], { stdio: "pipe" });
|
|
161
|
-
let output = "";
|
|
162
|
-
proc.stdout?.on("data", (data) => {
|
|
163
|
-
output += data.toString();
|
|
164
|
-
});
|
|
165
|
-
proc.on("close", () => {
|
|
166
|
-
const lines = output.split("\n");
|
|
167
|
-
const pidsToKill = [];
|
|
168
|
-
lines.forEach((line) => {
|
|
169
|
-
if (!line.includes("dsh")) return;
|
|
170
|
-
const parts = line.trim().split(/\s+/);
|
|
171
|
-
if (parts.length >= 3) {
|
|
172
|
-
const pid = parts[0];
|
|
173
|
-
const ppid = parts[1];
|
|
174
|
-
if (ppid === "1") {
|
|
175
|
-
pidsToKill.push(pid);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
if (pidsToKill.length > 0) {
|
|
180
|
-
log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
|
|
181
|
-
const killProc = spawn("kill", ["-9", ...pidsToKill], { stdio: "ignore" });
|
|
182
|
-
killProc.on("close", (code) => {
|
|
183
|
-
const killedCount = code === 0 ? pidsToKill.length : 0;
|
|
184
|
-
timer.end(
|
|
185
|
-
killedCount > 0 ? `\u2713 Killed ${killedCount} orphan processes` : "\u274C Failed to kill processes"
|
|
186
|
-
);
|
|
187
|
-
resolve(killedCount);
|
|
188
|
-
});
|
|
189
|
-
killProc.on("error", () => {
|
|
190
|
-
timer.end("\u274C Failed to kill processes");
|
|
191
|
-
resolve(0);
|
|
192
|
-
});
|
|
193
|
-
} else {
|
|
194
|
-
log.debug("No orphan processes found");
|
|
195
|
-
timer.end("No orphan processes found");
|
|
196
|
-
resolve(0);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
proc.on("error", (err) => {
|
|
200
|
-
log.debug("Failed to find orphan processes", { error: err.message });
|
|
201
|
-
timer.end("\u274C Failed to find orphan processes");
|
|
202
|
-
resolve(0);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
50
|
export {
|
|
206
51
|
MIN_DSH_VERSION,
|
|
207
52
|
checkDeepSeekInstalled,
|
package/lib/api.cjs
CHANGED
|
@@ -180,11 +180,9 @@ class DeepSeekAPI {
|
|
|
180
180
|
* sessionId === activeSessionId(当前选中会话,对应 UI 的 New Session 占位行)时展示。
|
|
181
181
|
*/
|
|
182
182
|
async listSessions(projectDir, activeSessionId, retries = import_core.DEFAULT_RETRIES) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { method: "session/list", projectDir });
|
|
183
|
+
return (0, import_core.withRetries)(
|
|
184
|
+
async (attempt) => {
|
|
185
|
+
log.debug(`Attempt ${attempt + 1}/${retries}`, { method: "listSessions" });
|
|
188
186
|
const workspaces = await this.fetchWorkspaceBaseline();
|
|
189
187
|
const matchedWorkspace = workspaces.items.find((w) => w.path === projectDir);
|
|
190
188
|
const ownedByWorkspace = new Set(matchedWorkspace?.sessionIds ?? []);
|
|
@@ -200,105 +198,54 @@ class DeepSeekAPI {
|
|
|
200
198
|
return false;
|
|
201
199
|
});
|
|
202
200
|
const result = filtered.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
203
|
-
timer.end(`Found ${result.length} sessions`);
|
|
204
201
|
return result;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
attempts: retries,
|
|
205
|
+
onRetry: (n, e) => log.debug(`Attempt ${n} failed: ${e instanceof Error ? e.message : String(e)}`, {
|
|
206
|
+
method: "listSessions"
|
|
207
|
+
})
|
|
211
208
|
}
|
|
212
|
-
|
|
213
|
-
timer.end("\u274C All retries exhausted");
|
|
214
|
-
throw lastError;
|
|
209
|
+
);
|
|
215
210
|
}
|
|
216
211
|
/** 在当前目录下创建会话(dsh 仅返回 { sessionId, agentPreset? },非完整 SessionSummary)。
|
|
217
212
|
* 与旧逻辑一致:先确保 projectDir 对应的 workspace 存在(workspace/create 幂等 get-or-create),
|
|
218
213
|
* 再用 workspaceId 调 session/create,让新会话挂到该 workspace。 */
|
|
219
214
|
async createSession(projectDir, retries = import_core.DEFAULT_RETRIES) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
try {
|
|
224
|
-
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
225
|
-
method: "session/create",
|
|
226
|
-
projectDir
|
|
227
|
-
});
|
|
215
|
+
return (0, import_core.withRetries)(
|
|
216
|
+
async (attempt) => {
|
|
217
|
+
log.debug(`Attempt ${attempt + 1}/${retries}`, { method: "createSession" });
|
|
228
218
|
const { workspace } = await this.call("workspace/create", {
|
|
229
219
|
request: { path: projectDir }
|
|
230
220
|
});
|
|
231
221
|
const session = await this.call("session/create", {
|
|
232
222
|
request: { workspaceId: workspace.workspaceId }
|
|
233
223
|
});
|
|
234
|
-
timer.end(`Created session: ${session.sessionId}`);
|
|
235
224
|
return session;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
timer.end("\u274C All retries exhausted");
|
|
245
|
-
throw lastError;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* 通过 dsh settings/mutate 应用 providerOptions 指定的用户设置(逐命名空间幂等 patch)。
|
|
249
|
-
* dsh 启动初期 API 未就绪,整体带重试;单个命名空间不存在会导致该次调用失败重试。
|
|
250
|
-
*/
|
|
251
|
-
async applySettings(sections, retries = import_core.DEFAULT_RETRIES) {
|
|
252
|
-
const namespaces = Object.keys(sections);
|
|
253
|
-
if (namespaces.length === 0) return;
|
|
254
|
-
const timer = log.timer("applySettings", { namespaces });
|
|
255
|
-
let lastError = null;
|
|
256
|
-
for (let i = 0; i < retries; i++) {
|
|
257
|
-
try {
|
|
258
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { method: "settings/mutate", namespaces });
|
|
259
|
-
for (const [ns, patch] of Object.entries(sections)) {
|
|
260
|
-
const ops = Object.entries(patch).map(([key, value]) => ({
|
|
261
|
-
op: "set",
|
|
262
|
-
path: [key],
|
|
263
|
-
value
|
|
264
|
-
}));
|
|
265
|
-
await this.call("settings/mutate", { ns, ops });
|
|
266
|
-
}
|
|
267
|
-
timer.end(`Applied settings: ${namespaces.join(", ")}`);
|
|
268
|
-
return;
|
|
269
|
-
} catch (e) {
|
|
270
|
-
lastError = e instanceof Error ? e : new Error(String(e));
|
|
271
|
-
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { method: "applySettings" });
|
|
272
|
-
if (i < retries - 1) {
|
|
273
|
-
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
274
|
-
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
attempts: retries,
|
|
228
|
+
onRetry: (n, e) => log.debug(`Attempt ${n} failed: ${e instanceof Error ? e.message : String(e)}`, {
|
|
229
|
+
method: "createSession"
|
|
230
|
+
})
|
|
275
231
|
}
|
|
276
|
-
|
|
277
|
-
timer.end("\u274C All retries exhausted");
|
|
278
|
-
throw lastError;
|
|
232
|
+
);
|
|
279
233
|
}
|
|
280
234
|
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
281
235
|
async archiveSession(sessionId, retries = import_core.DEFAULT_RETRIES) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { method: "workspace/archiveSession" });
|
|
236
|
+
return (0, import_core.withRetries)(
|
|
237
|
+
async (attempt) => {
|
|
238
|
+
log.debug(`Attempt ${attempt + 1}/${retries}`, { method: "archiveSession" });
|
|
287
239
|
await this.call("workspace/archiveSession", { request: { sessionId } });
|
|
288
|
-
timer.end(`Archived session: ${sessionId}`);
|
|
289
240
|
return;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
attempts: retries,
|
|
244
|
+
onRetry: (n, e) => log.debug(`Attempt ${n} failed: ${e instanceof Error ? e.message : String(e)}`, {
|
|
293
245
|
method: "archiveSession"
|
|
294
|
-
})
|
|
295
|
-
if (i < retries - 1) {
|
|
296
|
-
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
297
|
-
}
|
|
246
|
+
})
|
|
298
247
|
}
|
|
299
|
-
|
|
300
|
-
timer.end("\u274C All retries exhausted");
|
|
301
|
-
throw lastError;
|
|
248
|
+
);
|
|
302
249
|
}
|
|
303
250
|
/**
|
|
304
251
|
* 取 workspace/follow 流的 baseline(等价旧 workspace.list 的快照:{ items, archivedSessionIds })。
|
package/lib/api.d.ts
CHANGED
|
@@ -56,11 +56,6 @@ export declare class DeepSeekAPI {
|
|
|
56
56
|
createSession(projectDir: string, retries?: number): Promise<{
|
|
57
57
|
sessionId: string;
|
|
58
58
|
}>;
|
|
59
|
-
/**
|
|
60
|
-
* 通过 dsh settings/mutate 应用 providerOptions 指定的用户设置(逐命名空间幂等 patch)。
|
|
61
|
-
* dsh 启动初期 API 未就绪,整体带重试;单个命名空间不存在会导致该次调用失败重试。
|
|
62
|
-
*/
|
|
63
|
-
applySettings(sections: Record<string, Record<string, unknown>>, retries?: number): Promise<void>;
|
|
64
59
|
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
65
60
|
archiveSession(sessionId: string, retries?: number): Promise<void>;
|
|
66
61
|
/**
|
package/lib/constants.cjs
CHANGED
|
@@ -21,22 +21,13 @@ __export(constants_exports, {
|
|
|
21
21
|
DSH_API_BASE: () => DSH_API_BASE,
|
|
22
22
|
DSH_DEFAULT_PORT: () => DSH_DEFAULT_PORT,
|
|
23
23
|
DSH_LOOPBACK_HOST: () => DSH_LOOPBACK_HOST,
|
|
24
|
-
DSH_REMOTE_MUX_PATH: () => DSH_REMOTE_MUX_PATH
|
|
25
|
-
DSH_STORAGE_KEYS: () => DSH_STORAGE_KEYS
|
|
24
|
+
DSH_REMOTE_MUX_PATH: () => DSH_REMOTE_MUX_PATH
|
|
26
25
|
});
|
|
27
26
|
module.exports = __toCommonJS(constants_exports);
|
|
28
27
|
const DSH_API_BASE = "/api";
|
|
29
28
|
const DSH_REMOTE_MUX_PATH = "/api/remote.mux";
|
|
30
29
|
const DSH_LOOPBACK_HOST = "127.0.0.1";
|
|
31
30
|
const DSH_DEFAULT_PORT = 3080;
|
|
32
|
-
const DSH_STORAGE_KEYS = {
|
|
33
|
-
/** 当前选中会话(SPA 启动时据此恢复选中,无 URL 深链) */
|
|
34
|
-
CURRENT_SESSION: "dsh.sessions.current",
|
|
35
|
-
/** 选中的页面元素(bridge 写入,dsh-client 的 @aipanel source 读取) */
|
|
36
|
-
SELECTION: "dsh.bridge.selection",
|
|
37
|
-
/** 诊断功能开关标记(bridge 按 provider 配置写入,dsh-client 据此决定是否注册诊断视图) */
|
|
38
|
-
DIAGNOSTICS_ENABLED: "dsh.bridge.diagnostics.enabled"
|
|
39
|
-
};
|
|
40
31
|
const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS = {
|
|
41
32
|
// 对齐 opencode 的 enableLsp(默认 true):诊断功能默认开启
|
|
42
33
|
enableDiagnostics: true,
|
|
@@ -49,6 +40,5 @@ const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS = {
|
|
|
49
40
|
DSH_API_BASE,
|
|
50
41
|
DSH_DEFAULT_PORT,
|
|
51
42
|
DSH_LOOPBACK_HOST,
|
|
52
|
-
DSH_REMOTE_MUX_PATH
|
|
53
|
-
DSH_STORAGE_KEYS
|
|
43
|
+
DSH_REMOTE_MUX_PATH
|
|
54
44
|
});
|
package/lib/constants.d.ts
CHANGED
|
@@ -17,14 +17,5 @@ export declare const DSH_REMOTE_MUX_PATH = "/api/remote.mux";
|
|
|
17
17
|
export declare const DSH_LOOPBACK_HOST = "127.0.0.1";
|
|
18
18
|
/** dsh web 默认端口(未显式指定时) */
|
|
19
19
|
export declare const DSH_DEFAULT_PORT = 3080;
|
|
20
|
-
/** ==================== dsh localStorage 键 ==================== */
|
|
21
|
-
export declare const DSH_STORAGE_KEYS: {
|
|
22
|
-
/** 当前选中会话(SPA 启动时据此恢复选中,无 URL 深链) */
|
|
23
|
-
readonly CURRENT_SESSION: "dsh.sessions.current";
|
|
24
|
-
/** 选中的页面元素(bridge 写入,dsh-client 的 @aipanel source 读取) */
|
|
25
|
-
readonly SELECTION: "dsh.bridge.selection";
|
|
26
|
-
/** 诊断功能开关标记(bridge 按 provider 配置写入,dsh-client 据此决定是否注册诊断视图) */
|
|
27
|
-
readonly DIAGNOSTICS_ENABLED: "dsh.bridge.diagnostics.enabled";
|
|
28
|
-
};
|
|
29
20
|
/** ==================== Provider 专属配置默认值 ==================== */
|
|
30
21
|
export declare const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS: DeepSeekProviderOptions;
|
package/lib/index.cjs
CHANGED
|
@@ -24,7 +24,6 @@ __export(lib_exports, {
|
|
|
24
24
|
buildDshOverlay: () => import_profile.buildDshOverlay,
|
|
25
25
|
checkDeepSeekInstalled: () => import_system.checkDeepSeekInstalled,
|
|
26
26
|
createProvider: () => createProvider,
|
|
27
|
-
generateBridgeScript: () => import_bridge_script.generateBridgeScript,
|
|
28
27
|
getDeepSeekVersion: () => import_system.getDeepSeekVersion,
|
|
29
28
|
killOrphanDeepSeekProcesses: () => import_system.killOrphanDeepSeekProcesses,
|
|
30
29
|
startDeepSeekWeb: () => import_deepseek_web.startDeepSeekWeb,
|
|
@@ -36,7 +35,6 @@ var import_constants = require("./constants.cjs");
|
|
|
36
35
|
var import_api = require("./api.cjs");
|
|
37
36
|
var import_deepseek_web = require("./deepseek-web.cjs");
|
|
38
37
|
var import_profile = require("./profile.cjs");
|
|
39
|
-
var import_bridge_script = require("./bridge-script.cjs");
|
|
40
38
|
var import_system = require("./system.cjs");
|
|
41
39
|
var import_constants2 = require("./constants.cjs");
|
|
42
40
|
function createProvider(ctx) {
|
|
@@ -55,7 +53,6 @@ function createProvider(ctx) {
|
|
|
55
53
|
buildDshOverlay,
|
|
56
54
|
checkDeepSeekInstalled,
|
|
57
55
|
createProvider,
|
|
58
|
-
generateBridgeScript,
|
|
59
56
|
getDeepSeekVersion,
|
|
60
57
|
killOrphanDeepSeekProcesses,
|
|
61
58
|
startDeepSeekWeb,
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DeepSeek Harness Web Provider
|
|
3
|
-
* 实现 WebProvider 契约:进程管理、RPC 会话 API
|
|
3
|
+
* 实现 WebProvider 契约:进程管理、RPC 会话 API、dsh 侧插件编排、CLI 环境检查。
|
|
4
4
|
* 所有 dsh 专属类型与常量自包含于此包。
|
|
5
5
|
*/
|
|
6
6
|
import type { ProviderInitContext, WebProvider } from "@aipanel/core";
|
|
@@ -10,7 +10,6 @@ export { DeepSeekAPI } from "./api";
|
|
|
10
10
|
export type { DeepSeekWebProviderConfig, DeepSeekWebProviderDeps } from "./provider";
|
|
11
11
|
export { startDeepSeekWeb, type DeepSeekWebOptions } from "./deepseek-web";
|
|
12
12
|
export { buildDshOverlay, writeDshOverlay } from "./profile";
|
|
13
|
-
export { generateBridgeScript, type BridgeScriptOptions } from "./bridge-script";
|
|
14
13
|
export { checkDeepSeekInstalled, getDeepSeekVersion, killOrphanDeepSeekProcesses } from "./system";
|
|
15
14
|
export { DEFAULT_DEEPSEEK_PROVIDER_OPTIONS, DSH_LOOPBACK_HOST, DSH_DEFAULT_PORT } from "./constants";
|
|
16
15
|
export type { DeepSeekProviderOptions, DeepSeekPermissionPreset, DeepSeekBusyEnter, SessionSummary, WorkspaceView, SessionStreamEvent, ServerRequest, ServerResponse, ClientRequest, } from "./types";
|
package/lib/profile.cjs
CHANGED
|
@@ -34,6 +34,8 @@ module.exports = __toCommonJS(profile_exports);
|
|
|
34
34
|
var import_fs = __toESM(require("fs"));
|
|
35
35
|
var import_path = __toESM(require("path"));
|
|
36
36
|
var import_node = require("@aipanel/core/node");
|
|
37
|
+
var import_constants = require("./constants.cjs");
|
|
38
|
+
var import_dsh_install = require("./dsh-install.cjs");
|
|
37
39
|
const log = (0, import_node.createLogger)("DeepSeekProfile");
|
|
38
40
|
function buildDshOverlay(options) {
|
|
39
41
|
const {
|
|
@@ -43,9 +45,13 @@ function buildDshOverlay(options) {
|
|
|
43
45
|
clientAvailable = true,
|
|
44
46
|
autoDiagnose,
|
|
45
47
|
enableDiagnostics = true,
|
|
46
|
-
eventsToken
|
|
48
|
+
eventsToken,
|
|
49
|
+
agentPreset,
|
|
50
|
+
permissionPreset,
|
|
51
|
+
busyEnter,
|
|
52
|
+
theme = "auto"
|
|
47
53
|
} = options;
|
|
48
|
-
const mcpUrl = `http
|
|
54
|
+
const mcpUrl = `http://${import_constants.DSH_LOOPBACK_HOST}:${vitePort}${import_node.MCP_API_PATH}`;
|
|
49
55
|
const rows = [];
|
|
50
56
|
rows.push(
|
|
51
57
|
[
|
|
@@ -61,7 +67,7 @@ function buildDshOverlay(options) {
|
|
|
61
67
|
rows.push(
|
|
62
68
|
[
|
|
63
69
|
" - id: aipanel",
|
|
64
|
-
|
|
70
|
+
` name: ${JSON.stringify(import_dsh_install.DSH_PLUGIN_PACKAGE)}`,
|
|
65
71
|
...pluginAvailable ? [] : [" disabled: true"],
|
|
66
72
|
" inject: [tools]",
|
|
67
73
|
" config:",
|
|
@@ -73,14 +79,21 @@ function buildDshOverlay(options) {
|
|
|
73
79
|
...eventsToken ? [
|
|
74
80
|
` eventsToken: ${JSON.stringify(eventsToken)}`,
|
|
75
81
|
` eventsPath: ${JSON.stringify(import_node.HOST_EVENTS_API_PATH)}`
|
|
76
|
-
] : []
|
|
82
|
+
] : [],
|
|
83
|
+
// providerOptions → 启动期设置(dsh-plugin/applyProviderSettings 经 ctx.settings 写入)
|
|
84
|
+
...agentPreset !== void 0 ? [` agentPreset: ${JSON.stringify(agentPreset)}`] : [],
|
|
85
|
+
...permissionPreset !== void 0 ? [` permissionPreset: ${JSON.stringify(permissionPreset)}`] : [],
|
|
86
|
+
...busyEnter !== void 0 ? [` busyEnter: ${JSON.stringify(busyEnter)}`] : []
|
|
77
87
|
].join("\n")
|
|
78
88
|
);
|
|
79
89
|
rows.push(
|
|
80
90
|
[
|
|
81
91
|
" - id: aipanel-client",
|
|
82
|
-
|
|
83
|
-
...clientAvailable ? [] : [" disabled: true"]
|
|
92
|
+
` name: ${JSON.stringify(import_dsh_install.DSH_CLIENT_PACKAGE)}`,
|
|
93
|
+
...clientAvailable ? [] : [" disabled: true"],
|
|
94
|
+
" config:",
|
|
95
|
+
` enableDiagnostics: ${enableDiagnostics ? "true" : "false"}`,
|
|
96
|
+
...theme !== "auto" ? [` theme: ${JSON.stringify(theme)}`] : []
|
|
84
97
|
].join("\n")
|
|
85
98
|
);
|
|
86
99
|
return ["- insert:", rows.join("\n"), ""].join("\n");
|
package/lib/profile.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import type { AIPanelWidgetTheme } from "@aipanel/core";
|
|
2
|
+
import type { DeepSeekBusyEnter, DeepSeekPermissionPreset } from "./types";
|
|
1
3
|
/** 组装 overlay YAML */
|
|
2
4
|
export declare function buildDshOverlay(options: {
|
|
3
5
|
vitePort: number;
|
|
4
6
|
cwd: string;
|
|
5
|
-
/** host 插件(@aipanel/dsh-plugin
|
|
7
|
+
/** host 插件(@aipanel/dsh-plugin)是否已同步到 dsh profile;false 时停用该行,避免 fail-loud */
|
|
6
8
|
pluginAvailable?: boolean;
|
|
7
|
-
/** client 插件(@aipanel/dsh-client)是否可被 dsh
|
|
9
|
+
/** client 插件(@aipanel/dsh-client)是否可被 dsh 解析;false 时停用该行,避免 fail-loud */
|
|
8
10
|
clientAvailable?: boolean;
|
|
9
11
|
/**
|
|
10
12
|
* 编辑后自动诊断开关(provider option autoDiagnose)。
|
|
@@ -14,14 +16,22 @@ export declare function buildDshOverlay(options: {
|
|
|
14
16
|
/**
|
|
15
17
|
* 宿主事件推送令牌(core 每轮启动随机):随 plugin config 注入 dsh-plugin,
|
|
16
18
|
* 使其把归一化 ProviderEvent POST 到 core 的 HOST_EVENTS_API_PATH。
|
|
17
|
-
* 缺省(undefined)时不写该配置行,事件中继不启用(兼容未升级的 dsh-plugin)。
|
|
18
19
|
*/
|
|
19
20
|
eventsToken?: string;
|
|
20
21
|
/**
|
|
21
22
|
* 诊断功能总开关(provider option enableDiagnostics)。
|
|
22
|
-
* true(默认,对齐 opencode enableLsp)时 host 插件注册 run_diagnostics
|
|
23
|
+
* true(默认,对齐 opencode enableLsp)时 host 插件注册 run_diagnostics 工具与自动诊断逻辑,
|
|
24
|
+
* client 插件注册诊断卡片视图。
|
|
23
25
|
*/
|
|
24
26
|
enableDiagnostics?: boolean;
|
|
27
|
+
/** provider option agentPreset:dsh settings agent-presets.default(随 host 插件 config 下发) */
|
|
28
|
+
agentPreset?: string;
|
|
29
|
+
/** provider option permissionPreset:dsh settings permission.defaultPreset(单一来源 ./types) */
|
|
30
|
+
permissionPreset?: DeepSeekPermissionPreset;
|
|
31
|
+
/** provider option busyEnter:dsh settings ui-conversation.busyEnter(单一来源 ./types) */
|
|
32
|
+
busyEnter?: DeepSeekBusyEnter;
|
|
33
|
+
/** AIPanel 侧主题偏好(applyConfig.theme,AIPanelWidgetTheme);auto 不干预(沿用 dsh 持久化偏好),light/dark 随 client 插件 config 下发 */
|
|
34
|
+
theme?: AIPanelWidgetTheme;
|
|
25
35
|
}): string;
|
|
26
36
|
/** 将 overlay 写入项目缓存目录(AIPANEL_CACHE_DIR 下按 provider 分二级目录),不污染用户项目根目录。 */
|
|
27
37
|
export declare function writeDshOverlay(workspaceCwd: string, overlay: string): string;
|
package/lib/provider.cjs
CHANGED
|
@@ -28,7 +28,6 @@ var import_node = require("@aipanel/core/node");
|
|
|
28
28
|
var import_constants = require("./constants.cjs");
|
|
29
29
|
var import_constants2 = require("./constants.cjs");
|
|
30
30
|
var import_api = require("./api.cjs");
|
|
31
|
-
var import_bridge_script = require("./bridge-script.cjs");
|
|
32
31
|
var import_deepseek_web = require("./deepseek-web.cjs");
|
|
33
32
|
var import_profile = require("./profile.cjs");
|
|
34
33
|
var import_system = require("./system.cjs");
|
|
@@ -43,22 +42,17 @@ class DeepSeekWebProvider {
|
|
|
43
42
|
__publicField(this, "api");
|
|
44
43
|
__publicField(this, "deps");
|
|
45
44
|
__publicField(this, "process", null);
|
|
46
|
-
|
|
45
|
+
/** AIPanel 侧下发的主题偏好(AIPanelWidgetTheme,default auto):随 client 插件 config 注入,作为启动初值 */
|
|
46
|
+
__publicField(this, "uiTheme", "auto");
|
|
47
47
|
__publicField(this, "opts");
|
|
48
48
|
this.deps = deps;
|
|
49
49
|
this.opts = resolveDeepSeekOptions(options);
|
|
50
50
|
this.api = new import_api.DeepSeekAPI(import_constants2.DSH_LOOPBACK_HOST, deps.getWebPort);
|
|
51
51
|
}
|
|
52
|
-
/**
|
|
53
|
-
get bridgeScript() {
|
|
54
|
-
return (0, import_bridge_script.generateBridgeScript)(this.bridgeOptions);
|
|
55
|
-
}
|
|
56
|
-
/** 初始化桥接配置(主题、诊断开关等) */
|
|
52
|
+
/** 记录 AIPanel 侧主题偏好(applyConfig 在 start 前调用;start 时随 client 插件 config 下发) */
|
|
57
53
|
applyConfig(config) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
diagnosticsEnabled: this.opts.enableDiagnostics ?? false
|
|
61
|
-
};
|
|
54
|
+
const t = config.theme;
|
|
55
|
+
this.uiTheme = t === "light" || t === "dark" || t === "auto" ? t : "auto";
|
|
62
56
|
}
|
|
63
57
|
async checkEnvironment() {
|
|
64
58
|
if (!await (0, import_system.checkDeepSeekInstalled)()) {
|
|
@@ -119,7 +113,7 @@ Please upgrade:
|
|
|
119
113
|
this.opts.home
|
|
120
114
|
);
|
|
121
115
|
if (!pluginAvailable) {
|
|
122
|
-
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics &
|
|
116
|
+
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics & settings application disabled", {
|
|
123
117
|
metaUrl: import_meta.url
|
|
124
118
|
});
|
|
125
119
|
}
|
|
@@ -131,7 +125,11 @@ Please upgrade:
|
|
|
131
125
|
autoDiagnose: this.opts.autoDiagnose,
|
|
132
126
|
enableDiagnostics: this.opts.enableDiagnostics,
|
|
133
127
|
// 宿主事件推送令牌(core 每轮启动随机):随 plugin config 注入 dsh-plugin 用于回推鉴权
|
|
134
|
-
eventsToken: options.eventsToken
|
|
128
|
+
eventsToken: options.eventsToken,
|
|
129
|
+
agentPreset: this.opts.agentPreset,
|
|
130
|
+
permissionPreset: this.opts.permissionPreset,
|
|
131
|
+
busyEnter: this.opts.busyEnter,
|
|
132
|
+
theme: this.uiTheme
|
|
135
133
|
});
|
|
136
134
|
const patchPath = (0, import_profile.writeDshOverlay)(options.cwd, overlay);
|
|
137
135
|
const launchToken = new import_deepseek_web.LaunchToken();
|
|
@@ -173,37 +171,8 @@ Please upgrade:
|
|
|
173
171
|
}
|
|
174
172
|
);
|
|
175
173
|
}
|
|
176
|
-
const settings = this.buildSettingsToApply();
|
|
177
|
-
if (Object.keys(settings).length > 0) {
|
|
178
|
-
void this.api.applySettings(settings).catch((e) => {
|
|
179
|
-
log.warn("failed to apply provider settings to dsh", {
|
|
180
|
-
settings,
|
|
181
|
-
error: e instanceof Error ? e.message : String(e)
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
174
|
return { url: this.api.shellUrl, processHandle: proc, webAuthCookie };
|
|
186
175
|
}
|
|
187
|
-
/** 把 providerOptions 配置映射为 dsh settings 命名空间 patch(仅含用户显式配置项) */
|
|
188
|
-
buildSettingsToApply() {
|
|
189
|
-
const sections = {};
|
|
190
|
-
if (this.opts.agentPreset !== void 0) {
|
|
191
|
-
sections["agent-presets"] = { ...sections["agent-presets"], default: this.opts.agentPreset };
|
|
192
|
-
}
|
|
193
|
-
if (this.opts.permissionPreset !== void 0) {
|
|
194
|
-
sections.permission = {
|
|
195
|
-
...sections.permission,
|
|
196
|
-
defaultPreset: this.opts.permissionPreset
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
if (this.opts.busyEnter !== void 0) {
|
|
200
|
-
sections["ui-conversation"] = {
|
|
201
|
-
...sections["ui-conversation"],
|
|
202
|
-
busyEnter: this.opts.busyEnter
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
return sections;
|
|
206
|
-
}
|
|
207
176
|
async stop() {
|
|
208
177
|
if (this.process) {
|
|
209
178
|
log.debug("Killing dsh web process", { pid: this.process.pid });
|
package/lib/provider.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ export interface DeepSeekWebProviderDeps {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* DeepSeek Harness Web Provider
|
|
16
|
-
* 组合 CLI 进程管理、RPC 会话 API
|
|
16
|
+
* 组合 CLI 进程管理、RPC 会话 API、dsh 侧插件编排(host 插件 + 浏览器 client 插件),
|
|
17
|
+
* 向核心层暴露 WebProvider 契约。dsh 页内行为(会话聚焦/主题/布局/选中元素)全部
|
|
18
|
+
* 由浏览器插件 @aipanel/dsh-client 承担,不再注入 bridge 脚本。
|
|
17
19
|
*/
|
|
18
20
|
export declare class DeepSeekWebProvider implements WebProvider {
|
|
19
21
|
readonly id = "deepseek";
|
|
@@ -25,17 +27,14 @@ export declare class DeepSeekWebProvider implements WebProvider {
|
|
|
25
27
|
private readonly api;
|
|
26
28
|
private deps;
|
|
27
29
|
private process;
|
|
28
|
-
|
|
30
|
+
/** AIPanel 侧下发的主题偏好(AIPanelWidgetTheme,default auto):随 client 插件 config 注入,作为启动初值 */
|
|
31
|
+
private uiTheme;
|
|
29
32
|
private readonly opts;
|
|
30
33
|
constructor(config: DeepSeekWebProviderConfig, deps: DeepSeekWebProviderDeps, options?: Record<string, unknown>);
|
|
31
|
-
/**
|
|
32
|
-
get bridgeScript(): string | undefined;
|
|
33
|
-
/** 初始化桥接配置(主题、诊断开关等) */
|
|
34
|
+
/** 记录 AIPanel 侧主题偏好(applyConfig 在 start 前调用;start 时随 client 插件 config 下发) */
|
|
34
35
|
applyConfig(config: ProviderConfig): void;
|
|
35
36
|
checkEnvironment(): Promise<ProviderEnvironmentInfo>;
|
|
36
37
|
start(options: ProviderStartOptions): Promise<ProviderStartResult>;
|
|
37
|
-
/** 把 providerOptions 配置映射为 dsh settings 命名空间 patch(仅含用户显式配置项) */
|
|
38
|
-
private buildSettingsToApply;
|
|
39
38
|
stop(): Promise<void>;
|
|
40
39
|
killOrphans(): Promise<number>;
|
|
41
40
|
listSessions(projectDir: string, activeSessionId?: string): Promise<ChatSession[]>;
|