Files
openclaw/src/gateway/protocol/schema/logs-chat.ts
Vincent Koc 563a125c66 fix(gateway): stop shared-main chat.send from inheriting stale external routes (#38418)
* 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>
2026-03-06 21:59:08 -05:00

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 },
);