@jeffusion/bungee-llms 5.12.0 → 5.14.0

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/index.js CHANGED
@@ -4407,7 +4407,7 @@ class AnthropicToOpenAIConverter {
4407
4407
  }
4408
4408
  }
4409
4409
  async processStreamChunk(chunk, ctx) {
4410
- if (this.isResponsesStreamChunk(chunk)) {
4410
+ if (this.isResponsesStreamChunk(chunk, ctx)) {
4411
4411
  return this.processResponsesStreamChunk(chunk, ctx);
4412
4412
  }
4413
4413
  const events = [];
@@ -4671,8 +4671,8 @@ class AnthropicToOpenAIConverter {
4671
4671
  }
4672
4672
  return [];
4673
4673
  }
4674
- isResponsesStreamChunk(chunk) {
4675
- const eventType = typeof chunk?._event === "string" ? chunk._event : "";
4674
+ isResponsesStreamChunk(chunk, ctx) {
4675
+ const eventType = ctx.sseEvent?.event ?? "";
4676
4676
  const type = typeof chunk?.type === "string" ? chunk.type : "";
4677
4677
  if (eventType.startsWith("response."))
4678
4678
  return true;
@@ -4682,7 +4682,7 @@ class AnthropicToOpenAIConverter {
4682
4682
  }
4683
4683
  async processResponsesStreamChunk(chunk, ctx) {
4684
4684
  const events = [];
4685
- const eventType = typeof chunk?._event === "string" && chunk._event.length > 0 ? chunk._event : chunk.type;
4685
+ const eventType = ctx.sseEvent?.event || chunk.type;
4686
4686
  const ensureMessageStarted = () => {
4687
4687
  if (!ctx.streamState.has("message_started")) {
4688
4688
  events.push({
@@ -7597,7 +7597,7 @@ function isDeferredFailure(body) {
7597
7597
  const type = asString2(body.type)?.toLowerCase();
7598
7598
  return isErrorResponse(body) || status === "incomplete" || type === "incomplete" || type?.endsWith(".incomplete") === true;
7599
7599
  }
7600
- function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true) {
7600
+ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true, event) {
7601
7601
  if (state.outputAuthority === "official")
7602
7602
  return;
7603
7603
  let nodes = MAX_INPUT_ESTIMATE_NODES;
@@ -7605,7 +7605,7 @@ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true) {
7605
7605
  if (isDeferred(state))
7606
7606
  state.estimateTruncated = true;
7607
7607
  };
7608
- const type = asString2(chunk.type);
7608
+ const type = event ?? asString2(chunk.type);
7609
7609
  if (type === "response.output_text.delta") {
7610
7610
  if (isDeferred(state))
7611
7611
  observeBoundedOutput(state, chunk.delta);
@@ -7969,7 +7969,7 @@ function createOpenAIAdapter() {
7969
7969
  outputAuthority: state.outputAuthority
7970
7970
  }, isIncomplete || isFailed ? "failed" : "completed");
7971
7971
  },
7972
- consumeStreamChunk(state, chunk) {
7972
+ consumeStreamChunk(state, chunk, event) {
7973
7973
  if (state.finalReceived || isDoneSentinel(chunk))
7974
7974
  return null;
7975
7975
  const response = readRecord(chunk, "response");
@@ -7989,10 +7989,10 @@ function createOpenAIAdapter() {
7989
7989
  const reportedCache = readNumber(promptDetails, "cached_tokens");
7990
7990
  if (reportedCache !== undefined)
7991
7991
  state.cacheReadTokens = reportedCache;
7992
- const responseType = asString2(chunk.type);
7992
+ const responseType = event ?? asString2(chunk.type);
7993
7993
  const responseStatus = asString2(response?.status);
7994
7994
  const responseCompleted = responseType === "response.completed" || responseStatus === "completed";
7995
- observeOpenAIOutput(state, chunk, !responseCompleted);
7995
+ observeOpenAIOutput(state, chunk, !responseCompleted, event);
7996
7996
  const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
7997
7997
  if (choices.some((choice) => isRecord6(choice) && asString2(choice.finish_reason) !== undefined && choice.finish_reason !== null)) {
7998
7998
  state.protocolTerminalSeen = true;
@@ -8160,10 +8160,10 @@ function createAnthropicAdapter() {
8160
8160
  outputAuthority: estimatedOutput === undefined ? "none" : "local"
8161
8161
  });
8162
8162
  },
8163
- consumeStreamChunk(state, chunk) {
8163
+ consumeStreamChunk(state, chunk, event) {
8164
8164
  if (state.finalReceived || isDoneSentinel(chunk))
8165
8165
  return null;
8166
- const type = asString2(chunk.type);
8166
+ const type = event ?? asString2(chunk.type);
8167
8167
  if (isDeferred(state) && type === "error") {
8168
8168
  state.protocolTerminalSeen = true;
8169
8169
  state.deferredOutcome = "failed";
@@ -8373,7 +8373,7 @@ function createGeminiAdapter() {
8373
8373
  outputAuthority: state.outputAuthority
8374
8374
  });
8375
8375
  },
8376
- consumeStreamChunk(state, chunk) {
8376
+ consumeStreamChunk(state, chunk, event) {
8377
8377
  if (state.finalReceived || isDoneSentinel(chunk))
8378
8378
  return null;
8379
8379
  observeGeminiOutput(state, chunk);
@@ -8504,8 +8504,8 @@ function createTokenAccountingSession(input, options = {}) {
8504
8504
  terminalEvent = event;
8505
8505
  return event;
8506
8506
  },
8507
- consumeStreamChunk({ chunk }) {
8508
- const event = adapter.consumeStreamChunk(state, chunk);
8507
+ consumeStreamChunk({ chunk, event: eventName }) {
8508
+ const event = adapter.consumeStreamChunk(state, chunk, eventName);
8509
8509
  if (event && (event.final || event.outcome !== "completed"))
8510
8510
  terminalEvent = event;
8511
8511
  return event;
@@ -1925,7 +1925,7 @@ class AnthropicToOpenAIConverter {
1925
1925
  }
1926
1926
  }
1927
1927
  async processStreamChunk(chunk, ctx) {
1928
- if (this.isResponsesStreamChunk(chunk)) {
1928
+ if (this.isResponsesStreamChunk(chunk, ctx)) {
1929
1929
  return this.processResponsesStreamChunk(chunk, ctx);
1930
1930
  }
1931
1931
  const events = [];
@@ -2189,8 +2189,8 @@ class AnthropicToOpenAIConverter {
2189
2189
  }
2190
2190
  return [];
2191
2191
  }
2192
- isResponsesStreamChunk(chunk) {
2193
- const eventType = typeof chunk?._event === "string" ? chunk._event : "";
2192
+ isResponsesStreamChunk(chunk, ctx) {
2193
+ const eventType = ctx.sseEvent?.event ?? "";
2194
2194
  const type = typeof chunk?.type === "string" ? chunk.type : "";
2195
2195
  if (eventType.startsWith("response."))
2196
2196
  return true;
@@ -2200,7 +2200,7 @@ class AnthropicToOpenAIConverter {
2200
2200
  }
2201
2201
  async processResponsesStreamChunk(chunk, ctx) {
2202
2202
  const events = [];
2203
- const eventType = typeof chunk?._event === "string" && chunk._event.length > 0 ? chunk._event : chunk.type;
2203
+ const eventType = ctx.sseEvent?.event || chunk.type;
2204
2204
  const ensureMessageStarted = () => {
2205
2205
  if (!ctx.streamState.has("message_started")) {
2206
2206
  events.push({
@@ -7603,7 +7603,7 @@ function isDeferredFailure(body) {
7603
7603
  const type = asString2(body.type)?.toLowerCase();
7604
7604
  return isErrorResponse(body) || status === "incomplete" || type === "incomplete" || type?.endsWith(".incomplete") === true;
7605
7605
  }
7606
- function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true) {
7606
+ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true, event) {
7607
7607
  if (state.outputAuthority === "official")
7608
7608
  return;
7609
7609
  let nodes = MAX_INPUT_ESTIMATE_NODES;
@@ -7611,7 +7611,7 @@ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true) {
7611
7611
  if (isDeferred(state))
7612
7612
  state.estimateTruncated = true;
7613
7613
  };
7614
- const type = asString2(chunk.type);
7614
+ const type = event ?? asString2(chunk.type);
7615
7615
  if (type === "response.output_text.delta") {
7616
7616
  if (isDeferred(state))
7617
7617
  observeBoundedOutput(state, chunk.delta);
@@ -7975,7 +7975,7 @@ function createOpenAIAdapter() {
7975
7975
  outputAuthority: state.outputAuthority
7976
7976
  }, isIncomplete || isFailed ? "failed" : "completed");
7977
7977
  },
7978
- consumeStreamChunk(state, chunk) {
7978
+ consumeStreamChunk(state, chunk, event) {
7979
7979
  if (state.finalReceived || isDoneSentinel(chunk))
7980
7980
  return null;
7981
7981
  const response = readRecord(chunk, "response");
@@ -7995,10 +7995,10 @@ function createOpenAIAdapter() {
7995
7995
  const reportedCache = readNumber(promptDetails, "cached_tokens");
7996
7996
  if (reportedCache !== undefined)
7997
7997
  state.cacheReadTokens = reportedCache;
7998
- const responseType = asString2(chunk.type);
7998
+ const responseType = event ?? asString2(chunk.type);
7999
7999
  const responseStatus = asString2(response?.status);
8000
8000
  const responseCompleted = responseType === "response.completed" || responseStatus === "completed";
8001
- observeOpenAIOutput(state, chunk, !responseCompleted);
8001
+ observeOpenAIOutput(state, chunk, !responseCompleted, event);
8002
8002
  const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
8003
8003
  if (choices.some((choice) => isRecord6(choice) && asString2(choice.finish_reason) !== undefined && choice.finish_reason !== null)) {
8004
8004
  state.protocolTerminalSeen = true;
@@ -8166,10 +8166,10 @@ function createAnthropicAdapter() {
8166
8166
  outputAuthority: estimatedOutput === undefined ? "none" : "local"
8167
8167
  });
8168
8168
  },
8169
- consumeStreamChunk(state, chunk) {
8169
+ consumeStreamChunk(state, chunk, event) {
8170
8170
  if (state.finalReceived || isDoneSentinel(chunk))
8171
8171
  return null;
8172
- const type = asString2(chunk.type);
8172
+ const type = event ?? asString2(chunk.type);
8173
8173
  if (isDeferred(state) && type === "error") {
8174
8174
  state.protocolTerminalSeen = true;
8175
8175
  state.deferredOutcome = "failed";
@@ -8379,7 +8379,7 @@ function createGeminiAdapter() {
8379
8379
  outputAuthority: state.outputAuthority
8380
8380
  });
8381
8381
  },
8382
- consumeStreamChunk(state, chunk) {
8382
+ consumeStreamChunk(state, chunk, event) {
8383
8383
  if (state.finalReceived || isDoneSentinel(chunk))
8384
8384
  return null;
8385
8385
  observeGeminiOutput(state, chunk);
@@ -8510,8 +8510,8 @@ function createTokenAccountingSession(input, options = {}) {
8510
8510
  terminalEvent = event;
8511
8511
  return event;
8512
8512
  },
8513
- consumeStreamChunk({ chunk }) {
8514
- const event = adapter.consumeStreamChunk(state, chunk);
8513
+ consumeStreamChunk({ chunk, event: eventName }) {
8514
+ const event = adapter.consumeStreamChunk(state, chunk, eventName);
8515
8515
  if (event && (event.final || event.outcome !== "completed"))
8516
8516
  terminalEvent = event;
8517
8517
  return event;
@@ -9,6 +9,13 @@ export interface ResponseContext {
9
9
  [key: string]: any;
10
10
  }
11
11
  export interface StreamChunkContext {
12
+ /** SSE metadata belongs to the transport envelope, not the JSON object. */
13
+ sseEvent?: {
14
+ event?: string;
15
+ id?: string;
16
+ retry?: string;
17
+ comments?: string[];
18
+ };
12
19
  streamState: Map<string, any>;
13
20
  chunkIndex?: number;
14
21
  isFirstChunk?: boolean;
@@ -39,6 +39,8 @@ export interface TokenAccountingResponseInput {
39
39
  body: Record<string, unknown>;
40
40
  }
41
41
  export interface TokenAccountingStreamChunkInput {
42
+ /** Independent SSE event name; never injected into JSON. */
43
+ event?: string;
42
44
  chunk: Record<string, unknown>;
43
45
  }
44
46
  export interface TokenAccountingSession {
@@ -93,7 +95,7 @@ export interface ProviderTokenAccountingAdapter {
93
95
  readonly capabilities: ProviderTokenAccountingCapabilities;
94
96
  consumeRequest(state: TokenAccountingSessionState, body: Record<string, unknown>): void;
95
97
  consumeResponse(state: TokenAccountingSessionState, body: Record<string, unknown>): CanonicalTokenAccountingEventV2;
96
- consumeStreamChunk(state: TokenAccountingSessionState, chunk: Record<string, unknown>): CanonicalTokenAccountingEventV2 | null;
98
+ consumeStreamChunk(state: TokenAccountingSessionState, chunk: Record<string, unknown>, event?: string): CanonicalTokenAccountingEventV2 | null;
97
99
  finalizeCompletedStream(state: TokenAccountingSessionState): CanonicalTokenAccountingEventV2;
98
100
  finalizeAbortedStream(state: TokenAccountingSessionState): CanonicalTokenAccountingEventV2;
99
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jeffusion/bungee-llms",
3
- "version": "5.12.0",
3
+ "version": "5.14.0",
4
4
  "description": "Extensible LLM adapters and protocol conversion package for Bungee",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,7 +11,7 @@
11
11
  "prepublishOnly": "bun run build"
12
12
  },
13
13
  "dependencies": {
14
- "@jeffusion/bungee-types": "^5.12.0"
14
+ "@jeffusion/bungee-types": "^5.14.0"
15
15
  },
16
16
  "devDependencies": {
17
17
  "bun-types": "^1.3.2",