mn-ws 0.1.0 → 0.2.1

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 (178) hide show
  1. package/assets/groups.json +10 -0
  2. package/assets/mn-ws/SKILL.md +55 -0
  3. package/assets/mn-ws/hooks.json +14 -0
  4. package/assets/mn-ws/install/inject-root.mjs +26 -0
  5. package/bin/ws.mjs +13 -0
  6. package/dist/core/auth.d.ts +194 -0
  7. package/dist/core/auth.d.ts.map +1 -0
  8. package/dist/core/auth.js +331 -0
  9. package/dist/core/auth.js.map +1 -0
  10. package/dist/core/brand.d.ts +11 -0
  11. package/dist/core/brand.d.ts.map +1 -0
  12. package/dist/core/brand.js +7 -0
  13. package/dist/core/brand.js.map +1 -0
  14. package/dist/core/bridge.d.ts +106 -0
  15. package/dist/core/bridge.d.ts.map +1 -0
  16. package/dist/core/bridge.js +308 -0
  17. package/dist/core/bridge.js.map +1 -0
  18. package/dist/core/config.d.ts +174 -0
  19. package/dist/core/config.d.ts.map +1 -0
  20. package/dist/core/config.js +417 -0
  21. package/dist/core/config.js.map +1 -0
  22. package/dist/core/controller.d.ts +64 -0
  23. package/dist/core/controller.d.ts.map +1 -0
  24. package/dist/core/controller.js +100 -0
  25. package/dist/core/controller.js.map +1 -0
  26. package/dist/core/errors/index.d.ts +30 -0
  27. package/dist/core/errors/index.d.ts.map +1 -0
  28. package/dist/core/errors/index.js +88 -0
  29. package/dist/core/errors/index.js.map +1 -0
  30. package/dist/core/open.d.ts +3 -0
  31. package/dist/core/open.d.ts.map +1 -0
  32. package/dist/core/open.js +27 -0
  33. package/dist/core/open.js.map +1 -0
  34. package/dist/core/paths.d.ts +15 -0
  35. package/dist/core/paths.d.ts.map +1 -0
  36. package/dist/core/paths.js +50 -0
  37. package/dist/core/paths.js.map +1 -0
  38. package/dist/core/serve-port.d.ts +73 -0
  39. package/dist/core/serve-port.d.ts.map +1 -0
  40. package/dist/core/serve-port.js +134 -0
  41. package/dist/core/serve-port.js.map +1 -0
  42. package/dist/core/session.d.ts +78 -0
  43. package/dist/core/session.d.ts.map +1 -0
  44. package/dist/core/session.js +124 -0
  45. package/dist/core/session.js.map +1 -0
  46. package/dist/core/skills/bus.d.ts +29 -0
  47. package/dist/core/skills/bus.d.ts.map +1 -0
  48. package/dist/core/skills/bus.js +114 -0
  49. package/dist/core/skills/bus.js.map +1 -0
  50. package/dist/core/skills/get.d.ts +17 -0
  51. package/dist/core/skills/get.d.ts.map +1 -0
  52. package/dist/core/skills/get.js +87 -0
  53. package/dist/core/skills/get.js.map +1 -0
  54. package/dist/core/skills/handlers.d.ts +22 -0
  55. package/dist/core/skills/handlers.d.ts.map +1 -0
  56. package/dist/core/skills/handlers.js +86 -0
  57. package/dist/core/skills/handlers.js.map +1 -0
  58. package/dist/core/skills/index.d.ts +47 -0
  59. package/dist/core/skills/index.d.ts.map +1 -0
  60. package/dist/core/skills/index.js +268 -0
  61. package/dist/core/skills/index.js.map +1 -0
  62. package/dist/core/skills/install.d.ts +18 -0
  63. package/dist/core/skills/install.d.ts.map +1 -0
  64. package/dist/core/skills/install.js +123 -0
  65. package/dist/core/skills/install.js.map +1 -0
  66. package/dist/core/skills/text-util.d.ts +2 -0
  67. package/dist/core/skills/text-util.d.ts.map +1 -0
  68. package/dist/core/skills/text-util.js +14 -0
  69. package/dist/core/skills/text-util.js.map +1 -0
  70. package/dist/core/store.d.ts +29 -0
  71. package/dist/core/store.d.ts.map +1 -0
  72. package/dist/core/store.js +100 -0
  73. package/dist/core/store.js.map +1 -0
  74. package/dist/core/views.d.ts +11 -0
  75. package/dist/core/views.d.ts.map +1 -0
  76. package/dist/core/views.js +20 -0
  77. package/dist/core/views.js.map +1 -0
  78. package/dist/index.d.ts +6 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +8 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/modules/auth/index.d.ts +73 -0
  83. package/dist/modules/auth/index.d.ts.map +1 -0
  84. package/dist/modules/auth/index.js +64 -0
  85. package/dist/modules/auth/index.js.map +1 -0
  86. package/dist/modules/auth/service.d.ts +98 -0
  87. package/dist/modules/auth/service.d.ts.map +1 -0
  88. package/dist/modules/auth/service.js +200 -0
  89. package/dist/modules/auth/service.js.map +1 -0
  90. package/dist/modules/bridge/index.d.ts +73 -0
  91. package/dist/modules/bridge/index.d.ts.map +1 -0
  92. package/dist/modules/bridge/index.js +89 -0
  93. package/dist/modules/bridge/index.js.map +1 -0
  94. package/dist/modules/bridge/service.d.ts +75 -0
  95. package/dist/modules/bridge/service.d.ts.map +1 -0
  96. package/dist/modules/bridge/service.js +134 -0
  97. package/dist/modules/bridge/service.js.map +1 -0
  98. package/dist/modules/home/index.d.ts +95 -0
  99. package/dist/modules/home/index.d.ts.map +1 -0
  100. package/dist/modules/home/index.js +123 -0
  101. package/dist/modules/home/index.js.map +1 -0
  102. package/dist/modules/home/service.d.ts +48 -0
  103. package/dist/modules/home/service.d.ts.map +1 -0
  104. package/dist/modules/home/service.js +195 -0
  105. package/dist/modules/home/service.js.map +1 -0
  106. package/dist/modules/skill/index.d.ts +78 -0
  107. package/dist/modules/skill/index.d.ts.map +1 -0
  108. package/dist/modules/skill/index.js +132 -0
  109. package/dist/modules/skill/index.js.map +1 -0
  110. package/dist/runtime/api.d.ts +24 -0
  111. package/dist/runtime/api.d.ts.map +1 -0
  112. package/dist/runtime/api.js +140 -0
  113. package/dist/runtime/api.js.map +1 -0
  114. package/dist/runtime/cli.d.ts +23 -0
  115. package/dist/runtime/cli.d.ts.map +1 -0
  116. package/dist/runtime/cli.js +410 -0
  117. package/dist/runtime/cli.js.map +1 -0
  118. package/dist/runtime/help.d.ts +29 -0
  119. package/dist/runtime/help.d.ts.map +1 -0
  120. package/dist/runtime/help.js +89 -0
  121. package/dist/runtime/help.js.map +1 -0
  122. package/dist/runtime/registry.d.ts +318 -0
  123. package/dist/runtime/registry.d.ts.map +1 -0
  124. package/dist/runtime/registry.js +75 -0
  125. package/dist/runtime/registry.js.map +1 -0
  126. package/dist/runtime/server.d.ts +10 -0
  127. package/dist/runtime/server.d.ts.map +1 -0
  128. package/dist/runtime/server.js +127 -0
  129. package/dist/runtime/server.js.map +1 -0
  130. package/dist/runtime/spec.d.ts +32 -0
  131. package/dist/runtime/spec.d.ts.map +1 -0
  132. package/dist/runtime/spec.js +180 -0
  133. package/dist/runtime/spec.js.map +1 -0
  134. package/dist/runtime/types/action.d.ts +101 -0
  135. package/dist/runtime/types/action.d.ts.map +1 -0
  136. package/dist/runtime/types/action.js +19 -0
  137. package/dist/runtime/types/action.js.map +1 -0
  138. package/dist/runtime/types/client.d.ts +39 -0
  139. package/dist/runtime/types/client.d.ts.map +1 -0
  140. package/dist/runtime/types/client.js +2 -0
  141. package/dist/runtime/types/client.js.map +1 -0
  142. package/dist/runtime/types/http.d.ts +22 -0
  143. package/dist/runtime/types/http.d.ts.map +1 -0
  144. package/dist/runtime/types/http.js +6 -0
  145. package/dist/runtime/types/http.js.map +1 -0
  146. package/dist/runtime/types/module.d.ts +72 -0
  147. package/dist/runtime/types/module.d.ts.map +1 -0
  148. package/dist/runtime/types/module.js +15 -0
  149. package/dist/runtime/types/module.js.map +1 -0
  150. package/dist/web/public/assets/CliHints-BOxU-Duc.js +1 -0
  151. package/dist/web/public/assets/index-BTRKdMIW.js +50 -0
  152. package/dist/web/public/assets/index-BjGe8ggI.css +1 -0
  153. package/dist/web/public/assets/view-CE4tnCuy.js +1 -0
  154. package/dist/web/public/assets/view-CEQ2uPxE.js +1 -0
  155. package/dist/web/public/favicon-16.png +0 -0
  156. package/dist/web/public/favicon-32.png +0 -0
  157. package/dist/web/public/favicon-48.png +0 -0
  158. package/dist/web/public/favicon.ico +0 -0
  159. package/dist/web/public/index.html +19 -0
  160. package/dist/web/public/logo-rounded.png +0 -0
  161. package/dist/web/public/logo-rounded.svg +6 -0
  162. package/dist/web/public/logo.png +0 -0
  163. package/dist/web/public/logo.svg +6 -0
  164. package/package.json +56 -35
  165. package/README.md +0 -251
  166. package/bin/index.js +0 -714
  167. package/client/bridge-client.js +0 -160
  168. package/client/web.js +0 -234
  169. package/client/ws-client.js +0 -191
  170. package/lib/apps.js +0 -237
  171. package/lib/auth.js +0 -319
  172. package/lib/config.js +0 -534
  173. package/lib/index.js +0 -15
  174. package/lib/logger.js +0 -63
  175. package/lib/protocol.js +0 -208
  176. package/lib/store.js +0 -66
  177. package/server/auth.js +0 -274
  178. package/server/server.js +0 -752
@@ -0,0 +1,195 @@
1
+ // home 域业务逻辑:演示业务动作(greet)+ 本机设置读写与**严格校验**。
2
+ //
3
+ // 本模块同时承担两件事:
4
+ // ① 一个演示业务动作(greet)——演示「面板操作 → 状态落盘」闭环;
5
+ // ② 本机设置的读写与**严格校验**(主题、头部导航:分组 / 隐藏 / 平铺顺序)。
6
+ //
7
+ // 为什么「首页」和「设置」合成一个模块:这两块都是「关于这个应用本身」的内容,
8
+ // 拆成两个模块,初始就凭空多出一个只有 meta 信息的空壳页。合成一个模块,
9
+ // 每一个出厂模块都有真实内容。
10
+ import { loadStore, mutateStore } from '../../core/store.js';
11
+ import { VIEWS_META, viewMetaOf } from '../../core/views.js';
12
+ import { badInput, notFound } from '../../core/errors/index.js';
13
+ // 打个招呼,并把问候次数累计进本机存储——演示「面板操作 → 状态落盘」闭环。
14
+ //
15
+ // 走 mutateStore 读-改-写事务:计数 +1 与落盘是一个原子动作,
16
+ // 两个并发请求不会丢计数,函数抛错则半个事务不会写进磁盘。
17
+ export async function greet(name, loud = false) {
18
+ const t = await mutateStore((s) => {
19
+ const count = Number(s.greetCount || 0) + 1;
20
+ s.greetCount = count;
21
+ return count;
22
+ });
23
+ const count = Number(t);
24
+ let greeting = `你好,${name}!这是第 ${count} 次问候。`;
25
+ if (loud)
26
+ greeting = greeting.toUpperCase();
27
+ return { greeting, name, count, at: new Date().toISOString() };
28
+ }
29
+ /** 已知设置项 → 校验器 + 说明(面板据此提示)。 */
30
+ const SCHEMA = {
31
+ navGroups: { hint: '头部导航分组:[{title, views:[页面id…]}],数组顺序 = 显示顺序', coerce: coerceNavGroups },
32
+ navHidden: { hint: '隐藏的页面 id(入口不显示,直达仍可用)', coerce: coerceNavHidden },
33
+ navOrder: { hint: '平铺区的显示顺序(页面 id 数组;没列进去的按页面自身顺序跟在后面)', coerce: coerceNavOrder },
34
+ theme: { hint: '色彩主题:light(浅色)/ dark(深色)/ auto(跟随系统)', coerce: coerceTheme },
35
+ };
36
+ /** 主题白名单:只认 light / dark / auto,别的一律拒绝。 */
37
+ function coerceTheme(value) {
38
+ const t = String(value ?? '').trim().toLowerCase();
39
+ if (!['light', 'dark', 'auto'].includes(t)) {
40
+ throw badInput('主题只能是 light / dark / auto,收到: ' + String(value));
41
+ }
42
+ return t;
43
+ }
44
+ /**
45
+ * 「页面 id 清单」校验(隐藏清单 / 平铺顺序共用):每一项都必须是真实存在的页面;
46
+ * 去重保序,并归一成真实 id。label 只影响报错措辞。
47
+ * 三种写法都吃:数组(面板)、`a,b`(CLI 省事写法)、`["a","b"]`(CLI 的 JSON 写法)。
48
+ */
49
+ function coerceIdList(value, label) {
50
+ let raw = value;
51
+ if (typeof raw === 'string') {
52
+ const s = raw.trim();
53
+ if (s.startsWith('[')) {
54
+ try {
55
+ raw = JSON.parse(s);
56
+ }
57
+ catch (e) {
58
+ throw badInput(`${label}需要 JSON 数组或逗号分隔:${e.message}`);
59
+ }
60
+ }
61
+ }
62
+ const list = Array.isArray(raw) ? raw : String(raw ?? '').split(',');
63
+ const out = [];
64
+ for (const item of list) {
65
+ const id = String(item ?? '').trim();
66
+ if (!id)
67
+ continue;
68
+ if (!viewMetaOf(id))
69
+ throw badInput(`${label}里的页面不存在: ${id}`);
70
+ if (!out.includes(id))
71
+ out.push(id);
72
+ }
73
+ return out;
74
+ }
75
+ // 函数声明(会提升):SCHEMA 在模块顶层引用它们,const 箭头函数会踩 TDZ
76
+ function coerceNavHidden(value) {
77
+ return coerceIdList(value, '隐藏清单');
78
+ }
79
+ function coerceNavOrder(value) {
80
+ return coerceIdList(value, '平铺顺序');
81
+ }
82
+ /** 分组校验 + 归一:组名非空、页面必须存在、组内去重、跨组重复拒绝、空组拒绝。 */
83
+ function coerceNavGroups(value) {
84
+ let arr = value;
85
+ if (typeof arr === 'string') {
86
+ try {
87
+ arr = JSON.parse(arr);
88
+ }
89
+ catch (e) {
90
+ throw badInput(`navGroups 需要 JSON 数组(${e.message}):[{"title":"求职","views":["home"]}, …]`);
91
+ }
92
+ }
93
+ if (!Array.isArray(arr)) {
94
+ throw badInput('navGroups 需要是数组:[{"title":"求职","views":["home"]}, …]');
95
+ }
96
+ const owner = new Map();
97
+ return arr.map((raw, i) => {
98
+ if (!raw || typeof raw !== 'object')
99
+ throw badInput(`第 ${i + 1} 个分组不是对象`);
100
+ const g = raw;
101
+ const title = String(g.title ?? '').trim();
102
+ if (!title)
103
+ throw badInput(`第 ${i + 1} 个分组缺少 title(组名)`);
104
+ const views = [];
105
+ for (const item of Array.isArray(g.views) ? g.views : []) {
106
+ const id = String(item ?? '').trim();
107
+ if (!id || views.includes(id))
108
+ continue; // 组内重复(或空串)直接去重
109
+ if (!viewMetaOf(id))
110
+ throw badInput(`分组「${title}」里的页面不存在: ${id}`);
111
+ const ownerTitle = owner.get(id);
112
+ if (ownerTitle)
113
+ throw badInput(`页面 ${id} 同时在分组「${ownerTitle}」与「${title}」里——一个页面只能属于一个分组`);
114
+ owner.set(id, title);
115
+ views.push(id);
116
+ }
117
+ if (!views.length)
118
+ throw badInput(`分组「${title}」没有任何页面——要么加一个,要么删掉这个分组`);
119
+ return { title, views };
120
+ });
121
+ }
122
+ export async function getSettings() {
123
+ const store = await loadStore();
124
+ return {
125
+ settings: store.settings,
126
+ views: VIEWS_META.map((v) => ({ ...v })),
127
+ schema: Object.entries(SCHEMA).map(([key, s]) => ({ key, hint: s.hint })),
128
+ };
129
+ }
130
+ /**
131
+ * PATCH 语义:只改传入的项。
132
+ * 返回 `{ settings }` 的**最新全量**(面板保存后直接拿来刷新头部)。
133
+ */
134
+ export async function setSettings(input) {
135
+ const patch = { ...(input.set || {}) };
136
+ if (input.key !== undefined)
137
+ patch[input.key] = input.value;
138
+ const keys = Object.keys(patch);
139
+ if (!keys.length)
140
+ throw badInput('至少要给一项:setting set --key <名> --value <值>,或 --set k=v(可重复)');
141
+ const resolved = {};
142
+ for (const k of keys) {
143
+ const spec = SCHEMA[k];
144
+ if (!spec)
145
+ throw notFound(`未知设置项: ${k}(可用: ${Object.keys(SCHEMA).join(', ')})`);
146
+ resolved[k] = spec.coerce(patch[k]);
147
+ }
148
+ if (input['dry-run'])
149
+ return { status: 'skipped', dryRun: true, wouldSet: resolved };
150
+ const after = (await mutateStore((s) => {
151
+ const settings = s.settings;
152
+ for (const [k, v] of Object.entries(resolved))
153
+ settings[k] = v;
154
+ return { ...settings };
155
+ }));
156
+ return { status: 'ok', settings: after };
157
+ }
158
+ export function renderSettings(d) {
159
+ const hidden = new Set(d.settings.navHidden || []);
160
+ const lines = [`当前设置(改:mn-ws setting set --set k=v)· 主题: ${d.settings.theme || 'light'}`];
161
+ for (const s of d.schema)
162
+ lines.push(` ${s.key.padEnd(12)} ${s.hint}`);
163
+ lines.push('', `页面(${d.views.length})· 隐藏 ${hidden.size} 个`);
164
+ for (const v of d.views) {
165
+ lines.push(` ${v.id.padEnd(12)} ${v.title.padEnd(10)} ${hidden.has(v.id) ? '隐藏' : '显示'}`);
166
+ }
167
+ const order = d.settings.navOrder || [];
168
+ const ranked = order.filter((id) => d.views.some((v) => v.id === id));
169
+ if (ranked.length)
170
+ lines.push(`平铺顺序(前 ${ranked.length} 个已显式排序): ${ranked.join(' → ')}`);
171
+ const groups = d.settings.navGroups || [];
172
+ if (!groups.length) {
173
+ lines.push('', '分组:无(全部页面平铺在头部)');
174
+ }
175
+ else {
176
+ lines.push('', `分组(${groups.length})· 组顺序 = 头部顺序,组内顺序 = 展开列表顺序`);
177
+ for (const g of groups)
178
+ lines.push(` ${g.title}: ${g.views.join(' → ')}`);
179
+ }
180
+ lines.push('', '例:mn-ws setting set --set \'navGroups=[{"title":"求职","views":["home"]}]\' --dry-run');
181
+ return lines.join('\n');
182
+ }
183
+ export function renderSettingSet(d) {
184
+ if (d.status === 'skipped')
185
+ return `试运行(未落盘):将写入 ${JSON.stringify(d.wouldSet)}`;
186
+ const groups = d.settings?.navGroups || [];
187
+ const hidden = d.settings?.navHidden || [];
188
+ const lines = [`已更新设置:${groups.length} 个导航分组,隐藏 ${hidden.length} 个页面`];
189
+ for (const g of groups)
190
+ lines.push(` ${g.title}: ${g.views.join(' → ')}`);
191
+ if (hidden.length)
192
+ lines.push(` 隐藏: ${hidden.join(', ')}`);
193
+ return lines.join('\n');
194
+ }
195
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/modules/home/service.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,cAAc;AACd,0CAA0C;AAC1C,gDAAgD;AAChD,EAAE;AACF,yCAAyC;AACzC,yCAAyC;AACzC,iBAAiB;AACjB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAWhE,yCAAyC;AACzC,EAAE;AACF,0CAA0C;AAC1C,+BAA+B;AAC/B,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAY,EAAE,IAAI,GAAG,KAAK;IACpD,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,QAAQ,GAAG,MAAM,IAAI,QAAQ,KAAK,OAAO,CAAC;IAC9C,IAAI,IAAI;QAAE,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AACjE,CAAC;AAWD,gCAAgC;AAChC,MAAM,MAAM,GAAsE;IAChF,SAAS,EAAE,EAAE,IAAI,EAAE,6CAA6C,EAAE,MAAM,EAAE,eAAe,EAAE;IAC3F,SAAS,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,eAAe,EAAE;IACrE,QAAQ,EAAE,EAAE,IAAI,EAAE,qCAAqC,EAAE,MAAM,EAAE,cAAc,EAAE;IACjF,KAAK,EAAE,EAAE,IAAI,EAAE,sCAAsC,EAAE,MAAM,EAAE,WAAW,EAAE;CAC7E,CAAC;AAEF,2CAA2C;AAC3C,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnD,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,QAAQ,CAAC,gCAAgC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,KAAc,EAAE,KAAa;IACjD,IAAI,GAAG,GAAY,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,QAAQ,CAAC,GAAG,KAAK,mBAAoB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAAE,MAAM,QAAQ,CAAC,GAAG,KAAK,YAAY,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8CAA8C;AAC9C,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,8CAA8C;AAC9C,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,GAAG,GAAY,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,QAAQ,CAAC,wBAAyB,CAAW,CAAC,OAAO,wCAAwC,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,QAAQ,CAAC,sDAAsD,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,MAAM,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1E,MAAM,CAAC,GAAG,GAA2C,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK;YAAE,MAAM,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACzD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACzD,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAAE,SAAS,CAAC,gBAAgB;YACzD,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBAAE,MAAM,QAAQ,CAAC,MAAM,KAAK,aAAa,EAAE,EAAE,CAAC,CAAC;YAClE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,UAAU;gBAAE,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,UAAU,MAAM,KAAK,kBAAkB,CAAC,CAAC;YAC1F,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,QAAQ,CAAC,MAAM,KAAK,yBAAyB,CAAC,CAAC;QACxE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAKjC;IAIC,MAAM,KAAK,GAA4B,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;IAChE,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAE5D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,MAAM,QAAQ,CAAC,2DAA2D,CAAC,CAAC;IAE9F,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI;YAAE,MAAM,QAAQ,CAAC,UAAU,CAAC,QAAQ,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChF,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAErF,MAAM,KAAK,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAoB,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAG,QAAoC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5F,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC,CAAC,CAAa,CAAC;IAEhB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAe;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,CAAC,4CAA4C,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1F,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAExE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,MAAM,aAAa,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAExF,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,MAAM,CAAC,MAAM,6BAA6B,CAAC,CAAC;QACjE,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,qFAAqF,CAAC,CAAC;IACtG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAKhC;IACC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IAChF,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,IAAI,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,IAAI,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,SAAS,MAAM,CAAC,MAAM,aAAa,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,78 @@
1
+ import * as skills from '../../core/skills/index.js';
2
+ declare const _default: {
3
+ readonly id: "skill";
4
+ readonly title: "Skill";
5
+ readonly order: 20;
6
+ readonly actions: readonly [import("../../runtime/types/action.js").TypedAction<{
7
+ readonly id: "skill.list";
8
+ readonly cli: readonly ["skill", "list"];
9
+ readonly http: readonly ["GET", "/api/skills"];
10
+ readonly summary: "列出可装的 skill 与 group";
11
+ }, {
12
+ skills: string[];
13
+ groups: string[];
14
+ defaultGroup: string | null;
15
+ source: "manifest" | "assets-dirs";
16
+ }>, import("../../runtime/types/action.js").TypedAction<{
17
+ readonly id: "skill.groups";
18
+ readonly cli: readonly ["skill", "groups"];
19
+ readonly http: readonly ["GET", "/api/skill-groups"];
20
+ readonly summary: "列出每个 group 含哪些 skill";
21
+ }, {
22
+ source: "manifest" | "assets-dirs";
23
+ groups: Record<string, skills.GroupSpec>;
24
+ warning: string | undefined;
25
+ }>, import("../../runtime/types/action.js").TypedAction<{
26
+ readonly id: "skill.get";
27
+ readonly cli: readonly ["skill", "get"];
28
+ readonly http: readonly ["GET", "/api/skill-content"];
29
+ readonly summary: "导出 skill 文档(并幂等安装)";
30
+ readonly args: readonly [{
31
+ readonly name: "name";
32
+ readonly required: false;
33
+ }, {
34
+ readonly name: "ref";
35
+ readonly required: false;
36
+ }];
37
+ readonly flags: {
38
+ readonly to: {
39
+ readonly type: "string";
40
+ };
41
+ readonly force: {
42
+ readonly type: "boolean";
43
+ };
44
+ };
45
+ }, {
46
+ skillName: string;
47
+ ref: string;
48
+ contentBytes: number;
49
+ prefix: string;
50
+ content: string;
51
+ installStatus: string;
52
+ }>, import("../../runtime/types/action.js").TypedAction<{
53
+ readonly id: "skill.install";
54
+ readonly cli: readonly ["skill", "install"];
55
+ readonly http: readonly ["POST", "/api/skill-install"];
56
+ readonly summary: "安装 skill、整组 skill 或全部 skill";
57
+ readonly args: readonly [{
58
+ readonly name: "name";
59
+ readonly required: false;
60
+ }];
61
+ readonly flags: {
62
+ readonly all: {
63
+ readonly type: "boolean";
64
+ };
65
+ readonly group: {
66
+ readonly type: "string";
67
+ };
68
+ readonly to: {
69
+ readonly type: "string";
70
+ };
71
+ readonly force: {
72
+ readonly type: "boolean";
73
+ };
74
+ };
75
+ }, skills.InstallResult | skills.GroupInstallResult>];
76
+ };
77
+ export default _default;
78
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/skill/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIrD,wBAmIG"}
@@ -0,0 +1,132 @@
1
+ // skill 域:管理随包分发的多 skill(主 skill 与可选配套 skill)。
2
+ // 平台级能力,action 只做 I/O 编排;发现/分组/安装/导出的真相在 core/skills*.ts。
3
+ import { defineAction } from '../../runtime/types/action.js';
4
+ import { defineModule } from '../../runtime/types/module.js';
5
+ import * as skills from '../../core/skills/index.js';
6
+ import * as skillsGet from '../../core/skills/get.js';
7
+ import { badInput } from '../../core/errors/index.js';
8
+ export default defineModule({
9
+ id: 'skill',
10
+ title: 'Skill',
11
+ order: 20,
12
+ actions: [
13
+ defineAction({
14
+ id: 'skill.list',
15
+ cli: ['skill', 'list'],
16
+ http: ['GET', '/api/skills'],
17
+ summary: '列出可装的 skill 与 group',
18
+ })(async () => {
19
+ const [names, manifest] = await Promise.all([
20
+ skills.bundledSkillNames(),
21
+ skills.loadGroups(),
22
+ ]);
23
+ return {
24
+ skills: names,
25
+ groups: Object.keys(manifest.groups),
26
+ defaultGroup: manifest.defaultGroup,
27
+ source: manifest.source,
28
+ };
29
+ }, (r) => {
30
+ const lines = ['可装的 skill:'];
31
+ for (const n of r.skills)
32
+ lines.push(' ' + n + (n === r.defaultGroup ? ' (默认 install)' : ''));
33
+ lines.push('可装的 group:');
34
+ for (const g of r.groups)
35
+ lines.push(' ' + g + (g === r.defaultGroup ? ' (默认)' : ''));
36
+ return lines.join('\n');
37
+ }),
38
+ defineAction({
39
+ id: 'skill.groups',
40
+ cli: ['skill', 'groups'],
41
+ http: ['GET', '/api/skill-groups'],
42
+ summary: '列出每个 group 含哪些 skill',
43
+ })(async () => {
44
+ const manifest = await skills.loadGroups();
45
+ return { source: manifest.source, groups: manifest.groups, warning: manifest.warning };
46
+ }, (r) => {
47
+ const lines = [];
48
+ for (const [key, g] of Object.entries(r.groups)) {
49
+ lines.push(` ${key.padEnd(12)} [${g.skills.join(', ')}]${g.summary ? ' ' + g.summary : ''}`);
50
+ }
51
+ if (r.warning)
52
+ lines.push('', '⚠ ' + r.warning);
53
+ return `group 清单(来源: ${r.source})\n` + lines.join('\n');
54
+ }),
55
+ defineAction({
56
+ id: 'skill.get',
57
+ cli: ['skill', 'get'],
58
+ http: ['GET', '/api/skill-content'],
59
+ summary: '导出 skill 文档(并幂等安装)',
60
+ args: [
61
+ { name: 'name', required: false },
62
+ { name: 'ref', required: false },
63
+ ],
64
+ flags: {
65
+ to: { type: 'string' },
66
+ force: { type: 'boolean' },
67
+ },
68
+ })(async (ctx) => {
69
+ const result = await skillsGet.getSkill(ctx.name || 'mn-ws', {
70
+ ref: ctx.ref,
71
+ to: ctx.to,
72
+ force: ctx.force,
73
+ });
74
+ return {
75
+ skillName: result.skillName,
76
+ ref: result.ref,
77
+ contentBytes: result.contentBytes,
78
+ prefix: skillsGet.skillGetPrefix(result.skillName, result.ref),
79
+ content: result.content,
80
+ installStatus: skillsGet.installStatusLine(result.install),
81
+ };
82
+ },
83
+ // 人读模式:前缀 → 全文 → 安装状态,三段拼接。
84
+ (r) => [r.prefix, r.content, '', r.installStatus].join('\n')),
85
+ defineAction({
86
+ id: 'skill.install',
87
+ cli: ['skill', 'install'],
88
+ http: ['POST', '/api/skill-install'],
89
+ summary: '安装 skill、整组 skill 或全部 skill',
90
+ args: [{ name: 'name', required: false }],
91
+ flags: {
92
+ all: { type: 'boolean' },
93
+ group: { type: 'string' },
94
+ to: { type: 'string' },
95
+ force: { type: 'boolean' },
96
+ },
97
+ })(async (ctx) => {
98
+ const opts = { to: ctx.to, force: ctx.force };
99
+ if (ctx.name && ctx.group) {
100
+ throw badInput('位置参数 name 与 --group 互斥,只能给一个');
101
+ }
102
+ if (ctx.all && (ctx.name || ctx.group)) {
103
+ throw badInput('--all 与 name / --group 互斥,它会安装全部 skill');
104
+ }
105
+ if (ctx.all)
106
+ return skills.installAll(opts);
107
+ if (ctx.group)
108
+ return skills.installGroup(ctx.group, opts);
109
+ return skills.installOne(ctx.name || 'mn-ws', opts);
110
+ }, (r) => {
111
+ if ('group' in r && Array.isArray(r.skills)) {
112
+ const g = r;
113
+ const label = g.group === '*' ? '全部 skill' : `group ${g.group}`;
114
+ if (g.status === 'conflict') {
115
+ return `${label} 有冲突(未安装任何文件):\n` +
116
+ g.skills.map((x) => ` 冲突: ${x.path}(${x.files} 个文件不同)`).join('\n') +
117
+ '\n确认覆盖: 加 --force';
118
+ }
119
+ return `${label} 已安装:\n` +
120
+ g.skills.map((x) => ` ${x.status === 'skipped' ? '已是最新' : '已安装'}: ${x.path}`).join('\n');
121
+ }
122
+ const x = r;
123
+ if (x.status === 'conflict') {
124
+ return `冲突: ${x.path}(${x.files} 个文件不同);确认覆盖加 --force`;
125
+ }
126
+ if (x.status === 'skipped')
127
+ return `已是最新: ${x.path}`;
128
+ return `${x.replaced ? '已替换' : '已安装'}: ${x.path}(${x.files} 个文件)`;
129
+ }),
130
+ ],
131
+ });
132
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/skill/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ /**
3
+ * 登录门禁。
4
+ *
5
+ * 返回 null = 放行;返回对象 = 拒绝(status + error)。
6
+ *
7
+ * 为什么门禁在**服务端**:面板握着桥的凭据,能连 server、能改白名单。
8
+ * 门禁只做在前端(藏个按钮)的话,任何本机进程照样能直接调 API。
9
+ *
10
+ * 豁免的路径是「看一眼登录态」与「发起登录」这两条 —— 它们不返回敏感数据,
11
+ * 而且前端必须能先问一句「我登录了吗」才知道该渲染登录页还是主界面。
12
+ */
13
+ export interface ApiDenial {
14
+ status: number;
15
+ error: string;
16
+ }
17
+ export type ApiGate = (pathname: string, method: string) => ApiDenial | null;
18
+ /** 装上门禁(由 runtime/server 在起服务时调用)。传 null = 不设门禁。 */
19
+ export declare function setApiGate(gate: ApiGate | null): void;
20
+ /** 默认门禁:未登录一律 401,只有「问登录态」与「发起登录」放行。 */
21
+ export declare function defaultApiGate(isLoggedIn: () => boolean): ApiGate;
22
+ export declare function sendJson(res: ServerResponse, status: number, obj: unknown): void;
23
+ export declare function handleApi(req: IncomingMessage, res: ServerResponse, url: URL): Promise<void>;
24
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/runtime/api.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA+CjE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,CAAC;AAI7E,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAErD;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,OAAO,GAAG,OAAO,CAOjE;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAMhF;AA4BD,wBAAsB,SAAS,CAC7B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,IAAI,CAAC,CAoDf"}
@@ -0,0 +1,140 @@
1
+ import { compileRoute, applySpec } from './spec.js';
2
+ import { toErrorPayload, httpStatusOf, CODES } from '../core/errors/index.js';
3
+ import { ACTIONS } from './registry.js';
4
+ // 逐段比较两条模式,决定谁该先匹配:**字面量段优先于参数段**,段数多的优先。
5
+ //
6
+ // 为什么要排序而不是按声明顺序:`GET /api/repos/status` 与 `GET /api/repos/:id`
7
+ // 都能匹配 `/api/repos/status`,谁先声明谁赢。一旦有人调整 actions 顺序,
8
+ // 前者就会被后者抢走——这种 bug 只在运行时、且只在特定路径上出现,极难排查。
9
+ //
10
+ // 正确比较:算"前 N 段里**字面量段**的总个数",多者优先;同字数时
11
+ // 按"从左到右遇到的第一处分歧段"——字面量胜出。
12
+ function routeSpecificity(pattern) {
13
+ return pattern.split('/').filter(Boolean);
14
+ }
15
+ function compareRoutes(a, b) {
16
+ const pa = routeSpecificity(a.action.http[1]);
17
+ const pb = routeSpecificity(b.action.http[1]);
18
+ const litA = pa.filter((s) => !s.startsWith(':')).length;
19
+ const litB = pb.filter((s) => !s.startsWith(':')).length;
20
+ if (litA !== litB)
21
+ return litB - litA; // 字面量段越多越具体
22
+ if (pa.length !== pb.length)
23
+ return pb.length - pa.length;
24
+ for (let i = 0; i < pa.length; i++) {
25
+ const litA2 = !pa[i].startsWith(':');
26
+ const litB2 = !pb[i].startsWith(':');
27
+ if (litA2 !== litB2)
28
+ return litA2 ? -1 : 1;
29
+ }
30
+ return 0;
31
+ }
32
+ const ROUTES = ACTIONS.filter((a) => a.http)
33
+ .map((action) => ({
34
+ action,
35
+ route: compileRoute(action),
36
+ }))
37
+ .sort(compareRoutes);
38
+ let apiGate = null;
39
+ /** 装上门禁(由 runtime/server 在起服务时调用)。传 null = 不设门禁。 */
40
+ export function setApiGate(gate) {
41
+ apiGate = gate;
42
+ }
43
+ /** 默认门禁:未登录一律 401,只有「问登录态」与「发起登录」放行。 */
44
+ export function defaultApiGate(isLoggedIn) {
45
+ const EXEMPT = new Set(['/api/auth/status', '/api/auth/login/start', '/api/bootstrap']);
46
+ return (pathname, method) => {
47
+ if (EXEMPT.has(pathname))
48
+ return null;
49
+ if (isLoggedIn())
50
+ return null;
51
+ return { status: 401, error: 'not_logged_in' };
52
+ };
53
+ }
54
+ export function sendJson(res, status, obj) {
55
+ res.writeHead(status, {
56
+ 'content-type': 'application/json; charset=utf-8',
57
+ 'cache-control': 'no-store',
58
+ });
59
+ res.end(JSON.stringify(obj));
60
+ }
61
+ async function readBody(req) {
62
+ const chunks = [];
63
+ let size = 0;
64
+ for await (const c of req) {
65
+ size += c.length;
66
+ if (size > 4 * 1024 * 1024)
67
+ throw new Error('请求体过大');
68
+ chunks.push(c);
69
+ }
70
+ if (!chunks.length)
71
+ return {};
72
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'));
73
+ }
74
+ // 跨站防护。服务虽然只绑 127.0.0.1,但用户浏览器里的任意页面都能向它发起请求——
75
+ // 少了这道校验,一个恶意网页就能 POST /api/repos/scan 或 DELETE /api/repos/:id。
76
+ // 浏览器发跨域请求必带 Origin,非浏览器客户端(curl / agent / 测试)不带,故放行。
77
+ function originAllowed(req) {
78
+ const origin = req.headers.origin;
79
+ if (!origin)
80
+ return true;
81
+ try {
82
+ const h = new URL(origin).hostname;
83
+ return h === '127.0.0.1' || h === 'localhost' || h === '::1';
84
+ }
85
+ catch {
86
+ return false;
87
+ }
88
+ }
89
+ export async function handleApi(req, res, url) {
90
+ const method = (req.method || 'GET').toUpperCase();
91
+ // ── 登录门禁 ──
92
+ if (apiGate) {
93
+ const denied = apiGate(url.pathname, method);
94
+ if (denied) {
95
+ sendJson(res, denied.status, { ok: false, error: denied.error, code: 'not_logged_in' });
96
+ return;
97
+ }
98
+ }
99
+ for (const { action, route } of ROUTES) {
100
+ if (route.method !== method)
101
+ continue;
102
+ const m = route.regex.exec(url.pathname);
103
+ if (!m)
104
+ continue;
105
+ if (method !== 'GET' && method !== 'HEAD' && !originAllowed(req)) {
106
+ sendJson(res, 403, {
107
+ ok: false,
108
+ error: '跨站请求被拒绝(面板仅接受本机来源)',
109
+ code: CODES.BLOCKED,
110
+ });
111
+ return;
112
+ }
113
+ try {
114
+ const raw = {};
115
+ route.keys.forEach((k, i) => {
116
+ raw[k] = decodeURIComponent(m[i + 1]);
117
+ });
118
+ if (method === 'GET' || method === 'HEAD') {
119
+ for (const [k, v] of url.searchParams)
120
+ raw[k] = v;
121
+ }
122
+ else {
123
+ Object.assign(raw, await readBody(req).catch(() => ({})));
124
+ }
125
+ const data = await action.run(applySpec(action, raw), { transport: 'http' });
126
+ sendJson(res, 200, { ok: true, data });
127
+ }
128
+ catch (err) {
129
+ // 错误码 → HTTP 状态只在这一处映射(core/errors 提供表)
130
+ const p = toErrorPayload(err);
131
+ const payload = { ok: false, error: p.message, code: p.code };
132
+ if (p.details !== undefined)
133
+ payload.details = p.details;
134
+ sendJson(res, httpStatusOf(p.code), payload);
135
+ }
136
+ return;
137
+ }
138
+ sendJson(res, 404, { ok: false, error: '接口不存在: ' + method + ' ' + url.pathname });
139
+ }
140
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/runtime/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ActionShape, ArgEntry, FlagSpec, TransportMeta } from './types/action.js';
2
+ interface AnyCommand {
3
+ id: string;
4
+ module?: string;
5
+ cli?: ActionShape['cli'];
6
+ http?: readonly [string, string] | null;
7
+ summary?: string;
8
+ args?: readonly ArgEntry[];
9
+ flags?: Record<string, FlagSpec>;
10
+ openFlags?: boolean;
11
+ run?: (ctx: Record<string, unknown>, meta?: TransportMeta) => unknown;
12
+ render?: (result: unknown, ctx?: Record<string, unknown>) => unknown;
13
+ }
14
+ export declare const ALL_COMMANDS: AnyCommand[];
15
+ interface CommandHit {
16
+ cmd: AnyCommand;
17
+ path: string[];
18
+ rest: string[];
19
+ }
20
+ export declare function resolveCommand(argv: string[]): CommandHit | null;
21
+ export declare function runCli(argv: string[]): Promise<void>;
22
+ export {};
23
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/runtime/cli.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOxF,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC;IACtE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;CACtE;AAsDD,eAAO,MAAM,YAAY,EAAE,UAAU,EAGpC,CAAC;AAkCF,UAAU,UAAU;IAClB,GAAG,EAAE,UAAU,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAOD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,IAAI,CAahE;AA6PD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD1D"}