@ugm/desiagent 0.1.37 → 0.2.1
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/README.md +298 -156
- package/dist/core/execution/agents.d.ts.map +1 -1
- package/dist/core/execution/agents.js +18 -4
- package/dist/core/execution/agents.js.map +1 -1
- package/dist/core/execution/dagExecutor.d.ts +15 -2
- package/dist/core/execution/dagExecutor.d.ts.map +1 -1
- package/dist/core/execution/dagExecutor.js +164 -30
- package/dist/core/execution/dagExecutor.js.map +1 -1
- package/dist/core/execution/dags.d.ts +19 -1
- package/dist/core/execution/dags.d.ts.map +1 -1
- package/dist/core/execution/dags.js +171 -92
- package/dist/core/execution/dags.js.map +1 -1
- package/dist/core/execution/inference.d.ts +20 -16
- package/dist/core/execution/inference.d.ts.map +1 -1
- package/dist/core/execution/inference.js +2 -1
- package/dist/core/execution/inference.js.map +1 -1
- package/dist/core/providers/factory.d.ts +1 -0
- package/dist/core/providers/factory.d.ts.map +1 -1
- package/dist/core/providers/factory.js +5 -4
- package/dist/core/providers/factory.js.map +1 -1
- package/dist/core/providers/openrouter.d.ts +9 -2
- package/dist/core/providers/openrouter.d.ts.map +1 -1
- package/dist/core/providers/openrouter.js +66 -9
- package/dist/core/providers/openrouter.js.map +1 -1
- package/dist/core/providers/types.d.ts +9 -0
- package/dist/core/providers/types.d.ts.map +1 -1
- package/dist/core/skills/detector.d.ts +8 -0
- package/dist/core/skills/detector.d.ts.map +1 -0
- package/dist/core/skills/detector.js +60 -0
- package/dist/core/skills/detector.js.map +1 -0
- package/dist/core/skills/registry.d.ts +44 -0
- package/dist/core/skills/registry.d.ts.map +1 -0
- package/dist/core/skills/registry.js +149 -0
- package/dist/core/skills/registry.js.map +1 -0
- package/dist/core/tools/base.d.ts +14 -1
- package/dist/core/tools/base.d.ts.map +1 -1
- package/dist/core/tools/base.js.map +1 -1
- package/dist/core/tools/bash.js +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.js +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/executor.d.ts +4 -1
- package/dist/core/tools/executor.d.ts.map +1 -1
- package/dist/core/tools/executor.js +8 -2
- package/dist/core/tools/executor.js.map +1 -1
- package/dist/core/tools/fetchPage.d.ts +1 -1
- package/dist/core/tools/fetchPage.d.ts.map +1 -1
- package/dist/core/tools/fetchPage.js +20 -4
- package/dist/core/tools/fetchPage.js.map +1 -1
- package/dist/core/tools/glob.js +1 -1
- package/dist/core/tools/glob.js.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/llmExecute.d.ts +41 -32
- package/dist/core/tools/llmExecute.d.ts.map +1 -1
- package/dist/core/tools/llmExecute.js +13 -0
- package/dist/core/tools/llmExecute.js.map +1 -1
- package/dist/core/tools/readEmail.d.ts +1 -1
- package/dist/core/tools/readEmail.d.ts.map +1 -1
- package/dist/core/tools/readEmail.js +6 -9
- package/dist/core/tools/readEmail.js.map +1 -1
- package/dist/core/tools/readFile.js +1 -1
- package/dist/core/tools/readFile.js.map +1 -1
- package/dist/core/tools/sendEmail.d.ts +7 -7
- package/dist/core/tools/sendEmail.d.ts.map +1 -1
- package/dist/core/tools/sendEmail.js +12 -17
- package/dist/core/tools/sendEmail.js.map +1 -1
- package/dist/core/tools/writeFile.d.ts +1 -1
- package/dist/core/tools/writeFile.js +1 -1
- package/dist/core/tools/writeFile.js.map +1 -1
- package/dist/core/workers/statsQueue.d.ts +69 -0
- package/dist/core/workers/statsQueue.d.ts.map +1 -0
- package/dist/core/workers/statsQueue.js +106 -0
- package/dist/core/workers/statsQueue.js.map +1 -0
- package/dist/core/workers/statsWorker.d.ts +11 -0
- package/dist/core/workers/statsWorker.d.ts.map +1 -0
- package/dist/core/workers/statsWorker.js +235 -0
- package/dist/core/workers/statsWorker.js.map +1 -0
- package/dist/db/client.d.ts +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +21 -86
- package/dist/db/client.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -33
- package/dist/index.js.map +1 -1
- package/dist/services/agentsSeedData.d.ts.map +1 -1
- package/dist/services/agentsSeedData.js +14 -0
- package/dist/services/agentsSeedData.js.map +1 -1
- package/dist/services/initDB.d.ts +6 -0
- package/dist/services/initDB.d.ts.map +1 -1
- package/dist/services/initDB.js +2 -2
- package/dist/services/initDB.js.map +1 -1
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +3 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/types/client.d.ts +1 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/config.d.ts +40 -7
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +69 -7
- package/dist/types/config.js.map +1 -1
- package/dist/types/dag.d.ts +44 -44
- package/dist/types/dag.js +7 -7
- package/dist/types/dag.js.map +1 -1
- package/dist/util/logger.d.ts +1 -8
- package/dist/util/logger.d.ts.map +1 -1
- package/dist/util/logger.js +11 -60
- package/dist/util/logger.js.map +1 -1
- package/dist/util/sendEmailTool.d.ts +7 -7
- package/dist/util/sendEmailTool.d.ts.map +1 -1
- package/dist/util/sendEmailTool.js +8 -0
- package/dist/util/sendEmailTool.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,278 +1,420 @@
|
|
|
1
1
|
# desiAgent
|
|
2
2
|
|
|
3
|
-
A library-first async agent system for building autonomous workflows with TypeScript.
|
|
3
|
+
A library-first async agent system for building autonomous workflows with TypeScript. Give it a goal in plain English and it decomposes it into a DAG of tasks, executes them with built-in tools, and streams results back — all in a few lines of code.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
7
|
+
- **Goal → DAG → Execution** — Describe what you want; desiAgent plans a directed acyclic graph (DAG) of sub-tasks and executes them autonomously.
|
|
8
|
+
- **Multiple LLM Providers** — OpenAI, OpenRouter, and Ollama (local) out of the box.
|
|
9
|
+
- **Built-in Tools** — Web scraping, file I/O, bash commands, email (SMTP/IMAP), PDF parsing, and more.
|
|
10
|
+
- **Event Streaming** — `for await` over execution events to track progress in real-time.
|
|
11
|
+
- **Clarification Flow** — If the goal is ambiguous the agent asks for clarification before proceeding.
|
|
12
|
+
- **In-Memory or Persistent Storage** — Use `:memory:` for quick experiments or a SQLite file for production.
|
|
13
|
+
- **Cron Scheduling** — Schedule DAGs to run on a cron expression with timezone support.
|
|
14
|
+
- **Artifacts** — Tools can write output files (reports, code, images) that are automatically stored and retrievable.
|
|
15
|
+
- **Cost Tracking** — Token usage and USD cost are recorded per execution step.
|
|
16
|
+
- **Skills** — Drop a `SKILL.md` file into your workspace or global config and the agent discovers it automatically. Skills can be injected as context into LLM prompts or executed as sub-tasks in a DAG.
|
|
17
|
+
- **Experiments API** — Compare models and temperatures on the same goal in one call.
|
|
13
18
|
|
|
14
19
|
## Installation
|
|
15
20
|
|
|
16
21
|
### Prerequisites
|
|
17
22
|
|
|
18
|
-
- [Bun](https://bun.sh) 1.3.5
|
|
23
|
+
- [Bun](https://bun.sh) ≥ 1.3.5
|
|
19
24
|
|
|
20
25
|
### Install
|
|
21
26
|
|
|
22
27
|
```bash
|
|
23
|
-
bun add desiagent
|
|
28
|
+
bun add @ugm/desiagent
|
|
24
29
|
```
|
|
25
30
|
|
|
26
|
-
Or with npm/pnpm:
|
|
31
|
+
Or with npm / pnpm:
|
|
27
32
|
|
|
28
33
|
```bash
|
|
29
|
-
npm install desiagent
|
|
34
|
+
npm install @ugm/desiagent
|
|
30
35
|
# or
|
|
31
|
-
pnpm add desiagent
|
|
36
|
+
pnpm add @ugm/desiagent
|
|
32
37
|
```
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
### Environment Variables
|
|
35
40
|
|
|
36
|
-
Create a `.env` file
|
|
37
|
-
|
|
38
|
-
### OpenAI
|
|
41
|
+
Create a `.env` file with your provider's API key:
|
|
39
42
|
|
|
40
43
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
# OpenRouter (recommended — access to many models via one key)
|
|
45
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
# OpenAI
|
|
48
|
+
OPENAI_API_KEY=sk-...
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
# Ollama (local, no key needed)
|
|
51
|
+
OLLAMA_BASE_URL=http://localhost:11434 # optional, this is the default
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
## Examples
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
OLLAMA_BASE_URL=http://localhost:11434 # Optional, this is the default
|
|
54
|
-
```
|
|
56
|
+
> All examples below use OpenRouter and an in-memory database (`:memory:`) so you can run them without any local SQLite file.
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
### 1. Goal → Execute in One Call
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
The fastest way to go from idea to result. `createAndExecuteFromGoal` plans the DAG **and** executes it in a single call.
|
|
59
61
|
|
|
60
62
|
```typescript
|
|
61
|
-
import { setupDesiAgent } from 'desiagent';
|
|
63
|
+
import { setupDesiAgent } from '@ugm/desiagent';
|
|
62
64
|
|
|
63
65
|
const client = await setupDesiAgent({
|
|
64
|
-
llmProvider: '
|
|
65
|
-
|
|
66
|
-
modelName: '
|
|
66
|
+
llmProvider: 'openrouter',
|
|
67
|
+
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
68
|
+
modelName: 'google/gemini-2.5-flash-lite-preview-09-2025',
|
|
69
|
+
databasePath: ':memory:',
|
|
70
|
+
skipGenerationStats: true,
|
|
67
71
|
});
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
const result = await client.dags.createAndExecuteFromGoal({
|
|
74
|
+
goalText: 'Research the top 5 trends in AI agents for 2025 and write a concise briefing document to ai-trends.md',
|
|
75
|
+
agentName: 'DecomposerV9',
|
|
76
|
+
temperature: 0.7,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (result.status === 'clarification_required') {
|
|
80
|
+
console.log('Agent needs more info:', result.clarificationQuery);
|
|
81
|
+
} else {
|
|
82
|
+
console.log('Execution started:', result.executionId);
|
|
83
|
+
|
|
84
|
+
// Stream events until completion
|
|
85
|
+
for await (const event of client.executions.streamEvents(result.executionId)) {
|
|
86
|
+
console.log(event.type, event.data);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Retrieve final result
|
|
90
|
+
const details = await client.executions.getWithSubSteps(result.executionId);
|
|
91
|
+
console.log('Final result:\n', details.finalResult);
|
|
92
|
+
}
|
|
72
93
|
|
|
73
94
|
await client.shutdown();
|
|
74
95
|
```
|
|
75
96
|
|
|
76
|
-
###
|
|
97
|
+
### 2. Plan First, Execute Later
|
|
98
|
+
|
|
99
|
+
Separate planning from execution so you can inspect or modify the DAG before running it.
|
|
77
100
|
|
|
78
101
|
```typescript
|
|
79
|
-
import { setupDesiAgent } from 'desiagent';
|
|
102
|
+
import { setupDesiAgent } from '@ugm/desiagent';
|
|
80
103
|
|
|
81
104
|
const client = await setupDesiAgent({
|
|
82
105
|
llmProvider: 'openrouter',
|
|
83
106
|
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
84
|
-
modelName: 'google/gemini-2.5-flash-lite-preview-
|
|
107
|
+
modelName: 'google/gemini-2.5-flash-lite-preview-09-2025',
|
|
108
|
+
databasePath: ':memory:',
|
|
109
|
+
skipGenerationStats: true,
|
|
85
110
|
});
|
|
86
111
|
|
|
87
|
-
|
|
112
|
+
// Step 1 — Plan
|
|
113
|
+
const plan = await client.dags.createFromGoal({
|
|
114
|
+
goalText: 'Create a tutorial on processing driftwood into handicrafts — cover cleaning, tools, finishes — and write it to driftwood.md',
|
|
115
|
+
agentName: 'DecomposerV9',
|
|
116
|
+
temperature: 0.7,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (plan.status !== 'success') {
|
|
120
|
+
console.log('Planning issue:', plan.status);
|
|
121
|
+
await client.shutdown();
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log('DAG created:', plan.dagId);
|
|
126
|
+
|
|
127
|
+
// Step 2 — Execute
|
|
128
|
+
const execution = await client.dags.execute(plan.dagId);
|
|
129
|
+
console.log('Execution ID:', execution.id);
|
|
130
|
+
|
|
131
|
+
for await (const event of client.executions.streamEvents(execution.id)) {
|
|
132
|
+
console.log(event.type, event.data);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const details = await client.executions.getWithSubSteps(execution.id);
|
|
136
|
+
console.log('Final result:\n', details.finalResult);
|
|
137
|
+
|
|
88
138
|
await client.shutdown();
|
|
89
139
|
```
|
|
90
140
|
|
|
91
|
-
###
|
|
141
|
+
### 3. List Agents and Tools
|
|
142
|
+
|
|
143
|
+
Explore what's available in the system.
|
|
92
144
|
|
|
93
145
|
```typescript
|
|
94
|
-
import { setupDesiAgent } from 'desiagent';
|
|
146
|
+
import { setupDesiAgent } from '@ugm/desiagent';
|
|
95
147
|
|
|
96
148
|
const client = await setupDesiAgent({
|
|
97
|
-
llmProvider: '
|
|
98
|
-
|
|
99
|
-
modelName: '
|
|
149
|
+
llmProvider: 'openrouter',
|
|
150
|
+
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
151
|
+
modelName: 'openai/gpt-4o',
|
|
152
|
+
databasePath: ':memory:',
|
|
153
|
+
skipGenerationStats: true,
|
|
154
|
+
logLevel: 'warn',
|
|
100
155
|
});
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
// List seeded agents
|
|
158
|
+
const agents = await client.agents.list();
|
|
159
|
+
for (const a of agents) {
|
|
160
|
+
console.log(`${a.name} (${a.provider}/${a.model}) — ${a.description}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// List available tools
|
|
164
|
+
const tools = await client.tools.list();
|
|
165
|
+
for (const t of tools) {
|
|
166
|
+
console.log(t.function.name);
|
|
167
|
+
}
|
|
168
|
+
|
|
103
169
|
await client.shutdown();
|
|
104
170
|
```
|
|
105
171
|
|
|
106
|
-
|
|
172
|
+
### 4. Handle Clarifications
|
|
107
173
|
|
|
108
|
-
|
|
109
|
-
interface DesiAgentConfig {
|
|
110
|
-
// LLM Provider (required)
|
|
111
|
-
llmProvider: 'openai' | 'openrouter' | 'ollama';
|
|
112
|
-
modelName: string;
|
|
174
|
+
When the agent decides the goal is ambiguous, it returns a clarification query instead of creating a DAG.
|
|
113
175
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
openrouterApiKey?: string; // Required for 'openrouter' provider
|
|
117
|
-
ollamaBaseUrl?: string; // Optional for 'ollama', defaults to http://localhost:11434
|
|
176
|
+
```typescript
|
|
177
|
+
import { setupDesiAgent } from '@ugm/desiagent';
|
|
118
178
|
|
|
119
|
-
|
|
120
|
-
|
|
179
|
+
const client = await setupDesiAgent({
|
|
180
|
+
llmProvider: 'openrouter',
|
|
181
|
+
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
182
|
+
modelName: 'google/gemini-2.5-flash-lite-preview-09-2025',
|
|
183
|
+
databasePath: ':memory:',
|
|
184
|
+
skipGenerationStats: true,
|
|
185
|
+
});
|
|
121
186
|
|
|
122
|
-
|
|
123
|
-
|
|
187
|
+
const plan = await client.dags.createFromGoal({
|
|
188
|
+
goalText: 'Build the app',
|
|
189
|
+
agentName: 'DecomposerV9',
|
|
190
|
+
});
|
|
124
191
|
|
|
125
|
-
|
|
126
|
-
|
|
192
|
+
if (plan.status === 'clarification_required') {
|
|
193
|
+
console.log('Agent asks:', plan.clarificationQuery);
|
|
127
194
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
195
|
+
// Provide the answer and retry
|
|
196
|
+
const resumed = await client.dags.resumeFromClarification(
|
|
197
|
+
plan.dagId,
|
|
198
|
+
'A Pomodoro timer web app using HTML, CSS, and vanilla JS',
|
|
199
|
+
);
|
|
200
|
+
console.log('Resumed status:', resumed.status);
|
|
131
201
|
}
|
|
202
|
+
|
|
203
|
+
await client.shutdown();
|
|
132
204
|
```
|
|
133
205
|
|
|
134
|
-
|
|
206
|
+
### 5. Custom Inference (No DAG)
|
|
135
207
|
|
|
136
|
-
|
|
208
|
+
Use a named agent directly for a single LLM call — useful for summarisation, translation, or any one-shot task.
|
|
137
209
|
|
|
138
210
|
```typescript
|
|
139
|
-
|
|
140
|
-
const agent = await client.agents.create(name, version, prompt, params?);
|
|
211
|
+
import { setupDesiAgent } from '@ugm/desiagent';
|
|
141
212
|
|
|
142
|
-
|
|
143
|
-
|
|
213
|
+
const client = await setupDesiAgent({
|
|
214
|
+
llmProvider: 'openrouter',
|
|
215
|
+
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
216
|
+
modelName: 'openai/gpt-4o',
|
|
217
|
+
databasePath: ':memory:',
|
|
218
|
+
skipGenerationStats: true,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Resolve an agent by name and call it directly
|
|
222
|
+
const agent = await client.agents.resolve('Summarizer');
|
|
223
|
+
// ... or use the lower-level inference API in scripts/infer.ts
|
|
224
|
+
|
|
225
|
+
await client.shutdown();
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Running the Bundled Examples
|
|
144
229
|
|
|
145
|
-
|
|
146
|
-
const agent = await client.agents.get(id);
|
|
230
|
+
The [`examples/`](./examples/) directory contains runnable scripts:
|
|
147
231
|
|
|
148
|
-
|
|
149
|
-
|
|
232
|
+
```bash
|
|
233
|
+
# Execute a goal from a file
|
|
234
|
+
bun run examples/execute-goal.ts -f examples/goals/pomodoro-timer.txt
|
|
235
|
+
|
|
236
|
+
# In-memory database smoke test
|
|
237
|
+
bun run examples/init_6_memory_db.ts
|
|
150
238
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
await client.agents.delete(id);
|
|
239
|
+
# List all agents
|
|
240
|
+
bun run examples/list-agents.ts
|
|
154
241
|
|
|
155
|
-
|
|
156
|
-
|
|
242
|
+
# List all tools
|
|
243
|
+
bun run examples/list-tools.ts --names
|
|
157
244
|
```
|
|
158
245
|
|
|
159
|
-
|
|
246
|
+
## Skills
|
|
160
247
|
|
|
161
|
-
|
|
162
|
-
// Create a DAG from an objective
|
|
163
|
-
const dag = await client.dags.create(objective, params?);
|
|
248
|
+
Skills are reusable instruction files (`SKILL.md`) that extend what the agent can do. Each skill is a Markdown file with YAML frontmatter describing its name, description, and type. When a goal is submitted, desiAgent automatically discovers skills, detects which ones are relevant, and either injects their content into the LLM prompt or executes them as sub-tasks inside a DAG.
|
|
164
249
|
|
|
165
|
-
|
|
166
|
-
const execution = await client.dags.createAndExecute(objective, params?);
|
|
250
|
+
### Skill Types
|
|
167
251
|
|
|
168
|
-
|
|
169
|
-
|
|
252
|
+
| Type | Behaviour |
|
|
253
|
+
|---|---|
|
|
254
|
+
| `context` | The skill's Markdown body is loaded and injected as instructions into an LLM inference call during DAG execution. |
|
|
255
|
+
| `executable` | A sibling `handler.ts` file is imported and its default export is called with the task parameters. |
|
|
170
256
|
|
|
171
|
-
|
|
172
|
-
const dags = await client.dags.list(filter?);
|
|
173
|
-
const scheduled = await client.dags.listScheduled();
|
|
257
|
+
### SKILL.md Format
|
|
174
258
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
259
|
+
```markdown
|
|
260
|
+
---
|
|
261
|
+
name: my-skill
|
|
262
|
+
description: A short sentence describing what this skill does (min 10 chars).
|
|
263
|
+
type: context # or "executable"
|
|
264
|
+
model: openai/gpt-4o # optional — override model for this skill
|
|
265
|
+
provider: openrouter # optional — override provider
|
|
266
|
+
---
|
|
179
267
|
|
|
180
|
-
|
|
181
|
-
|
|
268
|
+
Your skill instructions in Markdown go here.
|
|
269
|
+
The agent receives this content when the skill is used.
|
|
182
270
|
```
|
|
183
271
|
|
|
184
|
-
|
|
272
|
+
> The `name` field **must** match the enclosing directory name (e.g., `my-skill/SKILL.md` must have `name: my-skill`).
|
|
185
273
|
|
|
186
|
-
|
|
187
|
-
// List executions
|
|
188
|
-
const executions = await client.executions.list(filter?);
|
|
274
|
+
### Discovery
|
|
189
275
|
|
|
190
|
-
|
|
191
|
-
const execution = await client.executions.get(id);
|
|
192
|
-
const subSteps = await client.executions.getSubSteps(id);
|
|
276
|
+
On startup, `SkillRegistry.discover()` scans the following locations **in order**. The first skill registered for a given name wins — later duplicates are silently skipped.
|
|
193
277
|
|
|
194
|
-
|
|
195
|
-
|
|
278
|
+
| Priority | Location | Scope |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| 1 | `<workspace>/.agents/skills/<name>/SKILL.md` | Local (workspace) |
|
|
281
|
+
| 2 | `<workspace>/skills/<name>/SKILL.md` | Local (workspace) |
|
|
282
|
+
| 3 | `<workspace>/SKILL.md` | Local (workspace root) |
|
|
283
|
+
| 4 | `~/.config/agents/skills/<name>/SKILL.md` | Global |
|
|
284
|
+
| 5 | `~/.desiAgent/skills/<name>/SKILL.md` | Global |
|
|
196
285
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
286
|
+
**Local wins over global.** If a workspace defines a skill named `summarizer` in `.agents/skills/summarizer/SKILL.md` and a global skill with the same name exists in `~/.desiAgent/skills/summarizer/SKILL.md`, the workspace version is used.
|
|
287
|
+
|
|
288
|
+
### How Skills Are Selected
|
|
289
|
+
|
|
290
|
+
When you submit a goal, a `MinimalSkillDetector` checks for:
|
|
291
|
+
|
|
292
|
+
1. **Explicit triggers** — phrases like `use skill <name>` or `use <name> skill` in the goal text.
|
|
293
|
+
2. **Keyword matching** — if no explicit trigger is found, skill descriptions are matched against keywords in the goal.
|
|
294
|
+
|
|
295
|
+
Matched skills are listed in the agent's system prompt so the LLM can plan DAG tasks with `action_type: 'skill'`.
|
|
296
|
+
|
|
297
|
+
### Using Skills Programmatically
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { SkillRegistry } from '@ugm/desiagent';
|
|
301
|
+
|
|
302
|
+
const registry = new SkillRegistry(process.cwd());
|
|
303
|
+
await registry.discover();
|
|
304
|
+
|
|
305
|
+
// List all discovered skills
|
|
306
|
+
for (const skill of registry.getAll()) {
|
|
307
|
+
console.log(`${skill.name} (${skill.type}) — ${skill.description}`);
|
|
200
308
|
}
|
|
309
|
+
|
|
310
|
+
// Load a skill's content
|
|
311
|
+
const content = await registry.loadContent('my-skill');
|
|
312
|
+
console.log(content);
|
|
201
313
|
```
|
|
202
314
|
|
|
203
|
-
##
|
|
315
|
+
## Configuration Reference
|
|
204
316
|
|
|
205
|
-
|
|
317
|
+
```typescript
|
|
318
|
+
interface DesiAgentConfig {
|
|
319
|
+
llmProvider: 'openai' | 'openrouter' | 'ollama';
|
|
320
|
+
modelName: string;
|
|
206
321
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
322
|
+
// Provider keys
|
|
323
|
+
openaiApiKey?: string;
|
|
324
|
+
openrouterApiKey?: string;
|
|
325
|
+
ollamaBaseUrl?: string; // default: http://localhost:11434
|
|
326
|
+
|
|
327
|
+
// Storage
|
|
328
|
+
databasePath?: string; // default: ~/.desiAgent/data/agent.db
|
|
329
|
+
// use ':memory:' for ephemeral experiments
|
|
330
|
+
artifactsDir?: string; // default: sibling of database file
|
|
211
331
|
|
|
212
|
-
|
|
213
|
-
|
|
332
|
+
// Agent definitions
|
|
333
|
+
agentDefinitionsPath?: string; // default: ~/.desiAgent/agents
|
|
214
334
|
|
|
215
|
-
|
|
216
|
-
|
|
335
|
+
// Logging
|
|
336
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
337
|
+
|
|
338
|
+
// Lifecycle hooks
|
|
339
|
+
onExecutionStart?: (executionId: string) => void;
|
|
340
|
+
onExecutionEnd?: (executionId: string, result: Record<string, any>) => void;
|
|
341
|
+
|
|
342
|
+
// Workspace root for skill discovery
|
|
343
|
+
workspaceRoot?: string; // default: process.cwd()
|
|
344
|
+
|
|
345
|
+
// Feature flags
|
|
346
|
+
autoStartScheduler?: boolean; // default: true
|
|
347
|
+
enableToolValidation?: boolean; // default: true
|
|
348
|
+
skipGenerationStats?: boolean; // default: false
|
|
349
|
+
}
|
|
217
350
|
```
|
|
218
351
|
|
|
219
|
-
##
|
|
352
|
+
## Contributing
|
|
220
353
|
|
|
221
|
-
|
|
354
|
+
We welcome contributions of all kinds — bug fixes, new tools, documentation improvements, and feature ideas.
|
|
222
355
|
|
|
223
|
-
|
|
356
|
+
### Getting Started
|
|
224
357
|
|
|
225
|
-
|
|
226
|
-
# Run with Ollama
|
|
227
|
-
bun run examples/news-bulletin.ts
|
|
358
|
+
1. **Fork & clone** the repository.
|
|
228
359
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
360
|
+
```bash
|
|
361
|
+
git clone https://github.com/<your-username>/desiAgent.git
|
|
362
|
+
cd desiAgent
|
|
363
|
+
```
|
|
232
364
|
|
|
233
|
-
|
|
365
|
+
2. **Install dependencies** (requires Bun ≥ 1.3.5).
|
|
234
366
|
|
|
235
|
-
|
|
367
|
+
```bash
|
|
368
|
+
bun install
|
|
369
|
+
```
|
|
236
370
|
|
|
237
|
-
|
|
238
|
-
# OpenRouter abort test
|
|
239
|
-
OPENROUTER_API_KEY=sk-or-... ABORT_AFTER_MS=2000 bun run test:abort:openrouter
|
|
371
|
+
3. **Create a branch** for your change.
|
|
240
372
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
```
|
|
373
|
+
```bash
|
|
374
|
+
git checkout -b feat/my-awesome-feature
|
|
375
|
+
```
|
|
244
376
|
|
|
245
|
-
|
|
377
|
+
4. **Make your changes**, then verify:
|
|
246
378
|
|
|
247
|
-
|
|
379
|
+
```bash
|
|
380
|
+
bun run type-check # TypeScript must compile cleanly
|
|
381
|
+
bun test # All tests must pass
|
|
382
|
+
```
|
|
248
383
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
384
|
+
### Code Guidelines
|
|
385
|
+
|
|
386
|
+
- **TypeScript only** — no plain JS files.
|
|
387
|
+
- **Follow existing patterns** — look at neighbouring files before writing new code. Match naming conventions, imports, and error handling style.
|
|
388
|
+
- **Keep PRs focused** — one logical change per pull request. Small, reviewable diffs are merged faster.
|
|
389
|
+
- **Write tests** — if you add a feature or fix a bug, add or update a test in the corresponding `*.test.ts` file. Run `bun test` to verify.
|
|
390
|
+
- **No secrets** — never commit API keys, tokens, or credentials. Use environment variables and `.env` files (already in `.gitignore`).
|
|
252
391
|
|
|
253
|
-
|
|
254
|
-
|
|
392
|
+
### Commit Messages
|
|
393
|
+
|
|
394
|
+
Follow the [Conventional Commits](https://www.conventionalcommits.org/) format:
|
|
395
|
+
|
|
396
|
+
```
|
|
397
|
+
feat: add PDF attachment support to inference
|
|
398
|
+
fix: handle empty goal text in DAG creation
|
|
399
|
+
docs: update README examples
|
|
400
|
+
chore: bump drizzle-orm to 0.46
|
|
255
401
|
```
|
|
256
402
|
|
|
257
|
-
###
|
|
403
|
+
### Pull Request Process
|
|
258
404
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
405
|
+
1. Ensure your branch is up to date with `main`.
|
|
406
|
+
2. Open a PR against `main` with a clear title and description of **what** and **why**.
|
|
407
|
+
3. Link any related issues (e.g., `Closes #42`).
|
|
408
|
+
4. A maintainer will review your PR. Address feedback promptly — we aim to merge within a few days.
|
|
262
409
|
|
|
263
|
-
|
|
264
|
-
pnpm type-check
|
|
410
|
+
### Reporting Issues
|
|
265
411
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
pnpm test:watch
|
|
269
|
-
pnpm test:coverage
|
|
412
|
+
- Use [GitHub Issues](https://github.com/ugmurthy/desiAgent/issues) to report bugs or request features.
|
|
413
|
+
- Include steps to reproduce, expected vs. actual behaviour, and your environment (OS, Bun version, provider used).
|
|
270
414
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
pnpm db:studio
|
|
275
|
-
```
|
|
415
|
+
### Code of Conduct
|
|
416
|
+
|
|
417
|
+
Be respectful and constructive. We follow the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.
|
|
276
418
|
|
|
277
419
|
## License
|
|
278
420
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/core/execution/agents.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAIlD;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAUD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkC;IAC3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAU;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAM;gBAEhC,EAAE,EAAE,SAAS;IAIzB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3C;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,KAAK,CAAC;IA2CjB;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAYrC;;OAEG;IACG,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAmB1D;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/core/execution/agents.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAIlD;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAUD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkC;IAC3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAU;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAM;gBAEhC,EAAE,EAAE,SAAS;IAIzB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3C;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,KAAK,CAAC;IA2CjB;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAYrC;;OAEG;IACG,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAmB1D;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAkFjE;;OAEG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAiC1C;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IA+BlD;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBvC;;OAEG;IACH,OAAO,CAAC,QAAQ;CAgBjB"}
|
|
@@ -133,11 +133,25 @@ export class AgentsService {
|
|
|
133
133
|
if (updates.systemPrompt !== undefined) {
|
|
134
134
|
updateData.promptTemplate = updates.systemPrompt;
|
|
135
135
|
}
|
|
136
|
-
if (updates.
|
|
137
|
-
updateData.
|
|
136
|
+
if (updates.provider !== undefined) {
|
|
137
|
+
updateData.provider = updates.provider;
|
|
138
138
|
}
|
|
139
|
-
if (updates.
|
|
140
|
-
updateData.
|
|
139
|
+
if (updates.model !== undefined) {
|
|
140
|
+
updateData.model = updates.model;
|
|
141
|
+
}
|
|
142
|
+
// Build metadata: if metadata is explicitly provided, it replaces existing;
|
|
143
|
+
// description and constraints are merged on top of existing metadata
|
|
144
|
+
if (updates.metadata !== undefined || updates.description !== undefined || updates.constraints !== undefined) {
|
|
145
|
+
const currentMetadata = existing.metadata || {};
|
|
146
|
+
const baseMetadata = updates.metadata !== undefined ? updates.metadata : currentMetadata;
|
|
147
|
+
updateData.metadata = {
|
|
148
|
+
...baseMetadata,
|
|
149
|
+
...(updates.constraints !== undefined ? { constraints: updates.constraints } : {}),
|
|
150
|
+
...(updates.description !== undefined ? { description: updates.description } : {}),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (updates.isActive !== undefined) {
|
|
154
|
+
updateData.active = updates.isActive;
|
|
141
155
|
}
|
|
142
156
|
await this.db.update(agents).set(updateData).where(eq(agents.id, id));
|
|
143
157
|
// Invalidate cache for this agent
|