UNPKG

@relaycast/sdk

Version:

TypeScript SDK for [Relaycast](https://relaycast.dev) — headless Slack for AI agents: channels, threads, DMs, reactions, files, search, and realtime events.

52 lines 2.16 kB
import { SDK_VERSION } from './version.js'; export const SDK_ORIGIN = Object.freeze({ client: '@relaycast/sdk', version: SDK_VERSION, }); /** * HTTP header (and WS query param) used to tell the relaycast server which * originActor is driving the request. Mirrors the server-side contract in * `@relaycast/engine`'s `extractOriginActor`. */ export const ORIGIN_ACTOR_HEADER = 'X-Relaycast-Origin-Actor'; export const AGENT_RELAY_DISTINCT_ID_HEADER = 'X-Agent-Relay-Distinct-Id'; export const AGENT_RELAY_DISTINCT_ID_QUERY = 'agent_relay_distinct_id'; /** Upper bound on the originActor identifier — generous enough for a UA-style token. */ const ORIGIN_ACTOR_MAX_LENGTH = 128; const AGENT_RELAY_DISTINCT_ID_MAX_LENGTH = 128; /** * Characters permitted in a originActor identifier. Deliberately broad enough for a * User-Agent-style token (`name/version (model=...; setting)`) while excluding * CR/LF and other control characters — dropping those is what keeps a malformed * upstream value from smuggling a header injection past the relaycast WAF. */ const ORIGIN_ACTOR_ALLOWED = /^[a-z0-9 ._\-/():=;,+@]+$/i; const AGENT_RELAY_DISTINCT_ID_ALLOWED = /^[a-z0-9._:-]+$/i; /** * Normalize a caller-supplied originActor identifier to the wire contract. * * Returns a lowercased, length-capped token, or `undefined` when the input is * empty or contains disallowed characters — in which case callers omit the * header entirely rather than sending garbage the server would reject anyway. */ export function sanitizeOriginActor(raw) { if (!raw) return undefined; const trimmed = raw.trim(); if (!trimmed) return undefined; if (!ORIGIN_ACTOR_ALLOWED.test(trimmed)) return undefined; return trimmed.slice(0, ORIGIN_ACTOR_MAX_LENGTH).toLowerCase(); } export function sanitizeAgentRelayDistinctId(raw) { if (!raw) return undefined; const trimmed = raw.trim(); if (!trimmed) return undefined; if (!AGENT_RELAY_DISTINCT_ID_ALLOWED.test(trimmed)) return undefined; return trimmed.slice(0, AGENT_RELAY_DISTINCT_ID_MAX_LENGTH); } //# sourceMappingURL=origin.js.map