@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 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、桥接脚本、CLI 环境检查。
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)是否已被同步到 dsh profile;false 时停用该行,避免 fail-loud */
7
+ /** host 插件(@aipanel/dsh-plugin)是否已同步到 dsh profile;false 时停用该行,避免 fail-loud */
6
8
  pluginAvailable?: boolean;
7
- /** client 插件(@aipanel/dsh-client)是否可被 dsh 解析(provider 已同步到 dsh profile);false 时停用该行,避免 fail-loud */
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、桥接脚本,向核心层暴露 WebProvider 契约。
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
- private bridgeOptions;
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
- /** 代理注入到 HTML 的桥接脚本(Provider 资产) */
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
- __publicField(this, "bridgeOptions", {});
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
- /** 代理注入到 HTML 的桥接脚本(Provider 资产) */
43
- get bridgeScript() {
44
- return generateBridgeScript(this.bridgeOptions);
45
- }
46
- /** 初始化桥接配置(主题、诊断开关等) */
42
+ /** 记录 AIPanel 侧主题偏好(applyConfig start 前调用;start 时随 client 插件 config 下发) */
47
43
  applyConfig(config) {
48
- this.bridgeOptions = {
49
- theme: config.theme ?? "auto",
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 & auto-diagnose disabled", {
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
  });
@@ -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、桥接脚本、CLI 环境检查。
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)是否已被同步到 dsh profile;false 时停用该行,避免 fail-loud */
7
+ /** host 插件(@aipanel/dsh-plugin)是否已同步到 dsh profile;false 时停用该行,避免 fail-loud */
6
8
  pluginAvailable?: boolean;
7
- /** client 插件(@aipanel/dsh-client)是否可被 dsh 解析(provider 已同步到 dsh profile);false 时停用该行,避免 fail-loud */
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
- __publicField(this, "bridgeOptions", {});
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
- /** 代理注入到 HTML 的桥接脚本(Provider 资产) */
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
- this.bridgeOptions = {
59
- theme: config.theme ?? "auto",
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 & auto-diagnose disabled", {
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、桥接脚本,向核心层暴露 WebProvider 契约。
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
- private bridgeOptions;
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
- /** 代理注入到 HTML 的桥接脚本(Provider 资产) */
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.8",
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.8"
25
+ "@aipanel/core": "1.2.9"
26
26
  },
27
27
  "devDependencies": {
28
28
  "esbuild": "^0.25.0"
@@ -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;
@@ -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
- };
@@ -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
- });
@@ -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;