@skillfm/local 2.6.4 → 2.7.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 (301) hide show
  1. package/README.md +50 -1
  2. package/dist/_signers/aliyun-v3.d.ts +21 -0
  3. package/dist/_signers/aliyun-v3.d.ts.map +1 -0
  4. package/dist/_signers/aliyun-v3.js +47 -0
  5. package/dist/_signers/aliyun-v3.js.map +1 -0
  6. package/dist/_signers/canonical.d.ts +29 -0
  7. package/dist/_signers/canonical.d.ts.map +1 -0
  8. package/dist/_signers/canonical.js +59 -0
  9. package/dist/_signers/canonical.js.map +1 -0
  10. package/dist/_signers/index.d.ts +9 -0
  11. package/dist/_signers/index.d.ts.map +1 -0
  12. package/dist/_signers/index.js +6 -0
  13. package/dist/_signers/index.js.map +1 -0
  14. package/dist/_signers/tencent-tc3.d.ts +21 -0
  15. package/dist/_signers/tencent-tc3.d.ts.map +1 -0
  16. package/dist/_signers/tencent-tc3.js +48 -0
  17. package/dist/_signers/tencent-tc3.js.map +1 -0
  18. package/dist/_signers/volc-v4.d.ts +18 -0
  19. package/dist/_signers/volc-v4.d.ts.map +1 -0
  20. package/dist/_signers/volc-v4.js +43 -0
  21. package/dist/_signers/volc-v4.js.map +1 -0
  22. package/dist/agent-hints.d.ts.map +1 -1
  23. package/dist/agent-hints.js +28 -13
  24. package/dist/agent-hints.js.map +1 -1
  25. package/dist/asset-connectors/aliyun-ecs.d.ts +18 -0
  26. package/dist/asset-connectors/aliyun-ecs.d.ts.map +1 -0
  27. package/dist/asset-connectors/aliyun-ecs.js +99 -0
  28. package/dist/asset-connectors/aliyun-ecs.js.map +1 -0
  29. package/dist/asset-connectors/base.d.ts +15 -0
  30. package/dist/asset-connectors/base.d.ts.map +1 -0
  31. package/dist/asset-connectors/base.js +19 -0
  32. package/dist/asset-connectors/base.js.map +1 -0
  33. package/dist/asset-connectors/cloudflare.d.ts +18 -0
  34. package/dist/asset-connectors/cloudflare.d.ts.map +1 -0
  35. package/dist/asset-connectors/cloudflare.js +94 -0
  36. package/dist/asset-connectors/cloudflare.js.map +1 -0
  37. package/dist/asset-connectors/digitalocean.d.ts +18 -0
  38. package/dist/asset-connectors/digitalocean.d.ts.map +1 -0
  39. package/dist/asset-connectors/digitalocean.js +79 -0
  40. package/dist/asset-connectors/digitalocean.js.map +1 -0
  41. package/dist/asset-connectors/godaddy.d.ts +18 -0
  42. package/dist/asset-connectors/godaddy.d.ts.map +1 -0
  43. package/dist/asset-connectors/godaddy.js +62 -0
  44. package/dist/asset-connectors/godaddy.js.map +1 -0
  45. package/dist/asset-connectors/hetzner.d.ts +18 -0
  46. package/dist/asset-connectors/hetzner.d.ts.map +1 -0
  47. package/dist/asset-connectors/hetzner.js +52 -0
  48. package/dist/asset-connectors/hetzner.js.map +1 -0
  49. package/dist/asset-connectors/index.d.ts +18 -0
  50. package/dist/asset-connectors/index.d.ts.map +1 -0
  51. package/dist/asset-connectors/index.js +52 -0
  52. package/dist/asset-connectors/index.js.map +1 -0
  53. package/dist/asset-connectors/namecheap.d.ts +34 -0
  54. package/dist/asset-connectors/namecheap.d.ts.map +1 -0
  55. package/dist/asset-connectors/namecheap.js +178 -0
  56. package/dist/asset-connectors/namecheap.js.map +1 -0
  57. package/dist/asset-connectors/ssl-labs.d.ts +22 -0
  58. package/dist/asset-connectors/ssl-labs.d.ts.map +1 -0
  59. package/dist/asset-connectors/ssl-labs.js +79 -0
  60. package/dist/asset-connectors/ssl-labs.js.map +1 -0
  61. package/dist/asset-connectors/tencent-cvm.d.ts +18 -0
  62. package/dist/asset-connectors/tencent-cvm.d.ts.map +1 -0
  63. package/dist/asset-connectors/tencent-cvm.js +145 -0
  64. package/dist/asset-connectors/tencent-cvm.js.map +1 -0
  65. package/dist/asset-connectors/types.d.ts +45 -0
  66. package/dist/asset-connectors/types.d.ts.map +1 -0
  67. package/dist/asset-connectors/types.js +26 -0
  68. package/dist/asset-connectors/types.js.map +1 -0
  69. package/dist/asset-connectors/vultr.d.ts +18 -0
  70. package/dist/asset-connectors/vultr.d.ts.map +1 -0
  71. package/dist/asset-connectors/vultr.js +73 -0
  72. package/dist/asset-connectors/vultr.js.map +1 -0
  73. package/dist/connectors/anthropic.d.ts +10 -0
  74. package/dist/connectors/anthropic.d.ts.map +1 -0
  75. package/dist/connectors/anthropic.js +103 -0
  76. package/dist/connectors/anthropic.js.map +1 -0
  77. package/dist/connectors/base.d.ts +11 -0
  78. package/dist/connectors/base.d.ts.map +1 -0
  79. package/dist/connectors/base.js +19 -0
  80. package/dist/connectors/base.js.map +1 -0
  81. package/dist/connectors/deepseek.d.ts +14 -0
  82. package/dist/connectors/deepseek.d.ts.map +1 -0
  83. package/dist/connectors/deepseek.js +77 -0
  84. package/dist/connectors/deepseek.js.map +1 -0
  85. package/dist/connectors/doubao.d.ts +10 -0
  86. package/dist/connectors/doubao.d.ts.map +1 -0
  87. package/dist/connectors/doubao.js +64 -0
  88. package/dist/connectors/doubao.js.map +1 -0
  89. package/dist/connectors/index.d.ts +14 -0
  90. package/dist/connectors/index.d.ts.map +1 -0
  91. package/dist/connectors/index.js +42 -0
  92. package/dist/connectors/index.js.map +1 -0
  93. package/dist/connectors/kimi.d.ts +10 -0
  94. package/dist/connectors/kimi.d.ts.map +1 -0
  95. package/dist/connectors/kimi.js +67 -0
  96. package/dist/connectors/kimi.js.map +1 -0
  97. package/dist/connectors/openai.d.ts +10 -0
  98. package/dist/connectors/openai.d.ts.map +1 -0
  99. package/dist/connectors/openai.js +101 -0
  100. package/dist/connectors/openai.js.map +1 -0
  101. package/dist/connectors/qwen.d.ts +10 -0
  102. package/dist/connectors/qwen.d.ts.map +1 -0
  103. package/dist/connectors/qwen.js +66 -0
  104. package/dist/connectors/qwen.js.map +1 -0
  105. package/dist/connectors/types.d.ts +47 -0
  106. package/dist/connectors/types.d.ts.map +1 -0
  107. package/dist/connectors/types.js +24 -0
  108. package/dist/connectors/types.js.map +1 -0
  109. package/dist/guard/bin.js +0 -0
  110. package/dist/index.js +83 -1
  111. package/dist/index.js.map +1 -1
  112. package/dist/mcp/_vendored-contracts/beacon-mcp-tools-v1.d.ts +373 -0
  113. package/dist/mcp/_vendored-contracts/beacon-mcp-tools-v1.d.ts.map +1 -0
  114. package/dist/mcp/_vendored-contracts/beacon-mcp-tools-v1.js +130 -0
  115. package/dist/mcp/_vendored-contracts/beacon-mcp-tools-v1.js.map +1 -0
  116. package/dist/mcp/brain-client.d.ts +96 -0
  117. package/dist/mcp/brain-client.d.ts.map +1 -0
  118. package/dist/mcp/brain-client.js +214 -0
  119. package/dist/mcp/brain-client.js.map +1 -0
  120. package/dist/mcp/cache.d.ts +55 -0
  121. package/dist/mcp/cache.d.ts.map +1 -0
  122. package/dist/mcp/cache.js +109 -0
  123. package/dist/mcp/cache.js.map +1 -0
  124. package/dist/mcp/config.d.ts +29 -0
  125. package/dist/mcp/config.d.ts.map +1 -0
  126. package/dist/mcp/config.js +69 -0
  127. package/dist/mcp/config.js.map +1 -0
  128. package/dist/mcp/decision-engine.d.ts +54 -0
  129. package/dist/mcp/decision-engine.d.ts.map +1 -0
  130. package/dist/mcp/decision-engine.js +107 -0
  131. package/dist/mcp/decision-engine.js.map +1 -0
  132. package/dist/mcp/errors.d.ts +66 -0
  133. package/dist/mcp/errors.d.ts.map +1 -0
  134. package/dist/mcp/errors.js +127 -0
  135. package/dist/mcp/errors.js.map +1 -0
  136. package/dist/mcp/index.d.ts +40 -0
  137. package/dist/mcp/index.d.ts.map +1 -0
  138. package/dist/mcp/index.js +104 -0
  139. package/dist/mcp/index.js.map +1 -0
  140. package/dist/mcp/tools/_placeholder.d.ts +24 -0
  141. package/dist/mcp/tools/_placeholder.d.ts.map +1 -0
  142. package/dist/mcp/tools/_placeholder.js +29 -0
  143. package/dist/mcp/tools/_placeholder.js.map +1 -0
  144. package/dist/mcp/tools/avatar-market.d.ts +22 -0
  145. package/dist/mcp/tools/avatar-market.d.ts.map +1 -0
  146. package/dist/mcp/tools/avatar-market.js +33 -0
  147. package/dist/mcp/tools/avatar-market.js.map +1 -0
  148. package/dist/mcp/tools/check-expiry.d.ts +23 -0
  149. package/dist/mcp/tools/check-expiry.d.ts.map +1 -0
  150. package/dist/mcp/tools/check-expiry.js +29 -0
  151. package/dist/mcp/tools/check-expiry.js.map +1 -0
  152. package/dist/mcp/tools/check-usage.d.ts +25 -0
  153. package/dist/mcp/tools/check-usage.d.ts.map +1 -0
  154. package/dist/mcp/tools/check-usage.js +33 -0
  155. package/dist/mcp/tools/check-usage.js.map +1 -0
  156. package/dist/mcp/tools/credential-tools.d.ts +37 -0
  157. package/dist/mcp/tools/credential-tools.d.ts.map +1 -0
  158. package/dist/mcp/tools/credential-tools.js +109 -0
  159. package/dist/mcp/tools/credential-tools.js.map +1 -0
  160. package/dist/mcp/tools/get-monthly-picks.d.ts +25 -0
  161. package/dist/mcp/tools/get-monthly-picks.d.ts.map +1 -0
  162. package/dist/mcp/tools/get-monthly-picks.js +35 -0
  163. package/dist/mcp/tools/get-monthly-picks.js.map +1 -0
  164. package/dist/mcp/tools/index.d.ts +44 -0
  165. package/dist/mcp/tools/index.d.ts.map +1 -0
  166. package/dist/mcp/tools/index.js +188 -0
  167. package/dist/mcp/tools/index.js.map +1 -0
  168. package/dist/mcp/tools/memory-recent.d.ts +17 -0
  169. package/dist/mcp/tools/memory-recent.d.ts.map +1 -0
  170. package/dist/mcp/tools/memory-recent.js +46 -0
  171. package/dist/mcp/tools/memory-recent.js.map +1 -0
  172. package/dist/mcp/tools/memory-save.d.ts +15 -0
  173. package/dist/mcp/tools/memory-save.d.ts.map +1 -0
  174. package/dist/mcp/tools/memory-save.js +53 -0
  175. package/dist/mcp/tools/memory-save.js.map +1 -0
  176. package/dist/mcp/tools/memory-search.d.ts +24 -0
  177. package/dist/mcp/tools/memory-search.d.ts.map +1 -0
  178. package/dist/mcp/tools/memory-search.js +64 -0
  179. package/dist/mcp/tools/memory-search.js.map +1 -0
  180. package/dist/mcp/tools/record-acceptance.d.ts +22 -0
  181. package/dist/mcp/tools/record-acceptance.d.ts.map +1 -0
  182. package/dist/mcp/tools/record-acceptance.js +33 -0
  183. package/dist/mcp/tools/record-acceptance.js.map +1 -0
  184. package/dist/mcp/tools/record-rejection.d.ts +23 -0
  185. package/dist/mcp/tools/record-rejection.d.ts.map +1 -0
  186. package/dist/mcp/tools/record-rejection.js +34 -0
  187. package/dist/mcp/tools/record-rejection.js.map +1 -0
  188. package/dist/mcp/tools/suggest-route.d.ts +26 -0
  189. package/dist/mcp/tools/suggest-route.d.ts.map +1 -0
  190. package/dist/mcp/tools/suggest-route.js +56 -0
  191. package/dist/mcp/tools/suggest-route.js.map +1 -0
  192. package/dist/mcp/tools/user-preferences.d.ts +22 -0
  193. package/dist/mcp/tools/user-preferences.d.ts.map +1 -0
  194. package/dist/mcp/tools/user-preferences.js +63 -0
  195. package/dist/mcp/tools/user-preferences.js.map +1 -0
  196. package/dist/mcp-stdio/bin.js +0 -0
  197. package/dist/memory/index.d.ts +5 -0
  198. package/dist/memory/index.d.ts.map +1 -0
  199. package/dist/memory/index.js +4 -0
  200. package/dist/memory/index.js.map +1 -0
  201. package/dist/memory/mem0-client.d.ts +32 -0
  202. package/dist/memory/mem0-client.d.ts.map +1 -0
  203. package/dist/memory/mem0-client.js +161 -0
  204. package/dist/memory/mem0-client.js.map +1 -0
  205. package/dist/memory/types.d.ts +47 -0
  206. package/dist/memory/types.d.ts.map +1 -0
  207. package/dist/memory/types.js +20 -0
  208. package/dist/memory/types.js.map +1 -0
  209. package/dist/router/catalog.d.ts +4 -0
  210. package/dist/router/catalog.d.ts.map +1 -0
  211. package/dist/router/catalog.js +103 -0
  212. package/dist/router/catalog.js.map +1 -0
  213. package/dist/router/classifier.d.ts +5 -0
  214. package/dist/router/classifier.d.ts.map +1 -0
  215. package/dist/router/classifier.js +43 -0
  216. package/dist/router/classifier.js.map +1 -0
  217. package/dist/router/index.d.ts +7 -0
  218. package/dist/router/index.d.ts.map +1 -0
  219. package/dist/router/index.js +6 -0
  220. package/dist/router/index.js.map +1 -0
  221. package/dist/router/litellm-config.d.ts +34 -0
  222. package/dist/router/litellm-config.d.ts.map +1 -0
  223. package/dist/router/litellm-config.js +78 -0
  224. package/dist/router/litellm-config.js.map +1 -0
  225. package/dist/router/route.d.ts +3 -0
  226. package/dist/router/route.d.ts.map +1 -0
  227. package/dist/router/route.js +63 -0
  228. package/dist/router/route.js.map +1 -0
  229. package/dist/router/types.d.ts +36 -0
  230. package/dist/router/types.d.ts.map +1 -0
  231. package/dist/router/types.js +7 -0
  232. package/dist/router/types.js.map +1 -0
  233. package/dist/saas-connectors/base.d.ts +16 -0
  234. package/dist/saas-connectors/base.d.ts.map +1 -0
  235. package/dist/saas-connectors/base.js +16 -0
  236. package/dist/saas-connectors/base.js.map +1 -0
  237. package/dist/saas-connectors/brave.d.ts +19 -0
  238. package/dist/saas-connectors/brave.d.ts.map +1 -0
  239. package/dist/saas-connectors/brave.js +50 -0
  240. package/dist/saas-connectors/brave.js.map +1 -0
  241. package/dist/saas-connectors/fal.d.ts +15 -0
  242. package/dist/saas-connectors/fal.d.ts.map +1 -0
  243. package/dist/saas-connectors/fal.js +35 -0
  244. package/dist/saas-connectors/fal.js.map +1 -0
  245. package/dist/saas-connectors/index.d.ts +11 -0
  246. package/dist/saas-connectors/index.d.ts.map +1 -0
  247. package/dist/saas-connectors/index.js +32 -0
  248. package/dist/saas-connectors/index.js.map +1 -0
  249. package/dist/saas-connectors/replicate.d.ts +19 -0
  250. package/dist/saas-connectors/replicate.d.ts.map +1 -0
  251. package/dist/saas-connectors/replicate.js +43 -0
  252. package/dist/saas-connectors/replicate.js.map +1 -0
  253. package/dist/saas-connectors/serper.d.ts +19 -0
  254. package/dist/saas-connectors/serper.d.ts.map +1 -0
  255. package/dist/saas-connectors/serper.js +47 -0
  256. package/dist/saas-connectors/serper.js.map +1 -0
  257. package/dist/saas-connectors/types.d.ts +31 -0
  258. package/dist/saas-connectors/types.d.ts.map +1 -0
  259. package/dist/saas-connectors/types.js +6 -0
  260. package/dist/saas-connectors/types.js.map +1 -0
  261. package/dist/scheduler/brain-push-client.d.ts +13 -0
  262. package/dist/scheduler/brain-push-client.d.ts.map +1 -0
  263. package/dist/scheduler/brain-push-client.js +46 -0
  264. package/dist/scheduler/brain-push-client.js.map +1 -0
  265. package/dist/scheduler/index.d.ts +6 -0
  266. package/dist/scheduler/index.d.ts.map +1 -0
  267. package/dist/scheduler/index.js +5 -0
  268. package/dist/scheduler/index.js.map +1 -0
  269. package/dist/scheduler/poll.d.ts +4 -0
  270. package/dist/scheduler/poll.d.ts.map +1 -0
  271. package/dist/scheduler/poll.js +170 -0
  272. package/dist/scheduler/poll.js.map +1 -0
  273. package/dist/scheduler/scheduler.d.ts +18 -0
  274. package/dist/scheduler/scheduler.d.ts.map +1 -0
  275. package/dist/scheduler/scheduler.js +67 -0
  276. package/dist/scheduler/scheduler.js.map +1 -0
  277. package/dist/scheduler/types.d.ts +49 -0
  278. package/dist/scheduler/types.d.ts.map +1 -0
  279. package/dist/scheduler/types.js +14 -0
  280. package/dist/scheduler/types.js.map +1 -0
  281. package/dist/vault/cli.d.ts +2 -0
  282. package/dist/vault/cli.d.ts.map +1 -0
  283. package/dist/vault/cli.js +170 -0
  284. package/dist/vault/cli.js.map +1 -0
  285. package/dist/vault/crypto.d.ts +9 -0
  286. package/dist/vault/crypto.d.ts.map +1 -0
  287. package/dist/vault/crypto.js +54 -0
  288. package/dist/vault/crypto.js.map +1 -0
  289. package/dist/vault/index.d.ts +6 -0
  290. package/dist/vault/index.d.ts.map +1 -0
  291. package/dist/vault/index.js +5 -0
  292. package/dist/vault/index.js.map +1 -0
  293. package/dist/vault/types.d.ts +28 -0
  294. package/dist/vault/types.d.ts.map +1 -0
  295. package/dist/vault/types.js +22 -0
  296. package/dist/vault/types.js.map +1 -0
  297. package/dist/vault/vault.d.ts +34 -0
  298. package/dist/vault/vault.d.ts.map +1 -0
  299. package/dist/vault/vault.js +149 -0
  300. package/dist/vault/vault.js.map +1 -0
  301. package/package.json +17 -5
@@ -0,0 +1,67 @@
1
+ // sdk/skillfm-local/src/connectors/kimi.ts
2
+ //
3
+ // Kimi (Moonshot) connector — 真实现 (Day 2 D2-1)
4
+ // Doc: https://platform.moonshot.cn/docs/api/misc#查询账户余额
5
+ // Endpoint: GET /v1/users/me/balance
6
+ // Auth: Authorization: Bearer <api-key>
7
+ //
8
+ // 同 DeepSeek: Kimi 也没公开 admin usage 时序 API (2026-04 现状)。
9
+ // 用 balance API + sidecar 端 cron poll + brain 端差量计算反推 usage。
10
+ import { BaseConnector } from './base.js';
11
+ import { sanitizeError } from './types.js';
12
+ const BASE_URL = 'https://api.moonshot.cn';
13
+ export class KimiConnector extends BaseConnector {
14
+ id = 'kimi';
15
+ name = '月之暗面 Kimi';
16
+ is_real = true;
17
+ async fetchUsage(byok_key, opts) {
18
+ const r = await this.safeFetch(`${BASE_URL}/v1/users/me/balance`, {
19
+ method: 'GET',
20
+ headers: {
21
+ authorization: `Bearer ${byok_key}`,
22
+ 'content-type': 'application/json',
23
+ },
24
+ }, byok_key);
25
+ if (!r.ok) {
26
+ const text = await r.text().catch(() => '<no body>');
27
+ throw new Error(sanitizeError(`Kimi ${r.status}: ${text}`, byok_key));
28
+ }
29
+ const data = (await r.json());
30
+ if (!data.status) {
31
+ throw new Error(`Kimi balance API status=false (code=${data.code})`);
32
+ }
33
+ const cny_balance = data.data?.available_balance ?? 0;
34
+ return [
35
+ {
36
+ provider: 'kimi',
37
+ model: 'balance-snapshot',
38
+ timestamp: opts.end_date.toISOString(),
39
+ input_tokens: 0,
40
+ output_tokens: 0,
41
+ estimated_usd: cny_balance / 7.3, // CNY → USD approx
42
+ calls: 0,
43
+ },
44
+ ];
45
+ }
46
+ async ping(byok_key) {
47
+ const fp = this.fingerprint(byok_key);
48
+ try {
49
+ const r = await this.safeFetch(`${BASE_URL}/v1/users/me/balance`, {
50
+ method: 'GET',
51
+ headers: { authorization: `Bearer ${byok_key}` },
52
+ }, byok_key);
53
+ if (r.ok)
54
+ return { ok: true, key_fingerprint: fp };
55
+ const text = await r.text().catch(() => '');
56
+ return {
57
+ ok: false,
58
+ error: `HTTP ${r.status}: ${sanitizeError(text, byok_key)}`,
59
+ key_fingerprint: fp,
60
+ };
61
+ }
62
+ catch (e) {
63
+ return { ok: false, error: sanitizeError(e, byok_key), key_fingerprint: fp };
64
+ }
65
+ }
66
+ }
67
+ //# sourceMappingURL=kimi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kimi.js","sourceRoot":"","sources":["../../src/connectors/kimi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { BaseConnector } from './base.js';
2
+ import type { ConnectorId, FetchUsageOptions, PingResult, UsageRecord } from './types.js';
3
+ export declare class OpenAIConnector extends BaseConnector {
4
+ id: ConnectorId;
5
+ name: string;
6
+ is_real: boolean;
7
+ fetchUsage(byok_key: string, opts: FetchUsageOptions): Promise<UsageRecord[]>;
8
+ ping(byok_key: string): Promise<PingResult>;
9
+ }
10
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/connectors/openai.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAwC1F,qBAAa,eAAgB,SAAQ,aAAa;IAChD,EAAE,EAAE,WAAW,CAAY;IAC3B,IAAI,SAAgB;IACpB,OAAO,UAAQ;IAET,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAkD7E,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CA2BlD"}
@@ -0,0 +1,101 @@
1
+ // sdk/skillfm-local/src/connectors/openai.ts
2
+ //
3
+ // OpenAI Usage API connector — 真实现
4
+ // Doc: https://platform.openai.com/docs/api-reference/usage
5
+ // Endpoint: GET /v1/organization/usage/completions
6
+ // Auth: Authorization: Bearer <admin-key> (sk-admin-*)
7
+ //
8
+ // 注意: 用户必须使用 admin-level key 才能调 organization/usage 端点。
9
+ // 普通 sk-* key 调会 401。
10
+ import { BaseConnector } from './base.js';
11
+ import { sanitizeError } from './types.js';
12
+ const BASE_URL = 'https://api.openai.com';
13
+ const PRICE_TABLE = {
14
+ 'gpt-4o': { in: 2.5, out: 10 },
15
+ 'gpt-4o-mini': { in: 0.15, out: 0.6 },
16
+ 'gpt-4-turbo': { in: 10, out: 30 },
17
+ 'gpt-4': { in: 30, out: 60 },
18
+ 'o1': { in: 15, out: 60 },
19
+ 'o1-mini': { in: 3, out: 12 },
20
+ 'gpt-3.5-turbo': { in: 0.5, out: 1.5 },
21
+ };
22
+ function estimateUsd(model, in_tok, out_tok) {
23
+ if (!model)
24
+ return (in_tok / 1_000_000) * 2.5 + (out_tok / 1_000_000) * 10;
25
+ const key = Object.keys(PRICE_TABLE).find((k) => model.toLowerCase().includes(k));
26
+ const p = key ? PRICE_TABLE[key] : { in: 2.5, out: 10 };
27
+ return (in_tok / 1_000_000) * p.in + (out_tok / 1_000_000) * p.out;
28
+ }
29
+ export class OpenAIConnector extends BaseConnector {
30
+ id = 'openai';
31
+ name = 'OpenAI GPT';
32
+ is_real = true;
33
+ async fetchUsage(byok_key, opts) {
34
+ const start_unix = Math.floor(opts.start_date.getTime() / 1000);
35
+ const end_unix = Math.floor(opts.end_date.getTime() / 1000);
36
+ const params = new URLSearchParams({
37
+ start_time: String(start_unix),
38
+ end_time: String(end_unix),
39
+ bucket_width: '1d',
40
+ limit: String(opts.limit ?? 100),
41
+ group_by: 'model',
42
+ });
43
+ let url = `${BASE_URL}/v1/organization/usage/completions?${params}`;
44
+ const records = [];
45
+ while (url) {
46
+ const r = await this.safeFetch(url, {
47
+ method: 'GET',
48
+ headers: {
49
+ authorization: `Bearer ${byok_key}`,
50
+ 'content-type': 'application/json',
51
+ },
52
+ }, byok_key);
53
+ if (!r.ok) {
54
+ const text = await r.text().catch(() => '<no body>');
55
+ throw new Error(sanitizeError(`OpenAI ${r.status}: ${text}`, byok_key));
56
+ }
57
+ const data = (await r.json());
58
+ for (const bucket of data.data ?? []) {
59
+ for (const item of bucket.results ?? []) {
60
+ records.push({
61
+ provider: 'openai',
62
+ model: item.model ?? 'unknown',
63
+ timestamp: new Date(bucket.start_time * 1000).toISOString(),
64
+ input_tokens: item.input_tokens,
65
+ output_tokens: item.output_tokens,
66
+ estimated_usd: estimateUsd(item.model, item.input_tokens, item.output_tokens),
67
+ calls: item.num_model_requests,
68
+ });
69
+ }
70
+ }
71
+ url = data.has_more && data.next_page ? `${BASE_URL}${data.next_page}` : null;
72
+ }
73
+ return records;
74
+ }
75
+ async ping(byok_key) {
76
+ const fp = this.fingerprint(byok_key);
77
+ try {
78
+ // 拉最短窗口 (近 1 天)
79
+ const end = Math.floor(Date.now() / 1000);
80
+ const start = end - 86400;
81
+ const params = new URLSearchParams({
82
+ start_time: String(start),
83
+ end_time: String(end),
84
+ bucket_width: '1d',
85
+ limit: '1',
86
+ });
87
+ const r = await this.safeFetch(`${BASE_URL}/v1/organization/usage/completions?${params}`, {
88
+ method: 'GET',
89
+ headers: { authorization: `Bearer ${byok_key}` },
90
+ }, byok_key);
91
+ if (r.ok)
92
+ return { ok: true, key_fingerprint: fp };
93
+ const text = await r.text().catch(() => '');
94
+ return { ok: false, error: `HTTP ${r.status}: ${sanitizeError(text, byok_key)}`, key_fingerprint: fp };
95
+ }
96
+ catch (e) {
97
+ return { ok: false, error: sanitizeError(e, byok_key), key_fingerprint: fp };
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/connectors/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { BaseConnector } from './base.js';
2
+ import type { ConnectorId, FetchUsageOptions, PingResult, UsageRecord } from './types.js';
3
+ export declare class QwenConnector extends BaseConnector {
4
+ id: ConnectorId;
5
+ name: string;
6
+ is_real: boolean;
7
+ fetchUsage(byok_key: string, opts: FetchUsageOptions): Promise<UsageRecord[]>;
8
+ ping(byok_key: string): Promise<PingResult>;
9
+ }
10
+ //# sourceMappingURL=qwen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen.d.ts","sourceRoot":"","sources":["../../src/connectors/qwen.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAc1F,qBAAa,aAAc,SAAQ,aAAa;IAC9C,EAAE,EAAE,WAAW,CAAU;IACzB,IAAI,SAAY;IAChB,OAAO,UAAQ;IAET,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAkC7E,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAmBlD"}
@@ -0,0 +1,66 @@
1
+ // sdk/skillfm-local/src/connectors/qwen.ts
2
+ //
3
+ // Qwen (阿里通义/百炼/DashScope) connector — Day 4 真实现
4
+ // Doc: https://help.aliyun.com/zh/model-studio
5
+ // Endpoint: DashScope https://dashscope.aliyuncs.com (Bearer auth, **不需要 SignerV4**)
6
+ //
7
+ // 调研校准 (2026-04):
8
+ // - 阿里云核心 API (ECS / RDS / BSS) 走 SignerV4 + AccessKey ID/Secret
9
+ // - DashScope (Qwen 模型) 走简单 Bearer + DashScope API key (sk-xxx)
10
+ // - usage 时序 API 暂未公开 (DashScope console 内查), 但有 me/usage 端点
11
+ // - 替代: 用 list-deployments 端点验 key + 后续 sidecar 自统计
12
+ import { BaseConnector } from './base.js';
13
+ import { sanitizeError } from './types.js';
14
+ const BASE_URL = 'https://dashscope.aliyuncs.com';
15
+ export class QwenConnector extends BaseConnector {
16
+ id = 'qwen';
17
+ name = '阿里通义千问';
18
+ is_real = true;
19
+ async fetchUsage(byok_key, opts) {
20
+ // DashScope 没公开时序 usage. 用 ping-style endpoint 拿 quota snapshot
21
+ // sidecar 内 cron poll + brain 端做差量
22
+ const r = await this.safeFetch(`${BASE_URL}/api/v1/users/me`, {
23
+ method: 'GET',
24
+ headers: {
25
+ authorization: `Bearer ${byok_key}`,
26
+ 'content-type': 'application/json',
27
+ },
28
+ }, byok_key);
29
+ if (!r.ok) {
30
+ const text = await r.text().catch(() => '');
31
+ throw new Error(sanitizeError(`Qwen DashScope ${r.status}: ${text}`, byok_key));
32
+ }
33
+ const data = (await r.json());
34
+ const used = data.output?.used ?? 0;
35
+ return [
36
+ {
37
+ provider: 'qwen',
38
+ model: 'quota-snapshot',
39
+ timestamp: opts.end_date.toISOString(),
40
+ input_tokens: 0,
41
+ output_tokens: 0,
42
+ // 复用 estimated_usd 字段为"已用 quota" (sidecar 解析时按 model 价目换算)
43
+ estimated_usd: used,
44
+ calls: 0,
45
+ },
46
+ ];
47
+ }
48
+ async ping(byok_key) {
49
+ const fp = this.fingerprint(byok_key);
50
+ try {
51
+ const r = await this.safeFetch(`${BASE_URL}/api/v1/users/me`, { method: 'GET', headers: { authorization: `Bearer ${byok_key}` } }, byok_key);
52
+ if (r.ok)
53
+ return { ok: true, key_fingerprint: fp };
54
+ const text = await r.text().catch(() => '');
55
+ return {
56
+ ok: false,
57
+ error: `HTTP ${r.status}: ${sanitizeError(text, byok_key)}`,
58
+ key_fingerprint: fp,
59
+ };
60
+ }
61
+ catch (e) {
62
+ return { ok: false, error: sanitizeError(e, byok_key), key_fingerprint: fp };
63
+ }
64
+ }
65
+ }
66
+ //# sourceMappingURL=qwen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen.js","sourceRoot":"","sources":["../../src/connectors/qwen.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,iDAAiD;AACjD,+CAA+C;AAC/C,qFAAqF;AACrF,EAAE;AACF,kBAAkB;AAClB,mEAAmE;AACnE,kEAAkE;AAClE,+DAA+D;AAC/D,sDAAsD;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,QAAQ,GAAG,gCAAgC,CAAC;AAWlD,MAAM,OAAO,aAAc,SAAQ,aAAa;IAC9C,EAAE,GAAgB,MAAM,CAAC;IACzB,IAAI,GAAG,QAAQ,CAAC;IAChB,OAAO,GAAG,IAAI,CAAC;IAEf,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,IAAuB;QACxD,gEAAgE;QAChE,mCAAmC;QACnC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAC5B,GAAG,QAAQ,kBAAkB,EAC7B;YACE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,QAAQ,EAAE;gBACnC,cAAc,EAAE,kBAAkB;aACnC;SACF,EACD,QAAQ,CACT,CAAC;QACF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAwB,CAAC;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC;QACpC,OAAO;YACL;gBACE,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,gBAAgB;gBACvB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;gBACtC,YAAY,EAAE,CAAC;gBACf,aAAa,EAAE,CAAC;gBAChB,2DAA2D;gBAC3D,aAAa,EAAE,IAAI;gBACnB,KAAK,EAAE,CAAC;aACT;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAC5B,GAAG,QAAQ,kBAAkB,EAC7B,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,EAAE,EAAE,EAAE,EACnE,QAAQ,CACT,CAAC;YACF,IAAI,CAAC,CAAC,EAAE;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5C,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;gBAC3D,eAAe,EAAE,EAAE;aACpB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,47 @@
1
+ export type ConnectorId = 'anthropic' | 'openai' | 'deepseek' | 'qwen' | 'doubao' | 'kimi';
2
+ export interface UsageRecord {
3
+ /** Connector 标识 */
4
+ provider: ConnectorId;
5
+ /** 模型名 (e.g. "claude-3-5-sonnet-20241022", "gpt-4o-2024-11-20") */
6
+ model: string;
7
+ /** 数据时间 (ISO 8601) */
8
+ timestamp: string;
9
+ /** 输入 token 数 */
10
+ input_tokens: number;
11
+ /** 输出 token 数 */
12
+ output_tokens: number;
13
+ /** 估算花费 (USD) */
14
+ estimated_usd: number;
15
+ /** 调用次数 (本聚合周期) */
16
+ calls: number;
17
+ }
18
+ export interface FetchUsageOptions {
19
+ start_date: Date;
20
+ end_date: Date;
21
+ /** 最大返回条数,防爆 */
22
+ limit?: number;
23
+ }
24
+ export interface PingResult {
25
+ ok: boolean;
26
+ /** 错误信息,绝不含 key 全文 */
27
+ error?: string;
28
+ /** key fingerprint (前 8 字符 hash, 安全) */
29
+ key_fingerprint?: string;
30
+ }
31
+ export interface Connector {
32
+ id: ConnectorId;
33
+ name: string;
34
+ /** 是否真实现 (false = stub, Day 2 接) */
35
+ is_real: boolean;
36
+ /**
37
+ * 拉用量数据 — BYOK key 通过 byok_key 参数传入,函数 scope 结束应不再持有
38
+ */
39
+ fetchUsage(byok_key: string, opts: FetchUsageOptions): Promise<UsageRecord[]>;
40
+ /** 验 key 有效性 — 不写库 */
41
+ ping(byok_key: string): Promise<PingResult>;
42
+ }
43
+ /** key 安全处理:返前 8 字符 hash 给日志 */
44
+ export declare function maskKey(key: string): string;
45
+ /** 错误信息脱敏 — 移除可能的 key 子串 */
46
+ export declare function sanitizeError(err: unknown, byok_key: string): string;
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/connectors/types.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,QAAQ,GACR,UAAU,GACV,MAAM,GACN,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,IAAI,CAAC;IACjB,QAAQ,EAAE,IAAI,CAAC;IACf,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9E,sBAAsB;IACtB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7C;AAED,gCAAgC;AAChC,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3C;AAED,4BAA4B;AAC5B,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKpE"}
@@ -0,0 +1,24 @@
1
+ // sdk/skillfm-local/src/connectors/types.ts
2
+ //
3
+ // LLM connector 共享类型 (Day 1 D1-C, sidecar 端)
4
+ //
5
+ // BYOK 红线 (CLAUDE.md):
6
+ // - API key 永远不出用户节点 — 只在调用瞬间从 in-memory 传入,函数 scope 结束 GC
7
+ // - error 路径绝不回显 key (mask 成 sk-***...***last4)
8
+ // - Day 3 凭证保险柜上线后,key 从 encrypted vault 取,不直接传
9
+ /** key 安全处理:返前 8 字符 hash 给日志 */
10
+ export function maskKey(key) {
11
+ if (!key || key.length < 8)
12
+ return '***invalid***';
13
+ const last4 = key.slice(-4);
14
+ return `${key.slice(0, 4)}***${last4}`;
15
+ }
16
+ /** 错误信息脱敏 — 移除可能的 key 子串 */
17
+ export function sanitizeError(err, byok_key) {
18
+ const msg = err instanceof Error ? err.message : String(err);
19
+ if (!byok_key)
20
+ return msg;
21
+ // 移除完整 key 出现 (任何长度 ≥ 16 的子串都视作敏感)
22
+ return msg.replace(byok_key, maskKey(byok_key));
23
+ }
24
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/connectors/types.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,uBAAuB;AACvB,6DAA6D;AAC7D,kDAAkD;AAClD,kDAAkD;AAuDlD,gCAAgC;AAChC,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,eAAe,CAAC;IACnD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,4BAA4B;AAC5B,MAAM,UAAU,aAAa,CAAC,GAAY,EAAE,QAAgB;IAC1D,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC;IAC1B,mCAAmC;IACnC,OAAO,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClD,CAAC"}
package/dist/guard/bin.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -1261,6 +1261,27 @@ async function runStartupSoulVerify() {
1261
1261
  clearTimeout(timer);
1262
1262
  }
1263
1263
  }
1264
+ // ============================================================================
1265
+ // Phase 2 — Beacon scheduler launcher
1266
+ // ============================================================================
1267
+ // 启动时初始化 Vault + BeaconScheduler (poll provider billing API → push brain)
1268
+ // vault 无 key 时, scheduler 以 idle 状态运行 (每次 poll 返 "no key in vault" 但不 throw)
1269
+ // 等用户通过 vault MCP tool 加 key 后, 下次 poll 自动开始上报。
1270
+ async function launchBeaconScheduler(brainKey) {
1271
+ const { Vault } = await import('./vault/index.js');
1272
+ const { BeaconScheduler, createBrainPushClient } = await import('./scheduler/index.js');
1273
+ const vault = new Vault();
1274
+ await vault.init();
1275
+ const brain = createBrainPushClient({
1276
+ apiRoot: DEFAULT_API_ROOT,
1277
+ agentToken: brainKey,
1278
+ userAgent: `${PKG_NAME}/${PKG_VERSION}`,
1279
+ });
1280
+ const scheduler = new BeaconScheduler(vault, brain, {
1281
+ interval: { kind: 'minutes', n: 30 },
1282
+ });
1283
+ scheduler.start();
1284
+ }
1264
1285
  async function cmdStart() {
1265
1286
  const existing = readLocalSettings();
1266
1287
  if (existing && isPidAlive(existing.pid)) {
@@ -1336,6 +1357,18 @@ async function cmdStart() {
1336
1357
  }));
1337
1358
  });
1338
1359
  }
1360
+ // Phase 2 — Beacon scheduler 自动启动 (走通 Beacon: 管 AI 资产 / 省 token)
1361
+ // BYOK: provider keys 由 vault 加密本地 (~/.skillfm/vault.{key,enc}), 永不出节点。
1362
+ // vault 没 key 时 scheduler idle (poll 返回 "no key in vault" 但不 fail)。
1363
+ // fire-and-forget;失败不阻塞 sidecar 主路径
1364
+ if (state.brainKey) {
1365
+ void launchBeaconScheduler(state.brainKey).catch((err) => {
1366
+ console.error(JSON.stringify({
1367
+ ok: false,
1368
+ beacon_scheduler_failed: err.message,
1369
+ }));
1370
+ });
1371
+ }
1339
1372
  const shutdown = () => {
1340
1373
  deleteLocalSettings();
1341
1374
  server.close(() => process.exit(0));
@@ -1384,7 +1417,16 @@ async function cmdStatus() {
1384
1417
  function cmdHelp() {
1385
1418
  console.log(`${PKG_NAME} v${PKG_VERSION}
1386
1419
 
1387
- Usage:
1420
+ Two top-level usages (subcommand router):
1421
+ npx -y @skillfm/local mcp Beacon MCP stdio server (cost-optimizer for any agent;
1422
+ plug into Cursor / Claude Code / OpenClaw)
1423
+ npx -y @skillfm/local skill <slug>
1424
+ Run a SkillFM skill bundle on this node (BYOK; sidecar
1425
+ auto-starts if needed)
1426
+ npx -y @skillfm/local login OAuth 2.1 device-flow activation (alias of \`activate\`)
1427
+ npx -y @skillfm/local doctor Three-layer self-check / config diagnostic
1428
+
1429
+ Sidecar / harness commands (legacy direct CLI):
1388
1430
  skillfm-local start Start local sidecar on 127.0.0.1:${DEFAULT_PORT}
1389
1431
  (falls back to a random port if ${DEFAULT_PORT} is taken)
1390
1432
  skillfm-local stop Stop the running sidecar
@@ -1400,6 +1442,10 @@ Usage:
1400
1442
  skillfm-local doctor [--v2] [--disable-hooks] [--json]
1401
1443
  Three-layer self-check (Layer 1 SKILL.md / Layer 2 MCP
1402
1444
  reject / Layer 3 hook), or v0.2 layered defense check.
1445
+ skillfm-local mcp Boot the Beacon MCP stdio server (BYOK; reads
1446
+ SKILLFM_AGENT_TOKEN; stdout reserved for JSON-RPC).
1447
+ skillfm-local skill <slug> Run a SkillFM skill bundle (delegates to run-skill).
1448
+ skillfm-local login Alias of \`activate\` (kept for the npx subcommand router).
1403
1449
  skillfm-local help Show this help
1404
1450
 
1405
1451
  Service discovery:
@@ -1459,6 +1505,42 @@ const main = async () => {
1459
1505
  await cmdTunnel();
1460
1506
  break;
1461
1507
  }
1508
+ case 'mcp': {
1509
+ // Beacon MCP stdio server — merged in from @skillfm/beacon-mcp
1510
+ // (Day 1 D1-B, 2026-05-01). Plug into Cursor / Claude Code / OpenClaw
1511
+ // via `npx -y @skillfm/local mcp`. BYOK red line: only reads
1512
+ // SKILLFM_AGENT_TOKEN; never touches LLM keys / cookies.
1513
+ const { startServer } = await import('./mcp/index.js');
1514
+ await startServer();
1515
+ break;
1516
+ }
1517
+ case 'skill': {
1518
+ // Alias for run-skill, kept for the npx subcommand router
1519
+ // (`npx -y @skillfm/local skill <slug>`).
1520
+ const { cmdRunSkill } = await import('./skill-runner/cli.js');
1521
+ await cmdRunSkill();
1522
+ break;
1523
+ }
1524
+ case 'login': {
1525
+ // Alias for activate, kept for the npx subcommand router
1526
+ // (`npx -y @skillfm/local login`). Activation is currently driven via
1527
+ // the `start` sidecar's /activate/start + /activate/poll endpoints, so
1528
+ // we surface the same "start sidecar" entry here for now and print a
1529
+ // one-line hint pointing at the agent flow.
1530
+ console.error(`[skillfm-local] 'login' triggers OAuth 2.1 device-flow activation.\n` +
1531
+ ` → For interactive use: run \`skillfm-local start\` then visit /activate/start\n` +
1532
+ ` → For agent-driven use: the sidecar's /activate/start + /activate/poll endpoints\n` +
1533
+ ` are the canonical path (see harness PreToolUse hook).`);
1534
+ await cmdStart();
1535
+ break;
1536
+ }
1537
+ case 'vault': {
1538
+ // Beacon credential vault (AES-256-GCM, ~/.skillfm/vault.enc).
1539
+ // BYOK 红线: key 永不出节点, 不通过 web 中转, 仅 sidecar terminal 直接调用。
1540
+ const { cmdVault } = await import('./vault/cli.js');
1541
+ await cmdVault();
1542
+ break;
1543
+ }
1462
1544
  case 'help':
1463
1545
  case '--help':
1464
1546
  case '-h':