@ci-kit/roundtable 0.0.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/example.mjs +194 -0
- package/dist/cli.mjs +71 -13
- package/dist/index.d.mts +270 -18
- package/dist/index.d.ts +270 -18
- package/dist/index.mjs +1830 -10
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,240 @@
|
|
|
1
|
+
import { text } from '@ci-kit/ai';
|
|
2
|
+
|
|
3
|
+
type Sees = 'all' | 'none' | 'lead-only' | string[];
|
|
4
|
+
type Fallback = 'skip' | 'retry' | 'abort';
|
|
5
|
+
type SeatOutput = 'text' | 'json' | 'markdown';
|
|
6
|
+
interface SeatIdentity {
|
|
7
|
+
name: string;
|
|
8
|
+
avatar?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
background?: string;
|
|
11
|
+
}
|
|
12
|
+
interface SeatPersona {
|
|
13
|
+
/** Decision tendency. Kept apart from expression so verdicts stay reproducible. */
|
|
14
|
+
stance?: string;
|
|
15
|
+
personality: string[];
|
|
16
|
+
style?: string;
|
|
17
|
+
speech?: string;
|
|
18
|
+
values?: string;
|
|
19
|
+
quirks?: string;
|
|
20
|
+
avoid?: string;
|
|
21
|
+
}
|
|
22
|
+
interface SeatPowers {
|
|
23
|
+
/** Phase ids this seat attends; empty means every phase. */
|
|
24
|
+
phase: string[];
|
|
25
|
+
sees: Sees;
|
|
26
|
+
canPropose: boolean;
|
|
27
|
+
canVeto: boolean;
|
|
28
|
+
lead: boolean;
|
|
29
|
+
weight: number;
|
|
30
|
+
priority: number;
|
|
31
|
+
budget?: number;
|
|
32
|
+
fallback: Fallback;
|
|
33
|
+
output: SeatOutput;
|
|
34
|
+
model?: string;
|
|
35
|
+
temperature?: number;
|
|
36
|
+
maxTokens?: number;
|
|
37
|
+
}
|
|
38
|
+
interface Seat {
|
|
39
|
+
id: string;
|
|
40
|
+
role: string;
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
identity: SeatIdentity;
|
|
43
|
+
persona: SeatPersona;
|
|
44
|
+
seat: SeatPowers;
|
|
45
|
+
/** Markdown body, used verbatim as the seat's instructions. */
|
|
46
|
+
body: string;
|
|
47
|
+
/** File the seat came from, for error messages only. */
|
|
48
|
+
source: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type PhaseMode = 'serial' | 'parallel';
|
|
52
|
+
type OnVeto = 're-propose' | 'revise' | 'abort';
|
|
53
|
+
interface Phase {
|
|
54
|
+
id: string;
|
|
55
|
+
/** Seats named here; empty means "derive from every seat's seat.phase". */
|
|
56
|
+
seats: string[];
|
|
57
|
+
vetoable: boolean;
|
|
58
|
+
requires: string[];
|
|
59
|
+
mode: PhaseMode;
|
|
60
|
+
}
|
|
61
|
+
interface Budget {
|
|
62
|
+
total?: number;
|
|
63
|
+
perSeat?: number;
|
|
64
|
+
}
|
|
65
|
+
interface Table {
|
|
66
|
+
title: string;
|
|
67
|
+
schedule?: string;
|
|
68
|
+
budget: Budget;
|
|
69
|
+
onVeto: OnVeto;
|
|
70
|
+
maxAttempts: number;
|
|
71
|
+
threshold: number;
|
|
72
|
+
/**
|
|
73
|
+
* How long one seat's model call may take. Undefined keeps the http
|
|
74
|
+
* package's default.
|
|
75
|
+
*
|
|
76
|
+
* A seat reads a whole article and replies with paragraphs, which routinely
|
|
77
|
+
* needs more than the transport default meant for short requests. The table
|
|
78
|
+
* owns this because "how long may a seat think" is a property of the review,
|
|
79
|
+
* not of the provider.
|
|
80
|
+
*/
|
|
81
|
+
timeoutMs?: number;
|
|
82
|
+
phases: Phase[];
|
|
83
|
+
/** Phase ids given the special roles, resolved during validation. */
|
|
84
|
+
special: {
|
|
85
|
+
propose: string;
|
|
86
|
+
converge: string;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
declare class RoundtableConfigError extends Error {
|
|
91
|
+
constructor(message: string);
|
|
92
|
+
}
|
|
93
|
+
interface LoadedRoundtable {
|
|
94
|
+
table: Table;
|
|
95
|
+
seats: Seat[];
|
|
96
|
+
/** Seats after `enabled` filtering, keyed by id. */
|
|
97
|
+
byId: Map<string, Seat>;
|
|
98
|
+
/** Phases with their participant lists resolved. */
|
|
99
|
+
phases: Phase[];
|
|
100
|
+
configDir: string;
|
|
101
|
+
/** Content fingerprint over table, seats and the roundtable schema. */
|
|
102
|
+
fingerprint: string;
|
|
103
|
+
}
|
|
1
104
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Placeholder package. The design is settled in `ai-docs/design-docs/roundtable/`;
|
|
5
|
-
* the implementation has not started yet, so this module exports only the
|
|
6
|
-
* names and types that downstream code may already reference.
|
|
105
|
+
* Read and validate a roundtable directory without calling any model.
|
|
7
106
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
107
|
+
* Everything a meeting needs to be well defined is checked here: unknown
|
|
108
|
+
* fields, missing required fields, duplicate ids, phase references and the
|
|
109
|
+
* table/seat membership intersection. A meeting that starts is a meeting that
|
|
110
|
+
* can finish.
|
|
11
111
|
*/
|
|
12
|
-
declare
|
|
13
|
-
|
|
112
|
+
declare function loadRoundtable(options: {
|
|
113
|
+
configDir: string;
|
|
114
|
+
schema?: number;
|
|
115
|
+
}): Promise<LoadedRoundtable>;
|
|
116
|
+
/** Convenience for the CLI: validate and report, never call a model. */
|
|
117
|
+
declare function checkRoundtable(options: {
|
|
118
|
+
configDir: string;
|
|
119
|
+
env?: NodeJS.ProcessEnv;
|
|
120
|
+
}): Promise<LoadedRoundtable>;
|
|
121
|
+
/** Resolved default output directory. */
|
|
122
|
+
declare function defaultOutDir(cwd?: string): string;
|
|
123
|
+
|
|
124
|
+
/** One seat's turn in a phase, as seen by later seats. */
|
|
125
|
+
interface Statement {
|
|
126
|
+
seat: string;
|
|
127
|
+
name: string;
|
|
128
|
+
role: string;
|
|
129
|
+
phase: string;
|
|
130
|
+
status: StatementStatus;
|
|
131
|
+
content: string;
|
|
132
|
+
structured?: unknown;
|
|
133
|
+
durationMs?: number;
|
|
134
|
+
model?: string;
|
|
135
|
+
usage?: {
|
|
136
|
+
input: number;
|
|
137
|
+
output: number;
|
|
138
|
+
};
|
|
139
|
+
/** One log-safe line when the seat failed. */
|
|
140
|
+
error?: string;
|
|
141
|
+
artifacts?: ArtifactRef[];
|
|
142
|
+
}
|
|
143
|
+
type StatementStatus = 'completed' | 'skipped' | 'failed' | 'budget-exhausted' | 'invalid-veto';
|
|
144
|
+
interface ArtifactRef {
|
|
145
|
+
path: string;
|
|
146
|
+
bytes: number;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface Vote {
|
|
150
|
+
seatId: string;
|
|
151
|
+
weight: number;
|
|
152
|
+
/** `undefined` when the seat failed or was skipped, so it cannot count. */
|
|
153
|
+
vote?: 'pass' | 'reject';
|
|
154
|
+
/** Set when a veto-capable seat wrote `reject` with a reason. */
|
|
155
|
+
veto?: boolean;
|
|
156
|
+
/** Whether the seat actually wrote text for its reason. */
|
|
157
|
+
hasReason?: boolean;
|
|
158
|
+
}
|
|
159
|
+
interface Judgement {
|
|
160
|
+
passed: boolean;
|
|
161
|
+
/** Seats whose valid veto blocked the phase. */
|
|
162
|
+
vetoed: string[];
|
|
163
|
+
/** Seats that voted reject without a valid veto. */
|
|
164
|
+
rejected: string[];
|
|
165
|
+
/** Weighted pass ratio over seats that actually voted. */
|
|
166
|
+
score: number;
|
|
167
|
+
/** Seats whose veto had no reason and was therefore ignored. */
|
|
168
|
+
invalidVetoes: string[];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
type RoundtableStatus = 'running' | 'passed' | 'rejected' | 'aborted' | 'failed';
|
|
172
|
+
type PhaseStatus = 'completed' | 'skipped' | 'failed' | 'budget-exhausted';
|
|
173
|
+
interface PhaseRecord {
|
|
174
|
+
id: string;
|
|
175
|
+
status: PhaseStatus;
|
|
176
|
+
statements: Statement[];
|
|
177
|
+
judgement?: Judgement;
|
|
178
|
+
/** True when a completed phase had no input from its dependencies. */
|
|
179
|
+
pruned?: boolean;
|
|
180
|
+
}
|
|
181
|
+
interface RoundRecord {
|
|
182
|
+
attempt: number;
|
|
183
|
+
phases: PhaseRecord[];
|
|
184
|
+
}
|
|
185
|
+
interface BudgetState {
|
|
186
|
+
total?: number;
|
|
187
|
+
used: number;
|
|
188
|
+
perSeat: Record<string, number>;
|
|
189
|
+
perSeatLimit: Record<string, number | undefined>;
|
|
190
|
+
}
|
|
191
|
+
/** The AI call the engine depends on; injectable so meetings can be tested offline. */
|
|
192
|
+
type TextCaller = typeof text;
|
|
193
|
+
|
|
194
|
+
declare const RECORD_SCHEMA = 1;
|
|
195
|
+
interface RoundtableRecord {
|
|
196
|
+
schema: number;
|
|
197
|
+
title: string;
|
|
198
|
+
startedAt: string;
|
|
199
|
+
finishedAt?: string;
|
|
200
|
+
status: RoundtableStatus;
|
|
201
|
+
attempts: number;
|
|
202
|
+
verdict: {
|
|
203
|
+
passed: boolean;
|
|
204
|
+
vetoed: string[];
|
|
205
|
+
rejected: string[];
|
|
206
|
+
score: number;
|
|
207
|
+
invalidVetoes: string[];
|
|
208
|
+
};
|
|
209
|
+
rounds: RoundRecord[];
|
|
210
|
+
budget: {
|
|
211
|
+
total?: number;
|
|
212
|
+
used: number;
|
|
213
|
+
perSeat: Record<string, number>;
|
|
214
|
+
};
|
|
215
|
+
/** Files produced under artifacts/, referenced by statements. */
|
|
216
|
+
artifacts?: string[];
|
|
217
|
+
error?: string;
|
|
218
|
+
}
|
|
219
|
+
interface RunState {
|
|
220
|
+
schema: number;
|
|
221
|
+
runId: string;
|
|
222
|
+
/** `running` until the loop settles on a terminal status. */
|
|
223
|
+
status: RoundtableStatus | 'running';
|
|
224
|
+
attempt: number;
|
|
225
|
+
phaseIndex: number;
|
|
226
|
+
phaseId?: string;
|
|
227
|
+
budget: BudgetState;
|
|
228
|
+
fingerprint: string;
|
|
229
|
+
resumable: boolean;
|
|
230
|
+
rounds: RoundRecord[];
|
|
231
|
+
startedAt: string;
|
|
232
|
+
finishedAt?: string;
|
|
233
|
+
topic?: string;
|
|
234
|
+
context: string[];
|
|
235
|
+
error?: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
14
238
|
interface RoundtableOptions {
|
|
15
239
|
/** Directory holding `table.md` and `seats/` */
|
|
16
240
|
configDir: string;
|
|
@@ -21,17 +245,45 @@ interface RoundtableOptions {
|
|
|
21
245
|
/** Where run directories are written */
|
|
22
246
|
outDir?: string;
|
|
23
247
|
env?: NodeJS.ProcessEnv;
|
|
248
|
+
/** Emit one line per statement while the meeting runs. */
|
|
249
|
+
onProgress?: (line: string) => void;
|
|
250
|
+
/** Defaults to `@ci-kit/ai`'s text(); tests pass a stub. */
|
|
251
|
+
callText?: TextCaller;
|
|
24
252
|
}
|
|
25
253
|
interface RoundtableResult {
|
|
26
254
|
status: RoundtableStatus;
|
|
27
255
|
recordPath: string;
|
|
256
|
+
/** Directory holding record.json, record.md, state.json. */
|
|
257
|
+
runDir: string;
|
|
258
|
+
record: RoundtableRecord;
|
|
259
|
+
/** Total AI calls consumed. */
|
|
260
|
+
used: number;
|
|
261
|
+
budgetTotal?: number;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Run one meeting.
|
|
265
|
+
*
|
|
266
|
+
* Business failure is reported through `status`, never thrown: a rejected
|
|
267
|
+
* meeting is a normal result. Only configuration and usage errors throw,
|
|
268
|
+
* because those mean nothing could start.
|
|
269
|
+
*/
|
|
270
|
+
declare function runRoundtable(options: RoundtableOptions): Promise<RoundtableResult>;
|
|
271
|
+
interface ResumeOptions extends Omit<RoundtableOptions, 'outDir'> {
|
|
272
|
+
/** Run directory produced by a previous, interrupted execution. */
|
|
273
|
+
runDir: string;
|
|
28
274
|
}
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Continue an interrupted run from the phase that did not finish.
|
|
277
|
+
*
|
|
278
|
+
* Rules are fingerprinted: if a seat or the table changed, the previous
|
|
279
|
+
* progress described a different meeting and cannot be resumed. That mirrors
|
|
280
|
+
* "editing a prompt never rewrites an already-published draft".
|
|
281
|
+
*
|
|
282
|
+
* A run that already reached a terminal status is returned as-is rather than
|
|
283
|
+
* re-executed: repeating a finished meeting would spend money to reach the same
|
|
284
|
+
* answer.
|
|
285
|
+
*/
|
|
286
|
+
declare function resumeRoundtable(options: ResumeOptions): Promise<RoundtableResult>;
|
|
35
287
|
|
|
36
|
-
export { ROUNDTABLE_SCHEMA, checkRoundtable, loadRoundtable, runRoundtable };
|
|
37
|
-
export type { RoundtableOptions, RoundtableResult, RoundtableStatus };
|
|
288
|
+
export { RECORD_SCHEMA as ROUNDTABLE_SCHEMA, RoundtableConfigError, checkRoundtable, defaultOutDir, loadRoundtable, resumeRoundtable, runRoundtable };
|
|
289
|
+
export type { ArtifactRef, BudgetState, Judgement, LoadedRoundtable, Phase, PhaseMode, PhaseRecord, ResumeOptions, RoundRecord, RoundtableOptions, RoundtableRecord, RoundtableResult, RoundtableStatus, RunState, Seat, SeatIdentity, SeatOutput, SeatPersona, SeatPowers, Statement, StatementStatus, Table, TextCaller, Vote };
|