Files
backnotprop__plannotator/packages/ui/utils/sharing.inReplyTo.test.ts
Michael Ramos 6903d7a3dd feat(webmcp): expose plan review and annotate as WebMCP tools for browser agents (#1393)
Phase 1 of WebMCP support: a zero-dependency, feature-detected engine in packages/ui/webmcp plus a read-and-comment tool catalog for plan review and annotate (read_document, add_comments, update_comment, remove_comments, reveal, nudge_user, list_documents). No decision tools; the human approves. Zero footprint in browsers without document.modelContext (DOM, network, console, timers, and cookies identical to main), idle until called where the API exists, and never registered inside the annotate iframes. Adds an optional inReplyTo field on annotations for threaded replies. Client-only; no server changes.

AI-assisted (Claude) under maintainer direction.
2026-08-26 14:39:37 -07:00

29 lines
1.4 KiB
TypeScript

/**
* Share-URL contract for threaded replies: like element anchors and
* multi-select targets, `inReplyTo` is deliberately NOT carried by the
* compact tuple format. A reply shares as a plain comment on the same
* quote, which is the existing text-restore contract. Documented choice,
* pinned here so a future "helpful" addition is a deliberate one.
*/
import { describe, expect, test } from 'bun:test';
import { AnnotationType, type Annotation } from '../types';
import { fromShareable, toShareable } from './sharing';
const PARENT: Annotation = {
id: 'p', blockId: 'blk-a', startOffset: 0, endOffset: 5, type: AnnotationType.COMMENT,
text: 'Parent', originalText: 'quote', createdA: 1, author: 'ramos',
};
const REPLY: Annotation = { ...PARENT, id: 'r', text: 'Reply', author: 'tater', source: 'browser-agent', inReplyTo: 'p', createdA: 2 };
describe('sharing and inReplyTo', () => {
test('toShareable drops inReplyTo and the round trip restores the reply as a plain comment on the same quote', () => {
const shareable = toShareable([PARENT, REPLY]);
expect(JSON.stringify(shareable)).not.toContain('inReplyTo');
const restored = fromShareable(shareable);
expect(restored.length).toBe(2);
expect(restored[1]!.originalText).toBe('quote');
expect(restored[1]!.text).toBe('Reply');
expect(restored[1]!.inReplyTo).toBeUndefined();
});
});