@neotx/core 0.1.0-alpha.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/dist/index.d.ts +1359 -0
- package/dist/index.js +3190 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1359 @@
|
|
|
1
|
+
import { z, ZodType } from 'zod';
|
|
2
|
+
import { HookEvent as HookEvent$1, HookCallbackMatcher } from '@anthropic-ai/claude-agent-sdk';
|
|
3
|
+
|
|
4
|
+
declare const agentModelSchema: z.ZodEnum<{
|
|
5
|
+
opus: "opus";
|
|
6
|
+
sonnet: "sonnet";
|
|
7
|
+
haiku: "haiku";
|
|
8
|
+
}>;
|
|
9
|
+
declare const agentToolSchema: z.ZodEnum<{
|
|
10
|
+
Read: "Read";
|
|
11
|
+
Write: "Write";
|
|
12
|
+
Edit: "Edit";
|
|
13
|
+
Bash: "Bash";
|
|
14
|
+
Glob: "Glob";
|
|
15
|
+
Grep: "Grep";
|
|
16
|
+
Agent: "Agent";
|
|
17
|
+
WebSearch: "WebSearch";
|
|
18
|
+
WebFetch: "WebFetch";
|
|
19
|
+
NotebookEdit: "NotebookEdit";
|
|
20
|
+
}>;
|
|
21
|
+
declare const agentToolEntrySchema: z.ZodUnion<readonly [z.ZodEnum<{
|
|
22
|
+
Read: "Read";
|
|
23
|
+
Write: "Write";
|
|
24
|
+
Edit: "Edit";
|
|
25
|
+
Bash: "Bash";
|
|
26
|
+
Glob: "Glob";
|
|
27
|
+
Grep: "Grep";
|
|
28
|
+
Agent: "Agent";
|
|
29
|
+
WebSearch: "WebSearch";
|
|
30
|
+
WebFetch: "WebFetch";
|
|
31
|
+
NotebookEdit: "NotebookEdit";
|
|
32
|
+
}>, z.ZodLiteral<"$inherited">]>;
|
|
33
|
+
declare const agentSandboxSchema: z.ZodEnum<{
|
|
34
|
+
readonly: "readonly";
|
|
35
|
+
writable: "writable";
|
|
36
|
+
}>;
|
|
37
|
+
declare const agentConfigSchema: z.ZodObject<{
|
|
38
|
+
name: z.ZodString;
|
|
39
|
+
extends: z.ZodOptional<z.ZodString>;
|
|
40
|
+
description: z.ZodOptional<z.ZodString>;
|
|
41
|
+
model: z.ZodOptional<z.ZodEnum<{
|
|
42
|
+
opus: "opus";
|
|
43
|
+
sonnet: "sonnet";
|
|
44
|
+
haiku: "haiku";
|
|
45
|
+
}>>;
|
|
46
|
+
tools: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodEnum<{
|
|
47
|
+
Read: "Read";
|
|
48
|
+
Write: "Write";
|
|
49
|
+
Edit: "Edit";
|
|
50
|
+
Bash: "Bash";
|
|
51
|
+
Glob: "Glob";
|
|
52
|
+
Grep: "Grep";
|
|
53
|
+
Agent: "Agent";
|
|
54
|
+
WebSearch: "WebSearch";
|
|
55
|
+
WebFetch: "WebFetch";
|
|
56
|
+
NotebookEdit: "NotebookEdit";
|
|
57
|
+
}>, z.ZodLiteral<"$inherited">]>>>;
|
|
58
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
59
|
+
promptAppend: z.ZodOptional<z.ZodString>;
|
|
60
|
+
sandbox: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
readonly: "readonly";
|
|
62
|
+
writable: "writable";
|
|
63
|
+
}>>;
|
|
64
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
mcpServers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
type AgentConfig = z.infer<typeof agentConfigSchema>;
|
|
68
|
+
type AgentModel = z.infer<typeof agentModelSchema>;
|
|
69
|
+
type AgentTool = z.infer<typeof agentToolSchema>;
|
|
70
|
+
type AgentToolEntry = z.infer<typeof agentToolEntrySchema>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Load a single agent definition from a YAML file.
|
|
74
|
+
* If the `prompt` field points to a .md file, resolve it relative
|
|
75
|
+
* to the YAML file's directory and read its content.
|
|
76
|
+
*/
|
|
77
|
+
declare function loadAgentFile(filePath: string): Promise<AgentConfig>;
|
|
78
|
+
|
|
79
|
+
declare const mcpServerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
80
|
+
type: z.ZodLiteral<"http">;
|
|
81
|
+
url: z.ZodString;
|
|
82
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
83
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
84
|
+
type: z.ZodLiteral<"stdio">;
|
|
85
|
+
command: z.ZodString;
|
|
86
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
87
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
88
|
+
}, z.core.$strip>], "type">;
|
|
89
|
+
declare const repoConfigSchema: z.ZodObject<{
|
|
90
|
+
path: z.ZodString;
|
|
91
|
+
name: z.ZodOptional<z.ZodString>;
|
|
92
|
+
defaultBranch: z.ZodDefault<z.ZodString>;
|
|
93
|
+
branchPrefix: z.ZodDefault<z.ZodString>;
|
|
94
|
+
pushRemote: z.ZodDefault<z.ZodString>;
|
|
95
|
+
autoCreatePr: z.ZodDefault<z.ZodBoolean>;
|
|
96
|
+
prBaseBranch: z.ZodOptional<z.ZodString>;
|
|
97
|
+
}, z.core.$strip>;
|
|
98
|
+
declare const globalConfigSchema: z.ZodObject<{
|
|
99
|
+
repos: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
100
|
+
path: z.ZodString;
|
|
101
|
+
name: z.ZodOptional<z.ZodString>;
|
|
102
|
+
defaultBranch: z.ZodDefault<z.ZodString>;
|
|
103
|
+
branchPrefix: z.ZodDefault<z.ZodString>;
|
|
104
|
+
pushRemote: z.ZodDefault<z.ZodString>;
|
|
105
|
+
autoCreatePr: z.ZodDefault<z.ZodBoolean>;
|
|
106
|
+
prBaseBranch: z.ZodOptional<z.ZodString>;
|
|
107
|
+
}, z.core.$strip>>>;
|
|
108
|
+
concurrency: z.ZodDefault<z.ZodObject<{
|
|
109
|
+
maxSessions: z.ZodDefault<z.ZodNumber>;
|
|
110
|
+
maxPerRepo: z.ZodDefault<z.ZodNumber>;
|
|
111
|
+
queueMax: z.ZodDefault<z.ZodNumber>;
|
|
112
|
+
}, z.core.$strip>>;
|
|
113
|
+
budget: z.ZodDefault<z.ZodObject<{
|
|
114
|
+
dailyCapUsd: z.ZodDefault<z.ZodNumber>;
|
|
115
|
+
alertThresholdPct: z.ZodDefault<z.ZodNumber>;
|
|
116
|
+
}, z.core.$strip>>;
|
|
117
|
+
recovery: z.ZodDefault<z.ZodObject<{
|
|
118
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
119
|
+
backoffBaseMs: z.ZodDefault<z.ZodNumber>;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
sessions: z.ZodDefault<z.ZodObject<{
|
|
122
|
+
initTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
123
|
+
maxDurationMs: z.ZodDefault<z.ZodNumber>;
|
|
124
|
+
}, z.core.$strip>>;
|
|
125
|
+
webhooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
126
|
+
url: z.ZodString;
|
|
127
|
+
events: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
128
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
129
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
130
|
+
}, z.core.$strip>>>;
|
|
131
|
+
supervisor: z.ZodDefault<z.ZodObject<{
|
|
132
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
133
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
134
|
+
idleIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
135
|
+
heartbeatTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
136
|
+
maxConsecutiveFailures: z.ZodDefault<z.ZodNumber>;
|
|
137
|
+
maxEventsPerSec: z.ZodDefault<z.ZodNumber>;
|
|
138
|
+
dailyCapUsd: z.ZodDefault<z.ZodNumber>;
|
|
139
|
+
instructions: z.ZodOptional<z.ZodString>;
|
|
140
|
+
}, z.core.$strip>>;
|
|
141
|
+
mcpServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
142
|
+
type: z.ZodLiteral<"http">;
|
|
143
|
+
url: z.ZodString;
|
|
144
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
145
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
146
|
+
type: z.ZodLiteral<"stdio">;
|
|
147
|
+
command: z.ZodString;
|
|
148
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
149
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
150
|
+
}, z.core.$strip>], "type">>>;
|
|
151
|
+
claudeCodePath: z.ZodOptional<z.ZodString>;
|
|
152
|
+
idempotency: z.ZodOptional<z.ZodObject<{
|
|
153
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
154
|
+
key: z.ZodDefault<z.ZodEnum<{
|
|
155
|
+
prompt: "prompt";
|
|
156
|
+
metadata: "metadata";
|
|
157
|
+
}>>;
|
|
158
|
+
ttlMs: z.ZodDefault<z.ZodNumber>;
|
|
159
|
+
}, z.core.$strip>>;
|
|
160
|
+
}, z.core.$strip>;
|
|
161
|
+
declare const neoConfigSchema: z.ZodObject<{
|
|
162
|
+
repos: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
163
|
+
path: z.ZodString;
|
|
164
|
+
name: z.ZodOptional<z.ZodString>;
|
|
165
|
+
defaultBranch: z.ZodDefault<z.ZodString>;
|
|
166
|
+
branchPrefix: z.ZodDefault<z.ZodString>;
|
|
167
|
+
pushRemote: z.ZodDefault<z.ZodString>;
|
|
168
|
+
autoCreatePr: z.ZodDefault<z.ZodBoolean>;
|
|
169
|
+
prBaseBranch: z.ZodOptional<z.ZodString>;
|
|
170
|
+
}, z.core.$strip>>>;
|
|
171
|
+
concurrency: z.ZodDefault<z.ZodObject<{
|
|
172
|
+
maxSessions: z.ZodDefault<z.ZodNumber>;
|
|
173
|
+
maxPerRepo: z.ZodDefault<z.ZodNumber>;
|
|
174
|
+
queueMax: z.ZodDefault<z.ZodNumber>;
|
|
175
|
+
}, z.core.$strip>>;
|
|
176
|
+
budget: z.ZodDefault<z.ZodObject<{
|
|
177
|
+
dailyCapUsd: z.ZodDefault<z.ZodNumber>;
|
|
178
|
+
alertThresholdPct: z.ZodDefault<z.ZodNumber>;
|
|
179
|
+
}, z.core.$strip>>;
|
|
180
|
+
recovery: z.ZodDefault<z.ZodObject<{
|
|
181
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
182
|
+
backoffBaseMs: z.ZodDefault<z.ZodNumber>;
|
|
183
|
+
}, z.core.$strip>>;
|
|
184
|
+
sessions: z.ZodDefault<z.ZodObject<{
|
|
185
|
+
initTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
186
|
+
maxDurationMs: z.ZodDefault<z.ZodNumber>;
|
|
187
|
+
}, z.core.$strip>>;
|
|
188
|
+
webhooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
189
|
+
url: z.ZodString;
|
|
190
|
+
events: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
191
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
192
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
193
|
+
}, z.core.$strip>>>;
|
|
194
|
+
supervisor: z.ZodDefault<z.ZodObject<{
|
|
195
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
196
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
197
|
+
idleIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
198
|
+
heartbeatTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
199
|
+
maxConsecutiveFailures: z.ZodDefault<z.ZodNumber>;
|
|
200
|
+
maxEventsPerSec: z.ZodDefault<z.ZodNumber>;
|
|
201
|
+
dailyCapUsd: z.ZodDefault<z.ZodNumber>;
|
|
202
|
+
instructions: z.ZodOptional<z.ZodString>;
|
|
203
|
+
}, z.core.$strip>>;
|
|
204
|
+
mcpServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
205
|
+
type: z.ZodLiteral<"http">;
|
|
206
|
+
url: z.ZodString;
|
|
207
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
208
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
209
|
+
type: z.ZodLiteral<"stdio">;
|
|
210
|
+
command: z.ZodString;
|
|
211
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
212
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
213
|
+
}, z.core.$strip>], "type">>>;
|
|
214
|
+
claudeCodePath: z.ZodOptional<z.ZodString>;
|
|
215
|
+
idempotency: z.ZodOptional<z.ZodObject<{
|
|
216
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
217
|
+
key: z.ZodDefault<z.ZodEnum<{
|
|
218
|
+
prompt: "prompt";
|
|
219
|
+
metadata: "metadata";
|
|
220
|
+
}>>;
|
|
221
|
+
ttlMs: z.ZodDefault<z.ZodNumber>;
|
|
222
|
+
}, z.core.$strip>>;
|
|
223
|
+
}, z.core.$strip>;
|
|
224
|
+
type NeoConfig = z.infer<typeof neoConfigSchema>;
|
|
225
|
+
type GlobalConfig = NeoConfig;
|
|
226
|
+
type RepoConfig = z.infer<typeof repoConfigSchema>;
|
|
227
|
+
type RepoConfigInput = z.input<typeof repoConfigSchema>;
|
|
228
|
+
type McpServerConfig = z.infer<typeof mcpServerConfigSchema>;
|
|
229
|
+
/**
|
|
230
|
+
* Load NeoConfig from a single file (legacy compatibility).
|
|
231
|
+
*/
|
|
232
|
+
declare function loadConfig(configPath: string): Promise<NeoConfig>;
|
|
233
|
+
/**
|
|
234
|
+
* Load the global config from ~/.neo/config.yml.
|
|
235
|
+
* Creates the file with defaults if it does not exist.
|
|
236
|
+
*/
|
|
237
|
+
declare function loadGlobalConfig(): Promise<NeoConfig>;
|
|
238
|
+
/**
|
|
239
|
+
* Add a repo to ~/.neo/config.yml. Deduplicates by resolved path.
|
|
240
|
+
*/
|
|
241
|
+
declare function addRepoToGlobalConfig(repo: RepoConfigInput): Promise<void>;
|
|
242
|
+
/**
|
|
243
|
+
* Remove a repo from ~/.neo/config.yml by path, name, or slug.
|
|
244
|
+
*/
|
|
245
|
+
declare function removeRepoFromGlobalConfig(pathOrName: string): Promise<boolean>;
|
|
246
|
+
/**
|
|
247
|
+
* List all registered repos from ~/.neo/config.yml.
|
|
248
|
+
*/
|
|
249
|
+
declare function listReposFromGlobalConfig(): Promise<RepoConfig[]>;
|
|
250
|
+
|
|
251
|
+
interface AgentDefinition {
|
|
252
|
+
description: string;
|
|
253
|
+
prompt: string;
|
|
254
|
+
tools: string[];
|
|
255
|
+
model: string;
|
|
256
|
+
}
|
|
257
|
+
interface ResolvedAgent {
|
|
258
|
+
name: string;
|
|
259
|
+
definition: AgentDefinition;
|
|
260
|
+
sandbox: "writable" | "readonly";
|
|
261
|
+
maxTurns?: number | undefined;
|
|
262
|
+
source: "built-in" | "custom" | "extended";
|
|
263
|
+
}
|
|
264
|
+
interface WorkflowDefinition {
|
|
265
|
+
name: string;
|
|
266
|
+
description?: string | undefined;
|
|
267
|
+
steps: Record<string, WorkflowStepDef | WorkflowGateDef>;
|
|
268
|
+
}
|
|
269
|
+
interface WorkflowStepDef {
|
|
270
|
+
type?: "step" | undefined;
|
|
271
|
+
agent: string;
|
|
272
|
+
dependsOn?: string[] | undefined;
|
|
273
|
+
prompt?: string | undefined;
|
|
274
|
+
sandbox?: "writable" | "readonly" | undefined;
|
|
275
|
+
maxTurns?: number | undefined;
|
|
276
|
+
mcpServers?: string[] | undefined;
|
|
277
|
+
recovery?: {
|
|
278
|
+
maxRetries?: number | undefined;
|
|
279
|
+
nonRetryable?: string[] | undefined;
|
|
280
|
+
} | undefined;
|
|
281
|
+
}
|
|
282
|
+
interface WorkflowGateDef {
|
|
283
|
+
type: "gate";
|
|
284
|
+
dependsOn?: string[] | undefined;
|
|
285
|
+
description: string;
|
|
286
|
+
timeout?: string | undefined;
|
|
287
|
+
autoApprove?: boolean | undefined;
|
|
288
|
+
}
|
|
289
|
+
interface PersistedRun {
|
|
290
|
+
version: 1;
|
|
291
|
+
runId: string;
|
|
292
|
+
workflow: string;
|
|
293
|
+
repo: string;
|
|
294
|
+
prompt: string;
|
|
295
|
+
branch?: string | undefined;
|
|
296
|
+
worktreePath?: string | undefined;
|
|
297
|
+
pid?: number | undefined;
|
|
298
|
+
status: "running" | "paused" | "completed" | "failed";
|
|
299
|
+
steps: Record<string, StepResult>;
|
|
300
|
+
createdAt: string;
|
|
301
|
+
updatedAt: string;
|
|
302
|
+
metadata?: Record<string, unknown> | undefined;
|
|
303
|
+
}
|
|
304
|
+
interface StepResult {
|
|
305
|
+
status: "pending" | "running" | "success" | "failure" | "skipped";
|
|
306
|
+
sessionId?: string | undefined;
|
|
307
|
+
output?: unknown;
|
|
308
|
+
rawOutput?: string | undefined;
|
|
309
|
+
costUsd: number;
|
|
310
|
+
durationMs: number;
|
|
311
|
+
agent: string;
|
|
312
|
+
startedAt?: string | undefined;
|
|
313
|
+
completedAt?: string | undefined;
|
|
314
|
+
error?: string | undefined;
|
|
315
|
+
attempt: number;
|
|
316
|
+
}
|
|
317
|
+
type Priority = "critical" | "high" | "medium" | "low";
|
|
318
|
+
interface DispatchInput {
|
|
319
|
+
workflow: string;
|
|
320
|
+
repo: string;
|
|
321
|
+
prompt: string;
|
|
322
|
+
runId?: string | undefined;
|
|
323
|
+
step?: string | undefined;
|
|
324
|
+
from?: string | undefined;
|
|
325
|
+
retry?: string | undefined;
|
|
326
|
+
priority?: Priority | undefined;
|
|
327
|
+
overrides?: {
|
|
328
|
+
agents?: Record<string, string> | undefined;
|
|
329
|
+
maxTurns?: number | undefined;
|
|
330
|
+
sandbox?: "writable" | "readonly" | undefined;
|
|
331
|
+
} | undefined;
|
|
332
|
+
metadata?: Record<string, unknown> | undefined;
|
|
333
|
+
}
|
|
334
|
+
interface TaskResult {
|
|
335
|
+
runId: string;
|
|
336
|
+
workflow: string;
|
|
337
|
+
repo: string;
|
|
338
|
+
status: "success" | "failure" | "timeout" | "cancelled";
|
|
339
|
+
steps: Record<string, StepResult>;
|
|
340
|
+
prUrl?: string | undefined;
|
|
341
|
+
prNumber?: number | undefined;
|
|
342
|
+
branch?: string | undefined;
|
|
343
|
+
summary?: string | undefined;
|
|
344
|
+
costUsd: number;
|
|
345
|
+
durationMs: number;
|
|
346
|
+
timestamp: string;
|
|
347
|
+
metadata?: Record<string, unknown> | undefined;
|
|
348
|
+
}
|
|
349
|
+
interface ActiveSession {
|
|
350
|
+
sessionId: string;
|
|
351
|
+
runId: string;
|
|
352
|
+
workflow: string;
|
|
353
|
+
step: string;
|
|
354
|
+
agent: string;
|
|
355
|
+
repo: string;
|
|
356
|
+
status: "running" | "queued" | "waiting_gate";
|
|
357
|
+
startedAt: string;
|
|
358
|
+
worktreePath?: string | undefined;
|
|
359
|
+
}
|
|
360
|
+
interface OrchestratorStatus {
|
|
361
|
+
paused: boolean;
|
|
362
|
+
activeSessions: ActiveSession[];
|
|
363
|
+
queueDepth: number;
|
|
364
|
+
costToday: number;
|
|
365
|
+
budgetCapUsd: number;
|
|
366
|
+
budgetRemainingPct: number;
|
|
367
|
+
uptime: number;
|
|
368
|
+
}
|
|
369
|
+
interface WorkflowContext {
|
|
370
|
+
runId: string;
|
|
371
|
+
workflow: string;
|
|
372
|
+
repo: string;
|
|
373
|
+
prompt: string;
|
|
374
|
+
steps: Record<string, StepResult>;
|
|
375
|
+
startedAt: Date;
|
|
376
|
+
}
|
|
377
|
+
interface SessionStartEvent {
|
|
378
|
+
type: "session:start";
|
|
379
|
+
sessionId: string;
|
|
380
|
+
runId: string;
|
|
381
|
+
workflow: string;
|
|
382
|
+
step: string;
|
|
383
|
+
agent: string;
|
|
384
|
+
repo: string;
|
|
385
|
+
metadata?: Record<string, unknown> | undefined;
|
|
386
|
+
timestamp: string;
|
|
387
|
+
}
|
|
388
|
+
interface SessionCompleteEvent {
|
|
389
|
+
type: "session:complete";
|
|
390
|
+
sessionId: string;
|
|
391
|
+
runId: string;
|
|
392
|
+
status: "success" | "failure";
|
|
393
|
+
costUsd: number;
|
|
394
|
+
durationMs: number;
|
|
395
|
+
output?: unknown;
|
|
396
|
+
metadata?: Record<string, unknown> | undefined;
|
|
397
|
+
timestamp: string;
|
|
398
|
+
}
|
|
399
|
+
interface SessionFailEvent {
|
|
400
|
+
type: "session:fail";
|
|
401
|
+
sessionId: string;
|
|
402
|
+
runId: string;
|
|
403
|
+
error: string;
|
|
404
|
+
attempt: number;
|
|
405
|
+
maxRetries: number;
|
|
406
|
+
willRetry: boolean;
|
|
407
|
+
metadata?: Record<string, unknown> | undefined;
|
|
408
|
+
timestamp: string;
|
|
409
|
+
}
|
|
410
|
+
interface AgentToolUseEvent {
|
|
411
|
+
type: "agent:tool_use";
|
|
412
|
+
sessionId: string;
|
|
413
|
+
agent: string;
|
|
414
|
+
tool: string;
|
|
415
|
+
input: Record<string, unknown>;
|
|
416
|
+
durationMs: number;
|
|
417
|
+
timestamp: string;
|
|
418
|
+
}
|
|
419
|
+
interface AgentMessageEvent {
|
|
420
|
+
type: "agent:message";
|
|
421
|
+
sessionId: string;
|
|
422
|
+
agent: string;
|
|
423
|
+
text: string;
|
|
424
|
+
timestamp: string;
|
|
425
|
+
}
|
|
426
|
+
interface WorkflowStepStartEvent {
|
|
427
|
+
type: "workflow:step_start";
|
|
428
|
+
runId: string;
|
|
429
|
+
step: string;
|
|
430
|
+
agent: string;
|
|
431
|
+
metadata?: Record<string, unknown> | undefined;
|
|
432
|
+
timestamp: string;
|
|
433
|
+
}
|
|
434
|
+
interface WorkflowStepCompleteEvent {
|
|
435
|
+
type: "workflow:step_complete";
|
|
436
|
+
runId: string;
|
|
437
|
+
step: string;
|
|
438
|
+
status: "success" | "failure" | "skipped";
|
|
439
|
+
costUsd: number;
|
|
440
|
+
durationMs: number;
|
|
441
|
+
metadata?: Record<string, unknown> | undefined;
|
|
442
|
+
timestamp: string;
|
|
443
|
+
}
|
|
444
|
+
interface GateWaitingEvent {
|
|
445
|
+
type: "gate:waiting";
|
|
446
|
+
runId: string;
|
|
447
|
+
gate: string;
|
|
448
|
+
description: string;
|
|
449
|
+
context: WorkflowContext;
|
|
450
|
+
approve: () => void;
|
|
451
|
+
reject: (reason: string) => void;
|
|
452
|
+
metadata?: Record<string, unknown> | undefined;
|
|
453
|
+
timestamp: string;
|
|
454
|
+
}
|
|
455
|
+
interface CostUpdateEvent {
|
|
456
|
+
type: "cost:update";
|
|
457
|
+
sessionId: string;
|
|
458
|
+
sessionCost: number;
|
|
459
|
+
todayTotal: number;
|
|
460
|
+
budgetRemainingPct: number;
|
|
461
|
+
timestamp: string;
|
|
462
|
+
}
|
|
463
|
+
interface BudgetAlertEvent {
|
|
464
|
+
type: "budget:alert";
|
|
465
|
+
todayTotal: number;
|
|
466
|
+
capUsd: number;
|
|
467
|
+
utilizationPct: number;
|
|
468
|
+
timestamp: string;
|
|
469
|
+
}
|
|
470
|
+
interface QueueEnqueueEvent {
|
|
471
|
+
type: "queue:enqueue";
|
|
472
|
+
sessionId: string;
|
|
473
|
+
repo: string;
|
|
474
|
+
position: number;
|
|
475
|
+
timestamp: string;
|
|
476
|
+
}
|
|
477
|
+
interface QueueDequeueEvent {
|
|
478
|
+
type: "queue:dequeue";
|
|
479
|
+
sessionId: string;
|
|
480
|
+
repo: string;
|
|
481
|
+
waitedMs: number;
|
|
482
|
+
timestamp: string;
|
|
483
|
+
}
|
|
484
|
+
interface OrchestratorShutdownEvent {
|
|
485
|
+
type: "orchestrator:shutdown";
|
|
486
|
+
timestamp: string;
|
|
487
|
+
}
|
|
488
|
+
type NeoEvent = SessionStartEvent | SessionCompleteEvent | SessionFailEvent | AgentToolUseEvent | AgentMessageEvent | WorkflowStepStartEvent | WorkflowStepCompleteEvent | GateWaitingEvent | CostUpdateEvent | BudgetAlertEvent | QueueEnqueueEvent | QueueDequeueEvent | OrchestratorShutdownEvent;
|
|
489
|
+
type HookEvent = "PreToolUse" | "PostToolUse" | "Notification";
|
|
490
|
+
interface Middleware {
|
|
491
|
+
name: string;
|
|
492
|
+
on: HookEvent;
|
|
493
|
+
match?: string | string[] | undefined;
|
|
494
|
+
handler: MiddlewareHandler;
|
|
495
|
+
}
|
|
496
|
+
type MiddlewareHandler = (event: MiddlewareEvent, context: MiddlewareContext) => Promise<MiddlewareResult>;
|
|
497
|
+
interface MiddlewareEvent {
|
|
498
|
+
hookEvent: HookEvent;
|
|
499
|
+
sessionId: string;
|
|
500
|
+
toolName?: string | undefined;
|
|
501
|
+
input?: Record<string, unknown> | undefined;
|
|
502
|
+
output?: string | undefined;
|
|
503
|
+
message?: string | undefined;
|
|
504
|
+
}
|
|
505
|
+
/** Well-known context keys set by the orchestrator. */
|
|
506
|
+
interface MiddlewareContextMap {
|
|
507
|
+
costToday: number;
|
|
508
|
+
budgetCapUsd: number;
|
|
509
|
+
[key: string]: unknown;
|
|
510
|
+
}
|
|
511
|
+
interface MiddlewareContext {
|
|
512
|
+
runId: string;
|
|
513
|
+
workflow: string;
|
|
514
|
+
step: string;
|
|
515
|
+
agent: string;
|
|
516
|
+
repo: string;
|
|
517
|
+
get: <K extends string & keyof MiddlewareContextMap>(key: K) => MiddlewareContextMap[K] | undefined;
|
|
518
|
+
set: <K extends string & keyof MiddlewareContextMap>(key: K, value: MiddlewareContextMap[K]) => void;
|
|
519
|
+
}
|
|
520
|
+
type MiddlewareResult = {
|
|
521
|
+
decision: "pass";
|
|
522
|
+
} | {
|
|
523
|
+
decision: "block";
|
|
524
|
+
reason: string;
|
|
525
|
+
} | {
|
|
526
|
+
decision: "async";
|
|
527
|
+
asyncTimeout: number;
|
|
528
|
+
};
|
|
529
|
+
interface CostEntry {
|
|
530
|
+
timestamp: string;
|
|
531
|
+
runId: string;
|
|
532
|
+
workflow: string;
|
|
533
|
+
step: string;
|
|
534
|
+
sessionId: string;
|
|
535
|
+
agent: string;
|
|
536
|
+
costUsd: number;
|
|
537
|
+
models: Record<string, number>;
|
|
538
|
+
durationMs: number;
|
|
539
|
+
repo?: string;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
declare class AgentRegistry {
|
|
543
|
+
private readonly builtInDir;
|
|
544
|
+
private readonly customDir;
|
|
545
|
+
private agents;
|
|
546
|
+
constructor(builtInDir: string, customDir?: string);
|
|
547
|
+
load(): Promise<void>;
|
|
548
|
+
get(name: string): ResolvedAgent | undefined;
|
|
549
|
+
list(): ResolvedAgent[];
|
|
550
|
+
has(name: string): boolean;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Resolve an agent config into a fully-merged ResolvedAgent.
|
|
555
|
+
*
|
|
556
|
+
* Resolution rules:
|
|
557
|
+
* 1. No `extends` → agent must define all required fields
|
|
558
|
+
* 2. With `extends: "developer"` → start from built-in, apply overrides
|
|
559
|
+
* 3. Same name as built-in without `extends:` → treated as `extends: <name>` implicitly
|
|
560
|
+
*/
|
|
561
|
+
declare function resolveAgent(config: AgentConfig, builtIns: Map<string, AgentConfig>): ResolvedAgent;
|
|
562
|
+
|
|
563
|
+
interface SemaphoreConfig {
|
|
564
|
+
maxSessions: number;
|
|
565
|
+
maxPerRepo: number;
|
|
566
|
+
queueMax?: number;
|
|
567
|
+
}
|
|
568
|
+
interface SemaphoreCallbacks {
|
|
569
|
+
onEnqueue?: (sessionId: string, repo: string, position: number) => void;
|
|
570
|
+
onDequeue?: (sessionId: string, repo: string, waitedMs: number) => void;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Concurrency semaphore with global + per-repo limits and a priority queue.
|
|
574
|
+
* When at capacity, `acquire()` blocks until a slot is available.
|
|
575
|
+
*/
|
|
576
|
+
declare class Semaphore {
|
|
577
|
+
private readonly maxSessions;
|
|
578
|
+
private readonly maxPerRepo;
|
|
579
|
+
private readonly queue;
|
|
580
|
+
private readonly callbacks;
|
|
581
|
+
private readonly activeSessions;
|
|
582
|
+
private readonly repoCounts;
|
|
583
|
+
constructor(config: SemaphoreConfig, callbacks?: SemaphoreCallbacks);
|
|
584
|
+
/**
|
|
585
|
+
* Acquire a slot. Blocks (via promise) if at capacity.
|
|
586
|
+
* Throws if the queue is full.
|
|
587
|
+
*/
|
|
588
|
+
acquire(repo: string, sessionId: string, priority?: Priority, signal?: AbortSignal): Promise<void>;
|
|
589
|
+
/** Release a slot and process the next waiting entry. */
|
|
590
|
+
release(sessionId: string): void;
|
|
591
|
+
/** Non-blocking attempt to acquire a slot. Returns true if successful. */
|
|
592
|
+
tryAcquire(repo: string, sessionId: string): boolean;
|
|
593
|
+
/** Total number of active slots. */
|
|
594
|
+
activeCount(): number;
|
|
595
|
+
/** Number of active slots for a specific repo. */
|
|
596
|
+
activeCountForRepo(repo: string): number;
|
|
597
|
+
/** Can a slot be acquired for this repo without blocking? */
|
|
598
|
+
isAvailable(repo: string): boolean;
|
|
599
|
+
/** Current queue depth. */
|
|
600
|
+
queueDepth(): number;
|
|
601
|
+
private canAcquire;
|
|
602
|
+
private allocate;
|
|
603
|
+
private processQueue;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Append-only JSONL journal for cost tracking.
|
|
608
|
+
* Monthly file rotation: cost-YYYY-MM.jsonl
|
|
609
|
+
*/
|
|
610
|
+
declare class CostJournal {
|
|
611
|
+
private readonly dir;
|
|
612
|
+
private dirCreated;
|
|
613
|
+
private dayCache;
|
|
614
|
+
constructor(options: {
|
|
615
|
+
dir: string;
|
|
616
|
+
});
|
|
617
|
+
append(entry: CostEntry): Promise<void>;
|
|
618
|
+
getDayTotal(date?: Date): Promise<number>;
|
|
619
|
+
private fileForDate;
|
|
620
|
+
private ensureDir;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Safe EventEmitter wrapper (ADR-022).
|
|
625
|
+
*
|
|
626
|
+
* - Catches listener errors to prevent cascading crashes
|
|
627
|
+
* - Emits on both the specific event type and the wildcard "*" channel
|
|
628
|
+
* - Swallows errors from the error handler itself to guarantee stability
|
|
629
|
+
*/
|
|
630
|
+
declare class NeoEventEmitter {
|
|
631
|
+
private readonly emitter;
|
|
632
|
+
emit(event: NeoEvent): void;
|
|
633
|
+
on(eventType: string, listener: (event: NeoEvent) => void): this;
|
|
634
|
+
off(eventType: string, listener: (event: NeoEvent) => void): this;
|
|
635
|
+
once(eventType: string, listener: (event: NeoEvent) => void): this;
|
|
636
|
+
removeAllListeners(eventType?: string): this;
|
|
637
|
+
private safeEmit;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Append-only JSONL journal for events.
|
|
642
|
+
* Monthly file rotation: events-YYYY-MM.jsonl
|
|
643
|
+
* Write-only for v0.1 — read API comes in v0.2.
|
|
644
|
+
*/
|
|
645
|
+
declare class EventJournal {
|
|
646
|
+
private readonly dir;
|
|
647
|
+
private dirCreated;
|
|
648
|
+
constructor(options: {
|
|
649
|
+
dir: string;
|
|
650
|
+
});
|
|
651
|
+
append(event: NeoEvent): Promise<void>;
|
|
652
|
+
private fileForDate;
|
|
653
|
+
private ensureDir;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
type WebhookConfig = NeoConfig["webhooks"][number];
|
|
657
|
+
/**
|
|
658
|
+
* Fire-and-forget webhook dispatcher for NeoEvents.
|
|
659
|
+
*
|
|
660
|
+
* - Matches events against per-webhook filters (exact or wildcard like "session:*")
|
|
661
|
+
* - Excludes gate:waiting events (contain non-serializable callbacks)
|
|
662
|
+
* - Signs payloads with HMAC-SHA256 when a secret is configured
|
|
663
|
+
* - Never throws — errors are silently swallowed (consistent with EventJournal)
|
|
664
|
+
*/
|
|
665
|
+
declare class WebhookDispatcher {
|
|
666
|
+
private readonly webhooks;
|
|
667
|
+
constructor(webhooks: WebhookConfig[]);
|
|
668
|
+
dispatch(event: NeoEvent): void;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Check if an event type matches a filter list.
|
|
672
|
+
* Supports exact matches and wildcard prefixes (e.g. "session:*").
|
|
673
|
+
* No filter (undefined) means all events match.
|
|
674
|
+
*/
|
|
675
|
+
declare function matchesFilter(eventType: string, filters?: string[]): boolean;
|
|
676
|
+
|
|
677
|
+
declare function createBranch(repoPath: string, branch: string, baseBranch: string): Promise<void>;
|
|
678
|
+
declare function pushBranch(repoPath: string, branch: string, remote: string): Promise<void>;
|
|
679
|
+
declare function fetchRemote(repoPath: string, remote: string): Promise<void>;
|
|
680
|
+
declare function deleteBranch(repoPath: string, branch: string): Promise<void>;
|
|
681
|
+
declare function getCurrentBranch(repoPath: string): Promise<string>;
|
|
682
|
+
/**
|
|
683
|
+
* Generate a deterministic branch name for a run.
|
|
684
|
+
* Uses the repo's branchPrefix (default "feat") and the runId.
|
|
685
|
+
*/
|
|
686
|
+
declare function getBranchName(config: RepoConfig, runId: string): string;
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Per-repository in-memory mutex to serialise git operations.
|
|
690
|
+
* Concurrent git commands on the same repo corrupt the index — this prevents that.
|
|
691
|
+
*/
|
|
692
|
+
/**
|
|
693
|
+
* Execute `fn` while holding an exclusive lock for `repoPath`.
|
|
694
|
+
* Concurrent calls for the same repo are queued and executed serially.
|
|
695
|
+
* Operations on different repos run in parallel.
|
|
696
|
+
*/
|
|
697
|
+
declare function withGitLock<T>(repoPath: string, fn: () => Promise<T>): Promise<T>;
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* SDK-compatible sandbox configuration.
|
|
701
|
+
* Controls which tools an agent can use and which paths it can access.
|
|
702
|
+
*/
|
|
703
|
+
interface SandboxConfig {
|
|
704
|
+
/** Tools the agent is allowed to use */
|
|
705
|
+
allowedTools: string[];
|
|
706
|
+
/** Directories the agent can read from */
|
|
707
|
+
readablePaths: string[];
|
|
708
|
+
/** Directories the agent can write to (empty for readonly agents) */
|
|
709
|
+
writablePaths: string[];
|
|
710
|
+
/** Whether the agent has write access */
|
|
711
|
+
writable: boolean;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Build an SDK-compatible sandbox configuration for an agent.
|
|
715
|
+
*
|
|
716
|
+
* - Writable agents: all their tools are allowed, write paths include the worktree
|
|
717
|
+
* - Readonly agents: write tools are filtered out, no writable paths
|
|
718
|
+
*/
|
|
719
|
+
declare function buildSandboxConfig(agent: ResolvedAgent, worktreePath?: string): SandboxConfig;
|
|
720
|
+
|
|
721
|
+
interface WorktreeInfo {
|
|
722
|
+
path: string;
|
|
723
|
+
branch: string;
|
|
724
|
+
repoPath: string;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Create a new git worktree with an associated branch.
|
|
728
|
+
* Creates the branch from baseBranch, then adds the worktree at worktreeDir.
|
|
729
|
+
*/
|
|
730
|
+
declare function createWorktree(options: {
|
|
731
|
+
repoPath: string;
|
|
732
|
+
branch: string;
|
|
733
|
+
baseBranch: string;
|
|
734
|
+
worktreeDir: string;
|
|
735
|
+
}): Promise<WorktreeInfo>;
|
|
736
|
+
/**
|
|
737
|
+
* Remove a worktree. Does NOT delete the branch (branch stays for the PR).
|
|
738
|
+
* Idempotent — does not throw if the worktree is already gone.
|
|
739
|
+
*/
|
|
740
|
+
declare function removeWorktree(worktreePath: string): Promise<void>;
|
|
741
|
+
/**
|
|
742
|
+
* List all worktrees for a repository.
|
|
743
|
+
*/
|
|
744
|
+
declare function listWorktrees(repoPath: string): Promise<WorktreeInfo[]>;
|
|
745
|
+
/**
|
|
746
|
+
* Clean up worktrees under worktreeBaseDir that no longer have a matching run.
|
|
747
|
+
* Removes any subdirectory that is a git worktree.
|
|
748
|
+
*/
|
|
749
|
+
declare function cleanupOrphanedWorktrees(worktreeBaseDir: string): Promise<void>;
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Audit log middleware.
|
|
753
|
+
*
|
|
754
|
+
* Buffers JSONL entries in memory and flushes to disk either when
|
|
755
|
+
* the buffer reaches `flushSize` entries or every `flushIntervalMs`.
|
|
756
|
+
* File per session. Uses `{ decision: "async" }` so it never blocks the chain.
|
|
757
|
+
*
|
|
758
|
+
* Call `flush()` to force-write remaining entries (e.g. on shutdown).
|
|
759
|
+
*/
|
|
760
|
+
interface AuditLogMiddleware extends Middleware {
|
|
761
|
+
flush: () => Promise<void>;
|
|
762
|
+
}
|
|
763
|
+
declare function auditLog(options: {
|
|
764
|
+
dir: string;
|
|
765
|
+
includeInput?: boolean;
|
|
766
|
+
includeOutput?: boolean;
|
|
767
|
+
flushIntervalMs?: number;
|
|
768
|
+
flushSize?: number;
|
|
769
|
+
}): AuditLogMiddleware;
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Budget guard middleware.
|
|
773
|
+
*
|
|
774
|
+
* Checks daily cost against budget cap on every tool call.
|
|
775
|
+
* If over budget, blocks with reason "Daily budget exceeded".
|
|
776
|
+
* Uses the middleware context's `get("costToday")` and `get("budgetCapUsd")`.
|
|
777
|
+
*/
|
|
778
|
+
declare function budgetGuard(): Middleware;
|
|
779
|
+
|
|
780
|
+
interface MiddlewareChain {
|
|
781
|
+
execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult>;
|
|
782
|
+
}
|
|
783
|
+
declare function buildMiddlewareChain(middleware: Middleware[]): MiddlewareChain;
|
|
784
|
+
/**
|
|
785
|
+
* SDK hooks type — maps hook event names to callback matchers.
|
|
786
|
+
*/
|
|
787
|
+
type SDKHooks = Partial<Record<HookEvent$1, HookCallbackMatcher[]>>;
|
|
788
|
+
/**
|
|
789
|
+
* Convert a middleware chain to Agent SDK hooks format.
|
|
790
|
+
*
|
|
791
|
+
* Creates one HookCallbackMatcher per supported event (PreToolUse, PostToolUse, Notification).
|
|
792
|
+
* The matcher delegates to the chain's execute method, translating SDK input to our
|
|
793
|
+
* MiddlewareEvent format.
|
|
794
|
+
*/
|
|
795
|
+
declare function buildSDKHooks(chain: MiddlewareChain, context: MiddlewareContext, middleware?: Middleware[]): SDKHooks;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Loop detection middleware.
|
|
799
|
+
*
|
|
800
|
+
* Tracks Bash commands per session. If the same command appears
|
|
801
|
+
* `threshold` times, blocks it and tells the agent to escalate.
|
|
802
|
+
*
|
|
803
|
+
* Call `cleanup(sessionId)` when a session ends to prevent memory leaks.
|
|
804
|
+
*/
|
|
805
|
+
interface LoopDetectionMiddleware extends Middleware {
|
|
806
|
+
cleanup: (sessionId: string) => void;
|
|
807
|
+
}
|
|
808
|
+
declare function loopDetection(options: {
|
|
809
|
+
threshold: number;
|
|
810
|
+
scope?: "session";
|
|
811
|
+
}): LoopDetectionMiddleware;
|
|
812
|
+
|
|
813
|
+
interface OrchestratorOptions {
|
|
814
|
+
middleware?: Middleware[] | undefined;
|
|
815
|
+
journalDir?: string | undefined;
|
|
816
|
+
builtInWorkflowDir?: string | undefined;
|
|
817
|
+
customWorkflowDir?: string | undefined;
|
|
818
|
+
}
|
|
819
|
+
declare class Orchestrator extends NeoEventEmitter {
|
|
820
|
+
private readonly config;
|
|
821
|
+
private readonly semaphore;
|
|
822
|
+
private readonly userMiddleware;
|
|
823
|
+
private readonly workflows;
|
|
824
|
+
private readonly registeredAgents;
|
|
825
|
+
private readonly _activeSessions;
|
|
826
|
+
private readonly idempotencyCache;
|
|
827
|
+
private readonly abortControllers;
|
|
828
|
+
private readonly repoIndex;
|
|
829
|
+
private readonly createdRunDirs;
|
|
830
|
+
private readonly journalDir;
|
|
831
|
+
private readonly builtInWorkflowDir;
|
|
832
|
+
private readonly customWorkflowDir;
|
|
833
|
+
private costJournal;
|
|
834
|
+
private eventJournal;
|
|
835
|
+
private webhookDispatcher;
|
|
836
|
+
private _paused;
|
|
837
|
+
private _costToday;
|
|
838
|
+
private _startedAt;
|
|
839
|
+
private _drainResolve;
|
|
840
|
+
constructor(config: NeoConfig, options?: OrchestratorOptions);
|
|
841
|
+
registerWorkflow(definition: WorkflowDefinition): void;
|
|
842
|
+
registerAgent(agent: ResolvedAgent): void;
|
|
843
|
+
dispatch(input: DispatchInput): Promise<TaskResult>;
|
|
844
|
+
pause(): void;
|
|
845
|
+
resume(): void;
|
|
846
|
+
kill(sessionId: string): Promise<void>;
|
|
847
|
+
drain(): Promise<void>;
|
|
848
|
+
get status(): OrchestratorStatus;
|
|
849
|
+
get activeSessions(): ActiveSession[];
|
|
850
|
+
start(): Promise<void>;
|
|
851
|
+
shutdown(): Promise<void>;
|
|
852
|
+
emit(event: NeoEvent): void;
|
|
853
|
+
static middleware: {
|
|
854
|
+
loopDetection: (options: {
|
|
855
|
+
threshold: number;
|
|
856
|
+
scope?: "session";
|
|
857
|
+
}) => LoopDetectionMiddleware;
|
|
858
|
+
auditLog: (options: {
|
|
859
|
+
dir: string;
|
|
860
|
+
includeInput?: boolean;
|
|
861
|
+
includeOutput?: boolean;
|
|
862
|
+
flushIntervalMs?: number;
|
|
863
|
+
flushSize?: number;
|
|
864
|
+
}) => AuditLogMiddleware;
|
|
865
|
+
budgetGuard: () => Middleware;
|
|
866
|
+
};
|
|
867
|
+
private preDispatchChecks;
|
|
868
|
+
private buildDispatchContext;
|
|
869
|
+
private executeStep;
|
|
870
|
+
private runAgentSession;
|
|
871
|
+
private finalizeDispatch;
|
|
872
|
+
private emitCostEvents;
|
|
873
|
+
private emitSessionComplete;
|
|
874
|
+
private emitSessionFail;
|
|
875
|
+
private validateInput;
|
|
876
|
+
private evictExpiredIdempotencyEntries;
|
|
877
|
+
private computeIdempotencyKey;
|
|
878
|
+
private getFirstStep;
|
|
879
|
+
private resolveStepAgent;
|
|
880
|
+
private resolveRepo;
|
|
881
|
+
private buildMiddlewareContext;
|
|
882
|
+
private computeBudgetRemainingPct;
|
|
883
|
+
private persistRun;
|
|
884
|
+
private recoverOrphanedRuns;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Global data directory for runtime artifacts (journals, runs).
|
|
889
|
+
* Located at ~/.neo, similar to how Claude Code uses ~/.claude.
|
|
890
|
+
*/
|
|
891
|
+
declare function getDataDir(): string;
|
|
892
|
+
declare function getJournalsDir(): string;
|
|
893
|
+
declare function getRunsDir(): string;
|
|
894
|
+
/**
|
|
895
|
+
* Derive a filesystem-safe slug from a repo config.
|
|
896
|
+
* Uses `name` if present, otherwise `basename(path)`.
|
|
897
|
+
*/
|
|
898
|
+
declare function toRepoSlug(repo: {
|
|
899
|
+
name?: string | undefined;
|
|
900
|
+
path: string;
|
|
901
|
+
}): string;
|
|
902
|
+
/**
|
|
903
|
+
* Runs directory for a specific repo: ~/.neo/runs/<slug>/
|
|
904
|
+
*/
|
|
905
|
+
declare function getRepoRunsDir(repoSlug: string): string;
|
|
906
|
+
/**
|
|
907
|
+
* Path to the dispatch request file for a detached run.
|
|
908
|
+
*/
|
|
909
|
+
declare function getRunDispatchPath(repoSlug: string, runId: string): string;
|
|
910
|
+
/**
|
|
911
|
+
* Path to the log file for a detached run.
|
|
912
|
+
*/
|
|
913
|
+
declare function getRunLogPath(repoSlug: string, runId: string): string;
|
|
914
|
+
/**
|
|
915
|
+
* Directory for all supervisor instances: ~/.neo/supervisors/
|
|
916
|
+
*/
|
|
917
|
+
declare function getSupervisorsDir(): string;
|
|
918
|
+
/**
|
|
919
|
+
* Directory for a specific supervisor instance: ~/.neo/supervisors/<name>/
|
|
920
|
+
*/
|
|
921
|
+
declare function getSupervisorDir(name: string): string;
|
|
922
|
+
/**
|
|
923
|
+
* Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json
|
|
924
|
+
*/
|
|
925
|
+
declare function getSupervisorStatePath(name: string): string;
|
|
926
|
+
declare function getSupervisorMemoryPath(name: string): string;
|
|
927
|
+
declare function getSupervisorActivityPath(name: string): string;
|
|
928
|
+
declare function getSupervisorInboxPath(name: string): string;
|
|
929
|
+
declare function getSupervisorEventsPath(name: string): string;
|
|
930
|
+
declare function getSupervisorLockPath(name: string): string;
|
|
931
|
+
|
|
932
|
+
interface ParsedOutput {
|
|
933
|
+
rawOutput: string;
|
|
934
|
+
output?: unknown;
|
|
935
|
+
parseError?: string;
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Parse agent output, optionally validating against a Zod schema.
|
|
939
|
+
*
|
|
940
|
+
* - If no schema: returns rawOutput only
|
|
941
|
+
* - If schema provided: extracts JSON from output, validates with schema
|
|
942
|
+
* - On failure: returns rawOutput + parseError (caller decides whether to retry)
|
|
943
|
+
*/
|
|
944
|
+
declare function parseOutput(raw: string, schema?: ZodType): ParsedOutput;
|
|
945
|
+
|
|
946
|
+
interface SessionOptions {
|
|
947
|
+
agent: ResolvedAgent;
|
|
948
|
+
prompt: string;
|
|
949
|
+
repoPath?: string;
|
|
950
|
+
worktreePath?: string;
|
|
951
|
+
sandboxConfig: SandboxConfig;
|
|
952
|
+
hooks?: Record<string, unknown>;
|
|
953
|
+
mcpServers?: McpServerConfig[];
|
|
954
|
+
initTimeoutMs: number;
|
|
955
|
+
maxDurationMs: number;
|
|
956
|
+
resumeSessionId?: string | undefined;
|
|
957
|
+
onEvent?: ((event: SessionEvent) => void) | undefined;
|
|
958
|
+
}
|
|
959
|
+
interface SessionResult {
|
|
960
|
+
sessionId: string;
|
|
961
|
+
output: string;
|
|
962
|
+
costUsd: number;
|
|
963
|
+
durationMs: number;
|
|
964
|
+
turnCount: number;
|
|
965
|
+
}
|
|
966
|
+
type SessionEvent = {
|
|
967
|
+
type: "session:start";
|
|
968
|
+
sessionId: string;
|
|
969
|
+
} | {
|
|
970
|
+
type: "session:complete";
|
|
971
|
+
sessionId: string;
|
|
972
|
+
result: SessionResult;
|
|
973
|
+
} | {
|
|
974
|
+
type: "session:fail";
|
|
975
|
+
sessionId: string;
|
|
976
|
+
error: string;
|
|
977
|
+
};
|
|
978
|
+
declare function runSession(options: SessionOptions): Promise<SessionResult>;
|
|
979
|
+
declare class SessionError extends Error {
|
|
980
|
+
readonly errorType: string;
|
|
981
|
+
readonly sessionId: string;
|
|
982
|
+
constructor(message: string, errorType: string, sessionId: string);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
interface RecoveryOptions extends SessionOptions {
|
|
986
|
+
maxRetries: number;
|
|
987
|
+
backoffBaseMs: number;
|
|
988
|
+
nonRetryable?: string[];
|
|
989
|
+
onAttempt?: (attempt: number, strategy: string) => void;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Run a session with 3-level recovery escalation (ADR-020).
|
|
993
|
+
*
|
|
994
|
+
* Level 1 (attempt 1): Normal execution — new session
|
|
995
|
+
* Level 2 (attempt 2): Resume session — pass resumeSessionId from level 1
|
|
996
|
+
* Level 3 (attempt 3): Fresh session — abandon previous, start clean
|
|
997
|
+
*
|
|
998
|
+
* Non-retryable errors skip to immediate failure.
|
|
999
|
+
* Backoff: backoffBaseMs * attempt between levels.
|
|
1000
|
+
*/
|
|
1001
|
+
declare function runWithRecovery(options: RecoveryOptions): Promise<SessionResult>;
|
|
1002
|
+
|
|
1003
|
+
declare const supervisorDaemonStateSchema: z.ZodObject<{
|
|
1004
|
+
pid: z.ZodNumber;
|
|
1005
|
+
tmuxSession: z.ZodString;
|
|
1006
|
+
sessionId: z.ZodString;
|
|
1007
|
+
port: z.ZodNumber;
|
|
1008
|
+
cwd: z.ZodString;
|
|
1009
|
+
startedAt: z.ZodString;
|
|
1010
|
+
lastHeartbeat: z.ZodOptional<z.ZodString>;
|
|
1011
|
+
heartbeatCount: z.ZodDefault<z.ZodNumber>;
|
|
1012
|
+
totalCostUsd: z.ZodDefault<z.ZodNumber>;
|
|
1013
|
+
todayCostUsd: z.ZodDefault<z.ZodNumber>;
|
|
1014
|
+
costResetDate: z.ZodOptional<z.ZodString>;
|
|
1015
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
1016
|
+
running: "running";
|
|
1017
|
+
draining: "draining";
|
|
1018
|
+
stopped: "stopped";
|
|
1019
|
+
}>>;
|
|
1020
|
+
}, z.core.$strip>;
|
|
1021
|
+
type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;
|
|
1022
|
+
declare const webhookIncomingEventSchema: z.ZodObject<{
|
|
1023
|
+
id: z.ZodOptional<z.ZodString>;
|
|
1024
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1025
|
+
event: z.ZodOptional<z.ZodString>;
|
|
1026
|
+
payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1027
|
+
receivedAt: z.ZodString;
|
|
1028
|
+
processedAt: z.ZodOptional<z.ZodString>;
|
|
1029
|
+
}, z.core.$strip>;
|
|
1030
|
+
type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;
|
|
1031
|
+
declare const inboxMessageSchema: z.ZodObject<{
|
|
1032
|
+
id: z.ZodString;
|
|
1033
|
+
from: z.ZodEnum<{
|
|
1034
|
+
tui: "tui";
|
|
1035
|
+
api: "api";
|
|
1036
|
+
external: "external";
|
|
1037
|
+
}>;
|
|
1038
|
+
text: z.ZodString;
|
|
1039
|
+
timestamp: z.ZodString;
|
|
1040
|
+
processedAt: z.ZodOptional<z.ZodString>;
|
|
1041
|
+
}, z.core.$strip>;
|
|
1042
|
+
type InboxMessage = z.infer<typeof inboxMessageSchema>;
|
|
1043
|
+
declare const activityEntrySchema: z.ZodObject<{
|
|
1044
|
+
id: z.ZodString;
|
|
1045
|
+
type: z.ZodEnum<{
|
|
1046
|
+
error: "error";
|
|
1047
|
+
message: "message";
|
|
1048
|
+
decision: "decision";
|
|
1049
|
+
event: "event";
|
|
1050
|
+
heartbeat: "heartbeat";
|
|
1051
|
+
action: "action";
|
|
1052
|
+
thinking: "thinking";
|
|
1053
|
+
plan: "plan";
|
|
1054
|
+
dispatch: "dispatch";
|
|
1055
|
+
tool_use: "tool_use";
|
|
1056
|
+
}>;
|
|
1057
|
+
summary: z.ZodString;
|
|
1058
|
+
detail: z.ZodOptional<z.ZodUnknown>;
|
|
1059
|
+
timestamp: z.ZodString;
|
|
1060
|
+
}, z.core.$strip>;
|
|
1061
|
+
type ActivityEntry = z.infer<typeof activityEntrySchema>;
|
|
1062
|
+
type QueuedEvent = {
|
|
1063
|
+
kind: "webhook";
|
|
1064
|
+
data: WebhookIncomingEvent;
|
|
1065
|
+
} | {
|
|
1066
|
+
kind: "message";
|
|
1067
|
+
data: InboxMessage;
|
|
1068
|
+
} | {
|
|
1069
|
+
kind: "run_complete";
|
|
1070
|
+
runId: string;
|
|
1071
|
+
timestamp: string;
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
declare class ActivityLog {
|
|
1075
|
+
private readonly filePath;
|
|
1076
|
+
private readonly dir;
|
|
1077
|
+
constructor(dir: string);
|
|
1078
|
+
/**
|
|
1079
|
+
* Append a structured entry to the activity log.
|
|
1080
|
+
* Rotates the file if it exceeds MAX_SIZE_BYTES.
|
|
1081
|
+
*/
|
|
1082
|
+
append(entry: ActivityEntry): Promise<void>;
|
|
1083
|
+
/**
|
|
1084
|
+
* Create and append a new entry with auto-generated id and timestamp.
|
|
1085
|
+
*/
|
|
1086
|
+
log(type: ActivityEntry["type"], summary: string, detail?: unknown): Promise<void>;
|
|
1087
|
+
/**
|
|
1088
|
+
* Read the last N entries from the activity log.
|
|
1089
|
+
*/
|
|
1090
|
+
tail(n: number): Promise<ActivityEntry[]>;
|
|
1091
|
+
private checkRotation;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
interface SupervisorDaemonOptions {
|
|
1095
|
+
name: string;
|
|
1096
|
+
config: GlobalConfig;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Orchestrates all supervisor components: webhook server, event queue,
|
|
1100
|
+
* heartbeat loop, memory, and activity logging.
|
|
1101
|
+
*/
|
|
1102
|
+
declare class SupervisorDaemon {
|
|
1103
|
+
private readonly name;
|
|
1104
|
+
private readonly config;
|
|
1105
|
+
private readonly dir;
|
|
1106
|
+
private webhookServer;
|
|
1107
|
+
private eventQueue;
|
|
1108
|
+
private heartbeatLoop;
|
|
1109
|
+
private activityLog;
|
|
1110
|
+
private sessionId;
|
|
1111
|
+
constructor(options: SupervisorDaemonOptions);
|
|
1112
|
+
start(): Promise<void>;
|
|
1113
|
+
stop(): Promise<void>;
|
|
1114
|
+
private getHealthInfo;
|
|
1115
|
+
private readState;
|
|
1116
|
+
private writeState;
|
|
1117
|
+
private readLockPid;
|
|
1118
|
+
private isProcessAlive;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
interface EventQueueOptions {
|
|
1122
|
+
maxEventsPerSec: number;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* In-memory event queue with deduplication, rate limiting, and file watching.
|
|
1126
|
+
*
|
|
1127
|
+
* Accumulates events from 3 sources:
|
|
1128
|
+
* - Webhooks (pushed directly by WebhookServer)
|
|
1129
|
+
* - Inbox messages (watched from inbox.jsonl)
|
|
1130
|
+
* - Run completions (watched from runs directory)
|
|
1131
|
+
*
|
|
1132
|
+
* The daemon drains this queue at each heartbeat.
|
|
1133
|
+
*/
|
|
1134
|
+
declare class EventQueue {
|
|
1135
|
+
private readonly queue;
|
|
1136
|
+
private readonly seenIds;
|
|
1137
|
+
private readonly maxSeenIds;
|
|
1138
|
+
private readonly maxEventsPerSec;
|
|
1139
|
+
private eventCountThisSecond;
|
|
1140
|
+
private currentSecond;
|
|
1141
|
+
private watchers;
|
|
1142
|
+
private fileOffsets;
|
|
1143
|
+
/** Resolve function to wake up the heartbeat loop when an event arrives */
|
|
1144
|
+
private wakeUp;
|
|
1145
|
+
constructor(options: EventQueueOptions);
|
|
1146
|
+
/**
|
|
1147
|
+
* Push an event into the queue. Applies dedup and rate limiting.
|
|
1148
|
+
*/
|
|
1149
|
+
push(event: QueuedEvent): boolean;
|
|
1150
|
+
/**
|
|
1151
|
+
* Drain all queued events and return them. Clears the queue.
|
|
1152
|
+
*/
|
|
1153
|
+
drain(): QueuedEvent[];
|
|
1154
|
+
size(): number;
|
|
1155
|
+
/**
|
|
1156
|
+
* Start watching inbox.jsonl and events.jsonl for new entries.
|
|
1157
|
+
* New lines are parsed and pushed into the queue.
|
|
1158
|
+
*/
|
|
1159
|
+
startWatching(inboxPath: string, eventsPath: string): void;
|
|
1160
|
+
stopWatching(): void;
|
|
1161
|
+
/**
|
|
1162
|
+
* Replay unprocessed events from disk on startup.
|
|
1163
|
+
*/
|
|
1164
|
+
replayUnprocessed(inboxPath: string, eventsPath: string): Promise<void>;
|
|
1165
|
+
/**
|
|
1166
|
+
* Returns a promise that resolves when a new event arrives or timeout is reached.
|
|
1167
|
+
*/
|
|
1168
|
+
waitForEvent(timeoutMs: number): Promise<void>;
|
|
1169
|
+
/**
|
|
1170
|
+
* Interrupt any pending waitForEvent — used during shutdown.
|
|
1171
|
+
*/
|
|
1172
|
+
interrupt(): void;
|
|
1173
|
+
private getEventId;
|
|
1174
|
+
private watchJsonlFile;
|
|
1175
|
+
private readNewLines;
|
|
1176
|
+
private replayFile;
|
|
1177
|
+
/**
|
|
1178
|
+
* Mark events as processed by rewriting the source files.
|
|
1179
|
+
*/
|
|
1180
|
+
markProcessed(inboxPath: string, eventsPath: string, events: QueuedEvent[]): Promise<void>;
|
|
1181
|
+
private markInFile;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
interface HeartbeatLoopOptions {
|
|
1185
|
+
config: GlobalConfig;
|
|
1186
|
+
supervisorDir: string;
|
|
1187
|
+
statePath: string;
|
|
1188
|
+
sessionId: string;
|
|
1189
|
+
eventQueue: EventQueue;
|
|
1190
|
+
activityLog: ActivityLog;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* The core autonomous loop. At each iteration:
|
|
1194
|
+
* 1. Drain events from the queue
|
|
1195
|
+
* 2. Build a prompt with context + memory + events
|
|
1196
|
+
* 3. Call sdk.query() for Claude to reason and act
|
|
1197
|
+
* 4. Extract and save updated memory
|
|
1198
|
+
* 5. Log activity
|
|
1199
|
+
* 6. Wait for the next event or idle timeout
|
|
1200
|
+
*/
|
|
1201
|
+
declare class HeartbeatLoop {
|
|
1202
|
+
private stopping;
|
|
1203
|
+
private consecutiveFailures;
|
|
1204
|
+
private activeAbort;
|
|
1205
|
+
private readonly config;
|
|
1206
|
+
private readonly supervisorDir;
|
|
1207
|
+
private readonly statePath;
|
|
1208
|
+
private sessionId;
|
|
1209
|
+
private readonly eventQueue;
|
|
1210
|
+
private readonly activityLog;
|
|
1211
|
+
private customInstructions;
|
|
1212
|
+
constructor(options: HeartbeatLoopOptions);
|
|
1213
|
+
start(): Promise<void>;
|
|
1214
|
+
stop(): void;
|
|
1215
|
+
private runHeartbeat;
|
|
1216
|
+
private readState;
|
|
1217
|
+
private updateState;
|
|
1218
|
+
/**
|
|
1219
|
+
* Load custom instructions from SUPERVISOR.md.
|
|
1220
|
+
* Resolution order:
|
|
1221
|
+
* 1. Explicit path via `supervisor.instructions` in config
|
|
1222
|
+
* 2. Default: ~/.neo/SUPERVISOR.md
|
|
1223
|
+
*/
|
|
1224
|
+
private loadInstructions;
|
|
1225
|
+
/** Route a single SDK stream message to the appropriate log handler. */
|
|
1226
|
+
private logStreamMessage;
|
|
1227
|
+
/** Log thinking and plan blocks from assistant content. */
|
|
1228
|
+
private logContentBlocks;
|
|
1229
|
+
/** Log tool use events — distinguish MCP tools from built-in tools. */
|
|
1230
|
+
private logToolUse;
|
|
1231
|
+
/** Detect agent dispatches from bash tool results. */
|
|
1232
|
+
private logToolResult;
|
|
1233
|
+
private sleep;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Load the supervisor memory from disk.
|
|
1238
|
+
* Returns empty string if no memory file exists yet.
|
|
1239
|
+
*/
|
|
1240
|
+
declare function loadMemory(dir: string): Promise<string>;
|
|
1241
|
+
/**
|
|
1242
|
+
* Save the supervisor memory to disk (full overwrite).
|
|
1243
|
+
*/
|
|
1244
|
+
declare function saveMemory(dir: string, content: string): Promise<void>;
|
|
1245
|
+
/**
|
|
1246
|
+
* Extract memory content from Claude's response using <memory>...</memory> tags.
|
|
1247
|
+
* Handles both JSON and markdown content inside the tags.
|
|
1248
|
+
* Returns null if no memory block is found.
|
|
1249
|
+
*/
|
|
1250
|
+
declare function extractMemoryFromResponse(response: string): string | null;
|
|
1251
|
+
/**
|
|
1252
|
+
* Check if memory content exceeds the recommended size limit.
|
|
1253
|
+
*/
|
|
1254
|
+
declare function checkMemorySize(content: string): {
|
|
1255
|
+
ok: boolean;
|
|
1256
|
+
sizeKB: number;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
interface HeartbeatPromptOptions {
|
|
1260
|
+
repos: RepoConfig[];
|
|
1261
|
+
memory: string;
|
|
1262
|
+
memorySizeKB: number;
|
|
1263
|
+
events: QueuedEvent[];
|
|
1264
|
+
budgetStatus: {
|
|
1265
|
+
todayUsd: number;
|
|
1266
|
+
capUsd: number;
|
|
1267
|
+
remainingPct: number;
|
|
1268
|
+
};
|
|
1269
|
+
activeRuns: string[];
|
|
1270
|
+
heartbeatCount: number;
|
|
1271
|
+
mcpServerNames: string[];
|
|
1272
|
+
customInstructions?: string | undefined;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Build the prompt sent to Claude at each heartbeat.
|
|
1276
|
+
*
|
|
1277
|
+
* Includes: role definition, current memory, pending events,
|
|
1278
|
+
* budget status, active runs, and available integrations.
|
|
1279
|
+
*/
|
|
1280
|
+
declare function buildHeartbeatPrompt(opts: HeartbeatPromptOptions): string;
|
|
1281
|
+
|
|
1282
|
+
interface WebhookServerOptions {
|
|
1283
|
+
port: number;
|
|
1284
|
+
secret?: string | undefined;
|
|
1285
|
+
eventsPath: string;
|
|
1286
|
+
onEvent: (event: WebhookIncomingEvent) => void;
|
|
1287
|
+
getHealth: () => Record<string, unknown>;
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Minimal HTTP server for receiving incoming webhooks.
|
|
1291
|
+
*
|
|
1292
|
+
* Routes:
|
|
1293
|
+
* POST /webhook — receive any JSON payload, persist to disk, push to queue
|
|
1294
|
+
* GET /health — liveness check with daemon status
|
|
1295
|
+
*
|
|
1296
|
+
* Uses raw http.createServer — zero external dependencies.
|
|
1297
|
+
*/
|
|
1298
|
+
declare class WebhookServer {
|
|
1299
|
+
private server;
|
|
1300
|
+
private readonly port;
|
|
1301
|
+
private readonly secret;
|
|
1302
|
+
private readonly eventsPath;
|
|
1303
|
+
private readonly onEvent;
|
|
1304
|
+
private readonly getHealth;
|
|
1305
|
+
constructor(options: WebhookServerOptions);
|
|
1306
|
+
start(): Promise<void>;
|
|
1307
|
+
stop(): Promise<void>;
|
|
1308
|
+
private handleRequest;
|
|
1309
|
+
private handleWebhook;
|
|
1310
|
+
private readBody;
|
|
1311
|
+
private sendJson;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
declare const workflowStepDefSchema: z.ZodObject<{
|
|
1315
|
+
type: z.ZodDefault<z.ZodOptional<z.ZodLiteral<"step">>>;
|
|
1316
|
+
agent: z.ZodString;
|
|
1317
|
+
dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1318
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
1319
|
+
sandbox: z.ZodOptional<z.ZodEnum<{
|
|
1320
|
+
readonly: "readonly";
|
|
1321
|
+
writable: "writable";
|
|
1322
|
+
}>>;
|
|
1323
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
1324
|
+
mcpServers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1325
|
+
recovery: z.ZodOptional<z.ZodObject<{
|
|
1326
|
+
maxRetries: z.ZodOptional<z.ZodNumber>;
|
|
1327
|
+
nonRetryable: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1328
|
+
}, z.core.$strip>>;
|
|
1329
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
1330
|
+
}, z.core.$strip>;
|
|
1331
|
+
declare const workflowGateDefSchema: z.ZodObject<{
|
|
1332
|
+
type: z.ZodLiteral<"gate">;
|
|
1333
|
+
dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1334
|
+
description: z.ZodString;
|
|
1335
|
+
timeout: z.ZodOptional<z.ZodString>;
|
|
1336
|
+
autoApprove: z.ZodOptional<z.ZodBoolean>;
|
|
1337
|
+
}, z.core.$strip>;
|
|
1338
|
+
declare function loadWorkflow(filePath: string): Promise<WorkflowDefinition>;
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Registry for workflow definitions.
|
|
1342
|
+
* Loads built-in workflows from a directory and optional custom workflows.
|
|
1343
|
+
* Custom workflows with the same name override built-in ones.
|
|
1344
|
+
*/
|
|
1345
|
+
declare class WorkflowRegistry {
|
|
1346
|
+
private readonly builtInDir;
|
|
1347
|
+
private readonly customDir;
|
|
1348
|
+
private readonly workflows;
|
|
1349
|
+
constructor(builtInDir: string, customDir?: string);
|
|
1350
|
+
load(): Promise<void>;
|
|
1351
|
+
get(name: string): WorkflowDefinition | undefined;
|
|
1352
|
+
list(): WorkflowDefinition[];
|
|
1353
|
+
has(name: string): boolean;
|
|
1354
|
+
private loadFromDir;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
declare const VERSION = "0.1.0";
|
|
1358
|
+
|
|
1359
|
+
export { type ActiveSession, type ActivityEntry, ActivityLog, type AgentConfig, type AgentDefinition, type AgentMessageEvent, type AgentModel, AgentRegistry, type AgentTool, type AgentToolEntry, type AgentToolUseEvent, type AuditLogMiddleware, type BudgetAlertEvent, type CostEntry, CostJournal, type CostUpdateEvent, type DispatchInput, EventJournal, EventQueue, type GateWaitingEvent, type GlobalConfig, HeartbeatLoop, type HeartbeatLoopOptions, type HeartbeatPromptOptions, type HookEvent, type InboxMessage, type LoopDetectionMiddleware, type McpServerConfig, type Middleware, type MiddlewareChain, type MiddlewareContext, type MiddlewareContextMap, type MiddlewareEvent, type MiddlewareHandler, type MiddlewareResult, type NeoConfig, type NeoEvent, NeoEventEmitter, Orchestrator, type OrchestratorOptions, type OrchestratorShutdownEvent, type OrchestratorStatus, type ParsedOutput, type PersistedRun, type Priority, type QueueDequeueEvent, type QueueEnqueueEvent, type QueuedEvent, type RecoveryOptions, type RepoConfig, type RepoConfigInput, type ResolvedAgent, type SDKHooks, type SandboxConfig, Semaphore, type SemaphoreCallbacks, type SemaphoreConfig, type SessionCompleteEvent, SessionError, type SessionEvent, type SessionFailEvent, type SessionOptions, type SessionResult, type SessionStartEvent, type StepResult, SupervisorDaemon, type SupervisorDaemonOptions, type SupervisorDaemonState, type SupervisorDaemonState as SupervisorState, type TaskResult, VERSION, WebhookDispatcher, type WebhookIncomingEvent, WebhookServer, type WorkflowContext, type WorkflowDefinition, type WorkflowGateDef, WorkflowRegistry, type WorkflowStepCompleteEvent, type WorkflowStepDef, type WorkflowStepStartEvent, type WorktreeInfo, activityEntrySchema, addRepoToGlobalConfig, agentConfigSchema, agentModelSchema, agentSandboxSchema, agentToolEntrySchema, agentToolSchema, auditLog, budgetGuard, buildHeartbeatPrompt, buildMiddlewareChain, buildSDKHooks, buildSandboxConfig, checkMemorySize, cleanupOrphanedWorktrees, createBranch, createWorktree, deleteBranch, extractMemoryFromResponse, fetchRemote, getBranchName, getCurrentBranch, getDataDir, getJournalsDir, getRepoRunsDir, getRunDispatchPath, getRunLogPath, getRunsDir, getSupervisorActivityPath, getSupervisorDir, getSupervisorEventsPath, getSupervisorInboxPath, getSupervisorLockPath, getSupervisorMemoryPath, getSupervisorStatePath, getSupervisorsDir, globalConfigSchema, inboxMessageSchema, listReposFromGlobalConfig, listWorktrees, loadAgentFile, loadConfig, loadGlobalConfig, loadMemory, loadWorkflow, loopDetection, matchesFilter, mcpServerConfigSchema, neoConfigSchema, parseOutput, pushBranch, removeRepoFromGlobalConfig, removeWorktree, repoConfigSchema, resolveAgent, runSession, runWithRecovery, saveMemory, supervisorDaemonStateSchema, supervisorDaemonStateSchema as supervisorStateSchema, toRepoSlug, webhookIncomingEventSchema, withGitLock, workflowGateDefSchema, workflowStepDefSchema };
|