@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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/agent-harness.d.ts +3 -0
  4. package/dist/agent-harness.d.ts.map +1 -0
  5. package/dist/agent-harness.js +326 -0
  6. package/dist/agent-harness.js.map +1 -0
  7. package/dist/db/index.d.ts +6 -0
  8. package/dist/db/index.d.ts.map +1 -0
  9. package/dist/db/index.js +11 -0
  10. package/dist/db/index.js.map +1 -0
  11. package/dist/db/schema.d.ts +335 -0
  12. package/dist/db/schema.d.ts.map +1 -0
  13. package/dist/db/schema.js +39 -0
  14. package/dist/db/schema.js.map +1 -0
  15. package/dist/index.d.ts +99 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +156 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/lib/assert.d.ts +2 -0
  20. package/dist/lib/assert.d.ts.map +1 -0
  21. package/dist/lib/assert.js +4 -0
  22. package/dist/lib/assert.js.map +1 -0
  23. package/dist/lib/async.d.ts +18 -0
  24. package/dist/lib/async.d.ts.map +1 -0
  25. package/dist/lib/async.js +41 -0
  26. package/dist/lib/async.js.map +1 -0
  27. package/dist/lib/error.d.ts +47 -0
  28. package/dist/lib/error.d.ts.map +1 -0
  29. package/dist/lib/error.js +101 -0
  30. package/dist/lib/error.js.map +1 -0
  31. package/dist/lib/fs.d.ts +3 -0
  32. package/dist/lib/fs.d.ts.map +1 -0
  33. package/dist/lib/fs.js +17 -0
  34. package/dist/lib/fs.js.map +1 -0
  35. package/dist/lib/mcp-config.d.ts +62 -0
  36. package/dist/lib/mcp-config.d.ts.map +1 -0
  37. package/dist/lib/mcp-config.js +80 -0
  38. package/dist/lib/mcp-config.js.map +1 -0
  39. package/dist/lib/mcp.d.ts +19 -0
  40. package/dist/lib/mcp.d.ts.map +1 -0
  41. package/dist/lib/mcp.js +105 -0
  42. package/dist/lib/mcp.js.map +1 -0
  43. package/dist/lib/prompts.d.ts +5 -0
  44. package/dist/lib/prompts.d.ts.map +1 -0
  45. package/dist/lib/prompts.js +63 -0
  46. package/dist/lib/prompts.js.map +1 -0
  47. package/dist/lib/utils.d.ts +5 -0
  48. package/dist/lib/utils.d.ts.map +1 -0
  49. package/dist/lib/utils.js +13 -0
  50. package/dist/lib/utils.js.map +1 -0
  51. package/dist/models/anthropic.d.ts +20 -0
  52. package/dist/models/anthropic.d.ts.map +1 -0
  53. package/dist/models/anthropic.js +312 -0
  54. package/dist/models/anthropic.js.map +1 -0
  55. package/dist/models/deepseek/index.d.ts +20 -0
  56. package/dist/models/deepseek/index.d.ts.map +1 -0
  57. package/dist/models/deepseek/index.js +210 -0
  58. package/dist/models/deepseek/index.js.map +1 -0
  59. package/dist/models/gemini.d.ts +20 -0
  60. package/dist/models/gemini.d.ts.map +1 -0
  61. package/dist/models/gemini.js +250 -0
  62. package/dist/models/gemini.js.map +1 -0
  63. package/dist/models/index.d.ts +70 -0
  64. package/dist/models/index.d.ts.map +1 -0
  65. package/dist/models/index.js +30 -0
  66. package/dist/models/index.js.map +1 -0
  67. package/dist/models/mistral.d.ts +19 -0
  68. package/dist/models/mistral.d.ts.map +1 -0
  69. package/dist/models/mistral.js +259 -0
  70. package/dist/models/mistral.js.map +1 -0
  71. package/dist/models/moonshotai.d.ts +20 -0
  72. package/dist/models/moonshotai.d.ts.map +1 -0
  73. package/dist/models/moonshotai.js +220 -0
  74. package/dist/models/moonshotai.js.map +1 -0
  75. package/dist/models/openai.d.ts +21 -0
  76. package/dist/models/openai.d.ts.map +1 -0
  77. package/dist/models/openai.js +302 -0
  78. package/dist/models/openai.js.map +1 -0
  79. package/dist/models/provider.d.ts +19 -0
  80. package/dist/models/provider.d.ts.map +1 -0
  81. package/dist/models/provider.js +95 -0
  82. package/dist/models/provider.js.map +1 -0
  83. package/dist/resources/experiment.d.ts +18 -0
  84. package/dist/resources/experiment.d.ts.map +1 -0
  85. package/dist/resources/experiment.js +55 -0
  86. package/dist/resources/experiment.js.map +1 -0
  87. package/dist/resources/messages.d.ts +23 -0
  88. package/dist/resources/messages.d.ts.map +1 -0
  89. package/dist/resources/messages.js +81 -0
  90. package/dist/resources/messages.js.map +1 -0
  91. package/dist/runner/config.d.ts +4 -0
  92. package/dist/runner/config.d.ts.map +1 -0
  93. package/dist/runner/config.js +2 -0
  94. package/dist/runner/config.js.map +1 -0
  95. package/dist/runner/index.d.ts +41 -0
  96. package/dist/runner/index.d.ts.map +1 -0
  97. package/dist/runner/index.js +370 -0
  98. package/dist/runner/index.js.map +1 -0
  99. package/dist/tools/index.d.ts +2 -0
  100. package/dist/tools/index.d.ts.map +1 -0
  101. package/dist/tools/index.js +4 -0
  102. package/dist/tools/index.js.map +1 -0
  103. package/package.json +57 -0
  104. package/profiles/example/prompt.md +54 -0
  105. package/profiles/example/settings.json +11 -0
  106. 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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=agent-harness.d.ts.map
@@ -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"}
@@ -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"}