@anonx3247/universal-agent-harness 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/agent-harness.d.ts +3 -0
- package/dist/agent-harness.d.ts.map +1 -0
- package/dist/agent-harness.js +326 -0
- package/dist/agent-harness.js.map +1 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +11 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +335 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +39 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +156 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/assert.d.ts +2 -0
- package/dist/lib/assert.d.ts.map +1 -0
- package/dist/lib/assert.js +4 -0
- package/dist/lib/assert.js.map +1 -0
- package/dist/lib/async.d.ts +18 -0
- package/dist/lib/async.d.ts.map +1 -0
- package/dist/lib/async.js +41 -0
- package/dist/lib/async.js.map +1 -0
- package/dist/lib/error.d.ts +47 -0
- package/dist/lib/error.d.ts.map +1 -0
- package/dist/lib/error.js +101 -0
- package/dist/lib/error.js.map +1 -0
- package/dist/lib/fs.d.ts +3 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +17 -0
- package/dist/lib/fs.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +62 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +80 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/mcp.d.ts +19 -0
- package/dist/lib/mcp.d.ts.map +1 -0
- package/dist/lib/mcp.js +105 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/prompts.d.ts +5 -0
- package/dist/lib/prompts.d.ts.map +1 -0
- package/dist/lib/prompts.js +63 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +13 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/models/anthropic.d.ts +20 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +312 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/deepseek/index.d.ts +20 -0
- package/dist/models/deepseek/index.d.ts.map +1 -0
- package/dist/models/deepseek/index.js +210 -0
- package/dist/models/deepseek/index.js.map +1 -0
- package/dist/models/gemini.d.ts +20 -0
- package/dist/models/gemini.d.ts.map +1 -0
- package/dist/models/gemini.js +250 -0
- package/dist/models/gemini.js.map +1 -0
- package/dist/models/index.d.ts +70 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +30 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/mistral.d.ts +19 -0
- package/dist/models/mistral.d.ts.map +1 -0
- package/dist/models/mistral.js +259 -0
- package/dist/models/mistral.js.map +1 -0
- package/dist/models/moonshotai.d.ts +20 -0
- package/dist/models/moonshotai.d.ts.map +1 -0
- package/dist/models/moonshotai.js +220 -0
- package/dist/models/moonshotai.js.map +1 -0
- package/dist/models/openai.d.ts +21 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +302 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/provider.d.ts +19 -0
- package/dist/models/provider.d.ts.map +1 -0
- package/dist/models/provider.js +95 -0
- package/dist/models/provider.js.map +1 -0
- package/dist/resources/experiment.d.ts +18 -0
- package/dist/resources/experiment.d.ts.map +1 -0
- package/dist/resources/experiment.js +55 -0
- package/dist/resources/experiment.js.map +1 -0
- package/dist/resources/messages.d.ts +23 -0
- package/dist/resources/messages.d.ts.map +1 -0
- package/dist/resources/messages.js +81 -0
- package/dist/resources/messages.js.map +1 -0
- package/dist/runner/config.d.ts +4 -0
- package/dist/runner/config.d.ts.map +1 -0
- package/dist/runner/config.js +2 -0
- package/dist/runner/config.js.map +1 -0
- package/dist/runner/index.d.ts +41 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +370 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +57 -0
- package/profiles/example/prompt.md +54 -0
- package/profiles/example/settings.json +11 -0
- package/profiles/example/settings.json.example +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anas Lecaillon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Universal Agent Harness
|
|
2
|
+
|
|
3
|
+
A multi-agent orchestration system with MCP (Model Context Protocol) server support. Run AI agents with configurable tools and capabilities.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🤖 Multi-agent orchestration
|
|
8
|
+
- 🔌 MCP server integration for extensible tool support
|
|
9
|
+
- 💾 SQLite-based run tracking
|
|
10
|
+
- 💰 Cost and token usage tracking
|
|
11
|
+
- 📊 Support for multiple LLM providers (Anthropic, OpenAI, Google, Mistral, Deepseek, etc.)
|
|
12
|
+
- 📚 Library and CLI interfaces
|
|
13
|
+
- 📁 Dynamic profile and problem discovery from directories
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install universal-agent-harness
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Library Usage
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createRun, run } from 'universal-agent-harness';
|
|
25
|
+
|
|
26
|
+
// Create a run
|
|
27
|
+
const result = await createRun({
|
|
28
|
+
name: "solve-math-problem",
|
|
29
|
+
problemId: "factorial-problem", // References ./problems/factorial-problem/
|
|
30
|
+
model: "claude-sonnet-4-5",
|
|
31
|
+
agentCount: 1,
|
|
32
|
+
profile: "example"
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Run (single tick)
|
|
36
|
+
await run({
|
|
37
|
+
runName: "solve-math-problem",
|
|
38
|
+
singleTick: true,
|
|
39
|
+
onMessage: (msg) => console.log("Agent output:", msg)
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Profiles and Problems
|
|
44
|
+
|
|
45
|
+
**Profiles** define agent behavior and are stored in `./profiles/` (configurable via `PROFILES_DIR`):
|
|
46
|
+
- `prompt.md` - System prompt for the agent
|
|
47
|
+
- `settings.json` - MCP server configuration (optional)
|
|
48
|
+
- Any additional files accessible via `getProfilePath(profile, relativePath)`
|
|
49
|
+
|
|
50
|
+
**Problems** are stored in `./problems/` (configurable via `PROBLEMS_DIR`):
|
|
51
|
+
- Each problem is a directory with a unique ID
|
|
52
|
+
- Must contain `problem.md` with the problem statement
|
|
53
|
+
- Can include additional files accessible via `getProblemPath(problemId, relativePath)`
|
|
54
|
+
|
|
55
|
+
Example structure:
|
|
56
|
+
```
|
|
57
|
+
problems/
|
|
58
|
+
factorial-problem/
|
|
59
|
+
problem.md
|
|
60
|
+
test-cases.json
|
|
61
|
+
profiles/
|
|
62
|
+
example/
|
|
63
|
+
prompt.md
|
|
64
|
+
settings.json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### MCP Server Configuration
|
|
68
|
+
|
|
69
|
+
Configure MCP servers in `profiles/{profile}/settings.json`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": [
|
|
74
|
+
{
|
|
75
|
+
"name": "filesystem",
|
|
76
|
+
"transport": "stdio",
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
79
|
+
"enabled": true
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "github",
|
|
83
|
+
"transport": "stdio",
|
|
84
|
+
"command": "npx",
|
|
85
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
86
|
+
"env": {
|
|
87
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
|
|
88
|
+
},
|
|
89
|
+
"enabled": true
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## CLI Usage
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Create a run
|
|
99
|
+
npx agent-harness create my-run \
|
|
100
|
+
-p factorial-problem \
|
|
101
|
+
-m claude-sonnet-4-5 \
|
|
102
|
+
-n 1 \
|
|
103
|
+
--profile example
|
|
104
|
+
|
|
105
|
+
# Run (single tick)
|
|
106
|
+
npx agent-harness run my-run --tick 0
|
|
107
|
+
|
|
108
|
+
# Run continuously
|
|
109
|
+
npx agent-harness run my-run
|
|
110
|
+
|
|
111
|
+
# Run specific agent
|
|
112
|
+
npx agent-harness run my-run --agent 0
|
|
113
|
+
|
|
114
|
+
# Run with cost limit
|
|
115
|
+
npx agent-harness run my-run --max-cost 5.0
|
|
116
|
+
|
|
117
|
+
# List runs
|
|
118
|
+
npx agent-harness list
|
|
119
|
+
|
|
120
|
+
# Clean up run
|
|
121
|
+
npx agent-harness clean my-run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### `createRun(config)`
|
|
127
|
+
|
|
128
|
+
Create a new run.
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
- `name` (string): Unique run name
|
|
132
|
+
- `problemId` (string): Problem ID (directory name in `./problems/`)
|
|
133
|
+
- `model` (Model): AI model to use
|
|
134
|
+
- `agentCount` (number, optional): Number of agents (default: 1)
|
|
135
|
+
- `profile` (string, optional): Profile name (default: "example")
|
|
136
|
+
|
|
137
|
+
**Returns:** `Promise<Result<RunResource>>`
|
|
138
|
+
|
|
139
|
+
### `run(config)`
|
|
140
|
+
|
|
141
|
+
Run or continue a run.
|
|
142
|
+
|
|
143
|
+
**Parameters:**
|
|
144
|
+
- `runName` (string): Run name
|
|
145
|
+
- `agentIndex` (number, optional): Run specific agent
|
|
146
|
+
- `singleTick` (boolean, optional): Run one tick only
|
|
147
|
+
- `maxCost` (number, optional): Maximum cost limit
|
|
148
|
+
- `thinking` (boolean, optional): Enable extended thinking (default: true)
|
|
149
|
+
- `onMessage` (function, optional): Message callback
|
|
150
|
+
- `onCostUpdate` (function, optional): Cost update callback
|
|
151
|
+
|
|
152
|
+
**Returns:** `Promise<Result<{ cost: number } | void>>`
|
|
153
|
+
|
|
154
|
+
### `getRun(name)`
|
|
155
|
+
|
|
156
|
+
Get run by name.
|
|
157
|
+
|
|
158
|
+
**Returns:** `Promise<Result<RunResource>>`
|
|
159
|
+
|
|
160
|
+
### `listRuns()`
|
|
161
|
+
|
|
162
|
+
List all runs.
|
|
163
|
+
|
|
164
|
+
**Returns:** `Promise<RunResource[]>`
|
|
165
|
+
|
|
166
|
+
### `getRunCost(run)`
|
|
167
|
+
|
|
168
|
+
Get total cost for a run.
|
|
169
|
+
|
|
170
|
+
**Returns:** `Promise<number>`
|
|
171
|
+
|
|
172
|
+
### `deleteRun(name)`
|
|
173
|
+
|
|
174
|
+
Delete a run and all its data.
|
|
175
|
+
|
|
176
|
+
**Returns:** `Promise<Result<void>>`
|
|
177
|
+
|
|
178
|
+
### Profile Utilities
|
|
179
|
+
|
|
180
|
+
- `listProfiles()` - Get all available profiles
|
|
181
|
+
- `getProfileDir(profile)` - Get profile directory path
|
|
182
|
+
- `getProfilePath(profile, relativePath)` - Resolve file path within profile
|
|
183
|
+
|
|
184
|
+
### Problem Utilities
|
|
185
|
+
|
|
186
|
+
- `listProblems()` - Get all available problems
|
|
187
|
+
- `getProblemDir(problemId)` - Get problem directory path
|
|
188
|
+
- `getProblemPath(problemId, relativePath)` - Resolve file path within problem
|
|
189
|
+
- `getProblemContent(problemId)` - Read problem.md content
|
|
190
|
+
|
|
191
|
+
### Model Utilities
|
|
192
|
+
|
|
193
|
+
- `createLLM(model, config?)` - Create an LLM instance for a given model
|
|
194
|
+
- `MODELS` - Record of all available models
|
|
195
|
+
|
|
196
|
+
**Example:**
|
|
197
|
+
```typescript
|
|
198
|
+
import { createLLM } from 'universal-agent-harness';
|
|
199
|
+
|
|
200
|
+
const llm = createLLM('claude-sonnet-4-5', {
|
|
201
|
+
maxTokens: 4096,
|
|
202
|
+
thinking: true
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Exported Types
|
|
207
|
+
|
|
208
|
+
The library exports all core types for TypeScript users:
|
|
209
|
+
|
|
210
|
+
**Model Types:**
|
|
211
|
+
- `Model` - Union type of all supported models
|
|
212
|
+
- `Message` - Agent message structure
|
|
213
|
+
- `TextContent`, `ToolUse`, `ToolResult`, `Thinking` - Message content types
|
|
214
|
+
- `Tool` - Tool definition structure
|
|
215
|
+
- `TokenUsage` - Token usage tracking
|
|
216
|
+
- `ModelConfig` - LLM configuration options
|
|
217
|
+
- `LLM` - Abstract LLM base class
|
|
218
|
+
- `ProviderData` - Provider-specific data
|
|
219
|
+
|
|
220
|
+
**Configuration Types:**
|
|
221
|
+
- `MCPServerConfig` - MCP server configuration
|
|
222
|
+
- `ProfileConfig` - Profile configuration with MCP servers
|
|
223
|
+
- `Result<T>` - Success/error result type
|
|
224
|
+
|
|
225
|
+
## Supported Models
|
|
226
|
+
|
|
227
|
+
- **Anthropic**: claude-opus-4-5, claude-sonnet-4-5, claude-haiku-4-5
|
|
228
|
+
- **OpenAI**: gpt-5.2-pro, gpt-5.2, gpt-5.1, gpt-5, gpt-4.1, gpt-5-mini, etc.
|
|
229
|
+
- **Google**: gemini-3-pro-preview, gemini-2.5-pro, gemini-2.5-flash
|
|
230
|
+
- **Mistral**: mistral-large-latest, devstral-medium-latest, codestral-latest
|
|
231
|
+
- **Deepseek**: deepseek-chat, deepseek-reasoner
|
|
232
|
+
- **Moonshot AI**: kimi-k2-thinking
|
|
233
|
+
- **RedPill AI**: kimi-k2.5, glm-4.7, llama-3.3-70b-instruct, qwen-2.5-7b-instruct
|
|
234
|
+
|
|
235
|
+
## Development
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# Install dependencies
|
|
239
|
+
npm install
|
|
240
|
+
|
|
241
|
+
# Run type checking
|
|
242
|
+
npm run typecheck
|
|
243
|
+
|
|
244
|
+
# Run linting
|
|
245
|
+
npm run lint
|
|
246
|
+
|
|
247
|
+
# Build
|
|
248
|
+
npm run build
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Database
|
|
252
|
+
|
|
253
|
+
The system uses SQLite with Drizzle ORM:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Generate migrations
|
|
257
|
+
npx drizzle-kit generate
|
|
258
|
+
|
|
259
|
+
# Run migrations
|
|
260
|
+
npx drizzle-kit migrate
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-harness.d.ts","sourceRoot":"","sources":["../src/agent-harness.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { readFileContent } from "./lib/fs";
|
|
4
|
+
import { ExperimentResource } from "./resources/experiment";
|
|
5
|
+
import { Runner } from "./runner";
|
|
6
|
+
import { removeNulls } from "./lib/utils";
|
|
7
|
+
import { MODELS } from "./models/provider";
|
|
8
|
+
import { MessageResource } from "./resources/messages";
|
|
9
|
+
import { db } from "./db";
|
|
10
|
+
import { messages } from "./db/schema";
|
|
11
|
+
import { eq } from "drizzle-orm";
|
|
12
|
+
import { select, confirm, number, prompt } from "./lib/prompts";
|
|
13
|
+
import { existsSync } from "fs";
|
|
14
|
+
const exitWithError = (err) => {
|
|
15
|
+
console.error(`\x1b[31mError [${err.error.code}] ${err.error.message}\x1b[0m`);
|
|
16
|
+
if (err.error.cause) {
|
|
17
|
+
console.error(`\x1b[31mCause: ${err.error.cause.message}\x1b[0m`);
|
|
18
|
+
}
|
|
19
|
+
process.exit(1);
|
|
20
|
+
};
|
|
21
|
+
const program = new Command();
|
|
22
|
+
program
|
|
23
|
+
.name("agent-harness")
|
|
24
|
+
.description("Universal agent harness management CLI")
|
|
25
|
+
.version("0.1.0");
|
|
26
|
+
// Create command
|
|
27
|
+
program
|
|
28
|
+
.command("create [name]")
|
|
29
|
+
.description("Create a new experiment")
|
|
30
|
+
.option("-p, --problem <path>", "Path to problem file")
|
|
31
|
+
.option("-m, --model <model>", "AI model to use", "claude-sonnet-4-5")
|
|
32
|
+
.option("-n, --agents <count>", "Number of agents", "1")
|
|
33
|
+
.option("--profile <profile>", "Agent profile", "example")
|
|
34
|
+
.action(async (name, options) => {
|
|
35
|
+
console.log("\n\x1b[1m=== Create New Experiment ===\x1b[0m\n");
|
|
36
|
+
// Get experiment name
|
|
37
|
+
if (!name) {
|
|
38
|
+
name = await prompt("Experiment name: ");
|
|
39
|
+
if (!name) {
|
|
40
|
+
console.log("Error: Experiment name is required.");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Check if experiment already exists
|
|
45
|
+
const existing = await ExperimentResource.findByName(name);
|
|
46
|
+
if (existing.isOk()) {
|
|
47
|
+
console.log(`Error: Experiment '${name}' already exists.`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
// Get problem file
|
|
51
|
+
let problemPath = options?.problem;
|
|
52
|
+
if (!problemPath) {
|
|
53
|
+
problemPath = await prompt("Problem file path: ");
|
|
54
|
+
while (!existsSync(problemPath)) {
|
|
55
|
+
console.log(`Error: File '${problemPath}' not found.`);
|
|
56
|
+
problemPath = await prompt("Problem file path: ");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (!existsSync(problemPath)) {
|
|
60
|
+
console.log(`Error: File '${problemPath}' not found.`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const problem = await readFileContent(problemPath);
|
|
64
|
+
if (problem.isErr()) {
|
|
65
|
+
return exitWithError(problem);
|
|
66
|
+
}
|
|
67
|
+
console.log(`\nProblem loaded (${problem.value.length} characters)`);
|
|
68
|
+
// Select model
|
|
69
|
+
let model;
|
|
70
|
+
if (options?.model) {
|
|
71
|
+
model = options.model;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const modelChoices = Object.keys(MODELS);
|
|
75
|
+
model = await select("Select AI model:", modelChoices, "claude-sonnet-4-5");
|
|
76
|
+
}
|
|
77
|
+
// Get agent count
|
|
78
|
+
let agentCount;
|
|
79
|
+
if (options?.agents) {
|
|
80
|
+
agentCount = parseInt(options.agents, 10);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
agentCount = await number("Number of agents", 1, 1, 100);
|
|
84
|
+
}
|
|
85
|
+
// Select profile
|
|
86
|
+
let profile;
|
|
87
|
+
if (options?.profile) {
|
|
88
|
+
profile = options.profile;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const validProfiles = ["example"];
|
|
92
|
+
profile = await select("Select agent profile:", validProfiles, "example");
|
|
93
|
+
}
|
|
94
|
+
// Create experiment
|
|
95
|
+
const experiment = await ExperimentResource.create({
|
|
96
|
+
name,
|
|
97
|
+
problem: problem.value,
|
|
98
|
+
model,
|
|
99
|
+
agent_count: agentCount,
|
|
100
|
+
profile,
|
|
101
|
+
});
|
|
102
|
+
const e = experiment.toJSON();
|
|
103
|
+
console.log(`\n\x1b[32m✓ Experiment created successfully!\x1b[0m`);
|
|
104
|
+
console.log(`\n Name: ${e.name}`);
|
|
105
|
+
console.log(` Model: ${e.model}`);
|
|
106
|
+
console.log(` Agents: ${e.agent_count}`);
|
|
107
|
+
console.log(` Profile: ${e.profile}`);
|
|
108
|
+
console.log(`\nRun with: npx tsx src/agent-harness.ts run ${e.name}\n`);
|
|
109
|
+
});
|
|
110
|
+
// List command
|
|
111
|
+
program
|
|
112
|
+
.command("list")
|
|
113
|
+
.description("List all experiments")
|
|
114
|
+
.action(async () => {
|
|
115
|
+
const experiments = await ExperimentResource.all();
|
|
116
|
+
if (experiments.length === 0) {
|
|
117
|
+
console.log("No experiments found.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log(`\n\x1b[1mExperiments (${experiments.length}):\x1b[0m\n`);
|
|
121
|
+
for (const exp of experiments) {
|
|
122
|
+
const e = exp.toJSON();
|
|
123
|
+
const cost = await MessageResource.totalCostForExperiment(exp);
|
|
124
|
+
const tokens = await MessageResource.totalTokensForExperiment(exp);
|
|
125
|
+
console.log(` \x1b[1m${e.name}\x1b[0m`);
|
|
126
|
+
console.log(` Model: ${e.model}`);
|
|
127
|
+
console.log(` Agents: ${e.agent_count}`);
|
|
128
|
+
console.log(` Profile: ${e.profile}`);
|
|
129
|
+
console.log(` Cost: $${cost.toFixed(4)} (${tokens.toLocaleString()} tokens)`);
|
|
130
|
+
console.log();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Run command
|
|
134
|
+
program
|
|
135
|
+
.command("run <experiment>")
|
|
136
|
+
.description("Run agents in an experiment")
|
|
137
|
+
.option("--tick <agent>", "Run single tick for specific agent (0-indexed)")
|
|
138
|
+
.option("--agent <index>", "Run specific agent continuously (0-indexed)")
|
|
139
|
+
.option("--max-cost <amount>", "Maximum cost limit in dollars")
|
|
140
|
+
.option("--no-thinking", "Disable extended thinking")
|
|
141
|
+
.action(async (experimentName, options) => {
|
|
142
|
+
// Find experiment
|
|
143
|
+
const experimentRes = await ExperimentResource.findByName(experimentName);
|
|
144
|
+
if (experimentRes.isErr()) {
|
|
145
|
+
return exitWithError(experimentRes);
|
|
146
|
+
}
|
|
147
|
+
const experiment = experimentRes.value;
|
|
148
|
+
const expData = experiment.toJSON();
|
|
149
|
+
const agentCount = expData.agent_count;
|
|
150
|
+
console.log(`\n\x1b[1m=== Run Experiment: ${experimentName} ===\x1b[0m\n`);
|
|
151
|
+
console.log(` Model: ${expData.model}`);
|
|
152
|
+
console.log(` Agents: ${agentCount}`);
|
|
153
|
+
console.log(` Profile: ${expData.profile}`);
|
|
154
|
+
const cost = await MessageResource.totalCostForExperiment(experiment);
|
|
155
|
+
console.log(` Current cost: $${cost.toFixed(4)}\n`);
|
|
156
|
+
// Determine run mode
|
|
157
|
+
let agentIndices = [];
|
|
158
|
+
let singleTick = false;
|
|
159
|
+
if (options?.tick !== undefined) {
|
|
160
|
+
// Run single tick for specific agent
|
|
161
|
+
const agentIndex = parseInt(options.tick, 10);
|
|
162
|
+
if (agentIndex < 0 || agentIndex >= agentCount) {
|
|
163
|
+
console.log(`Error: Agent index must be between 0 and ${agentCount - 1}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
agentIndices = [agentIndex];
|
|
167
|
+
singleTick = true;
|
|
168
|
+
}
|
|
169
|
+
else if (options?.agent !== undefined) {
|
|
170
|
+
// Run specific agent continuously
|
|
171
|
+
const agentIndex = parseInt(options.agent, 10);
|
|
172
|
+
if (agentIndex < 0 || agentIndex >= agentCount) {
|
|
173
|
+
console.log(`Error: Agent index must be between 0 and ${agentCount - 1}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
agentIndices = [agentIndex];
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// Interactive mode or all agents
|
|
180
|
+
const runMode = await select("Select run mode:", ["all-continuous", "single-tick", "specific-agent"], "all-continuous");
|
|
181
|
+
if (runMode === "single-tick") {
|
|
182
|
+
const agentIndex = await number("Which agent to run one tick?", 0, 0, agentCount - 1);
|
|
183
|
+
agentIndices = [agentIndex];
|
|
184
|
+
singleTick = true;
|
|
185
|
+
}
|
|
186
|
+
else if (runMode === "specific-agent") {
|
|
187
|
+
const agentIndex = await number("Which agent to run continuously?", 0, 0, agentCount - 1);
|
|
188
|
+
agentIndices = [agentIndex];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// All agents
|
|
192
|
+
for (let i = 0; i < agentCount; i++) {
|
|
193
|
+
agentIndices.push(i);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Get max cost
|
|
198
|
+
let maxCost;
|
|
199
|
+
if (options?.maxCost !== undefined) {
|
|
200
|
+
maxCost = parseFloat(options.maxCost);
|
|
201
|
+
}
|
|
202
|
+
else if (!singleTick) {
|
|
203
|
+
const setCostLimit = await confirm("Set maximum cost limit?", false);
|
|
204
|
+
if (setCostLimit) {
|
|
205
|
+
maxCost = await number("Maximum cost in dollars", 5.0, 0.01);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Get thinking mode
|
|
209
|
+
const thinking = options?.thinking !== false
|
|
210
|
+
? (options?.thinking === undefined
|
|
211
|
+
? await confirm("Enable extended thinking?", true)
|
|
212
|
+
: true)
|
|
213
|
+
: false;
|
|
214
|
+
console.log("\n\x1b[1mStarting experiment...\x1b[0m\n");
|
|
215
|
+
// Build runners for all agents
|
|
216
|
+
const builders = await Promise.all(agentIndices.map((agentIndex) => Runner.builder(experiment, agentIndex, {
|
|
217
|
+
thinking,
|
|
218
|
+
})));
|
|
219
|
+
for (const res of builders) {
|
|
220
|
+
if (res.isErr()) {
|
|
221
|
+
return exitWithError(res);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const runners = removeNulls(builders.map((res) => {
|
|
225
|
+
if (res.isOk()) {
|
|
226
|
+
return res.value;
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}));
|
|
230
|
+
// Run single tick if specified
|
|
231
|
+
if (singleTick) {
|
|
232
|
+
console.log(`\nRunning single tick for agent ${agentIndices[0]}...\n`);
|
|
233
|
+
const tickResults = await Promise.all(runners.map((r) => r.tick()));
|
|
234
|
+
for (const tick of tickResults) {
|
|
235
|
+
if (tick.isErr()) {
|
|
236
|
+
return exitWithError(tick);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
console.log("\n\x1b[32m✓ Single tick completed.\x1b[0m\n");
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
// Check every 20 ticks except when near the max value
|
|
243
|
+
const shouldCheck = (tickCount, lastVal, maxVal) => (lastVal / maxVal) < 0.95 ? tickCount % 20 === 0 : true;
|
|
244
|
+
let tickCount = 0;
|
|
245
|
+
let lastCost = await MessageResource.totalCostForExperiment(experiment);
|
|
246
|
+
// Fast shutdown - exit cleanly
|
|
247
|
+
const fastShutdown = (reason) => {
|
|
248
|
+
console.log(`\n\x1b[33m${reason}\x1b[0m`);
|
|
249
|
+
if (process.stdin.isTTY) {
|
|
250
|
+
process.stdin.setRawMode(false);
|
|
251
|
+
}
|
|
252
|
+
process.exit(0);
|
|
253
|
+
};
|
|
254
|
+
// Set up keyboard listener for 'q' to quit
|
|
255
|
+
if (process.stdin.isTTY) {
|
|
256
|
+
process.stdin.setRawMode(true);
|
|
257
|
+
process.stdin.resume();
|
|
258
|
+
process.stdin.on("data", (key) => {
|
|
259
|
+
const char = key.toString();
|
|
260
|
+
if (char === "q" || char === "Q") {
|
|
261
|
+
fastShutdown("Quit requested.");
|
|
262
|
+
}
|
|
263
|
+
// Also handle Ctrl+C
|
|
264
|
+
if (char === "\x03") {
|
|
265
|
+
fastShutdown("Interrupted.");
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
// Display instructions
|
|
270
|
+
console.log("\n\x1b[36mPress 'q' to quit\x1b[0m\n");
|
|
271
|
+
// For continuous running, start each agent in its own independent loop
|
|
272
|
+
const runnerPromises = runners.map(async (runner) => {
|
|
273
|
+
while (true) {
|
|
274
|
+
if (maxCost && shouldCheck(tickCount, lastCost, maxCost)) {
|
|
275
|
+
lastCost = await MessageResource.totalCostForExperiment(experiment);
|
|
276
|
+
if (lastCost > maxCost) {
|
|
277
|
+
console.log(`\nCost limit reached: $${lastCost.toFixed(2)}`);
|
|
278
|
+
fastShutdown("Cost limit reached.");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const tick = await runner.tick();
|
|
283
|
+
tickCount++;
|
|
284
|
+
if (tick.isErr()) {
|
|
285
|
+
// eslint-disable-next-line
|
|
286
|
+
throw tick;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
// Wait for agents to finish or stop
|
|
291
|
+
try {
|
|
292
|
+
await Promise.all(runnerPromises);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
fastShutdown("Error occurred.");
|
|
296
|
+
return exitWithError(error);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// Clean command
|
|
300
|
+
program
|
|
301
|
+
.command("clean <experiment>")
|
|
302
|
+
.description("Delete an experiment and all its data")
|
|
303
|
+
.action(async (experimentName) => {
|
|
304
|
+
// Find experiment
|
|
305
|
+
const experimentRes = await ExperimentResource.findByName(experimentName);
|
|
306
|
+
if (experimentRes.isErr()) {
|
|
307
|
+
return exitWithError(experimentRes);
|
|
308
|
+
}
|
|
309
|
+
const experiment = experimentRes.value;
|
|
310
|
+
const expId = experiment.toJSON().id;
|
|
311
|
+
console.log(`\n\x1b[1m=== Clean Experiment: ${experimentName} ===\x1b[0m\n`);
|
|
312
|
+
const confirmed = await confirm("Delete experiment and all data?", false);
|
|
313
|
+
if (!confirmed) {
|
|
314
|
+
console.log("Aborted.");
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
console.log(`\nDeleting experiment '${experimentName}'...`);
|
|
318
|
+
// Delete messages
|
|
319
|
+
console.log(" Deleting messages...");
|
|
320
|
+
db.delete(messages).where(eq(messages.experiment, expId)).run();
|
|
321
|
+
console.log(" Deleting experiment...");
|
|
322
|
+
await experiment.delete();
|
|
323
|
+
console.log(`\n\x1b[32m✓ Experiment '${experimentName}' deleted.\x1b[0m\n`);
|
|
324
|
+
});
|
|
325
|
+
program.parse();
|
|
326
|
+
//# sourceMappingURL=agent-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-harness.js","sourceRoot":"","sources":["../src/agent-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
export declare const db: import("drizzle-orm/better-sqlite3").BetterSQLite3Database<any> & {
|
|
3
|
+
$client: Database.Database;
|
|
4
|
+
};
|
|
5
|
+
export type Tx = Parameters<Parameters<(typeof db)["transaction"]>[0]>[0];
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAatC,eAAO,MAAM,EAAE;;CAAsC,CAAC;AAEtD,MAAM,MAAM,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
2
|
+
import Database from "better-sqlite3";
|
|
3
|
+
import * as schema from "./schema";
|
|
4
|
+
const dbPath = process.env.DATABASE_PATH ?? "./db.sqlite";
|
|
5
|
+
const sqlite = new Database(dbPath);
|
|
6
|
+
// Enable WAL mode for better concurrent access
|
|
7
|
+
sqlite.pragma("journal_mode = WAL");
|
|
8
|
+
// Set busy timeout to 5 seconds to handle concurrent writes
|
|
9
|
+
sqlite.pragma("busy_timeout = 5000");
|
|
10
|
+
export const db = drizzle({ client: sqlite, schema });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,aAAa,CAAC;AAC1D,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;AAEpC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEpC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC"}
|