From 7155e1a48e486abd9918672934e454f876a7d817 Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 21 May 2025 15:38:35 +0200 Subject: [PATCH 1/5] Load tiny-agents from Hub --- packages/tiny-agents/package.json | 1 + packages/tiny-agents/pnpm-lock.yaml | 3 + .../src/agents/evalstate/hf-search/PROMPT.md | 7 - .../src/agents/evalstate/hf-search/agent.json | 12 -- .../evalstate/hf.js-assistant/PROMPT.md | 7 - .../evalstate/hf.js-assistant/agent.json | 12 -- .../flux-schnell-generator/agent.json | 12 -- .../src/agents/julien-c/local-coder/PROMPT.md | 5 - .../agents/julien-c/local-coder/agent.json | 13 -- packages/tiny-agents/src/cli.ts | 133 +++++++++++++----- 10 files changed, 99 insertions(+), 106 deletions(-) delete mode 100644 packages/tiny-agents/src/agents/evalstate/hf-search/PROMPT.md delete mode 100644 packages/tiny-agents/src/agents/evalstate/hf-search/agent.json delete mode 100644 packages/tiny-agents/src/agents/evalstate/hf.js-assistant/PROMPT.md delete mode 100644 packages/tiny-agents/src/agents/evalstate/hf.js-assistant/agent.json delete mode 100644 packages/tiny-agents/src/agents/julien-c/flux-schnell-generator/agent.json delete mode 100644 packages/tiny-agents/src/agents/julien-c/local-coder/PROMPT.md delete mode 100644 packages/tiny-agents/src/agents/julien-c/local-coder/agent.json diff --git a/packages/tiny-agents/package.json b/packages/tiny-agents/package.json index 39df6c0135..29a9942b1d 100644 --- a/packages/tiny-agents/package.json +++ b/packages/tiny-agents/package.json @@ -54,6 +54,7 @@ "@huggingface/inference": "workspace:^", "@huggingface/mcp-client": "workspace:^", "@huggingface/tasks": "workspace:^", + "@huggingface/hub": "workspace:^", "@modelcontextprotocol/sdk": "^1.11.4", "zod": "^3.25.7" } diff --git a/packages/tiny-agents/pnpm-lock.yaml b/packages/tiny-agents/pnpm-lock.yaml index 3e9aca9ca8..7f76c0f22c 100644 --- a/packages/tiny-agents/pnpm-lock.yaml +++ b/packages/tiny-agents/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@huggingface/hub': + specifier: workspace:^ + version: link:../hub '@huggingface/inference': specifier: workspace:^ version: link:../inference diff --git a/packages/tiny-agents/src/agents/evalstate/hf-search/PROMPT.md b/packages/tiny-agents/src/agents/evalstate/hf-search/PROMPT.md deleted file mode 100644 index 6691100959..0000000000 --- a/packages/tiny-agents/src/agents/evalstate/hf-search/PROMPT.md +++ /dev/null @@ -1,7 +0,0 @@ -You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved, or if you need more info from the user to solve the problem. - -If you are not sure about anything pertaining to the user’s request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer. - -You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. - -Help the User find relevant Papers, Models and Spaces (which are hosted, running Models accesible via a User Interface) to aid them with their Machine Learning research. Paper IDs are arXiv identifiers, and are commonly referenced between Papers and Models. diff --git a/packages/tiny-agents/src/agents/evalstate/hf-search/agent.json b/packages/tiny-agents/src/agents/evalstate/hf-search/agent.json deleted file mode 100644 index 7e07596f7f..0000000000 --- a/packages/tiny-agents/src/agents/evalstate/hf-search/agent.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "model": "Qwen/Qwen2.5-72B-Instruct", - "provider": "nebius", - "servers": [ - { - "type": "http", - "config": { - "url": "https://evalstate-hf-mcp-server.hf.space/mcp" - } - } - ] -} diff --git a/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/PROMPT.md b/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/PROMPT.md deleted file mode 100644 index b740872819..0000000000 --- a/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/PROMPT.md +++ /dev/null @@ -1,7 +0,0 @@ -You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved, or if you need more info from the user to solve the problem. - -If you are not sure about anything pertaining to the user’s request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer. - -You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. - -You have access to tools to help you answer questions the User has about the "huggingface.js" repository. The repository contains a number of packages for working with the Hugging Face APIs, Tools and Services. This includes API search functions, inference libraries, LLM Clients and MCP, Agents. diff --git a/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/agent.json b/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/agent.json deleted file mode 100644 index 7e07596f7f..0000000000 --- a/packages/tiny-agents/src/agents/evalstate/hf.js-assistant/agent.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "model": "Qwen/Qwen2.5-72B-Instruct", - "provider": "nebius", - "servers": [ - { - "type": "http", - "config": { - "url": "https://evalstate-hf-mcp-server.hf.space/mcp" - } - } - ] -} diff --git a/packages/tiny-agents/src/agents/julien-c/flux-schnell-generator/agent.json b/packages/tiny-agents/src/agents/julien-c/flux-schnell-generator/agent.json deleted file mode 100644 index fa0c26c148..0000000000 --- a/packages/tiny-agents/src/agents/julien-c/flux-schnell-generator/agent.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "model": "Qwen/Qwen2.5-72B-Instruct", - "provider": "nebius", - "servers": [ - { - "type": "sse", - "config": { - "url": "https://evalstate-flux1-schnell.hf.space/gradio_api/mcp/sse" - } - } - ] -} diff --git a/packages/tiny-agents/src/agents/julien-c/local-coder/PROMPT.md b/packages/tiny-agents/src/agents/julien-c/local-coder/PROMPT.md deleted file mode 100644 index e880614bf2..0000000000 --- a/packages/tiny-agents/src/agents/julien-c/local-coder/PROMPT.md +++ /dev/null @@ -1,5 +0,0 @@ -You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved, or if you need more info from the user to solve the problem. - -If you are not sure about anything pertaining to the user’s request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer. - -You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. diff --git a/packages/tiny-agents/src/agents/julien-c/local-coder/agent.json b/packages/tiny-agents/src/agents/julien-c/local-coder/agent.json deleted file mode 100644 index 31a926839d..0000000000 --- a/packages/tiny-agents/src/agents/julien-c/local-coder/agent.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "model": "Qwen/Qwen2.5-72B-Instruct", - "provider": "nebius", - "servers": [ - { - "type": "stdio", - "config": { - "command": "npx", - "args": ["@playwright/mcp@latest"] - } - } - ] -} diff --git a/packages/tiny-agents/src/cli.ts b/packages/tiny-agents/src/cli.ts index 0722b394f0..690d0e3bfd 100644 --- a/packages/tiny-agents/src/cli.ts +++ b/packages/tiny-agents/src/cli.ts @@ -3,6 +3,7 @@ import { dirname, join } from "node:path"; import { parseArgs } from "node:util"; import { lstat, readFile } from "node:fs/promises"; import { z } from "zod"; +import { downloadFileToCacheDir, type RepoDesignation } from "@huggingface/hub"; import { PROVIDERS_OR_POLICIES } from "@huggingface/inference"; import { Agent } from "@huggingface/mcp-client"; import { version as packageVersion } from "../package.json"; @@ -25,6 +26,11 @@ Flags: -v, --version Show version information `.trim(); +interface TinyAgentConfig { + configJson: string; + prompt?: string; +} + const CLI_COMMANDS = ["run", "serve"] as const; function isValidCommand(command: string): command is (typeof CLI_COMMANDS)[number] { return (CLI_COMMANDS as unknown as string[]).includes(command); @@ -34,51 +40,102 @@ const FILENAME_CONFIG = "agent.json"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const FILENAME_PROMPT = "PROMPT.md"; -async function loadConfigFrom(loadFrom: string): Promise<{ configJson: string; prompt?: string }> { +const TINY_AGENTS_HUB_REPO: RepoDesignation = { + name: "huggingface/tiny-agents", + type: "dataset", +}; + +async function tryLoadFromFile(filePath: string): Promise { + try { + const configJson = await readFile(filePath, { encoding: "utf8" }); + return { configJson }; + } catch { + return undefined; + } +} + +async function tryLoadFromDirectory(dirPath: string): Promise { + const stats = await lstat(dirPath).catch(() => undefined); + if (!stats?.isDirectory()) { + return undefined; + } + + let prompt: string | undefined; + try { + prompt = await readFile(join(dirPath, FILENAME_PROMPT), { encoding: "utf8" }); + } catch { + debug(`PROMPT.md not found in ${dirPath}, continuing without prompt template`); + } + try { - /// First try it as a local file path, then as a local directory, then we will try as a path inside the repo itself return { - configJson: await readFile(loadFrom, { encoding: "utf8" }), + configJson: await readFile(join(dirPath, FILENAME_CONFIG), { encoding: "utf8" }), + prompt, }; } catch { - if ((await lstat(loadFrom)).isDirectory()) { - /// local directory - try { - let prompt: string | undefined; - try { - prompt = await readFile(join(loadFrom, FILENAME_PROMPT), { encoding: "utf8" }); - } catch { - debug(`PROMPT.md not found in ${loadFrom}, continuing without prompt template`); - } - return { - configJson: await readFile(join(loadFrom, FILENAME_CONFIG), { encoding: "utf8" }), - prompt, - }; - } catch { - error(`Config file not found in specified local directory.`); - process.exit(1); - } - } - const srcDir = dirname(__filename); - const configDir = join(srcDir, "agents", loadFrom); - try { - let prompt: string | undefined; - try { - prompt = await readFile(join(configDir, FILENAME_PROMPT), { encoding: "utf8" }); - } catch { - debug(`PROMPT.md not found in ${configDir}, continuing without prompt template`); - } - return { - configJson: await readFile(join(configDir, FILENAME_CONFIG), { encoding: "utf8" }), - prompt, - }; - } catch { - error(`Config file not found in tiny-agents repo! Loading from the HF Hub is not implemented yet`); - process.exit(1); - } + error(`Config file not found in specified local directory.`); + process.exit(1); } } +async function tryLoadFromHub(agentId: string): Promise { + let configJson: string; + try { + const configPath = await downloadFileToCacheDir({ + repo: TINY_AGENTS_HUB_REPO, + path: `${agentId}/${FILENAME_CONFIG}`, + accessToken: process.env.HF_TOKEN, + }); + configJson = await readFile(configPath, { encoding: "utf8" }); + } catch { + return undefined; + } + + let prompt: string | undefined; + try { + const promptPath = await downloadFileToCacheDir({ + repo: TINY_AGENTS_HUB_REPO, + path: `${agentId}/${FILENAME_PROMPT}`, + accessToken: process.env.HF_TOKEN, + }); + prompt = await readFile(promptPath, { encoding: "utf8" }); + } catch { + debug( + `PROMPT.md not found in https://huggingface.co/datasets/huggingface/tiny-agents/tree/main/${agentId}, continuing without prompt template` + ); + } + + return { + configJson, + prompt, + }; +} + +async function loadConfigFrom(loadFrom: string): Promise { + // First try as a local file + const fileConfig = await tryLoadFromFile(loadFrom); + if (fileConfig) { + return fileConfig; + } + + // Then try as a local directory + const dirConfig = await tryLoadFromDirectory(loadFrom); + if (dirConfig) { + return dirConfig; + } + + // Finally try loading from repo + const repoConfig = await tryLoadFromHub(loadFrom); + if (repoConfig) { + return repoConfig; + } + + error( + `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/huggingface/tiny-agents.` + ); + process.exit(1); +} + async function main() { const { values: { help, version }, From b3f41a6fc910578d4a791e57c492ef05aacb3f33 Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 21 May 2025 15:39:33 +0200 Subject: [PATCH 2/5] lint --- packages/tiny-agents/src/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tiny-agents/src/cli.ts b/packages/tiny-agents/src/cli.ts index 690d0e3bfd..02a52513b3 100644 --- a/packages/tiny-agents/src/cli.ts +++ b/packages/tiny-agents/src/cli.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { dirname, join } from "node:path"; +import { join } from "node:path"; import { parseArgs } from "node:util"; import { lstat, readFile } from "node:fs/promises"; import { z } from "zod"; From 33730b60f9304a48e636bc52754c90fa9d74832c Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 21 May 2025 15:47:56 +0200 Subject: [PATCH 3/5] readme --- packages/tiny-agents/README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/tiny-agents/README.md b/packages/tiny-agents/README.md index 487cb48023..472d86a71a 100644 --- a/packages/tiny-agents/README.md +++ b/packages/tiny-agents/README.md @@ -85,10 +85,19 @@ npx @huggingface/tiny-agents run ./my-agent Voilà! 🔥 + +## Tiny Agents collection + +Browse our curated collection of Tiny Agents at https://huggingface.co/datasets/huggingface/tiny-agents. Each agent is stored in its own subdirectory, following the structure outlined above. Running an agent from the Hub is as simple as using its `agent_id`. For example, to run the [`julien-c/flux-schnell-generator`](https://huggingface.co/datasets/huggingface/tiny-agents/tree/main/julien-c/flux-schnell-generator) agent: + +```bash +npx @huggingface/tiny-agents run "julien-c/flux-schnell-generator" +``` + > [!NOTE] -> Note: you can open a PR in the huggingface.js repo to share your agent with the community, just upload it inside the `src/agents/` directory. +> Want to share your own agent with the community? Submit a PR to the [Tiny Agents](https://huggingface.co/datasets/huggingface/tiny-agents/discussions) repository on the Hub. Your submission must include an `agent.json` file, and you can optionally add a `PROMPT.md` file. To help others understand your agent's capabilities, consider including an `EXAMPLES.md` file with sample prompts and use cases. -### Advanced: Programmatic Usage +## Advanced: Programmatic Usage ```typescript import { Agent } from '@huggingface/tiny-agents'; From 51d42231ac3bd5927f23078a7b7764c9cad4c915 Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 21 May 2025 18:53:35 +0200 Subject: [PATCH 4/5] rename default org --- packages/tiny-agents/README.md | 4 ++-- packages/tiny-agents/src/cli.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/tiny-agents/README.md b/packages/tiny-agents/README.md index 472d86a71a..cc15e028bc 100644 --- a/packages/tiny-agents/README.md +++ b/packages/tiny-agents/README.md @@ -88,14 +88,14 @@ Voilà! 🔥 ## Tiny Agents collection -Browse our curated collection of Tiny Agents at https://huggingface.co/datasets/huggingface/tiny-agents. Each agent is stored in its own subdirectory, following the structure outlined above. Running an agent from the Hub is as simple as using its `agent_id`. For example, to run the [`julien-c/flux-schnell-generator`](https://huggingface.co/datasets/huggingface/tiny-agents/tree/main/julien-c/flux-schnell-generator) agent: +Browse our curated collection of Tiny Agents at https://huggingface.co/datasets/tiny-agents/tiny-agents. Each agent is stored in its own subdirectory, following the structure outlined above. Running an agent from the Hub is as simple as using its `agent_id`. For example, to run the [`julien-c/flux-schnell-generator`](https://huggingface.co/datasets/tiny-agents/tiny-agents/tree/main/julien-c/flux-schnell-generator) agent: ```bash npx @huggingface/tiny-agents run "julien-c/flux-schnell-generator" ``` > [!NOTE] -> Want to share your own agent with the community? Submit a PR to the [Tiny Agents](https://huggingface.co/datasets/huggingface/tiny-agents/discussions) repository on the Hub. Your submission must include an `agent.json` file, and you can optionally add a `PROMPT.md` file. To help others understand your agent's capabilities, consider including an `EXAMPLES.md` file with sample prompts and use cases. +> Want to share your own agent with the community? Submit a PR to the [Tiny Agents](https://huggingface.co/datasets/tiny-agents/tiny-agents/discussions) repository on the Hub. Your submission must include an `agent.json` file, and you can optionally add a `PROMPT.md` file. To help others understand your agent's capabilities, consider including an `EXAMPLES.md` file with sample prompts and use cases. ## Advanced: Programmatic Usage diff --git a/packages/tiny-agents/src/cli.ts b/packages/tiny-agents/src/cli.ts index 02a52513b3..b9618ea5ac 100644 --- a/packages/tiny-agents/src/cli.ts +++ b/packages/tiny-agents/src/cli.ts @@ -41,7 +41,7 @@ const FILENAME_CONFIG = "agent.json"; const FILENAME_PROMPT = "PROMPT.md"; const TINY_AGENTS_HUB_REPO: RepoDesignation = { - name: "huggingface/tiny-agents", + name: "tiny-agents/tiny-agents", type: "dataset", }; @@ -101,7 +101,7 @@ async function tryLoadFromHub(agentId: string): Promise { } error( - `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/huggingface/tiny-agents.` + `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/tiny-agents/tiny-agents.` ); process.exit(1); } From d532a69d027677752f1d9c727dcfdc7a0f65672e Mon Sep 17 00:00:00 2001 From: Wauplin Date: Wed, 21 May 2025 18:57:30 +0200 Subject: [PATCH 5/5] move to src/lib/loadConfigFrom.ts --- packages/tiny-agents/src/cli.ts | 109 +----------------- .../tiny-agents/src/lib/loadConfigFrom.ts | 105 +++++++++++++++++ packages/tiny-agents/src/lib/types.ts | 5 + 3 files changed, 111 insertions(+), 108 deletions(-) create mode 100644 packages/tiny-agents/src/lib/loadConfigFrom.ts diff --git a/packages/tiny-agents/src/cli.ts b/packages/tiny-agents/src/cli.ts index b9618ea5ac..2a670ee8d7 100644 --- a/packages/tiny-agents/src/cli.ts +++ b/packages/tiny-agents/src/cli.ts @@ -1,15 +1,13 @@ #!/usr/bin/env node -import { join } from "node:path"; import { parseArgs } from "node:util"; -import { lstat, readFile } from "node:fs/promises"; import { z } from "zod"; -import { downloadFileToCacheDir, type RepoDesignation } from "@huggingface/hub"; import { PROVIDERS_OR_POLICIES } from "@huggingface/inference"; import { Agent } from "@huggingface/mcp-client"; import { version as packageVersion } from "../package.json"; import { ServerConfigSchema } from "./lib/types"; import { debug, error } from "./lib/utils"; import { mainCliLoop } from "./lib/mainCliLoop"; +import { loadConfigFrom } from "./lib/loadConfigFrom"; const USAGE_HELP = ` Usage: @@ -26,116 +24,11 @@ Flags: -v, --version Show version information `.trim(); -interface TinyAgentConfig { - configJson: string; - prompt?: string; -} - const CLI_COMMANDS = ["run", "serve"] as const; function isValidCommand(command: string): command is (typeof CLI_COMMANDS)[number] { return (CLI_COMMANDS as unknown as string[]).includes(command); } -const FILENAME_CONFIG = "agent.json"; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const FILENAME_PROMPT = "PROMPT.md"; - -const TINY_AGENTS_HUB_REPO: RepoDesignation = { - name: "tiny-agents/tiny-agents", - type: "dataset", -}; - -async function tryLoadFromFile(filePath: string): Promise { - try { - const configJson = await readFile(filePath, { encoding: "utf8" }); - return { configJson }; - } catch { - return undefined; - } -} - -async function tryLoadFromDirectory(dirPath: string): Promise { - const stats = await lstat(dirPath).catch(() => undefined); - if (!stats?.isDirectory()) { - return undefined; - } - - let prompt: string | undefined; - try { - prompt = await readFile(join(dirPath, FILENAME_PROMPT), { encoding: "utf8" }); - } catch { - debug(`PROMPT.md not found in ${dirPath}, continuing without prompt template`); - } - - try { - return { - configJson: await readFile(join(dirPath, FILENAME_CONFIG), { encoding: "utf8" }), - prompt, - }; - } catch { - error(`Config file not found in specified local directory.`); - process.exit(1); - } -} - -async function tryLoadFromHub(agentId: string): Promise { - let configJson: string; - try { - const configPath = await downloadFileToCacheDir({ - repo: TINY_AGENTS_HUB_REPO, - path: `${agentId}/${FILENAME_CONFIG}`, - accessToken: process.env.HF_TOKEN, - }); - configJson = await readFile(configPath, { encoding: "utf8" }); - } catch { - return undefined; - } - - let prompt: string | undefined; - try { - const promptPath = await downloadFileToCacheDir({ - repo: TINY_AGENTS_HUB_REPO, - path: `${agentId}/${FILENAME_PROMPT}`, - accessToken: process.env.HF_TOKEN, - }); - prompt = await readFile(promptPath, { encoding: "utf8" }); - } catch { - debug( - `PROMPT.md not found in https://huggingface.co/datasets/tiny-agents/tiny-agents/tree/main/${agentId}, continuing without prompt template` - ); - } - - return { - configJson, - prompt, - }; -} - -async function loadConfigFrom(loadFrom: string): Promise { - // First try as a local file - const fileConfig = await tryLoadFromFile(loadFrom); - if (fileConfig) { - return fileConfig; - } - - // Then try as a local directory - const dirConfig = await tryLoadFromDirectory(loadFrom); - if (dirConfig) { - return dirConfig; - } - - // Finally try loading from repo - const repoConfig = await tryLoadFromHub(loadFrom); - if (repoConfig) { - return repoConfig; - } - - error( - `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/tiny-agents/tiny-agents.` - ); - process.exit(1); -} - async function main() { const { values: { help, version }, diff --git a/packages/tiny-agents/src/lib/loadConfigFrom.ts b/packages/tiny-agents/src/lib/loadConfigFrom.ts new file mode 100644 index 0000000000..7396f110df --- /dev/null +++ b/packages/tiny-agents/src/lib/loadConfigFrom.ts @@ -0,0 +1,105 @@ +#!/usr/bin/env node +import { join } from "node:path"; +import { lstat, readFile } from "node:fs/promises"; +import { downloadFileToCacheDir, type RepoDesignation } from "@huggingface/hub"; +import type { TinyAgentConfig } from "./types"; +import { debug, error } from "./utils"; + +const FILENAME_CONFIG = "agent.json"; +const FILENAME_PROMPT = "PROMPT.md"; + +const TINY_AGENTS_HUB_REPO: RepoDesignation = { + name: "tiny-agents/tiny-agents", + type: "dataset", +}; + +async function tryLoadFromFile(filePath: string): Promise { + try { + const configJson = await readFile(filePath, { encoding: "utf8" }); + return { configJson }; + } catch { + return undefined; + } +} + +async function tryLoadFromDirectory(dirPath: string): Promise { + const stats = await lstat(dirPath).catch(() => undefined); + if (!stats?.isDirectory()) { + return undefined; + } + + let prompt: string | undefined; + try { + prompt = await readFile(join(dirPath, FILENAME_PROMPT), { encoding: "utf8" }); + } catch { + debug(`PROMPT.md not found in ${dirPath}, continuing without prompt template`); + } + + try { + return { + configJson: await readFile(join(dirPath, FILENAME_CONFIG), { encoding: "utf8" }), + prompt, + }; + } catch { + error(`Config file not found in specified local directory.`); + process.exit(1); + } +} + +async function tryLoadFromHub(agentId: string): Promise { + let configJson: string; + try { + const configPath = await downloadFileToCacheDir({ + repo: TINY_AGENTS_HUB_REPO, + path: `${agentId}/${FILENAME_CONFIG}`, + accessToken: process.env.HF_TOKEN, + }); + configJson = await readFile(configPath, { encoding: "utf8" }); + } catch { + return undefined; + } + + let prompt: string | undefined; + try { + const promptPath = await downloadFileToCacheDir({ + repo: TINY_AGENTS_HUB_REPO, + path: `${agentId}/${FILENAME_PROMPT}`, + accessToken: process.env.HF_TOKEN, + }); + prompt = await readFile(promptPath, { encoding: "utf8" }); + } catch { + debug( + `PROMPT.md not found in https://huggingface.co/datasets/tiny-agents/tiny-agents/tree/main/${agentId}, continuing without prompt template` + ); + } + + return { + configJson, + prompt, + }; +} + +export async function loadConfigFrom(loadFrom: string): Promise { + // First try as a local file + const fileConfig = await tryLoadFromFile(loadFrom); + if (fileConfig) { + return fileConfig; + } + + // Then try as a local directory + const dirConfig = await tryLoadFromDirectory(loadFrom); + if (dirConfig) { + return dirConfig; + } + + // Finally try loading from repo + const repoConfig = await tryLoadFromHub(loadFrom); + if (repoConfig) { + return repoConfig; + } + + error( + `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/tiny-agents/tiny-agents.` + ); + process.exit(1); +} diff --git a/packages/tiny-agents/src/lib/types.ts b/packages/tiny-agents/src/lib/types.ts index 6c3d7bce85..a2c6bf3d35 100644 --- a/packages/tiny-agents/src/lib/types.ts +++ b/packages/tiny-agents/src/lib/types.ts @@ -1,5 +1,10 @@ import { z } from "zod"; +export interface TinyAgentConfig { + configJson: string; + prompt?: string; +} + export const ServerConfigSchema = z.discriminatedUnion("type", [ z.object({ type: z.literal("stdio"),