@cubicecho/agent-core 2.2.1 → 2.2.2

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/retry.d.ts CHANGED
@@ -33,10 +33,11 @@ export declare const compact: (tokens: number) => string;
33
33
  * built the entire transcript into a string on every call and threw it away having read nothing
34
34
  * but its `.length` — against a transcript that grows by a turn each turn, and one the SDK is
35
35
  * about to serialise again to send. What the walk misses is JSON's own punctuation and the keys,
36
- * which the envelope constants put back — one per key rather than one per message, since the
37
- * three keys only some shapes carry are most of what a tool-using transcript is made of. What
38
- * is left is a message's escaping, which is not a constant and is small against an estimate
39
- * that is already characters over four.
36
+ * which the envelope constants put back — one per key and one per content part, rather than one
37
+ * per message, since the keys only some shapes carry and the parts a client appends block by
38
+ * block are most of what a tool-using transcript is made of. What is left is a message's
39
+ * escaping, which is not a constant and is small against an estimate that is already characters
40
+ * over four.
40
41
  *
41
42
  * @param body The request as it will be sent, tools included.
42
43
  */
package/dist/retry.js CHANGED
@@ -40,6 +40,14 @@ const NAME_KEY = 10;
40
40
  const TOOL_CALL_ID_KEY = 18;
41
41
  /** The same for `"tool_calls":[]` around the calls; each call's own comma is in `CALL_ENVELOPE`. */
42
42
  const TOOL_CALLS_KEY = 15;
43
+ // A content part is an object in the body the same way a message is, and its two keys are in the
44
+ // request exactly as `tool_call_id` was. Charging only `part.text` left them out, which is 6.5
45
+ // tokens per part — short in proportion to how finely the content is split rather than to how
46
+ // much it says, so a transcript a client appends block by block is worst hit.
47
+ /** What `{"type":"text","text":""},` costs around a text part. */
48
+ const TEXT_PART = 26;
49
+ /** The same for `{"type":"refusal","refusal":""},` around a refusal part. */
50
+ const REFUSAL_PART = 32;
43
51
  /** The divisor behind `estimateTokens`, applied here to a character count rather than a string. */
44
52
  const CHARS_PER_TOKEN = 4;
45
53
  /** How many characters one message is worth: its keys, and its content in whichever shape. */
@@ -51,11 +59,13 @@ function messageChars(message) {
51
59
  else if (Array.isArray(content))
52
60
  for (const part of content) {
53
61
  // Text and refusal parts carry their own strings; an image or an audio part carries a URL
54
- // or a blob, and neither is priced by its length anyway.
62
+ // or a blob, and neither is priced by its length anyway — a vision model does not charge
63
+ // an image by its base64 length, so counting the data URL would overshoot by more than
64
+ // leaving the part out undershoots.
55
65
  if (part.type === "text")
56
- chars += part.text.length;
66
+ chars += TEXT_PART + part.text.length;
57
67
  else if (part.type === "refusal")
58
- chars += part.refusal.length;
68
+ chars += REFUSAL_PART + part.refusal.length;
59
69
  }
60
70
  if ("name" in message && typeof message.name === "string")
61
71
  chars += NAME_KEY + message.name.length;
@@ -105,10 +115,11 @@ function toolsCost(tools) {
105
115
  * built the entire transcript into a string on every call and threw it away having read nothing
106
116
  * but its `.length` — against a transcript that grows by a turn each turn, and one the SDK is
107
117
  * about to serialise again to send. What the walk misses is JSON's own punctuation and the keys,
108
- * which the envelope constants put back — one per key rather than one per message, since the
109
- * three keys only some shapes carry are most of what a tool-using transcript is made of. What
110
- * is left is a message's escaping, which is not a constant and is small against an estimate
111
- * that is already characters over four.
118
+ * which the envelope constants put back — one per key and one per content part, rather than one
119
+ * per message, since the keys only some shapes carry and the parts a client appends block by
120
+ * block are most of what a tool-using transcript is made of. What is left is a message's
121
+ * escaping, which is not a constant and is small against an estimate that is already characters
122
+ * over four.
112
123
  *
113
124
  * @param body The request as it will be sent, tools included.
114
125
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubicecho/agent-core",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
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",