Skip to content

Commit 8d2f2a5

Browse files
committed
fix: reconcile staging rebase contracts and migrations
1 parent 5b4dd02 commit 8d2f2a5

41 files changed

Lines changed: 58643 additions & 352 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/docs/openapi-v2-files-audit.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4806,6 +4806,10 @@
48064806
"type": "string",
48074807
"description": "File name, including its extension."
48084808
},
4809+
"path": {
4810+
"type": "string",
4811+
"description": "Canonical VFS path of the file that was read: `files/…`, or `uploads/<name>` for a Chat upload."
4812+
},
48094813
"type": {
48104814
"type": "string",
48114815
"description": "Stored MIME type of the source file."
@@ -4885,6 +4889,7 @@
48854889
"required": [
48864890
"fileId",
48874891
"name",
4892+
"path",
48884893
"type",
48894894
"text",
48904895
"truncated",

apps/sim/app/api/v2/files/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { workspaceFileVfsPath } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
21
import type { V2FileVersion } from '@/lib/api/contracts/v2/file-versions'
32
import type { V2File, V2FileText } from '@/lib/api/contracts/v2/files'
43
import { getBaseUrl } from '@/lib/core/utils/urls'
54
import { buildFolderPath } from '@/lib/folders/paths'
65
import { workspaceResourceWebUrl } from '@/lib/resources'
76
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
7+
import { workspaceFileVfsPath } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
88
import type { WorkspaceFileVersionRecord } from '@/lib/uploads/contexts/workspace/workspace-file-versions'
99
import {
1010
findUserEmailsByIds,

apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use client'
22

33
import { useEffect, useRef, useState } from 'react'
4-
import { Button, Chip, ChipDropdown, cn, Tooltip, toast } from '@sim/emcn'
5-
import { ArrowUp, Paperclip, Plus, Search, Slash } from '@sim/emcn/icons'
4+
import { Chip, ChipDropdown, ComposerActionButton, cn, Tooltip, toast } from '@sim/emcn'
5+
import { ArrowUp, Paperclip, Plus, Search, Slash, StopFilled } from '@sim/emcn/icons'
66
import { useQueries } from '@tanstack/react-query'
77
import {
88
ASSISTANT_IMAGE_ACCEPT_ATTRIBUTE,
@@ -14,11 +14,6 @@ import { SearchLevelSelector } from '@/app/o/[organizationId]/home/components/co
1414
import type { SearchLevel } from '@/app/o/[organizationId]/home/search-params'
1515
import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider'
1616
import { AttachedFilesList } from '@/app/workspace/[workspaceId]/home/components/user-input/components/attached-files-list/attached-files-list'
17-
import {
18-
SEND_BUTTON_ACTIVE,
19-
SEND_BUTTON_BASE,
20-
SEND_BUTTON_DISABLED,
21-
} from '@/app/workspace/[workspaceId]/home/components/user-input/components/constants'
2217
import { DropOverlay } from '@/app/workspace/[workspaceId]/home/components/user-input/components/drop-overlay/drop-overlay'
2318
import { InputToolbar } from '@/app/workspace/[workspaceId]/home/components/user-input/components/input-toolbar'
2419
import { MicButton } from '@/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button'
@@ -266,32 +261,19 @@ export function Composer({
266261
<SearchLevelSelector value={assistantSearchLevel} onChange={onAssistantSearchLevelChange} />
267262
)
268263
const submitControl = isSending ? (
269-
<Button
270-
type='button'
271-
variant='ghost'
272-
onClick={onStop}
273-
aria-label='Stop generation'
274-
className={cn(SEND_BUTTON_BASE, SEND_BUTTON_ACTIVE)}
275-
>
276-
<svg
277-
className='block size-[14px] fill-white dark:fill-black'
278-
viewBox='0 0 24 24'
279-
xmlns='http://www.w3.org/2000/svg'
280-
>
281-
<rect x='4' y='4' width='16' height='16' rx='3' ry='3' />
282-
</svg>
283-
</Button>
264+
<ComposerActionButton type='button' onClick={onStop} aria-label='Stop generation' active>
265+
<StopFilled className='block size-[14px] fill-white dark:fill-black' />
266+
</ComposerActionButton>
284267
) : (
285-
<Button
268+
<ComposerActionButton
286269
type='button'
287-
variant='ghost'
288270
onClick={submit}
289271
disabled={!canSubmit}
290272
aria-label='Send'
291-
className={cn(SEND_BUTTON_BASE, canSubmit ? SEND_BUTTON_ACTIVE : SEND_BUTTON_DISABLED)}
273+
active={canSubmit}
292274
>
293275
<ArrowUp className='block size-[16px] text-white dark:text-black' />
294-
</Button>
276+
</ComposerActionButton>
295277
)
296278

297279
return (

apps/sim/app/o/[organizationId]/search/search-results-view.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ export function SearchResultsView({
2929
const scope = { kind: 'organization' as const, organizationId: organization.id }
3030
const scrollContainerRef = useRef<HTMLDivElement>(null)
3131
const scrollContentRef = useRef<HTMLDivElement>(null)
32-
const scrollEdges = useScrollEdges(scrollContainerRef, { contentRef: scrollContentRef })
3332
const searching = query.trim().length > 0
33+
const scrollEdges = useScrollEdges(scrollContainerRef, {
34+
contentRef: scrollContentRef,
35+
enabled: searching,
36+
})
3437
return (
3538
<div className='flex h-full min-h-0 flex-col bg-[var(--bg)]'>
3639
<div className={PAGE_HEADER_BAR} />

apps/sim/app/o/[organizationId]/search/search.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { useEffect, useRef, useState } from 'react'
4-
import { Button, cn, toast } from '@sim/emcn'
4+
import { ComposerActionButton, toast } from '@sim/emcn'
55
import { ArrowUp } from '@sim/emcn/icons'
66
import { useRouter } from 'next/navigation'
77
import { useQueryStates } from 'nuqs'
@@ -15,11 +15,6 @@ import {
1515
organizationSearchUrlKeys,
1616
} from '@/app/o/[organizationId]/search/search-params'
1717
import { SearchResultsView } from '@/app/o/[organizationId]/search/search-results-view'
18-
import {
19-
SEND_BUTTON_ACTIVE,
20-
SEND_BUTTON_BASE,
21-
SEND_BUTTON_DISABLED,
22-
} from '@/app/workspace/[workspaceId]/home/components/user-input/components/constants'
2318
import { MicButton } from '@/app/workspace/[workspaceId]/home/components/user-input/components/mic-button/mic-button'
2419
import { MicrophonePermissionHelp } from '@/app/workspace/[workspaceId]/home/components/user-input/components/microphone-permission-help/microphone-permission-help'
2520
import { useVoiceInput } from '@/hooks/use-voice-input'
@@ -61,16 +56,15 @@ function SearchField({ initialValue, onSubmit }: SearchFieldProps) {
6156
)
6257
}
6358
submitControl={
64-
<Button
59+
<ComposerActionButton
6560
type='button'
66-
variant='ghost'
6761
onClick={() => onSubmit(value)}
6862
disabled={!canSubmit}
6963
aria-label='Search'
70-
className={cn(SEND_BUTTON_BASE, canSubmit ? SEND_BUTTON_ACTIVE : SEND_BUTTON_DISABLED)}
64+
active={canSubmit}
7165
>
7266
<ArrowUp className='block size-[16px] text-white dark:text-black' />
73-
</Button>
67+
</ComposerActionButton>
7468
}
7569
/>
7670
<MicrophonePermissionHelp

apps/sim/app/workspace/[workspaceId]/home/components/knowledge-search-results/search-transitions.test.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ beforeEach(() => {
9090
vi.useFakeTimers()
9191
vi.setSystemTime(new Date('2026-01-15T12:00:00Z'))
9292
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true)
93+
vi.stubGlobal(
94+
'ResizeObserver',
95+
class {
96+
observe() {}
97+
unobserve() {}
98+
disconnect() {}
99+
}
100+
)
93101
mocks.userId = 'reader'
94102
requests = []
95103
mocks.request.mockImplementation(
@@ -204,10 +212,10 @@ describe('search refinement with the real query cache and URL state', () => {
204212
await render({ organizationPage: true, params: '?q=launch' })
205213
expect(container.querySelector('h1')).toBeNull()
206214
expect(container.querySelector('[aria-label="Search filters"]')).toBeNull()
207-
const input = container.querySelector('input')
215+
const input = container.querySelector('textarea')
208216
await complete(0)
209217
expect(container.querySelector('h1')).toBeNull()
210-
expect(container.querySelector('input')).toBe(input)
218+
expect(container.querySelector('textarea')).toBe(input)
211219
const filters = container.querySelector('[aria-label="Search filters"]')
212220

213221
for (const [label, expectedFilters] of [
@@ -223,9 +231,10 @@ describe('search refinement with the real query cache and URL state', () => {
223231
organizationId: 'organization',
224232
query: 'launch',
225233
filters: expectedFilters,
234+
topK: 20,
226235
})
227236
expect(container.querySelector('h1')).toBeNull()
228-
expect(container.querySelector('input')).toBe(input)
237+
expect(container.querySelector('textarea')).toBe(input)
229238
expect(container.querySelector('[aria-label="Search filters"]')).toBe(filters)
230239
expect(document.activeElement).toBe(control)
231240
expect(container.textContent).toContain('Updating results…')

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/activity-stream.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ describe.each(['mothership', 'workflow', 'browser', 'deploy'])('%s activity', (a
154154
expect(header()?.textContent).toBe('Read first')
155155
act(() => container.querySelector<HTMLElement>('[role="button"]')?.click())
156156
expect(container.querySelector('[data-state="open"]')?.textContent).toContain(
157-
'Failed reading second'
157+
'Reading second'
158158
)
159159
}
160160
)
@@ -340,8 +340,8 @@ describe.each(['mothership', 'workflow', 'browser', 'deploy'])('%s activity', (a
340340

341341
if (agentName === 'mothership') {
342342
it.each([
343-
['error', 'Failed creating sign-in link'],
344-
['rejected', 'Failed creating sign-in link'],
343+
['error', 'Creating sign-in link'],
344+
['rejected', 'Creating sign-in link'],
345345
['success', 'Created sign-in link'],
346346
] as const)(
347347
'renders a singleton %s action directly instead of a count disclosure',
@@ -389,7 +389,7 @@ describe.each(['mothership', 'workflow', 'browser', 'deploy'])('%s activity', (a
389389
act(() => container.querySelector<HTMLElement>('[role="button"]')!.click())
390390
expect(header()?.textContent).toBe(activity.title)
391391
expect(container.querySelector('[data-state="open"]')?.textContent).toContain(
392-
'Failed reading validation'
392+
'Reading validation'
393393
)
394394
})
395395

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/agent-group.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,11 @@ describe('AgentGroup inline main activity', () => {
223223

224224
it.each([
225225
['success', 'Searched'],
226-
['error', 'Failed searching'],
226+
['error', 'Searching'],
227227
['cancelled', 'Stopped searching'],
228228
['skipped', 'Skipped searching'],
229229
['interrupted', 'Stopped searching'],
230-
['rejected', 'Failed searching'],
230+
['rejected', 'Searching'],
231231
] as const)('shows the single call directly after %s', (status, expected) => {
232232
const item = tool(status)
233233
act(() =>
@@ -422,7 +422,7 @@ describe('AgentGroup inline main activity', () => {
422422
)
423423
expect(container.querySelector('[role="status"]')?.textContent).toBe('Read second document')
424424
act(() => container.querySelector<HTMLElement>('[role="button"]')?.click())
425-
expect(container.textContent).toContain('Failed reading first document')
425+
expect(container.textContent).toContain('Reading first document')
426426
})
427427

428428
it.each(['mothership', 'workflow'])(
@@ -448,16 +448,16 @@ describe('AgentGroup inline main activity', () => {
448448
)
449449
)
450450
if (agentName === 'mothership') {
451-
expect(container.textContent).toBe('Failed reading notes')
451+
expect(container.textContent).toBe('Reading notes')
452452
expect(container.querySelector('[aria-expanded]')).toBeNull()
453453
return
454454
}
455455
expect(container.textContent).not.toContain('Failed')
456-
expect(container.textContent).toContain('1 tool call')
456+
expect(container.textContent).toContain('Reading notes')
457457
const disclosure = container.querySelector<HTMLElement>('[role="button"]')
458458
expect(disclosure?.getAttribute('aria-expanded')).toBe('false')
459459
act(() => disclosure?.click())
460-
expect(container.textContent).toContain('Failed reading notes')
460+
expect(container.textContent).toContain('Reading notes')
461461
}
462462
)
463463

@@ -504,8 +504,8 @@ describe('AgentGroup inline main activity', () => {
504504
status === 'executing' ? 'Viewing image.png' : 'Viewed image.png'
505505
)
506506
act(() => container.querySelector<HTMLElement>('[role="button"]')?.click())
507-
expect(container.textContent).toContain('Failed reading image.png')
508-
expect(container.textContent).toContain('Failed reading notes')
507+
expect(container.textContent).toContain('Reading image.png')
508+
expect(container.textContent).toContain('Reading notes')
509509
}
510510
)
511511

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-activity-group.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function toolCountLabel(tools: ToolCallData[]): string {
2222
/** Summarize completed actions without describing failed or skipped work as successful. */
2323
export function getToolActivitySummary(tools: ToolCallData[]): string {
2424
const statusTool = getActivityStatusTool(tools)
25-
if (!statusTool || isFailedTool(statusTool)) return toolCountLabel(tools)
25+
if (!statusTool || (tools.length > 1 && isFailedTool(statusTool))) return toolCountLabel(tools)
2626
const label = getToolStatusDisplayTitle(
2727
statusTool.displayTitle,
2828
statusTool.status,
@@ -54,7 +54,6 @@ export function getActiveToolActivityTitle(
5454
tool: ToolCallData,
5555
tools: ToolCallData[]
5656
): string {
57-
if (isFailedTool(tool)) return toolCountLabel(tools)
5857
return tool.status === ToolCallStatus.executing || tool.status === ToolCallStatus.success
5958
? [label, ...getToolActivityInterruptions(tools)].join(' · ')
6059
: label

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content-thinking.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,16 @@ describe('MessageContent shared thinking indicator', () => {
204204
(status) => {
205205
render([start('workflow'), start('browser'), tool('workflow', status)])
206206
expect(groups()).toHaveLength(1)
207-
expect(container.querySelector('[role="status"]')?.textContent).toBe('1 tool call')
208-
expect(container.textContent).not.toContain('workflow notes')
207+
expect(container.querySelector('[role="status"]')?.textContent).toBe('Reading workflow notes')
208+
expect(container.textContent).not.toContain('Failed')
209209
expect(thinking()).toHaveLength(1)
210210

211211
const disclosure = container.querySelector<HTMLElement>('[role="button"]')!
212212
expect(disclosure.getAttribute('aria-expanded')).toBe('false')
213213
act(() => disclosure.click())
214214
expect(disclosure.getAttribute('aria-expanded')).toBe('true')
215215
expect(container.querySelector('[data-state="open"]')?.textContent).toContain(
216-
'Failed reading workflow notes'
216+
'Reading workflow notes'
217217
)
218218
expect(thinking()).toHaveLength(1)
219219
}

0 commit comments

Comments
 (0)