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>).
264 lines
5.7 KiB
TypeScript
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;
|