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
7 changes: 4 additions & 3 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
"lodash": "*",
"micromatch": "^4.0.8",
"nanoid": "5.0.7",
"node-machine-id": "^1.1.12",
"onetime": "5.1.2",
"picocolors": "1.1.0",
"pino": "9.4.0",
Expand Down Expand Up @@ -1653,7 +1654,7 @@

"devlop": ["[email protected]", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],

"devtools-protocol": ["[email protected].1452169", "", {}, "sha512-FOFDVMGrAUNp0dDKsAU1TorWJUx2JOU1k9xdgBKKJF3IBh/Uhl2yswG5r3TEAOrCiGY2QRp1e6LVDQrCsTKO4g=="],
"devtools-protocol": ["[email protected].1464554", "", {}, "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw=="],

"didyoumean": ["[email protected]", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],

Expand Down Expand Up @@ -2865,7 +2866,7 @@

"punycode": ["[email protected]", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],

"puppeteer-core": ["puppeteer-core@24.10.1", "", { "dependencies": { "@puppeteer/browsers": "2.10.5", "chromium-bidi": "5.1.0", "debug": "^4.4.1", "devtools-protocol": "0.0.1452169", "typed-query-selector": "^2.12.0", "ws": "^8.18.2" } }, "sha512-AE6doA9znmEEps/pC5lc9p0zejCdNLR6UBp3EZ49/15Nbvh+uklXxGox7Qh8/lFGqGVwxInl0TXmsOmIuIMwiQ=="],
"puppeteer-core": ["puppeteer-core@24.12.0", "", { "dependencies": { "@puppeteer/browsers": "2.10.5", "chromium-bidi": "5.1.0", "debug": "^4.4.1", "devtools-protocol": "0.0.1464554", "typed-query-selector": "^2.12.0", "ws": "^8.18.3" } }, "sha512-VrPXPho5Q90Ao86FwJVb+JeAF2Tf41wOTGg8k2SyQJePiJ6hJ5iujYpmP+bmhlb6o+J26bQYRDPOYXP7ALWcxQ=="],

"pure-rand": ["[email protected]", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],

Expand Down Expand Up @@ -4061,7 +4062,7 @@

"puppeteer-core/debug": ["[email protected]", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],

"puppeteer-core/ws": ["[email protected].2", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ=="],
"puppeteer-core/ws": ["[email protected].3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],

"react-devtools-core/ws": ["[email protected]", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],

Expand Down
1 change: 1 addition & 0 deletions npm-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"lodash": "*",
"micromatch": "^4.0.8",
"nanoid": "5.0.7",
"node-machine-id": "^1.1.12",
"onetime": "5.1.2",
"picocolors": "1.1.0",
"pino": "9.4.0",
Expand Down
63 changes: 63 additions & 0 deletions npm-app/src/__tests__/fingerprint-integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { calculateFingerprint } from '../fingerprint'

describe('Fingerprint Integration Test', () => {
it('should generate fingerprints and test both enhanced CLI and legacy modes', async () => {
console.log('🔍 Testing enhanced CLI fingerprinting implementation...')

// Test multiple fingerprint generations
const results = []
for (let i = 0; i < 3; i++) {
const start = Date.now()
const fingerprint = await calculateFingerprint()
const duration = Date.now() - start

results.push({
fingerprint,
duration,
isEnhanced: fingerprint.startsWith('enhanced-') || fingerprint.startsWith('fp-'),
isLegacy: fingerprint.startsWith('legacy-')
})

console.log(`Attempt ${i + 1}: ${fingerprint} (${duration}ms)`)
}

// Verify all fingerprints are valid
results.forEach((result, index) => {
expect(result.fingerprint).toBeDefined()
expect(typeof result.fingerprint).toBe('string')
expect(result.fingerprint.length).toBeGreaterThan(20)
expect(result.isEnhanced || result.isLegacy).toBe(true)
})

// Check uniqueness patterns
// Enhanced fingerprints should be deterministic (same each time)
// Legacy fingerprints should be unique (due to random suffix)
const enhancedResults = results.filter(r => r.isEnhanced)
const legacyResults = results.filter(r => r.isLegacy)

if (enhancedResults.length > 1) {
// Enhanced fingerprints should be identical (deterministic)
const uniqueEnhanced = new Set(enhancedResults.map(r => r.fingerprint))
expect(uniqueEnhanced.size).toBe(1)
}

if (legacyResults.length > 1) {
// Legacy fingerprints should be unique (random suffix)
const uniqueLegacy = new Set(legacyResults.map(r => r.fingerprint))
expect(uniqueLegacy.size).toBe(legacyResults.length)
}

// Log summary
const enhancedCount = results.filter(r => r.isEnhanced).length
const legacyCount = results.filter(r => r.isLegacy).length
const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length

console.log(`\n📊 Results Summary:`)
console.log(` Enhanced: ${enhancedCount}/${results.length}`)
console.log(` Legacy: ${legacyCount}/${results.length}`)
console.log(` Avg Duration: ${avgDuration.toFixed(0)}ms`)

// At least one should succeed
expect(results.length).toBeGreaterThan(0)
}, 10000) // 10 second timeout for CLI operations
})
24 changes: 12 additions & 12 deletions npm-app/src/browser-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ import { logger } from './utils/logger'

type NonOptional<T, K extends keyof T> = T & { [P in K]-?: T[P] }

// Define helper to find Chrome in standard locations
export const findChrome = () => {
switch (process.platform) {
case 'win32':
return 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
case 'darwin':
return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
default:
return '/usr/bin/google-chrome'
}
}

export class BrowserRunner {
// Add getter methods for diagnostic loop
getLogs(): BrowserResponse['logs'] {
Expand Down Expand Up @@ -328,18 +340,6 @@ export class BrowserRunner {
} catch (error) {}

try {
// Define helper to find Chrome in standard locations
const findChrome = () => {
switch (process.platform) {
case 'win32':
return 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
case 'darwin':
return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
default:
return '/usr/bin/google-chrome'
}
}

this.browser = await puppeteer.launch({
defaultViewport: {
width: BROWSER_DEFAULTS.viewportWidth,
Expand Down
8 changes: 5 additions & 3 deletions npm-app/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import {
import { logAndHandleStartup } from './startup-process-handler'
import { handleToolCall } from './tool-handlers'
import { GitCommand, MakeNullable } from './types'
import { identifyUser, trackEvent } from './utils/analytics'
import { identifyUser, identifyUserWithFingerprint, trackEvent } from './utils/analytics'
import { getRepoMetrics, gitCommandIsAvailable } from './utils/git'
import { logger, loggerContext } from './utils/logger'
import { Spinner } from './utils/spinner'
Expand Down Expand Up @@ -289,7 +289,8 @@ export class Client {
const credentialsFile = readFileSync(CREDENTIALS_PATH, 'utf8')
const user = userFromJson(credentialsFile)
if (user) {
identifyUser(user.id, {
// Use enhanced fingerprint identification for better analytics
identifyUserWithFingerprint(user.id, {
email: user.email,
name: user.name,
fingerprintId: this.fingerprintId,
Expand Down Expand Up @@ -593,7 +594,8 @@ export class Client {
shouldRequestLogin = false
this.user = user

identifyUser(user.id, {
// Use enhanced fingerprint identification for login
identifyUserWithFingerprint(user.id, {
email: user.email,
name: user.name,
fingerprintId: fingerprintId,
Expand Down
Loading