Skip to content

Commit

Permalink
feat: set proxy by env AGENT_PROXY (elizaOS#3751)
Browse files Browse the repository at this point in the history
* set proxy by  env AGENT_PROXY

* remove twitter client, cause it's not a must dependency.

---------

Co-authored-by: Odilitime <[email protected]>
  • Loading branch information
v1xingyue and odilitime authored Mar 3, 2025
1 parent 3bd9609 commit 5aee0e0
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 56 deletions.
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -1004,4 +1004,8 @@ DATA_AUTH_TOKEN= # Your d.a.t.a auth token

# NKN Configuration
NKN_CLIENT_PRIVATE_KEY= # Required, NKN client private key
NKN_CLIENT_ID= # Optional, NKN client ID
NKN_CLIENT_ID= # Optional, NKN client ID

# setting global proxy for all agents
#AGENT_PROXY=http://127.0.0.1:7890
AGENT_PROXY=
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@types/node": "^22.13.5",
"json5": "2.2.3",
"ts-node": "^10.9.2",
"undici": "^7.4.0",
"yargs": "17.7.2"
},
"devDependencies": {
Expand Down
171 changes: 116 additions & 55 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DirectClient } from "@elizaos/client-direct";
import { ProxyAgent, setGlobalDispatcher } from "undici";
import {
type Adapter,
AgentRuntime,
Expand All @@ -22,7 +23,7 @@ import {
import { defaultCharacter } from "./defaultCharacter.ts";

import { bootstrapPlugin } from "@elizaos/plugin-bootstrap";
import JSON5 from 'json5';
import JSON5 from "json5";

import fs from "fs";
import net from "net";
Expand All @@ -31,9 +32,6 @@ import path from "path";
import { fileURLToPath } from "url";
import yargs from "yargs";

const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const __dirname = path.dirname(__filename); // get the name of the directory

export const wait = (minTime = 1000, maxTime = 3000) => {
const waitTime =
Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;
Expand Down Expand Up @@ -215,12 +213,24 @@ async function jsonToCharacter(
}
// Handle plugins
character.plugins = await handlePluginImporting(character.plugins);
elizaLogger.info(character.name, 'loaded plugins:', "[\n " + character.plugins.map(p => `"${p.npmName}"`).join(", \n ") + "\n]");
elizaLogger.info(
character.name,
"loaded plugins:",
"[\n " +
character.plugins.map((p) => `"${p.npmName}"`).join(", \n ") +
"\n]"
);

// Handle Post Processors plugins
if (character.postProcessors?.length > 0) {
elizaLogger.info(character.name, 'loading postProcessors', character.postProcessors);
character.postProcessors = await handlePluginImporting(character.postProcessors);
elizaLogger.info(
character.name,
"loading postProcessors",
character.postProcessors
);
character.postProcessors = await handlePluginImporting(
character.postProcessors
);
}

// Handle extends
Expand Down Expand Up @@ -297,7 +307,9 @@ async function loadCharacterTryPath(characterPath: string): Promise<Character> {
}
try {
const character: Character = await loadCharacter(resolvedPath);
elizaLogger.success(`Successfully loaded character from: ${resolvedPath}`);
elizaLogger.success(
`Successfully loaded character from: ${resolvedPath}`
);
return character;
} catch (e) {
console.error(`Error parsing character from ${resolvedPath}: `, e);
Expand Down Expand Up @@ -376,19 +388,28 @@ async function handlePluginImporting(plugins: string[]) {
const importedPlugins = await Promise.all(
plugins.map(async (plugin) => {
try {
const importedPlugin:Plugin = await import(plugin);
const importedPlugin: Plugin = await import(plugin);
const functionName =
plugin
.replace("@elizaos/plugin-", "")
.replace("@elizaos-plugins/plugin-", "")
.replace(/-./g, (x) => x[1].toUpperCase()) +
"Plugin"; // Assumes plugin function is camelCased with Plugin suffix
if (!importedPlugin[functionName] && !importedPlugin.default) {
elizaLogger.warn(plugin, 'does not have an default export or', functionName)
if (
!importedPlugin[functionName] &&
!importedPlugin.default
) {
elizaLogger.warn(
plugin,
"does not have an default export or",
functionName
);
}
return {...(
importedPlugin.default || importedPlugin[functionName]
), npmName: plugin };
return {
...(importedPlugin.default ||
importedPlugin[functionName]),
npmName: plugin,
};
} catch (importError) {
console.error(
`Failed to import plugin: ${plugin}`,
Expand All @@ -397,9 +418,9 @@ async function handlePluginImporting(plugins: string[]) {
return false; // Return null for failed imports
}
})
)
);
// remove plugins that failed to load, so agent can try to start
return importedPlugins.filter(p => !!p);
return importedPlugins.filter((p) => !!p);
} else {
return [];
}
Expand Down Expand Up @@ -569,7 +590,12 @@ export function getTokenForProvider(
);
case ModelProviderName.NEARAI:
try {
const config = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.nearai/config.json'), 'utf8'));
const config = JSON.parse(
fs.readFileSync(
path.join(os.homedir(), ".nearai/config.json"),
"utf8"
)
);
return JSON.stringify(config?.auth);
} catch (e) {
elizaLogger.warn(`Error loading NEAR AI config: ${e}`);
Expand Down Expand Up @@ -602,9 +628,7 @@ export async function initializeClients(
if (plugin.clients) {
for (const client of plugin.clients) {
const startedClient = await client.start(runtime);
elizaLogger.debug(
`Initializing client: ${client.name}`
);
elizaLogger.debug(`Initializing client: ${client.name}`);
clients.push(startedClient);
}
}
Expand All @@ -625,11 +649,7 @@ export async function createAgent(
evaluators: [],
character,
// character.plugins are handled when clients are added
plugins: [
bootstrapPlugin,
]
.flat()
.filter(Boolean),
plugins: [bootstrapPlugin].flat().filter(Boolean),
providers: [],
managers: [],
fetch: logFetch,
Expand Down Expand Up @@ -709,23 +729,29 @@ function initializeCache(
}

async function findDatabaseAdapter(runtime: AgentRuntime) {
const { adapters } = runtime;
let adapter: Adapter | undefined;
// if not found, default to sqlite
if (adapters.length === 0) {
const sqliteAdapterPlugin = await import('@elizaos-plugins/adapter-sqlite');
const sqliteAdapterPluginDefault = sqliteAdapterPlugin.default;
adapter = sqliteAdapterPluginDefault.adapters[0];
if (!adapter) {
throw new Error("Internal error: No database adapter found for default adapter-sqlite");
}
} else if (adapters.length === 1) {
adapter = adapters[0];
} else {
throw new Error("Multiple database adapters found. You must have no more than one. Adjust your plugins configuration.");
const { adapters } = runtime;
let adapter: Adapter | undefined;
// if not found, default to sqlite
if (adapters.length === 0) {
const sqliteAdapterPlugin = await import(
"@elizaos-plugins/adapter-sqlite"
);
const sqliteAdapterPluginDefault = sqliteAdapterPlugin.default;
adapter = sqliteAdapterPluginDefault.adapters[0];
if (!adapter) {
throw new Error(
"Internal error: No database adapter found for default adapter-sqlite"
);
}
} else if (adapters.length === 1) {
adapter = adapters[0];
} else {
throw new Error(
"Multiple database adapters found. You must have no more than one. Adjust your plugins configuration."
);
}
const adapterInterface = adapter?.init(runtime);
return adapterInterface;
const adapterInterface = adapter?.init(runtime);
return adapterInterface;
}

async function startAgent(
Expand All @@ -739,10 +765,7 @@ async function startAgent(

const token = getTokenForProvider(character.modelProvider, character);

const runtime: AgentRuntime = await createAgent(
character,
token
);
const runtime: AgentRuntime = await createAgent(character, token);

// initialize database
// find a db from the plugins
Expand Down Expand Up @@ -812,21 +835,29 @@ const hasValidRemoteUrls = () =>
* Post processing of character after loading
* @param character
*/
const handlePostCharacterLoaded = async (character: Character): Promise<Character> => {
const handlePostCharacterLoaded = async (
character: Character
): Promise<Character> => {
let processedCharacter = character;
// Filtering the plugins with the method of handlePostCharacterLoaded
const processors = character?.postProcessors?.filter(p => typeof p.handlePostCharacterLoaded === 'function');
const processors = character?.postProcessors?.filter(
(p) => typeof p.handlePostCharacterLoaded === "function"
);
if (processors?.length > 0) {
processedCharacter = Object.assign({}, character, { postProcessors: undefined });
processedCharacter = Object.assign({}, character, {
postProcessors: undefined,
});
// process the character with each processor
// the order is important, so we loop through the processors
for (let i = 0; i < processors.length; i++) {
const processor = processors[i];
processedCharacter = await processor.handlePostCharacterLoaded(processedCharacter);
processedCharacter = await processor.handlePostCharacterLoaded(
processedCharacter
);
}
}
return processedCharacter;
}
};

const startAgents = async () => {
const directClient = new DirectClient();
Expand All @@ -835,13 +866,15 @@ const startAgents = async () => {
const charactersArg = args.characters || args.character;
let characters = [defaultCharacter];

if ((charactersArg) || hasValidRemoteUrls()) {
if (charactersArg || hasValidRemoteUrls()) {
characters = await loadCharacters(charactersArg);
}

try {
for (const character of characters) {
const processedCharacter = await handlePostCharacterLoaded(character);
const processedCharacter = await handlePostCharacterLoaded(
character
);
await startAgent(processedCharacter, directClient);
}
} catch (error) {
Expand All @@ -861,12 +894,24 @@ const startAgents = async () => {
directClient.startAgent = async (character) => {
// Handle plugins
character.plugins = await handlePluginImporting(character.plugins);
elizaLogger.info(character.name, 'loaded plugins:', '[' + character.plugins.map(p => `"${p.npmName}"`).join(', ') + ']');
elizaLogger.info(
character.name,
"loaded plugins:",
"[" +
character.plugins.map((p) => `"${p.npmName}"`).join(", ") +
"]"
);

// Handle Post Processors plugins
if (character.postProcessors?.length > 0) {
elizaLogger.info(character.name, 'loading postProcessors', character.postProcessors);
character.postProcessors = await handlePluginImporting(character.postProcessors);
elizaLogger.info(
character.name,
"loading postProcessors",
character.postProcessors
);
character.postProcessors = await handlePluginImporting(
character.postProcessors
);
}
// character's post processing
const processedCharacter = await handlePostCharacterLoaded(character);
Expand All @@ -889,6 +934,22 @@ const startAgents = async () => {
);
};

const setProxy = () => {
const proxy = process.env.AGENT_PROXY;
if (proxy) {
elizaLogger.info("start agents use proxy : ", proxy);
const proxyAgent = new ProxyAgent(proxy);
setGlobalDispatcher(proxyAgent);
}
};

// begin start agents

setProxy();

const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const __dirname = path.dirname(__filename); // get the name of the directory

startAgents().catch((error) => {
elizaLogger.error("Unhandled error in startAgents:", error);
process.exit(1);
Expand Down

0 comments on commit 5aee0e0

Please sign in to comment.