Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 57 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# Eremos

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
![TypeScript](https://img.shields.io/badge/language-TypeScript-3178C6?logo=typescript&logoColor=white)
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)
[![Follow on X](https://img.shields.io/badge/follow-@EremosCore-000000?logo=x)](https://x.com/EremosCore)

![Eremos](docs/banner2.png)

**Autonomous swarm agents for early on-chain signal detection**

Eremos is a lightweight framework for deploying modular agents that monitor blockchain activity - tracking wallet clusters, mint patterns, and contract anomalies.
Eremos is a lightweight framework for deploying modular agents that monitor blockchain activity tracking wallet clusters, mint patterns, and contract anomalies.
Designed for devs who want low-noise, early signals embedded into their workflows.

---
Expand All @@ -23,6 +28,22 @@ Modular and extendable by design.*

---

## Table of Contents

- [Features](#features)
- [Quick Links](#quick-links)
- [Example Signal](#example-signal)
- [Signal Confidence](#signal-confidence)
- [Tech Stack](#tech-stack)
- [Getting Started](#getting-started)
- [Key Folders](#key-folders)
- [Common Commands](#common-commands)
- [Contributing](#contributing)
- [License](#license)
- [Links](#links)

---

## Features

- **Modular Agents** - Scoped logic for detecting wallet activity, contract spawns, and anomalies
Expand All @@ -35,6 +56,20 @@ Modular and extendable by design.*
- *+ More to come.*


---

## Quick Links

- **Docs**: [`/docs`](./docs)
- **Architecture**: [`/docs/architecture.md`](./docs/architecture.md)
- **Agents**: [`/docs/agents.md`](./docs/agents.md)
- **Signals**: [`/docs/signals.md`](./docs/signals.md)
- **Metrics**: [`/docs/metrics.md`](./docs/metrics.md)
- **Events**: [`/docs/events.md`](./docs/events.md)
- **Deployment**: [`/docs/deployment.md`](./docs/deployment.md)
- **Contributing**: [`/docs/contributing.md`](./docs/contributing.md)
- **Whitepaper (v1.0)**: [`/docs/whitepaper.pdf`](./docs/whitepaper.pdf)

---

## Example Signal
Expand Down Expand Up @@ -75,10 +110,9 @@ Confidence is computed via agent-side scoring and logged alongside the signal.

## Tech Stack

- **Frontend:** Next.js, Tailwind CSS
- **Backend:** Node.js (TypeScript-based agent runner)
- **Language:** TypeScript (typed logic across agents, utils, and infra)
- **Chain Layer:** RPC watchers, mempool filters, native triggers
- **Runtime:** Node.js (TypeScript-based agent runner)
- **Chain Layer:** Solana RPC watchers, mempool filters, native triggers

---

Expand All @@ -90,10 +124,9 @@ cd Eremos
npm install
```

Set up your environment:
Run a local development agent:

```bash
cp .env.example .env.local
npm run dev
```

Expand All @@ -109,6 +142,24 @@ npm run dev

---

## Common Commands

```bash
# List available agents
npm run agents:list

# Run the example dev agent
npm run agent:dev

# Generate a new agent scaffold
npm run agent:generate MyAgent

# Validate an agent implementation
npm run agent:validate
```

---

## Contributing

We’re open to contributors.
Expand Down
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
"description": "Modular agent framework for on-chain activity monitoring.",
"main": "index.js",
"scripts": {
"dev": "echo 'Running dev mode...'"
"dev": "tsx scripts/dev-agent.ts",
"agents:list": "tsx scripts/agent-list.ts",
"agent:dev": "tsx scripts/dev-agent.ts",
"agent:generate": "tsx scripts/generate-agent.ts",
"agent:validate": "tsx scripts/validate-agent.ts || echo 'validate script not yet implemented'"
},
"keywords": [
"agent",
Expand All @@ -14,5 +18,9 @@
"framework"
],
"license": "MIT",
"author": "EremosCore"
"author": "EremosCore",
"devDependencies": {
"tsx": "^4.19.0",
"typescript": "^5.4.0"
}
}
24 changes: 19 additions & 5 deletions scripts/agent-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@ import * as fs from "fs";
import * as path from "path";

const agentsPath = path.join(__dirname, "../agents");
const agentFiles = fs.readdirSync(agentsPath);
const agentFiles = fs
.readdirSync(agentsPath)
.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));

agentFiles.forEach(file => {
const agent = require(path.join(agentsPath, file));
console.log(`${agent.name || file.replace(".ts", "")} (${agent.id}) - ${agent.description}`);
});
for (const file of agentFiles) {
const full = path.join(agentsPath, file);
try {
// Support both ESM transpiled and TS via tsx
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mod = require(full);
const exportKeys = Object.keys(mod);
const exported = exportKeys.length === 1 ? mod[exportKeys[0]] : mod.ExampleAgent || mod.default || mod;
const name = exported?.name ?? path.basename(file, path.extname(file));
const id = exported?.id ?? "unknown";
const desc = exported?.description ?? "(no description)";
console.log(`${name} (${id}) - ${desc}`);
} catch (err) {
console.error(`Failed to load agent from ${file}:`, (err as Error).message);
}
}
32 changes: 28 additions & 4 deletions scripts/generate-agent.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import fs from 'fs';
import path from 'path';

const name = process.argv[2];
if (!name) throw new Error("Please specify agent name.");

const content = `export const ${name} = {
const targetPath = path.join(process.cwd(), 'agents', `${name.toLowerCase()}.ts`);
if (fs.existsSync(targetPath)) {
throw new Error(`Agent file already exists: ${targetPath}`);
}

const content = `import { Agent } from "../types/agent";
import { generateSignalHash } from "../utils/signal";
import { logSignal } from "../utils/logger";

export const ${name}: Agent = {
id: "${name.toLowerCase()}",
name: "${name}",
...
};`;
role: "template",
glyph: "?",
watchType: "wallet_activity",
triggerThreshold: 3,
lastSignal: null,
originTimestamp: new Date().toISOString(),
description: "${name} agent",
observe: (event) => {
if (!event) return;
const hash = generateSignalHash(event);
logSignal({ agent: "${name}", type: "observe", glyph: "?", hash, timestamp: new Date().toISOString() });
},
getMemory: () => [],
};
`;

fs.writeFileSync(`agents/${name.toLowerCase()}.ts`, content);
fs.writeFileSync(targetPath, content, 'utf8');
console.log(`Created ${targetPath}`);
56 changes: 56 additions & 0 deletions scripts/validate-agent.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
import * as fs from "fs";
import * as path from "path";

type ValidationIssue = { file: string; message: string };

const agentsDir = path.join(__dirname, "../agents");
const files = fs
.readdirSync(agentsDir)
.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));

const issues: ValidationIssue[] = [];

for (const file of files) {
const full = path.join(agentsDir, file);
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mod = require(full);
const exportKeys = Object.keys(mod);
const agent = exportKeys.length === 1 ? mod[exportKeys[0]] : mod.default || mod.ExampleAgent || mod;

const required = [
"id",
"name",
"role",
"glyph",
"watchType",
"triggerThreshold",
"originTimestamp",
"description",
"observe",
];
for (const key of required) {
if (!(key in agent)) {
issues.push({ file, message: `Missing required field: ${key}` });
}
}

if (typeof agent.observe !== "function") {
issues.push({ file, message: `observe must be a function` });
}
} catch (e) {
issues.push({ file, message: `Failed to load: ${(e as Error).message}` });
}
}

if (issues.length === 0) {
console.log("All agents look valid.");
process.exit(0);
} else {
console.error("Validation issues found:\n");
for (const issue of issues) {
console.error(`- ${issue.file}: ${issue.message}`);
}
process.exit(1);
}

import { Agent } from "../types/agent";
import fs from "fs";

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"include": ["./agents", "./types", "./utils"]
"include": ["./agents", "./types", "./utils", "./scripts"]
}