Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions core/app/components/walkthrough/CommitView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ArrowsClockwiseIcon as ArrowsClockwise } from '@phosphor-icons/react/Ar
import { CheckIcon as Check } from '@phosphor-icons/react/Check';
import { GitBranchIcon as GitBranch } from '@phosphor-icons/react/GitBranch';
import { XIcon as X } from '@phosphor-icons/react/X';
import { init as initGhostty, Terminal } from 'ghostty-web';
import type { Terminal } from 'ghostty-web';
import { useEffect, useRef, useState } from 'react';
import {
changeTypeLabel,
Expand Down Expand Up @@ -78,6 +78,16 @@ function resolveBackdrop(element: HTMLElement): string {
return '#00000000';
}

// `ghostty-web` inlines its WASM binary as a ~550KB base64 data URL, and only
// the commit log terminal needs it. Importing it on demand keeps that payload
// out of the entry bundle every window parses before first paint.
let ghosttyModule: Promise<typeof import('ghostty-web')> | null = null;
const loadGhostty = async () => {
const ghostty = await (ghosttyModule ??= import('ghostty-web'));
await ghostty.init();
return ghostty;
};

/**
* Read-only ghostty-web terminal that replays the streamed commit output, so
* ANSI colors and cursor movement from pre-commit hooks render as they would
Expand All @@ -97,7 +107,7 @@ function CommitLogTerminal({ output }: { output: string }) {
let instance: Terminal | null = null;
// ghostty-web loads its WASM module asynchronously; output streamed in the
// meantime is replayed by the write effect once the terminal exists.
void initGhostty().then(() => {
void loadGhostty().then(({ Terminal }) => {
if (disposed) {
return;
}
Expand Down
5 changes: 3 additions & 2 deletions electron/plan-review.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const { createHash, randomUUID } = require('node:crypto');
const { mkdir, open, readFile, rename, unlink } = require('node:fs/promises');
const { dirname, join, resolve } = require('node:path');
const lockfile = require('proper-lockfile');

const MAX_PLAN_REVIEW_BYTES = 2 * 1024 * 1024;
const PLAN_REVIEW_LOCK_STALE_MS = 10_000;
Expand Down Expand Up @@ -144,7 +143,9 @@ const readPlanReviewAtPath = async (path) => {
/** @template T @param {string} path @param {() => Promise<T>} operation */
const withPlanReviewLock = async (path, operation) => {
await mkdir(dirname(path), { recursive: true });
const release = await lockfile.lock(path, {
// Only plan reviews take this lock, so `proper-lockfile` and its dependency
// tree stay out of the startup path.
const release = await require('proper-lockfile').lock(path, {
realpath: false,
retries: {
factor: 1,
Expand Down
8 changes: 6 additions & 2 deletions electron/walkthrough-commit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ const { accessSync, chmodSync, constants, mkdtempSync, rmSync, writeFileSync } =
const { tmpdir } = require('node:os');
const { dirname, join } = require('node:path');

const pty = require('node-pty');

const { git, validateRepositoryPath } = require('./git-state/common.cjs');

// `node-pty` is a native addon and only a walkthrough commit needs it, so it is
// loaded on first use rather than at startup.
/** @returns {typeof import('node-pty')} */
const loadPty = () => require('node-pty');

/**
* @typedef {import('../core/types.ts').WalkthroughCommitRequest} WalkthroughCommitRequest
* @typedef {import('../core/types.ts').WalkthroughCommitResult} WalkthroughCommitResult
Expand Down Expand Up @@ -73,6 +76,7 @@ const normalizeTerminalOutput = (text) =>
*/
const gitStreaming = (repoPath, args, onOutput) =>
new Promise((resolve, reject) => {
const pty = loadPty();
ensureSpawnHelperIsExecutable();
/** @type {import('node-pty').IPty} */
let child;
Expand Down