in packages/tiny-agents/src/cli.ts [35:224]
async function main() {
const {
values: { help, version },
positionals,
} = parseArgs({
options: {
help: {
type: "boolean",
short: "h",
},
version: {
type: "boolean",
short: "v",
},
},
allowPositionals: true,
});
if (version) {
console.log(packageVersion);
process.exit(0);
}
const command = positionals[0];
const loadFrom = positionals[1];
if (help) {
console.log(USAGE_HELP);
process.exit(0);
}
if (positionals.length !== 2 || !isValidCommand(command)) {
error(`You need to call run or serve, followed by an agent id (local path or Hub identifier).`);
console.log(USAGE_HELP);
process.exit(1);
}
const { configJson, prompt } = await loadConfigFrom(loadFrom);
const ConfigSchema = z
.object({
model: z.string(),
provider: z.enum(PROVIDERS_OR_POLICIES).optional(),
endpointUrl: z.string().optional(),
apiKey: z.string().optional(),
inputs: z.array(InputConfigSchema).optional(),
servers: z.array(ServerConfigSchema),
})
.refine((data) => data.provider !== undefined || data.endpointUrl !== undefined, {
message: "At least one of 'provider' or 'endpointUrl' is required",
});
let config: z.infer<typeof ConfigSchema>;
try {
const parsedConfig = JSON.parse(configJson);
config = ConfigSchema.parse(parsedConfig);
} catch (err) {
error("Invalid configuration file:", err instanceof Error ? err.message : err);
process.exit(1);
}
// Handle inputs (i.e. env variables injection)
if (config.inputs && config.inputs.length > 0) {
const rl = readline.createInterface({ input: stdin, output: stdout });
stdout.write(ANSI.BLUE);
stdout.write("Some initial inputs are required by the agent. ");
stdout.write("Please provide a value or leave empty to load from env.");
stdout.write(ANSI.RESET);
stdout.write("\n");
for (const inputItem of config.inputs) {
const inputId = inputItem.id;
const description = inputItem.description;
const envSpecialValue = `\${input:${inputId}}`; // Special value to indicate env variable injection
// Check env variables that will use this input
const inputVars = new Set<string>();
for (const server of config.servers) {
if (server.type === "stdio" && server.config.env) {
for (const [key, value] of Object.entries(server.config.env)) {
if (value === envSpecialValue) {
inputVars.add(key);
}
}
}
if ((server.type === "http" || server.type === "sse") && server.config.options?.requestInit?.headers) {
for (const [key, value] of Object.entries(server.config.options.requestInit.headers)) {
if (value.includes(envSpecialValue)) {
inputVars.add(key);
}
}
}
}
if (inputVars.size === 0) {
stdout.write(ANSI.YELLOW);
stdout.write(`Input ${inputId} defined in config but not used by any server.`);
stdout.write(ANSI.RESET);
stdout.write("\n");
continue;
}
// Prompt user for input
stdout.write(ANSI.BLUE);
stdout.write(` • ${inputId}`);
stdout.write(ANSI.RESET);
stdout.write(`: ${description}. (default: load from ${Array.from(inputVars).join(", ")}) `);
const userInput = (await rl.question("")).trim();
// Inject user input (or env variable) into servers' env
for (const server of config.servers) {
if (server.type === "stdio" && server.config.env) {
for (const [key, value] of Object.entries(server.config.env)) {
if (value === envSpecialValue) {
if (userInput) {
server.config.env[key] = userInput;
} else {
const valueFromEnv = process.env[key] || "";
server.config.env[key] = valueFromEnv;
if (valueFromEnv) {
stdout.write(ANSI.GREEN);
stdout.write(`Value successfully loaded from '${key}'`);
stdout.write(ANSI.RESET);
stdout.write("\n");
} else {
stdout.write(ANSI.YELLOW);
stdout.write(`No value found for '${key}' in environment variables. Continuing.`);
stdout.write(ANSI.RESET);
stdout.write("\n");
}
}
}
}
}
if ((server.type === "http" || server.type === "sse") && server.config.options?.requestInit?.headers) {
for (const [key, value] of Object.entries(server.config.options.requestInit.headers)) {
if (value.includes(envSpecialValue)) {
if (userInput) {
server.config.options.requestInit.headers[key] = value.replace(envSpecialValue, userInput);
} else {
const valueFromEnv = process.env[key] || "";
server.config.options.requestInit.headers[key] = value.replace(envSpecialValue, valueFromEnv);
if (valueFromEnv) {
stdout.write(ANSI.GREEN);
stdout.write(`Value successfully loaded from '${key}'`);
stdout.write(ANSI.RESET);
stdout.write("\n");
} else {
stdout.write(ANSI.YELLOW);
stdout.write(`No value found for '${key}' in environment variables. Continuing.`);
stdout.write(ANSI.RESET);
stdout.write("\n");
}
}
}
}
}
}
}
stdout.write("\n");
rl.close();
}
const agent = new Agent(
config.endpointUrl
? {
endpointUrl: config.endpointUrl,
model: config.model,
apiKey: config.apiKey ?? process.env.API_KEY ?? process.env.HF_TOKEN,
servers: config.servers,
prompt,
}
: {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
provider: config.provider!,
model: config.model,
apiKey: config.apiKey ?? process.env.API_KEY ?? process.env.HF_TOKEN,
servers: config.servers,
prompt,
}
);
debug(agent);
await agent.loadTools();
if (command === "run") {
mainCliLoop(agent);
} else {
startServer(agent);
}
}