@boardwalk-labs/runner 0.2.1 → 0.2.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.
@@ -238,7 +238,13 @@ export class EngineLeafExecutor {
238
238
  providerIo.onDelta?.(frame.text);
239
239
  }
240
240
  else if (frame.kind === "result") {
241
- result = { turn: frame.turn, modelRef: frame.modelRef };
241
+ // contextTokens (when the broker knows the served model's window) lets the engine's loop
242
+ // size compaction against the real window instead of a conservative default.
243
+ result = {
244
+ turn: frame.turn,
245
+ modelRef: frame.modelRef,
246
+ ...(frame.contextTokens !== undefined ? { contextTokens: frame.contextTokens } : {}),
247
+ };
242
248
  // The broker stamps the turn's exact upstream cost on the result frame (0 ⇒ none / BYO); hand
243
249
  // it to the budget guardrail via the caller's stash so max_usd caps on real spend.
244
250
  if (frame.costMicros > 0)
@@ -41,6 +41,7 @@ export type InferenceFrame = {
41
41
  turn: ChatTurn;
42
42
  modelRef: string;
43
43
  costMicros: number;
44
+ contextTokens?: number;
44
45
  } | {
45
46
  kind: "error";
46
47
  error: ProxyError;
@@ -60,7 +61,7 @@ export declare function serializeDeltaFrame(text: string): string;
60
61
  /** Serialize the single terminal turn result as one NDJSON line. `costMicros` is the turn's EXACT
61
62
  * upstream cost (the managed provider's per-request cost × 1e6) on the managed lane — 0 for BYO or when unavailable.
62
63
  * The worker feeds it to the budget guardrail so `max_usd` tracks real spend, not a token estimate. */
63
- export declare function serializeResultFrame(turn: ChatTurn, modelRef: string, costMicros?: number): string;
64
+ export declare function serializeResultFrame(turn: ChatTurn, modelRef: string, costMicros?: number, contextTokens?: number): string;
64
65
  /** Serialize a terminal error as a single NDJSON line. */
65
66
  export declare function serializeErrorFrame(error: ProxyError): string;
66
67
  /** Serialize a heartbeat (no payload) as a single NDJSON line. The broker emits these on an interval
@@ -15,7 +15,8 @@
15
15
  // many text deltas; NDJSON lets the runner consume them incrementally over the raw socket (the
16
16
  // buffered REST path can't stream). Each frame is one of:
17
17
  // { "t": "delta", "text": <string> } — a streamed assistant-text chunk
18
- // { "t": "result", "turn": <ChatTurn>, "modelRef": <string>, "costMicros": <number> } — terminal turn
18
+ // { "t": "result", "turn": <ChatTurn>, "modelRef": <string>, "costMicros": <number>,
19
+ // "contextTokens"?: <number> } — terminal turn
19
20
  // { "t": "error", "error": { code, message } } — a terminal model/broker error
20
21
  //
21
22
  // A well-formed stream is zero-or-more `delta` frames followed by EXACTLY ONE `result` frame, OR a
@@ -80,8 +81,15 @@ export function serializeDeltaFrame(text) {
80
81
  /** Serialize the single terminal turn result as one NDJSON line. `costMicros` is the turn's EXACT
81
82
  * upstream cost (the managed provider's per-request cost × 1e6) on the managed lane — 0 for BYO or when unavailable.
82
83
  * The worker feeds it to the budget guardrail so `max_usd` tracks real spend, not a token estimate. */
83
- export function serializeResultFrame(turn, modelRef, costMicros = 0) {
84
- return `${JSON.stringify({ t: "result", turn, modelRef, costMicros })}\n`;
84
+ export function serializeResultFrame(turn, modelRef, costMicros = 0, contextTokens) {
85
+ const frame = {
86
+ t: "result",
87
+ turn,
88
+ modelRef,
89
+ costMicros,
90
+ ...(contextTokens !== undefined ? { contextTokens } : {}),
91
+ };
92
+ return `${JSON.stringify(frame)}\n`;
85
93
  }
86
94
  /** Serialize a terminal error as a single NDJSON line. */
87
95
  export function serializeErrorFrame(error) {
@@ -110,6 +118,11 @@ export function parseInferenceFrame(line) {
110
118
  // A pre-cost-forwarding broker (rolling deploy) omits this → 0 → the worker falls back to the
111
119
  // representative-rate estimate, exactly as before. Non-number / negative also clamps to 0.
112
120
  costMicros: typeof rec.costMicros === "number" && rec.costMicros > 0 ? rec.costMicros : 0,
121
+ // The served model's context window; absent from a pre-window broker (rolling deploy) or
122
+ // when its catalog can't say ⇒ the agent loop keeps its conservative default budget.
123
+ ...(typeof rec.contextTokens === "number" && rec.contextTokens > 0
124
+ ? { contextTokens: rec.contextTokens }
125
+ : {}),
113
126
  };
114
127
  case "error":
115
128
  return { kind: "error", error: toProxyError(rec.error) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boardwalk-labs/runner",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "description": "Boardwalk self-hosted runner: execute cloud-scheduled runs on your own machines. Currently: the canonical runner contract types.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -53,8 +53,8 @@
53
53
  "prebuild": "prebuildify --napi --strip -t 24.0.0"
54
54
  },
55
55
  "dependencies": {
56
- "@boardwalk-labs/engine": "^0.2.0",
57
- "@boardwalk-labs/workflow": "^0.2.0",
56
+ "@boardwalk-labs/engine": "0.2.3",
57
+ "@boardwalk-labs/workflow": "0.2.1",
58
58
  "@modelcontextprotocol/sdk": "^1.29.0",
59
59
  "node-gyp-build": "^4.8.4",
60
60
  "tar": "^7.5.16",