@heretek-ai/epistemic-swarm 1.0.4 → 1.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/dist/tui.js +182 -121
- package/package.json +2 -2
- package/src/agents.ts +6 -0
- package/src/continue.ts +2 -2
- package/src/panels.tsx +19 -0
- package/src/policy.ts +9 -1
- package/src/research.ts +4 -2
- package/src/rpc-def.ts +10 -0
- package/src/rpc.ts +16 -1
- package/src/runtime.ts +2 -0
- package/src/server.ts +65 -5
- package/src/session.ts +4 -2
- package/src/tools.ts +15 -1
package/dist/tui.js
CHANGED
|
@@ -94,51 +94,107 @@ var FactoryPanel = (props) => {
|
|
|
94
94
|
return _el$8;
|
|
95
95
|
})(), _$createComponent(Show, {
|
|
96
96
|
get when() {
|
|
97
|
-
return data().
|
|
97
|
+
return data().tree;
|
|
98
98
|
},
|
|
99
99
|
get children() {
|
|
100
|
-
var _el$0 = _$createElement("text"), _el$1 = _$createTextNode(`
|
|
100
|
+
var _el$0 = _$createElement("text"), _el$1 = _$createTextNode(`Design tree (round `), _el$10 = _$createTextNode(`): `), _el$11 = _$createTextNode(` settled \xB7 `), _el$12 = _$createTextNode(` open \xB7 `), _el$14 = _$createTextNode(` deferred`);
|
|
101
101
|
_$insertNode(_el$0, _el$1);
|
|
102
|
-
_$
|
|
102
|
+
_$insertNode(_el$0, _el$10);
|
|
103
|
+
_$insertNode(_el$0, _el$11);
|
|
104
|
+
_$insertNode(_el$0, _el$12);
|
|
105
|
+
_$insertNode(_el$0, _el$14);
|
|
106
|
+
_$insert(_el$0, () => data().tree.round, _el$10);
|
|
107
|
+
_$insert(_el$0, () => data().tree.settled, _el$11);
|
|
108
|
+
_$insert(_el$0, () => data().tree.open, _el$12);
|
|
109
|
+
_$insert(_el$0, () => data().tree.deferred, _el$14);
|
|
110
|
+
_$insert(_el$0, (() => {
|
|
111
|
+
var _c$3 = _$memo(() => !!data().tree.facts);
|
|
112
|
+
return () => _c$3() ? ` (${data().tree.facts} for research)` : "";
|
|
113
|
+
})(), null);
|
|
103
114
|
return _el$0;
|
|
104
115
|
}
|
|
116
|
+
}), _$createComponent(Show, {
|
|
117
|
+
get when() {
|
|
118
|
+
return data().halt;
|
|
119
|
+
},
|
|
120
|
+
get children() {
|
|
121
|
+
var _el$15 = _$createElement("text"), _el$16 = _$createTextNode(`HALTED: `);
|
|
122
|
+
_$insertNode(_el$15, _el$16);
|
|
123
|
+
_$insert(_el$15, () => data().halt, null);
|
|
124
|
+
return _el$15;
|
|
125
|
+
}
|
|
105
126
|
}), _$createComponent(Show, {
|
|
106
127
|
get when() {
|
|
107
128
|
return data().release;
|
|
108
129
|
},
|
|
109
130
|
get children() {
|
|
110
|
-
var _el$
|
|
111
|
-
_$insertNode(_el$
|
|
112
|
-
_$insert(_el$
|
|
113
|
-
return _el$
|
|
131
|
+
var _el$17 = _$createElement("text"), _el$18 = _$createTextNode(`PR: `);
|
|
132
|
+
_$insertNode(_el$17, _el$18);
|
|
133
|
+
_$insert(_el$17, () => data().release, null);
|
|
134
|
+
return _el$17;
|
|
114
135
|
}
|
|
115
136
|
}), _$createComponent(Show, {
|
|
116
137
|
get when() {
|
|
117
138
|
return data().pending.length;
|
|
118
139
|
},
|
|
119
140
|
get children() {
|
|
120
|
-
var _el$
|
|
121
|
-
_$insertNode(_el$
|
|
122
|
-
_$insert(_el$
|
|
123
|
-
return _el$
|
|
141
|
+
var _el$19 = _$createElement("text"), _el$20 = _$createTextNode(`Waiting on human: `);
|
|
142
|
+
_$insertNode(_el$19, _el$20);
|
|
143
|
+
_$insert(_el$19, () => data().pending.join(", "), null);
|
|
144
|
+
return _el$19;
|
|
145
|
+
}
|
|
146
|
+
}), _$createComponent(Show, {
|
|
147
|
+
get when() {
|
|
148
|
+
return data().audits?.length;
|
|
149
|
+
},
|
|
150
|
+
get children() {
|
|
151
|
+
return [(() => {
|
|
152
|
+
var _el$21 = _$createElement("text");
|
|
153
|
+
_$insertNode(_el$21, _$createTextNode(`Audits:`));
|
|
154
|
+
return _el$21;
|
|
155
|
+
})(), _$createComponent(For, {
|
|
156
|
+
get each() {
|
|
157
|
+
return data().audits;
|
|
158
|
+
},
|
|
159
|
+
children: (audit) => (() => {
|
|
160
|
+
var _el$25 = _$createElement("text"), _el$26 = _$createTextNode(` `), _el$27 = _$createTextNode(` \xB7 `), _el$28 = _$createTextNode(` \xB7 `), _el$29 = _$createTextNode(` r`), _el$30 = _$createTextNode(` \xB7 t:`), _el$31 = _$createTextNode(` a:`);
|
|
161
|
+
_$insertNode(_el$25, _el$26);
|
|
162
|
+
_$insertNode(_el$25, _el$27);
|
|
163
|
+
_$insertNode(_el$25, _el$28);
|
|
164
|
+
_$insertNode(_el$25, _el$29);
|
|
165
|
+
_$insertNode(_el$25, _el$30);
|
|
166
|
+
_$insertNode(_el$25, _el$31);
|
|
167
|
+
_$insert(_el$25, () => audit.id, _el$27);
|
|
168
|
+
_$insert(_el$25, () => audit.target, _el$28);
|
|
169
|
+
_$insert(_el$25, () => audit.status, _el$29);
|
|
170
|
+
_$insert(_el$25, () => audit.round, _el$30);
|
|
171
|
+
_$insert(_el$25, () => audit.thesis, _el$31);
|
|
172
|
+
_$insert(_el$25, () => audit.antithesis, null);
|
|
173
|
+
_$insert(_el$25, (() => {
|
|
174
|
+
var _c$4 = _$memo(() => !!audit.tiebreak);
|
|
175
|
+
return () => _c$4() ? ` x:${audit.tiebreak}` : "";
|
|
176
|
+
})(), null);
|
|
177
|
+
return _el$25;
|
|
178
|
+
})()
|
|
179
|
+
})];
|
|
124
180
|
}
|
|
125
181
|
}), (() => {
|
|
126
|
-
var _el$
|
|
127
|
-
_$insertNode(_el$
|
|
128
|
-
return _el$
|
|
182
|
+
var _el$23 = _$createElement("text");
|
|
183
|
+
_$insertNode(_el$23, _$createTextNode(`Phases:`));
|
|
184
|
+
return _el$23;
|
|
129
185
|
})(), _$createComponent(For, {
|
|
130
186
|
get each() {
|
|
131
187
|
return data().phases;
|
|
132
188
|
},
|
|
133
189
|
children: (phase) => (() => {
|
|
134
|
-
var _el$
|
|
135
|
-
_$insertNode(_el$
|
|
136
|
-
_$insertNode(_el$
|
|
137
|
-
_$insert(_el$
|
|
138
|
-
_$insert(_el$
|
|
139
|
-
_$insert(_el$
|
|
140
|
-
_$insert(_el$
|
|
141
|
-
return _el$
|
|
190
|
+
var _el$32 = _$createElement("text"), _el$33 = _$createTextNode(` \xB7 `), _el$34 = _$createTextNode(` \xB7 failures `);
|
|
191
|
+
_$insertNode(_el$32, _el$33);
|
|
192
|
+
_$insertNode(_el$32, _el$34);
|
|
193
|
+
_$insert(_el$32, () => phase.id === data().activePhase ? "\u25B6 " : " ", _el$33);
|
|
194
|
+
_$insert(_el$32, () => phase.id, _el$33);
|
|
195
|
+
_$insert(_el$32, () => phase.status, _el$34);
|
|
196
|
+
_$insert(_el$32, () => phase.failures, null);
|
|
197
|
+
return _el$32;
|
|
142
198
|
})()
|
|
143
199
|
})]
|
|
144
200
|
})];
|
|
@@ -160,43 +216,43 @@ var LspPanel = (props) => {
|
|
|
160
216
|
},
|
|
161
217
|
get fallback() {
|
|
162
218
|
return (() => {
|
|
163
|
-
var _el$
|
|
164
|
-
_$insert(_el$
|
|
165
|
-
return _el$
|
|
219
|
+
var _el$35 = _$createElement("text");
|
|
220
|
+
_$insert(_el$35, () => state.error() ? "" : "Loading language servers\u2026");
|
|
221
|
+
return _el$35;
|
|
166
222
|
})();
|
|
167
223
|
},
|
|
168
224
|
children: (data) => [(() => {
|
|
169
|
-
var _el$
|
|
170
|
-
_$insert(_el$
|
|
171
|
-
return _el$
|
|
225
|
+
var _el$36 = _$createElement("text");
|
|
226
|
+
_$insert(_el$36, () => data().enabled ? "LSP is on." : "LSP is disabled (lsp: false).");
|
|
227
|
+
return _el$36;
|
|
172
228
|
})(), _$createComponent(For, {
|
|
173
229
|
get each() {
|
|
174
230
|
return data().servers;
|
|
175
231
|
},
|
|
176
232
|
children: (server) => (() => {
|
|
177
|
-
var _el$
|
|
178
|
-
_$insertNode(_el$
|
|
179
|
-
_$insertNode(_el$
|
|
180
|
-
_$insertNode(_el$
|
|
181
|
-
_$insert(_el$
|
|
182
|
-
_$insert(_el$
|
|
183
|
-
_$insert(_el$
|
|
184
|
-
_$insert(_el$
|
|
185
|
-
var _c$
|
|
186
|
-
return () => _c$
|
|
233
|
+
var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createTextNode(` [`), _el$40 = _$createTextNode(`]`);
|
|
234
|
+
_$insertNode(_el$37, _el$38);
|
|
235
|
+
_$insertNode(_el$37, _el$39);
|
|
236
|
+
_$insertNode(_el$37, _el$40);
|
|
237
|
+
_$insert(_el$37, () => server.available ? "\u25CF" : "\u25CB", _el$38);
|
|
238
|
+
_$insert(_el$37, () => server.id, _el$39);
|
|
239
|
+
_$insert(_el$37, () => server.extensions.join(" "), _el$40);
|
|
240
|
+
_$insert(_el$37, (() => {
|
|
241
|
+
var _c$5 = _$memo(() => !!server.running);
|
|
242
|
+
return () => _c$5() ? ` \xB7 ${server.running} running` : "";
|
|
187
243
|
})(), null);
|
|
188
|
-
_$insert(_el$
|
|
189
|
-
return _el$
|
|
244
|
+
_$insert(_el$37, () => server.available ? "" : " \u2014 not installed", null);
|
|
245
|
+
return _el$37;
|
|
190
246
|
})()
|
|
191
247
|
}), _$createComponent(For, {
|
|
192
248
|
get each() {
|
|
193
249
|
return data().diagnostics;
|
|
194
250
|
},
|
|
195
251
|
children: (diagnostic) => (() => {
|
|
196
|
-
var _el$
|
|
197
|
-
_$insertNode(_el$
|
|
198
|
-
_$insert(_el$
|
|
199
|
-
return _el$
|
|
252
|
+
var _el$41 = _$createElement("text"), _el$42 = _$createTextNode(`! `);
|
|
253
|
+
_$insertNode(_el$41, _el$42);
|
|
254
|
+
_$insert(_el$41, diagnostic, null);
|
|
255
|
+
return _el$41;
|
|
200
256
|
})()
|
|
201
257
|
})]
|
|
202
258
|
})];
|
|
@@ -218,30 +274,30 @@ var HooksPanel = (props) => {
|
|
|
218
274
|
},
|
|
219
275
|
get fallback() {
|
|
220
276
|
return (() => {
|
|
221
|
-
var _el$
|
|
222
|
-
_$insert(_el$
|
|
223
|
-
return _el$
|
|
277
|
+
var _el$43 = _$createElement("text");
|
|
278
|
+
_$insert(_el$43, () => state.error() ? "" : "Loading hooks\u2026");
|
|
279
|
+
return _el$43;
|
|
224
280
|
})();
|
|
225
281
|
},
|
|
226
282
|
children: (data) => [(() => {
|
|
227
|
-
var _el$
|
|
228
|
-
_$insertNode(_el$
|
|
229
|
-
_$insertNode(_el$
|
|
230
|
-
_$insert(_el$
|
|
231
|
-
_$insert(_el$
|
|
232
|
-
_$insert(_el$
|
|
233
|
-
var _c$
|
|
234
|
-
return () => _c$
|
|
283
|
+
var _el$44 = _$createElement("text"), _el$45 = _$createTextNode(` handler(s) \xB7 `), _el$46 = _$createTextNode(` from the project \xB7 `);
|
|
284
|
+
_$insertNode(_el$44, _el$45);
|
|
285
|
+
_$insertNode(_el$44, _el$46);
|
|
286
|
+
_$insert(_el$44, () => data().handlers, _el$45);
|
|
287
|
+
_$insert(_el$44, () => data().projectHandlers, _el$46);
|
|
288
|
+
_$insert(_el$44, (() => {
|
|
289
|
+
var _c$6 = _$memo(() => data().projectHandlers === 0);
|
|
290
|
+
return () => _c$6() ? "nothing to trust" : data().trusted ? "trusted" : "NOT trusted";
|
|
235
291
|
})(), null);
|
|
236
|
-
return _el$
|
|
292
|
+
return _el$44;
|
|
237
293
|
})(), _$createComponent(For, {
|
|
238
294
|
get each() {
|
|
239
295
|
return data().projectLines;
|
|
240
296
|
},
|
|
241
297
|
children: (line) => (() => {
|
|
242
|
-
var _el$
|
|
243
|
-
_$insert(_el$
|
|
244
|
-
return _el$
|
|
298
|
+
var _el$50 = _$createElement("text");
|
|
299
|
+
_$insert(_el$50, line);
|
|
300
|
+
return _el$50;
|
|
245
301
|
})()
|
|
246
302
|
}), _$createComponent(Show, {
|
|
247
303
|
get when() {
|
|
@@ -249,24 +305,24 @@ var HooksPanel = (props) => {
|
|
|
249
305
|
},
|
|
250
306
|
get children() {
|
|
251
307
|
return [(() => {
|
|
252
|
-
var _el$
|
|
253
|
-
_$insertNode(_el$
|
|
254
|
-
return _el$
|
|
308
|
+
var _el$48 = _$createElement("text");
|
|
309
|
+
_$insertNode(_el$48, _$createTextNode(`Capability loss (advisory rows):`));
|
|
310
|
+
return _el$48;
|
|
255
311
|
})(), _$createComponent(For, {
|
|
256
312
|
get each() {
|
|
257
313
|
return data().loss;
|
|
258
314
|
},
|
|
259
315
|
children: (item) => (() => {
|
|
260
|
-
var _el$
|
|
261
|
-
_$insertNode(_el$
|
|
262
|
-
_$insertNode(_el$
|
|
263
|
-
_$insertNode(_el$
|
|
264
|
-
_$insertNode(_el$
|
|
265
|
-
_$insert(_el$
|
|
266
|
-
_$insert(_el$
|
|
267
|
-
_$insert(_el$
|
|
268
|
-
_$insert(_el$
|
|
269
|
-
return _el$
|
|
316
|
+
var _el$51 = _$createElement("text"), _el$52 = _$createTextNode(`! `), _el$53 = _$createTextNode(` \xB7 `), _el$54 = _$createTextNode(` \u2014 `), _el$55 = _$createTextNode(`: `);
|
|
317
|
+
_$insertNode(_el$51, _el$52);
|
|
318
|
+
_$insertNode(_el$51, _el$53);
|
|
319
|
+
_$insertNode(_el$51, _el$54);
|
|
320
|
+
_$insertNode(_el$51, _el$55);
|
|
321
|
+
_$insert(_el$51, () => item.event, _el$53);
|
|
322
|
+
_$insert(_el$51, () => item.handler, _el$54);
|
|
323
|
+
_$insert(_el$51, () => item.support, _el$55);
|
|
324
|
+
_$insert(_el$51, () => item.reason, null);
|
|
325
|
+
return _el$51;
|
|
270
326
|
})()
|
|
271
327
|
})];
|
|
272
328
|
}
|
|
@@ -275,20 +331,20 @@ var HooksPanel = (props) => {
|
|
|
275
331
|
return data().diagnostics;
|
|
276
332
|
},
|
|
277
333
|
children: (item) => (() => {
|
|
278
|
-
var _el$
|
|
279
|
-
_$insertNode(_el$
|
|
280
|
-
_$insert(_el$
|
|
281
|
-
return _el$
|
|
334
|
+
var _el$56 = _$createElement("text"), _el$57 = _$createTextNode(`! `);
|
|
335
|
+
_$insertNode(_el$56, _el$57);
|
|
336
|
+
_$insert(_el$56, item, null);
|
|
337
|
+
return _el$56;
|
|
282
338
|
})()
|
|
283
339
|
}), _$createComponent(For, {
|
|
284
340
|
get each() {
|
|
285
341
|
return data().recent;
|
|
286
342
|
},
|
|
287
343
|
children: (item) => (() => {
|
|
288
|
-
var _el$
|
|
289
|
-
_$insertNode(_el$
|
|
290
|
-
_$insert(_el$
|
|
291
|
-
return _el$
|
|
344
|
+
var _el$58 = _$createElement("text"), _el$59 = _$createTextNode(`recent error: `);
|
|
345
|
+
_$insertNode(_el$58, _el$59);
|
|
346
|
+
_$insert(_el$58, item, null);
|
|
347
|
+
return _el$58;
|
|
292
348
|
})()
|
|
293
349
|
})]
|
|
294
350
|
})];
|
|
@@ -310,9 +366,9 @@ var BrainstormPanel = (props) => {
|
|
|
310
366
|
},
|
|
311
367
|
get fallback() {
|
|
312
368
|
return (() => {
|
|
313
|
-
var _el$
|
|
314
|
-
_$insert(_el$
|
|
315
|
-
return _el$
|
|
369
|
+
var _el$60 = _$createElement("text");
|
|
370
|
+
_$insert(_el$60, () => state.error() ? "" : "Loading brainstorm\u2026");
|
|
371
|
+
return _el$60;
|
|
316
372
|
})();
|
|
317
373
|
},
|
|
318
374
|
children: (data) => _$createComponent(Show, {
|
|
@@ -321,41 +377,41 @@ var BrainstormPanel = (props) => {
|
|
|
321
377
|
},
|
|
322
378
|
get fallback() {
|
|
323
379
|
return (() => {
|
|
324
|
-
var _el$
|
|
325
|
-
_$insertNode(_el$
|
|
326
|
-
return _el$
|
|
380
|
+
var _el$75 = _$createElement("text");
|
|
381
|
+
_$insertNode(_el$75, _$createTextNode(`No brainstorm in .factory/brainstorm yet. Run /brainstorm.`));
|
|
382
|
+
return _el$75;
|
|
327
383
|
})();
|
|
328
384
|
},
|
|
329
385
|
get children() {
|
|
330
386
|
return [(() => {
|
|
331
|
-
var _el$
|
|
332
|
-
_$insertNode(_el$
|
|
333
|
-
_$insert(_el$
|
|
334
|
-
return _el$
|
|
387
|
+
var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(`Brief: `);
|
|
388
|
+
_$insertNode(_el$61, _el$62);
|
|
389
|
+
_$insert(_el$61, () => data().brief, null);
|
|
390
|
+
return _el$61;
|
|
335
391
|
})(), (() => {
|
|
336
|
-
var _el$
|
|
337
|
-
_$insertNode(_el$
|
|
338
|
-
_$insertNode(_el$
|
|
339
|
-
_$insertNode(_el$
|
|
340
|
-
_$insert(_el$
|
|
341
|
-
_$insert(_el$
|
|
342
|
-
_$insert(_el$
|
|
343
|
-
_$insert(_el$
|
|
344
|
-
return _el$
|
|
392
|
+
var _el$63 = _$createElement("text"), _el$64 = _$createTextNode(` idea(s) \xB7 `), _el$65 = _$createTextNode(` duplicate(s) \xB7 `), _el$66 = _$createTextNode(` scored \xB7 `);
|
|
393
|
+
_$insertNode(_el$63, _el$64);
|
|
394
|
+
_$insertNode(_el$63, _el$65);
|
|
395
|
+
_$insertNode(_el$63, _el$66);
|
|
396
|
+
_$insert(_el$63, () => data().ideas, _el$64);
|
|
397
|
+
_$insert(_el$63, () => data().duplicates, _el$65);
|
|
398
|
+
_$insert(_el$63, () => data().scored, _el$66);
|
|
399
|
+
_$insert(_el$63, () => data().complete ? "complete" : "in progress", null);
|
|
400
|
+
return _el$63;
|
|
345
401
|
})(), (() => {
|
|
346
|
-
var _el$
|
|
347
|
-
_$insertNode(_el$
|
|
348
|
-
_$insert(_el$
|
|
349
|
-
return _el$
|
|
402
|
+
var _el$68 = _$createElement("text"), _el$69 = _$createTextNode(`Coverage: `);
|
|
403
|
+
_$insertNode(_el$68, _el$69);
|
|
404
|
+
_$insert(_el$68, () => data().lenses.map((lens) => `${lens} ${data().coverage[lens] ?? 0}`).join(" \xB7 "), null);
|
|
405
|
+
return _el$68;
|
|
350
406
|
})(), _$createComponent(Show, {
|
|
351
407
|
get when() {
|
|
352
408
|
return data().gaps.length;
|
|
353
409
|
},
|
|
354
410
|
get children() {
|
|
355
|
-
var _el$
|
|
356
|
-
_$insertNode(_el$
|
|
357
|
-
_$insert(_el$
|
|
358
|
-
return _el$
|
|
411
|
+
var _el$71 = _$createElement("text"), _el$72 = _$createTextNode(`Gaps: `);
|
|
412
|
+
_$insertNode(_el$71, _el$72);
|
|
413
|
+
_$insert(_el$71, () => data().gaps.join(", "), null);
|
|
414
|
+
return _el$71;
|
|
359
415
|
}
|
|
360
416
|
}), _$createComponent(Show, {
|
|
361
417
|
get when() {
|
|
@@ -363,24 +419,24 @@ var BrainstormPanel = (props) => {
|
|
|
363
419
|
},
|
|
364
420
|
get children() {
|
|
365
421
|
return [(() => {
|
|
366
|
-
var _el$
|
|
367
|
-
_$insertNode(_el$
|
|
368
|
-
return _el$
|
|
422
|
+
var _el$73 = _$createElement("text");
|
|
423
|
+
_$insertNode(_el$73, _$createTextNode(`Shortlist:`));
|
|
424
|
+
return _el$73;
|
|
369
425
|
})(), _$createComponent(For, {
|
|
370
426
|
get each() {
|
|
371
427
|
return data().shortlist;
|
|
372
428
|
},
|
|
373
429
|
children: (entry) => (() => {
|
|
374
|
-
var _el$
|
|
375
|
-
_$insertNode(_el$
|
|
376
|
-
_$insertNode(_el$
|
|
377
|
-
_$insertNode(_el$
|
|
378
|
-
_$insert(_el$
|
|
379
|
-
_$insert(_el$
|
|
380
|
-
_$insert(_el$
|
|
381
|
-
_$insert(_el$
|
|
382
|
-
_$insert(_el$
|
|
383
|
-
return _el$
|
|
430
|
+
var _el$77 = _$createElement("text"), _el$78 = _$createTextNode(` `), _el$79 = _$createTextNode(` (`), _el$80 = _$createTextNode(`/20) \u2014 `);
|
|
431
|
+
_$insertNode(_el$77, _el$78);
|
|
432
|
+
_$insertNode(_el$77, _el$79);
|
|
433
|
+
_$insertNode(_el$77, _el$80);
|
|
434
|
+
_$insert(_el$77, () => entry.outlier ? "\u25C7" : "\u25C6", _el$78);
|
|
435
|
+
_$insert(_el$77, () => entry.id, _el$79);
|
|
436
|
+
_$insert(_el$77, () => entry.total, _el$80);
|
|
437
|
+
_$insert(_el$77, () => entry.title, null);
|
|
438
|
+
_$insert(_el$77, () => entry.outlier ? " (forced outlier)" : "", null);
|
|
439
|
+
return _el$77;
|
|
384
440
|
})()
|
|
385
441
|
})];
|
|
386
442
|
}
|
|
@@ -511,7 +567,12 @@ var EsRpc = define({
|
|
|
511
567
|
"estimated"
|
|
512
568
|
]),
|
|
513
569
|
phases: { type: "array" },
|
|
514
|
-
pending: strArray
|
|
570
|
+
pending: strArray,
|
|
571
|
+
audits: { type: "array" },
|
|
572
|
+
tree: obj(Object.fromEntries(["round", "total", "settled", "open", "deferred", "facts", "frontier"].map((key) => [
|
|
573
|
+
key,
|
|
574
|
+
{ type: "number" }
|
|
575
|
+
])), ["round", "total", "settled", "open", "deferred", "facts", "frontier"])
|
|
515
576
|
}, ["stage", "spend", "phases", "pending"])
|
|
516
577
|
},
|
|
517
578
|
lspState: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heretek-ai/epistemic-swarm",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Epistemic Swarm: an AI build factory for OpenCode v2 — grill, research, spec, build, QA and release, gated mechanically.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"test": "bun test"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@heretek-ai/es-core": "1.0
|
|
44
|
+
"@heretek-ai/es-core": "1.1.0",
|
|
45
45
|
"@opencode/plugin": "2.0.24"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
package/src/agents.ts
CHANGED
|
@@ -12,6 +12,9 @@ export interface CompiledAgent {
|
|
|
12
12
|
readonly model?: { providerID: string; id: string }
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/** The host's own web tools, denied to seats whose web access is "cached". */
|
|
16
|
+
export const HOST_WEB_TOOLS = ["websearch", "webfetch"] as const
|
|
17
|
+
|
|
15
18
|
export function permissionRules(spec: AgentSpec, mcpServers: readonly string[]): CompiledAgent["permissions"] {
|
|
16
19
|
const rules: CompiledAgent["permissions"] = [
|
|
17
20
|
{ action: "es_*", resource: "*", effect: "deny" },
|
|
@@ -32,6 +35,9 @@ export function permissionRules(spec: AgentSpec, mcpServers: readonly string[]):
|
|
|
32
35
|
// this only grants autonomous seats access to a scratch directory.
|
|
33
36
|
rules.push({ action: "external_directory", resource: "/tmp/*", effect: "allow" }) // NOSONAR
|
|
34
37
|
}
|
|
38
|
+
if (spec.web === "cached")
|
|
39
|
+
// Search as policy: web facts only through the cached, citable es_research_* tools.
|
|
40
|
+
for (const action of HOST_WEB_TOOLS) rules.push({ action, resource: "*", effect: "deny" })
|
|
35
41
|
if (spec.writes.length === 0) rules.push({ action: "edit", resource: "*", effect: "deny" })
|
|
36
42
|
if (spec.lsp === "none") rules.push({ action: "lsp", resource: "*", effect: "deny" })
|
|
37
43
|
if (spec.lsp !== "full") rules.push({ action: "lsp_rename", resource: "*", effect: "deny" })
|
package/src/continue.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// work remains (not halted, not waiting on a human approval or the grill), we
|
|
3
3
|
// re-prompt it to continue. Progress-aware: three idle turns without any state
|
|
4
4
|
// change stop the loop so a confused agent cannot spin on budget.
|
|
5
|
-
import {
|
|
5
|
+
import { pendingApprovals } from "@heretek-ai/es-core"
|
|
6
6
|
import type { Runtime } from "./runtime.ts"
|
|
7
7
|
|
|
8
8
|
const ACTIVE = new Set(["RESEARCH", "SPEC", "BUILD", "QA", "RELEASE"])
|
|
@@ -34,7 +34,7 @@ export function createFactoryContinuation(
|
|
|
34
34
|
if (count >= STALL_LIMIT) return
|
|
35
35
|
await ctx.session.prompt({
|
|
36
36
|
sessionID,
|
|
37
|
-
text: `${
|
|
37
|
+
text: `${await runtime.factory.summary(state)}\nThe factory run is not finished. Continue from the current stage (no human is needed unless an approval is due).`,
|
|
38
38
|
})
|
|
39
39
|
}
|
|
40
40
|
}
|
package/src/panels.tsx
CHANGED
|
@@ -68,6 +68,13 @@ const FactoryPanel = (props: PanelProps) => {
|
|
|
68
68
|
{data().spend.ceilingUSD ? ` / $${data().spend.ceilingUSD}` : ""}
|
|
69
69
|
{data().spend.estimated ? " (estimated)" : ""}
|
|
70
70
|
</text>
|
|
71
|
+
<Show when={data().tree}>
|
|
72
|
+
<text>
|
|
73
|
+
Design tree (round {data().tree.round}): {data().tree.settled} settled · {data().tree.open} open ·{" "}
|
|
74
|
+
{data().tree.deferred} deferred
|
|
75
|
+
{data().tree.facts ? ` (${data().tree.facts} for research)` : ""}
|
|
76
|
+
</text>
|
|
77
|
+
</Show>
|
|
71
78
|
<Show when={data().halt}>
|
|
72
79
|
<text>HALTED: {data().halt}</text>
|
|
73
80
|
</Show>
|
|
@@ -77,6 +84,18 @@ const FactoryPanel = (props: PanelProps) => {
|
|
|
77
84
|
<Show when={data().pending.length}>
|
|
78
85
|
<text>Waiting on human: {data().pending.join(", ")}</text>
|
|
79
86
|
</Show>
|
|
87
|
+
<Show when={data().audits?.length}>
|
|
88
|
+
<text>Audits:</text>
|
|
89
|
+
<For each={data().audits}>
|
|
90
|
+
{(audit: any) => (
|
|
91
|
+
<text>
|
|
92
|
+
{" "}
|
|
93
|
+
{audit.id} · {audit.target} · {audit.status} r{audit.round} · t:{audit.thesis} a:{audit.antithesis}
|
|
94
|
+
{audit.tiebreak ? ` x:${audit.tiebreak}` : ""}
|
|
95
|
+
</text>
|
|
96
|
+
)}
|
|
97
|
+
</For>
|
|
98
|
+
</Show>
|
|
80
99
|
<text>Phases:</text>
|
|
81
100
|
<For each={data().phases}>
|
|
82
101
|
{(phase: any) => (
|
package/src/policy.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// read-only shells under bubblewrap, and get fast gate feedback after edits.
|
|
5
5
|
import path from "node:path"
|
|
6
6
|
import {
|
|
7
|
+
agentSpec,
|
|
7
8
|
bwrapAvailable,
|
|
8
9
|
checkStopFile,
|
|
9
10
|
evaluateRead,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
treeFingerprint,
|
|
20
21
|
} from "@heretek-ai/es-core"
|
|
21
22
|
import { Error as ToolError } from "@opencode/plugin/promise/tool"
|
|
23
|
+
import { HOST_WEB_TOOLS } from "./agents.ts"
|
|
22
24
|
import type { Runtime } from "./runtime.ts"
|
|
23
25
|
|
|
24
26
|
const WRITE_TOOLS = new Set(["write", "edit"])
|
|
@@ -58,11 +60,17 @@ export function createPolicyHooks(runtime: Runtime) {
|
|
|
58
60
|
if (stop.stopped)
|
|
59
61
|
deny(`The factory is stopped (.factory/STOP: ${stop.reason}). A human must remove it and resume.`)
|
|
60
62
|
}
|
|
61
|
-
|
|
63
|
+
// A halted run (spend ceiling, runtime cap, drift, STOP) stops every seat
|
|
64
|
+
// tool except es_status, so no seat keeps spending through its own es_* tools.
|
|
65
|
+
if (seat && event.tool !== "es_status") {
|
|
62
66
|
const state = await runtime.factory.read().catch(() => undefined)
|
|
63
67
|
if (state?.stage === "HALTED")
|
|
64
68
|
deny(`The factory is halted: ${state.halt?.reason}. Stop and report; a human must resume.`)
|
|
65
69
|
}
|
|
70
|
+
if (agentSpec(event.agent)?.web === "cached" && (HOST_WEB_TOOLS as readonly string[]).includes(event.tool))
|
|
71
|
+
deny(
|
|
72
|
+
`Seat "${event.agent}" gets web facts only through es_research_search and es_research_fetch (cached and citable); ${event.tool} is not available to it.`,
|
|
73
|
+
)
|
|
66
74
|
const context = await runtime.policy()
|
|
67
75
|
if (WRITE_TOOLS.has(event.tool) && typeof input.path === "string") {
|
|
68
76
|
const decision = evaluateWrite(context, event.agent, input.path)
|
package/src/research.ts
CHANGED
|
@@ -8,14 +8,16 @@ export function registerWebsearch(
|
|
|
8
8
|
editor: { add(definition: any): void; default: { get(): unknown; set(id: string): void } },
|
|
9
9
|
runtime: Runtime,
|
|
10
10
|
) {
|
|
11
|
-
const
|
|
11
|
+
const searxng = runtime.config.research?.searxngUrl
|
|
12
|
+
const env = searxng ? { ...process.env, SEARXNG_URL: searxng } : process.env
|
|
13
|
+
const provider = selectProvider(runtime.options.searchProvider, env)
|
|
12
14
|
if (!provider) return
|
|
13
15
|
const cache = researchCache(runtime.root)
|
|
14
16
|
editor.add({
|
|
15
17
|
id: "epistemic-swarm",
|
|
16
18
|
name: `Epistemic Swarm (${provider.id}, cached)`,
|
|
17
19
|
execute: async (input: { query: string; limit?: number }, context: { signal: AbortSignal }) => {
|
|
18
|
-
const results = await provider.search(input.query, { limit: input.limit ?? 8, signal: context.signal })
|
|
20
|
+
const results = await provider.search(input.query, { limit: input.limit ?? 8, signal: context.signal, env })
|
|
19
21
|
const out = []
|
|
20
22
|
for (const result of results) {
|
|
21
23
|
const cached = await cache.put({
|
package/src/rpc-def.ts
CHANGED
|
@@ -81,6 +81,16 @@ export const EsRpc = Rpc.define({
|
|
|
81
81
|
]),
|
|
82
82
|
phases: { type: "array" },
|
|
83
83
|
pending: strArray,
|
|
84
|
+
audits: { type: "array" },
|
|
85
|
+
tree: obj(
|
|
86
|
+
Object.fromEntries(
|
|
87
|
+
["round", "total", "settled", "open", "deferred", "facts", "frontier"].map((key) => [
|
|
88
|
+
key,
|
|
89
|
+
{ type: "number" },
|
|
90
|
+
]),
|
|
91
|
+
),
|
|
92
|
+
["round", "total", "settled", "open", "deferred", "facts", "frontier"],
|
|
93
|
+
),
|
|
84
94
|
},
|
|
85
95
|
["stage", "spend", "phases", "pending"],
|
|
86
96
|
),
|
package/src/rpc.ts
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
import { randomBytes } from "node:crypto"
|
|
6
6
|
import {
|
|
7
7
|
type ApprovalStage,
|
|
8
|
+
allAudits,
|
|
8
9
|
approvalSubject,
|
|
9
10
|
capabilityLoss,
|
|
10
11
|
commandSetHash,
|
|
12
|
+
describeTarget,
|
|
11
13
|
factoryLayout,
|
|
12
14
|
factorySummary,
|
|
13
15
|
type HookEngine,
|
|
@@ -15,12 +17,14 @@ import {
|
|
|
15
17
|
installServer,
|
|
16
18
|
isTrusted,
|
|
17
19
|
loadGatesConfig,
|
|
20
|
+
readFrontier,
|
|
18
21
|
readIdeas,
|
|
19
22
|
readPlan,
|
|
20
23
|
readResult,
|
|
21
24
|
readScores,
|
|
22
25
|
recordApproval,
|
|
23
26
|
recordConsent,
|
|
27
|
+
treeCounts,
|
|
24
28
|
trustProject,
|
|
25
29
|
verifyControl,
|
|
26
30
|
writeJson,
|
|
@@ -75,14 +79,16 @@ export function createRpcHandlers(runtime: Runtime, notify: () => Promise<void>,
|
|
|
75
79
|
status: async () => {
|
|
76
80
|
const state = await runtime.factory.read()
|
|
77
81
|
return {
|
|
78
|
-
summary:
|
|
82
|
+
summary: await runtime.factory.summary(state),
|
|
79
83
|
stage: state?.stage ?? "NONE",
|
|
80
84
|
pending: (await pendingApprovals(runtime.root)).map((item) => item.stage),
|
|
81
85
|
}
|
|
82
86
|
},
|
|
83
87
|
factoryState: async () => {
|
|
84
88
|
const state = await runtime.factory.read()
|
|
89
|
+
const frontier = await readFrontier(runtime.root).catch(() => undefined)
|
|
85
90
|
return {
|
|
91
|
+
...(frontier ? { tree: treeCounts(frontier) } : {}),
|
|
86
92
|
stage: state?.stage ?? "NONE",
|
|
87
93
|
...(state?.runId ? { runId: state.runId } : {}),
|
|
88
94
|
...(state?.halt ? { halt: state.halt.reason } : {}),
|
|
@@ -101,6 +107,15 @@ export function createRpcHandlers(runtime: Runtime, notify: () => Promise<void>,
|
|
|
101
107
|
qa: Object.fromEntries(Object.entries(phase.qa).filter(([, verdict]) => verdict !== undefined)),
|
|
102
108
|
})),
|
|
103
109
|
pending: (await pendingApprovals(runtime.root)).map((item) => item.stage),
|
|
110
|
+
audits: (state ? allAudits(state) : []).map((audit) => ({
|
|
111
|
+
id: audit.id,
|
|
112
|
+
target: describeTarget(audit.target),
|
|
113
|
+
status: audit.status,
|
|
114
|
+
round: audit.round,
|
|
115
|
+
thesis: audit.thesis?.verdict ?? "-",
|
|
116
|
+
antithesis: audit.antithesis?.verdict ?? "-",
|
|
117
|
+
...(audit.tiebreak ? { tiebreak: audit.tiebreak.verdict } : {}),
|
|
118
|
+
})),
|
|
104
119
|
}
|
|
105
120
|
},
|
|
106
121
|
lspState: async () => {
|
package/src/runtime.ts
CHANGED
|
@@ -73,6 +73,8 @@ export async function createRuntime(root: string, raw: RawPluginOptions): Promis
|
|
|
73
73
|
gates: gateRunner({ stateDir }),
|
|
74
74
|
...(options.pr === "off" ? {} : { pr: ghPrOpener }),
|
|
75
75
|
stateDir,
|
|
76
|
+
researchDepth: config.research.depth,
|
|
77
|
+
...(config.domainPack ? { domainPack: config.domainPack } : {}),
|
|
76
78
|
})
|
|
77
79
|
return {
|
|
78
80
|
root,
|
package/src/server.ts
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
import { readdir, readFile } from "node:fs/promises"
|
|
5
5
|
import path from "node:path"
|
|
6
6
|
import {
|
|
7
|
+
describeTarget,
|
|
7
8
|
factoryLayout,
|
|
8
|
-
factorySummary,
|
|
9
9
|
formatReport,
|
|
10
10
|
git,
|
|
11
11
|
loadSkills,
|
|
12
|
+
parseAuditTarget,
|
|
12
13
|
readJson,
|
|
13
14
|
researchSourcesDir,
|
|
14
15
|
runGates,
|
|
@@ -102,7 +103,7 @@ export default Plugin.define({
|
|
|
102
103
|
const notify = async () => {
|
|
103
104
|
const state = await runtime.factory.read()
|
|
104
105
|
await registration?.events
|
|
105
|
-
.emit("changed", { stage: state?.stage ?? "NONE", summary:
|
|
106
|
+
.emit("changed", { stage: state?.stage ?? "NONE", summary: await runtime.factory.summary(state) })
|
|
106
107
|
.catch(() => undefined)
|
|
107
108
|
}
|
|
108
109
|
registration = await ctx.rpc.register(EsRpc, createRpcHandlers(runtime, notify, bridge.engine) as any)
|
|
@@ -166,16 +167,75 @@ export default Plugin.define({
|
|
|
166
167
|
} as any)
|
|
167
168
|
},
|
|
168
169
|
})
|
|
170
|
+
editor.add({
|
|
171
|
+
name: "scout",
|
|
172
|
+
description: "Find and vet open-source candidates for a feature: licenses, maintenance, CVEs (Epistemic Swarm)",
|
|
173
|
+
execute: async ({ sessionID, prompt, delivery }) => {
|
|
174
|
+
await ctx.session.switchAgent({ sessionID, agent: "scout" } as any)
|
|
175
|
+
await ctx.session.prompt({
|
|
176
|
+
...prompt,
|
|
177
|
+
sessionID,
|
|
178
|
+
text: prompt.text?.trim()
|
|
179
|
+
? `Scout: ${prompt.text}`
|
|
180
|
+
: "Ask me for the feature to scout and our license posture, then plan the candidates.",
|
|
181
|
+
delivery,
|
|
182
|
+
} as any)
|
|
183
|
+
},
|
|
184
|
+
})
|
|
185
|
+
editor.add({
|
|
186
|
+
name: "audit",
|
|
187
|
+
description: "Open a code audit of the active phase or a path and run the auditor pair (Epistemic Swarm)",
|
|
188
|
+
execute: async ({ sessionID, prompt, delivery }) => {
|
|
189
|
+
const target = prompt.text?.trim()
|
|
190
|
+
const say = async (text: string) => {
|
|
191
|
+
await ctx.session.synthetic({ sessionID, text } as any)
|
|
192
|
+
}
|
|
193
|
+
if (!target) return say("Usage: /audit <active phase id | path in the project>")
|
|
194
|
+
const state = await runtime.factory.read().catch(() => undefined)
|
|
195
|
+
if (state?.spendCeilingUSD === undefined)
|
|
196
|
+
return say(
|
|
197
|
+
"Audits run inside a factory run with a spend ceiling. Start one at a terminal with `es audit <target> --max-usd N`, or run /grill first.",
|
|
198
|
+
)
|
|
199
|
+
let opened: Awaited<ReturnType<typeof runtime.factory.openAudit>>
|
|
200
|
+
try {
|
|
201
|
+
// The human typed /audit: opening it is their action.
|
|
202
|
+
opened = await runtime.factory.openAudit(
|
|
203
|
+
"human:tui",
|
|
204
|
+
parseAuditTarget(
|
|
205
|
+
target,
|
|
206
|
+
state.phases.map((phase) => phase.id),
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
} catch (error) {
|
|
210
|
+
return say(`Could not open the audit: ${error instanceof Error ? error.message : String(error)}`)
|
|
211
|
+
}
|
|
212
|
+
const { audit } = opened
|
|
213
|
+
await ctx.session.switchAgent({ sessionID, agent: "factory" } as any)
|
|
214
|
+
await ctx.session.prompt({
|
|
215
|
+
...prompt,
|
|
216
|
+
sessionID,
|
|
217
|
+
text: `${await runtime.factory.summary()}\nThe human opened code audit ${audit.id} (round ${audit.round}) on ${describeTarget(audit.target)}. Launch es-auditor-thesis and es-auditor-antithesis in parallel with the audit id and target; if they split, have es-manager break the tie (es_tiebreak with audit). Report the verdicts and the report path when the audit settles.`,
|
|
218
|
+
delivery,
|
|
219
|
+
} as any)
|
|
220
|
+
},
|
|
221
|
+
})
|
|
169
222
|
editor.add({
|
|
170
223
|
name: "factory",
|
|
171
224
|
description: "Drive the build factory from its current stage (Epistemic Swarm)",
|
|
172
225
|
execute: async ({ sessionID, prompt, delivery }) => {
|
|
173
|
-
await ctx.session.switchAgent({ sessionID, agent: "factory" } as any)
|
|
174
226
|
const state = await runtime.factory.read()
|
|
227
|
+
if (!state) {
|
|
228
|
+
await ctx.session.synthetic({
|
|
229
|
+
sessionID,
|
|
230
|
+
text: "No factory run here yet — run /grill first.",
|
|
231
|
+
} as any)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
await ctx.session.switchAgent({ sessionID, agent: "factory" } as any)
|
|
175
235
|
await ctx.session.prompt({
|
|
176
236
|
...prompt,
|
|
177
237
|
sessionID,
|
|
178
|
-
text: `${
|
|
238
|
+
text: `${await runtime.factory.summary(state)}\nContinue the factory run from its current stage.${prompt.text?.trim() ? `\nHuman note: ${prompt.text}` : ""}`,
|
|
179
239
|
delivery,
|
|
180
240
|
} as any)
|
|
181
241
|
},
|
|
@@ -241,7 +301,7 @@ export default Plugin.define({
|
|
|
241
301
|
name: "status",
|
|
242
302
|
description: "Show the factory state (Epistemic Swarm)",
|
|
243
303
|
execute: async ({ sessionID }) => {
|
|
244
|
-
await ctx.session.synthetic({ sessionID, text:
|
|
304
|
+
await ctx.session.synthetic({ sessionID, text: await runtime.factory.summary() } as any)
|
|
245
305
|
},
|
|
246
306
|
})
|
|
247
307
|
editor.add({
|
package/src/session.ts
CHANGED
|
@@ -14,15 +14,17 @@ export function createSessionHooks(runtime: Runtime) {
|
|
|
14
14
|
for (const name of ALL_ES_TOOLS) if (!visible.has(name)) delete event.tools[name]
|
|
15
15
|
if (!FACTORY_AGENTS.has(event.agent)) return
|
|
16
16
|
const state = await runtime.factory.read().catch(() => undefined)
|
|
17
|
-
|
|
17
|
+
const summary = state ? await runtime.factory.summary(state) : factorySummary(undefined)
|
|
18
|
+
event.system.push({ type: "text", text: summary })
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
const compaction = async (event: { agent: string; system: any[] }) => {
|
|
21
22
|
if (!FACTORY_AGENTS.has(event.agent)) return
|
|
22
23
|
const state = await runtime.factory.read().catch(() => undefined)
|
|
24
|
+
const summary = state ? await runtime.factory.summary(state) : factorySummary(undefined)
|
|
23
25
|
event.system.push({
|
|
24
26
|
type: "text",
|
|
25
|
-
text: `Preserve this factory state verbatim at the top of your summary; the run continues from it:\n${
|
|
27
|
+
text: `Preserve this factory state verbatim at the top of your summary; the run continues from it:\n${summary}`,
|
|
26
28
|
})
|
|
27
29
|
}
|
|
28
30
|
|
package/src/tools.ts
CHANGED
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
// action so per-agent rules can hide it. Refusals become model-facing tool errors.
|
|
4
4
|
import {
|
|
5
5
|
brainstormTools,
|
|
6
|
+
codeAuditTools,
|
|
6
7
|
designTools,
|
|
7
8
|
esTools,
|
|
8
9
|
harvestTools,
|
|
9
10
|
lspTools,
|
|
10
11
|
pendingApprovals,
|
|
12
|
+
researchOptions,
|
|
11
13
|
researchTools,
|
|
14
|
+
scoutTools,
|
|
12
15
|
} from "@heretek-ai/es-core"
|
|
13
16
|
import { Error as ToolError } from "@opencode/plugin/promise/tool"
|
|
14
17
|
import type { Runtime } from "./runtime.ts"
|
|
@@ -18,7 +21,7 @@ export function registerTools(editor: { add(tool: any): void }, runtime: Runtime
|
|
|
18
21
|
const research = researchTools({
|
|
19
22
|
root: runtime.root,
|
|
20
23
|
policy: () => runtime.policy(),
|
|
21
|
-
...(runtime.
|
|
24
|
+
...researchOptions(runtime.config),
|
|
22
25
|
})
|
|
23
26
|
const brainstorm = brainstormTools({
|
|
24
27
|
root: runtime.root,
|
|
@@ -30,8 +33,19 @@ export function registerTools(editor: { add(tool: any): void }, runtime: Runtime
|
|
|
30
33
|
stateDir: runtime.stateDir,
|
|
31
34
|
})
|
|
32
35
|
const design = designTools({ root: runtime.root })
|
|
36
|
+
const scout = scoutTools({
|
|
37
|
+
root: runtime.root,
|
|
38
|
+
whitelist: runtime.config.licenseWhitelist,
|
|
39
|
+
stateDir: runtime.stateDir,
|
|
40
|
+
halted: async () => {
|
|
41
|
+
const state = await runtime.factory.read().catch(() => undefined)
|
|
42
|
+
return state?.stage === "HALTED" ? (state.halt?.reason ?? "halted") : undefined
|
|
43
|
+
},
|
|
44
|
+
})
|
|
33
45
|
for (const def of [
|
|
34
46
|
...esTools({ ...runtime, lsp: runtime.lsp }),
|
|
47
|
+
...codeAuditTools({ ...runtime, lsp: runtime.lsp }),
|
|
48
|
+
...scout,
|
|
35
49
|
...lsp,
|
|
36
50
|
...research,
|
|
37
51
|
...brainstorm,
|