Artur Mukhamadiev 3751ab26b5 deadline: configurable protocol maximum (default 900 s); book favicon
The 180 s query cap was enforced independently by the backend clamp, the
agent limits, and the container supervisor. All three now follow
CONFLUENCE_WEB_MAX_DEADLINE_SECONDS (default 900, allowed 60-3600): the
backend passes it into the container at launch, the supervisor reads it and
forwards it to the bridge, and both fall back to 900 s on invalid input. The
query timeout must not exceed it (startup fails otherwise). The supervisor
keeps a separate 180 s guard for a container that never receives a start
frame.

Add assets/book.svg as the tab icon: the backend serves assets/ and the CSP
allows same-origin images (the sanitizer still never emits <img>).
2026-09-15 13:38:44 +03:00

264 lines
5.7 KiB
TypeScript

/**
* Protocol types and limits defined in CONTRACTS.md Revision 1
*/
export const PROTOCOL_VERSION = 1;
// Size limits in bytes
export const KIB = 1024;
export const MIB = 1024 * 1024;
/**
* Protocol maximum for one query in milliseconds. The backend sets
* CONFLUENCE_WEB_MAX_DEADLINE_SECONDS on the container; the supervisor forwards
* it. Invalid or absent values fall back to 900 s (15 minutes).
*/
function maxDeadlineMs(): number {
const raw = typeof process !== 'undefined' ? process.env.CONFLUENCE_WEB_MAX_DEADLINE_SECONDS : undefined;
const seconds = raw === undefined || raw === '' ? NaN : Number(raw);
return Number.isInteger(seconds) && seconds >= 60 && seconds <= 3600 ? seconds * 1000 : 900_000;
}
export const LIMITS = {
USER_PROMPT_MAX_BYTES: 16 * MIB,
FINAL_MARKDOWN_MAX_BYTES: 128 * MIB,
TOOL_REQUEST_PAYLOAD_MAX_BYTES: 16 * MIB,
TOOL_RESULT_PAYLOAD_MAX_BYTES: 128 * MIB,
MODEL_REQUEST_PAYLOAD_MAX_BYTES: 128 * MIB,
MODEL_RESULT_PAYLOAD_MAX_BYTES: 128 * MIB,
ENVELOPE_ALLOWANCE_BYTES: 64 * KIB,
START_FRAME_MAX_BYTES: 6 * (16 * MIB) + 64 * KIB,
COLLECTION_START_FRAME_MAX_BYTES: 6 * (128 * MIB) + 64 * KIB,
ORDINARY_FRAME_MAX_BYTES: 128 * MIB + 64 * KIB,
ARTIFACT_CHUNK_MAX_DECODED_BYTES: 64 * KIB,
ARTIFACT_MAX_FILES: 20,
ARTIFACT_MAX_FILE_BYTES: 10 * MIB,
ARTIFACT_MAX_TOTAL_BYTES: 50 * MIB,
MAX_DEADLINE_MS: maxDeadlineMs(),
MAX_REMOTE_CONCURRENCY: 4,
MAX_WARNINGS: 100,
MAX_ERROR_MESSAGE_BYTES: 1024,
MAX_PATH_BYTES: 1024
} as const;
export interface ErrorShape {
code: string;
message: string;
}
export interface Warning {
code: string;
message: string;
tool_call_id?: string;
name?: string;
}
export interface Page {
page_id: string;
title: string;
space: string;
url: string;
}
export interface Pagination {
offset: number;
limit: number;
has_more: boolean;
}
export interface ModelDescriptor {
id: string;
context_window_tokens: number;
max_output_tokens: number;
}
// Model Protocol
export type TextContentBlock = {
type: "text";
text: string;
};
export type ToolCallContentBlock = {
type: "tool_call";
id: string;
name: string;
arguments: Record<string, any>;
};
export type ContentBlock = TextContentBlock | ToolCallContentBlock;
export interface UserMessageContract {
role: "user";
content: Array<{ type: "text"; text: string }>;
}
export interface AssistantMessageContract {
role: "assistant";
content: ContentBlock[];
provider_state?: string;
}
export interface ToolMessageContract {
role: "tool";
tool_call_id: string;
name: string;
content: string;
is_error: boolean;
}
export type MessageContract =
| UserMessageContract
| AssistantMessageContract
| ToolMessageContract;
export interface ToolDeclaration {
name: string;
description: string;
input_schema: Record<string, any>;
}
export interface ModelRequest {
messages: MessageContract[];
tools: ToolDeclaration[];
}
export interface ModelResponse {
content: ContentBlock[];
stop_reason: "stop" | "tool_calls" | "length";
usage: {
input_tokens: number;
output_tokens: number;
};
provider_state?: string;
}
// Bridge Protocol Frames
export interface BridgeBaseMessage {
v: number;
type: string;
id: string;
reply_to?: string;
payload: any;
}
export interface StartMessage extends BridgeBaseMessage {
type: "start";
payload: {
prompt: string;
system_instruction: string;
remaining_ms: number;
model: ModelDescriptor;
};
}
export interface ToolRequestMessage extends BridgeBaseMessage {
type: "tool_request";
payload: {
tool: string;
parameters: Record<string, any>;
};
}
export interface ToolResponseMessage extends BridgeBaseMessage {
type: "tool_response";
reply_to: string;
payload: {
result: any;
error: ErrorShape | null;
};
}
export interface ModelRequestMessage extends BridgeBaseMessage {
type: "model_request";
payload: ModelRequest;
}
export interface ModelResponseMessage extends BridgeBaseMessage {
type: "model_response";
reply_to: string;
payload: {
result: ModelResponse | null;
error: ErrorShape | null;
};
}
export interface CollectionStartMessage extends BridgeBaseMessage {
type: "collection_start";
payload: {
markdown: string;
warnings: Warning[];
};
}
export interface CollectionReadyMessage extends BridgeBaseMessage {
type: "collection_ready";
reply_to: string;
payload: Record<string, never>;
}
export interface ArtifactBeginMessage extends BridgeBaseMessage {
type: "artifact_begin";
payload: {
transfer_id: string;
name: string;
size_bytes: number;
};
}
export interface ArtifactAckMessage extends BridgeBaseMessage {
type: "artifact_ack";
reply_to: string;
payload: {
transfer_id: string;
decision: "accept" | "skip" | "stored";
warning: Warning | null;
};
}
export interface ArtifactChunkMessage extends BridgeBaseMessage {
type: "artifact_chunk";
payload: {
transfer_id: string;
index: number;
data_base64: string;
};
}
export interface ArtifactEndMessage extends BridgeBaseMessage {
type: "artifact_end";
payload: {
transfer_id: string;
size_bytes: number;
chunks: number;
};
}
export interface CompleteMessage extends BridgeBaseMessage {
type: "complete";
payload: {
accepted_transfer_count: number;
};
}
export interface ErrorMessage extends BridgeBaseMessage {
type: "error";
payload: ErrorShape;
}
export type BridgeInboundMessage =
| StartMessage
| ToolResponseMessage
| ModelResponseMessage
| CollectionReadyMessage
| ArtifactAckMessage;
export type BridgeOutboundMessage =
| ToolRequestMessage
| ModelRequestMessage
| CollectionStartMessage
| ArtifactBeginMessage
| ArtifactChunkMessage
| ArtifactEndMessage
| CompleteMessage
| ErrorMessage;