@mulep/core 0.2.14
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/dist/index.d.ts +2902 -0
- package/dist/index.js +7159 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2902 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Ignore } from 'ignore';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { EventEmitter } from 'eventemitter3';
|
|
5
|
+
|
|
6
|
+
type ModelProvider = 'openai';
|
|
7
|
+
interface CliAdapterConfig {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
timeout: number;
|
|
11
|
+
outputFile?: string;
|
|
12
|
+
maxOutputBytes?: number;
|
|
13
|
+
envAllowlist?: string[];
|
|
14
|
+
}
|
|
15
|
+
interface ModelConfig {
|
|
16
|
+
provider: ModelProvider;
|
|
17
|
+
model: string;
|
|
18
|
+
maxTokens: number;
|
|
19
|
+
temperature: number;
|
|
20
|
+
timeout: number;
|
|
21
|
+
cliAdapter?: CliAdapterConfig;
|
|
22
|
+
}
|
|
23
|
+
interface RoleConfig {
|
|
24
|
+
model: string;
|
|
25
|
+
temperature?: number;
|
|
26
|
+
maxTokens?: number;
|
|
27
|
+
systemPromptFile?: string;
|
|
28
|
+
}
|
|
29
|
+
interface DebateConfig {
|
|
30
|
+
defaultPattern: DebatePattern;
|
|
31
|
+
maxRounds: number;
|
|
32
|
+
consensusThreshold: number;
|
|
33
|
+
}
|
|
34
|
+
type DebatePattern = 'structured-rounds' | 'proposal-critique' | 'free-flowing' | 'parallel-panel';
|
|
35
|
+
interface MemoryConfig {
|
|
36
|
+
embeddingModel?: string;
|
|
37
|
+
autoExtractFacts: boolean;
|
|
38
|
+
contextBudget: {
|
|
39
|
+
activeContext: number;
|
|
40
|
+
retrievedMemory: number;
|
|
41
|
+
messageBuffer: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
interface BudgetConfig {
|
|
45
|
+
perSession: number;
|
|
46
|
+
perDay: number;
|
|
47
|
+
perMonth: number;
|
|
48
|
+
warningAt: number;
|
|
49
|
+
action: 'warn' | 'pause' | 'block';
|
|
50
|
+
}
|
|
51
|
+
interface OutputConfig {
|
|
52
|
+
saveTranscripts: boolean;
|
|
53
|
+
transcriptFormat: 'markdown' | 'json';
|
|
54
|
+
transcriptDir: string;
|
|
55
|
+
}
|
|
56
|
+
interface ProjectConfig {
|
|
57
|
+
configVersion?: number;
|
|
58
|
+
project: {
|
|
59
|
+
name: string;
|
|
60
|
+
description: string;
|
|
61
|
+
};
|
|
62
|
+
models: Record<string, ModelConfig>;
|
|
63
|
+
roles: Record<string, RoleConfig>;
|
|
64
|
+
workflow: string;
|
|
65
|
+
mode: ExecutionMode;
|
|
66
|
+
debate: DebateConfig;
|
|
67
|
+
memory: MemoryConfig;
|
|
68
|
+
budget: BudgetConfig;
|
|
69
|
+
output: OutputConfig;
|
|
70
|
+
advanced: {
|
|
71
|
+
retryAttempts: number;
|
|
72
|
+
stream: boolean;
|
|
73
|
+
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
type ExecutionMode = 'autonomous' | 'interactive' | 'dashboard';
|
|
77
|
+
type PresetName = 'cli-first';
|
|
78
|
+
|
|
79
|
+
declare enum ErrorCode {
|
|
80
|
+
INVALID_INPUT = "INVALID_INPUT",
|
|
81
|
+
MODEL_UNAVAILABLE = "MODEL_UNAVAILABLE",
|
|
82
|
+
RATE_LIMITED = "RATE_LIMITED",
|
|
83
|
+
TIMEOUT = "TIMEOUT",
|
|
84
|
+
DLP_BLOCKED = "DLP_BLOCKED",
|
|
85
|
+
EGRESS_BLOCKED = "EGRESS_BLOCKED",
|
|
86
|
+
BUDGET_EXCEEDED = "BUDGET_EXCEEDED",
|
|
87
|
+
CLI_NOT_FOUND = "CLI_NOT_FOUND",
|
|
88
|
+
CLI_AUTH_FAILED = "CLI_AUTH_FAILED",
|
|
89
|
+
CANCELLED = "CANCELLED",
|
|
90
|
+
INTERNAL_ERROR = "INTERNAL_ERROR"
|
|
91
|
+
}
|
|
92
|
+
declare enum TerminalReason {
|
|
93
|
+
COMPLETED = "COMPLETED",
|
|
94
|
+
TIMEOUT = "TIMEOUT",
|
|
95
|
+
CANCELLED = "CANCELLED",
|
|
96
|
+
BUDGET_EXCEEDED = "BUDGET_EXCEEDED",
|
|
97
|
+
MAX_RETRIES = "MAX_RETRIES"
|
|
98
|
+
}
|
|
99
|
+
type ResultStatus = 'success' | 'partial' | 'error';
|
|
100
|
+
declare enum DlpReasonCode {
|
|
101
|
+
SECRET_DETECTED = "SECRET_DETECTED",
|
|
102
|
+
HIGH_ENTROPY = "HIGH_ENTROPY",
|
|
103
|
+
ABSOLUTE_PATH = "ABSOLUTE_PATH",
|
|
104
|
+
CONTEXT_TRUNCATED = "CONTEXT_TRUNCATED",
|
|
105
|
+
DECODE_BLOCKED = "DECODE_BLOCKED",
|
|
106
|
+
BUDGET_EXCEEDED = "BUDGET_EXCEEDED"
|
|
107
|
+
}
|
|
108
|
+
type MeteringSource = 'billed' | 'estimated' | 'sdk';
|
|
109
|
+
interface ReviewResult {
|
|
110
|
+
status: ResultStatus;
|
|
111
|
+
score: number;
|
|
112
|
+
verdict: 'approved' | 'needs_revision';
|
|
113
|
+
feedback: string[];
|
|
114
|
+
tokenUsage: {
|
|
115
|
+
inputTokens: number;
|
|
116
|
+
outputTokens: number;
|
|
117
|
+
totalTokens: number;
|
|
118
|
+
costUsd: number;
|
|
119
|
+
};
|
|
120
|
+
latencyMs: number;
|
|
121
|
+
meteringSource: MeteringSource;
|
|
122
|
+
model: string;
|
|
123
|
+
egressControl: 'mulep-enforced' | 'cli-managed';
|
|
124
|
+
}
|
|
125
|
+
interface DebateResponse {
|
|
126
|
+
model: string;
|
|
127
|
+
role: string;
|
|
128
|
+
text: string;
|
|
129
|
+
tokenUsage: {
|
|
130
|
+
inputTokens: number;
|
|
131
|
+
outputTokens: number;
|
|
132
|
+
totalTokens: number;
|
|
133
|
+
costUsd: number;
|
|
134
|
+
};
|
|
135
|
+
latencyMs: number;
|
|
136
|
+
meteringSource: MeteringSource;
|
|
137
|
+
error?: string;
|
|
138
|
+
}
|
|
139
|
+
interface DebateResult {
|
|
140
|
+
status: ResultStatus;
|
|
141
|
+
responses: DebateResponse[];
|
|
142
|
+
synthesis?: string;
|
|
143
|
+
agreement?: number;
|
|
144
|
+
totalTokenUsage: {
|
|
145
|
+
inputTokens: number;
|
|
146
|
+
outputTokens: number;
|
|
147
|
+
totalTokens: number;
|
|
148
|
+
costUsd: number;
|
|
149
|
+
};
|
|
150
|
+
partialFailure?: boolean;
|
|
151
|
+
egressControl: 'mulep-enforced' | 'cli-managed';
|
|
152
|
+
}
|
|
153
|
+
declare const reviewInputSchema: z.ZodObject<{
|
|
154
|
+
content: z.ZodString;
|
|
155
|
+
criteria: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
156
|
+
model: z.ZodOptional<z.ZodString>;
|
|
157
|
+
strict: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
158
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
159
|
+
}, "strip", z.ZodTypeAny, {
|
|
160
|
+
content: string;
|
|
161
|
+
strict: boolean;
|
|
162
|
+
timeout: number;
|
|
163
|
+
criteria?: string[] | undefined;
|
|
164
|
+
model?: string | undefined;
|
|
165
|
+
}, {
|
|
166
|
+
content: string;
|
|
167
|
+
criteria?: string[] | undefined;
|
|
168
|
+
model?: string | undefined;
|
|
169
|
+
strict?: boolean | undefined;
|
|
170
|
+
timeout?: number | undefined;
|
|
171
|
+
}>;
|
|
172
|
+
type ReviewInput = z.infer<typeof reviewInputSchema>;
|
|
173
|
+
declare const planInputSchema: z.ZodObject<{
|
|
174
|
+
task: z.ZodString;
|
|
175
|
+
maxRounds: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
176
|
+
stream: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
177
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
178
|
+
}, "strip", z.ZodTypeAny, {
|
|
179
|
+
timeout: number;
|
|
180
|
+
task: string;
|
|
181
|
+
maxRounds: number;
|
|
182
|
+
stream: boolean;
|
|
183
|
+
}, {
|
|
184
|
+
task: string;
|
|
185
|
+
timeout?: number | undefined;
|
|
186
|
+
maxRounds?: number | undefined;
|
|
187
|
+
stream?: boolean | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
type PlanInput = z.infer<typeof planInputSchema>;
|
|
190
|
+
declare const debateInputSchema: z.ZodObject<{
|
|
191
|
+
question: z.ZodString;
|
|
192
|
+
models: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
193
|
+
synthesize: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
194
|
+
maxRounds: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
195
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
196
|
+
}, "strip", z.ZodTypeAny, {
|
|
197
|
+
timeout: number;
|
|
198
|
+
maxRounds: number;
|
|
199
|
+
question: string;
|
|
200
|
+
synthesize: boolean;
|
|
201
|
+
models?: string[] | undefined;
|
|
202
|
+
}, {
|
|
203
|
+
question: string;
|
|
204
|
+
timeout?: number | undefined;
|
|
205
|
+
maxRounds?: number | undefined;
|
|
206
|
+
models?: string[] | undefined;
|
|
207
|
+
synthesize?: boolean | undefined;
|
|
208
|
+
}>;
|
|
209
|
+
type DebateInput = z.infer<typeof debateInputSchema>;
|
|
210
|
+
declare const memoryInputSchema: z.ZodObject<{
|
|
211
|
+
action: z.ZodEnum<["save", "search", "get", "delete"]>;
|
|
212
|
+
content: z.ZodOptional<z.ZodString>;
|
|
213
|
+
query: z.ZodOptional<z.ZodString>;
|
|
214
|
+
memoryId: z.ZodOptional<z.ZodNumber>;
|
|
215
|
+
category: z.ZodOptional<z.ZodEnum<["decision", "convention", "pattern", "issue", "preference"]>>;
|
|
216
|
+
importance: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
217
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
218
|
+
}, "strip", z.ZodTypeAny, {
|
|
219
|
+
timeout: number;
|
|
220
|
+
action: "save" | "search" | "get" | "delete";
|
|
221
|
+
importance: number;
|
|
222
|
+
content?: string | undefined;
|
|
223
|
+
query?: string | undefined;
|
|
224
|
+
memoryId?: number | undefined;
|
|
225
|
+
category?: "decision" | "convention" | "pattern" | "issue" | "preference" | undefined;
|
|
226
|
+
}, {
|
|
227
|
+
action: "save" | "search" | "get" | "delete";
|
|
228
|
+
content?: string | undefined;
|
|
229
|
+
timeout?: number | undefined;
|
|
230
|
+
query?: string | undefined;
|
|
231
|
+
memoryId?: number | undefined;
|
|
232
|
+
category?: "decision" | "convention" | "pattern" | "issue" | "preference" | undefined;
|
|
233
|
+
importance?: number | undefined;
|
|
234
|
+
}>;
|
|
235
|
+
type MemoryInput = z.infer<typeof memoryInputSchema>;
|
|
236
|
+
declare const costInputSchema: z.ZodObject<{
|
|
237
|
+
scope: z.ZodDefault<z.ZodOptional<z.ZodEnum<["session", "daily", "all"]>>>;
|
|
238
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
239
|
+
days: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
240
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
241
|
+
}, "strip", z.ZodTypeAny, {
|
|
242
|
+
timeout: number;
|
|
243
|
+
scope: "session" | "daily" | "all";
|
|
244
|
+
days: number;
|
|
245
|
+
sessionId?: string | undefined;
|
|
246
|
+
}, {
|
|
247
|
+
timeout?: number | undefined;
|
|
248
|
+
scope?: "session" | "daily" | "all" | undefined;
|
|
249
|
+
sessionId?: string | undefined;
|
|
250
|
+
days?: number | undefined;
|
|
251
|
+
}>;
|
|
252
|
+
type CostInput = z.infer<typeof costInputSchema>;
|
|
253
|
+
declare const reviewOutputSchema: z.ZodObject<{
|
|
254
|
+
status: z.ZodEnum<["success", "partial", "error"]>;
|
|
255
|
+
score: z.ZodNumber;
|
|
256
|
+
verdict: z.ZodEnum<["approved", "needs_revision"]>;
|
|
257
|
+
feedback: z.ZodArray<z.ZodString, "many">;
|
|
258
|
+
tokenUsage: z.ZodObject<{
|
|
259
|
+
inputTokens: z.ZodNumber;
|
|
260
|
+
outputTokens: z.ZodNumber;
|
|
261
|
+
totalTokens: z.ZodNumber;
|
|
262
|
+
costUsd: z.ZodNumber;
|
|
263
|
+
}, "strip", z.ZodTypeAny, {
|
|
264
|
+
inputTokens: number;
|
|
265
|
+
outputTokens: number;
|
|
266
|
+
totalTokens: number;
|
|
267
|
+
costUsd: number;
|
|
268
|
+
}, {
|
|
269
|
+
inputTokens: number;
|
|
270
|
+
outputTokens: number;
|
|
271
|
+
totalTokens: number;
|
|
272
|
+
costUsd: number;
|
|
273
|
+
}>;
|
|
274
|
+
latencyMs: z.ZodNumber;
|
|
275
|
+
meteringSource: z.ZodEnum<["billed", "estimated", "sdk"]>;
|
|
276
|
+
model: z.ZodString;
|
|
277
|
+
egressControl: z.ZodEnum<["mulep-enforced", "cli-managed"]>;
|
|
278
|
+
}, "strip", z.ZodTypeAny, {
|
|
279
|
+
status: "error" | "success" | "partial";
|
|
280
|
+
model: string;
|
|
281
|
+
score: number;
|
|
282
|
+
verdict: "approved" | "needs_revision";
|
|
283
|
+
feedback: string[];
|
|
284
|
+
tokenUsage: {
|
|
285
|
+
inputTokens: number;
|
|
286
|
+
outputTokens: number;
|
|
287
|
+
totalTokens: number;
|
|
288
|
+
costUsd: number;
|
|
289
|
+
};
|
|
290
|
+
latencyMs: number;
|
|
291
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
292
|
+
egressControl: "mulep-enforced" | "cli-managed";
|
|
293
|
+
}, {
|
|
294
|
+
status: "error" | "success" | "partial";
|
|
295
|
+
model: string;
|
|
296
|
+
score: number;
|
|
297
|
+
verdict: "approved" | "needs_revision";
|
|
298
|
+
feedback: string[];
|
|
299
|
+
tokenUsage: {
|
|
300
|
+
inputTokens: number;
|
|
301
|
+
outputTokens: number;
|
|
302
|
+
totalTokens: number;
|
|
303
|
+
costUsd: number;
|
|
304
|
+
};
|
|
305
|
+
latencyMs: number;
|
|
306
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
307
|
+
egressControl: "mulep-enforced" | "cli-managed";
|
|
308
|
+
}>;
|
|
309
|
+
declare const debateOutputSchema: z.ZodObject<{
|
|
310
|
+
status: z.ZodEnum<["success", "partial", "error"]>;
|
|
311
|
+
responses: z.ZodArray<z.ZodObject<{
|
|
312
|
+
model: z.ZodString;
|
|
313
|
+
role: z.ZodString;
|
|
314
|
+
text: z.ZodString;
|
|
315
|
+
tokenUsage: z.ZodObject<{
|
|
316
|
+
inputTokens: z.ZodNumber;
|
|
317
|
+
outputTokens: z.ZodNumber;
|
|
318
|
+
totalTokens: z.ZodNumber;
|
|
319
|
+
costUsd: z.ZodNumber;
|
|
320
|
+
}, "strip", z.ZodTypeAny, {
|
|
321
|
+
inputTokens: number;
|
|
322
|
+
outputTokens: number;
|
|
323
|
+
totalTokens: number;
|
|
324
|
+
costUsd: number;
|
|
325
|
+
}, {
|
|
326
|
+
inputTokens: number;
|
|
327
|
+
outputTokens: number;
|
|
328
|
+
totalTokens: number;
|
|
329
|
+
costUsd: number;
|
|
330
|
+
}>;
|
|
331
|
+
latencyMs: z.ZodNumber;
|
|
332
|
+
meteringSource: z.ZodEnum<["billed", "estimated", "sdk"]>;
|
|
333
|
+
error: z.ZodOptional<z.ZodString>;
|
|
334
|
+
}, "strip", z.ZodTypeAny, {
|
|
335
|
+
model: string;
|
|
336
|
+
tokenUsage: {
|
|
337
|
+
inputTokens: number;
|
|
338
|
+
outputTokens: number;
|
|
339
|
+
totalTokens: number;
|
|
340
|
+
costUsd: number;
|
|
341
|
+
};
|
|
342
|
+
latencyMs: number;
|
|
343
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
344
|
+
role: string;
|
|
345
|
+
text: string;
|
|
346
|
+
error?: string | undefined;
|
|
347
|
+
}, {
|
|
348
|
+
model: string;
|
|
349
|
+
tokenUsage: {
|
|
350
|
+
inputTokens: number;
|
|
351
|
+
outputTokens: number;
|
|
352
|
+
totalTokens: number;
|
|
353
|
+
costUsd: number;
|
|
354
|
+
};
|
|
355
|
+
latencyMs: number;
|
|
356
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
357
|
+
role: string;
|
|
358
|
+
text: string;
|
|
359
|
+
error?: string | undefined;
|
|
360
|
+
}>, "many">;
|
|
361
|
+
synthesis: z.ZodOptional<z.ZodString>;
|
|
362
|
+
agreement: z.ZodOptional<z.ZodNumber>;
|
|
363
|
+
totalTokenUsage: z.ZodObject<{
|
|
364
|
+
inputTokens: z.ZodNumber;
|
|
365
|
+
outputTokens: z.ZodNumber;
|
|
366
|
+
totalTokens: z.ZodNumber;
|
|
367
|
+
costUsd: z.ZodNumber;
|
|
368
|
+
}, "strip", z.ZodTypeAny, {
|
|
369
|
+
inputTokens: number;
|
|
370
|
+
outputTokens: number;
|
|
371
|
+
totalTokens: number;
|
|
372
|
+
costUsd: number;
|
|
373
|
+
}, {
|
|
374
|
+
inputTokens: number;
|
|
375
|
+
outputTokens: number;
|
|
376
|
+
totalTokens: number;
|
|
377
|
+
costUsd: number;
|
|
378
|
+
}>;
|
|
379
|
+
partialFailure: z.ZodOptional<z.ZodBoolean>;
|
|
380
|
+
egressControl: z.ZodEnum<["mulep-enforced", "cli-managed"]>;
|
|
381
|
+
}, "strip", z.ZodTypeAny, {
|
|
382
|
+
status: "error" | "success" | "partial";
|
|
383
|
+
egressControl: "mulep-enforced" | "cli-managed";
|
|
384
|
+
responses: {
|
|
385
|
+
model: string;
|
|
386
|
+
tokenUsage: {
|
|
387
|
+
inputTokens: number;
|
|
388
|
+
outputTokens: number;
|
|
389
|
+
totalTokens: number;
|
|
390
|
+
costUsd: number;
|
|
391
|
+
};
|
|
392
|
+
latencyMs: number;
|
|
393
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
394
|
+
role: string;
|
|
395
|
+
text: string;
|
|
396
|
+
error?: string | undefined;
|
|
397
|
+
}[];
|
|
398
|
+
totalTokenUsage: {
|
|
399
|
+
inputTokens: number;
|
|
400
|
+
outputTokens: number;
|
|
401
|
+
totalTokens: number;
|
|
402
|
+
costUsd: number;
|
|
403
|
+
};
|
|
404
|
+
synthesis?: string | undefined;
|
|
405
|
+
agreement?: number | undefined;
|
|
406
|
+
partialFailure?: boolean | undefined;
|
|
407
|
+
}, {
|
|
408
|
+
status: "error" | "success" | "partial";
|
|
409
|
+
egressControl: "mulep-enforced" | "cli-managed";
|
|
410
|
+
responses: {
|
|
411
|
+
model: string;
|
|
412
|
+
tokenUsage: {
|
|
413
|
+
inputTokens: number;
|
|
414
|
+
outputTokens: number;
|
|
415
|
+
totalTokens: number;
|
|
416
|
+
costUsd: number;
|
|
417
|
+
};
|
|
418
|
+
latencyMs: number;
|
|
419
|
+
meteringSource: "billed" | "estimated" | "sdk";
|
|
420
|
+
role: string;
|
|
421
|
+
text: string;
|
|
422
|
+
error?: string | undefined;
|
|
423
|
+
}[];
|
|
424
|
+
totalTokenUsage: {
|
|
425
|
+
inputTokens: number;
|
|
426
|
+
outputTokens: number;
|
|
427
|
+
totalTokens: number;
|
|
428
|
+
costUsd: number;
|
|
429
|
+
};
|
|
430
|
+
synthesis?: string | undefined;
|
|
431
|
+
agreement?: number | undefined;
|
|
432
|
+
partialFailure?: boolean | undefined;
|
|
433
|
+
}>;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* A workflow is a DAG of steps loaded from YAML.
|
|
437
|
+
* Sprint 1 supports: generate, review. Other types are parsed but not executed.
|
|
438
|
+
*/
|
|
439
|
+
interface WorkflowDefinition {
|
|
440
|
+
name: string;
|
|
441
|
+
description?: string;
|
|
442
|
+
steps: StepDefinition[];
|
|
443
|
+
}
|
|
444
|
+
interface StepDefinition {
|
|
445
|
+
id: string;
|
|
446
|
+
type: StepType;
|
|
447
|
+
role: string;
|
|
448
|
+
input?: string[];
|
|
449
|
+
output?: string;
|
|
450
|
+
loop?: LoopConfig;
|
|
451
|
+
steps?: StepDefinition[];
|
|
452
|
+
command?: string;
|
|
453
|
+
gateMode?: 'always' | 'conditional';
|
|
454
|
+
}
|
|
455
|
+
type StepType = 'generate' | 'review' | 'debate' | 'transform' | 'gate' | 'parallel' | 'conditional';
|
|
456
|
+
interface LoopConfig {
|
|
457
|
+
maxIterations: number;
|
|
458
|
+
exitWhen: string;
|
|
459
|
+
iteratesWith: string;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Validated workflow: steps resolved into execution order.
|
|
463
|
+
* The engine works with this, not the raw definition.
|
|
464
|
+
*/
|
|
465
|
+
interface ResolvedWorkflow {
|
|
466
|
+
name: string;
|
|
467
|
+
executionOrder: ResolvedStep[];
|
|
468
|
+
}
|
|
469
|
+
interface ResolvedStep {
|
|
470
|
+
definition: StepDefinition;
|
|
471
|
+
inputStepIds: string[];
|
|
472
|
+
isLoopEntry: boolean;
|
|
473
|
+
loopPartnerStepId?: string;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* AG-UI compatible event types.
|
|
478
|
+
* Emitted by the core engine and consumed by CLI / Web.
|
|
479
|
+
* Type names follow AG-UI convention (dot-separated).
|
|
480
|
+
*/
|
|
481
|
+
interface SessionStartedEvent {
|
|
482
|
+
type: 'session.started';
|
|
483
|
+
sessionId: string;
|
|
484
|
+
workflow: string;
|
|
485
|
+
task: string;
|
|
486
|
+
timestamp: string;
|
|
487
|
+
}
|
|
488
|
+
interface SessionCompletedEvent {
|
|
489
|
+
type: 'session.completed';
|
|
490
|
+
sessionId: string;
|
|
491
|
+
finalOutput: string;
|
|
492
|
+
totalCost: number;
|
|
493
|
+
totalTokens: number;
|
|
494
|
+
durationMs: number;
|
|
495
|
+
timestamp: string;
|
|
496
|
+
}
|
|
497
|
+
interface SessionFailedEvent {
|
|
498
|
+
type: 'session.failed';
|
|
499
|
+
sessionId: string;
|
|
500
|
+
error: string;
|
|
501
|
+
lastStep: string;
|
|
502
|
+
timestamp: string;
|
|
503
|
+
}
|
|
504
|
+
interface StepStartedEvent {
|
|
505
|
+
type: 'step.started';
|
|
506
|
+
stepId: string;
|
|
507
|
+
role: string;
|
|
508
|
+
model: string;
|
|
509
|
+
iteration: number;
|
|
510
|
+
timestamp: string;
|
|
511
|
+
}
|
|
512
|
+
interface StepCompletedEvent {
|
|
513
|
+
type: 'step.completed';
|
|
514
|
+
stepId: string;
|
|
515
|
+
output: string;
|
|
516
|
+
tokenUsage: TokenUsage;
|
|
517
|
+
durationMs: number;
|
|
518
|
+
timestamp: string;
|
|
519
|
+
}
|
|
520
|
+
interface StepFailedEvent {
|
|
521
|
+
type: 'step.failed';
|
|
522
|
+
stepId: string;
|
|
523
|
+
error: string;
|
|
524
|
+
retriesExhausted: boolean;
|
|
525
|
+
timestamp: string;
|
|
526
|
+
}
|
|
527
|
+
interface TextDeltaEvent {
|
|
528
|
+
type: 'text.delta';
|
|
529
|
+
stepId: string;
|
|
530
|
+
role: string;
|
|
531
|
+
delta: string;
|
|
532
|
+
}
|
|
533
|
+
interface TextDoneEvent {
|
|
534
|
+
type: 'text.done';
|
|
535
|
+
stepId: string;
|
|
536
|
+
role: string;
|
|
537
|
+
fullText: string;
|
|
538
|
+
}
|
|
539
|
+
interface LoopIterationEvent {
|
|
540
|
+
type: 'loop.iteration';
|
|
541
|
+
stepId: string;
|
|
542
|
+
iteration: number;
|
|
543
|
+
maxIterations: number;
|
|
544
|
+
verdict: 'approved' | 'needs_revision';
|
|
545
|
+
feedback?: string;
|
|
546
|
+
timestamp: string;
|
|
547
|
+
}
|
|
548
|
+
interface CostUpdateEvent {
|
|
549
|
+
type: 'cost.update';
|
|
550
|
+
model: string;
|
|
551
|
+
inputTokens: number;
|
|
552
|
+
outputTokens: number;
|
|
553
|
+
costUsd: number;
|
|
554
|
+
cumulativeSessionCost: number;
|
|
555
|
+
timestamp: string;
|
|
556
|
+
}
|
|
557
|
+
interface TokenUsage {
|
|
558
|
+
inputTokens: number;
|
|
559
|
+
outputTokens: number;
|
|
560
|
+
totalTokens: number;
|
|
561
|
+
costUsd: number;
|
|
562
|
+
}
|
|
563
|
+
type EngineEvent = SessionStartedEvent | SessionCompletedEvent | SessionFailedEvent | StepStartedEvent | StepCompletedEvent | StepFailedEvent | TextDeltaEvent | TextDoneEvent | LoopIterationEvent | CostUpdateEvent;
|
|
564
|
+
|
|
565
|
+
type SessionStatus = 'running' | 'paused' | 'completed' | 'failed' | 'cancelled';
|
|
566
|
+
interface Session {
|
|
567
|
+
id: string;
|
|
568
|
+
projectId: string;
|
|
569
|
+
workflowId: string;
|
|
570
|
+
task: string;
|
|
571
|
+
status: SessionStatus;
|
|
572
|
+
mode: ExecutionMode;
|
|
573
|
+
currentStep: string | null;
|
|
574
|
+
configSnapshot: string;
|
|
575
|
+
startedAt: string;
|
|
576
|
+
updatedAt: string;
|
|
577
|
+
completedAt: string | null;
|
|
578
|
+
summary: string | null;
|
|
579
|
+
totalCost: number;
|
|
580
|
+
totalTokens: number;
|
|
581
|
+
metadata: Record<string, unknown>;
|
|
582
|
+
}
|
|
583
|
+
interface TranscriptEntry {
|
|
584
|
+
id?: number;
|
|
585
|
+
sessionId: string;
|
|
586
|
+
stepId: string;
|
|
587
|
+
iteration: number | null;
|
|
588
|
+
role: string;
|
|
589
|
+
modelId: string | null;
|
|
590
|
+
content: string;
|
|
591
|
+
tokenCount: number | null;
|
|
592
|
+
cost: number | null;
|
|
593
|
+
createdAt: string;
|
|
594
|
+
metadata: Record<string, unknown> | null;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
type MemoryCategory = 'decision' | 'convention' | 'pattern' | 'issue' | 'preference';
|
|
598
|
+
interface MemoryRecord {
|
|
599
|
+
id?: number;
|
|
600
|
+
projectId: string;
|
|
601
|
+
category: MemoryCategory;
|
|
602
|
+
content: string;
|
|
603
|
+
sourceSessionId: string | null;
|
|
604
|
+
importance: number;
|
|
605
|
+
createdAt: string;
|
|
606
|
+
accessedAt: string;
|
|
607
|
+
accessCount: number;
|
|
608
|
+
}
|
|
609
|
+
type ArtifactType = 'plan' | 'code' | 'review' | 'test';
|
|
610
|
+
interface ArtifactRecord {
|
|
611
|
+
id?: number;
|
|
612
|
+
sessionId: string;
|
|
613
|
+
stepId: string;
|
|
614
|
+
iteration: number;
|
|
615
|
+
type: ArtifactType;
|
|
616
|
+
filePath: string | null;
|
|
617
|
+
content: string;
|
|
618
|
+
version: number;
|
|
619
|
+
createdAt: string;
|
|
620
|
+
metadata: Record<string, unknown> | null;
|
|
621
|
+
}
|
|
622
|
+
interface CostLogEntry {
|
|
623
|
+
id?: number;
|
|
624
|
+
sessionId: string;
|
|
625
|
+
stepId: string | null;
|
|
626
|
+
modelId: string;
|
|
627
|
+
inputTokens: number;
|
|
628
|
+
outputTokens: number;
|
|
629
|
+
costUsd: number;
|
|
630
|
+
latencyMs: number;
|
|
631
|
+
createdAt: string;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Chat message format. Aligns with Vercel AI SDK's CoreMessage.
|
|
636
|
+
*/
|
|
637
|
+
interface ChatMessage {
|
|
638
|
+
role: 'system' | 'user' | 'assistant';
|
|
639
|
+
content: string;
|
|
640
|
+
}
|
|
641
|
+
interface CallModelOptions {
|
|
642
|
+
maxTokens?: number;
|
|
643
|
+
temperature?: number;
|
|
644
|
+
systemPrompt?: string;
|
|
645
|
+
/** Timeout in seconds for CLI subprocess calls. Default: 120. */
|
|
646
|
+
timeout?: number;
|
|
647
|
+
}
|
|
648
|
+
interface ModelCallResult {
|
|
649
|
+
text: string;
|
|
650
|
+
model: string;
|
|
651
|
+
provider: ModelProvider;
|
|
652
|
+
usage: TokenUsage;
|
|
653
|
+
finishReason: string;
|
|
654
|
+
durationMs: number;
|
|
655
|
+
meteringSource?: MeteringSource;
|
|
656
|
+
/** Codex thread ID for session resume. */
|
|
657
|
+
sessionId?: string;
|
|
658
|
+
}
|
|
659
|
+
interface FallbackConfig {
|
|
660
|
+
primary: string;
|
|
661
|
+
fallbacks: string[];
|
|
662
|
+
maxRetries: number;
|
|
663
|
+
retryOn: {
|
|
664
|
+
rateLimit: boolean;
|
|
665
|
+
timeout: boolean;
|
|
666
|
+
serverError: boolean;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
type BuiltInRole = 'architect' | 'reviewer' | 'implementer';
|
|
671
|
+
interface Role {
|
|
672
|
+
id: string;
|
|
673
|
+
description: string;
|
|
674
|
+
modelAlias: string;
|
|
675
|
+
systemPrompt: string;
|
|
676
|
+
temperature: number;
|
|
677
|
+
maxTokens: number;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
type BuildStatus = 'planning' | 'implementing' | 'reviewing' | 'fixing' | 'completed' | 'failed' | 'paused';
|
|
681
|
+
type BuildPhase = 'debate' | 'plan_approved' | 'implementing' | 'review' | 'fix' | 'done';
|
|
682
|
+
type BuildEventType = 'debate_started' | 'debate_converged' | 'plan_approved' | 'impl_started' | 'impl_completed' | 'review_requested' | 'review_verdict' | 'bug_found' | 'fix_started' | 'fix_completed' | 'phase_transition' | 'error' | 'resumed' | 'scan_completed' | 'merge_completed' | 'adjudicated';
|
|
683
|
+
type BuildActor = 'claude' | 'codex' | 'system';
|
|
684
|
+
interface BuildRun {
|
|
685
|
+
id: number;
|
|
686
|
+
buildId: string;
|
|
687
|
+
task: string;
|
|
688
|
+
status: BuildStatus;
|
|
689
|
+
currentPhase: BuildPhase;
|
|
690
|
+
currentLoop: number;
|
|
691
|
+
lastEventSeq: number;
|
|
692
|
+
phaseCursor: PhaseCursor;
|
|
693
|
+
debateId: string | null;
|
|
694
|
+
baselineRef: string | null;
|
|
695
|
+
planCodexSession: string | null;
|
|
696
|
+
reviewCodexSession: string | null;
|
|
697
|
+
planVersion: number;
|
|
698
|
+
reviewCycles: number;
|
|
699
|
+
createdAt: number;
|
|
700
|
+
updatedAt: number;
|
|
701
|
+
completedAt: number | null;
|
|
702
|
+
metadata: Record<string, unknown> | null;
|
|
703
|
+
}
|
|
704
|
+
interface PhaseCursor {
|
|
705
|
+
phase: BuildPhase;
|
|
706
|
+
loop: number;
|
|
707
|
+
actor: BuildActor;
|
|
708
|
+
attempt: number;
|
|
709
|
+
lastEventId: number;
|
|
710
|
+
baselineRef?: string;
|
|
711
|
+
}
|
|
712
|
+
interface BuildEvent {
|
|
713
|
+
id: number;
|
|
714
|
+
buildId: string;
|
|
715
|
+
seq: number;
|
|
716
|
+
eventType: BuildEventType;
|
|
717
|
+
actor: BuildActor;
|
|
718
|
+
phase: BuildPhase;
|
|
719
|
+
loopIndex: number;
|
|
720
|
+
payload: Record<string, unknown> | null;
|
|
721
|
+
codexThreadId: string | null;
|
|
722
|
+
tokensUsed: number;
|
|
723
|
+
createdAt: number;
|
|
724
|
+
}
|
|
725
|
+
interface BuildSummary {
|
|
726
|
+
buildId: string;
|
|
727
|
+
task: string;
|
|
728
|
+
status: BuildStatus;
|
|
729
|
+
phase: BuildPhase;
|
|
730
|
+
loop: number;
|
|
731
|
+
reviewCycles: number;
|
|
732
|
+
planVersion: number;
|
|
733
|
+
debateId: string | null;
|
|
734
|
+
baselineRef: string | null;
|
|
735
|
+
createdAt: number;
|
|
736
|
+
updatedAt: number;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
type CleanupScope = 'deps' | 'unused-exports' | 'hardcoded' | 'duplicates' | 'deadcode' | 'security' | 'near-duplicates' | 'anti-patterns';
|
|
740
|
+
type CleanupConfidence = 'high' | 'medium' | 'low';
|
|
741
|
+
/** Which analysis sources identified this finding */
|
|
742
|
+
type CleanupSource = 'deterministic' | 'semantic' | 'host';
|
|
743
|
+
interface CleanupFinding {
|
|
744
|
+
/** Canonical key for merge matching: scope:normalizedPath:symbol */
|
|
745
|
+
key: string;
|
|
746
|
+
scope: CleanupScope;
|
|
747
|
+
confidence: CleanupConfidence;
|
|
748
|
+
file: string;
|
|
749
|
+
line?: number;
|
|
750
|
+
description: string;
|
|
751
|
+
recommendation: string;
|
|
752
|
+
/** Evidence from deterministic scanner */
|
|
753
|
+
deterministicEvidence: string[];
|
|
754
|
+
/** Evidence from semantic (codex) scanner */
|
|
755
|
+
semanticEvidence: string[];
|
|
756
|
+
/** Evidence from host AI (Claude) scanner */
|
|
757
|
+
hostEvidence: string[];
|
|
758
|
+
/** Which sources identified this finding */
|
|
759
|
+
sources: CleanupSource[];
|
|
760
|
+
/** Whether this finding was disputed between scanners */
|
|
761
|
+
disputed: boolean;
|
|
762
|
+
/** Group key for duplicate findings (sorted file:line pairs) */
|
|
763
|
+
groupKey?: string;
|
|
764
|
+
/** Package name for monorepo context */
|
|
765
|
+
packageName?: string;
|
|
766
|
+
}
|
|
767
|
+
interface CleanupReport {
|
|
768
|
+
scopes: CleanupScope[];
|
|
769
|
+
findings: CleanupFinding[];
|
|
770
|
+
stats: {
|
|
771
|
+
deterministic: number;
|
|
772
|
+
semantic: number;
|
|
773
|
+
host: number;
|
|
774
|
+
agreed: number;
|
|
775
|
+
disputed: number;
|
|
776
|
+
adjudicated: number;
|
|
777
|
+
highConfidence: number;
|
|
778
|
+
mediumConfidence: number;
|
|
779
|
+
lowConfidence: number;
|
|
780
|
+
};
|
|
781
|
+
durationMs: number;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
type DebateId = string;
|
|
785
|
+
type MessageId = string;
|
|
786
|
+
/** Stance a debater takes relative to the current proposal. */
|
|
787
|
+
type Stance = 'support' | 'oppose' | 'uncertain';
|
|
788
|
+
/** Message types in a debate thread. */
|
|
789
|
+
type DebateMessageKind = 'topic' | 'proposal' | 'critique' | 'rebuttal' | 'summary' | 'verdict';
|
|
790
|
+
/** A single message in the debate thread. */
|
|
791
|
+
interface DebateMessage {
|
|
792
|
+
id: MessageId;
|
|
793
|
+
turn: number;
|
|
794
|
+
round: number;
|
|
795
|
+
speakerId: string;
|
|
796
|
+
kind: DebateMessageKind;
|
|
797
|
+
text: string;
|
|
798
|
+
replyTo?: MessageId;
|
|
799
|
+
stance?: Stance;
|
|
800
|
+
confidence?: number;
|
|
801
|
+
tokens?: {
|
|
802
|
+
prompt: number;
|
|
803
|
+
completion: number;
|
|
804
|
+
};
|
|
805
|
+
createdAt: number;
|
|
806
|
+
}
|
|
807
|
+
/** Mutable state of an ongoing debate. */
|
|
808
|
+
interface DebateEngineState {
|
|
809
|
+
debateId: DebateId;
|
|
810
|
+
question: string;
|
|
811
|
+
models: string[];
|
|
812
|
+
round: number;
|
|
813
|
+
turn: number;
|
|
814
|
+
thread: DebateMessage[];
|
|
815
|
+
runningSummary: string;
|
|
816
|
+
stanceHistory: Array<{
|
|
817
|
+
round: number;
|
|
818
|
+
speakerId: string;
|
|
819
|
+
stance: Stance;
|
|
820
|
+
}>;
|
|
821
|
+
usage: {
|
|
822
|
+
totalPromptTokens: number;
|
|
823
|
+
totalCompletionTokens: number;
|
|
824
|
+
totalCalls: number;
|
|
825
|
+
startedAt: number;
|
|
826
|
+
};
|
|
827
|
+
status: 'running' | 'stopped';
|
|
828
|
+
/** Codex session IDs per speaker for resume. */
|
|
829
|
+
sessionIds: Record<string, string>;
|
|
830
|
+
/** Resume telemetry. */
|
|
831
|
+
resumeStats: {
|
|
832
|
+
attempted: number;
|
|
833
|
+
succeeded: number;
|
|
834
|
+
fallbacks: number;
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
/** Why the debate stopped. */
|
|
838
|
+
type StopReason = 'converged' | 'max_rounds' | 'time_budget' | 'error';
|
|
839
|
+
/** Final result of a debate. */
|
|
840
|
+
interface DebateEngineResult {
|
|
841
|
+
debateId: DebateId;
|
|
842
|
+
answer: string;
|
|
843
|
+
reason: StopReason;
|
|
844
|
+
rounds: number;
|
|
845
|
+
thread: DebateMessage[];
|
|
846
|
+
stanceHistory: DebateEngineState['stanceHistory'];
|
|
847
|
+
usage: DebateEngineState['usage'];
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
type JobType = 'review' | 'cleanup' | 'build-review' | 'composite' | 'watch-review';
|
|
851
|
+
type JobStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'canceled';
|
|
852
|
+
interface JobRecord {
|
|
853
|
+
id: string;
|
|
854
|
+
type: JobType;
|
|
855
|
+
status: JobStatus;
|
|
856
|
+
priority: number;
|
|
857
|
+
dedupeKey: string | null;
|
|
858
|
+
payloadJson: string;
|
|
859
|
+
resultJson: string | null;
|
|
860
|
+
errorText: string | null;
|
|
861
|
+
retryCount: number;
|
|
862
|
+
maxRetries: number;
|
|
863
|
+
sessionId: string | null;
|
|
864
|
+
workerId: string | null;
|
|
865
|
+
startedAt: number | null;
|
|
866
|
+
finishedAt: number | null;
|
|
867
|
+
createdAt: number;
|
|
868
|
+
updatedAt: number;
|
|
869
|
+
}
|
|
870
|
+
interface JobLogRecord {
|
|
871
|
+
id: number;
|
|
872
|
+
jobId: string;
|
|
873
|
+
seq: number;
|
|
874
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
875
|
+
eventType: string;
|
|
876
|
+
message: string | null;
|
|
877
|
+
payloadJson: string | null;
|
|
878
|
+
createdAt: number;
|
|
879
|
+
}
|
|
880
|
+
interface EnqueueOptions {
|
|
881
|
+
type: JobType;
|
|
882
|
+
payload: Record<string, unknown>;
|
|
883
|
+
priority?: number;
|
|
884
|
+
dedupeKey?: string;
|
|
885
|
+
sessionId?: string;
|
|
886
|
+
maxRetries?: number;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/** Generate a session ID with "ses_" prefix. */
|
|
890
|
+
declare function generateSessionId(): string;
|
|
891
|
+
/** Generate a generic unique ID. */
|
|
892
|
+
declare function generateId(prefix?: string): string;
|
|
893
|
+
|
|
894
|
+
declare class ConfigError extends Error {
|
|
895
|
+
readonly field?: string | undefined;
|
|
896
|
+
constructor(message: string, field?: string | undefined);
|
|
897
|
+
}
|
|
898
|
+
declare class ModelError extends Error {
|
|
899
|
+
readonly provider?: string | undefined;
|
|
900
|
+
readonly model?: string | undefined;
|
|
901
|
+
readonly statusCode?: number | undefined;
|
|
902
|
+
constructor(message: string, provider?: string | undefined, model?: string | undefined, statusCode?: number | undefined);
|
|
903
|
+
get isRateLimit(): boolean;
|
|
904
|
+
get isTimeout(): boolean;
|
|
905
|
+
get isServerError(): boolean;
|
|
906
|
+
}
|
|
907
|
+
declare class WorkflowError extends Error {
|
|
908
|
+
readonly stepId?: string | undefined;
|
|
909
|
+
constructor(message: string, stepId?: string | undefined);
|
|
910
|
+
}
|
|
911
|
+
declare class DatabaseError extends Error {
|
|
912
|
+
readonly operation?: string | undefined;
|
|
913
|
+
constructor(message: string, operation?: string | undefined);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
interface RetryOptions {
|
|
917
|
+
attempts: number;
|
|
918
|
+
backoff: number;
|
|
919
|
+
retryOn?: (error: unknown) => boolean;
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Retry an async function with exponential backoff.
|
|
923
|
+
* Returns the result on success, throws the last error after all attempts exhausted.
|
|
924
|
+
*/
|
|
925
|
+
declare function withRetry<T>(fn: () => Promise<T>, options?: Partial<RetryOptions>): Promise<T>;
|
|
926
|
+
|
|
927
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
928
|
+
interface Logger {
|
|
929
|
+
debug(message: string, ...args: unknown[]): void;
|
|
930
|
+
info(message: string, ...args: unknown[]): void;
|
|
931
|
+
warn(message: string, ...args: unknown[]): void;
|
|
932
|
+
error(message: string, ...args: unknown[]): void;
|
|
933
|
+
}
|
|
934
|
+
declare function createLogger(level?: LogLevel): Logger;
|
|
935
|
+
|
|
936
|
+
interface VerdictResult {
|
|
937
|
+
verdict: 'approved' | 'needs_revision';
|
|
938
|
+
feedback: string;
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Parse a reviewer response to extract the verdict.
|
|
942
|
+
*
|
|
943
|
+
* Looks for "VERDICT: APPROVED" or "VERDICT: NEEDS_REVISION" in the response.
|
|
944
|
+
* If APPROVED, feedback is empty.
|
|
945
|
+
* If NEEDS_REVISION, feedback is the text before the verdict line.
|
|
946
|
+
* If no match, conservatively returns needs_revision with the full response as feedback.
|
|
947
|
+
*/
|
|
948
|
+
declare function parseVerdict(response: string): VerdictResult;
|
|
949
|
+
|
|
950
|
+
/** Promise-based delay. */
|
|
951
|
+
declare function sleep(ms: number): Promise<void>;
|
|
952
|
+
|
|
953
|
+
/** Default timeout for model calls in seconds */
|
|
954
|
+
declare const DEFAULT_TIMEOUT_SEC = 600;
|
|
955
|
+
/** Default cleanup scan timeout in seconds */
|
|
956
|
+
declare const CLEANUP_TIMEOUT_SEC = 1200;
|
|
957
|
+
/** Default max tokens for model output */
|
|
958
|
+
declare const DEFAULT_MAX_TOKENS = 4096;
|
|
959
|
+
/** Implementer max tokens (larger for code generation) */
|
|
960
|
+
declare const IMPLEMENTER_MAX_TOKENS = 8192;
|
|
961
|
+
/** Max content length for MCP review input */
|
|
962
|
+
declare const MCP_CONTENT_MAX_LENGTH = 100000;
|
|
963
|
+
/** Max content length for MCP task/question input */
|
|
964
|
+
declare const MCP_TASK_MAX_LENGTH = 50000;
|
|
965
|
+
/** Max timeout for MCP tool calls in seconds */
|
|
966
|
+
declare const MCP_TIMEOUT_MAX = 900;
|
|
967
|
+
/** HTTP 429 Too Many Requests status code */
|
|
968
|
+
declare const HTTP_TOO_MANY_REQUESTS = 429;
|
|
969
|
+
/** Days in a year (for cost aggregation) */
|
|
970
|
+
declare const DAYS_PER_YEAR = 365;
|
|
971
|
+
/** Max diff size sent to reviewer */
|
|
972
|
+
declare const REVIEW_DIFF_MAX_CHARS = 50000;
|
|
973
|
+
/** Max review text stored in DB */
|
|
974
|
+
declare const REVIEW_TEXT_MAX_CHARS = 5000;
|
|
975
|
+
/** Binary detection buffer size */
|
|
976
|
+
declare const BINARY_SNIFF_BYTES = 512;
|
|
977
|
+
/** Context budget defaults */
|
|
978
|
+
declare const CONTEXT_ACTIVE = 8000;
|
|
979
|
+
declare const CONTEXT_RETRIEVED = 4000;
|
|
980
|
+
declare const CONTEXT_BUFFER = 2000;
|
|
981
|
+
/** DLP max content length */
|
|
982
|
+
declare const DLP_MAX_CONTENT = 2000;
|
|
983
|
+
/** DLP max processing time in milliseconds */
|
|
984
|
+
declare const DLP_MAX_PROCESSING_MS = 2000;
|
|
985
|
+
|
|
986
|
+
declare const DEFAULT_CONFIG: ProjectConfig;
|
|
987
|
+
|
|
988
|
+
declare const projectConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
989
|
+
configVersion: z.ZodOptional<z.ZodNumber>;
|
|
990
|
+
project: z.ZodDefault<z.ZodObject<{
|
|
991
|
+
name: z.ZodDefault<z.ZodString>;
|
|
992
|
+
description: z.ZodDefault<z.ZodString>;
|
|
993
|
+
}, "strip", z.ZodTypeAny, {
|
|
994
|
+
name: string;
|
|
995
|
+
description: string;
|
|
996
|
+
}, {
|
|
997
|
+
name?: string | undefined;
|
|
998
|
+
description?: string | undefined;
|
|
999
|
+
}>>;
|
|
1000
|
+
models: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1001
|
+
provider: z.ZodLiteral<"openai">;
|
|
1002
|
+
model: z.ZodString;
|
|
1003
|
+
maxTokens: z.ZodDefault<z.ZodNumber>;
|
|
1004
|
+
temperature: z.ZodDefault<z.ZodNumber>;
|
|
1005
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
1006
|
+
cliAdapter: z.ZodOptional<z.ZodObject<{
|
|
1007
|
+
command: z.ZodString;
|
|
1008
|
+
args: z.ZodArray<z.ZodString, "many">;
|
|
1009
|
+
timeout: z.ZodNumber;
|
|
1010
|
+
outputFile: z.ZodOptional<z.ZodString>;
|
|
1011
|
+
maxOutputBytes: z.ZodOptional<z.ZodNumber>;
|
|
1012
|
+
envAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1013
|
+
}, "strip", z.ZodTypeAny, {
|
|
1014
|
+
timeout: number;
|
|
1015
|
+
command: string;
|
|
1016
|
+
args: string[];
|
|
1017
|
+
outputFile?: string | undefined;
|
|
1018
|
+
maxOutputBytes?: number | undefined;
|
|
1019
|
+
envAllowlist?: string[] | undefined;
|
|
1020
|
+
}, {
|
|
1021
|
+
timeout: number;
|
|
1022
|
+
command: string;
|
|
1023
|
+
args: string[];
|
|
1024
|
+
outputFile?: string | undefined;
|
|
1025
|
+
maxOutputBytes?: number | undefined;
|
|
1026
|
+
envAllowlist?: string[] | undefined;
|
|
1027
|
+
}>>;
|
|
1028
|
+
}, "strip", z.ZodTypeAny, {
|
|
1029
|
+
model: string;
|
|
1030
|
+
timeout: number;
|
|
1031
|
+
provider: "openai";
|
|
1032
|
+
maxTokens: number;
|
|
1033
|
+
temperature: number;
|
|
1034
|
+
cliAdapter?: {
|
|
1035
|
+
timeout: number;
|
|
1036
|
+
command: string;
|
|
1037
|
+
args: string[];
|
|
1038
|
+
outputFile?: string | undefined;
|
|
1039
|
+
maxOutputBytes?: number | undefined;
|
|
1040
|
+
envAllowlist?: string[] | undefined;
|
|
1041
|
+
} | undefined;
|
|
1042
|
+
}, {
|
|
1043
|
+
model: string;
|
|
1044
|
+
provider: "openai";
|
|
1045
|
+
timeout?: number | undefined;
|
|
1046
|
+
maxTokens?: number | undefined;
|
|
1047
|
+
temperature?: number | undefined;
|
|
1048
|
+
cliAdapter?: {
|
|
1049
|
+
timeout: number;
|
|
1050
|
+
command: string;
|
|
1051
|
+
args: string[];
|
|
1052
|
+
outputFile?: string | undefined;
|
|
1053
|
+
maxOutputBytes?: number | undefined;
|
|
1054
|
+
envAllowlist?: string[] | undefined;
|
|
1055
|
+
} | undefined;
|
|
1056
|
+
}>>;
|
|
1057
|
+
roles: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1058
|
+
model: z.ZodString;
|
|
1059
|
+
temperature: z.ZodOptional<z.ZodNumber>;
|
|
1060
|
+
maxTokens: z.ZodOptional<z.ZodNumber>;
|
|
1061
|
+
systemPromptFile: z.ZodOptional<z.ZodString>;
|
|
1062
|
+
}, "strip", z.ZodTypeAny, {
|
|
1063
|
+
model: string;
|
|
1064
|
+
maxTokens?: number | undefined;
|
|
1065
|
+
temperature?: number | undefined;
|
|
1066
|
+
systemPromptFile?: string | undefined;
|
|
1067
|
+
}, {
|
|
1068
|
+
model: string;
|
|
1069
|
+
maxTokens?: number | undefined;
|
|
1070
|
+
temperature?: number | undefined;
|
|
1071
|
+
systemPromptFile?: string | undefined;
|
|
1072
|
+
}>>;
|
|
1073
|
+
workflow: z.ZodDefault<z.ZodString>;
|
|
1074
|
+
mode: z.ZodDefault<z.ZodEnum<["autonomous", "interactive", "dashboard"]>>;
|
|
1075
|
+
debate: z.ZodDefault<z.ZodObject<{
|
|
1076
|
+
defaultPattern: z.ZodDefault<z.ZodEnum<["structured-rounds", "proposal-critique", "free-flowing", "parallel-panel"]>>;
|
|
1077
|
+
maxRounds: z.ZodDefault<z.ZodNumber>;
|
|
1078
|
+
consensusThreshold: z.ZodDefault<z.ZodNumber>;
|
|
1079
|
+
}, "strip", z.ZodTypeAny, {
|
|
1080
|
+
maxRounds: number;
|
|
1081
|
+
defaultPattern: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel";
|
|
1082
|
+
consensusThreshold: number;
|
|
1083
|
+
}, {
|
|
1084
|
+
maxRounds?: number | undefined;
|
|
1085
|
+
defaultPattern?: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel" | undefined;
|
|
1086
|
+
consensusThreshold?: number | undefined;
|
|
1087
|
+
}>>;
|
|
1088
|
+
memory: z.ZodDefault<z.ZodObject<{
|
|
1089
|
+
embeddingModel: z.ZodOptional<z.ZodString>;
|
|
1090
|
+
autoExtractFacts: z.ZodDefault<z.ZodBoolean>;
|
|
1091
|
+
contextBudget: z.ZodDefault<z.ZodObject<{
|
|
1092
|
+
activeContext: z.ZodDefault<z.ZodNumber>;
|
|
1093
|
+
retrievedMemory: z.ZodDefault<z.ZodNumber>;
|
|
1094
|
+
messageBuffer: z.ZodDefault<z.ZodNumber>;
|
|
1095
|
+
}, "strip", z.ZodTypeAny, {
|
|
1096
|
+
activeContext: number;
|
|
1097
|
+
retrievedMemory: number;
|
|
1098
|
+
messageBuffer: number;
|
|
1099
|
+
}, {
|
|
1100
|
+
activeContext?: number | undefined;
|
|
1101
|
+
retrievedMemory?: number | undefined;
|
|
1102
|
+
messageBuffer?: number | undefined;
|
|
1103
|
+
}>>;
|
|
1104
|
+
}, "strip", z.ZodTypeAny, {
|
|
1105
|
+
autoExtractFacts: boolean;
|
|
1106
|
+
contextBudget: {
|
|
1107
|
+
activeContext: number;
|
|
1108
|
+
retrievedMemory: number;
|
|
1109
|
+
messageBuffer: number;
|
|
1110
|
+
};
|
|
1111
|
+
embeddingModel?: string | undefined;
|
|
1112
|
+
}, {
|
|
1113
|
+
embeddingModel?: string | undefined;
|
|
1114
|
+
autoExtractFacts?: boolean | undefined;
|
|
1115
|
+
contextBudget?: {
|
|
1116
|
+
activeContext?: number | undefined;
|
|
1117
|
+
retrievedMemory?: number | undefined;
|
|
1118
|
+
messageBuffer?: number | undefined;
|
|
1119
|
+
} | undefined;
|
|
1120
|
+
}>>;
|
|
1121
|
+
budget: z.ZodDefault<z.ZodObject<{
|
|
1122
|
+
perSession: z.ZodDefault<z.ZodNumber>;
|
|
1123
|
+
perDay: z.ZodDefault<z.ZodNumber>;
|
|
1124
|
+
perMonth: z.ZodDefault<z.ZodNumber>;
|
|
1125
|
+
warningAt: z.ZodDefault<z.ZodNumber>;
|
|
1126
|
+
action: z.ZodDefault<z.ZodEnum<["warn", "pause", "block"]>>;
|
|
1127
|
+
}, "strip", z.ZodTypeAny, {
|
|
1128
|
+
action: "warn" | "pause" | "block";
|
|
1129
|
+
perSession: number;
|
|
1130
|
+
perDay: number;
|
|
1131
|
+
perMonth: number;
|
|
1132
|
+
warningAt: number;
|
|
1133
|
+
}, {
|
|
1134
|
+
action?: "warn" | "pause" | "block" | undefined;
|
|
1135
|
+
perSession?: number | undefined;
|
|
1136
|
+
perDay?: number | undefined;
|
|
1137
|
+
perMonth?: number | undefined;
|
|
1138
|
+
warningAt?: number | undefined;
|
|
1139
|
+
}>>;
|
|
1140
|
+
output: z.ZodDefault<z.ZodObject<{
|
|
1141
|
+
saveTranscripts: z.ZodDefault<z.ZodBoolean>;
|
|
1142
|
+
transcriptFormat: z.ZodDefault<z.ZodEnum<["markdown", "json"]>>;
|
|
1143
|
+
transcriptDir: z.ZodDefault<z.ZodString>;
|
|
1144
|
+
}, "strip", z.ZodTypeAny, {
|
|
1145
|
+
saveTranscripts: boolean;
|
|
1146
|
+
transcriptFormat: "markdown" | "json";
|
|
1147
|
+
transcriptDir: string;
|
|
1148
|
+
}, {
|
|
1149
|
+
saveTranscripts?: boolean | undefined;
|
|
1150
|
+
transcriptFormat?: "markdown" | "json" | undefined;
|
|
1151
|
+
transcriptDir?: string | undefined;
|
|
1152
|
+
}>>;
|
|
1153
|
+
advanced: z.ZodDefault<z.ZodObject<{
|
|
1154
|
+
retryAttempts: z.ZodDefault<z.ZodNumber>;
|
|
1155
|
+
stream: z.ZodDefault<z.ZodBoolean>;
|
|
1156
|
+
logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
|
|
1157
|
+
}, "strip", z.ZodTypeAny, {
|
|
1158
|
+
stream: boolean;
|
|
1159
|
+
retryAttempts: number;
|
|
1160
|
+
logLevel: "warn" | "debug" | "info" | "error";
|
|
1161
|
+
}, {
|
|
1162
|
+
stream?: boolean | undefined;
|
|
1163
|
+
retryAttempts?: number | undefined;
|
|
1164
|
+
logLevel?: "warn" | "debug" | "info" | "error" | undefined;
|
|
1165
|
+
}>>;
|
|
1166
|
+
}, "strip", z.ZodTypeAny, {
|
|
1167
|
+
models: Record<string, {
|
|
1168
|
+
model: string;
|
|
1169
|
+
timeout: number;
|
|
1170
|
+
provider: "openai";
|
|
1171
|
+
maxTokens: number;
|
|
1172
|
+
temperature: number;
|
|
1173
|
+
cliAdapter?: {
|
|
1174
|
+
timeout: number;
|
|
1175
|
+
command: string;
|
|
1176
|
+
args: string[];
|
|
1177
|
+
outputFile?: string | undefined;
|
|
1178
|
+
maxOutputBytes?: number | undefined;
|
|
1179
|
+
envAllowlist?: string[] | undefined;
|
|
1180
|
+
} | undefined;
|
|
1181
|
+
}>;
|
|
1182
|
+
debate: {
|
|
1183
|
+
maxRounds: number;
|
|
1184
|
+
defaultPattern: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel";
|
|
1185
|
+
consensusThreshold: number;
|
|
1186
|
+
};
|
|
1187
|
+
project: {
|
|
1188
|
+
name: string;
|
|
1189
|
+
description: string;
|
|
1190
|
+
};
|
|
1191
|
+
roles: Record<string, {
|
|
1192
|
+
model: string;
|
|
1193
|
+
maxTokens?: number | undefined;
|
|
1194
|
+
temperature?: number | undefined;
|
|
1195
|
+
systemPromptFile?: string | undefined;
|
|
1196
|
+
}>;
|
|
1197
|
+
workflow: string;
|
|
1198
|
+
mode: "autonomous" | "interactive" | "dashboard";
|
|
1199
|
+
memory: {
|
|
1200
|
+
autoExtractFacts: boolean;
|
|
1201
|
+
contextBudget: {
|
|
1202
|
+
activeContext: number;
|
|
1203
|
+
retrievedMemory: number;
|
|
1204
|
+
messageBuffer: number;
|
|
1205
|
+
};
|
|
1206
|
+
embeddingModel?: string | undefined;
|
|
1207
|
+
};
|
|
1208
|
+
budget: {
|
|
1209
|
+
action: "warn" | "pause" | "block";
|
|
1210
|
+
perSession: number;
|
|
1211
|
+
perDay: number;
|
|
1212
|
+
perMonth: number;
|
|
1213
|
+
warningAt: number;
|
|
1214
|
+
};
|
|
1215
|
+
output: {
|
|
1216
|
+
saveTranscripts: boolean;
|
|
1217
|
+
transcriptFormat: "markdown" | "json";
|
|
1218
|
+
transcriptDir: string;
|
|
1219
|
+
};
|
|
1220
|
+
advanced: {
|
|
1221
|
+
stream: boolean;
|
|
1222
|
+
retryAttempts: number;
|
|
1223
|
+
logLevel: "warn" | "debug" | "info" | "error";
|
|
1224
|
+
};
|
|
1225
|
+
configVersion?: number | undefined;
|
|
1226
|
+
}, {
|
|
1227
|
+
models: Record<string, {
|
|
1228
|
+
model: string;
|
|
1229
|
+
provider: "openai";
|
|
1230
|
+
timeout?: number | undefined;
|
|
1231
|
+
maxTokens?: number | undefined;
|
|
1232
|
+
temperature?: number | undefined;
|
|
1233
|
+
cliAdapter?: {
|
|
1234
|
+
timeout: number;
|
|
1235
|
+
command: string;
|
|
1236
|
+
args: string[];
|
|
1237
|
+
outputFile?: string | undefined;
|
|
1238
|
+
maxOutputBytes?: number | undefined;
|
|
1239
|
+
envAllowlist?: string[] | undefined;
|
|
1240
|
+
} | undefined;
|
|
1241
|
+
}>;
|
|
1242
|
+
roles: Record<string, {
|
|
1243
|
+
model: string;
|
|
1244
|
+
maxTokens?: number | undefined;
|
|
1245
|
+
temperature?: number | undefined;
|
|
1246
|
+
systemPromptFile?: string | undefined;
|
|
1247
|
+
}>;
|
|
1248
|
+
debate?: {
|
|
1249
|
+
maxRounds?: number | undefined;
|
|
1250
|
+
defaultPattern?: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel" | undefined;
|
|
1251
|
+
consensusThreshold?: number | undefined;
|
|
1252
|
+
} | undefined;
|
|
1253
|
+
configVersion?: number | undefined;
|
|
1254
|
+
project?: {
|
|
1255
|
+
name?: string | undefined;
|
|
1256
|
+
description?: string | undefined;
|
|
1257
|
+
} | undefined;
|
|
1258
|
+
workflow?: string | undefined;
|
|
1259
|
+
mode?: "autonomous" | "interactive" | "dashboard" | undefined;
|
|
1260
|
+
memory?: {
|
|
1261
|
+
embeddingModel?: string | undefined;
|
|
1262
|
+
autoExtractFacts?: boolean | undefined;
|
|
1263
|
+
contextBudget?: {
|
|
1264
|
+
activeContext?: number | undefined;
|
|
1265
|
+
retrievedMemory?: number | undefined;
|
|
1266
|
+
messageBuffer?: number | undefined;
|
|
1267
|
+
} | undefined;
|
|
1268
|
+
} | undefined;
|
|
1269
|
+
budget?: {
|
|
1270
|
+
action?: "warn" | "pause" | "block" | undefined;
|
|
1271
|
+
perSession?: number | undefined;
|
|
1272
|
+
perDay?: number | undefined;
|
|
1273
|
+
perMonth?: number | undefined;
|
|
1274
|
+
warningAt?: number | undefined;
|
|
1275
|
+
} | undefined;
|
|
1276
|
+
output?: {
|
|
1277
|
+
saveTranscripts?: boolean | undefined;
|
|
1278
|
+
transcriptFormat?: "markdown" | "json" | undefined;
|
|
1279
|
+
transcriptDir?: string | undefined;
|
|
1280
|
+
} | undefined;
|
|
1281
|
+
advanced?: {
|
|
1282
|
+
stream?: boolean | undefined;
|
|
1283
|
+
retryAttempts?: number | undefined;
|
|
1284
|
+
logLevel?: "warn" | "debug" | "info" | "error" | undefined;
|
|
1285
|
+
} | undefined;
|
|
1286
|
+
}>, {
|
|
1287
|
+
models: Record<string, {
|
|
1288
|
+
model: string;
|
|
1289
|
+
timeout: number;
|
|
1290
|
+
provider: "openai";
|
|
1291
|
+
maxTokens: number;
|
|
1292
|
+
temperature: number;
|
|
1293
|
+
cliAdapter?: {
|
|
1294
|
+
timeout: number;
|
|
1295
|
+
command: string;
|
|
1296
|
+
args: string[];
|
|
1297
|
+
outputFile?: string | undefined;
|
|
1298
|
+
maxOutputBytes?: number | undefined;
|
|
1299
|
+
envAllowlist?: string[] | undefined;
|
|
1300
|
+
} | undefined;
|
|
1301
|
+
}>;
|
|
1302
|
+
debate: {
|
|
1303
|
+
maxRounds: number;
|
|
1304
|
+
defaultPattern: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel";
|
|
1305
|
+
consensusThreshold: number;
|
|
1306
|
+
};
|
|
1307
|
+
project: {
|
|
1308
|
+
name: string;
|
|
1309
|
+
description: string;
|
|
1310
|
+
};
|
|
1311
|
+
roles: Record<string, {
|
|
1312
|
+
model: string;
|
|
1313
|
+
maxTokens?: number | undefined;
|
|
1314
|
+
temperature?: number | undefined;
|
|
1315
|
+
systemPromptFile?: string | undefined;
|
|
1316
|
+
}>;
|
|
1317
|
+
workflow: string;
|
|
1318
|
+
mode: "autonomous" | "interactive" | "dashboard";
|
|
1319
|
+
memory: {
|
|
1320
|
+
autoExtractFacts: boolean;
|
|
1321
|
+
contextBudget: {
|
|
1322
|
+
activeContext: number;
|
|
1323
|
+
retrievedMemory: number;
|
|
1324
|
+
messageBuffer: number;
|
|
1325
|
+
};
|
|
1326
|
+
embeddingModel?: string | undefined;
|
|
1327
|
+
};
|
|
1328
|
+
budget: {
|
|
1329
|
+
action: "warn" | "pause" | "block";
|
|
1330
|
+
perSession: number;
|
|
1331
|
+
perDay: number;
|
|
1332
|
+
perMonth: number;
|
|
1333
|
+
warningAt: number;
|
|
1334
|
+
};
|
|
1335
|
+
output: {
|
|
1336
|
+
saveTranscripts: boolean;
|
|
1337
|
+
transcriptFormat: "markdown" | "json";
|
|
1338
|
+
transcriptDir: string;
|
|
1339
|
+
};
|
|
1340
|
+
advanced: {
|
|
1341
|
+
stream: boolean;
|
|
1342
|
+
retryAttempts: number;
|
|
1343
|
+
logLevel: "warn" | "debug" | "info" | "error";
|
|
1344
|
+
};
|
|
1345
|
+
configVersion?: number | undefined;
|
|
1346
|
+
}, {
|
|
1347
|
+
models: Record<string, {
|
|
1348
|
+
model: string;
|
|
1349
|
+
provider: "openai";
|
|
1350
|
+
timeout?: number | undefined;
|
|
1351
|
+
maxTokens?: number | undefined;
|
|
1352
|
+
temperature?: number | undefined;
|
|
1353
|
+
cliAdapter?: {
|
|
1354
|
+
timeout: number;
|
|
1355
|
+
command: string;
|
|
1356
|
+
args: string[];
|
|
1357
|
+
outputFile?: string | undefined;
|
|
1358
|
+
maxOutputBytes?: number | undefined;
|
|
1359
|
+
envAllowlist?: string[] | undefined;
|
|
1360
|
+
} | undefined;
|
|
1361
|
+
}>;
|
|
1362
|
+
roles: Record<string, {
|
|
1363
|
+
model: string;
|
|
1364
|
+
maxTokens?: number | undefined;
|
|
1365
|
+
temperature?: number | undefined;
|
|
1366
|
+
systemPromptFile?: string | undefined;
|
|
1367
|
+
}>;
|
|
1368
|
+
debate?: {
|
|
1369
|
+
maxRounds?: number | undefined;
|
|
1370
|
+
defaultPattern?: "structured-rounds" | "proposal-critique" | "free-flowing" | "parallel-panel" | undefined;
|
|
1371
|
+
consensusThreshold?: number | undefined;
|
|
1372
|
+
} | undefined;
|
|
1373
|
+
configVersion?: number | undefined;
|
|
1374
|
+
project?: {
|
|
1375
|
+
name?: string | undefined;
|
|
1376
|
+
description?: string | undefined;
|
|
1377
|
+
} | undefined;
|
|
1378
|
+
workflow?: string | undefined;
|
|
1379
|
+
mode?: "autonomous" | "interactive" | "dashboard" | undefined;
|
|
1380
|
+
memory?: {
|
|
1381
|
+
embeddingModel?: string | undefined;
|
|
1382
|
+
autoExtractFacts?: boolean | undefined;
|
|
1383
|
+
contextBudget?: {
|
|
1384
|
+
activeContext?: number | undefined;
|
|
1385
|
+
retrievedMemory?: number | undefined;
|
|
1386
|
+
messageBuffer?: number | undefined;
|
|
1387
|
+
} | undefined;
|
|
1388
|
+
} | undefined;
|
|
1389
|
+
budget?: {
|
|
1390
|
+
action?: "warn" | "pause" | "block" | undefined;
|
|
1391
|
+
perSession?: number | undefined;
|
|
1392
|
+
perDay?: number | undefined;
|
|
1393
|
+
perMonth?: number | undefined;
|
|
1394
|
+
warningAt?: number | undefined;
|
|
1395
|
+
} | undefined;
|
|
1396
|
+
output?: {
|
|
1397
|
+
saveTranscripts?: boolean | undefined;
|
|
1398
|
+
transcriptFormat?: "markdown" | "json" | undefined;
|
|
1399
|
+
transcriptDir?: string | undefined;
|
|
1400
|
+
} | undefined;
|
|
1401
|
+
advanced?: {
|
|
1402
|
+
stream?: boolean | undefined;
|
|
1403
|
+
retryAttempts?: number | undefined;
|
|
1404
|
+
logLevel?: "warn" | "debug" | "info" | "error" | undefined;
|
|
1405
|
+
} | undefined;
|
|
1406
|
+
}>;
|
|
1407
|
+
type ProjectConfigInput = z.input<typeof projectConfigSchema>;
|
|
1408
|
+
/**
|
|
1409
|
+
* Validate and parse a config object. Throws ConfigError on invalid input.
|
|
1410
|
+
*/
|
|
1411
|
+
declare function validateConfig(config: unknown): z.output<typeof projectConfigSchema>;
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Load a built-in preset by name. Returns a partial config to be merged with defaults.
|
|
1415
|
+
*/
|
|
1416
|
+
declare function loadPreset(name: PresetName): Record<string, unknown>;
|
|
1417
|
+
/** List available preset names. */
|
|
1418
|
+
declare function listPresets(): PresetName[];
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* Load config with precedence: overrides > .mulep.yml > preset > defaults.
|
|
1422
|
+
*
|
|
1423
|
+
* 1. Start with hardcoded defaults
|
|
1424
|
+
* 2. If a preset name is found (in file or overrides), merge preset on top
|
|
1425
|
+
* 3. Merge .mulep.yml from projectDir on top
|
|
1426
|
+
* 4. Merge programmatic overrides on top
|
|
1427
|
+
* 5. Validate the final result
|
|
1428
|
+
*/
|
|
1429
|
+
declare function loadConfig(options?: {
|
|
1430
|
+
projectDir?: string;
|
|
1431
|
+
preset?: PresetName;
|
|
1432
|
+
overrides?: Partial<ProjectConfig>;
|
|
1433
|
+
skipFile?: boolean;
|
|
1434
|
+
}): ProjectConfig;
|
|
1435
|
+
/**
|
|
1436
|
+
* Write a ProjectConfig to .mulep.yml in the given directory.
|
|
1437
|
+
* Also creates .mulep/db/ and .mulep/transcripts/ directories.
|
|
1438
|
+
*/
|
|
1439
|
+
declare function writeConfig(config: ProjectConfig, dir: string): void;
|
|
1440
|
+
|
|
1441
|
+
declare const CURRENT_VERSION = 2;
|
|
1442
|
+
/**
|
|
1443
|
+
* Migrate a ProjectConfig from an older schema version to the current version.
|
|
1444
|
+
* Creates a .bak backup before writing changes if configPath is provided.
|
|
1445
|
+
* Returns the migrated config (always in-memory; optionally persisted to disk).
|
|
1446
|
+
*/
|
|
1447
|
+
declare function migrateConfig(config: ProjectConfig, configPath?: string): ProjectConfig;
|
|
1448
|
+
|
|
1449
|
+
interface ReviewPreset {
|
|
1450
|
+
name: string;
|
|
1451
|
+
focus: string;
|
|
1452
|
+
constraints: string[];
|
|
1453
|
+
timeoutSec: number;
|
|
1454
|
+
severityFloor: 'info' | 'warning' | 'critical';
|
|
1455
|
+
strictOutput: boolean;
|
|
1456
|
+
}
|
|
1457
|
+
declare const REVIEW_PRESETS: Record<string, ReviewPreset>;
|
|
1458
|
+
declare function getReviewPreset(name: string): ReviewPreset | undefined;
|
|
1459
|
+
declare function listPresetNames(): string[];
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Load and compile all ignore patterns into a single matcher.
|
|
1463
|
+
* Precedence: builtins -> .gitignore -> .mulepignore
|
|
1464
|
+
*/
|
|
1465
|
+
declare function createIgnoreFilter(projectDir: string, options?: {
|
|
1466
|
+
skipGitignore?: boolean;
|
|
1467
|
+
}): Ignore;
|
|
1468
|
+
declare function loadIgnorePatterns(projectDir: string): string[];
|
|
1469
|
+
declare function shouldIgnore(filePath: string, patterns: string[]): boolean;
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* Open a SQLite database and run migrations.
|
|
1473
|
+
* Pass ':memory:' for in-memory databases (testing).
|
|
1474
|
+
*/
|
|
1475
|
+
declare function openDatabase(dbPath: string): Database.Database;
|
|
1476
|
+
/**
|
|
1477
|
+
* Run all schema migrations. Idempotent (uses IF NOT EXISTS).
|
|
1478
|
+
*/
|
|
1479
|
+
declare function runMigrations(db: Database.Database): void;
|
|
1480
|
+
/** Get the current schema version. */
|
|
1481
|
+
declare function getSchemaVersion(db: Database.Database): string | null;
|
|
1482
|
+
|
|
1483
|
+
declare class SessionStore {
|
|
1484
|
+
private db;
|
|
1485
|
+
constructor(db: Database.Database);
|
|
1486
|
+
create(params: {
|
|
1487
|
+
projectId: string;
|
|
1488
|
+
workflowId: string;
|
|
1489
|
+
task: string;
|
|
1490
|
+
mode: ExecutionMode;
|
|
1491
|
+
config: ProjectConfig;
|
|
1492
|
+
}): Session;
|
|
1493
|
+
get(sessionId: string): Session | null;
|
|
1494
|
+
list(filter?: {
|
|
1495
|
+
status?: SessionStatus;
|
|
1496
|
+
projectId?: string;
|
|
1497
|
+
limit?: number;
|
|
1498
|
+
}): Session[];
|
|
1499
|
+
updateStatus(sessionId: string, status: SessionStatus): void;
|
|
1500
|
+
updateCurrentStep(sessionId: string, stepId: string): void;
|
|
1501
|
+
complete(sessionId: string, summary?: string): void;
|
|
1502
|
+
addUsage(sessionId: string, cost: number, tokens: number): void;
|
|
1503
|
+
saveTranscriptEntry(entry: TranscriptEntry): void;
|
|
1504
|
+
getTranscript(sessionId: string): TranscriptEntry[];
|
|
1505
|
+
private rowToSession;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
declare class MemoryStore {
|
|
1509
|
+
private db;
|
|
1510
|
+
constructor(db: Database.Database);
|
|
1511
|
+
save(memory: Omit<MemoryRecord, 'id' | 'createdAt' | 'accessedAt' | 'accessCount'>): number;
|
|
1512
|
+
search(query: string, projectId: string, limit?: number): MemoryRecord[];
|
|
1513
|
+
getByCategory(projectId: string, category: MemoryCategory): MemoryRecord[];
|
|
1514
|
+
getById(memoryId: number): MemoryRecord | null;
|
|
1515
|
+
recordAccess(memoryId: number): void;
|
|
1516
|
+
/** Check if a memory with matching category and content prefix already exists. */
|
|
1517
|
+
findByPrefix(projectId: string, category: string, contentPrefix: string): MemoryRecord | null;
|
|
1518
|
+
delete(memoryId: number): void;
|
|
1519
|
+
private rowToMemory;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
declare class ArtifactStore {
|
|
1523
|
+
private db;
|
|
1524
|
+
constructor(db: Database.Database);
|
|
1525
|
+
save(artifact: Omit<ArtifactRecord, 'id' | 'createdAt'>): number;
|
|
1526
|
+
getBySession(sessionId: string): ArtifactRecord[];
|
|
1527
|
+
getByStep(sessionId: string, stepId: string): ArtifactRecord[];
|
|
1528
|
+
getLatestByStep(sessionId: string, stepId: string): ArtifactRecord | null;
|
|
1529
|
+
getByType(sessionId: string, type: ArtifactType): ArtifactRecord[];
|
|
1530
|
+
private rowToArtifact;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
interface CostSummary {
|
|
1534
|
+
modelId: string;
|
|
1535
|
+
callCount: number;
|
|
1536
|
+
totalInputTokens: number;
|
|
1537
|
+
totalOutputTokens: number;
|
|
1538
|
+
totalCost: number;
|
|
1539
|
+
avgLatencyMs: number;
|
|
1540
|
+
}
|
|
1541
|
+
declare class CostStore {
|
|
1542
|
+
private db;
|
|
1543
|
+
constructor(db: Database.Database);
|
|
1544
|
+
log(entry: Omit<CostLogEntry, 'id' | 'createdAt'>): number;
|
|
1545
|
+
getBySession(sessionId: string): CostLogEntry[];
|
|
1546
|
+
getSessionSummary(sessionId: string): CostSummary[];
|
|
1547
|
+
getDailySummary(days?: number): Record<string, unknown>[];
|
|
1548
|
+
private rowToEntry;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
type DebateTurnStatus = 'active' | 'completed' | 'interrupted' | 'stale' | 'expired';
|
|
1552
|
+
interface DebateTurnRow {
|
|
1553
|
+
id: number;
|
|
1554
|
+
debateId: string;
|
|
1555
|
+
role: string;
|
|
1556
|
+
codexSessionId: string | null;
|
|
1557
|
+
round: number;
|
|
1558
|
+
status: DebateTurnStatus;
|
|
1559
|
+
resumeFailCount: number;
|
|
1560
|
+
lastActivityAt: number;
|
|
1561
|
+
createdAt: number;
|
|
1562
|
+
stateJson: string | null;
|
|
1563
|
+
}
|
|
1564
|
+
declare class DebateStore {
|
|
1565
|
+
private db;
|
|
1566
|
+
constructor(db: Database.Database);
|
|
1567
|
+
/** Create or update a debate turn (upsert on debate_id + role). */
|
|
1568
|
+
upsert(params: {
|
|
1569
|
+
debateId: string;
|
|
1570
|
+
role: string;
|
|
1571
|
+
codexSessionId?: string;
|
|
1572
|
+
round?: number;
|
|
1573
|
+
status?: DebateTurnStatus;
|
|
1574
|
+
stateJson?: string;
|
|
1575
|
+
}): void;
|
|
1576
|
+
/** Get a debate turn by debate_id and role. */
|
|
1577
|
+
get(debateId: string, role: string): DebateTurnRow | null;
|
|
1578
|
+
/** Get all turns for a debate. */
|
|
1579
|
+
getByDebateId(debateId: string): DebateTurnRow[];
|
|
1580
|
+
/** List debates, optionally filtered by status. */
|
|
1581
|
+
list(filter?: {
|
|
1582
|
+
status?: DebateTurnStatus;
|
|
1583
|
+
limit?: number;
|
|
1584
|
+
}): DebateTurnRow[];
|
|
1585
|
+
/** Update session ID after a successful codex call. */
|
|
1586
|
+
updateSessionId(debateId: string, role: string, codexSessionId: string): void;
|
|
1587
|
+
/** Update status (e.g., active → completed). */
|
|
1588
|
+
updateStatus(debateId: string, role: string, status: DebateTurnStatus): void;
|
|
1589
|
+
/** Increment resume failure count. */
|
|
1590
|
+
incrementResumeFailCount(debateId: string, role: string): void;
|
|
1591
|
+
/** Persist full debate state as JSON for crash recovery. */
|
|
1592
|
+
saveState(debateId: string, role: string, state: DebateEngineState): void;
|
|
1593
|
+
/** Load saved debate state from JSON. */
|
|
1594
|
+
loadState(debateId: string, role: string): DebateEngineState | null;
|
|
1595
|
+
/** Mark stale debates (active but inactive for > threshold). */
|
|
1596
|
+
markStale(thresholdMs: number): number;
|
|
1597
|
+
/** Mark expired debates (stale and older than threshold). */
|
|
1598
|
+
markExpired(thresholdMs: number): number;
|
|
1599
|
+
private toRow;
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
declare class BuildStore {
|
|
1603
|
+
private db;
|
|
1604
|
+
constructor(db: Database.Database);
|
|
1605
|
+
/** Create a new build run. */
|
|
1606
|
+
create(params: {
|
|
1607
|
+
buildId: string;
|
|
1608
|
+
task: string;
|
|
1609
|
+
debateId?: string;
|
|
1610
|
+
baselineRef?: string;
|
|
1611
|
+
}): void;
|
|
1612
|
+
/** Get a build run by build_id. */
|
|
1613
|
+
get(buildId: string): BuildRun | null;
|
|
1614
|
+
/** List builds, optionally filtered by status. */
|
|
1615
|
+
list(filter?: {
|
|
1616
|
+
status?: BuildStatus;
|
|
1617
|
+
limit?: number;
|
|
1618
|
+
}): BuildSummary[];
|
|
1619
|
+
/** Update build run fields atomically with event append. */
|
|
1620
|
+
updateWithEvent(buildId: string, updates: Partial<{
|
|
1621
|
+
status: BuildStatus;
|
|
1622
|
+
currentPhase: BuildPhase;
|
|
1623
|
+
currentLoop: number;
|
|
1624
|
+
debateId: string;
|
|
1625
|
+
baselineRef: string;
|
|
1626
|
+
planCodexSession: string;
|
|
1627
|
+
reviewCodexSession: string;
|
|
1628
|
+
planVersion: number;
|
|
1629
|
+
reviewCycles: number;
|
|
1630
|
+
completedAt: number;
|
|
1631
|
+
metadata: Record<string, unknown>;
|
|
1632
|
+
}>, event: {
|
|
1633
|
+
eventType: BuildEventType;
|
|
1634
|
+
actor: BuildActor;
|
|
1635
|
+
phase: BuildPhase;
|
|
1636
|
+
loopIndex?: number;
|
|
1637
|
+
payload?: Record<string, unknown>;
|
|
1638
|
+
codexThreadId?: string;
|
|
1639
|
+
tokensUsed?: number;
|
|
1640
|
+
}): void;
|
|
1641
|
+
/** Get events for a build, ordered by seq. */
|
|
1642
|
+
getEvents(buildId: string, afterSeq?: number): BuildEvent[];
|
|
1643
|
+
/** Count events by type for a build. */
|
|
1644
|
+
countEventsByType(buildId: string, eventType: BuildEventType): number;
|
|
1645
|
+
private toRun;
|
|
1646
|
+
private toEvent;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
type MessageStatus = 'queued' | 'running' | 'completed' | 'failed';
|
|
1650
|
+
interface DebateMessageRow {
|
|
1651
|
+
id: number;
|
|
1652
|
+
debateId: string;
|
|
1653
|
+
round: number;
|
|
1654
|
+
role: string;
|
|
1655
|
+
bridge: string;
|
|
1656
|
+
model: string;
|
|
1657
|
+
promptText: string;
|
|
1658
|
+
responseText: string | null;
|
|
1659
|
+
stance: string | null;
|
|
1660
|
+
confidence: number | null;
|
|
1661
|
+
verdictRaw: string | null;
|
|
1662
|
+
usageJson: string | null;
|
|
1663
|
+
durationMs: number | null;
|
|
1664
|
+
sessionId: string | null;
|
|
1665
|
+
status: MessageStatus;
|
|
1666
|
+
error: string | null;
|
|
1667
|
+
createdAt: number;
|
|
1668
|
+
updatedAt: number;
|
|
1669
|
+
completedAt: number | null;
|
|
1670
|
+
}
|
|
1671
|
+
interface ParsedVerdict {
|
|
1672
|
+
stance: string | null;
|
|
1673
|
+
confidence: number | null;
|
|
1674
|
+
raw: string | null;
|
|
1675
|
+
}
|
|
1676
|
+
/** Parse structured verdict from model response. */
|
|
1677
|
+
declare function parseDebateVerdict(text: string): ParsedVerdict;
|
|
1678
|
+
declare class MessageStore {
|
|
1679
|
+
private db;
|
|
1680
|
+
constructor(db: Database.Database);
|
|
1681
|
+
/** Insert a new message in queued state. Returns the row ID. */
|
|
1682
|
+
insertQueued(params: {
|
|
1683
|
+
debateId: string;
|
|
1684
|
+
round: number;
|
|
1685
|
+
role: string;
|
|
1686
|
+
bridge: string;
|
|
1687
|
+
model: string;
|
|
1688
|
+
promptText: string;
|
|
1689
|
+
}): number;
|
|
1690
|
+
/** Update prompt text on a queued or failed row (for retries with different prompts). */
|
|
1691
|
+
updatePrompt(id: number, promptText: string): boolean;
|
|
1692
|
+
/** Transition to running. Only from queued or failed. Returns true if transition succeeded. */
|
|
1693
|
+
markRunning(id: number): boolean;
|
|
1694
|
+
/** Transition to completed with response data. Only from running. */
|
|
1695
|
+
markCompleted(id: number, params: {
|
|
1696
|
+
responseText: string;
|
|
1697
|
+
verdict: ParsedVerdict;
|
|
1698
|
+
usageJson: string;
|
|
1699
|
+
durationMs: number;
|
|
1700
|
+
sessionId: string | null;
|
|
1701
|
+
}): boolean;
|
|
1702
|
+
/** Transition to failed with error. Only from running. */
|
|
1703
|
+
markFailed(id: number, error: string): boolean;
|
|
1704
|
+
/** Get a message by debate_id, round, and role (for idempotency checks). */
|
|
1705
|
+
getByRound(debateId: string, round: number, role: string): DebateMessageRow | null;
|
|
1706
|
+
/** Get full message history for a debate, ordered by round. */
|
|
1707
|
+
getHistory(debateId: string): DebateMessageRow[];
|
|
1708
|
+
/** Recover stale running rows older than threshold. Returns count recovered. */
|
|
1709
|
+
recoverStale(thresholdMs: number): number;
|
|
1710
|
+
/** Recover stale running rows for a specific debate only. */
|
|
1711
|
+
recoverStaleForDebate(debateId: string, thresholdMs: number): number;
|
|
1712
|
+
private toRow;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* Build a reconstruction preamble from stored debate messages.
|
|
1717
|
+
* Used when session resume fails and we need to give GPT context of previous rounds.
|
|
1718
|
+
*
|
|
1719
|
+
* Strategy:
|
|
1720
|
+
* - If history fits within tokenBudget: include all rounds verbatim
|
|
1721
|
+
* - If over budget: summarize oldest rounds, keep newest verbatim
|
|
1722
|
+
*
|
|
1723
|
+
* @param history - Previous completed messages from MessageStore.getHistory()
|
|
1724
|
+
* @param currentPrompt - The new prompt for this round
|
|
1725
|
+
* @param maxChars - Approximate character budget (rough proxy for tokens; ~4 chars/token)
|
|
1726
|
+
* @returns The reconstructed prompt with history preamble
|
|
1727
|
+
*/
|
|
1728
|
+
declare function buildReconstructionPrompt(history: DebateMessageRow[], currentPrompt: string, maxChars?: number): string;
|
|
1729
|
+
|
|
1730
|
+
interface TokenBudgetStatus {
|
|
1731
|
+
/** Total tokens used across all rounds. */
|
|
1732
|
+
totalTokensUsed: number;
|
|
1733
|
+
/** Maximum context tokens for the model. */
|
|
1734
|
+
maxContextTokens: number;
|
|
1735
|
+
/** Usage as a fraction (0-1). */
|
|
1736
|
+
utilizationRatio: number;
|
|
1737
|
+
/** Whether auto-summarization is recommended (>= 70%). */
|
|
1738
|
+
shouldSummarize: boolean;
|
|
1739
|
+
/** Whether the debate should be completed (>= 90%). */
|
|
1740
|
+
shouldStop: boolean;
|
|
1741
|
+
/** Estimated tokens remaining. */
|
|
1742
|
+
tokensRemaining: number;
|
|
1743
|
+
}
|
|
1744
|
+
/** Estimate token count from character length. */
|
|
1745
|
+
declare function estimateTokens(text: string): number;
|
|
1746
|
+
/**
|
|
1747
|
+
* Calculate total tokens used in a debate from stored messages.
|
|
1748
|
+
* Uses actual usage_json when available, falls back to text length estimation.
|
|
1749
|
+
*/
|
|
1750
|
+
declare function calculateDebateTokens(history: DebateMessageRow[]): number;
|
|
1751
|
+
/**
|
|
1752
|
+
* Get the current token budget status for a debate.
|
|
1753
|
+
*/
|
|
1754
|
+
declare function getTokenBudgetStatus(history: DebateMessageRow[], maxContextTokens: number): TokenBudgetStatus;
|
|
1755
|
+
/**
|
|
1756
|
+
* Preflight check: estimate if a new prompt will fit within budget.
|
|
1757
|
+
* Returns the status AFTER the hypothetical send.
|
|
1758
|
+
*/
|
|
1759
|
+
declare function preflightTokenCheck(history: DebateMessageRow[], newPrompt: string, maxContextTokens: number): TokenBudgetStatus;
|
|
1760
|
+
|
|
1761
|
+
interface UnifiedSession {
|
|
1762
|
+
id: string;
|
|
1763
|
+
name: string | null;
|
|
1764
|
+
codexThreadId: string | null;
|
|
1765
|
+
status: 'active' | 'completed' | 'stale';
|
|
1766
|
+
tokenUsage: number;
|
|
1767
|
+
maxContext: number;
|
|
1768
|
+
createdAt: number;
|
|
1769
|
+
updatedAt: number;
|
|
1770
|
+
completedAt: number | null;
|
|
1771
|
+
}
|
|
1772
|
+
interface SessionEvent {
|
|
1773
|
+
id: number;
|
|
1774
|
+
sessionId: string;
|
|
1775
|
+
command: string;
|
|
1776
|
+
subcommand: string | null;
|
|
1777
|
+
promptPreview: string | null;
|
|
1778
|
+
responsePreview: string | null;
|
|
1779
|
+
usageJson: string | null;
|
|
1780
|
+
durationMs: number | null;
|
|
1781
|
+
codexThreadId: string | null;
|
|
1782
|
+
createdAt: number;
|
|
1783
|
+
}
|
|
1784
|
+
declare class SessionManager {
|
|
1785
|
+
private db;
|
|
1786
|
+
constructor(db: Database.Database);
|
|
1787
|
+
/** Create a new session. Returns the session ID. */
|
|
1788
|
+
create(name?: string): string;
|
|
1789
|
+
/** Get a session by ID. */
|
|
1790
|
+
get(id: string): UnifiedSession | null;
|
|
1791
|
+
/** Get the current active session (most recently updated). */
|
|
1792
|
+
getActive(): UnifiedSession | null;
|
|
1793
|
+
/** Get or create the active session. If none exists, auto-create one. */
|
|
1794
|
+
resolveActive(autoName?: string): UnifiedSession;
|
|
1795
|
+
/** Update the codex thread ID for a session. Pass null to clear. */
|
|
1796
|
+
updateThreadId(sessionId: string, threadId: string | null): void;
|
|
1797
|
+
/** Update token usage for a session. Ignores negative values. */
|
|
1798
|
+
addTokenUsage(sessionId: string, tokens: number): void;
|
|
1799
|
+
/**
|
|
1800
|
+
* Add token usage from a model call result. Uses real usage when available,
|
|
1801
|
+
* falls back to char/4 estimate only when usage data is missing.
|
|
1802
|
+
*/
|
|
1803
|
+
addUsageFromResult(sessionId: string, usage: {
|
|
1804
|
+
totalTokens?: number;
|
|
1805
|
+
inputTokens?: number;
|
|
1806
|
+
outputTokens?: number;
|
|
1807
|
+
}, promptText?: string, responseText?: string): void;
|
|
1808
|
+
/** Touch the updated_at timestamp. */
|
|
1809
|
+
touch(sessionId: string): void;
|
|
1810
|
+
/** Mark a session as completed. */
|
|
1811
|
+
complete(sessionId: string): void;
|
|
1812
|
+
/** List sessions, optionally filtered by status. */
|
|
1813
|
+
list(options?: {
|
|
1814
|
+
status?: string;
|
|
1815
|
+
limit?: number;
|
|
1816
|
+
}): UnifiedSession[];
|
|
1817
|
+
/** Record a GPT interaction event. Stores preview (500 chars) + optional full text. */
|
|
1818
|
+
recordEvent(params: {
|
|
1819
|
+
sessionId: string;
|
|
1820
|
+
command: string;
|
|
1821
|
+
subcommand?: string;
|
|
1822
|
+
promptPreview?: string;
|
|
1823
|
+
responsePreview?: string;
|
|
1824
|
+
promptFull?: string;
|
|
1825
|
+
responseFull?: string;
|
|
1826
|
+
usageJson?: string;
|
|
1827
|
+
durationMs?: number;
|
|
1828
|
+
codexThreadId?: string;
|
|
1829
|
+
}): number;
|
|
1830
|
+
/** Get events for a session. */
|
|
1831
|
+
getEvents(sessionId: string, rawLimit?: number): SessionEvent[];
|
|
1832
|
+
/** Estimate tokens from prompt + response text (for usage tracking when real usage unavailable). */
|
|
1833
|
+
estimateEventTokens(promptText: string, responseText: string): number;
|
|
1834
|
+
private toSession;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
declare class JobStore {
|
|
1838
|
+
private db;
|
|
1839
|
+
constructor(db: Database.Database);
|
|
1840
|
+
/** Enqueue a new job. Returns the job ID. */
|
|
1841
|
+
enqueue(options: EnqueueOptions): string;
|
|
1842
|
+
/** Get a job by ID. */
|
|
1843
|
+
get(id: string): JobRecord | null;
|
|
1844
|
+
/** Atomically claim the next N queued jobs. Returns claimed jobs. */
|
|
1845
|
+
claimNext(workerId: string, limit?: number): JobRecord[];
|
|
1846
|
+
/** Mark a job as succeeded. Only updates if still running (not canceled). */
|
|
1847
|
+
succeed(id: string, result: Record<string, unknown>): void;
|
|
1848
|
+
/** Mark a job as failed. Only updates if still running (not canceled). */
|
|
1849
|
+
fail(id: string, error: string): void;
|
|
1850
|
+
/** Cancel a job. */
|
|
1851
|
+
cancel(id: string): void;
|
|
1852
|
+
/** Retry a failed/canceled job. */
|
|
1853
|
+
retry(id: string): boolean;
|
|
1854
|
+
/** List jobs with optional filters. */
|
|
1855
|
+
list(options?: {
|
|
1856
|
+
status?: JobStatus;
|
|
1857
|
+
type?: JobType;
|
|
1858
|
+
limit?: number;
|
|
1859
|
+
}): JobRecord[];
|
|
1860
|
+
/** Check if a dedupe key already has an active (queued/running) job. */
|
|
1861
|
+
hasActive(dedupeKey: string): boolean;
|
|
1862
|
+
/** Check if any active job exists for a given type. */
|
|
1863
|
+
hasActiveByType(type: string): boolean;
|
|
1864
|
+
/** Append a log entry. */
|
|
1865
|
+
appendLog(jobId: string, level: JobLogRecord['level'], eventType: string, message?: string, payload?: Record<string, unknown>): void;
|
|
1866
|
+
/** Get logs for a job. */
|
|
1867
|
+
getLogs(jobId: string, fromSeq?: number, limit?: number): JobLogRecord[];
|
|
1868
|
+
private toJob;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
interface CacheEntry {
|
|
1872
|
+
id: number;
|
|
1873
|
+
key: string;
|
|
1874
|
+
kind: string;
|
|
1875
|
+
contentHash: string;
|
|
1876
|
+
configHash: string;
|
|
1877
|
+
model: string;
|
|
1878
|
+
valueJson: string;
|
|
1879
|
+
expiresAt: number;
|
|
1880
|
+
hitCount: number;
|
|
1881
|
+
createdAt: number;
|
|
1882
|
+
}
|
|
1883
|
+
declare class CacheStore {
|
|
1884
|
+
private db;
|
|
1885
|
+
constructor(db: Database.Database);
|
|
1886
|
+
get(key: string, contentHash: string, configHash: string): CacheEntry | null;
|
|
1887
|
+
set(entry: {
|
|
1888
|
+
key: string;
|
|
1889
|
+
kind: string;
|
|
1890
|
+
contentHash: string;
|
|
1891
|
+
configHash: string;
|
|
1892
|
+
model: string;
|
|
1893
|
+
valueJson: string;
|
|
1894
|
+
ttlMs: number;
|
|
1895
|
+
}): void;
|
|
1896
|
+
evictExpired(): number;
|
|
1897
|
+
clear(): number;
|
|
1898
|
+
stats(): {
|
|
1899
|
+
totalEntries: number;
|
|
1900
|
+
totalHits: number;
|
|
1901
|
+
expiredCount: number;
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
declare function hashContent(content: string): string;
|
|
1905
|
+
declare function hashConfig(config: Record<string, unknown>): string;
|
|
1906
|
+
|
|
1907
|
+
/** Capabilities that a bridge implementation advertises. */
|
|
1908
|
+
interface BridgeCapabilities {
|
|
1909
|
+
/** Whether the bridge supports session resume (multi-turn statefulness). */
|
|
1910
|
+
supportsResume: boolean;
|
|
1911
|
+
/** Whether the bridge supports streaming output. */
|
|
1912
|
+
supportsStream: boolean;
|
|
1913
|
+
/** Maximum context window in tokens. */
|
|
1914
|
+
maxContextTokens: number;
|
|
1915
|
+
/** Whether the bridge can use tools (read files, run commands). */
|
|
1916
|
+
supportsTools: boolean;
|
|
1917
|
+
/** Whether the bridge can access the project working directory. */
|
|
1918
|
+
supportsCwd: boolean;
|
|
1919
|
+
}
|
|
1920
|
+
/** Options for a bridge send/resume call. */
|
|
1921
|
+
interface BridgeOptions extends ProgressCallbacks {
|
|
1922
|
+
timeout?: number;
|
|
1923
|
+
maxOutputBytes?: number;
|
|
1924
|
+
idleTimeout?: number;
|
|
1925
|
+
}
|
|
1926
|
+
/** Options for a bridge resume call. */
|
|
1927
|
+
interface BridgeResumeOptions extends BridgeOptions {
|
|
1928
|
+
sessionId: string;
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Generic interface for bridging communication between two CLI tools.
|
|
1932
|
+
* Each implementation handles its own CLI's quirks (JSONL parsing, session format, auth).
|
|
1933
|
+
*/
|
|
1934
|
+
interface CliBridge {
|
|
1935
|
+
/** Human-readable bridge name (e.g., 'codex', 'gemini', 'claude'). */
|
|
1936
|
+
readonly name: string;
|
|
1937
|
+
/** Model identifier. */
|
|
1938
|
+
readonly model: string;
|
|
1939
|
+
/** Advertised capabilities. */
|
|
1940
|
+
readonly capabilities: BridgeCapabilities;
|
|
1941
|
+
/** Send a prompt and get a response. */
|
|
1942
|
+
send(prompt: string, options?: BridgeOptions): Promise<ModelCallResult>;
|
|
1943
|
+
/** Resume a previous session with a new prompt. Falls back to send() if resume unsupported. */
|
|
1944
|
+
resume(sessionId: string, prompt: string, options?: BridgeOptions): Promise<ModelCallResult>;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
/** Progress callbacks for real-time feedback during CLI subprocess execution. */
|
|
1948
|
+
interface ProgressCallbacks {
|
|
1949
|
+
/** Called when the subprocess successfully spawns. */
|
|
1950
|
+
onSpawn?: (pid: number, command: string) => void;
|
|
1951
|
+
/** Called on each stderr chunk (tool calls, activity). */
|
|
1952
|
+
onStderr?: (chunk: string) => void;
|
|
1953
|
+
/** Called periodically (every 15s) with elapsed seconds. */
|
|
1954
|
+
onHeartbeat?: (elapsedSec: number) => void;
|
|
1955
|
+
/** Called on each stdout chunk for progress feedback. */
|
|
1956
|
+
onProgress?: (chunk: string) => void;
|
|
1957
|
+
/** Called when the subprocess closes — flush any buffered state. */
|
|
1958
|
+
onClose?: () => void;
|
|
1959
|
+
}
|
|
1960
|
+
interface CliCallOptions extends ProgressCallbacks {
|
|
1961
|
+
/** Total timeout in ms. Default: 600_000 (10 min). */
|
|
1962
|
+
timeout?: number;
|
|
1963
|
+
/** Inactivity timeout — kill if no stdout for this long. Default: 120_000 (2 min). */
|
|
1964
|
+
idleTimeout?: number;
|
|
1965
|
+
maxOutputBytes?: number;
|
|
1966
|
+
envAllowlist?: string[];
|
|
1967
|
+
}
|
|
1968
|
+
interface ResumeCallOptions extends CliCallOptions {
|
|
1969
|
+
/** Codex thread_id to resume a conversation. */
|
|
1970
|
+
sessionId?: string;
|
|
1971
|
+
}
|
|
1972
|
+
declare class CliAdapter implements CliBridge {
|
|
1973
|
+
private command;
|
|
1974
|
+
private baseArgs;
|
|
1975
|
+
private provider;
|
|
1976
|
+
readonly modelId: string;
|
|
1977
|
+
private cliName;
|
|
1978
|
+
private projectDir;
|
|
1979
|
+
readonly capabilities: BridgeCapabilities;
|
|
1980
|
+
get name(): string;
|
|
1981
|
+
get model(): string;
|
|
1982
|
+
constructor(config: {
|
|
1983
|
+
command: string;
|
|
1984
|
+
args: string[];
|
|
1985
|
+
provider: ModelProvider;
|
|
1986
|
+
model: string;
|
|
1987
|
+
cliName: string;
|
|
1988
|
+
projectDir?: string;
|
|
1989
|
+
});
|
|
1990
|
+
/** CliBridge.send — send a prompt without session resume. */
|
|
1991
|
+
send(prompt: string, options?: CliCallOptions): Promise<ModelCallResult>;
|
|
1992
|
+
/** CliBridge.resume — resume a session or fall back to send. */
|
|
1993
|
+
resume(sessionId: string, prompt: string, options?: CliCallOptions): Promise<ModelCallResult>;
|
|
1994
|
+
call(prompt: string, options?: CliCallOptions): Promise<ModelCallResult>;
|
|
1995
|
+
/**
|
|
1996
|
+
* Call codex with session resume support via --json JSONL output.
|
|
1997
|
+
* If sessionId is provided, resumes the conversation. On resume failure,
|
|
1998
|
+
* falls back to a fresh exec and returns the new sessionId.
|
|
1999
|
+
*/
|
|
2000
|
+
callWithResume(prompt: string, options?: ResumeCallOptions): Promise<ModelCallResult>;
|
|
2001
|
+
private buildArgs;
|
|
2002
|
+
private runProcess;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
/** All models are CLI adapters now. */
|
|
2006
|
+
type ModelAdapter = CliAdapter;
|
|
2007
|
+
declare class ModelRegistry {
|
|
2008
|
+
private models;
|
|
2009
|
+
private configs;
|
|
2010
|
+
private constructor();
|
|
2011
|
+
/**
|
|
2012
|
+
* Build a registry from a ProjectConfig.
|
|
2013
|
+
* All models are CLI adapters (codex).
|
|
2014
|
+
*/
|
|
2015
|
+
static fromConfig(config: ProjectConfig, projectDir?: string): ModelRegistry;
|
|
2016
|
+
/**
|
|
2017
|
+
* Resolve auto mode — probe codex CLI availability.
|
|
2018
|
+
* Kept for API compatibility; all models are CLI now.
|
|
2019
|
+
*/
|
|
2020
|
+
resolveAutoMode(): Promise<void>;
|
|
2021
|
+
/** Get the adapter for an alias, or null if not found. */
|
|
2022
|
+
tryGetAdapter(alias: string): ModelAdapter | null;
|
|
2023
|
+
/** Get the adapter for an alias. Throws if not found. */
|
|
2024
|
+
getAdapter(alias: string): ModelAdapter;
|
|
2025
|
+
/** Check if an alias is backed by CLI adapter (always true now). */
|
|
2026
|
+
isCliMode(_alias: string): boolean;
|
|
2027
|
+
/** Get the ModelConfig for an alias. */
|
|
2028
|
+
getModelConfig(alias: string): ModelConfig;
|
|
2029
|
+
/** Resolve role -> alias -> ModelAdapter. */
|
|
2030
|
+
getAdapterForRole(role: string, config: ProjectConfig): ModelAdapter;
|
|
2031
|
+
/** Resolve role -> alias -> ModelConfig. */
|
|
2032
|
+
getModelConfigForRole(role: string, config: ProjectConfig): ModelConfig;
|
|
2033
|
+
/** List all registered model aliases. */
|
|
2034
|
+
listAliases(): string[];
|
|
2035
|
+
/**
|
|
2036
|
+
* Health check: verify codex CLI is available and authenticated.
|
|
2037
|
+
*/
|
|
2038
|
+
healthCheckAll(): Promise<Map<string, boolean>>;
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
/**
|
|
2042
|
+
* Callback for receiving streaming text deltas.
|
|
2043
|
+
*/
|
|
2044
|
+
type TextDeltaEmitter = (delta: string) => void;
|
|
2045
|
+
/**
|
|
2046
|
+
* Unified model call: routes to CLI adapter.
|
|
2047
|
+
*/
|
|
2048
|
+
declare function callModel(model: ModelAdapter, messages: ChatMessage[], options?: CallModelOptions): Promise<ModelCallResult>;
|
|
2049
|
+
/**
|
|
2050
|
+
* Unified streaming model call.
|
|
2051
|
+
* CLI: chunked pseudo-streaming (paragraph-split after process completes).
|
|
2052
|
+
*/
|
|
2053
|
+
declare function streamModel(model: ModelAdapter, messages: ChatMessage[], onDelta: TextDeltaEmitter, _stepId: string, _role: string, options?: CallModelOptions): Promise<ModelCallResult>;
|
|
2054
|
+
|
|
2055
|
+
/**
|
|
2056
|
+
* Execute a model call with fallback support.
|
|
2057
|
+
*
|
|
2058
|
+
* Tries the primary call first. On retryable errors, tries each fallback in order.
|
|
2059
|
+
* The `callFn` receives the model alias and must perform the actual model call.
|
|
2060
|
+
*/
|
|
2061
|
+
declare function withFallback(callFn: (modelAlias: string) => Promise<ModelCallResult>, config: FallbackConfig): Promise<ModelCallResult>;
|
|
2062
|
+
|
|
2063
|
+
/**
|
|
2064
|
+
* Wraps model calls and records cost/usage to the CostStore.
|
|
2065
|
+
* Created per-session by the Orchestrator.
|
|
2066
|
+
*/
|
|
2067
|
+
declare class CostTracker {
|
|
2068
|
+
private costStore;
|
|
2069
|
+
private sessionId;
|
|
2070
|
+
constructor(costStore: CostStore, sessionId: string);
|
|
2071
|
+
/**
|
|
2072
|
+
* Execute a model call and record its cost.
|
|
2073
|
+
* Usage: `costTracker.tracked(() => callModel(model, msgs, opts), 'plan')`
|
|
2074
|
+
*/
|
|
2075
|
+
tracked(fn: () => Promise<ModelCallResult>, stepId?: string): Promise<ModelCallResult>;
|
|
2076
|
+
/** Record usage from an already-completed model call. */
|
|
2077
|
+
record(result: ModelCallResult, stepId?: string): void;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
interface ModelPricing {
|
|
2081
|
+
inputPer1M: number;
|
|
2082
|
+
outputPer1M: number;
|
|
2083
|
+
}
|
|
2084
|
+
declare function getModelPricing(modelId: string): ModelPricing | null;
|
|
2085
|
+
/**
|
|
2086
|
+
* Calculate cost in USD for a model call.
|
|
2087
|
+
* Returns 0 if the model is not in the pricing table.
|
|
2088
|
+
*/
|
|
2089
|
+
declare function calculateCost(modelId: string, inputTokens: number, outputTokens: number): number;
|
|
2090
|
+
|
|
2091
|
+
interface CliDetectionResult {
|
|
2092
|
+
available: boolean;
|
|
2093
|
+
path?: string;
|
|
2094
|
+
version?: string;
|
|
2095
|
+
authOk?: boolean;
|
|
2096
|
+
detectedAt: number;
|
|
2097
|
+
error?: string;
|
|
2098
|
+
}
|
|
2099
|
+
declare function detectCli(name: 'codex'): Promise<CliDetectionResult>;
|
|
2100
|
+
declare function clearDetectionCache(): void;
|
|
2101
|
+
|
|
2102
|
+
/**
|
|
2103
|
+
* The 5 prompt types supported in Sprint 1.
|
|
2104
|
+
*/
|
|
2105
|
+
type PromptType = 'plan' | 'plan-review' | 'plan-revision' | 'code' | 'code-review';
|
|
2106
|
+
/**
|
|
2107
|
+
* Variables passed into prompt templates.
|
|
2108
|
+
*/
|
|
2109
|
+
interface PromptVariables {
|
|
2110
|
+
task: string;
|
|
2111
|
+
projectName?: string;
|
|
2112
|
+
projectDescription?: string;
|
|
2113
|
+
plan?: string;
|
|
2114
|
+
previousPlan?: string;
|
|
2115
|
+
feedback?: string;
|
|
2116
|
+
code?: string;
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Render a prompt template into ChatMessage[] (system + user messages).
|
|
2120
|
+
*/
|
|
2121
|
+
declare function renderPrompt(type: PromptType, vars: PromptVariables): ChatMessage[];
|
|
2122
|
+
|
|
2123
|
+
/**
|
|
2124
|
+
* Resolves roles from config, provides prompt rendering and message assembly.
|
|
2125
|
+
*/
|
|
2126
|
+
declare class RoleManager {
|
|
2127
|
+
private config;
|
|
2128
|
+
constructor(config: ProjectConfig);
|
|
2129
|
+
/**
|
|
2130
|
+
* Resolve a role name to a fully hydrated Role object.
|
|
2131
|
+
* Merges built-in defaults with config overrides.
|
|
2132
|
+
*/
|
|
2133
|
+
getRole(roleName: string): Role;
|
|
2134
|
+
/**
|
|
2135
|
+
* Build a ChatMessage[] for a model call.
|
|
2136
|
+
* Renders the appropriate prompt template with project context and variables.
|
|
2137
|
+
*/
|
|
2138
|
+
buildMessages(promptType: PromptType, vars: PromptVariables): ChatMessage[];
|
|
2139
|
+
/** List all configured role names. */
|
|
2140
|
+
listRoles(): string[];
|
|
2141
|
+
/** Get the RoleConfig for a role name. */
|
|
2142
|
+
getRoleConfig(roleName: string): RoleConfig;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
interface EventBusEvents {
|
|
2146
|
+
event: (event: EngineEvent) => void;
|
|
2147
|
+
}
|
|
2148
|
+
/**
|
|
2149
|
+
* Typed event bus for AG-UI compatible engine events.
|
|
2150
|
+
* Wraps eventemitter3 with typed EngineEvent emission.
|
|
2151
|
+
*/
|
|
2152
|
+
declare class EventBus extends EventEmitter<EventBusEvents> {
|
|
2153
|
+
/** Emit a typed AG-UI event, auto-injecting timestamp if missing. */
|
|
2154
|
+
emitEvent(event: EngineEvent): void;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
interface StepResult {
|
|
2158
|
+
stepId: string;
|
|
2159
|
+
output: string;
|
|
2160
|
+
usage: TokenUsage;
|
|
2161
|
+
durationMs: number;
|
|
2162
|
+
verdict?: 'approved' | 'needs_revision';
|
|
2163
|
+
feedback?: string;
|
|
2164
|
+
score?: number;
|
|
2165
|
+
}
|
|
2166
|
+
declare class StepRunner {
|
|
2167
|
+
private registry;
|
|
2168
|
+
private roleManager;
|
|
2169
|
+
private costTracker;
|
|
2170
|
+
private eventBus;
|
|
2171
|
+
private sessionStore;
|
|
2172
|
+
private config;
|
|
2173
|
+
private sessionId;
|
|
2174
|
+
constructor(registry: ModelRegistry, roleManager: RoleManager, costTracker: CostTracker, eventBus: EventBus, sessionStore: SessionStore, config: ProjectConfig, sessionId: string);
|
|
2175
|
+
execute(step: ResolvedStep, inputs: Map<string, string>, task: string, iteration: number, options?: {
|
|
2176
|
+
stream?: boolean;
|
|
2177
|
+
}): Promise<StepResult>;
|
|
2178
|
+
private resolvePromptType;
|
|
2179
|
+
private buildPromptVars;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
interface LoopResult {
|
|
2183
|
+
finalOutput: string;
|
|
2184
|
+
iterations: number;
|
|
2185
|
+
approved: boolean;
|
|
2186
|
+
history: StepResult[];
|
|
2187
|
+
finalScore?: number;
|
|
2188
|
+
}
|
|
2189
|
+
interface LoopOptions {
|
|
2190
|
+
/** Score threshold for auto-approval on iteration >= 2. Only applies when set. */
|
|
2191
|
+
autoApproveThreshold?: number;
|
|
2192
|
+
}
|
|
2193
|
+
declare class LoopController {
|
|
2194
|
+
executeLoop(generateStep: ResolvedStep, reviewStep: ResolvedStep, inputs: Map<string, string>, task: string, maxIterations: number, runner: StepRunner, eventBus: EventBus, loopOptions?: LoopOptions): Promise<LoopResult>;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
declare class CancellationToken {
|
|
2198
|
+
private cancelled;
|
|
2199
|
+
private callbacks;
|
|
2200
|
+
/** Signal cancellation. Idempotent — multiple calls are safe. */
|
|
2201
|
+
cancel(): void;
|
|
2202
|
+
get isCancelled(): boolean;
|
|
2203
|
+
/** Throw if already cancelled. Call before starting expensive work. */
|
|
2204
|
+
throwIfCancelled(): void;
|
|
2205
|
+
/**
|
|
2206
|
+
* Register a callback to run on cancellation.
|
|
2207
|
+
* Deduplicated by reference — same function won't run twice.
|
|
2208
|
+
* If already cancelled, callback fires immediately.
|
|
2209
|
+
*/
|
|
2210
|
+
onCancel(callback: () => void): void;
|
|
2211
|
+
/** Remove a previously registered callback. */
|
|
2212
|
+
offCancel(callback: () => void): void;
|
|
2213
|
+
/**
|
|
2214
|
+
* Create a promise that resolves after `ms` but can be interrupted by cancellation.
|
|
2215
|
+
* Returns true if sleep completed, false if cancelled.
|
|
2216
|
+
*/
|
|
2217
|
+
sleep(ms: number): Promise<boolean>;
|
|
2218
|
+
}
|
|
2219
|
+
declare class CancellationError extends Error {
|
|
2220
|
+
constructor(message: string);
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
interface OrchestratorEvents {
|
|
2224
|
+
event: (event: EngineEvent) => void;
|
|
2225
|
+
}
|
|
2226
|
+
interface OrchestratorOptions {
|
|
2227
|
+
registry: ModelRegistry;
|
|
2228
|
+
db: Database.Database;
|
|
2229
|
+
config: ProjectConfig;
|
|
2230
|
+
workflowDir?: string;
|
|
2231
|
+
projectDir?: string;
|
|
2232
|
+
}
|
|
2233
|
+
interface RunOptions {
|
|
2234
|
+
mode?: ExecutionMode;
|
|
2235
|
+
maxIterations?: number;
|
|
2236
|
+
stream?: boolean;
|
|
2237
|
+
workflowDir?: string;
|
|
2238
|
+
}
|
|
2239
|
+
interface PlanOptions {
|
|
2240
|
+
maxRounds?: number;
|
|
2241
|
+
stream?: boolean;
|
|
2242
|
+
workflowDir?: string;
|
|
2243
|
+
/** Score threshold (1-10) for auto-approving plans on 2nd+ iteration. Default: 8. */
|
|
2244
|
+
autoApproveThreshold?: number;
|
|
2245
|
+
}
|
|
2246
|
+
interface SessionResult {
|
|
2247
|
+
sessionId: string;
|
|
2248
|
+
status: 'completed' | 'failed';
|
|
2249
|
+
finalOutput: string;
|
|
2250
|
+
totalCost: number;
|
|
2251
|
+
totalTokens: number;
|
|
2252
|
+
durationMs: number;
|
|
2253
|
+
iterations: number;
|
|
2254
|
+
error?: string;
|
|
2255
|
+
lastStep?: string;
|
|
2256
|
+
}
|
|
2257
|
+
interface ReviewOptions {
|
|
2258
|
+
criteria?: string[];
|
|
2259
|
+
model?: string;
|
|
2260
|
+
strict?: boolean;
|
|
2261
|
+
timeout?: number;
|
|
2262
|
+
}
|
|
2263
|
+
interface DebateOptions {
|
|
2264
|
+
modelAliases?: string[];
|
|
2265
|
+
synthesize?: boolean;
|
|
2266
|
+
timeout?: number;
|
|
2267
|
+
maxConcurrency?: number;
|
|
2268
|
+
}
|
|
2269
|
+
declare class Orchestrator extends EventEmitter<OrchestratorEvents> {
|
|
2270
|
+
private registry;
|
|
2271
|
+
private config;
|
|
2272
|
+
private sessionStore;
|
|
2273
|
+
private artifactStore;
|
|
2274
|
+
private costStore;
|
|
2275
|
+
private memoryStore;
|
|
2276
|
+
private roleManager;
|
|
2277
|
+
private workflowEngine;
|
|
2278
|
+
private eventBus;
|
|
2279
|
+
private contextBuilder;
|
|
2280
|
+
constructor(options: OrchestratorOptions);
|
|
2281
|
+
run(task: string, options?: RunOptions): Promise<SessionResult>;
|
|
2282
|
+
plan(task: string, options?: PlanOptions): Promise<SessionResult>;
|
|
2283
|
+
/**
|
|
2284
|
+
* Review content with a single model.
|
|
2285
|
+
* DLP-sanitizes content first (strict mode by default).
|
|
2286
|
+
*/
|
|
2287
|
+
review(content: string, options?: ReviewOptions, cancellationToken?: CancellationToken): Promise<ReviewResult>;
|
|
2288
|
+
/**
|
|
2289
|
+
* Debate a question across multiple models.
|
|
2290
|
+
* DLP-sanitizes question first. Runs models concurrently with async semaphore.
|
|
2291
|
+
*/
|
|
2292
|
+
debate(question: string, options?: DebateOptions, cancellationToken?: CancellationToken): Promise<DebateResult>;
|
|
2293
|
+
/**
|
|
2294
|
+
* Multi-round debate: models see and respond to each other's arguments.
|
|
2295
|
+
* Uses proposal-critique pattern: proposer → critic → revise → critique → ...
|
|
2296
|
+
* Models iterate until convergence (critic approves) or max rounds.
|
|
2297
|
+
*/
|
|
2298
|
+
debateMultiRound(question: string, options?: {
|
|
2299
|
+
modelAliases?: string[];
|
|
2300
|
+
maxRounds?: number;
|
|
2301
|
+
timeout?: number;
|
|
2302
|
+
}): Promise<DebateEngineResult>;
|
|
2303
|
+
/** Resolve the default reviewer model alias from roles config. */
|
|
2304
|
+
private resolveReviewerAlias;
|
|
2305
|
+
/** Resolve debate aliases — all configured model aliases. */
|
|
2306
|
+
private resolveDebateAliases;
|
|
2307
|
+
/**
|
|
2308
|
+
* Save a memory only if no similar entry already exists (content-prefix dedup).
|
|
2309
|
+
* Uses SQL LIKE prefix match instead of FTS5 for reliable exact matching.
|
|
2310
|
+
*/
|
|
2311
|
+
private saveMemoryIfNew;
|
|
2312
|
+
/**
|
|
2313
|
+
* Shared session lifecycle for run() and plan().
|
|
2314
|
+
* Extracts common session creation, workflow loading, cost tracking, and completion.
|
|
2315
|
+
*/
|
|
2316
|
+
private executeSession;
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
/**
|
|
2320
|
+
* Loads workflow YAML files, validates them, and resolves step dependencies
|
|
2321
|
+
* into a topologically sorted execution order.
|
|
2322
|
+
*/
|
|
2323
|
+
declare class WorkflowEngine {
|
|
2324
|
+
private workflowDir;
|
|
2325
|
+
constructor(workflowDir: string);
|
|
2326
|
+
/**
|
|
2327
|
+
* Load a workflow YAML file by name, validate it, and resolve into a DAG.
|
|
2328
|
+
*/
|
|
2329
|
+
load(workflowName: string): ResolvedWorkflow;
|
|
2330
|
+
/**
|
|
2331
|
+
* Returns the topologically sorted steps (already computed during load).
|
|
2332
|
+
*/
|
|
2333
|
+
getExecutionOrder(workflow: ResolvedWorkflow): ResolvedStep[];
|
|
2334
|
+
private validateDefinition;
|
|
2335
|
+
private validateStep;
|
|
2336
|
+
/**
|
|
2337
|
+
* Resolve steps into topological order, validating input references and loops.
|
|
2338
|
+
*/
|
|
2339
|
+
private resolveSteps;
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
type PolicyMode = 'warn' | 'enforce';
|
|
2343
|
+
type PolicyDecision = 'allow' | 'warn' | 'block';
|
|
2344
|
+
interface PolicyRule {
|
|
2345
|
+
id: string;
|
|
2346
|
+
when: string;
|
|
2347
|
+
predicate: string;
|
|
2348
|
+
threshold?: number;
|
|
2349
|
+
action: 'warn' | 'block';
|
|
2350
|
+
message: string;
|
|
2351
|
+
}
|
|
2352
|
+
interface PolicyContext {
|
|
2353
|
+
criticalCount: number;
|
|
2354
|
+
warningCount: number;
|
|
2355
|
+
verdict: string;
|
|
2356
|
+
stepsCompleted: Record<string, 'passed' | 'failed' | 'skipped'>;
|
|
2357
|
+
cleanupHighCount: number;
|
|
2358
|
+
}
|
|
2359
|
+
interface PolicyResult {
|
|
2360
|
+
decision: PolicyDecision;
|
|
2361
|
+
violations: {
|
|
2362
|
+
ruleId: string;
|
|
2363
|
+
action: 'warn' | 'block';
|
|
2364
|
+
message: string;
|
|
2365
|
+
}[];
|
|
2366
|
+
}
|
|
2367
|
+
declare const DEFAULT_RULES: PolicyRule[];
|
|
2368
|
+
declare function evaluatePolicy(event: string, context: PolicyContext, rules: PolicyRule[], mode?: PolicyMode): PolicyResult;
|
|
2369
|
+
|
|
2370
|
+
/** Token budget tiers for context assembly. */
|
|
2371
|
+
interface ContextBudget {
|
|
2372
|
+
/** Max tokens for tier 1: task + memories. Default 2000 */
|
|
2373
|
+
tier1: number;
|
|
2374
|
+
/** Max tokens for tier 2: file tree + snippets. Default 4000 */
|
|
2375
|
+
tier2: number;
|
|
2376
|
+
/** Max total tokens for assembled context. Default 8000 */
|
|
2377
|
+
total: number;
|
|
2378
|
+
}
|
|
2379
|
+
interface ContextBuilderOptions {
|
|
2380
|
+
projectDir?: string;
|
|
2381
|
+
projectId?: string;
|
|
2382
|
+
memoryStore?: MemoryStore;
|
|
2383
|
+
budget?: Partial<ContextBudget>;
|
|
2384
|
+
/** Max depth for file tree traversal. Default 3 */
|
|
2385
|
+
maxTreeDepth?: number;
|
|
2386
|
+
/** Max number of files to include in tree. Default 200 */
|
|
2387
|
+
maxFiles?: number;
|
|
2388
|
+
/** File extensions to include in tree. Default: common code extensions */
|
|
2389
|
+
includeExtensions?: string[];
|
|
2390
|
+
}
|
|
2391
|
+
interface AssembledContext {
|
|
2392
|
+
/** The enriched prompt with context prepended */
|
|
2393
|
+
prompt: string;
|
|
2394
|
+
/** Memories that were injected */
|
|
2395
|
+
memories: MemoryRecord[];
|
|
2396
|
+
/** File tree summary (if generated) */
|
|
2397
|
+
fileTree: string;
|
|
2398
|
+
/** Estimated token count of the assembled context */
|
|
2399
|
+
estimatedTokens: number;
|
|
2400
|
+
}
|
|
2401
|
+
/**
|
|
2402
|
+
* Builds enriched prompts by assembling relevant context from:
|
|
2403
|
+
* - Tier 1: Task framing + relevant memories from SQLite FTS
|
|
2404
|
+
* - Tier 2: Project file tree + relevant code snippets
|
|
2405
|
+
* - Tier 3: (Future) On-demand expansion when model requests more context
|
|
2406
|
+
*/
|
|
2407
|
+
declare class ContextBuilder {
|
|
2408
|
+
private projectDir;
|
|
2409
|
+
private projectId;
|
|
2410
|
+
private memoryStore;
|
|
2411
|
+
private budget;
|
|
2412
|
+
private maxTreeDepth;
|
|
2413
|
+
private maxFiles;
|
|
2414
|
+
private includeExtensions;
|
|
2415
|
+
constructor(options: ContextBuilderOptions);
|
|
2416
|
+
/**
|
|
2417
|
+
* Assemble enriched context for a model call.
|
|
2418
|
+
* @param taskPrompt The original prompt/task
|
|
2419
|
+
* @param taskType Context about what kind of task (review, debate, plan)
|
|
2420
|
+
*/
|
|
2421
|
+
assemble(taskPrompt: string, taskType?: string): AssembledContext;
|
|
2422
|
+
/** Query relevant memories using FTS5 search. */
|
|
2423
|
+
private queryMemories;
|
|
2424
|
+
/** Extract meaningful search terms from a prompt. */
|
|
2425
|
+
private extractSearchTerms;
|
|
2426
|
+
/** Format memories for injection into prompt. */
|
|
2427
|
+
private formatMemories;
|
|
2428
|
+
/** Build a compact file tree of the project, capped at maxFiles entries. */
|
|
2429
|
+
buildFileTree(): string;
|
|
2430
|
+
private walkDir;
|
|
2431
|
+
private shouldIncludeFile;
|
|
2432
|
+
/**
|
|
2433
|
+
* Read a specific file's content within token budget.
|
|
2434
|
+
* Useful for tier 3 on-demand context expansion.
|
|
2435
|
+
*/
|
|
2436
|
+
readFileContent(filePath: string, maxChars?: number): string | null;
|
|
2437
|
+
}
|
|
2438
|
+
/** Command types with pre-defined output contracts. */
|
|
2439
|
+
type HandoffCommand = 'review' | 'debate' | 'build-review' | 'cleanup' | 'adjudicate' | 'custom';
|
|
2440
|
+
interface HandoffEnvelopeOptions {
|
|
2441
|
+
/** The command being executed */
|
|
2442
|
+
command: HandoffCommand;
|
|
2443
|
+
/** The core task/instruction for GPT */
|
|
2444
|
+
task: string;
|
|
2445
|
+
/** Focus area or constraints */
|
|
2446
|
+
constraints?: string[];
|
|
2447
|
+
/** Whether this is a resumed session (GPT already has prior context) */
|
|
2448
|
+
resumed: boolean;
|
|
2449
|
+
/** Brief summary of what happened in prior turns (from session events) */
|
|
2450
|
+
priorContext?: string;
|
|
2451
|
+
/** Scope restriction (glob pattern) */
|
|
2452
|
+
scope?: string;
|
|
2453
|
+
}
|
|
2454
|
+
/**
|
|
2455
|
+
* Build a structured handoff envelope for Claude→GPT communication.
|
|
2456
|
+
*
|
|
2457
|
+
* Wraps any command's raw prompt with:
|
|
2458
|
+
* 1. Codebase access preamble
|
|
2459
|
+
* 2. Resume primer (when continuing a thread)
|
|
2460
|
+
* 3. The core task
|
|
2461
|
+
* 4. Constraints & scope
|
|
2462
|
+
* 5. Output contract
|
|
2463
|
+
*/
|
|
2464
|
+
declare function buildHandoffEnvelope(options: HandoffEnvelopeOptions): string;
|
|
2465
|
+
|
|
2466
|
+
declare function scanUnusedDeps(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2467
|
+
declare function scanUnusedExports(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2468
|
+
declare function scanHardcoded(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2469
|
+
declare function scanDuplicates(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2470
|
+
declare function scanDeadCode(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2471
|
+
declare function scanSecurity(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2472
|
+
declare function scanNearDuplicates(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2473
|
+
declare function scanAntiPatterns(projectDir: string, ig?: Ignore): CleanupFinding[];
|
|
2474
|
+
declare function runAllScanners(projectDir: string, scopes: CleanupScope[], ig?: Ignore): CleanupFinding[];
|
|
2475
|
+
|
|
2476
|
+
/**
|
|
2477
|
+
* Merge findings from up to 3 sources: deterministic, semantic (codex), and host (Claude).
|
|
2478
|
+
* Agreement rules:
|
|
2479
|
+
* - All 3 agree → confidence: high
|
|
2480
|
+
* - 2 of 3 agree → confidence: high (majority)
|
|
2481
|
+
* - Only 1 found → original confidence preserved, disputed: true
|
|
2482
|
+
*/
|
|
2483
|
+
declare function mergeThreeWay(deterministic: CleanupFinding[], semantic: CleanupFinding[], host: CleanupFinding[]): CleanupFinding[];
|
|
2484
|
+
/**
|
|
2485
|
+
* Compute stats from merged findings with 3-source tracking.
|
|
2486
|
+
*/
|
|
2487
|
+
declare function computeThreeWayStats(deterministic: CleanupFinding[], semantic: CleanupFinding[], host: CleanupFinding[], merged: CleanupFinding[]): CleanupReport['stats'];
|
|
2488
|
+
/**
|
|
2489
|
+
* Legacy 2-way merge (deterministic + semantic only). Wraps mergeThreeWay with empty host.
|
|
2490
|
+
*/
|
|
2491
|
+
declare function mergeTwoWay(deterministic: CleanupFinding[], semantic: CleanupFinding[]): CleanupFinding[];
|
|
2492
|
+
/**
|
|
2493
|
+
* Legacy 2-way stats. Wraps computeThreeWayStats with empty host.
|
|
2494
|
+
*/
|
|
2495
|
+
declare function computeTwoWayStats(deterministic: CleanupFinding[], semantic: CleanupFinding[], merged: CleanupFinding[]): CleanupReport['stats'];
|
|
2496
|
+
/**
|
|
2497
|
+
* Recalculate stats after adjudication modifies findings in place.
|
|
2498
|
+
* Note: `stats.adjudicated` is managed by the caller (incremented per adjudication).
|
|
2499
|
+
*/
|
|
2500
|
+
declare function recalculateConfidenceStats(findings: CleanupFinding[], stats: CleanupReport['stats']): void;
|
|
2501
|
+
|
|
2502
|
+
declare const hostFindingSchema: z.ZodEffects<z.ZodObject<{
|
|
2503
|
+
scope: z.ZodEnum<["deps", "unused-exports", "hardcoded", "duplicates", "deadcode"]>;
|
|
2504
|
+
confidence: z.ZodEnum<["high", "medium", "low"]>;
|
|
2505
|
+
file: z.ZodString;
|
|
2506
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
2507
|
+
symbol: z.ZodString;
|
|
2508
|
+
description: z.ZodString;
|
|
2509
|
+
recommendation: z.ZodString;
|
|
2510
|
+
}, "strip", z.ZodTypeAny, {
|
|
2511
|
+
symbol: string;
|
|
2512
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2513
|
+
description: string;
|
|
2514
|
+
confidence: "high" | "medium" | "low";
|
|
2515
|
+
file: string;
|
|
2516
|
+
recommendation: string;
|
|
2517
|
+
line?: number | undefined;
|
|
2518
|
+
}, {
|
|
2519
|
+
symbol: string;
|
|
2520
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2521
|
+
description: string;
|
|
2522
|
+
confidence: "high" | "medium" | "low";
|
|
2523
|
+
file: string;
|
|
2524
|
+
recommendation: string;
|
|
2525
|
+
line?: number | undefined;
|
|
2526
|
+
}>, {
|
|
2527
|
+
symbol: string;
|
|
2528
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2529
|
+
description: string;
|
|
2530
|
+
confidence: "high" | "medium" | "low";
|
|
2531
|
+
file: string;
|
|
2532
|
+
recommendation: string;
|
|
2533
|
+
line?: number | undefined;
|
|
2534
|
+
}, {
|
|
2535
|
+
symbol: string;
|
|
2536
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2537
|
+
description: string;
|
|
2538
|
+
confidence: "high" | "medium" | "low";
|
|
2539
|
+
file: string;
|
|
2540
|
+
recommendation: string;
|
|
2541
|
+
line?: number | undefined;
|
|
2542
|
+
}>;
|
|
2543
|
+
declare const hostFindingsSchema: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
2544
|
+
scope: z.ZodEnum<["deps", "unused-exports", "hardcoded", "duplicates", "deadcode"]>;
|
|
2545
|
+
confidence: z.ZodEnum<["high", "medium", "low"]>;
|
|
2546
|
+
file: z.ZodString;
|
|
2547
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
2548
|
+
symbol: z.ZodString;
|
|
2549
|
+
description: z.ZodString;
|
|
2550
|
+
recommendation: z.ZodString;
|
|
2551
|
+
}, "strip", z.ZodTypeAny, {
|
|
2552
|
+
symbol: string;
|
|
2553
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2554
|
+
description: string;
|
|
2555
|
+
confidence: "high" | "medium" | "low";
|
|
2556
|
+
file: string;
|
|
2557
|
+
recommendation: string;
|
|
2558
|
+
line?: number | undefined;
|
|
2559
|
+
}, {
|
|
2560
|
+
symbol: string;
|
|
2561
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2562
|
+
description: string;
|
|
2563
|
+
confidence: "high" | "medium" | "low";
|
|
2564
|
+
file: string;
|
|
2565
|
+
recommendation: string;
|
|
2566
|
+
line?: number | undefined;
|
|
2567
|
+
}>, {
|
|
2568
|
+
symbol: string;
|
|
2569
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2570
|
+
description: string;
|
|
2571
|
+
confidence: "high" | "medium" | "low";
|
|
2572
|
+
file: string;
|
|
2573
|
+
recommendation: string;
|
|
2574
|
+
line?: number | undefined;
|
|
2575
|
+
}, {
|
|
2576
|
+
symbol: string;
|
|
2577
|
+
scope: "deps" | "unused-exports" | "hardcoded" | "duplicates" | "deadcode";
|
|
2578
|
+
description: string;
|
|
2579
|
+
confidence: "high" | "medium" | "low";
|
|
2580
|
+
file: string;
|
|
2581
|
+
recommendation: string;
|
|
2582
|
+
line?: number | undefined;
|
|
2583
|
+
}>, "many">;
|
|
2584
|
+
type HostFindingInput = z.infer<typeof hostFindingSchema>;
|
|
2585
|
+
|
|
2586
|
+
interface RetryConfig {
|
|
2587
|
+
maxRetries: number;
|
|
2588
|
+
totalAttempts: number;
|
|
2589
|
+
toolTimeoutMs: number;
|
|
2590
|
+
onRetry?: (attempt: number, error: unknown, delayMs: number) => void;
|
|
2591
|
+
}
|
|
2592
|
+
interface AttemptResult<T> {
|
|
2593
|
+
result?: T;
|
|
2594
|
+
error?: Error;
|
|
2595
|
+
attempts: number;
|
|
2596
|
+
totalElapsedMs: number;
|
|
2597
|
+
}
|
|
2598
|
+
/**
|
|
2599
|
+
* Check if an error represents an HTTP 5xx or retryable network error.
|
|
2600
|
+
*/
|
|
2601
|
+
declare function isRetryable(error: unknown): boolean;
|
|
2602
|
+
/**
|
|
2603
|
+
* Check if an error represents an HTTP 429 rate limit.
|
|
2604
|
+
*/
|
|
2605
|
+
declare function isRateLimit(error: unknown): boolean;
|
|
2606
|
+
/**
|
|
2607
|
+
* Execute fn with canonical retry policy:
|
|
2608
|
+
* - totalAttempts <= 5 (absolute ceiling)
|
|
2609
|
+
* - 5xx -> retry (up to maxRetries)
|
|
2610
|
+
* - 429 -> wait-and-resume (parse Retry-After, clamp to 60s, progressive wait if missing)
|
|
2611
|
+
* - 4xx (except 429) -> fail immediately
|
|
2612
|
+
* - ETIMEDOUT, ECONNRESET, ECONNREFUSED -> retry
|
|
2613
|
+
* - Backoff: min(1000 * 2^retryCount, 30000) + random jitter [0, 1000]ms
|
|
2614
|
+
* - Timeout budget: if remaining < 5s, fail immediately
|
|
2615
|
+
*/
|
|
2616
|
+
declare function withCanonicalRetry<T>(fn: () => Promise<T>, config?: Partial<RetryConfig>): Promise<AttemptResult<T>>;
|
|
2617
|
+
|
|
2618
|
+
type DlpMode = 'strict' | 'open';
|
|
2619
|
+
interface DlpRedaction {
|
|
2620
|
+
stage: number;
|
|
2621
|
+
reasonCode: DlpReasonCode;
|
|
2622
|
+
original: string;
|
|
2623
|
+
replacement: string;
|
|
2624
|
+
}
|
|
2625
|
+
interface DlpAuditEntry {
|
|
2626
|
+
stage: number;
|
|
2627
|
+
action: string;
|
|
2628
|
+
detail: string;
|
|
2629
|
+
timestamp: string;
|
|
2630
|
+
}
|
|
2631
|
+
interface DlpResult {
|
|
2632
|
+
sanitized: string;
|
|
2633
|
+
redactions: DlpRedaction[];
|
|
2634
|
+
truncated: boolean;
|
|
2635
|
+
auditLog: DlpAuditEntry[];
|
|
2636
|
+
}
|
|
2637
|
+
interface DlpConfig {
|
|
2638
|
+
mode: DlpMode;
|
|
2639
|
+
maxInputBytes: number;
|
|
2640
|
+
maxProcessingMs: number;
|
|
2641
|
+
maxRegexOps: number;
|
|
2642
|
+
maxTokens: number;
|
|
2643
|
+
}
|
|
2644
|
+
declare const DEFAULT_DLP_CONFIG: DlpConfig;
|
|
2645
|
+
/**
|
|
2646
|
+
* Sanitize input through the 6-stage DLP pipeline.
|
|
2647
|
+
*
|
|
2648
|
+
* Stages:
|
|
2649
|
+
* 0: Decode — detect and skip base64/hex (budget-limited)
|
|
2650
|
+
* 1: Secrets — regex scan for common secret patterns
|
|
2651
|
+
* 2: Entropy — Shannon entropy check on long tokens (strict mode only)
|
|
2652
|
+
* 3: Paths — convert absolute paths to relative
|
|
2653
|
+
* 4: Context — truncate if exceeding token limit
|
|
2654
|
+
* 5: Audit — finalize audit log
|
|
2655
|
+
*
|
|
2656
|
+
* Risk-tiered defaults:
|
|
2657
|
+
* review/debate tools -> strict mode (external content)
|
|
2658
|
+
* memory/cost tools -> open mode (local data, skip stages 1-2)
|
|
2659
|
+
*/
|
|
2660
|
+
declare function sanitize(input: string, config?: Partial<DlpConfig>): DlpResult;
|
|
2661
|
+
|
|
2662
|
+
interface MuleProject {
|
|
2663
|
+
name: string;
|
|
2664
|
+
path: string;
|
|
2665
|
+
relativePath: string;
|
|
2666
|
+
muleVersion: string | null;
|
|
2667
|
+
runtimeEdition: 'CE' | 'EE' | 'unknown';
|
|
2668
|
+
hasMuleMavenPlugin: boolean;
|
|
2669
|
+
connectors: ConnectorInfo[];
|
|
2670
|
+
hasDataWeave: boolean;
|
|
2671
|
+
hasMunitTests: boolean;
|
|
2672
|
+
flowFiles: string[];
|
|
2673
|
+
dataweaveFiles: string[];
|
|
2674
|
+
propertiesFiles: string[];
|
|
2675
|
+
}
|
|
2676
|
+
interface ConnectorInfo {
|
|
2677
|
+
groupId: string;
|
|
2678
|
+
artifactId: string;
|
|
2679
|
+
version: string;
|
|
2680
|
+
type: string;
|
|
2681
|
+
}
|
|
2682
|
+
interface WorkspaceConfig {
|
|
2683
|
+
name?: string;
|
|
2684
|
+
projects?: Array<{
|
|
2685
|
+
path: string;
|
|
2686
|
+
name?: string;
|
|
2687
|
+
}>;
|
|
2688
|
+
shared?: {
|
|
2689
|
+
properties?: string;
|
|
2690
|
+
dataweave?: string;
|
|
2691
|
+
};
|
|
2692
|
+
ignore?: string[];
|
|
2693
|
+
}
|
|
2694
|
+
interface ProjectRegistry {
|
|
2695
|
+
workspaceRoot: string;
|
|
2696
|
+
projects: MuleProject[];
|
|
2697
|
+
discoveredAt: string;
|
|
2698
|
+
totalProjects: number;
|
|
2699
|
+
totalFlowFiles: number;
|
|
2700
|
+
totalDataweaveFiles: number;
|
|
2701
|
+
}
|
|
2702
|
+
declare class WorkspaceScanner {
|
|
2703
|
+
private workspaceRoot;
|
|
2704
|
+
private ignorePatterns;
|
|
2705
|
+
constructor(workspaceRoot: string, ignorePatterns?: string[]);
|
|
2706
|
+
scan(): ProjectRegistry;
|
|
2707
|
+
private discoverProjects;
|
|
2708
|
+
private scanDirectory;
|
|
2709
|
+
private analyzeMuleProject;
|
|
2710
|
+
private extractProjectName;
|
|
2711
|
+
private extractMuleVersion;
|
|
2712
|
+
private detectRuntimeEdition;
|
|
2713
|
+
private extractConnectors;
|
|
2714
|
+
private classifyConnector;
|
|
2715
|
+
private findFiles;
|
|
2716
|
+
private collectFiles;
|
|
2717
|
+
private shouldIgnore;
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
interface ProjectMetadata {
|
|
2721
|
+
projectName: string;
|
|
2722
|
+
projectPath: string;
|
|
2723
|
+
muleVersion: string | null;
|
|
2724
|
+
runtimeEdition: string;
|
|
2725
|
+
connectorCount: number;
|
|
2726
|
+
flowCount: number;
|
|
2727
|
+
dataweaveCount: number;
|
|
2728
|
+
hasMunitTests: boolean;
|
|
2729
|
+
}
|
|
2730
|
+
declare class ProjectContext {
|
|
2731
|
+
private project;
|
|
2732
|
+
constructor(project: MuleProject);
|
|
2733
|
+
getMetadata(): ProjectMetadata;
|
|
2734
|
+
getConnectorSummary(): string;
|
|
2735
|
+
toHandoffContext(): string;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
interface DataWeaveFinding {
|
|
2739
|
+
file: string;
|
|
2740
|
+
line: number;
|
|
2741
|
+
column: number;
|
|
2742
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
2743
|
+
rule: string;
|
|
2744
|
+
message: string;
|
|
2745
|
+
suggestion?: string;
|
|
2746
|
+
codeSnippet?: string;
|
|
2747
|
+
}
|
|
2748
|
+
interface DataWeaveReport {
|
|
2749
|
+
file: string;
|
|
2750
|
+
findings: DataWeaveFinding[];
|
|
2751
|
+
metrics: {
|
|
2752
|
+
lineCount: number;
|
|
2753
|
+
functionCount: number;
|
|
2754
|
+
complexityScore: number;
|
|
2755
|
+
hasNullSafetyIssues: boolean;
|
|
2756
|
+
hasHardcodedValues: boolean;
|
|
2757
|
+
};
|
|
2758
|
+
}
|
|
2759
|
+
declare class DataWeaveAnalyzer {
|
|
2760
|
+
analyze(filePath: string): DataWeaveReport;
|
|
2761
|
+
analyzeContent(filePath: string, content: string): DataWeaveReport;
|
|
2762
|
+
private checkNullSafety;
|
|
2763
|
+
private checkHardcodedValues;
|
|
2764
|
+
private checkPerformancePatterns;
|
|
2765
|
+
private checkErrorHandling;
|
|
2766
|
+
private checkTypeAnnotations;
|
|
2767
|
+
private countFunctions;
|
|
2768
|
+
private calculateComplexity;
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
interface FlowStep {
|
|
2772
|
+
type: string;
|
|
2773
|
+
name?: string;
|
|
2774
|
+
connectorType?: string;
|
|
2775
|
+
hasErrorHandler: boolean;
|
|
2776
|
+
children: FlowStep[];
|
|
2777
|
+
attributes: Record<string, string>;
|
|
2778
|
+
lineNumber: number;
|
|
2779
|
+
}
|
|
2780
|
+
interface FlowStructure {
|
|
2781
|
+
name: string;
|
|
2782
|
+
type: 'flow' | 'sub-flow' | 'error-handler';
|
|
2783
|
+
steps: FlowStep[];
|
|
2784
|
+
errorHandlers: FlowStep[];
|
|
2785
|
+
connectorRefs: string[];
|
|
2786
|
+
variableOps: string[];
|
|
2787
|
+
lineNumber: number;
|
|
2788
|
+
}
|
|
2789
|
+
interface FlowComplexity {
|
|
2790
|
+
file: string;
|
|
2791
|
+
flows: FlowStructure[];
|
|
2792
|
+
metrics: {
|
|
2793
|
+
totalFlows: number;
|
|
2794
|
+
totalSubFlows: number;
|
|
2795
|
+
totalSteps: number;
|
|
2796
|
+
maxNestingDepth: number;
|
|
2797
|
+
averageStepsPerFlow: number;
|
|
2798
|
+
errorHandlerCoverage: number;
|
|
2799
|
+
connectorDiversity: number;
|
|
2800
|
+
complexityScore: number;
|
|
2801
|
+
};
|
|
2802
|
+
findings: FlowFinding[];
|
|
2803
|
+
}
|
|
2804
|
+
interface FlowFinding {
|
|
2805
|
+
file: string;
|
|
2806
|
+
flowName: string;
|
|
2807
|
+
line: number;
|
|
2808
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
2809
|
+
rule: string;
|
|
2810
|
+
message: string;
|
|
2811
|
+
suggestion?: string;
|
|
2812
|
+
}
|
|
2813
|
+
declare class FlowParser {
|
|
2814
|
+
parse(filePath: string): FlowComplexity;
|
|
2815
|
+
parseContent(filePath: string, content: string): FlowComplexity;
|
|
2816
|
+
generateMermaid(complexity: FlowComplexity): string;
|
|
2817
|
+
private analyzeFlow;
|
|
2818
|
+
private calculateFlowComplexity;
|
|
2819
|
+
}
|
|
2820
|
+
|
|
2821
|
+
interface ConnectorFinding {
|
|
2822
|
+
project: string;
|
|
2823
|
+
connector: string;
|
|
2824
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
2825
|
+
rule: string;
|
|
2826
|
+
message: string;
|
|
2827
|
+
suggestion?: string;
|
|
2828
|
+
}
|
|
2829
|
+
interface ConnectorAuditResult {
|
|
2830
|
+
projects: string[];
|
|
2831
|
+
findings: ConnectorFinding[];
|
|
2832
|
+
versionMatrix: Map<string, Map<string, string>>;
|
|
2833
|
+
metrics: {
|
|
2834
|
+
totalConnectors: number;
|
|
2835
|
+
uniqueConnectors: number;
|
|
2836
|
+
versionConflicts: number;
|
|
2837
|
+
securityIssues: number;
|
|
2838
|
+
missingConfigs: number;
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
declare class ConnectorAuditor {
|
|
2842
|
+
audit(projects: MuleProject[]): ConnectorAuditResult;
|
|
2843
|
+
private checkConnectorConfigs;
|
|
2844
|
+
private checkSecuritySettings;
|
|
2845
|
+
private checkMissingTimeouts;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
interface ScenarioStep {
|
|
2849
|
+
name: string;
|
|
2850
|
+
flow?: string;
|
|
2851
|
+
input?: Record<string, unknown>;
|
|
2852
|
+
expectedOutput?: Record<string, unknown>;
|
|
2853
|
+
expectedStatus?: number;
|
|
2854
|
+
connectors?: string[];
|
|
2855
|
+
description?: string;
|
|
2856
|
+
}
|
|
2857
|
+
interface ScenarioDefinition {
|
|
2858
|
+
name: string;
|
|
2859
|
+
description: string;
|
|
2860
|
+
project?: string;
|
|
2861
|
+
steps: ScenarioStep[];
|
|
2862
|
+
dependencies?: string[];
|
|
2863
|
+
successCriteria?: string[];
|
|
2864
|
+
errorConditions?: string[];
|
|
2865
|
+
}
|
|
2866
|
+
type ValidationTier = 'spec-compliance' | 'documentation' | 'feasibility';
|
|
2867
|
+
interface TierResult {
|
|
2868
|
+
tier: ValidationTier;
|
|
2869
|
+
status: 'pass' | 'partial' | 'blocked';
|
|
2870
|
+
findings: TierFinding[];
|
|
2871
|
+
}
|
|
2872
|
+
interface TierFinding {
|
|
2873
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
2874
|
+
message: string;
|
|
2875
|
+
suggestion?: string;
|
|
2876
|
+
reference?: string;
|
|
2877
|
+
}
|
|
2878
|
+
interface ValidationResult {
|
|
2879
|
+
scenario: string;
|
|
2880
|
+
verdict: 'PASS' | 'PARTIAL' | 'BLOCKED';
|
|
2881
|
+
tiers: TierResult[];
|
|
2882
|
+
summary: string;
|
|
2883
|
+
actionItems: string[];
|
|
2884
|
+
}
|
|
2885
|
+
declare class ScenarioValidator {
|
|
2886
|
+
private projects;
|
|
2887
|
+
constructor(projects: MuleProject[]);
|
|
2888
|
+
validate(scenario: ScenarioDefinition): ValidationResult;
|
|
2889
|
+
validateTier(scenario: ScenarioDefinition, tier: ValidationTier): TierResult;
|
|
2890
|
+
private validateSpecCompliance;
|
|
2891
|
+
private validateDocumentationCoverage;
|
|
2892
|
+
private validateFeasibility;
|
|
2893
|
+
private findProject;
|
|
2894
|
+
private checkFlowExists;
|
|
2895
|
+
private calculateVerdict;
|
|
2896
|
+
private generateActionItems;
|
|
2897
|
+
private generateSummary;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
declare const VERSION = "0.2.14";
|
|
2901
|
+
|
|
2902
|
+
export { type ArtifactRecord, ArtifactStore, type ArtifactType, type AssembledContext, type AttemptResult, BINARY_SNIFF_BYTES, type BridgeCapabilities, type BridgeOptions, type BridgeResumeOptions, type BudgetConfig, type BuildPhase, type BuildRun, BuildStore, type BuildSummary, type BuiltInRole, CLEANUP_TIMEOUT_SEC, CONTEXT_ACTIVE, CONTEXT_BUFFER, CONTEXT_RETRIEVED, CURRENT_VERSION, type CacheEntry, CacheStore, type CallModelOptions, CancellationError, CancellationToken, type ChatMessage, type CleanupConfidence, type CleanupFinding, type CleanupReport, type CleanupScope, type CleanupSource, CliAdapter, type CliAdapterConfig, type CliBridge, type CliCallOptions, type CliDetectionResult, ConfigError, type ConnectorAuditResult, ConnectorAuditor, type ConnectorFinding, type ConnectorInfo, type ContextBudget, ContextBuilder, type ContextBuilderOptions, type CostInput, type CostLogEntry, CostStore, type CostSummary, CostTracker, type CostUpdateEvent, DAYS_PER_YEAR, DEFAULT_CONFIG, DEFAULT_DLP_CONFIG, DEFAULT_MAX_TOKENS, DEFAULT_RULES, DEFAULT_TIMEOUT_SEC, DLP_MAX_CONTENT, DLP_MAX_PROCESSING_MS, DataWeaveAnalyzer, type DataWeaveFinding, type DataWeaveReport, DatabaseError, type DebateConfig, type DebateEngineState, type DebateInput, type DebateMessageRow, type DebateOptions, type DebatePattern, type DebateResponse, type DebateResult, DebateStore, type DebateTurnRow, type DebateTurnStatus, type DlpAuditEntry, type DlpConfig, type DlpMode, DlpReasonCode, type DlpRedaction, type DlpResult, type EngineEvent, type EnqueueOptions, ErrorCode, EventBus, type ExecutionMode, type FallbackConfig, type FlowComplexity, type FlowFinding, FlowParser, type FlowStep, type FlowStructure, HTTP_TOO_MANY_REQUESTS, type HandoffCommand, type HandoffEnvelopeOptions, type HostFindingInput, IMPLEMENTER_MAX_TOKENS, type JobLogRecord, type JobRecord, type JobStatus, JobStore, type JobType, type LogLevel, type Logger, type LoopConfig, LoopController, type LoopIterationEvent, type LoopResult, MCP_CONTENT_MAX_LENGTH, MCP_TASK_MAX_LENGTH, MCP_TIMEOUT_MAX, type MemoryCategory, type MemoryConfig, type MemoryInput, type MemoryRecord, MemoryStore, type MessageStatus, MessageStore, type MeteringSource, type ModelAdapter, type ModelCallResult, type ModelConfig, ModelError, type ModelPricing, type ModelProvider, ModelRegistry, type MuleProject, Orchestrator, type OrchestratorOptions, type OutputConfig, type ParsedVerdict, type PlanInput, type PlanOptions, type PolicyContext, type PolicyDecision, type PolicyMode, type PolicyResult, type PolicyRule, type PresetName, type ProgressCallbacks, type ProjectConfig, type ProjectConfigInput, ProjectContext, type ProjectMetadata, type ProjectRegistry, type PromptType, type PromptVariables, REVIEW_DIFF_MAX_CHARS, REVIEW_PRESETS, REVIEW_TEXT_MAX_CHARS, type ResolvedStep, type ResolvedWorkflow, type ResultStatus, type RetryConfig, type RetryOptions, type ReviewInput, type ReviewOptions, type ReviewPreset, type ReviewResult, type Role, type RoleConfig, RoleManager, type RunOptions, type ScenarioDefinition, type ScenarioStep, ScenarioValidator, type Session, type SessionCompletedEvent, type SessionEvent, type SessionFailedEvent, SessionManager, type SessionResult, type SessionStartedEvent, type SessionStatus, SessionStore, type StepCompletedEvent, type StepDefinition, type StepFailedEvent, type StepResult, StepRunner, type StepStartedEvent, type StepType, TerminalReason, type TextDeltaEmitter, type TextDeltaEvent, type TextDoneEvent, type TierFinding, type TierResult, type TokenUsage, type TranscriptEntry, type UnifiedSession, VERSION, type ValidationResult, type ValidationTier, type VerdictResult, type WorkflowDefinition, WorkflowEngine, WorkflowError, type WorkspaceConfig, WorkspaceScanner, buildHandoffEnvelope, buildReconstructionPrompt, calculateCost, calculateDebateTokens, callModel, clearDetectionCache, computeThreeWayStats, computeTwoWayStats, costInputSchema, createIgnoreFilter, createLogger, debateInputSchema, debateOutputSchema, detectCli, estimateTokens, evaluatePolicy, generateId, generateSessionId, getModelPricing, getReviewPreset, getSchemaVersion, getTokenBudgetStatus, hashConfig, hashContent, hostFindingsSchema, isRateLimit, isRetryable, listPresetNames, listPresets, loadConfig, loadIgnorePatterns, loadPreset, memoryInputSchema, mergeThreeWay, mergeTwoWay, migrateConfig, openDatabase, parseDebateVerdict, parseVerdict, planInputSchema, preflightTokenCheck, projectConfigSchema, recalculateConfidenceStats, renderPrompt, reviewInputSchema, reviewOutputSchema, runAllScanners, runMigrations, sanitize, scanAntiPatterns, scanDeadCode, scanDuplicates, scanHardcoded, scanNearDuplicates, scanSecurity, scanUnusedDeps, scanUnusedExports, shouldIgnore, sleep, streamModel, validateConfig, withCanonicalRetry, withFallback, withRetry, writeConfig };
|