Skip to content

Commit 6be7c09

Browse files
author
Sorra
committed
Merge feature/SB-0MN3UDQFM0LB0LAH-modularize-bootstrap into main (SB-0MNODSVMD000AGXO)
2 parents 465e3a8 + d60aab5 commit 6be7c09

19 files changed

Lines changed: 539 additions & 187 deletions

src/discord/cli-error-report.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const DISCORD_CONTENT_LIMIT = 1900;
2+
3+
export async function postCliErrorReport(target: any, report: string, shortIntro?: string): Promise<void> {
4+
try {
5+
if (!report) return;
6+
7+
if (report.length <= DISCORD_CONTENT_LIMIT) {
8+
if (typeof target.send === "function") {
9+
await target.send(report);
10+
return;
11+
}
12+
if (typeof target.reply === "function") {
13+
await target.reply(report);
14+
return;
15+
}
16+
return;
17+
}
18+
19+
const intro = shortIntro || "Detailed CLI diagnostic attached.";
20+
const content = `${intro}\n\n(Full report attached as cli-error-report.txt)`;
21+
const file = { attachment: Buffer.from(report, "utf8"), name: "cli-error-report.txt" };
22+
23+
if (typeof target.send === "function") {
24+
await target.send({ content, files: [file] } as any);
25+
return;
26+
}
27+
if (typeof target.reply === "function") {
28+
await target.reply({ content, files: [file] } as any);
29+
return;
30+
}
31+
} catch {
32+
try {
33+
const truncated = report.slice(0, Math.max(0, DISCORD_CONTENT_LIMIT - 50)) + "...";
34+
if (typeof target.send === "function") await target.send(truncated);
35+
else if (typeof target.reply === "function") await target.reply(truncated);
36+
} catch {
37+
}
38+
}
39+
}

src/formatters/progress.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { AddProgressEvent } from "../bot/cli-runner.js";
2+
3+
export function formatProgressMessage(event: AddProgressEvent): string {
4+
const phase = typeof event.phase === "string" && event.phase.trim() !== "" ? event.phase : undefined;
5+
6+
if (!phase) {
7+
if (event.message) {
8+
const m = String(event.message).trim();
9+
const truncated = m.length > 1500 ? `${m.slice(0, 1500)}...` : m;
10+
if (event.title) return `❌ ${truncated} (${event.title})`;
11+
if (event.url) return `❌ ${truncated} (<${event.url}>)`;
12+
return `❌ ${truncated}`;
13+
}
14+
15+
const parts: string[] = [];
16+
if (event.id !== undefined) parts.push(`id:${event.id}`);
17+
if (event.title) parts.push(`title:${event.title}`);
18+
if (event.url) parts.push(`url:${event.url}`);
19+
if (event.timestamp) parts.push(`ts:${event.timestamp}`);
20+
21+
if (parts.length > 0) {
22+
return `⏳ Processing: unknown (${parts.join(", ")})`;
23+
}
24+
25+
return "⏳ Processing: unknown event";
26+
}
27+
28+
switch (phase) {
29+
case "downloading":
30+
return "⏳ Downloading content...";
31+
case "extracting":
32+
return "📝 Extracting text content...";
33+
case "embedding":
34+
return "🧠 Generating embeddings...";
35+
case "completed":
36+
return `✅ Added to OpenBrain: ${event.title || "URL processed"}`;
37+
case "failed":
38+
return `❌ Failed: ${event.message || "Unknown error"}`;
39+
default:
40+
const base = `⏳ Processing: ${phase}`;
41+
if (event.message) {
42+
const m = String(event.message).trim();
43+
const truncated = m.length > 1200 ? `${m.slice(0, 1200)}...` : m;
44+
return `${base}\n\n${truncated}`;
45+
}
46+
return base;
47+
}
48+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { Message } from "discord.js";
2+
import { runQueueCommand, type QueueResult } from "../bot/cli-runner.js";
3+
import type { MessageCommandHandler } from "../interfaces/command-handler.js";
4+
5+
export interface CrawlCommandParseResult {
6+
isCrawlCommand: boolean;
7+
seedUrl: string | null;
8+
}
9+
10+
export interface CrawlCommandHandlerDependencies {
11+
runQueue?: typeof runQueueCommand;
12+
}
13+
14+
export class CrawlCommandHandler implements MessageCommandHandler {
15+
private readonly queue: typeof runQueueCommand;
16+
17+
constructor(dependencies: CrawlCommandHandlerDependencies = {}) {
18+
this.queue = dependencies.runQueue ?? runQueueCommand;
19+
}
20+
21+
parse(content: string): CrawlCommandParseResult {
22+
const isCrawl = /^\s*crawl\s+/i.test(content);
23+
if (!isCrawl) {
24+
return {
25+
isCrawlCommand: false,
26+
seedUrl: null,
27+
};
28+
}
29+
30+
const match = content.match(/^\s*crawl\s+(https?:\/\/[^\s]+)/i);
31+
return {
32+
isCrawlCommand: true,
33+
seedUrl: match ? match[1] : null,
34+
};
35+
}
36+
37+
async queueSeed(message: Message, seedUrl: string): Promise<QueueResult> {
38+
return this.queue(seedUrl, {
39+
channelId: message.channelId,
40+
messageId: message.id,
41+
authorId: message.author.id,
42+
});
43+
}
44+
45+
async handleMessage(message: Message): Promise<boolean> {
46+
const parsed = this.parse(message.content);
47+
if (!parsed.isCrawlCommand) {
48+
return false;
49+
}
50+
if (!parsed.seedUrl) {
51+
return true;
52+
}
53+
54+
await this.queueSeed(message, parsed.seedUrl);
55+
return true;
56+
}
57+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { CommandInteraction } from "discord.js";
2+
import type { SlashCommandHandler } from "../interfaces/command-handler.js";
3+
4+
const DEFAULT_UNAVAILABLE_MESSAGE = "Stats functionality temporarily unavailable - CLI has been extracted to openBrain repository.";
5+
6+
export interface StatsCommandHandlerDependencies {
7+
unavailableMessage?: string;
8+
}
9+
10+
export class StatsCommandHandler implements SlashCommandHandler {
11+
private readonly unavailableMessage: string;
12+
13+
constructor(dependencies: StatsCommandHandlerDependencies = {}) {
14+
this.unavailableMessage = dependencies.unavailableMessage ?? DEFAULT_UNAVAILABLE_MESSAGE;
15+
}
16+
17+
async handleCommand(command: CommandInteraction): Promise<boolean> {
18+
if (command.commandName !== "stats") {
19+
return false;
20+
}
21+
22+
await command.reply(this.unavailableMessage);
23+
return true;
24+
}
25+
}

0 commit comments

Comments
 (0)