@web-remarq/mcp 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/server.js +107 -2
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,6 +109,29 @@ Copy-paste prompt to put an agent on duty in this mode:
|
|
|
109
109
|
> `watch_annotations` so new feedback is never missed. If a comment is
|
|
110
110
|
> ambiguous or unactionable, `dismiss` it with a reason instead of guessing.
|
|
111
111
|
|
|
112
|
+
## Ticket folder: `.remarq/tasks/`
|
|
113
|
+
|
|
114
|
+
In local mode the server also maintains `.remarq/tasks/` - a live projection of
|
|
115
|
+
actionable annotations (`pending` / `in_progress`). Each one is a `<id>.md`
|
|
116
|
+
ticket: YAML frontmatter (id, route, status), the designer's comment,
|
|
117
|
+
source `file:line:col` + grep search hints, and instructions to report back
|
|
118
|
+
via the MCP tools. Files appear when an annotation is submitted, update on
|
|
119
|
+
status changes, and disappear once it is verified or dismissed. The folder is
|
|
120
|
+
server-owned - never edit or commit it (`.remarq/` self-gitignores).
|
|
121
|
+
|
|
122
|
+
There is no mode switch:
|
|
123
|
+
|
|
124
|
+
- **Agent on duty** (watching via `watch_annotations`): the folder just mirrors
|
|
125
|
+
state while fixes flow through the live loop.
|
|
126
|
+
- **No agent running**: the folder is your backlog. Later, tell any agent:
|
|
127
|
+
|
|
128
|
+
> Work through the tickets in .remarq/tasks/, one background subagent per
|
|
129
|
+
> file, in parallel. Follow the instructions inside each file.
|
|
130
|
+
|
|
131
|
+
Duplicate work is prevented by the lifecycle machine, not by locks: the first
|
|
132
|
+
thing any executor does is `acknowledge` - if that fails, someone else owns
|
|
133
|
+
the task and the file should be skipped.
|
|
134
|
+
|
|
112
135
|
## Cloud mode prerequisites
|
|
113
136
|
|
|
114
137
|
1. A Supabase project provisioned with `@web-remarq/cloud` (≥0.2.0). Run both
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/server.ts
|
|
2
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
2
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
5
|
|
|
@@ -123,6 +124,10 @@ var FileStorageAdapter = class {
|
|
|
123
124
|
this.emitter.once("change", onChange);
|
|
124
125
|
});
|
|
125
126
|
}
|
|
127
|
+
/** Persistent listener for every mutation (save/remove/clear). */
|
|
128
|
+
onChange(listener) {
|
|
129
|
+
this.emitter.on("change", listener);
|
|
130
|
+
}
|
|
126
131
|
persist(store) {
|
|
127
132
|
const dir = dirname(this.filePath);
|
|
128
133
|
mkdirSync(dir, { recursive: true });
|
|
@@ -224,6 +229,103 @@ function startHttpServer(storage, port) {
|
|
|
224
229
|
});
|
|
225
230
|
}
|
|
226
231
|
|
|
232
|
+
// src/task-folder.ts
|
|
233
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
234
|
+
import { join as join2 } from "path";
|
|
235
|
+
import { actionableOnly, generateAgentExport } from "web-remarq/core";
|
|
236
|
+
function yamlString(value) {
|
|
237
|
+
return JSON.stringify(value);
|
|
238
|
+
}
|
|
239
|
+
function renderTaskFile(annotation) {
|
|
240
|
+
const agent = generateAgentExport([annotation], annotation.viewportBucket).annotations[0];
|
|
241
|
+
const lines = [];
|
|
242
|
+
lines.push("---");
|
|
243
|
+
lines.push(`id: ${yamlString(agent.id)}`);
|
|
244
|
+
lines.push(`route: ${yamlString(agent.route)}`);
|
|
245
|
+
lines.push(`status: ${agent.status}`);
|
|
246
|
+
lines.push(`viewportBucket: ${annotation.viewportBucket}`);
|
|
247
|
+
if (annotation.qualityCheck) lines.push(`quality: ${annotation.qualityCheck.score}`);
|
|
248
|
+
lines.push("---", "");
|
|
249
|
+
lines.push(`# web-remarq annotation ${agent.id}`, "");
|
|
250
|
+
lines.push("## Comment", "", agent.comment.trim(), "");
|
|
251
|
+
lines.push("## Element", "");
|
|
252
|
+
lines.push(`- Tag: \`${agent.searchHints.tagName}\``);
|
|
253
|
+
lines.push(`- DOM: \`${agent.searchHints.domContext}\``);
|
|
254
|
+
if (agent.source) {
|
|
255
|
+
const component = agent.source.component ? ` (component \`${agent.source.component}\`)` : "";
|
|
256
|
+
lines.push(`- Source: \`${agent.source.file}:${agent.source.line}:${agent.source.column}\`${component}`);
|
|
257
|
+
}
|
|
258
|
+
if (agent.searchHints.classes.length) {
|
|
259
|
+
lines.push(`- Classes: ${agent.searchHints.classes.map((c) => `\`${c}\``).join(" ")}`);
|
|
260
|
+
}
|
|
261
|
+
lines.push("");
|
|
262
|
+
if (agent.searchHints.grepQueries.length) {
|
|
263
|
+
lines.push("## Search hints", "");
|
|
264
|
+
for (const q of agent.searchHints.grepQueries) {
|
|
265
|
+
lines.push(`- [${q.confidence}] \`${q.query}\` in \`${q.glob}\``);
|
|
266
|
+
}
|
|
267
|
+
lines.push("");
|
|
268
|
+
}
|
|
269
|
+
const qc = annotation.qualityCheck;
|
|
270
|
+
if (qc && qc.score !== "clear") {
|
|
271
|
+
lines.push("## Quality check", "");
|
|
272
|
+
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.`, "");
|
|
273
|
+
for (const issue of qc.issues) lines.push(`- Issue: ${issue}`);
|
|
274
|
+
for (const q of qc.clarifyingQuestions) lines.push(`- Open question: ${q}`);
|
|
275
|
+
if (qc.suggestedRewrite) lines.push(`- Suggested rewrite: ${qc.suggestedRewrite}`);
|
|
276
|
+
lines.push("");
|
|
277
|
+
}
|
|
278
|
+
lines.push("## Agent instructions", "");
|
|
279
|
+
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.`);
|
|
280
|
+
lines.push("2. Apply the fix described in the comment.");
|
|
281
|
+
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.`);
|
|
282
|
+
lines.push("");
|
|
283
|
+
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.");
|
|
284
|
+
lines.push("");
|
|
285
|
+
return lines.join("\n");
|
|
286
|
+
}
|
|
287
|
+
var TaskFolder = class {
|
|
288
|
+
constructor(storage, dir) {
|
|
289
|
+
this.storage = storage;
|
|
290
|
+
this.dir = dir;
|
|
291
|
+
this.syncing = false;
|
|
292
|
+
this.dirty = false;
|
|
293
|
+
}
|
|
294
|
+
/** Full idempotent resync: folder contents converge to the actionable set. */
|
|
295
|
+
async sync() {
|
|
296
|
+
const store = await this.storage.load();
|
|
297
|
+
const actionable = actionableOnly(store?.annotations ?? []);
|
|
298
|
+
const desired = new Map(actionable.map((a) => [`${a.id}.md`, renderTaskFile(a)]));
|
|
299
|
+
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));
|
|
302
|
+
}
|
|
303
|
+
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);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Coalesces change bursts: at most one sync in flight, one more queued. Never throws. */
|
|
310
|
+
schedule() {
|
|
311
|
+
this.dirty = true;
|
|
312
|
+
void this.run();
|
|
313
|
+
}
|
|
314
|
+
async run() {
|
|
315
|
+
if (this.syncing) return;
|
|
316
|
+
this.syncing = true;
|
|
317
|
+
while (this.dirty) {
|
|
318
|
+
this.dirty = false;
|
|
319
|
+
try {
|
|
320
|
+
await this.sync();
|
|
321
|
+
} catch (err) {
|
|
322
|
+
console.error("[web-remarq-mcp] task folder sync failed:", err);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
this.syncing = false;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
227
329
|
// src/tools/list-annotations.ts
|
|
228
330
|
import { z } from "zod";
|
|
229
331
|
|
|
@@ -301,7 +403,7 @@ async function handleListAnnotations(input, storage) {
|
|
|
301
403
|
|
|
302
404
|
// src/tools/get-annotation.ts
|
|
303
405
|
import { z as z2 } from "zod";
|
|
304
|
-
import { generateAgentExport } from "web-remarq/core";
|
|
406
|
+
import { generateAgentExport as generateAgentExport2 } from "web-remarq/core";
|
|
305
407
|
var getAnnotationInputSchema = z2.object({
|
|
306
408
|
id: z2.string()
|
|
307
409
|
});
|
|
@@ -316,7 +418,7 @@ async function handleGetAnnotation(input, storage) {
|
|
|
316
418
|
if (!annotation) {
|
|
317
419
|
return toolError("annotation_not_found", `Annotation ${input.id} not found in this project`);
|
|
318
420
|
}
|
|
319
|
-
const agentExport =
|
|
421
|
+
const agentExport = generateAgentExport2([annotation], annotation.viewportBucket);
|
|
320
422
|
const agentAnnotation = agentExport.annotations[0];
|
|
321
423
|
return toolSuccess(agentAnnotation);
|
|
322
424
|
}
|
|
@@ -548,6 +650,9 @@ async function main() {
|
|
|
548
650
|
let waitForChange;
|
|
549
651
|
if (config.mode === "local") {
|
|
550
652
|
const adapter = new FileStorageAdapter(config.dataFile);
|
|
653
|
+
const taskFolder = new TaskFolder(adapter, join3(dirname2(config.dataFile), "tasks"));
|
|
654
|
+
adapter.onChange(() => taskFolder.schedule());
|
|
655
|
+
taskFolder.schedule();
|
|
551
656
|
await startHttpServer(adapter, config.port);
|
|
552
657
|
console.error(
|
|
553
658
|
`[web-remarq-mcp] local mode \u2014 widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}`
|
package/dist/server.js.map
CHANGED
|
@@ -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/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 { 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 { 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 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 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 { 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":"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","names":["z","z","z","z","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","z"]}
|
|
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":"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","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