Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,33 @@ describe('ChatDatabase', () => {
sinon.restore()
})

describe('pinned context', () => {
beforeEach(async () => {
await chatDb.databaseInitialize(0)
})

it('does not mutate the shared DEFAULT_PINNED_CONTEXT when pinning in a tab', () => {
const defaultLengthBefore = util.DEFAULT_PINNED_CONTEXT.length
const customContext = { id: 'custom-folder-ctx', command: 'myFolder', label: 'folder' } as any

// Create the tab first (with tabContext but no pinnedContext yet) so that
// addPinnedContext initializes pinnedContext from the shared default — the
// code path that previously aliased and then mutated DEFAULT_PINNED_CONTEXT.
chatDb.setRules('tab-1', { folders: {}, rules: {} } as any)
chatDb.addPinnedContext('tab-1', customContext)

// The shared module-level default must not be polluted by pinning in a tab,
// otherwise every new chat window would inherit the custom pinned item.
assert.strictEqual(util.DEFAULT_PINNED_CONTEXT.length, defaultLengthBefore)
assert.ok(!util.DEFAULT_PINNED_CONTEXT.some((c: any) => c.id === 'custom-folder-ctx'))

// A brand-new tab must only receive the default pinned context, not the item
// that was pinned in a different tab.
const freshTabPinned = chatDb.getPinnedContext('tab-2-fresh')
assert.ok(!freshTabPinned.some((c: any) => c.id === 'custom-folder-ctx'))
})
})

describe('replaceWithSummary', () => {
it('should create a new history with summary message', async () => {
await chatDb.databaseInitialize(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
estimateCharacterCountFromImageBlock,
isCachedValid,
} from './util'
import * as crypto from 'crypto'

Check warning on line 29 in server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/chatDb/chatDb.ts

View workflow job for this annotation

GitHub Actions / Test (Windows)

Do not import Node.js builtin module "crypto"

Check warning on line 29 in server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/chatDb/chatDb.ts

View workflow job for this annotation

GitHub Actions / Test

Do not import Node.js builtin module "crypto"
import * as path from 'path'
import { Features } from '@aws/language-server-runtimes/server-interface/server'
import { ContextCommand, ConversationItemGroup, Model } from '@aws/language-server-runtimes/protocol'
Expand Down Expand Up @@ -269,7 +269,9 @@
const historyId = this.getOrCreateHistoryId(tabId)
if (historyId) {
const tab = collection.findOne({ historyId })
return tab?.tabContext?.pinnedContext || DEFAULT_PINNED_CONTEXT
// Return a copy of the default so callers cannot mutate the shared
// module-level DEFAULT_PINNED_CONTEXT array.
return tab?.tabContext?.pinnedContext || [...DEFAULT_PINNED_CONTEXT]
}
}
return []
Expand Down Expand Up @@ -313,7 +315,10 @@
tab.tabContext = {}
}
if (!tab.tabContext.pinnedContext) {
tab.tabContext.pinnedContext = DEFAULT_PINNED_CONTEXT
// Use a copy: DEFAULT_PINNED_CONTEXT is a shared module-level array,
// and the unshift/push below would otherwise mutate it, polluting the
// default pinned context for every new tab/chat window.
tab.tabContext.pinnedContext = [...DEFAULT_PINNED_CONTEXT]
}
// Only add context item if its not already in this tab's pinned context
if (!tab.tabContext.pinnedContext.find(c => c.id === context.id)) {
Expand Down
Loading