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.
- package/.claude/projects/c--Users-klexi-OneDrive-Desktop-Levelup-level-up-mcp-server/memory/project_testing_service.md +11 -0
- package/.claude/settings.local.json +10 -0
- package/.env.example +19 -0
- package/CLAUDE.md +222 -0
- package/CODE_REVIEW.md +282 -0
- package/LICENSE +64 -0
- package/README.md +198 -0
- package/dist/constants.d.ts +33 -0
- package/dist/constants.js +78 -0
- package/dist/constants.js.map +1 -0
- package/dist/data/quest-seeds.d.ts +18 -0
- package/dist/data/quest-seeds.js +380 -0
- package/dist/data/quest-seeds.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +260 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +33 -0
- package/dist/schemas/common.js +96 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/services/dispatcher.d.ts +27 -0
- package/dist/services/dispatcher.js +47 -0
- package/dist/services/dispatcher.js.map +1 -0
- package/dist/services/errors.d.ts +56 -0
- package/dist/services/errors.js +99 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/format.d.ts +74 -0
- package/dist/services/format.js +144 -0
- package/dist/services/format.js.map +1 -0
- package/dist/services/ownership.d.ts +19 -0
- package/dist/services/ownership.js +79 -0
- package/dist/services/ownership.js.map +1 -0
- package/dist/services/quality-gate.d.ts +45 -0
- package/dist/services/quality-gate.js +131 -0
- package/dist/services/quality-gate.js.map +1 -0
- package/dist/services/rate-limit.d.ts +12 -0
- package/dist/services/rate-limit.js +49 -0
- package/dist/services/rate-limit.js.map +1 -0
- package/dist/services/register.d.ts +49 -0
- package/dist/services/register.js +63 -0
- package/dist/services/register.js.map +1 -0
- package/dist/services/supabase.d.ts +10 -0
- package/dist/services/supabase.js +79 -0
- package/dist/services/supabase.js.map +1 -0
- package/dist/tools/achievements.d.ts +6 -0
- package/dist/tools/achievements.js +242 -0
- package/dist/tools/achievements.js.map +1 -0
- package/dist/tools/admin.d.ts +16 -0
- package/dist/tools/admin.js +328 -0
- package/dist/tools/admin.js.map +1 -0
- package/dist/tools/agents.d.ts +3 -0
- package/dist/tools/agents.js +400 -0
- package/dist/tools/agents.js.map +1 -0
- package/dist/tools/bootstrap.d.ts +17 -0
- package/dist/tools/bootstrap.js +565 -0
- package/dist/tools/bootstrap.js.map +1 -0
- package/dist/tools/dispatchers/admin.d.ts +3 -0
- package/dist/tools/dispatchers/admin.js +50 -0
- package/dist/tools/dispatchers/admin.js.map +1 -0
- package/dist/tools/dispatchers/eval.d.ts +3 -0
- package/dist/tools/dispatchers/eval.js +40 -0
- package/dist/tools/dispatchers/eval.js.map +1 -0
- package/dist/tools/dispatchers/quests.d.ts +3 -0
- package/dist/tools/dispatchers/quests.js +60 -0
- package/dist/tools/dispatchers/quests.js.map +1 -0
- package/dist/tools/dispatchers/session.d.ts +3 -0
- package/dist/tools/dispatchers/session.js +38 -0
- package/dist/tools/dispatchers/session.js.map +1 -0
- package/dist/tools/dispatchers/skills.d.ts +3 -0
- package/dist/tools/dispatchers/skills.js +49 -0
- package/dist/tools/dispatchers/skills.js.map +1 -0
- package/dist/tools/dispatchers/tasks.d.ts +3 -0
- package/dist/tools/dispatchers/tasks.js +53 -0
- package/dist/tools/dispatchers/tasks.js.map +1 -0
- package/dist/tools/dispatchers/users.d.ts +3 -0
- package/dist/tools/dispatchers/users.js +65 -0
- package/dist/tools/dispatchers/users.js.map +1 -0
- package/dist/tools/dispatchers/xp.d.ts +3 -0
- package/dist/tools/dispatchers/xp.js +51 -0
- package/dist/tools/dispatchers/xp.js.map +1 -0
- package/dist/tools/growth-plan.d.ts +5 -0
- package/dist/tools/growth-plan.js +791 -0
- package/dist/tools/growth-plan.js.map +1 -0
- package/dist/tools/leaderboards.d.ts +10 -0
- package/dist/tools/leaderboards.js +279 -0
- package/dist/tools/leaderboards.js.map +1 -0
- package/dist/tools/leveling.d.ts +24 -0
- package/dist/tools/leveling.js +356 -0
- package/dist/tools/leveling.js.map +1 -0
- package/dist/tools/metrics.d.ts +3 -0
- package/dist/tools/metrics.js +247 -0
- package/dist/tools/metrics.js.map +1 -0
- package/dist/tools/quests.d.ts +5 -0
- package/dist/tools/quests.js +586 -0
- package/dist/tools/quests.js.map +1 -0
- package/dist/tools/ratings.d.ts +11 -0
- package/dist/tools/ratings.js +564 -0
- package/dist/tools/ratings.js.map +1 -0
- package/dist/tools/skills.d.ts +66 -0
- package/dist/tools/skills.js +1112 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/system.d.ts +31 -0
- package/dist/tools/system.js +605 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/tasks.d.ts +73 -0
- package/dist/tools/tasks.js +1572 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/users.d.ts +97 -0
- package/dist/tools/users.js +1306 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/tools/xp.d.ts +38 -0
- package/dist/tools/xp.js +670 -0
- package/dist/tools/xp.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/docs/recommended-skillsets.md +622 -0
- package/docs/skills-and-abilities-review.md +672 -0
- package/docs/v0.3-roadmap.md +191 -0
- package/package.json +35 -0
- package/sql/agent_pending_installs.sql +28 -0
- package/sql/award_class_xp.sql +81 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/.temp/gotrue-version +1 -0
- package/supabase/.temp/pooler-url +1 -0
- package/supabase/.temp/postgres-version +1 -0
- package/supabase/.temp/project-ref +1 -0
- package/supabase/.temp/rest-version +1 -0
- package/supabase/.temp/storage-migration +1 -0
- package/supabase/.temp/storage-version +1 -0
- package/supabase/migrations/20260314000000_anon_rls_policies.sql +311 -0
- package/supabase/migrations/20260314000001_ownership_rpcs.sql +382 -0
- package/supabase/migrations/20260314000002_evidence_and_growth_plan.sql +97 -0
- package/supabase/migrations/20260317000000_seed_quests.sql +62 -0
- package/supabase/migrations/20260317000001_star_cooldown_and_fixes.sql +16 -0
- package/supabase/migrations/20260318000000_restore_rank_names.sql +25 -0
- package/supabase/migrations/20260320000000_chinese_rank_names.sql +24 -0
- 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
|