feat(desktop): embed BoosAPI Desktop client as a subproject

Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
This commit is contained in:
boos
2026-06-22 11:32:57 +08:00
parent d9c78ecc73
commit e0a5f57793
2305 changed files with 449355 additions and 0 deletions
@@ -0,0 +1,774 @@
#!/usr/bin/env node
// Validate that diff presentation toggles refresh in place without remounting
// the Monaco diff tree or shifting the host geometry.
import net from 'node:net'
import path from 'node:path'
import process from 'node:process'
import { spawn } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import { chromium } from 'playwright'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const repoRoot = path.resolve(__dirname, '..')
const demoDir = path.join(repoRoot, 'examples', 'streaming-demo')
function isPortOpen(port, host = '127.0.0.1') {
return new Promise((resolve) => {
const sock = net.createConnection({ host, port })
sock.on('connect', () => {
sock.end()
resolve(true)
})
sock.on('error', () => {
sock.destroy()
resolve(false)
})
})
}
async function findFreePort(start = 5173, end = 5190) {
for (let port = start; port <= end; port++) {
// eslint-disable-next-line no-await-in-loop
const open = await isPortOpen(port)
if (!open) return port
}
throw new Error(`No free port found in ${start}-${end}`)
}
async function waitForPort(port, ms = 30000) {
const start = Date.now()
while (true) {
// eslint-disable-next-line no-await-in-loop
const open = await isPortOpen(port)
if (open) return
if (Date.now() - start > ms)
throw new Error(`Timed out waiting for port ${port}`)
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => setTimeout(r, 150))
}
}
function killProcessTree(child) {
if (!child || child.killed) return
try {
child.kill('SIGTERM')
} catch {}
setTimeout(() => {
try {
if (!child.killed) child.kill('SIGKILL')
} catch {}
}, 3000).unref?.()
}
function round(value) {
return Math.round(value * 1000) / 1000
}
function colorLuminance(color) {
const channels = String(color || '').match(/\d+(?:\.\d+)?/g)
if (!channels || channels.length < 3) return null
const [r, g, b] = channels.slice(0, 3).map(Number)
return 0.2126 * r + 0.7152 * g + 0.0722 * b
}
function rectDelta(a, b) {
if (!a || !b) return Number.POSITIVE_INFINITY
return Math.max(
Math.abs((a.left ?? 0) - (b.left ?? 0)),
Math.abs((a.top ?? 0) - (b.top ?? 0)),
Math.abs((a.width ?? 0) - (b.width ?? 0)),
Math.abs((a.height ?? 0) - (b.height ?? 0)),
)
}
function maxRectDelta(frames, key, baseline) {
return frames.reduce((max, frame) => {
return Math.max(max, rectDelta(frame[key], baseline[key]))
}, 0)
}
function allFramesTrue(frames, selector) {
return frames.every((frame) => selector(frame) === true)
}
async function invokeDiffTestApi(page, methodName, ...args) {
await page.evaluate(
({ methodName, args }) => {
const api = window.__streamMonacoDiffTestApi
const method = api?.[methodName]
if (typeof method !== 'function')
throw new Error(`Missing diff test API method: ${methodName}`)
return method(...args)
},
{ methodName, args },
)
}
async function primeModifiedScroll(page, top = 240) {
await invokeDiffTestApi(page, 'setModifiedScrollTop', top)
await page.waitForTimeout(180)
const actual = await page.evaluate(() => {
return window.__streamMonacoDiffTestApi?.getModifiedScrollTop?.() ?? 0
})
if (actual < Math.min(40, top * 0.2)) {
throw new Error(
`Failed to prime modified scroll position. expected around ${top}, got ${actual}`,
)
}
}
async function startTransitionProbe(page, frameCount = 42) {
await page.evaluate((requestedFrames) => {
const rectData = (node) => {
if (!(node instanceof HTMLElement)) return null
const rect = node.getBoundingClientRect()
return {
left: rect.left,
top: rect.top,
width: rect.width,
height: rect.height,
}
}
const isVisible = (node) => {
if (!(node instanceof HTMLElement)) return false
const style = getComputedStyle(node)
if (style.display === 'none' || style.visibility === 'hidden')
return false
const rect = node.getBoundingClientRect()
return rect.width > 0 && rect.height > 0
}
const countVisible = (selector) =>
Array.from(document.querySelectorAll(selector)).filter(isVisible).length
const readVisibleWidgets = (rootSelector) => {
const root = document.querySelector(rootSelector)
if (!(root instanceof HTMLElement)) return []
const rootRect = root.getBoundingClientRect()
return Array.from(root.querySelectorAll('.diff-hidden-lines-widget'))
.map((node) => {
if (!(node instanceof HTMLElement)) return null
const rect = node.getBoundingClientRect()
if (
rect.height <= 0 ||
rect.bottom <= rootRect.top + 1 ||
rect.top >= rootRect.bottom - 1
) {
return null
}
return {
topOffset: rect.top - rootRect.top,
height: rect.height,
}
})
.filter(Boolean)
.sort((a, b) => a.topOffset - b.topOffset)
}
const readVisibleAnchor = (rootSelector) => {
const root = document.querySelector(rootSelector)
if (!(root instanceof HTMLElement)) return null
const rootRect = root.getBoundingClientRect()
const anchor = Array.from(root.querySelectorAll('.line-numbers'))
.map((node) => {
const rect = node.getBoundingClientRect()
const lineNumber = Number.parseInt(node.textContent?.trim() || '', 10)
return { lineNumber, rect }
})
.filter(({ lineNumber, rect }) => {
return (
Number.isFinite(lineNumber) &&
rect.height > 0 &&
rect.bottom > rootRect.top + 1 &&
rect.top < rootRect.bottom - 1
)
})
.sort((a, b) => a.rect.top - b.rect.top)[0]
if (!anchor) return null
return {
lineNumber: anchor.lineNumber,
topOffset: anchor.rect.top - rootRect.top,
}
}
const readVisibleLineTops = (rootSelector) => {
const root = document.querySelector(rootSelector)
if (!(root instanceof HTMLElement)) return {}
const rootRect = root.getBoundingClientRect()
return Object.fromEntries(
Array.from(root.querySelectorAll('.line-numbers'))
.map((node) => {
if (!(node instanceof HTMLElement)) return null
const lineNumber = Number.parseInt(
node.textContent?.trim() || '',
10,
)
const rect = node.getBoundingClientRect()
if (
!Number.isFinite(lineNumber) ||
rect.height <= 0 ||
rect.bottom <= rootRect.top + 1 ||
rect.top >= rootRect.bottom - 1
) {
return null
}
return [String(lineNumber), rect.top - rootRect.top]
})
.filter(Boolean),
)
}
const readVisibleSummaryStates = (selector) => {
return Array.from(document.querySelectorAll(selector))
.filter(isVisible)
.map((node) => {
if (!(node instanceof HTMLButtonElement)) return null
const style = getComputedStyle(node)
return {
cursor: style.cursor,
pointerEvents: style.pointerEvents,
disabled: node.disabled,
}
})
.filter(Boolean)
}
const baselineNodes = {
host: document.querySelector('.editor-card'),
diffRoot: document.querySelector('.monaco-diff-editor'),
original: document.querySelector('.editor.original'),
modified: document.querySelector('.editor.modified'),
overlay: document.querySelector('.stream-monaco-diff-unchanged-overlay'),
}
const capture = () => {
const host = document.querySelector('.editor-card')
const frame = document.querySelector('.line-info-compare-frame')
const diffRoot = document.querySelector('.monaco-diff-editor')
const original = document.querySelector('.editor.original')
const modified = document.querySelector('.editor.modified')
const overlay = document.querySelector(
'.stream-monaco-diff-unchanged-overlay',
)
const backgroundProbe =
diffRoot?.querySelector('.monaco-editor .monaco-editor-background') ??
diffRoot?.querySelector('.monaco-editor-background')
const rootContainer = document.querySelector('.stream-monaco-diff-root')
return {
frameRect: rectData(frame),
hostRect: rectData(host),
diffRect: rectData(diffRoot),
overlayRect: rectData(overlay),
modifiedScrollTop:
window.__streamMonacoDiffTestApi?.getModifiedScrollTop?.() ?? 0,
modifiedAnchor: readVisibleAnchor('.editor.modified'),
modifiedVisibleWidgets: readVisibleWidgets('.editor.modified'),
modifiedVisibleLineTops: readVisibleLineTops('.editor.modified'),
visibleBridgeRailCount: countVisible(
'.stream-monaco-diff-unchanged-bridge .stream-monaco-unchanged-rail',
),
visibleBridgeRevealCount: countVisible(
'.stream-monaco-diff-unchanged-bridge .stream-monaco-unchanged-reveal',
),
visibleMetadataSummaryStates: readVisibleSummaryStates(
'.stream-monaco-diff-unchanged-bridge .stream-monaco-unchanged-summary-metadata',
),
visibleSimpleSummaryStates: readVisibleSummaryStates(
'.stream-monaco-diff-unchanged-bridge .stream-monaco-unchanged-summary-simple',
),
bridgeCount: countVisible('.stream-monaco-diff-unchanged-bridge'),
backgroundColor:
backgroundProbe instanceof HTMLElement
? getComputedStyle(backgroundProbe).backgroundColor
: '',
rootClasses:
rootContainer instanceof HTMLElement
? Array.from(rootContainer.classList)
: [],
nodes: {
hostSame: host === baselineNodes.host,
diffRootSame: diffRoot === baselineNodes.diffRoot,
originalSame: original === baselineNodes.original,
modifiedSame: modified === baselineNodes.modified,
overlaySame: overlay === baselineNodes.overlay,
},
}
}
const baseline = capture()
window.__streamMonacoTransitionProbe = new Promise((resolve) => {
const frames = []
let remaining = Math.max(1, requestedFrames)
const tick = () => {
frames.push(capture())
remaining--
if (remaining <= 0) {
resolve({ baseline, frames })
return
}
requestAnimationFrame(tick)
}
requestAnimationFrame(tick)
})
}, frameCount)
}
async function collectTransition(page, trigger) {
await startTransitionProbe(page)
await trigger()
return page.evaluate(() => window.__streamMonacoTransitionProbe)
}
function summarizeTransition(name, result, options = {}) {
const {
expectedRootClass,
geometryBudget = 0.75,
requireGeometryStable = true,
expectLuminance = null,
requireModifiedScrollStable = true,
scrollBudget = 1,
requireModifiedAnchorStable = false,
anchorBudget = 1,
expectedVisibleWidgetHeight = null,
expectAnyModifiedLineShiftUpAtLeast = null,
expectedVisibleRailCount = null,
expectedVisibleRevealCount = null,
requireMetadataSummaryNonInteractive = false,
requireSimpleSummaryNonInteractive = false,
} = options
const baseline = result.baseline
const frames = result.frames
const finalFrame = frames.at(-1) ?? baseline
const hostMaxDelta = maxRectDelta(frames, 'hostRect', baseline)
const diffMaxDelta = maxRectDelta(frames, 'diffRect', baseline)
const frameMaxDelta = maxRectDelta(frames, 'frameRect', baseline)
const overlayMaxDelta =
baseline.overlayRect && finalFrame.overlayRect
? maxRectDelta(frames, 'overlayRect', baseline)
: 0
const modifiedScrollMaxDelta = frames.reduce((max, frame) => {
return Math.max(
max,
Math.abs(
(frame.modifiedScrollTop ?? 0) - (baseline.modifiedScrollTop ?? 0),
),
)
}, 0)
const anchorLineStable = frames.every((frame) => {
return (
frame.modifiedAnchor?.lineNumber != null &&
frame.modifiedAnchor?.lineNumber === baseline.modifiedAnchor?.lineNumber
)
})
const modifiedAnchorMaxDelta = frames.reduce((max, frame) => {
if (
baseline.modifiedAnchor?.lineNumber == null ||
frame.modifiedAnchor?.lineNumber !== baseline.modifiedAnchor?.lineNumber
) {
return Number.POSITIVE_INFINITY
}
return Math.max(
max,
Math.abs(
(frame.modifiedAnchor?.topOffset ?? 0) -
(baseline.modifiedAnchor?.topOffset ?? 0),
),
)
}, 0)
const finalWidgetHeights = (finalFrame.modifiedVisibleWidgets ?? []).map(
(widget) => round(widget.height),
)
const widgetHeightOk =
expectedVisibleWidgetHeight == null
? true
: finalWidgetHeights.length > 0 &&
finalWidgetHeights.every(
(height) => Math.abs(height - expectedVisibleWidgetHeight) <= 1,
)
const baselineVisibleLineTops = baseline.modifiedVisibleLineTops ?? {}
const finalVisibleLineTops = finalFrame.modifiedVisibleLineTops ?? {}
const sharedLineShiftDeltas = Object.keys(baselineVisibleLineTops)
.filter((lineNumber) => lineNumber in finalVisibleLineTops)
.map((lineNumber) => {
return round(
finalVisibleLineTops[lineNumber] - baselineVisibleLineTops[lineNumber],
)
})
const minSharedLineShift =
sharedLineShiftDeltas.length > 0 ? Math.min(...sharedLineShiftDeltas) : null
const maxSharedLineShift =
sharedLineShiftDeltas.length > 0 ? Math.max(...sharedLineShiftDeltas) : null
const lineShiftOk =
expectAnyModifiedLineShiftUpAtLeast == null
? true
: sharedLineShiftDeltas.some(
(delta) => delta <= -expectAnyModifiedLineShiftUpAtLeast,
)
const visibleRailCountOk =
expectedVisibleRailCount == null
? true
: (finalFrame.visibleBridgeRailCount ?? 0) === expectedVisibleRailCount
const visibleRevealCountOk =
expectedVisibleRevealCount == null
? true
: (finalFrame.visibleBridgeRevealCount ?? 0) ===
expectedVisibleRevealCount
const metadataSummaryStates = finalFrame.visibleMetadataSummaryStates ?? []
const metadataSummaryNonInteractiveOk = requireMetadataSummaryNonInteractive
? metadataSummaryStates.length > 0 &&
metadataSummaryStates.every((state) => {
return (
state.cursor !== 'pointer' &&
state.pointerEvents === 'none' &&
state.disabled === true
)
})
: true
const simpleSummaryStates = finalFrame.visibleSimpleSummaryStates ?? []
const simpleSummaryNonInteractiveOk = requireSimpleSummaryNonInteractive
? simpleSummaryStates.length > 0 &&
simpleSummaryStates.every((state) => {
return (
state.cursor !== 'pointer' &&
state.pointerEvents === 'none' &&
state.disabled === true
)
})
: true
const nodeStable = {
host: allFramesTrue(frames, (frame) => frame.nodes.hostSame),
diffRoot: allFramesTrue(frames, (frame) => frame.nodes.diffRootSame),
original: allFramesTrue(frames, (frame) => frame.nodes.originalSame),
modified: allFramesTrue(frames, (frame) => frame.nodes.modifiedSame),
overlay: allFramesTrue(frames, (frame) => frame.nodes.overlaySame),
}
const finalLuminance = colorLuminance(finalFrame.backgroundColor)
const luminanceOk =
expectLuminance == null
? true
: expectLuminance === 'dark'
? finalLuminance != null && finalLuminance < 120
: finalLuminance != null && finalLuminance > 150
const geometryOk = requireGeometryStable
? hostMaxDelta <= geometryBudget &&
diffMaxDelta <= geometryBudget &&
frameMaxDelta <= geometryBudget
: true
const scrollOk = requireModifiedScrollStable
? modifiedScrollMaxDelta <= scrollBudget
: true
const anchorOk = requireModifiedAnchorStable
? anchorLineStable && modifiedAnchorMaxDelta <= anchorBudget
: true
const rootClassOk = expectedRootClass
? finalFrame.rootClasses.includes(expectedRootClass)
: true
const ok =
Object.values(nodeStable).every(Boolean) &&
geometryOk &&
scrollOk &&
anchorOk &&
widgetHeightOk &&
lineShiftOk &&
visibleRailCountOk &&
visibleRevealCountOk &&
metadataSummaryNonInteractiveOk &&
simpleSummaryNonInteractiveOk &&
rootClassOk &&
luminanceOk
return {
name,
ok,
expectedRootClass,
geometryBudget,
requireGeometryStable,
requireModifiedScrollStable,
scrollBudget,
requireModifiedAnchorStable,
anchorBudget,
rootClassOk,
scrollOk,
anchorOk,
widgetHeightOk,
lineShiftOk,
visibleRailCountOk,
visibleRevealCountOk,
metadataSummaryNonInteractiveOk,
simpleSummaryNonInteractiveOk,
luminanceOk,
finalLuminance: round(finalLuminance ?? Number.NaN),
nodeStable,
geometry: {
hostMaxDelta: round(hostMaxDelta),
diffMaxDelta: round(diffMaxDelta),
frameMaxDelta: round(frameMaxDelta),
overlayMaxDelta: round(overlayMaxDelta),
},
scroll: {
before: round(baseline.modifiedScrollTop ?? 0),
after: round(finalFrame.modifiedScrollTop ?? 0),
maxDelta: round(modifiedScrollMaxDelta),
},
anchor: {
before: baseline.modifiedAnchor ?? null,
after: finalFrame.modifiedAnchor ?? null,
lineStable: anchorLineStable,
maxDelta: round(modifiedAnchorMaxDelta),
},
unchangedWidgets: {
expectedHeight: expectedVisibleWidgetHeight,
finalHeights: finalWidgetHeights,
},
lineShift: {
min: minSharedLineShift,
max: maxSharedLineShift,
expectedShiftUpAtLeast: expectAnyModifiedLineShiftUpAtLeast,
},
bridgeChrome: {
expectedVisibleRailCount,
actualVisibleRailCount: finalFrame.visibleBridgeRailCount ?? 0,
expectedVisibleRevealCount,
actualVisibleRevealCount: finalFrame.visibleBridgeRevealCount ?? 0,
},
metadataSummary: {
requireNonInteractive: requireMetadataSummaryNonInteractive,
states: metadataSummaryStates,
},
simpleSummary: {
requireNonInteractive: requireSimpleSummaryNonInteractive,
states: simpleSummaryStates,
},
bridgeCount: {
before: baseline.bridgeCount,
after: finalFrame.bridgeCount,
},
finalRootClasses: finalFrame.rootClasses,
}
}
async function main() {
const port = process.env.PORT
? Number(process.env.PORT)
: await findFreePort()
const vite = spawn(
'pnpm',
[
'-C',
demoDir,
'dev',
'--host',
'127.0.0.1',
'--port',
String(port),
'--strictPort',
],
{ stdio: ['ignore', 'pipe', 'pipe'], env: process.env },
)
const logs = []
vite.stdout.on('data', (d) => logs.push(String(d)))
vite.stderr.on('data', (d) => logs.push(String(d)))
const onExit = () => killProcessTree(vite)
process.on('SIGINT', onExit)
process.on('SIGTERM', onExit)
process.on('exit', onExit)
try {
await waitForPort(port)
const browser = await chromium.launch({ headless: true })
const page = await browser.newPage({
viewport: { width: 1960, height: 1600 },
deviceScaleFactor: 2,
})
const pageErrors = []
const consoleErrors = []
page.on('pageerror', (error) => {
pageErrors.push(String(error))
})
page.on('console', (message) => {
if (message.type() === 'error') consoleErrors.push(message.text())
})
const url = `http://127.0.0.1:${port}/diff-ux?style=background&scenario=line-info-reference&theme=vitesse-light&appearance=light&unchangedStyle=line-info`
await page.goto(url, { waitUntil: 'networkidle' })
await page.waitForSelector('.editor-card', { timeout: 20000 })
await page.waitForSelector('.monaco-diff-editor', { timeout: 20000 })
await page.waitForSelector('.stream-monaco-diff-unchanged-overlay', {
timeout: 20000,
})
await page.waitForTimeout(1400)
const results = []
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'appearance-light-to-dark',
await collectTransition(page, async () => {
await page.getByRole('button', { name: /^Dark$/ }).click()
}),
{
expectedRootClass: 'stream-monaco-diff-appearance-dark',
requireGeometryStable: true,
expectLuminance: 'dark',
requireModifiedScrollStable: true,
expectedVisibleWidgetHeight: 32,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'appearance-dark-to-light',
await collectTransition(page, async () => {
await page.getByRole('button', { name: /^Light$/ }).click()
}),
{
expectedRootClass: 'stream-monaco-diff-appearance-light',
requireGeometryStable: true,
expectLuminance: 'light',
requireModifiedScrollStable: true,
expectedVisibleWidgetHeight: 32,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'style-line-info-to-basic',
await collectTransition(page, async () => {
await page.getByRole('button', { name: /^Line Info Basic$/ }).click()
}),
{
expectedRootClass:
'stream-monaco-diff-unchanged-style-line-info-basic',
requireGeometryStable: true,
requireModifiedScrollStable: true,
expectedVisibleWidgetHeight: 32,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'style-basic-to-metadata',
await collectTransition(page, async () => {
await page
.getByRole('button', { name: /^Metadata$/ })
.first()
.click()
}),
{
expectedRootClass: 'stream-monaco-diff-unchanged-style-metadata',
requireGeometryStable: true,
requireModifiedScrollStable: true,
expectedVisibleWidgetHeight: 32,
expectedVisibleRailCount: 0,
expectedVisibleRevealCount: 0,
requireMetadataSummaryNonInteractive: true,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'set-diff-models-same-content',
await collectTransition(page, async () => {
await invokeDiffTestApi(page, 'swapModelsSameContent')
}),
{
expectedRootClass: 'stream-monaco-diff-unchanged-style-metadata',
requireGeometryStable: true,
requireModifiedScrollStable: false,
requireModifiedAnchorStable: true,
anchorBudget: 1,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'set-diff-models-changed-content',
await collectTransition(page, async () => {
await invokeDiffTestApi(page, 'swapModelsChangedContent')
}),
{
expectedRootClass: 'stream-monaco-diff-unchanged-style-metadata',
requireGeometryStable: true,
requireModifiedScrollStable: false,
},
),
)
await primeModifiedScroll(page)
results.push(
summarizeTransition(
'style-metadata-to-simple',
await collectTransition(page, async () => {
await page
.getByRole('button', { name: /^Simple$/ })
.first()
.click()
}),
{
expectedRootClass: 'stream-monaco-diff-unchanged-style-simple',
requireGeometryStable: false,
requireModifiedScrollStable: true,
expectedVisibleRailCount: 0,
expectedVisibleRevealCount: 0,
requireSimpleSummaryNonInteractive: true,
},
),
)
await browser.close()
const ok =
pageErrors.length === 0 &&
consoleErrors.length === 0 &&
results.every((result) => result.ok)
const output = {
ok,
url,
pageErrors,
consoleErrors,
results,
}
console.log(JSON.stringify(output, null, 2))
if (!ok) {
console.error('Transition validation failed; recent Vite logs:\n')
console.error(logs.slice(-60).join(''))
process.exit(1)
}
} catch (error) {
console.error('Transition validation startup/runtime error:')
console.error(error)
if (logs.length > 0) {
console.error('Recent Vite logs:\n')
console.error(logs.slice(-60).join(''))
}
throw error
} finally {
killProcessTree(vite)
}
}
main().catch((error) => {
console.error(error)
process.exit(1)
})