@neotx/core 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +567 -0
- package/dist/index.d.ts +366 -122
- package/dist/index.js +2372 -898
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/README.md
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
# @neotx/core
|
|
2
|
+
|
|
3
|
+
Orchestration engine for autonomous developer agents. This is the programmatic API that powers the `neo` CLI.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @neotx/core
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @neotx/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node.js >= 22 and the [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { AgentRegistry, loadConfig, Orchestrator } from "@neotx/core";
|
|
19
|
+
|
|
20
|
+
const config = await loadConfig("~/.neo/config.yml");
|
|
21
|
+
|
|
22
|
+
const orchestrator = new Orchestrator(config, {
|
|
23
|
+
journalDir: ".neo/journals",
|
|
24
|
+
middleware: [
|
|
25
|
+
Orchestrator.middleware.budgetGuard(),
|
|
26
|
+
Orchestrator.middleware.loopDetection({ threshold: 5 }),
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Load agents from YAML files
|
|
31
|
+
const registry = new AgentRegistry("path/to/built-in-agents", "path/to/custom-agents");
|
|
32
|
+
await registry.load();
|
|
33
|
+
for (const agent of registry.list()) {
|
|
34
|
+
orchestrator.registerAgent(agent);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Register a workflow
|
|
38
|
+
orchestrator.registerWorkflow({
|
|
39
|
+
name: "implement",
|
|
40
|
+
steps: {
|
|
41
|
+
code: { agent: "developer" },
|
|
42
|
+
review: { agent: "reviewer-quality", dependsOn: ["code"] },
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Start the orchestrator
|
|
47
|
+
await orchestrator.start();
|
|
48
|
+
|
|
49
|
+
// Dispatch a task
|
|
50
|
+
const result = await orchestrator.dispatch({
|
|
51
|
+
workflow: "implement",
|
|
52
|
+
repo: "/path/to/repo",
|
|
53
|
+
prompt: "Add rate limiting to the API",
|
|
54
|
+
priority: "high",
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
console.log(result.status); // "success" | "failure"
|
|
58
|
+
console.log(result.branch); // "feat/run-<uuid>"
|
|
59
|
+
console.log(result.costUsd); // 0.1842
|
|
60
|
+
|
|
61
|
+
await orchestrator.shutdown();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API Reference
|
|
65
|
+
|
|
66
|
+
### `loadConfig(path: string): Promise<NeoConfig>`
|
|
67
|
+
|
|
68
|
+
Load configuration from a YAML file.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { loadConfig, loadGlobalConfig } from "@neotx/core";
|
|
72
|
+
|
|
73
|
+
// Load from a specific path
|
|
74
|
+
const config = await loadConfig(".neo/config.yml");
|
|
75
|
+
|
|
76
|
+
// Load from ~/.neo/config.yml (creates with defaults if missing)
|
|
77
|
+
const globalConfig = await loadGlobalConfig();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `Orchestrator`
|
|
81
|
+
|
|
82
|
+
The main orchestration class. Extends `NeoEventEmitter` for typed event subscriptions.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { Orchestrator } from "@neotx/core";
|
|
86
|
+
|
|
87
|
+
const orchestrator = new Orchestrator(config, {
|
|
88
|
+
middleware: [...], // Optional middleware array
|
|
89
|
+
journalDir: ".neo/journals", // Directory for JSONL journals
|
|
90
|
+
builtInWorkflowDir: "...", // Path to built-in workflow YAML files
|
|
91
|
+
customWorkflowDir: "...", // Path to custom workflow YAML files
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### Lifecycle
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Start the orchestrator (initializes journals, restores cost state)
|
|
99
|
+
await orchestrator.start();
|
|
100
|
+
|
|
101
|
+
// Graceful shutdown (drains active sessions, flushes middleware)
|
|
102
|
+
await orchestrator.shutdown();
|
|
103
|
+
|
|
104
|
+
// Pause/resume dispatch (active sessions continue, new dispatches rejected)
|
|
105
|
+
orchestrator.pause();
|
|
106
|
+
orchestrator.resume();
|
|
107
|
+
|
|
108
|
+
// Drain all active sessions
|
|
109
|
+
await orchestrator.drain();
|
|
110
|
+
|
|
111
|
+
// Kill a specific session
|
|
112
|
+
await orchestrator.kill(sessionId);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Registration
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Register an agent
|
|
119
|
+
orchestrator.registerAgent({
|
|
120
|
+
name: "developer",
|
|
121
|
+
definition: { description: "...", prompt: "...", tools: [...], model: "opus" },
|
|
122
|
+
sandbox: "writable",
|
|
123
|
+
source: "built-in",
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Register a workflow
|
|
127
|
+
orchestrator.registerWorkflow({
|
|
128
|
+
name: "implement",
|
|
129
|
+
steps: {
|
|
130
|
+
code: { agent: "developer" },
|
|
131
|
+
review: { agent: "reviewer-quality", dependsOn: ["code"] },
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Dispatch
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const result = await orchestrator.dispatch({
|
|
140
|
+
workflow: "implement", // Workflow name (required)
|
|
141
|
+
repo: "/path/to/repo", // Repository path (required)
|
|
142
|
+
prompt: "Add feature X", // Task prompt (required)
|
|
143
|
+
runId: "custom-id", // Optional custom run ID
|
|
144
|
+
priority: "high", // "critical" | "high" | "medium" | "low"
|
|
145
|
+
step: "review", // Start from a specific step
|
|
146
|
+
metadata: { ticket: "123" }, // Arbitrary metadata (passed through events)
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Returns a `TaskResult`:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
interface TaskResult {
|
|
154
|
+
runId: string;
|
|
155
|
+
workflow: string;
|
|
156
|
+
repo: string;
|
|
157
|
+
status: "success" | "failure" | "timeout" | "cancelled";
|
|
158
|
+
steps: Record<string, StepResult>;
|
|
159
|
+
branch?: string;
|
|
160
|
+
costUsd: number;
|
|
161
|
+
durationMs: number;
|
|
162
|
+
timestamp: string;
|
|
163
|
+
metadata?: Record<string, unknown>;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Status
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const status = orchestrator.status;
|
|
171
|
+
// {
|
|
172
|
+
// paused: false,
|
|
173
|
+
// activeSessions: [...],
|
|
174
|
+
// queueDepth: 3,
|
|
175
|
+
// costToday: 12.50,
|
|
176
|
+
// budgetCapUsd: 500,
|
|
177
|
+
// budgetRemainingPct: 97.5,
|
|
178
|
+
// uptime: 3600000,
|
|
179
|
+
// }
|
|
180
|
+
|
|
181
|
+
const sessions = orchestrator.activeSessions;
|
|
182
|
+
// [{ sessionId, runId, workflow, step, agent, repo, status, startedAt }]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### `AgentRegistry`
|
|
186
|
+
|
|
187
|
+
Load and manage agent definitions from YAML files.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { AgentRegistry } from "@neotx/core";
|
|
191
|
+
|
|
192
|
+
const registry = new AgentRegistry(
|
|
193
|
+
"path/to/built-in-agents", // Built-in agent directory
|
|
194
|
+
"path/to/custom-agents", // Optional custom agent directory
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
await registry.load();
|
|
198
|
+
|
|
199
|
+
const agent = registry.get("developer");
|
|
200
|
+
const allAgents = registry.list();
|
|
201
|
+
const hasAgent = registry.has("developer");
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Agents support inheritance via `extends`:
|
|
205
|
+
|
|
206
|
+
```yaml
|
|
207
|
+
# custom-agents/my-developer.yml
|
|
208
|
+
name: my-developer
|
|
209
|
+
extends: developer
|
|
210
|
+
promptAppend: |
|
|
211
|
+
Always use our internal logger.
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Events
|
|
215
|
+
|
|
216
|
+
The orchestrator emits typed events for real-time monitoring:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
orchestrator.on("session:start", (event) => {
|
|
220
|
+
// { type, sessionId, runId, workflow, step, agent, repo, metadata, timestamp }
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
orchestrator.on("session:complete", (event) => {
|
|
224
|
+
// { type, sessionId, runId, status, costUsd, durationMs, output, metadata, timestamp }
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
orchestrator.on("session:fail", (event) => {
|
|
228
|
+
// { type, sessionId, runId, error, attempt, maxRetries, willRetry, metadata, timestamp }
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
orchestrator.on("cost:update", (event) => {
|
|
232
|
+
// { type, sessionId, sessionCost, todayTotal, budgetRemainingPct, timestamp }
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
orchestrator.on("budget:alert", (event) => {
|
|
236
|
+
// { type, todayTotal, capUsd, utilizationPct, timestamp }
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
orchestrator.on("queue:enqueue", (event) => {
|
|
240
|
+
// { type, sessionId, repo, position, timestamp }
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
orchestrator.on("queue:dequeue", (event) => {
|
|
244
|
+
// { type, sessionId, repo, waitedMs, timestamp }
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Subscribe to all events
|
|
248
|
+
orchestrator.on("*", (event) => {
|
|
249
|
+
console.log(event.type, event);
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Events are also persisted to JSONL journals in `journalDir`.
|
|
254
|
+
|
|
255
|
+
## Middleware
|
|
256
|
+
|
|
257
|
+
Extend orchestrator behavior with middleware hooks. Middleware runs on every tool call within agent sessions.
|
|
258
|
+
|
|
259
|
+
### Built-in Middleware
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const orchestrator = new Orchestrator(config, {
|
|
263
|
+
middleware: [
|
|
264
|
+
// Block tool calls when over budget
|
|
265
|
+
Orchestrator.middleware.budgetGuard(),
|
|
266
|
+
|
|
267
|
+
// Detect repeated commands and force escalation
|
|
268
|
+
Orchestrator.middleware.loopDetection({
|
|
269
|
+
threshold: 5, // Block after 5 identical commands
|
|
270
|
+
scope: "session", // Track per session
|
|
271
|
+
}),
|
|
272
|
+
|
|
273
|
+
// JSONL audit trail of all tool calls
|
|
274
|
+
Orchestrator.middleware.auditLog({
|
|
275
|
+
dir: ".neo/audit",
|
|
276
|
+
includeInput: true, // Log tool inputs
|
|
277
|
+
includeOutput: false, // Skip tool outputs
|
|
278
|
+
flushIntervalMs: 500, // Flush buffer interval
|
|
279
|
+
flushSize: 20, // Flush after N entries
|
|
280
|
+
}),
|
|
281
|
+
],
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Custom Middleware
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import type { Middleware } from "@neotx/core";
|
|
289
|
+
|
|
290
|
+
const customMiddleware: Middleware = {
|
|
291
|
+
name: "my-middleware",
|
|
292
|
+
on: "PreToolUse", // "PreToolUse" | "PostToolUse" | "Notification"
|
|
293
|
+
match: "Bash", // Optional: only match specific tools
|
|
294
|
+
async handler(event, context) {
|
|
295
|
+
// event: { hookEvent, sessionId, toolName, input, output, message }
|
|
296
|
+
// context: { runId, workflow, step, agent, repo, get, set }
|
|
297
|
+
|
|
298
|
+
const costToday = context.get("costToday");
|
|
299
|
+
|
|
300
|
+
if (someCondition) {
|
|
301
|
+
return { decision: "block", reason: "Blocked by policy" };
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return { decision: "pass" };
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Middleware results:
|
|
310
|
+
- `{ decision: "pass" }` — continue execution
|
|
311
|
+
- `{ decision: "block", reason: string }` — block the tool call
|
|
312
|
+
- `{ decision: "async", asyncTimeout: number }` — non-blocking (for logging)
|
|
313
|
+
|
|
314
|
+
## Recovery System
|
|
315
|
+
|
|
316
|
+
Sessions use 3-level recovery escalation:
|
|
317
|
+
|
|
318
|
+
| Attempt | Strategy | Description |
|
|
319
|
+
|---------|----------|-------------|
|
|
320
|
+
| 1 | `normal` | Fresh session |
|
|
321
|
+
| 2 | `resume` | Resume previous session with context continuity |
|
|
322
|
+
| 3 | `fresh` | Clean slate, no previous context |
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { runWithRecovery } from "@neotx/core";
|
|
326
|
+
|
|
327
|
+
const result = await runWithRecovery({
|
|
328
|
+
agent,
|
|
329
|
+
prompt: "...",
|
|
330
|
+
repoPath: "/path/to/repo",
|
|
331
|
+
sandboxConfig,
|
|
332
|
+
hooks,
|
|
333
|
+
initTimeoutMs: 120_000,
|
|
334
|
+
maxDurationMs: 3_600_000,
|
|
335
|
+
maxRetries: 3,
|
|
336
|
+
backoffBaseMs: 30_000,
|
|
337
|
+
nonRetryable: ["error_max_turns", "budget_exceeded"],
|
|
338
|
+
onAttempt: (attempt, strategy) => {
|
|
339
|
+
console.log(`Attempt ${attempt}: ${strategy}`);
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Non-retryable errors (auth failures, budget exceeded, max turns) skip retries entirely.
|
|
345
|
+
|
|
346
|
+
## Isolation & Clones
|
|
347
|
+
|
|
348
|
+
Each writable agent runs in an isolated git clone (`git clone --local`). The main branch is never touched.
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import {
|
|
352
|
+
createSessionClone,
|
|
353
|
+
removeSessionClone,
|
|
354
|
+
listSessionClones,
|
|
355
|
+
} from "@neotx/core";
|
|
356
|
+
|
|
357
|
+
// Create a session clone with a new branch
|
|
358
|
+
const info = await createSessionClone({
|
|
359
|
+
repoPath: "/path/to/repo",
|
|
360
|
+
branch: "feat/run-abc123",
|
|
361
|
+
baseBranch: "main",
|
|
362
|
+
sessionDir: "/tmp/neo-sessions/abc123",
|
|
363
|
+
});
|
|
364
|
+
// { path, branch, repoPath }
|
|
365
|
+
|
|
366
|
+
// List all session clones
|
|
367
|
+
const clones = await listSessionClones("/tmp/neo-sessions");
|
|
368
|
+
|
|
369
|
+
// Remove a session clone (branch preserved for PR)
|
|
370
|
+
await removeSessionClone(info.path);
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Each clone is fully independent — no shared git state, no mutex needed.
|
|
374
|
+
|
|
375
|
+
## Concurrency Control
|
|
376
|
+
|
|
377
|
+
The orchestrator uses a priority semaphore with global and per-repo limits:
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
import { Semaphore } from "@neotx/core";
|
|
381
|
+
|
|
382
|
+
const semaphore = new Semaphore(
|
|
383
|
+
{
|
|
384
|
+
maxSessions: 5, // Total concurrent sessions
|
|
385
|
+
maxPerRepo: 4, // Max sessions per repository
|
|
386
|
+
queueMax: 50, // Max queued dispatches
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
onEnqueue: (sessionId, repo, position) => { ... },
|
|
390
|
+
onDequeue: (sessionId, repo, waitedMs) => { ... },
|
|
391
|
+
},
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
// Acquire a slot (blocks if at capacity)
|
|
395
|
+
await semaphore.acquire(repo, sessionId, "high", abortSignal);
|
|
396
|
+
|
|
397
|
+
// Release when done
|
|
398
|
+
semaphore.release(sessionId);
|
|
399
|
+
|
|
400
|
+
// Non-blocking check
|
|
401
|
+
if (semaphore.isAvailable(repo)) { ... }
|
|
402
|
+
|
|
403
|
+
// Status
|
|
404
|
+
semaphore.activeCount();
|
|
405
|
+
semaphore.activeCountForRepo(repo);
|
|
406
|
+
semaphore.queueDepth();
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Priority levels: `"critical"` > `"high"` > `"medium"` > `"low"`
|
|
410
|
+
|
|
411
|
+
## Cost Tracking
|
|
412
|
+
|
|
413
|
+
Costs are tracked in append-only JSONL journals with monthly rotation.
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { CostJournal } from "@neotx/core";
|
|
417
|
+
|
|
418
|
+
const journal = new CostJournal({ dir: ".neo/journals" });
|
|
419
|
+
|
|
420
|
+
// Append a cost entry
|
|
421
|
+
await journal.append({
|
|
422
|
+
timestamp: new Date().toISOString(),
|
|
423
|
+
runId: "...",
|
|
424
|
+
workflow: "implement",
|
|
425
|
+
step: "code",
|
|
426
|
+
sessionId: "...",
|
|
427
|
+
agent: "developer",
|
|
428
|
+
costUsd: 0.0842,
|
|
429
|
+
models: { "claude-3-opus": 0.0842 },
|
|
430
|
+
durationMs: 45000,
|
|
431
|
+
repo: "/path/to/repo",
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// Get today's total (cached)
|
|
435
|
+
const todayTotal = await journal.getDayTotal();
|
|
436
|
+
|
|
437
|
+
// Get a specific day's total
|
|
438
|
+
const yesterdayTotal = await journal.getDayTotal(new Date("2024-01-15"));
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Configuration
|
|
442
|
+
|
|
443
|
+
Configuration schema (Zod-validated):
|
|
444
|
+
|
|
445
|
+
```yaml
|
|
446
|
+
# ~/.neo/config.yml
|
|
447
|
+
|
|
448
|
+
repos:
|
|
449
|
+
- path: /path/to/repo
|
|
450
|
+
defaultBranch: main
|
|
451
|
+
branchPrefix: feat
|
|
452
|
+
pushRemote: origin
|
|
453
|
+
autoCreatePr: false
|
|
454
|
+
|
|
455
|
+
concurrency:
|
|
456
|
+
maxSessions: 5
|
|
457
|
+
maxPerRepo: 4
|
|
458
|
+
queueMax: 50
|
|
459
|
+
|
|
460
|
+
budget:
|
|
461
|
+
dailyCapUsd: 500
|
|
462
|
+
alertThresholdPct: 80
|
|
463
|
+
|
|
464
|
+
recovery:
|
|
465
|
+
maxRetries: 3
|
|
466
|
+
backoffBaseMs: 30000
|
|
467
|
+
|
|
468
|
+
sessions:
|
|
469
|
+
initTimeoutMs: 120000
|
|
470
|
+
maxDurationMs: 3600000
|
|
471
|
+
|
|
472
|
+
webhooks:
|
|
473
|
+
- url: https://example.com/webhook
|
|
474
|
+
events: ["session:complete", "budget:alert"]
|
|
475
|
+
secret: "webhook-secret"
|
|
476
|
+
timeoutMs: 5000
|
|
477
|
+
|
|
478
|
+
mcpServers:
|
|
479
|
+
linear:
|
|
480
|
+
type: http
|
|
481
|
+
url: https://mcp.linear.app
|
|
482
|
+
headers:
|
|
483
|
+
Authorization: "Bearer ${LINEAR_API_KEY}"
|
|
484
|
+
|
|
485
|
+
idempotency:
|
|
486
|
+
enabled: true
|
|
487
|
+
key: metadata # or "prompt"
|
|
488
|
+
ttlMs: 3600000
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Repo Management
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
import {
|
|
495
|
+
addRepoToGlobalConfig,
|
|
496
|
+
removeRepoFromGlobalConfig,
|
|
497
|
+
listReposFromGlobalConfig,
|
|
498
|
+
} from "@neotx/core";
|
|
499
|
+
|
|
500
|
+
// Add a repo
|
|
501
|
+
await addRepoToGlobalConfig({
|
|
502
|
+
path: "/path/to/repo",
|
|
503
|
+
defaultBranch: "main",
|
|
504
|
+
branchPrefix: "feat",
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
// Remove a repo (by path, name, or slug)
|
|
508
|
+
await removeRepoFromGlobalConfig("/path/to/repo");
|
|
509
|
+
|
|
510
|
+
// List all registered repos
|
|
511
|
+
const repos = await listReposFromGlobalConfig();
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Types
|
|
515
|
+
|
|
516
|
+
Key types exported from the package:
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
import type {
|
|
520
|
+
// Config
|
|
521
|
+
NeoConfig,
|
|
522
|
+
RepoConfig,
|
|
523
|
+
McpServerConfig,
|
|
524
|
+
|
|
525
|
+
// Agents
|
|
526
|
+
ResolvedAgent,
|
|
527
|
+
AgentConfig,
|
|
528
|
+
AgentDefinition,
|
|
529
|
+
|
|
530
|
+
// Workflows
|
|
531
|
+
WorkflowDefinition,
|
|
532
|
+
WorkflowStepDef,
|
|
533
|
+
|
|
534
|
+
// Dispatch
|
|
535
|
+
DispatchInput,
|
|
536
|
+
TaskResult,
|
|
537
|
+
StepResult,
|
|
538
|
+
Priority,
|
|
539
|
+
|
|
540
|
+
// Sessions
|
|
541
|
+
ActiveSession,
|
|
542
|
+
OrchestratorStatus,
|
|
543
|
+
SessionOptions,
|
|
544
|
+
SessionResult,
|
|
545
|
+
|
|
546
|
+
// Events
|
|
547
|
+
NeoEvent,
|
|
548
|
+
SessionStartEvent,
|
|
549
|
+
SessionCompleteEvent,
|
|
550
|
+
SessionFailEvent,
|
|
551
|
+
CostUpdateEvent,
|
|
552
|
+
BudgetAlertEvent,
|
|
553
|
+
|
|
554
|
+
// Middleware
|
|
555
|
+
Middleware,
|
|
556
|
+
MiddlewareContext,
|
|
557
|
+
MiddlewareEvent,
|
|
558
|
+
MiddlewareResult,
|
|
559
|
+
|
|
560
|
+
// Cost
|
|
561
|
+
CostEntry,
|
|
562
|
+
} from "@neotx/core";
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
## License
|
|
566
|
+
|
|
567
|
+
MIT
|