libero-mcp 0.2.26 → 0.3.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 (54) hide show
  1. package/data/migrations/017_ap_wallet.sql +25 -0
  2. package/data/migrations/018_ap_rewards.sql +21 -0
  3. package/data/migrations/019_ap_bounty.sql +10 -0
  4. package/data/migrations/020_chat_turns.sql +10 -0
  5. package/data/migrations/021_portrait.sql +4 -0
  6. package/data/migrations/022_family_emoji_single.sql +3 -0
  7. package/data/migrations/023_ap_balance_view_log.sql +9 -0
  8. package/dist/data/migrations/017_ap_wallet.sql +25 -0
  9. package/dist/data/migrations/018_ap_rewards.sql +21 -0
  10. package/dist/data/migrations/019_ap_bounty.sql +10 -0
  11. package/dist/data/migrations/020_chat_turns.sql +10 -0
  12. package/dist/data/migrations/021_portrait.sql +4 -0
  13. package/dist/data/migrations/022_family_emoji_single.sql +3 -0
  14. package/dist/data/migrations/023_ap_balance_view_log.sql +9 -0
  15. package/dist/mcp/contract/v1/rest.js +56 -0
  16. package/dist/mcp/rest-server.js +52 -0
  17. package/dist/mcp/server-core.js +255 -72
  18. package/dist/mcp/src/ap/index.js +14 -0
  19. package/dist/mcp/src/ap/rewards.js +44 -0
  20. package/dist/mcp/src/chat/from-env.js +111 -0
  21. package/dist/mcp/src/chat/history.js +35 -0
  22. package/dist/mcp/src/chat/loop.js +131 -0
  23. package/dist/mcp/src/chat/portrait.js +133 -0
  24. package/dist/mcp/src/chat/system-prompt.js +23 -0
  25. package/dist/mcp/src/chat/tool-names.js +27 -0
  26. package/dist/mcp/src/chat/tool-schema.js +20 -0
  27. package/dist/mcp/src/chat/types.js +1 -0
  28. package/dist/mcp/src/host-adapters/hermes-cron.js +24 -17
  29. package/dist/mcp/src/host-adapters/index.js +0 -1
  30. package/dist/mcp/src/identity/equivalent-ids.js +41 -0
  31. package/dist/mcp/src/profile/index.js +83 -6
  32. package/dist/mcp/src/reminder/index.js +7 -1
  33. package/dist/mcp/src/repo/factory.js +2 -0
  34. package/dist/mcp/src/repo/in-memory.js +129 -0
  35. package/dist/mcp/src/repo/sqlite-ap.js +188 -0
  36. package/dist/mcp/src/repo/sqlite.js +63 -36
  37. package/dist/mcp/src/rest/app.js +121 -0
  38. package/dist/mcp/src/rest/invoke-tool.js +98 -0
  39. package/dist/mcp/src/rest/short-token.js +38 -0
  40. package/dist/mcp/src/rest/tokens.js +55 -0
  41. package/dist/mcp/src/scheduler/index.js +41 -9
  42. package/dist/mcp/src/stickiness/report.js +174 -0
  43. package/dist/mcp/src/stickiness/types.js +1 -0
  44. package/dist/mcp/src/timeblock/index.js +12 -1
  45. package/dist/mcp/src/timeline/index.js +7 -5
  46. package/dist/mcp/src/weixin/app.js +97 -0
  47. package/dist/mcp/src/weixin/custom-send.js +82 -0
  48. package/dist/mcp/src/weixin/handle-text.js +49 -0
  49. package/dist/mcp/src/weixin/reminder-loop.js +39 -0
  50. package/dist/mcp/src/weixin/signature.js +13 -0
  51. package/dist/mcp/src/weixin/tencent-asr.js +101 -0
  52. package/dist/mcp/src/weixin/xml.js +37 -0
  53. package/dist/mcp/weixin-server.js +158 -0
  54. package/package.json +7 -3
@@ -0,0 +1,25 @@
1
+ -- INT-AP-tools R2 (2026-08-14): AP 账真源在 libero.db
2
+ -- 契约: libero-homm/docs/specs/INT-AP-tools.md §3
3
+ CREATE TABLE IF NOT EXISTS ap_wallet (
4
+ user_id TEXT PRIMARY KEY,
5
+ balance INTEGER NOT NULL DEFAULT 0,
6
+ updated_at TEXT NOT NULL
7
+ );
8
+
9
+ CREATE TABLE IF NOT EXISTS ap_credit_log (
10
+ user_id TEXT NOT NULL,
11
+ idempotency_key TEXT NOT NULL,
12
+ amount INTEGER NOT NULL,
13
+ source TEXT NOT NULL,
14
+ created_at TEXT NOT NULL,
15
+ UNIQUE(user_id, idempotency_key)
16
+ );
17
+
18
+ -- spend 幂等同 credit:同 key 只扣一次(spec §2b)
19
+ CREATE TABLE IF NOT EXISTS ap_spend_log (
20
+ user_id TEXT NOT NULL,
21
+ idempotency_key TEXT NOT NULL,
22
+ amount INTEGER NOT NULL,
23
+ created_at TEXT NOT NULL,
24
+ UNIQUE(user_id, idempotency_key)
25
+ );
@@ -0,0 +1,21 @@
1
+ -- INT-ap-rewards (2026-08-19): AP 换算引擎计数与事件幂等
2
+ -- 契约: libero-homm/docs/specs/INT-ap-rewards.md §4
3
+ CREATE TABLE IF NOT EXISTS ap_reward_log (
4
+ user_id TEXT NOT NULL,
5
+ event_id TEXT NOT NULL,
6
+ action_type TEXT NOT NULL,
7
+ period_key TEXT NOT NULL,
8
+ nth INTEGER NOT NULL,
9
+ amount INTEGER NOT NULL,
10
+ created_at TEXT NOT NULL,
11
+ UNIQUE(user_id, event_id)
12
+ );
13
+
14
+ CREATE TABLE IF NOT EXISTS ap_reward_counter (
15
+ user_id TEXT NOT NULL,
16
+ action_type TEXT NOT NULL,
17
+ period_key TEXT NOT NULL,
18
+ count INTEGER NOT NULL DEFAULT 0,
19
+ updated_at TEXT NOT NULL,
20
+ PRIMARY KEY (user_id, action_type, period_key)
21
+ );
@@ -0,0 +1,10 @@
1
+ -- INT-ap-rewards 悬赏(方案 A,2026-08-19):每日任务完成奖金,一日一任务只发一次
2
+ -- 契约: libero-homm/docs/specs/INT-ap-rewards.md §悬赏
3
+ CREATE TABLE IF NOT EXISTS ap_bounty_log (
4
+ user_id TEXT NOT NULL,
5
+ date_key TEXT NOT NULL,
6
+ quest_id TEXT NOT NULL,
7
+ bonus INTEGER NOT NULL,
8
+ created_at TEXT NOT NULL,
9
+ UNIQUE(user_id, date_key, quest_id)
10
+ );
@@ -0,0 +1,10 @@
1
+ -- 微信/REST chat 多轮上下文(2026-08-19)
2
+ -- 只存 user/assistant 正文;tool 轮次不落盘
3
+ CREATE TABLE IF NOT EXISTS chat_turns (
4
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
5
+ conversation_key TEXT NOT NULL,
6
+ role TEXT NOT NULL,
7
+ content TEXT NOT NULL,
8
+ created_at TEXT NOT NULL
9
+ );
10
+ CREATE INDEX IF NOT EXISTS idx_chat_turns_key_id ON chat_turns (conversation_key, id);
@@ -0,0 +1,4 @@
1
+ -- 账户画像:习惯与个人设置(非近期动作)。200 字硬顶,脏标记 + 刷新时间。
2
+ ALTER TABLE user_profile ADD COLUMN portrait TEXT;
3
+ ALTER TABLE user_profile ADD COLUMN portrait_refreshed_at TEXT;
4
+ ALTER TABLE user_profile ADD COLUMN portrait_dirty INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,3 @@
1
+ -- 2026-09-02: 陪伴分类 👨‍👩‍👧(ZWJ 三人组)在 emoji 矩阵里占 3 格宽导致错位,
2
+ -- 统一为单字素 👶(用户拍板:照顾孩子类用单一 emoji)。
3
+ UPDATE categories SET emoji = '👶' WHERE id = 'cat-family';
@@ -0,0 +1,9 @@
1
+ -- S3:看余额埋点(INT-mvp-100 游戏拉动信号)。只追加,不幂等去重——每次查询都是一次「看」。
2
+ CREATE TABLE IF NOT EXISTS ap_balance_view_log (
3
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ user_id TEXT NOT NULL,
5
+ balance INTEGER NOT NULL,
6
+ created_at TEXT NOT NULL
7
+ );
8
+ CREATE INDEX IF NOT EXISTS idx_ap_balance_view_user_created
9
+ ON ap_balance_view_log (user_id, created_at);
@@ -0,0 +1,25 @@
1
+ -- INT-AP-tools R2 (2026-08-14): AP 账真源在 libero.db
2
+ -- 契约: libero-homm/docs/specs/INT-AP-tools.md §3
3
+ CREATE TABLE IF NOT EXISTS ap_wallet (
4
+ user_id TEXT PRIMARY KEY,
5
+ balance INTEGER NOT NULL DEFAULT 0,
6
+ updated_at TEXT NOT NULL
7
+ );
8
+
9
+ CREATE TABLE IF NOT EXISTS ap_credit_log (
10
+ user_id TEXT NOT NULL,
11
+ idempotency_key TEXT NOT NULL,
12
+ amount INTEGER NOT NULL,
13
+ source TEXT NOT NULL,
14
+ created_at TEXT NOT NULL,
15
+ UNIQUE(user_id, idempotency_key)
16
+ );
17
+
18
+ -- spend 幂等同 credit:同 key 只扣一次(spec §2b)
19
+ CREATE TABLE IF NOT EXISTS ap_spend_log (
20
+ user_id TEXT NOT NULL,
21
+ idempotency_key TEXT NOT NULL,
22
+ amount INTEGER NOT NULL,
23
+ created_at TEXT NOT NULL,
24
+ UNIQUE(user_id, idempotency_key)
25
+ );
@@ -0,0 +1,21 @@
1
+ -- INT-ap-rewards (2026-08-19): AP 换算引擎计数与事件幂等
2
+ -- 契约: libero-homm/docs/specs/INT-ap-rewards.md §4
3
+ CREATE TABLE IF NOT EXISTS ap_reward_log (
4
+ user_id TEXT NOT NULL,
5
+ event_id TEXT NOT NULL,
6
+ action_type TEXT NOT NULL,
7
+ period_key TEXT NOT NULL,
8
+ nth INTEGER NOT NULL,
9
+ amount INTEGER NOT NULL,
10
+ created_at TEXT NOT NULL,
11
+ UNIQUE(user_id, event_id)
12
+ );
13
+
14
+ CREATE TABLE IF NOT EXISTS ap_reward_counter (
15
+ user_id TEXT NOT NULL,
16
+ action_type TEXT NOT NULL,
17
+ period_key TEXT NOT NULL,
18
+ count INTEGER NOT NULL DEFAULT 0,
19
+ updated_at TEXT NOT NULL,
20
+ PRIMARY KEY (user_id, action_type, period_key)
21
+ );
@@ -0,0 +1,10 @@
1
+ -- INT-ap-rewards 悬赏(方案 A,2026-08-19):每日任务完成奖金,一日一任务只发一次
2
+ -- 契约: libero-homm/docs/specs/INT-ap-rewards.md §悬赏
3
+ CREATE TABLE IF NOT EXISTS ap_bounty_log (
4
+ user_id TEXT NOT NULL,
5
+ date_key TEXT NOT NULL,
6
+ quest_id TEXT NOT NULL,
7
+ bonus INTEGER NOT NULL,
8
+ created_at TEXT NOT NULL,
9
+ UNIQUE(user_id, date_key, quest_id)
10
+ );
@@ -0,0 +1,10 @@
1
+ -- 微信/REST chat 多轮上下文(2026-08-19)
2
+ -- 只存 user/assistant 正文;tool 轮次不落盘
3
+ CREATE TABLE IF NOT EXISTS chat_turns (
4
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
5
+ conversation_key TEXT NOT NULL,
6
+ role TEXT NOT NULL,
7
+ content TEXT NOT NULL,
8
+ created_at TEXT NOT NULL
9
+ );
10
+ CREATE INDEX IF NOT EXISTS idx_chat_turns_key_id ON chat_turns (conversation_key, id);
@@ -0,0 +1,4 @@
1
+ -- 账户画像:习惯与个人设置(非近期动作)。200 字硬顶,脏标记 + 刷新时间。
2
+ ALTER TABLE user_profile ADD COLUMN portrait TEXT;
3
+ ALTER TABLE user_profile ADD COLUMN portrait_refreshed_at TEXT;
4
+ ALTER TABLE user_profile ADD COLUMN portrait_dirty INTEGER NOT NULL DEFAULT 0;
@@ -0,0 +1,3 @@
1
+ -- 2026-09-02: 陪伴分类 👨‍👩‍👧(ZWJ 三人组)在 emoji 矩阵里占 3 格宽导致错位,
2
+ -- 统一为单字素 👶(用户拍板:照顾孩子类用单一 emoji)。
3
+ UPDATE categories SET emoji = '👶' WHERE id = 'cat-family';
@@ -0,0 +1,9 @@
1
+ -- S3:看余额埋点(INT-mvp-100 游戏拉动信号)。只追加,不幂等去重——每次查询都是一次「看」。
2
+ CREATE TABLE IF NOT EXISTS ap_balance_view_log (
3
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ user_id TEXT NOT NULL,
5
+ balance INTEGER NOT NULL,
6
+ created_at TEXT NOT NULL
7
+ );
8
+ CREATE INDEX IF NOT EXISTS idx_ap_balance_view_user_created
9
+ ON ap_balance_view_log (user_id, created_at);
@@ -0,0 +1,56 @@
1
+ /**
2
+ * MC-0b REST contract v1 — single source of truth (api-contract-first).
3
+ *
4
+ * REST adapter and tests bind these schemas. Do not invent parallel field names.
5
+ */
6
+ import { z } from "zod";
7
+ export const restErrorCodeSchema = z.enum([
8
+ "unauthorized",
9
+ "forbidden",
10
+ "not_found",
11
+ "invalid_input",
12
+ "tool_error",
13
+ "internal",
14
+ "unavailable",
15
+ "llm_error",
16
+ ]);
17
+ export const restErrorBodySchema = z.object({
18
+ ok: z.literal(false),
19
+ error: z.object({
20
+ code: restErrorCodeSchema,
21
+ message: z.string().min(1),
22
+ }),
23
+ });
24
+ export const restSuccessBodySchema = z.object({
25
+ ok: z.literal(true),
26
+ data: z.unknown(),
27
+ });
28
+ export const restHealthBodySchema = z.object({
29
+ ok: z.literal(true),
30
+ });
31
+ export const chatRequestBodySchema = z.object({
32
+ message: z.string().min(1),
33
+ });
34
+ export const chatSuccessBodySchema = z.object({
35
+ ok: z.literal(true),
36
+ reply: z.string().min(1),
37
+ tools_called: z.array(z.string()),
38
+ });
39
+ /** INT-AP-tools — request/response data (fields bind to libero-homm spec). */
40
+ export const apCreditDataSchema = z.object({
41
+ balance: z.number().int().nonnegative(),
42
+ credited: z.number().int().positive(),
43
+ source: z.string().min(1),
44
+ });
45
+ export const apBalanceDataSchema = z.object({
46
+ balance: z.number().int().nonnegative(),
47
+ });
48
+ export const apSpendDataSchema = z.object({
49
+ balance: z.number().int().nonnegative(),
50
+ spent: z.number().int().positive(),
51
+ });
52
+ export const REST_V1 = {
53
+ health: { method: "GET", path: "/api/v1/health" },
54
+ invokeTool: { method: "POST", path: "/api/v1/tools/:toolName" },
55
+ chat: { method: "POST", path: "/api/v1/chat" },
56
+ };
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * libero REST server — HTTP adapter over the same tool registry (MC-0b).
4
+ *
5
+ * Usage:
6
+ * LIBERO_REST_TOKENS='{"<token>":"<libero_user_id>"}' libero-rest
7
+ * DB_PATH=/path/to/libero.db LIBERO_REST_PORT=8787 libero-rest
8
+ *
9
+ * Default bind 127.0.0.1 (local trial). Same DB_PATH as MCP → same ledger.
10
+ */
11
+ import { serve } from "@hono/node-server";
12
+ import { homedir } from "node:os";
13
+ import { join } from "node:path";
14
+ import { initDb, closeDb } from "../data/db.js";
15
+ import { createToolRuntime } from "./server-core.js";
16
+ import { createRestApp } from "./src/rest/app.js";
17
+ import { parseRestTokens } from "./src/rest/tokens.js";
18
+ import { chatLlmFromEnv } from "./src/chat/from-env.js";
19
+ const DB_PATH = process.env.DB_PATH ?? join(homedir(), ".libero", "libero.db");
20
+ const PORT = Number(process.env.LIBERO_REST_PORT ?? "8787");
21
+ const HOST = process.env.LIBERO_REST_HOST ?? "127.0.0.1";
22
+ let tokenMap;
23
+ try {
24
+ tokenMap = parseRestTokens(process.env);
25
+ }
26
+ catch (e) {
27
+ console.error(`[libero-rest] FATAL: ${e.message}`);
28
+ process.exit(1);
29
+ }
30
+ const db = initDb(DB_PATH);
31
+ console.error(`[libero-rest] DB initialized at ${DB_PATH}`);
32
+ const { registry } = createToolRuntime(db);
33
+ const chatLlm = chatLlmFromEnv(process.env);
34
+ if (!chatLlm) {
35
+ console.error("[libero-rest] chat disabled: set LIBERO_CHAT_BASE_URL, LIBERO_CHAT_API_KEY, LIBERO_CHAT_MODEL");
36
+ }
37
+ const linkSecret = process.env.LIBERO_LINK_TOKEN_SECRET?.trim() || undefined;
38
+ const linkBaseUrl = process.env.LIBERO_HOMM_LINK_BASE?.trim() || undefined;
39
+ const ttlSec = process.env.LIBERO_LINK_TOKEN_TTL_SEC ? Number(process.env.LIBERO_LINK_TOKEN_TTL_SEC) : undefined;
40
+ if (!linkSecret)
41
+ console.warn("[libero-rest] LIBERO_LINK_TOKEN_SECRET 未配置:homm 链接回退 tk_main(无逐用户短 token)");
42
+ const app = createRestApp({ registry, tokenMap, chatLlm: chatLlm ?? undefined, linkSecret, linkBaseUrl, ttlSec });
43
+ serve({ fetch: app.fetch, port: PORT, hostname: HOST }, (info) => {
44
+ console.error(`[libero-rest] listening on http://${info.address}:${info.port}`);
45
+ });
46
+ function shutdown() {
47
+ console.error("[libero-rest] Shutting down…");
48
+ closeDb();
49
+ process.exit(0);
50
+ }
51
+ process.on("SIGINT", shutdown);
52
+ process.on("SIGTERM", shutdown);