@chatpanel/events 0.82.2 → 0.83.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/package.json +1 -1
- package/team-run.js +18 -4
- package/team-trail.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/events",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.83.1",
|
|
4
4
|
"description": "The canonical ChatPanel event-log and capability contracts \u2014 typed durable facts, clock-free deterministic linearization, schema upcasting, and the invariants the replay harness asserts. Pure, dependency-free ESM shared by the ChatPanel extension, gateway and bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
package/team-run.js
CHANGED
|
@@ -122,6 +122,11 @@ export async function runTeam({
|
|
|
122
122
|
return (appoint ? appoint(r, { exclude }) : null) || (r.model && !exclude?.has(r.model) ? { model: r.model, mode: r.mode } : null);
|
|
123
123
|
};
|
|
124
124
|
const MAX_APPOINTMENTS = 3;
|
|
125
|
+
// A model that was not there for one member is not there for the next: what failed as
|
|
126
|
+
// unavailable anywhere in this run is skipped by every later appointment. Two members
|
|
127
|
+
// each spent two minutes finding out the same agent was down.
|
|
128
|
+
const runExclude = new Set();
|
|
129
|
+
const excluding = (local) => new Set([...runExclude, ...(local || [])]);
|
|
125
130
|
const stopped = () => !!signal?.aborted;
|
|
126
131
|
|
|
127
132
|
say(resume ? 'run.resumed' : 'run.started', { team: t.name, request: String(request || ''), budget: budget.cap, roles: t.roles.map((r) => r.id), ...(resume ? { carried: [...carried] } : {}) });
|
|
@@ -215,7 +220,7 @@ export async function runTeam({
|
|
|
215
220
|
const exclude = new Set();
|
|
216
221
|
let lastErr = '';
|
|
217
222
|
for (let attempt = 1; ; attempt++) {
|
|
218
|
-
const m = modelFor(role, exclude);
|
|
223
|
+
const m = modelFor(role, excluding(exclude));
|
|
219
224
|
if (!m?.model) throw new Error(exclude.size ? `no model left for role "${role.id}" after ${[...exclude].join(', ')}` : `no model for role "${role.id}"`);
|
|
220
225
|
if (attempt > 1) say('task.reappointed', { taskId: task.id, role: role.id, model: m.model, after: [...exclude], error: lastErr });
|
|
221
226
|
// Who is doing this task, for a ledger that shows the lanes — said per attempt.
|
|
@@ -234,9 +239,18 @@ export async function runTeam({
|
|
|
234
239
|
// once, the run merged nothing, and the caller ran the team again. It is treated
|
|
235
240
|
// like an unavailable model, so the next one on the roster gets the task.
|
|
236
241
|
if (res?.ok && String(res?.text || '').trim()) { text = String(res.text); break; }
|
|
242
|
+
// A member that wrote on the board and then ran out of turn has still answered:
|
|
243
|
+
// what it posted in its own thread during this attempt is its answer. A relayed
|
|
244
|
+
// agent that posted its assessment and kept searching past the cap was being
|
|
245
|
+
// failed for the searching.
|
|
246
|
+
if (res?.ok) {
|
|
247
|
+
const th = board.threadForTask(task.id);
|
|
248
|
+
const mine = th ? board.posts(th.id).filter((p) => p.by === role.id && p.at >= t0 && ['note', 'draft', 'finding'].includes(p.kind)) : [];
|
|
249
|
+
if (mine.length) { text = mine.map((p) => p.text).join('\n\n'); say('task.note', { taskId: task.id, role: role.id, text: 'answered from its board posts' }); break; }
|
|
250
|
+
}
|
|
237
251
|
const err = res?.ok ? 'the model returned no answer' : (res?.error || 'the model did not answer');
|
|
238
252
|
if (attempt >= MAX_APPOINTMENTS || stopped() || !isModelUnavailable(err)) throw new Error(err);
|
|
239
|
-
exclude.add(m.model); lastErr = err;
|
|
253
|
+
exclude.add(m.model); runExclude.add(m.model); lastErr = err;
|
|
240
254
|
}
|
|
241
255
|
}
|
|
242
256
|
} catch (e) {
|
|
@@ -294,7 +308,7 @@ export async function runTeam({
|
|
|
294
308
|
const excl = new Set();
|
|
295
309
|
let judgeErr = '';
|
|
296
310
|
for (let attempt = 1; attempt <= MAX_APPOINTMENTS; attempt++) {
|
|
297
|
-
const mm = attempt === 1 ? m : modelFor(judge, excl);
|
|
311
|
+
const mm = attempt === 1 ? (runExclude.has(m?.model) ? modelFor(judge, excluding(excl)) : m) : modelFor(judge, excluding(excl));
|
|
298
312
|
if (!mm?.model) break;
|
|
299
313
|
if (attempt > 1) say('task.reappointed', { taskId: 'merge', role: judge.id, model: mm.model, after: [...excl], error: judgeErr });
|
|
300
314
|
say('task.model', { taskId: 'merge', role: judge.id, model: mm.model, attempt });
|
|
@@ -303,7 +317,7 @@ export async function runTeam({
|
|
|
303
317
|
if (res?.ok && String(res.text || '').trim()) break;
|
|
304
318
|
const err = res?.ok ? 'the model returned no answer' : (res?.error || 'the model did not answer');
|
|
305
319
|
if (stopped() || !isModelUnavailable(err)) break;
|
|
306
|
-
excl.add(mm.model); judgeErr = err;
|
|
320
|
+
excl.add(mm.model); runExclude.add(mm.model); judgeErr = err;
|
|
307
321
|
}
|
|
308
322
|
const judged = res?.ok && String(res.text || '').trim();
|
|
309
323
|
say(judged ? 'task.done' : 'task.failed', { taskId: 'merge', role: judge.id, status: judged ? 'ok' : 'failed', error: judged ? null : (res?.error || 'the judge did not answer'), findings: 0 });
|
package/team-trail.js
CHANGED
|
@@ -35,6 +35,7 @@ export function teamLanes(prev, ev) {
|
|
|
35
35
|
case 'task.started': lanes.tasks[ev.taskId] = { ...(lanes.tasks[ev.taskId] || { id: ev.taskId, role: ev.role, title: ev.title }), status: 'running' }; break;
|
|
36
36
|
case 'task.delta': if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], text: ev.text }; break;
|
|
37
37
|
case 'task.finding': lanes.findings += 1; if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], findings: (lanes.tasks[ev.taskId].findings || 0) + 1 }; break;
|
|
38
|
+
case 'task.note': return { type: 'status', text: `${role}: ${ev.text}` };
|
|
38
39
|
case 'task.model': if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], model: ev.model }; break;
|
|
39
40
|
case 'task.tool': if (lanes.tasks[ev.taskId]) lanes.tasks[ev.taskId] = { ...lanes.tasks[ev.taskId], tools: (lanes.tasks[ev.taskId].tools || 0) + 1, lastTool: ev.text ? `${ev.name} ${ev.text}` : ev.name }; break;
|
|
40
41
|
case 'run.usage': lanes.usage = ev.usage; break;
|