@aipanel/provider-deepseek 1.2.0-beta.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/es/api.d.ts +36 -0
- package/es/api.js +196 -0
- package/es/bridge-script.d.ts +11 -0
- package/es/bridge-script.js +142 -0
- package/es/constants.d.ts +25 -0
- package/es/constants.js +23 -0
- package/es/deepseek-web.d.ts +21 -0
- package/es/deepseek-web.js +62 -0
- package/es/dsh-install.d.ts +16 -0
- package/es/dsh-install.js +58 -0
- package/es/index.d.ts +16 -0
- package/es/index.js +29 -0
- package/es/profile.d.ts +11 -0
- package/es/profile.js +57 -0
- package/es/provider.d.ts +49 -0
- package/es/provider.js +290 -0
- package/es/system.d.ts +3 -0
- package/es/system.js +170 -0
- package/es/types.d.ts +127 -0
- package/es/types.js +19 -0
- package/lib/api.cjs +228 -0
- package/lib/api.d.ts +36 -0
- package/lib/bridge-script.cjs +165 -0
- package/lib/bridge-script.d.ts +11 -0
- package/lib/constants.cjs +52 -0
- package/lib/constants.d.ts +25 -0
- package/lib/deepseek-web.cjs +85 -0
- package/lib/deepseek-web.d.ts +21 -0
- package/lib/dsh-install.cjs +95 -0
- package/lib/dsh-install.d.ts +16 -0
- package/lib/index.cjs +63 -0
- package/lib/index.d.ts +16 -0
- package/lib/profile.cjs +91 -0
- package/lib/profile.d.ts +11 -0
- package/lib/provider.cjs +308 -0
- package/lib/provider.d.ts +49 -0
- package/lib/system.cjs +195 -0
- package/lib/system.d.ts +3 -0
- package/lib/types.cjs +42 -0
- package/lib/types.d.ts +127 -0
- package/package.json +34 -0
package/es/types.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const SESSION_EVENT_TYPES = {
|
|
2
|
+
/** 回合开始 → 视为 streaming */
|
|
3
|
+
TURN_START: "turn/start",
|
|
4
|
+
/** 回合结束(稳定停等) */
|
|
5
|
+
TURN_END: "turn/end",
|
|
6
|
+
/** 步骤开始 */
|
|
7
|
+
STEP_START: "step/start",
|
|
8
|
+
/** 步骤结束 */
|
|
9
|
+
STEP_END: "step/end",
|
|
10
|
+
/** 助手输出完成 */
|
|
11
|
+
ASSISTANT_MESSAGE: "assistant/message",
|
|
12
|
+
/** 助手输出增量分片 */
|
|
13
|
+
ASSISTANT_CHUNK: "assistant/chunk",
|
|
14
|
+
/** 思考增量分片 */
|
|
15
|
+
THINKING_DELTA: "thinking/delta"
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
SESSION_EVENT_TYPES
|
|
19
|
+
};
|
package/lib/api.cjs
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
30
|
+
var api_exports = {};
|
|
31
|
+
__export(api_exports, {
|
|
32
|
+
DeepSeekAPI: () => DeepSeekAPI
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(api_exports);
|
|
35
|
+
var import_http = __toESM(require("http"));
|
|
36
|
+
var import_node_crypto = require("node:crypto");
|
|
37
|
+
var import_core = require("@aipanel/core");
|
|
38
|
+
var import_node = require("@aipanel/core/node");
|
|
39
|
+
var import_constants = require("./constants.cjs");
|
|
40
|
+
const log = (0, import_node.createLogger)("DeepSeekAPI");
|
|
41
|
+
class DeepSeekAPI {
|
|
42
|
+
constructor(hostname, getWebPort) {
|
|
43
|
+
__publicField(this, "hostname", hostname);
|
|
44
|
+
__publicField(this, "getWebPort", getWebPort);
|
|
45
|
+
}
|
|
46
|
+
/** 应用壳 URL(无 deepLink 能力,所有会话共用) */
|
|
47
|
+
get shellUrl() {
|
|
48
|
+
return `http://${this.hostname}:${this.getWebPort()}`;
|
|
49
|
+
}
|
|
50
|
+
/** 发起一次 unary RPC,返回 result.value(ok=false 时抛错) */
|
|
51
|
+
async call(method, payload = {}) {
|
|
52
|
+
const message = {
|
|
53
|
+
type: "client-request",
|
|
54
|
+
rpcId: (0, import_node_crypto.randomUUID)(),
|
|
55
|
+
method,
|
|
56
|
+
payload
|
|
57
|
+
};
|
|
58
|
+
const response = await this.createHttpRequest(
|
|
59
|
+
{
|
|
60
|
+
hostname: this.hostname,
|
|
61
|
+
port: this.getWebPort(),
|
|
62
|
+
path: `${import_constants.DSH_API_BASE}/${method}`,
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers: { "Content-Type": "application/json" }
|
|
65
|
+
},
|
|
66
|
+
JSON.stringify(message)
|
|
67
|
+
);
|
|
68
|
+
if (response?.result?.ok !== true) {
|
|
69
|
+
const err = response?.result && "error" in response.result ? response.result.error : void 0;
|
|
70
|
+
throw new Error(
|
|
71
|
+
`dsh RPC ${method} failed: ${err?.message ?? JSON.stringify(response?.result ?? response)}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return response.result.value;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 列出当前项目目录下的会话。
|
|
78
|
+
* dsh 的 session.list 不提供按目录过滤,故结合 workspace.list(path→sessionIds)
|
|
79
|
+
* 与各会话的 cwd 字段,在本端合并去重出属于 projectDir 的会话集。
|
|
80
|
+
*/
|
|
81
|
+
async listSessions(projectDir, retries = import_core.DEFAULT_RETRIES) {
|
|
82
|
+
const timer = log.timer("listSessions", { projectDir, retries });
|
|
83
|
+
let lastError = null;
|
|
84
|
+
for (let i = 0; i < retries; i++) {
|
|
85
|
+
try {
|
|
86
|
+
log.debug(`Attempt ${i + 1}/${retries}`, { method: "session.list", projectDir });
|
|
87
|
+
const workspaces = await this.call("workspace.list");
|
|
88
|
+
const matchedWorkspace = workspaces.items.find((w) => w.path === projectDir);
|
|
89
|
+
const ownedByWorkspace = new Set(matchedWorkspace?.sessionIds ?? []);
|
|
90
|
+
const archived = new Set(workspaces.archivedSessionIds);
|
|
91
|
+
const sessions = await this.call("session.list");
|
|
92
|
+
const all = sessions.items;
|
|
93
|
+
const filtered = all.filter((s) => {
|
|
94
|
+
if (s.blank) return false;
|
|
95
|
+
if (archived.has(s.sessionId)) return false;
|
|
96
|
+
if (ownedByWorkspace.has(s.sessionId)) return true;
|
|
97
|
+
if (s.cwd && s.cwd === projectDir) return true;
|
|
98
|
+
return false;
|
|
99
|
+
});
|
|
100
|
+
const result = filtered.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
101
|
+
timer.end(`Found ${result.length} sessions`);
|
|
102
|
+
return result;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
105
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { method: "listSessions" });
|
|
106
|
+
if (i < retries - 1) {
|
|
107
|
+
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
timer.end("\u274C All retries exhausted");
|
|
112
|
+
throw lastError;
|
|
113
|
+
}
|
|
114
|
+
/** 在当前目录下创建会话(dsh 仅返回 { sessionId, agentPreset? },非完整 SessionSummary)。
|
|
115
|
+
* 关键:必须先确保 projectDir 对应的 workspace 存在(workspace.create 幂等 get-or-create),
|
|
116
|
+
* 再用 workspaceId 调 session.create。若只传 cwd,dsh 侧不会把会话挂到任何 workspace,
|
|
117
|
+
* 新会话会落到侧边栏"未分组"。 */
|
|
118
|
+
async createSession(projectDir, retries = import_core.DEFAULT_RETRIES) {
|
|
119
|
+
const timer = log.timer("createSession", { projectDir, retries });
|
|
120
|
+
let lastError = null;
|
|
121
|
+
for (let i = 0; i < retries; i++) {
|
|
122
|
+
try {
|
|
123
|
+
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
124
|
+
method: "session.create",
|
|
125
|
+
projectDir
|
|
126
|
+
});
|
|
127
|
+
const { workspace } = await this.call("workspace.create", {
|
|
128
|
+
path: projectDir
|
|
129
|
+
});
|
|
130
|
+
const session = await this.call("session.create", {
|
|
131
|
+
workspaceId: workspace.workspaceId
|
|
132
|
+
});
|
|
133
|
+
timer.end(`Created session: ${session.sessionId}`);
|
|
134
|
+
return session;
|
|
135
|
+
} catch (e) {
|
|
136
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
137
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { method: "createSession" });
|
|
138
|
+
if (i < retries - 1) {
|
|
139
|
+
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
timer.end("\u274C All retries exhausted");
|
|
144
|
+
throw lastError;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 通过 dsh settings.update 应用 providerOptions 指定的用户设置(逐命名空间幂等 patch)。
|
|
148
|
+
* dsh 启动初期 API 未就绪,整体带重试;单个命名空间不存在会导致该次调用失败重试。
|
|
149
|
+
*/
|
|
150
|
+
async applySettings(sections, retries = import_core.DEFAULT_RETRIES) {
|
|
151
|
+
const namespaces = Object.keys(sections);
|
|
152
|
+
if (namespaces.length === 0) return;
|
|
153
|
+
const timer = log.timer("applySettings", { namespaces });
|
|
154
|
+
let lastError = null;
|
|
155
|
+
for (let i = 0; i < retries; i++) {
|
|
156
|
+
try {
|
|
157
|
+
log.debug(`Attempt ${i + 1}/${retries}`, { method: "settings.update", namespaces });
|
|
158
|
+
for (const [ns, patch] of Object.entries(sections)) {
|
|
159
|
+
await this.call("settings.update", { ns, patch });
|
|
160
|
+
}
|
|
161
|
+
timer.end(`Applied settings: ${namespaces.join(", ")}`);
|
|
162
|
+
return;
|
|
163
|
+
} catch (e) {
|
|
164
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
165
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { method: "applySettings" });
|
|
166
|
+
if (i < retries - 1) {
|
|
167
|
+
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
timer.end("\u274C All retries exhausted");
|
|
172
|
+
throw lastError;
|
|
173
|
+
}
|
|
174
|
+
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
175
|
+
async archiveSession(sessionId, retries = import_core.DEFAULT_RETRIES) {
|
|
176
|
+
const timer = log.timer("archiveSession", { sessionId, retries });
|
|
177
|
+
let lastError = null;
|
|
178
|
+
for (let i = 0; i < retries; i++) {
|
|
179
|
+
try {
|
|
180
|
+
log.debug(`Attempt ${i + 1}/${retries}`, { method: "workspace.archiveSession" });
|
|
181
|
+
await this.call("workspace.archiveSession", { sessionId });
|
|
182
|
+
timer.end(`Archived session: ${sessionId}`);
|
|
183
|
+
return;
|
|
184
|
+
} catch (e) {
|
|
185
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
186
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
187
|
+
method: "archiveSession"
|
|
188
|
+
});
|
|
189
|
+
if (i < retries - 1) {
|
|
190
|
+
await (0, import_core.sleep)(import_core.RETRY_DELAY);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
timer.end("\u274C All retries exhausted");
|
|
195
|
+
throw lastError;
|
|
196
|
+
}
|
|
197
|
+
createHttpRequest(options, body) {
|
|
198
|
+
const timer = new import_node.PerformanceTimer("HTTP Request", {
|
|
199
|
+
operation: `${options.method || "GET"} ${options.path}`
|
|
200
|
+
});
|
|
201
|
+
return new Promise((resolve, reject) => {
|
|
202
|
+
const req = import_http.default.request(options, (res) => {
|
|
203
|
+
let data = "";
|
|
204
|
+
res.on("data", (chunk) => data += chunk);
|
|
205
|
+
res.on("end", () => {
|
|
206
|
+
try {
|
|
207
|
+
const result = JSON.parse(data);
|
|
208
|
+
timer.end(`\u2713 Status: ${res.statusCode}`);
|
|
209
|
+
resolve(result);
|
|
210
|
+
} catch {
|
|
211
|
+
timer.end("\u274C JSON parse error");
|
|
212
|
+
reject(new Error(`JSON parse error: ${data.substring(0, 100)}`));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
req.on("error", (e) => {
|
|
217
|
+
timer.end("\u274C Request failed");
|
|
218
|
+
reject(e);
|
|
219
|
+
});
|
|
220
|
+
if (body) req.write(body);
|
|
221
|
+
req.end();
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
226
|
+
0 && (module.exports = {
|
|
227
|
+
DeepSeekAPI
|
|
228
|
+
});
|
package/lib/api.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SessionSummary } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* dsh 会话 API 客户端。
|
|
4
|
+
* dsh 使用自定义四象限 RPC envelope({type:'client-request',rpcId,method,payload} →
|
|
5
|
+
* {type:'server-response',rpcId,result:{ok,value|error}}),本节封装该协议。
|
|
6
|
+
*/
|
|
7
|
+
export declare class DeepSeekAPI {
|
|
8
|
+
private hostname;
|
|
9
|
+
private getWebPort;
|
|
10
|
+
constructor(hostname: string, getWebPort: () => number);
|
|
11
|
+
/** 应用壳 URL(无 deepLink 能力,所有会话共用) */
|
|
12
|
+
get shellUrl(): string;
|
|
13
|
+
/** 发起一次 unary RPC,返回 result.value(ok=false 时抛错) */
|
|
14
|
+
private call;
|
|
15
|
+
/**
|
|
16
|
+
* 列出当前项目目录下的会话。
|
|
17
|
+
* dsh 的 session.list 不提供按目录过滤,故结合 workspace.list(path→sessionIds)
|
|
18
|
+
* 与各会话的 cwd 字段,在本端合并去重出属于 projectDir 的会话集。
|
|
19
|
+
*/
|
|
20
|
+
listSessions(projectDir: string, retries?: number): Promise<SessionSummary[]>;
|
|
21
|
+
/** 在当前目录下创建会话(dsh 仅返回 { sessionId, agentPreset? },非完整 SessionSummary)。
|
|
22
|
+
* 关键:必须先确保 projectDir 对应的 workspace 存在(workspace.create 幂等 get-or-create),
|
|
23
|
+
* 再用 workspaceId 调 session.create。若只传 cwd,dsh 侧不会把会话挂到任何 workspace,
|
|
24
|
+
* 新会话会落到侧边栏"未分组"。 */
|
|
25
|
+
createSession(projectDir: string, retries?: number): Promise<{
|
|
26
|
+
sessionId: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* 通过 dsh settings.update 应用 providerOptions 指定的用户设置(逐命名空间幂等 patch)。
|
|
30
|
+
* dsh 启动初期 API 未就绪,整体带重试;单个命名空间不存在会导致该次调用失败重试。
|
|
31
|
+
*/
|
|
32
|
+
applySettings(sections: Record<string, Record<string, unknown>>, retries?: number): Promise<void>;
|
|
33
|
+
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
34
|
+
archiveSession(sessionId: string, retries?: number): Promise<void>;
|
|
35
|
+
private createHttpRequest;
|
|
36
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var bridge_script_exports = {};
|
|
19
|
+
__export(bridge_script_exports, {
|
|
20
|
+
generateBridgeScript: () => generateBridgeScript
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(bridge_script_exports);
|
|
23
|
+
var import_core = require("@aipanel/core");
|
|
24
|
+
var import_constants = require("./constants.cjs");
|
|
25
|
+
function generateBridgeScript(options = {}) {
|
|
26
|
+
const { theme = "auto" } = options;
|
|
27
|
+
return `
|
|
28
|
+
(function() {
|
|
29
|
+
const CURRENT_SESSION_KEY = ${JSON.stringify(import_constants.DSH_STORAGE_KEYS.CURRENT_SESSION)};
|
|
30
|
+
const SELECTION_KEY = ${JSON.stringify(import_constants.DSH_STORAGE_KEYS.SELECTION)};
|
|
31
|
+
const THEME = ${JSON.stringify(theme)};
|
|
32
|
+
|
|
33
|
+
// \u6865\u63A5\u5C42\u901A\u77E5 dsh-client \u7684\u9009\u4E2D\u5143\u7D20\u63D2\u5165\u4E8B\u4EF6\uFF08\u4E0E opencode \u4E00\u81F4\uFF1A\u9009\u4E2D\u5373\u8FFD\u52A0\u5230\u5BF9\u8BDD\u6846\uFF09
|
|
34
|
+
const INSERT_ELEMENT_EVENT = "aipanel:insert-element";
|
|
35
|
+
|
|
36
|
+
// === \u8BB0\u5F55\u6700\u8FD1\u9009\u4E2D\u5143\u7D20 ===
|
|
37
|
+
// \u4F9B dsh-client \u7684 @aipanel source \u4F5C\u4E3A\u5019\u9009\u8BFB\u53D6\uFF08\u53EF\u591A\u9009\uFF0C\u6700\u591A\u4FDD\u7559 20 \u4E2A\uFF09\uFF0C\u5E76\u6D3E\u53D1
|
|
38
|
+
// aipanel:insert-element \u8BA9 dsh-client \u7ACB\u5373\u628A\u5143\u7D20\u8FFD\u52A0\u5230\u5F53\u524D\u4F1A\u8BDD\u8F93\u5165\u6846\u3002
|
|
39
|
+
function pushSelection(element) {
|
|
40
|
+
if (!element) return;
|
|
41
|
+
try {
|
|
42
|
+
var list = [];
|
|
43
|
+
var raw = localStorage.getItem(SELECTION_KEY);
|
|
44
|
+
if (raw) list = JSON.parse(raw) || [];
|
|
45
|
+
if (!Array.isArray(list)) list = [];
|
|
46
|
+
var exists = list.some(function (e) {
|
|
47
|
+
return e && e.filePath === element.filePath && e.line === element.line;
|
|
48
|
+
});
|
|
49
|
+
if (!exists) list.unshift(element);
|
|
50
|
+
if (list.length > 20) list.length = 20;
|
|
51
|
+
localStorage.setItem(SELECTION_KEY, JSON.stringify(list));
|
|
52
|
+
// \u901A\u77E5 dsh-client \u8FFD\u52A0\u5230\u5BF9\u8BDD\u6846\uFF08\u9009\u4E2D\u5373\u63D2\u5165\uFF0C\u65E0\u9700\u518D\u8F93\u5165 @\uFF09
|
|
53
|
+
window.dispatchEvent(new CustomEvent(INSERT_ELEMENT_EVENT, {
|
|
54
|
+
detail: { element: element }
|
|
55
|
+
}));
|
|
56
|
+
} catch (e) { /* ignore */ }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// === \u4E3B\u9898\u540C\u6B65\uFF08UI \u5448\u73B0\uFF1B\u6301\u4E45\u5316\u4EA4\u7531 dsh settings\u300Cui-theme.preference\u300D\uFF0C\u4E0D\u5728\u6B64\u5199 localStorage\uFF09===
|
|
60
|
+
// dsh \u7684\u6697\u8272\u7531 body[data-ds-dark-theme] + colorScheme \u5448\u73B0\u3002
|
|
61
|
+
// \u6CE8\u610F\uFF1Abridge \u53EF\u80FD\u88AB\u6CE8\u5165\u5230 <head>\uFF0C\u6B64\u65F6 document.body \u5C1A\u4E0D\u5B58\u5728\uFF0C\u987B\u5728 DOM ready \u540E\u518D\u6267\u884C\u3002
|
|
62
|
+
// theme \u53C2\u6570\uFF1A"light" | "dark" | "auto"\uFF08auto \u4E0D\u5E72\u9884\uFF0C\u4EA4\u7ED9 dsh \u539F\u751F\u4E3B\u9898\u5904\u7406\uFF09\u3002
|
|
63
|
+
function applyTheme(theme) {
|
|
64
|
+
if (!document.body) return;
|
|
65
|
+
if (theme === "dark") {
|
|
66
|
+
document.body.setAttribute("data-ds-dark-theme", "");
|
|
67
|
+
document.documentElement.style.colorScheme = "dark";
|
|
68
|
+
} else if (theme === "light") {
|
|
69
|
+
document.body.removeAttribute("data-ds-dark-theme");
|
|
70
|
+
document.documentElement.style.colorScheme = "light";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// === \u5E03\u5C40\u8986\u76D6 ===
|
|
75
|
+
// \u9690\u85CF dsh \u7684\u4FA7\u8FB9\u680F\u5217\uFF0C\u907F\u514D\u4E0E AIPanel \u81EA\u5E26\u4F1A\u8BDD\u5217\u8868\u91CD\u590D\u3002
|
|
76
|
+
// \u7A33\u5B9A\u951A\u70B9\uFF1AAppFrame \u6839\u7F51\u683C\u5728\u4FA7\u8FB9\u680F\u6298\u53E0\u65F6\u5E26 data-sidebar-collapsed\uFF08AIPanel \u7A84 iframe \u4E0B\u6052\u5B58\u5728\uFF09\uFF0C
|
|
77
|
+
// \u4FA7\u8FB9\u680F\u5217\u662F\u6839\u7F51\u683C\u7684\u9996\u4E2A\u5B50\u5143\u7D20\u3002
|
|
78
|
+
// \u6CE8\u610F\u4E0D\u80FD\u53EA display:none \u5143\u7D20\uFF1A\u663E\u5F0F gridTemplateColumns\uFF08\u5185\u8054\u6837\u5F0F\uFF09\u8F68\u9053\u4E0D\u4F1A\u56E0\u5B50\u9879
|
|
79
|
+
// \u9690\u85CF\u800C\u6D88\u5931\uFF0C\u4F1A\u7559\u4E00\u6761\u7A7A\u767D\u5217\uFF0C\u987B\u628A\u9996\u5217\u8F68\u9053\u6539\u6210 auto\uFF08\u5B50\u9879\u9690\u85CF\u540E\u574D\u7F29\u4E3A 0\uFF09\u3002
|
|
80
|
+
function applyLayoutOverrides() {
|
|
81
|
+
try {
|
|
82
|
+
if (document.getElementById("aipanel-layout-overrides")) return;
|
|
83
|
+
var style = document.createElement("style");
|
|
84
|
+
style.id = "aipanel-layout-overrides";
|
|
85
|
+
style.textContent = [
|
|
86
|
+
"[data-sidebar-collapsed] {",
|
|
87
|
+
" grid-template-columns: auto !important;",
|
|
88
|
+
"}",
|
|
89
|
+
"[data-sidebar-collapsed] > :first-child {",
|
|
90
|
+
" display: none !important;",
|
|
91
|
+
"}",
|
|
92
|
+
].join("\\n");
|
|
93
|
+
document.head.appendChild(style);
|
|
94
|
+
} catch (e) { /* ignore */ }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// === \u6D88\u606F\u76D1\u542C ===
|
|
98
|
+
window.addEventListener("message", function(event) {
|
|
99
|
+
if (!event.data) return;
|
|
100
|
+
|
|
101
|
+
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u5207\u6362\u4E3B\u9898\uFF08\u5DE5\u5177\u680F\u4E3B\u9898\u6309\u94AE/\u8DDF\u968F\u7CFB\u7EDF\u53D8\u5316\uFF09\u3002\u52A8\u6001\u5E94\u7528\uFF0C\u65E0\u9700\u91CD\u8F7D\u3002
|
|
102
|
+
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.SET_THEME)}) {
|
|
103
|
+
applyTheme(event.data.theme);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u805A\u7126\u6307\u5B9A\u4F1A\u8BDD\uFF08\u65E0 deepLink \u6A21\u5F0F\uFF09\u3002
|
|
107
|
+
// dsh \u7684\u9009\u4E2D\u6001\u6301\u4E45\u5316\u4E3A JSON.stringify({ sessionId, subagentAddress? })\uFF0CSPA \u542F\u52A8\u65F6\u636E\u6B64\u6062\u590D\u3002
|
|
108
|
+
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.FOCUS_SESSION)}) {
|
|
109
|
+
const sessionId = event.data.sessionId;
|
|
110
|
+
if (!sessionId) return;
|
|
111
|
+
try {
|
|
112
|
+
localStorage.setItem(CURRENT_SESSION_KEY, JSON.stringify({ sessionId }));
|
|
113
|
+
} catch (e) {
|
|
114
|
+
console.warn("dsh bridge: failed to persist session selection", e);
|
|
115
|
+
}
|
|
116
|
+
// dsh SPA \u4ECE\u6301\u4E45\u5316\u9009\u4E2D\u6062\u590D\uFF0C\u5237\u65B0\u4EE5\u5207\u6362\u5230\u76EE\u6807\u4F1A\u8BDD
|
|
117
|
+
location.reload();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u9875\u9762\u9009\u4E2D\u5143\u7D20 \u2192 \u8BB0\u5F55\uFF0C\u4F9B @aipanel \u83DC\u5355\u7B5B\u9009\u540E\u4EE5 reference \u63D2\u5165
|
|
121
|
+
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.INSERT_FILE_PART)}) {
|
|
122
|
+
pushSelection(event.data.element);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// === \u5C31\u7EEA\u901A\u77E5 ===
|
|
127
|
+
// \u4E0D\u518D\u7528 MutationObserver \u6BCF\u5E27\u53D1 READY\uFF08\u90A3\u4F1A\u5728 dsh \u521A\u6E32\u67D3\u3001\u76EE\u6807\u4F1A\u8BDD\u5C1A\u672A\u6FC0\u6D3B\u65F6\u5C31
|
|
128
|
+
// \u63D0\u524D\u653E\u884C loading\uFF09\u3002\u6539\u4E3A\u76D1\u542C dsh-client \u63D2\u4EF6\u5728"\u76EE\u6807\u4F1A\u8BDD\u6FC0\u6D3B\u4E14\u6E32\u67D3\u7A33\u5B9A"\u540E\u6D3E\u53D1\u7684
|
|
129
|
+
// aipanel:session-ready \u4E8B\u4EF6\uFF0C\u6536\u5230\u540E\u4E0A\u62A5 SESSION_READY{sessionId}\u3002
|
|
130
|
+
// \u53EA\u53D1 SESSION_READY \u800C\u4E0D\u53D1 READY\uFF1A\u5BA2\u6237\u7AEF\u5DF2\u80FD\u51ED sessionId \u5339\u914D\u5F53\u524D\u4F1A\u8BDD\u51B3\u5B9A\u4F55\u65F6
|
|
131
|
+
// \u653E\u884C loading / \u8865\u53D1\u805A\u7126\uFF1B\u907F\u514D\u4E0E"FOCUS_SESSION \u2192 reload \u2192 \u518D\u5C31\u7EEA"\u6784\u6210\u5237\u65B0\u6B7B\u5FAA\u73AF\u3002
|
|
132
|
+
const SESSION_READY_EVENT = "aipanel:session-ready";
|
|
133
|
+
|
|
134
|
+
function sendSessionReady(sessionId) {
|
|
135
|
+
if (window.parent !== window) {
|
|
136
|
+
window.parent.postMessage({
|
|
137
|
+
type: ${JSON.stringify(import_core.WIDGET_MSG.SESSION_READY)},
|
|
138
|
+
sessionId
|
|
139
|
+
}, "*");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
window.addEventListener(SESSION_READY_EVENT, function(e) {
|
|
144
|
+
const sessionId = e && e.detail && e.detail.sessionId;
|
|
145
|
+
if (!sessionId) return;
|
|
146
|
+
sendSessionReady(sessionId);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// \u4E3B\u9898\u540C\u6B65/\u5E03\u5C40\u8986\u76D6\u4ECD\u987B\u5728\u6BCF\u6B21\u9875\u9762\u52A0\u8F7D\u65F6\u751F\u6548\uFF08\u4E0E\u5C31\u7EEA\u5224\u5B9A\u89E3\u8026\uFF0C\u4E0D\u53C2\u4E0E loading \u653E\u884C\uFF09
|
|
150
|
+
function init() {
|
|
151
|
+
applyTheme(THEME);
|
|
152
|
+
applyLayoutOverrides();
|
|
153
|
+
}
|
|
154
|
+
if (document.readyState === "loading") {
|
|
155
|
+
document.addEventListener("DOMContentLoaded", init);
|
|
156
|
+
} else {
|
|
157
|
+
init();
|
|
158
|
+
}
|
|
159
|
+
})();
|
|
160
|
+
`;
|
|
161
|
+
}
|
|
162
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
163
|
+
0 && (module.exports = {
|
|
164
|
+
generateBridgeScript
|
|
165
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface BridgeScriptOptions {
|
|
2
|
+
/** 主题模式 */
|
|
3
|
+
theme?: "light" | "dark" | "auto";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 生成 PostMessage Bridge 脚本。
|
|
7
|
+
* dsh 无正式"切换会话"URL 钩子,选中态持久化在 localStorage(CURRENT_SESSION),
|
|
8
|
+
* 且 SPA 启动时会据此恢复选中——因此桥接采用"写入选中 + 刷新 iframe"的策略。
|
|
9
|
+
* 若 dsh 后续暴露正式切会话接口,可替换以下 FOCUS_SESSION 分支。
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateBridgeScript(options?: BridgeScriptOptions): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var constants_exports = {};
|
|
19
|
+
__export(constants_exports, {
|
|
20
|
+
DEFAULT_DEEPSEEK_PROVIDER_OPTIONS: () => DEFAULT_DEEPSEEK_PROVIDER_OPTIONS,
|
|
21
|
+
DSH_API_BASE: () => DSH_API_BASE,
|
|
22
|
+
DSH_DEFAULT_PORT: () => DSH_DEFAULT_PORT,
|
|
23
|
+
DSH_HOST_EVENTS_PATH: () => DSH_HOST_EVENTS_PATH,
|
|
24
|
+
DSH_LOOPBACK_HOST: () => DSH_LOOPBACK_HOST,
|
|
25
|
+
DSH_MUX_EVENTS_PATH: () => DSH_MUX_EVENTS_PATH,
|
|
26
|
+
DSH_STORAGE_KEYS: () => DSH_STORAGE_KEYS
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(constants_exports);
|
|
29
|
+
const DSH_API_BASE = "/api";
|
|
30
|
+
const DSH_MUX_EVENTS_PATH = "/api/events.mux";
|
|
31
|
+
const DSH_HOST_EVENTS_PATH = "/api/events.host";
|
|
32
|
+
const DSH_LOOPBACK_HOST = "127.0.0.1";
|
|
33
|
+
const DSH_DEFAULT_PORT = 3080;
|
|
34
|
+
const DSH_STORAGE_KEYS = {
|
|
35
|
+
/** 当前选中会话(SPA 启动时据此恢复选中,无 URL 深链) */
|
|
36
|
+
CURRENT_SESSION: "dsh.sessions.current",
|
|
37
|
+
/** 选中的页面元素(bridge 写入,dsh-client 的 @aipanel source 读取) */
|
|
38
|
+
SELECTION: "dsh.bridge.selection"
|
|
39
|
+
};
|
|
40
|
+
const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS = {
|
|
41
|
+
agentPreset: "code"
|
|
42
|
+
};
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
DEFAULT_DEEPSEEK_PROVIDER_OPTIONS,
|
|
46
|
+
DSH_API_BASE,
|
|
47
|
+
DSH_DEFAULT_PORT,
|
|
48
|
+
DSH_HOST_EVENTS_PATH,
|
|
49
|
+
DSH_LOOPBACK_HOST,
|
|
50
|
+
DSH_MUX_EVENTS_PATH,
|
|
51
|
+
DSH_STORAGE_KEYS
|
|
52
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSeek Harness Provider 专属常量
|
|
3
|
+
* 与 dsh web 绑定的常量自包含于此,核心层不感知。
|
|
4
|
+
*/
|
|
5
|
+
import type { DeepSeekProviderOptions } from "./types";
|
|
6
|
+
/** ==================== dsh API ==================== */
|
|
7
|
+
/** dsh 所有 RPC 路径前缀(POST /api/<method>、GET /api/events.mux) */
|
|
8
|
+
export declare const DSH_API_BASE = "/api";
|
|
9
|
+
/** mux 事件流端点(会话级聚合流,含 session/event 可推导 thinking/streaming) */
|
|
10
|
+
export declare const DSH_MUX_EVENTS_PATH = "/api/events.mux";
|
|
11
|
+
/** host 事件流端点(host 级,含 host/session-status.running 运行态开关) */
|
|
12
|
+
export declare const DSH_HOST_EVENTS_PATH = "/api/events.host";
|
|
13
|
+
/** dsh 唯一允许的绑定主机字面量(服务 schema 只接受 127.0.0.1 / 0.0.0.0) */
|
|
14
|
+
export declare const DSH_LOOPBACK_HOST = "127.0.0.1";
|
|
15
|
+
/** dsh web 默认端口(未显式指定时) */
|
|
16
|
+
export declare const DSH_DEFAULT_PORT = 3080;
|
|
17
|
+
/** ==================== dsh localStorage 键 ==================== */
|
|
18
|
+
export declare const DSH_STORAGE_KEYS: {
|
|
19
|
+
/** 当前选中会话(SPA 启动时据此恢复选中,无 URL 深链) */
|
|
20
|
+
readonly CURRENT_SESSION: "dsh.sessions.current";
|
|
21
|
+
/** 选中的页面元素(bridge 写入,dsh-client 的 @aipanel source 读取) */
|
|
22
|
+
readonly SELECTION: "dsh.bridge.selection";
|
|
23
|
+
};
|
|
24
|
+
/** ==================== Provider 专属配置默认值 ==================== */
|
|
25
|
+
export declare const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS: DeepSeekProviderOptions;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var deepseek_web_exports = {};
|
|
19
|
+
__export(deepseek_web_exports, {
|
|
20
|
+
startDeepSeekWeb: () => startDeepSeekWeb
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(deepseek_web_exports);
|
|
23
|
+
var import_execa = require("execa");
|
|
24
|
+
var import_node = require("@aipanel/core/node");
|
|
25
|
+
const log = (0, import_node.createLogger)("DeepSeekWeb");
|
|
26
|
+
function startDeepSeekWeb(options) {
|
|
27
|
+
const { port, hostname, cwd, patchPath, home, verbose } = options;
|
|
28
|
+
const args = ["--profile", "web"];
|
|
29
|
+
if (patchPath) {
|
|
30
|
+
args.push("--patch", patchPath);
|
|
31
|
+
}
|
|
32
|
+
args.push(
|
|
33
|
+
"--port",
|
|
34
|
+
String(port),
|
|
35
|
+
"--host",
|
|
36
|
+
hostname,
|
|
37
|
+
// 由插件内嵌 iframe 展示,禁止 dsh 自动打开默认浏览器
|
|
38
|
+
"--no-open"
|
|
39
|
+
);
|
|
40
|
+
log.debug("Spawning dsh web process", {
|
|
41
|
+
command: "dsh",
|
|
42
|
+
args: args.join(" "),
|
|
43
|
+
cwd,
|
|
44
|
+
home: home ?? process.env.DSH_HOME
|
|
45
|
+
});
|
|
46
|
+
const proc = (0, import_execa.execa)("dsh", args, {
|
|
47
|
+
cwd,
|
|
48
|
+
reject: false,
|
|
49
|
+
cleanup: true,
|
|
50
|
+
shell: true,
|
|
51
|
+
env: {
|
|
52
|
+
...process.env,
|
|
53
|
+
...home ? { DSH_HOME: home } : {},
|
|
54
|
+
...verbose ? { VERBOSE: "1" } : {}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
proc.then((result) => {
|
|
58
|
+
if (result.exitCode !== 0) {
|
|
59
|
+
log.warn("[dsh exited]", { exitCode: result.exitCode, signal: result.signal });
|
|
60
|
+
} else {
|
|
61
|
+
log.debug("[dsh exited]", { exitCode: result.exitCode });
|
|
62
|
+
}
|
|
63
|
+
}).catch((e) => {
|
|
64
|
+
log.error("[dsh spawn failed]", { error: e instanceof Error ? e.message : String(e) });
|
|
65
|
+
});
|
|
66
|
+
proc.stdout?.on("data", (data) => {
|
|
67
|
+
const output = data.toString().trim();
|
|
68
|
+
if (output) {
|
|
69
|
+
log.debug("[dsh stdout]", { output });
|
|
70
|
+
(0, import_node.getProcessLogBuffer)().addProviderStdout(output);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
proc.stderr?.on("data", (data) => {
|
|
74
|
+
const output = data.toString().trim();
|
|
75
|
+
if (output) {
|
|
76
|
+
log.warn("[dsh stderr]", { output });
|
|
77
|
+
(0, import_node.getProcessLogBuffer)().addProviderStderr(output);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return proc;
|
|
81
|
+
}
|
|
82
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
83
|
+
0 && (module.exports = {
|
|
84
|
+
startDeepSeekWeb
|
|
85
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ResultPromise } from "execa";
|
|
2
|
+
export interface DeepSeekWebOptions {
|
|
3
|
+
/** 服务端口 */
|
|
4
|
+
port: number;
|
|
5
|
+
/** 服务主机(dsh 只接受 127.0.0.1,见 DSH_LOOPBACK_HOST) */
|
|
6
|
+
hostname: string;
|
|
7
|
+
/** 工作目录 */
|
|
8
|
+
cwd: string;
|
|
9
|
+
/** cordis overlay 文件路径(--patch 注入 MCP client / aipanel 插件) */
|
|
10
|
+
patchPath?: string;
|
|
11
|
+
/** dsh 数据目录(透传 DSH_HOME;缺省跟随 $DSH_HOME / ~/.dsh) */
|
|
12
|
+
home?: string;
|
|
13
|
+
/** 启用 verbose 模式 */
|
|
14
|
+
verbose?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 启动 dsh web 服务。
|
|
18
|
+
* dsh web 是自包含单进程(web server + agent runtime 同进程),无需额外配置/插件注入。
|
|
19
|
+
* 也无需 API key 即可启动 UI 壳。
|
|
20
|
+
*/
|
|
21
|
+
export declare function startDeepSeekWeb(options: DeepSeekWebOptions): ResultPromise;
|