chore(lint): convert type aliases to interfaces (autofix)

- Remove no-use-before-define rule (conflicts with unistyles ordering)
- Add typescript/consistent-type-definitions: interface
- Run oxlint --fix: 606 type->interface conversions across 268 files

Typecheck green. Warnings: 5432 -> 3787 (-1645).
This commit is contained in:
Mohamed Boudra
2026-04-23 22:59:49 +07:00
parent 7aaca4ec8d
commit 106249c632
268 changed files with 1247 additions and 1196 deletions

View File

@@ -18,7 +18,6 @@
"no-empty-pattern": "warn",
"no-self-assign": "warn",
"no-shadow": "warn",
"no-use-before-define": ["warn", { "functions": false, "classes": false, "variables": true }],
"require-await": "off",
"unicorn/consistent-function-scoping": "off",
"unicorn/no-array-sort": "off",
@@ -53,6 +52,7 @@
"typescript/no-explicit-any": "warn",
"typescript/prefer-as-const": "warn",
"typescript/no-this-alias": "warn",
"typescript/consistent-type-definitions": ["warn", "interface"],
"no-nested-ternary": "warn",
"no-unneeded-ternary": "warn",

View File

@@ -8,13 +8,13 @@ import { Buffer } from "node:buffer";
import dotenv from "dotenv";
import { forkPaseoHomeMetadata, resolvePaseoHomePath } from "./helpers/paseo-home-fork";
type WaitForServerOptions = {
interface WaitForServerOptions {
host?: string;
timeoutMs?: number;
label: string;
childProcess?: ChildProcess | null;
getRecentOutput?: () => string;
};
}
async function getAvailablePort(): Promise<number> {
return new Promise((resolve, reject) => {
@@ -197,12 +197,12 @@ function resolveOptionalPaseoHomeEnv(value: string | undefined): string | null {
return resolvePaseoHomePath(trimmed);
}
type OfferPayload = {
interface OfferPayload {
v: 2;
serverId: string;
daemonPublicKeyB64: string;
relay: { endpoint: string };
};
}
async function createFakeGhBin(): Promise<string> {
const binDir = await mkdtemp(path.join(tmpdir(), "paseo-e2e-gh-bin-"));

View File

@@ -7,22 +7,22 @@ import { buildHostWorkspaceRoute } from "../../src/utils/host-routes";
const NEAR_BOTTOM_THRESHOLD_PX = 72;
export type ScrollMetrics = {
export interface ScrollMetrics {
offsetY: number;
contentHeight: number;
viewportHeight: number;
distanceFromBottom: number;
};
}
export type SeededAgent = {
export interface SeededAgent {
id: string;
title: string;
expectedTailText: string;
url: string;
workspaceUrl: string;
};
}
export type DaemonClientInstance = {
export interface DaemonClientInstance {
connect(): Promise<void>;
close(): Promise<void>;
createAgent(options: {
@@ -36,7 +36,7 @@ export type DaemonClientInstance = {
}): Promise<{ id: string }>;
sendAgentMessage(agentId: string, text: string): Promise<void>;
waitForFinish(agentId: string, timeout?: number): Promise<{ status: string }>;
};
}
function getDaemonWsUrl(): string {
const daemonPort = process.env.E2E_DAEMON_PORT;
@@ -84,12 +84,12 @@ export function createReplyTurn(label: string): {
};
}
type DaemonClientConfig = {
interface DaemonClientConfig {
url: string;
clientId: string;
clientType: "cli";
webSocketFactory?: NodeWebSocketFactory;
};
}
async function loadDaemonClientConstructor(): Promise<
new (config: DaemonClientConfig) => DaemonClientInstance

View File

@@ -11,13 +11,13 @@ import {
buildHostWorkspaceRoute,
} from "@/utils/host-routes";
export type ArchiveTabAgent = {
export interface ArchiveTabAgent {
id: string;
title: string;
cwd: string;
};
}
type ArchiveTabDaemonClient = {
interface ArchiveTabDaemonClient {
connect(): Promise<void>;
close(): Promise<void>;
createAgent(options: {
@@ -36,7 +36,7 @@ type ArchiveTabDaemonClient = {
predicate: (snapshot: { status: string }) => boolean,
timeout?: number,
): Promise<{ status: string }>;
};
}
function getDaemonPort(): string {
const daemonPort = process.env.E2E_DAEMON_PORT;
@@ -73,12 +73,12 @@ function buildSeededStoragePayload() {
};
}
type ArchiveTabDaemonClientConfig = {
interface ArchiveTabDaemonClientConfig {
url: string;
clientId: string;
clientType: "cli";
webSocketFactory?: NodeWebSocketFactory;
};
}
async function loadDaemonClientConstructor(): Promise<
new (config: ArchiveTabDaemonClientConfig) => ArchiveTabDaemonClient

View File

@@ -17,21 +17,21 @@ type NewWorkspaceDaemonClient = Pick<
| "openProject"
>;
type NewWorkspaceDaemonClientConfig = {
interface NewWorkspaceDaemonClientConfig {
url: string;
clientId: string;
clientType: "cli";
webSocketFactory?: NodeWebSocketFactory;
};
}
type OpenProjectPayload = Awaited<ReturnType<NewWorkspaceDaemonClient["openProject"]>>;
export type OpenedProject = {
export interface OpenedProject {
workspaceId: string;
projectKey: string;
projectDisplayName: string;
workspaceName: string;
};
}
function getDaemonPort(): string {
const daemonPort = process.env.E2E_DAEMON_PORT;

View File

@@ -1,6 +1,6 @@
import WebSocket from "ws";
type WebSocketLike = {
interface WebSocketLike {
readyState: number;
send: (data: string | Uint8Array | ArrayBuffer) => void;
close: (code?: number, reason?: string) => void;
@@ -14,7 +14,7 @@ type WebSocketLike = {
onclose?: ((event: any) => void) | null;
onerror?: ((event: any) => void) | null;
onmessage?: ((event: any) => void) | null;
};
}
export type NodeWebSocketFactory = (
url: string,

View File

@@ -3,7 +3,7 @@ import { copyFile, mkdir, readdir, rm, stat } from "node:fs/promises";
import { homedir } from "node:os";
import path from "node:path";
export type PaseoHomeMetadataForkResult = {
export interface PaseoHomeMetadataForkResult {
sourceHome: string;
targetHome: string;
agentFiles: number;
@@ -13,13 +13,13 @@ export type PaseoHomeMetadataForkResult = {
copiedFiles: number;
copiedBytes: number;
skippedMissing: string[];
};
}
type CopyStats = {
interface CopyStats {
files: number;
bytes: number;
skippedMissing: string[];
};
}
export function resolvePaseoHomePath(value: string): string {
if (value === "~") {

View File

@@ -6,11 +6,11 @@ const SEED_NONCE_KEY = "@paseo:e2e-seed-nonce";
const REGISTRY_KEY = "@paseo:daemon-registry";
const E2E_KEY = "@paseo:e2e";
type SavedHostInput = {
interface SavedHostInput {
serverId: string;
label: string;
endpoint: string;
};
}
export function startupScenario(page: Page) {
return new StartupScenario(page);

View File

@@ -7,16 +7,16 @@ import {
type TerminalPerfDaemonClient,
} from "./terminal-perf";
type TempRepo = {
interface TempRepo {
path: string;
cleanup: () => Promise<void>;
};
}
export type TerminalInstance = {
export interface TerminalInstance {
id: string;
name: string;
cwd: string;
};
}
export class TerminalE2EHarness {
readonly client: TerminalPerfDaemonClient;

View File

@@ -5,7 +5,7 @@ import { randomUUID } from "node:crypto";
import { createNodeWebSocketFactory, type NodeWebSocketFactory } from "./node-ws-factory";
import { buildHostWorkspaceRoute } from "../../src/utils/host-routes";
export type TerminalPerfDaemonClient = {
export interface TerminalPerfDaemonClient {
connect(): Promise<void>;
close(): Promise<void>;
openProject(cwd: string): Promise<{
@@ -37,7 +37,7 @@ export type TerminalPerfDaemonClient = {
handler: (event: { terminalId: string; type: string; data?: Uint8Array }) => void,
): () => void;
killTerminal(terminalId: string): Promise<{ error: string | null }>;
};
}
function getDaemonWsUrl(): string {
const daemonPort = process.env.E2E_DAEMON_PORT;
@@ -55,12 +55,12 @@ function getServerId(): string {
return serverId;
}
type TerminalPerfDaemonClientConfig = {
interface TerminalPerfDaemonClientConfig {
url: string;
clientId: string;
clientType: "cli";
webSocketFactory?: NodeWebSocketFactory;
};
}
async function loadDaemonClientConstructor(): Promise<
new (config: TerminalPerfDaemonClientConfig) => TerminalPerfDaemonClient
@@ -191,10 +191,10 @@ export async function setupDeterministicPrompt(page: Page, sentinel?: string): P
await page.waitForTimeout(300);
}
export type LatencySample = {
export interface LatencySample {
char: string;
latencyMs: number;
};
}
/**
* Measures keystroke echo round-trip latency.

View File

@@ -1,6 +1,6 @@
import type { Page } from "@playwright/test";
export type TerminalRenderProbeSnapshot = {
export interface TerminalRenderProbeSnapshot {
setCount: number;
unsetCount: number;
writeCount: number;
@@ -10,28 +10,28 @@ export type TerminalRenderProbeSnapshot = {
altExitWrites: number;
events: TerminalRenderProbeEvent[];
frames: TerminalFrame[];
};
}
export type TerminalRenderProbeEvent = {
export interface TerminalRenderProbeEvent {
at: number;
type: "set" | "unset" | "reset-write" | "clear-write" | "alt-enter-write" | "alt-exit-write";
preview?: string;
};
}
export type TerminalFrame = {
export interface TerminalFrame {
at: number;
rowCount: number;
nonEmptyRows: number;
firstNonEmptyRow: number | null;
text: string;
topText: string;
};
}
export type TerminalRenderProbeSummary = Omit<TerminalRenderProbeSnapshot, "frames"> & {
frameCount: number;
};
export type TerminalKeystrokeStressReport = {
export interface TerminalKeystrokeStressReport {
inputTextLength: number;
keydownCount: number;
inputFrameCount: number;
@@ -70,20 +70,20 @@ export type TerminalKeystrokeStressReport = {
keydownToXtermCommitMs: LatencyStats | null;
firstKeydownAt: number | null;
lastXtermCommitAt: number | null;
};
}
export type LatencyStats = {
export interface LatencyStats {
count: number;
minMs: number;
p50Ms: number;
p95Ms: number;
maxMs: number;
avgMs: number;
};
}
export async function installTerminalRenderProbe(page: Page): Promise<void> {
await page.addInitScript(() => {
type ProbeState = {
interface ProbeState {
term: any;
setCount: number;
unsetCount: number;
@@ -99,7 +99,7 @@ export async function installTerminalRenderProbe(page: Page): Promise<void> {
reset: () => void;
snapshot: () => TerminalRenderProbeSnapshot;
startSampling: (durationMs: number) => void;
};
}
const win = window as any;
const existingDescriptor = Object.getOwnPropertyDescriptor(win, "__paseoTerminal");
@@ -272,29 +272,29 @@ export function summarizeTerminalRenderProbe(
export async function installTerminalKeystrokeStressProbe(page: Page): Promise<void> {
await page.addInitScript(() => {
type TimedTextEvent = {
interface TimedTextEvent {
at: number;
text: string;
bytes: number;
};
type TimedTextMessageEvent = {
}
interface TimedTextMessageEvent {
at: number;
bytes: number;
kind: string | null;
};
type XtermWriteEvent = {
}
interface XtermWriteEvent {
at: number;
committedAt: number | null;
text: string;
bytes: number;
};
type AppProbeEvent = {
}
interface AppProbeEvent {
type: string;
at: number;
bytes?: number;
queueDepth?: number;
};
type StressProbeState = {
}
interface StressProbeState {
keydowns: Array<{ at: number; key: string }>;
inputFrames: TimedTextEvent[];
outputFrames: TimedTextEvent[];
@@ -303,7 +303,7 @@ export async function installTerminalKeystrokeStressProbe(page: Page): Promise<v
appEvents: AppProbeEvent[];
reset: () => void;
report: (inputText: string) => TerminalKeystrokeStressReport;
};
}
const INPUT_OPCODE = 0x02;
const OUTPUT_OPCODE = 0x01;

View File

@@ -8,7 +8,7 @@ import { gotoAppShell } from "./app";
import { createNodeWebSocketFactory, type NodeWebSocketFactory } from "./node-ws-factory";
import type { SessionOutboundMessage } from "@server/shared/messages";
type WorkspaceSetupDaemonClient = {
interface WorkspaceSetupDaemonClient {
connect(): Promise<void>;
close(): Promise<void>;
openProject(cwd: string): Promise<{
@@ -52,7 +52,7 @@ type WorkspaceSetupDaemonClient = {
error?: string | null;
}>;
subscribeRawMessages(handler: (message: SessionOutboundMessage) => void): () => void;
};
}
export type WorkspaceSetupProgressPayload = Extract<
SessionOutboundMessage,

View File

@@ -3,11 +3,11 @@ import { mkdtemp, writeFile, rm, mkdir, realpath } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
type TempRepo = {
interface TempRepo {
path: string;
branchHeads: Record<string, string>;
cleanup: () => Promise<void>;
};
}
export const createTempGitRepo = async (
prefix = "paseo-e2e-",

View File

@@ -7,13 +7,13 @@ import { waitForSidebarHydration } from "./helpers/workspace-ui";
type WireDirection = "sent" | "received";
type WirePhase = "startup" | "workspace_clicks";
type ParsedWireMessage = {
interface ParsedWireMessage {
type: string | null;
requestId: string | null;
entryCount: number | null;
hasMore: boolean | null;
providerEntries: ProviderSnapshotWireEntry[] | null;
};
}
type WireFrameRecord = ParsedWireMessage & {
phase: WirePhase;
@@ -21,23 +21,23 @@ type WireFrameRecord = ParsedWireMessage & {
bytes: number;
};
type ProviderSnapshotWireEntry = {
interface ProviderSnapshotWireEntry {
provider: string;
status: string | null;
modelCount: number;
modeCount: number;
bytes: number;
};
}
type WebSocketFrameEvent = {
interface WebSocketFrameEvent {
requestId: string;
response: {
opcode: number;
payloadData: string;
};
};
}
type WireSummary = {
interface WireSummary {
totalFrames: number;
totalBytes: number;
byDirection: Record<WireDirection, { frames: number; bytes: number }>;
@@ -84,7 +84,7 @@ type WireSummary = {
copiedFiles: number | null;
copiedBytes: number | null;
};
};
}
class WireMonitor {
private phase: WirePhase = "startup";

View File

@@ -17,7 +17,7 @@ const STRESS_TIMEOUT_MS = 15_000;
const RUN_MANUAL_TERMINAL_PERF = process.env.PASEO_TERMINAL_PERF_E2E === "1";
const terminalPerfDescribe = RUN_MANUAL_TERMINAL_PERF ? test.describe : test.describe.skip;
type DaemonEchoReport = {
interface DaemonEchoReport {
inputTextLength: number;
inputFrameCount: number;
outputEventCount: number;
@@ -25,7 +25,7 @@ type DaemonEchoReport = {
sendToOutputMs: LatencyStats;
firstSendAt: number;
lastOutputAt: number;
};
}
terminalPerfDescribe("Terminal keystroke stress", () => {
let harness: TerminalE2EHarness;

View File

@@ -19,7 +19,7 @@ function getServerId(): string {
return serverId;
}
type WorkspaceScriptStarter = {
interface WorkspaceScriptStarter {
startWorkspaceScript(
workspaceId: string,
scriptName: string,
@@ -29,7 +29,7 @@ type WorkspaceScriptStarter = {
terminalId: string | null;
error: string | null;
}>;
};
}
/** Click the sidebar row for a workspace (by ID) and wait for navigation. */
async function navigateToWorkspaceViaSidebar(

View File

@@ -98,11 +98,11 @@ import { prepareWorkspaceTab } from "@/utils/workspace-navigation";
polyfillCrypto();
export type HostRuntimeBootstrapState = {
export interface HostRuntimeBootstrapState {
phase: "starting-daemon" | "connecting" | "online" | "error";
error: string | null;
retry: () => void;
};
}
function getRouteParamValue(value: string | string[] | undefined): string | undefined {
if (typeof value === "string") {

View File

@@ -10,12 +10,12 @@ import {
parseDataUrl,
} from "@/attachments/utils";
type StoredBlobRecord = {
interface StoredBlobRecord {
id: string;
blob: Blob;
createdAt: number;
fileName: string | null;
};
}
const DB_NAME = "paseo-attachment-bytes";
const STORE_NAME = "attachments";

View File

@@ -51,14 +51,14 @@ import { isWeb as platformIsWeb } from "@/constants/platform";
import { useToast } from "@/contexts/toast-context";
import { toErrorMessage } from "@/utils/error-messages";
type StatusOption = {
interface StatusOption {
id: string;
label: string;
};
}
type StatusSelector = "provider" | "mode" | "model" | "thinking" | `feature-${string}`;
type ControlledAgentStatusBarProps = {
interface ControlledAgentStatusBarProps {
provider: string;
providerOptions?: StatusOption[];
selectedProviderId?: string;
@@ -84,7 +84,7 @@ type ControlledAgentStatusBarProps = {
onSetFeature?: (featureId: string, value: unknown) => void;
onDropdownClose?: () => void;
onModelSelectorOpen?: () => void;
};
}
export interface DraftAgentStatusBarProps {
providerDefinitions: AgentProviderDefinition[];

View File

@@ -11,37 +11,37 @@ import {
} from "./stream-strategy";
import { resolveStreamRenderStrategy } from "./stream-strategy-resolver";
export type StreamRenderSegments = {
export interface StreamRenderSegments {
historyVirtualized: StreamItem[];
historyMounted: StreamItem[];
liveHead: StreamItem[];
};
}
export type StreamHistoryBoundary = {
export interface StreamHistoryBoundary {
hasVirtualizedHistory: boolean;
hasMountedHistory: boolean;
hasLiveHead: boolean;
historyToHeadGap: number;
};
}
export type StreamRenderAuxiliary = {
export interface StreamRenderAuxiliary {
pendingPermissions: ReactNode;
workingIndicator: ReactNode;
};
}
export type AgentStreamRenderModel = {
export interface AgentStreamRenderModel {
history: StreamItem[];
segments: StreamRenderSegments;
boundary: StreamHistoryBoundary;
auxiliary: StreamRenderAuxiliary;
};
}
export type BuildAgentStreamRenderModelInput = {
export interface BuildAgentStreamRenderModelInput {
tail: StreamItem[];
head: StreamItem[];
platform: "web" | "native";
isMobileBreakpoint: boolean;
};
}
const EMPTY_STREAM_ITEMS: StreamItem[] = [];
const EMPTY_AUXILIARY: StreamRenderAuxiliary = {

View File

@@ -31,15 +31,15 @@ export function getWebMountedRecentStreamItems(): number {
return override ?? DEFAULT_WEB_MOUNTED_RECENT_STREAM_ITEMS;
}
export type IndexedStreamItem = {
export interface IndexedStreamItem {
item: StreamItem;
index: number;
};
}
export type WebVirtualizedHistoryWindow = {
export interface WebVirtualizedHistoryWindow {
virtualizedEntries: IndexedStreamItem[];
mountedEntries: IndexedStreamItem[];
};
}
export function estimateStreamItemHeight(item: StreamItem): number {
switch (item.kind) {

View File

@@ -14,12 +14,12 @@ function agentKey(agent: Pick<AggregatedAgent, "serverId" | "id">): string {
return `${agent.serverId}:${agent.id}`;
}
type CommandCenterRowProps = {
interface CommandCenterRowProps {
active: boolean;
children: ReactNode;
onPress: () => void;
registerRow: (el: View | null) => void;
};
}
const CommandCenterRow = memo(function CommandCenterRow({
active,

View File

@@ -71,11 +71,11 @@ import { AttachmentLightbox } from "@/components/attachment-lightbox";
import { openExternalUrl } from "@/utils/open-external-url";
import { useIsDictationReady } from "@/hooks/use-is-dictation-ready";
type QueuedMessage = {
interface QueuedMessage {
id: string;
text: string;
attachments: ComposerAttachment[];
};
}
type AttachmentListUpdater =
| ComposerAttachment[]

View File

@@ -3,10 +3,10 @@ import Svg, { Circle } from "react-native-svg";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
type ContextWindowMeterProps = {
interface ContextWindowMeterProps {
maxTokens: number;
usedTokens: number;
};
}
const SVG_SIZE = 16;
const CENTER = SVG_SIZE / 2;

View File

@@ -8,12 +8,12 @@ import { useSessionStore } from "@/stores/session-store";
import { resolveAppVersion } from "@/utils/app-version";
import { buildSettingsHostRoute } from "@/utils/host-routes";
type DaemonVersionMismatch = {
interface DaemonVersionMismatch {
serverId: string;
label: string;
appVersion: string;
daemonVersion: string;
};
}
function useDaemonVersionMismatches(): DaemonVersionMismatch[] {
const hosts = useHosts();

View File

@@ -7,10 +7,10 @@ import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { DraggableList } from "./draggable-list.web";
type DndContextProps = {
interface DndContextProps {
onDragStart?: (event: { active: { id: string } }) => void;
onDragCancel?: () => void;
};
}
let latestDndContextProps: DndContextProps | null = null;

View File

@@ -152,7 +152,7 @@ type WebTextInputKeyPressEvent = NativeSyntheticEvent<
}
>;
type TextAreaHandle = {
interface TextAreaHandle {
scrollHeight?: number;
clientHeight?: number;
offsetHeight?: number;
@@ -163,7 +163,7 @@ type TextAreaHandle = {
height?: string;
overflowY?: string;
} & Record<string, unknown>;
};
}
function logWebStickyBottom(_event: string, _details: Record<string, unknown>): void {
// Intentionally disabled: this path is too noisy during voice debugging.

View File

@@ -132,7 +132,7 @@ const MARKDOWN_ALLOWED_IMAGE_HANDLERS = [
] as const;
const MARKDOWN_TOP_LEVEL_MAX_EXCEEDED_ITEM = <Text key="dotdotdot">...</Text>;
type MarkdownWithStableRendererProps = {
interface MarkdownWithStableRendererProps {
children: ReactNode;
style: ReturnType<typeof createMarkdownStyles>;
rules: RenderRules;
@@ -140,7 +140,7 @@ type MarkdownWithStableRendererProps = {
onLinkPress: (url: string) => boolean;
allowedImageHandlers: readonly string[];
topLevelMaxExceededItem: ReactNode;
};
}
const MarkdownWithStableRenderer = Markdown as ComponentType<MarkdownWithStableRendererProps>;
const WEB_TOOLCALL_SHIMMER_KEYFRAME_CSS = `

View File

@@ -45,13 +45,13 @@ vi.mock("@react-native-async-storage/async-storage", () => ({
const SERVER_ID = "sidebar-render-count";
type RenderCounts = {
interface RenderCounts {
frame: number;
headers: Record<string, number>;
rows: Record<string, number>;
projectSelection: Record<string, number>;
rowSelection: Record<string, number>;
};
}
const runningScript: WorkspaceScriptPayload = {
scriptName: "web",

View File

@@ -7,10 +7,10 @@ import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { SortableInlineList } from "./sortable-inline-list.web";
type DndContextProps = {
interface DndContextProps {
onDragStart?: (event: { active: { id: string } }) => void;
onDragCancel?: () => void;
};
}
let latestDndContextProps: DndContextProps | null = null;

View File

@@ -13,9 +13,9 @@ import { estimateStreamItemHeight } from "./agent-stream-web-virtualization";
import type { StreamRenderInput, StreamStrategy, StreamViewportHandle } from "./stream-strategy";
import { createStreamStrategy } from "./stream-strategy";
type CreateWebStreamStrategyInput = {
interface CreateWebStreamStrategyInput {
isMobileBreakpoint: boolean;
};
}
type ScrollBehaviorLike = "auto" | "smooth";

View File

@@ -21,36 +21,36 @@ export type BottomAnchorTransportBehavior = Readonly<{
verificationRetryMode: "rescroll" | "recheck";
}>;
export type StreamViewportMetrics = {
export interface StreamViewportMetrics {
contentHeight: number;
viewportHeight: number;
};
}
export type StreamNearBottomInput = StreamViewportMetrics & {
offsetY: number;
threshold: number;
};
export type StreamEdgeSlotProps = {
export interface StreamEdgeSlotProps {
ListHeaderComponent?: ReactElement | ComponentType<any> | null;
ListHeaderComponentStyle?: StyleProp<ViewStyle>;
ListFooterComponent?: ReactElement | ComponentType<any> | null;
ListFooterComponentStyle?: StyleProp<ViewStyle>;
};
}
export type StreamViewportHandle = {
export interface StreamViewportHandle {
scrollToBottom: (reason?: BottomAnchorLocalRequest["reason"]) => void;
prepareForViewportChange: () => void;
};
}
export type StreamSegmentRenderers = {
export interface StreamSegmentRenderers {
renderHistoryVirtualizedRow: (item: StreamItem, index: number, items: StreamItem[]) => ReactNode;
renderHistoryMountedRow: (item: StreamItem, index: number, items: StreamItem[]) => ReactNode;
renderLiveHeadRow: (item: StreamItem, index: number, items: StreamItem[]) => ReactNode;
renderLiveAuxiliary: () => ReactNode;
};
}
export type StreamRenderInput = {
export interface StreamRenderInput {
agentId: string;
segments: StreamRenderSegments;
boundary: StreamHistoryBoundary;
@@ -64,12 +64,12 @@ export type StreamRenderInput = {
listStyle: StyleProp<ViewStyle>;
baseListContentContainerStyle: StyleProp<ViewStyle>;
forwardListContentContainerStyle: StyleProp<ViewStyle>;
};
}
export type ResolveStreamRenderStrategyInput = {
export interface ResolveStreamRenderStrategyInput {
platform: string;
isMobileBreakpoint: boolean;
};
}
export interface StreamStrategy {
render: (input: StreamRenderInput) => ReactNode;
@@ -98,7 +98,7 @@ export interface StreamStrategy {
shouldUseVirtualizedList: () => boolean;
}
type StreamStrategyConfig = {
interface StreamStrategyConfig {
render: StreamStrategy["render"];
orderTailReverse: boolean;
orderHeadReverse: boolean;
@@ -114,7 +114,7 @@ type StreamStrategyConfig = {
useVirtualizedList: boolean;
isNearBottom: (input: StreamNearBottomInput) => boolean;
getBottomOffset: (metrics: StreamViewportMetrics) => number;
};
}
const NATIVE_SETTLING_VERIFICATION_DELAY_FRAMES = 4;

View File

@@ -35,11 +35,11 @@ const SCROLLBAR_HANDLE_SCROLL_VISIBILITY_MS = 1_200;
const SCROLLBAR_HANDLE_SCROLL_ACTIVE_MS = 110;
const WEBKIT_SCROLLBAR_STYLE_ID = "terminal-emulator-webkit-scrollbar-style";
type ViewportMetrics = {
interface ViewportMetrics {
offset: number;
viewportSize: number;
contentSize: number;
};
}
function buildXtermThemeKey(theme: ITheme): string {
const values: Array<string> = [

View File

@@ -51,11 +51,11 @@ const KEY_BUTTONS: Array<{ id: string; label: string; key: string }> = [
{ id: "c", label: "C", key: "c" },
];
type ModifierState = {
interface ModifierState {
ctrl: boolean;
shift: boolean;
alt: boolean;
};
}
type PendingTerminalInput =
| {

View File

@@ -15,15 +15,15 @@ import {
export type ToastVariant = "default" | "success" | "error";
export type ToastShowOptions = {
export interface ToastShowOptions {
icon?: ReactNode;
variant?: ToastVariant;
durationMs?: number;
nativeAndroid?: boolean;
testID?: string;
};
}
export type ToastState = {
export interface ToastState {
id: number;
content: ReactNode;
nativeMessage: string | null;
@@ -31,13 +31,13 @@ export type ToastState = {
variant: ToastVariant;
durationMs: number;
testID?: string;
};
}
export type ToastApi = {
export interface ToastApi {
show: (content: ReactNode, options?: ToastShowOptions) => void;
copied: (label?: string) => void;
error: (message: string) => void;
};
}
type ToastViewportPlacement = "app-shell" | "panel";

View File

@@ -18,14 +18,14 @@ import { ToolCallDetailsContent } from "./tool-call-details";
// ----- Types -----
export type ToolCallSheetData = {
export interface ToolCallSheetData {
toolName: string;
displayName: string;
summary?: string;
detail?: ToolCallDetail;
errorText?: string;
showLoadingSkeleton?: boolean;
};
}
interface ToolCallSheetContextValue {
openToolCall: (data: ToolCallSheetData) => void;

View File

@@ -53,13 +53,13 @@ interface Rect {
height: number;
}
type ContextMenuContextValue = {
interface ContextMenuContextValue {
open: boolean;
setOpen: (open: boolean) => void;
triggerRef: React.RefObject<View | null>;
anchorRect: Rect | null;
setAnchorRect: (rect: Rect | null) => void;
};
}
const ContextMenuContext = createContext<ContextMenuContextValue | null>(null);
@@ -235,7 +235,11 @@ export function ContextMenu({
return <ContextMenuContext.Provider value={value}>{children}</ContextMenuContext.Provider>;
}
type TriggerState = { pressed: boolean; hovered: boolean; open: boolean };
interface TriggerState {
pressed: boolean;
hovered: boolean;
open: boolean;
}
type TriggerStyleProp = StyleProp<ViewStyle> | ((state: TriggerState) => StyleProp<ViewStyle>);
export function ContextMenuTrigger({

View File

@@ -43,13 +43,13 @@ interface Rect {
height: number;
}
type DropdownMenuContextValue = {
interface DropdownMenuContextValue {
open: boolean;
setOpen: (open: boolean) => void;
selectItem: (onSelect: (() => void) | undefined, closeOnSelect: boolean) => void;
flushPendingSelect: () => void;
triggerRef: React.RefObject<View | null>;
};
}
const DropdownMenuContext = createContext<DropdownMenuContextValue | null>(null);
@@ -224,7 +224,11 @@ export function DropdownMenu({
return <DropdownMenuContext.Provider value={value}>{children}</DropdownMenuContext.Provider>;
}
type TriggerState = { pressed: boolean; hovered: boolean; open: boolean };
interface TriggerState {
pressed: boolean;
hovered: boolean;
open: boolean;
}
type TriggerStyleProp = StyleProp<ViewStyle> | ((state: TriggerState) => StyleProp<ViewStyle>);
interface DropdownMenuTriggerProps extends Omit<PressableProps, "style" | "children"> {

View File

@@ -7,15 +7,15 @@ type SegmentedControlSize = "sm" | "md";
type SegmentedControlIconRenderer = (props: { color: string; size: number }) => ReactNode;
export type SegmentedControlOption<T extends string> = {
export interface SegmentedControlOption<T extends string> {
value: T;
label: string;
icon?: SegmentedControlIconRenderer;
disabled?: boolean;
testID?: string;
};
}
type SegmentedControlProps<T extends string> = {
interface SegmentedControlProps<T extends string> {
options: SegmentedControlOption<T>[];
value: T;
onValueChange: (value: T) => void;
@@ -23,7 +23,7 @@ type SegmentedControlProps<T extends string> = {
hideLabels?: boolean;
style?: StyleProp<ViewStyle>;
testID?: string;
};
}
export function SegmentedControl<T extends string>({
options,

View File

@@ -41,14 +41,14 @@ interface Rect {
height: number;
}
type TooltipContextValue = {
interface TooltipContextValue {
open: boolean;
setOpen: (open: boolean) => void;
triggerRef: React.RefObject<View | null>;
enabled: boolean;
openOnPress: boolean;
delayDuration: number;
};
}
const TooltipContext = createContext<TooltipContextValue | null>(null);

View File

@@ -3,16 +3,16 @@ import type { BottomAnchorTransportBehavior } from "./agent-stream-render-strate
export type BottomAnchorMode = "sticky-bottom" | "detached";
export type BottomAnchorRouteRequest = {
export interface BottomAnchorRouteRequest {
reason: "initial-entry" | "resume";
agentId: string;
requestKey: string;
};
}
export type BottomAnchorLocalRequest = {
export interface BottomAnchorLocalRequest {
reason: "jump-to-bottom" | "message-sent";
agentId: string;
};
}
export type BottomAnchorBlockedReason =
| "waiting_for_history_readiness"
@@ -24,14 +24,14 @@ type BottomAnchorRequestReason =
| BottomAnchorRouteRequest["reason"]
| BottomAnchorLocalRequest["reason"];
type BottomAnchorRequest = {
interface BottomAnchorRequest {
id: number;
agentId: string;
reason: BottomAnchorRequestReason;
requestKey: string;
};
}
type ControllerMeasurementState = {
interface ControllerMeasurementState {
containerKey: string;
viewportWidth: number;
viewportHeight: number;
@@ -39,23 +39,23 @@ type ControllerMeasurementState = {
offsetY: number;
viewportMeasuredForKey: string | null;
contentMeasuredForKey: string | null;
};
}
type AttemptContext = {
interface AttemptContext {
requestId: number | null;
retries: number;
confirmationPasses?: number;
startedContentHeight?: number;
startedOffsetY?: number;
startedViewportHeight?: number;
};
}
type ScheduledFrameHandle = {
interface ScheduledFrameHandle {
cancelled: boolean;
rafId: number | null;
remainingFrames: number;
callback: () => void;
};
}
type BottomAnchorEvent =
| "request_created"
@@ -69,7 +69,7 @@ type BottomAnchorEvent =
| "verification_scheduled"
| "blocked_reason_changed";
type BottomAnchorControllerDriver = {
interface BottomAnchorControllerDriver {
destroy: () => void;
getSnapshot: () => {
mode: BottomAnchorMode;
@@ -99,9 +99,9 @@ type BottomAnchorControllerDriver = {
}) => void;
notifyAuthoritativeHistoryMaybeChanged: () => void;
reevaluate: (animated?: boolean) => void;
};
}
type CreateBottomAnchorControllerDriverInput = {
interface CreateBottomAnchorControllerDriverInput {
getAgentId: () => string;
getIsAuthoritativeHistoryReady: () => boolean;
getRenderStrategy: () => string;
@@ -116,7 +116,7 @@ type CreateBottomAnchorControllerDriverInput = {
delayFrames?: number;
}) => unknown;
cancelFrame: (handle: unknown) => void;
};
}
const MAX_VERIFICATION_RETRIES = 3;
const WEB_PARTIAL_VIRTUALIZED_CONFIRMATION_DELAY_FRAMES = 1;

View File

@@ -4,20 +4,20 @@ function clamp(value: number, min: number, max: number): number {
return Math.min(max, Math.max(min, value));
}
export type VerticalScrollbarGeometryInput = {
export interface VerticalScrollbarGeometryInput {
viewportSize: number;
contentSize: number;
offset: number;
minHandleSize?: number;
};
}
export type VerticalScrollbarGeometry = {
export interface VerticalScrollbarGeometry {
isVisible: boolean;
maxScrollOffset: number;
handleSize: number;
handleOffset: number;
maxHandleOffset: number;
};
}
export function computeVerticalScrollbarGeometry(
input: VerticalScrollbarGeometryInput,
@@ -55,12 +55,12 @@ export function computeVerticalScrollbarGeometry(
};
}
export type ScrollOffsetFromDragDeltaInput = {
export interface ScrollOffsetFromDragDeltaInput {
startOffset: number;
dragDelta: number;
maxScrollOffset: number;
maxHandleOffset: number;
};
}
export function computeScrollOffsetFromDragDelta(input: ScrollOffsetFromDragDeltaInput): number {
if (input.maxScrollOffset <= 0 || input.maxHandleOffset <= 0) {

View File

@@ -37,11 +37,11 @@ function clamp(value: number, min: number, max: number): number {
return Math.min(max, Math.max(min, value));
}
export type ScrollbarMetrics = {
export interface ScrollbarMetrics {
offset: number;
viewportSize: number;
contentSize: number;
};
}
function areMetricsEqual(a: ScrollbarMetrics, b: ScrollbarMetrics): boolean {
return (
@@ -107,12 +107,12 @@ export function useWebDesktopScrollbarMetrics() {
};
}
type WebDesktopScrollbarOverlayProps = {
interface WebDesktopScrollbarOverlayProps {
enabled: boolean;
metrics: ScrollbarMetrics;
onScrollToOffset: (offset: number) => void;
inverted?: boolean;
};
}
export function WebDesktopScrollbarOverlay({
enabled,

View File

@@ -16,14 +16,14 @@ import { PaseoLogo } from "@/components/icons/paseo-logo";
import { openExternalUrl } from "@/utils/open-external-url";
import { isWeb, isNative } from "@/constants/platform";
type WelcomeAction = {
interface WelcomeAction {
key: "scan-qr" | "direct-connection" | "paste-pairing-link";
label: string;
testID: string;
primary: boolean;
icon: typeof QrCode;
onPress: () => void;
};
}
const styles = StyleSheet.create((theme) => ({
root: {

View File

@@ -25,11 +25,11 @@ const AGENT_STREAM_REDUCER_FLUSH_DELAY_MS = 16 * 3;
// Shared cursor type
// ---------------------------------------------------------------------------
export type TimelineCursor = {
export interface TimelineCursor {
epoch: string;
startSeq: number;
endSeq: number;
};
}
// ---------------------------------------------------------------------------
// Side-effect discriminated unions
@@ -39,10 +39,10 @@ export type TimelineReducerSideEffect =
| { type: "catch_up"; cursor: { epoch: string; endSeq: number } }
| { type: "flush_pending_updates" };
export type AgentStreamReducerSideEffect = {
export interface AgentStreamReducerSideEffect {
type: "catch_up";
cursor: { epoch: string; endSeq: number };
};
}
// ---------------------------------------------------------------------------
// processTimelineResponse
@@ -51,13 +51,13 @@ export type AgentStreamReducerSideEffect = {
type TimelineDirection = "tail" | "before" | "after";
type InitRequestDirection = "tail" | "after";
type TimelineResponseEntry = {
interface TimelineResponseEntry {
seqStart: number;
seqEnd: number;
provider: string;
item: Record<string, unknown>;
timestamp: string;
};
}
export interface ProcessTimelineResponseInput {
payload: {
@@ -337,37 +337,37 @@ export interface ProcessAgentStreamEventOutput {
sideEffects: AgentStreamReducerSideEffect[];
}
export type AgentStreamReducerEvent = {
export interface AgentStreamReducerEvent {
event: AgentStreamEventPayload;
seq: number | undefined;
epoch: string | undefined;
timestamp: Date;
};
}
export type AgentStreamReducerAgentSnapshot = {
export interface AgentStreamReducerAgentSnapshot {
status: AgentLifecycleStatus;
updatedAt: Date;
lastActivityAt: Date;
};
}
export type ProcessAgentStreamEventsInput = {
export interface ProcessAgentStreamEventsInput {
events: AgentStreamReducerEvent[];
currentTail: StreamItem[];
currentHead: StreamItem[];
currentCursor: TimelineCursor | undefined;
currentAgent: AgentStreamReducerAgentSnapshot | null;
};
}
export type AgentStreamReducerSnapshot = Omit<ProcessAgentStreamEventsInput, "events">;
export type AgentStreamReducerQueue = {
export interface AgentStreamReducerQueue {
enqueue: (agentId: string, event: AgentStreamReducerEvent) => void;
flush: () => void;
flushAgent: (agentId: string) => void;
dispose: (options?: { flush?: boolean }) => void;
};
}
export type CreateAgentStreamReducerQueueInput = {
export interface CreateAgentStreamReducerQueueInput {
getSnapshot: (agentId: string) => AgentStreamReducerSnapshot;
commit: (
agentId: string,
@@ -377,7 +377,7 @@ export type CreateAgentStreamReducerQueueInput = {
handleSideEffects: (agentId: string, sideEffects: AgentStreamReducerSideEffect[]) => void;
scheduleFlush: (callback: () => void) => number;
cancelFlush: (id: number) => void;
};
}
function applyAgentPatch(
currentAgent: AgentStreamReducerAgentSnapshot | null,
@@ -632,12 +632,12 @@ export function createAgentStreamReducerQueue(
};
}
type StreamStatePatch = {
interface StreamStatePatch {
tail?: StreamItem[];
head?: StreamItem[];
};
}
export type CreateSessionAgentStreamReducerQueueInput = {
export interface CreateSessionAgentStreamReducerQueueInput {
serverId: string;
setAgentStreamState: (serverId: string, agentId: string, state: StreamStatePatch) => void;
setAgentTimelineCursor: (
@@ -646,7 +646,7 @@ export type CreateSessionAgentStreamReducerQueueInput = {
) => void;
setAgents: (serverId: string, state: (prev: Map<string, Agent>) => Map<string, Agent>) => void;
requestCanonicalCatchUp: (agentId: string, cursor: { epoch: string; endSeq: number }) => void;
};
}
function scheduleAgentStreamReducerFlush(callback: () => void): number {
return setTimeout(callback, AGENT_STREAM_REDUCER_FLUSH_DELAY_MS) as unknown as number;

View File

@@ -3,7 +3,7 @@ import { invokeDesktopCommand } from "@/desktop/electron/invoke";
export type DesktopDaemonState = "starting" | "running" | "stopped" | "errored";
export type DesktopDaemonStatus = {
export interface DesktopDaemonStatus {
serverId: string;
status: DesktopDaemonState;
listen: string | null;
@@ -13,25 +13,25 @@ export type DesktopDaemonStatus = {
version: string | null;
desktopManaged: boolean;
error: string | null;
};
}
export type DesktopDaemonLogs = {
export interface DesktopDaemonLogs {
logPath: string;
contents: string;
};
}
export type DesktopPairingOffer = {
export interface DesktopPairingOffer {
relayEnabled: boolean;
url: string | null;
qr: string | null;
};
}
export type LocalTransportTarget = {
export interface LocalTransportTarget {
transportType: "socket" | "pipe";
transportPath: string;
};
}
type LocalTransportEventPayload = {
interface LocalTransportEventPayload {
sessionId: string;
kind: "open" | "message" | "close" | "error";
text?: string | null;
@@ -39,7 +39,7 @@ type LocalTransportEventPayload = {
code?: number | null;
reason?: string | null;
error?: string | null;
};
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;

View File

@@ -2,9 +2,9 @@ import { getDesktopHost } from "@/desktop/host";
export type DesktopEventUnlisten = () => void;
type EventEnvelope = {
interface EventEnvelope {
payload?: unknown;
};
}
export async function listenToDesktopEvent<TPayload>(
event: string,

View File

@@ -2,12 +2,12 @@ import { afterEach, describe, expect, it, vi } from "vitest";
type MockPlatform = "web" | "ios" | "android";
type GlobalSnapshot = {
interface GlobalSnapshot {
Notification: unknown;
navigatorDescriptor?: PropertyDescriptor;
windowDescriptor?: PropertyDescriptor;
paseoDesktop: unknown;
};
}
const originalGlobals: GlobalSnapshot = {
Notification: (globalThis as { Notification?: unknown }).Notification,

View File

@@ -22,27 +22,27 @@ export interface DesktopPermissionSnapshot {
microphone: DesktopPermissionStatus;
}
type NotificationConstructorLike = {
interface NotificationConstructorLike {
permission?: string;
requestPermission?: () => Promise<string>;
};
}
type MediaStreamTrackLike = {
interface MediaStreamTrackLike {
stop?: () => void;
};
}
type MediaStreamLike = {
interface MediaStreamLike {
getTracks?: () => MediaStreamTrackLike[];
};
}
type NavigatorLike = {
interface NavigatorLike {
mediaDevices?: {
getUserMedia?: (constraints: { audio: boolean }) => Promise<MediaStreamLike>;
};
permissions?: {
query?: (descriptor: { name: string }) => Promise<{ state?: string }>;
};
};
}
export function shouldShowDesktopPermissionSection(): boolean {
return isWeb && getDesktopHost() !== null;

View File

@@ -2,9 +2,20 @@ import { describe, expect, it } from "vitest";
import { DictationStreamSender } from "@/dictation/dictation-stream-sender";
type FakeFinish = { dictationId: string; finalSeq: number };
type FakeStart = { dictationId: string; format: string };
type FakeChunk = { dictationId: string; seq: number; audio: string; format: string };
interface FakeFinish {
dictationId: string;
finalSeq: number;
}
interface FakeStart {
dictationId: string;
format: string;
}
interface FakeChunk {
dictationId: string;
seq: number;
audio: string;
format: string;
}
class FakeDaemonClient {
isConnected = true;

View File

@@ -1,13 +1,16 @@
import { generateMessageId } from "@/types/stream";
import type { DaemonClient } from "@server/client/daemon-client";
export type DictationStreamSenderParams = {
export interface DictationStreamSenderParams {
client: DaemonClient | null;
format: string;
createDictationId?: () => string;
};
}
type DictationFinishResult = { dictationId: string; text: string };
interface DictationFinishResult {
dictationId: string;
text: string;
}
/**
* Small, non-React state machine for dictation streaming.

View File

@@ -55,16 +55,16 @@ interface FormState {
workingDir: string;
}
type UseAgentFormStateOptions = {
interface UseAgentFormStateOptions {
initialServerId?: string | null;
initialValues?: FormInitialValues;
isVisible?: boolean;
isCreateFlow?: boolean;
isTargetDaemonReady?: boolean;
onlineServerIds?: string[];
};
}
export type UseAgentFormStateResult = {
export interface UseAgentFormStateResult {
selectedServerId: string | null;
setSelectedServerId: (value: string | null) => void;
setSelectedServerIdFromUser: (value: string | null) => void;
@@ -95,7 +95,7 @@ export type UseAgentFormStateResult = {
setProviderAndModelFromUser: (provider: AgentProvider, modelId: string) => void;
workingDirIsEmpty: boolean;
persistFormPreferences: () => Promise<void>;
};
}
function normalizeSelectedModelId(modelId: string | null | undefined): string {
const normalized = typeof modelId === "string" ? modelId.trim() : "";

View File

@@ -26,10 +26,10 @@ export interface AgentHistoryResult {
loadMore: () => void;
}
type AgentHistoryPage = {
interface AgentHistoryPage {
agents: AggregatedAgent[];
pageInfo: FetchAgentHistoryPageInfo;
};
}
async function fetchAgentHistoryPage(input: {
client: DaemonClient;

View File

@@ -16,25 +16,25 @@ type AttachmentUpdater =
| ComposerAttachment[]
| ((prev: ComposerAttachment[]) => ComposerAttachment[]);
type AgentInputDraftComposerOptions = {
interface AgentInputDraftComposerOptions {
initialServerId: string | null;
initialValues?: CreateAgentInitialValues;
isVisible?: boolean;
onlineServerIds?: string[];
lockedWorkingDir?: string;
};
}
type DraftKeyContext = {
interface DraftKeyContext {
selectedServerId: string | null;
};
}
type DraftKeyInput = string | ((context: DraftKeyContext) => string);
type UseAgentInputDraftInput = {
interface UseAgentInputDraftInput {
draftKey: DraftKeyInput;
initialCwd?: string;
composer?: AgentInputDraftComposerOptions;
};
}
type DraftComposerState = UseAgentFormStateResult & {
workingDir: string;

View File

@@ -4,13 +4,13 @@ import { JSDOM } from "jsdom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { useClientActivity } from "./use-client-activity";
type HeartbeatPayload = {
interface HeartbeatPayload {
deviceType: "web" | "mobile";
focusedAgentId: string | null;
lastActivityAt: string;
appVisible: boolean;
appVisibilityChangedAt?: string;
};
}
const { platformState, getDesktopSystemIdleTimeMs } = vi.hoisted(() => ({
platformState: {

View File

@@ -51,14 +51,14 @@ function sortAgents(left: AggregatedAgent, right: AggregatedAgent): number {
return right.lastActivityAt.getTime() - left.lastActivityAt.getTime();
}
type CommandCenterActionDefinition = {
interface CommandCenterActionDefinition {
id: string;
title: string;
icon?: "plus" | "settings";
actionId?: string;
keywords: string[];
routeKind: "settings" | "none";
};
}
const COMMAND_CENTER_ACTIONS: readonly CommandCenterActionDefinition[] = [
{
@@ -87,14 +87,14 @@ function matchesActionQuery(query: string, action: CommandCenterActionDefinition
return action.keywords.some((keyword) => keyword.includes(normalized));
}
export type CommandCenterActionItem = {
export interface CommandCenterActionItem {
kind: "action";
id: string;
title: string;
icon?: "plus" | "settings";
route?: Href;
shortcutKeys?: ShortcutKey[][];
};
}
export type CommandCenterItem =
| {

View File

@@ -1,10 +1,10 @@
export type DictationAudioSourceConfig = {
export interface DictationAudioSourceConfig {
onPcmSegment: (pcm16Base64: string) => void;
onError?: (error: Error) => void;
};
}
export type DictationAudioSource = {
export interface DictationAudioSource {
start: () => Promise<void>;
stop: () => Promise<void>;
volume: number;
};
}

View File

@@ -82,13 +82,13 @@ const int16ToBase64 = (pcm: Int16Array): string => {
return btoa(binary);
};
type RecorderRefs = {
interface RecorderRefs {
recorder: MediaRecorder | null;
audioChunks: Blob[];
stoppedPromise: Promise<Blob> | null;
stoppedResolve: ((blob: Blob) => void) | null;
stoppedReject: ((error: unknown) => void) | null;
};
}
export function useDictationAudioSource(config: DictationAudioSourceConfig): DictationAudioSource {
const [volume, setVolume] = useState(0);

View File

@@ -1,6 +1,6 @@
export type DictationStatus = "idle" | "recording" | "uploading" | "failed";
export type UseDictationOptions = {
export interface UseDictationOptions {
client: import("@server/client/daemon-client").DaemonClient | null;
onTranscript: (text: string, meta: { requestId: string }) => void;
onPartialTranscript?: (text: string, meta: { requestId: string }) => void;
@@ -10,9 +10,9 @@ export type UseDictationOptions = {
canConfirm?: () => boolean;
autoStopWhenHidden?: { isVisible: boolean };
enableDuration?: boolean;
};
}
export type UseDictationResult = {
export interface UseDictationResult {
isRecording: boolean;
isProcessing: boolean;
partialTranscript: string;
@@ -26,7 +26,7 @@ export type UseDictationResult = {
retryFailedDictation: () => Promise<void>;
discardFailedDictation: () => void;
reset: () => void;
};
}
export const DURATION_TICK_MS = 1000;
export const PCM_DICTATION_FORMAT = "audio/pcm;rate=16000;bits=16";

View File

@@ -11,12 +11,12 @@ import type { AgentAttachment } from "@server/shared/messages";
const EMPTY_STREAM_ITEMS: StreamItem[] = [];
type CreateAttempt = {
interface CreateAttempt {
clientMessageId: string;
text: string;
timestamp: Date;
images?: UserMessageImageAttachment[];
};
}
type DraftAgentMachineState =
| { tag: "draft"; errorMessage: string }
@@ -56,24 +56,24 @@ function reducer(
}
}
type CreateRequestResult<TCreateResult> = {
interface CreateRequestResult<TCreateResult> {
agentId: string | null;
result: TCreateResult;
};
}
type SubmitContext = {
interface SubmitContext {
text: string;
attachments: ComposerAttachment[];
cwd: string;
};
}
type CreateRequestContext = {
interface CreateRequestContext {
attempt: CreateAttempt;
text: string;
images?: UserMessageImageAttachment[];
attachments?: AgentAttachment[];
cwd: string;
};
}
interface UseDraftAgentCreateFlowOptions<TDraftAgent, TCreateResult> {
draftId: string;

View File

@@ -46,9 +46,9 @@ type DesktopDragDropPayload =
type: "leave";
};
type DesktopDragDropEvent = {
interface DesktopDragDropEvent {
payload: DesktopDragDropPayload;
};
}
function isImageFile(file: File): boolean {
return file.type.startsWith("image/");

View File

@@ -12,12 +12,12 @@ vi.mock("@/constants/platform", () => ({
isWeb: true,
}));
type RectInput = {
interface RectInput {
left: number;
right: number;
top: number;
bottom: number;
};
}
let root: Root | null = null;
let container: HTMLElement | null = null;

View File

@@ -6,14 +6,14 @@ import {
type KeyboardActionId,
} from "@/keyboard/keyboard-action-dispatcher";
type UseKeyboardActionHandlerInput = {
interface UseKeyboardActionHandlerInput {
handlerId: string;
actions: readonly KeyboardActionId[];
enabled: boolean;
priority: number;
isActive?: () => boolean;
handle: (action: KeyboardActionDefinition) => boolean;
};
}
export function useKeyboardActionHandler(input: UseKeyboardActionHandlerInput) {
useEffect(() => {

View File

@@ -11,20 +11,20 @@ import type { ProviderSnapshotEntry } from "@server/server/agent/agent-sdk-types
import { useSessionStore } from "@/stores/session-store";
import { providersSnapshotQueryKey, useProvidersSnapshot } from "./use-providers-snapshot";
type ProviderSnapshotUpdateMessage = {
interface ProviderSnapshotUpdateMessage {
type: "providers_snapshot_update";
payload: {
cwd: string;
entries: ProviderSnapshotEntry[];
generatedAt: string;
};
};
}
type ProviderSnapshotUpdateListener = (message: ProviderSnapshotUpdateMessage) => void;
type ProvidersSnapshot = {
interface ProvidersSnapshot {
entries: ProviderSnapshotEntry[];
generatedAt: string;
requestId: string;
};
}
type HookResult = ReturnType<typeof renderProvidersSnapshotHook>["result"];
const { mockClient, mockRuntime, snapshotUpdateListeners } = vi.hoisted(() => {

View File

@@ -58,14 +58,14 @@ export type KeyboardActionDefinition =
| { id: "worktree.new"; scope: KeyboardActionScope }
| { id: "worktree.archive"; scope: KeyboardActionScope };
export type KeyboardActionHandler = {
export interface KeyboardActionHandler {
handlerId: string;
actions: readonly KeyboardActionId[];
enabled: boolean;
priority: number;
isActive?: () => boolean;
handle: (action: KeyboardActionDefinition) => boolean;
};
}
type KeyboardActionRegistryEntry = KeyboardActionHandler & {
registeredAt: number;

View File

@@ -94,7 +94,7 @@ function expectNoShortcutResolution(input: {
expect(result.nextChordState).toEqual(initialChordState());
}
type MatchingShortcutCase = {
interface MatchingShortcutCase {
name: string;
event: Partial<KeyboardEvent>;
context?: Partial<KeyboardShortcutContext>;
@@ -102,22 +102,22 @@ type MatchingShortcutCase = {
payload?: unknown;
preventDefault?: boolean;
stopPropagation?: boolean;
};
}
type NonMatchingShortcutCase = {
interface NonMatchingShortcutCase {
name: string;
event: Partial<KeyboardEvent>;
context?: Partial<KeyboardShortcutContext>;
};
}
type HelpSectionCase = {
interface HelpSectionCase {
name: string;
context: {
isMac: boolean;
isDesktop: boolean;
};
expectedKeys: Record<string, string[]>;
};
}
describe("keyboard-shortcuts", () => {
const matchingCases: MatchingShortcutCase[] = [

View File

@@ -11,41 +11,41 @@ export type { KeyCombo } from "@/keyboard/shortcut-string";
// --- Public types ---
export type KeyboardShortcutContext = {
export interface KeyboardShortcutContext {
isMac: boolean;
isDesktop: boolean;
focusScope: KeyboardFocusScope;
commandCenterOpen: boolean;
};
}
export type KeyboardShortcutMatch = {
export interface KeyboardShortcutMatch {
action: KeyboardActionId;
payload: KeyboardShortcutPayload;
preventDefault: boolean;
stopPropagation: boolean;
};
}
export type KeyboardShortcutHelpRow = {
export interface KeyboardShortcutHelpRow {
id: string;
label: string;
keys: ShortcutKey[];
note?: string;
};
}
export type ShortcutSectionId = "navigation" | "tabs-panes" | "projects" | "panels" | "agent-input";
export type KeyboardShortcutHelpSection = {
export interface KeyboardShortcutHelpSection {
id: ShortcutSectionId;
title: string;
rows: KeyboardShortcutHelpRow[];
};
}
// --- Binding definition types ---
type KeyboardShortcutPlatformContext = {
interface KeyboardShortcutPlatformContext {
isMac: boolean;
isDesktop: boolean;
};
}
interface ShortcutWhen {
/** true = mac only, false = non-mac only */

View File

@@ -15,7 +15,7 @@ import type { PendingPermission } from "@/types/shared";
import type { StreamItem } from "@/types/stream";
import type { AgentPermissionRequest } from "@server/server/agent/agent-sdk-types";
type PanelTestTheme = {
interface PanelTestTheme {
colors: {
foreground: string;
foregroundMuted: string;
@@ -31,7 +31,7 @@ type PanelTestTheme = {
fontSize: Record<string, number>;
fontWeight: Record<string, string>;
iconSize: Record<string, number>;
};
}
type PanelTestStyles = Record<string, unknown>;
type PanelTestStyleFactory = (input: PanelTestTheme) => PanelTestStyles;

View File

@@ -55,7 +55,7 @@ export type HostRuntimeAgentDirectoryStatus =
| "error_before_first_success"
| "error_after_ready";
export type HostRuntimeSnapshot = {
export interface HostRuntimeSnapshot {
serverId: string;
activeConnectionId: string | null;
activeConnection: ActiveConnection | null;
@@ -68,7 +68,7 @@ export type HostRuntimeSnapshot = {
hasEverLoadedAgentDirectory: boolean;
probeByConnectionId: Map<string, ConnectionProbeState>;
clientGeneration: number;
};
}
type HostRuntimeSnapshotPatch = Partial<Omit<HostRuntimeSnapshot, "serverId" | "clientGeneration">>;
@@ -112,7 +112,7 @@ function hashForLog(value: string): string {
return `h_${Math.abs(hash).toString(16)}`;
}
export type HostRuntimeControllerDeps = {
export interface HostRuntimeControllerDeps {
createClient: (input: {
host: HostProfile;
connection: HostConnection;
@@ -125,15 +125,15 @@ export type HostRuntimeControllerDeps = {
hostname: string | null;
}>;
getClientId: () => Promise<string>;
};
}
export type HostRuntimeStartOptions = {
export interface HostRuntimeStartOptions {
autoProbe?: boolean;
initialConnection?: {
connectionId: string;
existingClient: DaemonClient;
};
};
}
const PROBE_TICK_MS = 2_000;
const PROBE_STEADY_MS = 10_000;

View File

@@ -1,9 +1,9 @@
import type { BottomAnchorRouteRequest } from "@/components/use-bottom-anchor-controller";
export type RouteBottomAnchorIntent = {
export interface RouteBottomAnchorIntent {
routeKey: string;
reason: BottomAnchorRouteRequest["reason"];
};
}
export function deriveRouteBottomAnchorIntent(input: {
cachedIntent: RouteBottomAnchorIntent | null;

View File

@@ -12,13 +12,13 @@ import { TitlebarDragRegion } from "@/components/desktop/titlebar-drag-region";
import { isWeb } from "@/constants/platform";
import { useWebScrollbarStyle } from "@/hooks/use-web-scrollbar-style";
type StartupSplashScreenProps = {
interface StartupSplashScreenProps {
bootstrapState?: {
phase: "starting-daemon" | "connecting" | "online" | "error";
error: string | null;
retry: () => void;
};
};
}
const GITHUB_ISSUE_URL = "https://github.com/getpaseo/paseo/issues/new";
const DOCS_URL = "https://paseo.sh/docs";

View File

@@ -5,7 +5,7 @@ import {
type WorkspaceTabLayoutResult,
} from "@/screens/workspace/workspace-tab-layout";
type UseWorkspaceTabLayoutInput = {
interface UseWorkspaceTabLayoutInput {
tabLabelLengths: number[];
viewportWidthOverride?: number | null;
metrics: {
@@ -19,11 +19,11 @@ type UseWorkspaceTabLayoutInput = {
estimatedCharWidth: number;
closeButtonWidth: number;
};
};
}
type UseWorkspaceTabLayoutResult = {
interface UseWorkspaceTabLayoutResult {
layout: WorkspaceTabLayoutResult;
};
}
export function useWorkspaceTabLayout(
input: UseWorkspaceTabLayoutInput,

View File

@@ -1,11 +1,11 @@
import type { DaemonClient } from "@server/client/daemon-client";
import type { WorkspaceTabDescriptor } from "@/screens/workspace/workspace-tabs-types";
export type BulkClosableTabGroups = {
export interface BulkClosableTabGroups {
agentTabs: Array<{ tabId: string; agentId: string }>;
terminalTabs: Array<{ tabId: string; terminalId: string }>;
otherTabs: Array<{ tabId: string }>;
};
}
interface CloseWorkspaceTabWithCleanupInput {
tabId: string;

View File

@@ -63,7 +63,7 @@ export interface WorkspaceDesktopTabRowItem {
isClosingTab: boolean;
}
type WorkspaceDesktopTabsRowProps = {
interface WorkspaceDesktopTabsRowProps {
paneId?: string;
isFocused?: boolean;
tabs: WorkspaceDesktopTabRowItem[];
@@ -90,7 +90,7 @@ type WorkspaceDesktopTabsRowProps = {
activeDragTabId?: string | null;
tabDropPreviewIndex?: number | null;
showPaneSplitActions?: boolean;
};
}
function getFallbackTabLabel(tab: WorkspaceTabDescriptor): string {
if (tab.target.kind === "draft") {

View File

@@ -31,7 +31,7 @@ const DRAFT_CAPABILITIES: AgentCapabilityFlags = {
supportsToolInvocations: false,
};
type WorkspaceDraftAgentTabProps = {
interface WorkspaceDraftAgentTabProps {
serverId: string;
workspaceId: string;
tabId: string;
@@ -39,7 +39,7 @@ type WorkspaceDraftAgentTabProps = {
isPaneFocused: boolean;
onCreated: (snapshot: AgentSnapshotPayload) => void;
onOpenWorkspaceFile: (input: { filePath: string }) => void;
};
}
export function WorkspaceDraftAgentTab({
serverId,

View File

@@ -129,11 +129,11 @@ const EMPTY_UI_TABS: WorkspaceTab[] = [];
const EMPTY_PINNED_AGENT_IDS = new Set<string>();
const EMPTY_SET = new Set<string>();
type WorkspaceScreenProps = {
interface WorkspaceScreenProps {
serverId: string;
workspaceId: string;
isRouteFocused?: boolean;
};
}
type WorkspaceScreenContentProps = WorkspaceScreenProps & {
isRouteFocused: boolean;
@@ -187,7 +187,7 @@ function getFallbackTabOptionDescription(tab: WorkspaceTabDescriptor): string {
return tab.target.path;
}
type MobileWorkspaceTabSwitcherProps = {
interface MobileWorkspaceTabSwitcherProps {
tabs: WorkspaceTabDescriptor[];
activeTabKey: string;
activeTab: WorkspaceTabDescriptor | null;
@@ -203,7 +203,7 @@ type MobileWorkspaceTabSwitcherProps = {
onCloseTabsAbove: (tabId: string) => Promise<void> | void;
onCloseTabsBelow: (tabId: string) => Promise<void> | void;
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
};
}
function MobileActiveTabTrigger({
activeTab,

View File

@@ -1,6 +1,6 @@
export type WorkspaceTabCloseButtonPolicy = "all";
export type WorkspaceTabLayoutInput = {
export interface WorkspaceTabLayoutInput {
viewportWidth: number;
tabLabelLengths: number[];
metrics: {
@@ -14,19 +14,19 @@ export type WorkspaceTabLayoutInput = {
estimatedCharWidth: number;
closeButtonWidth: number;
};
};
}
export type WorkspaceTabLayoutItem = {
export interface WorkspaceTabLayoutItem {
width: number;
showLabel: boolean;
labelCharCap: number;
};
}
export type WorkspaceTabLayoutResult = {
export interface WorkspaceTabLayoutResult {
items: WorkspaceTabLayoutItem[];
closeButtonPolicy: WorkspaceTabCloseButtonPolicy;
requiresHorizontalScrollFallback: boolean;
};
}
function clamp(value: number, min: number, max: number): number {
if (value < min) {

View File

@@ -26,12 +26,12 @@ const EMPHASIZED_STATUS_DOT_SIZE = 9;
const DEFAULT_STATUS_DOT_OFFSET = -2;
const EMPHASIZED_STATUS_DOT_OFFSET = -3;
type WorkspaceTabPresentationResolverProps = {
interface WorkspaceTabPresentationResolverProps {
tab: WorkspaceTabDescriptor;
serverId: string;
workspaceId: string;
children: (presentation: WorkspaceTabPresentation) => ReactNode;
};
}
type WorkspaceTabPresentationResolverInnerProps = WorkspaceTabPresentationResolverProps & {
registration: NonNullable<ReturnType<typeof getPanelRegistration>>;
@@ -96,12 +96,12 @@ function WorkspaceTabPresentationResolverInner({
return <>{children(presentation)}</>;
}
type WorkspaceTabIconProps = {
interface WorkspaceTabIconProps {
presentation: WorkspaceTabPresentation;
active?: boolean;
size?: number;
statusDotBorderColor?: string;
};
}
export function WorkspaceTabIcon({
presentation,
@@ -168,13 +168,13 @@ export function WorkspaceTabIcon({
);
}
type WorkspaceTabOptionRowProps = {
interface WorkspaceTabOptionRowProps {
presentation: WorkspaceTabPresentation;
selected: boolean;
active: boolean;
onPress: () => void;
trailingAccessory?: ReactNode;
};
}
export function WorkspaceTabOptionRow({
presentation,

View File

@@ -3,7 +3,7 @@ import type { UserMessageImageAttachment } from "@/types/stream";
export type CreateFlowLifecycleState = "active" | "abandoned" | "sent";
type PendingCreateAttempt = {
interface PendingCreateAttempt {
draftId: string;
serverId: string;
agentId: string | null;
@@ -12,9 +12,9 @@ type PendingCreateAttempt = {
timestamp: number;
lifecycle: CreateFlowLifecycleState;
images?: UserMessageImageAttachment[];
};
}
type CreateFlowState = {
interface CreateFlowState {
pendingByDraftId: Record<string, PendingCreateAttempt>;
setPending: (pending: Omit<PendingCreateAttempt, "lifecycle">) => void;
updateAgentId: (input: { draftId: string; agentId: string }) => void;
@@ -22,7 +22,7 @@ type CreateFlowState = {
rekeyDraft: (input: { fromDraftId: string; toDraftId: string }) => void;
clear: (input: { draftId: string }) => void;
clearAll: () => void;
};
}
export const useCreateFlowStore = create<CreateFlowState>((set) => ({
pendingByDraftId: {},

View File

@@ -236,11 +236,11 @@ function findMostRecentDownloadId(downloads: Map<string, Download>): string | nu
return mostRecent?.id ?? null;
}
type DownloadTarget = {
interface DownloadTarget {
baseUrl: string | null;
authHeader: string | null;
authCredentials: { username: string; password: string } | null;
};
}
function resolveDaemonDownloadTarget(daemon?: HostProfile): DownloadTarget {
const endpoint = daemon?.connections.find((conn) => conn.type === "directTcp")?.endpoint ?? null;

View File

@@ -14,10 +14,10 @@ import { useSessionStore } from "@/stores/session-store";
const DRAFT_STORE_VERSION = 4;
const FINALIZED_DRAFT_TTL_MS = 5 * 60 * 1000;
type LegacyDraftImage = {
interface LegacyDraftImage {
uri: string;
mimeType?: string;
};
}
type PersistedDraftImage = AttachmentMetadata | LegacyDraftImage;

View File

@@ -17,15 +17,15 @@ interface ActivateWorkspaceSelectionOptions {
historyMode?: "push" | "replace";
}
type NavigationRouteParams = {
interface NavigationRouteParams {
serverId?: string | string[];
workspaceId?: string | string[];
};
}
type NavigationRouteLike = {
interface NavigationRouteLike {
params?: NavigationRouteParams | null;
path?: string | null;
};
}
type NavigationWorkspaceRouteState =
| { kind: "workspace"; selection: ActiveWorkspaceSelection }

View File

@@ -218,13 +218,13 @@ export interface AgentFileExplorerState {
selectedEntryPath: string | null;
}
export type DaemonServerInfo = {
export interface DaemonServerInfo {
serverId: string;
hostname: string | null;
version: string | null;
capabilities?: ServerCapabilities;
features?: ServerInfoStatusPayload["features"];
};
}
export interface AgentTimelineCursorState {
epoch: string;

View File

@@ -8,9 +8,9 @@ interface SidebarCollapsedSectionsState {
setProjectCollapsed: (projectKey: string, collapsed: boolean) => void;
}
type PersistedSidebarCollapsedSectionsState = {
interface PersistedSidebarCollapsedSectionsState {
collapsedProjectKeys?: string[];
};
}
function serializeCollapsedProjectKeys(keys: Set<string>): string[] {
return Array.from(keys);

View File

@@ -17,7 +17,7 @@ export interface PendingWorkspaceDraftSubmission {
allowEmptyText?: boolean;
}
type WorkspaceDraftSubmissionState = {
interface WorkspaceDraftSubmissionState {
pendingByDraftId: Record<string, PendingWorkspaceDraftSubmission>;
setPending: (submission: PendingWorkspaceDraftSubmission) => void;
consumePending: (input: {
@@ -25,7 +25,7 @@ type WorkspaceDraftSubmissionState = {
workspaceId: string;
draftId: string;
}) => PendingWorkspaceDraftSubmission | null;
};
}
function matchesPendingSubmission(
pending: PendingWorkspaceDraftSubmission | null | undefined,

View File

@@ -14,11 +14,11 @@ export type WorkspaceTabTarget =
| { kind: "file"; path: string }
| { kind: "setup"; workspaceId: string };
export type WorkspaceTab = {
export interface WorkspaceTab {
tabId: string;
target: WorkspaceTabTarget;
createdAt: number;
};
}
function trimNonEmpty(value: string | null | undefined): string | null {
if (typeof value !== "string") {
@@ -64,7 +64,7 @@ function ensureInOrder(input: { current: string[]; tabId: string }): string[] {
return [...input.current, input.tabId];
}
type WorkspaceTabsState = {
interface WorkspaceTabsState {
uiTabsByWorkspace: Record<string, WorkspaceTab[]>;
tabOrderByWorkspace: Record<string, string[]>;
focusedTabIdByWorkspace: Record<string, string>;
@@ -94,7 +94,7 @@ type WorkspaceTabsState = {
reorderTabs: (input: { serverId: string; workspaceId: string; tabIds: string[] }) => void;
getWorkspaceTabs: (input: { serverId: string; workspaceId: string }) => WorkspaceTab[];
purgeWorkspace: (input: { serverId: string; workspaceId: string }) => void;
};
}
export const useWorkspaceTabsStore = create<WorkspaceTabsState>()(
persist(

View File

@@ -30,22 +30,22 @@ StyleSheet.configure({
});
// Type augmentation for TypeScript
type AppThemes = {
interface AppThemes {
light: typeof lightTheme;
dark: typeof darkTheme;
darkZinc: typeof darkZincTheme;
darkMidnight: typeof darkMidnightTheme;
darkClaude: typeof darkClaudeTheme;
darkGhostty: typeof darkGhosttyTheme;
};
}
type AppBreakpoints = {
interface AppBreakpoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
};
}
declare module "react-native-unistyles" {
export interface UnistylesThemes extends AppThemes {}

View File

@@ -10,19 +10,22 @@ vi.mock("@xterm/addon-webgl", () => ({
},
}));
type TerminalSize = { rows: number; cols: number };
interface TerminalSize {
rows: number;
cols: number;
}
type BrowserTerminal = TerminalSize & {
refresh: (start: number, end: number) => void;
reset: () => void;
};
type MountedTerminal = {
interface MountedTerminal {
host: HTMLDivElement;
root: HTMLDivElement;
runtime: TerminalEmulatorRuntime;
sizes: TerminalSize[];
};
}
const mountedTerminals: MountedTerminal[] = [];

View File

@@ -41,7 +41,7 @@ vi.mock("@xterm/xterm", () => ({
import { TerminalEmulatorRuntime } from "./terminal-emulator-runtime";
type StubTerminal = {
interface StubTerminal {
write: (text: string, callback?: () => void) => void;
reset: () => void;
resize?: (cols: number, rows: number) => void;
@@ -50,7 +50,7 @@ type StubTerminal = {
options?: { theme?: unknown };
rows?: number;
cols?: number;
};
}
function createRuntimeWithTerminal(): {
runtime: TerminalEmulatorRuntime;

View File

@@ -18,14 +18,14 @@ import {
} from "@/utils/terminal-keys";
import { renderTerminalSnapshotToAnsi } from "./terminal-snapshot";
export type TerminalEmulatorRuntimeMountInput = {
export interface TerminalEmulatorRuntimeMountInput {
root: HTMLDivElement;
host: HTMLDivElement;
initialSnapshot: TerminalState | null;
theme: ITheme;
};
}
export type TerminalEmulatorRuntimeCallbacks = {
export interface TerminalEmulatorRuntimeCallbacks {
onInput?: (data: string) => Promise<void> | void;
onResize?: (input: { rows: number; cols: number }) => Promise<void> | void;
onTerminalKey?: (input: {
@@ -37,9 +37,9 @@ export type TerminalEmulatorRuntimeCallbacks = {
}) => Promise<void> | void;
onPendingModifiersConsumed?: () => Promise<void> | void;
onOpenExternalUrl?: (url: string) => Promise<void> | void;
};
}
type TerminalEmulatorRuntimeDisposables = {
interface TerminalEmulatorRuntimeDisposables {
disposeInput: () => void;
disconnectResizeObserver: () => void;
removeWindowResize: () => void;
@@ -55,16 +55,16 @@ type TerminalEmulatorRuntimeDisposables = {
disposeFitAddon: () => void;
disposeWebglAddon: () => void;
disposeTerminal: () => void;
};
}
type TerminalOutputOperation = {
interface TerminalOutputOperation {
type: "write" | "clear" | "snapshot";
text: string;
rows?: number;
cols?: number;
suppressInput?: boolean;
onCommitted?: () => void;
};
}
declare global {
interface Window {

View File

@@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest";
import { renderTerminalSnapshotToAnsi } from "./terminal-snapshot";
type SnapshotCell = {
interface SnapshotCell {
char: string;
fg: number | undefined;
bg: number | undefined;
@@ -13,9 +13,9 @@ type SnapshotCell = {
bold?: boolean;
italic?: boolean;
underline?: boolean;
};
}
type SnapshotState = {
interface SnapshotState {
rows: number;
cols: number;
grid: SnapshotCell[][];
@@ -27,7 +27,7 @@ type SnapshotState = {
style?: "block" | "underline" | "bar";
blink?: boolean;
};
};
}
async function writeToTerminal(
terminal: Pick<ClientTerminal | HeadlessTerminal, "write">,

View File

@@ -1,6 +1,6 @@
import type { TerminalCell, TerminalState } from "@server/shared/messages";
type TerminalStyle = {
interface TerminalStyle {
fg: number | undefined;
bg: number | undefined;
fgMode: number | undefined;
@@ -11,7 +11,7 @@ type TerminalStyle = {
dim: boolean;
inverse: boolean;
strikethrough: boolean;
};
}
const DEFAULT_STYLE: TerminalStyle = {
fg: undefined,

View File

@@ -6,13 +6,13 @@ import {
type TerminalStreamControllerStatus,
} from "./terminal-stream-controller";
type TerminalSnapshot = {
interface TerminalSnapshot {
rows: number;
cols: number;
grid: Array<Array<{ char: string }>>;
scrollback: Array<Array<{ char: string }>>;
cursor: { row: number; col: number };
};
}
type TerminalStreamEvent =
| { terminalId: string; type: "output"; data: Uint8Array }

View File

@@ -1,6 +1,6 @@
import type { TerminalState } from "@server/shared/messages";
export type TerminalStreamControllerClient = {
export interface TerminalStreamControllerClient {
subscribeTerminal: (terminalId: string) => Promise<{
terminalId: string;
error?: string | null;
@@ -17,26 +17,26 @@ export type TerminalStreamControllerClient = {
| { terminalId: string; type: "snapshot"; state: TerminalState },
) => void,
) => () => void;
};
}
export type TerminalStreamControllerSize = {
export interface TerminalStreamControllerSize {
rows: number;
cols: number;
};
}
export type TerminalStreamControllerStatus = {
export interface TerminalStreamControllerStatus {
terminalId: string | null;
isAttaching: boolean;
error: string | null;
};
}
export type TerminalStreamControllerOptions = {
export interface TerminalStreamControllerOptions {
client: TerminalStreamControllerClient;
getPreferredSize: () => TerminalStreamControllerSize | null;
onOutput: (input: { terminalId: string; text: string }) => void;
onSnapshot: (input: { terminalId: string; state: TerminalState }) => void;
onStatusChange?: (status: TerminalStreamControllerStatus) => void;
};
}
const TERMINAL_EXITED_ERROR = "Terminal exited";

View File

@@ -1,21 +1,21 @@
import type { TerminalState } from "@server/shared/messages";
export type WorkspaceTerminalSnapshots = {
export interface WorkspaceTerminalSnapshots {
get: (input: { terminalId: string }) => TerminalState | null;
set: (input: { terminalId: string; state: TerminalState }) => void;
clear: (input: { terminalId: string }) => void;
prune: (input: { terminalIds: string[] }) => void;
};
}
export type WorkspaceTerminalSession = {
export interface WorkspaceTerminalSession {
scopeKey: string;
snapshots: WorkspaceTerminalSnapshots;
};
}
type WorkspaceTerminalSessionRecord = {
interface WorkspaceTerminalSessionRecord {
snapshotByTerminalId: Map<string, TerminalState>;
session: WorkspaceTerminalSession;
};
}
const sessionsByScopeKey = new Map<string, WorkspaceTerminalSessionRecord>();
const refCountByScopeKey = new Map<string, number>();

View File

@@ -123,12 +123,12 @@ export interface MergedToolCall {
export type GroupedActivity = GroupedTextMessage | MergedToolCall | AgentActivity;
type TextGroup = {
interface TextGroup {
messageType: TextMessageType;
chunks: string[];
startTimestamp: Date;
endTimestamp: Date;
};
}
type ToolCallAccumulator = Omit<MergedToolCall, "kind"> & {
insertIndex: number;

View File

@@ -1,29 +1,29 @@
import { normalizeHostPort, normalizeLoopbackToLocalhost } from "@server/shared/daemon-endpoints";
export type DirectTcpHostConnection = {
export interface DirectTcpHostConnection {
id: string;
type: "directTcp";
endpoint: string;
};
}
export type DirectSocketHostConnection = {
export interface DirectSocketHostConnection {
id: string;
type: "directSocket";
path: string;
};
}
export type DirectPipeHostConnection = {
export interface DirectPipeHostConnection {
id: string;
type: "directPipe";
path: string;
};
}
export type RelayHostConnection = {
export interface RelayHostConnection {
id: string;
type: "relay";
relayEndpoint: string;
daemonPublicKeyB64: string;
};
}
export type HostConnection =
| DirectTcpHostConnection
@@ -33,7 +33,7 @@ export type HostConnection =
export type HostLifecycle = Record<string, never>;
export type HostProfile = {
export interface HostProfile {
serverId: string;
label: string;
lifecycle: HostLifecycle;
@@ -41,7 +41,7 @@ export type HostProfile = {
preferredConnectionId: string | null;
createdAt: string;
updatedAt: string;
};
}
export function defaultLifecycle(): HostLifecycle {
return {};

View File

@@ -9,7 +9,10 @@ import {
import type { AgentStreamEventPayload } from "@server/shared/messages";
import type { ToolCallDetail } from "@server/server/agent/agent-sdk-types";
type HarnessUpdate = { event: AgentStreamEventPayload; timestamp: Date };
interface HarnessUpdate {
event: AgentStreamEventPayload;
timestamp: Date;
}
type ToolStatus = "running" | "completed" | "failed" | "canceled";
const HARNESS_CALL_IDS = {

View File

@@ -142,7 +142,10 @@ export interface CompactionItem {
preTokens?: number;
}
export type TodoEntry = { text: string; completed: boolean };
export interface TodoEntry {
text: string;
completed: boolean;
}
export interface TodoListItem {
kind: "todo_list";

View File

@@ -5,11 +5,11 @@ import { resolveProjectPlacement } from "@/utils/project-placement";
type AgentDirectoryFetchEntry = FetchAgentsEntry | FetchAgentHistoryEntry;
type PendingPermissionEntry = {
interface PendingPermissionEntry {
key: string;
agentId: string;
request: Agent["pendingPermissions"][number];
};
}
export function buildAgentDirectoryState(input: {
serverId: string;

Some files were not shown because too many files have changed in this diff Show More