mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(platform): address review feedback on copilot-bot service
- Fix .env.example: AUTOGPT_BOT_API_KEY → PLATFORM_BOT_API_KEY - Replace all any types with proper Chat SDK types (Thread, Message, Adapter) - Fix gateway duration: 10min → 9min to match cron interval - Add startup validation for critical env vars in production - Fix error handling: use unknown catch type with instanceof checks
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# ── AutoGPT Platform API ──────────────────────────────────────────────
|
||||
AUTOGPT_API_URL=http://localhost:8006
|
||||
# Service API key for bot-facing endpoints (TODO: implement in backend)
|
||||
# AUTOGPT_BOT_API_KEY=
|
||||
# Service API key for bot-facing endpoints (must match backend PLATFORM_BOT_API_KEY)
|
||||
# PLATFORM_BOT_API_KEY=
|
||||
|
||||
# ── Discord ───────────────────────────────────────────────────────────
|
||||
DISCORD_BOT_TOKEN=
|
||||
|
||||
@@ -28,7 +28,7 @@ export async function GET(request: Request) {
|
||||
|
||||
const baseUrl = process.env.WEBHOOK_BASE_URL ?? "http://localhost:3000";
|
||||
const webhookUrl = `${baseUrl}/api/webhooks/discord`;
|
||||
const durationMs = 10 * 60 * 1000; // 10 minutes
|
||||
const durationMs = 9 * 60 * 1000; // 9 minutes (matches cron interval)
|
||||
|
||||
return (discord as any).startGatewayListener(
|
||||
{},
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* - Streaming responses back to the user
|
||||
*/
|
||||
|
||||
import { Chat } from "chat";
|
||||
import type { StateAdapter } from "chat";
|
||||
import { Chat, Message } from "chat";
|
||||
import type { Adapter, StateAdapter, Thread } from "chat";
|
||||
import { PlatformAPI } from "./platform-api.js";
|
||||
import type { Config } from "./config.js";
|
||||
|
||||
@@ -22,11 +22,13 @@ export interface BotThreadState {
|
||||
pendingLinkToken?: string;
|
||||
}
|
||||
|
||||
type BotThread = Thread<BotThreadState>;
|
||||
|
||||
export async function createBot(config: Config, stateAdapter: StateAdapter) {
|
||||
const api = new PlatformAPI(config.autogptApiUrl);
|
||||
|
||||
// Build adapters based on config
|
||||
const adapters: Record<string, any> = {};
|
||||
const adapters: Record<string, Adapter> = {};
|
||||
|
||||
if (config.discord) {
|
||||
const { createDiscordAdapter } = await import("@chat-adapter/discord");
|
||||
@@ -118,9 +120,9 @@ export async function createBot(config: Config, stateAdapter: StateAdapter) {
|
||||
|
||||
/**
|
||||
* Get the adapter/platform name from a thread.
|
||||
* Thread ID format is "adapter:channel:thread".
|
||||
*/
|
||||
function getAdapterName(thread: any): string {
|
||||
// Thread ID format is "adapter:channel:thread"
|
||||
function getAdapterName(thread: BotThread): string {
|
||||
const parts = thread.id.split(":");
|
||||
return parts[0] ?? "unknown";
|
||||
}
|
||||
@@ -129,8 +131,8 @@ function getAdapterName(thread: any): string {
|
||||
* Handle an unlinked user — create a link token and send them a prompt.
|
||||
*/
|
||||
async function handleUnlinkedUser(
|
||||
thread: any,
|
||||
message: any,
|
||||
thread: BotThread,
|
||||
message: Message,
|
||||
platform: string,
|
||||
api: PlatformAPI
|
||||
) {
|
||||
@@ -142,7 +144,7 @@ async function handleUnlinkedUser(
|
||||
const linkResult = await api.createLinkToken({
|
||||
platform,
|
||||
platformUserId: message.author.userId,
|
||||
platformUsername: message.author.fullName ?? message.author.username,
|
||||
platformUsername: message.author.fullName ?? message.author.userName,
|
||||
});
|
||||
|
||||
await thread.post(
|
||||
@@ -153,8 +155,9 @@ async function handleUnlinkedUser(
|
||||
|
||||
// Store the pending token so we could poll later if needed
|
||||
await thread.setState({ pendingLinkToken: linkResult.token });
|
||||
} catch (err: any) {
|
||||
if (err.message?.includes("409")) {
|
||||
} catch (err: unknown) {
|
||||
const errMsg = err instanceof Error ? err.message : String(err);
|
||||
if (errMsg.includes("409")) {
|
||||
// Already linked (race condition) — retry resolve
|
||||
const resolved = await api.resolve(platform, message.author.userId);
|
||||
if (resolved.linked) {
|
||||
@@ -181,7 +184,7 @@ async function handleUnlinkedUser(
|
||||
* Forward a message to CoPilot and stream the response back.
|
||||
*/
|
||||
async function handleCoPilotMessage(
|
||||
thread: any,
|
||||
thread: BotThread,
|
||||
text: string,
|
||||
userId: string,
|
||||
api: PlatformAPI
|
||||
@@ -203,11 +206,12 @@ async function handleCoPilotMessage(
|
||||
console.log(`[bot] Created session ${sessionId} for user ${userId.slice(-8)}`);
|
||||
}
|
||||
|
||||
// Stream CoPilot response directly to the chat platform
|
||||
// Stream CoPilot response — thread.post() accepts AsyncIterable<string>
|
||||
const stream = api.streamChat(userId, text, sessionId);
|
||||
await thread.post(stream);
|
||||
} catch (err: any) {
|
||||
console.error(`[bot] CoPilot error for user ${userId.slice(-8)}:`, err.message);
|
||||
} catch (err: unknown) {
|
||||
const errMsg = err instanceof Error ? err.message : String(err);
|
||||
console.error(`[bot] CoPilot error for user ${userId.slice(-8)}:`, errMsg);
|
||||
await thread.post(
|
||||
"Sorry, I ran into an issue processing your message. Please try again."
|
||||
);
|
||||
|
||||
@@ -14,6 +14,24 @@ export interface Config {
|
||||
}
|
||||
|
||||
export function loadConfig(): Config {
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
if (isProduction) {
|
||||
requireEnv("PLATFORM_BOT_API_KEY");
|
||||
|
||||
const hasAdapter =
|
||||
!!process.env.DISCORD_BOT_TOKEN ||
|
||||
!!process.env.TELEGRAM_BOT_TOKEN ||
|
||||
!!process.env.SLACK_BOT_TOKEN;
|
||||
|
||||
if (!hasAdapter) {
|
||||
throw new Error(
|
||||
"Production requires at least one adapter token: " +
|
||||
"DISCORD_BOT_TOKEN, TELEGRAM_BOT_TOKEN, or SLACK_BOT_TOKEN"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
autogptApiUrl: env("AUTOGPT_API_URL", "http://localhost:8006"),
|
||||
discord: !!process.env.DISCORD_BOT_TOKEN,
|
||||
@@ -26,3 +44,11 @@ export function loadConfig(): Config {
|
||||
function env(key: string, fallback: string): string {
|
||||
return process.env[key] ?? fallback;
|
||||
}
|
||||
|
||||
function requireEnv(key: string): string {
|
||||
const value = process.env[key];
|
||||
if (!value) {
|
||||
throw new Error(`Missing required environment variable: ${key}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user