Skip to content

Commit e986ce3

Browse files
committed
feat(vfs): add lazy vfs + remove dynamic fields for prompt caching hits
1 parent f0b3550 commit e986ce3

5 files changed

Lines changed: 523 additions & 256 deletions

File tree

apps/sim/lib/copilot/chat/workspace-context.test.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,157 @@ describe('buildWorkspaceMd - connected integrations / credentials', () => {
116116
expect(md).toContain('## Connected Integrations\n(none)')
117117
})
118118
})
119+
120+
describe('buildWorkspaceMd - determinism (prompt-cache stability)', () => {
121+
it('is byte-identical regardless of input row order', () => {
122+
const a = buildWorkspaceMd(
123+
baseData({
124+
members: [
125+
{ name: 'Bob', email: 'bob@x.com', permissionType: 'admin' },
126+
{ name: 'Amy', email: 'amy@x.com', permissionType: 'write' },
127+
],
128+
workflows: [
129+
{ id: 'wf-2', name: 'Zeta', isDeployed: false, folderPath: null },
130+
{ id: 'wf-1', name: 'Alpha', isDeployed: true, folderPath: null },
131+
],
132+
tables: [
133+
{ id: 't-2', name: 'Orders', description: null, rowCount: 5 },
134+
{ id: 't-1', name: 'Customers', description: null, rowCount: 9 },
135+
],
136+
knowledgeBases: [
137+
{ id: 'kb-2', name: 'Docs', connectorTypes: ['notion', 'github'] },
138+
{ id: 'kb-1', name: 'Articles', connectorTypes: ['github', 'notion'] },
139+
],
140+
oauthIntegrations: [
141+
{ id: 'c-2', providerId: 'slack', displayName: null, role: null },
142+
{ id: 'c-1', providerId: 'github', displayName: null, role: null },
143+
],
144+
envVariables: ['ZED', 'API_KEY'],
145+
customTools: [
146+
{ id: 'ct-2', name: 'Beta Tool' },
147+
{ id: 'ct-1', name: 'Alpha Tool' },
148+
],
149+
mcpServers: [
150+
{ id: 'mcp-2', name: 'Zulu', url: null, enabled: false },
151+
{ id: 'mcp-1', name: 'Mike', url: 'https://x', enabled: true },
152+
],
153+
skills: [
154+
{ id: 'sk-2', name: 'Writer', description: 'writes' },
155+
{ id: 'sk-1', name: 'Editor', description: 'edits' },
156+
],
157+
jobs: [
158+
{
159+
id: 'j-2',
160+
title: 'Nightly',
161+
prompt: 'run nightly',
162+
cronExpression: '0 0 * * *',
163+
status: 'active',
164+
lifecycle: 'persistent',
165+
sourceTaskName: null,
166+
},
167+
{
168+
id: 'j-1',
169+
title: 'Hourly',
170+
prompt: 'run hourly',
171+
cronExpression: '0 * * * *',
172+
status: 'active',
173+
lifecycle: 'persistent',
174+
sourceTaskName: null,
175+
},
176+
],
177+
})
178+
)
179+
const b = buildWorkspaceMd(
180+
baseData({
181+
members: [
182+
{ name: 'Amy', email: 'amy@x.com', permissionType: 'write' },
183+
{ name: 'Bob', email: 'bob@x.com', permissionType: 'admin' },
184+
],
185+
workflows: [
186+
{ id: 'wf-1', name: 'Alpha', isDeployed: true, folderPath: null },
187+
{ id: 'wf-2', name: 'Zeta', isDeployed: false, folderPath: null },
188+
],
189+
tables: [
190+
{ id: 't-1', name: 'Customers', description: null, rowCount: 9 },
191+
{ id: 't-2', name: 'Orders', description: null, rowCount: 5 },
192+
],
193+
knowledgeBases: [
194+
{ id: 'kb-1', name: 'Articles', connectorTypes: ['notion', 'github'] },
195+
{ id: 'kb-2', name: 'Docs', connectorTypes: ['github', 'notion'] },
196+
],
197+
oauthIntegrations: [
198+
{ id: 'c-1', providerId: 'github', displayName: null, role: null },
199+
{ id: 'c-2', providerId: 'slack', displayName: null, role: null },
200+
],
201+
envVariables: ['API_KEY', 'ZED'],
202+
customTools: [
203+
{ id: 'ct-1', name: 'Alpha Tool' },
204+
{ id: 'ct-2', name: 'Beta Tool' },
205+
],
206+
mcpServers: [
207+
{ id: 'mcp-1', name: 'Mike', url: 'https://x', enabled: true },
208+
{ id: 'mcp-2', name: 'Zulu', url: null, enabled: false },
209+
],
210+
skills: [
211+
{ id: 'sk-1', name: 'Editor', description: 'edits' },
212+
{ id: 'sk-2', name: 'Writer', description: 'writes' },
213+
],
214+
jobs: [
215+
{
216+
id: 'j-1',
217+
title: 'Hourly',
218+
prompt: 'run hourly',
219+
cronExpression: '0 * * * *',
220+
status: 'active',
221+
lifecycle: 'persistent',
222+
sourceTaskName: null,
223+
},
224+
{
225+
id: 'j-2',
226+
title: 'Nightly',
227+
prompt: 'run nightly',
228+
cronExpression: '0 0 * * *',
229+
status: 'active',
230+
lifecycle: 'persistent',
231+
sourceTaskName: null,
232+
},
233+
],
234+
})
235+
)
236+
expect(a).toBe(b)
237+
})
238+
239+
it('ignores volatile workflow run timestamps', () => {
240+
const withRun = buildWorkspaceMd(
241+
baseData({
242+
workflows: [
243+
{
244+
id: 'wf-1',
245+
name: 'Alpha',
246+
isDeployed: false,
247+
folderPath: null,
248+
lastRunAt: new Date('2026-06-18T12:00:00Z'),
249+
},
250+
],
251+
})
252+
)
253+
const withoutRun = buildWorkspaceMd(
254+
baseData({
255+
workflows: [{ id: 'wf-1', name: 'Alpha', isDeployed: false, folderPath: null }],
256+
})
257+
)
258+
expect(withRun).toBe(withoutRun)
259+
expect(withRun).not.toContain('last run')
260+
})
261+
262+
it('ignores volatile table row counts', () => {
263+
const a = buildWorkspaceMd(
264+
baseData({ tables: [{ id: 't-1', name: 'Customers', description: null, rowCount: 1 }] })
265+
)
266+
const b = buildWorkspaceMd(
267+
baseData({ tables: [{ id: 't-1', name: 'Customers', description: null, rowCount: 9999 }] })
268+
)
269+
expect(a).toBe(b)
270+
expect(a).not.toContain('rows')
271+
})
272+
})

0 commit comments

Comments
 (0)