@chatpanel/events 0.80.0 → 0.80.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/team-run.js +10 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/events",
3
- "version": "0.80.0",
3
+ "version": "0.80.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
@@ -51,7 +51,10 @@ const strongestRole = (team) => [...team.roles].sort((a, b) => (TIER[b.prefer] ?
51
51
  */
52
52
  export function isModelUnavailable(error) {
53
53
  const m = String(error?.message || error || '');
54
- return /model[_ ]not[_ ]found|not found|not deployed|inaccessible|does not exist|no such model|unknown model|unsupported model|not available|unavailable|no api key|not configured|"status":\s*(404|401|403)\b|\b(404|401|403)\b/i.test(m);
54
+ // Also: a relayed agent that exited, a provider that closed the stream, and a turn that
55
+ // came back with nothing — the model did not answer, and the next one might. A refusal,
56
+ // a timeout the caller set, a bad request or a budget stop are not this.
57
+ return /model[_ ]not[_ ]found|not found|not deployed|inaccessible|does not exist|no such model|unknown model|unsupported model|not available|unavailable|no api key|not configured|"status":\s*(404|401|403|500|502|503)\b|\b(404|401|403|502|503)\b|exited \d+|returned no answer|did not answer|closed the connection|couldn't reach|could not reach|ECONNREFUSED|overloaded|capacity/i.test(m);
55
58
  }
56
59
 
57
60
  export function dryRunTeam(team, request, { appoint = null } = {}) {
@@ -171,15 +174,12 @@ export async function runTeam({
171
174
  usage = res?.usage || null;
172
175
  if (usage) budget.charge(usage);
173
176
  if (res?.aborted) { status = 'stopped'; break; }
174
- if (res?.ok) {
175
- text = String(res?.text || '');
176
- // A turn that ended with nothing to say an agent that exited, a stream that
177
- // died after its tool calls is not a done task. Three members "completed"
178
- // empty once, the run merged nothing, and the caller ran the team again.
179
- if (!text.trim()) throw new Error('the model returned no answer');
180
- break;
181
- }
182
- const err = res?.error || 'the model did not answer';
177
+ // A turn that ended with nothing to say — an agent that exited, a stream that
178
+ // died after its tool calls — is not a done task: three members "completed" empty
179
+ // once, the run merged nothing, and the caller ran the team again. It is treated
180
+ // like an unavailable model, so the next one on the roster gets the task.
181
+ if (res?.ok && String(res?.text || '').trim()) { text = String(res.text); break; }
182
+ const err = res?.ok ? 'the model returned no answer' : (res?.error || 'the model did not answer');
183
183
  if (attempt >= MAX_APPOINTMENTS || stopped() || !isModelUnavailable(err)) throw new Error(err);
184
184
  exclude.add(m.model);
185
185
  }