mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
* feat(web): in-place cursor variant drill-down (closes #48) Rebased onto upstream/main: iOS-style nested picker keeps overlay open on multi-variant base pick, applies default variant immediately, dismisses on variant selection; preserves upstream Pi model panels and Codex Fast mode. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web+cli): accept bare Cursor ACP model ids in picker catalog Current Cursor ACP returns bare bases (composer-2.5, …) with empty cliModelSkus. The bracket-only wire gate emptied the catalog so the picker showed only Default. Treat bare non-default ACP ids as catalog rows, keep CLI effort/speed SKUs as variants, and widen SKU enrichment the same way. Closes #1129. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web): ignore stale selectedModelVariant during Cursor base drill-down Only highlight a session variant when it is still among the visible rows, so a multi-variant base switch uses the new default until parent state catches up (Codex Minor on #947). Co-authored-by: Cursor <cursoragent@cursor.com> * fix(cli+shared): do not attach CLI variant SKUs to bare ACP catalogs Bare ACP bases cannot express effort/speed (apply is model+fast on parameterized wires). Drop suffixed SKUs unless a base has bracket wires, and refuse matchCliSkuToAcpWireId collapse onto bare-only rows. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web): serialize Cursor model applies across base/variant picks Drill-down default apply and a quick variant click could race setModel RPCs; last-finisher wins. Queue Cursor applies in SessionChat so the explicit variant cannot be overwritten by a late default. Co-authored-by: Cursor <cursoragent@cursor.com> * test(web): align cursor picker auto-row label with upstream Auto Rebase onto main picked up Default→Auto rename; keep #1129 coverage. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Debian <heavygee@oos-linux.in.lockhouse>
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { createSerialAsyncQueue } from './serialAsyncQueue'
|
|
|
|
describe('createSerialAsyncQueue', () => {
|
|
it('runs enqueued work in order even when the second starts while the first is pending', async () => {
|
|
const enqueue = createSerialAsyncQueue()
|
|
const order: number[] = []
|
|
let releaseFirst!: () => void
|
|
const firstGate = new Promise<void>((resolve) => {
|
|
releaseFirst = resolve
|
|
})
|
|
|
|
const first = enqueue(async () => {
|
|
await firstGate
|
|
order.push(1)
|
|
})
|
|
const second = enqueue(async () => {
|
|
order.push(2)
|
|
})
|
|
|
|
expect(order).toEqual([])
|
|
releaseFirst()
|
|
await Promise.all([first, second])
|
|
expect(order).toEqual([1, 2])
|
|
})
|
|
|
|
it('continues after a rejected run', async () => {
|
|
const enqueue = createSerialAsyncQueue()
|
|
const order: number[] = []
|
|
await enqueue(async () => {
|
|
order.push(1)
|
|
throw new Error('boom')
|
|
}).catch(() => undefined)
|
|
await enqueue(async () => {
|
|
order.push(2)
|
|
})
|
|
expect(order).toEqual([1, 2])
|
|
})
|
|
})
|