revert: message loading delay
This commit is contained in:
parent
d3f19834ff
commit
73f1f5a781
7 changed files with 102 additions and 174 deletions
|
|
@ -114,7 +114,6 @@ import type {
|
|||
TeamCreateRequest,
|
||||
TeamCreateResponse,
|
||||
TeamData,
|
||||
TeamGetDataOptions,
|
||||
TeamLaunchRequest,
|
||||
TeamLaunchResponse,
|
||||
TeamMessageNotificationData,
|
||||
|
|
@ -378,23 +377,17 @@ async function handleListTeams(_event: IpcMainInvokeEvent): Promise<IpcResult<Te
|
|||
|
||||
async function handleGetData(
|
||||
_event: IpcMainInvokeEvent,
|
||||
teamName: unknown,
|
||||
options: unknown
|
||||
teamName: unknown
|
||||
): Promise<IpcResult<TeamData>> {
|
||||
const validated = validateTeamName(teamName);
|
||||
if (!validated.valid) {
|
||||
return { success: false, error: validated.error ?? 'Invalid teamName' };
|
||||
}
|
||||
const tn = validated.value!;
|
||||
const includeMessages =
|
||||
!options ||
|
||||
typeof options !== 'object' ||
|
||||
!('includeMessages' in options) ||
|
||||
(options as TeamGetDataOptions).includeMessages !== false;
|
||||
const startedAt = Date.now();
|
||||
let data: TeamData;
|
||||
try {
|
||||
data = await getTeamDataService().getTeamData(tn, { includeMessages });
|
||||
data = await getTeamDataService().getTeamData(tn);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
if (
|
||||
|
|
@ -416,10 +409,6 @@ async function handleGetData(
|
|||
const displayName = data.config.name || tn;
|
||||
const projectPath = data.config.projectPath;
|
||||
|
||||
if (!includeMessages) {
|
||||
return { success: true, data: { ...data, isAlive } };
|
||||
}
|
||||
|
||||
const live = provisioning.getLiveLeadProcessMessages(tn);
|
||||
if (live.length === 0) {
|
||||
checkRateLimitMessages(data.messages, tn, displayName, projectPath);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ import type {
|
|||
TeamConfig,
|
||||
TeamCreateConfigRequest,
|
||||
TeamData,
|
||||
TeamGetDataOptions,
|
||||
TeamMember,
|
||||
TeamProcess,
|
||||
TeamSummary,
|
||||
|
|
@ -248,9 +247,8 @@ export class TeamDataService {
|
|||
await fs.promises.rm(tasksDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
async getTeamData(teamName: string, options?: TeamGetDataOptions): Promise<TeamData> {
|
||||
async getTeamData(teamName: string): Promise<TeamData> {
|
||||
const startedAt = Date.now();
|
||||
const includeMessages = options?.includeMessages !== false;
|
||||
const marks: Record<string, number> = {};
|
||||
const mark = (label: string): void => {
|
||||
marks[label] = Date.now();
|
||||
|
|
@ -285,38 +283,32 @@ export class TeamDataService {
|
|||
mark('inboxNames');
|
||||
|
||||
let messages: InboxMessage[] = [];
|
||||
if (includeMessages) {
|
||||
try {
|
||||
messages = await this.inboxReader.getMessages(teamName);
|
||||
} catch {
|
||||
warnings.push('Messages failed to load');
|
||||
}
|
||||
try {
|
||||
messages = await this.inboxReader.getMessages(teamName);
|
||||
} catch {
|
||||
warnings.push('Messages failed to load');
|
||||
}
|
||||
mark('messages');
|
||||
|
||||
let leadTexts: InboxMessage[] = [];
|
||||
if (includeMessages) {
|
||||
try {
|
||||
leadTexts = await this.extractLeadSessionTexts(config);
|
||||
if (leadTexts.length > 0) {
|
||||
messages = [...messages, ...leadTexts];
|
||||
}
|
||||
} catch {
|
||||
warnings.push('Lead session texts failed to load');
|
||||
try {
|
||||
leadTexts = await this.extractLeadSessionTexts(config);
|
||||
if (leadTexts.length > 0) {
|
||||
messages = [...messages, ...leadTexts];
|
||||
}
|
||||
} catch {
|
||||
warnings.push('Lead session texts failed to load');
|
||||
}
|
||||
mark('leadTexts');
|
||||
|
||||
let sentMessages: InboxMessage[] = [];
|
||||
if (includeMessages) {
|
||||
try {
|
||||
sentMessages = await this.sentMessagesStore.readMessages(teamName);
|
||||
if (sentMessages.length > 0) {
|
||||
messages = [...messages, ...sentMessages];
|
||||
}
|
||||
} catch {
|
||||
warnings.push('Sent messages failed to load');
|
||||
try {
|
||||
sentMessages = await this.sentMessagesStore.readMessages(teamName);
|
||||
if (sentMessages.length > 0) {
|
||||
messages = [...messages, ...sentMessages];
|
||||
}
|
||||
} catch {
|
||||
warnings.push('Sent messages failed to load');
|
||||
}
|
||||
mark('sentMessages');
|
||||
|
||||
|
|
@ -339,57 +331,55 @@ export class TeamDataService {
|
|||
});
|
||||
}
|
||||
|
||||
if (includeMessages) {
|
||||
// Enrich inbox messages without leadSessionId by assigning the nearest neighbor's
|
||||
// session ID (by timestamp). This avoids the old forward-only propagation bug.
|
||||
if (config.leadSessionId || messages.some((m) => m.leadSessionId)) {
|
||||
messages.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
||||
// Enrich inbox messages without leadSessionId by assigning the nearest neighbor's
|
||||
// session ID (by timestamp). This avoids the old forward-only propagation bug.
|
||||
if (config.leadSessionId || messages.some((m) => m.leadSessionId)) {
|
||||
messages.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
||||
|
||||
const anchors: { index: number; time: number; sessionId: string }[] = [];
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (messages[i].leadSessionId) {
|
||||
anchors.push({
|
||||
index: i,
|
||||
time: Date.parse(messages[i].timestamp),
|
||||
sessionId: messages[i].leadSessionId!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (anchors.length > 0) {
|
||||
let anchorIdx = 0;
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (messages[i].leadSessionId) {
|
||||
while (anchorIdx < anchors.length - 1 && anchors[anchorIdx].index < i) {
|
||||
anchorIdx++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const msgTime = Date.parse(messages[i].timestamp);
|
||||
let bestAnchor = anchors[0];
|
||||
let bestDist = Math.abs(msgTime - bestAnchor.time);
|
||||
for (const anchor of anchors) {
|
||||
const dist = Math.abs(msgTime - anchor.time);
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
bestAnchor = anchor;
|
||||
} else if (dist > bestDist && anchor.time > msgTime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
messages[i].leadSessionId = bestAnchor.sessionId;
|
||||
}
|
||||
} else if (config.leadSessionId) {
|
||||
for (const msg of messages) {
|
||||
msg.leadSessionId = config.leadSessionId;
|
||||
}
|
||||
const anchors: { index: number; time: number; sessionId: string }[] = [];
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (messages[i].leadSessionId) {
|
||||
anchors.push({
|
||||
index: i,
|
||||
time: Date.parse(messages[i].timestamp),
|
||||
sessionId: messages[i].leadSessionId!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
messages.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
|
||||
if (anchors.length > 0) {
|
||||
let anchorIdx = 0;
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (messages[i].leadSessionId) {
|
||||
while (anchorIdx < anchors.length - 1 && anchors[anchorIdx].index < i) {
|
||||
anchorIdx++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const msgTime = Date.parse(messages[i].timestamp);
|
||||
let bestAnchor = anchors[0];
|
||||
let bestDist = Math.abs(msgTime - bestAnchor.time);
|
||||
for (const anchor of anchors) {
|
||||
const dist = Math.abs(msgTime - anchor.time);
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
bestAnchor = anchor;
|
||||
} else if (dist > bestDist && anchor.time > msgTime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
messages[i].leadSessionId = bestAnchor.sessionId;
|
||||
}
|
||||
} else if (config.leadSessionId) {
|
||||
for (const msg of messages) {
|
||||
msg.leadSessionId = config.leadSessionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
messages.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
|
||||
|
||||
let metaMembers: TeamConfig['members'] = [];
|
||||
try {
|
||||
metaMembers = await this.membersMetaStore.getMembers(teamName);
|
||||
|
|
|
|||
|
|
@ -233,7 +233,6 @@ import type {
|
|||
TeamCreateRequest,
|
||||
TeamCreateResponse,
|
||||
TeamData,
|
||||
TeamGetDataOptions,
|
||||
TeamLaunchRequest,
|
||||
TeamLaunchResponse,
|
||||
TeamMessageNotificationData,
|
||||
|
|
@ -741,8 +740,8 @@ const electronAPI: ElectronAPI = {
|
|||
list: async () => {
|
||||
return invokeIpcWithResult<TeamSummary[]>(TEAM_LIST);
|
||||
},
|
||||
getData: async (teamName: string, options?: TeamGetDataOptions) => {
|
||||
return invokeIpcWithResult<TeamData>(TEAM_GET_DATA, teamName, options);
|
||||
getData: async (teamName: string) => {
|
||||
return invokeIpcWithResult<TeamData>(TEAM_GET_DATA, teamName);
|
||||
},
|
||||
getClaudeLogs: async (teamName: string, query?: TeamClaudeLogsQuery) => {
|
||||
return invokeIpcWithResult<TeamClaudeLogsResponse>(TEAM_GET_CLAUDE_LOGS, teamName, query);
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ interface TeamDetailViewProps {
|
|||
}
|
||||
|
||||
const ACTIVE_PROVISIONING_STATES = new Set(['validating', 'spawning', 'monitoring', 'verifying']);
|
||||
const MESSAGE_LOAD_DELAY_MS = 2_000;
|
||||
|
||||
interface CreateTaskDialogState {
|
||||
open: boolean;
|
||||
|
|
@ -203,7 +202,6 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
|||
const {
|
||||
data,
|
||||
loading,
|
||||
messagesLoading,
|
||||
error,
|
||||
projects,
|
||||
repositoryGroups,
|
||||
|
|
@ -244,7 +242,6 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
|||
useShallow((s) => ({
|
||||
data: s.selectedTeamData,
|
||||
loading: s.selectedTeamLoading,
|
||||
messagesLoading: s.selectedTeamMessagesLoading,
|
||||
error: s.selectedTeamError,
|
||||
projects: s.projects,
|
||||
repositoryGroups: s.repositoryGroups,
|
||||
|
|
@ -336,20 +333,6 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
|||
void fetchDeletedTasks(teamName);
|
||||
}, [teamName, selectTeam, fetchDeletedTasks]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!teamName || loading || !data || data.teamName !== teamName || !messagesLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
void refreshTeamData(teamName, { includeMessages: true, messagesLoading: true });
|
||||
}, MESSAGE_LOAD_DELAY_MS);
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(timeoutId);
|
||||
};
|
||||
}, [teamName, loading, data, messagesLoading, refreshTeamData]);
|
||||
|
||||
// Fetch active teams when launch dialog opens (for conflict warning)
|
||||
useEffect(() => {
|
||||
if (!launchDialogOpen) return;
|
||||
|
|
@ -1459,14 +1442,14 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
|||
sectionId="messages"
|
||||
title="Messages"
|
||||
icon={<MessageSquare size={14} />}
|
||||
badge={messagesLoading ? '...' : filteredMessages.length}
|
||||
badge={filteredMessages.length}
|
||||
secondaryBadge={
|
||||
!messagesLoading && filteredMessages.length > 0 && messagesUnreadCount > 0
|
||||
filteredMessages.length > 0 && messagesUnreadCount > 0
|
||||
? messagesUnreadCount
|
||||
: undefined
|
||||
}
|
||||
afterBadge={
|
||||
!messagesLoading && messagesUnreadCount > 0 ? (
|
||||
messagesUnreadCount > 0 ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
|
|
@ -1592,40 +1575,34 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
|||
onTaskClick={setSelectedTask}
|
||||
/>
|
||||
</div>
|
||||
{messagesLoading ? (
|
||||
<div className="rounded-md border border-[var(--color-border)] p-3 text-xs text-[var(--color-text-muted)]">
|
||||
Loading messages in 2 seconds so the rest of the team view can open faster.
|
||||
</div>
|
||||
) : (
|
||||
<ActivityTimeline
|
||||
messages={filteredMessages}
|
||||
teamName={teamName}
|
||||
members={data.members}
|
||||
readState={{ readSet, getMessageKey: toMessageKey }}
|
||||
allCollapsed={messagesCollapsed}
|
||||
expandOverrides={expandedSet}
|
||||
onToggleExpandOverride={toggleExpandOverride}
|
||||
onMemberClick={setSelectedMember}
|
||||
onCreateTaskFromMessage={(subject, description) => {
|
||||
openCreateTaskDialog(subject, description);
|
||||
}}
|
||||
onReplyToMessage={(message) => {
|
||||
setSendDialogRecipient(message.from);
|
||||
setSendDialogDefaultText(undefined);
|
||||
setSendDialogDefaultChip(undefined);
|
||||
setReplyQuote({ from: message.from, text: stripAgentBlocks(message.text) });
|
||||
setSendDialogOpen(true);
|
||||
}}
|
||||
onMessageVisible={handleMessageVisible}
|
||||
onRestartTeam={() => setLaunchDialogOpen(true)}
|
||||
onTaskIdClick={(taskId) => {
|
||||
const task =
|
||||
taskMap.get(taskId) ??
|
||||
data.tasks.find((candidate) => candidate.displayId === taskId);
|
||||
if (task) setSelectedTask(task);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ActivityTimeline
|
||||
messages={filteredMessages}
|
||||
teamName={teamName}
|
||||
members={data.members}
|
||||
readState={{ readSet, getMessageKey: toMessageKey }}
|
||||
allCollapsed={messagesCollapsed}
|
||||
expandOverrides={expandedSet}
|
||||
onToggleExpandOverride={toggleExpandOverride}
|
||||
onMemberClick={setSelectedMember}
|
||||
onCreateTaskFromMessage={(subject, description) => {
|
||||
openCreateTaskDialog(subject, description);
|
||||
}}
|
||||
onReplyToMessage={(message) => {
|
||||
setSendDialogRecipient(message.from);
|
||||
setSendDialogDefaultText(undefined);
|
||||
setSendDialogDefaultChip(undefined);
|
||||
setReplyQuote({ from: message.from, text: stripAgentBlocks(message.text) });
|
||||
setSendDialogOpen(true);
|
||||
}}
|
||||
onMessageVisible={handleMessageVisible}
|
||||
onRestartTeam={() => setLaunchDialogOpen(true)}
|
||||
onTaskIdClick={(taskId) => {
|
||||
const task =
|
||||
taskMap.get(taskId) ??
|
||||
data.tasks.find((candidate) => candidate.displayId === taskId);
|
||||
if (task) setSelectedTask(task);
|
||||
}}
|
||||
/>
|
||||
</CollapsibleTeamSection>
|
||||
|
||||
<ReviewDialog
|
||||
|
|
|
|||
|
|
@ -264,7 +264,6 @@ export interface TeamSlice {
|
|||
selectedTeamName: string | null;
|
||||
selectedTeamData: TeamData | null;
|
||||
selectedTeamLoading: boolean;
|
||||
selectedTeamMessagesLoading: boolean;
|
||||
selectedTeamError: string | null;
|
||||
sendingMessage: boolean;
|
||||
sendMessageError: string | null;
|
||||
|
|
@ -290,10 +289,7 @@ export interface TeamSlice {
|
|||
openTeamTab: (teamName: string, projectPath?: string, taskId?: string) => void;
|
||||
clearKanbanFilter: () => void;
|
||||
selectTeam: (teamName: string, opts?: { skipProjectAutoSelect?: boolean }) => Promise<void>;
|
||||
refreshTeamData: (
|
||||
teamName: string,
|
||||
opts?: { includeMessages?: boolean; messagesLoading?: boolean }
|
||||
) => Promise<void>;
|
||||
refreshTeamData: (teamName: string) => Promise<void>;
|
||||
sendTeamMessage: (teamName: string, request: SendMessageRequest) => Promise<void>;
|
||||
requestReview: (teamName: string, taskId: string) => Promise<void>;
|
||||
updateKanban: (teamName: string, taskId: string, patch: UpdateKanbanPatch) => Promise<void>;
|
||||
|
|
@ -399,7 +395,6 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
selectedTeamName: null,
|
||||
selectedTeamData: null,
|
||||
selectedTeamLoading: false,
|
||||
selectedTeamMessagesLoading: false,
|
||||
selectedTeamError: null,
|
||||
sendingMessage: false,
|
||||
sendMessageError: null,
|
||||
|
|
@ -620,14 +615,13 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
selectedTeamName: teamName,
|
||||
selectedTeamData: prev !== teamName ? null : get().selectedTeamData,
|
||||
selectedTeamLoading: true,
|
||||
selectedTeamMessagesLoading: true,
|
||||
selectedTeamError: null,
|
||||
reviewActionError: null,
|
||||
});
|
||||
|
||||
try {
|
||||
const data = await withTimeout(
|
||||
unwrapIpc('team:getData', () => api.teams.getData(teamName, { includeMessages: false })),
|
||||
unwrapIpc('team:getData', () => api.teams.getData(teamName)),
|
||||
TEAM_GET_DATA_TIMEOUT_MS,
|
||||
`team:getData(${teamName})`
|
||||
);
|
||||
|
|
@ -718,7 +712,6 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
if (msg === 'TEAM_PROVISIONING' || (msg.includes('TEAM_PROVISIONING') && isProvisioning)) {
|
||||
set({
|
||||
selectedTeamLoading: true,
|
||||
selectedTeamMessagesLoading: true,
|
||||
selectedTeamData: null,
|
||||
selectedTeamError: null,
|
||||
});
|
||||
|
|
@ -733,27 +726,22 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
: 'Failed to fetch team data';
|
||||
set({
|
||||
selectedTeamLoading: false,
|
||||
selectedTeamMessagesLoading: false,
|
||||
selectedTeamData: null,
|
||||
selectedTeamError: message,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
refreshTeamData: async (teamName: string, opts) => {
|
||||
refreshTeamData: async (teamName: string) => {
|
||||
const state = get();
|
||||
if (state.selectedTeamName !== teamName) {
|
||||
return;
|
||||
}
|
||||
const includeMessages = opts?.includeMessages !== false;
|
||||
if (opts?.messagesLoading !== undefined) {
|
||||
set({ selectedTeamMessagesLoading: opts.messagesLoading });
|
||||
}
|
||||
// Silent refresh — update data without showing loading skeleton.
|
||||
// Only selectTeam() sets loading: true (for initial load).
|
||||
try {
|
||||
const data = await withTimeout(
|
||||
unwrapIpc('team:getData', () => api.teams.getData(teamName, { includeMessages })),
|
||||
unwrapIpc('team:getData', () => api.teams.getData(teamName)),
|
||||
TEAM_GET_DATA_TIMEOUT_MS,
|
||||
`refreshTeamData(${teamName})`
|
||||
);
|
||||
|
|
@ -763,7 +751,6 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
}
|
||||
set({
|
||||
selectedTeamData: data,
|
||||
selectedTeamMessagesLoading: includeMessages ? false : get().selectedTeamMessagesLoading,
|
||||
selectedTeamError: null,
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
@ -777,10 +764,7 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
? error.message
|
||||
: 'Failed to refresh team data';
|
||||
logger.warn(`refreshTeamData(${teamName}) failed: ${msg}`);
|
||||
set({
|
||||
selectedTeamError: msg,
|
||||
selectedTeamMessagesLoading: includeMessages ? false : get().selectedTeamMessagesLoading,
|
||||
});
|
||||
set({ selectedTeamError: msg });
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -996,13 +980,7 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
|||
await unwrapIpc('team:permanentlyDeleteTeam', () => api.teams.permanentlyDeleteTeam(teamName));
|
||||
const state = get();
|
||||
if (state.selectedTeamName === teamName) {
|
||||
set({
|
||||
selectedTeamName: null,
|
||||
selectedTeamData: null,
|
||||
selectedTeamLoading: false,
|
||||
selectedTeamMessagesLoading: false,
|
||||
selectedTeamError: null,
|
||||
});
|
||||
set({ selectedTeamName: null, selectedTeamData: null, selectedTeamError: null });
|
||||
}
|
||||
await get().fetchTeams();
|
||||
await get().fetchAllTasks();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import type {
|
|||
TeamCreateRequest,
|
||||
TeamCreateResponse,
|
||||
TeamData,
|
||||
TeamGetDataOptions,
|
||||
TeamLaunchRequest,
|
||||
TeamLaunchResponse,
|
||||
TeamMessageNotificationData,
|
||||
|
|
@ -409,7 +408,7 @@ export interface HttpServerAPI {
|
|||
|
||||
export interface TeamsAPI {
|
||||
list: () => Promise<TeamSummary[]>;
|
||||
getData: (teamName: string, options?: TeamGetDataOptions) => Promise<TeamData>;
|
||||
getData: (teamName: string) => Promise<TeamData>;
|
||||
getClaudeLogs: (teamName: string, query?: TeamClaudeLogsQuery) => Promise<TeamClaudeLogsResponse>;
|
||||
deleteTeam: (teamName: string) => Promise<void>;
|
||||
restoreTeam: (teamName: string) => Promise<void>;
|
||||
|
|
|
|||
|
|
@ -301,10 +301,6 @@ export interface TeamData {
|
|||
isAlive?: boolean;
|
||||
}
|
||||
|
||||
export interface TeamGetDataOptions {
|
||||
includeMessages?: boolean;
|
||||
}
|
||||
|
||||
export type EffortLevel = 'low' | 'medium' | 'high';
|
||||
|
||||
export interface TeamLaunchRequest {
|
||||
|
|
|
|||
Loading…
Reference in a new issue