- Add thinking_content column to room_message table - Migration for thinking_content column - ws-protocol update with streaming chunk types - Billing: first project gets $10, first workspace gets $30 - Subsequent projects/workspaces get $0 budget
445 lines
9.4 KiB
TypeScript
445 lines
9.4 KiB
TypeScript
export interface WsRequest {
|
|
type: 'request';
|
|
request_id: string;
|
|
action: WsAction;
|
|
params?: WsRequestParams;
|
|
}
|
|
|
|
export type WsAction =
|
|
| 'room.list'
|
|
| 'room.get'
|
|
| 'room.create'
|
|
| 'room.update'
|
|
| 'room.delete'
|
|
| 'category.list'
|
|
| 'category.create'
|
|
| 'category.update'
|
|
| 'category.delete'
|
|
| 'message.list'
|
|
| 'message.create'
|
|
| 'message.update'
|
|
| 'message.revoke'
|
|
| 'message.get'
|
|
| 'member.list'
|
|
| 'member.add'
|
|
| 'member.remove'
|
|
| 'member.leave'
|
|
| 'member.set_read_seq'
|
|
| 'member.update_role'
|
|
| 'pin.list'
|
|
| 'pin.add'
|
|
| 'pin.remove'
|
|
| 'thread.list'
|
|
| 'thread.create'
|
|
| 'thread.messages'
|
|
| 'reaction.add'
|
|
| 'reaction.remove'
|
|
| 'reaction.get'
|
|
| 'message.search'
|
|
| 'message.edit_history'
|
|
| 'ai.list'
|
|
| 'ai.upsert'
|
|
| 'ai.delete'
|
|
| 'notification.list'
|
|
| 'notification.mark_read'
|
|
| 'notification.mark_all_read'
|
|
| 'notification.archive'
|
|
| 'mention.list'
|
|
| 'mention.read_all'
|
|
| 'room.subscribe'
|
|
| 'room.unsubscribe'
|
|
| 'project.subscribe'
|
|
| 'project.unsubscribe'
|
|
| 'reaction.list_batch'
|
|
| 'typing.start'
|
|
| 'typing.stop';
|
|
|
|
export interface WsRequestParams {
|
|
project_name?: string;
|
|
room_id?: string;
|
|
message_id?: string;
|
|
user_id?: string;
|
|
category_id?: string;
|
|
thread_id?: string;
|
|
model_id?: string;
|
|
notification_id?: string;
|
|
emoji?: string;
|
|
only_public?: boolean;
|
|
only_unread?: boolean;
|
|
limit?: number;
|
|
offset?: number;
|
|
before_seq?: number;
|
|
after_seq?: number;
|
|
room_name?: string;
|
|
room_public?: boolean;
|
|
room_category?: string;
|
|
content?: string;
|
|
content_type?: string;
|
|
in_reply_to?: string;
|
|
parent_seq?: number;
|
|
role?: string;
|
|
last_read_seq?: number;
|
|
name?: string;
|
|
position?: number;
|
|
model?: string;
|
|
model_version?: string;
|
|
history_limit?: number;
|
|
system_prompt?: string;
|
|
temperature?: number;
|
|
max_tokens?: number;
|
|
use_exact?: boolean;
|
|
think?: boolean;
|
|
stream?: boolean;
|
|
min_score?: number;
|
|
query?: string;
|
|
message_ids?: string[];
|
|
attachment_ids?: string[];
|
|
typing?: string;
|
|
}
|
|
|
|
export interface WsResponse {
|
|
type: 'response';
|
|
request_id: string;
|
|
action: string;
|
|
data?: WsResponseData;
|
|
error?: WsErrorInfo | null;
|
|
}
|
|
|
|
export interface WsErrorInfo {
|
|
code: number;
|
|
error: string;
|
|
message: string;
|
|
}
|
|
|
|
/** 响应数据类型 */
|
|
export type WsResponseData =
|
|
| boolean
|
|
| number
|
|
| RoomResponse
|
|
| RoomResponse[]
|
|
| RoomCategoryResponse
|
|
| RoomCategoryResponse[]
|
|
| RoomMessageResponse
|
|
| RoomMessageListResponse
|
|
| RoomMemberResponse
|
|
| RoomMemberResponse[]
|
|
| PinResponseData
|
|
| PinResponseData[]
|
|
| RoomThreadResponse
|
|
| RoomThreadResponse[]
|
|
| ReactionListData
|
|
| ReactionListData[]
|
|
| SearchResultData
|
|
| MessageEditHistoryResponse
|
|
| AiConfigData
|
|
| AiConfigData[]
|
|
| NotificationListData
|
|
| MentionListData
|
|
| SubscribeData
|
|
| UserInfo[]
|
|
| null;
|
|
|
|
export interface TypingStartPayload {
|
|
room_id: string;
|
|
user_id: string;
|
|
username: string;
|
|
avatar_url?: string;
|
|
/** "user" or "ai". Defaults to "user". */
|
|
sender_type?: string;
|
|
}
|
|
|
|
export interface TypingStopPayload {
|
|
room_id: string;
|
|
user_id: string;
|
|
}
|
|
|
|
export interface WsEvent {
|
|
type: 'event';
|
|
event: string;
|
|
room_id?: string | null;
|
|
project_id?: string | null;
|
|
data?: unknown;
|
|
error?: string | null;
|
|
}
|
|
|
|
/** Maps backend event string to typed event. Only room-relevant events are typed. */
|
|
export type WsEventPayload =
|
|
| { type: 'room_message'; data: RoomMessagePayload }
|
|
| { type: 'project_event'; data: ProjectEventPayload }
|
|
| { type: 'ai_stream_chunk'; data: AiStreamChunkPayload }
|
|
| { type: 'room_reaction_updated'; data: RoomReactionUpdatedPayload }
|
|
| { type: 'message_edited'; data: MessageEditedPayload }
|
|
| { type: 'message_revoked'; data: MessageRevokedPayload }
|
|
| { type: 'message_pinned'; data: MessagePinnedPayload }
|
|
| { type: 'message_unpinned'; data: MessageUnpinnedPayload }
|
|
| { type: 'user_presence'; data: UserPresencePayload }
|
|
| { type: 'typing_start'; data: TypingStartPayload }
|
|
| { type: 'typing_stop'; data: TypingStopPayload }
|
|
| { type: 'notification_created'; data: NotificationCreatedPayload }
|
|
| { type: string; data: unknown }; // catch-all for unknown events
|
|
|
|
/** Payload for real-time notification push via WebSocket. */
|
|
export interface NotificationCreatedPayload {
|
|
notification: NotificationData;
|
|
/** URL to navigate to for this notification (e.g. /project/x/issues/42) */
|
|
deep_link_url?: string;
|
|
}
|
|
|
|
export interface RoomMessagePayload {
|
|
id: string;
|
|
room_id: string;
|
|
sender_type: string;
|
|
sender_id?: string;
|
|
thread_id?: string;
|
|
content: string;
|
|
content_type: string;
|
|
/** Accumulated AI reasoning/thinking text. */
|
|
thinking_content?: string;
|
|
send_at: string;
|
|
seq: number;
|
|
display_name?: string;
|
|
/** Present when this event carries reaction updates for the message */
|
|
reactions?: ReactionItem[];
|
|
}
|
|
|
|
export interface ProjectEventPayload {
|
|
event_type: string;
|
|
project_id: string;
|
|
room_id?: string;
|
|
category_id?: string;
|
|
message_id?: string;
|
|
seq?: number;
|
|
timestamp: string;
|
|
}
|
|
|
|
export interface AiStreamChunkPayload {
|
|
message_id: string;
|
|
room_id: string;
|
|
content: string;
|
|
done: boolean;
|
|
error?: string;
|
|
/** Human-readable AI model name for display (e.g. "Claude 3.5 Sonnet"). */
|
|
display_name?: string;
|
|
/** What kind of content: "thinking", "answer", "tool_call", "tool_result". */
|
|
chunk_type?: string;
|
|
}
|
|
|
|
export interface RoomResponse {
|
|
id: string;
|
|
project: string;
|
|
room_name: string;
|
|
public: boolean;
|
|
category?: string;
|
|
created_by: string;
|
|
created_at: string;
|
|
last_msg_at: string;
|
|
unread_count: number;
|
|
}
|
|
|
|
export interface RoomCategoryResponse {
|
|
id: string;
|
|
project: string;
|
|
name: string;
|
|
position: number;
|
|
created_by: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface RoomMessageResponse {
|
|
id: string;
|
|
seq: number;
|
|
room: string;
|
|
sender_type: string;
|
|
sender_id?: string;
|
|
display_name?: string;
|
|
thread?: string;
|
|
in_reply_to?: string;
|
|
content: string;
|
|
content_type: string;
|
|
edited_at?: string;
|
|
send_at: string;
|
|
revoked?: string;
|
|
revoked_by?: string;
|
|
}
|
|
|
|
export interface RoomMessageListResponse {
|
|
messages: RoomMessageResponse[];
|
|
total: number;
|
|
}
|
|
|
|
export interface RoomMemberResponse {
|
|
room: string;
|
|
user: string;
|
|
user_info?: UserInfo;
|
|
role: string;
|
|
first_msg_in?: string;
|
|
joined_at?: string;
|
|
last_read_seq?: number;
|
|
do_not_disturb: boolean;
|
|
dnd_start_hour?: number;
|
|
dnd_end_hour?: number;
|
|
}
|
|
|
|
export interface UserInfo {
|
|
uid: string;
|
|
username: string;
|
|
avatar_url?: string;
|
|
}
|
|
|
|
export interface PinResponseData {
|
|
room: string;
|
|
message: string;
|
|
pinned_by: string;
|
|
pinned_at: string;
|
|
message_data?: RoomMessageResponse;
|
|
}
|
|
|
|
export interface RoomThreadResponse {
|
|
id: string;
|
|
room: string;
|
|
parent: number;
|
|
created_by: string;
|
|
participants: unknown;
|
|
last_message_at: string;
|
|
last_message_preview?: string;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface ReactionItem {
|
|
emoji: string;
|
|
count: number;
|
|
reacted_by_me: boolean;
|
|
users: string[];
|
|
}
|
|
|
|
export interface ReactionListData {
|
|
message_id: string;
|
|
reactions: ReactionItem[];
|
|
}
|
|
|
|
export interface RoomReactionUpdatedPayload {
|
|
room_id: string;
|
|
message_id: string;
|
|
reactions: ReactionItem[];
|
|
}
|
|
|
|
export interface MessageEditedPayload {
|
|
message_id: string;
|
|
room_id: string;
|
|
edited_at: string;
|
|
}
|
|
|
|
export interface MessageRevokedPayload {
|
|
message_id: string;
|
|
room_id: string;
|
|
revoked_at: string;
|
|
revoked_by: string;
|
|
}
|
|
|
|
export interface MessagePinnedPayload {
|
|
message_id: string;
|
|
room_id: string;
|
|
pinned_by: string;
|
|
pinned_at: string;
|
|
}
|
|
|
|
export interface MessageUnpinnedPayload {
|
|
message_id: string;
|
|
room_id: string;
|
|
}
|
|
|
|
export interface UserPresencePayload {
|
|
user_id: string;
|
|
room_id: string;
|
|
status: 'online' | 'away' | 'dnd' | 'offline';
|
|
}
|
|
|
|
export interface SearchResultData {
|
|
messages: RoomMessageResponse[];
|
|
total: number;
|
|
}
|
|
|
|
export interface EditHistoryEntry {
|
|
old_content: string;
|
|
new_content: string;
|
|
edited_at: string;
|
|
}
|
|
|
|
export interface MessageEditHistoryResponse {
|
|
message_id: string;
|
|
history: EditHistoryEntry[];
|
|
total_edits: number;
|
|
}
|
|
|
|
export interface AiConfigData {
|
|
room: string;
|
|
model: string;
|
|
model_name?: string;
|
|
version?: string;
|
|
call_count: number;
|
|
last_call_at?: string;
|
|
history_limit?: number;
|
|
system_prompt?: string;
|
|
temperature?: number;
|
|
max_tokens?: number;
|
|
use_exact: boolean;
|
|
think: boolean;
|
|
stream: boolean;
|
|
min_score?: number;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface NotificationData {
|
|
id: string;
|
|
room?: string;
|
|
project?: string;
|
|
user_id?: string;
|
|
user_info?: UserInfo;
|
|
notification_type: string;
|
|
title: string;
|
|
content?: string;
|
|
related_message_id?: string;
|
|
related_user_id?: string;
|
|
related_room_id?: string;
|
|
is_read: boolean;
|
|
is_archived: boolean;
|
|
created_at: string;
|
|
read_at?: string;
|
|
expires_at?: string;
|
|
}
|
|
|
|
export interface NotificationListData {
|
|
notifications: NotificationData[];
|
|
total: number;
|
|
unread_count: number;
|
|
}
|
|
|
|
export interface MentionListData {
|
|
mentions: MentionData[];
|
|
}
|
|
|
|
export interface MentionData {
|
|
message_id: string;
|
|
mentioned_by: string;
|
|
mentioned_by_name: string;
|
|
content_preview: string;
|
|
room_id: string;
|
|
room_name: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface SubscribeData {
|
|
room_id?: string;
|
|
project_id?: string;
|
|
}
|
|
|
|
export type WsInMessage = WsResponse | WsEvent | WsErrorMessage;
|
|
|
|
export interface WsErrorMessage {
|
|
type: 'error';
|
|
error: string;
|
|
message?: string;
|
|
}
|