Skip to content

Commit 9a1b16e

Browse files
committed
cleanup code and fix types
1 parent ee39dea commit 9a1b16e

6 files changed

Lines changed: 36 additions & 36 deletions

File tree

apps/sim/app/api/mothership/chats/[chatId]/route.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe('GET /api/mothership/chats/[chatId]', () => {
123123
mockGetLatestRunForStream.mockResolvedValue(null)
124124
})
125125

126-
it('clears conversationId when the redis lock has expired (stuck-yellow bug)', async () => {
126+
it('clears activeStreamId when the redis lock has expired (stuck-yellow bug)', async () => {
127127
mockGetAccessibleCopilotChat.mockResolvedValueOnce({
128128
id: 'chat-stuck',
129129
type: 'mothership',
@@ -147,12 +147,12 @@ describe('GET /api/mothership/chats/[chatId]', () => {
147147
{ repairVerifiedStaleMarkers: true }
148148
)
149149
expect(body.success).toBe(true)
150-
expect(body.chat.conversationId).toBeNull()
150+
expect(body.chat.activeStreamId).toBeNull()
151151
expect(body.chat.streamSnapshot).toBeUndefined()
152152
expect(mockReadEvents).not.toHaveBeenCalled()
153153
})
154154

155-
it('returns the live conversationId when redis confirms the lock', async () => {
155+
it('returns the live activeStreamId when redis confirms the lock', async () => {
156156
mockGetAccessibleCopilotChat.mockResolvedValueOnce({
157157
id: 'chat-live',
158158
type: 'mothership',
@@ -169,13 +169,13 @@ describe('GET /api/mothership/chats/[chatId]', () => {
169169
expect(response.status).toBe(200)
170170
const body = await response.json()
171171

172-
expect(body.chat.conversationId).toBe('stream-live')
172+
expect(body.chat.activeStreamId).toBe('stream-live')
173173
expect(mockReadEvents).toHaveBeenCalledWith('stream-live', '0')
174174
expect(body.chat.streamSnapshot).toBeDefined()
175175
expect(body.chat.streamSnapshot.status).toBe('active')
176176
})
177177

178-
it('uses the Redis lock owner when it differs from a stale conversationId', async () => {
178+
it('uses the Redis lock owner when it differs from a stale persisted streamId', async () => {
179179
mockGetAccessibleCopilotChat.mockResolvedValueOnce({
180180
id: 'chat-mismatch',
181181
type: 'mothership',
@@ -196,11 +196,11 @@ describe('GET /api/mothership/chats/[chatId]', () => {
196196
expect(response.status).toBe(200)
197197
const body = await response.json()
198198

199-
expect(body.chat.conversationId).toBe('stream-live')
199+
expect(body.chat.activeStreamId).toBe('stream-live')
200200
expect(mockReadEvents).toHaveBeenCalledWith('stream-live', '0')
201201
})
202202

203-
it('returns null when conversationId is already null', async () => {
203+
it('returns null when the persisted stream marker is already null', async () => {
204204
mockGetAccessibleCopilotChat.mockResolvedValueOnce({
205205
id: 'chat-idle',
206206
type: 'mothership',
@@ -220,7 +220,7 @@ describe('GET /api/mothership/chats/[chatId]', () => {
220220
{ repairVerifiedStaleMarkers: true }
221221
)
222222
const body = await response.json()
223-
expect(body.chat.conversationId).toBeNull()
223+
expect(body.chat.activeStreamId).toBeNull()
224224
})
225225

226226
it('returns 404 when the chat does not exist', async () => {

apps/sim/app/api/mothership/chats/[chatId]/route.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,25 @@ export const GET = withRouteHandler(
5757
[{ chatId: chat.id, streamId: chat.conversationId }],
5858
{ repairVerifiedStaleMarkers: true }
5959
)
60-
const liveConversationId = reconciledMarkers.get(chat.id)?.streamId ?? null
60+
const liveStreamId = reconciledMarkers.get(chat.id)?.streamId ?? null
6161

62-
if (liveConversationId) {
62+
if (liveStreamId) {
6363
try {
6464
const [events, previewSessions] = await Promise.all([
65-
readEvents(liveConversationId, '0'),
66-
readFilePreviewSessions(liveConversationId).catch((error) => {
65+
readEvents(liveStreamId, '0'),
66+
readFilePreviewSessions(liveStreamId).catch((error) => {
6767
logger.warn('Failed to read preview sessions for mothership chat', {
6868
chatId,
69-
conversationId: liveConversationId,
69+
streamId: liveStreamId,
7070
error: toError(error).message,
7171
})
7272
return []
7373
}),
7474
])
75-
const run = await getLatestRunForStream(liveConversationId, userId).catch((error) => {
75+
const run = await getLatestRunForStream(liveStreamId, userId).catch((error) => {
7676
logger.warn('Failed to fetch latest run for mothership chat snapshot', {
7777
chatId,
78-
conversationId: liveConversationId,
78+
streamId: liveStreamId,
7979
error: toError(error).message,
8080
})
8181
return null
@@ -94,7 +94,7 @@ export const GET = withRouteHandler(
9494
} catch (error) {
9595
logger.warn('Failed to read stream snapshot for mothership chat', {
9696
chatId,
97-
conversationId: liveConversationId,
97+
streamId: liveStreamId,
9898
error: toError(error).message,
9999
})
100100
}
@@ -107,7 +107,7 @@ export const GET = withRouteHandler(
107107
: []
108108
const effectiveMessages = buildEffectiveChatTranscript({
109109
messages: normalizedMessages,
110-
activeStreamId: liveConversationId || null,
110+
activeStreamId: liveStreamId,
111111
...(streamSnapshot ? { streamSnapshot } : {}),
112112
})
113113

@@ -117,7 +117,7 @@ export const GET = withRouteHandler(
117117
id: chat.id,
118118
title: chat.title,
119119
messages: effectiveMessages,
120-
conversationId: liveConversationId || null,
120+
activeStreamId: liveStreamId,
121121
resources: Array.isArray(chat.resources) ? chat.resources : [],
122122
createdAt: chat.createdAt,
123123
updatedAt: chat.updatedAt,

apps/sim/hooks/queries/tasks.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ describe('tasks query boundary parsing', () => {
100100
id: 'chat-1',
101101
title: 'Task history',
102102
messages: [],
103-
conversationId: 'stream-1',
103+
activeStreamId: 'stream-1',
104104
resources: [{ type: 'file', id: 'file-1', title: 'Spec.md' }],
105105
streamSnapshot: {
106106
events: [],
@@ -144,7 +144,7 @@ describe('tasks query boundary parsing', () => {
144144
)
145145

146146
await expect(fetchChatHistory('chat-1')).rejects.toThrow(
147-
'Invalid copilot chat response: chat.resources[0].type is invalid'
147+
'Invalid chat response: chat.resources[0].type is invalid'
148148
)
149149
})
150150

apps/sim/hooks/queries/tasks.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ export const taskKeys = {
5757
detail: (chatId: string | undefined) => [...taskKeys.details(), chatId ?? ''] as const,
5858
}
5959

60-
type ChatHistorySource = 'copilot' | 'mothership'
61-
6260
function isRecord(value: unknown): value is Record<string, unknown> {
6361
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
6462
}
@@ -150,30 +148,28 @@ function parseStrictStreamSnapshot(
150148
return snapshot
151149
}
152150

153-
function parseChatHistory(value: unknown, source: ChatHistorySource): TaskChatHistory {
154-
const responseContext = `Invalid ${source} chat response`
151+
function parseChatHistory(value: unknown): TaskChatHistory {
152+
const responseContext = 'Invalid chat response'
155153
const chatContext = `${responseContext}: chat`
156154

157155
assertValid(isRecord(value), `${responseContext}: body must be an object`)
158156
assertValid(isRecord(value.chat), `${chatContext} must be an object`)
159157

160158
const chat = value.chat
161-
const activeStreamField = source === 'mothership' ? 'conversationId' : 'activeStreamId'
162-
const activeStreamId = chat[activeStreamField]
163159

164160
assertValid(typeof chat.id === 'string', `${chatContext}.id must be a string`)
165161
assertValid(isNullableString(chat.title), `${chatContext}.title must be a string or null`)
166162
assertValid(Array.isArray(chat.messages), `${chatContext}.messages must be an array`)
167163
assertValid(
168-
isNullableString(activeStreamId),
169-
`${chatContext}.${activeStreamField} must be a string or null`
164+
isNullableString(chat.activeStreamId),
165+
`${chatContext}.activeStreamId must be a string or null`
170166
)
171167

172168
return {
173169
id: chat.id,
174170
title: chat.title,
175171
messages: normalizeMessages(chat.messages),
176-
activeStreamId,
172+
activeStreamId: chat.activeStreamId,
177173
resources: parseResources(chat.resources, `${chatContext}.resources`),
178174
streamSnapshot: parseStrictStreamSnapshot(chat.streamSnapshot, `${chatContext}.streamSnapshot`),
179175
}
@@ -233,7 +229,7 @@ export async function fetchChatHistory(
233229
params: { chatId },
234230
signal,
235231
})
236-
return parseChatHistory(data, 'mothership')
232+
return parseChatHistory(data)
237233
} catch (error) {
238234
if (!isApiClientError(error)) throw error
239235
// Fall through to the legacy copilot-shape alias on any HTTP error (typically 404
@@ -251,7 +247,7 @@ export async function fetchChatHistory(
251247
throw new Error('Failed to load chat')
252248
}
253249

254-
return parseChatHistory(await copilotRes.json(), 'copilot')
250+
return parseChatHistory(await copilotRes.json())
255251
}
256252

257253
/**

apps/sim/lib/api/contracts/mothership-tasks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ export const getMothershipChatResponseSchema = z.object({
283283
id: z.string(),
284284
title: z.string().nullable(),
285285
messages: z.array(z.unknown()),
286-
conversationId: z.string().nullable(),
286+
activeStreamId: z.string().nullable(),
287287
resources: z.array(z.unknown()),
288288
createdAt: z.union([z.string(), z.date()]).nullable().optional(),
289289
updatedAt: z.union([z.string(), z.date()]).nullable().optional(),

apps/sim/lib/copilot/chat/stream-liveness.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,14 @@ async function repairVerifiedStaleMarkers(
100100
candidates: ChatStreamMarkerCandidate[],
101101
results: Map<string, ReconciledChatStreamMarker>
102102
): Promise<void> {
103-
const staleCandidates = candidates.filter((candidate) => {
104-
const result = results.get(candidate.chatId)
105-
return candidate.streamId !== null && result?.status === 'inactive' && result.streamId === null
106-
})
103+
const staleCandidates = candidates.filter(
104+
(candidate): candidate is { chatId: string; streamId: string } => {
105+
const result = results.get(candidate.chatId)
106+
return (
107+
candidate.streamId !== null && result?.status === 'inactive' && result.streamId === null
108+
)
109+
}
110+
)
107111

108112
if (staleCandidates.length === 0) return
109113

0 commit comments

Comments
 (0)