Compare commits
2
Commits
9c83ec86cc
...
416c690ebc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
416c690ebc | ||
|
|
c590a8be27 |
No files matched your search
@@ -108,5 +108,5 @@ export async function retryWithBackoff<T>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw lastError!;
|
throw lastError ?? new Error("Request failed after all retries");
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ export async function initializeDiscordGateway() {
|
|||||||
gracefulShutdown("uncaughtException");
|
gracefulShutdown("uncaughtException");
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("unhandledRejection", (reason, promise) => {
|
process.on("unhandledRejection", (reason) => {
|
||||||
const err =
|
const err =
|
||||||
reason instanceof Error ? reason : new Error(String(reason ?? "unknown"));
|
reason instanceof Error ? reason : new Error(String(reason ?? "unknown"));
|
||||||
const code = (err as NodeJS.ErrnoException).code ?? "";
|
const code = (err as NodeJS.ErrnoException).code ?? "";
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ export async function downloadMediaCandidate(
|
|||||||
if (candidate.customEmojiId || candidate.stickerName) {
|
if (candidate.customEmojiId || candidate.stickerName) {
|
||||||
const vck = candidate.customEmojiId
|
const vck = candidate.customEmojiId
|
||||||
? makeCustomEmojiCacheKey(candidate.customEmojiId)
|
? makeCustomEmojiCacheKey(candidate.customEmojiId)
|
||||||
: makeStickerCacheKey(candidate.stickerName!);
|
: makeStickerCacheKey(candidate.stickerName ?? "");
|
||||||
const cached = await getCachedMediaAnalysis(vck);
|
const cached = await getCachedMediaAnalysis(vck);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
const existing = mediaAnalysisMap.get(targetId) ?? [];
|
const existing = mediaAnalysisMap.get(targetId) ?? [];
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export async function runModerationAnalysis(
|
|||||||
if (embeddings && embeddings.length === texts.length) {
|
if (embeddings && embeddings.length === texts.length) {
|
||||||
// index-aligned with semanticCandidates
|
// index-aligned with semanticCandidates
|
||||||
for (let i = 0; i < semanticCandidates.length; i++) {
|
for (let i = 0; i < semanticCandidates.length; i++) {
|
||||||
const { target, cacheKey } = semanticCandidates[i];
|
const { cacheKey } = semanticCandidates[i];
|
||||||
embeddingsByKey.set(cacheKey, embeddings[i]);
|
embeddingsByKey.set(cacheKey, embeddings[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,8 @@ export async function runTextOnlyBatch(
|
|||||||
if (pics.length === 0) return { id: msg.id, lines: [] as string[] };
|
if (pics.length === 0) return { id: msg.id, lines: [] as string[] };
|
||||||
const lines = await Promise.all(
|
const lines = await Promise.all(
|
||||||
pics.map(async (url) => {
|
pics.map(async (url) => {
|
||||||
const img = urlImages.get(url)!;
|
const img = urlImages.get(url);
|
||||||
|
if (!img) return null;
|
||||||
try {
|
try {
|
||||||
const { data: resizedBuffer, mimeType: resizedMime } =
|
const { data: resizedBuffer, mimeType: resizedMime } =
|
||||||
await resizeImageForVision(img.data, maxDim);
|
await resizeImageForVision(img.data, maxDim);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { createChildLogger } from "@/shared/logger/index";
|
|||||||
import { executeAll, executeGet } from "../../shared/database/drizzle.js";
|
import { executeAll, executeGet } from "../../shared/database/drizzle.js";
|
||||||
import { findBestEmbeddingMatch } from "./embeddingClient.js";
|
import { findBestEmbeddingMatch } from "./embeddingClient.js";
|
||||||
import {
|
import {
|
||||||
deleteExpiredQdrantPoints,
|
|
||||||
deleteQdrantPoint,
|
deleteQdrantPoint,
|
||||||
deleteQdrantPointsByContentHash,
|
deleteQdrantPointsByContentHash,
|
||||||
isQdrantConfigured,
|
isQdrantConfigured,
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ export async function resizeImageForVision(
|
|||||||
originalSize: buf.length,
|
originalSize: buf.length,
|
||||||
originalFormat: inputFormat,
|
originalFormat: inputFormat,
|
||||||
resizedSize: resized.length,
|
resizedSize: resized.length,
|
||||||
reductionPct: Math.round(((buf.length - resized.length) / buf.length) * 100),
|
reductionPct: Math.round(
|
||||||
|
((buf.length - resized.length) / buf.length) * 100,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
"Image resized for vision analysis (JPEG)",
|
"Image resized for vision analysis (JPEG)",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ export function renderDiscordMentions(
|
|||||||
content: string,
|
content: string,
|
||||||
metadata: string | null | undefined,
|
metadata: string | null | undefined,
|
||||||
): string {
|
): string {
|
||||||
if (!content || !content.includes("<")) return content;
|
if (!content?.includes("<")) return content;
|
||||||
const parsed = parseRichMessageMetadata(metadata);
|
const parsed = parseRichMessageMetadata(metadata);
|
||||||
const roleName = new Map(
|
const roleName = new Map(
|
||||||
(parsed?.mentionedRoles ?? []).map((r) => [r.id, r.name] as const),
|
(parsed?.mentionedRoles ?? []).map((r) => [r.id, r.name] as const),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
|
import { and, desc, eq, inArray, type SQL } from "drizzle-orm";
|
||||||
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
||||||
import type * as schema from "../../shared/database/schema.js";
|
import type * as schema from "../../shared/database/schema.js";
|
||||||
import { moderationActionsTable } from "../../shared/database/schema.js";
|
import { moderationActionsTable } from "../../shared/database/schema.js";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { and, eq, isNull, or } from "drizzle-orm";
|
import { and, eq, isNull } from "drizzle-orm";
|
||||||
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
||||||
import { createChildLogger, type Logger } from "@/shared/logger/index";
|
import { createChildLogger, type Logger } from "@/shared/logger/index";
|
||||||
import type * as schema from "../../shared/database/schema.js";
|
import type * as schema from "../../shared/database/schema.js";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
|
import { and, desc, eq, inArray, type SQL } from "drizzle-orm";
|
||||||
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
||||||
import type * as schema from "../../shared/database/schema.js";
|
import type * as schema from "../../shared/database/schema.js";
|
||||||
import { messageReviewsTable } from "../../shared/database/schema.js";
|
import { messageReviewsTable } from "../../shared/database/schema.js";
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ export class VoiceTransmitter {
|
|||||||
private gate = Promise.resolve();
|
private gate = Promise.resolve();
|
||||||
/** Set true before sending SIGTERM so exit handler knows it's intentional */
|
/** Set true before sending SIGTERM so exit handler knows it's intentional */
|
||||||
private _expectedExit = false;
|
private _expectedExit = false;
|
||||||
/** True while the underlying stream is in a drain state (backpressure) */
|
|
||||||
private draining = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start listening for PCM audio data from Redis and stream to Discord
|
* Start listening for PCM audio data from Redis and stream to Discord
|
||||||
@@ -179,15 +177,13 @@ export class VoiceTransmitter {
|
|||||||
const canContinue = stream.write(pcmBuffer);
|
const canContinue = stream.write(pcmBuffer);
|
||||||
// Backpressure: queue until drain
|
// Backpressure: queue until drain
|
||||||
if (!canContinue) {
|
if (!canContinue) {
|
||||||
this.draining = true;
|
|
||||||
stream.once("drain", () => {
|
stream.once("drain", () => {
|
||||||
this.draining = false;
|
|
||||||
// Re-acquire stream reference (could have been replaced by restart)
|
|
||||||
const currentStream = this.pcmStream;
|
const currentStream = this.pcmStream;
|
||||||
if (!currentStream || !this.isActive) return;
|
if (!currentStream || !this.isActive) return;
|
||||||
// Flush queued chunks
|
// Flush queued chunks
|
||||||
while (this.backpressureQueue.length > 0) {
|
while (this.backpressureQueue.length > 0) {
|
||||||
const queued = this.backpressureQueue.shift()!;
|
const queued = this.backpressureQueue.shift();
|
||||||
|
if (!queued) break;
|
||||||
try {
|
try {
|
||||||
if (!currentStream.write(queued)) break;
|
if (!currentStream.write(queued)) break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -237,7 +233,6 @@ export class VoiceTransmitter {
|
|||||||
this.isActive = false;
|
this.isActive = false;
|
||||||
|
|
||||||
this.backpressureQueue = [];
|
this.backpressureQueue = [];
|
||||||
this.draining = false;
|
|
||||||
|
|
||||||
if (this.pcmStream) {
|
if (this.pcmStream) {
|
||||||
this.pcmStream.removeAllListeners("drain");
|
this.pcmStream.removeAllListeners("drain");
|
||||||
|
|||||||
Reference in new issue
Block a user