mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
* [comment audit] Align legacy failure-read counts with cached display * [comment audit] Condense shared provider lifecycle and browser recovery comments [skip ci] * [comment audit] Condense shared generation, path and preview comments [skip ci] * [comment audit] Condense host, file and Git contract rationale [skip ci] * [comment audit] Tighten Git lifecycle and provider contract comments [skip ci] * [comment audit] Clarify shared host authority and launch isolation [skip ci] * [comment audit] simplify local access mobile and native chat contracts [skip ci] * [comment audit] simplify native chat presentation and state contracts [skip ci] * [comment audit] simplify native runtime and provider contracts [skip ci] * [comment audit] simplify migration and orchestration contracts [skip ci] * [comment audit] simplify plugin trust and process capture rationale [skip ci] * [comment audit] simplify terminal delivery and remote compatibility rationale [skip ci] * [comment audit] clarify remote recovery and launch wire rationale [skip ci] * [comment audit] shorten shared RPC compatibility and runtime evidence comments [skip ci] * [comment audit] simplify secure storage shell startup and sidebar rationale [skip ci] * [comment audit] clarify sidebar, skill and SSH invariants [skip ci] * [comment audit] condense structured chat delivery and timing rationale [skip ci] * [comment audit] condense terminal replay and telemetry invariants [skip ci] * [comment audit] clarify launch permission and terminal delivery rationale [skip ci] * [comment audit] clarify workspace ownership and layout contracts [skip ci] * [comment audit] wait for fitted and painted SSH terminal links * [comment audit] clarify layout persistence and session ownership [skip ci] * [comment audit] clarify host routing and workspace lifecycle contracts [skip ci] * [comment audit] clarify startup persistence and app lifetime comments [skip ci] * [comment audit] clarify recovery and activity boundaries [skip ci] * [comment audit] condense activity and artifact invariants [skip ci] * [comment audit] condense automation authority contracts [skip ci] * [comment audit] simplify automation scheduling and history contracts [skip ci] * [comment audit] clarify browser chrome and annotation lifecycles [skip ci] * [comment audit] clarify browser routing and retained guest ownership [skip ci] * [comment audit] clarify browser recovery and document ownership comments [skip ci] * [comment audit] restore hosted runners required by native IME fixtures * [comment audit] shorten preview, palette and dashboard invariants [skip ci] * [comment audit] clarify terminal preview, dashboard and retention comments [skip ci] * [comment audit] clarify diff-note recovery and editor lifecycle comments [skip ci] * [comment audit] shorten rich-text and combined-diff ownership comments [skip ci] * [comment audit] shorten autosave, draft recovery and model ownership comments [skip ci] * [comment audit] shorten save-queue, notebook and Markdown constraints [skip ci] * [comment audit] shorten Monaco, PDF and rich Markdown safeguards [skip ci] * [comment audit] clarify rich Markdown source and selection safeguards [skip ci] * [comment audit] clarify editor loading and emulator stream lifetimes [skip ci] * [comment audit] trim emulator and feature tour narration [skip ci] * [comment audit] clarify floating workspace and GitHub cache ownership [skip ci] * [comment audit] trim provider controls and Linear filter explanations [skip ci] * [comment audit] clarify pairing and chat resume lifetimes [skip ci] * [comment audit] clarify chat delivery and transcript lifetimes [skip ci] * [comment audit] clarify session options and host-owned status [skip ci] * [comment audit] clarify draft durability and live-status precedence [skip ci] * [comment audit] Trim chat send and model ownership explanations [skip ci] * [comment audit] Shorten transcript ownership and send recovery comments [skip ci] * [comment audit] Simplify native chat composer and transcript hook comments [skip ci] * [comment audit] Shorten native chat scroll and structured session explanations [skip ci] * [comment audit] Trim workspace picker and onboarding commentary [skip ci] * [comment audit] Simplify pet rendering, review cache and quick open comments [skip ci] * [comment audit] Trim sidebar and session history explanations [skip ci] * [comment audit] Condense session resume and review checks comments [skip ci] * [comment audit] Shorten checks state and file explorer refresh comments [skip ci] * [comment audit] Trim plugin bridge and source-control action rationale [skip ci] * [comment audit] Trim source-control listing and review rationale [skip ci] * [comment audit] Shorten sidebar lifecycle and explorer safeguards [skip ci] * [comment audit] Condense Settings account and appearance rationale [skip ci] * [comment audit] Trim pairing and repository Settings explanations [skip ci] * [comment audit] Condense Settings search SSH and terminal safeguards [skip ci] * [comment audit] Shorten Settings voice and provider ownership comments [skip ci] * [comment audit] Condense Settings draft persistence and host-state rationale [skip ci] * [comment audit] Trim Settings hooks and sidebar setup rationale [skip ci] * [comment audit] Condense sidebar deletion and board-filter safeguards [skip ci] * [comment audit] Condense worktree cards, host ownership and Markdown contracts [skip ci] * [comment audit] Condense sidebar drag, folder and filtering contracts [skip ci] * [comment audit] Condense sidebar parity, sleep and host ownership contracts [skip ci] * [comment audit] Prune focus-read baseline after comment cleanup * [comment audit] Clarify sidebar visibility, board drops and agent evidence [skip ci] * [comment audit] Tighten sidebar listing, drag and reveal contracts [skip ci] * [comment audit] Clarify viewport geometry and skill update safeguards [skip ci] * [comment audit] Tighten skill inventory, usage and host status comments [skip ci] * [comment audit] Clarify usage ownership and resource kill safeguards [skip ci] * [comment audit] Tighten tab selection, rename and search contracts [skip ci] * [comment audit] Tighten tab-strip geometry and drag ownership comments [skip ci] * [comment audit] Tighten Tasks recovery, pagination and mutation comments [skip ci] * [comment audit] Tighten provider loading and terminal recovery comments [skip ci] * [comment audit] Tighten completion, cadence and PTY ownership comments [skip ci] * [comment audit] Clarify terminal restore and parked-pane boundaries [skip ci] * [comment audit] Tighten PTY startup and replay explanations [skip ci] * [comment audit] Clarify PTY identity and delivery ownership [skip ci] * [comment audit] Shorten remote reconnect and input replay rationale [skip ci] * [comment audit] Condense terminal parking clipboard and file link comments [skip ci] * [comment audit] Clarify IME ownership and trim trace history [skip ci] * [comment audit] Shorten pane recovery and parked watcher explanations [skip ci] * [comment audit] Condense snapshot replay and visibility recovery rationale [skip ci] * [comment audit] Shorten terminal parking and keyboard ownership rationale [skip ci] * [comment audit] Trim renderer lifecycle and menu rationale [skip ci] * [comment audit] Condense workspace cleanup ownership and settlement notes [skip ci] * [comment audit] Clarify renderer hook evidence and source ownership [skip ci] * [comment audit] Tighten IPC ownership and reconnect explanations [skip ci] * [comment audit] Trim renderer focus, paste and attention comments [skip ci] * [comment audit] Shorten scroll, locale and agent lifecycle comments [skip ci] * [comment audit] Trim agent launch, resume and ownership commentary [skip ci] * [comment audit] Shorten account, browser and editor comments [skip ci] * [comment audit] Clarify host-mirror waits, previews and input ownership [skip ci] * [comment audit] Condense launch recovery and editor tokenization comments [skip ci] * [comment audit] Condense workspace selection and terminal pane rationale [skip ci] * [comment audit] Condense terminal fitting and rendering recovery comments [skip ci] * [comment audit] Condense terminal input and host routing explanations [skip ci] * [comment audit] Condense ownership and sleeping-session recovery rationale [skip ci] * [comment audit] Condense structured launch and terminal link explanations [skip ci] * [comment audit] Condense terminal ownership and workspace file routing rationale [skip ci] * [comment audit] Condense session persistence and workspace activation rationale [skip ci] * [comment audit] Condense workspace routing and browser ownership rationale [skip ci] * [comment audit] Condense mirror recovery and layout authority rationale [skip ci] * [comment audit] Condense runtime transport and file safety rationale [skip ci] * [comment audit] Condense runtime graph and structured session rationale [skip ci] * [comment audit] Condense browser creation and remote tab recovery rationale [skip ci] * [comment audit] Condense snapshot authority and publisher recovery rationale [skip ci] * [comment audit] Condense frame, startup and provider cache rationale [skip ci] * [comment audit] Condense host twin and agent lifecycle rationale [skip ci] * [comment audit] Condense browser authority and editor cleanup rationale [skip ci] * [comment audit] Condense editor buffer identity and review cache rationale [skip ci] * [comment audit] Condense provider lifetime and repository ownership rationale [skip ci] * [comment audit] Condense reconnect, hydration and terminal retirement rationale [skip ci] * [comment audit] Condense recovery, reconciliation and persistence rationale [skip ci] * [comment audit] Condense cleanup ownership and listing admission rationale [skip ci] * [comment audit] Condense teardown ordering and terminal ownership rationale [skip ci] * [comment audit] Condense recovery ledger and web host-boundary rationale [skip ci] * [comment audit] Condense web reconnect and credential lifecycle rationale [skip ci] * [comment audit] Condense cloud rollout and assignment safety rationale [skip ci] * [comment audit] Condense relay session and database recovery rationale [skip ci] * [comment audit] Condense relay placement and protocol compatibility rationale [skip ci] * [comment audit] Condense build and packaging constraints [skip ci] * [comment audit] Condense CI gates and validation isolation rationale [skip ci] * [comment audit] Condense catalog identity and browser validation rationale [skip ci] * [comment audit] Condense mobile browser and frame-budget rationale [skip ci] * [comment audit] Shorten mobile route and browser test explanations [skip ci] * [comment audit] Condense editor and session seam test rationale [skip ci] * [comment audit] Trim session and terminal closure history [skip ci] * [comment audit] Shorten terminal browser and census explanations [skip ci] * [comment audit] Preserve root-only E2E diagnostic baseline * [comment audit] Condense mobile seam and HTML preview test rationale [skip ci] * [comment audit] Condense preview instrumentation and render harness rationale [skip ci] * [comment audit] Condense bundle contracts and native-build constraints [skip ci] * [comment audit] Shorten native packaging and CI routing rationale [skip ci] * [comment audit] Condense release tooling and benchmark constraints [skip ci] * [comment audit] Condense packaging and platform gate rationale [skip ci] * [comment audit] Shorten mobile route and history rationale [skip ci] * [comment audit] Condense mobile browser and component rationale [skip ci] * [comment audit] Shorten drawer and workspace-form rationale [skip ci] * [comment audit] Trim mobile review and editor-document explanations [skip ci] * [comment audit] Condense editor lifecycle and Markdown explanations [skip ci] * [comment audit] Trim mobile file, diagnostics and dictation commentary [skip ci] * [comment audit] Simplify mobile host-list and workspace-view explanations [skip ci] * [comment audit] Clarify mobile shell lifetime and bridge delivery constraints [skip ci] * [comment audit] Condense bridge stream, native request and audio rationale [skip ci] * [comment audit] Reduce bridge schema and page-client commentary [skip ci] * [comment audit] Tighten mobile page bridge contracts [skip ci] * [comment audit] Clarify mobile cache and session constraints [skip ci] * [comment audit] Condense mobile route and lifecycle rationale [skip ci] * [comment audit] Tighten mobile shell hook timing rationale [skip ci] * [comment audit] Clarify route handoff and notification compatibility [skip ci] * [comment audit] Clarify push registration and dictation cleanup constraints [skip ci] * [comment audit] Condense keyboard geometry and native media ownership rationale [skip ci] * [comment audit] Tighten mobile chat scroll and composer concurrency rationale [skip ci] * [comment audit] Condense mobile reply compatibility and upload ownership rationale [skip ci] * [comment audit] Condense optimistic echo and scroll ownership rationale [skip ci] * [comment audit] Tighten stream replay and queued session ownership rationale [skip ci] * [comment audit] Condense mobile composer and reply-schema constraints [skip ci] * [comment audit] Clarify mobile transcript recovery and session ownership [skip ci] * [comment audit] Clarify mobile queue and source-control compatibility [skip ci] * [comment audit] Condense storage and task launch constraints [skip ci] * [comment audit] Clarify task schemas and terminal document ownership [skip ci] * [comment audit] Tighten terminal input and viewport rationale [skip ci] * [comment audit] Shorten terminal and RPC recorder contracts [skip ci] * [comment audit] Condense recorder engine and connection contracts [skip ci] * [comment audit] Shorten host credential and relay recovery comments [skip ci] * [comment audit] Tighten pairing recovery and bundle transport rationale [skip ci] * [comment audit] Clarify RPC delivery and workspace catalog boundaries [skip ci] * [comment audit] Condense catalog and relay entry contracts [skip ci] * [comment audit] Shorten shutdown and SSH relay delivery contracts [skip ci] * [comment audit] Condense WSL relay and E2E regression rationale [skip ci] * [comment audit] Shorten cross-version harness and renderer fixture explanations [skip ci] * [comment audit] Condense paired-host and E2E lifecycle rationale [skip ci] * [comment audit] Shorten layout oracle and regression explanations [skip ci] * [comment audit] Condense paired recovery and ownership regression contracts [skip ci] * [comment audit] Shorten restart, sidebar and SSH lifecycle contracts [skip ci] * [comment audit] Condense terminal rendering and IME regression rationale [skip ci] * [comment audit] Shorten terminal recovery and benchmark contracts [skip ci] * [comment audit] Condense tooling and Windows lifecycle proof rationale [skip ci] * [comment audit] Condense workflow routing and release rationale [skip ci] * [comment audit] Condense mobile security and installer contracts [skip ci] * [comment audit] Shorten native rationale and stylesheet workarounds [skip ci] * [comment audit] Shorten Windows visibility probe rationale [skip ci] * [comment audit] Condense embedded release and signing rationale [skip ci] * [comment audit] Retain current main test behavior in final reconciliation [skip ci] * [comment audit] Complete final comment review across current source inventory * [comment audit] Handle consolidated audit reports before final CI * [comment audit] Preserve credential storage census detail [skip ci] * [comment audit] Scale broad changed E2E selections with verified timing shards * [comment audit] Align E2E assertions with browser close and settled session metadata * [comment audit] Match existing E2Es to current resource and windowing contracts * [comment audit] Observe the shared server outage notice in reconnect coverage * [comment audit] Make existing renderer probes measure settled tab and PTY work * [comment audit] Align palette E2E selector with task search * [comment audit] Refresh remaining palette search selectors * [comment audit] Keep selector correction within selected audit specs * [comment audit] Await emoji fixture settings inside renderer evaluation * [comment audit] Cancel fixture fit retries between terminal tests --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
209 lines
7.3 KiB
JavaScript
209 lines
7.3 KiB
JavaScript
#!/usr/bin/env node
|
|
// Trim macOS Icon Composer inset when generating Windows ICO; untrimmed glyph fills only ~83% and looks undersized (#5357).
|
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
import { dirname, join } from 'node:path'
|
|
import { PNG } from 'pngjs'
|
|
|
|
// Target ~96% largest-frame fill because Windows downscales it; retain margin for antialiasing/shadow.
|
|
export const ICON_CANVAS_MARGIN_RATIO = 0.02
|
|
// Ignore low-alpha safe-area shadow when finding glyph bounds.
|
|
const ALPHA_BACKGROUND_THRESHOLD = 16
|
|
// Standard Windows ICO sizes, largest first (matches the prior ImageMagick set).
|
|
export const ICO_FRAME_SIZES = [256, 128, 64, 48, 32, 16]
|
|
|
|
export function decodePng(buffer) {
|
|
const png = PNG.sync.read(buffer)
|
|
return { width: png.width, height: png.height, data: png.data }
|
|
}
|
|
|
|
export function encodePng({ width, height, data }) {
|
|
const png = new PNG({ width, height })
|
|
data.copy(png.data)
|
|
return PNG.sync.write(png)
|
|
}
|
|
|
|
// Return tight alpha-threshold bounds or null for fully transparent image.
|
|
export function findOpaqueBounds({ width, height, data }, threshold = ALPHA_BACKGROUND_THRESHOLD) {
|
|
let minX = width
|
|
let minY = height
|
|
let maxX = -1
|
|
let maxY = -1
|
|
for (let y = 0; y < height; y++) {
|
|
for (let x = 0; x < width; x++) {
|
|
const alpha = data[(y * width + x) * 4 + 3]
|
|
if (alpha > threshold) {
|
|
if (x < minX) {
|
|
minX = x
|
|
}
|
|
if (x > maxX) {
|
|
maxX = x
|
|
}
|
|
if (y < minY) {
|
|
minY = y
|
|
}
|
|
if (y > maxY) {
|
|
maxY = y
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (maxX < 0) {
|
|
return null
|
|
}
|
|
return { minX, minY, maxX, maxY, width: maxX - minX + 1, height: maxY - minY + 1 }
|
|
}
|
|
|
|
export function cropImage({ width, data }, bounds) {
|
|
const cropWidth = bounds.width
|
|
const cropHeight = bounds.height
|
|
const out = Buffer.alloc(cropWidth * cropHeight * 4)
|
|
for (let y = 0; y < cropHeight; y++) {
|
|
const srcRow = (bounds.minY + y) * width + bounds.minX
|
|
const srcStart = srcRow * 4
|
|
out.set(data.subarray(srcStart, srcStart + cropWidth * 4), y * cropWidth * 4)
|
|
}
|
|
return { width: cropWidth, height: cropHeight, data: out }
|
|
}
|
|
|
|
// Pad trimmed glyph uniformly into square without clipping shadow or distorting aspect ratio.
|
|
export function squareWithMargin(image, marginRatio = ICON_CANVAS_MARGIN_RATIO) {
|
|
const longSide = Math.max(image.width, image.height)
|
|
const side = Math.round(longSide / (1 - 2 * marginRatio))
|
|
const data = Buffer.alloc(side * side * 4)
|
|
const offsetX = Math.floor((side - image.width) / 2)
|
|
const offsetY = Math.floor((side - image.height) / 2)
|
|
for (let y = 0; y < image.height; y++) {
|
|
const srcStart = y * image.width * 4
|
|
const dstStart = ((offsetY + y) * side + offsetX) * 4
|
|
data.set(image.data.subarray(srcStart, srcStart + image.width * 4), dstStart)
|
|
}
|
|
return { width: side, height: side, data }
|
|
}
|
|
|
|
// Premultiply alpha during box-filter downscale to avoid dark fringes at transparent edges.
|
|
export function resizeImage(image, targetWidth, targetHeight) {
|
|
const { width: srcW, height: srcH, data: src } = image
|
|
const out = Buffer.alloc(targetWidth * targetHeight * 4)
|
|
const scaleX = srcW / targetWidth
|
|
const scaleY = srcH / targetHeight
|
|
for (let ty = 0; ty < targetHeight; ty++) {
|
|
const sy0 = ty * scaleY
|
|
const sy1 = (ty + 1) * scaleY
|
|
const y0 = Math.floor(sy0)
|
|
const y1 = Math.min(srcH, Math.ceil(sy1))
|
|
for (let tx = 0; tx < targetWidth; tx++) {
|
|
const sx0 = tx * scaleX
|
|
const sx1 = (tx + 1) * scaleX
|
|
const x0 = Math.floor(sx0)
|
|
const x1 = Math.min(srcW, Math.ceil(sx1))
|
|
let rSum = 0
|
|
let gSum = 0
|
|
let bSum = 0
|
|
let aSum = 0
|
|
let weightSum = 0
|
|
for (let sy = y0; sy < y1; sy++) {
|
|
const wy = Math.min(sy1, sy + 1) - Math.max(sy0, sy)
|
|
for (let sx = x0; sx < x1; sx++) {
|
|
const wx = Math.min(sx1, sx + 1) - Math.max(sx0, sx)
|
|
const weight = wx * wy
|
|
if (weight <= 0) {
|
|
continue
|
|
}
|
|
const idx = (sy * srcW + sx) * 4
|
|
const alpha = src[idx + 3]
|
|
const premul = (alpha / 255) * weight
|
|
rSum += src[idx] * premul
|
|
gSum += src[idx + 1] * premul
|
|
bSum += src[idx + 2] * premul
|
|
aSum += alpha * weight
|
|
weightSum += weight
|
|
}
|
|
}
|
|
const dst = (ty * targetWidth + tx) * 4
|
|
if (weightSum === 0 || aSum === 0) {
|
|
out[dst] = 0
|
|
out[dst + 1] = 0
|
|
out[dst + 2] = 0
|
|
out[dst + 3] = 0
|
|
continue
|
|
}
|
|
const alphaAvg = aSum / weightSum
|
|
const colorDivisor = alphaAvg / 255
|
|
out[dst] = Math.round(rSum / weightSum / colorDivisor)
|
|
out[dst + 1] = Math.round(gSum / weightSum / colorDivisor)
|
|
out[dst + 2] = Math.round(bSum / weightSum / colorDivisor)
|
|
out[dst + 3] = Math.round(alphaAvg)
|
|
}
|
|
}
|
|
return { width: targetWidth, height: targetHeight, data: out }
|
|
}
|
|
|
|
// Use PNG-compressed ICO frames, supported since Vista and matching previous ImageMagick output.
|
|
export function encodeIco(frames) {
|
|
const header = Buffer.alloc(6)
|
|
header.writeUInt16LE(0, 0) // reserved
|
|
header.writeUInt16LE(1, 2) // type 1 = icon
|
|
header.writeUInt16LE(frames.length, 4)
|
|
|
|
const directory = Buffer.alloc(frames.length * 16)
|
|
let dataOffset = 6 + frames.length * 16
|
|
const payloads = []
|
|
frames.forEach((frame, index) => {
|
|
const png = encodePng(frame)
|
|
payloads.push(png)
|
|
const entry = index * 16
|
|
// Width/height of 256 are stored as 0 per the ICO spec.
|
|
directory.writeUInt8(frame.width >= 256 ? 0 : frame.width, entry)
|
|
directory.writeUInt8(frame.height >= 256 ? 0 : frame.height, entry + 1)
|
|
directory.writeUInt8(0, entry + 2) // color count (0 = truecolor)
|
|
directory.writeUInt8(0, entry + 3) // reserved
|
|
directory.writeUInt16LE(1, entry + 4) // color planes
|
|
directory.writeUInt16LE(32, entry + 6) // bits per pixel
|
|
directory.writeUInt32LE(png.length, entry + 8)
|
|
directory.writeUInt32LE(dataOffset, entry + 12)
|
|
dataOffset += png.length
|
|
})
|
|
|
|
return Buffer.concat([header, directory, ...payloads])
|
|
}
|
|
|
|
// Trim safe-area inset from source and return filled multi-size ICO; export permits pixel-level regression test.
|
|
export function buildWindowsIcoFromPng(sourcePngBuffer, sizes = ICO_FRAME_SIZES) {
|
|
const source = decodePng(sourcePngBuffer)
|
|
const bounds = findOpaqueBounds(source)
|
|
if (!bounds) {
|
|
throw new Error('Source icon is fully transparent; cannot trim safe-area inset.')
|
|
}
|
|
const trimmed = cropImage(source, bounds)
|
|
const filled = squareWithMargin(trimmed)
|
|
const frames = sizes.map((size) => resizeImage(filled, size, size))
|
|
return encodeIco(frames)
|
|
}
|
|
|
|
function resolveDefaultPaths() {
|
|
const scriptDir = import.meta.dirname
|
|
const projectDir = dirname(dirname(scriptDir))
|
|
return {
|
|
sourcePng: join(projectDir, 'resources', 'build', 'icon.png'),
|
|
outputIco: join(projectDir, 'resources', 'build', 'icon.ico')
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const { sourcePng, outputIco } = resolveDefaultPaths()
|
|
if (!existsSync(sourcePng)) {
|
|
console.error(`Error: source PNG not found at ${sourcePng}`)
|
|
process.exit(1)
|
|
}
|
|
const ico = buildWindowsIcoFromPng(readFileSync(sourcePng))
|
|
writeFileSync(outputIco, ico)
|
|
console.log(` -> ${outputIco} (filled multi-size ICO, safe-area inset trimmed)`)
|
|
}
|
|
|
|
if (
|
|
import.meta.url === `file://${process.argv[1]}` ||
|
|
process.argv[1]?.endsWith('trim-windows-icon-source.mjs')
|
|
) {
|
|
main()
|
|
}
|