Files
Dirigent/plugin/core/mentions.ts
hzhang b5196e972c feat: rewrite plugin as v2 with globalThis-based turn management
Complete rewrite of the Dirigent plugin turn management system to work
correctly with OpenClaw's VM-context-per-session architecture:

- All turn state stored on globalThis (persists across VM context hot-reloads)
- Hooks registered unconditionally on every api instance; event-level dedup
  (runId Set for agent_end, WeakSet for before_model_resolve) prevents
  double-processing
- Gateway lifecycle events (gateway_start/stop) guarded once via globalThis flag
- Shared initializingChannels lock prevents concurrent channel init across VM
  contexts in message_received and before_model_resolve
- New ChannelStore and IdentityRegistry replace old policy/session-state modules
- Added agent_end hook with tail-match polling for Discord delivery confirmation
- Added web control page, padded-cell auto-scan, discussion tool support
- Removed obsolete v1 modules: channel-resolver, channel-modes, discussion-service,
  session-state, turn-bootstrap, policy/store, rules, decision-input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:41:25 +01:00

30 lines
811 B
TypeScript

function userIdFromToken(token: string): string | undefined {
try {
const segment = token.split(".")[0];
const padded = segment + "=".repeat((4 - (segment.length % 4)) % 4);
return Buffer.from(padded, "base64").toString("utf8");
} catch {
return undefined;
}
}
export function extractMentionedUserIds(content: string): string[] {
const regex = /<@!?(\d+)>/g;
const ids: string[] = [];
const seen = new Set<string>();
let match: RegExpExecArray | null;
while ((match = regex.exec(content)) !== null) {
const id = match[1];
if (!seen.has(id)) {
seen.add(id);
ids.push(id);
}
}
return ids;
}
export function getModeratorUserIdFromToken(token: string | undefined): string | undefined {
if (!token) return undefined;
return userIdFromToken(token);
}