@web-remarq/mcp 0.3.0 → 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/README.md CHANGED
@@ -97,7 +97,10 @@ loop:
97
97
  # do not wait for subagents - go straight back to watch_annotations
98
98
  ```
99
99
 
100
- Copy-paste prompt to put an agent on duty in this mode:
100
+ The server ships this recipe as an MCP prompt: in clients that support them
101
+ (Claude Code renders it as the `/mcp__web-remarq__watch` slash command) one
102
+ command puts the agent on duty - no copy-paste needed. For clients without
103
+ MCP-prompt support, paste this instead:
101
104
 
102
105
  > You are on annotation duty for this project. Designers drop feedback via
103
106
  > the web-remarq MCP server. Run this loop until I tell you to stop: call
@@ -119,6 +122,10 @@ via the MCP tools. Files appear when an annotation is submitted, update on
119
122
  status changes, and disappear once it is verified or dismissed. The folder is
120
123
  server-owned - never edit or commit it (`.remarq/` self-gitignores).
121
124
 
125
+ Caveat: with a custom `REMARQ_DATA_FILE` pointing outside `.remarq/`, the
126
+ `tasks/` folder is created next to your data file and is NOT auto-gitignored -
127
+ add it to your `.gitignore` yourself.
128
+
122
129
  There is no mode switch:
123
130
 
124
131
  - **Agent on duty** (watching via `watch_annotations`): the folder just mirrors
package/dist/server.js CHANGED
@@ -145,89 +145,6 @@ var FileStorageAdapter = class {
145
145
 
146
146
  // src/http-server.ts
147
147
  import * as http from "http";
148
- var CORS_HEADERS = {
149
- "Access-Control-Allow-Origin": "*",
150
- "Access-Control-Allow-Methods": "GET, PUT, DELETE, OPTIONS",
151
- "Access-Control-Allow-Headers": "content-type"
152
- };
153
- var MAX_BODY_BYTES = 1024 * 1024;
154
- function json(res, status, body) {
155
- res.writeHead(status, { ...CORS_HEADERS, "content-type": "application/json" });
156
- res.end(JSON.stringify(body));
157
- }
158
- function readBody(req) {
159
- return new Promise((resolve, reject) => {
160
- let size = 0;
161
- const chunks = [];
162
- req.on("data", (chunk) => {
163
- size += chunk.length;
164
- if (size > MAX_BODY_BYTES) {
165
- reject(new Error("body too large"));
166
- req.destroy();
167
- return;
168
- }
169
- chunks.push(chunk);
170
- });
171
- req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
172
- req.on("error", reject);
173
- });
174
- }
175
- async function handle(req, res, storage) {
176
- if (req.method === "OPTIONS") {
177
- res.writeHead(204, CORS_HEADERS);
178
- res.end();
179
- return;
180
- }
181
- const pathname = new URL(req.url ?? "/", "http://localhost").pathname;
182
- const annMatch = pathname.match(/^\/annotations\/([^/]+)$/);
183
- try {
184
- if (req.method === "GET" && pathname === "/store") {
185
- const rev = storage.rev;
186
- const store = await storage.load() ?? { version: 1, annotations: [] };
187
- json(res, 200, { rev, store });
188
- return;
189
- }
190
- if (req.method === "PUT" && annMatch) {
191
- const id = decodeURIComponent(annMatch[1]);
192
- let annotation;
193
- try {
194
- annotation = JSON.parse(await readBody(req));
195
- } catch {
196
- json(res, 400, { error: "invalid JSON body" });
197
- return;
198
- }
199
- if (!annotation || annotation.id !== id) {
200
- json(res, 400, { error: "annotation.id must match the URL id" });
201
- return;
202
- }
203
- await storage.save(annotation);
204
- json(res, 200, { rev: storage.rev });
205
- return;
206
- }
207
- if (req.method === "DELETE" && annMatch) {
208
- await storage.remove(decodeURIComponent(annMatch[1]));
209
- json(res, 200, { rev: storage.rev });
210
- return;
211
- }
212
- if (req.method === "DELETE" && pathname === "/annotations") {
213
- await storage.clear();
214
- json(res, 200, { rev: storage.rev });
215
- return;
216
- }
217
- json(res, 404, { error: "not found" });
218
- } catch (err) {
219
- json(res, 500, { error: err instanceof Error ? err.message : String(err) });
220
- }
221
- }
222
- function startHttpServer(storage, port) {
223
- const server = http.createServer((req, res) => {
224
- void handle(req, res, storage);
225
- });
226
- return new Promise((resolve, reject) => {
227
- server.once("error", reject);
228
- server.listen(port, "127.0.0.1", () => resolve(server));
229
- });
230
- }
231
148
 
232
149
  // src/task-folder.ts
233
150
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -236,6 +153,9 @@ import { actionableOnly, generateAgentExport } from "web-remarq/core";
236
153
  function yamlString(value) {
237
154
  return JSON.stringify(value);
238
155
  }
156
+ function isSafeAnnotationId(id) {
157
+ return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(id);
158
+ }
239
159
  function renderTaskFile(annotation) {
240
160
  const agent = generateAgentExport([annotation], annotation.viewportBucket).annotations[0];
241
161
  const lines = [];
@@ -295,15 +215,31 @@ var TaskFolder = class {
295
215
  async sync() {
296
216
  const store = await this.storage.load();
297
217
  const actionable = actionableOnly(store?.annotations ?? []);
298
- const desired = new Map(actionable.map((a) => [`${a.id}.md`, renderTaskFile(a)]));
218
+ const desired = /* @__PURE__ */ new Map();
219
+ for (const a of actionable) {
220
+ if (!isSafeAnnotationId(a.id)) {
221
+ console.error(`[web-remarq-mcp] skipping annotation with unsafe id: ${JSON.stringify(a.id)}`);
222
+ continue;
223
+ }
224
+ desired.set(`${a.id}.md`, renderTaskFile(a));
225
+ }
299
226
  mkdirSync2(this.dir, { recursive: true });
300
- for (const name of readdirSync(this.dir)) {
301
- if (name.endsWith(".md") && !desired.has(name)) unlinkSync(join2(this.dir, name));
227
+ for (const entry of readdirSync(this.dir, { withFileTypes: true })) {
228
+ if (!entry.isFile() || !entry.name.endsWith(".md") || desired.has(entry.name)) continue;
229
+ try {
230
+ unlinkSync(join2(this.dir, entry.name));
231
+ } catch (err) {
232
+ console.error(`[web-remarq-mcp] failed to remove stale task file ${entry.name}:`, err);
233
+ }
302
234
  }
303
235
  for (const [name, content] of desired) {
304
- const path = join2(this.dir, name);
305
- if (existsSync2(path) && readFileSync2(path, "utf8") === content) continue;
306
- writeFileSync2(path, content);
236
+ try {
237
+ const path = join2(this.dir, name);
238
+ if (existsSync2(path) && readFileSync2(path, "utf8") === content) continue;
239
+ writeFileSync2(path, content);
240
+ } catch (err) {
241
+ console.error(`[web-remarq-mcp] failed to write task file ${name}:`, err);
242
+ }
307
243
  }
308
244
  }
309
245
  /** Coalesces change bursts: at most one sync in flight, one more queued. Never throws. */
@@ -326,6 +262,115 @@ var TaskFolder = class {
326
262
  }
327
263
  };
328
264
 
265
+ // src/http-server.ts
266
+ var CORS_HEADERS = {
267
+ "Access-Control-Allow-Origin": "*",
268
+ "Access-Control-Allow-Methods": "GET, PUT, DELETE, OPTIONS",
269
+ "Access-Control-Allow-Headers": "content-type"
270
+ };
271
+ var MAX_BODY_BYTES = 1024 * 1024;
272
+ function json(res, status, body) {
273
+ res.writeHead(status, { ...CORS_HEADERS, "content-type": "application/json" });
274
+ res.end(JSON.stringify(body));
275
+ }
276
+ function readBody(req) {
277
+ return new Promise((resolve, reject) => {
278
+ let size = 0;
279
+ const chunks = [];
280
+ req.on("data", (chunk) => {
281
+ size += chunk.length;
282
+ if (size > MAX_BODY_BYTES) {
283
+ reject(new Error("body too large"));
284
+ req.destroy();
285
+ return;
286
+ }
287
+ chunks.push(chunk);
288
+ });
289
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
290
+ req.on("error", reject);
291
+ });
292
+ }
293
+ async function handle(req, res, storage) {
294
+ if (req.method === "OPTIONS") {
295
+ res.writeHead(204, CORS_HEADERS);
296
+ res.end();
297
+ return;
298
+ }
299
+ const pathname = new URL(req.url ?? "/", "http://localhost").pathname;
300
+ const annMatch = pathname.match(/^\/annotations\/([^/]+)$/);
301
+ try {
302
+ if (req.method === "GET" && pathname === "/store") {
303
+ const rev = storage.rev;
304
+ const store = await storage.load() ?? { version: 1, annotations: [] };
305
+ json(res, 200, { rev, store });
306
+ return;
307
+ }
308
+ if (req.method === "PUT" && annMatch) {
309
+ const id = decodeURIComponent(annMatch[1]);
310
+ if (!isSafeAnnotationId(id)) {
311
+ json(res, 400, { error: "invalid annotation id" });
312
+ return;
313
+ }
314
+ let annotation;
315
+ try {
316
+ annotation = JSON.parse(await readBody(req));
317
+ } catch {
318
+ json(res, 400, { error: "invalid JSON body" });
319
+ return;
320
+ }
321
+ if (!annotation || annotation.id !== id) {
322
+ json(res, 400, { error: "annotation.id must match the URL id" });
323
+ return;
324
+ }
325
+ await storage.save(annotation);
326
+ json(res, 200, { rev: storage.rev });
327
+ return;
328
+ }
329
+ if (req.method === "DELETE" && annMatch) {
330
+ const id = decodeURIComponent(annMatch[1]);
331
+ if (!isSafeAnnotationId(id)) {
332
+ json(res, 400, { error: "invalid annotation id" });
333
+ return;
334
+ }
335
+ await storage.remove(id);
336
+ json(res, 200, { rev: storage.rev });
337
+ return;
338
+ }
339
+ if (req.method === "DELETE" && pathname === "/annotations") {
340
+ await storage.clear();
341
+ json(res, 200, { rev: storage.rev });
342
+ return;
343
+ }
344
+ json(res, 404, { error: "not found" });
345
+ } catch (err) {
346
+ json(res, 500, { error: err instanceof Error ? err.message : String(err) });
347
+ }
348
+ }
349
+ function startHttpServer(storage, port) {
350
+ const server = http.createServer((req, res) => {
351
+ void handle(req, res, storage);
352
+ });
353
+ return new Promise((resolve, reject) => {
354
+ server.once("error", reject);
355
+ server.listen(port, "127.0.0.1", () => resolve(server));
356
+ });
357
+ }
358
+
359
+ // src/prompts.ts
360
+ var DUTY_PROMPT = "You are on annotation duty for this project. Designers drop feedback via the web-remarq MCP server. Run this loop until told to stop: call watch_annotations (timeoutSeconds: 60); if it times out, call it again. For EACH annotation it returns, call acknowledge with its id first. Then, if you can run background subagents, dispatch one that applies the fix to the project files and calls claim_fix when done - do not fix anything yourself in the main loop and do not wait for subagents, go straight back to watch_annotations so new feedback is never missed. Without background subagents, apply the fix inline after acknowledging, then return to watch_annotations. If a comment is ambiguous or unactionable, dismiss it with a reason instead of guessing.";
361
+ function registerPrompts(server) {
362
+ server.registerPrompt(
363
+ "watch",
364
+ {
365
+ title: "Annotation duty (dispatcher loop)",
366
+ description: "Put this agent on annotation duty: loop on watch_annotations, acknowledge each annotation first, hand the fix to a background subagent that calls claim_fix, return to watching immediately."
367
+ },
368
+ () => ({
369
+ messages: [{ role: "user", content: { type: "text", text: DUTY_PROMPT } }]
370
+ })
371
+ );
372
+ }
373
+
329
374
  // src/tools/list-annotations.ts
330
375
  import { z } from "zod";
331
376
 
@@ -586,7 +631,7 @@ function registerTools(server, storage, opts) {
586
631
  server.registerTool(
587
632
  "list_annotations",
588
633
  {
589
- description: "List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran.",
634
+ description: "List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran. In local mode, actionable annotations (pending / in_progress) are also mirrored as ticket files in .remarq/tasks/.",
590
635
  inputSchema: listAnnotationsInputSchema.shape
591
636
  },
592
637
  (input) => cast(handleListAnnotations(input, storage))
@@ -650,12 +695,13 @@ async function main() {
650
695
  let waitForChange;
651
696
  if (config.mode === "local") {
652
697
  const adapter = new FileStorageAdapter(config.dataFile);
653
- const taskFolder = new TaskFolder(adapter, join3(dirname2(config.dataFile), "tasks"));
698
+ const tasksDir = join3(dirname2(config.dataFile), "tasks");
699
+ const taskFolder = new TaskFolder(adapter, tasksDir);
654
700
  adapter.onChange(() => taskFolder.schedule());
655
701
  taskFolder.schedule();
656
702
  await startHttpServer(adapter, config.port);
657
703
  console.error(
658
- `[web-remarq-mcp] local mode \u2014 widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}`
704
+ `[web-remarq-mcp] local mode \u2014 widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}, tasks ${tasksDir}`
659
705
  );
660
706
  storage = adapter;
661
707
  waitForChange = (ms) => adapter.waitForChange(ms);
@@ -665,9 +711,10 @@ async function main() {
665
711
  }
666
712
  const server = new McpServer({
667
713
  name: "web-remarq",
668
- version: "0.2.0"
714
+ version: "0.4.0"
669
715
  });
670
716
  registerTools(server, storage, { waitForChange });
717
+ registerPrompts(server);
671
718
  const transport = new StdioServerTransport();
672
719
  await server.connect(transport);
673
720
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/config.ts","../src/storage-factory.ts","../src/file-storage-adapter.ts","../src/http-server.ts","../src/task-folder.ts","../src/tools/list-annotations.ts","../src/errors.ts","../src/tools/get-annotation.ts","../src/tools/acknowledge.ts","../src/tools/claim-fix.ts","../src/tools/dismiss.ts","../src/tools/watch-annotations.ts","../src/tools/index.ts"],"sourcesContent":["import { dirname, join } from 'node:path'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport type { StorageAdapter } from 'web-remarq'\nimport { parseEnv, ConfigError } from './config.js'\nimport { createStorage } from './storage-factory.js'\nimport { FileStorageAdapter } from './file-storage-adapter.js'\nimport { startHttpServer } from './http-server.js'\nimport { TaskFolder } from './task-folder.js'\nimport { registerTools, type WaitForChange } from './tools/index.js'\n\nconst CLOUD_POLL_MS = 3000\n\nasync function main(): Promise<void> {\n let config\n try {\n config = parseEnv(process.env)\n } catch (err) {\n if (err instanceof ConfigError) {\n console.error(`[web-remarq-mcp] config error: ${err.message}`)\n process.exit(1)\n }\n throw err\n }\n\n let storage: StorageAdapter\n let waitForChange: WaitForChange\n\n if (config.mode === 'local') {\n const adapter = new FileStorageAdapter(config.dataFile)\n const taskFolder = new TaskFolder(adapter, join(dirname(config.dataFile), 'tasks'))\n adapter.onChange(() => taskFolder.schedule())\n taskFolder.schedule() // project existing annotations on startup\n await startHttpServer(adapter, config.port)\n console.error(\n `[web-remarq-mcp] local mode — widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}`,\n )\n storage = adapter\n waitForChange = (ms) => adapter.waitForChange(ms)\n } else {\n storage = createStorage(config)\n waitForChange = (ms) =>\n new Promise((resolve) => setTimeout(() => resolve(false), Math.min(ms, CLOUD_POLL_MS)))\n }\n\n const server = new McpServer({\n name: 'web-remarq',\n version: '0.2.0',\n })\n\n registerTools(server, storage, { waitForChange })\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\nmain().catch((err) => {\n console.error('[web-remarq-mcp] fatal:', err)\n process.exit(1)\n})\n","export interface CloudConfig {\n mode: 'cloud'\n projectKey: string\n supabaseUrl: string\n supabaseAnonKey: string\n}\n\nexport interface LocalConfig {\n mode: 'local'\n port: number\n dataFile: string\n}\n\nexport type MCPConfig = CloudConfig | LocalConfig\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ConfigError'\n }\n}\n\nfunction require_(env: NodeJS.ProcessEnv, key: string): string {\n const v = env[key]\n if (!v || v.trim() === '') {\n throw new ConfigError(`Missing required env var: ${key}`)\n }\n return v\n}\n\nconst DEFAULT_PORT = 1817\nconst DEFAULT_DATA_FILE = '.remarq/annotations.json'\n\nexport function parseEnv(env: NodeJS.ProcessEnv): MCPConfig {\n const cloudRequested = Boolean(\n env.REMARQ_PROJECT_KEY || env.REMARQ_SUPABASE_URL || env.REMARQ_SUPABASE_ANON_KEY,\n )\n\n if (cloudRequested) {\n const projectKey = require_(env, 'REMARQ_PROJECT_KEY')\n const supabaseUrl = require_(env, 'REMARQ_SUPABASE_URL')\n const supabaseAnonKey = require_(env, 'REMARQ_SUPABASE_ANON_KEY')\n\n if (!projectKey.startsWith('pk_')) {\n throw new ConfigError('REMARQ_PROJECT_KEY must start with `pk_` (generated by `npx @web-remarq/cloud gen-key`)')\n }\n if (!supabaseUrl.startsWith('https://')) {\n throw new ConfigError('REMARQ_SUPABASE_URL must start with https://')\n }\n\n return { mode: 'cloud', projectKey, supabaseUrl, supabaseAnonKey }\n }\n\n const rawPort = env.REMARQ_PORT ?? String(DEFAULT_PORT)\n const port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`REMARQ_PORT must be an integer between 1 and 65535, got \"${rawPort}\"`)\n }\n\n return { mode: 'local', port, dataFile: env.REMARQ_DATA_FILE ?? DEFAULT_DATA_FILE }\n}\n","import { createCloudStorage } from '@web-remarq/cloud'\nimport type { StorageAdapter } from 'web-remarq'\nimport type { CloudConfig } from './config'\n\nexport function createStorage(config: CloudConfig): StorageAdapter {\n return createCloudStorage({\n projectKey: config.projectKey,\n supabaseUrl: config.supabaseUrl,\n supabaseAnonKey: config.supabaseAnonKey,\n onError: 'throw',\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport type { Annotation, AnnotationStore, StorageAdapter } from 'web-remarq'\n\n/**\n * Local-mode StorageAdapter over a JSON file (default .remarq/annotations.json).\n * All mutations flow through this process (MCP tools + the local HTTP server),\n * so change notification is a plain in-memory emitter — no fs.watch needed.\n */\nexport class FileStorageAdapter implements StorageAdapter {\n /** Monotonic revision — bumps on every mutation. Exposed via GET /store. */\n rev = 0\n private emitter = new EventEmitter()\n /** Serializes mutations (save/remove/clear) so concurrent read-modify-write ops don't clobber each other. */\n private queue: Promise<void> = Promise.resolve()\n\n constructor(private filePath: string) {\n this.emitter.setMaxListeners(0)\n }\n\n async load(): Promise<AnnotationStore | null> {\n if (!existsSync(this.filePath)) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(this.filePath, 'utf8'))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`annotations store corrupted at ${this.filePath}: ${message}`)\n }\n const store = parsed as { annotations?: unknown }\n return {\n version: 1,\n annotations: Array.isArray(store.annotations) ? (store.annotations as Annotation[]) : [],\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n const idx = store.annotations.findIndex((a) => a.id === annotation.id)\n if (idx === -1) store.annotations.push(annotation)\n else store.annotations[idx] = annotation\n this.persist(store)\n })\n }\n\n async remove(id: string): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n store.annotations = store.annotations.filter((a) => a.id !== id)\n this.persist(store)\n })\n }\n\n async clear(): Promise<void> {\n return this.enqueue(async () => {\n this.persist({ version: 1, annotations: [] })\n })\n }\n\n /** Chains `op` onto the mutation queue; a rejected op doesn't poison later ops. */\n private enqueue(op: () => Promise<void>): Promise<void> {\n const result = this.queue.then(op)\n // Swallow the rejection on the shared chain so the next enqueued op still runs;\n // the caller's own `result` promise still rejects with the original error.\n this.queue = result.catch(() => undefined)\n return result\n }\n\n /** Resolves true on the next mutation, false after timeoutMs. */\n waitForChange(timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const onChange = (): void => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n this.emitter.off('change', onChange)\n resolve(false)\n }, timeoutMs)\n this.emitter.once('change', onChange)\n })\n }\n\n /** Persistent listener for every mutation (save/remove/clear). */\n onChange(listener: () => void): void {\n this.emitter.on('change', listener)\n }\n\n private persist(store: AnnotationStore): void {\n const dir = dirname(this.filePath)\n mkdirSync(dir, { recursive: true })\n // Auto-ignore the store when it lives in the conventional .remarq dir.\n // NEVER write a wildcard .gitignore into an arbitrary user directory.\n if (basename(dir) === '.remarq') {\n const gitignore = join(dir, '.gitignore')\n if (!existsSync(gitignore)) writeFileSync(gitignore, '*\\n')\n }\n const tmp = `${this.filePath}.tmp`\n writeFileSync(tmp, JSON.stringify(store, null, 2))\n renameSync(tmp, this.filePath)\n this.rev++\n this.emitter.emit('change')\n }\n}\n","import * as http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { FileStorageAdapter } from './file-storage-adapter.js'\n\nconst CORS_HEADERS: Record<string, string> = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'content-type',\n}\n\nconst MAX_BODY_BYTES = 1024 * 1024\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { ...CORS_HEADERS, 'content-type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_BODY_BYTES) {\n reject(new Error('body too large'))\n req.destroy()\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\nasync function handle(req: IncomingMessage, res: ServerResponse, storage: FileStorageAdapter): Promise<void> {\n if (req.method === 'OPTIONS') {\n res.writeHead(204, CORS_HEADERS)\n res.end()\n return\n }\n\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n const annMatch = pathname.match(/^\\/annotations\\/([^/]+)$/)\n\n try {\n if (req.method === 'GET' && pathname === '/store') {\n // Capture rev before the await, not after: a concurrent mutation between\n // load() and reading storage.rev would pair a newer rev with the older\n // content this response body carries. Under-reporting is safe (the\n // client's next poll re-diffs); over-reporting is not.\n const rev = storage.rev\n const store = (await storage.load()) ?? { version: 1 as const, annotations: [] }\n json(res, 200, { rev, store })\n return\n }\n\n if (req.method === 'PUT' && annMatch) {\n const id = decodeURIComponent(annMatch[1])\n let annotation: { id?: unknown }\n try {\n annotation = JSON.parse(await readBody(req))\n } catch {\n json(res, 400, { error: 'invalid JSON body' })\n return\n }\n if (!annotation || annotation.id !== id) {\n json(res, 400, { error: 'annotation.id must match the URL id' })\n return\n }\n // The store is trusted local input from the widget; no schema validation.\n await storage.save(annotation as never)\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && annMatch) {\n await storage.remove(decodeURIComponent(annMatch[1]))\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && pathname === '/annotations') {\n await storage.clear()\n json(res, 200, { rev: storage.rev })\n return\n }\n\n json(res, 404, { error: 'not found' })\n } catch (err) {\n json(res, 500, { error: err instanceof Error ? err.message : String(err) })\n }\n}\n\n/** Starts the widget-facing endpoint on 127.0.0.1:port. Rejects on bind errors. */\nexport function startHttpServer(storage: FileStorageAdapter, port: number): Promise<http.Server> {\n const server = http.createServer((req, res) => {\n void handle(req, res, storage)\n })\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', () => resolve(server))\n })\n}\n","import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { Annotation, StorageAdapter } from 'web-remarq'\nimport { actionableOnly, generateAgentExport } from 'web-remarq/core'\n\n/** Double-quoted YAML scalar; JSON string escaping is valid YAML. */\nfunction yamlString(value: string): string {\n return JSON.stringify(value)\n}\n\n/**\n * Renders one annotation as a ticket file for .remarq/tasks/.\n * Deterministic: TaskFolder diffs the output against the file on disk\n * to skip no-op rewrites.\n */\nexport function renderTaskFile(annotation: Annotation): string {\n // Reuse core agent-export for source resolution + search hints (same pattern as get_annotation).\n const agent = generateAgentExport([annotation], annotation.viewportBucket).annotations[0]\n const lines: string[] = []\n\n lines.push('---')\n lines.push(`id: ${yamlString(agent.id)}`)\n lines.push(`route: ${yamlString(agent.route)}`)\n lines.push(`status: ${agent.status}`)\n lines.push(`viewportBucket: ${annotation.viewportBucket}`)\n if (annotation.qualityCheck) lines.push(`quality: ${annotation.qualityCheck.score}`)\n lines.push('---', '')\n\n lines.push(`# web-remarq annotation ${agent.id}`, '')\n lines.push('## Comment', '', agent.comment.trim(), '')\n\n lines.push('## Element', '')\n lines.push(`- Tag: \\`${agent.searchHints.tagName}\\``)\n lines.push(`- DOM: \\`${agent.searchHints.domContext}\\``)\n if (agent.source) {\n const component = agent.source.component ? ` (component \\`${agent.source.component}\\`)` : ''\n lines.push(`- Source: \\`${agent.source.file}:${agent.source.line}:${agent.source.column}\\`${component}`)\n }\n if (agent.searchHints.classes.length) {\n lines.push(`- Classes: ${agent.searchHints.classes.map((c) => `\\`${c}\\``).join(' ')}`)\n }\n lines.push('')\n\n if (agent.searchHints.grepQueries.length) {\n lines.push('## Search hints', '')\n for (const q of agent.searchHints.grepQueries) {\n lines.push(`- [${q.confidence}] \\`${q.query}\\` in \\`${q.glob}\\``)\n }\n lines.push('')\n }\n\n const qc = annotation.qualityCheck\n if (qc && qc.score !== 'clear') {\n lines.push('## Quality check', '')\n lines.push(`Verdict: **${qc.score}** - this comment may need designer clarification; if you cannot act on it confidently, dismiss with a reason instead of guessing.`, '')\n for (const issue of qc.issues) lines.push(`- Issue: ${issue}`)\n for (const q of qc.clarifyingQuestions) lines.push(`- Open question: ${q}`)\n if (qc.suggestedRewrite) lines.push(`- Suggested rewrite: ${qc.suggestedRewrite}`)\n lines.push('')\n }\n\n lines.push('## Agent instructions', '')\n lines.push(`1. BEFORE touching code, call the web-remarq MCP tool \\`acknowledge\\` with \\`{ \"id\": ${yamlString(agent.id)} }\\`. If it errors, another agent already owns this task - skip this file.`)\n lines.push('2. Apply the fix described in the comment.')\n lines.push(`3. When the fix is committed to the working tree, call \\`claim_fix\\` with \\`{ \"id\": ${yamlString(agent.id)} }\\`. A human verifies afterwards - never mark anything as done yourself.`)\n lines.push('')\n lines.push('This file is a live projection maintained by the web-remarq MCP server: it updates when the annotation changes and disappears once the annotation is verified or dismissed. Do not edit or delete it.')\n lines.push('')\n\n return lines.join('\\n')\n}\n\n/**\n * Live projection of actionable annotations (pending/in_progress) into a\n * folder of <id>.md ticket files. The folder is server-owned: every *.md in\n * it is managed - stale ones are deleted on sync. Non-md files are ignored.\n */\nexport class TaskFolder {\n private syncing = false\n private dirty = false\n\n constructor(\n private storage: Pick<StorageAdapter, 'load'>,\n private dir: string,\n ) {}\n\n /** Full idempotent resync: folder contents converge to the actionable set. */\n async sync(): Promise<void> {\n const store = await this.storage.load()\n const actionable = actionableOnly(store?.annotations ?? [])\n const desired = new Map(actionable.map((a) => [`${a.id}.md`, renderTaskFile(a)]))\n\n mkdirSync(this.dir, { recursive: true })\n for (const name of readdirSync(this.dir)) {\n if (name.endsWith('.md') && !desired.has(name)) unlinkSync(join(this.dir, name))\n }\n for (const [name, content] of desired) {\n const path = join(this.dir, name)\n if (existsSync(path) && readFileSync(path, 'utf8') === content) continue\n writeFileSync(path, content)\n }\n }\n\n /** Coalesces change bursts: at most one sync in flight, one more queued. Never throws. */\n schedule(): void {\n this.dirty = true\n void this.run()\n }\n\n private async run(): Promise<void> {\n if (this.syncing) return\n this.syncing = true\n while (this.dirty) {\n this.dirty = false\n try {\n await this.sync()\n } catch (err) {\n console.error('[web-remarq-mcp] task folder sync failed:', err)\n }\n }\n this.syncing = false\n }\n}\n","import { z } from 'zod'\nimport type { Annotation, AnnotationStatus, QualityCheck, StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\n\nconst STATUS_VALUES = ['draft', 'pending', 'in_progress', 'fixed_unverified', 'verified', 'dismissed'] as const\n\nexport const listAnnotationsInputSchema = z.object({\n route: z.string().optional(),\n status: z.union([z.enum(STATUS_VALUES), z.array(z.enum(STATUS_VALUES))]).optional(),\n viewportBucket: z.number().int().optional(),\n file: z.string().optional(),\n limit: z.number().int().min(1).max(200).optional(),\n})\n\nexport type ListAnnotationsInput = z.infer<typeof listAnnotationsInputSchema>\n\nexport interface ThinAnnotation {\n id: string\n route: string\n comment: string\n status: AnnotationStatus\n viewport: number\n timestamp: number\n source: { file: string; line: number; column: number; component?: string } | null\n quality?: QualityCheck['score']\n}\n\nfunction parseSource(annotation: Annotation): ThinAnnotation['source'] {\n const fp = annotation.fingerprint\n const raw = fp.sourceLocation ?? fp.detectedSource\n if (!raw) return null\n const parts = raw.split(':')\n if (parts.length < 2) return null\n const column = parseInt(parts.pop()!, 10)\n const line = parseInt(parts.pop()!, 10)\n const file = parts.join(':')\n if (!file || isNaN(line)) return null\n const component = fp.componentName ?? fp.detectedComponent ?? undefined\n return { file, line, column: isNaN(column) ? 0 : column, ...(component ? { component } : {}) }\n}\n\nexport function toThin(a: Annotation): ThinAnnotation {\n return {\n id: a.id,\n route: a.route,\n comment: a.comment,\n status: a.status,\n viewport: a.viewportBucket,\n timestamp: a.timestamp,\n source: parseSource(a),\n ...(a.qualityCheck ? { quality: a.qualityCheck.score } : {}),\n }\n}\n\nexport async function handleListAnnotations(input: ListAnnotationsInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const all = store?.annotations ?? []\n\n const statusFilter = Array.isArray(input.status)\n ? new Set(input.status)\n : input.status\n ? new Set([input.status])\n : null\n\n const filtered = all.filter((a) => {\n if (input.route !== undefined && a.route !== input.route) return false\n if (statusFilter && !statusFilter.has(a.status)) return false\n if (input.viewportBucket !== undefined && a.viewportBucket !== input.viewportBucket) return false\n if (input.file !== undefined) {\n const src = a.fingerprint.sourceLocation ?? a.fingerprint.detectedSource ?? ''\n if (!src.includes(input.file)) return false\n }\n return true\n })\n\n const limit = input.limit ?? 50\n const thinned = filtered.slice(0, limit).map(toThin)\n\n return toolSuccess({ annotations: thinned, total: filtered.length })\n}\n","export type ToolErrorCode =\n | 'annotation_not_found'\n | 'invalid_transition'\n | 'storage_error'\n | 'validation_error'\n\nexport interface ToolErrorPayload {\n code: ToolErrorCode\n message: string\n details?: Record<string, unknown>\n}\n\nexport interface ToolErrorResult {\n isError: true\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolError(code: ToolErrorCode, message: string, details?: Record<string, unknown>): ToolErrorResult {\n const payload: ToolErrorPayload = { code, message, details }\n return {\n isError: true,\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n }\n}\n\nexport interface ToolSuccessResult {\n isError?: false\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolSuccess(value: unknown): ToolSuccessResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(value) }],\n }\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { generateAgentExport } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const getAnnotationInputSchema = z.object({\n id: z.string(),\n})\n\nexport type GetAnnotationInput = z.infer<typeof getAnnotationInputSchema>\n\nexport async function handleGetAnnotation(input: GetAnnotationInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n // Reuse core agent-export to build the rich shape (source + searchHints + lifecycle).\n // generateAgentExport takes an array — pass the single annotation, then extract.\n const agentExport = generateAgentExport([annotation], annotation.viewportBucket)\n const agentAnnotation = agentExport.annotations[0]\n\n return toolSuccess(agentAnnotation)\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const acknowledgeInputSchema = z.object({\n id: z.string(),\n})\n\nexport type AcknowledgeInput = z.infer<typeof acknowledgeInputSchema>\n\nexport async function handleAcknowledge(input: AcknowledgeInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'acknowledge', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'acknowledge',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const claimFixInputSchema = z.object({\n id: z.string(),\n})\n\nexport type ClaimFixInput = z.infer<typeof claimFixInputSchema>\n\nexport async function handleClaimFix(input: ClaimFixInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'claimFix', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'claimFix',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const dismissInputSchema = z.object({\n id: z.string(),\n reason: z.string().optional(),\n})\n\nexport type DismissInput = z.infer<typeof dismissInputSchema>\n\nexport async function handleDismiss(input: DismissInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'dismiss', { actor: 'agent', reason: input.reason })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'dismiss',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\nimport { toThin } from './list-annotations.js'\n\n/** Waits up to timeoutMs for a backend change. Local mode resolves early on\n * mutation events; cloud mode just sleeps a poll interval and returns false. */\nexport type WaitForChange = (timeoutMs: number) => Promise<boolean>\n\nconst DEFAULT_TIMEOUT_SECONDS = 25\n\nexport const watchAnnotationsInputSchema = z.object({\n timeoutSeconds: z.number().int().min(1).max(120).optional(),\n})\n\nexport type WatchAnnotationsInput = z.infer<typeof watchAnnotationsInputSchema>\n\nexport async function handleWatchAnnotations(\n input: WatchAnnotationsInput,\n storage: StorageAdapter,\n waitForChange: WaitForChange,\n) {\n const timeoutMs = (input.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n const pending = (store?.annotations ?? []).filter((a) => a.status === 'pending')\n if (pending.length > 0) {\n return toolSuccess({ annotations: pending.map(toThin), total: pending.length, timedOut: false })\n }\n\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n return toolSuccess({ annotations: [], total: 0, timedOut: true })\n }\n\n await waitForChange(remaining)\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { StorageAdapter } from 'web-remarq'\n\nimport { listAnnotationsInputSchema, handleListAnnotations } from './list-annotations.js'\nimport { getAnnotationInputSchema, handleGetAnnotation } from './get-annotation.js'\nimport { acknowledgeInputSchema, handleAcknowledge } from './acknowledge.js'\nimport { claimFixInputSchema, handleClaimFix } from './claim-fix.js'\nimport { dismissInputSchema, handleDismiss } from './dismiss.js'\nimport { watchAnnotationsInputSchema, handleWatchAnnotations, type WaitForChange } from './watch-annotations.js'\n\nexport type { WaitForChange } from './watch-annotations.js'\n\n// Cast helper: our tool results satisfy CallToolResult at runtime; the SDK's\n// inferred type carries an index signature that our narrower types lack.\nfunction cast(p: Promise<{ isError?: boolean; content: Array<{ type: 'text'; text: string }> }>): Promise<CallToolResult> {\n return p as Promise<CallToolResult>\n}\n\nexport function registerTools(\n server: McpServer,\n storage: StorageAdapter,\n opts: { waitForChange: WaitForChange },\n): void {\n server.registerTool(\n 'list_annotations',\n {\n description: 'List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran.',\n inputSchema: listAnnotationsInputSchema.shape,\n },\n (input) => cast(handleListAnnotations(input, storage)),\n )\n\n server.registerTool(\n 'get_annotation',\n {\n description: 'Get full annotation details including source file:line:col, grep search hints, and the AI quality verdict (`qualityCheck`). If qualityCheck.score is \"ambiguous\" or \"unactionable\", the comment may need designer clarification before fixing — consider dismissing with a reason instead of guessing.',\n inputSchema: getAnnotationInputSchema.shape,\n },\n (input) => cast(handleGetAnnotation(input, storage)),\n )\n\n server.registerTool(\n 'acknowledge',\n {\n description: 'Mark an annotation as in-progress (pending → in_progress).',\n inputSchema: acknowledgeInputSchema.shape,\n },\n (input) => cast(handleAcknowledge(input, storage)),\n )\n\n server.registerTool(\n 'claim_fix',\n {\n description: 'Claim a fix for an annotation (→ fixed_unverified). Human verification still required.',\n inputSchema: claimFixInputSchema.shape,\n },\n (input) => cast(handleClaimFix(input, storage)),\n )\n\n server.registerTool(\n 'dismiss',\n {\n description: 'Dismiss an annotation with an optional reason (terminal state).',\n inputSchema: dismissInputSchema.shape,\n },\n (input) => cast(handleDismiss(input, storage)),\n )\n\n server.registerTool(\n 'watch_annotations',\n {\n description:\n 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {\"annotations\": [], \"timedOut\": true}. Call this in a loop to continuously pick up designer feedback. If your environment can run background subagents (e.g. a Task tool), act as a dispatcher: for each returned annotation call acknowledge first (so it stops being redelivered), hand the fix to a background subagent that will claim_fix when done, and return to watch_annotations immediately instead of fixing inline - new feedback must never wait on a fix in progress. Without subagents, acknowledge each annotation before you start fixing it.',\n inputSchema: watchAnnotationsInputSchema.shape,\n },\n (input) => cast(handleWatchAnnotations(input, storage, opts.waitForChange)),\n )\n}\n"],"mappings":";AAAA,SAAS,WAAAA,UAAS,QAAAC,aAAY;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACa9B,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,SAAS,KAAwB,KAAqB;AAC7D,QAAM,IAAI,IAAI,GAAG;AACjB,MAAI,CAAC,KAAK,EAAE,KAAK,MAAM,IAAI;AACzB,UAAM,IAAI,YAAY,6BAA6B,GAAG,EAAE;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAEnB,SAAS,SAAS,KAAmC;AAC1D,QAAM,iBAAiB;AAAA,IACrB,IAAI,sBAAsB,IAAI,uBAAuB,IAAI;AAAA,EAC3D;AAEA,MAAI,gBAAgB;AAClB,UAAM,aAAa,SAAS,KAAK,oBAAoB;AACrD,UAAM,cAAc,SAAS,KAAK,qBAAqB;AACvD,UAAM,kBAAkB,SAAS,KAAK,0BAA0B;AAEhE,QAAI,CAAC,WAAW,WAAW,KAAK,GAAG;AACjC,YAAM,IAAI,YAAY,yFAAyF;AAAA,IACjH;AACA,QAAI,CAAC,YAAY,WAAW,UAAU,GAAG;AACvC,YAAM,IAAI,YAAY,8CAA8C;AAAA,IACtE;AAEA,WAAO,EAAE,MAAM,SAAS,YAAY,aAAa,gBAAgB;AAAA,EACnE;AAEA,QAAM,UAAU,IAAI,eAAe,OAAO,YAAY;AACtD,QAAM,OAAO,OAAO,OAAO;AAC3B,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,UAAM,IAAI,YAAY,4DAA4D,OAAO,GAAG;AAAA,EAC9F;AAEA,SAAO,EAAE,MAAM,SAAS,MAAM,UAAU,IAAI,oBAAoB,kBAAkB;AACpF;;;AC5DA,SAAS,0BAA0B;AAI5B,SAAS,cAAc,QAAqC;AACjE,SAAO,mBAAmB;AAAA,IACxB,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,iBAAiB,OAAO;AAAA,IACxB,SAAS;AAAA,EACX,CAAC;AACH;;;ACXA,SAAS,oBAAoB;AAC7B,SAAS,YAAY,WAAW,cAAc,YAAY,qBAAqB;AAC/E,SAAS,UAAU,SAAS,YAAY;AAQjC,IAAM,qBAAN,MAAmD;AAAA,EAOxD,YAAoB,UAAkB;AAAlB;AALpB;AAAA,eAAM;AACN,SAAQ,UAAU,IAAI,aAAa;AAEnC;AAAA,SAAQ,QAAuB,QAAQ,QAAQ;AAG7C,SAAK,QAAQ,gBAAgB,CAAC;AAAA,EAChC;AAAA,EAEA,MAAM,OAAwC;AAC5C,QAAI,CAAC,WAAW,KAAK,QAAQ,EAAG,QAAO;AACvC,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,aAAa,KAAK,UAAU,MAAM,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAM,IAAI,MAAM,kCAAkC,KAAK,QAAQ,KAAK,OAAO,EAAE;AAAA,IAC/E;AACA,UAAM,QAAQ;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,MAAM,QAAQ,MAAM,WAAW,IAAK,MAAM,cAA+B,CAAC;AAAA,IACzF;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,YAAuC;AAChD,WAAO,KAAK,QAAQ,YAAY;AAC9B,YAAM,QAAS,MAAM,KAAK,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC5E,YAAM,MAAM,MAAM,YAAY,UAAU,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE;AACrE,UAAI,QAAQ,GAAI,OAAM,YAAY,KAAK,UAAU;AAAA,UAC5C,OAAM,YAAY,GAAG,IAAI;AAC9B,WAAK,QAAQ,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,WAAO,KAAK,QAAQ,YAAY;AAC9B,YAAM,QAAS,MAAM,KAAK,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC5E,YAAM,cAAc,MAAM,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/D,WAAK,QAAQ,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAuB;AAC3B,WAAO,KAAK,QAAQ,YAAY;AAC9B,WAAK,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,EAAE,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,QAAQ,IAAwC;AACtD,UAAM,SAAS,KAAK,MAAM,KAAK,EAAE;AAGjC,SAAK,QAAQ,OAAO,MAAM,MAAM,MAAS;AACzC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAc,WAAqC;AACjD,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,WAAW,MAAY;AAC3B,qBAAa,KAAK;AAClB,gBAAQ,IAAI;AAAA,MACd;AACA,YAAM,QAAQ,WAAW,MAAM;AAC7B,aAAK,QAAQ,IAAI,UAAU,QAAQ;AACnC,gBAAQ,KAAK;AAAA,MACf,GAAG,SAAS;AACZ,WAAK,QAAQ,KAAK,UAAU,QAAQ;AAAA,IACtC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,UAA4B;AACnC,SAAK,QAAQ,GAAG,UAAU,QAAQ;AAAA,EACpC;AAAA,EAEQ,QAAQ,OAA8B;AAC5C,UAAM,MAAM,QAAQ,KAAK,QAAQ;AACjC,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGlC,QAAI,SAAS,GAAG,MAAM,WAAW;AAC/B,YAAM,YAAY,KAAK,KAAK,YAAY;AACxC,UAAI,CAAC,WAAW,SAAS,EAAG,eAAc,WAAW,KAAK;AAAA,IAC5D;AACA,UAAM,MAAM,GAAG,KAAK,QAAQ;AAC5B,kBAAc,KAAK,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACjD,eAAW,KAAK,KAAK,QAAQ;AAC7B,SAAK;AACL,SAAK,QAAQ,KAAK,QAAQ;AAAA,EAC5B;AACF;;;ACzGA,YAAY,UAAU;AAItB,IAAM,eAAuC;AAAA,EAC3C,+BAA+B;AAAA,EAC/B,gCAAgC;AAAA,EAChC,gCAAgC;AAClC;AAEA,IAAM,iBAAiB,OAAO;AAE9B,SAAS,KAAK,KAAqB,QAAgB,MAAqB;AACtE,MAAI,UAAU,QAAQ,EAAE,GAAG,cAAc,gBAAgB,mBAAmB,CAAC;AAC7E,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAEA,SAAS,SAAS,KAAuC;AACvD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,OAAO;AACX,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,cAAQ,MAAM;AACd,UAAI,OAAO,gBAAgB;AACzB,eAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,YAAI,QAAQ;AACZ;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,QAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC,CAAC;AACnE,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEA,eAAe,OAAO,KAAsB,KAAqB,SAA4C;AAC3G,MAAI,IAAI,WAAW,WAAW;AAC5B,QAAI,UAAU,KAAK,YAAY;AAC/B,QAAI,IAAI;AACR;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB,EAAE;AAC7D,QAAM,WAAW,SAAS,MAAM,0BAA0B;AAE1D,MAAI;AACF,QAAI,IAAI,WAAW,SAAS,aAAa,UAAU;AAKjD,YAAM,MAAM,QAAQ;AACpB,YAAM,QAAS,MAAM,QAAQ,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC/E,WAAK,KAAK,KAAK,EAAE,KAAK,MAAM,CAAC;AAC7B;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,SAAS,UAAU;AACpC,YAAM,KAAK,mBAAmB,SAAS,CAAC,CAAC;AACzC,UAAI;AACJ,UAAI;AACF,qBAAa,KAAK,MAAM,MAAM,SAAS,GAAG,CAAC;AAAA,MAC7C,QAAQ;AACN,aAAK,KAAK,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAC7C;AAAA,MACF;AACA,UAAI,CAAC,cAAc,WAAW,OAAO,IAAI;AACvC,aAAK,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAC/D;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,UAAmB;AACtC,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,YAAY,UAAU;AACvC,YAAM,QAAQ,OAAO,mBAAmB,SAAS,CAAC,CAAC,CAAC;AACpD,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,YAAY,aAAa,gBAAgB;AAC1D,YAAM,QAAQ,MAAM;AACpB,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,SAAK,KAAK,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,EACvC,SAAS,KAAK;AACZ,SAAK,KAAK,KAAK,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,EAC5E;AACF;AAGO,SAAS,gBAAgB,SAA6B,MAAoC;AAC/F,QAAM,SAAc,kBAAa,CAAC,KAAK,QAAQ;AAC7C,SAAK,OAAO,KAAK,KAAK,OAAO;AAAA,EAC/B,CAAC;AACD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC;AAAA,EACxD,CAAC;AACH;;;ACvGA,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,aAAa,YAAY,iBAAAC,sBAAqB;AAC5F,SAAS,QAAAC,aAAY;AAErB,SAAS,gBAAgB,2BAA2B;AAGpD,SAAS,WAAW,OAAuB;AACzC,SAAO,KAAK,UAAU,KAAK;AAC7B;AAOO,SAAS,eAAe,YAAgC;AAE7D,QAAM,QAAQ,oBAAoB,CAAC,UAAU,GAAG,WAAW,cAAc,EAAE,YAAY,CAAC;AACxF,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,OAAO,WAAW,MAAM,EAAE,CAAC,EAAE;AACxC,QAAM,KAAK,UAAU,WAAW,MAAM,KAAK,CAAC,EAAE;AAC9C,QAAM,KAAK,WAAW,MAAM,MAAM,EAAE;AACpC,QAAM,KAAK,mBAAmB,WAAW,cAAc,EAAE;AACzD,MAAI,WAAW,aAAc,OAAM,KAAK,YAAY,WAAW,aAAa,KAAK,EAAE;AACnF,QAAM,KAAK,OAAO,EAAE;AAEpB,QAAM,KAAK,2BAA2B,MAAM,EAAE,IAAI,EAAE;AACpD,QAAM,KAAK,cAAc,IAAI,MAAM,QAAQ,KAAK,GAAG,EAAE;AAErD,QAAM,KAAK,cAAc,EAAE;AAC3B,QAAM,KAAK,YAAY,MAAM,YAAY,OAAO,IAAI;AACpD,QAAM,KAAK,YAAY,MAAM,YAAY,UAAU,IAAI;AACvD,MAAI,MAAM,QAAQ;AAChB,UAAM,YAAY,MAAM,OAAO,YAAY,iBAAiB,MAAM,OAAO,SAAS,QAAQ;AAC1F,UAAM,KAAK,eAAe,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,MAAM,KAAK,SAAS,EAAE;AAAA,EACzG;AACA,MAAI,MAAM,YAAY,QAAQ,QAAQ;AACpC,UAAM,KAAK,cAAc,MAAM,YAAY,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE;AAAA,EACvF;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,MAAM,YAAY,YAAY,QAAQ;AACxC,UAAM,KAAK,mBAAmB,EAAE;AAChC,eAAW,KAAK,MAAM,YAAY,aAAa;AAC7C,YAAM,KAAK,MAAM,EAAE,UAAU,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,IAAI;AAAA,IAClE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,WAAW;AACtB,MAAI,MAAM,GAAG,UAAU,SAAS;AAC9B,UAAM,KAAK,oBAAoB,EAAE;AACjC,UAAM,KAAK,cAAc,GAAG,KAAK,sIAAsI,EAAE;AACzK,eAAW,SAAS,GAAG,OAAQ,OAAM,KAAK,YAAY,KAAK,EAAE;AAC7D,eAAW,KAAK,GAAG,oBAAqB,OAAM,KAAK,oBAAoB,CAAC,EAAE;AAC1E,QAAI,GAAG,iBAAkB,OAAM,KAAK,wBAAwB,GAAG,gBAAgB,EAAE;AACjF,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,yBAAyB,EAAE;AACtC,QAAM,KAAK,wFAAwF,WAAW,MAAM,EAAE,CAAC,4EAA4E;AACnM,QAAM,KAAK,4CAA4C;AACvD,QAAM,KAAK,uFAAuF,WAAW,MAAM,EAAE,CAAC,2EAA2E;AACjM,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uMAAuM;AAClN,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;AAOO,IAAM,aAAN,MAAiB;AAAA,EAItB,YACU,SACA,KACR;AAFQ;AACA;AALV,SAAQ,UAAU;AAClB,SAAQ,QAAQ;AAAA,EAKb;AAAA;AAAA,EAGH,MAAM,OAAsB;AAC1B,UAAM,QAAQ,MAAM,KAAK,QAAQ,KAAK;AACtC,UAAM,aAAa,eAAe,OAAO,eAAe,CAAC,CAAC;AAC1D,UAAM,UAAU,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC;AAEhF,IAAAH,WAAU,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,eAAW,QAAQ,YAAY,KAAK,GAAG,GAAG;AACxC,UAAI,KAAK,SAAS,KAAK,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAG,YAAWG,MAAK,KAAK,KAAK,IAAI,CAAC;AAAA,IACjF;AACA,eAAW,CAAC,MAAM,OAAO,KAAK,SAAS;AACrC,YAAM,OAAOA,MAAK,KAAK,KAAK,IAAI;AAChC,UAAIJ,YAAW,IAAI,KAAKE,cAAa,MAAM,MAAM,MAAM,QAAS;AAChE,MAAAC,eAAc,MAAM,OAAO;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA,EAGA,WAAiB;AACf,SAAK,QAAQ;AACb,SAAK,KAAK,IAAI;AAAA,EAChB;AAAA,EAEA,MAAc,MAAqB;AACjC,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf,WAAO,KAAK,OAAO;AACjB,WAAK,QAAQ;AACb,UAAI;AACF,cAAM,KAAK,KAAK;AAAA,MAClB,SAAS,KAAK;AACZ,gBAAQ,MAAM,6CAA6C,GAAG;AAAA,MAChE;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB;AACF;;;AC1HA,SAAS,SAAS;;;ACiBX,SAAS,UAAU,MAAqB,SAAiB,SAAoD;AAClH,QAAM,UAA4B,EAAE,MAAM,SAAS,QAAQ;AAC3D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,EAAE,CAAC;AAAA,EAC3D;AACF;AAOO,SAAS,YAAY,OAAmC;AAC7D,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,EAAE,CAAC;AAAA,EACzD;AACF;;;AD9BA,IAAM,gBAAgB,CAAC,SAAS,WAAW,eAAe,oBAAoB,YAAY,WAAW;AAE9F,IAAM,6BAA6B,EAAE,OAAO;AAAA,EACjD,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,aAAa,GAAG,EAAE,MAAM,EAAE,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,EAClF,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC1C,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AACnD,CAAC;AAeD,SAAS,YAAY,YAAkD;AACrE,QAAM,KAAK,WAAW;AACtB,QAAM,MAAM,GAAG,kBAAkB,GAAG;AACpC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,SAAS,MAAM,IAAI,GAAI,EAAE;AACxC,QAAM,OAAO,SAAS,MAAM,IAAI,GAAI,EAAE;AACtC,QAAM,OAAO,MAAM,KAAK,GAAG;AAC3B,MAAI,CAAC,QAAQ,MAAM,IAAI,EAAG,QAAO;AACjC,QAAM,YAAY,GAAG,iBAAiB,GAAG,qBAAqB;AAC9D,SAAO,EAAE,MAAM,MAAM,QAAQ,MAAM,MAAM,IAAI,IAAI,QAAQ,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AAC/F;AAEO,SAAS,OAAO,GAA+B;AACpD,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,OAAO,EAAE;AAAA,IACT,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,UAAU,EAAE;AAAA,IACZ,WAAW,EAAE;AAAA,IACb,QAAQ,YAAY,CAAC;AAAA,IACrB,GAAI,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,MAAM,IAAI,CAAC;AAAA,EAC5D;AACF;AAEA,eAAsB,sBAAsB,OAA6B,SAAyB;AAChG,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,MAAM,OAAO,eAAe,CAAC;AAEnC,QAAM,eAAe,MAAM,QAAQ,MAAM,MAAM,IAC3C,IAAI,IAAI,MAAM,MAAM,IACpB,MAAM,SACN,oBAAI,IAAI,CAAC,MAAM,MAAM,CAAC,IACtB;AAEJ,QAAM,WAAW,IAAI,OAAO,CAAC,MAAM;AACjC,QAAI,MAAM,UAAU,UAAa,EAAE,UAAU,MAAM,MAAO,QAAO;AACjE,QAAI,gBAAgB,CAAC,aAAa,IAAI,EAAE,MAAM,EAAG,QAAO;AACxD,QAAI,MAAM,mBAAmB,UAAa,EAAE,mBAAmB,MAAM,eAAgB,QAAO;AAC5F,QAAI,MAAM,SAAS,QAAW;AAC5B,YAAM,MAAM,EAAE,YAAY,kBAAkB,EAAE,YAAY,kBAAkB;AAC5E,UAAI,CAAC,IAAI,SAAS,MAAM,IAAI,EAAG,QAAO;AAAA,IACxC;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,UAAU,SAAS,MAAM,GAAG,KAAK,EAAE,IAAI,MAAM;AAEnD,SAAO,YAAY,EAAE,aAAa,SAAS,OAAO,SAAS,OAAO,CAAC;AACrE;;;AEpFA,SAAS,KAAAE,UAAS;AAElB,SAAS,uBAAAC,4BAA2B;AAG7B,IAAM,2BAA2BC,GAAE,OAAO;AAAA,EAC/C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,oBAAoB,OAA2B,SAAyB;AAC5F,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAIA,QAAM,cAAcC,qBAAoB,CAAC,UAAU,GAAG,WAAW,cAAc;AAC/E,QAAM,kBAAkB,YAAY,YAAY,CAAC;AAEjD,SAAO,YAAY,eAAe;AACpC;;;AC7BA,SAAS,KAAAC,UAAS;AAElB,SAAS,YAAY,8BAA8B;AAG5C,IAAM,yBAAyBC,GAAE,OAAO;AAAA,EAC7C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,kBAAkB,OAAyB,SAAyB;AACxF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,WAAW,YAAY,eAAe,EAAE,OAAO,QAAQ,CAAC;AAAA,EACnE,SAAS,KAAK;AACZ,QAAI,eAAe,wBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;ACjDA,SAAS,KAAAC,UAAS;AAElB,SAAS,cAAAC,aAAY,0BAAAC,+BAA8B;AAG5C,IAAM,sBAAsBC,GAAE,OAAO;AAAA,EAC1C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,eAAe,OAAsB,SAAyB;AAClF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAASC,YAAW,YAAY,YAAY,EAAE,OAAO,QAAQ,CAAC;AAAA,EAChE,SAAS,KAAK;AACZ,QAAI,eAAeC,yBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;ACjDA,SAAS,KAAAC,UAAS;AAElB,SAAS,cAAAC,aAAY,0BAAAC,+BAA8B;AAG5C,IAAM,qBAAqBC,GAAE,OAAO;AAAA,EACzC,IAAIA,GAAE,OAAO;AAAA,EACb,QAAQA,GAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAID,eAAsB,cAAc,OAAqB,SAAyB;AAChF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAASC,YAAW,YAAY,WAAW,EAAE,OAAO,SAAS,QAAQ,MAAM,OAAO,CAAC;AAAA,EACrF,SAAS,KAAK;AACZ,QAAI,eAAeC,yBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;AClDA,SAAS,KAAAC,UAAS;AASlB,IAAM,0BAA0B;AAEzB,IAAM,8BAA8BC,GAAE,OAAO;AAAA,EAClD,gBAAgBA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAC5D,CAAC;AAID,eAAsB,uBACpB,OACA,SACA,eACA;AACA,QAAM,aAAa,MAAM,kBAAkB,2BAA2B;AACtE,QAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,aAAS;AACP,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,KAAK;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACpF;AAEA,UAAM,WAAW,OAAO,eAAe,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC/E,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,YAAY,EAAE,aAAa,QAAQ,IAAI,MAAM,GAAG,OAAO,QAAQ,QAAQ,UAAU,MAAM,CAAC;AAAA,IACjG;AAEA,UAAM,YAAY,WAAW,KAAK,IAAI;AACtC,QAAI,aAAa,GAAG;AAClB,aAAO,YAAY,EAAE,aAAa,CAAC,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAAA,IAClE;AAEA,UAAM,cAAc,SAAS;AAAA,EAC/B;AACF;;;AC9BA,SAAS,KAAK,GAA4G;AACxH,SAAO;AACT;AAEO,SAAS,cACd,QACA,SACA,MACM;AACN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,2BAA2B;AAAA,IAC1C;AAAA,IACA,CAAC,UAAU,KAAK,sBAAsB,OAAO,OAAO,CAAC;AAAA,EACvD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,yBAAyB;AAAA,IACxC;AAAA,IACA,CAAC,UAAU,KAAK,oBAAoB,OAAO,OAAO,CAAC;AAAA,EACrD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,uBAAuB;AAAA,IACtC;AAAA,IACA,CAAC,UAAU,KAAK,kBAAkB,OAAO,OAAO,CAAC;AAAA,EACnD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,oBAAoB;AAAA,IACnC;AAAA,IACA,CAAC,UAAU,KAAK,eAAe,OAAO,OAAO,CAAC;AAAA,EAChD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,mBAAmB;AAAA,IAClC;AAAA,IACA,CAAC,UAAU,KAAK,cAAc,OAAO,OAAO,CAAC;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa,4BAA4B;AAAA,IAC3C;AAAA,IACA,CAAC,UAAU,KAAK,uBAAuB,OAAO,SAAS,KAAK,aAAa,CAAC;AAAA,EAC5E;AACF;;;AbnEA,IAAM,gBAAgB;AAEtB,eAAe,OAAsB;AACnC,MAAI;AACJ,MAAI;AACF,aAAS,SAAS,QAAQ,GAAG;AAAA,EAC/B,SAAS,KAAK;AACZ,QAAI,eAAe,aAAa;AAC9B,cAAQ,MAAM,kCAAkC,IAAI,OAAO,EAAE;AAC7D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AAEA,MAAI;AACJ,MAAI;AAEJ,MAAI,OAAO,SAAS,SAAS;AAC3B,UAAM,UAAU,IAAI,mBAAmB,OAAO,QAAQ;AACtD,UAAM,aAAa,IAAI,WAAW,SAASC,MAAKC,SAAQ,OAAO,QAAQ,GAAG,OAAO,CAAC;AAClF,YAAQ,SAAS,MAAM,WAAW,SAAS,CAAC;AAC5C,eAAW,SAAS;AACpB,UAAM,gBAAgB,SAAS,OAAO,IAAI;AAC1C,YAAQ;AAAA,MACN,uEAAkE,OAAO,IAAI,WAAW,OAAO,QAAQ;AAAA,IACzG;AACA,cAAU;AACV,oBAAgB,CAAC,OAAO,QAAQ,cAAc,EAAE;AAAA,EAClD,OAAO;AACL,cAAU,cAAc,MAAM;AAC9B,oBAAgB,CAAC,OACf,IAAI,QAAQ,CAAC,YAAY,WAAW,MAAM,QAAQ,KAAK,GAAG,KAAK,IAAI,IAAI,aAAa,CAAC,CAAC;AAAA,EAC1F;AAEA,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAED,gBAAc,QAAQ,SAAS,EAAE,cAAc,CAAC;AAEhD,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,2BAA2B,GAAG;AAC5C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["dirname","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","z","generateAgentExport","z","generateAgentExport","z","z","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","z","join","dirname"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/config.ts","../src/storage-factory.ts","../src/file-storage-adapter.ts","../src/http-server.ts","../src/task-folder.ts","../src/prompts.ts","../src/tools/list-annotations.ts","../src/errors.ts","../src/tools/get-annotation.ts","../src/tools/acknowledge.ts","../src/tools/claim-fix.ts","../src/tools/dismiss.ts","../src/tools/watch-annotations.ts","../src/tools/index.ts"],"sourcesContent":["import { dirname, join } from 'node:path'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport type { StorageAdapter } from 'web-remarq'\nimport { parseEnv, ConfigError } from './config.js'\nimport { createStorage } from './storage-factory.js'\nimport { FileStorageAdapter } from './file-storage-adapter.js'\nimport { startHttpServer } from './http-server.js'\nimport { TaskFolder } from './task-folder.js'\nimport { registerPrompts } from './prompts.js'\nimport { registerTools, type WaitForChange } from './tools/index.js'\n\nconst CLOUD_POLL_MS = 3000\n\nasync function main(): Promise<void> {\n let config\n try {\n config = parseEnv(process.env)\n } catch (err) {\n if (err instanceof ConfigError) {\n console.error(`[web-remarq-mcp] config error: ${err.message}`)\n process.exit(1)\n }\n throw err\n }\n\n let storage: StorageAdapter\n let waitForChange: WaitForChange\n\n if (config.mode === 'local') {\n const adapter = new FileStorageAdapter(config.dataFile)\n const tasksDir = join(dirname(config.dataFile), 'tasks')\n const taskFolder = new TaskFolder(adapter, tasksDir)\n adapter.onChange(() => taskFolder.schedule())\n taskFolder.schedule() // project existing annotations on startup\n await startHttpServer(adapter, config.port)\n console.error(\n `[web-remarq-mcp] local mode — widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}, tasks ${tasksDir}`,\n )\n storage = adapter\n waitForChange = (ms) => adapter.waitForChange(ms)\n } else {\n storage = createStorage(config)\n waitForChange = (ms) =>\n new Promise((resolve) => setTimeout(() => resolve(false), Math.min(ms, CLOUD_POLL_MS)))\n }\n\n const server = new McpServer({\n name: 'web-remarq',\n version: '0.4.0',\n })\n\n registerTools(server, storage, { waitForChange })\n registerPrompts(server)\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\nmain().catch((err) => {\n console.error('[web-remarq-mcp] fatal:', err)\n process.exit(1)\n})\n","export interface CloudConfig {\n mode: 'cloud'\n projectKey: string\n supabaseUrl: string\n supabaseAnonKey: string\n}\n\nexport interface LocalConfig {\n mode: 'local'\n port: number\n dataFile: string\n}\n\nexport type MCPConfig = CloudConfig | LocalConfig\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ConfigError'\n }\n}\n\nfunction require_(env: NodeJS.ProcessEnv, key: string): string {\n const v = env[key]\n if (!v || v.trim() === '') {\n throw new ConfigError(`Missing required env var: ${key}`)\n }\n return v\n}\n\nconst DEFAULT_PORT = 1817\nconst DEFAULT_DATA_FILE = '.remarq/annotations.json'\n\nexport function parseEnv(env: NodeJS.ProcessEnv): MCPConfig {\n const cloudRequested = Boolean(\n env.REMARQ_PROJECT_KEY || env.REMARQ_SUPABASE_URL || env.REMARQ_SUPABASE_ANON_KEY,\n )\n\n if (cloudRequested) {\n const projectKey = require_(env, 'REMARQ_PROJECT_KEY')\n const supabaseUrl = require_(env, 'REMARQ_SUPABASE_URL')\n const supabaseAnonKey = require_(env, 'REMARQ_SUPABASE_ANON_KEY')\n\n if (!projectKey.startsWith('pk_')) {\n throw new ConfigError('REMARQ_PROJECT_KEY must start with `pk_` (generated by `npx @web-remarq/cloud gen-key`)')\n }\n if (!supabaseUrl.startsWith('https://')) {\n throw new ConfigError('REMARQ_SUPABASE_URL must start with https://')\n }\n\n return { mode: 'cloud', projectKey, supabaseUrl, supabaseAnonKey }\n }\n\n const rawPort = env.REMARQ_PORT ?? String(DEFAULT_PORT)\n const port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`REMARQ_PORT must be an integer between 1 and 65535, got \"${rawPort}\"`)\n }\n\n return { mode: 'local', port, dataFile: env.REMARQ_DATA_FILE ?? DEFAULT_DATA_FILE }\n}\n","import { createCloudStorage } from '@web-remarq/cloud'\nimport type { StorageAdapter } from 'web-remarq'\nimport type { CloudConfig } from './config'\n\nexport function createStorage(config: CloudConfig): StorageAdapter {\n return createCloudStorage({\n projectKey: config.projectKey,\n supabaseUrl: config.supabaseUrl,\n supabaseAnonKey: config.supabaseAnonKey,\n onError: 'throw',\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport type { Annotation, AnnotationStore, StorageAdapter } from 'web-remarq'\n\n/**\n * Local-mode StorageAdapter over a JSON file (default .remarq/annotations.json).\n * All mutations flow through this process (MCP tools + the local HTTP server),\n * so change notification is a plain in-memory emitter — no fs.watch needed.\n */\nexport class FileStorageAdapter implements StorageAdapter {\n /** Monotonic revision — bumps on every mutation. Exposed via GET /store. */\n rev = 0\n private emitter = new EventEmitter()\n /** Serializes mutations (save/remove/clear) so concurrent read-modify-write ops don't clobber each other. */\n private queue: Promise<void> = Promise.resolve()\n\n constructor(private filePath: string) {\n this.emitter.setMaxListeners(0)\n }\n\n async load(): Promise<AnnotationStore | null> {\n if (!existsSync(this.filePath)) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(this.filePath, 'utf8'))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`annotations store corrupted at ${this.filePath}: ${message}`)\n }\n const store = parsed as { annotations?: unknown }\n return {\n version: 1,\n annotations: Array.isArray(store.annotations) ? (store.annotations as Annotation[]) : [],\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n const idx = store.annotations.findIndex((a) => a.id === annotation.id)\n if (idx === -1) store.annotations.push(annotation)\n else store.annotations[idx] = annotation\n this.persist(store)\n })\n }\n\n async remove(id: string): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n store.annotations = store.annotations.filter((a) => a.id !== id)\n this.persist(store)\n })\n }\n\n async clear(): Promise<void> {\n return this.enqueue(async () => {\n this.persist({ version: 1, annotations: [] })\n })\n }\n\n /** Chains `op` onto the mutation queue; a rejected op doesn't poison later ops. */\n private enqueue(op: () => Promise<void>): Promise<void> {\n const result = this.queue.then(op)\n // Swallow the rejection on the shared chain so the next enqueued op still runs;\n // the caller's own `result` promise still rejects with the original error.\n this.queue = result.catch(() => undefined)\n return result\n }\n\n /** Resolves true on the next mutation, false after timeoutMs. */\n waitForChange(timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const onChange = (): void => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n this.emitter.off('change', onChange)\n resolve(false)\n }, timeoutMs)\n this.emitter.once('change', onChange)\n })\n }\n\n /** Persistent listener for every mutation (save/remove/clear). */\n onChange(listener: () => void): void {\n this.emitter.on('change', listener)\n }\n\n private persist(store: AnnotationStore): void {\n const dir = dirname(this.filePath)\n mkdirSync(dir, { recursive: true })\n // Auto-ignore the store when it lives in the conventional .remarq dir.\n // NEVER write a wildcard .gitignore into an arbitrary user directory.\n if (basename(dir) === '.remarq') {\n const gitignore = join(dir, '.gitignore')\n if (!existsSync(gitignore)) writeFileSync(gitignore, '*\\n')\n }\n const tmp = `${this.filePath}.tmp`\n writeFileSync(tmp, JSON.stringify(store, null, 2))\n renameSync(tmp, this.filePath)\n this.rev++\n this.emitter.emit('change')\n }\n}\n","import * as http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { FileStorageAdapter } from './file-storage-adapter.js'\nimport { isSafeAnnotationId } from './task-folder.js'\n\nconst CORS_HEADERS: Record<string, string> = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'content-type',\n}\n\nconst MAX_BODY_BYTES = 1024 * 1024\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { ...CORS_HEADERS, 'content-type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_BODY_BYTES) {\n reject(new Error('body too large'))\n req.destroy()\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\nasync function handle(req: IncomingMessage, res: ServerResponse, storage: FileStorageAdapter): Promise<void> {\n if (req.method === 'OPTIONS') {\n res.writeHead(204, CORS_HEADERS)\n res.end()\n return\n }\n\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n const annMatch = pathname.match(/^\\/annotations\\/([^/]+)$/)\n\n try {\n if (req.method === 'GET' && pathname === '/store') {\n // Capture rev before the await, not after: a concurrent mutation between\n // load() and reading storage.rev would pair a newer rev with the older\n // content this response body carries. Under-reporting is safe (the\n // client's next poll re-diffs); over-reporting is not.\n const rev = storage.rev\n const store = (await storage.load()) ?? { version: 1 as const, annotations: [] }\n json(res, 200, { rev, store })\n return\n }\n\n if (req.method === 'PUT' && annMatch) {\n const id = decodeURIComponent(annMatch[1])\n if (!isSafeAnnotationId(id)) {\n json(res, 400, { error: 'invalid annotation id' })\n return\n }\n let annotation: { id?: unknown }\n try {\n annotation = JSON.parse(await readBody(req))\n } catch {\n json(res, 400, { error: 'invalid JSON body' })\n return\n }\n if (!annotation || annotation.id !== id) {\n json(res, 400, { error: 'annotation.id must match the URL id' })\n return\n }\n // The store is trusted local input from the widget; no schema validation.\n await storage.save(annotation as never)\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && annMatch) {\n const id = decodeURIComponent(annMatch[1])\n if (!isSafeAnnotationId(id)) {\n json(res, 400, { error: 'invalid annotation id' })\n return\n }\n await storage.remove(id)\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && pathname === '/annotations') {\n await storage.clear()\n json(res, 200, { rev: storage.rev })\n return\n }\n\n json(res, 404, { error: 'not found' })\n } catch (err) {\n json(res, 500, { error: err instanceof Error ? err.message : String(err) })\n }\n}\n\n/** Starts the widget-facing endpoint on 127.0.0.1:port. Rejects on bind errors. */\nexport function startHttpServer(storage: FileStorageAdapter, port: number): Promise<http.Server> {\n const server = http.createServer((req, res) => {\n void handle(req, res, storage)\n })\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', () => resolve(server))\n })\n}\n","import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { Annotation, StorageAdapter } from 'web-remarq'\nimport { actionableOnly, generateAgentExport } from 'web-remarq/core'\n\n/** Double-quoted YAML scalar; JSON string escaping is valid YAML. */\nfunction yamlString(value: string): string {\n return JSON.stringify(value)\n}\n\n/**\n * Annotation ids become `<id>.md` filenames under a server-owned directory.\n * Ids normally come from core (filename-safe by construction) but the widget\n * HTTP endpoint accepts arbitrary strings, so both the file projection and\n * the HTTP layer must reject anything that isn't a plain filename segment\n * (no path separators, no leading dot, no traversal).\n */\nexport function isSafeAnnotationId(id: string): boolean {\n return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(id)\n}\n\n/**\n * Renders one annotation as a ticket file for .remarq/tasks/.\n * Deterministic: TaskFolder diffs the output against the file on disk\n * to skip no-op rewrites.\n */\nexport function renderTaskFile(annotation: Annotation): string {\n // Reuse core agent-export for source resolution + search hints (same pattern as get_annotation).\n const agent = generateAgentExport([annotation], annotation.viewportBucket).annotations[0]\n const lines: string[] = []\n\n lines.push('---')\n lines.push(`id: ${yamlString(agent.id)}`)\n lines.push(`route: ${yamlString(agent.route)}`)\n lines.push(`status: ${agent.status}`)\n lines.push(`viewportBucket: ${annotation.viewportBucket}`)\n if (annotation.qualityCheck) lines.push(`quality: ${annotation.qualityCheck.score}`)\n lines.push('---', '')\n\n lines.push(`# web-remarq annotation ${agent.id}`, '')\n lines.push('## Comment', '', agent.comment.trim(), '')\n\n lines.push('## Element', '')\n lines.push(`- Tag: \\`${agent.searchHints.tagName}\\``)\n lines.push(`- DOM: \\`${agent.searchHints.domContext}\\``)\n if (agent.source) {\n const component = agent.source.component ? ` (component \\`${agent.source.component}\\`)` : ''\n lines.push(`- Source: \\`${agent.source.file}:${agent.source.line}:${agent.source.column}\\`${component}`)\n }\n if (agent.searchHints.classes.length) {\n lines.push(`- Classes: ${agent.searchHints.classes.map((c) => `\\`${c}\\``).join(' ')}`)\n }\n lines.push('')\n\n if (agent.searchHints.grepQueries.length) {\n lines.push('## Search hints', '')\n for (const q of agent.searchHints.grepQueries) {\n lines.push(`- [${q.confidence}] \\`${q.query}\\` in \\`${q.glob}\\``)\n }\n lines.push('')\n }\n\n const qc = annotation.qualityCheck\n if (qc && qc.score !== 'clear') {\n lines.push('## Quality check', '')\n lines.push(`Verdict: **${qc.score}** - this comment may need designer clarification; if you cannot act on it confidently, dismiss with a reason instead of guessing.`, '')\n for (const issue of qc.issues) lines.push(`- Issue: ${issue}`)\n for (const q of qc.clarifyingQuestions) lines.push(`- Open question: ${q}`)\n if (qc.suggestedRewrite) lines.push(`- Suggested rewrite: ${qc.suggestedRewrite}`)\n lines.push('')\n }\n\n lines.push('## Agent instructions', '')\n lines.push(`1. BEFORE touching code, call the web-remarq MCP tool \\`acknowledge\\` with \\`{ \"id\": ${yamlString(agent.id)} }\\`. If it errors, another agent already owns this task - skip this file.`)\n lines.push('2. Apply the fix described in the comment.')\n lines.push(`3. When the fix is committed to the working tree, call \\`claim_fix\\` with \\`{ \"id\": ${yamlString(agent.id)} }\\`. A human verifies afterwards - never mark anything as done yourself.`)\n lines.push('')\n lines.push('This file is a live projection maintained by the web-remarq MCP server: it updates when the annotation changes and disappears once the annotation is verified or dismissed. Do not edit or delete it.')\n lines.push('')\n\n return lines.join('\\n')\n}\n\n/**\n * Live projection of actionable annotations (pending/in_progress) into a\n * folder of <id>.md ticket files. The folder is server-owned: every *.md in\n * it is managed - stale ones are deleted on sync. Non-md files are ignored.\n */\nexport class TaskFolder {\n private syncing = false\n private dirty = false\n\n constructor(\n private storage: Pick<StorageAdapter, 'load'>,\n private dir: string,\n ) {}\n\n /** Full idempotent resync: folder contents converge to the actionable set. */\n async sync(): Promise<void> {\n const store = await this.storage.load()\n const actionable = actionableOnly(store?.annotations ?? [])\n const desired = new Map<string, string>()\n for (const a of actionable) {\n if (!isSafeAnnotationId(a.id)) {\n console.error(`[web-remarq-mcp] skipping annotation with unsafe id: ${JSON.stringify(a.id)}`)\n continue\n }\n desired.set(`${a.id}.md`, renderTaskFile(a))\n }\n\n mkdirSync(this.dir, { recursive: true })\n for (const entry of readdirSync(this.dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith('.md') || desired.has(entry.name)) continue\n try {\n unlinkSync(join(this.dir, entry.name))\n } catch (err) {\n console.error(`[web-remarq-mcp] failed to remove stale task file ${entry.name}:`, err)\n }\n }\n for (const [name, content] of desired) {\n try {\n const path = join(this.dir, name)\n if (existsSync(path) && readFileSync(path, 'utf8') === content) continue\n writeFileSync(path, content)\n } catch (err) {\n console.error(`[web-remarq-mcp] failed to write task file ${name}:`, err)\n }\n }\n }\n\n /** Coalesces change bursts: at most one sync in flight, one more queued. Never throws. */\n schedule(): void {\n this.dirty = true\n void this.run()\n }\n\n private async run(): Promise<void> {\n if (this.syncing) return\n this.syncing = true\n while (this.dirty) {\n this.dirty = false\n try {\n await this.sync()\n } catch (err) {\n console.error('[web-remarq-mcp] task folder sync failed:', err)\n }\n }\n this.syncing = false\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\n/**\n * The \"agent on duty\" dispatcher prompt, exposed via MCP prompts so clients\n * that support them (Claude Code renders it as /mcp__web-remarq__watch)\n * don't need the copy-paste block from the README.\n * Keep the text in sync with the README's \"Parallel mode\" section.\n */\nexport const DUTY_PROMPT =\n 'You are on annotation duty for this project. Designers drop feedback via ' +\n 'the web-remarq MCP server. Run this loop until told to stop: call ' +\n 'watch_annotations (timeoutSeconds: 60); if it times out, call it again. ' +\n 'For EACH annotation it returns, call acknowledge with its id first. Then, ' +\n 'if you can run background subagents, dispatch one that applies the fix to ' +\n 'the project files and calls claim_fix when done - do not fix anything ' +\n 'yourself in the main loop and do not wait for subagents, go straight back ' +\n 'to watch_annotations so new feedback is never missed. Without background ' +\n 'subagents, apply the fix inline after acknowledging, then return to ' +\n 'watch_annotations. If a comment is ambiguous or unactionable, dismiss it ' +\n 'with a reason instead of guessing.'\n\nexport function registerPrompts(server: McpServer): void {\n server.registerPrompt(\n 'watch',\n {\n title: 'Annotation duty (dispatcher loop)',\n description:\n 'Put this agent on annotation duty: loop on watch_annotations, acknowledge each annotation first, hand the fix to a background subagent that calls claim_fix, return to watching immediately.',\n },\n () => ({\n messages: [{ role: 'user' as const, content: { type: 'text' as const, text: DUTY_PROMPT } }],\n }),\n )\n}\n","import { z } from 'zod'\nimport type { Annotation, AnnotationStatus, QualityCheck, StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\n\nconst STATUS_VALUES = ['draft', 'pending', 'in_progress', 'fixed_unverified', 'verified', 'dismissed'] as const\n\nexport const listAnnotationsInputSchema = z.object({\n route: z.string().optional(),\n status: z.union([z.enum(STATUS_VALUES), z.array(z.enum(STATUS_VALUES))]).optional(),\n viewportBucket: z.number().int().optional(),\n file: z.string().optional(),\n limit: z.number().int().min(1).max(200).optional(),\n})\n\nexport type ListAnnotationsInput = z.infer<typeof listAnnotationsInputSchema>\n\nexport interface ThinAnnotation {\n id: string\n route: string\n comment: string\n status: AnnotationStatus\n viewport: number\n timestamp: number\n source: { file: string; line: number; column: number; component?: string } | null\n quality?: QualityCheck['score']\n}\n\nfunction parseSource(annotation: Annotation): ThinAnnotation['source'] {\n const fp = annotation.fingerprint\n const raw = fp.sourceLocation ?? fp.detectedSource\n if (!raw) return null\n const parts = raw.split(':')\n if (parts.length < 2) return null\n const column = parseInt(parts.pop()!, 10)\n const line = parseInt(parts.pop()!, 10)\n const file = parts.join(':')\n if (!file || isNaN(line)) return null\n const component = fp.componentName ?? fp.detectedComponent ?? undefined\n return { file, line, column: isNaN(column) ? 0 : column, ...(component ? { component } : {}) }\n}\n\nexport function toThin(a: Annotation): ThinAnnotation {\n return {\n id: a.id,\n route: a.route,\n comment: a.comment,\n status: a.status,\n viewport: a.viewportBucket,\n timestamp: a.timestamp,\n source: parseSource(a),\n ...(a.qualityCheck ? { quality: a.qualityCheck.score } : {}),\n }\n}\n\nexport async function handleListAnnotations(input: ListAnnotationsInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const all = store?.annotations ?? []\n\n const statusFilter = Array.isArray(input.status)\n ? new Set(input.status)\n : input.status\n ? new Set([input.status])\n : null\n\n const filtered = all.filter((a) => {\n if (input.route !== undefined && a.route !== input.route) return false\n if (statusFilter && !statusFilter.has(a.status)) return false\n if (input.viewportBucket !== undefined && a.viewportBucket !== input.viewportBucket) return false\n if (input.file !== undefined) {\n const src = a.fingerprint.sourceLocation ?? a.fingerprint.detectedSource ?? ''\n if (!src.includes(input.file)) return false\n }\n return true\n })\n\n const limit = input.limit ?? 50\n const thinned = filtered.slice(0, limit).map(toThin)\n\n return toolSuccess({ annotations: thinned, total: filtered.length })\n}\n","export type ToolErrorCode =\n | 'annotation_not_found'\n | 'invalid_transition'\n | 'storage_error'\n | 'validation_error'\n\nexport interface ToolErrorPayload {\n code: ToolErrorCode\n message: string\n details?: Record<string, unknown>\n}\n\nexport interface ToolErrorResult {\n isError: true\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolError(code: ToolErrorCode, message: string, details?: Record<string, unknown>): ToolErrorResult {\n const payload: ToolErrorPayload = { code, message, details }\n return {\n isError: true,\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n }\n}\n\nexport interface ToolSuccessResult {\n isError?: false\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolSuccess(value: unknown): ToolSuccessResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(value) }],\n }\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { generateAgentExport } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const getAnnotationInputSchema = z.object({\n id: z.string(),\n})\n\nexport type GetAnnotationInput = z.infer<typeof getAnnotationInputSchema>\n\nexport async function handleGetAnnotation(input: GetAnnotationInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n // Reuse core agent-export to build the rich shape (source + searchHints + lifecycle).\n // generateAgentExport takes an array — pass the single annotation, then extract.\n const agentExport = generateAgentExport([annotation], annotation.viewportBucket)\n const agentAnnotation = agentExport.annotations[0]\n\n return toolSuccess(agentAnnotation)\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const acknowledgeInputSchema = z.object({\n id: z.string(),\n})\n\nexport type AcknowledgeInput = z.infer<typeof acknowledgeInputSchema>\n\nexport async function handleAcknowledge(input: AcknowledgeInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'acknowledge', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'acknowledge',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const claimFixInputSchema = z.object({\n id: z.string(),\n})\n\nexport type ClaimFixInput = z.infer<typeof claimFixInputSchema>\n\nexport async function handleClaimFix(input: ClaimFixInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'claimFix', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'claimFix',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const dismissInputSchema = z.object({\n id: z.string(),\n reason: z.string().optional(),\n})\n\nexport type DismissInput = z.infer<typeof dismissInputSchema>\n\nexport async function handleDismiss(input: DismissInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'dismiss', { actor: 'agent', reason: input.reason })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'dismiss',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\nimport { toThin } from './list-annotations.js'\n\n/** Waits up to timeoutMs for a backend change. Local mode resolves early on\n * mutation events; cloud mode just sleeps a poll interval and returns false. */\nexport type WaitForChange = (timeoutMs: number) => Promise<boolean>\n\nconst DEFAULT_TIMEOUT_SECONDS = 25\n\nexport const watchAnnotationsInputSchema = z.object({\n timeoutSeconds: z.number().int().min(1).max(120).optional(),\n})\n\nexport type WatchAnnotationsInput = z.infer<typeof watchAnnotationsInputSchema>\n\nexport async function handleWatchAnnotations(\n input: WatchAnnotationsInput,\n storage: StorageAdapter,\n waitForChange: WaitForChange,\n) {\n const timeoutMs = (input.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n const pending = (store?.annotations ?? []).filter((a) => a.status === 'pending')\n if (pending.length > 0) {\n return toolSuccess({ annotations: pending.map(toThin), total: pending.length, timedOut: false })\n }\n\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n return toolSuccess({ annotations: [], total: 0, timedOut: true })\n }\n\n await waitForChange(remaining)\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { StorageAdapter } from 'web-remarq'\n\nimport { listAnnotationsInputSchema, handleListAnnotations } from './list-annotations.js'\nimport { getAnnotationInputSchema, handleGetAnnotation } from './get-annotation.js'\nimport { acknowledgeInputSchema, handleAcknowledge } from './acknowledge.js'\nimport { claimFixInputSchema, handleClaimFix } from './claim-fix.js'\nimport { dismissInputSchema, handleDismiss } from './dismiss.js'\nimport { watchAnnotationsInputSchema, handleWatchAnnotations, type WaitForChange } from './watch-annotations.js'\n\nexport type { WaitForChange } from './watch-annotations.js'\n\n// Cast helper: our tool results satisfy CallToolResult at runtime; the SDK's\n// inferred type carries an index signature that our narrower types lack.\nfunction cast(p: Promise<{ isError?: boolean; content: Array<{ type: 'text'; text: string }> }>): Promise<CallToolResult> {\n return p as Promise<CallToolResult>\n}\n\nexport function registerTools(\n server: McpServer,\n storage: StorageAdapter,\n opts: { waitForChange: WaitForChange },\n): void {\n server.registerTool(\n 'list_annotations',\n {\n description: 'List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran. In local mode, actionable annotations (pending / in_progress) are also mirrored as ticket files in .remarq/tasks/.',\n inputSchema: listAnnotationsInputSchema.shape,\n },\n (input) => cast(handleListAnnotations(input, storage)),\n )\n\n server.registerTool(\n 'get_annotation',\n {\n description: 'Get full annotation details including source file:line:col, grep search hints, and the AI quality verdict (`qualityCheck`). If qualityCheck.score is \"ambiguous\" or \"unactionable\", the comment may need designer clarification before fixing — consider dismissing with a reason instead of guessing.',\n inputSchema: getAnnotationInputSchema.shape,\n },\n (input) => cast(handleGetAnnotation(input, storage)),\n )\n\n server.registerTool(\n 'acknowledge',\n {\n description: 'Mark an annotation as in-progress (pending → in_progress).',\n inputSchema: acknowledgeInputSchema.shape,\n },\n (input) => cast(handleAcknowledge(input, storage)),\n )\n\n server.registerTool(\n 'claim_fix',\n {\n description: 'Claim a fix for an annotation (→ fixed_unverified). Human verification still required.',\n inputSchema: claimFixInputSchema.shape,\n },\n (input) => cast(handleClaimFix(input, storage)),\n )\n\n server.registerTool(\n 'dismiss',\n {\n description: 'Dismiss an annotation with an optional reason (terminal state).',\n inputSchema: dismissInputSchema.shape,\n },\n (input) => cast(handleDismiss(input, storage)),\n )\n\n server.registerTool(\n 'watch_annotations',\n {\n description:\n 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {\"annotations\": [], \"timedOut\": true}. Call this in a loop to continuously pick up designer feedback. If your environment can run background subagents (e.g. a Task tool), act as a dispatcher: for each returned annotation call acknowledge first (so it stops being redelivered), hand the fix to a background subagent that will claim_fix when done, and return to watch_annotations immediately instead of fixing inline - new feedback must never wait on a fix in progress. Without subagents, acknowledge each annotation before you start fixing it.',\n inputSchema: watchAnnotationsInputSchema.shape,\n },\n (input) => cast(handleWatchAnnotations(input, storage, opts.waitForChange)),\n )\n}\n"],"mappings":";AAAA,SAAS,WAAAA,UAAS,QAAAC,aAAY;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACa9B,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,SAAS,KAAwB,KAAqB;AAC7D,QAAM,IAAI,IAAI,GAAG;AACjB,MAAI,CAAC,KAAK,EAAE,KAAK,MAAM,IAAI;AACzB,UAAM,IAAI,YAAY,6BAA6B,GAAG,EAAE;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAEnB,SAAS,SAAS,KAAmC;AAC1D,QAAM,iBAAiB;AAAA,IACrB,IAAI,sBAAsB,IAAI,uBAAuB,IAAI;AAAA,EAC3D;AAEA,MAAI,gBAAgB;AAClB,UAAM,aAAa,SAAS,KAAK,oBAAoB;AACrD,UAAM,cAAc,SAAS,KAAK,qBAAqB;AACvD,UAAM,kBAAkB,SAAS,KAAK,0BAA0B;AAEhE,QAAI,CAAC,WAAW,WAAW,KAAK,GAAG;AACjC,YAAM,IAAI,YAAY,yFAAyF;AAAA,IACjH;AACA,QAAI,CAAC,YAAY,WAAW,UAAU,GAAG;AACvC,YAAM,IAAI,YAAY,8CAA8C;AAAA,IACtE;AAEA,WAAO,EAAE,MAAM,SAAS,YAAY,aAAa,gBAAgB;AAAA,EACnE;AAEA,QAAM,UAAU,IAAI,eAAe,OAAO,YAAY;AACtD,QAAM,OAAO,OAAO,OAAO;AAC3B,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,UAAM,IAAI,YAAY,4DAA4D,OAAO,GAAG;AAAA,EAC9F;AAEA,SAAO,EAAE,MAAM,SAAS,MAAM,UAAU,IAAI,oBAAoB,kBAAkB;AACpF;;;AC5DA,SAAS,0BAA0B;AAI5B,SAAS,cAAc,QAAqC;AACjE,SAAO,mBAAmB;AAAA,IACxB,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,iBAAiB,OAAO;AAAA,IACxB,SAAS;AAAA,EACX,CAAC;AACH;;;ACXA,SAAS,oBAAoB;AAC7B,SAAS,YAAY,WAAW,cAAc,YAAY,qBAAqB;AAC/E,SAAS,UAAU,SAAS,YAAY;AAQjC,IAAM,qBAAN,MAAmD;AAAA,EAOxD,YAAoB,UAAkB;AAAlB;AALpB;AAAA,eAAM;AACN,SAAQ,UAAU,IAAI,aAAa;AAEnC;AAAA,SAAQ,QAAuB,QAAQ,QAAQ;AAG7C,SAAK,QAAQ,gBAAgB,CAAC;AAAA,EAChC;AAAA,EAEA,MAAM,OAAwC;AAC5C,QAAI,CAAC,WAAW,KAAK,QAAQ,EAAG,QAAO;AACvC,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,aAAa,KAAK,UAAU,MAAM,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAM,IAAI,MAAM,kCAAkC,KAAK,QAAQ,KAAK,OAAO,EAAE;AAAA,IAC/E;AACA,UAAM,QAAQ;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,MAAM,QAAQ,MAAM,WAAW,IAAK,MAAM,cAA+B,CAAC;AAAA,IACzF;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,YAAuC;AAChD,WAAO,KAAK,QAAQ,YAAY;AAC9B,YAAM,QAAS,MAAM,KAAK,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC5E,YAAM,MAAM,MAAM,YAAY,UAAU,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE;AACrE,UAAI,QAAQ,GAAI,OAAM,YAAY,KAAK,UAAU;AAAA,UAC5C,OAAM,YAAY,GAAG,IAAI;AAC9B,WAAK,QAAQ,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,WAAO,KAAK,QAAQ,YAAY;AAC9B,YAAM,QAAS,MAAM,KAAK,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC5E,YAAM,cAAc,MAAM,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/D,WAAK,QAAQ,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAuB;AAC3B,WAAO,KAAK,QAAQ,YAAY;AAC9B,WAAK,QAAQ,EAAE,SAAS,GAAG,aAAa,CAAC,EAAE,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,QAAQ,IAAwC;AACtD,UAAM,SAAS,KAAK,MAAM,KAAK,EAAE;AAGjC,SAAK,QAAQ,OAAO,MAAM,MAAM,MAAS;AACzC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,cAAc,WAAqC;AACjD,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,WAAW,MAAY;AAC3B,qBAAa,KAAK;AAClB,gBAAQ,IAAI;AAAA,MACd;AACA,YAAM,QAAQ,WAAW,MAAM;AAC7B,aAAK,QAAQ,IAAI,UAAU,QAAQ;AACnC,gBAAQ,KAAK;AAAA,MACf,GAAG,SAAS;AACZ,WAAK,QAAQ,KAAK,UAAU,QAAQ;AAAA,IACtC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,UAA4B;AACnC,SAAK,QAAQ,GAAG,UAAU,QAAQ;AAAA,EACpC;AAAA,EAEQ,QAAQ,OAA8B;AAC5C,UAAM,MAAM,QAAQ,KAAK,QAAQ;AACjC,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGlC,QAAI,SAAS,GAAG,MAAM,WAAW;AAC/B,YAAM,YAAY,KAAK,KAAK,YAAY;AACxC,UAAI,CAAC,WAAW,SAAS,EAAG,eAAc,WAAW,KAAK;AAAA,IAC5D;AACA,UAAM,MAAM,GAAG,KAAK,QAAQ;AAC5B,kBAAc,KAAK,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACjD,eAAW,KAAK,KAAK,QAAQ;AAC7B,SAAK;AACL,SAAK,QAAQ,KAAK,QAAQ;AAAA,EAC5B;AACF;;;ACzGA,YAAY,UAAU;;;ACAtB,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,aAAa,YAAY,iBAAAC,sBAAqB;AAC5F,SAAS,QAAAC,aAAY;AAErB,SAAS,gBAAgB,2BAA2B;AAGpD,SAAS,WAAW,OAAuB;AACzC,SAAO,KAAK,UAAU,KAAK;AAC7B;AASO,SAAS,mBAAmB,IAAqB;AACtD,SAAO,+BAA+B,KAAK,EAAE;AAC/C;AAOO,SAAS,eAAe,YAAgC;AAE7D,QAAM,QAAQ,oBAAoB,CAAC,UAAU,GAAG,WAAW,cAAc,EAAE,YAAY,CAAC;AACxF,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,OAAO,WAAW,MAAM,EAAE,CAAC,EAAE;AACxC,QAAM,KAAK,UAAU,WAAW,MAAM,KAAK,CAAC,EAAE;AAC9C,QAAM,KAAK,WAAW,MAAM,MAAM,EAAE;AACpC,QAAM,KAAK,mBAAmB,WAAW,cAAc,EAAE;AACzD,MAAI,WAAW,aAAc,OAAM,KAAK,YAAY,WAAW,aAAa,KAAK,EAAE;AACnF,QAAM,KAAK,OAAO,EAAE;AAEpB,QAAM,KAAK,2BAA2B,MAAM,EAAE,IAAI,EAAE;AACpD,QAAM,KAAK,cAAc,IAAI,MAAM,QAAQ,KAAK,GAAG,EAAE;AAErD,QAAM,KAAK,cAAc,EAAE;AAC3B,QAAM,KAAK,YAAY,MAAM,YAAY,OAAO,IAAI;AACpD,QAAM,KAAK,YAAY,MAAM,YAAY,UAAU,IAAI;AACvD,MAAI,MAAM,QAAQ;AAChB,UAAM,YAAY,MAAM,OAAO,YAAY,iBAAiB,MAAM,OAAO,SAAS,QAAQ;AAC1F,UAAM,KAAK,eAAe,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,MAAM,KAAK,SAAS,EAAE;AAAA,EACzG;AACA,MAAI,MAAM,YAAY,QAAQ,QAAQ;AACpC,UAAM,KAAK,cAAc,MAAM,YAAY,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE;AAAA,EACvF;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,MAAM,YAAY,YAAY,QAAQ;AACxC,UAAM,KAAK,mBAAmB,EAAE;AAChC,eAAW,KAAK,MAAM,YAAY,aAAa;AAC7C,YAAM,KAAK,MAAM,EAAE,UAAU,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,IAAI;AAAA,IAClE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,WAAW;AACtB,MAAI,MAAM,GAAG,UAAU,SAAS;AAC9B,UAAM,KAAK,oBAAoB,EAAE;AACjC,UAAM,KAAK,cAAc,GAAG,KAAK,sIAAsI,EAAE;AACzK,eAAW,SAAS,GAAG,OAAQ,OAAM,KAAK,YAAY,KAAK,EAAE;AAC7D,eAAW,KAAK,GAAG,oBAAqB,OAAM,KAAK,oBAAoB,CAAC,EAAE;AAC1E,QAAI,GAAG,iBAAkB,OAAM,KAAK,wBAAwB,GAAG,gBAAgB,EAAE;AACjF,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,yBAAyB,EAAE;AACtC,QAAM,KAAK,wFAAwF,WAAW,MAAM,EAAE,CAAC,4EAA4E;AACnM,QAAM,KAAK,4CAA4C;AACvD,QAAM,KAAK,uFAAuF,WAAW,MAAM,EAAE,CAAC,2EAA2E;AACjM,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uMAAuM;AAClN,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;AAOO,IAAM,aAAN,MAAiB;AAAA,EAItB,YACU,SACA,KACR;AAFQ;AACA;AALV,SAAQ,UAAU;AAClB,SAAQ,QAAQ;AAAA,EAKb;AAAA;AAAA,EAGH,MAAM,OAAsB;AAC1B,UAAM,QAAQ,MAAM,KAAK,QAAQ,KAAK;AACtC,UAAM,aAAa,eAAe,OAAO,eAAe,CAAC,CAAC;AAC1D,UAAM,UAAU,oBAAI,IAAoB;AACxC,eAAW,KAAK,YAAY;AAC1B,UAAI,CAAC,mBAAmB,EAAE,EAAE,GAAG;AAC7B,gBAAQ,MAAM,wDAAwD,KAAK,UAAU,EAAE,EAAE,CAAC,EAAE;AAC5F;AAAA,MACF;AACA,cAAQ,IAAI,GAAG,EAAE,EAAE,OAAO,eAAe,CAAC,CAAC;AAAA,IAC7C;AAEA,IAAAH,WAAU,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,eAAW,SAAS,YAAY,KAAK,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAClE,UAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,EAAG;AAC/E,UAAI;AACF,mBAAWG,MAAK,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,MACvC,SAAS,KAAK;AACZ,gBAAQ,MAAM,qDAAqD,MAAM,IAAI,KAAK,GAAG;AAAA,MACvF;AAAA,IACF;AACA,eAAW,CAAC,MAAM,OAAO,KAAK,SAAS;AACrC,UAAI;AACF,cAAM,OAAOA,MAAK,KAAK,KAAK,IAAI;AAChC,YAAIJ,YAAW,IAAI,KAAKE,cAAa,MAAM,MAAM,MAAM,QAAS;AAChE,QAAAC,eAAc,MAAM,OAAO;AAAA,MAC7B,SAAS,KAAK;AACZ,gBAAQ,MAAM,8CAA8C,IAAI,KAAK,GAAG;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,WAAiB;AACf,SAAK,QAAQ;AACb,SAAK,KAAK,IAAI;AAAA,EAChB;AAAA,EAEA,MAAc,MAAqB;AACjC,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf,WAAO,KAAK,OAAO;AACjB,WAAK,QAAQ;AACb,UAAI;AACF,cAAM,KAAK,KAAK;AAAA,MAClB,SAAS,KAAK;AACZ,gBAAQ,MAAM,6CAA6C,GAAG;AAAA,MAChE;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB;AACF;;;ADhJA,IAAM,eAAuC;AAAA,EAC3C,+BAA+B;AAAA,EAC/B,gCAAgC;AAAA,EAChC,gCAAgC;AAClC;AAEA,IAAM,iBAAiB,OAAO;AAE9B,SAAS,KAAK,KAAqB,QAAgB,MAAqB;AACtE,MAAI,UAAU,QAAQ,EAAE,GAAG,cAAc,gBAAgB,mBAAmB,CAAC;AAC7E,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC9B;AAEA,SAAS,SAAS,KAAuC;AACvD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,OAAO;AACX,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,cAAQ,MAAM;AACd,UAAI,OAAO,gBAAgB;AACzB,eAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,YAAI,QAAQ;AACZ;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,QAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC,CAAC;AACnE,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEA,eAAe,OAAO,KAAsB,KAAqB,SAA4C;AAC3G,MAAI,IAAI,WAAW,WAAW;AAC5B,QAAI,UAAU,KAAK,YAAY;AAC/B,QAAI,IAAI;AACR;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB,EAAE;AAC7D,QAAM,WAAW,SAAS,MAAM,0BAA0B;AAE1D,MAAI;AACF,QAAI,IAAI,WAAW,SAAS,aAAa,UAAU;AAKjD,YAAM,MAAM,QAAQ;AACpB,YAAM,QAAS,MAAM,QAAQ,KAAK,KAAM,EAAE,SAAS,GAAY,aAAa,CAAC,EAAE;AAC/E,WAAK,KAAK,KAAK,EAAE,KAAK,MAAM,CAAC;AAC7B;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,SAAS,UAAU;AACpC,YAAM,KAAK,mBAAmB,SAAS,CAAC,CAAC;AACzC,UAAI,CAAC,mBAAmB,EAAE,GAAG;AAC3B,aAAK,KAAK,KAAK,EAAE,OAAO,wBAAwB,CAAC;AACjD;AAAA,MACF;AACA,UAAI;AACJ,UAAI;AACF,qBAAa,KAAK,MAAM,MAAM,SAAS,GAAG,CAAC;AAAA,MAC7C,QAAQ;AACN,aAAK,KAAK,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAC7C;AAAA,MACF;AACA,UAAI,CAAC,cAAc,WAAW,OAAO,IAAI;AACvC,aAAK,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAC/D;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,UAAmB;AACtC,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,YAAY,UAAU;AACvC,YAAM,KAAK,mBAAmB,SAAS,CAAC,CAAC;AACzC,UAAI,CAAC,mBAAmB,EAAE,GAAG;AAC3B,aAAK,KAAK,KAAK,EAAE,OAAO,wBAAwB,CAAC;AACjD;AAAA,MACF;AACA,YAAM,QAAQ,OAAO,EAAE;AACvB,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,YAAY,aAAa,gBAAgB;AAC1D,YAAM,QAAQ,MAAM;AACpB,WAAK,KAAK,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AACnC;AAAA,IACF;AAEA,SAAK,KAAK,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,EACvC,SAAS,KAAK;AACZ,SAAK,KAAK,KAAK,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,EAC5E;AACF;AAGO,SAAS,gBAAgB,SAA6B,MAAoC;AAC/F,QAAM,SAAc,kBAAa,CAAC,KAAK,QAAQ;AAC7C,SAAK,OAAO,KAAK,KAAK,OAAO;AAAA,EAC/B,CAAC;AACD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC;AAAA,EACxD,CAAC;AACH;;;AEzGO,IAAM,cACX;AAYK,SAAS,gBAAgB,QAAyB;AACvD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,MACL,UAAU,CAAC,EAAE,MAAM,QAAiB,SAAS,EAAE,MAAM,QAAiB,MAAM,YAAY,EAAE,CAAC;AAAA,IAC7F;AAAA,EACF;AACF;;;ACjCA,SAAS,SAAS;;;ACiBX,SAAS,UAAU,MAAqB,SAAiB,SAAoD;AAClH,QAAM,UAA4B,EAAE,MAAM,SAAS,QAAQ;AAC3D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,EAAE,CAAC;AAAA,EAC3D;AACF;AAOO,SAAS,YAAY,OAAmC;AAC7D,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,EAAE,CAAC;AAAA,EACzD;AACF;;;AD9BA,IAAM,gBAAgB,CAAC,SAAS,WAAW,eAAe,oBAAoB,YAAY,WAAW;AAE9F,IAAM,6BAA6B,EAAE,OAAO;AAAA,EACjD,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,aAAa,GAAG,EAAE,MAAM,EAAE,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,EAClF,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC1C,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AACnD,CAAC;AAeD,SAAS,YAAY,YAAkD;AACrE,QAAM,KAAK,WAAW;AACtB,QAAM,MAAM,GAAG,kBAAkB,GAAG;AACpC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,MAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,QAAM,SAAS,SAAS,MAAM,IAAI,GAAI,EAAE;AACxC,QAAM,OAAO,SAAS,MAAM,IAAI,GAAI,EAAE;AACtC,QAAM,OAAO,MAAM,KAAK,GAAG;AAC3B,MAAI,CAAC,QAAQ,MAAM,IAAI,EAAG,QAAO;AACjC,QAAM,YAAY,GAAG,iBAAiB,GAAG,qBAAqB;AAC9D,SAAO,EAAE,MAAM,MAAM,QAAQ,MAAM,MAAM,IAAI,IAAI,QAAQ,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AAC/F;AAEO,SAAS,OAAO,GAA+B;AACpD,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,OAAO,EAAE;AAAA,IACT,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,UAAU,EAAE;AAAA,IACZ,WAAW,EAAE;AAAA,IACb,QAAQ,YAAY,CAAC;AAAA,IACrB,GAAI,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,MAAM,IAAI,CAAC;AAAA,EAC5D;AACF;AAEA,eAAsB,sBAAsB,OAA6B,SAAyB;AAChG,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,MAAM,OAAO,eAAe,CAAC;AAEnC,QAAM,eAAe,MAAM,QAAQ,MAAM,MAAM,IAC3C,IAAI,IAAI,MAAM,MAAM,IACpB,MAAM,SACN,oBAAI,IAAI,CAAC,MAAM,MAAM,CAAC,IACtB;AAEJ,QAAM,WAAW,IAAI,OAAO,CAAC,MAAM;AACjC,QAAI,MAAM,UAAU,UAAa,EAAE,UAAU,MAAM,MAAO,QAAO;AACjE,QAAI,gBAAgB,CAAC,aAAa,IAAI,EAAE,MAAM,EAAG,QAAO;AACxD,QAAI,MAAM,mBAAmB,UAAa,EAAE,mBAAmB,MAAM,eAAgB,QAAO;AAC5F,QAAI,MAAM,SAAS,QAAW;AAC5B,YAAM,MAAM,EAAE,YAAY,kBAAkB,EAAE,YAAY,kBAAkB;AAC5E,UAAI,CAAC,IAAI,SAAS,MAAM,IAAI,EAAG,QAAO;AAAA,IACxC;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,UAAU,SAAS,MAAM,GAAG,KAAK,EAAE,IAAI,MAAM;AAEnD,SAAO,YAAY,EAAE,aAAa,SAAS,OAAO,SAAS,OAAO,CAAC;AACrE;;;AEpFA,SAAS,KAAAE,UAAS;AAElB,SAAS,uBAAAC,4BAA2B;AAG7B,IAAM,2BAA2BC,GAAE,OAAO;AAAA,EAC/C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,oBAAoB,OAA2B,SAAyB;AAC5F,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAIA,QAAM,cAAcC,qBAAoB,CAAC,UAAU,GAAG,WAAW,cAAc;AAC/E,QAAM,kBAAkB,YAAY,YAAY,CAAC;AAEjD,SAAO,YAAY,eAAe;AACpC;;;AC7BA,SAAS,KAAAC,UAAS;AAElB,SAAS,YAAY,8BAA8B;AAG5C,IAAM,yBAAyBC,GAAE,OAAO;AAAA,EAC7C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,kBAAkB,OAAyB,SAAyB;AACxF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,WAAW,YAAY,eAAe,EAAE,OAAO,QAAQ,CAAC;AAAA,EACnE,SAAS,KAAK;AACZ,QAAI,eAAe,wBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;ACjDA,SAAS,KAAAC,UAAS;AAElB,SAAS,cAAAC,aAAY,0BAAAC,+BAA8B;AAG5C,IAAM,sBAAsBC,GAAE,OAAO;AAAA,EAC1C,IAAIA,GAAE,OAAO;AACf,CAAC;AAID,eAAsB,eAAe,OAAsB,SAAyB;AAClF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAASC,YAAW,YAAY,YAAY,EAAE,OAAO,QAAQ,CAAC;AAAA,EAChE,SAAS,KAAK;AACZ,QAAI,eAAeC,yBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;ACjDA,SAAS,KAAAC,UAAS;AAElB,SAAS,cAAAC,aAAY,0BAAAC,+BAA8B;AAG5C,IAAM,qBAAqBC,GAAE,OAAO;AAAA,EACzC,IAAIA,GAAE,OAAO;AAAA,EACb,QAAQA,GAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAID,eAAsB,cAAc,OAAqB,SAAyB;AAChF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,QAAQ,KAAK;AAAA,EAC7B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AACA,QAAM,aAAa,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AACnE,MAAI,CAAC,YAAY;AACf,WAAO,UAAU,wBAAwB,cAAc,MAAM,EAAE,4BAA4B;AAAA,EAC7F;AAEA,MAAI;AACJ,MAAI;AACF,aAASC,YAAW,YAAY,WAAW,EAAE,OAAO,SAAS,QAAQ,MAAM,OAAO,CAAC;AAAA,EACrF,SAAS,KAAK;AACZ,QAAI,eAAeC,yBAAwB;AACzC,aAAO,UAAU,sBAAsB,IAAI,SAAS;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,qBAAqB;AAAA,MACvB,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,IACf,WAAW,CAAC,GAAG,WAAW,WAAW,OAAO,KAAK;AAAA,EACnD;AAEA,MAAI;AACF,UAAM,QAAQ,KAAK,OAAO;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EACpF;AAEA,SAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC;AACxD;;;AClDA,SAAS,KAAAC,UAAS;AASlB,IAAM,0BAA0B;AAEzB,IAAM,8BAA8BC,GAAE,OAAO;AAAA,EAClD,gBAAgBA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAC5D,CAAC;AAID,eAAsB,uBACpB,OACA,SACA,eACA;AACA,QAAM,aAAa,MAAM,kBAAkB,2BAA2B;AACtE,QAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,aAAS;AACP,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,KAAK;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,UAAU,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACpF;AAEA,UAAM,WAAW,OAAO,eAAe,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC/E,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,YAAY,EAAE,aAAa,QAAQ,IAAI,MAAM,GAAG,OAAO,QAAQ,QAAQ,UAAU,MAAM,CAAC;AAAA,IACjG;AAEA,UAAM,YAAY,WAAW,KAAK,IAAI;AACtC,QAAI,aAAa,GAAG;AAClB,aAAO,YAAY,EAAE,aAAa,CAAC,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAAA,IAClE;AAEA,UAAM,cAAc,SAAS;AAAA,EAC/B;AACF;;;AC9BA,SAAS,KAAK,GAA4G;AACxH,SAAO;AACT;AAEO,SAAS,cACd,QACA,SACA,MACM;AACN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,2BAA2B;AAAA,IAC1C;AAAA,IACA,CAAC,UAAU,KAAK,sBAAsB,OAAO,OAAO,CAAC;AAAA,EACvD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,yBAAyB;AAAA,IACxC;AAAA,IACA,CAAC,UAAU,KAAK,oBAAoB,OAAO,OAAO,CAAC;AAAA,EACrD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,uBAAuB;AAAA,IACtC;AAAA,IACA,CAAC,UAAU,KAAK,kBAAkB,OAAO,OAAO,CAAC;AAAA,EACnD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,oBAAoB;AAAA,IACnC;AAAA,IACA,CAAC,UAAU,KAAK,eAAe,OAAO,OAAO,CAAC;AAAA,EAChD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa,mBAAmB;AAAA,IAClC;AAAA,IACA,CAAC,UAAU,KAAK,cAAc,OAAO,OAAO,CAAC;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa,4BAA4B;AAAA,IAC3C;AAAA,IACA,CAAC,UAAU,KAAK,uBAAuB,OAAO,SAAS,KAAK,aAAa,CAAC;AAAA,EAC5E;AACF;;;AdlEA,IAAM,gBAAgB;AAEtB,eAAe,OAAsB;AACnC,MAAI;AACJ,MAAI;AACF,aAAS,SAAS,QAAQ,GAAG;AAAA,EAC/B,SAAS,KAAK;AACZ,QAAI,eAAe,aAAa;AAC9B,cAAQ,MAAM,kCAAkC,IAAI,OAAO,EAAE;AAC7D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AAEA,MAAI;AACJ,MAAI;AAEJ,MAAI,OAAO,SAAS,SAAS;AAC3B,UAAM,UAAU,IAAI,mBAAmB,OAAO,QAAQ;AACtD,UAAM,WAAWC,MAAKC,SAAQ,OAAO,QAAQ,GAAG,OAAO;AACvD,UAAM,aAAa,IAAI,WAAW,SAAS,QAAQ;AACnD,YAAQ,SAAS,MAAM,WAAW,SAAS,CAAC;AAC5C,eAAW,SAAS;AACpB,UAAM,gBAAgB,SAAS,OAAO,IAAI;AAC1C,YAAQ;AAAA,MACN,uEAAkE,OAAO,IAAI,WAAW,OAAO,QAAQ,WAAW,QAAQ;AAAA,IAC5H;AACA,cAAU;AACV,oBAAgB,CAAC,OAAO,QAAQ,cAAc,EAAE;AAAA,EAClD,OAAO;AACL,cAAU,cAAc,MAAM;AAC9B,oBAAgB,CAAC,OACf,IAAI,QAAQ,CAAC,YAAY,WAAW,MAAM,QAAQ,KAAK,GAAG,KAAK,IAAI,IAAI,aAAa,CAAC,CAAC;AAAA,EAC1F;AAEA,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAED,gBAAc,QAAQ,SAAS,EAAE,cAAc,CAAC;AAChD,kBAAgB,MAAM;AAEtB,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,2BAA2B,GAAG;AAC5C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["dirname","join","existsSync","mkdirSync","readFileSync","writeFileSync","join","z","generateAgentExport","z","generateAgentExport","z","z","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","z","join","dirname"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@web-remarq/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "MCP server for web-remarq - gives AI agents access to annotations via a local file store or Supabase cloud backend",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",