@timetick/mcp 0.2.1 → 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.
- package/LICENSE +662 -0
- package/README.md +65 -70
- package/dist/index.js +3100 -284
- package/package.json +8 -4
- package/dist/index.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timetick/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Timetick (https://app.timetick.io) platform",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"author": "Timetick <support@timetick.io>",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"ocpp",
|
|
15
15
|
"ev-charging",
|
|
16
16
|
"claude",
|
|
17
|
+
"codex",
|
|
18
|
+
"gemini",
|
|
17
19
|
"ai-agent",
|
|
18
20
|
"load-testing"
|
|
19
21
|
],
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
"README.md"
|
|
28
30
|
],
|
|
29
31
|
"engines": {
|
|
30
|
-
"node": ">=18"
|
|
32
|
+
"node": ">=18.14"
|
|
31
33
|
},
|
|
32
34
|
"publishConfig": {
|
|
33
35
|
"access": "public",
|
|
@@ -40,11 +42,13 @@
|
|
|
40
42
|
"typecheck": "tsc --noEmit",
|
|
41
43
|
"start": "node dist/index.js",
|
|
42
44
|
"inspect": "npx @modelcontextprotocol/inspector node dist/index.js",
|
|
43
|
-
"test": "vitest run"
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:contract": "vitest run src/__tests__/contract",
|
|
47
|
+
"plugin:sync": "node scripts/sync-plugin.mjs"
|
|
44
48
|
},
|
|
45
49
|
"dependencies": {
|
|
46
50
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
47
|
-
"@timetick/sdk": "^
|
|
51
|
+
"@timetick/sdk": "^3.0.0",
|
|
48
52
|
"graphql": "^16.0.0",
|
|
49
53
|
"zod": "^4.4.3"
|
|
50
54
|
},
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/tools/context.ts","../src/sdk.ts","../src/context.ts","../src/result.ts","../src/tools/data.ts","../src/links.ts","../src/resolve.ts","../src/pagination.ts","../src/tools/simulators.ts","../src/tools/tests.ts","../src/tools/test-runs.ts","../src/tools/support.ts","../src/logs-format.ts","../src/tools/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { isReadOnlyMode, registerTools } from \"./tools/index.js\";\n\nasync function main() {\n if (!process.env.TIMETICK_API_TOKEN) {\n console.error(\n \"TIMETICK_API_TOKEN is not set. Generate an API key in the Timetick portal \" +\n \"(Account → API keys) and expose it to the MCP server as TIMETICK_API_TOKEN.\",\n );\n process.exit(1);\n }\n\n const server = new McpServer({ name: \"timetick\", version: \"0.2.1\" });\n\n const readOnly = isReadOnlyMode();\n registerTools(server, { readOnly });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(`Timetick MCP server running on stdio${readOnly ? \" (read-only)\" : \"\"}`);\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error starting Timetick MCP server:\", error);\n process.exit(1);\n});\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { getContext, useProject, peekContext } from \"../context.js\";\nimport { ok, guard } from \"../result.js\";\n\nexport function registerContextTools(server: McpServer) {\n server.registerTool(\n \"get_context\",\n {\n annotations: { readOnlyHint: true },\n title: \"Get active context\",\n description:\n \"Show the project and sim world the MCP server is currently operating on. \" +\n \"If no project is selected yet and you have only one project, it is auto-selected.\",\n inputSchema: {},\n },\n async () =>\n guard(async () => {\n const ctx = peekContext() ?? (await getContext());\n return ok(\n `Active project: ${ctx.projectName} (id: ${ctx.projectId}); sim world: ${ctx.simWorldId} [${ctx.source}]`,\n ctx,\n );\n }),\n );\n\n server.registerTool(\n \"use_project\",\n {\n annotations: { readOnlyHint: true },\n title: \"Select project\",\n description:\n \"Switch the active project by name or id. Only needed if you have more than one project. \" +\n \"Caches the project's sim world for subsequent tools.\",\n inputSchema: {\n project: z.string().describe(\"Project name or id to make active\"),\n },\n },\n async ({ project }) =>\n guard(async () => {\n const ctx = await useProject({ project });\n return ok(`Active project is now ${ctx.projectName} (id: ${ctx.projectId}).`, ctx);\n }),\n );\n}\n","import { createClient, type TimetickClient } from \"@timetick/sdk\";\n\nlet client: TimetickClient | null = null;\n\n/** Lazily-created singleton Timetick SDK client, authenticated from the environment. */\nexport function sdk(): TimetickClient {\n if (client) return client;\n\n const apiKey = process.env.TIMETICK_API_TOKEN;\n if (!apiKey) {\n throw new Error(\n \"TIMETICK_API_TOKEN is not set. Generate an API key in the Timetick portal \" +\n \"(Account → API keys) and expose it to the MCP server as TIMETICK_API_TOKEN.\",\n );\n }\n\n client = createClient({ apiKey, endpoint: process.env.TIMETICK_API_URL });\n return client;\n}\n","import { sdk } from \"./sdk.js\";\n\nexport interface Context {\n projectId: string;\n projectName: string;\n simWorldId: string;\n /** Scope id used by hardware/device queries — distinct from simWorldId. */\n deviceScopeId: string;\n /** How the project was chosen — surfaced to the user for transparency. */\n source: \"single-project\" | \"explicit\";\n}\n\n/** Thrown when the project/sim world can't be resolved without user input. */\nexport class ContextError extends Error {}\n\nlet cached: Context | null = null;\n\n/** Resolves a project's sim world (one sim world per project today). */\nasync function buildContext(\n projectId: string,\n projectName: string,\n source: Context[\"source\"],\n): Promise<Context> {\n const worlds = await sdk().simWorlds.list(projectId);\n const world = worlds?.[0];\n if (!world?.id) {\n throw new ContextError(`Project \"${projectName}\" has no sim world to operate on.`);\n }\n return {\n projectId,\n projectName,\n simWorldId: world.id,\n deviceScopeId: world.deviceScopeId ?? world.id,\n source,\n };\n}\n\nconst PROJECT_LIST_LIMIT = 15;\n\ntype ProjectSummary = { id?: string | null; name?: string | null } | null | undefined;\n\nfunction formatProjects(projects: readonly ProjectSummary[] | null | undefined): string {\n const all = projects ?? [];\n const lines = all\n .slice(0, PROJECT_LIST_LIMIT)\n .map((p) => ` - ${p?.name} (id: ${p?.id})`);\n if (all.length > PROJECT_LIST_LIMIT) {\n lines.push(` …and ${all.length - PROJECT_LIST_LIMIT} more — call list_projects to see them all.`);\n }\n return lines.join(\"\\n\");\n}\n\nasync function findProject(project: string): Promise<{ id: string; name: string }> {\n const projects = await sdk().projects.list();\n const needle = project.toLowerCase();\n const match = projects?.find(\n (p) => p?.id === project || p?.name?.toLowerCase() === needle,\n );\n if (!match?.id) {\n throw new ContextError(\n `No project matching \"${project}\". Available:\\n${formatProjects(projects)}`,\n );\n }\n return { id: match.id, name: match.name ?? \"(unnamed)\" };\n}\n\n/**\n * Returns the active context, auto-selecting the project when there is only one.\n * Throws ContextError (with the project list) when the choice is ambiguous.\n */\nexport async function getContext(): Promise<Context> {\n if (cached) return cached;\n\n const projects = await sdk().projects.list();\n if (!projects || projects.length === 0) {\n throw new ContextError(\"No projects are available for this API key.\");\n }\n if (projects.length > 1) {\n throw new ContextError(\n `You have ${projects.length} projects. Call \\`use_project\\` with a project name or id ` +\n `first:\\n${formatProjects(projects)}`,\n );\n }\n\n const only = projects[0]!;\n cached = await buildContext(only.id!, only.name ?? \"(unnamed)\", \"single-project\");\n return cached;\n}\n\n/** Explicitly switches the active project by name or id, and caches its sim world. */\nexport async function useProject(input: { project: string }): Promise<Context> {\n const match = await findProject(input.project);\n cached = await buildContext(match.id, match.name, \"explicit\");\n return cached;\n}\n\nexport async function lookupProject(project: string): Promise<Context> {\n const match = await findProject(project);\n return buildContext(match.id, match.name, \"explicit\");\n}\n\n/** Returns the cached context without resolving, if any. */\nexport function peekContext(): Context | null {\n return cached;\n}\n","import { TimetickError } from \"@timetick/sdk\";\n\ntype ToolResult = {\n content: { type: \"text\"; text: string }[];\n isError?: boolean;\n};\n\n/** Wraps a value into an MCP text result, pretty-printing objects as JSON. */\nexport function ok(text: string, data?: unknown): ToolResult {\n const body = data === undefined ? text : `${text}\\n\\n${JSON.stringify(data, null, 2)}`;\n return { content: [{ type: \"text\", text: body }] };\n}\n\nexport function fail(message: string): ToolResult {\n return { content: [{ type: \"text\", text: message }], isError: true };\n}\n\n/** Runs a tool handler, normalizing SDK/unknown errors into an isError result. */\nexport async function guard(fn: () => Promise<ToolResult>): Promise<ToolResult> {\n try {\n return await fn();\n } catch (err) {\n if (err instanceof TimetickError) return fail(`Timetick API error: ${err.message}`);\n return fail(err instanceof Error ? err.message : String(err));\n }\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { sdk } from \"../sdk.js\";\nimport { resolveSimWorld, resolveSimulatorTarget } from \"../resolve.js\";\nimport { SIMULATOR_ARG_DESCRIPTION } from \"../links.js\";\nimport { paginationArgs, pagination, pageSummary } from \"../pagination.js\";\nimport { ok, guard } from \"../result.js\";\n\nconst protocolEnum = z.enum([\"OCPP_1_6\", \"OCPP_2_0_1\"]);\n\nfunction summarizeArgs(params: unknown): Record<string, string> | undefined {\n if (!params || typeof params !== \"object\") return undefined;\n const summary: Record<string, string> = {};\n for (const [name, spec] of Object.entries(params as Record<string, unknown>)) {\n if (!spec || typeof spec !== \"object\") continue;\n const { type, allowNull, defaultValue, visible } = spec as Record<string, unknown>;\n if (visible === false) continue;\n const parts = [String(type ?? \"unknown\"), allowNull === false ? \"required\" : \"optional\"];\n if (defaultValue !== undefined) parts.push(`default ${JSON.stringify(defaultValue)}`);\n summary[name] = parts.join(\", \");\n }\n return Object.keys(summary).length > 0 ? summary : undefined;\n}\n\nexport function registerDataTools(server: McpServer) {\n server.registerTool(\n \"list_projects\",\n {\n annotations: { readOnlyHint: true },\n title: \"List projects\",\n description: \"List all projects available to your API key.\",\n inputSchema: {},\n },\n async () =>\n guard(async () => {\n const projects = await sdk().projects.list();\n return ok(`Found ${projects?.length ?? 0} project(s).`, projects);\n }),\n );\n\n server.registerTool(\n \"list_simulators\",\n {\n annotations: { readOnlyHint: true },\n title: \"List simulators\",\n description:\n \"List simulators (virtual chargers) in the active project's sim world. \" +\n \"Optionally filter by name search or protocol.\",\n inputSchema: {\n search: z.string().optional().describe(\"Filter by simulator base name\"),\n protocol: protocolEnum.optional(),\n ...paginationArgs,\n project: z.string().optional().describe(\"Project name or id (defaults to active project)\"),\n },\n },\n async ({ search, protocol, page, pageSize, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n const result = await sdk().simulators.list({\n simWorldId: ctx.simWorldId,\n searchValue: search,\n filters: protocol ? { protocol } : undefined,\n pagination: pagination(page, pageSize),\n });\n return ok(\n pageSummary(\"simulator(s)\", result?.records?.length ?? 0, result?.pageInfo),\n result,\n );\n }),\n );\n\n server.registerTool(\n \"get_simulator\",\n {\n annotations: { readOnlyHint: true },\n title: \"Get simulator\",\n description:\n \"Get a simulator's details and live status (network status, launched/power status, connectors) \" +\n \"by id or base name.\",\n inputSchema: {\n simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION),\n project: z.string().optional().describe(\"Project name or id (defaults to active project)\"),\n },\n },\n async ({ simulator, project }) =>\n guard(async () => {\n const { sim: resolved } = await resolveSimulatorTarget(simulator, project);\n const details = await sdk().simulators.get(resolved.id);\n return ok(`Simulator ${resolved.baseName} (id: ${resolved.id}).`, details);\n }),\n );\n\n server.registerTool(\n \"list_hardware\",\n {\n annotations: { readOnlyHint: true },\n title: \"List hardware\",\n description: \"List physical OCPP hardware devices in the active project's sim world.\",\n inputSchema: {\n search: z.string().optional().describe(\"Filter by serial number / model\"),\n ...paginationArgs,\n project: z.string().optional().describe(\"Project name or id (defaults to active project)\"),\n },\n },\n async ({ search, page, pageSize, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n const result = await sdk().hardware.list({\n deviceScopeId: ctx.deviceScopeId,\n searchValue: search,\n pagination: pagination(page, pageSize),\n });\n return ok(\n pageSummary(\"hardware device(s)\", result?.records?.length ?? 0, result?.pageInfo),\n result,\n );\n }),\n );\n\n server.registerTool(\n \"list_actions\",\n {\n annotations: { readOnlyHint: true },\n title: \"List actions (test steps)\",\n description:\n \"List available actions (steps) you can use to build a test — e.g. 'Power On Charger', \" +\n \"'Plug In Connector', 'Charge a Vehicle'. Filter by protocol. Each action lists its \" +\n \"arguments: the name, whether it is required (allowNull false), and any default.\",\n inputSchema: {\n protocol: protocolEnum.optional(),\n search: z.string().optional().describe(\"Filter by action name\"),\n ...paginationArgs,\n project: z.string().optional().describe(\"Project name or id (defaults to active project)\"),\n },\n },\n async ({ protocol, search, page, pageSize, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n const result = await sdk().actions.list({\n simWorldId: ctx.simWorldId,\n searchValue: search,\n filters: { isSystem: true, deviceType: \"CHARGER\", ...(protocol ? { protocol } : {}) },\n pagination: pagination(page, pageSize, 100),\n });\n const actions = (result?.records ?? []).map((a) => ({\n name: a?.name,\n description: a?.description ?? undefined,\n args: summarizeArgs(a?.params),\n }));\n return ok(pageSummary(\"action(s)\", actions.length, result?.pageInfo), actions);\n }),\n );\n}\n","export interface SimulatorRef {\n simulator: string;\n project?: string;\n}\n\nconst SIMULATOR_PATH = /\\/projects\\/([^/?#&|>\\s]+)\\/simulators\\/([^/?#&|>\\s]+)/;\n\nfunction looksLikeLink(text: string): boolean {\n return /^<?https?:\\/\\//i.test(text) || /(^|\\.)timetick\\.io\\//i.test(text);\n}\n\nexport function parseSimulatorRef(input: string): SimulatorRef {\n const text = input.trim();\n if (!looksLikeLink(text)) return { simulator: text };\n\n // Slack escapes & as & in links.\n const unescaped = text.replace(/&/g, \"&\");\n const match = unescaped.match(SIMULATOR_PATH);\n if (!match) {\n throw new Error(\n `\"${input}\" looks like a link but not to a simulator. Expected ` +\n \"https://app.timetick.io/projects/<project id>/simulators/<simulator id>.\",\n );\n }\n return { project: decodeURIComponent(match[1]!), simulator: decodeURIComponent(match[2]!) };\n}\n\nexport const SIMULATOR_ARG_DESCRIPTION =\n \"Simulator id, base name, or portal link (https://app.timetick.io/projects/<id>/simulators/<id>)\";\n","import { sdk } from \"./sdk.js\";\nimport { getContext, lookupProject, type Context } from \"./context.js\";\nimport { parseSimulatorRef } from \"./links.js\";\n\n/** Resolves the sim world to operate in: explicit project arg wins, else session context. */\nexport async function resolveSimWorld(project?: string): Promise<Context> {\n if (project) return lookupProject(project);\n return getContext();\n}\n\nexport interface ResolvedSimulator {\n id: string;\n baseName: string;\n protocol: string;\n}\n\n/** Resolves a simulator by id or by (case-insensitive) base name within a sim world. */\nexport async function resolveSimulator(\n simWorldId: string,\n simulator: string,\n): Promise<ResolvedSimulator> {\n const needle = simulator.toLowerCase();\n const page = await sdk().simulators.list({ simWorldId, searchValue: simulator });\n const records = page?.records ?? [];\n\n const exact =\n records.find((r) => r?.id === simulator) ??\n records.find((r) => r?.baseName?.toLowerCase() === needle) ??\n (records.length === 1 ? records[0] : undefined);\n\n if (exact?.id) {\n return { id: exact.id, baseName: exact.baseName ?? \"\", protocol: String(exact.protocol) };\n }\n\n // Fall back to treating the input as a raw id.\n const byId = await sdk().simulators.get(simulator).catch(() => null);\n if (byId?.id) {\n return { id: byId.id, baseName: byId.baseName ?? \"\", protocol: String(byId.protocol) };\n }\n\n const candidates = records.map((r) => ` - ${r?.baseName} (id: ${r?.id})`).join(\"\\n\");\n throw new Error(\n `No simulator matching \"${simulator}\".` +\n (candidates ? `\\nCandidates:\\n${candidates}` : \" No simulators found in this sim world.\"),\n );\n}\n\nexport async function resolveSimulatorTarget(\n simulator: string,\n project?: string,\n): Promise<{ ctx: Context; sim: ResolvedSimulator }> {\n const ref = parseSimulatorRef(simulator);\n const ctx = await resolveSimWorld(ref.project ?? project);\n const sim = ref.project !== undefined\n ? await resolveSimulatorById(ref.simulator)\n : await resolveSimulator(ctx.simWorldId, ref.simulator);\n return { ctx, sim };\n}\n\nasync function resolveSimulatorById(id: string): Promise<ResolvedSimulator> {\n const byId = await sdk().simulators.get(id).catch((err: unknown) => {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`No simulator with id ${id} from the portal link: ${reason}`);\n });\n if (!byId?.id) throw new Error(`No simulator with id ${id} from the portal link.`);\n return { id: byId.id, baseName: byId.baseName ?? \"\", protocol: String(byId.protocol) };\n}\n\n/** Finds a system action by exact name for a given protocol; returns its id. */\nexport async function resolveActionId(\n simWorldId: string,\n protocol: string,\n actionName: string,\n): Promise<string> {\n const page = await sdk().actions.list({\n simWorldId,\n searchValue: actionName,\n filters: { isSystem: true, protocol: protocol as any, deviceType: \"CHARGER\" },\n pagination: { page: 1, pageSize: 50 },\n });\n const records = page?.records ?? [];\n const needle = actionName.toLowerCase();\n const match =\n records.find((a) => a?.name?.toLowerCase() === needle) ??\n records.find((a) => a?.name?.toLowerCase().includes(needle));\n\n if (!match?.id) {\n const available = records.map((a) => ` - ${a?.name}`).join(\"\\n\");\n throw new Error(\n `Action \"${actionName}\" not found for ${protocol}.` +\n (available ? `\\nAvailable system actions matching your search:\\n${available}` : \"\"),\n );\n }\n return match.id;\n}\n","import { z } from \"zod\";\n\nexport const DEFAULT_PAGE_SIZE = 20;\n\nexport const paginationArgs = {\n page: z.number().int().min(1).optional().describe(\"Page number, starting at 1 (default 1)\"),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(`Results per page (default ${DEFAULT_PAGE_SIZE})`),\n};\n\nexport function pagination(page?: number, pageSize?: number, defaultPageSize = DEFAULT_PAGE_SIZE) {\n return { page: page ?? 1, pageSize: pageSize ?? defaultPageSize };\n}\n\ninterface PageInfoLike {\n page?: number | null;\n pageSize?: number | null;\n hasNextPage?: boolean | null;\n totalCount?: number | null;\n}\n\nexport function pageSummary(noun: string, count: number, pageInfo?: PageInfoLike | null): string {\n const total = pageInfo?.totalCount;\n const head =\n total != null && total !== count\n ? `Showing ${count} of ${total} ${noun} (page ${pageInfo?.page ?? 1}).`\n : `Found ${count} ${noun}.`;\n return pageInfo?.hasNextPage ? `${head} More results available — request the next page.` : head;\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { sdk } from \"../sdk.js\";\nimport { resolveSimulatorTarget, resolveActionId } from \"../resolve.js\";\nimport { SIMULATOR_ARG_DESCRIPTION } from \"../links.js\";\nimport { ok, guard } from \"../result.js\";\n\n/** Runs a single named action against a simulator via the SDK's runAction. */\nasync function runOnSimulator(\n project: string | undefined,\n simulator: string,\n actionName: string,\n args: { key: string; value: string }[] = [],\n) {\n const { ctx, sim } = await resolveSimulatorTarget(simulator, project);\n const actionId = await resolveActionId(ctx.simWorldId, sim.protocol, actionName);\n\n const status = await sdk().testRuns.runAction({\n chargerId: sim.id,\n action: { requirementKey: \"1\", stream: 1, order: 1, actionId, args },\n });\n return { sim, actionName, status };\n}\n\nexport function registerSimulatorTools(server: McpServer) {\n const projectArg = z\n .string()\n .optional()\n .describe(\"Project name or id (defaults to active project)\");\n\n server.registerTool(\n \"power_on_simulator\",\n {\n annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },\n title: \"Power on simulator\",\n description: \"Power on a simulator (boots it and connects it to the OCPP server).\",\n inputSchema: {\n simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION),\n project: projectArg,\n },\n },\n async ({ simulator, project }) =>\n guard(async () => {\n const { sim, status } = await runOnSimulator(project, simulator, \"Power On Charger\");\n return ok(`Powered on ${sim.baseName} (id: ${sim.id}).`, { status });\n }),\n );\n\n server.registerTool(\n \"power_off_simulator\",\n {\n annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },\n title: \"Power off simulator\",\n description: \"Power off a simulator.\",\n inputSchema: {\n simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION),\n project: projectArg,\n },\n },\n async ({ simulator, project }) =>\n guard(async () => {\n const { sim, status } = await runOnSimulator(project, simulator, \"Power Off Charger\");\n return ok(`Powered off ${sim.baseName} (id: ${sim.id}).`, { status });\n }),\n );\n\n server.registerTool(\n \"run_simulator_action\",\n {\n annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },\n title: \"Run simulator action\",\n description:\n \"Run a single named action against a simulator — e.g. 'Reset Charger', 'Plug In Connector', \" +\n \"'Plug Out Connector'. Use list_actions to discover names and required args. \" +\n \"Args are passed as key/value pairs (e.g. connectorId=1).\",\n inputSchema: {\n simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION),\n actionName: z.string().describe(\"Exact action name, e.g. 'Reset Charger'\"),\n args: z\n .array(z.object({ key: z.string(), value: z.string() }))\n .optional()\n .describe(\"Action arguments as key/value pairs\"),\n project: projectArg,\n },\n },\n async ({ simulator, actionName, args, project }) =>\n guard(async () => {\n const { sim, status } = await runOnSimulator(project, simulator, actionName, args ?? []);\n return ok(`Ran \"${actionName}\" on ${sim.baseName} (id: ${sim.id}).`, { status });\n }),\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { sdk } from \"../sdk.js\";\nimport { resolveSimWorld, resolveActionId } from \"../resolve.js\";\nimport { paginationArgs, pagination, pageSummary } from \"../pagination.js\";\nimport { ok, guard } from \"../result.js\";\n\nconst protocolEnum = z.enum([\"OCPP_1_6\", \"OCPP_2_0_1\"]);\n\nexport function registerTestTools(server: McpServer) {\n const projectArg = z\n .string()\n .optional()\n .describe(\"Project name or id (defaults to active project)\");\n\n server.registerTool(\n \"list_tests\",\n {\n annotations: { readOnlyHint: true },\n title: \"List tests\",\n description: \"List tests (scenarios) in the active project's sim world.\",\n inputSchema: {\n protocol: protocolEnum.optional(),\n search: z.string().optional().describe(\"Filter by test name\"),\n ...paginationArgs,\n project: projectArg,\n },\n },\n async ({ protocol, search, page, pageSize, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n const result = await sdk().tests.list({\n simWorldId: ctx.simWorldId,\n searchValue: search,\n filters: protocol ? { protocol } : undefined,\n pagination: pagination(page, pageSize),\n });\n return ok(pageSummary(\"test(s)\", result?.records?.length ?? 0, result?.pageInfo), result);\n }),\n );\n\n server.registerTool(\n \"get_test\",\n {\n annotations: { readOnlyHint: true },\n title: \"Get test\",\n description: \"Get a test by id, including its device requirements.\",\n inputSchema: {\n testId: z.string().describe(\"Test (scenario) id\"),\n },\n },\n async ({ testId }) =>\n guard(async () => {\n const test = await sdk().tests.get(testId);\n if (!test) return ok(`No test found with id ${testId}.`);\n return ok(`Test ${test.name} (id: ${testId}).`, test);\n }),\n );\n\n server.registerTool(\n \"create_test\",\n {\n annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },\n title: \"Create test\",\n description:\n \"Create a test from an ordered list of steps. Each step references an action by name \" +\n \"(use list_actions to discover them) plus optional key/value args. The steps run in order \" +\n \"against a single simulator. Example steps: 'Power On Charger', 'Plug In Connector', \" +\n \"'Use RFID Card', 'Charge a Vehicle', 'Plug Out Connector', 'Power Off Charger'.\",\n inputSchema: {\n name: z.string().describe(\"Test name\"),\n protocol: protocolEnum,\n steps: z\n .array(\n z.object({\n actionName: z.string().describe(\"Exact action name, e.g. 'Power On Charger'\"),\n args: z\n .array(z.object({ key: z.string(), value: z.string() }))\n .optional()\n .describe(\"Action arguments as key/value pairs\"),\n }),\n )\n .min(1)\n .describe(\"Ordered list of steps\"),\n project: projectArg,\n },\n },\n async ({ name, protocol, steps, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n\n const actions = [];\n for (let i = 0; i < steps.length; i++) {\n const actionId = await resolveActionId(ctx.simWorldId, protocol, steps[i].actionName);\n actions.push({\n order: i + 1,\n stream: 1,\n actionId,\n requirementKey: \"charger\",\n args: steps[i].args ?? [],\n });\n }\n\n const test = await sdk().tests.create({\n simWorldId: ctx.simWorldId,\n name,\n deviceType: \"CHARGER\",\n requirements: [\n { key: \"charger\", type: \"CHARGER\", params: [{ key: \"protocol\", value: protocol }] },\n ],\n actions,\n });\n return ok(`Created test \"${name}\" (id: ${test?.id}).`, test);\n }),\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { sdk } from \"../sdk.js\";\nimport { resolveSimWorld, resolveSimulatorTarget } from \"../resolve.js\";\nimport { SIMULATOR_ARG_DESCRIPTION } from \"../links.js\";\nimport { paginationArgs, pagination, pageSummary } from \"../pagination.js\";\nimport { ok, fail, guard } from \"../result.js\";\n\nexport function registerTestRunTools(server: McpServer) {\n const projectArg = z\n .string()\n .optional()\n .describe(\"Project name or id (defaults to active project)\");\n\n server.registerTool(\n \"run_test\",\n {\n annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },\n title: \"Run test\",\n description:\n \"Run a test (scenario) on a simulator, starting immediately. \" +\n \"Returns the test run id and status — poll with get_test_run to follow it. \" +\n \"A simulator runs one test at a time; if it is busy this says so and starts nothing.\",\n inputSchema: {\n testId: z.string().describe(\"Test (scenario) id to run\"),\n simulator: z.string().describe(`${SIMULATOR_ARG_DESCRIPTION} to run the test on`),\n project: projectArg,\n },\n },\n async ({ testId, simulator, project }) =>\n guard(async () => {\n const { ctx, sim } = await resolveSimulatorTarget(simulator, project);\n const test = await sdk().tests.get(testId);\n const requirementId = test?.requirements?.[0]?.id;\n if (!requirementId) return fail(`Test ${testId} has no device requirement to assign.`);\n\n const run = await sdk()\n .testRuns.create({\n scenarioId: testId,\n simWorldId: ctx.simWorldId,\n scheduleMode: \"NOW\",\n speedup: 1,\n forceDelete: false,\n requirementDevices: [\n { requirementId, deviceId: sim.id, deviceMode: \"SIMULATOR\" },\n ],\n })\n .catch(async (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n if (!/conflict/i.test(message)) throw err;\n\n const details = await sdk().simulators.get(sim.id).catch(() => null);\n const blocking = details?.lastRun;\n throw new Error(\n `${sim.baseName} (id: ${sim.id}) is busy` +\n (blocking?.id ? ` with test run ${blocking.id} (${blocking.status})` : \"\") +\n `, so nothing was started. Stop that run with stop_test_run — the simulator is ` +\n `free once it stops — then run this test again.`,\n );\n });\n return ok(\n `Started test \"${test?.name}\" on ${sim.baseName} — run id ${run?.id}, status ${run?.status}.`,\n run,\n );\n }),\n );\n\n server.registerTool(\n \"get_test_run\",\n {\n annotations: { readOnlyHint: true },\n title: \"Get test run\",\n description: \"Get a test run's status by id.\",\n inputSchema: {\n runId: z.string().describe(\"Test run id\"),\n },\n },\n async ({ runId }) =>\n guard(async () => {\n const run = await sdk().testRuns.get(runId);\n if (!run) return ok(`No test run found with id ${runId}.`);\n const reason = run.failReason ? ` — ${run.failReason}` : \"\";\n return ok(`Test run ${runId} (\"${run.scenario?.name}\"): ${run.status}${reason}.`, run);\n }),\n );\n\n server.registerTool(\n \"list_test_runs\",\n {\n annotations: { readOnlyHint: true },\n title: \"List test runs\",\n description: \"List recent test runs in the active project's sim world.\",\n inputSchema: {\n ...paginationArgs,\n project: projectArg,\n },\n },\n async ({ page, pageSize, project }) =>\n guard(async () => {\n const ctx = await resolveSimWorld(project);\n const result = await sdk().testRuns.list({\n simWorldId: ctx.simWorldId,\n pagination: pagination(page, pageSize),\n });\n return ok(pageSummary(\"test run(s)\", result?.records?.length ?? 0, result?.pageInfo), result);\n }),\n );\n\n server.registerTool(\n \"stop_test_run\",\n {\n annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },\n title: \"Stop test run\",\n description: \"Shut down (stop) a running or scheduled test run by id.\",\n inputSchema: {\n runId: z.string().describe(\"Test run id\"),\n },\n },\n async ({ runId }) =>\n guard(async () => {\n const existing = await sdk().testRuns.get(runId);\n if (!existing) return fail(`No test run found with id ${runId}.`);\n\n await sdk().testRuns.shutDown(runId);\n const after = await sdk().testRuns.get(runId);\n return ok(\n `Shut down test run ${runId} (was ${existing.status}, now ${after?.status ?? \"unknown\"}).`,\n after,\n );\n }),\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { sdk } from \"../sdk.js\";\nimport { resolveSimulatorTarget } from \"../resolve.js\";\nimport { SIMULATOR_ARG_DESCRIPTION } from \"../links.js\";\nimport {\n DEFAULT_LOGS_LAST,\n DEFAULT_LOGS_LIMIT,\n MAX_LOGS_LIMIT,\n formatLine,\n matchesAction,\n resolveWindow,\n toLogLines,\n} from \"../logs-format.js\";\nimport { ok, fail, guard } from \"../result.js\";\nimport { pageSummary } from \"../pagination.js\";\n\nconst READ_ONLY = { readOnlyHint: true, openWorldHint: true } as const;\n\nconst SECRET_KEY = /authorizationkey|password|secret|privatekey|passphrase/i;\n\ntype ConfigItem = { key?: string | null; variableName?: string | null; value?: string | null };\n\nexport function maskSecretItems<T extends ConfigItem>(items: readonly T[] | null | undefined): T[] {\n return (items ?? []).map((item) =>\n SECRET_KEY.test(item.key ?? item.variableName ?? \"\") && item.value ? { ...item, value: \"***\" } : item,\n );\n}\n\nfunction summarizeSimulator(sim: any): string {\n const model = sim.chargerModel;\n const config = sim.chargerConfig;\n const connectors = (model?.connectorModels ?? sim.chargerConnectors ?? [])\n .map((c: any) => `#${c.number ?? c.connectorId} ${c.type} (cable ${c.cableFixed ? \"fixed\" : \"flexible\"})`)\n .join(\", \");\n const lines = [\n `Simulator ${sim.baseName} (id: ${sim.id}), ${sim.protocol}; network ${sim.networkStatus}, ` +\n `power ${sim.launchedStatus}, OCPP status ${sim.chargerStatus}${sim.emergency ? \", EMERGENCY\" : \"\"}.`,\n `Model: ${model?.name ?? \"?\"} by ${model?.deviceManufacturer?.name ?? \"?\"}` +\n (connectors ? `; connectors: ${connectors}.` : \".\"),\n `Behavior: ${config?.behavior ?? \"?\"}; remote templates ${config?.useRemoteTemplates ? \"on\" : \"off\"}; ` +\n `supported commands: ${(config?.supportedCommands ?? []).join(\", \") || \"—\"}.`,\n `OCPP configuration keys: ${sim.chargerOcppConfigItems?.length ?? 0}.`,\n ];\n if (sim.lastRun) {\n lines.push(\n `Last run ${sim.lastRun.id}: ${sim.lastRun.status}` +\n (sim.lastRun.failReason ? ` — ${sim.lastRun.failReason}` : \"\") + \".\",\n );\n }\n return lines.join(\"\\n\");\n}\n\nconst RUN_SIMULATORS_PAGE_SIZE = 20;\n\nfunction simulatorName(rc: any): string {\n return rc.charger?.baseName ?? rc.device?.serialNumber ?? rc.id;\n}\n\nfunction findRunSimulator(records: any[], simulator: string): any {\n const needle = simulator.trim().toLowerCase();\n return (\n records.find((rc) => rc.id === simulator.trim()) ??\n records.find((rc) => rc.charger?.id === simulator.trim() || rc.device?.id === simulator.trim()) ??\n records.find((rc) =>\n rc.charger?.baseName?.toLowerCase() === needle || rc.device?.serialNumber?.toLowerCase() === needle,\n )\n );\n}\n\nfunction summarizeRun(run: any, simulators: any, page: number, steps: any): string {\n const records = (simulators?.records ?? []).filter(Boolean);\n const lines = [\n `Test run ${run.id} (\"${run.scenario?.name ?? \"?\"}\"): ${run.status}` +\n (run.failReason ? ` — ${run.failReason}` : \"\") +\n `. Started ${run.realStartTimestamp ?? run.startTimestamp ?? \"—\"}, stopped ${run.realStopTimestamp ?? \"—\"}.`,\n pageSummary(\"simulator(s)\", records.length, simulators?.pageInfo ?? { page }),\n ];\n for (const rc of records) {\n lines.push(`- ${simulatorName(rc)} (simulator ${rc.charger?.id ?? rc.device?.id ?? \"?\"}, run entry ${rc.id}): ${rc.status}`);\n }\n if (steps) {\n lines.push(\"\", `Steps of ${simulatorName(steps)}:`);\n for (const step of steps.chargerActions ?? []) {\n lines.push(\n ` step ${step.order} ${step.scenarioAction?.action?.name ?? \"?\"}: ${step.status}` +\n (step.failReason ? ` — ${step.failReason}` : \"\"),\n );\n }\n } else if (records.length > 1 || simulators?.pageInfo?.hasNextPage) {\n lines.push(\"\", \"Pass `simulator` with one of the names or ids above to see its steps.\");\n }\n return lines.join(\"\\n\");\n}\n\nexport function registerSupportTools(server: McpServer) {\n const projectArg = z\n .string()\n .optional()\n .describe(\"Project name or id (defaults to active project; a portal link sets its own)\");\n\n server.registerTool(\n \"get_simulator_config\",\n {\n title: \"Get simulator configuration\",\n description:\n \"Read-only. Everything that explains why a simulator behaves the way it does: its OCPP \" +\n \"configuration keys (e.g. FreevendEnabled, HeartbeatInterval), behavior settings (vendor \" +\n \"behavior, remote start/stop templates, supported commands, timeouts), model and connector \" +\n \"types (fixed or flexible cable), live connectors, authorizations, charging profiles, \" +\n \"transactions, reservations, and the last test run with its fail reason. Credential values \" +\n \"are masked.\",\n inputSchema: { simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION), project: projectArg },\n annotations: READ_ONLY,\n },\n async ({ simulator, project }) =>\n guard(async () => {\n const { sim } = await resolveSimulatorTarget(simulator, project);\n const details = await sdk().simulators.getDetails(sim.id);\n if (!details) return ok(`No simulator found with id ${sim.id}.`);\n const items = await sdk().simulators.getOcppConfigItems(sim.id);\n const safe = { ...details, chargerOcppConfigItems: maskSecretItems(items as ConfigItem[] | null) };\n return ok(summarizeSimulator(safe), safe);\n }),\n );\n\n server.registerTool(\n \"get_simulator_logs\",\n {\n title: \"Get simulator logs\",\n description:\n \"Read-only. The simulator's OCPP message log for a time window, one line per message: \" +\n \"`time direction action payload` (payload cut at ~500 chars). Newest messages are kept \" +\n \"when the limit cuts the window; lines are printed oldest first. Use `action` to keep one \" +\n \"OCPP action, e.g. StatusNotification (its results and errors are kept too).\",\n inputSchema: {\n simulator: z.string().describe(SIMULATOR_ARG_DESCRIPTION),\n from: z.string().optional().describe(\"Window start, ISO date-time (wins over `last`)\"),\n to: z.string().optional().describe(\"Window end, ISO date-time (default now)\"),\n last: z.string().optional().describe(`Window length back from \\`to\\`, e.g. 30m, 6h, 2d (default ${DEFAULT_LOGS_LAST})`),\n limit: z.number().int().min(1).max(MAX_LOGS_LIMIT).optional()\n .describe(`Max messages to show (default ${DEFAULT_LOGS_LIMIT}, max ${MAX_LOGS_LIMIT})`),\n action: z.string().optional().describe(\"Keep only this OCPP action, e.g. StatusNotification\"),\n project: projectArg,\n },\n annotations: READ_ONLY,\n },\n async ({ simulator, from, to, last, limit, action, project }) =>\n guard(async () => {\n const window = resolveWindow({ from, to, last });\n const { sim } = await resolveSimulatorTarget(simulator, project);\n // With a filter, scan a full page and cut to the limit afterwards.\n const shown = Math.min(limit ?? DEFAULT_LOGS_LIMIT, MAX_LOGS_LIMIT);\n const result = await sdk().logs.list({\n simulatorId: sim.id,\n from: window.from,\n to: window.to,\n limit: action ? MAX_LOGS_LIMIT : shown,\n });\n\n const all = toLogLines(result.records);\n const matched = action ? all.filter((line) => matchesAction(line, action)) : all;\n const lines = matched.slice(0, shown).reverse();\n const truncated = matched.length > shown || Boolean(result.pageInfo?.hasNextPage);\n\n const head =\n `${sim.baseName} (id: ${sim.id}) ${window.from.toISOString()} … ${window.to.toISOString()}: ` +\n `${lines.length} message(s) shown` +\n (action ? ` matching \"${action}\" of ${all.length} scanned` : \"\") +\n (result.pageInfo?.totalCount != null ? `; ${result.pageInfo.totalCount} in window` : \"\") +\n `; truncated: ${truncated ? \"yes — narrow the window or raise the limit\" : \"no\"}.`;\n return ok([head, \"\", ...lines.map(formatLine)].join(\"\\n\"));\n }),\n );\n\n server.registerTool(\n \"get_test_run_details\",\n {\n title: \"Get test run details\",\n description:\n \"Read-only. A test run's status and fail reason, plus one page of its simulators or devices \" +\n `with their status (${RUN_SIMULATORS_PAGE_SIZE} per page). Steps — status, fail reason, ` +\n \"expected / actual result — are shown for one simulator at a time: pass `simulator` with a \" +\n \"name or id from the page. A run with a single simulator shows its steps right away.\",\n inputSchema: {\n runId: z.string().describe(\"Test run id\"),\n page: z.number().int().min(1).optional().describe(\"Page of the run's simulators, starting at 1 (default 1)\"),\n simulator: z.string().optional()\n .describe(\"Show the steps of this simulator from the page: its name, simulator id or run entry id\"),\n },\n annotations: READ_ONLY,\n },\n async ({ runId, page, simulator }) =>\n guard(async () => {\n const run = await sdk().testRuns.getDetails(runId);\n if (!run) return ok(`No test run found with id ${runId}.`);\n const current = page ?? 1;\n const simulators = await sdk().testRuns.listSimulators(runId, {\n pagination: { page: current, pageSize: RUN_SIMULATORS_PAGE_SIZE },\n });\n const records = (simulators?.records ?? []).filter(Boolean);\n\n let target: any;\n if (simulator) {\n target = findRunSimulator(records, simulator);\n if (!target) {\n return fail(\n `No simulator \"${simulator}\" on page ${current} of test run ${runId}. ` +\n \"Pass a name or id listed on this page, or another page.\",\n );\n }\n } else if (simulators?.pageInfo?.totalCount === 1 || (current === 1 && records.length === 1 && !simulators?.pageInfo?.hasNextPage)) {\n target = records[0];\n }\n\n const ref = target?.charger?.id\n ? { chargerId: target.charger.id as string }\n : target?.device?.id ? { deviceId: target.device.id as string } : null;\n const steps = ref ? await sdk().testRuns.getSimulatorSteps(runId, ref) : null;\n return ok(summarizeRun(run, simulators, current, steps), { run, simulators, steps });\n }),\n );\n}\n","\nexport const DEFAULT_LOGS_LAST = \"1h\";\nexport const DEFAULT_LOGS_LIMIT = 200;\nexport const MAX_LOGS_LIMIT = 1000;\nexport const PAYLOAD_MAX_CHARS = 500;\n\nconst UNIT_MS: Record<string, number> = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 };\n\nexport function parseDuration(value: string): number {\n const match = value.trim().match(/^(\\d+)\\s*([smhd])$/i);\n if (!match) throw new Error(`Invalid duration \"${value}\". Use a number and a unit: 30m, 6h, 2d.`);\n return Number(match[1]) * UNIT_MS[match[2]!.toLowerCase()]!;\n}\n\nfunction parseInstant(value: string, name: string): Date {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) throw new Error(`Invalid ${name} \"${value}\". Use an ISO date-time.`);\n return date;\n}\n\nexport function resolveWindow(\n input: { from?: string; to?: string; last?: string },\n now: Date = new Date(),\n): { from: Date; to: Date } {\n const to = input.to ? parseInstant(input.to, \"to\") : now;\n const from = input.from\n ? parseInstant(input.from, \"from\")\n : new Date(to.getTime() - parseDuration(input.last ?? DEFAULT_LOGS_LAST));\n if (from.getTime() > to.getTime()) throw new Error(`\"from\" (${from.toISOString()}) is after \"to\" (${to.toISOString()}).`);\n return { from, to };\n}\n\nexport interface LogRecordLike {\n id: string;\n timestamp: string | null;\n sender: string | null;\n receiver: string | null;\n protocol: string | null;\n content: string | null;\n rawContent: string | null;\n error: string | null;\n}\n\nexport interface LogLine {\n time: string;\n direction: string;\n action: string;\n payload: string;\n}\n\nfunction tryJson(text: string | null): unknown {\n if (text == null) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction stringify(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\nexport function truncate(text: string, max = PAYLOAD_MAX_CHARS): string {\n return text.length > max ? `${text.slice(0, max)}…(+${text.length - max} chars)` : text;\n}\n\nfunction direction(record: LogRecordLike, envelope: any): string {\n const dir = envelope?.payload?.direction;\n if (dir === \"client_to_server\") return \"CP→CSMS\";\n if (dir === \"server_to_client\") return \"CSMS→CP\";\n if (record.sender || record.receiver) return `${record.sender ?? \"?\"}→${record.receiver ?? \"?\"}`;\n return \"-\";\n}\n\nexport function toLogLines(records: LogRecordLike[]): LogLine[] {\n const parsed = records.map((r) => ({ record: r, message: tryJson(r.content), envelope: tryJson(r.rawContent) }));\n\n const callActions = new Map<string, string>();\n for (const { message } of parsed) {\n if (Array.isArray(message) && message[0] === 2) callActions.set(String(message[1]), String(message[2]));\n }\n\n return parsed.map(({ record, message, envelope }) => {\n let action: string;\n let payload: string;\n if (record.protocol === \"OCPP\" && Array.isArray(message) && [2, 3, 4].includes(message[0])) {\n const call = callActions.get(String(message[1]));\n if (message[0] === 2) {\n action = String(message[2]);\n payload = stringify(message[3] ?? {});\n } else if (message[0] === 3) {\n action = `${call ?? \"?\"}.result`;\n payload = stringify(message[2] ?? {});\n } else {\n action = `${call ?? \"?\"}.error`;\n payload = [message[2], message[3], message[4] ? stringify(message[4]) : \"\"].filter(Boolean).join(\" \");\n }\n } else {\n action = String((envelope as any)?.type ?? record.protocol ?? \"log\");\n payload = record.content ?? \"\";\n }\n if (record.error) payload = `${payload} [error: ${record.error}]`;\n return {\n time: record.timestamp ?? \"?\",\n direction: direction(record, envelope),\n action,\n payload: truncate(payload.replace(/\\s+/g, \" \").trim()),\n };\n });\n}\n\nexport function matchesAction(line: LogLine, action: string): boolean {\n const base = line.action.replace(/\\.(result|error)$/, \"\").toLowerCase();\n return base === action.trim().toLowerCase();\n}\n\nexport function formatLine(line: LogLine): string {\n return `${line.time} ${line.direction} ${line.action} ${line.payload}`;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerContextTools } from \"./context.js\";\nimport { registerDataTools } from \"./data.js\";\nimport { registerSimulatorTools } from \"./simulators.js\";\nimport { registerTestTools } from \"./tests.js\";\nimport { registerTestRunTools } from \"./test-runs.js\";\nimport { registerSupportTools } from \"./support.js\";\n\nexport const READONLY_ENV = \"TIMETICK_MCP_READONLY\";\n\nexport function isReadOnlyMode(env: NodeJS.ProcessEnv = process.env): boolean {\n const value = env[READONLY_ENV]?.trim().toLowerCase();\n return value === \"1\" || value === \"true\";\n}\n\nfunction readOnlyView(server: McpServer): McpServer {\n return new Proxy(server, {\n get(target, prop, receiver) {\n if (prop !== \"registerTool\") return Reflect.get(target, prop, receiver);\n return (name: string, config: { annotations?: { readOnlyHint?: boolean } }, cb: unknown) =>\n config.annotations?.readOnlyHint === true\n ? (target.registerTool as (...args: unknown[]) => unknown)(name, config, cb)\n : undefined;\n },\n });\n}\n\nexport function registerTools(server: McpServer, options: { readOnly: boolean }) {\n const target = options.readOnly ? readOnlyView(server) : server;\n registerContextTools(target);\n registerDataTools(target);\n registerSimulatorTools(target);\n registerTestTools(target);\n registerTestRunTools(target);\n registerSupportTools(target);\n}\n"],"mappings":";;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACDrC,SAAS,SAAS;;;ACAlB,SAAS,oBAAyC;AAElD,IAAI,SAAgC;AAG7B,SAAS,MAAsB;AACpC,MAAI,OAAQ,QAAO;AAEnB,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,WAAS,aAAa,EAAE,QAAQ,UAAU,QAAQ,IAAI,iBAAiB,CAAC;AACxE,SAAO;AACT;;;ACLO,IAAM,eAAN,cAA2B,MAAM;AAAC;AAEzC,IAAI,SAAyB;AAG7B,eAAe,aACb,WACA,aACA,QACkB;AAClB,QAAM,SAAS,MAAM,IAAI,EAAE,UAAU,KAAK,SAAS;AACnD,QAAM,QAAQ,SAAS,CAAC;AACxB,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,aAAa,YAAY,WAAW,mCAAmC;AAAA,EACnF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM;AAAA,IAClB,eAAe,MAAM,iBAAiB,MAAM;AAAA,IAC5C;AAAA,EACF;AACF;AAEA,IAAM,qBAAqB;AAI3B,SAAS,eAAe,UAAgE;AACtF,QAAM,MAAM,YAAY,CAAC;AACzB,QAAM,QAAQ,IACX,MAAM,GAAG,kBAAkB,EAC3B,IAAI,CAAC,MAAM,OAAO,GAAG,IAAI,SAAS,GAAG,EAAE,GAAG;AAC7C,MAAI,IAAI,SAAS,oBAAoB;AACnC,UAAM,KAAK,eAAU,IAAI,SAAS,kBAAkB,kDAA6C;AAAA,EACnG;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAe,YAAY,SAAwD;AACjF,QAAM,WAAW,MAAM,IAAI,EAAE,SAAS,KAAK;AAC3C,QAAM,SAAS,QAAQ,YAAY;AACnC,QAAM,QAAQ,UAAU;AAAA,IACtB,CAAC,MAAM,GAAG,OAAO,WAAW,GAAG,MAAM,YAAY,MAAM;AAAA,EACzD;AACA,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI;AAAA,MACR,wBAAwB,OAAO;AAAA,EAAkB,eAAe,QAAQ,CAAC;AAAA,IAC3E;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,IAAI,MAAM,MAAM,QAAQ,YAAY;AACzD;AAMA,eAAsB,aAA+B;AACnD,MAAI,OAAQ,QAAO;AAEnB,QAAM,WAAW,MAAM,IAAI,EAAE,SAAS,KAAK;AAC3C,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,UAAM,IAAI,aAAa,6CAA6C;AAAA,EACtE;AACA,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,IAAI;AAAA,MACR,YAAY,SAAS,MAAM;AAAA,EACd,eAAe,QAAQ,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,OAAO,SAAS,CAAC;AACvB,WAAS,MAAM,aAAa,KAAK,IAAK,KAAK,QAAQ,aAAa,gBAAgB;AAChF,SAAO;AACT;AAGA,eAAsB,WAAW,OAA8C;AAC7E,QAAM,QAAQ,MAAM,YAAY,MAAM,OAAO;AAC7C,WAAS,MAAM,aAAa,MAAM,IAAI,MAAM,MAAM,UAAU;AAC5D,SAAO;AACT;AAEA,eAAsB,cAAc,SAAmC;AACrE,QAAM,QAAQ,MAAM,YAAY,OAAO;AACvC,SAAO,aAAa,MAAM,IAAI,MAAM,MAAM,UAAU;AACtD;AAGO,SAAS,cAA8B;AAC5C,SAAO;AACT;;;ACxGA,SAAS,qBAAqB;AAQvB,SAAS,GAAG,MAAc,MAA4B;AAC3D,QAAM,OAAO,SAAS,SAAY,OAAO,GAAG,IAAI;AAAA;AAAA,EAAO,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACpF,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,CAAC,EAAE;AACnD;AAEO,SAAS,KAAK,SAA6B;AAChD,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG,SAAS,KAAK;AACrE;AAGA,eAAsB,MAAM,IAAoD;AAC9E,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,SAAS,KAAK;AACZ,QAAI,eAAe,cAAe,QAAO,KAAK,uBAAuB,IAAI,OAAO,EAAE;AAClF,WAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EAC9D;AACF;;;AHpBO,SAAS,qBAAqB,QAAmB;AACtD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aACE;AAAA,MAEF,aAAa,CAAC;AAAA,IAChB;AAAA,IACA,YACE,MAAM,YAAY;AAChB,YAAM,MAAM,YAAY,KAAM,MAAM,WAAW;AAC/C,aAAO;AAAA,QACL,mBAAmB,IAAI,WAAW,SAAS,IAAI,SAAS,iBAAiB,IAAI,UAAU,KAAK,IAAI,MAAM;AAAA,QACtG;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aACE;AAAA,MAEF,aAAa;AAAA,QACX,SAAS,EAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,MAClE;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,MACf,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,WAAW,EAAE,QAAQ,CAAC;AACxC,aAAO,GAAG,yBAAyB,IAAI,WAAW,SAAS,IAAI,SAAS,MAAM,GAAG;AAAA,IACnF,CAAC;AAAA,EACL;AACF;;;AI5CA,SAAS,KAAAA,UAAS;;;ACKlB,IAAM,iBAAiB;AAEvB,SAAS,cAAc,MAAuB;AAC5C,SAAO,kBAAkB,KAAK,IAAI,KAAK,wBAAwB,KAAK,IAAI;AAC1E;AAEO,SAAS,kBAAkB,OAA6B;AAC7D,QAAM,OAAO,MAAM,KAAK;AACxB,MAAI,CAAC,cAAc,IAAI,EAAG,QAAO,EAAE,WAAW,KAAK;AAGnD,QAAM,YAAY,KAAK,QAAQ,UAAU,GAAG;AAC5C,QAAM,QAAQ,UAAU,MAAM,cAAc;AAC5C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,IAAI,KAAK;AAAA,IAEX;AAAA,EACF;AACA,SAAO,EAAE,SAAS,mBAAmB,MAAM,CAAC,CAAE,GAAG,WAAW,mBAAmB,MAAM,CAAC,CAAE,EAAE;AAC5F;AAEO,IAAM,4BACX;;;ACvBF,eAAsB,gBAAgB,SAAoC;AACxE,MAAI,QAAS,QAAO,cAAc,OAAO;AACzC,SAAO,WAAW;AACpB;AASA,eAAsB,iBACpB,YACA,WAC4B;AAC5B,QAAM,SAAS,UAAU,YAAY;AACrC,QAAM,OAAO,MAAM,IAAI,EAAE,WAAW,KAAK,EAAE,YAAY,aAAa,UAAU,CAAC;AAC/E,QAAM,UAAU,MAAM,WAAW,CAAC;AAElC,QAAM,QACJ,QAAQ,KAAK,CAAC,MAAM,GAAG,OAAO,SAAS,KACvC,QAAQ,KAAK,CAAC,MAAM,GAAG,UAAU,YAAY,MAAM,MAAM,MACxD,QAAQ,WAAW,IAAI,QAAQ,CAAC,IAAI;AAEvC,MAAI,OAAO,IAAI;AACb,WAAO,EAAE,IAAI,MAAM,IAAI,UAAU,MAAM,YAAY,IAAI,UAAU,OAAO,MAAM,QAAQ,EAAE;AAAA,EAC1F;AAGA,QAAM,OAAO,MAAM,IAAI,EAAE,WAAW,IAAI,SAAS,EAAE,MAAM,MAAM,IAAI;AACnE,MAAI,MAAM,IAAI;AACZ,WAAO,EAAE,IAAI,KAAK,IAAI,UAAU,KAAK,YAAY,IAAI,UAAU,OAAO,KAAK,QAAQ,EAAE;AAAA,EACvF;AAEA,QAAM,aAAa,QAAQ,IAAI,CAAC,MAAM,OAAO,GAAG,QAAQ,SAAS,GAAG,EAAE,GAAG,EAAE,KAAK,IAAI;AACpF,QAAM,IAAI;AAAA,IACR,0BAA0B,SAAS,QAChC,aAAa;AAAA;AAAA,EAAkB,UAAU,KAAK;AAAA,EACnD;AACF;AAEA,eAAsB,uBACpB,WACA,SACmD;AACnD,QAAM,MAAM,kBAAkB,SAAS;AACvC,QAAM,MAAM,MAAM,gBAAgB,IAAI,WAAW,OAAO;AACxD,QAAM,MAAM,IAAI,YAAY,SACxB,MAAM,qBAAqB,IAAI,SAAS,IACxC,MAAM,iBAAiB,IAAI,YAAY,IAAI,SAAS;AACxD,SAAO,EAAE,KAAK,IAAI;AACpB;AAEA,eAAe,qBAAqB,IAAwC;AAC1E,QAAM,OAAO,MAAM,IAAI,EAAE,WAAW,IAAI,EAAE,EAAE,MAAM,CAAC,QAAiB;AAClE,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAM,IAAI,MAAM,wBAAwB,EAAE,0BAA0B,MAAM,EAAE;AAAA,EAC9E,CAAC;AACD,MAAI,CAAC,MAAM,GAAI,OAAM,IAAI,MAAM,wBAAwB,EAAE,wBAAwB;AACjF,SAAO,EAAE,IAAI,KAAK,IAAI,UAAU,KAAK,YAAY,IAAI,UAAU,OAAO,KAAK,QAAQ,EAAE;AACvF;AAGA,eAAsB,gBACpB,YACA,UACA,YACiB;AACjB,QAAM,OAAO,MAAM,IAAI,EAAE,QAAQ,KAAK;AAAA,IACpC;AAAA,IACA,aAAa;AAAA,IACb,SAAS,EAAE,UAAU,MAAM,UAA2B,YAAY,UAAU;AAAA,IAC5E,YAAY,EAAE,MAAM,GAAG,UAAU,GAAG;AAAA,EACtC,CAAC;AACD,QAAM,UAAU,MAAM,WAAW,CAAC;AAClC,QAAM,SAAS,WAAW,YAAY;AACtC,QAAM,QACJ,QAAQ,KAAK,CAAC,MAAM,GAAG,MAAM,YAAY,MAAM,MAAM,KACrD,QAAQ,KAAK,CAAC,MAAM,GAAG,MAAM,YAAY,EAAE,SAAS,MAAM,CAAC;AAE7D,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,YAAY,QAAQ,IAAI,CAAC,MAAM,OAAO,GAAG,IAAI,EAAE,EAAE,KAAK,IAAI;AAChE,UAAM,IAAI;AAAA,MACR,WAAW,UAAU,mBAAmB,QAAQ,OAC7C,YAAY;AAAA;AAAA,EAAqD,SAAS,KAAK;AAAA,IACpF;AAAA,EACF;AACA,SAAO,MAAM;AACf;;;AC9FA,SAAS,KAAAC,UAAS;AAEX,IAAM,oBAAoB;AAE1B,IAAM,iBAAiB;AAAA,EAC5B,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,EAC1F,UAAUA,GACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,6BAA6B,iBAAiB,GAAG;AAC/D;AAEO,SAAS,WAAW,MAAe,UAAmB,kBAAkB,mBAAmB;AAChG,SAAO,EAAE,MAAM,QAAQ,GAAG,UAAU,YAAY,gBAAgB;AAClE;AASO,SAAS,YAAY,MAAc,OAAe,UAAwC;AAC/F,QAAM,QAAQ,UAAU;AACxB,QAAM,OACJ,SAAS,QAAQ,UAAU,QACvB,WAAW,KAAK,OAAO,KAAK,IAAI,IAAI,UAAU,UAAU,QAAQ,CAAC,OACjE,SAAS,KAAK,IAAI,IAAI;AAC5B,SAAO,UAAU,cAAc,GAAG,IAAI,0DAAqD;AAC7F;;;AHzBA,IAAM,eAAeC,GAAE,KAAK,CAAC,YAAY,YAAY,CAAC;AAEtD,SAAS,cAAc,QAAqD;AAC1E,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,UAAkC,CAAC;AACzC,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAiC,GAAG;AAC5E,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,EAAE,MAAM,WAAW,cAAc,QAAQ,IAAI;AACnD,QAAI,YAAY,MAAO;AACvB,UAAM,QAAQ,CAAC,OAAO,QAAQ,SAAS,GAAG,cAAc,QAAQ,aAAa,UAAU;AACvF,QAAI,iBAAiB,OAAW,OAAM,KAAK,WAAW,KAAK,UAAU,YAAY,CAAC,EAAE;AACpF,YAAQ,IAAI,IAAI,MAAM,KAAK,IAAI;AAAA,EACjC;AACA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;AAEO,SAAS,kBAAkB,QAAmB;AACnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,CAAC;AAAA,IAChB;AAAA,IACA,YACE,MAAM,YAAY;AAChB,YAAM,WAAW,MAAM,IAAI,EAAE,SAAS,KAAK;AAC3C,aAAO,GAAG,SAAS,UAAU,UAAU,CAAC,gBAAgB,QAAQ;AAAA,IAClE,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aACE;AAAA,MAEF,aAAa;AAAA,QACX,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,QACtE,UAAU,aAAa,SAAS;AAAA,QAChC,GAAG;AAAA,QACH,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,MAC3F;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,UAAU,MAAM,UAAU,QAAQ,MACjD,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,YAAM,SAAS,MAAM,IAAI,EAAE,WAAW,KAAK;AAAA,QACzC,YAAY,IAAI;AAAA,QAChB,aAAa;AAAA,QACb,SAAS,WAAW,EAAE,SAAS,IAAI;AAAA,QACnC,YAAY,WAAW,MAAM,QAAQ;AAAA,MACvC,CAAC;AACD,aAAO;AAAA,QACL,YAAY,gBAAgB,QAAQ,SAAS,UAAU,GAAG,QAAQ,QAAQ;AAAA,QAC1E;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aACE;AAAA,MAEF,aAAa;AAAA,QACX,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,QACxD,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,MAC3F;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,QAAQ,MAC1B,MAAM,YAAY;AAChB,YAAM,EAAE,KAAK,SAAS,IAAI,MAAM,uBAAuB,WAAW,OAAO;AACzE,YAAM,UAAU,MAAM,IAAI,EAAE,WAAW,IAAI,SAAS,EAAE;AACtD,aAAO,GAAG,aAAa,SAAS,QAAQ,SAAS,SAAS,EAAE,MAAM,OAAO;AAAA,IAC3E,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iCAAiC;AAAA,QACxE,GAAG;AAAA,QACH,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,MAC3F;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,MAAM,UAAU,QAAQ,MACvC,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,YAAM,SAAS,MAAM,IAAI,EAAE,SAAS,KAAK;AAAA,QACvC,eAAe,IAAI;AAAA,QACnB,aAAa;AAAA,QACb,YAAY,WAAW,MAAM,QAAQ;AAAA,MACvC,CAAC;AACD,aAAO;AAAA,QACL,YAAY,sBAAsB,QAAQ,SAAS,UAAU,GAAG,QAAQ,QAAQ;AAAA,QAChF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aACE;AAAA,MAGF,aAAa;AAAA,QACX,UAAU,aAAa,SAAS;AAAA,QAChC,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,QAC9D,GAAG;AAAA,QACH,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,MAC3F;AAAA,IACF;AAAA,IACA,OAAO,EAAE,UAAU,QAAQ,MAAM,UAAU,QAAQ,MACjD,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,YAAM,SAAS,MAAM,IAAI,EAAE,QAAQ,KAAK;AAAA,QACtC,YAAY,IAAI;AAAA,QAChB,aAAa;AAAA,QACb,SAAS,EAAE,UAAU,MAAM,YAAY,WAAW,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG;AAAA,QACpF,YAAY,WAAW,MAAM,UAAU,GAAG;AAAA,MAC5C,CAAC;AACD,YAAM,WAAW,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QAClD,MAAM,GAAG;AAAA,QACT,aAAa,GAAG,eAAe;AAAA,QAC/B,MAAM,cAAc,GAAG,MAAM;AAAA,MAC/B,EAAE;AACF,aAAO,GAAG,YAAY,aAAa,QAAQ,QAAQ,QAAQ,QAAQ,GAAG,OAAO;AAAA,IAC/E,CAAC;AAAA,EACL;AACF;;;AIxJA,SAAS,KAAAC,UAAS;AAQlB,eAAe,eACb,SACA,WACA,YACA,OAAyC,CAAC,GAC1C;AACA,QAAM,EAAE,KAAK,IAAI,IAAI,MAAM,uBAAuB,WAAW,OAAO;AACpE,QAAM,WAAW,MAAM,gBAAgB,IAAI,YAAY,IAAI,UAAU,UAAU;AAE/E,QAAM,SAAS,MAAM,IAAI,EAAE,SAAS,UAAU;AAAA,IAC5C,WAAW,IAAI;AAAA,IACf,QAAQ,EAAE,gBAAgB,KAAK,QAAQ,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,EACrE,CAAC;AACD,SAAO,EAAE,KAAK,YAAY,OAAO;AACnC;AAEO,SAAS,uBAAuB,QAAmB;AACxD,QAAM,aAAaC,GAChB,OAAO,EACP,SAAS,EACT,SAAS,iDAAiD;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,OAAO,eAAe,KAAK;AAAA,MAChF,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,QACxD,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,QAAQ,MAC1B,MAAM,YAAY;AAChB,YAAM,EAAE,KAAK,OAAO,IAAI,MAAM,eAAe,SAAS,WAAW,kBAAkB;AACnF,aAAO,GAAG,cAAc,IAAI,QAAQ,SAAS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,IACrE,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,MAAM,eAAe,KAAK;AAAA,MAC/E,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,QACxD,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,QAAQ,MAC1B,MAAM,YAAY;AAChB,YAAM,EAAE,KAAK,OAAO,IAAI,MAAM,eAAe,SAAS,WAAW,mBAAmB;AACpF,aAAO,GAAG,eAAe,IAAI,QAAQ,SAAS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,IACtE,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,MAAM,eAAe,KAAK;AAAA,MAC/E,OAAO;AAAA,MACP,aACE;AAAA,MAGF,aAAa;AAAA,QACX,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,QACxD,YAAYA,GAAE,OAAO,EAAE,SAAS,yCAAyC;AAAA,QACzE,MAAMA,GACH,MAAMA,GAAE,OAAO,EAAE,KAAKA,GAAE,OAAO,GAAG,OAAOA,GAAE,OAAO,EAAE,CAAC,CAAC,EACtD,SAAS,EACT,SAAS,qCAAqC;AAAA,QACjD,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,YAAY,MAAM,QAAQ,MAC5C,MAAM,YAAY;AAChB,YAAM,EAAE,KAAK,OAAO,IAAI,MAAM,eAAe,SAAS,WAAW,YAAY,QAAQ,CAAC,CAAC;AACvF,aAAO,GAAG,QAAQ,UAAU,QAAQ,IAAI,QAAQ,SAAS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,IACjF,CAAC;AAAA,EACL;AACF;;;AC3FA,SAAS,KAAAC,UAAS;AAOlB,IAAMC,gBAAeC,GAAE,KAAK,CAAC,YAAY,YAAY,CAAC;AAE/C,SAAS,kBAAkB,QAAmB;AACnD,QAAM,aAAaA,GAChB,OAAO,EACP,SAAS,EACT,SAAS,iDAAiD;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUD,cAAa,SAAS;AAAA,QAChC,QAAQC,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qBAAqB;AAAA,QAC5D,GAAG;AAAA,QACH,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,UAAU,QAAQ,MAAM,UAAU,QAAQ,MACjD,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,YAAM,SAAS,MAAM,IAAI,EAAE,MAAM,KAAK;AAAA,QACpC,YAAY,IAAI;AAAA,QAChB,aAAa;AAAA,QACb,SAAS,WAAW,EAAE,SAAS,IAAI;AAAA,QACnC,YAAY,WAAW,MAAM,QAAQ;AAAA,MACvC,CAAC;AACD,aAAO,GAAG,YAAY,WAAW,QAAQ,SAAS,UAAU,GAAG,QAAQ,QAAQ,GAAG,MAAM;AAAA,IAC1F,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,QAAQA,GAAE,OAAO,EAAE,SAAS,oBAAoB;AAAA,MAClD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,MACd,MAAM,YAAY;AAChB,YAAM,OAAO,MAAM,IAAI,EAAE,MAAM,IAAI,MAAM;AACzC,UAAI,CAAC,KAAM,QAAO,GAAG,yBAAyB,MAAM,GAAG;AACvD,aAAO,GAAG,QAAQ,KAAK,IAAI,SAAS,MAAM,MAAM,IAAI;AAAA,IACtD,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,OAAO,eAAe,KAAK;AAAA,MAChF,OAAO;AAAA,MACP,aACE;AAAA,MAIF,aAAa;AAAA,QACX,MAAMA,GAAE,OAAO,EAAE,SAAS,WAAW;AAAA,QACrC,UAAUD;AAAA,QACV,OAAOC,GACJ;AAAA,UACCA,GAAE,OAAO;AAAA,YACP,YAAYA,GAAE,OAAO,EAAE,SAAS,4CAA4C;AAAA,YAC5E,MAAMA,GACH,MAAMA,GAAE,OAAO,EAAE,KAAKA,GAAE,OAAO,GAAG,OAAOA,GAAE,OAAO,EAAE,CAAC,CAAC,EACtD,SAAS,EACT,SAAS,qCAAqC;AAAA,UACnD,CAAC;AAAA,QACH,EACC,IAAI,CAAC,EACL,SAAS,uBAAuB;AAAA,QACnC,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ,MACtC,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AAEzC,YAAM,UAAU,CAAC;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,WAAW,MAAM,gBAAgB,IAAI,YAAY,UAAU,MAAM,CAAC,EAAE,UAAU;AACpF,gBAAQ,KAAK;AAAA,UACX,OAAO,IAAI;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,UACA,gBAAgB;AAAA,UAChB,MAAM,MAAM,CAAC,EAAE,QAAQ,CAAC;AAAA,QAC1B,CAAC;AAAA,MACH;AAEA,YAAM,OAAO,MAAM,IAAI,EAAE,MAAM,OAAO;AAAA,QACpC,YAAY,IAAI;AAAA,QAChB;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,UACZ,EAAE,KAAK,WAAW,MAAM,WAAW,QAAQ,CAAC,EAAE,KAAK,YAAY,OAAO,SAAS,CAAC,EAAE;AAAA,QACpF;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,GAAG,iBAAiB,IAAI,UAAU,MAAM,EAAE,MAAM,IAAI;AAAA,IAC7D,CAAC;AAAA,EACL;AACF;;;ACnHA,SAAS,KAAAC,UAAS;AAQX,SAAS,qBAAqB,QAAmB;AACtD,QAAM,aAAaC,GAChB,OAAO,EACP,SAAS,EACT,SAAS,iDAAiD;AAE7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,OAAO,eAAe,KAAK;AAAA,MAChF,OAAO;AAAA,MACP,aACE;AAAA,MAGF,aAAa;AAAA,QACX,QAAQA,GAAE,OAAO,EAAE,SAAS,2BAA2B;AAAA,QACvD,WAAWA,GAAE,OAAO,EAAE,SAAS,GAAG,yBAAyB,qBAAqB;AAAA,QAChF,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,QAAQ,WAAW,QAAQ,MAClC,MAAM,YAAY;AAChB,YAAM,EAAE,KAAK,IAAI,IAAI,MAAM,uBAAuB,WAAW,OAAO;AACpE,YAAM,OAAO,MAAM,IAAI,EAAE,MAAM,IAAI,MAAM;AACzC,YAAM,gBAAgB,MAAM,eAAe,CAAC,GAAG;AAC/C,UAAI,CAAC,cAAe,QAAO,KAAK,QAAQ,MAAM,uCAAuC;AAErF,YAAM,MAAM,MAAM,IAAI,EACnB,SAAS,OAAO;AAAA,QACf,YAAY;AAAA,QACZ,YAAY,IAAI;AAAA,QAChB,cAAc;AAAA,QACd,SAAS;AAAA,QACT,aAAa;AAAA,QACb,oBAAoB;AAAA,UAClB,EAAE,eAAe,UAAU,IAAI,IAAI,YAAY,YAAY;AAAA,QAC7D;AAAA,MACF,CAAC,EACA,MAAM,OAAO,QAAiB;AAC7B,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAI,CAAC,YAAY,KAAK,OAAO,EAAG,OAAM;AAEtC,cAAM,UAAU,MAAM,IAAI,EAAE,WAAW,IAAI,IAAI,EAAE,EAAE,MAAM,MAAM,IAAI;AACnE,cAAM,WAAW,SAAS;AAC1B,cAAM,IAAI;AAAA,UACR,GAAG,IAAI,QAAQ,SAAS,IAAI,EAAE,eAC3B,UAAU,KAAK,kBAAkB,SAAS,EAAE,KAAK,SAAS,MAAM,MAAM,MACvE;AAAA,QAEJ;AAAA,MACF,CAAC;AACH,aAAO;AAAA,QACL,iBAAiB,MAAM,IAAI,QAAQ,IAAI,QAAQ,kBAAa,KAAK,EAAE,YAAY,KAAK,MAAM;AAAA,QAC1F;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,GAAE,OAAO,EAAE,SAAS,aAAa;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,MACb,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,IAAI,EAAE,SAAS,IAAI,KAAK;AAC1C,UAAI,CAAC,IAAK,QAAO,GAAG,6BAA6B,KAAK,GAAG;AACzD,YAAM,SAAS,IAAI,aAAa,WAAM,IAAI,UAAU,KAAK;AACzD,aAAO,GAAG,YAAY,KAAK,MAAM,IAAI,UAAU,IAAI,OAAO,IAAI,MAAM,GAAG,MAAM,KAAK,GAAG;AAAA,IACvF,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,GAAG;AAAA,QACH,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,QAAQ,MAC/B,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,gBAAgB,OAAO;AACzC,YAAM,SAAS,MAAM,IAAI,EAAE,SAAS,KAAK;AAAA,QACvC,YAAY,IAAI;AAAA,QAChB,YAAY,WAAW,MAAM,QAAQ;AAAA,MACvC,CAAC;AACD,aAAO,GAAG,YAAY,eAAe,QAAQ,SAAS,UAAU,GAAG,QAAQ,QAAQ,GAAG,MAAM;AAAA,IAC9F,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa,EAAE,cAAc,OAAO,iBAAiB,MAAM,eAAe,KAAK;AAAA,MAC/E,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,GAAE,OAAO,EAAE,SAAS,aAAa;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,MACb,MAAM,YAAY;AAChB,YAAM,WAAW,MAAM,IAAI,EAAE,SAAS,IAAI,KAAK;AAC/C,UAAI,CAAC,SAAU,QAAO,KAAK,6BAA6B,KAAK,GAAG;AAEhE,YAAM,IAAI,EAAE,SAAS,SAAS,KAAK;AACnC,YAAM,QAAQ,MAAM,IAAI,EAAE,SAAS,IAAI,KAAK;AAC5C,aAAO;AAAA,QACL,sBAAsB,KAAK,SAAS,SAAS,MAAM,SAAS,OAAO,UAAU,SAAS;AAAA,QACtF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AACF;;;ACnIA,SAAS,KAAAC,UAAS;;;ACCX,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAC3B,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAEjC,IAAM,UAAkC,EAAE,GAAG,KAAO,GAAG,KAAQ,GAAG,MAAW,GAAG,MAAW;AAEpF,SAAS,cAAc,OAAuB;AACnD,QAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,qBAAqB;AACtD,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,qBAAqB,KAAK,0CAA0C;AAChG,SAAO,OAAO,MAAM,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,EAAG,YAAY,CAAC;AAC3D;AAEA,SAAS,aAAa,OAAe,MAAoB;AACvD,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,OAAM,IAAI,MAAM,WAAW,IAAI,KAAK,KAAK,0BAA0B;AACrG,SAAO;AACT;AAEO,SAAS,cACd,OACA,MAAY,oBAAI,KAAK,GACK;AAC1B,QAAM,KAAK,MAAM,KAAK,aAAa,MAAM,IAAI,IAAI,IAAI;AACrD,QAAM,OAAO,MAAM,OACf,aAAa,MAAM,MAAM,MAAM,IAC/B,IAAI,KAAK,GAAG,QAAQ,IAAI,cAAc,MAAM,QAAQ,iBAAiB,CAAC;AAC1E,MAAI,KAAK,QAAQ,IAAI,GAAG,QAAQ,EAAG,OAAM,IAAI,MAAM,WAAW,KAAK,YAAY,CAAC,oBAAoB,GAAG,YAAY,CAAC,IAAI;AACxH,SAAO,EAAE,MAAM,GAAG;AACpB;AAoBA,SAAS,QAAQ,MAA8B;AAC7C,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,OAAwB;AACzC,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACjE;AAEO,SAAS,SAAS,MAAc,MAAM,mBAA2B;AACtE,SAAO,KAAK,SAAS,MAAM,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC,WAAM,KAAK,SAAS,GAAG,YAAY;AACrF;AAEA,SAAS,UAAU,QAAuB,UAAuB;AAC/D,QAAM,MAAM,UAAU,SAAS;AAC/B,MAAI,QAAQ,mBAAoB,QAAO;AACvC,MAAI,QAAQ,mBAAoB,QAAO;AACvC,MAAI,OAAO,UAAU,OAAO,SAAU,QAAO,GAAG,OAAO,UAAU,GAAG,SAAI,OAAO,YAAY,GAAG;AAC9F,SAAO;AACT;AAEO,SAAS,WAAW,SAAqC;AAC9D,QAAM,SAAS,QAAQ,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,SAAS,QAAQ,EAAE,OAAO,GAAG,UAAU,QAAQ,EAAE,UAAU,EAAE,EAAE;AAE/G,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,EAAE,QAAQ,KAAK,QAAQ;AAChC,QAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,CAAC,MAAM,EAAG,aAAY,IAAI,OAAO,QAAQ,CAAC,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC,CAAC;AAAA,EACxG;AAEA,SAAO,OAAO,IAAI,CAAC,EAAE,QAAQ,SAAS,SAAS,MAAM;AACnD,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,aAAa,UAAU,MAAM,QAAQ,OAAO,KAAK,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,QAAQ,CAAC,CAAC,GAAG;AAC1F,YAAM,OAAO,YAAY,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC;AAC/C,UAAI,QAAQ,CAAC,MAAM,GAAG;AACpB,iBAAS,OAAO,QAAQ,CAAC,CAAC;AAC1B,kBAAU,UAAU,QAAQ,CAAC,KAAK,CAAC,CAAC;AAAA,MACtC,WAAW,QAAQ,CAAC,MAAM,GAAG;AAC3B,iBAAS,GAAG,QAAQ,GAAG;AACvB,kBAAU,UAAU,QAAQ,CAAC,KAAK,CAAC,CAAC;AAAA,MACtC,OAAO;AACL,iBAAS,GAAG,QAAQ,GAAG;AACvB,kBAAU,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,IAAI,UAAU,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACtG;AAAA,IACF,OAAO;AACL,eAAS,OAAQ,UAAkB,QAAQ,OAAO,YAAY,KAAK;AACnE,gBAAU,OAAO,WAAW;AAAA,IAC9B;AACA,QAAI,OAAO,MAAO,WAAU,GAAG,OAAO,YAAY,OAAO,KAAK;AAC9D,WAAO;AAAA,MACL,MAAM,OAAO,aAAa;AAAA,MAC1B,WAAW,UAAU,QAAQ,QAAQ;AAAA,MACrC;AAAA,MACA,SAAS,SAAS,QAAQ,QAAQ,QAAQ,GAAG,EAAE,KAAK,CAAC;AAAA,IACvD;AAAA,EACF,CAAC;AACH;AAEO,SAAS,cAAc,MAAe,QAAyB;AACpE,QAAM,OAAO,KAAK,OAAO,QAAQ,qBAAqB,EAAE,EAAE,YAAY;AACtE,SAAO,SAAS,OAAO,KAAK,EAAE,YAAY;AAC5C;AAEO,SAAS,WAAW,MAAuB;AAChD,SAAO,GAAG,KAAK,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK,MAAM,KAAK,KAAK,OAAO;AACzE;;;ADtGA,IAAM,YAAY,EAAE,cAAc,MAAM,eAAe,KAAK;AAE5D,IAAM,aAAa;AAIZ,SAAS,gBAAsC,OAA6C;AACjG,UAAQ,SAAS,CAAC,GAAG;AAAA,IAAI,CAAC,SACxB,WAAW,KAAK,KAAK,OAAO,KAAK,gBAAgB,EAAE,KAAK,KAAK,QAAQ,EAAE,GAAG,MAAM,OAAO,MAAM,IAAI;AAAA,EACnG;AACF;AAEA,SAAS,mBAAmB,KAAkB;AAC5C,QAAM,QAAQ,IAAI;AAClB,QAAM,SAAS,IAAI;AACnB,QAAM,cAAc,OAAO,mBAAmB,IAAI,qBAAqB,CAAC,GACrE,IAAI,CAAC,MAAW,IAAI,EAAE,UAAU,EAAE,WAAW,IAAI,EAAE,IAAI,WAAW,EAAE,aAAa,UAAU,UAAU,GAAG,EACxG,KAAK,IAAI;AACZ,QAAM,QAAQ;AAAA,IACZ,aAAa,IAAI,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI,QAAQ,aAAa,IAAI,aAAa,WAC7E,IAAI,cAAc,iBAAiB,IAAI,aAAa,GAAG,IAAI,YAAY,gBAAgB,EAAE;AAAA,IACpG,UAAU,OAAO,QAAQ,GAAG,OAAO,OAAO,oBAAoB,QAAQ,GAAG,MACtE,aAAa,iBAAiB,UAAU,MAAM;AAAA,IACjD,aAAa,QAAQ,YAAY,GAAG,sBAAsB,QAAQ,qBAAqB,OAAO,KAAK,0BACzE,QAAQ,qBAAqB,CAAC,GAAG,KAAK,IAAI,KAAK,QAAG;AAAA,IAC5E,4BAA4B,IAAI,wBAAwB,UAAU,CAAC;AAAA,EACrE;AACA,MAAI,IAAI,SAAS;AACf,UAAM;AAAA,MACJ,YAAY,IAAI,QAAQ,EAAE,KAAK,IAAI,QAAQ,MAAM,MAC9C,IAAI,QAAQ,aAAa,WAAM,IAAI,QAAQ,UAAU,KAAK,MAAM;AAAA,IACrE;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,IAAM,2BAA2B;AAEjC,SAAS,cAAc,IAAiB;AACtC,SAAO,GAAG,SAAS,YAAY,GAAG,QAAQ,gBAAgB,GAAG;AAC/D;AAEA,SAAS,iBAAiB,SAAgB,WAAwB;AAChE,QAAM,SAAS,UAAU,KAAK,EAAE,YAAY;AAC5C,SACE,QAAQ,KAAK,CAAC,OAAO,GAAG,OAAO,UAAU,KAAK,CAAC,KAC/C,QAAQ,KAAK,CAAC,OAAO,GAAG,SAAS,OAAO,UAAU,KAAK,KAAK,GAAG,QAAQ,OAAO,UAAU,KAAK,CAAC,KAC9F,QAAQ;AAAA,IAAK,CAAC,OACZ,GAAG,SAAS,UAAU,YAAY,MAAM,UAAU,GAAG,QAAQ,cAAc,YAAY,MAAM;AAAA,EAC/F;AAEJ;AAEA,SAAS,aAAa,KAAU,YAAiB,MAAc,OAAoB;AACjF,QAAM,WAAW,YAAY,WAAW,CAAC,GAAG,OAAO,OAAO;AAC1D,QAAM,QAAQ;AAAA,IACZ,YAAY,IAAI,EAAE,MAAM,IAAI,UAAU,QAAQ,GAAG,OAAO,IAAI,MAAM,MAC/D,IAAI,aAAa,WAAM,IAAI,UAAU,KAAK,MAC3C,aAAa,IAAI,sBAAsB,IAAI,kBAAkB,QAAG,aAAa,IAAI,qBAAqB,QAAG;AAAA,IAC3G,YAAY,gBAAgB,QAAQ,QAAQ,YAAY,YAAY,EAAE,KAAK,CAAC;AAAA,EAC9E;AACA,aAAW,MAAM,SAAS;AACxB,UAAM,KAAK,KAAK,cAAc,EAAE,CAAC,eAAe,GAAG,SAAS,MAAM,GAAG,QAAQ,MAAM,GAAG,eAAe,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;AAAA,EAC7H;AACA,MAAI,OAAO;AACT,UAAM,KAAK,IAAI,YAAY,cAAc,KAAK,CAAC,GAAG;AAClD,eAAW,QAAQ,MAAM,kBAAkB,CAAC,GAAG;AAC7C,YAAM;AAAA,QACJ,YAAY,KAAK,KAAK,IAAI,KAAK,gBAAgB,QAAQ,QAAQ,GAAG,KAAK,KAAK,MAAM,MAC/E,KAAK,aAAa,WAAM,KAAK,UAAU,KAAK;AAAA,MACjD;AAAA,IACF;AAAA,EACF,WAAW,QAAQ,SAAS,KAAK,YAAY,UAAU,aAAa;AAClE,UAAM,KAAK,IAAI,uEAAuE;AAAA,EACxF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,qBAAqB,QAAmB;AACtD,QAAM,aAAaC,GAChB,OAAO,EACP,SAAS,EACT,SAAS,6EAA6E;AAEzF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MAMF,aAAa,EAAE,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB,GAAG,SAAS,WAAW;AAAA,MAC9F,aAAa;AAAA,IACf;AAAA,IACA,OAAO,EAAE,WAAW,QAAQ,MAC1B,MAAM,YAAY;AAChB,YAAM,EAAE,IAAI,IAAI,MAAM,uBAAuB,WAAW,OAAO;AAC/D,YAAM,UAAU,MAAM,IAAI,EAAE,WAAW,WAAW,IAAI,EAAE;AACxD,UAAI,CAAC,QAAS,QAAO,GAAG,8BAA8B,IAAI,EAAE,GAAG;AAC/D,YAAM,QAAQ,MAAM,IAAI,EAAE,WAAW,mBAAmB,IAAI,EAAE;AAC9D,YAAM,OAAO,EAAE,GAAG,SAAS,wBAAwB,gBAAgB,KAA4B,EAAE;AACjG,aAAO,GAAG,mBAAmB,IAAI,GAAG,IAAI;AAAA,IAC1C,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MAIF,aAAa;AAAA,QACX,WAAWA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,QACxD,MAAMA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,QACrF,IAAIA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;AAAA,QAC5E,MAAMA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6DAA6D,iBAAiB,GAAG;AAAA,QACtH,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,cAAc,EAAE,SAAS,EACzD,SAAS,iCAAiC,kBAAkB,SAAS,cAAc,GAAG;AAAA,QACzF,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qDAAqD;AAAA,QAC5F,SAAS;AAAA,MACX;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,OAAO,EAAE,WAAW,MAAM,IAAI,MAAM,OAAO,QAAQ,QAAQ,MACzD,MAAM,YAAY;AAChB,YAAM,SAAS,cAAc,EAAE,MAAM,IAAI,KAAK,CAAC;AAC/C,YAAM,EAAE,IAAI,IAAI,MAAM,uBAAuB,WAAW,OAAO;AAE/D,YAAM,QAAQ,KAAK,IAAI,SAAS,oBAAoB,cAAc;AAClE,YAAM,SAAS,MAAM,IAAI,EAAE,KAAK,KAAK;AAAA,QACnC,aAAa,IAAI;AAAA,QACjB,MAAM,OAAO;AAAA,QACb,IAAI,OAAO;AAAA,QACX,OAAO,SAAS,iBAAiB;AAAA,MACnC,CAAC;AAED,YAAM,MAAM,WAAW,OAAO,OAAO;AACrC,YAAM,UAAU,SAAS,IAAI,OAAO,CAAC,SAAS,cAAc,MAAM,MAAM,CAAC,IAAI;AAC7E,YAAM,QAAQ,QAAQ,MAAM,GAAG,KAAK,EAAE,QAAQ;AAC9C,YAAM,YAAY,QAAQ,SAAS,SAAS,QAAQ,OAAO,UAAU,WAAW;AAEhF,YAAM,OACJ,GAAG,IAAI,QAAQ,SAAS,IAAI,EAAE,KAAK,OAAO,KAAK,YAAY,CAAC,WAAM,OAAO,GAAG,YAAY,CAAC,KACtF,MAAM,MAAM,uBACd,SAAS,cAAc,MAAM,QAAQ,IAAI,MAAM,aAAa,OAC5D,OAAO,UAAU,cAAc,OAAO,KAAK,OAAO,SAAS,UAAU,eAAe,MACrF,gBAAgB,YAAY,oDAA+C,IAAI;AACjF,aAAO,GAAG,CAAC,MAAM,IAAI,GAAG,MAAM,IAAI,UAAU,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC3D,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE,iHACsB,wBAAwB;AAAA,MAGhD,aAAa;AAAA,QACX,OAAOA,GAAE,OAAO,EAAE,SAAS,aAAa;AAAA,QACxC,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,yDAAyD;AAAA,QAC3G,WAAWA,GAAE,OAAO,EAAE,SAAS,EAC5B,SAAS,wFAAwF;AAAA,MACtG;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,OAAO,EAAE,OAAO,MAAM,UAAU,MAC9B,MAAM,YAAY;AAChB,YAAM,MAAM,MAAM,IAAI,EAAE,SAAS,WAAW,KAAK;AACjD,UAAI,CAAC,IAAK,QAAO,GAAG,6BAA6B,KAAK,GAAG;AACzD,YAAM,UAAU,QAAQ;AACxB,YAAM,aAAa,MAAM,IAAI,EAAE,SAAS,eAAe,OAAO;AAAA,QAC5D,YAAY,EAAE,MAAM,SAAS,UAAU,yBAAyB;AAAA,MAClE,CAAC;AACD,YAAM,WAAW,YAAY,WAAW,CAAC,GAAG,OAAO,OAAO;AAE1D,UAAI;AACJ,UAAI,WAAW;AACb,iBAAS,iBAAiB,SAAS,SAAS;AAC5C,YAAI,CAAC,QAAQ;AACX,iBAAO;AAAA,YACL,iBAAiB,SAAS,aAAa,OAAO,gBAAgB,KAAK;AAAA,UAErE;AAAA,QACF;AAAA,MACF,WAAW,YAAY,UAAU,eAAe,KAAM,YAAY,KAAK,QAAQ,WAAW,KAAK,CAAC,YAAY,UAAU,aAAc;AAClI,iBAAS,QAAQ,CAAC;AAAA,MACpB;AAEA,YAAM,MAAM,QAAQ,SAAS,KACzB,EAAE,WAAW,OAAO,QAAQ,GAAa,IACzC,QAAQ,QAAQ,KAAK,EAAE,UAAU,OAAO,OAAO,GAAa,IAAI;AACpE,YAAM,QAAQ,MAAM,MAAM,IAAI,EAAE,SAAS,kBAAkB,OAAO,GAAG,IAAI;AACzE,aAAO,GAAG,aAAa,KAAK,YAAY,SAAS,KAAK,GAAG,EAAE,KAAK,YAAY,MAAM,CAAC;AAAA,IACrF,CAAC;AAAA,EACL;AACF;;;AEtNO,IAAM,eAAe;AAErB,SAAS,eAAe,MAAyB,QAAQ,KAAc;AAC5E,QAAM,QAAQ,IAAI,YAAY,GAAG,KAAK,EAAE,YAAY;AACpD,SAAO,UAAU,OAAO,UAAU;AACpC;AAEA,SAAS,aAAa,QAA8B;AAClD,SAAO,IAAI,MAAM,QAAQ;AAAA,IACvB,IAAI,QAAQ,MAAM,UAAU;AAC1B,UAAI,SAAS,eAAgB,QAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AACtE,aAAO,CAAC,MAAc,QAAsD,OAC1E,OAAO,aAAa,iBAAiB,OAChC,OAAO,aAAiD,MAAM,QAAQ,EAAE,IACzE;AAAA,IACR;AAAA,EACF,CAAC;AACH;AAEO,SAAS,cAAc,QAAmB,SAAgC;AAC/E,QAAM,SAAS,QAAQ,WAAW,aAAa,MAAM,IAAI;AACzD,uBAAqB,MAAM;AAC3B,oBAAkB,MAAM;AACxB,yBAAuB,MAAM;AAC7B,oBAAkB,MAAM;AACxB,uBAAqB,MAAM;AAC3B,uBAAqB,MAAM;AAC7B;;;Ad9BA,eAAe,OAAO;AACpB,MAAI,CAAC,QAAQ,IAAI,oBAAoB;AACnC,YAAQ;AAAA,MACN;AAAA,IAEF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,IAAI,UAAU,EAAE,MAAM,YAAY,SAAS,QAAQ,CAAC;AAEnE,QAAM,WAAW,eAAe;AAChC,gBAAc,QAAQ,EAAE,SAAS,CAAC;AAElC,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,UAAQ,MAAM,uCAAuC,WAAW,iBAAiB,EAAE,EAAE;AACvF;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,UAAQ,MAAM,6CAA6C,KAAK;AAChE,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["z","z","z","z","z","z","protocolEnum","z","z","z","z","z"]}
|