Skip to content

Commit 4fd0b06

Browse files
authored
fix(cli): strip endpoint trailing slashes in linear time, deflake projection test (#8285)
1 parent 40f4a8e commit 4fd0b06

3 files changed

Lines changed: 31 additions & 2 deletions

File tree

‎apps/sim/lib/knowledge/__integration__/knowledge-projection.integration.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ const members = {
9898
const subjectToken = (subject: string) => `s:github-repositories:-:${subject}`
9999
const aclOf = (...who: Array<'alice' | 'bob'>) =>
100100
who.map((name) => subjectToken(members[name].subject)).sort()
101-
const vector = [1, ...Array<number>(1535).fill(0)]
101+
/**
102+
* A direction no other integration file writes. The vector legs here walk the approximate index,
103+
* which the files sharing this database crowd with `[1, 0, …]` rows; tied at distance zero with
104+
* this file's chunks, those can exhaust the walk's tuple cap before it reaches them. Inside the
105+
* first 512 dimensions, the only ones the candidate projection keeps.
106+
*/
107+
const vector = Array.from({ length: 1536 }, (_, index) => (index === 511 ? 1 : 0))
102108
const queryVector = {
103109
vector: JSON.stringify(vector),
104110
dimensions: 1536 as const,

‎packages/sim-cli/src/config/profile.test.ts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,18 @@ describe('profile resolution', () => {
257257
expect(resolveProfile({ endpoint: 'https://sim.ai///' }).endpoint).toBe('https://sim.ai')
258258
})
259259

260+
it('keeps inner slashes and strips a long trailing run in linear time', () => {
261+
expect(resolveProfile({ endpoint: 'https://sim.ai/a//b//' }).endpoint).toBe(
262+
'https://sim.ai/a//b'
263+
)
264+
const slashes = '/'.repeat(100_000)
265+
const started = performance.now()
266+
expect(resolveProfile({ endpoint: `https://sim.ai/${slashes}x` }).endpoint).toBe(
267+
`https://sim.ai/${slashes}x`
268+
)
269+
expect(performance.now() - started).toBeLessThan(1000)
270+
})
271+
260272
it('trims a padded endpoint instead of storing text the writer would refuse', () => {
261273
// `new URL()` tolerates padding and hands the string straight back, but the
262274
// config writer refuses it. Untrimmed, `login --endpoint " https://…"` threw

‎packages/sim-cli/src/config/profile.ts‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,17 @@ export function deleteProfile(profile: string): { config: boolean; credentials:
576576
return { config, credentials }
577577
}
578578

579+
/**
580+
* Removes every trailing `/`. A backward scan rather than `/\/+$/`: that regex
581+
* restarts at each `/` in a long run that does not reach the end, so it is
582+
* quadratic in the run length.
583+
*/
584+
function stripTrailingSlashes(value: string): string {
585+
let end = value.length
586+
while (end > 0 && value.charCodeAt(end - 1) === 0x2f) end--
587+
return value.slice(0, end)
588+
}
589+
579590
/**
580591
* Validates an endpoint and strips its trailing slashes.
581592
*
@@ -597,7 +608,7 @@ export function normalizeEndpoint(endpoint: string, source: string): string {
597608
// naming the flag. It also has to come first so the slash strip sees the real
598609
// end of the URL — and that strip is there because a trailing slash produces
599610
// `https://sim.ai//api/v2/...`, which some proxies 404 rather than normalize.
600-
const trimmed = endpoint.trim().replace(/\/+$/, '')
611+
const trimmed = stripTrailingSlashes(endpoint.trim())
601612

602613
// Trimming only reaches the ends, and a control character in the middle is
603614
// the one that matters: the URL parser deletes tabs and line breaks from

0 commit comments

Comments
 (0)