weflow-cli 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/ARCHITECTURE.md +3 -2
  2. package/CHANGELOG.md +1966 -0
  3. package/OPERATIONS.md +808 -0
  4. package/README.en.md +93 -7
  5. package/README.md +31 -6
  6. package/bin/weflow-cli.ts +1245 -26
  7. package/dist/bin/weflow-cli.js +1349 -72
  8. package/dist/bin/weflow-cli.js.map +1 -1
  9. package/dist/mcp-server/index.js +39 -13
  10. package/dist/mcp-server/index.js.map +1 -1
  11. package/dist/src/core/appMsgFormat.d.ts +37 -0
  12. package/dist/src/core/appMsgFormat.d.ts.map +1 -0
  13. package/dist/src/core/appMsgFormat.js +106 -0
  14. package/dist/src/core/appMsgFormat.js.map +1 -0
  15. package/dist/src/core/ntCore.d.ts +43 -0
  16. package/dist/src/core/ntCore.d.ts.map +1 -1
  17. package/dist/src/core/ntCore.js +31 -0
  18. package/dist/src/core/ntCore.js.map +1 -1
  19. package/dist/src/core/sqlcipherCore.d.ts +0 -12
  20. package/dist/src/core/sqlcipherCore.d.ts.map +1 -1
  21. package/dist/src/core/sqlcipherCore.js +5 -64
  22. package/dist/src/core/sqlcipherCore.js.map +1 -1
  23. package/dist/src/core/wcdbCore.d.ts +1 -1
  24. package/dist/src/core/wcdbCore.d.ts.map +1 -1
  25. package/dist/src/core/wcdbCore.js +5 -1
  26. package/dist/src/core/wcdbCore.js.map +1 -1
  27. package/dist/src/panel/client.d.ts +25 -0
  28. package/dist/src/panel/client.d.ts.map +1 -0
  29. package/dist/src/panel/client.js +34 -0
  30. package/dist/src/panel/client.js.map +1 -0
  31. package/dist/src/panel/endpoint.d.ts +45 -0
  32. package/dist/src/panel/endpoint.d.ts.map +1 -0
  33. package/dist/src/panel/endpoint.js +132 -0
  34. package/dist/src/panel/endpoint.js.map +1 -0
  35. package/dist/src/panel/launch.d.ts +50 -0
  36. package/dist/src/panel/launch.d.ts.map +1 -0
  37. package/dist/src/panel/launch.js +74 -0
  38. package/dist/src/panel/launch.js.map +1 -0
  39. package/dist/src/panel/server.d.ts +23 -0
  40. package/dist/src/panel/server.d.ts.map +1 -0
  41. package/dist/src/panel/server.js +413 -0
  42. package/dist/src/panel/server.js.map +1 -0
  43. package/dist/src/panel/userId.d.ts +37 -0
  44. package/dist/src/panel/userId.d.ts.map +1 -0
  45. package/dist/src/panel/userId.js +56 -0
  46. package/dist/src/panel/userId.js.map +1 -0
  47. package/dist/src/services/assistantDaemon.d.ts +20 -3
  48. package/dist/src/services/assistantDaemon.d.ts.map +1 -1
  49. package/dist/src/services/assistantDaemon.js +46 -9
  50. package/dist/src/services/assistantDaemon.js.map +1 -1
  51. package/dist/src/services/assistantEval.d.ts +141 -0
  52. package/dist/src/services/assistantEval.d.ts.map +1 -0
  53. package/dist/src/services/assistantEval.js +497 -0
  54. package/dist/src/services/assistantEval.js.map +1 -0
  55. package/dist/src/services/assistantMemory.d.ts +106 -4
  56. package/dist/src/services/assistantMemory.d.ts.map +1 -1
  57. package/dist/src/services/assistantMemory.js +396 -61
  58. package/dist/src/services/assistantMemory.js.map +1 -1
  59. package/dist/src/services/assistantPrivacy.d.ts +15 -2
  60. package/dist/src/services/assistantPrivacy.d.ts.map +1 -1
  61. package/dist/src/services/assistantPrivacy.js +18 -4
  62. package/dist/src/services/assistantPrivacy.js.map +1 -1
  63. package/dist/src/services/assistantRouter.d.ts +41 -0
  64. package/dist/src/services/assistantRouter.d.ts.map +1 -0
  65. package/dist/src/services/assistantRouter.js +151 -0
  66. package/dist/src/services/assistantRouter.js.map +1 -0
  67. package/dist/src/services/assistantService.d.ts +209 -3
  68. package/dist/src/services/assistantService.d.ts.map +1 -1
  69. package/dist/src/services/assistantService.js +590 -75
  70. package/dist/src/services/assistantService.js.map +1 -1
  71. package/dist/src/services/assistantTools.d.ts +205 -1
  72. package/dist/src/services/assistantTools.d.ts.map +1 -1
  73. package/dist/src/services/assistantTools.js +1089 -58
  74. package/dist/src/services/assistantTools.js.map +1 -1
  75. package/dist/src/services/assistantTrace.d.ts +47 -0
  76. package/dist/src/services/assistantTrace.d.ts.map +1 -0
  77. package/dist/src/services/assistantTrace.js +150 -0
  78. package/dist/src/services/assistantTrace.js.map +1 -0
  79. package/dist/src/services/chatService.d.ts +13 -0
  80. package/dist/src/services/chatService.d.ts.map +1 -1
  81. package/dist/src/services/chatService.js +23 -0
  82. package/dist/src/services/chatService.js.map +1 -1
  83. package/dist/src/services/configService.d.ts +9 -0
  84. package/dist/src/services/configService.d.ts.map +1 -1
  85. package/dist/src/services/configService.js +15 -8
  86. package/dist/src/services/configService.js.map +1 -1
  87. package/dist/src/services/messageQuery.d.ts +35 -0
  88. package/dist/src/services/messageQuery.d.ts.map +1 -1
  89. package/dist/src/services/messageQuery.js +61 -0
  90. package/dist/src/services/messageQuery.js.map +1 -1
  91. package/dist/src/services/pythonBridge.d.ts +41 -0
  92. package/dist/src/services/pythonBridge.d.ts.map +1 -0
  93. package/dist/src/services/pythonBridge.js +119 -0
  94. package/dist/src/services/pythonBridge.js.map +1 -0
  95. package/dist/src/services/syncService.d.ts +127 -0
  96. package/dist/src/services/syncService.d.ts.map +1 -0
  97. package/dist/src/services/syncService.js +263 -0
  98. package/dist/src/services/syncService.js.map +1 -0
  99. package/dist/src/services/syncState.d.ts +113 -0
  100. package/dist/src/services/syncState.d.ts.map +1 -0
  101. package/dist/src/services/syncState.js +214 -0
  102. package/dist/src/services/syncState.js.map +1 -0
  103. package/dist/src/services/wechatMessageService.d.ts +25 -0
  104. package/dist/src/services/wechatMessageService.d.ts.map +1 -1
  105. package/dist/src/services/wechatMessageService.js +69 -7
  106. package/dist/src/services/wechatMessageService.js.map +1 -1
  107. package/dist/src/utils/atomicWrite.d.ts +4 -0
  108. package/dist/src/utils/atomicWrite.d.ts.map +1 -0
  109. package/dist/src/utils/atomicWrite.js +60 -0
  110. package/dist/src/utils/atomicWrite.js.map +1 -0
  111. package/dist/src/utils/dateRange.d.ts +15 -0
  112. package/dist/src/utils/dateRange.d.ts.map +1 -1
  113. package/dist/src/utils/dateRange.js +47 -0
  114. package/dist/src/utils/dateRange.js.map +1 -1
  115. package/dist/src/utils/text.d.ts +18 -0
  116. package/dist/src/utils/text.d.ts.map +1 -0
  117. package/dist/src/utils/text.js +20 -0
  118. package/dist/src/utils/text.js.map +1 -0
  119. package/docs/AI_INTERFACE.md +2 -0
  120. package/docs/DECISIONS.md +1484 -20
  121. package/docs/EXTENDING.md +187 -0
  122. package/docs/FUNCTIONAL-IMPROVEMENT-SPEC.md +338 -0
  123. package/docs/JEV/345/272/224/347/224/250/346/226/275/345/267/245/346/226/207/346/241/243.md +310 -0
  124. package/docs/MCP.md +23 -4
  125. package/docs/PROJECT_STATE.md +299 -96
  126. package/docs/SETUP.md +22 -0
  127. package/docs/SYNC_CONTRACT.md +180 -0
  128. package/mcp-server/index.ts +681 -657
  129. package/package.json +84 -83
  130. package/resources/panel/ball-position.cjs +153 -0
  131. package/resources/panel/index.html +46 -0
  132. package/resources/panel/main.cjs +447 -0
  133. package/resources/panel/mascot-focus.png +0 -0
  134. package/resources/panel/mascot-happy.png +0 -0
  135. package/resources/panel/mascot-sorry.png +0 -0
  136. package/resources/panel/mascot-tired.png +0 -0
  137. package/resources/panel/mascot.png +0 -0
  138. package/resources/panel/package.json +7 -0
  139. package/resources/panel/panel.css +407 -0
  140. package/resources/panel/preload.cjs +72 -0
  141. package/resources/panel/quick-menu.cjs +197 -0
  142. package/resources/panel/renderer.js +441 -0
  143. package/resources/panel/tray-menu.cjs +40 -0
  144. package/resources/panel/tray.png +0 -0
  145. package/scripts/_utils.py +403 -54
  146. package/scripts/annual_report.py +4 -2
  147. package/scripts/article_notes.py +423 -0
  148. package/scripts/backfill_articles.py +438 -0
  149. package/scripts/biz_daily.py +590 -105
  150. package/scripts/chat_notes.py +470 -0
  151. package/scripts/classify_daily.py +10 -18
  152. package/scripts/compile_wiki.py +1059 -46
  153. package/scripts/create_reading_notes.py +199 -14
  154. package/scripts/decide.py +253 -0
  155. package/scripts/draft_reply.py +671 -0
  156. package/scripts/export_chat_html.py +212 -46
  157. package/scripts/extract_todos.py +31 -5
  158. package/scripts/fav_notes.py +318 -0
  159. package/scripts/fix_topics.py +2 -1
  160. package/scripts/generate_ai_report.py +214 -9
  161. package/scripts/generate_html.py +18 -3
  162. package/scripts/generate_review.py +2 -2
  163. package/scripts/jev_client.py +294 -0
  164. package/scripts/jev_probe.py +440 -0
  165. package/scripts/nt_common.py +82 -0
  166. package/scripts/nt_decrypt.py +1755 -1352
  167. package/scripts/pipeline.py +27 -2
  168. package/scripts/promote_ideas.py +19 -4
  169. package/scripts/quality_eval.py +707 -0
  170. package/scripts/rag_chat.py +4 -4
  171. package/scripts/read_image.py +187 -0
  172. package/scripts/reply_debt.py +488 -0
  173. package/scripts/route_cards.py +453 -0
  174. package/scripts/semantic_search.py +208 -49
  175. package/scripts/user_notes.py +315 -0
  176. package/scripts/vault_rag.py +13 -7
  177. package/scripts/vault_search.py +21 -4
  178. package/scripts/wiki_lint.py +397 -0
  179. package/src/core/appMsgFormat.ts +117 -0
  180. package/src/core/ntCore.ts +67 -0
  181. package/src/core/sqlcipherCore.ts +5 -61
  182. package/src/core/wcdbCore.ts +6 -2
  183. package/src/panel/client.ts +49 -0
  184. package/src/panel/endpoint.ts +144 -0
  185. package/src/panel/launch.ts +101 -0
  186. package/src/panel/server.ts +424 -0
  187. package/src/panel/userId.ts +72 -0
  188. package/src/services/assistantDaemon.ts +57 -9
  189. package/src/services/assistantEval.ts +611 -0
  190. package/src/services/assistantMemory.ts +413 -57
  191. package/src/services/assistantPrivacy.ts +18 -4
  192. package/src/services/assistantRouter.ts +191 -0
  193. package/src/services/assistantService.ts +671 -74
  194. package/src/services/assistantTools.ts +1118 -57
  195. package/src/services/assistantTrace.ts +175 -0
  196. package/src/services/chatService.ts +30 -0
  197. package/src/services/configService.ts +403 -385
  198. package/src/services/messageQuery.ts +97 -0
  199. package/src/services/pythonBridge.ts +139 -0
  200. package/src/services/syncService.ts +363 -0
  201. package/src/services/syncState.ts +275 -0
  202. package/src/services/wechatMessageService.ts +73 -7
  203. package/src/utils/atomicWrite.ts +56 -0
  204. package/src/utils/dateRange.ts +46 -0
  205. package/src/utils/text.ts +20 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 端点客户端:`weflow-cli panel` 用它读状态、换一次性口令、问一句话。
3
+ *
4
+ * 和悬浮窗走的是**同一个端点、同一套规矩**——所以"面板与微信共用一个大脑"这件事,
5
+ * 可以在命令行上被端到端地测(`panel ask` 就是"面板减去像素")。
6
+ *
7
+ * 凭据从不进日志、不进错误信息:出错时只说状态码与分类,不回显 token。
8
+ */
9
+ import type { PanelEndpoint } from './endpoint.js';
10
+ export type ClientResult<T> = {
11
+ ok: true;
12
+ data: T;
13
+ } | {
14
+ ok: false;
15
+ code: string;
16
+ error?: string;
17
+ };
18
+ export declare function panelStatus(endpoint: PanelEndpoint): Promise<ClientResult<any>>;
19
+ /** 换一个一次性口令,用来拼浏览器那条路的 URL(口令不是 token,可以进命令行) */
20
+ export declare function panelPair(endpoint: PanelEndpoint): Promise<ClientResult<{
21
+ url: string;
22
+ expiresInMs: number;
23
+ }>>;
24
+ export declare function panelAsk(endpoint: PanelEndpoint, text: string): Promise<ClientResult<any>>;
25
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/panel/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD,MAAM,MAAM,YAAY,CAAC,CAAC,IACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GACrB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAyB/C,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAE/E;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAE9G;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAE1F"}
@@ -0,0 +1,34 @@
1
+ async function request(endpoint, path, init = {}, timeoutMs = 10_000) {
2
+ try {
3
+ const res = await fetch(`http://127.0.0.1:${endpoint.port}${path}`, {
4
+ ...init,
5
+ headers: {
6
+ Authorization: `Bearer ${endpoint.token}`,
7
+ ...(init.body ? { 'Content-Type': 'application/json' } : {}),
8
+ ...(init.headers ?? {}),
9
+ },
10
+ signal: AbortSignal.timeout(timeoutMs),
11
+ });
12
+ const body = await res.json().catch(() => ({}));
13
+ if (!res.ok)
14
+ return { ok: false, code: String(body?.code ?? `HTTP_${res.status}`), error: body?.error };
15
+ return { ok: true, data: body };
16
+ }
17
+ catch (error) {
18
+ // 连不上:进程可能刚被停掉,或端点文件是残留的。**分开说**,别都说成"失败"
19
+ if (error?.name === 'TimeoutError')
20
+ return { ok: false, code: 'TIMEOUT' };
21
+ return { ok: false, code: 'UNREACHABLE' };
22
+ }
23
+ }
24
+ export function panelStatus(endpoint) {
25
+ return request(endpoint, '/api/status');
26
+ }
27
+ /** 换一个一次性口令,用来拼浏览器那条路的 URL(口令不是 token,可以进命令行) */
28
+ export function panelPair(endpoint) {
29
+ return request(endpoint, '/api/pair', { method: 'POST' });
30
+ }
31
+ export function panelAsk(endpoint, text) {
32
+ return request(endpoint, '/api/ask', { method: 'POST', body: JSON.stringify({ text }) }, 200_000);
33
+ }
34
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/panel/client.ts"],"names":[],"mappings":"AAcA,KAAK,UAAU,OAAO,CACpB,QAAuB,EAAE,IAAY,EAAE,OAAoB,EAAE,EAAE,SAAS,GAAG,MAAM;IAEjF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,QAAQ,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE;YAClE,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,QAAQ,CAAC,KAAK,EAAE;gBACzC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;aACxB;YACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAA;QACF,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;QACvG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACjC,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,0CAA0C;QAC1C,IAAI,KAAK,EAAE,IAAI,KAAK,cAAc;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;QACzE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;IAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAuB;IACjD,OAAO,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;AACzC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,SAAS,CAAC,QAAuB;IAC/C,OAAO,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAuB,EAAE,IAAY;IAC5D,OAAO,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;AACnG,CAAC"}
@@ -0,0 +1,45 @@
1
+ /** 端点文件的格式版本。读不出来或不认识就**当作不存在**,不猜、不迁移(同记忆文件的纪律) */
2
+ export declare const PANEL_ENDPOINT_VERSION = 1;
3
+ /** `/api/status` 的身份字段:防止把别人的端口当成助手(`service !== 它` 就不认) */
4
+ export declare const PANEL_SERVICE_ID = "weflow-assistant";
5
+ /**
6
+ * 默认端口。**固定**而不是随机:便于本人手工 `curl` 排查,也让文档能写一个确定的地址。
7
+ * 端口被占时**大声失败**,不静默换一个——静默换端口会让"文件里写着 A、实际在 B"成为可能。
8
+ */
9
+ export declare const DEFAULT_PANEL_PORT = 8766;
10
+ export type PanelChannelMode = 'wechat' | 'local';
11
+ export interface PanelEndpoint {
12
+ version: number;
13
+ service: string;
14
+ port: number;
15
+ token: string;
16
+ pid: number;
17
+ startedAt: string;
18
+ channel: PanelChannelMode;
19
+ /** 这个进程给本机入口用的记忆桶(与微信直聊同一个 id 时才是"共用一个大脑") */
20
+ memoryBucket: string;
21
+ }
22
+ export declare function weflowHome(): string;
23
+ export declare function endpointFile(): string;
24
+ /** 每进程一份,**每次启动重新生成**。32 字节 base64url。 */
25
+ export declare function generateToken(): string;
26
+ /** 原子写:先 `.tmp` 再 rename。失败不抛——端点起不来不该把助手一起弄死,调用方会记日志 */
27
+ export declare function writeEndpoint(endpoint: PanelEndpoint): boolean;
28
+ /**
29
+ * 读并校验。**任何一种不可信都返回 `null`**,绝不返回一个"大概是它"的对象:
30
+ * 文件不存在、JSON 坏了、版本不认识、字段缺、**进程已经没了**。
31
+ */
32
+ export declare function readEndpoint(): PanelEndpoint | null;
33
+ /** 探活。照抄 `assistantDaemon.isDaemonAlive()`:`kill(pid, 0)` 不真发信号,只做权限/存在性检查 */
34
+ export declare function isProcessAlive(pid: number): boolean;
35
+ /**
36
+ * 删除端点文件。**只在"确认要停"时用**(例如 `assistant stop`),
37
+ * 不要指望它在崩溃/被 SIGTERM 时被调用——见文件头第 3 条。
38
+ */
39
+ export declare function clearEndpoint(): void;
40
+ /**
41
+ * token 比较。长度不等时 `timingSafeEqual` 会**抛**,所以先比长度。
42
+ * 用 `timingSafeEqual` 是为了不把"前几个字符对了"这件事通过耗时泄漏出去。
43
+ */
44
+ export declare function tokenMatches(expected: string, given: unknown): boolean;
45
+ //# sourceMappingURL=endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../../src/panel/endpoint.ts"],"names":[],"mappings":"AAmCA,oDAAoD;AACpD,eAAO,MAAM,sBAAsB,IAAI,CAAA;AACvC,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAClD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,gBAAgB,CAAA;IACzB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,0CAA0C;AAC1C,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAcD,yDAAyD;AACzD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAU9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,aAAa,GAAG,IAAI,CAWnD;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAOtE"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * 本机面板的**发现 + 凭据**:一个文件解决两件事。
3
+ *
4
+ * 悬浮窗要跟助手说话,需要知道两样东西——**端口**和**口令**。分开存会让"端口写死但服务没起来"
5
+ * 变成一类难查的故障,所以合在一个文件里,由守护进程**原子写**(先写 `.tmp` 再 `rename`,
6
+ * 照抄 `configService.save()` 的手法)。
7
+ *
8
+ * ## 三个必须处理的失效模式
9
+ *
10
+ * 1. **崩溃残留**:文件还在,进程没了 → 用 `process.kill(pid, 0)` 探活
11
+ * (照抄 `assistantDaemon.isDaemonAlive()` 的写法)。
12
+ * 2. **端口被别的进程占了**:文件里的端口是准的,但回应的人不是我们 → 拿到之后
13
+ * **必须打一次 `/api/status`**,校验 `service` 与 `startedAt` 都对得上
14
+ * (照抄 `getDailyReaderStatus()` 里那三行;它就是为这个存在的)。
15
+ * 3. **退出时不删文件**:**不要指望清理**。`stopDaemon()` 发的是 SIGTERM,而 Node 默认不为它跑
16
+ * 清理逻辑,所以文件**一定会残留**。"退出时删掉它"看起来太像一个能用的方案了,
17
+ * 所以这里明说:正确做法是探活,不是删。
18
+ *
19
+ * ## 关于 Windows 上的文件权限
20
+ *
21
+ * token 写在 `~/.weflow-cli/` 下。**不要声称"权限已收紧"**:Windows 上 `fs.chmod` /
22
+ * `mode: 0o600` 基本无效(Node 只能映射只读位)。真正起作用的是 `%USERPROFILE%\.weflow-cli\`
23
+ * 的默认 ACL(只有本人 + SYSTEM + Administrators)——**那是既成事实,不是我们做的事**。
24
+ * `mode: 0o600` 仍然传,因为在 Linux/macOS/WSL 上有意义;在 Windows 上它是空操作。
25
+ *
26
+ * 所以这道 token 的真实作用是:挡住**本机其它程序与任意网页**(它们读不到这个文件)。
27
+ * 它**挡不住**以同一用户身份运行、且愿意翻 `~/.weflow-cli/` 的程序——那种程序本来就能直接读库。
28
+ * 这是这条设计的真实边界,别把它说成比这更强。
29
+ */
30
+ import { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';
31
+ import { writeFileAtomic } from '../utils/atomicWrite.js';
32
+ import { randomBytes, timingSafeEqual } from 'crypto';
33
+ import { join } from 'path';
34
+ import os from 'os';
35
+ /** 端点文件的格式版本。读不出来或不认识就**当作不存在**,不猜、不迁移(同记忆文件的纪律) */
36
+ export const PANEL_ENDPOINT_VERSION = 1;
37
+ /** `/api/status` 的身份字段:防止把别人的端口当成助手(`service !== 它` 就不认) */
38
+ export const PANEL_SERVICE_ID = 'weflow-assistant';
39
+ /**
40
+ * 默认端口。**固定**而不是随机:便于本人手工 `curl` 排查,也让文档能写一个确定的地址。
41
+ * 端口被占时**大声失败**,不静默换一个——静默换端口会让"文件里写着 A、实际在 B"成为可能。
42
+ */
43
+ export const DEFAULT_PANEL_PORT = 8766;
44
+ export function weflowHome() {
45
+ return join(os.homedir(), '.weflow-cli');
46
+ }
47
+ export function endpointFile() {
48
+ return join(weflowHome(), 'assistant_endpoint.json');
49
+ }
50
+ /** 每进程一份,**每次启动重新生成**。32 字节 base64url。 */
51
+ export function generateToken() {
52
+ return randomBytes(32).toString('base64url');
53
+ }
54
+ function isEndpoint(value) {
55
+ return !!value && typeof value === 'object'
56
+ && value.version === PANEL_ENDPOINT_VERSION
57
+ && value.service === PANEL_SERVICE_ID
58
+ && typeof value.port === 'number' && Number.isInteger(value.port) && value.port > 0 && value.port < 65536
59
+ && typeof value.token === 'string' && value.token.length > 0
60
+ && typeof value.pid === 'number'
61
+ && typeof value.startedAt === 'string'
62
+ && (value.channel === 'wechat' || value.channel === 'local')
63
+ && typeof value.memoryBucket === 'string';
64
+ }
65
+ /** 原子写:先 `.tmp` 再 rename。失败不抛——端点起不来不该把助手一起弄死,调用方会记日志 */
66
+ export function writeEndpoint(endpoint) {
67
+ try {
68
+ mkdirSync(weflowHome(), { recursive: true });
69
+ // `mode` 在 Windows 上是空操作,见文件头注释;不是为了"安全",是为了别的平台。
70
+ // 用 writeFileAtomic:rename 在被占用时会 EPERM,重试+兜底由它负责
71
+ writeFileAtomic(endpointFile(), JSON.stringify(endpoint, null, 2), { mode: 0o600 });
72
+ return true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * 读并校验。**任何一种不可信都返回 `null`**,绝不返回一个"大概是它"的对象:
80
+ * 文件不存在、JSON 坏了、版本不认识、字段缺、**进程已经没了**。
81
+ */
82
+ export function readEndpoint() {
83
+ try {
84
+ const file = endpointFile();
85
+ if (!existsSync(file))
86
+ return null;
87
+ const parsed = JSON.parse(readFileSync(file, 'utf8'));
88
+ if (!isEndpoint(parsed))
89
+ return null;
90
+ if (!isProcessAlive(parsed.pid))
91
+ return null;
92
+ return parsed;
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ /** 探活。照抄 `assistantDaemon.isDaemonAlive()`:`kill(pid, 0)` 不真发信号,只做权限/存在性检查 */
99
+ export function isProcessAlive(pid) {
100
+ try {
101
+ process.kill(pid, 0);
102
+ return true;
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ /**
109
+ * 删除端点文件。**只在"确认要停"时用**(例如 `assistant stop`),
110
+ * 不要指望它在崩溃/被 SIGTERM 时被调用——见文件头第 3 条。
111
+ */
112
+ export function clearEndpoint() {
113
+ try {
114
+ rmSync(endpointFile(), { force: true });
115
+ }
116
+ catch { /* 删不掉不影响正确性:读取端会探活 */ }
117
+ }
118
+ /**
119
+ * token 比较。长度不等时 `timingSafeEqual` 会**抛**,所以先比长度。
120
+ * 用 `timingSafeEqual` 是为了不把"前几个字符对了"这件事通过耗时泄漏出去。
121
+ */
122
+ export function tokenMatches(expected, given) {
123
+ if (typeof given !== 'string' || given.length !== expected.length)
124
+ return false;
125
+ try {
126
+ return timingSafeEqual(Buffer.from(expected, 'utf8'), Buffer.from(given, 'utf8'));
127
+ }
128
+ catch {
129
+ return false;
130
+ }
131
+ }
132
+ //# sourceMappingURL=endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../../src/panel/endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAiB,MAAM,IAAI,CAAA;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,oDAAoD;AACpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAA;AACvC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA;AAClD;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAA;AAgBtC,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,yBAAyB,CAAC,CAAA;AACtD,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AAC9C,CAAC;AAED,SAAS,UAAU,CAAC,KAAU;IAC5B,OAAO,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;WACtC,KAAK,CAAC,OAAO,KAAK,sBAAsB;WACxC,KAAK,CAAC,OAAO,KAAK,gBAAgB;WAClC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK;WACtG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;WACzD,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;WAC7B,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;WACnC,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC;WACzD,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,CAAA;AAC7C,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,aAAa,CAAC,QAAuB;IACnD,IAAI,CAAC;QACH,SAAS,CAAC,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5C,kDAAkD;QAClD,kDAAkD;QAClD,eAAe,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACnF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,EAAE,CAAA;QAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACrD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAA;QACpC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAA;QAC5C,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QAAC,MAAM,CAAC,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,KAAc;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAC/E,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ export type ExistsFn = (path: string) => boolean;
2
+ export interface ElectronLookup {
3
+ /** 找 Electron 的顺序:包内 → 全局 npm 目录 → 都没有就是 null */
4
+ candidates: string[];
5
+ found: string | null;
6
+ }
7
+ /**
8
+ * 找 Electron。**用 `existsSync` 逐个试,不用 `where`/`which`**:
9
+ * PATH 上可能有 shim,而 shim 的行为不比一个确定的路径更可信。
10
+ */
11
+ export declare function resolveElectronBinary(env: {
12
+ packageRoot: string;
13
+ localAppData?: string;
14
+ programFiles?: string;
15
+ exists?: ExistsFn;
16
+ }): ElectronLookup;
17
+ /**
18
+ * Electron 的 argv。**就一个参数**:应用目录(里面的 `package.json` 指向 `main.cjs`)。
19
+ * 什么都不多带——不带 token、不带端口、不带 URL。
20
+ */
21
+ export declare function electronLaunchArgs(panelDir: string): string[];
22
+ export interface EdgeLookup {
23
+ candidates: string[];
24
+ found: string | null;
25
+ }
26
+ /** 找 Edge;找不到再找 Chrome(Chromium 内核的 `--app=` 都能用) */
27
+ export declare function resolveBrowserBinary(env: {
28
+ programFiles?: string;
29
+ programFilesX86?: string;
30
+ localAppData?: string;
31
+ exists?: ExistsFn;
32
+ }): EdgeLookup;
33
+ /**
34
+ * 浏览器降级的 argv。
35
+ *
36
+ * - `--app=<url>`:没有地址栏、没有标签栏,看起来就是个独立小窗。**这就是降级能给的极限**:
37
+ * 它不是悬浮球——不能无边框、不能置顶、没有托盘、没有全局快捷键。这件事必须对用户说清。
38
+ * - `--user-data-dir=<独立目录>`:**不是可选的**。不带它,`--app` 会挤进用户日常那个浏览器实例
39
+ * (共享 cookie 与会话,甚至可能被并进已有窗口而不是新开一个)。代价是多一个约 50MB 的
40
+ * profile 目录,**它要进隐私文档的敏感路径清单**。
41
+ * - URL 里带的是**一次性口令**(`?c=`),不是 token:口令单次使用、60 秒过期,
42
+ * 所以它出现在命令行与浏览器历史里都不构成泄漏。
43
+ */
44
+ export declare function browserLaunchArgs(options: {
45
+ url: string;
46
+ profileDir: string;
47
+ }): string[];
48
+ /** 浏览器降级专用的 profile 目录(与用户日常浏览器隔离) */
49
+ export declare function browserProfileDir(weflowHome: string): string;
50
+ //# sourceMappingURL=launch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../../src/panel/launch.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;AAEhD,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,QAAQ,CAAA;CAClB,GAAG,cAAc,CAWjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7D;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IACxC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,QAAQ,CAAA;CAClB,GAAG,UAAU,CAWb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAOxF;AAED,sCAAsC;AACtC,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 面板的**启动决策**:用哪个二进制、argv 是什么、URL 是什么。
3
+ *
4
+ * 全部是纯函数,返回路径与数组、没有副作用——**因为这一层能进 CI,而窗口不能**。
5
+ * `resources/panel/main.cjs` 里只剩"调用 spawn / new BrowserWindow",决策都在这儿,
6
+ * 于是"会不会把凭据写进命令行"这种问题有地方可以钉住。
7
+ *
8
+ * 一条硬规矩贯穿本文件:**任何凭据都不许进 argv**。Windows 上同机任何进程都能从
9
+ * `wmic process get commandline` 读到命令行,把 token 放进去就是一次**看不出破绽的泄漏**。
10
+ * 所以浏览器那条路只带**一次性口令**(见 `server.ts` 的 `/api/pair`),Electron 那条什么都不带
11
+ * (它自己去读端点文件)。
12
+ */
13
+ import { existsSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ /**
16
+ * 找 Electron。**用 `existsSync` 逐个试,不用 `where`/`which`**:
17
+ * PATH 上可能有 shim,而 shim 的行为不比一个确定的路径更可信。
18
+ */
19
+ export function resolveElectronBinary(env) {
20
+ const exists = env.exists ?? existsSync;
21
+ const candidates = [
22
+ // 1. 本项目里装过(npm i -D electron)
23
+ join(env.packageRoot, 'node_modules', 'electron', 'dist', 'electron.exe'),
24
+ // 2. 全局 npm 装过(npm i -g electron)
25
+ env.localAppData ? join(env.localAppData, 'npm', 'node_modules', 'electron', 'dist', 'electron.exe') : '',
26
+ // 3. 全局装到别处时的兜底
27
+ env.programFiles ? join(env.programFiles, 'nodejs', 'node_modules', 'electron', 'dist', 'electron.exe') : '',
28
+ ].filter(Boolean);
29
+ return { candidates, found: candidates.find((p) => exists(p)) ?? null };
30
+ }
31
+ /**
32
+ * Electron 的 argv。**就一个参数**:应用目录(里面的 `package.json` 指向 `main.cjs`)。
33
+ * 什么都不多带——不带 token、不带端口、不带 URL。
34
+ */
35
+ export function electronLaunchArgs(panelDir) {
36
+ return [panelDir];
37
+ }
38
+ /** 找 Edge;找不到再找 Chrome(Chromium 内核的 `--app=` 都能用) */
39
+ export function resolveBrowserBinary(env) {
40
+ const exists = env.exists ?? existsSync;
41
+ const roots = [env.programFilesX86, env.programFiles, env.localAppData].filter(Boolean);
42
+ const candidates = [];
43
+ for (const root of roots) {
44
+ candidates.push(join(root, 'Microsoft', 'Edge', 'Application', 'msedge.exe'));
45
+ }
46
+ for (const root of roots) {
47
+ candidates.push(join(root, 'Google', 'Chrome', 'Application', 'chrome.exe'));
48
+ }
49
+ return { candidates, found: candidates.find((p) => exists(p)) ?? null };
50
+ }
51
+ /**
52
+ * 浏览器降级的 argv。
53
+ *
54
+ * - `--app=<url>`:没有地址栏、没有标签栏,看起来就是个独立小窗。**这就是降级能给的极限**:
55
+ * 它不是悬浮球——不能无边框、不能置顶、没有托盘、没有全局快捷键。这件事必须对用户说清。
56
+ * - `--user-data-dir=<独立目录>`:**不是可选的**。不带它,`--app` 会挤进用户日常那个浏览器实例
57
+ * (共享 cookie 与会话,甚至可能被并进已有窗口而不是新开一个)。代价是多一个约 50MB 的
58
+ * profile 目录,**它要进隐私文档的敏感路径清单**。
59
+ * - URL 里带的是**一次性口令**(`?c=`),不是 token:口令单次使用、60 秒过期,
60
+ * 所以它出现在命令行与浏览器历史里都不构成泄漏。
61
+ */
62
+ export function browserLaunchArgs(options) {
63
+ return [
64
+ `--app=${options.url}`,
65
+ `--user-data-dir=${options.profileDir}`,
66
+ '--no-first-run',
67
+ '--no-default-browser-check',
68
+ ];
69
+ }
70
+ /** 浏览器降级专用的 profile 目录(与用户日常浏览器隔离) */
71
+ export function browserProfileDir(weflowHome) {
72
+ return join(weflowHome, 'panel-browser-profile');
73
+ }
74
+ //# sourceMappingURL=launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../../src/panel/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAUhC;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAKrC;IACC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,UAAU,CAAA;IACvC,MAAM,UAAU,GAAG;QACjB,+BAA+B;QAC/B,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC;QACzE,kCAAkC;QAClC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE;QACzG,gBAAgB;QAChB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE;KAC7G,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACjB,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,CAAC,QAAQ,CAAC,CAAA;AACnB,CAAC;AAOD,qDAAqD;AACrD,MAAM,UAAU,oBAAoB,CAAC,GAKpC;IACC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,UAAU,CAAA;IACvC,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAA;IACnG,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAA;IAC/E,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;AACzE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA4C;IAC5E,OAAO;QACL,SAAS,OAAO,CAAC,GAAG,EAAE;QACtB,mBAAmB,OAAO,CAAC,UAAU,EAAE;QACvC,gBAAgB;QAChB,4BAA4B;KAC7B,CAAA;AACH,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,IAAI,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAA;AAClD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { type PanelChannelMode, type PanelEndpoint } from './endpoint.js';
2
+ import type { AssistantService } from '../services/assistantService.js';
3
+ export interface PanelServerOptions {
4
+ service: AssistantService;
5
+ memoryBucket: string;
6
+ /** 给人看的一句话:这个桶是不是与微信共用的,以及为什么。界面要显示它 */
7
+ memoryNote?: string;
8
+ channel: PanelChannelMode;
9
+ port?: number;
10
+ onLog?: (line: string) => void;
11
+ }
12
+ export interface PanelServer {
13
+ port: number;
14
+ endpoint: PanelEndpoint;
15
+ close: () => Promise<void>;
16
+ }
17
+ /** 只认本机来源。带 Origin 就必须对得上;不带 Origin 放行(curl / file:// 的 Electron) */
18
+ export declare function isLocalOrigin(origin: string | undefined, port: number): boolean;
19
+ /**
20
+ * 起端点。返回**实际**监听的端口——调用方要把它写进端点文件,不要用请求的那个值。
21
+ */
22
+ export declare function startPanelServer(options: PanelServerOptions): Promise<PanelServer>;
23
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/panel/server.ts"],"names":[],"mappings":"AA+BA,OAAO,EAEU,KAAK,gBAAgB,EAAE,KAAK,aAAa,EACzD,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,iCAAiC,CAAA;AAyCpF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,gBAAgB,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAYD,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/E;AAyED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CA8NxF"}