@cubicecho/agent-core 2.0.3 → 2.0.4

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.
@@ -30,6 +30,8 @@ export function capabilitiesFor(baseUrl) {
30
30
  export function resetCapabilities() {
31
31
  capabilities.clear();
32
32
  }
33
+ /** Every flag on a `Capabilities`, typed, so a third one is compared without an edit here. */
34
+ const keys = (of) => Object.keys(of);
33
35
  /** `stream_options` is named in the refusal by every server that has not heard of it. */
34
36
  const REJECTS_USAGE = /stream_options/i;
35
37
  /**
@@ -61,6 +63,10 @@ const REJECTS_USAGE = /stream_options/i;
61
63
  */
62
64
  export async function negotiate(supports, send, { produced = { any: false }, onNotice } = {}) {
63
65
  for (;;) {
66
+ // What this attempt was built with. `capabilitiesFor` hands one object per endpoint to
67
+ // everyone on it, so a run starting alongside this one may latch a flag off while this call
68
+ // is in flight — and the branches below are guarded on the flag still being set.
69
+ const sent = { ...supports };
64
70
  try {
65
71
  return await send(supports, produced);
66
72
  }
@@ -76,9 +82,16 @@ export async function negotiate(supports, send, { produced = { any: false }, onN
76
82
  supports.usageInStream = false;
77
83
  onNotice?.("server rejected stream_options; token counts unavailable");
78
84
  }
79
- else {
85
+ else if (keys(sent).every((flag) => sent[flag] === supports[flag])) {
80
86
  throw error;
81
87
  }
88
+ // Otherwise the refusal was answered by whoever got there first, and this attempt was
89
+ // built before the answer existed. Two runs opening on a fresh llama.cpp box both get the
90
+ // grammar error; the first latches it off and re-sends, and the second used to find the
91
+ // flag already clear, fall through to the throw and die on an error the process had just
92
+ // learned to fix — `isTransient` refuses a 400, so `runTurn` would not send it again
93
+ // either. Sending it again is the whole of the fix: flags only ever latch off, so this
94
+ // gives up after one pass per flag.
82
95
  }
83
96
  }
84
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubicecho/agent-core",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "The endpoint-agnostic half of an OpenAI-compatible agent loop: tool-schema compatibility, on-demand tool loading, one-shot side tasks, run events, and a pooled client.",
5
5
  "keywords": [
6
6
  "openai",