Replace inline SKILL.md instructions with executable shell scripts for each setup phase (environment check, deps, container, auth, groups, channels, mounts, service, verify). Scripts emit structured status blocks for reliable parsing. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
import { Channel, NewMessage } from './types.js';
|
|
|
|
export function escapeXml(s: string): string {
|
|
if (!s) return '';
|
|
return s
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
|
|
export function formatMessages(messages: NewMessage[]): string {
|
|
const lines = messages.map((m) =>
|
|
`<message sender="${escapeXml(m.sender_name)}" time="${m.timestamp}">${escapeXml(m.content)}</message>`,
|
|
);
|
|
return `<messages>\n${lines.join('\n')}\n</messages>`;
|
|
}
|
|
|
|
export function stripInternalTags(text: string): string {
|
|
return text.replace(/<internal>[\s\S]*?<\/internal>/g, '').trim();
|
|
}
|
|
|
|
export function formatOutbound(rawText: string): string {
|
|
const text = stripInternalTags(rawText);
|
|
if (!text) return '';
|
|
return text;
|
|
}
|
|
|
|
export function routeOutbound(
|
|
channels: Channel[],
|
|
jid: string,
|
|
text: string,
|
|
): Promise<void> {
|
|
const channel = channels.find((c) => c.ownsJid(jid) && c.isConnected());
|
|
if (!channel) throw new Error(`No channel for JID: ${jid}`);
|
|
return channel.sendMessage(jid, text);
|
|
}
|
|
|
|
export function findChannel(
|
|
channels: Channel[],
|
|
jid: string,
|
|
): Channel | undefined {
|
|
return channels.find((c) => c.ownsJid(jid));
|
|
}
|