level-up-mcp-server-cn 0.4.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 (137) hide show
  1. package/.claude/projects/c--Users-klexi-OneDrive-Desktop-Levelup-level-up-mcp-server/memory/project_testing_service.md +11 -0
  2. package/.claude/settings.local.json +10 -0
  3. package/.env.example +19 -0
  4. package/CLAUDE.md +222 -0
  5. package/CODE_REVIEW.md +282 -0
  6. package/LICENSE +64 -0
  7. package/README.md +198 -0
  8. package/dist/constants.d.ts +33 -0
  9. package/dist/constants.js +78 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/data/quest-seeds.d.ts +18 -0
  12. package/dist/data/quest-seeds.js +380 -0
  13. package/dist/data/quest-seeds.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +260 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/schemas/common.d.ts +33 -0
  18. package/dist/schemas/common.js +96 -0
  19. package/dist/schemas/common.js.map +1 -0
  20. package/dist/services/dispatcher.d.ts +27 -0
  21. package/dist/services/dispatcher.js +47 -0
  22. package/dist/services/dispatcher.js.map +1 -0
  23. package/dist/services/errors.d.ts +56 -0
  24. package/dist/services/errors.js +99 -0
  25. package/dist/services/errors.js.map +1 -0
  26. package/dist/services/format.d.ts +74 -0
  27. package/dist/services/format.js +144 -0
  28. package/dist/services/format.js.map +1 -0
  29. package/dist/services/ownership.d.ts +19 -0
  30. package/dist/services/ownership.js +79 -0
  31. package/dist/services/ownership.js.map +1 -0
  32. package/dist/services/quality-gate.d.ts +45 -0
  33. package/dist/services/quality-gate.js +131 -0
  34. package/dist/services/quality-gate.js.map +1 -0
  35. package/dist/services/rate-limit.d.ts +12 -0
  36. package/dist/services/rate-limit.js +49 -0
  37. package/dist/services/rate-limit.js.map +1 -0
  38. package/dist/services/register.d.ts +49 -0
  39. package/dist/services/register.js +63 -0
  40. package/dist/services/register.js.map +1 -0
  41. package/dist/services/supabase.d.ts +10 -0
  42. package/dist/services/supabase.js +79 -0
  43. package/dist/services/supabase.js.map +1 -0
  44. package/dist/tools/achievements.d.ts +6 -0
  45. package/dist/tools/achievements.js +242 -0
  46. package/dist/tools/achievements.js.map +1 -0
  47. package/dist/tools/admin.d.ts +16 -0
  48. package/dist/tools/admin.js +328 -0
  49. package/dist/tools/admin.js.map +1 -0
  50. package/dist/tools/agents.d.ts +3 -0
  51. package/dist/tools/agents.js +400 -0
  52. package/dist/tools/agents.js.map +1 -0
  53. package/dist/tools/bootstrap.d.ts +17 -0
  54. package/dist/tools/bootstrap.js +565 -0
  55. package/dist/tools/bootstrap.js.map +1 -0
  56. package/dist/tools/dispatchers/admin.d.ts +3 -0
  57. package/dist/tools/dispatchers/admin.js +50 -0
  58. package/dist/tools/dispatchers/admin.js.map +1 -0
  59. package/dist/tools/dispatchers/eval.d.ts +3 -0
  60. package/dist/tools/dispatchers/eval.js +40 -0
  61. package/dist/tools/dispatchers/eval.js.map +1 -0
  62. package/dist/tools/dispatchers/quests.d.ts +3 -0
  63. package/dist/tools/dispatchers/quests.js +60 -0
  64. package/dist/tools/dispatchers/quests.js.map +1 -0
  65. package/dist/tools/dispatchers/session.d.ts +3 -0
  66. package/dist/tools/dispatchers/session.js +38 -0
  67. package/dist/tools/dispatchers/session.js.map +1 -0
  68. package/dist/tools/dispatchers/skills.d.ts +3 -0
  69. package/dist/tools/dispatchers/skills.js +49 -0
  70. package/dist/tools/dispatchers/skills.js.map +1 -0
  71. package/dist/tools/dispatchers/tasks.d.ts +3 -0
  72. package/dist/tools/dispatchers/tasks.js +53 -0
  73. package/dist/tools/dispatchers/tasks.js.map +1 -0
  74. package/dist/tools/dispatchers/users.d.ts +3 -0
  75. package/dist/tools/dispatchers/users.js +65 -0
  76. package/dist/tools/dispatchers/users.js.map +1 -0
  77. package/dist/tools/dispatchers/xp.d.ts +3 -0
  78. package/dist/tools/dispatchers/xp.js +51 -0
  79. package/dist/tools/dispatchers/xp.js.map +1 -0
  80. package/dist/tools/growth-plan.d.ts +5 -0
  81. package/dist/tools/growth-plan.js +791 -0
  82. package/dist/tools/growth-plan.js.map +1 -0
  83. package/dist/tools/leaderboards.d.ts +10 -0
  84. package/dist/tools/leaderboards.js +279 -0
  85. package/dist/tools/leaderboards.js.map +1 -0
  86. package/dist/tools/leveling.d.ts +24 -0
  87. package/dist/tools/leveling.js +356 -0
  88. package/dist/tools/leveling.js.map +1 -0
  89. package/dist/tools/metrics.d.ts +3 -0
  90. package/dist/tools/metrics.js +247 -0
  91. package/dist/tools/metrics.js.map +1 -0
  92. package/dist/tools/quests.d.ts +5 -0
  93. package/dist/tools/quests.js +586 -0
  94. package/dist/tools/quests.js.map +1 -0
  95. package/dist/tools/ratings.d.ts +11 -0
  96. package/dist/tools/ratings.js +564 -0
  97. package/dist/tools/ratings.js.map +1 -0
  98. package/dist/tools/skills.d.ts +66 -0
  99. package/dist/tools/skills.js +1112 -0
  100. package/dist/tools/skills.js.map +1 -0
  101. package/dist/tools/system.d.ts +31 -0
  102. package/dist/tools/system.js +605 -0
  103. package/dist/tools/system.js.map +1 -0
  104. package/dist/tools/tasks.d.ts +73 -0
  105. package/dist/tools/tasks.js +1572 -0
  106. package/dist/tools/tasks.js.map +1 -0
  107. package/dist/tools/users.d.ts +97 -0
  108. package/dist/tools/users.js +1306 -0
  109. package/dist/tools/users.js.map +1 -0
  110. package/dist/tools/xp.d.ts +38 -0
  111. package/dist/tools/xp.js +670 -0
  112. package/dist/tools/xp.js.map +1 -0
  113. package/dist/types.d.ts +178 -0
  114. package/dist/types.js +12 -0
  115. package/dist/types.js.map +1 -0
  116. package/docs/recommended-skillsets.md +622 -0
  117. package/docs/skills-and-abilities-review.md +672 -0
  118. package/docs/v0.3-roadmap.md +191 -0
  119. package/package.json +35 -0
  120. package/sql/agent_pending_installs.sql +28 -0
  121. package/sql/award_class_xp.sql +81 -0
  122. package/supabase/.temp/cli-latest +1 -0
  123. package/supabase/.temp/gotrue-version +1 -0
  124. package/supabase/.temp/pooler-url +1 -0
  125. package/supabase/.temp/postgres-version +1 -0
  126. package/supabase/.temp/project-ref +1 -0
  127. package/supabase/.temp/rest-version +1 -0
  128. package/supabase/.temp/storage-migration +1 -0
  129. package/supabase/.temp/storage-version +1 -0
  130. package/supabase/migrations/20260314000000_anon_rls_policies.sql +311 -0
  131. package/supabase/migrations/20260314000001_ownership_rpcs.sql +382 -0
  132. package/supabase/migrations/20260314000002_evidence_and_growth_plan.sql +97 -0
  133. package/supabase/migrations/20260317000000_seed_quests.sql +62 -0
  134. package/supabase/migrations/20260317000001_star_cooldown_and_fixes.sql +16 -0
  135. package/supabase/migrations/20260318000000_restore_rank_names.sql +25 -0
  136. package/supabase/migrations/20260320000000_chinese_rank_names.sql +24 -0
  137. package/vitest.config.ts +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ /** UUID format validation. Supabase uses UUIDs for all primary keys. */
3
+ export declare const uuidSchema: z.ZodString;
4
+ /** Pagination: limit parameter */
5
+ export declare const limitSchema: z.ZodDefault<z.ZodNumber>;
6
+ /** Pagination: offset parameter */
7
+ export declare const offsetSchema: z.ZodDefault<z.ZodNumber>;
8
+ /** Difficulty scale used for tasks (1-7) */
9
+ export declare const difficultySchema: z.ZodNumber;
10
+ /** Completion percentage (0-100) */
11
+ export declare const completionPctSchema: z.ZodNumber;
12
+ export declare const identityProviderSchema: z.ZodEnum<[string, ...string[]]>;
13
+ export declare const performerTypeSchema: z.ZodEnum<[string, ...string[]]>;
14
+ export declare const outputTypeSchema: z.ZodEnum<[string, ...string[]]>;
15
+ export declare const taskStatusSchema: z.ZodEnum<[string, ...string[]]>;
16
+ export declare const userClassSchema: z.ZodEnum<[string, ...string[]]>;
17
+ export declare const agentPlatformSchema: z.ZodEnum<[string, ...string[]]>;
18
+ export declare const xpTierSchema: z.ZodEnum<[string, ...string[]]>;
19
+ export declare const entityTypeSchema: z.ZodEnum<[string, ...string[]]>;
20
+ /** Standard pagination parameters — used by most list_* tools */
21
+ export declare const paginationSchema: z.ZodObject<{
22
+ limit: z.ZodDefault<z.ZodNumber>;
23
+ offset: z.ZodDefault<z.ZodNumber>;
24
+ }, "strip", z.ZodTypeAny, {
25
+ limit: number;
26
+ offset: number;
27
+ }, {
28
+ limit?: number | undefined;
29
+ offset?: number | undefined;
30
+ }>;
31
+ /** Flexible metadata field — allows tools to accept extra JSON data (max 10KB) */
32
+ export declare const metadataSchema: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, Record<string, unknown> | undefined, Record<string, unknown> | undefined>;
33
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1,96 @@
1
+ // ============================================================
2
+ // schemas/common.ts — Reusable Zod validation schemas
3
+ // ============================================================
4
+ // Zod is a "runtime validator" — it checks data WHILE your code
5
+ // runs (not just at compile time like TypeScript alone).
6
+ //
7
+ // Why do we need both TypeScript AND Zod?
8
+ // - TypeScript checks your code when you BUILD it (compile time)
9
+ // - Zod checks INCOMING DATA when tools are actually called
10
+ //
11
+ // Example: an LLM might call levelup_start_task with
12
+ // { difficulty: "banana" }. TypeScript can't catch that because
13
+ // the data comes from outside your code. But Zod will reject it
14
+ // and return a clear error: "Expected number, got string."
15
+ //
16
+ // These are SHARED schemas — patterns that appear in many tools.
17
+ // Each tool file will compose these with tool-specific schemas.
18
+ // ============================================================
19
+ import { z } from "zod";
20
+ import { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, IDENTITY_PROVIDERS, PERFORMER_TYPES, OUTPUT_TYPES, TASK_STATUSES, USER_CLASSES, AGENT_PLATFORMS, XP_TIERS, } from "../constants.js";
21
+ // ---------- Primitive validators ----------
22
+ /** UUID format validation. Supabase uses UUIDs for all primary keys. */
23
+ export const uuidSchema = z
24
+ .string()
25
+ .uuid("Must be a valid UUID (e.g., '550e8400-e29b-41d4-a716-446655440000')");
26
+ /** Pagination: limit parameter */
27
+ export const limitSchema = z
28
+ .number()
29
+ .int("Limit must be a whole number")
30
+ .min(1, "Minimum limit is 1")
31
+ .max(MAX_PAGE_SIZE, `Maximum limit is ${MAX_PAGE_SIZE}`)
32
+ .default(DEFAULT_PAGE_SIZE)
33
+ .describe(`Maximum results to return (default: ${DEFAULT_PAGE_SIZE}, max: ${MAX_PAGE_SIZE})`);
34
+ /** Pagination: offset parameter */
35
+ export const offsetSchema = z
36
+ .number()
37
+ .int("Offset must be a whole number")
38
+ .min(0, "Offset cannot be negative")
39
+ .default(0)
40
+ .describe("Number of results to skip for pagination (default: 0)");
41
+ /** Difficulty scale used for tasks (1-7) */
42
+ export const difficultySchema = z
43
+ .number()
44
+ .int()
45
+ .min(1, "Minimum difficulty is 1")
46
+ .max(7, "Maximum difficulty is 7")
47
+ .describe("Task difficulty on a 1-7 scale (default 3, determined by TDI)");
48
+ /** Completion percentage (0-100) */
49
+ export const completionPctSchema = z
50
+ .number()
51
+ .int()
52
+ .min(0)
53
+ .max(100)
54
+ .describe("Completion percentage (0-100)");
55
+ // ---------- Enum validators ----------
56
+ // z.enum() creates a validator that only accepts specific string values.
57
+ // The "as [string, ...string[]]" syntax is a TypeScript trick to tell
58
+ // Zod that the array has at least one element (required by z.enum).
59
+ export const identityProviderSchema = z
60
+ .enum(IDENTITY_PROVIDERS)
61
+ .describe("Identity provider platform");
62
+ export const performerTypeSchema = z
63
+ .enum(PERFORMER_TYPES)
64
+ .describe("Who performed the task");
65
+ export const outputTypeSchema = z
66
+ .enum(OUTPUT_TYPES)
67
+ .describe("Type of output produced: conversational (1x), deliverable (1.5-2x), deployed (2-3x)");
68
+ export const taskStatusSchema = z
69
+ .enum(TASK_STATUSES)
70
+ .describe("Current task status");
71
+ export const userClassSchema = z
72
+ .enum(USER_CLASSES)
73
+ .describe("User class track");
74
+ export const agentPlatformSchema = z
75
+ .enum(AGENT_PLATFORMS)
76
+ .describe("Agent's hosting platform");
77
+ export const xpTierSchema = z
78
+ .enum(XP_TIERS)
79
+ .describe("XP base tier: micro(1-3), light(3-5), standard(10-25), complex(30-60), major(75-150)");
80
+ export const entityTypeSchema = z
81
+ .enum(["user", "agent"])
82
+ .describe("Entity type: 'user' or 'agent'");
83
+ // ---------- Composite schemas ----------
84
+ // These combine multiple fields that appear together in many tools.
85
+ /** Standard pagination parameters — used by most list_* tools */
86
+ export const paginationSchema = z.object({
87
+ limit: limitSchema,
88
+ offset: offsetSchema,
89
+ });
90
+ /** Flexible metadata field — allows tools to accept extra JSON data (max 10KB) */
91
+ export const metadataSchema = z
92
+ .record(z.unknown())
93
+ .optional()
94
+ .refine((val) => !val || JSON.stringify(val).length <= 10_000, "Metadata too large (max 10KB when serialized)")
95
+ .describe("Optional extra data as key-value pairs (JSON object, max 10KB)");
96
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { toMcpResponse } from "./register.js";
3
+ /**
4
+ * An action handler function — receives validated params and returns an MCP response.
5
+ * The `action` field is already stripped; params contain only the action-specific fields.
6
+ */
7
+ export type ActionHandler = (params: Record<string, unknown>) => Promise<ReturnType<typeof toMcpResponse>>;
8
+ /**
9
+ * Action definition for a dispatcher.
10
+ */
11
+ export interface ActionDef {
12
+ /** Short description shown in the action list */
13
+ description: string;
14
+ /** The handler function */
15
+ handler: ActionHandler;
16
+ }
17
+ /**
18
+ * Register a category dispatcher tool on the MCP server.
19
+ *
20
+ * Instead of registering 10+ individual tools, this registers ONE tool
21
+ * with an `action` parameter that routes to the correct handler.
22
+ *
23
+ * The tool description lists all available actions — this is the only
24
+ * schema the LLM sees, dramatically reducing token usage.
25
+ */
26
+ export declare function registerDispatcher(server: McpServer, toolName: string, categoryDescription: string, actions: Record<string, ActionDef>): void;
27
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1,47 @@
1
+ // ============================================================
2
+ // services/dispatcher.ts — Category dispatcher framework
3
+ // ============================================================
4
+ // Creates a single MCP tool that routes to multiple action handlers.
5
+ // Reduces 75 tools → 8 dispatchers, cutting ~93% of token overhead.
6
+ // ============================================================
7
+ import { z } from "zod";
8
+ import { toMcpResponse } from "./register.js";
9
+ import { fail } from "./errors.js";
10
+ /**
11
+ * Register a category dispatcher tool on the MCP server.
12
+ *
13
+ * Instead of registering 10+ individual tools, this registers ONE tool
14
+ * with an `action` parameter that routes to the correct handler.
15
+ *
16
+ * The tool description lists all available actions — this is the only
17
+ * schema the LLM sees, dramatically reducing token usage.
18
+ */
19
+ export function registerDispatcher(server, toolName, categoryDescription, actions) {
20
+ const actionNames = Object.keys(actions);
21
+ // Build a compact action list for the description
22
+ const actionList = actionNames
23
+ .map((name) => ` - ${name}: ${actions[name].description}`)
24
+ .join("\n");
25
+ const fullDescription = `${categoryDescription}\n\n操作列表:\n${actionList}\n\n传入 { "action": "<名称>", ...params },其中 params 取决于具体操作。`;
26
+ server.tool(toolName, fullDescription, {
27
+ action: z.enum(actionNames)
28
+ .describe("要执行的操作"),
29
+ params: z.record(z.unknown()).default({})
30
+ .describe("操作特定参数"),
31
+ }, async ({ action, params }) => {
32
+ const actionDef = actions[action];
33
+ if (!actionDef) {
34
+ return toMcpResponse(fail(`未知操作 "${action}"`, `可用操作:${actionNames.join(", ")}`));
35
+ }
36
+ try {
37
+ return await actionDef.handler(params);
38
+ }
39
+ catch (err) {
40
+ const message = err instanceof Error ? err.message : String(err);
41
+ console.error(`[${toolName}:${action}] Error:`, message);
42
+ return toMcpResponse(fail(`操作 "${action}" 失败:${message}`));
43
+ }
44
+ });
45
+ console.error(` ✅ ${toolName} (${actionNames.length} actions: ${actionNames.join(", ")})`);
46
+ }
47
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/services/dispatcher.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,yDAAyD;AACzD,+DAA+D;AAC/D,qEAAqE;AACrE,oEAAoE;AACpE,+DAA+D;AAG/D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAkBnC;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAiB,EACjB,QAAgB,EAChB,mBAA2B,EAC3B,OAAkC;IAElC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEzC,kDAAkD;IAClD,MAAM,UAAU,GAAG,WAAW;SAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;SAC1D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,eAAe,GAAG,GAAG,mBAAmB,cAAc,UAAU,2DAA2D,CAAC;IAElI,MAAM,CAAC,IAAI,CACT,QAAQ,EACR,eAAe,EACf;QACE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,WAAoC,CAAC;aACjD,QAAQ,CAAC,QAAQ,CAAC;QACrB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;aACtC,QAAQ,CAAC,QAAQ,CAAC;KACtB,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,IAAI,CACvB,SAAS,MAAM,GAAG,EAClB,QAAQ,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,IAAI,MAAM,UAAU,EAAE,OAAO,CAAC,CAAC;YACzD,OAAO,aAAa,CAAC,IAAI,CAAC,OAAO,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,KAAK,WAAW,CAAC,MAAM,aAAa,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { ToolError, ToolResult, ToolSuccess } from "../types.js";
2
+ /**
3
+ * Create a success response envelope.
4
+ *
5
+ * Every tool wraps its return value in this so the LLM always
6
+ * gets a predictable shape: { success: true, data: ... }
7
+ *
8
+ * @example
9
+ * return ok({ user_id: "abc-123", username: "alice" });
10
+ */
11
+ export declare function ok<T>(data: T): ToolSuccess<T>;
12
+ /**
13
+ * Create an error response envelope.
14
+ *
15
+ * The `suggestion` field tells the LLM what to try next.
16
+ * This is critical for MCP — without it, the agent might
17
+ * just retry the same failing call in a loop.
18
+ *
19
+ * @example
20
+ * return fail(
21
+ * "User not found",
22
+ * "Check the user_id is a valid UUID, or use levelup_find_user to look them up"
23
+ * );
24
+ */
25
+ export declare function fail(error: string, suggestion?: string): ToolError;
26
+ /**
27
+ * Convert a Supabase error into a user-friendly ToolError.
28
+ *
29
+ * Supabase errors come in a specific format:
30
+ * { message: string, details: string, hint: string, code: string }
31
+ *
32
+ * We map common Postgres error codes to helpful messages.
33
+ */
34
+ export declare function handleSupabaseError(error: {
35
+ message: string;
36
+ code?: string;
37
+ details?: string;
38
+ hint?: string;
39
+ }, context?: string): ToolError;
40
+ /**
41
+ * Wrap an async tool handler with standard error catching.
42
+ *
43
+ * This is a "higher-order function" — a function that takes
44
+ * a function and returns a new function. It's like wrapping
45
+ * a gift: the original function is inside, but now it has
46
+ * automatic error handling wrapped around it.
47
+ *
48
+ * @example
49
+ * // Instead of writing try/catch in every tool:
50
+ * const handler = withErrorHandling("register_user", async (params) => {
51
+ * // ... your logic here, just return ok() or fail()
52
+ * return ok({ user_id: "abc" });
53
+ * });
54
+ */
55
+ export declare function withErrorHandling<TParams, TData>(toolName: string, handler: (params: TParams) => Promise<ToolResult<TData>>): (params: TParams) => Promise<ToolResult<TData>>;
56
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,99 @@
1
+ // ============================================================
2
+ // services/errors.ts — Centralized error handling
3
+ // ============================================================
4
+ // Instead of writing try/catch in every tool with different
5
+ // error messages, we funnel all errors through these helpers.
6
+ // This gives us:
7
+ // 1. Consistent error format across all 69 tools
8
+ // 2. Actionable messages (tells the LLM what to do next)
9
+ // 3. One place to update if we change error handling later
10
+ // ============================================================
11
+ /**
12
+ * Create a success response envelope.
13
+ *
14
+ * Every tool wraps its return value in this so the LLM always
15
+ * gets a predictable shape: { success: true, data: ... }
16
+ *
17
+ * @example
18
+ * return ok({ user_id: "abc-123", username: "alice" });
19
+ */
20
+ export function ok(data) {
21
+ return { success: true, data };
22
+ }
23
+ /**
24
+ * Create an error response envelope.
25
+ *
26
+ * The `suggestion` field tells the LLM what to try next.
27
+ * This is critical for MCP — without it, the agent might
28
+ * just retry the same failing call in a loop.
29
+ *
30
+ * @example
31
+ * return fail(
32
+ * "User not found",
33
+ * "Check the user_id is a valid UUID, or use levelup_find_user to look them up"
34
+ * );
35
+ */
36
+ export function fail(error, suggestion) {
37
+ return { success: false, error, suggestion };
38
+ }
39
+ /**
40
+ * Convert a Supabase error into a user-friendly ToolError.
41
+ *
42
+ * Supabase errors come in a specific format:
43
+ * { message: string, details: string, hint: string, code: string }
44
+ *
45
+ * We map common Postgres error codes to helpful messages.
46
+ */
47
+ export function handleSupabaseError(error, context = "operation") {
48
+ // Postgres error code reference:
49
+ // 23505 = unique_violation (e.g., duplicate handle)
50
+ // 23503 = foreign_key_violation (e.g., referencing nonexistent user)
51
+ // 23502 = not_null_violation (e.g., missing required field)
52
+ // 42P01 = undefined_table
53
+ // PGRST116 = PostgREST "not exactly one row" (from .single())
54
+ const code = error.code || "";
55
+ if (code === "23505") {
56
+ return fail(`重复条目:${error.details || error.message}`, "该值已存在,请尝试使用其他值。");
57
+ }
58
+ if (code === "23503") {
59
+ return fail(`引用的记录未找到:${error.details || error.message}`, "请确保您引用的ID在数据库中存在。");
60
+ }
61
+ if (code === "23502") {
62
+ return fail(`缺少必填字段:${error.details || error.message}`, "请检查是否提供了所有必需的参数。");
63
+ }
64
+ if (code === "PGRST116") {
65
+ return fail(`在${context}期间未找到匹配的记录`, "请验证ID是否正确以及记录是否存在。");
66
+ }
67
+ // 未知错误的通用处理
68
+ return fail(`${context}期间发生数据库错误:${error.message}`, error.hint || "请检查参数后重试。");
69
+ }
70
+ /**
71
+ * Wrap an async tool handler with standard error catching.
72
+ *
73
+ * This is a "higher-order function" — a function that takes
74
+ * a function and returns a new function. It's like wrapping
75
+ * a gift: the original function is inside, but now it has
76
+ * automatic error handling wrapped around it.
77
+ *
78
+ * @example
79
+ * // Instead of writing try/catch in every tool:
80
+ * const handler = withErrorHandling("register_user", async (params) => {
81
+ * // ... your logic here, just return ok() or fail()
82
+ * return ok({ user_id: "abc" });
83
+ * });
84
+ */
85
+ export function withErrorHandling(toolName, handler) {
86
+ return async (params) => {
87
+ try {
88
+ return await handler(params);
89
+ }
90
+ catch (error) {
91
+ // Log the full error for debugging (goes to stderr, not to the LLM)
92
+ console.error(`[${toolName}] Unexpected error:`, error);
93
+ // Return a clean error to the LLM
94
+ const message = error instanceof Error ? error.message : String(error);
95
+ return fail(`${toolName}中发生意外错误:${message}`, "这可能是服务器问题,请重试或联系支持团队。");
96
+ }
97
+ };
98
+ }
99
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/services/errors.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kDAAkD;AAClD,+DAA+D;AAC/D,4DAA4D;AAC5D,8DAA8D;AAC9D,iBAAiB;AACjB,mDAAmD;AACnD,2DAA2D;AAC3D,6DAA6D;AAC7D,+DAA+D;AAI/D;;;;;;;;GAQG;AACH,MAAM,UAAU,EAAE,CAAI,IAAO;IAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,UAAmB;IACrD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA0E,EAC1E,UAAkB,WAAW;IAE7B,iCAAiC;IACjC,oDAAoD;IACpD,qEAAqE;IACrE,4DAA4D;IAC5D,0BAA0B;IAC1B,8DAA8D;IAE9D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;IAE9B,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CACT,QAAQ,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,EACxC,iBAAiB,CAClB,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CACT,YAAY,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,EAC5C,mBAAmB,CACpB,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CACT,UAAU,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,EAC1C,kBAAkB,CACnB,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,IAAI,CACT,IAAI,OAAO,YAAY,EACvB,oBAAoB,CACrB,CAAC;IACJ,CAAC;IAED,YAAY;IACZ,OAAO,IAAI,CACT,GAAG,OAAO,aAAa,KAAK,CAAC,OAAO,EAAE,EACtC,KAAK,CAAC,IAAI,IAAI,WAAW,CAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,OAAwD;IAExD,OAAO,KAAK,EAAE,MAAe,EAA8B,EAAE;QAC3D,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,oEAAoE;YACpE,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAExD,kCAAkC;YAClC,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,OAAO,IAAI,CACT,GAAG,QAAQ,WAAW,OAAO,EAAE,EAC/B,uBAAuB,CACxB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { PaginatedResponse, ToolResult } from "../types.js";
2
+ /**
3
+ * Format a ToolResult as a text string for the MCP response.
4
+ *
5
+ * This is the final step before returning from any tool —
6
+ * it converts our structured result into the text content
7
+ * that the MCP protocol expects.
8
+ */
9
+ export declare function formatToolResponse(result: ToolResult): string;
10
+ /**
11
+ * Build a standard paginated response object.
12
+ *
13
+ * Used by any tool that returns lists (list_tasks, list_agents, etc).
14
+ * Gives the LLM all the info it needs to paginate:
15
+ * - total: how many items exist in total
16
+ * - has_more: whether there's another page
17
+ * - next_offset: what offset to use for the next page
18
+ *
19
+ * @param items - The items for this page
20
+ * @param total - Total count of all matching items
21
+ * @param offset - Current offset (how many items were skipped)
22
+ *
23
+ * @example
24
+ * const response = paginate(users, totalCount, params.offset);
25
+ * return ok(response);
26
+ */
27
+ export declare function paginate<T>(items: T[], total: number, offset: number): PaginatedResponse<T>;
28
+ /**
29
+ * Truncate a response string if it exceeds CHARACTER_LIMIT.
30
+ *
31
+ * LLMs have context windows. If a tool returns a 500KB response,
32
+ * it wastes context and slows everything down. This function
33
+ * truncates gracefully and tells the LLM to use pagination.
34
+ */
35
+ export declare function truncateIfNeeded(text: string, hint?: string): string;
36
+ /**
37
+ * Generate a random profile code in the format LVL-XXXX-XXXX.
38
+ *
39
+ * Uses alphanumeric characters (no O/0/I/1 to avoid confusion).
40
+ * This is used during user registration.
41
+ */
42
+ export declare function generateProfileCode(): string;
43
+ /**
44
+ * Generate a random link code in the format LINK-XXXX.
45
+ */
46
+ export declare function generateLinkCode(): string;
47
+ /**
48
+ * Format rank display with stars.
49
+ *
50
+ * Each rank covers a range of levels. Stars show progress within that range.
51
+ * E.g. Rank E covers levels 1-5:
52
+ * Level 1 → "Rank E ★☆☆☆☆ — Analyst"
53
+ * Level 3 → "Rank E ★★★☆☆ — Analyst"
54
+ * Level 5 → "Rank E ★★★★★ — Analyst"
55
+ *
56
+ * @param level - Current level (1-30)
57
+ * @param rankLetter - e.g. "E", "D", "C", "B", "A", "S"
58
+ * @param rankName - e.g. "Analyst", "Novice", "Pathfinder", "Enlightened"
59
+ * @param minLevel - The rank's min_level from rank_definitions
60
+ * @param maxLevel - The rank's max_level from rank_definitions
61
+ */
62
+ export declare function formatRankDisplay(level: number, rankLetter: string | null, rankName: string | null, minLevel: number, maxLevel: number): {
63
+ rank_display: string;
64
+ stars: string;
65
+ stars_earned: number;
66
+ stars_total: number;
67
+ };
68
+ /**
69
+ * Format a timestamp string to a human-readable form.
70
+ * Converts ISO strings like "2025-03-13T10:30:00Z" to
71
+ * "Mar 13, 2025, 10:30 AM"
72
+ */
73
+ export declare function formatTimestamp(iso: string): string;
74
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1,144 @@
1
+ // ============================================================
2
+ // services/format.ts — Response formatting helpers
3
+ // ============================================================
4
+ // MCP tools return text to the LLM. This file provides helpers
5
+ // to format that text consistently — either as JSON (for when
6
+ // the LLM needs to process data) or Markdown (for when a human
7
+ // will read it).
8
+ //
9
+ // Why both formats?
10
+ // - JSON: compact, easy for agents to parse, good for chaining
11
+ // tool calls (e.g., get user → start task with user_id)
12
+ // - Markdown: readable, good for when the user asks "show me
13
+ // my profile" and expects a nice display
14
+ // ============================================================
15
+ import { CHARACTER_LIMIT } from "../constants.js";
16
+ /**
17
+ * Format a ToolResult as a text string for the MCP response.
18
+ *
19
+ * This is the final step before returning from any tool —
20
+ * it converts our structured result into the text content
21
+ * that the MCP protocol expects.
22
+ */
23
+ export function formatToolResponse(result) {
24
+ return JSON.stringify(result, null, 2);
25
+ }
26
+ /**
27
+ * Build a standard paginated response object.
28
+ *
29
+ * Used by any tool that returns lists (list_tasks, list_agents, etc).
30
+ * Gives the LLM all the info it needs to paginate:
31
+ * - total: how many items exist in total
32
+ * - has_more: whether there's another page
33
+ * - next_offset: what offset to use for the next page
34
+ *
35
+ * @param items - The items for this page
36
+ * @param total - Total count of all matching items
37
+ * @param offset - Current offset (how many items were skipped)
38
+ *
39
+ * @example
40
+ * const response = paginate(users, totalCount, params.offset);
41
+ * return ok(response);
42
+ */
43
+ export function paginate(items, total, offset) {
44
+ const hasMore = total > offset + items.length;
45
+ return {
46
+ total,
47
+ count: items.length,
48
+ offset,
49
+ items,
50
+ has_more: hasMore,
51
+ ...(hasMore ? { next_offset: offset + items.length } : {}),
52
+ };
53
+ }
54
+ /**
55
+ * Truncate a response string if it exceeds CHARACTER_LIMIT.
56
+ *
57
+ * LLMs have context windows. If a tool returns a 500KB response,
58
+ * it wastes context and slows everything down. This function
59
+ * truncates gracefully and tells the LLM to use pagination.
60
+ */
61
+ export function truncateIfNeeded(text, hint = "使用分页(limit + offset)获取更多结果。") {
62
+ if (text.length <= CHARACTER_LIMIT) {
63
+ return text;
64
+ }
65
+ // Cut roughly in half and add a truncation notice
66
+ const truncated = text.slice(0, CHARACTER_LIMIT - 200);
67
+ const notice = `\n\n⚠️ 响应已截断(${text.length} → ${truncated.length} 字符)。${hint}`;
68
+ return truncated + notice;
69
+ }
70
+ /**
71
+ * Generate a random profile code in the format LVL-XXXX-XXXX.
72
+ *
73
+ * Uses alphanumeric characters (no O/0/I/1 to avoid confusion).
74
+ * This is used during user registration.
75
+ */
76
+ export function generateProfileCode() {
77
+ // Characters that are easy to read (no ambiguous ones)
78
+ const chars = "2345679ABCDEFGHJKLMNPQRSTUVWXYZ";
79
+ const segment = () => {
80
+ let result = "";
81
+ for (let i = 0; i < 4; i++) {
82
+ result += chars[Math.floor(Math.random() * chars.length)];
83
+ }
84
+ return result;
85
+ };
86
+ return `LVL-${segment()}-${segment()}`;
87
+ }
88
+ /**
89
+ * Generate a random link code in the format LINK-XXXX.
90
+ */
91
+ export function generateLinkCode() {
92
+ const chars = "2345679ABCDEFGHJKLMNPQRSTUVWXYZ";
93
+ let code = "";
94
+ for (let i = 0; i < 4; i++) {
95
+ code += chars[Math.floor(Math.random() * chars.length)];
96
+ }
97
+ return `LINK-${code}`;
98
+ }
99
+ /**
100
+ * Format rank display with stars.
101
+ *
102
+ * Each rank covers a range of levels. Stars show progress within that range.
103
+ * E.g. Rank E covers levels 1-5:
104
+ * Level 1 → "Rank E ★☆☆☆☆ — Analyst"
105
+ * Level 3 → "Rank E ★★★☆☆ — Analyst"
106
+ * Level 5 → "Rank E ★★★★★ — Analyst"
107
+ *
108
+ * @param level - Current level (1-30)
109
+ * @param rankLetter - e.g. "E", "D", "C", "B", "A", "S"
110
+ * @param rankName - e.g. "Analyst", "Novice", "Pathfinder", "Enlightened"
111
+ * @param minLevel - The rank's min_level from rank_definitions
112
+ * @param maxLevel - The rank's max_level from rank_definitions
113
+ */
114
+ export function formatRankDisplay(level, rankLetter, rankName, minLevel, maxLevel) {
115
+ if (!rankLetter) {
116
+ return { rank_display: "未定级", stars: "☆☆☆☆☆", stars_earned: 0, stars_total: 5 };
117
+ }
118
+ const starsTotal = maxLevel - minLevel + 1;
119
+ const starsEarned = Math.min(level - minLevel + 1, starsTotal);
120
+ const stars = "★".repeat(starsEarned) + "☆".repeat(Math.max(0, starsTotal - starsEarned));
121
+ const name = rankName || "未知";
122
+ const rankDisplay = `段位 ${rankLetter} ${stars} — ${name}`;
123
+ return { rank_display: rankDisplay, stars, stars_earned: starsEarned, stars_total: starsTotal };
124
+ }
125
+ /**
126
+ * Format a timestamp string to a human-readable form.
127
+ * Converts ISO strings like "2025-03-13T10:30:00Z" to
128
+ * "Mar 13, 2025, 10:30 AM"
129
+ */
130
+ export function formatTimestamp(iso) {
131
+ try {
132
+ return new Date(iso).toLocaleString("zh-CN", {
133
+ month: "short",
134
+ day: "numeric",
135
+ year: "numeric",
136
+ hour: "numeric",
137
+ minute: "2-digit",
138
+ });
139
+ }
140
+ catch {
141
+ return iso; // Return as-is if parsing fails
142
+ }
143
+ }
144
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/services/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { toMcpResponse } from "./register.js";
2
+ /**
3
+ * Verify that a caller has access to the requested entity's data.
4
+ *
5
+ * Rules:
6
+ * - If target user_id matches caller_user_id → allowed
7
+ * - If target agent_id is owned by caller_user_id → allowed
8
+ * - If target is a task, verify caller owns the task's user_id or agent
9
+ * - Otherwise → denied
10
+ *
11
+ * @returns null if access is allowed, or an MCP error response if denied
12
+ */
13
+ export declare function verifyOwnership(params: {
14
+ caller_user_id: string;
15
+ target_user_id?: string | null;
16
+ target_agent_id?: string | null;
17
+ target_task_id?: string | null;
18
+ }): Promise<ReturnType<typeof toMcpResponse> | null>;
19
+ //# sourceMappingURL=ownership.d.ts.map