feat: openrouter byok support through /connect (#735)
This commit is contained in:
@@ -25,6 +25,12 @@ import {
|
||||
OPENAI_CODEX_PROVIDER_NAME,
|
||||
removeOpenAICodexProvider,
|
||||
} from "../../providers/openai-codex-provider";
|
||||
import {
|
||||
createOrUpdateOpenrouterProvider,
|
||||
getOpenrouterProvider,
|
||||
OPENROUTER_PROVIDER_NAME,
|
||||
removeOpenrouterProvider,
|
||||
} from "../../providers/openrouter-provider";
|
||||
import {
|
||||
createOrUpdateZaiProvider,
|
||||
getZaiProvider,
|
||||
@@ -120,7 +126,7 @@ export async function handleConnect(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Usage: /connect <provider> [options]\n\nAvailable providers:\n \u2022 codex - Connect via OAuth to authenticate with ChatGPT Plus/Pro\n \u2022 zai <api_key> - Connect to zAI with your API key\n \u2022 minimax <api_key> - Connect to MiniMax with your API key\n \u2022 bedrock <method> - Connect to AWS Bedrock (iam/profile/default)",
|
||||
"Usage: /connect <provider> [options]\n\nAvailable providers:\n \u2022 codex - Connect via OAuth to authenticate with ChatGPT Plus/Pro\n \u2022 zai <api_key> - Connect to zAI with your API key\n \u2022 minimax <api_key> - Connect to MiniMax with your API key\n \u2022 openrouter <api_key> - Connect to OpenRouter with your API key\n \u2022 bedrock <method> - Connect to AWS Bedrock (iam/profile/default)",
|
||||
false,
|
||||
);
|
||||
return;
|
||||
@@ -130,13 +136,14 @@ export async function handleConnect(
|
||||
provider !== "codex" &&
|
||||
provider !== "zai" &&
|
||||
provider !== "minimax" &&
|
||||
provider !== "openrouter" &&
|
||||
provider !== "bedrock"
|
||||
) {
|
||||
addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
`Error: Unknown provider "${provider}"\n\nAvailable providers: codex, zai, minimax, bedrock\nUsage: /connect <provider> [options]`,
|
||||
`Error: Unknown provider "${provider}"\n\nAvailable providers: codex, zai, minimax, openrouter, bedrock\nUsage: /connect <provider> [options]`,
|
||||
false,
|
||||
);
|
||||
return;
|
||||
@@ -154,6 +161,12 @@ export async function handleConnect(
|
||||
return;
|
||||
}
|
||||
|
||||
// OpenRouter is handled here
|
||||
if (provider === "openrouter") {
|
||||
await handleConnectOpenrouter(ctx, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// Bedrock is handled here
|
||||
if (provider === "bedrock") {
|
||||
await handleConnectBedrock(ctx, msg);
|
||||
@@ -631,7 +644,7 @@ export async function handleDisconnect(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Usage: /disconnect <provider>\n\nAvailable providers: codex, claude, zai, minimax, bedrock",
|
||||
"Usage: /disconnect <provider>\n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock",
|
||||
false,
|
||||
);
|
||||
return;
|
||||
@@ -649,6 +662,12 @@ export async function handleDisconnect(
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle /disconnect openrouter
|
||||
if (provider === "openrouter") {
|
||||
await handleDisconnectOpenrouter(ctx, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle /disconnect bedrock
|
||||
if (provider === "bedrock") {
|
||||
await handleDisconnectBedrock(ctx, msg);
|
||||
@@ -672,7 +691,7 @@ export async function handleDisconnect(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
`Error: Unknown provider "${provider}"\n\nAvailable providers: codex, claude, zai, minimax, bedrock\nUsage: /disconnect <provider>`,
|
||||
`Error: Unknown provider "${provider}"\n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock\nUsage: /disconnect <provider>`,
|
||||
false,
|
||||
);
|
||||
}
|
||||
@@ -956,3 +975,135 @@ export async function handleConnectZai(
|
||||
ctx.setCommandRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /connect openrouter command
|
||||
* Usage: /connect openrouter <api_key>
|
||||
*
|
||||
* Creates the lc-openrouter provider with the provided API key
|
||||
*/
|
||||
export async function handleConnectOpenrouter(
|
||||
ctx: ConnectCommandContext,
|
||||
msg: string,
|
||||
): Promise<void> {
|
||||
const parts = msg.trim().split(/\s+/);
|
||||
// Join all remaining parts in case the API key got split
|
||||
const apiKey = parts.slice(2).join("");
|
||||
|
||||
// If no API key provided, show usage
|
||||
if (!apiKey || apiKey.length === 0) {
|
||||
addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Usage: /connect openrouter <api_key>\n\n" +
|
||||
"Connect to OpenRouter by providing your API key.\n\n" +
|
||||
"Get your API key at https://openrouter.ai/keys\n\n" +
|
||||
"Example: /connect openrouter sk-or-v1-...",
|
||||
false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show running status
|
||||
const cmdId = addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Creating OpenRouter provider...",
|
||||
true,
|
||||
"running",
|
||||
);
|
||||
|
||||
ctx.setCommandRunning(true);
|
||||
|
||||
try {
|
||||
// Create or update the OpenRouter provider with the API key
|
||||
await createOrUpdateOpenrouterProvider(apiKey);
|
||||
|
||||
updateCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
cmdId,
|
||||
msg,
|
||||
`\u2713 Successfully connected to OpenRouter!\n\n` +
|
||||
`Provider '${OPENROUTER_PROVIDER_NAME}' created in Letta.\n\n` +
|
||||
`The models are populated in /model \u2192 "All Available Models"`,
|
||||
true,
|
||||
"finished",
|
||||
);
|
||||
} catch (error) {
|
||||
updateCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
cmdId,
|
||||
msg,
|
||||
`\u2717 Failed to create OpenRouter provider: ${getErrorMessage(error)}`,
|
||||
false,
|
||||
"finished",
|
||||
);
|
||||
} finally {
|
||||
ctx.setCommandRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /disconnect openrouter
|
||||
*/
|
||||
async function handleDisconnectOpenrouter(
|
||||
ctx: ConnectCommandContext,
|
||||
msg: string,
|
||||
): Promise<void> {
|
||||
// Check if OpenRouter provider exists
|
||||
const existing = await getOpenrouterProvider();
|
||||
if (!existing) {
|
||||
addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Not currently connected to OpenRouter.\n\nUse /connect openrouter <api_key> to connect.",
|
||||
false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show running status
|
||||
const cmdId = addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Disconnecting from OpenRouter...",
|
||||
true,
|
||||
"running",
|
||||
);
|
||||
|
||||
ctx.setCommandRunning(true);
|
||||
|
||||
try {
|
||||
// Remove provider from Letta
|
||||
await removeOpenrouterProvider();
|
||||
|
||||
updateCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
cmdId,
|
||||
msg,
|
||||
`\u2713 Disconnected from OpenRouter.\n\n` +
|
||||
`Provider '${OPENROUTER_PROVIDER_NAME}' removed from Letta.`,
|
||||
true,
|
||||
"finished",
|
||||
);
|
||||
} catch (error) {
|
||||
updateCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
cmdId,
|
||||
msg,
|
||||
`\u2717 Failed to disconnect from OpenRouter: ${getErrorMessage(error)}`,
|
||||
false,
|
||||
"finished",
|
||||
);
|
||||
} finally {
|
||||
ctx.setCommandRunning(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user