mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
fix(antigravity): restore workspaces by exact conversation identity (#21638)
This commit is contained in:
@@ -28,7 +28,10 @@ type AntigravityHistoryEntry = {
|
||||
workspace: string
|
||||
}
|
||||
|
||||
type AntigravityHistoryIndex = Map<string, AntigravityHistoryEntry[]>
|
||||
type AntigravityHistoryIndex = {
|
||||
byConversationId: Map<string, AntigravityHistoryEntry>
|
||||
byDisplay: Map<string, AntigravityHistoryEntry[]>
|
||||
}
|
||||
|
||||
export type AntigravityWorkspaceResolver = {
|
||||
enrich(session: AiVaultSession, historyPath: string): Promise<AiVaultSession>
|
||||
@@ -67,18 +70,32 @@ export function createAntigravityWorkspaceResolver(
|
||||
}
|
||||
|
||||
function indexAntigravityHistory(content: string | null): AntigravityHistoryIndex {
|
||||
const index: AntigravityHistoryIndex = new Map()
|
||||
const index: AntigravityHistoryIndex = {
|
||||
byConversationId: new Map(),
|
||||
byDisplay: new Map()
|
||||
}
|
||||
for (const line of content?.split(/\r?\n/) ?? []) {
|
||||
const record = parseJsonObject(line)
|
||||
const display = typeof record?.display === 'string' ? normalizeTitleText(record.display) : null
|
||||
const workspace = typeof record?.workspace === 'string' ? record.workspace.trim() : ''
|
||||
const conversationId =
|
||||
typeof record?.conversationId === 'string' ? record.conversationId.trim() : ''
|
||||
const entryTimestampMs = timestampMs(record?.timestamp)
|
||||
if (!display || !workspace || !Number.isFinite(entryTimestampMs)) {
|
||||
if (!workspace || !Number.isFinite(entryTimestampMs)) {
|
||||
continue
|
||||
}
|
||||
const entries = index.get(display) ?? []
|
||||
entries.push({ timestampMs: entryTimestampMs, workspace })
|
||||
index.set(display, entries)
|
||||
const entry = { timestampMs: entryTimestampMs, workspace }
|
||||
const directEntry = index.byConversationId.get(conversationId)
|
||||
if (conversationId && (!directEntry || entryTimestampMs < directEntry.timestampMs)) {
|
||||
index.byConversationId.set(conversationId, entry)
|
||||
}
|
||||
// An explicit conversation ID must never become another session's prompt fallback.
|
||||
if (conversationId || !display) {
|
||||
continue
|
||||
}
|
||||
const entries = index.byDisplay.get(display) ?? []
|
||||
entries.push(entry)
|
||||
index.byDisplay.set(display, entries)
|
||||
}
|
||||
return index
|
||||
}
|
||||
@@ -87,6 +104,10 @@ function findAntigravityWorkspace(
|
||||
session: AiVaultSession,
|
||||
index: AntigravityHistoryIndex
|
||||
): string | null {
|
||||
const directMatch = index.byConversationId.get(session.sessionId)
|
||||
if (directMatch) {
|
||||
return directMatch.workspace
|
||||
}
|
||||
// Why: truncated titles are not prompt identities; long worker prompts often
|
||||
// share the same 96-character prefix across unrelated workspaces.
|
||||
if (session.title.endsWith('...')) {
|
||||
@@ -99,10 +120,10 @@ function findAntigravityWorkspace(
|
||||
if (!Number.isFinite(promptTimestampMs)) {
|
||||
return null
|
||||
}
|
||||
const matches = (index.get(session.title) ?? []).filter(
|
||||
const matches = (index.byDisplay.get(session.title) ?? []).filter(
|
||||
(entry) => Math.abs(entry.timestampMs - promptTimestampMs) <= HISTORY_MATCH_WINDOW_MS
|
||||
)
|
||||
// Why: history rows have no conversation id. A unique prompt/time match is
|
||||
// evidence for cwd; ambiguity must stay unknown instead of crossing projects.
|
||||
// Why: legacy history rows have no conversation id. A unique prompt/time
|
||||
// match is evidence for cwd; ambiguity must stay unknown instead of crossing projects.
|
||||
return matches.length === 1 ? (matches[0]?.workspace ?? null) : null
|
||||
}
|
||||
|
||||
@@ -105,6 +105,71 @@ describe('Antigravity AI Vault discovery', () => {
|
||||
).toEqual([sessionId])
|
||||
})
|
||||
|
||||
it.each(['Connectivity setup only', 'Long setup prompt '.repeat(12)])(
|
||||
'uses the conversation id for a mismatched or truncated title: %s',
|
||||
async (firstPrompt) => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-antigravity-conversation-id-'))
|
||||
tempRoots.push(root)
|
||||
const roots = isolatedScanRoots(root)
|
||||
const sessionId = 'dddddddd-eeee-4fff-8aaa-bbbbbbbbbbbb'
|
||||
const workspace = join(root, 'active-workspace')
|
||||
await writeAntigravityTranscript(roots.antigravityBrainDir, sessionId, [
|
||||
{
|
||||
source: 'USER_EXPLICIT',
|
||||
type: 'USER_INPUT',
|
||||
created_at: '2026-07-15T11:39:10.000Z',
|
||||
content: `<USER_REQUEST>${firstPrompt}</USER_REQUEST>`
|
||||
},
|
||||
{
|
||||
source: 'USER_EXPLICIT',
|
||||
type: 'USER_INPUT',
|
||||
created_at: '2026-07-15T11:40:00.000Z',
|
||||
content: `<USER_REQUEST>${'long dispatched worker prompt '.repeat(8)}</USER_REQUEST>`
|
||||
}
|
||||
])
|
||||
await writeAntigravityHistory(roots.antigravityBrainDir, [
|
||||
{
|
||||
conversationId: sessionId,
|
||||
display: 'A later prompt with a different title',
|
||||
timestamp: Date.parse('2026-07-15T11:40:00.100Z'),
|
||||
workspace
|
||||
}
|
||||
])
|
||||
|
||||
const result = await scanAiVaultSessions({ ...roots, platform: 'darwin' })
|
||||
|
||||
expect(result.sessions[0]).toMatchObject({
|
||||
sessionId,
|
||||
cwd: workspace
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it('does not borrow a matching prompt from an explicitly different conversation', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-antigravity-foreign-id-'))
|
||||
tempRoots.push(root)
|
||||
const roots = isolatedScanRoots(root)
|
||||
const sessionId = '11111111-2222-4333-8444-555555555555'
|
||||
await writeAntigravityTranscript(roots.antigravityBrainDir, sessionId, [
|
||||
{
|
||||
source: 'USER_EXPLICIT',
|
||||
type: 'USER_INPUT',
|
||||
created_at: '2026-07-15T11:39:10.000Z',
|
||||
content: 'Same prompt'
|
||||
}
|
||||
])
|
||||
await writeAntigravityHistory(roots.antigravityBrainDir, [
|
||||
{
|
||||
conversationId: 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee',
|
||||
display: 'Same prompt',
|
||||
timestamp: Date.parse('2026-07-15T11:39:10.000Z'),
|
||||
workspace: join(root, 'other-workspace')
|
||||
}
|
||||
])
|
||||
const result = await scanAiVaultSessions({ ...roots, platform: 'darwin' })
|
||||
expect(result.sessions[0]?.cwd).toBeNull()
|
||||
})
|
||||
|
||||
it('keeps workspace unknown when matching history rows are ambiguous', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-antigravity-ambiguous-'))
|
||||
tempRoots.push(root)
|
||||
|
||||
Reference in New Issue
Block a user