@aipanel/provider-deepseek 1.2.8 → 1.2.9
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 +0 -33
- 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 +14 -3
- package/es/provider.d.ts +6 -7
- package/es/provider.js +11 -42
- package/lib/api.cjs +0 -33
- 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 +14 -3
- package/lib/profile.d.ts +14 -4
- package/lib/provider.cjs +11 -42
- package/lib/provider.d.ts +6 -7
- 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/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/es/api.js
CHANGED
|
@@ -213,39 +213,6 @@ class DeepSeekAPI {
|
|
|
213
213
|
timer.end("\u274C All retries exhausted");
|
|
214
214
|
throw lastError;
|
|
215
215
|
}
|
|
216
|
-
/**
|
|
217
|
-
* 通过 dsh settings/mutate 应用 providerOptions 指定的用户设置(逐命名空间幂等 patch)。
|
|
218
|
-
* dsh 启动初期 API 未就绪,整体带重试;单个命名空间不存在会导致该次调用失败重试。
|
|
219
|
-
*/
|
|
220
|
-
async applySettings(sections, retries = DEFAULT_RETRIES) {
|
|
221
|
-
const namespaces = Object.keys(sections);
|
|
222
|
-
if (namespaces.length === 0) return;
|
|
223
|
-
const timer = log.timer("applySettings", { namespaces });
|
|
224
|
-
let lastError = null;
|
|
225
|
-
for (let i = 0; i < retries; i++) {
|
|
226
|
-
try {
|
|
227
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { method: "settings/mutate", namespaces });
|
|
228
|
-
for (const [ns, patch] of Object.entries(sections)) {
|
|
229
|
-
const ops = Object.entries(patch).map(([key, value]) => ({
|
|
230
|
-
op: "set",
|
|
231
|
-
path: [key],
|
|
232
|
-
value
|
|
233
|
-
}));
|
|
234
|
-
await this.call("settings/mutate", { ns, ops });
|
|
235
|
-
}
|
|
236
|
-
timer.end(`Applied settings: ${namespaces.join(", ")}`);
|
|
237
|
-
return;
|
|
238
|
-
} catch (e) {
|
|
239
|
-
lastError = e instanceof Error ? e : new Error(String(e));
|
|
240
|
-
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { method: "applySettings" });
|
|
241
|
-
if (i < retries - 1) {
|
|
242
|
-
await sleep(RETRY_DELAY);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
timer.end("\u274C All retries exhausted");
|
|
247
|
-
throw lastError;
|
|
248
|
-
}
|
|
249
216
|
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
250
217
|
async archiveSession(sessionId, retries = DEFAULT_RETRIES) {
|
|
251
218
|
const timer = log.timer("archiveSession", { sessionId, retries });
|
package/es/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/es/constants.js
CHANGED
|
@@ -2,14 +2,6 @@ const DSH_API_BASE = "/api";
|
|
|
2
2
|
const DSH_REMOTE_MUX_PATH = "/api/remote.mux";
|
|
3
3
|
const DSH_LOOPBACK_HOST = "127.0.0.1";
|
|
4
4
|
const DSH_DEFAULT_PORT = 3080;
|
|
5
|
-
const DSH_STORAGE_KEYS = {
|
|
6
|
-
/** 当前选中会话(SPA 启动时据此恢复选中,无 URL 深链) */
|
|
7
|
-
CURRENT_SESSION: "dsh.sessions.current",
|
|
8
|
-
/** 选中的页面元素(bridge 写入,dsh-client 的 @aipanel source 读取) */
|
|
9
|
-
SELECTION: "dsh.bridge.selection",
|
|
10
|
-
/** 诊断功能开关标记(bridge 按 provider 配置写入,dsh-client 据此决定是否注册诊断视图) */
|
|
11
|
-
DIAGNOSTICS_ENABLED: "dsh.bridge.diagnostics.enabled"
|
|
12
|
-
};
|
|
13
5
|
const DEFAULT_DEEPSEEK_PROVIDER_OPTIONS = {
|
|
14
6
|
// 对齐 opencode 的 enableLsp(默认 true):诊断功能默认开启
|
|
15
7
|
enableDiagnostics: true,
|
|
@@ -21,6 +13,5 @@ export {
|
|
|
21
13
|
DSH_API_BASE,
|
|
22
14
|
DSH_DEFAULT_PORT,
|
|
23
15
|
DSH_LOOPBACK_HOST,
|
|
24
|
-
DSH_REMOTE_MUX_PATH
|
|
25
|
-
DSH_STORAGE_KEYS
|
|
16
|
+
DSH_REMOTE_MUX_PATH
|
|
26
17
|
};
|
package/es/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/es/index.js
CHANGED
|
@@ -10,7 +10,6 @@ function createProvider(ctx) {
|
|
|
10
10
|
import { DeepSeekAPI } from "./api.js";
|
|
11
11
|
import { startDeepSeekWeb } from "./deepseek-web.js";
|
|
12
12
|
import { buildDshOverlay, writeDshOverlay } from "./profile.js";
|
|
13
|
-
import { generateBridgeScript } from "./bridge-script.js";
|
|
14
13
|
import { checkDeepSeekInstalled, getDeepSeekVersion, killOrphanDeepSeekProcesses } from "./system.js";
|
|
15
14
|
import { DEFAULT_DEEPSEEK_PROVIDER_OPTIONS, DSH_LOOPBACK_HOST as DSH_LOOPBACK_HOST2, DSH_DEFAULT_PORT } from "./constants.js";
|
|
16
15
|
export {
|
|
@@ -21,7 +20,6 @@ export {
|
|
|
21
20
|
buildDshOverlay,
|
|
22
21
|
checkDeepSeekInstalled,
|
|
23
22
|
createProvider,
|
|
24
|
-
generateBridgeScript,
|
|
25
23
|
getDeepSeekVersion,
|
|
26
24
|
killOrphanDeepSeekProcesses,
|
|
27
25
|
startDeepSeekWeb,
|
package/es/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/es/profile.js
CHANGED
|
@@ -16,7 +16,11 @@ function buildDshOverlay(options) {
|
|
|
16
16
|
clientAvailable = true,
|
|
17
17
|
autoDiagnose,
|
|
18
18
|
enableDiagnostics = true,
|
|
19
|
-
eventsToken
|
|
19
|
+
eventsToken,
|
|
20
|
+
agentPreset,
|
|
21
|
+
permissionPreset,
|
|
22
|
+
busyEnter,
|
|
23
|
+
theme = "auto"
|
|
20
24
|
} = options;
|
|
21
25
|
const mcpUrl = `http://127.0.0.1:${vitePort}${MCP_API_PATH}`;
|
|
22
26
|
const rows = [];
|
|
@@ -46,14 +50,21 @@ function buildDshOverlay(options) {
|
|
|
46
50
|
...eventsToken ? [
|
|
47
51
|
` eventsToken: ${JSON.stringify(eventsToken)}`,
|
|
48
52
|
` eventsPath: ${JSON.stringify(HOST_EVENTS_API_PATH)}`
|
|
49
|
-
] : []
|
|
53
|
+
] : [],
|
|
54
|
+
// providerOptions → 启动期设置(dsh-plugin/applyProviderSettings 经 ctx.settings 写入)
|
|
55
|
+
...agentPreset !== void 0 ? [` agentPreset: ${JSON.stringify(agentPreset)}`] : [],
|
|
56
|
+
...permissionPreset !== void 0 ? [` permissionPreset: ${JSON.stringify(permissionPreset)}`] : [],
|
|
57
|
+
...busyEnter !== void 0 ? [` busyEnter: ${JSON.stringify(busyEnter)}`] : []
|
|
50
58
|
].join("\n")
|
|
51
59
|
);
|
|
52
60
|
rows.push(
|
|
53
61
|
[
|
|
54
62
|
" - id: aipanel-client",
|
|
55
63
|
" name: '@aipanel/dsh-client'",
|
|
56
|
-
...clientAvailable ? [] : [" disabled: true"]
|
|
64
|
+
...clientAvailable ? [] : [" disabled: true"],
|
|
65
|
+
" config:",
|
|
66
|
+
` enableDiagnostics: ${enableDiagnostics ? "true" : "false"}`,
|
|
67
|
+
...theme !== "auto" ? [` theme: ${JSON.stringify(theme)}`] : []
|
|
57
68
|
].join("\n")
|
|
58
69
|
);
|
|
59
70
|
return ["- insert:", rows.join("\n"), ""].join("\n");
|
package/es/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[]>;
|
package/es/provider.js
CHANGED
|
@@ -6,7 +6,6 @@ import { createLogger } from "@aipanel/core/node";
|
|
|
6
6
|
import { DEFAULT_DEEPSEEK_PROVIDER_OPTIONS } from "./constants.js";
|
|
7
7
|
import { DSH_LOOPBACK_HOST } from "./constants.js";
|
|
8
8
|
import { DeepSeekAPI } from "./api.js";
|
|
9
|
-
import { generateBridgeScript } from "./bridge-script.js";
|
|
10
9
|
import { LaunchToken, startDeepSeekWeb } from "./deepseek-web.js";
|
|
11
10
|
import { buildDshOverlay, writeDshOverlay } from "./profile.js";
|
|
12
11
|
import {
|
|
@@ -33,22 +32,17 @@ class DeepSeekWebProvider {
|
|
|
33
32
|
__publicField(this, "api");
|
|
34
33
|
__publicField(this, "deps");
|
|
35
34
|
__publicField(this, "process", null);
|
|
36
|
-
|
|
35
|
+
/** AIPanel 侧下发的主题偏好(AIPanelWidgetTheme,default auto):随 client 插件 config 注入,作为启动初值 */
|
|
36
|
+
__publicField(this, "uiTheme", "auto");
|
|
37
37
|
__publicField(this, "opts");
|
|
38
38
|
this.deps = deps;
|
|
39
39
|
this.opts = resolveDeepSeekOptions(options);
|
|
40
40
|
this.api = new DeepSeekAPI(DSH_LOOPBACK_HOST, deps.getWebPort);
|
|
41
41
|
}
|
|
42
|
-
/**
|
|
43
|
-
get bridgeScript() {
|
|
44
|
-
return generateBridgeScript(this.bridgeOptions);
|
|
45
|
-
}
|
|
46
|
-
/** 初始化桥接配置(主题、诊断开关等) */
|
|
42
|
+
/** 记录 AIPanel 侧主题偏好(applyConfig 在 start 前调用;start 时随 client 插件 config 下发) */
|
|
47
43
|
applyConfig(config) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
diagnosticsEnabled: this.opts.enableDiagnostics ?? false
|
|
51
|
-
};
|
|
44
|
+
const t = config.theme;
|
|
45
|
+
this.uiTheme = t === "light" || t === "dark" || t === "auto" ? t : "auto";
|
|
52
46
|
}
|
|
53
47
|
async checkEnvironment() {
|
|
54
48
|
if (!await checkDeepSeekInstalled()) {
|
|
@@ -109,7 +103,7 @@ Please upgrade:
|
|
|
109
103
|
this.opts.home
|
|
110
104
|
);
|
|
111
105
|
if (!pluginAvailable) {
|
|
112
|
-
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics &
|
|
106
|
+
log.warn("@aipanel/dsh-plugin unavailable; run_diagnostics & settings application disabled", {
|
|
113
107
|
metaUrl: import.meta.url
|
|
114
108
|
});
|
|
115
109
|
}
|
|
@@ -121,7 +115,11 @@ Please upgrade:
|
|
|
121
115
|
autoDiagnose: this.opts.autoDiagnose,
|
|
122
116
|
enableDiagnostics: this.opts.enableDiagnostics,
|
|
123
117
|
// 宿主事件推送令牌(core 每轮启动随机):随 plugin config 注入 dsh-plugin 用于回推鉴权
|
|
124
|
-
eventsToken: options.eventsToken
|
|
118
|
+
eventsToken: options.eventsToken,
|
|
119
|
+
agentPreset: this.opts.agentPreset,
|
|
120
|
+
permissionPreset: this.opts.permissionPreset,
|
|
121
|
+
busyEnter: this.opts.busyEnter,
|
|
122
|
+
theme: this.uiTheme
|
|
125
123
|
});
|
|
126
124
|
const patchPath = writeDshOverlay(options.cwd, overlay);
|
|
127
125
|
const launchToken = new LaunchToken();
|
|
@@ -163,37 +161,8 @@ Please upgrade:
|
|
|
163
161
|
}
|
|
164
162
|
);
|
|
165
163
|
}
|
|
166
|
-
const settings = this.buildSettingsToApply();
|
|
167
|
-
if (Object.keys(settings).length > 0) {
|
|
168
|
-
void this.api.applySettings(settings).catch((e) => {
|
|
169
|
-
log.warn("failed to apply provider settings to dsh", {
|
|
170
|
-
settings,
|
|
171
|
-
error: e instanceof Error ? e.message : String(e)
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
164
|
return { url: this.api.shellUrl, processHandle: proc, webAuthCookie };
|
|
176
165
|
}
|
|
177
|
-
/** 把 providerOptions 配置映射为 dsh settings 命名空间 patch(仅含用户显式配置项) */
|
|
178
|
-
buildSettingsToApply() {
|
|
179
|
-
const sections = {};
|
|
180
|
-
if (this.opts.agentPreset !== void 0) {
|
|
181
|
-
sections["agent-presets"] = { ...sections["agent-presets"], default: this.opts.agentPreset };
|
|
182
|
-
}
|
|
183
|
-
if (this.opts.permissionPreset !== void 0) {
|
|
184
|
-
sections.permission = {
|
|
185
|
-
...sections.permission,
|
|
186
|
-
defaultPreset: this.opts.permissionPreset
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (this.opts.busyEnter !== void 0) {
|
|
190
|
-
sections["ui-conversation"] = {
|
|
191
|
-
...sections["ui-conversation"],
|
|
192
|
-
busyEnter: this.opts.busyEnter
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
return sections;
|
|
196
|
-
}
|
|
197
166
|
async stop() {
|
|
198
167
|
if (this.process) {
|
|
199
168
|
log.debug("Killing dsh web process", { pid: this.process.pid });
|
package/lib/api.cjs
CHANGED
|
@@ -244,39 +244,6 @@ class DeepSeekAPI {
|
|
|
244
244
|
timer.end("\u274C All retries exhausted");
|
|
245
245
|
throw lastError;
|
|
246
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
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
timer.end("\u274C All retries exhausted");
|
|
278
|
-
throw lastError;
|
|
279
|
-
}
|
|
280
247
|
/** 归档会话(dsh 无硬删除,仅归档;幂等) */
|
|
281
248
|
async archiveSession(sessionId, retries = import_core.DEFAULT_RETRIES) {
|
|
282
249
|
const timer = log.timer("archiveSession", { sessionId, retries });
|
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
|
@@ -43,7 +43,11 @@ function buildDshOverlay(options) {
|
|
|
43
43
|
clientAvailable = true,
|
|
44
44
|
autoDiagnose,
|
|
45
45
|
enableDiagnostics = true,
|
|
46
|
-
eventsToken
|
|
46
|
+
eventsToken,
|
|
47
|
+
agentPreset,
|
|
48
|
+
permissionPreset,
|
|
49
|
+
busyEnter,
|
|
50
|
+
theme = "auto"
|
|
47
51
|
} = options;
|
|
48
52
|
const mcpUrl = `http://127.0.0.1:${vitePort}${import_node.MCP_API_PATH}`;
|
|
49
53
|
const rows = [];
|
|
@@ -73,14 +77,21 @@ function buildDshOverlay(options) {
|
|
|
73
77
|
...eventsToken ? [
|
|
74
78
|
` eventsToken: ${JSON.stringify(eventsToken)}`,
|
|
75
79
|
` eventsPath: ${JSON.stringify(import_node.HOST_EVENTS_API_PATH)}`
|
|
76
|
-
] : []
|
|
80
|
+
] : [],
|
|
81
|
+
// providerOptions → 启动期设置(dsh-plugin/applyProviderSettings 经 ctx.settings 写入)
|
|
82
|
+
...agentPreset !== void 0 ? [` agentPreset: ${JSON.stringify(agentPreset)}`] : [],
|
|
83
|
+
...permissionPreset !== void 0 ? [` permissionPreset: ${JSON.stringify(permissionPreset)}`] : [],
|
|
84
|
+
...busyEnter !== void 0 ? [` busyEnter: ${JSON.stringify(busyEnter)}`] : []
|
|
77
85
|
].join("\n")
|
|
78
86
|
);
|
|
79
87
|
rows.push(
|
|
80
88
|
[
|
|
81
89
|
" - id: aipanel-client",
|
|
82
90
|
" name: '@aipanel/dsh-client'",
|
|
83
|
-
...clientAvailable ? [] : [" disabled: true"]
|
|
91
|
+
...clientAvailable ? [] : [" disabled: true"],
|
|
92
|
+
" config:",
|
|
93
|
+
` enableDiagnostics: ${enableDiagnostics ? "true" : "false"}`,
|
|
94
|
+
...theme !== "auto" ? [` theme: ${JSON.stringify(theme)}`] : []
|
|
84
95
|
].join("\n")
|
|
85
96
|
);
|
|
86
97
|
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[]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipanel/provider-deepseek",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.cjs",
|
|
6
6
|
"module": "es/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"execa": "^9.6.1",
|
|
25
|
-
"@aipanel/core": "1.2.
|
|
25
|
+
"@aipanel/core": "1.2.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"esbuild": "^0.25.0"
|
package/es/bridge-script.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface BridgeScriptOptions {
|
|
2
|
-
/** 主题模式 */
|
|
3
|
-
theme?: "light" | "dark" | "auto";
|
|
4
|
-
/** 诊断功能开关(provider option enableDiagnostics;写入 localStorage 供 dsh-client 决定是否注册诊断视图) */
|
|
5
|
-
diagnosticsEnabled?: boolean;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* 生成 PostMessage Bridge 脚本。
|
|
9
|
-
* dsh 无正式"切换会话"URL 钩子,选中态持久化在 localStorage(CURRENT_SESSION),
|
|
10
|
-
* 且 SPA 启动时会据此恢复选中——因此桥接采用"写入选中 + 刷新 iframe"的策略。
|
|
11
|
-
* 若 dsh 后续暴露正式切会话接口,可替换以下 FOCUS_SESSION 分支。
|
|
12
|
-
*/
|
|
13
|
-
export declare function generateBridgeScript(options?: BridgeScriptOptions): string;
|
package/es/bridge-script.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import { WIDGET_MSG } from "@aipanel/core";
|
|
2
|
-
import { DSH_STORAGE_KEYS } from "./constants.js";
|
|
3
|
-
function generateBridgeScript(options = {}) {
|
|
4
|
-
const { theme = "auto", diagnosticsEnabled = false } = options;
|
|
5
|
-
return `
|
|
6
|
-
(function() {
|
|
7
|
-
const CURRENT_SESSION_KEY = ${JSON.stringify(DSH_STORAGE_KEYS.CURRENT_SESSION)};
|
|
8
|
-
const SELECTION_KEY = ${JSON.stringify(DSH_STORAGE_KEYS.SELECTION)};
|
|
9
|
-
const DIAGNOSTICS_KEY = ${JSON.stringify(DSH_STORAGE_KEYS.DIAGNOSTICS_ENABLED)};
|
|
10
|
-
const DIAGNOSTICS_ENABLED = ${JSON.stringify(diagnosticsEnabled)};
|
|
11
|
-
const THEME = ${JSON.stringify(theme)};
|
|
12
|
-
|
|
13
|
-
// \u8BCA\u65AD\u529F\u80FD\u5F00\u5173\uFF1A\u540C\u6B65\u5199\u5165\uFF08\u4E0D\u4F9D\u8D56 DOM\uFF09\uFF0C\u4FDD\u8BC1 dsh-client apply \u65F6\u5373\u53EF\u8BFB\u5230\u6807\u8BB0\u3002
|
|
14
|
-
// bridge \u811A\u672C\u6CE8\u5165\u4E8E <head>\uFF0Cdsh-client \u63D2\u4EF6\u5728\u9875\u9762\u811A\u672C/React \u521D\u59CB\u5316\u540E\u624D apply\uFF0C
|
|
15
|
-
// \u82E5\u7B49 DOMContentLoaded \u518D\u5199\u5219\u5B58\u5728\u65F6\u5E8F\u7ADE\u4E89\uFF0C\u89C6\u56FE\u53EF\u80FD\u6F0F\u6CE8\u518C\u3002
|
|
16
|
-
try {
|
|
17
|
-
if (DIAGNOSTICS_ENABLED) {
|
|
18
|
-
localStorage.setItem(DIAGNOSTICS_KEY, "1");
|
|
19
|
-
} else {
|
|
20
|
-
localStorage.removeItem(DIAGNOSTICS_KEY);
|
|
21
|
-
}
|
|
22
|
-
} catch (e) { /* ignore */ }
|
|
23
|
-
|
|
24
|
-
// \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
|
|
25
|
-
const INSERT_ELEMENT_EVENT = "aipanel:insert-element";
|
|
26
|
-
|
|
27
|
-
// === \u8BB0\u5F55\u6700\u8FD1\u9009\u4E2D\u5143\u7D20 ===
|
|
28
|
-
// \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
|
|
29
|
-
// aipanel:insert-element \u8BA9 dsh-client \u7ACB\u5373\u628A\u5143\u7D20\u8FFD\u52A0\u5230\u5F53\u524D\u4F1A\u8BDD\u8F93\u5165\u6846\u3002
|
|
30
|
-
function pushSelection(element) {
|
|
31
|
-
if (!element) return;
|
|
32
|
-
try {
|
|
33
|
-
var list = [];
|
|
34
|
-
var raw = localStorage.getItem(SELECTION_KEY);
|
|
35
|
-
if (raw) list = JSON.parse(raw) || [];
|
|
36
|
-
if (!Array.isArray(list)) list = [];
|
|
37
|
-
var exists = list.some(function (e) {
|
|
38
|
-
return e && e.filePath === element.filePath && e.line === element.line;
|
|
39
|
-
});
|
|
40
|
-
if (!exists) list.unshift(element);
|
|
41
|
-
if (list.length > 20) list.length = 20;
|
|
42
|
-
localStorage.setItem(SELECTION_KEY, JSON.stringify(list));
|
|
43
|
-
// \u901A\u77E5 dsh-client \u8FFD\u52A0\u5230\u5BF9\u8BDD\u6846\uFF08\u9009\u4E2D\u5373\u63D2\u5165\uFF0C\u65E0\u9700\u518D\u8F93\u5165 @\uFF09
|
|
44
|
-
window.dispatchEvent(new CustomEvent(INSERT_ELEMENT_EVENT, {
|
|
45
|
-
detail: { element: element }
|
|
46
|
-
}));
|
|
47
|
-
} catch (e) { /* ignore */ }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// === \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===
|
|
51
|
-
// dsh \u7684\u6697\u8272\u7531 body[data-ds-dark-theme] + colorScheme \u5448\u73B0\u3002
|
|
52
|
-
// \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
|
|
53
|
-
// theme \u53C2\u6570\uFF1A"light" | "dark" | "auto"\uFF08auto \u4E0D\u5E72\u9884\uFF0C\u4EA4\u7ED9 dsh \u539F\u751F\u4E3B\u9898\u5904\u7406\uFF09\u3002
|
|
54
|
-
function applyTheme(theme) {
|
|
55
|
-
if (!document.body) return;
|
|
56
|
-
if (theme === "dark") {
|
|
57
|
-
document.body.setAttribute("data-ds-dark-theme", "");
|
|
58
|
-
document.documentElement.style.colorScheme = "dark";
|
|
59
|
-
} else if (theme === "light") {
|
|
60
|
-
document.body.removeAttribute("data-ds-dark-theme");
|
|
61
|
-
document.documentElement.style.colorScheme = "light";
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// === \u5E03\u5C40\u8986\u76D6 ===
|
|
66
|
-
// \u9690\u85CF dsh \u7684\u4FA7\u8FB9\u680F\u5217\uFF0C\u907F\u514D\u4E0E AIPanel \u81EA\u5E26\u4F1A\u8BDD\u5217\u8868\u91CD\u590D\u3002
|
|
67
|
-
// \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
|
|
68
|
-
// \u4FA7\u8FB9\u680F\u5217\u662F\u6839\u7F51\u683C\u7684\u9996\u4E2A\u5B50\u5143\u7D20\u3002
|
|
69
|
-
// \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
|
|
70
|
-
// \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
|
|
71
|
-
function applyLayoutOverrides() {
|
|
72
|
-
try {
|
|
73
|
-
if (document.getElementById("aipanel-layout-overrides")) return;
|
|
74
|
-
var style = document.createElement("style");
|
|
75
|
-
style.id = "aipanel-layout-overrides";
|
|
76
|
-
style.textContent = [
|
|
77
|
-
"[data-sidebar-collapsed] {",
|
|
78
|
-
" grid-template-columns: auto !important;",
|
|
79
|
-
"}",
|
|
80
|
-
"[data-sidebar-collapsed] > :first-child {",
|
|
81
|
-
" display: none !important;",
|
|
82
|
-
"}",
|
|
83
|
-
'[aria-label="\\u9009\\u62E9\\u5DE5\\u4F5C\\u533A"] {',
|
|
84
|
-
" display: none !important;",
|
|
85
|
-
"}",
|
|
86
|
-
].join("\\n");
|
|
87
|
-
document.head.appendChild(style);
|
|
88
|
-
} catch (e) { /* ignore */ }
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// === \u9009\u62E9\u6A21\u5F0F\u72B6\u6001 ===
|
|
92
|
-
// \u8BB0\u5F55\u5BBF\u4E3B\u662F\u5426\u5904\u4E8E"\u9009\u62E9\u5143\u7D20"\u6A21\u5F0F\uFF1A\u9009\u62E9\u6A21\u5F0F\u5F00\u542F\u65F6\uFF0Ciframe \u5185\u6355\u83B7\u7684 Esc \u5E94\u4F18\u5148
|
|
93
|
-
// \u8F6C\u53D1\u7ED9\u5BBF\u4E3B\u9000\u51FA\u9009\u62E9\u6A21\u5F0F\uFF0C\u5E76\u541E\u6389\u672C\u9875\u81EA\u8EAB\u7684\u6309\u952E\u5904\u7406\uFF08\u5982\u505C\u6B62\u751F\u6210/\u5173\u95ED\u5F39\u5C42\uFF09\u3002
|
|
94
|
-
let isInSelectMode = false;
|
|
95
|
-
|
|
96
|
-
// === \u6D88\u606F\u76D1\u542C ===
|
|
97
|
-
window.addEventListener("message", function(event) {
|
|
98
|
-
if (!event.data) return;
|
|
99
|
-
|
|
100
|
-
// \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
|
|
101
|
-
if (event.data.type === ${JSON.stringify(WIDGET_MSG.SET_THEME)}) {
|
|
102
|
-
applyTheme(event.data.theme);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u805A\u7126\u6307\u5B9A\u4F1A\u8BDD\uFF08\u65E0 deepLink \u6A21\u5F0F\uFF09\u3002
|
|
106
|
-
// dsh \u7684\u9009\u4E2D\u6001\u6301\u4E45\u5316\u4E3A JSON.stringify({ sessionId, subagentAddress? })\uFF0CSPA \u542F\u52A8\u65F6\u636E\u6B64\u6062\u590D\u3002
|
|
107
|
-
if (event.data.type === ${JSON.stringify(WIDGET_MSG.FOCUS_SESSION)}) {
|
|
108
|
-
const sessionId = event.data.sessionId;
|
|
109
|
-
if (!sessionId) return;
|
|
110
|
-
try {
|
|
111
|
-
localStorage.setItem(CURRENT_SESSION_KEY, JSON.stringify({ sessionId }));
|
|
112
|
-
} catch (e) {
|
|
113
|
-
console.warn("dsh bridge: failed to persist session selection", e);
|
|
114
|
-
}
|
|
115
|
-
// dsh SPA \u4ECE\u6301\u4E45\u5316\u9009\u4E2D\u6062\u590D\uFF0C\u5237\u65B0\u4EE5\u5207\u6362\u5230\u76EE\u6807\u4F1A\u8BDD
|
|
116
|
-
location.reload();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// \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
|
|
120
|
-
if (event.data.type === ${JSON.stringify(WIDGET_MSG.INSERT_FILE_PART)}) {
|
|
121
|
-
pushSelection(event.data.element);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u53D8\u5316\uFF08\u66F4\u65B0\u672C\u5730\u72B6\u6001\uFF0C\u4F9B\u952E\u76D8\u8F6C\u53D1\u5224\u65AD\u662F\u5426\u541E\u6389\u672C\u9875 Esc \u5904\u7406\uFF09
|
|
125
|
-
if (event.data.type === ${JSON.stringify(WIDGET_MSG.SELECT_MODE_CHANGE)}) {
|
|
126
|
-
isInSelectMode = event.data.selectMode === true;
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// === \u952E\u76D8\u4E8B\u4EF6\u8F6C\u53D1\uFF08\u9000\u51FA/\u5207\u6362\u9009\u62E9\u6A21\u5F0F\uFF09 ===
|
|
131
|
-
// \u4E0E opencode bridge \u4E00\u81F4\uFF1Aiframe \u5185\u7684 keydown \u4E0D\u4F1A\u5192\u6CE1\u5230\u5BBF\u4E3B\u6587\u6863\uFF08\u8DE8\u6587\u6863\u4E8B\u4EF6\u9694\u79BB\uFF09\uFF0C
|
|
132
|
-
// \u56E0\u6B64\u5F53\u7126\u70B9\u5728\u804A\u5929 iframe \u5185\u65F6\uFF0C\u5BBF\u4E3B App \u6536\u4E0D\u5230 Esc / Ctrl+P\uFF0C\u5BFC\u81F4\uFF1A
|
|
133
|
-
// - \u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u5F00\u542F\u65F6\u6309 Esc \u65E0\u6CD5\u9000\u51FA\uFF08\u88AB dsh \u81EA\u8EAB\u6309\u952E\u5904\u7406\u541E\u6389\u6216\u76F4\u63A5\u4E22\u5931\uFF09\uFF1B
|
|
134
|
-
// - \u5149\u6807\u5728\u804A\u5929\u8F93\u5165\u6846\u65F6\u65E0\u6CD5\u7528 Ctrl+P \u8FDB\u5165\u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u3002
|
|
135
|
-
// \u6B64\u5904\u7528\u6355\u83B7\u9636\u6BB5\u76D1\u542C Esc / Ctrl+P \u5E76\u8F6C\u53D1\u4E3A KEYDOWN \u6D88\u606F\u7ED9\u5BBF\u4E3B App\uFF08App.vue \u636E\u6B64
|
|
136
|
-
// \u9000\u51FA/\u5207\u6362\u9009\u62E9\u6A21\u5F0F\uFF09\u3002\u9009\u62E9\u6A21\u5F0F\u5F00\u542F\u65F6\u4F18\u5148\u9000\u51FA\uFF1ApreventDefault + stopPropagation\uFF0C
|
|
137
|
-
// \u907F\u514D dsh \u81EA\u8EAB\u5BF9 Esc \u7684\u5904\u7406\u62A2\u8D70\u6309\u952E\u3002
|
|
138
|
-
window.addEventListener("keydown", function(event) {
|
|
139
|
-
if (event.key === "Escape" || (event.ctrlKey && event.key.toLowerCase() === "p")) {
|
|
140
|
-
if (isInSelectMode) {
|
|
141
|
-
event.preventDefault();
|
|
142
|
-
event.stopPropagation();
|
|
143
|
-
}
|
|
144
|
-
if (window.parent !== window) {
|
|
145
|
-
window.parent.postMessage({
|
|
146
|
-
type: ${JSON.stringify(WIDGET_MSG.KEYDOWN)},
|
|
147
|
-
key: event.key,
|
|
148
|
-
ctrlKey: event.ctrlKey,
|
|
149
|
-
metaKey: event.metaKey,
|
|
150
|
-
shiftKey: event.shiftKey,
|
|
151
|
-
altKey: event.altKey
|
|
152
|
-
}, "*");
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}, true);
|
|
156
|
-
|
|
157
|
-
// === \u5C31\u7EEA\u901A\u77E5 ===
|
|
158
|
-
// \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
|
|
159
|
-
// \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
|
|
160
|
-
// aipanel:session-ready \u4E8B\u4EF6\uFF0C\u6536\u5230\u540E\u4E0A\u62A5 SESSION_READY{sessionId}\u3002
|
|
161
|
-
// \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
|
|
162
|
-
// \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
|
|
163
|
-
const SESSION_READY_EVENT = "aipanel:session-ready";
|
|
164
|
-
|
|
165
|
-
function sendSessionReady(sessionId) {
|
|
166
|
-
if (window.parent !== window) {
|
|
167
|
-
window.parent.postMessage({
|
|
168
|
-
type: ${JSON.stringify(WIDGET_MSG.SESSION_READY)},
|
|
169
|
-
sessionId
|
|
170
|
-
}, "*");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
window.addEventListener(SESSION_READY_EVENT, function(e) {
|
|
175
|
-
const sessionId = e && e.detail && e.detail.sessionId;
|
|
176
|
-
if (!sessionId) return;
|
|
177
|
-
sendSessionReady(sessionId);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// \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
|
|
181
|
-
function init() {
|
|
182
|
-
applyTheme(THEME);
|
|
183
|
-
applyLayoutOverrides();
|
|
184
|
-
}
|
|
185
|
-
if (document.readyState === "loading") {
|
|
186
|
-
document.addEventListener("DOMContentLoaded", init);
|
|
187
|
-
} else {
|
|
188
|
-
init();
|
|
189
|
-
}
|
|
190
|
-
})();
|
|
191
|
-
`;
|
|
192
|
-
}
|
|
193
|
-
export {
|
|
194
|
-
generateBridgeScript
|
|
195
|
-
};
|
package/lib/bridge-script.cjs
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
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", diagnosticsEnabled = false } = 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 DIAGNOSTICS_KEY = ${JSON.stringify(import_constants.DSH_STORAGE_KEYS.DIAGNOSTICS_ENABLED)};
|
|
32
|
-
const DIAGNOSTICS_ENABLED = ${JSON.stringify(diagnosticsEnabled)};
|
|
33
|
-
const THEME = ${JSON.stringify(theme)};
|
|
34
|
-
|
|
35
|
-
// \u8BCA\u65AD\u529F\u80FD\u5F00\u5173\uFF1A\u540C\u6B65\u5199\u5165\uFF08\u4E0D\u4F9D\u8D56 DOM\uFF09\uFF0C\u4FDD\u8BC1 dsh-client apply \u65F6\u5373\u53EF\u8BFB\u5230\u6807\u8BB0\u3002
|
|
36
|
-
// bridge \u811A\u672C\u6CE8\u5165\u4E8E <head>\uFF0Cdsh-client \u63D2\u4EF6\u5728\u9875\u9762\u811A\u672C/React \u521D\u59CB\u5316\u540E\u624D apply\uFF0C
|
|
37
|
-
// \u82E5\u7B49 DOMContentLoaded \u518D\u5199\u5219\u5B58\u5728\u65F6\u5E8F\u7ADE\u4E89\uFF0C\u89C6\u56FE\u53EF\u80FD\u6F0F\u6CE8\u518C\u3002
|
|
38
|
-
try {
|
|
39
|
-
if (DIAGNOSTICS_ENABLED) {
|
|
40
|
-
localStorage.setItem(DIAGNOSTICS_KEY, "1");
|
|
41
|
-
} else {
|
|
42
|
-
localStorage.removeItem(DIAGNOSTICS_KEY);
|
|
43
|
-
}
|
|
44
|
-
} catch (e) { /* ignore */ }
|
|
45
|
-
|
|
46
|
-
// \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
|
|
47
|
-
const INSERT_ELEMENT_EVENT = "aipanel:insert-element";
|
|
48
|
-
|
|
49
|
-
// === \u8BB0\u5F55\u6700\u8FD1\u9009\u4E2D\u5143\u7D20 ===
|
|
50
|
-
// \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
|
|
51
|
-
// aipanel:insert-element \u8BA9 dsh-client \u7ACB\u5373\u628A\u5143\u7D20\u8FFD\u52A0\u5230\u5F53\u524D\u4F1A\u8BDD\u8F93\u5165\u6846\u3002
|
|
52
|
-
function pushSelection(element) {
|
|
53
|
-
if (!element) return;
|
|
54
|
-
try {
|
|
55
|
-
var list = [];
|
|
56
|
-
var raw = localStorage.getItem(SELECTION_KEY);
|
|
57
|
-
if (raw) list = JSON.parse(raw) || [];
|
|
58
|
-
if (!Array.isArray(list)) list = [];
|
|
59
|
-
var exists = list.some(function (e) {
|
|
60
|
-
return e && e.filePath === element.filePath && e.line === element.line;
|
|
61
|
-
});
|
|
62
|
-
if (!exists) list.unshift(element);
|
|
63
|
-
if (list.length > 20) list.length = 20;
|
|
64
|
-
localStorage.setItem(SELECTION_KEY, JSON.stringify(list));
|
|
65
|
-
// \u901A\u77E5 dsh-client \u8FFD\u52A0\u5230\u5BF9\u8BDD\u6846\uFF08\u9009\u4E2D\u5373\u63D2\u5165\uFF0C\u65E0\u9700\u518D\u8F93\u5165 @\uFF09
|
|
66
|
-
window.dispatchEvent(new CustomEvent(INSERT_ELEMENT_EVENT, {
|
|
67
|
-
detail: { element: element }
|
|
68
|
-
}));
|
|
69
|
-
} catch (e) { /* ignore */ }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// === \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===
|
|
73
|
-
// dsh \u7684\u6697\u8272\u7531 body[data-ds-dark-theme] + colorScheme \u5448\u73B0\u3002
|
|
74
|
-
// \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
|
|
75
|
-
// theme \u53C2\u6570\uFF1A"light" | "dark" | "auto"\uFF08auto \u4E0D\u5E72\u9884\uFF0C\u4EA4\u7ED9 dsh \u539F\u751F\u4E3B\u9898\u5904\u7406\uFF09\u3002
|
|
76
|
-
function applyTheme(theme) {
|
|
77
|
-
if (!document.body) return;
|
|
78
|
-
if (theme === "dark") {
|
|
79
|
-
document.body.setAttribute("data-ds-dark-theme", "");
|
|
80
|
-
document.documentElement.style.colorScheme = "dark";
|
|
81
|
-
} else if (theme === "light") {
|
|
82
|
-
document.body.removeAttribute("data-ds-dark-theme");
|
|
83
|
-
document.documentElement.style.colorScheme = "light";
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// === \u5E03\u5C40\u8986\u76D6 ===
|
|
88
|
-
// \u9690\u85CF dsh \u7684\u4FA7\u8FB9\u680F\u5217\uFF0C\u907F\u514D\u4E0E AIPanel \u81EA\u5E26\u4F1A\u8BDD\u5217\u8868\u91CD\u590D\u3002
|
|
89
|
-
// \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
|
|
90
|
-
// \u4FA7\u8FB9\u680F\u5217\u662F\u6839\u7F51\u683C\u7684\u9996\u4E2A\u5B50\u5143\u7D20\u3002
|
|
91
|
-
// \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
|
|
92
|
-
// \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
|
|
93
|
-
function applyLayoutOverrides() {
|
|
94
|
-
try {
|
|
95
|
-
if (document.getElementById("aipanel-layout-overrides")) return;
|
|
96
|
-
var style = document.createElement("style");
|
|
97
|
-
style.id = "aipanel-layout-overrides";
|
|
98
|
-
style.textContent = [
|
|
99
|
-
"[data-sidebar-collapsed] {",
|
|
100
|
-
" grid-template-columns: auto !important;",
|
|
101
|
-
"}",
|
|
102
|
-
"[data-sidebar-collapsed] > :first-child {",
|
|
103
|
-
" display: none !important;",
|
|
104
|
-
"}",
|
|
105
|
-
'[aria-label="\\u9009\\u62E9\\u5DE5\\u4F5C\\u533A"] {',
|
|
106
|
-
" display: none !important;",
|
|
107
|
-
"}",
|
|
108
|
-
].join("\\n");
|
|
109
|
-
document.head.appendChild(style);
|
|
110
|
-
} catch (e) { /* ignore */ }
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// === \u9009\u62E9\u6A21\u5F0F\u72B6\u6001 ===
|
|
114
|
-
// \u8BB0\u5F55\u5BBF\u4E3B\u662F\u5426\u5904\u4E8E"\u9009\u62E9\u5143\u7D20"\u6A21\u5F0F\uFF1A\u9009\u62E9\u6A21\u5F0F\u5F00\u542F\u65F6\uFF0Ciframe \u5185\u6355\u83B7\u7684 Esc \u5E94\u4F18\u5148
|
|
115
|
-
// \u8F6C\u53D1\u7ED9\u5BBF\u4E3B\u9000\u51FA\u9009\u62E9\u6A21\u5F0F\uFF0C\u5E76\u541E\u6389\u672C\u9875\u81EA\u8EAB\u7684\u6309\u952E\u5904\u7406\uFF08\u5982\u505C\u6B62\u751F\u6210/\u5173\u95ED\u5F39\u5C42\uFF09\u3002
|
|
116
|
-
let isInSelectMode = false;
|
|
117
|
-
|
|
118
|
-
// === \u6D88\u606F\u76D1\u542C ===
|
|
119
|
-
window.addEventListener("message", function(event) {
|
|
120
|
-
if (!event.data) return;
|
|
121
|
-
|
|
122
|
-
// \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
|
|
123
|
-
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.SET_THEME)}) {
|
|
124
|
-
applyTheme(event.data.theme);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u805A\u7126\u6307\u5B9A\u4F1A\u8BDD\uFF08\u65E0 deepLink \u6A21\u5F0F\uFF09\u3002
|
|
128
|
-
// dsh \u7684\u9009\u4E2D\u6001\u6301\u4E45\u5316\u4E3A JSON.stringify({ sessionId, subagentAddress? })\uFF0CSPA \u542F\u52A8\u65F6\u636E\u6B64\u6062\u590D\u3002
|
|
129
|
-
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.FOCUS_SESSION)}) {
|
|
130
|
-
const sessionId = event.data.sessionId;
|
|
131
|
-
if (!sessionId) return;
|
|
132
|
-
try {
|
|
133
|
-
localStorage.setItem(CURRENT_SESSION_KEY, JSON.stringify({ sessionId }));
|
|
134
|
-
} catch (e) {
|
|
135
|
-
console.warn("dsh bridge: failed to persist session selection", e);
|
|
136
|
-
}
|
|
137
|
-
// dsh SPA \u4ECE\u6301\u4E45\u5316\u9009\u4E2D\u6062\u590D\uFF0C\u5237\u65B0\u4EE5\u5207\u6362\u5230\u76EE\u6807\u4F1A\u8BDD
|
|
138
|
-
location.reload();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// \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
|
|
142
|
-
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.INSERT_FILE_PART)}) {
|
|
143
|
-
pushSelection(event.data.element);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// \u6838\u5FC3\u5C42\u901A\u77E5\uFF1A\u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u53D8\u5316\uFF08\u66F4\u65B0\u672C\u5730\u72B6\u6001\uFF0C\u4F9B\u952E\u76D8\u8F6C\u53D1\u5224\u65AD\u662F\u5426\u541E\u6389\u672C\u9875 Esc \u5904\u7406\uFF09
|
|
147
|
-
if (event.data.type === ${JSON.stringify(import_core.WIDGET_MSG.SELECT_MODE_CHANGE)}) {
|
|
148
|
-
isInSelectMode = event.data.selectMode === true;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// === \u952E\u76D8\u4E8B\u4EF6\u8F6C\u53D1\uFF08\u9000\u51FA/\u5207\u6362\u9009\u62E9\u6A21\u5F0F\uFF09 ===
|
|
153
|
-
// \u4E0E opencode bridge \u4E00\u81F4\uFF1Aiframe \u5185\u7684 keydown \u4E0D\u4F1A\u5192\u6CE1\u5230\u5BBF\u4E3B\u6587\u6863\uFF08\u8DE8\u6587\u6863\u4E8B\u4EF6\u9694\u79BB\uFF09\uFF0C
|
|
154
|
-
// \u56E0\u6B64\u5F53\u7126\u70B9\u5728\u804A\u5929 iframe \u5185\u65F6\uFF0C\u5BBF\u4E3B App \u6536\u4E0D\u5230 Esc / Ctrl+P\uFF0C\u5BFC\u81F4\uFF1A
|
|
155
|
-
// - \u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u5F00\u542F\u65F6\u6309 Esc \u65E0\u6CD5\u9000\u51FA\uFF08\u88AB dsh \u81EA\u8EAB\u6309\u952E\u5904\u7406\u541E\u6389\u6216\u76F4\u63A5\u4E22\u5931\uFF09\uFF1B
|
|
156
|
-
// - \u5149\u6807\u5728\u804A\u5929\u8F93\u5165\u6846\u65F6\u65E0\u6CD5\u7528 Ctrl+P \u8FDB\u5165\u9009\u62E9\u5143\u7D20\u6A21\u5F0F\u3002
|
|
157
|
-
// \u6B64\u5904\u7528\u6355\u83B7\u9636\u6BB5\u76D1\u542C Esc / Ctrl+P \u5E76\u8F6C\u53D1\u4E3A KEYDOWN \u6D88\u606F\u7ED9\u5BBF\u4E3B App\uFF08App.vue \u636E\u6B64
|
|
158
|
-
// \u9000\u51FA/\u5207\u6362\u9009\u62E9\u6A21\u5F0F\uFF09\u3002\u9009\u62E9\u6A21\u5F0F\u5F00\u542F\u65F6\u4F18\u5148\u9000\u51FA\uFF1ApreventDefault + stopPropagation\uFF0C
|
|
159
|
-
// \u907F\u514D dsh \u81EA\u8EAB\u5BF9 Esc \u7684\u5904\u7406\u62A2\u8D70\u6309\u952E\u3002
|
|
160
|
-
window.addEventListener("keydown", function(event) {
|
|
161
|
-
if (event.key === "Escape" || (event.ctrlKey && event.key.toLowerCase() === "p")) {
|
|
162
|
-
if (isInSelectMode) {
|
|
163
|
-
event.preventDefault();
|
|
164
|
-
event.stopPropagation();
|
|
165
|
-
}
|
|
166
|
-
if (window.parent !== window) {
|
|
167
|
-
window.parent.postMessage({
|
|
168
|
-
type: ${JSON.stringify(import_core.WIDGET_MSG.KEYDOWN)},
|
|
169
|
-
key: event.key,
|
|
170
|
-
ctrlKey: event.ctrlKey,
|
|
171
|
-
metaKey: event.metaKey,
|
|
172
|
-
shiftKey: event.shiftKey,
|
|
173
|
-
altKey: event.altKey
|
|
174
|
-
}, "*");
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}, true);
|
|
178
|
-
|
|
179
|
-
// === \u5C31\u7EEA\u901A\u77E5 ===
|
|
180
|
-
// \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
|
|
181
|
-
// \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
|
|
182
|
-
// aipanel:session-ready \u4E8B\u4EF6\uFF0C\u6536\u5230\u540E\u4E0A\u62A5 SESSION_READY{sessionId}\u3002
|
|
183
|
-
// \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
|
|
184
|
-
// \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
|
|
185
|
-
const SESSION_READY_EVENT = "aipanel:session-ready";
|
|
186
|
-
|
|
187
|
-
function sendSessionReady(sessionId) {
|
|
188
|
-
if (window.parent !== window) {
|
|
189
|
-
window.parent.postMessage({
|
|
190
|
-
type: ${JSON.stringify(import_core.WIDGET_MSG.SESSION_READY)},
|
|
191
|
-
sessionId
|
|
192
|
-
}, "*");
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
window.addEventListener(SESSION_READY_EVENT, function(e) {
|
|
197
|
-
const sessionId = e && e.detail && e.detail.sessionId;
|
|
198
|
-
if (!sessionId) return;
|
|
199
|
-
sendSessionReady(sessionId);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// \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
|
|
203
|
-
function init() {
|
|
204
|
-
applyTheme(THEME);
|
|
205
|
-
applyLayoutOverrides();
|
|
206
|
-
}
|
|
207
|
-
if (document.readyState === "loading") {
|
|
208
|
-
document.addEventListener("DOMContentLoaded", init);
|
|
209
|
-
} else {
|
|
210
|
-
init();
|
|
211
|
-
}
|
|
212
|
-
})();
|
|
213
|
-
`;
|
|
214
|
-
}
|
|
215
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
216
|
-
0 && (module.exports = {
|
|
217
|
-
generateBridgeScript
|
|
218
|
-
});
|
package/lib/bridge-script.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface BridgeScriptOptions {
|
|
2
|
-
/** 主题模式 */
|
|
3
|
-
theme?: "light" | "dark" | "auto";
|
|
4
|
-
/** 诊断功能开关(provider option enableDiagnostics;写入 localStorage 供 dsh-client 决定是否注册诊断视图) */
|
|
5
|
-
diagnosticsEnabled?: boolean;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* 生成 PostMessage Bridge 脚本。
|
|
9
|
-
* dsh 无正式"切换会话"URL 钩子,选中态持久化在 localStorage(CURRENT_SESSION),
|
|
10
|
-
* 且 SPA 启动时会据此恢复选中——因此桥接采用"写入选中 + 刷新 iframe"的策略。
|
|
11
|
-
* 若 dsh 后续暴露正式切会话接口,可替换以下 FOCUS_SESSION 分支。
|
|
12
|
-
*/
|
|
13
|
-
export declare function generateBridgeScript(options?: BridgeScriptOptions): string;
|