fix(channels): warn on scalar streaming fallback (#106796)

This commit is contained in:
Peter Steinberger
2026-07-13 14:27:39 -07:00
committed by GitHub
parent 2198591d0f
commit 08d7440442
4 changed files with 29 additions and 19 deletions
@@ -2,6 +2,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resetFlatStreamingKeyDeprecationWarningsForTest } from "./streaming-flat-key-deprecation.js";
import {
resolveChannelPreviewStreamMode,
resolveChannelStreamingBlockCoalesce,
resolveChannelStreamingBlockEnabled,
resolveChannelStreamingChunkMode,
@@ -56,4 +57,15 @@ describe("flat streaming key deprecation warning", () => {
expect(resolveChannelStreamingBlockCoalesce({})).toBeUndefined();
expect(loggerMocks.warn).not.toHaveBeenCalled();
});
it.each([
{ scalar: "block", expected: "block" },
{ scalar: true, expected: "partial" },
])("warns once when the scalar streaming fallback is used", ({ scalar, expected }) => {
expect(resolveChannelPreviewStreamMode({ streaming: scalar }, "off")).toBe(expected);
expect(resolveChannelPreviewStreamMode({ streaming: scalar }, "off")).toBe(expected);
expect(loggerMocks.warn).toHaveBeenCalledTimes(1);
expect(loggerMocks.warn.mock.calls[0]?.[0]).toContain('"streaming"');
expect(loggerMocks.warn.mock.calls[0]?.[0]).toContain("streaming.mode");
});
});
+4 -5
View File
@@ -95,9 +95,8 @@ describe("buildChannelProgressDraftLine", () => {
});
describe("streaming config resolution", () => {
// Flat delivery keys stay canonical for channels without a nested streaming
// schema and for SDK plugins; mode-family aliases (streamMode, scalar
// streaming, nativeStreaming) are doctor-migrated and unread at runtime.
// Flat delivery keys remain external SDK compatibility fallbacks. Bundled
// schemas are nested-only; mode-family aliases stay doctor-only.
it("resolves flat delivery keys while ignoring mode-family aliases", () => {
const legacyEntry = {
streamMode: "block",
@@ -135,8 +134,8 @@ describe("streaming config resolution", () => {
expect(resolveChannelStreamingNativeTransport(entry)).toBe(false);
});
it("keeps scalar streaming support for channels whose schema allows it", () => {
// Mattermost's schema accepts a scalar mode string or boolean as canonical.
it("keeps the scalar streaming fallback for external SDK plugin configs", () => {
// Bundled schemas are nested-only; this compatibility path is deprecated.
expect(resolveChannelPreviewStreamMode({ streaming: "block" }, "partial")).toBe("block");
expect(resolveChannelPreviewStreamMode({ streaming: true }, "off")).toBe("partial");
expect(resolveChannelPreviewStreamMode({ streaming: false }, "partial")).toBe("off");
+10 -10
View File
@@ -41,13 +41,10 @@ export type StreamingCompatEntry = {
draftChunk?: unknown;
};
// Nested streaming config wins. Every bundled channel now uses a nested-only
// streaming schema with doctor migrating the flat spellings, so in-tree the
// flat delivery keys (chunkMode, blockStreaming, blockStreamingCoalesce,
// draftChunk) are legacy config. The fallback reads below serve external SDK
// plugin configs only and emit a once-per-key deprecation warning; remove
// them (and the flat StreamingCompatEntry fields) when the next release train
// closes the SDK deprecation window.
// Bundled schemas are nested-only; doctor migrates flat delivery keys
// (chunkMode, blockStreaming, blockStreamingCoalesce, draftChunk) and scalar
// `streaming`. External SDK fallbacks warn once; remove them, the flat
// StreamingCompatEntry fields, and scalar support after the next release train.
// Mode-family aliases (streamMode) are doctor-only and stay unread here.
function asObjectRecord(value: unknown): Record<string, unknown> | null {
@@ -922,13 +919,16 @@ export function resolveChannelPreviewStreamMode(
// Scalar `streaming` (mode string or boolean) is rejected by every bundled
// channel schema and doctor-migrated to streaming.mode; the read here stays
// only for external SDK plugin configs that predate the nested shape.
const parsedStreaming = parsePreviewStreamingMode(
getChannelStreamingConfigObject(entry)?.mode ?? entry?.streaming,
);
const streamingConfig = getChannelStreamingConfigObject(entry);
const parsedStreaming = parsePreviewStreamingMode(streamingConfig?.mode ?? entry?.streaming);
if (parsedStreaming) {
if (!streamingConfig) {
warnFlatStreamingKeyFallback("streaming", "mode");
}
return parsedStreaming;
}
if (typeof entry?.streaming === "boolean") {
warnFlatStreamingKeyFallback("streaming", "mode");
return entry.streaming ? "partial" : "off";
}
return defaultMode;
+3 -4
View File
@@ -121,10 +121,9 @@ describe("channel-streaming", () => {
});
it("resolves flat delivery keys when no nested streaming config exists", () => {
// Flat delivery keys stay canonical for channels without a nested
// streaming schema (Mattermost, WhatsApp, Google Chat, IRC, Signal) and
// for external SDK plugins; mode-family aliases (streamMode, scalar
// streaming, nativeStreaming) are doctor-only and stay unread.
// Bundled channel schemas are nested-only. Flat delivery keys remain
// compatibility fallbacks for external SDK plugins; mode-family aliases
// are doctor-only and stay unread.
const entry = {
chunkMode: "newline",
blockStreaming: true,