@aipanel/core 1.2.8 → 1.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/es/{logger.d.ts → client/logger.d.ts} +1 -1
  2. package/es/{logger.mjs → client/logger.mjs} +4 -10
  3. package/es/client/storage.d.ts +15 -0
  4. package/es/client/storage.mjs +33 -0
  5. package/es/client/theme.d.ts +15 -0
  6. package/es/client/theme.mjs +11 -0
  7. package/es/client.d.ts +3 -0
  8. package/es/client.mjs +3 -0
  9. package/es/{constants.d.ts → common/constants.d.ts} +34 -6
  10. package/es/{constants.mjs → common/constants.mjs} +31 -8
  11. package/{lib → es/common}/options.d.ts +40 -0
  12. package/{lib → es/common}/types.d.ts +36 -11
  13. package/es/{utils.d.ts → common/utils.d.ts} +26 -3
  14. package/es/{utils.mjs → common/utils.mjs} +42 -1
  15. package/es/index.d.ts +6 -7
  16. package/es/index.mjs +6 -7
  17. package/es/node/diagnostics.d.ts +5 -0
  18. package/es/node/diagnostics.mjs +26 -4
  19. package/es/{file-log-watcher.mjs → node/file-log-watcher.mjs} +1 -1
  20. package/{lib → es/node}/node-logger.d.ts +1 -1
  21. package/es/{node-logger.mjs → node/node-logger.mjs} +4 -17
  22. package/es/node/node-utils.d.ts +69 -0
  23. package/es/node/node-utils.mjs +291 -0
  24. package/es/node.d.ts +6 -6
  25. package/es/node.mjs +6 -6
  26. package/lib/{logger.cjs → client/logger.cjs} +3 -10
  27. package/lib/{logger.d.ts → client/logger.d.ts} +1 -1
  28. package/lib/client/storage.cjs +58 -0
  29. package/lib/client/storage.d.ts +15 -0
  30. package/lib/client/theme.cjs +35 -0
  31. package/lib/client/theme.d.ts +15 -0
  32. package/lib/client.cjs +25 -0
  33. package/lib/client.d.ts +3 -0
  34. package/lib/{constants.cjs → common/constants.cjs} +38 -12
  35. package/lib/{constants.d.ts → common/constants.d.ts} +34 -6
  36. package/{es → lib/common}/options.d.ts +40 -0
  37. package/{es → lib/common}/types.d.ts +36 -11
  38. package/lib/{utils.cjs → common/utils.cjs} +47 -2
  39. package/lib/{utils.d.ts → common/utils.d.ts} +26 -3
  40. package/lib/index.cjs +12 -14
  41. package/lib/index.d.ts +6 -7
  42. package/lib/node/diagnostics.cjs +27 -4
  43. package/lib/node/diagnostics.d.ts +5 -0
  44. package/lib/{file-log-watcher.cjs → node/file-log-watcher.cjs} +1 -1
  45. package/lib/{node-logger.cjs → node/node-logger.cjs} +4 -19
  46. package/{es → lib/node}/node-logger.d.ts +1 -1
  47. package/lib/node/node-utils.cjs +329 -0
  48. package/lib/node/node-utils.d.ts +69 -0
  49. package/lib/node.cjs +12 -12
  50. package/lib/node.d.ts +6 -6
  51. package/package.json +6 -1
  52. package/es/node-utils.d.ts +0 -28
  53. package/es/node-utils.mjs +0 -56
  54. package/lib/node-utils.cjs +0 -93
  55. package/lib/node-utils.d.ts +0 -28
  56. /package/es/{logger-core.d.ts → common/logger-core.d.ts} +0 -0
  57. /package/es/{logger-core.mjs → common/logger-core.mjs} +0 -0
  58. /package/es/{options.mjs → common/options.mjs} +0 -0
  59. /package/es/{provider.d.ts → common/provider.d.ts} +0 -0
  60. /package/es/{provider.mjs → common/provider.mjs} +0 -0
  61. /package/es/{types.mjs → common/types.mjs} +0 -0
  62. /package/es/{file-log-watcher.d.ts → node/file-log-watcher.d.ts} +0 -0
  63. /package/es/{process-logger.d.ts → node/process-logger.d.ts} +0 -0
  64. /package/es/{process-logger.mjs → node/process-logger.mjs} +0 -0
  65. /package/lib/{logger-core.cjs → common/logger-core.cjs} +0 -0
  66. /package/lib/{logger-core.d.ts → common/logger-core.d.ts} +0 -0
  67. /package/lib/{options.cjs → common/options.cjs} +0 -0
  68. /package/lib/{provider.cjs → common/provider.cjs} +0 -0
  69. /package/lib/{provider.d.ts → common/provider.d.ts} +0 -0
  70. /package/lib/{types.cjs → common/types.cjs} +0 -0
  71. /package/lib/{file-log-watcher.d.ts → node/file-log-watcher.d.ts} +0 -0
  72. /package/lib/{process-logger.cjs → node/process-logger.cjs} +0 -0
  73. /package/lib/{process-logger.d.ts → node/process-logger.d.ts} +0 -0
@@ -30,8 +30,6 @@ __export(constants_exports, {
30
30
  DEFAULT_PROXY_PORT: () => DEFAULT_PROXY_PORT,
31
31
  DEFAULT_RETRIES: () => DEFAULT_RETRIES,
32
32
  DEFAULT_WEB_PORT: () => DEFAULT_WEB_PORT,
33
- ENV_VSCODE_MODE: () => ENV_VSCODE_MODE,
34
- ENV_VSCODE_PORT: () => ENV_VSCODE_PORT,
35
33
  EXT_BROADCAST: () => EXT_BROADCAST,
36
34
  EXT_MSG: () => EXT_MSG,
37
35
  HOST_EVENTS_API_PATH: () => HOST_EVENTS_API_PATH,
@@ -42,7 +40,9 @@ __export(constants_exports, {
42
40
  MAX_PORT_TRIES: () => MAX_PORT_TRIES,
43
41
  MAX_TEXT_LENGTH: () => MAX_TEXT_LENGTH,
44
42
  MCP_API_PATH: () => MCP_API_PATH,
43
+ MUTATING_TOOLS: () => MUTATING_TOOLS,
45
44
  NOTIFICATION_DURATION: () => NOTIFICATION_DURATION,
45
+ OPENCODE_ENV: () => OPENCODE_ENV,
46
46
  PAGE_CONTEXT_MARKER: () => PAGE_CONTEXT_MARKER,
47
47
  PAGE_CONTEXT_MAX_TEXT_LENGTH: () => PAGE_CONTEXT_MAX_TEXT_LENGTH,
48
48
  RETRY_DELAY: () => RETRY_DELAY,
@@ -51,16 +51,19 @@ __export(constants_exports, {
51
51
  SERVER_START_TIMEOUT: () => SERVER_START_TIMEOUT,
52
52
  SERVER_SYNC_INTERVAL: () => SERVER_SYNC_INTERVAL,
53
53
  SESSIONS_API_PATH: () => SESSIONS_API_PATH,
54
+ SESSION_ID_KEY: () => SESSION_ID_KEY,
54
55
  SEVERITY_ERROR: () => SEVERITY_ERROR,
55
56
  SEVERITY_WARN: () => SEVERITY_WARN,
56
57
  SSE_EVENTS_PATH: () => SSE_EVENTS_PATH,
58
+ SSE_EVENT_TYPES: () => SSE_EVENT_TYPES,
57
59
  START_API_PATH: () => START_API_PATH,
58
- VSCODE_EXTENSION_PORT: () => VSCODE_EXTENSION_PORT,
59
60
  VUE_DEVTOOLS_ACTIONS: () => VUE_DEVTOOLS_ACTIONS,
61
+ VUE_DEVTOOLS_API_PATH: () => VUE_DEVTOOLS_API_PATH,
60
62
  WARMUP_API_PATH: () => WARMUP_API_PATH,
61
63
  WIDGET_MSG: () => WIDGET_MSG,
62
64
  WIDGET_SCRIPT_PATH: () => WIDGET_SCRIPT_PATH,
63
- WIDGET_STYLE_PATH: () => WIDGET_STYLE_PATH
65
+ WIDGET_STYLE_PATH: () => WIDGET_STYLE_PATH,
66
+ WIDGET_THEME_MODES: () => WIDGET_THEME_MODES
64
67
  });
65
68
  module.exports = __toCommonJS(constants_exports);
66
69
  const DEFAULT_HOSTNAME = "127.0.0.1";
@@ -87,6 +90,7 @@ const AUTO_OPEN_DELAY = 1e3;
87
90
  const NOTIFICATION_DURATION = 3e3;
88
91
  const INIT_MARKER = "__AIPANEL_INITIALIZED__";
89
92
  const SELECTED_ELEMENTS_KEY = "__aipanel_selected_elements__";
93
+ const SESSION_ID_KEY = "_aipanel_pk";
90
94
  const AIPANEL_CACHE_DIR = "node_modules/.cache/aipanel";
91
95
  const CHROME_DEVTOOLS_PORT = 9222;
92
96
  const CHROME_DEVTOOLS_CHECK_TIMEOUT = 2e3;
@@ -103,7 +107,9 @@ const EXT_MSG = {
103
107
  REQUEST_PAGE_CONTEXT: "REQUEST_PAGE_CONTEXT",
104
108
  SELECTION_START: "SELECTION_START",
105
109
  SELECTION_STOP: "SELECTION_STOP",
106
- CS_QUERY_WINDOW: "__CS_QUERY_WINDOW__"
110
+ CS_QUERY_WINDOW: "__CS_QUERY_WINDOW__",
111
+ /** Side Panel → Background:立即轮询一次并回传当前服务信息 */
112
+ FORCE_POLL: "FORCE_POLL"
107
113
  };
108
114
  const WIDGET_MSG = {
109
115
  READY: "AIPANEL_READY",
@@ -128,15 +134,13 @@ const WARMUP_API_PATH = "/__aipanel_warmup__";
128
134
  const BRIDGE_SCRIPT_PATH = "/__aipanel_bridge__.js";
129
135
  const LOGS_API_PATH = "/__aipanel_process_logs__";
130
136
  const WIDGET_STYLE_PATH = "/__aipanel_widget__.css";
137
+ const VUE_DEVTOOLS_API_PATH = "/__aipanel_vue_devtools__";
131
138
  const MAX_TEXT_LENGTH = 100;
132
139
  const CONTEXT_MARKER = "[\u5143\u7D20\u4E0A\u4E0B\u6587]";
133
140
  const PAGE_CONTEXT_MARKER = "__AIPANEL_CONTEXT__";
134
141
  const PAGE_CONTEXT_MAX_TEXT_LENGTH = 1e4;
135
142
  const SEVERITY_ERROR = 1;
136
143
  const SEVERITY_WARN = 2;
137
- const VSCODE_EXTENSION_PORT = 51939;
138
- const ENV_VSCODE_MODE = "AIPANEL_VSCODE_MODE";
139
- const ENV_VSCODE_PORT = "AIPANEL_VSCODE_PORT";
140
144
  const VUE_DEVTOOLS_ACTIONS = {
141
145
  GET_COMPONENT_TREE: "getComponentTree",
142
146
  GET_COMPONENT_STATE: "getComponentState",
@@ -145,6 +149,25 @@ const VUE_DEVTOOLS_ACTIONS = {
145
149
  TOGGLE_APP: "toggleApp",
146
150
  GET_ROUTER_INFO: "getRouterInfo"
147
151
  };
152
+ const MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "apply_patch"]);
153
+ const WIDGET_THEME_MODES = ["auto", "light", "dark"];
154
+ const OPENCODE_ENV = {
155
+ CONFIG_DIR: "OPENCODE_CONFIG_DIR",
156
+ CONTEXT_API_URL: "OPENCODE_CONTEXT_API_URL",
157
+ VITE_LOGS_API_URL: "OPENCODE_VITE_LOGS_API_URL",
158
+ LOG_FILES_JSON: "OPENCODE_LOG_FILES_JSON",
159
+ VERBOSE: "OPENCODE_VERBOSE",
160
+ ENABLE_LINT: "OPENCODE_ENABLE_LINT",
161
+ VUE_DEVTOOLS_API_URL: "OPENCODE_VUE_DEVTOOLS_API_URL",
162
+ WORKSPACE: "OPENCODE_WORKSPACE"
163
+ };
164
+ const SSE_EVENT_TYPES = {
165
+ CONNECTED: "CONNECTED",
166
+ STATUS_SYNC: "STATUS_SYNC",
167
+ TASK_UPDATE: "TASK_UPDATE",
168
+ SESSION_EVENT: "SESSION_EVENT",
169
+ CLEAR_ELEMENTS: "CLEAR_ELEMENTS"
170
+ };
148
171
  // Annotate the CommonJS export names for ESM import in node:
149
172
  0 && (module.exports = {
150
173
  AIPANEL_CACHE_DIR,
@@ -160,8 +183,6 @@ const VUE_DEVTOOLS_ACTIONS = {
160
183
  DEFAULT_PROXY_PORT,
161
184
  DEFAULT_RETRIES,
162
185
  DEFAULT_WEB_PORT,
163
- ENV_VSCODE_MODE,
164
- ENV_VSCODE_PORT,
165
186
  EXT_BROADCAST,
166
187
  EXT_MSG,
167
188
  HOST_EVENTS_API_PATH,
@@ -172,7 +193,9 @@ const VUE_DEVTOOLS_ACTIONS = {
172
193
  MAX_PORT_TRIES,
173
194
  MAX_TEXT_LENGTH,
174
195
  MCP_API_PATH,
196
+ MUTATING_TOOLS,
175
197
  NOTIFICATION_DURATION,
198
+ OPENCODE_ENV,
176
199
  PAGE_CONTEXT_MARKER,
177
200
  PAGE_CONTEXT_MAX_TEXT_LENGTH,
178
201
  RETRY_DELAY,
@@ -181,14 +204,17 @@ const VUE_DEVTOOLS_ACTIONS = {
181
204
  SERVER_START_TIMEOUT,
182
205
  SERVER_SYNC_INTERVAL,
183
206
  SESSIONS_API_PATH,
207
+ SESSION_ID_KEY,
184
208
  SEVERITY_ERROR,
185
209
  SEVERITY_WARN,
186
210
  SSE_EVENTS_PATH,
211
+ SSE_EVENT_TYPES,
187
212
  START_API_PATH,
188
- VSCODE_EXTENSION_PORT,
189
213
  VUE_DEVTOOLS_ACTIONS,
214
+ VUE_DEVTOOLS_API_PATH,
190
215
  WARMUP_API_PATH,
191
216
  WIDGET_MSG,
192
217
  WIDGET_SCRIPT_PATH,
193
- WIDGET_STYLE_PATH
218
+ WIDGET_STYLE_PATH,
219
+ WIDGET_THEME_MODES
194
220
  });
@@ -56,6 +56,8 @@ export declare const NOTIFICATION_DURATION = 3000;
56
56
  export declare const INIT_MARKER = "__AIPANEL_INITIALIZED__";
57
57
  /** 选中元素存储键 */
58
58
  export declare const SELECTED_ELEMENTS_KEY = "__aipanel_selected_elements__";
59
+ /** 页面会话标识键(sessionStorage,跨导航标识同一 Tab 的页面上下文) */
60
+ export declare const SESSION_ID_KEY = "_aipanel_pk";
59
61
  /** ==================== 缓存目录 ==================== */
60
62
  /**
61
63
  * AIPanel 项目级资源/缓存目录(相对于项目根目录,各 Provider 统一使用)。
@@ -83,6 +85,8 @@ export declare const EXT_MSG: {
83
85
  readonly SELECTION_START: "SELECTION_START";
84
86
  readonly SELECTION_STOP: "SELECTION_STOP";
85
87
  readonly CS_QUERY_WINDOW: "__CS_QUERY_WINDOW__";
88
+ /** Side Panel → Background:立即轮询一次并回传当前服务信息 */
89
+ readonly FORCE_POLL: "FORCE_POLL";
86
90
  readonly PAGE_CONTEXT: "PAGE_CONTEXT";
87
91
  readonly THEME_CHANGE: "THEME_CHANGE";
88
92
  readonly SERVICE_APPEARED: "SERVICE_APPEARED";
@@ -118,6 +122,8 @@ export declare const BRIDGE_SCRIPT_PATH = "/__aipanel_bridge__.js";
118
122
  export declare const LOGS_API_PATH = "/__aipanel_process_logs__";
119
123
  /** Widget 样式路径 */
120
124
  export declare const WIDGET_STYLE_PATH = "/__aipanel_widget__.css";
125
+ /** Vue DevTools API 路径 */
126
+ export declare const VUE_DEVTOOLS_API_PATH = "/__aipanel_vue_devtools__";
121
127
  /** ==================== 文本处理 ==================== */
122
128
  /** 元素文本最大显示长度 */
123
129
  export declare const MAX_TEXT_LENGTH = 100;
@@ -134,12 +140,6 @@ export declare const PAGE_CONTEXT_MAX_TEXT_LENGTH = 10000;
134
140
  */
135
141
  export declare const SEVERITY_ERROR = 1;
136
142
  export declare const SEVERITY_WARN = 2;
137
- /** ==================== VS Code 扩展桥接 ==================== */
138
- /** VS Code 扩展 HTTP 服务端口(vscode-extension ↔ provider 通信协议) */
139
- export declare const VSCODE_EXTENSION_PORT = 51939;
140
- /** VS Code 扩展相关环境变量名 */
141
- export declare const ENV_VSCODE_MODE = "AIPANEL_VSCODE_MODE";
142
- export declare const ENV_VSCODE_PORT = "AIPANEL_VSCODE_PORT";
143
143
  /** ==================== Vue DevTools API ==================== */
144
144
  /** Vue DevTools API action 名称 */
145
145
  export declare const VUE_DEVTOOLS_ACTIONS: {
@@ -151,3 +151,31 @@ export declare const VUE_DEVTOOLS_ACTIONS: {
151
151
  readonly GET_ROUTER_INFO: "getRouterInfo";
152
152
  };
153
153
  export type VueDevtoolsAction = (typeof VUE_DEVTOOLS_ACTIONS)[keyof typeof VUE_DEVTOOLS_ACTIONS];
154
+ /** ==================== 写类工具名单 ==================== */
155
+ /** 会修改文件的工具名(host 插件与编辑后自动诊断共用的单一来源) */
156
+ export declare const MUTATING_TOOLS: ReadonlySet<string>;
157
+ /** ==================== 挂件主题 ==================== */
158
+ /** 挂件主题可选值(对应 AIPanelWidgetTheme) */
159
+ export declare const WIDGET_THEME_MODES: readonly ["auto", "light", "dark"];
160
+ /** ==================== OpenCode 环境变量名 ==================== */
161
+ /** OpenCode 相关环境变量名(opencode provider 写、es/plugins 与 dsh-plugin 读,统一引用防止字面量漂移) */
162
+ export declare const OPENCODE_ENV: {
163
+ readonly CONFIG_DIR: "OPENCODE_CONFIG_DIR";
164
+ readonly CONTEXT_API_URL: "OPENCODE_CONTEXT_API_URL";
165
+ readonly VITE_LOGS_API_URL: "OPENCODE_VITE_LOGS_API_URL";
166
+ readonly LOG_FILES_JSON: "OPENCODE_LOG_FILES_JSON";
167
+ readonly VERBOSE: "OPENCODE_VERBOSE";
168
+ readonly ENABLE_LINT: "OPENCODE_ENABLE_LINT";
169
+ readonly VUE_DEVTOOLS_API_URL: "OPENCODE_VUE_DEVTOOLS_API_URL";
170
+ readonly WORKSPACE: "OPENCODE_WORKSPACE";
171
+ };
172
+ /** ==================== SSE 事件流消息类型 ==================== */
173
+ /** 服务端 → 客户端 SSE 信封 type 字段(vite endpoints 写、client useServerSSE 读) */
174
+ export declare const SSE_EVENT_TYPES: {
175
+ readonly CONNECTED: "CONNECTED";
176
+ readonly STATUS_SYNC: "STATUS_SYNC";
177
+ readonly TASK_UPDATE: "TASK_UPDATE";
178
+ readonly SESSION_EVENT: "SESSION_EVENT";
179
+ readonly CLEAR_ELEMENTS: "CLEAR_ELEMENTS";
180
+ };
181
+ export type SSEEventType = (typeof SSE_EVENT_TYPES)[keyof typeof SSE_EVENT_TYPES];
@@ -3,6 +3,44 @@
3
3
  * Provider 专属配置通过泛型 P 注入,核心层不感知具体 schema。
4
4
  */
5
5
  import type { DisplayMode, LogFileConfig, SplitModeOptions } from "./types";
6
+ /**
7
+ * chrome-devtools-mcp 进程的用户透传配置。
8
+ * 只允许“追加”,不允许覆盖核心受保护参数(由 McpProxy 统一过滤)。
9
+ */
10
+ export interface ChromeMcpOptions {
11
+ /**
12
+ * 追加的 CLI 参数(先于核心参数注入)。
13
+ * 与核心受保护项(auto-connect / usage-statistics / performance-crux /
14
+ * page-id-routing 及其反义)冲突的参数会被剔除并告警。
15
+ */
16
+ args?: string[];
17
+ /** 透传给 chrome-devtools-mcp 进程的额外环境变量(合并到 process.env 之上) */
18
+ env?: Record<string, string>;
19
+ /** 项目边界策略(默认缺失 = 现状行为) */
20
+ project?: ChromeProjectOptions;
21
+ }
22
+ /**
23
+ * 项目边界策略(chrome-devtools-mcp 工具层的“本项目内操作”可配选项,默认均为现状)。
24
+ * 所有项只会收窄/放宽我们的边界判定,不改变白名单的权威性。
25
+ */
26
+ export interface ChromeProjectOptions {
27
+ /**
28
+ * 白名单条目:除自动项目页外,可开启/可见/可操作的额外页面。每条三种写法:
29
+ * - 精确 origin:"https://example.com"(前缀匹配该 origin 下任意路径)
30
+ * - glob 通配符:"https://*.example.com/**"(picomatch,* 不跨 /,放开路径需 /**)
31
+ * - 正则字面量:"/^https:\\/\\/app\\.example\\.com\\//"(以 / 起止、可带 flags,对完整 URL 匹配)
32
+ */
33
+ allowOrigins?: string[];
34
+ /** 是否允许扩展页(chrome-extension://)纳入可操作页面;启用时自动注入 --experimental-include-all-pages */
35
+ includeExtensionPages?: boolean;
36
+ /** 工具面选择:在默认白名单上按名字调整 */
37
+ tools?: {
38
+ /** 从默认白名单隐藏(如 ["upload_file"]) */
39
+ deny?: string[];
40
+ /** 仅可开启官方二级目录中的工具(如 click_at);非目录名将被忽略并告警 */
41
+ extra?: string[];
42
+ };
43
+ }
6
44
  /**
7
45
  * 插件配置选项
8
46
  * @typeParam P - 当前 Provider 的专属配置段(schema 由具体 Provider 声明)
@@ -34,6 +72,8 @@ export interface PluginOptions<P extends Record<string, unknown> = Record<string
34
72
  warmupChromeMcp?: boolean;
35
73
  /** Chrome DevTools Protocol 端口,默认 9222 */
36
74
  chromeDevtoolsPort?: number;
75
+ /** chrome-devtools-mcp 进程透传配置(只可追加,不可覆盖核心受保护参数) */
76
+ chromeMcp?: ChromeMcpOptions;
37
77
  /** 展示模式,默认 'bubble' */
38
78
  displayMode?: DisplayMode;
39
79
  /** 分屏模式配置 */
@@ -2,6 +2,7 @@
2
2
  * 通用类型(Provider 无关)
3
3
  * Provider 专属类型已下沉至 @aipanel/provider-opencode。
4
4
  */
5
+ import type { SessionStatus } from "./provider";
5
6
  /**
6
7
  * 展示模式类型
7
8
  */
@@ -84,6 +85,8 @@ export interface SelectedElement {
84
85
  innerText: string;
85
86
  /** 元素描述(标签名+选择器) */
86
87
  description?: string;
88
+ /** 用户选中节点时的页面 URL(AIPanel 附加;host 端上下文注入用) */
89
+ previewPageUrl?: string;
87
90
  }
88
91
  /**
89
92
  * 页面上下文数据
@@ -121,9 +124,9 @@ export type AIPanelWidgetTheme = "light" | "dark" | "auto";
121
124
  */
122
125
  export type ServiceStatus = "idle" | "starting" | "ready" | "partial" | "failed";
123
126
  /**
124
- * Session 状态类型
127
+ * Session 状态类型(别名:以 ./provider 的 SessionStatus 为单一来源)
125
128
  */
126
- export type AIPanelSessionStatusType = "idle" | "running" | "streaming" | "completed";
129
+ export type AIPanelSessionStatusType = SessionStatus;
127
130
  /**
128
131
  * Session 思考状态
129
132
  */
@@ -144,16 +147,22 @@ export interface AIPanelWidgetSession {
144
147
  url?: string;
145
148
  }
146
149
  /**
147
- * 挂件选中的元素
150
+ * 挂件选中的元素(别名:与 host 端 SelectedElement 同构,单一来源为本文件上方的 SelectedElement)
148
151
  */
149
- export interface AIPanelSelectedElement {
150
- /** 节点唯一 id(与 SelectedElement.id 同源,`@节点[n<id>]` 标记与上下文注入共用) */
151
- id?: string;
152
- filePath: string | null;
153
- line: number | null;
154
- column: number | null;
155
- innerText: string;
156
- description?: string;
152
+ export type AIPanelSelectedElement = SelectedElement;
153
+ /**
154
+ * 单条代码诊断(1-based 行列坐标)——AIPanel 诊断工具(run_diagnostics 等)的
155
+ * canonical 持久化/展示共用协议:宿主插件写 tool/result.meta,client 插件据此渲染卡片。
156
+ */
157
+ export interface AIPanelDiagnosticEntry {
158
+ /** 所属文件(绝对路径) */
159
+ file: string;
160
+ /** 1-based 行号 */
161
+ line: number;
162
+ /** 1-based 列号 */
163
+ column: number;
164
+ severity: "error" | "warning";
165
+ message: string;
157
166
  }
158
167
  /**
159
168
  * 删除选中节点的载荷
@@ -185,6 +194,22 @@ export interface AIPanelSelectedElementItem {
185
194
  panelFileText: string;
186
195
  element: AIPanelSelectedElement;
187
196
  }
197
+ /**
198
+ * 服务实例信息(Chrome 扩展 Background ↔ Side Panel 共享的服务载荷;
199
+ * 由 widget 的 SERVICE_INFO 上报与 vite start 端点探测归一化而来)。
200
+ */
201
+ export interface AIPanelServiceInfo {
202
+ /** 代理端口 */
203
+ proxyPort: number;
204
+ /** Vite 开发服务端口(字符串;可能来自 widget 上报或探测 origin) */
205
+ vitePort: string;
206
+ /** 项目根目录 */
207
+ projectRoot: string;
208
+ /** 服务实例唯一 id(多实例隔离) */
209
+ serviceInstanceId: string;
210
+ /** 是否开启 verbose(可选) */
211
+ verbose?: boolean;
212
+ }
188
213
  /**
189
214
  * 挂件组件 Props
190
215
  */
@@ -21,10 +21,15 @@ __export(utils_exports, {
21
21
  base64Encode: () => base64Encode,
22
22
  ensureNodeId: () => ensureNodeId,
23
23
  extractTextFromResponse: () => extractTextFromResponse,
24
+ parseNodeMentions: () => parseNodeMentions,
24
25
  sleep: () => sleep,
25
- truncate: () => truncate
26
+ toNodeMention: () => toNodeMention,
27
+ truncate: () => truncate,
28
+ widgetEnvelope: () => widgetEnvelope,
29
+ withRetries: () => withRetries
26
30
  });
27
31
  module.exports = __toCommonJS(utils_exports);
32
+ var import_constants = require("./constants.cjs");
28
33
  function ensureNodeId(element) {
29
34
  if (element.id) return element.id;
30
35
  const random = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID().replace(/-/g, "").slice(0, 8) : Math.random().toString(36).slice(2, 10);
@@ -77,12 +82,52 @@ function extractTextFromResponse(data) {
77
82
  }
78
83
  return null;
79
84
  }
85
+ const NODE_MENTION_RE = /@节点\[(n[0-9a-z]+)\]/g;
86
+ function toNodeMention(id) {
87
+ return `@\u8282\u70B9[${id}]`;
88
+ }
89
+ function parseNodeMentions(text) {
90
+ const out = [];
91
+ const seen = /* @__PURE__ */ new Set();
92
+ for (const m of text.matchAll(NODE_MENTION_RE)) {
93
+ const id = m[1];
94
+ if (!seen.has(id)) {
95
+ seen.add(id);
96
+ out.push(id);
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ function widgetEnvelope(type, data) {
102
+ return { type, ...data };
103
+ }
104
+ async function withRetries(fn, options = {}) {
105
+ const attempts = options.attempts ?? import_constants.DEFAULT_RETRIES;
106
+ const delayMs = options.delayMs ?? import_constants.RETRY_DELAY;
107
+ let lastError;
108
+ for (let i = 0; i < attempts; i++) {
109
+ try {
110
+ return await fn(i);
111
+ } catch (e) {
112
+ lastError = e;
113
+ if (i < attempts - 1) {
114
+ options.onRetry?.(i + 1, e);
115
+ if (delayMs > 0) await sleep(delayMs);
116
+ }
117
+ }
118
+ }
119
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
120
+ }
80
121
  // Annotate the CommonJS export names for ESM import in node:
81
122
  0 && (module.exports = {
82
123
  base64Decode,
83
124
  base64Encode,
84
125
  ensureNodeId,
85
126
  extractTextFromResponse,
127
+ parseNodeMentions,
86
128
  sleep,
87
- truncate
129
+ toNodeMention,
130
+ truncate,
131
+ widgetEnvelope,
132
+ withRetries
88
133
  });
@@ -1,6 +1,3 @@
1
- /**
2
- * @fileoverview 通用工具函数
3
- */
4
1
  /**
5
2
  * 取(或生成)元素的节点唯一 id:优先复用已赋值的 id,否则生成随机 id 并写回元素。
6
3
  * 同一引用在会话标记(`@节点[n<id>]`)与上下文注入里使用同一个 id;
@@ -42,3 +39,29 @@ export declare function base64Decode(base64: string): string;
42
39
  * 支持多种常见响应格式
43
40
  */
44
41
  export declare function extractTextFromResponse(data: unknown): string | null;
42
+ /**
43
+ * 生成节点提及标记 `@节点[n<id>]`(与 ensureNodeId 分配的 n<hex> id 体系一致)
44
+ */
45
+ export declare function toNodeMention(id: string): string;
46
+ /**
47
+ * 从文本中提取全部节点提及 id(去重、保序)
48
+ */
49
+ export declare function parseNodeMentions(text: string): string[];
50
+ /**
51
+ * 构造 iframe postMessage 信封:{ type, ...data }(AIPanel 挂件与 dsh-client 共用同一形状)
52
+ */
53
+ export declare function widgetEnvelope(type: string, data?: Record<string, unknown>): Record<string, unknown>;
54
+ /** 重试配置 */
55
+ export interface RetryOptions {
56
+ /** 总尝试次数(默认 core DEFAULT_RETRIES) */
57
+ attempts?: number;
58
+ /** 失败后连续尝试间隔毫秒(默认 core RETRY_DELAY) */
59
+ delayMs?: number;
60
+ /** 每次失败、重试前回调(attempt 为 1-based) */
61
+ onRetry?: (attempt: number, error: unknown) => void;
62
+ }
63
+ /**
64
+ * 带线性重试的执行包裹:执行 fn 直到成功或尝试完毕;最后一次失败原样抛出。
65
+ * 环境无关(仅使用 setTimeout),放于 common 供浏览器与 node 共用。
66
+ */
67
+ export declare function withRetries<T>(fn: (attempt: number) => Promise<T>, options?: RetryOptions): Promise<T>;
package/lib/index.cjs CHANGED
@@ -14,20 +14,18 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
14
14
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
15
  var lib_exports = {};
16
16
  module.exports = __toCommonJS(lib_exports);
17
- __reExport(lib_exports, require("./constants.cjs"), module.exports);
18
- __reExport(lib_exports, require("./logger-core.cjs"), module.exports);
19
- __reExport(lib_exports, require("./logger.cjs"), module.exports);
20
- __reExport(lib_exports, require("./options.cjs"), module.exports);
21
- __reExport(lib_exports, require("./provider.cjs"), module.exports);
22
- __reExport(lib_exports, require("./types.cjs"), module.exports);
23
- __reExport(lib_exports, require("./utils.cjs"), module.exports);
17
+ __reExport(lib_exports, require("./common/constants.cjs"), module.exports);
18
+ __reExport(lib_exports, require("./common/logger-core.cjs"), module.exports);
19
+ __reExport(lib_exports, require("./common/options.cjs"), module.exports);
20
+ __reExport(lib_exports, require("./common/provider.cjs"), module.exports);
21
+ __reExport(lib_exports, require("./common/types.cjs"), module.exports);
22
+ __reExport(lib_exports, require("./common/utils.cjs"), module.exports);
24
23
  // Annotate the CommonJS export names for ESM import in node:
25
24
  0 && (module.exports = {
26
- ...require("./constants.cjs"),
27
- ...require("./logger-core.cjs"),
28
- ...require("./logger.cjs"),
29
- ...require("./options.cjs"),
30
- ...require("./provider.cjs"),
31
- ...require("./types.cjs"),
32
- ...require("./utils.cjs")
25
+ ...require("./common/constants.cjs"),
26
+ ...require("./common/logger-core.cjs"),
27
+ ...require("./common/options.cjs"),
28
+ ...require("./common/provider.cjs"),
29
+ ...require("./common/types.cjs"),
30
+ ...require("./common/utils.cjs")
33
31
  });
package/lib/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- export * from "./constants";
2
- export * from "./logger-core";
3
- export * from "./logger";
4
- export * from "./options";
5
- export * from "./provider";
6
- export * from "./types";
7
- export * from "./utils";
1
+ export * from "./common/constants";
2
+ export * from "./common/logger-core";
3
+ export * from "./common/options";
4
+ export * from "./common/provider";
5
+ export * from "./common/types";
6
+ export * from "./common/utils";
@@ -27,6 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
  var diagnostics_exports = {};
29
29
  __export(diagnostics_exports, {
30
+ DIAGNOSTICS_TOOL_DESCRIPTION: () => DIAGNOSTICS_TOOL_DESCRIPTION,
30
31
  findAllTsconfigDirs: () => findAllTsconfigDirs,
31
32
  findTsconfigDir: () => findTsconfigDir,
32
33
  formatDiagnosticsSections: () => formatDiagnosticsSections,
@@ -41,8 +42,8 @@ var import_node_fs = __toESM(require("node:fs"));
41
42
  var import_node_path = __toESM(require("node:path"));
42
43
  var import_node_child_process = require("node:child_process");
43
44
  var import_node_module = require("node:module");
44
- var import_constants = require("../constants.cjs");
45
- var import_node_logger = require("../node-logger.cjs");
45
+ var import_constants = require("../common/constants.cjs");
46
+ var import_node_logger = require("./node-logger.cjs");
46
47
  const import_meta = {};
47
48
  const log = (0, import_node_logger.createLogger)("Diagnostics");
48
49
  const JS_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -59,6 +60,19 @@ const JS_EXTENSIONS = /* @__PURE__ */ new Set([
59
60
  function isJsFile(filePath) {
60
61
  return JS_EXTENSIONS.has(import_node_path.default.extname(filePath));
61
62
  }
63
+ const DIAGNOSTICS_TOOL_DESCRIPTION = [
64
+ "\u8FD0\u884C ESLint \u4E0E TypeScript \u7C7B\u578B\u8BCA\u65AD\uFF0C\u8FD4\u56DE\u8BCA\u65AD\u7ED3\u679C\u3002",
65
+ "",
66
+ "**\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B**\uFF1A",
67
+ `- ESLint\uFF1AJavaScript / TypeScript / Vue \u6E90\u7801\uFF08${[...JS_EXTENSIONS].map((e) => `*${e}`).join(" ")}\uFF09`,
68
+ "- TypeScript \u7C7B\u578B\u68C0\u67E5\uFF1A*.ts *.tsx *.vue",
69
+ "",
70
+ "**\u4F55\u65F6\u4F7F\u7528\u6B64\u5DE5\u5177**\uFF1A",
71
+ "- \u521A\u5B8C\u6210\u4EE3\u7801\u4FEE\u6539\uFF0C\u60F3\u9A8C\u8BC1\u662F\u5426\u6709 ESLint \u9519\u8BEF\u6216\u7C7B\u578B\u9519\u8BEF",
72
+ "- \u5728\u63D0\u4EA4\u4EE3\u7801\u524D\u8FDB\u884C\u8D28\u91CF\u68C0\u67E5",
73
+ "- \u6392\u67E5\u7F16\u8F91\u5668\u672A\u663E\u793A\u4F46\u5B9E\u9645\u5B58\u5728\u7684\u7C7B\u578B\u95EE\u9898",
74
+ "- \u4E0D\u4F20\u53C2\u6570\u53EF\u5168\u91CF\u8BCA\u65AD\u6574\u4E2A\u9879\u76EE"
75
+ ].join("\n");
62
76
  let ESLintClass;
63
77
  function loadESLint(workspace) {
64
78
  if (ESLintClass) return;
@@ -74,7 +88,12 @@ function loadESLint(workspace) {
74
88
  }
75
89
  async function lintFiles(pattern, cwd, warnLimit = 5) {
76
90
  loadESLint(cwd);
77
- if (!ESLintClass) return {};
91
+ if (!ESLintClass) {
92
+ return {
93
+ text: `[ESLint] \u672A\u8FD0\u884C\uFF1A\u65E0\u6CD5\u5728 workspace "${cwd}" \u89E3\u6790\u5230 eslint\uFF08\u4EC5\u663E\u793A TypeScript \u8BCA\u65AD\uFF09`,
94
+ diagnostics: []
95
+ };
96
+ }
78
97
  try {
79
98
  const eslint = new ESLintClass({ cwd });
80
99
  const results = await eslint.lintFiles(pattern);
@@ -122,7 +141,10 @@ async function lintFiles(pattern, cwd, warnLimit = 5) {
122
141
  return { text: lines.length > 0 ? lines.join("\n") : void 0, diagnostics };
123
142
  } catch (err) {
124
143
  log.warn("ESLint failed", { pattern, error: err.message });
125
- return {};
144
+ return {
145
+ text: `[ESLint] \u8FD0\u884C\u5931\u8D25\uFF1A${err.message}\uFF08\u4EC5\u663E\u793A TypeScript \u8BCA\u65AD\uFF09`,
146
+ diagnostics: []
147
+ };
126
148
  }
127
149
  }
128
150
  let _vueTscBin;
@@ -296,6 +318,7 @@ function formatDiagnosticsSections(title, eslintOutput, tscOutput) {
296
318
  }
297
319
  // Annotate the CommonJS export names for ESM import in node:
298
320
  0 && (module.exports = {
321
+ DIAGNOSTICS_TOOL_DESCRIPTION,
299
322
  findAllTsconfigDirs,
300
323
  findTsconfigDir,
301
324
  formatDiagnosticsSections,
@@ -1,5 +1,10 @@
1
1
  /** 是否为可诊断的源码文件(供宿主钩子过滤 edit/write 目标) */
2
2
  export declare function isJsFile(filePath: string): boolean;
3
+ /**
4
+ * run_diagnostics 工具描述(单一来源,供 opencode / dsh 两侧插件引用):
5
+ * 只声明能力与支持的文件类型,不涉及内部使用的检查工具。
6
+ */
7
+ export declare const DIAGNOSTICS_TOOL_DESCRIPTION: string;
3
8
  /** LSP 风格诊断项(供宿主写入 metadata.diagnostics 等结构化输出) */
4
9
  export interface DiagnosticItem {
5
10
  /** 所属文件路径(相对/绝对,按来源解析);跨文件诊断(全量模式)时必有 */
@@ -33,7 +33,7 @@ __export(file_log_watcher_exports, {
33
33
  module.exports = __toCommonJS(file_log_watcher_exports);
34
34
  var import_fs = __toESM(require("fs"));
35
35
  var import_path = __toESM(require("path"));
36
- var import_logger = require("./logger.cjs");
36
+ var import_logger = require("../client/logger.cjs");
37
37
  const log = (0, import_logger.createLogger)("FileLogReader");
38
38
  function detectLogLevel(line) {
39
39
  const lowerLine = line.toLowerCase();
@@ -28,8 +28,8 @@ __export(node_logger_exports, {
28
28
  nodeLogger: () => nodeLogger
29
29
  });
30
30
  module.exports = __toCommonJS(node_logger_exports);
31
- var import_constants = require("./constants.cjs");
32
- var import_logger_core = require("./logger-core.cjs");
31
+ var import_constants = require("../common/constants.cjs");
32
+ var import_logger_core = require("../common/logger-core.cjs");
33
33
  const COLORS = {
34
34
  reset: "\x1B[0m",
35
35
  dim: "\x1B[2m",
@@ -49,21 +49,6 @@ const LEVEL_COLORS = {
49
49
  [import_logger_core.LogLevel.ERROR]: COLORS.red,
50
50
  [import_logger_core.LogLevel.NONE]: COLORS.reset
51
51
  };
52
- const LEVEL_NAMES = {
53
- [import_logger_core.LogLevel.DEBUG]: "DEBUG",
54
- [import_logger_core.LogLevel.INFO]: "INFO",
55
- [import_logger_core.LogLevel.WARN]: "WARN",
56
- [import_logger_core.LogLevel.ERROR]: "ERROR",
57
- [import_logger_core.LogLevel.NONE]: "NONE"
58
- };
59
- function getTimestamp() {
60
- const now = /* @__PURE__ */ new Date();
61
- const hours = String(now.getHours()).padStart(2, "0");
62
- const minutes = String(now.getMinutes()).padStart(2, "0");
63
- const seconds = String(now.getSeconds()).padStart(2, "0");
64
- const ms = String(now.getMilliseconds()).padStart(3, "0");
65
- return `${hours}:${minutes}:${seconds}.${ms}`;
66
- }
67
52
  function getCallerInfo(depth = 3) {
68
53
  const stack = new Error().stack;
69
54
  if (!stack) return "";
@@ -82,10 +67,10 @@ function log(level, message, context, ...args) {
82
67
  const parts = [];
83
68
  parts.push(`${COLORS.dim}[${process.pid}]${COLORS.reset}`);
84
69
  if ((0, import_logger_core.getConfig)().showTimestamp) {
85
- parts.push(`${COLORS.dim}${getTimestamp()}${COLORS.reset}`);
70
+ parts.push(`${COLORS.dim}${(0, import_logger_core.getTimestamp)()}${COLORS.reset}`);
86
71
  }
87
72
  const levelColor = LEVEL_COLORS[level];
88
- const levelName = LEVEL_NAMES[level].padEnd(5);
73
+ const levelName = import_logger_core.LEVEL_NAMES[level].padEnd(5);
89
74
  parts.push(`${levelColor}${levelName}${COLORS.reset}`);
90
75
  parts.push(`${COLORS.bright}${import_constants.LOG_PREFIX}${COLORS.reset}`);
91
76
  const contextStr = (0, import_logger_core.formatContext)(context);
@@ -1,4 +1,4 @@
1
- import { type LogContext } from "./logger-core";
1
+ import { type LogContext } from "../common/logger-core";
2
2
  export declare const nodeLogger: {
3
3
  debug(message: string, context?: LogContext, ...args: unknown[]): void;
4
4
  info(message: string, context?: LogContext, ...args: unknown[]): void;