Skip to content

Commit 34798aa

Browse files
committed
Merge remote-tracking branch 'origin/staging' into feat/project-workspace-column-expand
2 parents 5dc6f90 + c1c5ae0 commit 34798aa

4 files changed

Lines changed: 139 additions & 20 deletions

File tree

‎apps/sim/lib/sim-search/live/application.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,12 @@ function resultFor(
261261
}
262262
}
263263

264-
/** Accounts searched at once; bounds token refresh and provider fan-out in large organizations. */
265-
const ACCOUNT_CONCURRENCY = 4
264+
/**
265+
* Accounts searched at once; bounds token refresh and provider fan-out in large organizations.
266+
* Each account is one provider, and a search waits for every account, so a second wave adds a
267+
* full provider round trip; eight covers the account count most organizations search.
268+
*/
269+
const ACCOUNT_CONCURRENCY = 8
266270
/** Candidates verified at once; each verification is one or more provider requests. */
267271
const VERIFY_CONCURRENCY = 5
268272
const MAX_ACCOUNTS = 20
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { readLucidMcp } from '@/lib/sim-search/live/lucid-mcp'
3+
import type { ManagedSearchMcpClient } from '@/lib/sim-search/live/managed-mcp'
4+
5+
const ID = '0b6a3f0e-5a52-4c55-9d8c-6d2f2a1b9c11'
6+
const COUNTS = [3, 0, 2, 1]
7+
const TITLE = 'Fixture diagram'
8+
const metadataRow = {
9+
documentId: ID,
10+
viewUrl: `https://lucid.app/lucidchart/${ID}/view`,
11+
product: 'lucidchart',
12+
title: TITLE,
13+
version: 7,
14+
pageCount: COUNTS.length,
15+
lastModified: '2026-10-01T12:00:00Z',
16+
}
17+
18+
function manifest(extra: Record<string, unknown> = {}) {
19+
return {
20+
document_id: ID,
21+
edit_url: `https://lucid.app/lucidchart/${ID}/edit`,
22+
title: TITLE,
23+
metadata: { page_count: COUNTS.length, page_region_counts: COUNTS, ...extra },
24+
}
25+
}
26+
27+
function regionResponse(pageIndex: number, region: number) {
28+
const pageId = `page-${pageIndex}`
29+
return {
30+
...manifest({ page_index: pageIndex + 1 }),
31+
page_index: pageIndex + 1,
32+
page_id: pageId,
33+
text: JSON.stringify({
34+
pages: [
35+
{
36+
pageIndex,
37+
pageId,
38+
pageTitle: `Page ${pageIndex + 1}`,
39+
totalChunks: COUNTS[pageIndex],
40+
requestedChunks: COUNTS[pageIndex]
41+
? [{ chunkIndex: region, data: { label: `p${pageIndex}r${region}` } }]
42+
: [],
43+
},
44+
],
45+
}),
46+
}
47+
}
48+
49+
/** Region fetches settle in reverse request order, after a number of ticks, to expose ordering. */
50+
function lucidClient(options: { corruptFirstRegion?: boolean } = {}) {
51+
let inFlight = 0
52+
let maxInFlight = 0
53+
let regionCalls = 0
54+
const client: ManagedSearchMcpClient = {
55+
async call(name, args) {
56+
if (name === 'lucid_get_document_metadata') return metadataRow
57+
if (args.metadata_only) return manifest()
58+
const pageIndex = Number(args.page_index) - 1
59+
const region = Array.isArray(args.region_index) ? Number(args.region_index[0]) - 1 : 0
60+
const call = regionCalls++
61+
inFlight++
62+
maxInFlight = Math.max(maxInFlight, inFlight)
63+
for (let tick = 0; tick < 10 - call; tick++) await Promise.resolve()
64+
inFlight--
65+
const response = regionResponse(pageIndex, region)
66+
return options.corruptFirstRegion && call === 0 ? { ...response, page_id: 'other' } : response
67+
},
68+
}
69+
return { client, maxInFlight: () => maxInFlight, regionCalls: () => regionCalls }
70+
}
71+
72+
const REFERENCE = { id: ID, kind: 'lucidchart', revision: '7' }
73+
74+
describe('readLucidMcp', () => {
75+
it('fetches at most four regions at once and assembles them in page and region order', async () => {
76+
const { client, maxInFlight, regionCalls } = lucidClient()
77+
const document = await readLucidMcp(client, REFERENCE)
78+
expect(regionCalls()).toBe(7)
79+
expect(maxInFlight()).toBe(4)
80+
const pages = JSON.parse(document.content ?? '').pages as {
81+
pageId: string
82+
requestedChunks: { data: { label: string } }[]
83+
}[]
84+
expect(pages.map((page) => page.pageId)).toEqual(['page-0', 'page-1', 'page-2', 'page-3'])
85+
expect(pages.map((page) => page.requestedChunks.map((chunk) => chunk.data.label))).toEqual([
86+
['p0r0', 'p0r1', 'p0r2'],
87+
[],
88+
['p2r0', 'p2r1'],
89+
['p3r0'],
90+
])
91+
})
92+
93+
it('stops scheduling region fetches once a region fails validation', async () => {
94+
const { client, regionCalls } = lucidClient({ corruptFirstRegion: true })
95+
await expect(readLucidMcp(client, REFERENCE)).rejects.toThrow(/mismatched page regions/)
96+
expect(regionCalls()).toBe(4)
97+
})
98+
})

‎apps/sim/lib/sim-search/live/lucid-mcp.ts‎

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -322,44 +322,59 @@ function manifest(value: unknown, id: string, kind: string | undefined) {
322322
return { row, counts: counts as number[] }
323323
}
324324

325+
/**
326+
* Region fetches are independent provider reads; running them together keeps a full read inside
327+
* the live read deadline. Validation walks them in page and region order, and a fetch is only
328+
* scheduled once the region this many places before it has been validated, so a rejected or
329+
* oversized document stops further reads and holds at most this many responses.
330+
*/
331+
const REGION_FETCH_CONCURRENCY = 4
332+
325333
/** Complete, bounded provider pages preserve graph data; no returned URL is fetched. */
326334
export async function readLucidMcp(
327335
client: ManagedSearchMcpClient,
328336
reference: Pick<NativeDocument, 'id' | 'kind' | 'revision'>
329337
): Promise<NativeDocument> {
330-
const before = await metadata(client, reference.id)
338+
const [before, initialRaw] = await Promise.all([
339+
metadata(client, reference.id),
340+
client.call('fetch', { id: reference.id, metadata_only: true }),
341+
])
331342
if (!before) invalid('Lucid document metadata is incomplete or no longer readable.')
332343
if (
333344
(reference.kind && reference.kind !== before.kind) ||
334345
(reference.revision && reference.revision !== before.revision)
335346
)
336347
invalid('Lucid document changed since this result was issued. Search again before reading.')
337-
const initial = manifest(
338-
await client.call('fetch', { id: before.id, metadata_only: true }),
339-
before.id,
340-
before.kind
341-
)
348+
const initial = manifest(initialRaw, before.id, before.kind)
342349
if (
343350
initial.counts.length !== before.accessMetadata?.pageCount ||
344351
initial.row.title !== before.title
345352
)
346353
invalid('Lucid document coverage changed before reading. Search again.')
347354
const pages: Record<string, unknown>[] = []
348355
const output = () => JSON.stringify({ document_id: before.id, title: before.title, pages })
349-
for (let pageIndex = 0; pageIndex < initial.counts.length; pageIndex++) {
350-
const count = initial.counts[pageIndex]!
356+
const requests = initial.counts.flatMap((count, pageIndex) =>
357+
Array.from({ length: Math.max(1, count) }, (_, region) => ({
358+
id: before.id,
359+
page_index: pageIndex + 1,
360+
...(count ? { region_index: [region + 1] } : {}),
361+
}))
362+
)
363+
const responses: Promise<unknown>[] = []
364+
const schedule = (index: number) => {
365+
if (index >= requests.length) return
366+
const response = client.call('fetch', requests[index])
367+
// An invalid earlier region abandons in-flight fetches; their rejections must not go unhandled.
368+
response.catch(() => {})
369+
responses[index] = response
370+
}
371+
for (let index = 0; index < REGION_FETCH_CONCURRENCY; index++) schedule(index)
372+
let next = 0
373+
for (const [pageIndex, count] of initial.counts.entries()) {
351374
let assembled: Record<string, unknown> | undefined
352375
const chunks: Record<string, unknown>[] = []
353376
for (let region = 0; region < Math.max(1, count); region++) {
354-
const fetched = manifest(
355-
await client.call('fetch', {
356-
id: before.id,
357-
page_index: pageIndex + 1,
358-
...(count ? { region_index: [region + 1] } : {}),
359-
}),
360-
before.id,
361-
before.kind
362-
)
377+
const fetched = manifest(await responses[next], before.id, before.kind)
363378
if (
364379
fetched.counts.some((value, index) => value !== initial.counts[index]) ||
365380
fetched.counts.length !== initial.counts.length ||
@@ -404,6 +419,8 @@ export async function readLucidMcp(
404419
chunks.push(...returnedChunks)
405420
if (Buffer.byteLength(output(), 'utf8') > MAX_CONTENT_BYTES)
406421
invalid('Lucid document exceeds the 512 KiB complete-read limit. Open the source document.')
422+
schedule(next + REGION_FETCH_CONCURRENCY)
423+
next++
407424
}
408425
}
409426
const after = await metadata(client, before.id)

‎scripts/check-explicit-any.baseline.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@
16501650
"apps/sim/lib/sim-search/live/google-meet.ts": 1,
16511651
"apps/sim/lib/sim-search/live/granola-mcp.ts": 2,
16521652
"apps/sim/lib/sim-search/live/hubspot-mcp.test.ts": 1,
1653-
"apps/sim/lib/sim-search/live/lucid-mcp.ts": 2,
1653+
"apps/sim/lib/sim-search/live/lucid-mcp.ts": 1,
16541654
"apps/sim/lib/sim-search/live/pages.ts": 1,
16551655
"apps/sim/lib/sim-search/live/policy-schema.ts": 1,
16561656
"apps/sim/lib/sim-search/live/policy.ts": 2,

0 commit comments

Comments
 (0)