* fix(gateway): prevent webchat messages from cross-routing to external channels
chat.send always originates from the webchat/control-UI surface. Previously,
channel-scoped session keys (e.g. agent:main:slack:direct:U…) caused
OriginatingChannel to inherit the session's stored external route, so the
reply dispatcher would route responses to Slack/Telegram instead of back to
the gateway connection. Remove the route-inheritance logic from chat.send and
always set OriginatingChannel to INTERNAL_MESSAGE_CHANNEL ("webchat").
Closes #34647
Made-with: Cursor
* Gateway: preserve configured-main connect gating
* Gateway: cover connect-without-client routing
* Gateway: add chat.send session key length limit
* Gateway: cap chat.send session key schema
* Gateway: bound chat.send session key parsing
* Gateway: cover oversized chat.send session keys
* Update CHANGELOG.md
---------
Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
import { Type } from "@sinclair/typebox";
|
|
import { ChatSendSessionKeyString, NonEmptyString } from "./primitives.js";
|
|
|
|
export const LogsTailParamsSchema = Type.Object(
|
|
{
|
|
cursor: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 5000 })),
|
|
maxBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 1_000_000 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const LogsTailResultSchema = Type.Object(
|
|
{
|
|
file: NonEmptyString,
|
|
cursor: Type.Integer({ minimum: 0 }),
|
|
size: Type.Integer({ minimum: 0 }),
|
|
lines: Type.Array(Type.String()),
|
|
truncated: Type.Optional(Type.Boolean()),
|
|
reset: Type.Optional(Type.Boolean()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
// WebChat/WebSocket-native chat methods
|
|
export const ChatHistoryParamsSchema = Type.Object(
|
|
{
|
|
sessionKey: NonEmptyString,
|
|
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const ChatSendParamsSchema = Type.Object(
|
|
{
|
|
sessionKey: ChatSendSessionKeyString,
|
|
message: Type.String(),
|
|
thinking: Type.Optional(Type.String()),
|
|
deliver: Type.Optional(Type.Boolean()),
|
|
attachments: Type.Optional(Type.Array(Type.Unknown())),
|
|
timeoutMs: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
idempotencyKey: NonEmptyString,
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const ChatAbortParamsSchema = Type.Object(
|
|
{
|
|
sessionKey: NonEmptyString,
|
|
runId: Type.Optional(NonEmptyString),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const ChatInjectParamsSchema = Type.Object(
|
|
{
|
|
sessionKey: NonEmptyString,
|
|
message: NonEmptyString,
|
|
label: Type.Optional(Type.String({ maxLength: 100 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
|
|
export const ChatEventSchema = Type.Object(
|
|
{
|
|
runId: NonEmptyString,
|
|
sessionKey: NonEmptyString,
|
|
seq: Type.Integer({ minimum: 0 }),
|
|
state: Type.Union([
|
|
Type.Literal("delta"),
|
|
Type.Literal("final"),
|
|
Type.Literal("aborted"),
|
|
Type.Literal("error"),
|
|
]),
|
|
message: Type.Optional(Type.Unknown()),
|
|
errorMessage: Type.Optional(Type.String()),
|
|
usage: Type.Optional(Type.Unknown()),
|
|
stopReason: Type.Optional(Type.String()),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|