From 661de072ed6693f6c3f13b6c90905f44789195dc Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:05:10 +0800 Subject: [PATCH] chore: adopt oxfmt for root packages Model: gpt-5 --- .github/labeler.yml | 3 +- .oxfmtrc.json | 46 ++++ .prettierignore | 14 -- .prettierrc | 12 - AGENTS.md | 12 +- apps/cli/package.json | 5 +- apps/cli/src/commands/app.test.ts | 28 +-- .../lib/__tests__/concurrent-queue.test.ts | 31 +-- apps/cli/src/lib/acp/tool-call-history.ts | 6 +- .../code-collab-publish-repair.test.ts | 24 +- .../lib/code-collab/file-index-scan-core.ts | 2 +- .../code-collab/workspace-watch-protocol.ts | 9 +- .../src/lib/git/resolve-git-branch-name.ts | 7 +- apps/cli/src/lib/local-workspace-catalog.ts | 12 +- apps/cli/src/lib/loro/history-auto-read.ts | 2 +- .../pr-poller/github-credential-resolver.ts | 10 +- .../src/lib/pr-poller/pr-poll-select.test.ts | 7 +- apps/cli/src/lib/pr-poller/pr-poll-select.ts | 5 +- .../lib/pr-poller/pr-poll-writeback.test.ts | 26 +- .../src/lib/pr-poller/pr-poll-writeback.ts | 2 +- .../cli/src/lib/pr-poller/pr-poller-config.ts | 6 +- apps/cli/src/lib/pr-poller/pr-poller-state.ts | 7 +- .../src/lib/pr-poller/pr-poller-workspace.ts | 4 +- .../review-automation-engine.ts | 19 +- .../review-automation-github.ts | 50 ++-- .../review-automation-plan.test.ts | 4 +- .../review-automation-plan.ts | 3 +- .../review-automation-scheduler.ts | 5 +- .../src/lib/session-export/export-service.ts | 9 +- apps/cli/src/lib/session-export/formatters.ts | 4 +- .../lib/session-export/image-downloader.ts | 9 +- .../src/lib/session-export/output-dir.test.ts | 4 +- .../lib/session-export/task-export.test.ts | 6 +- apps/cli/src/lib/session-export/types.ts | 7 +- .../session-export/workspace-usage.test.ts | 3 +- .../task-automation-plan.test.ts | 39 ++- .../task-automation/task-automation-start.ts | 4 +- apps/cli/src/lib/usage/price.ts | 162 ++++++------- apps/cli/src/mcp/lody-mcp-server.ts | 2 +- .../worktree/worktree-config-resolver.ts | 17 +- .../worktree/worktree-setup-config-store.ts | 9 +- apps/electron/.prettierignore | 6 - apps/electron/.prettierrc.yaml | 4 - apps/electron/.vscode/extensions.json | 2 +- apps/electron/.vscode/settings.json | 6 +- apps/electron/README.md | 2 +- apps/electron/electron-builder.yml | 3 +- apps/electron/package.json | 3 +- .../app-updater-sparkle-policy.test.mjs | 15 +- .../electron/src/main/services/cli-service.ts | 10 +- package.json | 6 +- packages/cloud-api/package.json | 4 +- pnpm-lock.yaml | 223 +++++++++++++++++- 53 files changed, 576 insertions(+), 344 deletions(-) create mode 100644 .oxfmtrc.json delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 apps/electron/.prettierignore delete mode 100644 apps/electron/.prettierrc.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index 5e50e774d..375cef673 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -63,8 +63,7 @@ - '.gitignore' - '.gitmodules' - '.oxlintrc.json' - - '.prettierignore' - - '.prettierrc' + - '.oxfmtrc.json' - 'scripts/**' - 'packages/configs/**' - 'patches/**' diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 000000000..d9204f1be --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,46 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "semi": true, + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 100, + "sortPackageJson": false, + "ignorePatterns": [ + "node_modules/", + "dist/", + "build/", + ".next/", + ".nuxt/", + ".vscode/", + ".idea/", + "*.log", + "*.tgz", + "*.tar.gz", + "package-lock.json", + "yarn.lock", + ".DS_Store", + "coverage/", + "packages/acp-extension-claude/", + "packages/acp-extension-codex/", + "packages/acp-extension-core/", + "packages/acp-extension-dsh/", + "packages/acp-extension-grok/", + "packages/acp-extension-kimi/", + "apps/electron/out/", + "apps/electron/dist/", + "apps/electron/.vscode/", + "apps/electron/pnpm-lock.yaml", + "apps/electron/LICENSE.md", + "apps/electron/tsconfig.json", + "apps/electron/tsconfig.*.json" + ], + "overrides": [ + { + "files": ["apps/electron/**"], + "options": { + "semi": false, + "trailingComma": "none" + } + } + ] +} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index d5abeb982..000000000 --- a/.prettierignore +++ /dev/null @@ -1,14 +0,0 @@ -node_modules/ -dist/ -build/ -.next/ -.nuxt/ -.vscode/ -.idea/ -*.log -*.tgz -*.tar.gz -package-lock.json -yarn.lock -.DS_Store -coverage/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 95f104d86..000000000 --- a/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "semi": true, - "trailingComma": "es5", - "singleQuote": true, - "printWidth": 100, - "tabWidth": 2, - "useTabs": false, - "endOfLine": "lf", - "bracketSpacing": true, - "bracketSameLine": false, - "quoteProps": "as-needed" -} diff --git a/AGENTS.md b/AGENTS.md index 57c6b4fbe..c08b03197 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -98,12 +98,12 @@ Use Node.js 22+ and the pnpm version pinned in `package.json`. Install with `pnpm install`. A parent pnpm workspace owns nested checkouts; the public preinstall guard rejects a second install. Use a separate clone for standalone public development. `pnpm start:local` is the canonical desktop command; root -`pnpm build` is the same local composition. Before committing, normally run -`pnpm check` and `pnpm format`. If asked to skip tests, report the narrower -type/build/static validation instead. Conventional Commits (`feat:`, `fix:`, -`docs:`, `chore:`, `test:`); AI commits end with `Model: `. -CI uses `pnpm install --frozen-lockfile`, so manifest changes update -`pnpm-lock.yaml`. +`pnpm build` is the same local composition. Before committing, run +`pnpm check` and `pnpm format`. Root packages share `.oxfmtrc.json`; ACP +submodules stay independently formatted. If tests are explicitly skipped, +report narrower validation. Use Conventional Commits; AI commits end with +`Model: `. CI uses `pnpm install --frozen-lockfile`, so +manifests update `pnpm-lock.yaml`. ## Test quality diff --git a/apps/cli/package.json b/apps/cli/package.json index 2a9aefdb6..d92a44c72 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -19,8 +19,8 @@ "copy:dsh-presets": "node scripts/copy-deepseek-presets.js", "copy:wasm": "node scripts/copy-loro-wasm.js", "clean": "rimraf dist dist-dev", - "format": "prettier --write src/**/*.ts", - "format:check": "prettier --check src/**/*.ts", + "format": "oxfmt 'src/**/*.ts'", + "format:check": "oxfmt --check 'src/**/*.ts'", "typecheck": "tsgo --noEmit", "test": "vitest run", "bench:acp-history": "vitest bench tests/acp-history.bench.ts", @@ -92,7 +92,6 @@ "loro-repo": "catalog:", "ora": "^8.2.0", "posthog-node": "^5.38.8", - "prettier": "^3.6.2", "proxy-from-env": "^1.1.0", "rimraf": "^6.1.2", "tar": "^7.5.7", diff --git a/apps/cli/src/commands/app.test.ts b/apps/cli/src/commands/app.test.ts index 5401d466d..9e52be7c7 100644 --- a/apps/cli/src/commands/app.test.ts +++ b/apps/cli/src/commands/app.test.ts @@ -142,14 +142,12 @@ describe('resolveLocalProjectForApp', () => { }); it('still resolves the deterministic project id when the daemon is down', async () => { - const send = vi.fn( - async (): Promise => ({ - ok: false, - type: 'local-project/add', - error: 'daemon_unavailable', - message: 'Local CLI daemon is not running.', - }) - ); + const send = vi.fn(async (): Promise => ({ + ok: false, + type: 'local-project/add', + error: 'daemon_unavailable', + message: 'Local CLI daemon is not running.', + })); const target = await resolveLocalProjectForApp({ machineId: MACHINE_ID, @@ -166,14 +164,12 @@ describe('resolveLocalProjectForApp', () => { }); it('propagates other control failures', async () => { - const send = vi.fn( - async (): Promise => ({ - ok: false, - type: 'local-project/add', - error: 'path_invalid', - message: 'Selected path is not a directory', - }) - ); + const send = vi.fn(async (): Promise => ({ + ok: false, + type: 'local-project/add', + error: 'path_invalid', + message: 'Selected path is not a directory', + })); await expect( resolveLocalProjectForApp({ diff --git a/apps/cli/src/lib/__tests__/concurrent-queue.test.ts b/apps/cli/src/lib/__tests__/concurrent-queue.test.ts index aa03f419b..2532973d7 100644 --- a/apps/cli/src/lib/__tests__/concurrent-queue.test.ts +++ b/apps/cli/src/lib/__tests__/concurrent-queue.test.ts @@ -314,16 +314,18 @@ describe('ConcurrentQueue', () => { const queue = new ConcurrentQueue(2); const log: string[] = []; - const task = (name: string, delay: number, shouldFail = false) => async () => { - log.push(`${name}:start`); - await new Promise((r) => setTimeout(r, delay)); - if (shouldFail) { - log.push(`${name}:error`); - throw new Error(`${name} failed`); - } - log.push(`${name}:end`); - return name; - }; + const task = + (name: string, delay: number, shouldFail = false) => + async () => { + log.push(`${name}:start`); + await new Promise((r) => setTimeout(r, delay)); + if (shouldFail) { + log.push(`${name}:error`); + throw new Error(`${name} failed`); + } + log.push(`${name}:end`); + return name; + }; const results = await Promise.allSettled([ queue.enqueue('A', task('A1', 30)), @@ -335,14 +337,7 @@ describe('ConcurrentQueue', () => { // A 系列应该串行 const aLogs = log.filter((l) => l.startsWith('A')); - expect(aLogs).toEqual([ - 'A1:start', - 'A1:end', - 'A2:start', - 'A2:error', - 'A3:start', - 'A3:end', - ]); + expect(aLogs).toEqual(['A1:start', 'A1:end', 'A2:start', 'A2:error', 'A3:start', 'A3:end']); // B 系列应该串行 const bLogs = log.filter((l) => l.startsWith('B')); diff --git a/apps/cli/src/lib/acp/tool-call-history.ts b/apps/cli/src/lib/acp/tool-call-history.ts index e1d77d827..7d60d94f3 100644 --- a/apps/cli/src/lib/acp/tool-call-history.ts +++ b/apps/cli/src/lib/acp/tool-call-history.ts @@ -1 +1,5 @@ -export { deriveLocationsFromRawInput, deriveLocationsFromToolCallContent, stripToolCallContentForHistory } from '@lody/shared'; +export { + deriveLocationsFromRawInput, + deriveLocationsFromToolCallContent, + stripToolCallContentForHistory, +} from '@lody/shared'; diff --git a/apps/cli/src/lib/code-collab/code-collab-publish-repair.test.ts b/apps/cli/src/lib/code-collab/code-collab-publish-repair.test.ts index 29db79830..9e21147dd 100644 --- a/apps/cli/src/lib/code-collab/code-collab-publish-repair.test.ts +++ b/apps/cli/src/lib/code-collab/code-collab-publish-repair.test.ts @@ -65,17 +65,15 @@ describe('CodeCollabV2Service targeted file-index repair', () => { vi.useRealTimers(); }); - const createService = ( - options: { - readonly publishFileIndex: ( - publication: CodeCollabV2FileIndexPublication - ) => Promise<{ changed: boolean }>; - readonly publishFileIndexSignal?: (publication: { - readonly ownerSessionId: SessionId; - readonly updatedAtMs: number; - }) => Promise; - } - ): CodeCollabV2Service => { + const createService = (options: { + readonly publishFileIndex: ( + publication: CodeCollabV2FileIndexPublication + ) => Promise<{ changed: boolean }>; + readonly publishFileIndexSignal?: (publication: { + readonly ownerSessionId: SessionId; + readonly updatedAtMs: number; + }) => Promise; + }): CodeCollabV2Service => { const service = new CodeCollabV2Service({ resolveWorkspace: async () => ({ ok: false, @@ -219,9 +217,7 @@ describe('CodeCollabV2Service targeted file-index repair', () => { publishFileIndex.mockRejectedValueOnce(new Error('transport failed again')); state.fileTree['newer.ts'] = true; - await expect(publishOwner(service, OWNER_A, state)).rejects.toThrow( - 'transport failed again' - ); + await expect(publishOwner(service, OWNER_A, state)).rejects.toThrow('transport failed again'); service.dispose(); await vi.advanceTimersByTimeAsync(30_000); expect(publishFileIndex).toHaveBeenCalledTimes(3); diff --git a/apps/cli/src/lib/code-collab/file-index-scan-core.ts b/apps/cli/src/lib/code-collab/file-index-scan-core.ts index fd06062b0..c394036c3 100644 --- a/apps/cli/src/lib/code-collab/file-index-scan-core.ts +++ b/apps/cli/src/lib/code-collab/file-index-scan-core.ts @@ -225,7 +225,7 @@ async function lineStatsForUntrackedFile( function parseDeletedPathsFromNameStatus(stdout: string): Set { const deleted = new Set(); const tokens = stdout.split('\0').filter(Boolean); - for (let index = 0; index < tokens.length; ) { + for (let index = 0; index < tokens.length;) { const status = tokens[index] ?? ''; index += 1; if (status.startsWith('R') || status.startsWith('C')) { diff --git a/apps/cli/src/lib/code-collab/workspace-watch-protocol.ts b/apps/cli/src/lib/code-collab/workspace-watch-protocol.ts index c314c65ff..7a7eeac47 100644 --- a/apps/cli/src/lib/code-collab/workspace-watch-protocol.ts +++ b/apps/cli/src/lib/code-collab/workspace-watch-protocol.ts @@ -69,14 +69,9 @@ export function parseWorkspaceWatchParentMessage( return null; } -export function parseWorkspaceWatchChildMessage( - value: unknown -): WorkspaceWatchChildMessage | null { +export function parseWorkspaceWatchChildMessage(value: unknown): WorkspaceWatchChildMessage | null { if (!isGenerationMessage(value)) return null; - if ( - value.type === 'code-collab-watch/dirty' && - typeof value.root === 'string' - ) { + if (value.type === 'code-collab-watch/dirty' && typeof value.root === 'string') { return { type: value.type, generation: value.generation, root: value.root }; } if ( diff --git a/apps/cli/src/lib/git/resolve-git-branch-name.ts b/apps/cli/src/lib/git/resolve-git-branch-name.ts index 3bc0111b3..803339eeb 100644 --- a/apps/cli/src/lib/git/resolve-git-branch-name.ts +++ b/apps/cli/src/lib/git/resolve-git-branch-name.ts @@ -46,7 +46,12 @@ export const resolveGitBranch = async ( return { kind: 'branch', branch: current }; } - const abbrevRef = await tryExecTrimmed(exec, 'git', ['rev-parse', '--abbrev-ref', 'HEAD'], workdir); + const abbrevRef = await tryExecTrimmed( + exec, + 'git', + ['rev-parse', '--abbrev-ref', 'HEAD'], + workdir + ); if (!abbrevRef) { return { kind: 'unresolved' }; } diff --git a/apps/cli/src/lib/local-workspace-catalog.ts b/apps/cli/src/lib/local-workspace-catalog.ts index 620207bfb..61aa716d4 100644 --- a/apps/cli/src/lib/local-workspace-catalog.ts +++ b/apps/cli/src/lib/local-workspace-catalog.ts @@ -333,13 +333,11 @@ export function makeLocalWorkspaceCatalog( }); const remoteMissing = snapshot.workspaces .filter((workspace) => !remoteIds.has(workspace.workspaceId)) - .map( - (workspace): LocalCatalogWorkspace => ({ - ...workspace, - state: 'remote_missing', - remoteMissingAt: workspace.remoteMissingAt ?? now, - }) - ); + .map((workspace): LocalCatalogWorkspace => ({ + ...workspace, + state: 'remote_missing', + remoteMissingAt: workspace.remoteMissingAt ?? now, + })); return { ...snapshot, identity: input.identity, diff --git a/apps/cli/src/lib/loro/history-auto-read.ts b/apps/cli/src/lib/loro/history-auto-read.ts index db23892e7..6e48afac8 100644 --- a/apps/cli/src/lib/loro/history-auto-read.ts +++ b/apps/cli/src/lib/loro/history-auto-read.ts @@ -47,7 +47,7 @@ export const attachAutoMarkLatestUserHistoryAsRead = ( return; } - const history = next.history as SessionHistoryInput[] ?? []; + const history = (next.history as SessionHistoryInput[]) ?? []; const latestUserEntry = findLatestUserHistoryEntry(history); if (!latestUserEntry || resolveSessionHistoryStatus(latestUserEntry) !== 'pending') { return; diff --git a/apps/cli/src/lib/pr-poller/github-credential-resolver.ts b/apps/cli/src/lib/pr-poller/github-credential-resolver.ts index fa1f4a2f2..8dbaddd92 100644 --- a/apps/cli/src/lib/pr-poller/github-credential-resolver.ts +++ b/apps/cli/src/lib/pr-poller/github-credential-resolver.ts @@ -1,8 +1,5 @@ import { execFile } from 'node:child_process'; -import type { - CloudGithubTokenManager, - CloudGithubWriteTokenContext, -} from '@lody/platform'; +import type { CloudGithubTokenManager, CloudGithubWriteTokenContext } from '@lody/platform'; import type { Logger } from '@/utils/logger'; import { formatErrorMessage } from '@/utils/format-error'; @@ -67,10 +64,7 @@ const defaultFetchGhUserId = (): Promise => export type GitHubCredentialResolverDeps = { /** Workspace-bound token manager; null disables the managed tier entirely. */ - tokenManager: Pick< - CloudGithubTokenManager, - 'getWriteTokenInfoForRepo' | 'invalidate' - > | null; + tokenManager: Pick | null; /** Requester context for managed write tokens (per-workspace wiring, see M3). */ writeTokenContext: CloudGithubWriteTokenContext; /** Workspace identity used only for the old-backend App-token fallback scope. */ diff --git a/apps/cli/src/lib/pr-poller/pr-poll-select.test.ts b/apps/cli/src/lib/pr-poller/pr-poll-select.test.ts index 437ff951f..04e106e46 100644 --- a/apps/cli/src/lib/pr-poller/pr-poll-select.test.ts +++ b/apps/cli/src/lib/pr-poller/pr-poll-select.test.ts @@ -48,7 +48,12 @@ describe('computeTargetDueAtMs', () => { it('a priority change reshapes dueness with no stored next-poll time', () => { const low = target({ lastSuccessAtMs: T0, desiredIntervalMs: 300_000 }); - const promoted = { ...low, lane: 'high' as const, desiredIntervalMs: 20_000, minIntervalMs: 20_000 }; + const promoted = { + ...low, + lane: 'high' as const, + desiredIntervalMs: 20_000, + minIntervalMs: 20_000, + }; expect(computeTargetDueAtMs(low)).toBe(T0 + 300_000); expect(computeTargetDueAtMs(promoted)).toBe(T0 + 20_000); }); diff --git a/apps/cli/src/lib/pr-poller/pr-poll-select.ts b/apps/cli/src/lib/pr-poller/pr-poll-select.ts index 0856793e5..a4d0b6fa3 100644 --- a/apps/cli/src/lib/pr-poller/pr-poll-select.ts +++ b/apps/cli/src/lib/pr-poller/pr-poll-select.ts @@ -120,7 +120,10 @@ export function pickNextBatch( (a.workspaceId + a.repoFullName < b.workspaceId + b.repoFullName ? -1 : 1); const highs = batches.filter((batch) => batch.lane === 'high').sort(byOldest); const lows = batches.filter((batch) => batch.lane === 'low').sort(byOldest); - if (lows.length > 0 && (highs.length === 0 || consecutiveHighDispatches >= lowEveryNBatches - 1)) { + if ( + lows.length > 0 && + (highs.length === 0 || consecutiveHighDispatches >= lowEveryNBatches - 1) + ) { return lows[0] ?? null; } return highs[0] ?? lows[0] ?? null; diff --git a/apps/cli/src/lib/pr-poller/pr-poll-writeback.test.ts b/apps/cli/src/lib/pr-poller/pr-poll-writeback.test.ts index 54701a4a2..ebd876b90 100644 --- a/apps/cli/src/lib/pr-poller/pr-poll-writeback.test.ts +++ b/apps/cli/src/lib/pr-poller/pr-poll-writeback.test.ts @@ -57,9 +57,9 @@ describe('selectCurrentPullRequestUrl', () => { [URL_1, obs(1, { headRefName: 'feat/x', updatedAt: '2026-07-17T09:00:00Z' })], [URL_2, obs(2, { headRefName: 'other', updatedAt: '2026-07-17T11:00:00Z' })], ]); - expect( - selectCurrentPullRequestUrl({ associated, observations, runtimeBranch: 'feat/x' }) - ).toBe(URL_1); + expect(selectCurrentPullRequestUrl({ associated, observations, runtimeBranch: 'feat/x' })).toBe( + URL_1 + ); // Without a runtime branch the branch rule is ignored → newer wins. expect(selectCurrentPullRequestUrl({ associated, observations, runtimeBranch: null })).toBe( URL_2 @@ -69,9 +69,9 @@ describe('selectCurrentPullRequestUrl', () => { it('prefers open/draft over terminal, even an unobserved open association', () => { // Same branch rank (observation on another branch) → openness decides. const observations = new Map([[URL_2, obs(2, { status: 'merged', headRefName: 'other' })]]); - expect( - selectCurrentPullRequestUrl({ associated, observations, runtimeBranch: 'feat/x' }) - ).toBe(URL_1); + expect(selectCurrentPullRequestUrl({ associated, observations, runtimeBranch: 'feat/x' })).toBe( + URL_1 + ); }); it('a terminal PR on the runtime branch outranks an open association from another context', () => { @@ -175,7 +175,12 @@ describe('planAssociation', () => { }) ).toEqual({ url: 'https://github.com/owner/repo/pull/5', prNumber: 5, status: 'open' }); expect( - planAssociation({ meta: makeMeta(), observations: [], discovered: [], runtimeBranch: 'feat/x' }) + planAssociation({ + meta: makeMeta(), + observations: [], + discovered: [], + runtimeBranch: 'feat/x', + }) ).toBeNull(); }); }); @@ -243,7 +248,12 @@ describe('planPullRequestMetaWrite', () => { it('strips legacy detail fields exactly once (ordering bootstrap)', () => { const meta = makeMeta({ pullRequests: [ - { url: URL_1, status: 'open', number: 1, reportedAt: '2026-01-01' } as SessionPullRequestMeta, + { + url: URL_1, + status: 'open', + number: 1, + reportedAt: '2026-01-01', + } as SessionPullRequestMeta, ], }); diff --git a/apps/cli/src/lib/pr-poller/pr-poll-writeback.ts b/apps/cli/src/lib/pr-poller/pr-poll-writeback.ts index 552235706..8edb01e7d 100644 --- a/apps/cli/src/lib/pr-poller/pr-poll-writeback.ts +++ b/apps/cli/src/lib/pr-poller/pr-poll-writeback.ts @@ -52,7 +52,7 @@ export function selectCurrentPullRequestUrl(args: { const branchMatch = observation && runtimeBranch && observation.headRefName === runtimeBranch ? 1 : 0; const open = isTerminal(status) ? 0 : 1; - const updatedAtMs = observation ? (Date.parse(observation.updatedAt) || 0) : -1; + const updatedAtMs = observation ? Date.parse(observation.updatedAt) || 0 : -1; const prNumber = observation?.number ?? parseGitHubPullRequestUrl(pr.url)?.prNumber ?? -1; const rank: [number, number, number, number, number] = [ branchMatch, diff --git a/apps/cli/src/lib/pr-poller/pr-poller-config.ts b/apps/cli/src/lib/pr-poller/pr-poller-config.ts index 3748de55a..bc94f558c 100644 --- a/apps/cli/src/lib/pr-poller/pr-poller-config.ts +++ b/apps/cli/src/lib/pr-poller/pr-poller-config.ts @@ -103,7 +103,11 @@ export function loadPrPollerConfig(env: NodeJS.ProcessEnv = process.env): PrPoll 'LODY_PR_POLL_ACTIVITY_WINDOW_MS', PR_POLLER_DEFAULTS.activityWindowMs ), - highOwnerCap: readEnvNumber(env, 'LODY_PR_POLL_HIGH_OWNER_CAP', PR_POLLER_DEFAULTS.highOwnerCap), + highOwnerCap: readEnvNumber( + env, + 'LODY_PR_POLL_HIGH_OWNER_CAP', + PR_POLLER_DEFAULTS.highOwnerCap + ), lowLaneEveryNBatches: readEnvNumber( env, 'LODY_PR_POLL_LOW_LANE_EVERY_N', diff --git a/apps/cli/src/lib/pr-poller/pr-poller-state.ts b/apps/cli/src/lib/pr-poller/pr-poller-state.ts index a739c84f1..4bc32e97c 100644 --- a/apps/cli/src/lib/pr-poller/pr-poller-state.ts +++ b/apps/cli/src/lib/pr-poller/pr-poller-state.ts @@ -127,9 +127,10 @@ export class PrPollerStateStore { lastErrorKind: row.last_error_kind, }; } - for (const row of db - .prepare('SELECT key, last_success_at_ms FROM targets') - .all() as Array<{ key: string; last_success_at_ms: number }>) { + for (const row of db.prepare('SELECT key, last_success_at_ms FROM targets').all() as Array<{ + key: string; + last_success_at_ms: number; + }>) { state.targets[row.key] = { lastSuccessAtMs: row.last_success_at_ms }; } for (const row of db diff --git a/apps/cli/src/lib/pr-poller/pr-poller-workspace.ts b/apps/cli/src/lib/pr-poller/pr-poller-workspace.ts index 61a06c62e..14c7db8c6 100644 --- a/apps/cli/src/lib/pr-poller/pr-poller-workspace.ts +++ b/apps/cli/src/lib/pr-poller/pr-poller-workspace.ts @@ -173,9 +173,7 @@ export function createLodyPrPollerWorkspace(options: { }), ]); if (!associated) { - logger.debug( - `[pr-poller] PR association was rejected for ${args.prUrl}` - ); + logger.debug(`[pr-poller] PR association was rejected for ${args.prUrl}`); return false; } return true; diff --git a/apps/cli/src/lib/review-automation/review-automation-engine.ts b/apps/cli/src/lib/review-automation/review-automation-engine.ts index d2ceb7c6e..58be9c1a9 100644 --- a/apps/cli/src/lib/review-automation/review-automation-engine.ts +++ b/apps/cli/src/lib/review-automation/review-automation-engine.ts @@ -20,7 +20,12 @@ import { } from '@lody/shared'; import type { LoroRepo } from 'loro-repo'; import type { Logger } from '@/utils/logger'; -import { advanceReviewRun, readReviewRun, writeReviewPolicy, readReviewPolicy } from './review-automation-store'; +import { + advanceReviewRun, + readReviewRun, + writeReviewPolicy, + readReviewPolicy, +} from './review-automation-store'; import { nextStateForAction, planReviewStep, type ReviewAction } from './review-automation-plan'; /** @@ -518,7 +523,11 @@ export class ReviewAutomationEngine { await advanceReviewRun(this.deps.repo, this.deps.workspaceId, run, { state: nextState, detail: `Asked the author to fix CI (attempt ${run.ciFixUsed + 1}).`, - patch: { ...basePatch, ciFixUsed: run.ciFixUsed + 1, lastEngineTurnId: dispatched.userTurnId }, + patch: { + ...basePatch, + ciFixUsed: run.ciFixUsed + 1, + lastEngineTurnId: dispatched.userTurnId, + }, }); return; } @@ -531,7 +540,11 @@ export class ReviewAutomationEngine { await advanceReviewRun(this.deps.repo, this.deps.workspaceId, run, { state: nextState, detail: `Asked the author to resolve conflicts (attempt ${run.conflictUsed + 1}).`, - patch: { ...basePatch, conflictUsed: run.conflictUsed + 1, lastEngineTurnId: dispatched.userTurnId }, + patch: { + ...basePatch, + conflictUsed: run.conflictUsed + 1, + lastEngineTurnId: dispatched.userTurnId, + }, }); return; } diff --git a/apps/cli/src/lib/review-automation/review-automation-github.ts b/apps/cli/src/lib/review-automation/review-automation-github.ts index 66422514a..7a8a34ef2 100644 --- a/apps/cli/src/lib/review-automation/review-automation-github.ts +++ b/apps/cli/src/lib/review-automation/review-automation-github.ts @@ -31,32 +31,32 @@ export const parseRepoFromPrUrl = (url: string): string | null => { * it never reaches a process listing. A repository with no resolvable * credential fails closed: no token means no merge. */ -export const createGhRunner = ( - resolveToken: (repoFullName: string | null) => Promise -): GhRunner => async (args, repoFullName) => { - const token = await resolveToken(repoFullName); - if (!token) { - return { stdout: 'no GitHub credential available', exitCode: 1 }; - } - return await new Promise((resolve) => { - execFile( - 'gh', - [...args], - { - timeout: GH_TIMEOUT_MS, - env: { ...process.env, GH_TOKEN: token, GH_PROMPT: 'disabled' }, - maxBuffer: 8 * 1024 * 1024, - }, - (error, stdout, stderr) => { - if (error) { - resolve({ stdout: `${stdout}${stderr}`.trim(), exitCode: 1 }); - return; +export const createGhRunner = + (resolveToken: (repoFullName: string | null) => Promise): GhRunner => + async (args, repoFullName) => { + const token = await resolveToken(repoFullName); + if (!token) { + return { stdout: 'no GitHub credential available', exitCode: 1 }; + } + return await new Promise((resolve) => { + execFile( + 'gh', + [...args], + { + timeout: GH_TIMEOUT_MS, + env: { ...process.env, GH_TOKEN: token, GH_PROMPT: 'disabled' }, + maxBuffer: 8 * 1024 * 1024, + }, + (error, stdout, stderr) => { + if (error) { + resolve({ stdout: `${stdout}${stderr}`.trim(), exitCode: 1 }); + return; + } + resolve({ stdout, exitCode: 0 }); } - resolve({ stdout, exitCode: 0 }); - } - ); - }); -}; + ); + }); + }; const PullRequestFactsSchema = z.object({ headRefOid: z.string().optional(), diff --git a/apps/cli/src/lib/review-automation/review-automation-plan.test.ts b/apps/cli/src/lib/review-automation/review-automation-plan.test.ts index 7614c0783..aee6b91a9 100644 --- a/apps/cli/src/lib/review-automation/review-automation-plan.test.ts +++ b/apps/cli/src/lib/review-automation/review-automation-plan.test.ts @@ -373,9 +373,7 @@ describe('planReviewStep', () => { }); it('blocks when the reviewer ends its turn without submitting', () => { - const action = planReviewStep( - facts({ state: 'reviewing', submissionForCurrentRound: false }) - ); + const action = planReviewStep(facts({ state: 'reviewing', submissionForCurrentRound: false })); expect(action).toMatchObject({ kind: 'block' }); }); }); diff --git a/apps/cli/src/lib/review-automation/review-automation-plan.ts b/apps/cli/src/lib/review-automation/review-automation-plan.ts index c5c28ccf3..991d0810f 100644 --- a/apps/cli/src/lib/review-automation/review-automation-plan.ts +++ b/apps/cli/src/lib/review-automation/review-automation-plan.ts @@ -123,8 +123,7 @@ const isTerminalPlanState = (state: ReviewRunState): boolean => const isHumanOnlyBlocker = (blocker: AutoMergeBlocker): boolean => blocker === 'protected_path' || blocker === 'human_review_pending' || blocker === 'disputed'; -const describeBlockers = (blockers: readonly AutoMergeBlocker[]): string => - blockers.join(', '); +const describeBlockers = (blockers: readonly AutoMergeBlocker[]): string => blockers.join(', '); export const planReviewStep = (facts: ReviewPlanFacts): ReviewAction => { // A human taking the wheel outranks every other consideration, including a diff --git a/apps/cli/src/lib/review-automation/review-automation-scheduler.ts b/apps/cli/src/lib/review-automation/review-automation-scheduler.ts index b75965815..d652a945a 100644 --- a/apps/cli/src/lib/review-automation/review-automation-scheduler.ts +++ b/apps/cli/src/lib/review-automation/review-automation-scheduler.ts @@ -94,7 +94,10 @@ export class ReviewAutomationScheduler { // slot indefinitely. Rotating the start point gives each run its turn. const ordered = active.length > limit - ? [...active.slice(this.rotation % active.length), ...active.slice(0, this.rotation % active.length)] + ? [ + ...active.slice(this.rotation % active.length), + ...active.slice(0, this.rotation % active.length), + ] : active; this.rotation = (this.rotation + limit) % Math.max(1, active.length); diff --git a/apps/cli/src/lib/session-export/export-service.ts b/apps/cli/src/lib/session-export/export-service.ts index 353c40976..e45e65122 100644 --- a/apps/cli/src/lib/session-export/export-service.ts +++ b/apps/cli/src/lib/session-export/export-service.ts @@ -245,16 +245,17 @@ export async function exportWorkspaceData( workspaceId: options.workspace.id, cliToken: options.cliToken, }); - await writeJson(path.join(options.outputDir, 'usage', 'workspace-summary.json'), usageBundle.summary); + await writeJson( + path.join(options.outputDir, 'usage', 'workspace-summary.json'), + usageBundle.summary + ); await writeJson( path.join(options.outputDir, 'usage', 'workspace-timeline.json'), usageBundle.timelines ); usageExported = true; } catch (error) { - warnings.push( - `Workspace usage export failed: ${formatErrorMessage(error)}` - ); + warnings.push(`Workspace usage export failed: ${formatErrorMessage(error)}`); } const manifest: ExportManifest = { diff --git a/apps/cli/src/lib/session-export/formatters.ts b/apps/cli/src/lib/session-export/formatters.ts index 42da1b076..ac010ddcf 100644 --- a/apps/cli/src/lib/session-export/formatters.ts +++ b/apps/cli/src/lib/session-export/formatters.ts @@ -43,9 +43,7 @@ function sanitizeTranscriptItem(item: MessageContent): MessageContent { return { ...item, content: (item.content ?? []).filter( - ( - content - ): content is Exclude[number], { type: 'diff' }> => + (content): content is Exclude[number], { type: 'diff' }> => content.type !== 'diff' ), }; diff --git a/apps/cli/src/lib/session-export/image-downloader.ts b/apps/cli/src/lib/session-export/image-downloader.ts index 28420f351..8fdf767c6 100644 --- a/apps/cli/src/lib/session-export/image-downloader.ts +++ b/apps/cli/src/lib/session-export/image-downloader.ts @@ -1,9 +1,6 @@ import { promises as fs } from 'node:fs'; import path from 'node:path'; -import { - buildSessionImageApiUrl, - getSessionImageDownloadApiPath, -} from '@lody/shared'; +import { buildSessionImageApiUrl, getSessionImageDownloadApiPath } from '@lody/shared'; import { LODY_SERVER_URL } from '@/utils/const'; import type { ExportAttachmentRecord } from './types'; import { ensurePathWithinBase } from './path-utils'; @@ -37,9 +34,7 @@ function resolveOutputPath( } const extension = - MIME_EXTENSION_MAP[attachment.mimeType] || - path.extname(attachment.fileName ?? '').trim() || - ''; + MIME_EXTENSION_MAP[attachment.mimeType] || path.extname(attachment.fileName ?? '').trim() || ''; const fileName = attachment.fileName?.trim() ? sanitizeFileStem(attachment.fileName) : `${sanitizeFileStem(attachment.imageId)}${extension}`; diff --git a/apps/cli/src/lib/session-export/output-dir.test.ts b/apps/cli/src/lib/session-export/output-dir.test.ts index 2b20ff291..07f5d9991 100644 --- a/apps/cli/src/lib/session-export/output-dir.test.ts +++ b/apps/cli/src/lib/session-export/output-dir.test.ts @@ -42,8 +42,6 @@ describe('prepareExportOutputDir', () => { const target = await createTempDir(); await fs.writeFile(path.join(target, 'notes.txt'), 'keep out', 'utf8'); - await expect(prepareExportOutputDir(target)).rejects.toThrow( - /Output directory is not empty/ - ); + await expect(prepareExportOutputDir(target)).rejects.toThrow(/Output directory is not empty/); }); }); diff --git a/apps/cli/src/lib/session-export/task-export.test.ts b/apps/cli/src/lib/session-export/task-export.test.ts index 9fd0538f8..8a969ebd9 100644 --- a/apps/cli/src/lib/session-export/task-export.test.ts +++ b/apps/cli/src/lib/session-export/task-export.test.ts @@ -1,11 +1,7 @@ import { describe, expect, it } from 'vitest'; import type { TaskSnapshot } from '@/lib/task-doc'; -import { - buildTaskIndexExportEntry, - formatTaskMarkdown, - sortTasksByCreatedAt, -} from './task-export'; +import { buildTaskIndexExportEntry, formatTaskMarkdown, sortTasksByCreatedAt } from './task-export'; const baseSnapshot = (overrides: Partial = {}): TaskSnapshot => ({ diff --git a/apps/cli/src/lib/session-export/types.ts b/apps/cli/src/lib/session-export/types.ts index 5004428ab..3b4d186d3 100644 --- a/apps/cli/src/lib/session-export/types.ts +++ b/apps/cli/src/lib/session-export/types.ts @@ -1,4 +1,9 @@ -import type { MessageContent, SessionHistoryInput, SessionMeta, SessionPlanEntry } from '@lody/shared'; +import type { + MessageContent, + SessionHistoryInput, + SessionMeta, + SessionPlanEntry, +} from '@lody/shared'; export type ExportSessionSummary = { sessionId: string; diff --git a/apps/cli/src/lib/session-export/workspace-usage.test.ts b/apps/cli/src/lib/session-export/workspace-usage.test.ts index cf5e3480b..e02002626 100644 --- a/apps/cli/src/lib/session-export/workspace-usage.test.ts +++ b/apps/cli/src/lib/session-export/workspace-usage.test.ts @@ -13,7 +13,8 @@ vi.mock('convex/browser', () => ({ vi.mock('@lody/cloud-api', () => ({ api: { usage: { - getWorkspaceUsageSummaryBundleFromCliToken: 'usage.getWorkspaceUsageSummaryBundleFromCliToken', + getWorkspaceUsageSummaryBundleFromCliToken: + 'usage.getWorkspaceUsageSummaryBundleFromCliToken', getWorkspaceUsageTimelineFromCliToken: 'usage.getWorkspaceUsageTimelineFromCliToken', }, }, diff --git a/apps/cli/src/lib/task-automation/task-automation-plan.test.ts b/apps/cli/src/lib/task-automation/task-automation-plan.test.ts index 7484e1f5a..af2434682 100644 --- a/apps/cli/src/lib/task-automation/task-automation-plan.test.ts +++ b/apps/cli/src/lib/task-automation/task-automation-plan.test.ts @@ -57,9 +57,9 @@ describe('isTaskAutomationEligible', () => { }); it('ignores agents that live on another machine', () => { - expect( - isTaskAutomationEligible(candidate({ agentConfigId: 'agent-elsewhere' }), input()) - ).toBe(false); + expect(isTaskAutomationEligible(candidate({ agentConfigId: 'agent-elsewhere' }), input())).toBe( + false + ); }); it("refuses to run another user's task under this operator", () => { @@ -94,7 +94,10 @@ describe('planTaskAutomation', () => { it('respects the user-visible order rather than discovery order', () => { const plan = planTaskAutomation( input({ - candidates: [candidate({ taskId: 'late', order: '9' }), candidate({ taskId: 'early', order: '1' })], + candidates: [ + candidate({ taskId: 'late', order: '9' }), + candidate({ taskId: 'early', order: '1' }), + ], }) ); expect(plan.start[0]?.taskId).toBe('early'); @@ -192,10 +195,10 @@ describe('collectTaskAutomationBaseline', () => { }); it('is empty when nothing is entrusted yet', () => { - const baseline = collectTaskAutomationBaseline( - [candidate({ agentConfigId: undefined })], - { ownedAgentConfigIds: new Set(['agent-1']), operatorUserId: OPERATOR } - ); + const baseline = collectTaskAutomationBaseline([candidate({ agentConfigId: undefined })], { + ownedAgentConfigIds: new Set(['agent-1']), + operatorUserId: OPERATOR, + }); expect(baseline.size).toBe(0); }); }); @@ -284,13 +287,19 @@ describe('planTaskAutomation safety invariants', () => { }; }; - const STATUSES: TaskStatus[] = ['backlog', 'todo', 'in_progress', 'needs_review', 'done', 'canceled']; + const STATUSES: TaskStatus[] = [ + 'backlog', + 'todo', + 'in_progress', + 'needs_review', + 'done', + 'canceled', + ]; it('never starts work the gates forbid, across randomized fleets', () => { for (let seed = 1; seed <= 300; seed += 1) { const random = makeRandom(seed); - const pick = (items: readonly T[]): T => - items[Math.floor(random() * items.length)] as T; + const pick = (items: readonly T[]): T => items[Math.floor(random() * items.length)] as T; const agentIds = ['a1', 'a2', 'a3']; const owned = new Set(agentIds.filter(() => random() < 0.7)); @@ -339,11 +348,15 @@ describe('planTaskAutomation safety invariants', () => { `${where}: started a task that was neither backlog nor todo` ).toBe(true); expect(entry?.ready, `${where}: started an incomplete task`).toBe(true); - expect(owned.has(started.agentConfigId), `${where}: started on an unowned agent`).toBe(true); + expect(owned.has(started.agentConfigId), `${where}: started on an unowned agent`).toBe( + true + ); expect(online.has(started.agentConfigId), `${where}: started on an offline agent`).toBe( true ); - expect(inFlight.has(started.agentConfigId), `${where}: started on a busy agent`).toBe(false); + expect(inFlight.has(started.agentConfigId), `${where}: started on a busy agent`).toBe( + false + ); expect(baselineTaskIds.has(started.taskId), `${where}: replayed the startup backlog`).toBe( false ); diff --git a/apps/cli/src/lib/task-automation/task-automation-start.ts b/apps/cli/src/lib/task-automation/task-automation-start.ts index c2d82faef..1a9bf08da 100644 --- a/apps/cli/src/lib/task-automation/task-automation-start.ts +++ b/apps/cli/src/lib/task-automation/task-automation-start.ts @@ -99,9 +99,7 @@ export const startDelegatedTask = async ( }, }); - deps.logger.debug( - `[task-automation] started sessionId=${result.sessionId} for taskId=${taskId}` - ); + deps.logger.debug(`[task-automation] started sessionId=${result.sessionId} for taskId=${taskId}`); await applyAgentTaskUpdate( deps.manager, diff --git a/apps/cli/src/lib/usage/price.ts b/apps/cli/src/lib/usage/price.ts index 577134965..f0e9af006 100644 --- a/apps/cli/src/lib/usage/price.ts +++ b/apps/cli/src/lib/usage/price.ts @@ -1,86 +1,86 @@ // https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json export type Price = { - inputCostPerToken: number; - outputCostPerToken: number; - cacheReadInputTokenCost: number; -} + inputCostPerToken: number; + outputCostPerToken: number; + cacheReadInputTokenCost: number; +}; export const PRICE_DATA: { [key: string]: Price } = { - 'gpt-5.6': { - inputCostPerToken: 5e-06, - cacheReadInputTokenCost: 5e-07, - outputCostPerToken: 3e-05 - }, - 'gpt-5.6-sol': { - inputCostPerToken: 5e-06, - cacheReadInputTokenCost: 5e-07, - outputCostPerToken: 3e-05 - }, - 'gpt-5.6-terra': { - inputCostPerToken: 2.5e-06, - cacheReadInputTokenCost: 2.5e-07, - outputCostPerToken: 1.5e-05 - }, - 'gpt-5.6-luna': { - inputCostPerToken: 1e-06, - cacheReadInputTokenCost: 1e-07, - outputCostPerToken: 6e-06 - }, - 'gpt-5.5': { - inputCostPerToken: 5e-06, - cacheReadInputTokenCost: 5e-07, - outputCostPerToken: 3e-05 - }, - 'gpt-5.4': { - inputCostPerToken: 2.5e-06, - cacheReadInputTokenCost: 2.5e-07, - outputCostPerToken: 1.5e-05 - }, - 'gpt-5.3-codex-spark': { - inputCostPerToken: 1.75e-06, - cacheReadInputTokenCost: 1.75e-07, - outputCostPerToken: 1.4e-05 - }, - 'gpt-5.3-codex': { - inputCostPerToken: 1.75e-06, - cacheReadInputTokenCost: 1.75e-07, - outputCostPerToken: 1.4e-05 - }, - 'gpt-5.2-codex': { - inputCostPerToken: 1.75e-06, - cacheReadInputTokenCost: 1.75e-07, - outputCostPerToken: 1.4e-05 - }, - 'gpt-5.1-codex': { - inputCostPerToken: 1.25e-06, - cacheReadInputTokenCost: 1.25e-07, - outputCostPerToken: 1e-05 - }, - 'gpt-5.1-codex-max': { - inputCostPerToken: 1.25e-06, - cacheReadInputTokenCost: 1.25e-07, - outputCostPerToken: 1e-05 - }, - 'gpt-5.1-codex-mini': { - inputCostPerToken: 2.5e-07, - cacheReadInputTokenCost: 2.5e-08, - outputCostPerToken: 2e-06 - }, - 'gpt-5.2': { - inputCostPerToken: 1.75e-06, - cacheReadInputTokenCost: 1.75e-07, - outputCostPerToken: 1.4e-05 - }, - // https://www.kimi.com/resources/kimi-k2-7-code-pricing - 'kimi-for-coding': { - inputCostPerToken: 0.95e-06, - cacheReadInputTokenCost: 0.19e-06, - outputCostPerToken: 4e-06 - }, - 'kimi-for-coding-highspeed': { - inputCostPerToken: 0.95e-06, - cacheReadInputTokenCost: 0.19e-06, - outputCostPerToken: 8e-06 - } -} + 'gpt-5.6': { + inputCostPerToken: 5e-6, + cacheReadInputTokenCost: 5e-7, + outputCostPerToken: 3e-5, + }, + 'gpt-5.6-sol': { + inputCostPerToken: 5e-6, + cacheReadInputTokenCost: 5e-7, + outputCostPerToken: 3e-5, + }, + 'gpt-5.6-terra': { + inputCostPerToken: 2.5e-6, + cacheReadInputTokenCost: 2.5e-7, + outputCostPerToken: 1.5e-5, + }, + 'gpt-5.6-luna': { + inputCostPerToken: 1e-6, + cacheReadInputTokenCost: 1e-7, + outputCostPerToken: 6e-6, + }, + 'gpt-5.5': { + inputCostPerToken: 5e-6, + cacheReadInputTokenCost: 5e-7, + outputCostPerToken: 3e-5, + }, + 'gpt-5.4': { + inputCostPerToken: 2.5e-6, + cacheReadInputTokenCost: 2.5e-7, + outputCostPerToken: 1.5e-5, + }, + 'gpt-5.3-codex-spark': { + inputCostPerToken: 1.75e-6, + cacheReadInputTokenCost: 1.75e-7, + outputCostPerToken: 1.4e-5, + }, + 'gpt-5.3-codex': { + inputCostPerToken: 1.75e-6, + cacheReadInputTokenCost: 1.75e-7, + outputCostPerToken: 1.4e-5, + }, + 'gpt-5.2-codex': { + inputCostPerToken: 1.75e-6, + cacheReadInputTokenCost: 1.75e-7, + outputCostPerToken: 1.4e-5, + }, + 'gpt-5.1-codex': { + inputCostPerToken: 1.25e-6, + cacheReadInputTokenCost: 1.25e-7, + outputCostPerToken: 1e-5, + }, + 'gpt-5.1-codex-max': { + inputCostPerToken: 1.25e-6, + cacheReadInputTokenCost: 1.25e-7, + outputCostPerToken: 1e-5, + }, + 'gpt-5.1-codex-mini': { + inputCostPerToken: 2.5e-7, + cacheReadInputTokenCost: 2.5e-8, + outputCostPerToken: 2e-6, + }, + 'gpt-5.2': { + inputCostPerToken: 1.75e-6, + cacheReadInputTokenCost: 1.75e-7, + outputCostPerToken: 1.4e-5, + }, + // https://www.kimi.com/resources/kimi-k2-7-code-pricing + 'kimi-for-coding': { + inputCostPerToken: 0.95e-6, + cacheReadInputTokenCost: 0.19e-6, + outputCostPerToken: 4e-6, + }, + 'kimi-for-coding-highspeed': { + inputCostPerToken: 0.95e-6, + cacheReadInputTokenCost: 0.19e-6, + outputCostPerToken: 8e-6, + }, +}; diff --git a/apps/cli/src/mcp/lody-mcp-server.ts b/apps/cli/src/mcp/lody-mcp-server.ts index 9ae820995..ae9739b60 100644 --- a/apps/cli/src/mcp/lody-mcp-server.ts +++ b/apps/cli/src/mcp/lody-mcp-server.ts @@ -1747,7 +1747,7 @@ const buildSessionList = async (input: SessionListToolInput): Promise = execution: SessionExecutionSnapshot; }> = []; const readChunkSize = MAX_MCP_STATUS_BATCH_SIZE; - for (let offset = 0; offset < candidates.length && matches.length <= limit; ) { + for (let offset = 0; offset < candidates.length && matches.length <= limit;) { const chunk = candidates.slice(offset, offset + readChunkSize); offset += chunk.length; const liveStatuses = await readSessionLiveStatusesMany({ diff --git a/apps/cli/src/session/worktree/worktree-config-resolver.ts b/apps/cli/src/session/worktree/worktree-config-resolver.ts index afd1cd80f..6e7949f7a 100644 --- a/apps/cli/src/session/worktree/worktree-config-resolver.ts +++ b/apps/cli/src/session/worktree/worktree-config-resolver.ts @@ -62,15 +62,16 @@ export async function resolveSessionWorktreeCleanupConfig(input: { return null; } - const repoFullName = - resolveProjectGitHubRepo(sessionMeta?.project) ?? sessionMeta?.repoFullName; + const repoFullName = resolveProjectGitHubRepo(sessionMeta?.project) ?? sessionMeta?.repoFullName; return ( - (await resolveGitHubRepoWorktreeConfig({ - token: input.token, - workspaceId: input.workspaceId, - repoFullName, - logger: input.logger, - }))?.worktreeCleanup ?? + ( + await resolveGitHubRepoWorktreeConfig({ + token: input.token, + workspaceId: input.workspaceId, + repoFullName, + logger: input.logger, + }) + )?.worktreeCleanup ?? ( await readLegacySessionLaunchConfig({ repo: input.workspaceDocument.repo, diff --git a/apps/cli/src/session/worktree/worktree-setup-config-store.ts b/apps/cli/src/session/worktree/worktree-setup-config-store.ts index bf91e321b..c270c3b73 100644 --- a/apps/cli/src/session/worktree/worktree-setup-config-store.ts +++ b/apps/cli/src/session/worktree/worktree-setup-config-store.ts @@ -45,10 +45,7 @@ export function getLocalProjectWorktreeCleanupPath(localProjectId: LocalProjectI async function readLocalProjectWorktreeScript< TConfig extends WorktreeSetupScriptConfig | WorktreeCleanupScriptConfig, ->( - localProjectId: LocalProjectId, - phase: WorktreeScriptPhase -): Promise { +>(localProjectId: LocalProjectId, phase: WorktreeScriptPhase): Promise { try { return JSON.parse( await readFile(getLocalProjectWorktreeScriptPath(localProjectId, phase), 'utf8') @@ -109,7 +106,9 @@ export async function deleteLocalProjectWorktreeSetup( export function isLocalProjectWorktreeConfigRequest( request: LocalProjectControlRequest ): request is LocalProjectWorktreeConfigRequest { - return WORKTREE_CONFIG_REQUEST_TYPES.has(request.type as LocalProjectWorktreeConfigRequest['type']); + return WORKTREE_CONFIG_REQUEST_TYPES.has( + request.type as LocalProjectWorktreeConfigRequest['type'] + ); } export async function handleLocalProjectWorktreeConfigRequest( diff --git a/apps/electron/.prettierignore b/apps/electron/.prettierignore deleted file mode 100644 index 9c6b791d5..000000000 --- a/apps/electron/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -out -dist -pnpm-lock.yaml -LICENSE.md -tsconfig.json -tsconfig.*.json diff --git a/apps/electron/.prettierrc.yaml b/apps/electron/.prettierrc.yaml deleted file mode 100644 index 35893b3be..000000000 --- a/apps/electron/.prettierrc.yaml +++ /dev/null @@ -1,4 +0,0 @@ -singleQuote: true -semi: false -printWidth: 100 -trailingComma: none diff --git a/apps/electron/.vscode/extensions.json b/apps/electron/.vscode/extensions.json index 940260d85..0d4efacdc 100644 --- a/apps/electron/.vscode/extensions.json +++ b/apps/electron/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["dbaeumer.vscode-eslint"] + "recommendations": ["dbaeumer.vscode-eslint", "oxc.oxc-vscode"] } diff --git a/apps/electron/.vscode/settings.json b/apps/electron/.vscode/settings.json index 4c05394ec..703f6dec0 100644 --- a/apps/electron/.vscode/settings.json +++ b/apps/electron/.vscode/settings.json @@ -1,11 +1,11 @@ { "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "oxc.oxc-vscode" } } diff --git a/apps/electron/README.md b/apps/electron/README.md index c970991e4..33d873580 100644 --- a/apps/electron/README.md +++ b/apps/electron/README.md @@ -4,7 +4,7 @@ Lody desktop application built with Electron, React, and TypeScript. ## Recommended IDE Setup -- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) +- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Oxc](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) ## Project Setup diff --git a/apps/electron/electron-builder.yml b/apps/electron/electron-builder.yml index 110ac03f9..df9f79259 100644 --- a/apps/electron/electron-builder.yml +++ b/apps/electron/electron-builder.yml @@ -15,7 +15,7 @@ files: - '!src/*' - '!scripts/*' - '!electron.vite.config.{js,ts,mjs,cjs}' - - '!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' + - '!{.eslintcache,eslint.config.mjs,dev-app-update.yml,CHANGELOG.md,README.md}' - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' - '!**/node_modules/electron-sparkle-updater/native/vendor/**' @@ -33,6 +33,7 @@ files: # Exclude transitive runtime-unneeded utility/tooling libs. - '!node_modules/effect/**' - '!node_modules/prettier/**' + - '!node_modules/oxfmt/**' - '!node_modules/@cloudflare/workers-types/**' - '!node_modules/esbuild/**' - '!node_modules/@esbuild/**' diff --git a/apps/electron/package.json b/apps/electron/package.json index 60ebf85f3..3df154150 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -9,7 +9,8 @@ "author": "LodyAI", "homepage": "https://github.com/LodyAI/Lody", "scripts": { - "format": "prettier --write .", + "format": "oxfmt", + "format:check": "oxfmt --check", "test": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --experimental-strip-types --test src/system-language-argument.test.mjs src/main/reload-shortcut.test.mjs src/main/close-focused-tab-or-window.test.mjs src/main/onboarding-launch-policy.test.mjs src/main/auto-launch-policy.test.mjs src/main/window-theme.test.mjs src/main/local-platform-snapshot.test.mjs src/main/ipc/ipc-channel-list.test.mjs src/main/services/local-path-launcher-core.test.mjs src/main/services/image-export-core.test.mjs src/main/services/public-browser-state.test.mjs src/main/services/app-updater-metadata.test.mjs src/main/services/app-updater-sparkle-policy.test.mjs src/main/services/app-updater-sparkle-events.test.mjs src/main/services/loro-data-plane-relay.test.mjs src/renderer/renderer-csp.test.mjs src/renderer/src/auth-callback-transaction.test.mjs src/renderer/src/auth-query-generation.test.mjs src/renderer/src/renderer-error-reporting.test.mjs scripts/sparkle-packaging.test.mjs", "lint": "eslint --cache .", "typecheck:node": "tsgo --noEmit -p tsconfig.node.json --composite false", diff --git a/apps/electron/src/main/services/app-updater-sparkle-policy.test.mjs b/apps/electron/src/main/services/app-updater-sparkle-policy.test.mjs index 62596e28c..62305a3c7 100644 --- a/apps/electron/src/main/services/app-updater-sparkle-policy.test.mjs +++ b/apps/electron/src/main/services/app-updater-sparkle-policy.test.mjs @@ -12,18 +12,9 @@ import { } from './app-updater-sparkle-policy.ts' void test('keeps OSS local updater off unless explicitly force-enabled', () => { - assert.equal( - shouldConstructUpdaterEnabled({ localPlatform: true, forceEnable: false }), - false - ) - assert.equal( - shouldConstructUpdaterEnabled({ localPlatform: true, forceEnable: true }), - true - ) - assert.equal( - shouldConstructUpdaterEnabled({ localPlatform: false, forceEnable: false }), - true - ) + assert.equal(shouldConstructUpdaterEnabled({ localPlatform: true, forceEnable: false }), false) + assert.equal(shouldConstructUpdaterEnabled({ localPlatform: true, forceEnable: true }), true) + assert.equal(shouldConstructUpdaterEnabled({ localPlatform: false, forceEnable: false }), true) }) void test('uses Sparkle only for packaged macOS when the native bridge is available', () => { diff --git a/apps/electron/src/main/services/cli-service.ts b/apps/electron/src/main/services/cli-service.ts index 2e12242f8..fb364e65c 100644 --- a/apps/electron/src/main/services/cli-service.ts +++ b/apps/electron/src/main/services/cli-service.ts @@ -658,12 +658,10 @@ export class CliService { this.localControlClient .sessionControl(message, { timeoutMs, onResponse: options.onResponse }) .pipe( - Effect.map( - (responses): SendLocalSessionControlResult => ({ - ok: true, - responses - }) - ), + Effect.map((responses): SendLocalSessionControlResult => ({ + ok: true, + responses + })), Effect.catchTag('IpcTimeoutError', () => Effect.succeed({ ok: false as const, error: 'request_timeout' }) ), diff --git a/package.json b/package.json index e86a0ae2e..0fadfacd8 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "storybook:review-helper": "corepack pnpm --filter @lody/code-review-helper storybook", "build-storybook:review-helper": "corepack pnpm --filter @lody/code-review-helper build-storybook", "clean": "corepack pnpm -r run clean", - "format": "corepack pnpm -r --filter '!acp-extension-claude' --filter '!acp-extension-codex' run format", - "format:check": "corepack pnpm -r --filter '!acp-extension-claude' --filter '!acp-extension-codex' run format:check", + "format": "corepack pnpm -r --filter '!acp-extension-claude' --filter '!acp-extension-codex' --filter '!acp-extension-core' --filter '!acp-extension-dsh' --filter '!acp-extension-grok' run format", + "format:check": "corepack pnpm -r --filter '!acp-extension-claude' --filter '!acp-extension-codex' --filter '!acp-extension-core' --filter '!acp-extension-dsh' --filter '!acp-extension-grok' run format:check", "typecheck": "corepack pnpm --filter lody prepare:acp-adapters && corepack pnpm -r --workspace-concurrency=1 --filter '!acp-extension-claude' --filter '!acp-extension-codex' run typecheck", "test": "corepack pnpm -r --workspace-concurrency=1 run test", "test:ci": "corepack pnpm -r --workspace-concurrency=2 --filter \"!@lody/electron\" --filter \"!acp-extension-codex\" --filter \"!acp-extension-claude\" run test --maxWorkers=2 && corepack pnpm --filter @lody/electron run test", @@ -60,9 +60,9 @@ }, "devDependencies": { "@typescript/native-preview": "7.0.0-dev.20251217.1", + "oxfmt": "^0.65.0", "oxlint": "^1.61.0", "oxlint-tsgolint": "^0.22.0", - "prettier": "^3.6.2", "proxy-from-env": "^1.1.0", "tar": "^7.5.7", "tailwindcss": "^4.3.0", diff --git a/packages/cloud-api/package.json b/packages/cloud-api/package.json index 3592424e6..72b5528c7 100644 --- a/packages/cloud-api/package.json +++ b/packages/cloud-api/package.json @@ -13,8 +13,8 @@ }, "scripts": { "typecheck": "tsgo --noEmit", - "format": "prettier --write src/**/*.ts", - "format:check": "prettier --check src/**/*.ts" + "format": "oxfmt 'src/**/*.ts'", + "format:check": "oxfmt --check 'src/**/*.ts'" }, "dependencies": { "@lody/shared": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52dac9a5b..29d455fa7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,15 +160,15 @@ importers: '@typescript/native-preview': specifier: 7.0.0-dev.20251217.1 version: 7.0.0-dev.20251217.1 + oxfmt: + specifier: ^0.65.0 + version: 0.65.0 oxlint: specifier: ^1.61.0 version: 1.61.0(oxlint-tsgolint@0.22.0) oxlint-tsgolint: specifier: ^0.22.0 version: 0.22.0 - prettier: - specifier: ^3.6.2 - version: 3.8.1 proxy-from-env: specifier: ^1.1.0 version: 1.1.0 @@ -359,9 +359,6 @@ importers: posthog-node: specifier: ^5.38.8 version: 5.38.8(rxjs@7.8.2) - prettier: - specifier: ^3.6.2 - version: 3.8.1 proxy-from-env: specifier: ^1.1.0 version: 1.1.0 @@ -3441,6 +3438,120 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxfmt/binding-android-arm-eabi@0.65.0': + resolution: {integrity: sha512-M10Gs1SSpTNI6ahGx3M/OlIdUF4hkaP6OgUb+MS79t/Pgflk3r1nW5gPFqsZGUAXg0H1AfANT9AvLdBSTIhZKg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.65.0': + resolution: {integrity: sha512-6DXH5sftNlaHpWJG50hFMF+Qxtq5D2TmahvcDPxWNcGIf8qrC9Y0YgHYcYZ2hlWzaccKXh/f3GcssH8vtkl4JA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.65.0': + resolution: {integrity: sha512-K9m7lr53pcOLETNsC88sWes/GWHUGjZyHx95UhYcSXy0r30haLdeXlSufSenEAtoLaW753WN8/l4M7GYcRt6cg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.65.0': + resolution: {integrity: sha512-sTNwIx1gre3MyiHOPLu7IGW4UyMScYL4DTmJT01p4vzB0En+OJUQz6KuH8t0PpsClRSaMuY3b0QmtoPItfO8Lg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.65.0': + resolution: {integrity: sha512-lYZMVIiIpnjGu5hJb2jxA8NYQ/e0OTGuaiAf4dqlGPNnPmUTu23FZRMltmjro/KkQm1uE4NT4n5yJ2zWmKcpfA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.65.0': + resolution: {integrity: sha512-gIdXFAt/bURnjxuoedDEWdZ0PEWEmdDcm8qdpoFYYvW3QMk/5D4vUaH4mlMeRpeTdST4izUgHVO6RawQ4QulJw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.65.0': + resolution: {integrity: sha512-jJVyADto7gA2AaX5qAjAexrxx9PJQaKWOe8PICE7yKMbjBRyOHcmj9TtVJ+MZYDUQ3hodU0AcoTj0jFQ1W4C6Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.65.0': + resolution: {integrity: sha512-p3RFkB+u7u+8up99b/NEcI1hdpLDiGgJYNwDorB60n7eH+eKposAKuMBxx+NqB3b+sJP4CZmYDh9G7X62tUsKg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-arm64-musl@0.65.0': + resolution: {integrity: sha512-5Prb0uFzJHr+OUD/qS/TmU526wD+PaHDsm3KoRiUXbMIDpTSErjeQYkK3OQeshAvD/PuLa9WGEi9WPajjdOZJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-ppc64-gnu@0.65.0': + resolution: {integrity: sha512-S8svxTp81obnF3admN9yd+u2rOYXtyzThLGBTg1PY6TPtGcC09BaaXLQD+TBSMa7yvqhCDZ8DFri+S/yG60qCg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-gnu@0.65.0': + resolution: {integrity: sha512-WtXBr75G/h2qOHy8SiGtC1R6aS3jt4mE52v1D8AtwMXIgoOmSNP9lKvbSaTRoL0e5wsMPoi6T72QWDYPu+S+nA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-musl@0.65.0': + resolution: {integrity: sha512-YwSLVvpaz4o/nv/miiPEBJz+eJ+VmbgNIrao6RccK9ce+L5EA8wP+ZD0uFeq6wKOza6zoWv/dR0sj6lip6R3EA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-s390x-gnu@0.65.0': + resolution: {integrity: sha512-XQTPqgvyrgkKcFq+Tp2eK6JS7sqqJ+nRmy2Fav4j3I+i4dJoPJm7YwEdoeSDX9xkqj9jZ/lWfF3bXUWztIrn6A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@oxfmt/binding-linux-x64-gnu@0.65.0': + resolution: {integrity: sha512-cjZlx6S/VkeCNWCbwZriTnLnZeTcV3DEyeRGSw/2wwLP9viq+C0bJ4bC1k/ZLkFxDcB1lUgSasPkYGP1bdraOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-linux-x64-musl@0.65.0': + resolution: {integrity: sha512-2azCjxdLtK4zCcIOU1dlXlU0xxfbPi6EjwWx7Ac7teWPidIIDOcIhudup83xNCKYhtqeVd/gaVDOxbUq4syXWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-openharmony-arm64@0.65.0': + resolution: {integrity: sha512-KXQ7xi1e/voP0IQaw6fG6XY4Z5+Llf1XmRSZS1t7pVFCecFJ0iXaboKmVwjFtp5MLlT5iWQrJ2U1C3GJdZ2u+Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.65.0': + resolution: {integrity: sha512-2FbbjG5jEqLSLKVJwBap84uJfpn5Y5A53KEO0aUNr+zeiRB9nyPUIFMcSbZVMFLitfBytFWRNngozXYjb6Rsbw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.65.0': + resolution: {integrity: sha512-LJ+ZacAPSjegDOnSLyA1TMWAhdDrsK4el3REdr1oL2UtVBCMhO2II/Sb3cEW6mF2MfLhl8hDNCSvc7KSbgk3LQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.65.0': + resolution: {integrity: sha512-higu9cWEO6XXFzATD1jf0mCK34rNfN2H9JrJie7QB1IhleVpTh0QlLH9Ip2C1H/Nd5n0v5pvRtC+5R0uE4HpVg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxlint-tsgolint/darwin-arm64@0.22.0': resolution: {integrity: sha512-/exgXceakHbQrzaHTtKOe7MuDATaWMCCWpsCDQCZKeYhLGXzComipTrCYnHzAXrdnNBb5r5K+RRf5A6ormrhMA==} cpu: [arm64] @@ -10073,6 +10184,19 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxfmt@0.65.0: + resolution: {integrity: sha512-SgS5VgnP42T0zl3zWD+xoH8FCqg1SAFnSRoOT/qeoa6gxcYIqrDMOmcXIg/EWSN92Du4ogB4riuKhKd6Y4CGhw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + svelte: ^5.0.0 + vite-plus: '*' + peerDependenciesMeta: + svelte: + optional: true + vite-plus: + optional: true + oxlint-tsgolint@0.22.0: resolution: {integrity: sha512-ku4MecLmCQIj1ScCtzNAqTuyl0BJQ02B36fJT+c5XQihHpYSFak+FC3GYO5fPyYk4oDwi0w0S7hTvrpNzuZhig==} hasBin: true @@ -11501,6 +11625,10 @@ packages: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + tinyrainbow@2.0.0: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} @@ -14587,6 +14715,63 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@oxfmt/binding-android-arm-eabi@0.65.0': + optional: true + + '@oxfmt/binding-android-arm64@0.65.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.65.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.65.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.65.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.65.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.65.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.65.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.65.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.65.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.65.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.65.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.65.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.65.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.65.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.65.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.65.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.65.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.65.0': + optional: true + '@oxlint-tsgolint/darwin-arm64@0.22.0': optional: true @@ -22749,6 +22934,30 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxfmt@0.65.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.65.0 + '@oxfmt/binding-android-arm64': 0.65.0 + '@oxfmt/binding-darwin-arm64': 0.65.0 + '@oxfmt/binding-darwin-x64': 0.65.0 + '@oxfmt/binding-freebsd-x64': 0.65.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.65.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.65.0 + '@oxfmt/binding-linux-arm64-gnu': 0.65.0 + '@oxfmt/binding-linux-arm64-musl': 0.65.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.65.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.65.0 + '@oxfmt/binding-linux-riscv64-musl': 0.65.0 + '@oxfmt/binding-linux-s390x-gnu': 0.65.0 + '@oxfmt/binding-linux-x64-gnu': 0.65.0 + '@oxfmt/binding-linux-x64-musl': 0.65.0 + '@oxfmt/binding-openharmony-arm64': 0.65.0 + '@oxfmt/binding-win32-arm64-msvc': 0.65.0 + '@oxfmt/binding-win32-ia32-msvc': 0.65.0 + '@oxfmt/binding-win32-x64-msvc': 0.65.0 + oxlint-tsgolint@0.22.0: optionalDependencies: '@oxlint-tsgolint/darwin-arm64': 0.22.0 @@ -24533,6 +24742,8 @@ snapshots: tinypool@1.1.1: {} + tinypool@2.1.0: {} + tinyrainbow@2.0.0: {} tinyrainbow@3.1.0: {}