jev-planner 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +481 -2
- package/config.schema.json +264 -0
- package/dist/bin.cjs +19 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.mts +1 -0
- package/dist/bin.mjs +20 -0
- package/dist/index.cjs +12 -0
- package/dist/index.d.cts +566 -0
- package/dist/index.d.mts +566 -0
- package/dist/index.mjs +2 -0
- package/dist/jev-CIzG0Rhl.mjs +2685 -0
- package/dist/jev-aqxfEUdB.cjs +2756 -0
- package/llms.txt +206 -0
- package/package.json +77 -5
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import { TypeSafeClient } from "@typesafe-ai/sdk";
|
|
2
|
+
//#region ../core/dist/index.d.mts
|
|
3
|
+
//#region src/doctor/doctor.types.d.ts
|
|
4
|
+
interface CheckResult {
|
|
5
|
+
name: string;
|
|
6
|
+
ok: boolean;
|
|
7
|
+
detail: string;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/provider/provider.types.d.ts
|
|
11
|
+
type Env = Readonly<Record<string, string | undefined>>;
|
|
12
|
+
/** What the planner factory hands a provider when it builds an agent for a run. */
|
|
13
|
+
interface AgentSetup {
|
|
14
|
+
/**
|
|
15
|
+
* The agent's name in the run, for a provider used more than once:
|
|
16
|
+
* `--agents codex:sol` or the config's `agents.sol`. The provider's `id` otherwise.
|
|
17
|
+
*/
|
|
18
|
+
name?: string;
|
|
19
|
+
/** How prompts, stages and the judge refer to it. `agentLabel` otherwise. */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** A model from `--model <name>=<model>` or the config's `agents.<name>.model`; the provider's default otherwise. */
|
|
22
|
+
model?: string;
|
|
23
|
+
/** A reasoning effort from `--effort <name>=<level>` or the config; only for a provider whose `effort` is true. */
|
|
24
|
+
effort?: string;
|
|
25
|
+
/** Every provider's secret variables, and the judge's: never passed to an agent subprocess. */
|
|
26
|
+
omitEnv: readonly string[];
|
|
27
|
+
env: Env;
|
|
28
|
+
/** Replaces the global `fetch`; for tests. */
|
|
29
|
+
fetch?: typeof fetch;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* One AI the planner can plan with. Build one with `cliProvider` or
|
|
33
|
+
* `openAICompatibleProvider` and add it to `PROVIDERS` in `providers.ts`.
|
|
34
|
+
*/
|
|
35
|
+
interface Provider {
|
|
36
|
+
/**
|
|
37
|
+
* Lowercase, what `--agents` takes, and a key of the config's `agents`. An
|
|
38
|
+
* agent's name defaults to it; a second agent of the same provider is named
|
|
39
|
+
* (`--agents codex:sol,codex:terra`), and `--model` and `--finalizer` take
|
|
40
|
+
* the name.
|
|
41
|
+
*/
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly label: string;
|
|
44
|
+
/** `cli` agents read the repository themselves; `api` agents get a snapshot of it. */
|
|
45
|
+
readonly kind: 'cli' | 'api';
|
|
46
|
+
/** Variables holding this provider's credentials, stripped from every agent subprocess. */
|
|
47
|
+
readonly secretEnv: readonly string[];
|
|
48
|
+
/** Whether it takes a reasoning effort, from `--effort` or the config's `agents.<id>.effort`. */
|
|
49
|
+
readonly effort: boolean;
|
|
50
|
+
create(setup: AgentSetup): PlanningAgent;
|
|
51
|
+
/** Local checks only: `doctor` never makes a paid call. */
|
|
52
|
+
doctor(cwd: string, env: Env): Promise<CheckResult[]>;
|
|
53
|
+
}
|
|
54
|
+
interface CliProviderConfig {
|
|
55
|
+
id: string;
|
|
56
|
+
label: string;
|
|
57
|
+
command: string;
|
|
58
|
+
/**
|
|
59
|
+
* Arguments for one read-only, non-interactive run that reads the prompt on
|
|
60
|
+
* stdin and prints the answer on stdout. `model` and `effort` are the
|
|
61
|
+
* overrides for this run; each is set only when given, and wins over the
|
|
62
|
+
* CLI's own configuration.
|
|
63
|
+
*/
|
|
64
|
+
args: (overrides: {
|
|
65
|
+
model?: string;
|
|
66
|
+
effort?: string;
|
|
67
|
+
}) => string[];
|
|
68
|
+
/** Whether `args` passes an effort on, so `--effort` is accepted for it. */
|
|
69
|
+
effort?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* For a CLI whose `args` make it print its work as one JSON event per stdout
|
|
72
|
+
* line: what one event means. `progress` is shown while the agent works, and
|
|
73
|
+
* the last `result` any event gives is the answer. A line that is not JSON is
|
|
74
|
+
* shown as it is. Without `events`, stdout is the answer; either way, each
|
|
75
|
+
* stderr line is progress.
|
|
76
|
+
*/
|
|
77
|
+
events?: (event: unknown) => {
|
|
78
|
+
progress?: string;
|
|
79
|
+
result?: string;
|
|
80
|
+
session?: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* For a CLI that can keep a conversation and continue it in a later call:
|
|
84
|
+
* the arguments for each. Used when the request carries an `AgentSession`;
|
|
85
|
+
* `args` otherwise. Both keep the run read-only, like `args`.
|
|
86
|
+
*/
|
|
87
|
+
sessions?: {
|
|
88
|
+
/**
|
|
89
|
+
* The first call, keeping its conversation. `id` is a fresh UUID for a CLI
|
|
90
|
+
* that lets the caller name the session; a CLI that names its own reports
|
|
91
|
+
* the name as an event's `session`.
|
|
92
|
+
*/
|
|
93
|
+
start: (overrides: {
|
|
94
|
+
model?: string;
|
|
95
|
+
effort?: string;
|
|
96
|
+
}, id: string) => string[];
|
|
97
|
+
/** A later call, continuing the conversation `id`, with the prompt on stdin. */
|
|
98
|
+
resume: (overrides: {
|
|
99
|
+
model?: string;
|
|
100
|
+
effort?: string;
|
|
101
|
+
}, id: string) => string[];
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* How `doctor` checks the login: arguments to `command` that exit 0 when
|
|
105
|
+
* logged in, or a check of its own.
|
|
106
|
+
*/
|
|
107
|
+
auth?: readonly string[] | ((cwd: string) => Promise<CheckResult>);
|
|
108
|
+
}
|
|
109
|
+
interface OpenAICompatibleConfig {
|
|
110
|
+
id: string;
|
|
111
|
+
label: string;
|
|
112
|
+
/** Up to, not including, `/chat/completions`. */
|
|
113
|
+
baseUrl: string;
|
|
114
|
+
/** The variable holding the API key. */
|
|
115
|
+
apiKeyEnv: string;
|
|
116
|
+
/** The model used when neither `--model` nor the config sets one. */
|
|
117
|
+
model: string;
|
|
118
|
+
}
|
|
119
|
+
/** An agent's name in a run: its provider id (`codex`, `claude`, …) unless named (`sol`). */
|
|
120
|
+
type AgentName = string;
|
|
121
|
+
/**
|
|
122
|
+
* One agent's conversation, carried from one stage of a run to the next. The
|
|
123
|
+
* planner creates one per agent per run and passes it on every call to that
|
|
124
|
+
* agent; the provider fills it in on the first call and continues from it on
|
|
125
|
+
* the next ones. An agent that ignores it starts every call afresh.
|
|
126
|
+
*/
|
|
127
|
+
interface AgentSession {
|
|
128
|
+
/** The conversation to continue, once a call has started one: a CLI's session or thread id. */
|
|
129
|
+
id?: string;
|
|
130
|
+
}
|
|
131
|
+
interface AgentRequest {
|
|
132
|
+
/** The whole prompt, for an agent that starts afresh. */
|
|
133
|
+
prompt: string;
|
|
134
|
+
/**
|
|
135
|
+
* The same request for an agent continuing `session`, which already holds
|
|
136
|
+
* the task and its own earlier plans: `prompt` without them. `prompt` is used
|
|
137
|
+
* when this is absent or the conversation cannot be continued.
|
|
138
|
+
*/
|
|
139
|
+
resumePrompt?: string;
|
|
140
|
+
/** Continue this conversation, when the agent can; see `AgentSession`. */
|
|
141
|
+
session?: AgentSession;
|
|
142
|
+
/**
|
|
143
|
+
* A reasoning effort for this call only, over the one the agent was created
|
|
144
|
+
* with. An agent that takes no effort ignores it.
|
|
145
|
+
*/
|
|
146
|
+
effort?: string;
|
|
147
|
+
cwd: string;
|
|
148
|
+
timeoutMs: number;
|
|
149
|
+
/** Called with a line about the agent's work as it happens: a message, a command, a file read. */
|
|
150
|
+
onProgress?: (line: string) => void;
|
|
151
|
+
/** Aborted when the run no longer needs this answer, so the agent stops working and stops billing. */
|
|
152
|
+
signal?: AbortSignal;
|
|
153
|
+
}
|
|
154
|
+
interface PlanningAgent {
|
|
155
|
+
/**
|
|
156
|
+
* Unique in a run: what `--finalizer`, the judge's verdict, objection ids and the
|
|
157
|
+
* rounds files use. Its provider id, unless named (`--agents codex:sol`).
|
|
158
|
+
*/
|
|
159
|
+
readonly name: AgentName;
|
|
160
|
+
/**
|
|
161
|
+
* How prompts, stages, the plan and the judge refer to it: `Codex`, `DeepSeek`, or
|
|
162
|
+
* `Codex (sol)` for a named one. Keep labels unique too: the judge tells plans
|
|
163
|
+
* apart by label.
|
|
164
|
+
*/
|
|
165
|
+
readonly label: string;
|
|
166
|
+
/**
|
|
167
|
+
* Whether the agent opens files in the repository itself, as an agent CLI
|
|
168
|
+
* does. Only such agents check disputed claims in `debate` review; an agent
|
|
169
|
+
* that leaves this out is treated as one that does not.
|
|
170
|
+
*/
|
|
171
|
+
readonly readsRepository?: boolean;
|
|
172
|
+
generate(request: AgentRequest): Promise<string>;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/debate/debate.types.d.ts
|
|
176
|
+
/** One objection a critic raised against another agent's plan, in `debate` review. */
|
|
177
|
+
interface Objection {
|
|
178
|
+
/** `<critic>:<target>:C<n>`, unique in a run: what the author's reply answers. */
|
|
179
|
+
id: string;
|
|
180
|
+
critic: AgentName;
|
|
181
|
+
/** The agent whose plan the objection is about. */
|
|
182
|
+
target: AgentName;
|
|
183
|
+
claim: string;
|
|
184
|
+
/** The critic's reason, or `''` when it gave none. */
|
|
185
|
+
why: string;
|
|
186
|
+
/** Whether the claim is about a file, symbol or export in the repository, and so can be checked. */
|
|
187
|
+
repo: boolean;
|
|
188
|
+
}
|
|
189
|
+
/** An author's answer to one objection against its plan. */
|
|
190
|
+
interface Reply {
|
|
191
|
+
/** The `Objection.id` it answers. */
|
|
192
|
+
id: string;
|
|
193
|
+
author: AgentName;
|
|
194
|
+
decision: 'accept' | 'reject';
|
|
195
|
+
reason: string;
|
|
196
|
+
}
|
|
197
|
+
/** What an agent that reads the repository found when it checked a disputed claim. */
|
|
198
|
+
interface ClaimCheck {
|
|
199
|
+
checker: AgentName;
|
|
200
|
+
/** `unknown` also stands for an answer that could not be parsed, or a checker that was dropped. */
|
|
201
|
+
result: 'confirm' | 'refute' | 'unknown';
|
|
202
|
+
/** Where the checker looked, such as `src/jev.ts:agentOptions`; `''` when it said nothing. */
|
|
203
|
+
evidence: string;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* An objection its author rejected, for the judge to rule on. The same claim from
|
|
207
|
+
* several critics against the same plan is one dispute.
|
|
208
|
+
*/
|
|
209
|
+
interface Dispute {
|
|
210
|
+
/** `D1`, `D2`, …, in the order the disputes are ranked. */
|
|
211
|
+
id: string;
|
|
212
|
+
/** The author, whose plan the claim is about. */
|
|
213
|
+
target: AgentName;
|
|
214
|
+
/** Every critic who raised it, in the order they raised it. */
|
|
215
|
+
critics: AgentName[];
|
|
216
|
+
/** The ids of the objections it merges. */
|
|
217
|
+
objections: string[];
|
|
218
|
+
claim: string;
|
|
219
|
+
/** The critics' reasons, those that gave one. */
|
|
220
|
+
reasons: string[];
|
|
221
|
+
/** The author's reasons for rejecting it. */
|
|
222
|
+
rejections: string[];
|
|
223
|
+
repo: boolean;
|
|
224
|
+
/** Present once a claim check ran on it. */
|
|
225
|
+
check?: ClaimCheck;
|
|
226
|
+
}
|
|
227
|
+
/** The judge's ruling on one dispute. */
|
|
228
|
+
interface DisputeRuling {
|
|
229
|
+
/** The `Dispute.id` it rules on. */
|
|
230
|
+
id: string;
|
|
231
|
+
/** Whose position holds; `unclear` when the material does not settle it. */
|
|
232
|
+
choice: 'critic' | 'author' | 'unclear';
|
|
233
|
+
confidence: number;
|
|
234
|
+
}
|
|
235
|
+
/** The debate behind a round, in `debate` review; see `PlanRound.debate`. */
|
|
236
|
+
interface RoundDebate {
|
|
237
|
+
/** Every objection the critics raised, as parsed. */
|
|
238
|
+
objections: Objection[];
|
|
239
|
+
/** Every reply the authors gave that answers an objection, first reply per objection. */
|
|
240
|
+
replies?: Reply[];
|
|
241
|
+
/** The ids of objections that got no parseable reply, including those to a dropped author. */
|
|
242
|
+
unanswered?: string[];
|
|
243
|
+
/** The rejected objections the judge rules on: at most eight, ranked. */
|
|
244
|
+
disputes?: Dispute[];
|
|
245
|
+
/** Rejected objections past the cap, which the judge did not rule on. */
|
|
246
|
+
overflow?: Dispute[];
|
|
247
|
+
/** Whether claim checks ran, when they were asked for. */
|
|
248
|
+
claimChecks?: 'ran' | 'skipped';
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/questions/questions.types.d.ts
|
|
252
|
+
type JudgeStage = 'solo' | 'draft' | 'review';
|
|
253
|
+
/** The judge's answer on one set of plans. Every confidence and probability is from 0 to 1, every score from 0 to 3. */
|
|
254
|
+
interface Verdict {
|
|
255
|
+
/** An agent's name, or `'tie'`. */
|
|
256
|
+
strongerPlan: string;
|
|
257
|
+
strongerPlanConfidence: number;
|
|
258
|
+
finalizer: AgentName;
|
|
259
|
+
finalizerConfidence: number;
|
|
260
|
+
completeness: number;
|
|
261
|
+
completenessConfidence: number;
|
|
262
|
+
feasibility: number;
|
|
263
|
+
feasibilityConfidence: number;
|
|
264
|
+
riskCoverage: number;
|
|
265
|
+
riskCoverageConfidence: number;
|
|
266
|
+
needsAnotherPassProbability: number;
|
|
267
|
+
/**
|
|
268
|
+
* How likely the strongest plan is already a final plan on its own. In `balanced`
|
|
269
|
+
* mode a cross-reviewed run above the threshold is answered with that plan
|
|
270
|
+
* rather than a synthesis call.
|
|
271
|
+
*/
|
|
272
|
+
standsAloneProbability: number;
|
|
273
|
+
/** The judge's ruling on each dispute it was given, in `debate` review; absent when it was given none. */
|
|
274
|
+
disputes?: DisputeRuling[];
|
|
275
|
+
model: string;
|
|
276
|
+
}
|
|
277
|
+
/** One plan, for the judge: the agent that wrote it and the text. */
|
|
278
|
+
interface JudgedPlan {
|
|
279
|
+
agent: AgentName;
|
|
280
|
+
label: string;
|
|
281
|
+
plan: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* What rates a run's plans and routes it: which plan is stronger, who merges,
|
|
285
|
+
* whether another pass would help, and the rulings on a debate's disputes.
|
|
286
|
+
* The planner never calls a model for this itself; `TypeSafeJevJudge` in
|
|
287
|
+
* `jev-planner` is one judge.
|
|
288
|
+
*/
|
|
289
|
+
interface PlanJudge {
|
|
290
|
+
/** How the run's stage messages refer to the judge: `Jev`. */
|
|
291
|
+
readonly name: string;
|
|
292
|
+
judge(input: {
|
|
293
|
+
task: string;
|
|
294
|
+
plans: readonly JudgedPlan[];
|
|
295
|
+
/**
|
|
296
|
+
* `draft` for the independent drafts, `review` for plans that have been
|
|
297
|
+
* cross-reviewed, and `solo` for one draft judged alone in `fast` mode.
|
|
298
|
+
* A `solo` verdict's `strongerPlan` and `finalizer` can only name that
|
|
299
|
+
* agent or `tie`, and the planner ignores both.
|
|
300
|
+
*/
|
|
301
|
+
stage: 'solo' | 'draft' | 'review';
|
|
302
|
+
/** In `debate` review, the rejected objections to rule on alongside the plans. */
|
|
303
|
+
disputes?: readonly Dispute[];
|
|
304
|
+
/** `PlanOptions.judgeModel`, when the run set one. */
|
|
305
|
+
model?: string;
|
|
306
|
+
}): Promise<Verdict>;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/orchestrator/orchestrator.types.d.ts
|
|
310
|
+
/**
|
|
311
|
+
* How much work a run spends before it answers.
|
|
312
|
+
*
|
|
313
|
+
* - `fast` answers with the first draft the judge rates 0.5 or more to stand alone,
|
|
314
|
+
* and stops the agents still drafting. That plan is one agent's, which no
|
|
315
|
+
* other agent has seen, and the quickest agent's draft is judged first, so it
|
|
316
|
+
* has the first chance. When the judge accepts no draft, the drafts are merged with
|
|
317
|
+
* no cross-review. It never cross-reviews.
|
|
318
|
+
* - `balanced` lets the judge cut the run short: it judges the drafts first and orders a
|
|
319
|
+
* cross-review only when one would help, adopts a cross-reviewed plan that
|
|
320
|
+
* already stands alone instead of paying for a merge, and stops waiting on a
|
|
321
|
+
* straggling agent once the round has enough plans.
|
|
322
|
+
* - `ultra` always runs the first cross-review, a second when the judge asks for it,
|
|
323
|
+
* and then merges, unless `selectStronger` keeps the reviewed plan the judge rates
|
|
324
|
+
* stronger: 2N + 1 agent calls in three sequential rounds, or 3N + 1 in four.
|
|
325
|
+
*/
|
|
326
|
+
type PlanMode = 'fast' | 'balanced' | 'ultra';
|
|
327
|
+
/**
|
|
328
|
+
* How the agents review each other once the judge orders a cross-review.
|
|
329
|
+
*
|
|
330
|
+
* - `standard` has each agent read every other plan and return a revised one.
|
|
331
|
+
* - `debate` (experimental) turns the first cross-review into an argument: each
|
|
332
|
+
* agent lists its objections to every other plan, each author accepts or
|
|
333
|
+
* rejects the objections it received and revises its plan, and the judge rules on
|
|
334
|
+
* every objection an author rejected. A second pass, when the judge asks for one,
|
|
335
|
+
* is aimed at the disagreements the judge's rulings left open.
|
|
336
|
+
*/
|
|
337
|
+
type ReviewMode = 'standard' | 'debate';
|
|
338
|
+
interface PlanOptions {
|
|
339
|
+
task: string;
|
|
340
|
+
cwd: string;
|
|
341
|
+
timeoutMs: number;
|
|
342
|
+
/**
|
|
343
|
+
* `balanced` (the default) lets the judge skip work a run does not need; `ultra`
|
|
344
|
+
* never skips; `fast` answers with the first draft the judge accepts. See `PlanMode`.
|
|
345
|
+
*/
|
|
346
|
+
mode?: PlanMode;
|
|
347
|
+
/** Cross-review rounds a run may spend; `balanced` runs only the ones the judge asks for, `fast` none. */
|
|
348
|
+
maxReviewRounds?: 0 | 1 | 2;
|
|
349
|
+
/** `standard` (the default) or `debate`; see `ReviewMode`. */
|
|
350
|
+
reviewMode?: ReviewMode;
|
|
351
|
+
/**
|
|
352
|
+
* In `debate` review, have an agent that reads the repository check each
|
|
353
|
+
* disputed claim about it before the judge rules. Needs two or more such agents;
|
|
354
|
+
* with fewer, the checks are skipped and the run says so. `false` by default.
|
|
355
|
+
* Neither this nor `reviewMode: 'debate'` is allowed in `fast` mode, which has no review.
|
|
356
|
+
*/
|
|
357
|
+
claimChecks?: boolean;
|
|
358
|
+
/**
|
|
359
|
+
* How long a round waits for the agents still working once enough of them
|
|
360
|
+
* have answered, in `balanced` and `fast` mode. `0` waits for every agent, as `ultra` always
|
|
361
|
+
* does. A dropped agent's call is aborted, and a round never falls below two
|
|
362
|
+
* plans, so nothing is dropped that the round still needs.
|
|
363
|
+
*/
|
|
364
|
+
stragglerGraceMs?: number;
|
|
365
|
+
/** The model the judge should use, passed to it as `model`; what that names is up to the judge. */
|
|
366
|
+
judgeModel?: string;
|
|
367
|
+
/**
|
|
368
|
+
* Override the judge's choice; must be the name of one of the planner's agents.
|
|
369
|
+
* In `fast` mode it only chooses who merges when the judge accepts no draft.
|
|
370
|
+
*/
|
|
371
|
+
finalizer?: AgentName;
|
|
372
|
+
/**
|
|
373
|
+
* Skip the placeholder check `plan` runs before any agent call. An empty
|
|
374
|
+
* task is still passed through unchecked, as before the check existed.
|
|
375
|
+
*/
|
|
376
|
+
allowAnyTask?: boolean;
|
|
377
|
+
/**
|
|
378
|
+
* Skip the synthesis when the judge rates one cross-reviewed plan stronger, and
|
|
379
|
+
* return that plan as it is, whatever `standsAloneProbability` says. Saves
|
|
380
|
+
* the last agent call at some cost in quality. On a tie, or when no
|
|
381
|
+
* cross-review ran, the finalizer still merges the plans. `false` by default.
|
|
382
|
+
* Ignored in `fast` mode, which never cross-reviews.
|
|
383
|
+
*/
|
|
384
|
+
selectStronger?: boolean;
|
|
385
|
+
/**
|
|
386
|
+
* A reasoning effort for the cross-review and synthesis calls, by agent name:
|
|
387
|
+
* lower effort where the job is editing a plan rather than exploring. An
|
|
388
|
+
* agent not listed uses the effort it was created with in every stage.
|
|
389
|
+
*/
|
|
390
|
+
reviewEfforts?: Readonly<Record<AgentName, string>>;
|
|
391
|
+
/**
|
|
392
|
+
* Keep each agent's conversation from its draft to its later calls, so the
|
|
393
|
+
* cross-review and synthesis continue with what it already read. `true` by
|
|
394
|
+
* default; `false` starts every call afresh.
|
|
395
|
+
*/
|
|
396
|
+
resume?: boolean;
|
|
397
|
+
onStage?: (message: string) => void;
|
|
398
|
+
/** Called with each agent's progress lines while it works, as `AgentRequest.onProgress` gets them. */
|
|
399
|
+
onAgentProgress?: (agent: AgentName, line: string) => void;
|
|
400
|
+
/**
|
|
401
|
+
* Called with every round's plans as soon as the round ends, and awaited:
|
|
402
|
+
* a rejection stops the run. Rounds are numbered from 1 — the drafts, then
|
|
403
|
+
* each cross-review — and the final plan comes last.
|
|
404
|
+
*/
|
|
405
|
+
onRound?: (round: PlanRound) => void | Promise<void>;
|
|
406
|
+
}
|
|
407
|
+
/** One round of a run, as `PlanOptions.onRound` sees it. */
|
|
408
|
+
interface PlanRound {
|
|
409
|
+
/** 1 for the drafts, 2 and up for the cross-reviews; one more for the final plan. */
|
|
410
|
+
round: number;
|
|
411
|
+
/**
|
|
412
|
+
* `draft`, `review` and `final` in every run. A `debate` review adds
|
|
413
|
+
* `critique`, whose `plans` are the drafts unchanged, and then `review`; with
|
|
414
|
+
* claim checks, `reply` (the revised plans, not yet judged) and `check` (the
|
|
415
|
+
* same plans, judged) take the place of that `review`.
|
|
416
|
+
*/
|
|
417
|
+
stage: 'draft' | 'critique' | 'reply' | 'check' | 'review' | 'final';
|
|
418
|
+
/** Each agent's plan in this round, by agent name; for `final`, the plan the run answers with. */
|
|
419
|
+
plans: Record<AgentName, string>;
|
|
420
|
+
/** In a `debate` review, each agent's raw answer in this round: its critique, reply or check. */
|
|
421
|
+
artifacts?: Record<AgentName, string>;
|
|
422
|
+
/** In a `debate` review, what the round's answers said, parsed. */
|
|
423
|
+
debate?: RoundDebate;
|
|
424
|
+
/** The judge's verdict on this round's plans, and the one the final plan followed. */
|
|
425
|
+
verdict?: Verdict;
|
|
426
|
+
/** How long the round took. */
|
|
427
|
+
timings: RoundTimings;
|
|
428
|
+
/**
|
|
429
|
+
* On the `final` round: the plan is one agent's own, adopted whole rather
|
|
430
|
+
* than merged. A `fast` run that accepts a draft still reports `draft`, then
|
|
431
|
+
* `final`.
|
|
432
|
+
*/
|
|
433
|
+
selected?: true;
|
|
434
|
+
}
|
|
435
|
+
/** How long one round of a run took, in milliseconds. */
|
|
436
|
+
interface RoundTimings {
|
|
437
|
+
/** The whole round: its agent calls, then the judge when it judged the round. */
|
|
438
|
+
totalMs: number;
|
|
439
|
+
/** Each agent call in the round that answered, by agent name; a dropped straggler has none. */
|
|
440
|
+
agents: Record<AgentName, number>;
|
|
441
|
+
/** The judge's call on the round's plans; in `fast` mode, every solo judgement in the round, added up. */
|
|
442
|
+
judgeMs?: number;
|
|
443
|
+
}
|
|
444
|
+
/** How long a whole run took, in milliseconds. */
|
|
445
|
+
interface RunTimings {
|
|
446
|
+
totalMs: number;
|
|
447
|
+
/** One entry per round, in the order `onRound` receives them. */
|
|
448
|
+
rounds: (RoundTimings & Pick<PlanRound, 'round' | 'stage'>)[];
|
|
449
|
+
}
|
|
450
|
+
interface PlanResult {
|
|
451
|
+
plan: string;
|
|
452
|
+
verdict: Verdict;
|
|
453
|
+
/** The agent that merged the plans, or whose plan was adopted whole. */
|
|
454
|
+
finalizer: AgentName;
|
|
455
|
+
/**
|
|
456
|
+
* The plan is `finalizer`'s own plan, adopted whole rather than merged: in
|
|
457
|
+
* `balanced` mode when the judge judged it final as it stands, in `fast` mode when
|
|
458
|
+
* the judge accepted it as it arrived, or by `selectStronger`.
|
|
459
|
+
*/
|
|
460
|
+
selected?: true;
|
|
461
|
+
/** Each agent's last plan, by agent name; in `fast` mode, only the drafts that arrived. */
|
|
462
|
+
drafts: Record<AgentName, string>;
|
|
463
|
+
/** The debate, in `debate` review once one ran: its objections, replies, disputes and checks. */
|
|
464
|
+
debate?: RoundDebate;
|
|
465
|
+
timings: RunTimings;
|
|
466
|
+
/** What the run actually cost, for reporting and for tuning the next one. */
|
|
467
|
+
cost: PlanCost;
|
|
468
|
+
}
|
|
469
|
+
/** What a finished run spent, and where it stopped short. */
|
|
470
|
+
interface PlanCost {
|
|
471
|
+
mode: PlanMode;
|
|
472
|
+
reviewMode: ReviewMode;
|
|
473
|
+
/** Cross-review rounds run: `0` when the judge found the drafts ready as they were. */
|
|
474
|
+
reviewRounds: number;
|
|
475
|
+
/** Whether a synthesis call merged the plans, or one plan was adopted whole. */
|
|
476
|
+
synthesized: boolean;
|
|
477
|
+
/** Agent calls made, the synthesis included. */
|
|
478
|
+
agentCalls: number;
|
|
479
|
+
/** The judge evaluations made: one per judged round, and in `fast` mode one per draft judged alone. */
|
|
480
|
+
judgeCalls: number;
|
|
481
|
+
/**
|
|
482
|
+
* Agents a round stopped waiting for, in the order they were dropped; in
|
|
483
|
+
* `fast` mode, also the agents stopped once a draft was accepted.
|
|
484
|
+
*/
|
|
485
|
+
dropped: AgentName[];
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Each provider's own checks, in order. No paid call. The CLI adds a check for
|
|
489
|
+
* each variable its judge reads (`PlannerProgram.judgeEnv`).
|
|
490
|
+
*/
|
|
491
|
+
export declare function runDoctor(cwd: string, providers: readonly Provider[], env?: Readonly<Record<string, string | undefined>>): Promise<CheckResult[]>;
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/orchestrator/orchestrator.d.ts
|
|
494
|
+
/** What a `balanced` round waits for a straggler once enough agents have answered. */
|
|
495
|
+
export declare const DEFAULT_STRAGGLER_GRACE_MS = 90000;
|
|
496
|
+
export declare class Planner {
|
|
497
|
+
private readonly judge;
|
|
498
|
+
private readonly agents;
|
|
499
|
+
/** Two or more agents with distinct names; each drafts, revises, and may finalize. */
|
|
500
|
+
constructor(agents: readonly PlanningAgent[], judge: PlanJudge);
|
|
501
|
+
plan(options: PlanOptions): Promise<PlanResult>;
|
|
502
|
+
}
|
|
503
|
+
//#endregion
|
|
504
|
+
//#region src/process/process.types.d.ts
|
|
505
|
+
interface ProcessResult {
|
|
506
|
+
stdout: string;
|
|
507
|
+
stderr: string;
|
|
508
|
+
exitCode: number;
|
|
509
|
+
}
|
|
510
|
+
//#endregion
|
|
511
|
+
//#region src/process/process.d.ts
|
|
512
|
+
export declare class ProcessError extends Error {
|
|
513
|
+
readonly command: string;
|
|
514
|
+
readonly exitCode: number | null;
|
|
515
|
+
readonly stderr: string;
|
|
516
|
+
constructor(command: string, exitCode: number | null, stderr: string);
|
|
517
|
+
}
|
|
518
|
+
//#endregion
|
|
519
|
+
//#region src/provider/provider.d.ts
|
|
520
|
+
/** An agent CLI installed and logged in on this machine, run read-only in the repository. */
|
|
521
|
+
export declare function cliProvider(config: CliProviderConfig): Provider;
|
|
522
|
+
/**
|
|
523
|
+
* A chat API that speaks OpenAI's `/chat/completions`, as DeepSeek, Moonshot,
|
|
524
|
+
* Z.ai and most others do. It cannot read the repository, so each prompt is
|
|
525
|
+
* sent with a snapshot of it: the tracked file list and the top-level docs and
|
|
526
|
+
* manifests (see `repoSnapshot`). Given an `AgentSession`, it keeps the
|
|
527
|
+
* conversation and sends it back on the next call, so the snapshot is sent once
|
|
528
|
+
* and later prompts can leave out what the conversation already holds.
|
|
529
|
+
*/
|
|
530
|
+
export declare function openAICompatibleProvider(config: OpenAICompatibleConfig): Provider;
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/providers/providers.d.ts
|
|
533
|
+
/**
|
|
534
|
+
* Every AI the planner can plan with. To add one, add an entry here, and the
|
|
535
|
+
* agent to `config.schema.json` and its copy in `apps/docs/public/`, which a
|
|
536
|
+
* test keeps in step: the CLI, `doctor`, `--help`, the config, the prompts and
|
|
537
|
+
* the judge all read this list. An OpenAI-compatible chat API is one
|
|
538
|
+
* `openAICompatibleProvider` call; an agent CLI that can run read-only is one
|
|
539
|
+
* `cliProvider` call.
|
|
540
|
+
*/
|
|
541
|
+
export declare const PROVIDERS: readonly Provider[];
|
|
542
|
+
/** The agents a run uses without `--agents`. */
|
|
543
|
+
export declare const DEFAULT_AGENTS: string[];
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region src/task/task.d.ts
|
|
546
|
+
/** Thrown before any agent call when the task is empty or a placeholder. */
|
|
547
|
+
export declare class TaskValidationError extends Error {
|
|
548
|
+
name: string;
|
|
549
|
+
}
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region src/jev/jev.d.ts
|
|
552
|
+
/** TypeSafe Jev, asked the planner's questions in one `systemOne` call per judged round. */
|
|
553
|
+
export declare class TypeSafeJevJudge implements PlanJudge {
|
|
554
|
+
private readonly client;
|
|
555
|
+
readonly name = "Jev";
|
|
556
|
+
constructor(client?: TypeSafeClient);
|
|
557
|
+
judge(input: {
|
|
558
|
+
task: string;
|
|
559
|
+
plans: readonly JudgedPlan[];
|
|
560
|
+
stage: JudgeStage;
|
|
561
|
+
disputes?: readonly Dispute[];
|
|
562
|
+
model?: string;
|
|
563
|
+
}): Promise<Verdict>;
|
|
564
|
+
}
|
|
565
|
+
//#endregion
|
|
566
|
+
export type { AgentName, AgentRequest, AgentSession, AgentSetup, CheckResult, ClaimCheck, CliProviderConfig, Dispute, DisputeRuling, JudgedPlan, Objection, OpenAICompatibleConfig, PlanCost, PlanJudge, PlanMode, PlanOptions, PlanResult, PlanRound, PlanningAgent, ProcessResult, Provider, Reply, ReviewMode, RoundDebate, RoundTimings, RunTimings, Verdict };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as Planner, c as cliProvider, f as runDoctor, i as PROVIDERS, n as DEFAULT_AGENTS, o as ProcessError, r as DEFAULT_STRAGGLER_GRACE_MS, s as TaskValidationError, t as TypeSafeJevJudge, u as openAICompatibleProvider } from "./jev-CIzG0Rhl.mjs";
|
|
2
|
+
export { DEFAULT_AGENTS, DEFAULT_STRAGGLER_GRACE_MS, PROVIDERS, Planner, ProcessError, TaskValidationError, TypeSafeJevJudge, cliProvider, openAICompatibleProvider, runDoctor };
|