Files
grimoire/src/lib/chat-parser.ts
Alejandro Gómez 6d01ee33ef feat: implement unified chat system with NIP-C7 and NIP-29 support
Core Architecture:
- Protocol adapter pattern for chat implementations
- Base adapter interface with protocol-specific implementations
- Auto-detection of protocol from identifier format
- Reactive message loading via EventStore observables

Protocol Implementations:
- NIP-C7 adapter: Simple chat (kind 9) with npub/nprofile support
- NIP-29 adapter: Relay-based groups with member roles and moderation
- Protocol-aware reply message loading with relay hints
- Proper NIP-29 members/admins fetching using #d tags

UI Components:
- ChatViewer: Main chat interface with virtualized message timeline
- ChatMessage: Message rendering with reply preview
- ReplyPreview: Auto-loading replied-to messages from relays
- MembersDropdown: Virtualized member list with role labels
- RelaysDropdown: Connection status for chat relays
- ChatComposer: Message input with send functionality

Command System:
- chat command with identifier parsing and auto-detection
- Support for npub, nprofile, NIP-05, and relay'group-id formats
- Integration with window system and dynamic titles

NIP-29 Specific:
- Fetch kind:39000 (metadata), kind:39001 (admins), kind:39002 (members)
- Extract roles from p tags: ["p", "<pubkey>", "<role1>", "<role2>"]
- Role normalization (admin, moderator, host, member)
- Single group relay connection management

Testing:
- Comprehensive chat parser tests
- Protocol adapter test structure
- All tests passing (704 tests)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-11 21:38:23 +01:00

72 lines
2.6 KiB
TypeScript

import type { ChatCommandResult } from "@/types/chat";
// import { NipC7Adapter } from "./chat/adapters/nip-c7-adapter";
import { Nip29Adapter } from "./chat/adapters/nip-29-adapter";
// Import other adapters as they're implemented
// import { Nip17Adapter } from "./chat/adapters/nip-17-adapter";
// import { Nip28Adapter } from "./chat/adapters/nip-28-adapter";
// import { Nip53Adapter } from "./chat/adapters/nip-53-adapter";
/**
* Parse a chat command identifier and auto-detect the protocol
*
* Tries each adapter's parseIdentifier() in priority order:
* 1. NIP-17 (encrypted DMs) - prioritized for privacy
* 2. NIP-28 (channels) - specific event format (kind 40)
* 3. NIP-29 (groups) - specific group ID format
* 4. NIP-53 (live chat) - specific addressable format (kind 30311)
* 5. NIP-C7 (simple chat) - fallback for generic pubkeys
*
* @param args - Command arguments (first arg is the identifier)
* @returns Parsed result with protocol and identifier
* @throws Error if no adapter can parse the identifier
*/
export function parseChatCommand(args: string[]): ChatCommandResult {
if (args.length === 0) {
throw new Error("Chat identifier required. Usage: chat <identifier>");
}
// Handle NIP-29 format that may be split by shell-quote
// If we have 2 args and they look like relay + group-id, join them with '
let identifier = args[0];
if (args.length === 2 && args[0].includes(".") && !args[0].includes("'")) {
// Looks like "relay.com" "group-id" split by shell-quote
// Rejoin with apostrophe for NIP-29 format
identifier = `${args[0]}'${args[1]}`;
}
// Try each adapter in priority order
const adapters = [
// new Nip17Adapter(), // Phase 2
// new Nip28Adapter(), // Phase 3
new Nip29Adapter(), // Phase 4 - Relay groups (currently only enabled)
// new Nip53Adapter(), // Phase 5
// new NipC7Adapter(), // Phase 1 - Simple chat (disabled for now)
];
for (const adapter of adapters) {
const parsed = adapter.parseIdentifier(identifier);
if (parsed) {
return {
protocol: adapter.protocol,
identifier: parsed,
adapter,
};
}
}
throw new Error(
`Unable to determine chat protocol from identifier: ${identifier}
Currently supported format:
- relay.com'group-id (NIP-29 relay group, wss:// prefix optional)
Examples:
chat relay.example.com'bitcoin-dev
chat wss://relay.example.com'nostr-dev
More formats coming soon:
- npub/nprofile/hex pubkey (NIP-C7/NIP-17 direct messages)
- note/nevent (NIP-28 public channels)
- naddr (NIP-53 live activity chat)`,
);
}