From 106249c632011634d8c96b8eba500124c26dfca6 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Thu, 23 Apr 2026 22:59:49 +0700 Subject: [PATCH] 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). --- .oxlintrc.json | 2 +- packages/app/e2e/global-setup.ts | 8 +- .../app/e2e/helpers/agent-bottom-anchor.ts | 16 ++-- packages/app/e2e/helpers/archive-tab.ts | 12 +-- packages/app/e2e/helpers/new-workspace.ts | 8 +- packages/app/e2e/helpers/node-ws-factory.ts | 4 +- packages/app/e2e/helpers/paseo-home-fork.ts | 8 +- packages/app/e2e/helpers/startup-dsl.ts | 4 +- packages/app/e2e/helpers/terminal-dsl.ts | 8 +- packages/app/e2e/helpers/terminal-perf.ts | 12 +-- packages/app/e2e/helpers/terminal-probes.ts | 44 +++++----- packages/app/e2e/helpers/workspace-setup.ts | 4 +- packages/app/e2e/helpers/workspace.ts | 4 +- packages/app/e2e/startup-wire-metrics.spec.ts | 16 ++-- .../app/e2e/terminal-keystroke-stress.spec.ts | 4 +- .../app/e2e/workspace-setup-streaming.spec.ts | 4 +- packages/app/src/app/_layout.tsx | 4 +- .../web/indexeddb-attachment-store.ts | 4 +- .../app/src/components/agent-status-bar.tsx | 8 +- .../components/agent-stream-render-model.ts | 20 ++--- .../agent-stream-web-virtualization.ts | 8 +- .../app/src/components/command-center.tsx | 4 +- packages/app/src/components/composer.tsx | 4 +- .../src/components/context-window-meter.tsx | 4 +- ...daemon-version-mismatch-callout-source.tsx | 4 +- .../components/draggable-list.web.test.tsx | 4 +- packages/app/src/components/message-input.tsx | 4 +- packages/app/src/components/message.tsx | 4 +- .../sidebar-workspace-list.test.tsx | 4 +- .../sortable-inline-list.web.test.tsx | 4 +- .../src/components/stream-strategy-web.tsx | 4 +- .../app/src/components/stream-strategy.ts | 28 +++---- .../app/src/components/terminal-emulator.tsx | 4 +- packages/app/src/components/terminal-pane.tsx | 4 +- packages/app/src/components/toast-host.tsx | 12 +-- .../app/src/components/tool-call-sheet.tsx | 4 +- .../app/src/components/ui/context-menu.tsx | 10 ++- .../app/src/components/ui/dropdown-menu.tsx | 10 ++- .../src/components/ui/segmented-control.tsx | 8 +- packages/app/src/components/ui/tooltip.tsx | 4 +- .../use-bottom-anchor-controller.ts | 32 ++++---- .../components/web-desktop-scrollbar.math.ts | 12 +-- .../src/components/web-desktop-scrollbar.tsx | 8 +- .../app/src/components/welcome-screen.tsx | 4 +- .../src/contexts/session-stream-reducers.ts | 40 +++++----- .../app/src/desktop/daemon/desktop-daemon.ts | 20 ++--- packages/app/src/desktop/electron/events.ts | 4 +- .../permissions/desktop-permissions.test.ts | 4 +- .../permissions/desktop-permissions.ts | 16 ++-- .../dictation/dictation-stream-sender.test.ts | 17 +++- .../src/dictation/dictation-stream-sender.ts | 9 ++- .../app/src/hooks/use-agent-form-state.ts | 8 +- packages/app/src/hooks/use-agent-history.ts | 4 +- .../app/src/hooks/use-agent-input-draft.ts | 12 +-- .../src/hooks/use-client-activity.test.tsx | 4 +- packages/app/src/hooks/use-command-center.ts | 8 +- .../hooks/use-dictation-audio-source.types.ts | 8 +- .../hooks/use-dictation-audio-source.web.ts | 4 +- .../app/src/hooks/use-dictation.shared.ts | 8 +- .../src/hooks/use-draft-agent-create-flow.ts | 16 ++-- packages/app/src/hooks/use-file-drop-zone.ts | 4 +- .../src/hooks/use-hover-safe-zone.test.tsx | 4 +- .../src/hooks/use-keyboard-action-handler.ts | 4 +- .../src/hooks/use-providers-snapshot.test.ts | 8 +- .../keyboard/keyboard-action-dispatcher.ts | 4 +- .../src/keyboard/keyboard-shortcuts.test.ts | 12 +-- .../app/src/keyboard/keyboard-shortcuts.ts | 20 ++--- packages/app/src/panels/agent-panel.test.tsx | 4 +- packages/app/src/runtime/host-runtime.ts | 12 +-- .../agent/agent-ready-screen-bottom-anchor.ts | 4 +- .../app/src/screens/startup-splash-screen.tsx | 4 +- .../workspace/use-workspace-tab-layout.ts | 8 +- .../screens/workspace/workspace-bulk-close.ts | 4 +- .../workspace/workspace-desktop-tabs-row.tsx | 4 +- .../workspace/workspace-draft-agent-tab.tsx | 4 +- .../screens/workspace/workspace-screen.tsx | 8 +- .../screens/workspace/workspace-tab-layout.ts | 12 +-- .../workspace/workspace-tab-presentation.tsx | 12 +-- packages/app/src/stores/create-flow-store.ts | 8 +- packages/app/src/stores/download-store.ts | 4 +- packages/app/src/stores/draft-store.ts | 4 +- .../navigation-active-workspace-store.ts | 8 +- packages/app/src/stores/session-store.ts | 4 +- .../sidebar-collapsed-sections-store.ts | 4 +- .../workspace-draft-submission-store.ts | 4 +- .../app/src/stores/workspace-tabs-store.ts | 8 +- packages/app/src/styles/unistyles.ts | 8 +- .../terminal-emulator-runtime.browser.test.ts | 9 ++- .../runtime/terminal-emulator-runtime.test.ts | 4 +- .../runtime/terminal-emulator-runtime.ts | 16 ++-- .../runtime/terminal-snapshot.test.ts | 8 +- .../src/terminal/runtime/terminal-snapshot.ts | 4 +- .../terminal-stream-controller.test.ts | 4 +- .../runtime/terminal-stream-controller.ts | 16 ++-- .../runtime/workspace-terminal-session.ts | 12 +-- packages/app/src/types/agent-activity.ts | 4 +- packages/app/src/types/host-connection.ts | 20 ++--- packages/app/src/types/stream.harness.test.ts | 5 +- packages/app/src/types/stream.ts | 5 +- .../app/src/utils/agent-directory-sync.ts | 4 +- packages/app/src/utils/branch-suggestions.ts | 4 +- packages/app/src/utils/confirm-dialog.test.ts | 4 +- .../app/src/utils/connection-selection.ts | 8 +- packages/app/src/utils/desktop-window.ts | 4 +- packages/app/src/utils/markdown-list.ts | 4 +- .../app/src/utils/os-notifications.test.ts | 12 +-- packages/app/src/utils/os-notifications.ts | 12 +-- .../app/src/utils/pending-create-images.ts | 4 +- packages/app/src/utils/terminal-keys.ts | 4 +- packages/app/src/utils/tool-call-parsers.ts | 12 +-- packages/app/src/utils/web-focus.ts | 4 +- packages/app/src/utils/workspace-execution.ts | 4 +- .../app/src/utils/workspace-script-links.ts | 4 +- packages/app/src/voice/voice-runtime.ts | 8 +- .../cli/src/commands/daemon/local-daemon.ts | 4 +- packages/cli/src/commands/daemon/status.ts | 4 +- packages/cli/src/commands/onboard.ts | 4 +- packages/cli/src/utils/timeline.ts | 4 +- packages/cli/src/version.ts | 4 +- packages/cli/tests/15-provider.test.ts | 4 +- .../tests/21-run-output-schema-helper.test.ts | 4 +- .../tests/22-daemon-stop-supervisor.test.ts | 8 +- .../tests/23-daemon-sigint-supervisor.test.ts | 8 +- .../25-daemon-restart-supervisor.test.ts | 4 +- .../26-daemon-restart-unsupervised.test.ts | 4 +- packages/cli/tests/helpers/test-daemon.ts | 4 +- packages/cli/tests/run-all.ts | 5 +- packages/desktop/src/daemon/daemon-manager.ts | 12 +-- .../desktop/src/daemon/local-transport.ts | 12 +-- .../src/daemon/node-entrypoint-launcher.ts | 16 ++-- packages/desktop/src/daemon/runtime-paths.ts | 4 +- packages/desktop/src/features/attachments.ts | 4 +- packages/desktop/src/features/auto-updater.ts | 8 +- packages/desktop/src/features/dialogs.ts | 8 +- packages/desktop/src/features/menu.ts | 4 +- .../desktop/src/features/notifications.ts | 8 +- .../desktop/src/features/react-devtools.ts | 8 +- packages/desktop/src/window/window-manager.ts | 8 +- packages/expo-two-way-audio/src/events.ts | 16 ++-- packages/relay/src/cloudflare-adapter.ts | 4 +- packages/relay/src/crypto.ts | 4 +- packages/relay/src/encrypted-channel.ts | 4 +- .../scripts/generate-sherpa-tts-matrix.ts | 8 +- .../server/scripts/supervisor-entrypoint.ts | 4 +- packages/server/scripts/supervisor.ts | 4 +- packages/server/scripts/test-mcp-inject.ts | 8 +- .../server/scripts/transcribe-local-wav.ts | 4 +- .../server/scripts/voice-main-daemon-e2e.ts | 4 +- .../client/daemon-client-runtime-metrics.ts | 20 ++--- .../client/daemon-client-transport-types.ts | 8 +- packages/server/src/client/daemon-client.ts | 80 +++++++++---------- .../src/server/agent-attention-policy.ts | 4 +- .../agent-manager-stream-coalescing.test.ts | 4 +- .../src/server/agent/agent-manager.test.ts | 4 +- .../server/src/server/agent/agent-manager.ts | 48 +++++------ .../src/server/agent/agent-mcp.e2e.test.ts | 12 +-- .../server/agent/agent-metadata-generator.ts | 12 +-- .../src/server/agent/agent-projections.ts | 4 +- .../agent/agent-response-loop.e2e.test.ts | 4 +- .../src/server/agent/agent-response-loop.ts | 8 +- .../src/server/agent/agent-sdk-types.ts | 80 ++++++++++--------- .../server/agent/agent-stream-coalescer.ts | 24 +++--- .../agent/agent-timeline-store-types.ts | 20 ++--- .../src/server/agent/agent-timeline-store.ts | 8 +- .../src/server/agent/mcp-parity.e2e.test.ts | 12 +-- .../src/server/agent/mcp-server.test.ts | 4 +- .../server/src/server/agent/mcp-shared.ts | 4 +- .../server/src/server/agent/model-resolver.ts | 4 +- .../server/agent/provider-launch-config.ts | 4 +- .../server/agent/provider-registry.test.ts | 4 +- .../src/server/agent/provider-registry.ts | 8 +- .../agent/provider-snapshot-manager.test.ts | 12 +-- .../server/agent/provider-snapshot-manager.ts | 16 ++-- .../src/server/agent/providers/acp-agent.ts | 36 ++++----- ...agent.interrupt-restart-regression.test.ts | 12 +-- .../providers/claude-agent.redesign.test.ts | 8 +- .../claude-agent.sub-agent-sidechain.test.ts | 4 +- .../server/agent/providers/claude-agent.ts | 53 ++++++------ .../agent/providers/claude/partial-json.ts | 4 +- .../providers/claude/sidechain-tracker.ts | 17 ++-- .../claude/task-notification-tool-call.ts | 12 +-- .../providers/claude/tool-call-mapper.ts | 4 +- .../agent/providers/codex-app-server-agent.ts | 41 +++++----- .../agent/providers/codex-rollout-timeline.ts | 4 +- .../codex/tool-call-detail-parser.ts | 4 +- .../agent/providers/codex/tool-call-mapper.ts | 16 ++-- .../agent/providers/copilot-acp-agent.ts | 4 +- .../agent/providers/diagnostic-utils.ts | 4 +- .../agent/providers/generic-acp-agent.ts | 4 +- .../agent/providers/mock-load-test-agent.ts | 12 +-- .../server/agent/providers/opencode-agent.ts | 8 +- .../providers/opencode-server-manager.test.ts | 4 +- .../providers/opencode/tool-call-mapper.ts | 4 +- .../providers/provider-windows-launch.test.ts | 8 +- .../providers/tool-call-detail-primitives.ts | 4 +- .../agent/providers/tool-call-mapper-utils.ts | 4 +- .../src/server/agent/timeline-projection.ts | 12 +-- .../server/src/server/agent/tts-manager.ts | 4 +- packages/server/src/server/bootstrap.ts | 8 +- .../server/src/server/chat/chat-service.ts | 4 +- .../src/server/checkout-diff-manager.ts | 8 +- .../server/src/server/checkout-git-utils.ts | 4 +- .../server/src/server/connection-offer.ts | 4 +- .../server/src/server/daemon-config-store.ts | 4 +- .../claude-autonomous-wake.real.e2e.test.ts | 8 +- .../ui-action-stress.real.e2e.test.ts | 8 +- packages/server/src/server/daemon-keypair.ts | 4 +- .../dictation/dictation-stream-manager.ts | 4 +- packages/server/src/server/editor-targets.ts | 12 +-- .../src/server/file-download/token-store.ts | 8 +- packages/server/src/server/logger.ts | 8 +- packages/server/src/server/package-version.ts | 8 +- packages/server/src/server/pairing-offer.ts | 4 +- .../server/paseo-worktree-archive-service.ts | 8 +- .../server/src/server/persisted-config.ts | 4 +- .../server/src/server/persistence-hooks.ts | 8 +- packages/server/src/server/relay-transport.ts | 12 +-- .../src/server/script-health-monitor.test.ts | 4 +- .../src/server/script-health-monitor.ts | 4 +- .../src/server/script-status-projection.ts | 8 +- packages/server/src/server/server-id.ts | 4 +- packages/server/src/server/session.test.ts | 4 +- packages/server/src/server/session.ts | 48 +++++------ .../server/speech/providers/local/config.ts | 12 +-- .../providers/local/pocket/pocket-tts-onnx.ts | 8 +- .../server/speech/providers/local/runtime.ts | 12 +-- .../providers/local/sherpa/model-catalog.ts | 4 +- .../local/sherpa/model-downloader.ts | 8 +- .../local/sherpa/sherpa-offline-recognizer.ts | 8 +- .../local/sherpa/sherpa-online-recognizer.ts | 4 +- .../local/sherpa/sherpa-onnx-loader.ts | 4 +- .../local/sherpa/sherpa-onnx-node-loader.ts | 8 +- .../local/sherpa/sherpa-parakeet-stt.ts | 4 +- .../local/sherpa/sherpa-runtime-env.ts | 4 +- .../providers/local/sherpa/sherpa-stt.ts | 4 +- .../providers/local/sherpa/sherpa-tts.ts | 4 +- .../local/sherpa/silero-vad-session.ts | 12 +-- .../server/speech/providers/openai/config.ts | 4 +- .../server/speech/providers/openai/runtime.ts | 12 +-- .../src/server/speech/speech-provider.ts | 4 +- .../src/server/speech/speech-runtime.ts | 12 +-- .../server/src/server/speech/speech-types.ts | 4 +- .../server/speech/turn-detection-provider.ts | 4 +- .../server/test-utils/fake-agent-client.ts | 4 +- .../src/server/test-utils/paseo-daemon.ts | 8 +- packages/server/src/server/voice-types.ts | 4 +- .../websocket-server.runtime-metrics.test.ts | 8 +- .../server/src/server/websocket-server.ts | 28 +++---- .../src/server/workspace-git-metadata.ts | 4 +- .../src/server/workspace-git-service.ts | 8 +- .../workspace-reconciliation-service.ts | 8 +- .../src/server/workspace-registry-model.ts | 4 +- .../server/workspace-script-runtime-store.ts | 4 +- .../server/src/server/worktree-bootstrap.ts | 8 +- .../server/src/server/worktree-session.ts | 16 ++-- .../shared/agent-attention-notification.ts | 16 ++-- .../server/src/shared/daemon-endpoints.ts | 4 +- .../src/shared/terminal-stream-protocol.ts | 4 +- .../server/src/shared/tool-call-display.ts | 8 +- .../src/terminal/terminal-output-coalescer.ts | 12 +-- packages/server/src/terminal/terminal.ts | 4 +- packages/server/src/utils/checkout-git.ts | 32 ++++---- .../server/src/utils/directory-suggestions.ts | 28 +++---- packages/server/src/utils/promise-timeout.ts | 4 +- packages/server/src/utils/script-hostname.ts | 4 +- .../src/utils/spawn.launch-regression.test.ts | 4 +- packages/server/src/utils/worktree.ts | 12 +-- .../website/src/components/hero-mockup.tsx | 16 ++-- 268 files changed, 1247 insertions(+), 1196 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 31f765836..a7c0aa890 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -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", diff --git a/packages/app/e2e/global-setup.ts b/packages/app/e2e/global-setup.ts index 0151718b7..44c115126 100644 --- a/packages/app/e2e/global-setup.ts +++ b/packages/app/e2e/global-setup.ts @@ -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 { 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 { const binDir = await mkdtemp(path.join(tmpdir(), "paseo-e2e-gh-bin-")); diff --git a/packages/app/e2e/helpers/agent-bottom-anchor.ts b/packages/app/e2e/helpers/agent-bottom-anchor.ts index c33c99d68..6a7f99e20 100644 --- a/packages/app/e2e/helpers/agent-bottom-anchor.ts +++ b/packages/app/e2e/helpers/agent-bottom-anchor.ts @@ -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; close(): Promise; createAgent(options: { @@ -36,7 +36,7 @@ export type DaemonClientInstance = { }): Promise<{ id: string }>; sendAgentMessage(agentId: string, text: string): Promise; 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 diff --git a/packages/app/e2e/helpers/archive-tab.ts b/packages/app/e2e/helpers/archive-tab.ts index fb5798ad0..d12b57787 100644 --- a/packages/app/e2e/helpers/archive-tab.ts +++ b/packages/app/e2e/helpers/archive-tab.ts @@ -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; close(): Promise; 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 diff --git a/packages/app/e2e/helpers/new-workspace.ts b/packages/app/e2e/helpers/new-workspace.ts index 0471496ea..4bd698b57 100644 --- a/packages/app/e2e/helpers/new-workspace.ts +++ b/packages/app/e2e/helpers/new-workspace.ts @@ -17,21 +17,21 @@ type NewWorkspaceDaemonClient = Pick< | "openProject" >; -type NewWorkspaceDaemonClientConfig = { +interface NewWorkspaceDaemonClientConfig { url: string; clientId: string; clientType: "cli"; webSocketFactory?: NodeWebSocketFactory; -}; +} type OpenProjectPayload = Awaited>; -export type OpenedProject = { +export interface OpenedProject { workspaceId: string; projectKey: string; projectDisplayName: string; workspaceName: string; -}; +} function getDaemonPort(): string { const daemonPort = process.env.E2E_DAEMON_PORT; diff --git a/packages/app/e2e/helpers/node-ws-factory.ts b/packages/app/e2e/helpers/node-ws-factory.ts index fed9af2a6..888edd865 100644 --- a/packages/app/e2e/helpers/node-ws-factory.ts +++ b/packages/app/e2e/helpers/node-ws-factory.ts @@ -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, diff --git a/packages/app/e2e/helpers/paseo-home-fork.ts b/packages/app/e2e/helpers/paseo-home-fork.ts index 0b4f2049e..5526096ae 100644 --- a/packages/app/e2e/helpers/paseo-home-fork.ts +++ b/packages/app/e2e/helpers/paseo-home-fork.ts @@ -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 === "~") { diff --git a/packages/app/e2e/helpers/startup-dsl.ts b/packages/app/e2e/helpers/startup-dsl.ts index 67702e20f..72c5b4e2f 100644 --- a/packages/app/e2e/helpers/startup-dsl.ts +++ b/packages/app/e2e/helpers/startup-dsl.ts @@ -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); diff --git a/packages/app/e2e/helpers/terminal-dsl.ts b/packages/app/e2e/helpers/terminal-dsl.ts index 8c12547ce..cf0b42a86 100644 --- a/packages/app/e2e/helpers/terminal-dsl.ts +++ b/packages/app/e2e/helpers/terminal-dsl.ts @@ -7,16 +7,16 @@ import { type TerminalPerfDaemonClient, } from "./terminal-perf"; -type TempRepo = { +interface TempRepo { path: string; cleanup: () => Promise; -}; +} -export type TerminalInstance = { +export interface TerminalInstance { id: string; name: string; cwd: string; -}; +} export class TerminalE2EHarness { readonly client: TerminalPerfDaemonClient; diff --git a/packages/app/e2e/helpers/terminal-perf.ts b/packages/app/e2e/helpers/terminal-perf.ts index 36de7aa41..2902ce3d7 100644 --- a/packages/app/e2e/helpers/terminal-perf.ts +++ b/packages/app/e2e/helpers/terminal-perf.ts @@ -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; close(): Promise; 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. diff --git a/packages/app/e2e/helpers/terminal-probes.ts b/packages/app/e2e/helpers/terminal-probes.ts index 0e91ebf97..2281b8118 100644 --- a/packages/app/e2e/helpers/terminal-probes.ts +++ b/packages/app/e2e/helpers/terminal-probes.ts @@ -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 & { 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 { await page.addInitScript(() => { - type ProbeState = { + interface ProbeState { term: any; setCount: number; unsetCount: number; @@ -99,7 +99,7 @@ export async function installTerminalRenderProbe(page: Page): Promise { 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 { 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 void; report: (inputText: string) => TerminalKeystrokeStressReport; - }; + } const INPUT_OPCODE = 0x02; const OUTPUT_OPCODE = 0x01; diff --git a/packages/app/e2e/helpers/workspace-setup.ts b/packages/app/e2e/helpers/workspace-setup.ts index 37dd71406..ea94aa1df 100644 --- a/packages/app/e2e/helpers/workspace-setup.ts +++ b/packages/app/e2e/helpers/workspace-setup.ts @@ -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; close(): Promise; openProject(cwd: string): Promise<{ @@ -52,7 +52,7 @@ type WorkspaceSetupDaemonClient = { error?: string | null; }>; subscribeRawMessages(handler: (message: SessionOutboundMessage) => void): () => void; -}; +} export type WorkspaceSetupProgressPayload = Extract< SessionOutboundMessage, diff --git a/packages/app/e2e/helpers/workspace.ts b/packages/app/e2e/helpers/workspace.ts index 4b6600367..467ecd300 100644 --- a/packages/app/e2e/helpers/workspace.ts +++ b/packages/app/e2e/helpers/workspace.ts @@ -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; cleanup: () => Promise; -}; +} export const createTempGitRepo = async ( prefix = "paseo-e2e-", diff --git a/packages/app/e2e/startup-wire-metrics.spec.ts b/packages/app/e2e/startup-wire-metrics.spec.ts index fca4e8dc2..b72cc660c 100644 --- a/packages/app/e2e/startup-wire-metrics.spec.ts +++ b/packages/app/e2e/startup-wire-metrics.spec.ts @@ -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; @@ -84,7 +84,7 @@ type WireSummary = { copiedFiles: number | null; copiedBytes: number | null; }; -}; +} class WireMonitor { private phase: WirePhase = "startup"; diff --git a/packages/app/e2e/terminal-keystroke-stress.spec.ts b/packages/app/e2e/terminal-keystroke-stress.spec.ts index 6c56d4921..da7ae0191 100644 --- a/packages/app/e2e/terminal-keystroke-stress.spec.ts +++ b/packages/app/e2e/terminal-keystroke-stress.spec.ts @@ -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; diff --git a/packages/app/e2e/workspace-setup-streaming.spec.ts b/packages/app/e2e/workspace-setup-streaming.spec.ts index 329edbffa..d5390c7a6 100644 --- a/packages/app/e2e/workspace-setup-streaming.spec.ts +++ b/packages/app/e2e/workspace-setup-streaming.spec.ts @@ -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( diff --git a/packages/app/src/app/_layout.tsx b/packages/app/src/app/_layout.tsx index 5b3200a46..895e5e0aa 100644 --- a/packages/app/src/app/_layout.tsx +++ b/packages/app/src/app/_layout.tsx @@ -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") { diff --git a/packages/app/src/attachments/web/indexeddb-attachment-store.ts b/packages/app/src/attachments/web/indexeddb-attachment-store.ts index c807b7bb8..e2352749b 100644 --- a/packages/app/src/attachments/web/indexeddb-attachment-store.ts +++ b/packages/app/src/attachments/web/indexeddb-attachment-store.ts @@ -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"; diff --git a/packages/app/src/components/agent-status-bar.tsx b/packages/app/src/components/agent-status-bar.tsx index d1096a792..7a9cbe712 100644 --- a/packages/app/src/components/agent-status-bar.tsx +++ b/packages/app/src/components/agent-status-bar.tsx @@ -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[]; diff --git a/packages/app/src/components/agent-stream-render-model.ts b/packages/app/src/components/agent-stream-render-model.ts index c5d9cda1e..8ecf0fe8e 100644 --- a/packages/app/src/components/agent-stream-render-model.ts +++ b/packages/app/src/components/agent-stream-render-model.ts @@ -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 = { diff --git a/packages/app/src/components/agent-stream-web-virtualization.ts b/packages/app/src/components/agent-stream-web-virtualization.ts index 794413182..b922fbd4d 100644 --- a/packages/app/src/components/agent-stream-web-virtualization.ts +++ b/packages/app/src/components/agent-stream-web-virtualization.ts @@ -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) { diff --git a/packages/app/src/components/command-center.tsx b/packages/app/src/components/command-center.tsx index 2f1bd0d83..d9e046370 100644 --- a/packages/app/src/components/command-center.tsx +++ b/packages/app/src/components/command-center.tsx @@ -14,12 +14,12 @@ function agentKey(agent: Pick): 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, diff --git a/packages/app/src/components/composer.tsx b/packages/app/src/components/composer.tsx index ec57a7f1a..3164d07e3 100644 --- a/packages/app/src/components/composer.tsx +++ b/packages/app/src/components/composer.tsx @@ -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[] diff --git a/packages/app/src/components/context-window-meter.tsx b/packages/app/src/components/context-window-meter.tsx index 9e7576aaf..7d4f18f6c 100644 --- a/packages/app/src/components/context-window-meter.tsx +++ b/packages/app/src/components/context-window-meter.tsx @@ -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; diff --git a/packages/app/src/components/daemon-version-mismatch-callout-source.tsx b/packages/app/src/components/daemon-version-mismatch-callout-source.tsx index e27960df9..276139206 100644 --- a/packages/app/src/components/daemon-version-mismatch-callout-source.tsx +++ b/packages/app/src/components/daemon-version-mismatch-callout-source.tsx @@ -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(); diff --git a/packages/app/src/components/draggable-list.web.test.tsx b/packages/app/src/components/draggable-list.web.test.tsx index a2e0150ad..32b009142 100644 --- a/packages/app/src/components/draggable-list.web.test.tsx +++ b/packages/app/src/components/draggable-list.web.test.tsx @@ -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; diff --git a/packages/app/src/components/message-input.tsx b/packages/app/src/components/message-input.tsx index 65a5bbfb5..c03987541 100644 --- a/packages/app/src/components/message-input.tsx +++ b/packages/app/src/components/message-input.tsx @@ -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; -}; +} function logWebStickyBottom(_event: string, _details: Record): void { // Intentionally disabled: this path is too noisy during voice debugging. diff --git a/packages/app/src/components/message.tsx b/packages/app/src/components/message.tsx index 0bd6154a9..70c361c26 100644 --- a/packages/app/src/components/message.tsx +++ b/packages/app/src/components/message.tsx @@ -132,7 +132,7 @@ const MARKDOWN_ALLOWED_IMAGE_HANDLERS = [ ] as const; const MARKDOWN_TOP_LEVEL_MAX_EXCEEDED_ITEM = ...; -type MarkdownWithStableRendererProps = { +interface MarkdownWithStableRendererProps { children: ReactNode; style: ReturnType; rules: RenderRules; @@ -140,7 +140,7 @@ type MarkdownWithStableRendererProps = { onLinkPress: (url: string) => boolean; allowedImageHandlers: readonly string[]; topLevelMaxExceededItem: ReactNode; -}; +} const MarkdownWithStableRenderer = Markdown as ComponentType; const WEB_TOOLCALL_SHIMMER_KEYFRAME_CSS = ` diff --git a/packages/app/src/components/sidebar-workspace-list.test.tsx b/packages/app/src/components/sidebar-workspace-list.test.tsx index d6bb497d6..9c14519b1 100644 --- a/packages/app/src/components/sidebar-workspace-list.test.tsx +++ b/packages/app/src/components/sidebar-workspace-list.test.tsx @@ -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; rows: Record; projectSelection: Record; rowSelection: Record; -}; +} const runningScript: WorkspaceScriptPayload = { scriptName: "web", diff --git a/packages/app/src/components/sortable-inline-list.web.test.tsx b/packages/app/src/components/sortable-inline-list.web.test.tsx index 00d77c95f..29cfb6a56 100644 --- a/packages/app/src/components/sortable-inline-list.web.test.tsx +++ b/packages/app/src/components/sortable-inline-list.web.test.tsx @@ -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; diff --git a/packages/app/src/components/stream-strategy-web.tsx b/packages/app/src/components/stream-strategy-web.tsx index 3c228833a..8f4abf145 100644 --- a/packages/app/src/components/stream-strategy-web.tsx +++ b/packages/app/src/components/stream-strategy-web.tsx @@ -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"; diff --git a/packages/app/src/components/stream-strategy.ts b/packages/app/src/components/stream-strategy.ts index c7f3f013b..4c5289a9b 100644 --- a/packages/app/src/components/stream-strategy.ts +++ b/packages/app/src/components/stream-strategy.ts @@ -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 | null; ListHeaderComponentStyle?: StyleProp; ListFooterComponent?: ReactElement | ComponentType | null; ListFooterComponentStyle?: StyleProp; -}; +} -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; baseListContentContainerStyle: StyleProp; forwardListContentContainerStyle: StyleProp; -}; +} -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; diff --git a/packages/app/src/components/terminal-emulator.tsx b/packages/app/src/components/terminal-emulator.tsx index de14ccf9c..195c4b37d 100644 --- a/packages/app/src/components/terminal-emulator.tsx +++ b/packages/app/src/components/terminal-emulator.tsx @@ -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 = [ diff --git a/packages/app/src/components/terminal-pane.tsx b/packages/app/src/components/terminal-pane.tsx index 61794a5fa..b748ac277 100644 --- a/packages/app/src/components/terminal-pane.tsx +++ b/packages/app/src/components/terminal-pane.tsx @@ -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 = | { diff --git a/packages/app/src/components/toast-host.tsx b/packages/app/src/components/toast-host.tsx index f2f23b235..d5ecde0b0 100644 --- a/packages/app/src/components/toast-host.tsx +++ b/packages/app/src/components/toast-host.tsx @@ -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"; diff --git a/packages/app/src/components/tool-call-sheet.tsx b/packages/app/src/components/tool-call-sheet.tsx index 372774358..b98967abf 100644 --- a/packages/app/src/components/tool-call-sheet.tsx +++ b/packages/app/src/components/tool-call-sheet.tsx @@ -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; diff --git a/packages/app/src/components/ui/context-menu.tsx b/packages/app/src/components/ui/context-menu.tsx index 8698a0bfe..2d4cd9434 100644 --- a/packages/app/src/components/ui/context-menu.tsx +++ b/packages/app/src/components/ui/context-menu.tsx @@ -53,13 +53,13 @@ interface Rect { height: number; } -type ContextMenuContextValue = { +interface ContextMenuContextValue { open: boolean; setOpen: (open: boolean) => void; triggerRef: React.RefObject; anchorRect: Rect | null; setAnchorRect: (rect: Rect | null) => void; -}; +} const ContextMenuContext = createContext(null); @@ -235,7 +235,11 @@ export function ContextMenu({ return {children}; } -type TriggerState = { pressed: boolean; hovered: boolean; open: boolean }; +interface TriggerState { + pressed: boolean; + hovered: boolean; + open: boolean; +} type TriggerStyleProp = StyleProp | ((state: TriggerState) => StyleProp); export function ContextMenuTrigger({ diff --git a/packages/app/src/components/ui/dropdown-menu.tsx b/packages/app/src/components/ui/dropdown-menu.tsx index 42e6cfd58..9348a4562 100644 --- a/packages/app/src/components/ui/dropdown-menu.tsx +++ b/packages/app/src/components/ui/dropdown-menu.tsx @@ -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; -}; +} const DropdownMenuContext = createContext(null); @@ -224,7 +224,11 @@ export function DropdownMenu({ return {children}; } -type TriggerState = { pressed: boolean; hovered: boolean; open: boolean }; +interface TriggerState { + pressed: boolean; + hovered: boolean; + open: boolean; +} type TriggerStyleProp = StyleProp | ((state: TriggerState) => StyleProp); interface DropdownMenuTriggerProps extends Omit { diff --git a/packages/app/src/components/ui/segmented-control.tsx b/packages/app/src/components/ui/segmented-control.tsx index 483f4c5cb..8515061b5 100644 --- a/packages/app/src/components/ui/segmented-control.tsx +++ b/packages/app/src/components/ui/segmented-control.tsx @@ -7,15 +7,15 @@ type SegmentedControlSize = "sm" | "md"; type SegmentedControlIconRenderer = (props: { color: string; size: number }) => ReactNode; -export type SegmentedControlOption = { +export interface SegmentedControlOption { value: T; label: string; icon?: SegmentedControlIconRenderer; disabled?: boolean; testID?: string; -}; +} -type SegmentedControlProps = { +interface SegmentedControlProps { options: SegmentedControlOption[]; value: T; onValueChange: (value: T) => void; @@ -23,7 +23,7 @@ type SegmentedControlProps = { hideLabels?: boolean; style?: StyleProp; testID?: string; -}; +} export function SegmentedControl({ options, diff --git a/packages/app/src/components/ui/tooltip.tsx b/packages/app/src/components/ui/tooltip.tsx index add551c15..af3560581 100644 --- a/packages/app/src/components/ui/tooltip.tsx +++ b/packages/app/src/components/ui/tooltip.tsx @@ -41,14 +41,14 @@ interface Rect { height: number; } -type TooltipContextValue = { +interface TooltipContextValue { open: boolean; setOpen: (open: boolean) => void; triggerRef: React.RefObject; enabled: boolean; openOnPress: boolean; delayDuration: number; -}; +} const TooltipContext = createContext(null); diff --git a/packages/app/src/components/use-bottom-anchor-controller.ts b/packages/app/src/components/use-bottom-anchor-controller.ts index 55457bebe..7de3e56cc 100644 --- a/packages/app/src/components/use-bottom-anchor-controller.ts +++ b/packages/app/src/components/use-bottom-anchor-controller.ts @@ -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; diff --git a/packages/app/src/components/web-desktop-scrollbar.math.ts b/packages/app/src/components/web-desktop-scrollbar.math.ts index 05a7f3259..cdf155d7a 100644 --- a/packages/app/src/components/web-desktop-scrollbar.math.ts +++ b/packages/app/src/components/web-desktop-scrollbar.math.ts @@ -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) { diff --git a/packages/app/src/components/web-desktop-scrollbar.tsx b/packages/app/src/components/web-desktop-scrollbar.tsx index ce0977038..63b929a5c 100644 --- a/packages/app/src/components/web-desktop-scrollbar.tsx +++ b/packages/app/src/components/web-desktop-scrollbar.tsx @@ -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, diff --git a/packages/app/src/components/welcome-screen.tsx b/packages/app/src/components/welcome-screen.tsx index 52e740590..e21ed41f8 100644 --- a/packages/app/src/components/welcome-screen.tsx +++ b/packages/app/src/components/welcome-screen.tsx @@ -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: { diff --git a/packages/app/src/contexts/session-stream-reducers.ts b/packages/app/src/contexts/session-stream-reducers.ts index e74bf8803..e47b1064d 100644 --- a/packages/app/src/contexts/session-stream-reducers.ts +++ b/packages/app/src/contexts/session-stream-reducers.ts @@ -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; 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; -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) => Map) => 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; diff --git a/packages/app/src/desktop/daemon/desktop-daemon.ts b/packages/app/src/desktop/daemon/desktop-daemon.ts index 9204dc7b3..4bd0dc550 100644 --- a/packages/app/src/desktop/daemon/desktop-daemon.ts +++ b/packages/app/src/desktop/daemon/desktop-daemon.ts @@ -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 { return typeof value === "object" && value !== null; diff --git a/packages/app/src/desktop/electron/events.ts b/packages/app/src/desktop/electron/events.ts index 409f13a06..095cac731 100644 --- a/packages/app/src/desktop/electron/events.ts +++ b/packages/app/src/desktop/electron/events.ts @@ -2,9 +2,9 @@ import { getDesktopHost } from "@/desktop/host"; export type DesktopEventUnlisten = () => void; -type EventEnvelope = { +interface EventEnvelope { payload?: unknown; -}; +} export async function listenToDesktopEvent( event: string, diff --git a/packages/app/src/desktop/permissions/desktop-permissions.test.ts b/packages/app/src/desktop/permissions/desktop-permissions.test.ts index 899b4e663..a773cb767 100644 --- a/packages/app/src/desktop/permissions/desktop-permissions.test.ts +++ b/packages/app/src/desktop/permissions/desktop-permissions.test.ts @@ -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, diff --git a/packages/app/src/desktop/permissions/desktop-permissions.ts b/packages/app/src/desktop/permissions/desktop-permissions.ts index 9e10ca8ac..12964e1ea 100644 --- a/packages/app/src/desktop/permissions/desktop-permissions.ts +++ b/packages/app/src/desktop/permissions/desktop-permissions.ts @@ -22,27 +22,27 @@ export interface DesktopPermissionSnapshot { microphone: DesktopPermissionStatus; } -type NotificationConstructorLike = { +interface NotificationConstructorLike { permission?: string; requestPermission?: () => Promise; -}; +} -type MediaStreamTrackLike = { +interface MediaStreamTrackLike { stop?: () => void; -}; +} -type MediaStreamLike = { +interface MediaStreamLike { getTracks?: () => MediaStreamTrackLike[]; -}; +} -type NavigatorLike = { +interface NavigatorLike { mediaDevices?: { getUserMedia?: (constraints: { audio: boolean }) => Promise; }; permissions?: { query?: (descriptor: { name: string }) => Promise<{ state?: string }>; }; -}; +} export function shouldShowDesktopPermissionSection(): boolean { return isWeb && getDesktopHost() !== null; diff --git a/packages/app/src/dictation/dictation-stream-sender.test.ts b/packages/app/src/dictation/dictation-stream-sender.test.ts index d7c6d9eaf..9fa75315d 100644 --- a/packages/app/src/dictation/dictation-stream-sender.test.ts +++ b/packages/app/src/dictation/dictation-stream-sender.test.ts @@ -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; diff --git a/packages/app/src/dictation/dictation-stream-sender.ts b/packages/app/src/dictation/dictation-stream-sender.ts index a4bbf218e..8729a8b3b 100644 --- a/packages/app/src/dictation/dictation-stream-sender.ts +++ b/packages/app/src/dictation/dictation-stream-sender.ts @@ -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. diff --git a/packages/app/src/hooks/use-agent-form-state.ts b/packages/app/src/hooks/use-agent-form-state.ts index e39ae2b97..be93c0241 100644 --- a/packages/app/src/hooks/use-agent-form-state.ts +++ b/packages/app/src/hooks/use-agent-form-state.ts @@ -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; -}; +} function normalizeSelectedModelId(modelId: string | null | undefined): string { const normalized = typeof modelId === "string" ? modelId.trim() : ""; diff --git a/packages/app/src/hooks/use-agent-history.ts b/packages/app/src/hooks/use-agent-history.ts index b65064c0b..265a07cb1 100644 --- a/packages/app/src/hooks/use-agent-history.ts +++ b/packages/app/src/hooks/use-agent-history.ts @@ -26,10 +26,10 @@ export interface AgentHistoryResult { loadMore: () => void; } -type AgentHistoryPage = { +interface AgentHistoryPage { agents: AggregatedAgent[]; pageInfo: FetchAgentHistoryPageInfo; -}; +} async function fetchAgentHistoryPage(input: { client: DaemonClient; diff --git a/packages/app/src/hooks/use-agent-input-draft.ts b/packages/app/src/hooks/use-agent-input-draft.ts index 081090307..73e6e08be 100644 --- a/packages/app/src/hooks/use-agent-input-draft.ts +++ b/packages/app/src/hooks/use-agent-input-draft.ts @@ -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; diff --git a/packages/app/src/hooks/use-client-activity.test.tsx b/packages/app/src/hooks/use-client-activity.test.tsx index b89eab1fc..f3747c804 100644 --- a/packages/app/src/hooks/use-client-activity.test.tsx +++ b/packages/app/src/hooks/use-client-activity.test.tsx @@ -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: { diff --git a/packages/app/src/hooks/use-command-center.ts b/packages/app/src/hooks/use-command-center.ts index 33f9c2606..35328748c 100644 --- a/packages/app/src/hooks/use-command-center.ts +++ b/packages/app/src/hooks/use-command-center.ts @@ -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 = | { diff --git a/packages/app/src/hooks/use-dictation-audio-source.types.ts b/packages/app/src/hooks/use-dictation-audio-source.types.ts index 08d4e124b..331c53945 100644 --- a/packages/app/src/hooks/use-dictation-audio-source.types.ts +++ b/packages/app/src/hooks/use-dictation-audio-source.types.ts @@ -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; stop: () => Promise; volume: number; -}; +} diff --git a/packages/app/src/hooks/use-dictation-audio-source.web.ts b/packages/app/src/hooks/use-dictation-audio-source.web.ts index b982597de..5e20c6a34 100644 --- a/packages/app/src/hooks/use-dictation-audio-source.web.ts +++ b/packages/app/src/hooks/use-dictation-audio-source.web.ts @@ -82,13 +82,13 @@ const int16ToBase64 = (pcm: Int16Array): string => { return btoa(binary); }; -type RecorderRefs = { +interface RecorderRefs { recorder: MediaRecorder | null; audioChunks: Blob[]; stoppedPromise: Promise | null; stoppedResolve: ((blob: Blob) => void) | null; stoppedReject: ((error: unknown) => void) | null; -}; +} export function useDictationAudioSource(config: DictationAudioSourceConfig): DictationAudioSource { const [volume, setVolume] = useState(0); diff --git a/packages/app/src/hooks/use-dictation.shared.ts b/packages/app/src/hooks/use-dictation.shared.ts index bd74c836b..14d3eaa32 100644 --- a/packages/app/src/hooks/use-dictation.shared.ts +++ b/packages/app/src/hooks/use-dictation.shared.ts @@ -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; discardFailedDictation: () => void; reset: () => void; -}; +} export const DURATION_TICK_MS = 1000; export const PCM_DICTATION_FORMAT = "audio/pcm;rate=16000;bits=16"; diff --git a/packages/app/src/hooks/use-draft-agent-create-flow.ts b/packages/app/src/hooks/use-draft-agent-create-flow.ts index a346818bd..ea5eba739 100644 --- a/packages/app/src/hooks/use-draft-agent-create-flow.ts +++ b/packages/app/src/hooks/use-draft-agent-create-flow.ts @@ -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 = { +interface CreateRequestResult { 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 { draftId: string; diff --git a/packages/app/src/hooks/use-file-drop-zone.ts b/packages/app/src/hooks/use-file-drop-zone.ts index 65ce91426..cb6cfb004 100644 --- a/packages/app/src/hooks/use-file-drop-zone.ts +++ b/packages/app/src/hooks/use-file-drop-zone.ts @@ -46,9 +46,9 @@ type DesktopDragDropPayload = type: "leave"; }; -type DesktopDragDropEvent = { +interface DesktopDragDropEvent { payload: DesktopDragDropPayload; -}; +} function isImageFile(file: File): boolean { return file.type.startsWith("image/"); diff --git a/packages/app/src/hooks/use-hover-safe-zone.test.tsx b/packages/app/src/hooks/use-hover-safe-zone.test.tsx index 616e9fd80..1899b61ad 100644 --- a/packages/app/src/hooks/use-hover-safe-zone.test.tsx +++ b/packages/app/src/hooks/use-hover-safe-zone.test.tsx @@ -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; diff --git a/packages/app/src/hooks/use-keyboard-action-handler.ts b/packages/app/src/hooks/use-keyboard-action-handler.ts index e014b578e..dda2bd85d 100644 --- a/packages/app/src/hooks/use-keyboard-action-handler.ts +++ b/packages/app/src/hooks/use-keyboard-action-handler.ts @@ -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(() => { diff --git a/packages/app/src/hooks/use-providers-snapshot.test.ts b/packages/app/src/hooks/use-providers-snapshot.test.ts index cdfdef63f..ce8b9c6e3 100644 --- a/packages/app/src/hooks/use-providers-snapshot.test.ts +++ b/packages/app/src/hooks/use-providers-snapshot.test.ts @@ -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["result"]; const { mockClient, mockRuntime, snapshotUpdateListeners } = vi.hoisted(() => { diff --git a/packages/app/src/keyboard/keyboard-action-dispatcher.ts b/packages/app/src/keyboard/keyboard-action-dispatcher.ts index 88d57b8e7..0adc733e4 100644 --- a/packages/app/src/keyboard/keyboard-action-dispatcher.ts +++ b/packages/app/src/keyboard/keyboard-action-dispatcher.ts @@ -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; diff --git a/packages/app/src/keyboard/keyboard-shortcuts.test.ts b/packages/app/src/keyboard/keyboard-shortcuts.test.ts index ddcffc0c2..18cdcc9b7 100644 --- a/packages/app/src/keyboard/keyboard-shortcuts.test.ts +++ b/packages/app/src/keyboard/keyboard-shortcuts.test.ts @@ -94,7 +94,7 @@ function expectNoShortcutResolution(input: { expect(result.nextChordState).toEqual(initialChordState()); } -type MatchingShortcutCase = { +interface MatchingShortcutCase { name: string; event: Partial; context?: Partial; @@ -102,22 +102,22 @@ type MatchingShortcutCase = { payload?: unknown; preventDefault?: boolean; stopPropagation?: boolean; -}; +} -type NonMatchingShortcutCase = { +interface NonMatchingShortcutCase { name: string; event: Partial; context?: Partial; -}; +} -type HelpSectionCase = { +interface HelpSectionCase { name: string; context: { isMac: boolean; isDesktop: boolean; }; expectedKeys: Record; -}; +} describe("keyboard-shortcuts", () => { const matchingCases: MatchingShortcutCase[] = [ diff --git a/packages/app/src/keyboard/keyboard-shortcuts.ts b/packages/app/src/keyboard/keyboard-shortcuts.ts index 7c2c93b4a..f2b9a378a 100644 --- a/packages/app/src/keyboard/keyboard-shortcuts.ts +++ b/packages/app/src/keyboard/keyboard-shortcuts.ts @@ -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 */ diff --git a/packages/app/src/panels/agent-panel.test.tsx b/packages/app/src/panels/agent-panel.test.tsx index e4c024445..daa288b48 100644 --- a/packages/app/src/panels/agent-panel.test.tsx +++ b/packages/app/src/panels/agent-panel.test.tsx @@ -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; fontWeight: Record; iconSize: Record; -}; +} type PanelTestStyles = Record; type PanelTestStyleFactory = (input: PanelTestTheme) => PanelTestStyles; diff --git a/packages/app/src/runtime/host-runtime.ts b/packages/app/src/runtime/host-runtime.ts index 7e03ea3d8..193c07891 100644 --- a/packages/app/src/runtime/host-runtime.ts +++ b/packages/app/src/runtime/host-runtime.ts @@ -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; clientGeneration: number; -}; +} type HostRuntimeSnapshotPatch = Partial>; @@ -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; -}; +} -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; diff --git a/packages/app/src/screens/agent/agent-ready-screen-bottom-anchor.ts b/packages/app/src/screens/agent/agent-ready-screen-bottom-anchor.ts index 393326158..7b2bedf13 100644 --- a/packages/app/src/screens/agent/agent-ready-screen-bottom-anchor.ts +++ b/packages/app/src/screens/agent/agent-ready-screen-bottom-anchor.ts @@ -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; diff --git a/packages/app/src/screens/startup-splash-screen.tsx b/packages/app/src/screens/startup-splash-screen.tsx index 15157877c..cbd6a7dc0 100644 --- a/packages/app/src/screens/startup-splash-screen.tsx +++ b/packages/app/src/screens/startup-splash-screen.tsx @@ -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"; diff --git a/packages/app/src/screens/workspace/use-workspace-tab-layout.ts b/packages/app/src/screens/workspace/use-workspace-tab-layout.ts index 967dc9be8..d7ee879cd 100644 --- a/packages/app/src/screens/workspace/use-workspace-tab-layout.ts +++ b/packages/app/src/screens/workspace/use-workspace-tab-layout.ts @@ -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, diff --git a/packages/app/src/screens/workspace/workspace-bulk-close.ts b/packages/app/src/screens/workspace/workspace-bulk-close.ts index 647799b46..73fe19049 100644 --- a/packages/app/src/screens/workspace/workspace-bulk-close.ts +++ b/packages/app/src/screens/workspace/workspace-bulk-close.ts @@ -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; diff --git a/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx b/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx index 879f50c38..f4e8871c2 100644 --- a/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx +++ b/packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx @@ -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") { diff --git a/packages/app/src/screens/workspace/workspace-draft-agent-tab.tsx b/packages/app/src/screens/workspace/workspace-draft-agent-tab.tsx index c003f4f68..a43371e00 100644 --- a/packages/app/src/screens/workspace/workspace-draft-agent-tab.tsx +++ b/packages/app/src/screens/workspace/workspace-draft-agent-tab.tsx @@ -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, diff --git a/packages/app/src/screens/workspace/workspace-screen.tsx b/packages/app/src/screens/workspace/workspace-screen.tsx index c8875f406..70978aff9 100644 --- a/packages/app/src/screens/workspace/workspace-screen.tsx +++ b/packages/app/src/screens/workspace/workspace-screen.tsx @@ -129,11 +129,11 @@ const EMPTY_UI_TABS: WorkspaceTab[] = []; const EMPTY_PINNED_AGENT_IDS = new Set(); const EMPTY_SET = new Set(); -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; onCloseTabsBelow: (tabId: string) => Promise | void; onCloseOtherTabs: (tabId: string) => Promise | void; -}; +} function MobileActiveTabTrigger({ activeTab, diff --git a/packages/app/src/screens/workspace/workspace-tab-layout.ts b/packages/app/src/screens/workspace/workspace-tab-layout.ts index b625f7159..4bd8892db 100644 --- a/packages/app/src/screens/workspace/workspace-tab-layout.ts +++ b/packages/app/src/screens/workspace/workspace-tab-layout.ts @@ -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) { diff --git a/packages/app/src/screens/workspace/workspace-tab-presentation.tsx b/packages/app/src/screens/workspace/workspace-tab-presentation.tsx index 5116cb7b4..e14aa3aba 100644 --- a/packages/app/src/screens/workspace/workspace-tab-presentation.tsx +++ b/packages/app/src/screens/workspace/workspace-tab-presentation.tsx @@ -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>; @@ -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, diff --git a/packages/app/src/stores/create-flow-store.ts b/packages/app/src/stores/create-flow-store.ts index 7604159a0..a1f7a9ed0 100644 --- a/packages/app/src/stores/create-flow-store.ts +++ b/packages/app/src/stores/create-flow-store.ts @@ -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; setPending: (pending: Omit) => 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((set) => ({ pendingByDraftId: {}, diff --git a/packages/app/src/stores/download-store.ts b/packages/app/src/stores/download-store.ts index 3c9bec08c..c72f7c9dd 100644 --- a/packages/app/src/stores/download-store.ts +++ b/packages/app/src/stores/download-store.ts @@ -236,11 +236,11 @@ function findMostRecentDownloadId(downloads: Map): 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; diff --git a/packages/app/src/stores/draft-store.ts b/packages/app/src/stores/draft-store.ts index 410f112fa..b15c0a5aa 100644 --- a/packages/app/src/stores/draft-store.ts +++ b/packages/app/src/stores/draft-store.ts @@ -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; diff --git a/packages/app/src/stores/navigation-active-workspace-store.ts b/packages/app/src/stores/navigation-active-workspace-store.ts index 35eb2f086..f39bf8b20 100644 --- a/packages/app/src/stores/navigation-active-workspace-store.ts +++ b/packages/app/src/stores/navigation-active-workspace-store.ts @@ -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 } diff --git a/packages/app/src/stores/session-store.ts b/packages/app/src/stores/session-store.ts index 027aec045..cd5c646c6 100644 --- a/packages/app/src/stores/session-store.ts +++ b/packages/app/src/stores/session-store.ts @@ -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; diff --git a/packages/app/src/stores/sidebar-collapsed-sections-store.ts b/packages/app/src/stores/sidebar-collapsed-sections-store.ts index d2f61348e..43013074d 100644 --- a/packages/app/src/stores/sidebar-collapsed-sections-store.ts +++ b/packages/app/src/stores/sidebar-collapsed-sections-store.ts @@ -8,9 +8,9 @@ interface SidebarCollapsedSectionsState { setProjectCollapsed: (projectKey: string, collapsed: boolean) => void; } -type PersistedSidebarCollapsedSectionsState = { +interface PersistedSidebarCollapsedSectionsState { collapsedProjectKeys?: string[]; -}; +} function serializeCollapsedProjectKeys(keys: Set): string[] { return Array.from(keys); diff --git a/packages/app/src/stores/workspace-draft-submission-store.ts b/packages/app/src/stores/workspace-draft-submission-store.ts index 5f8b5cbfb..865a28b90 100644 --- a/packages/app/src/stores/workspace-draft-submission-store.ts +++ b/packages/app/src/stores/workspace-draft-submission-store.ts @@ -17,7 +17,7 @@ export interface PendingWorkspaceDraftSubmission { allowEmptyText?: boolean; } -type WorkspaceDraftSubmissionState = { +interface WorkspaceDraftSubmissionState { pendingByDraftId: Record; setPending: (submission: PendingWorkspaceDraftSubmission) => void; consumePending: (input: { @@ -25,7 +25,7 @@ type WorkspaceDraftSubmissionState = { workspaceId: string; draftId: string; }) => PendingWorkspaceDraftSubmission | null; -}; +} function matchesPendingSubmission( pending: PendingWorkspaceDraftSubmission | null | undefined, diff --git a/packages/app/src/stores/workspace-tabs-store.ts b/packages/app/src/stores/workspace-tabs-store.ts index 4cef62be7..dd4b8c8a7 100644 --- a/packages/app/src/stores/workspace-tabs-store.ts +++ b/packages/app/src/stores/workspace-tabs-store.ts @@ -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; tabOrderByWorkspace: Record; focusedTabIdByWorkspace: Record; @@ -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()( persist( diff --git a/packages/app/src/styles/unistyles.ts b/packages/app/src/styles/unistyles.ts index 3bb09dc8a..bab8cb8ea 100644 --- a/packages/app/src/styles/unistyles.ts +++ b/packages/app/src/styles/unistyles.ts @@ -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 {} diff --git a/packages/app/src/terminal/runtime/terminal-emulator-runtime.browser.test.ts b/packages/app/src/terminal/runtime/terminal-emulator-runtime.browser.test.ts index 04e14178e..e56eb81e5 100644 --- a/packages/app/src/terminal/runtime/terminal-emulator-runtime.browser.test.ts +++ b/packages/app/src/terminal/runtime/terminal-emulator-runtime.browser.test.ts @@ -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[] = []; diff --git a/packages/app/src/terminal/runtime/terminal-emulator-runtime.test.ts b/packages/app/src/terminal/runtime/terminal-emulator-runtime.test.ts index e8a5fe532..b3b2af2f0 100644 --- a/packages/app/src/terminal/runtime/terminal-emulator-runtime.test.ts +++ b/packages/app/src/terminal/runtime/terminal-emulator-runtime.test.ts @@ -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; diff --git a/packages/app/src/terminal/runtime/terminal-emulator-runtime.ts b/packages/app/src/terminal/runtime/terminal-emulator-runtime.ts index 8fb79b01b..65b36a436 100644 --- a/packages/app/src/terminal/runtime/terminal-emulator-runtime.ts +++ b/packages/app/src/terminal/runtime/terminal-emulator-runtime.ts @@ -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; onResize?: (input: { rows: number; cols: number }) => Promise | void; onTerminalKey?: (input: { @@ -37,9 +37,9 @@ export type TerminalEmulatorRuntimeCallbacks = { }) => Promise | void; onPendingModifiersConsumed?: () => Promise | void; onOpenExternalUrl?: (url: string) => Promise | 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 { diff --git a/packages/app/src/terminal/runtime/terminal-snapshot.test.ts b/packages/app/src/terminal/runtime/terminal-snapshot.test.ts index e3570115c..bf2333157 100644 --- a/packages/app/src/terminal/runtime/terminal-snapshot.test.ts +++ b/packages/app/src/terminal/runtime/terminal-snapshot.test.ts @@ -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, diff --git a/packages/app/src/terminal/runtime/terminal-snapshot.ts b/packages/app/src/terminal/runtime/terminal-snapshot.ts index 67a830208..c739db076 100644 --- a/packages/app/src/terminal/runtime/terminal-snapshot.ts +++ b/packages/app/src/terminal/runtime/terminal-snapshot.ts @@ -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, diff --git a/packages/app/src/terminal/runtime/terminal-stream-controller.test.ts b/packages/app/src/terminal/runtime/terminal-stream-controller.test.ts index 541481b6d..097feea70 100644 --- a/packages/app/src/terminal/runtime/terminal-stream-controller.test.ts +++ b/packages/app/src/terminal/runtime/terminal-stream-controller.test.ts @@ -6,13 +6,13 @@ import { type TerminalStreamControllerStatus, } from "./terminal-stream-controller"; -type TerminalSnapshot = { +interface TerminalSnapshot { rows: number; cols: number; grid: Array>; scrollback: Array>; cursor: { row: number; col: number }; -}; +} type TerminalStreamEvent = | { terminalId: string; type: "output"; data: Uint8Array } diff --git a/packages/app/src/terminal/runtime/terminal-stream-controller.ts b/packages/app/src/terminal/runtime/terminal-stream-controller.ts index b5978b64c..1e42a7199 100644 --- a/packages/app/src/terminal/runtime/terminal-stream-controller.ts +++ b/packages/app/src/terminal/runtime/terminal-stream-controller.ts @@ -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"; diff --git a/packages/app/src/terminal/runtime/workspace-terminal-session.ts b/packages/app/src/terminal/runtime/workspace-terminal-session.ts index d45c16468..5dcabbd05 100644 --- a/packages/app/src/terminal/runtime/workspace-terminal-session.ts +++ b/packages/app/src/terminal/runtime/workspace-terminal-session.ts @@ -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; session: WorkspaceTerminalSession; -}; +} const sessionsByScopeKey = new Map(); const refCountByScopeKey = new Map(); diff --git a/packages/app/src/types/agent-activity.ts b/packages/app/src/types/agent-activity.ts index 7e100798d..28c987b20 100644 --- a/packages/app/src/types/agent-activity.ts +++ b/packages/app/src/types/agent-activity.ts @@ -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 & { insertIndex: number; diff --git a/packages/app/src/types/host-connection.ts b/packages/app/src/types/host-connection.ts index d470df2a2..7d0191de5 100644 --- a/packages/app/src/types/host-connection.ts +++ b/packages/app/src/types/host-connection.ts @@ -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; -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 {}; diff --git a/packages/app/src/types/stream.harness.test.ts b/packages/app/src/types/stream.harness.test.ts index e4d07bc71..d032abc80 100644 --- a/packages/app/src/types/stream.harness.test.ts +++ b/packages/app/src/types/stream.harness.test.ts @@ -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 = { diff --git a/packages/app/src/types/stream.ts b/packages/app/src/types/stream.ts index 0b37243cd..647c796c0 100644 --- a/packages/app/src/types/stream.ts +++ b/packages/app/src/types/stream.ts @@ -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"; diff --git a/packages/app/src/utils/agent-directory-sync.ts b/packages/app/src/utils/agent-directory-sync.ts index f9526df46..1c5bb28fb 100644 --- a/packages/app/src/utils/agent-directory-sync.ts +++ b/packages/app/src/utils/agent-directory-sync.ts @@ -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; diff --git a/packages/app/src/utils/branch-suggestions.ts b/packages/app/src/utils/branch-suggestions.ts index 40295a89f..5c35e1fec 100644 --- a/packages/app/src/utils/branch-suggestions.ts +++ b/packages/app/src/utils/branch-suggestions.ts @@ -1,7 +1,7 @@ -export type BranchComboOption = { +export interface BranchComboOption { id: string; label: string; -}; +} export function normalizeBranchOptionName(input: string | null | undefined): string | null { const trimmed = input?.trim(); diff --git a/packages/app/src/utils/confirm-dialog.test.ts b/packages/app/src/utils/confirm-dialog.test.ts index 702297bc9..b5d4b48b8 100644 --- a/packages/app/src/utils/confirm-dialog.test.ts +++ b/packages/app/src/utils/confirm-dialog.test.ts @@ -10,9 +10,9 @@ const desktopHostState = { type MockPlatform = "web" | "ios" | "android"; -type AlertButton = { +interface AlertButton { onPress?: () => void; -}; +} async function loadModuleForPlatform(platform: MockPlatform): Promise<{ confirmDialog: typeof import("./confirm-dialog").confirmDialog; diff --git a/packages/app/src/utils/connection-selection.ts b/packages/app/src/utils/connection-selection.ts index 60bebbf95..40a314437 100644 --- a/packages/app/src/utils/connection-selection.ts +++ b/packages/app/src/utils/connection-selection.ts @@ -1,19 +1,19 @@ import type { HostConnection } from "@/types/host-connection"; -export type ConnectionCandidate = { +export interface ConnectionCandidate { connectionId: string; connection: HostConnection; -}; +} export type ConnectionProbeState = | { status: "pending"; latencyMs: null } | { status: "unavailable"; latencyMs: null } | { status: "available"; latencyMs: number }; -export type SelectBestConnectionInput = { +export interface SelectBestConnectionInput { candidates: ConnectionCandidate[]; probeByConnectionId: Map; -}; +} function getAvailableLatency(input: { connectionId: string; diff --git a/packages/app/src/utils/desktop-window.ts b/packages/app/src/utils/desktop-window.ts index 346092ca6..b374b5c76 100644 --- a/packages/app/src/utils/desktop-window.ts +++ b/packages/app/src/utils/desktop-window.ts @@ -11,11 +11,11 @@ import { getDesktopWindow } from "@/desktop/electron/window"; import { usePanelStore } from "@/stores/panel-store"; import { isNative } from "@/constants/platform"; -type RawWindowControlsPadding = { +interface RawWindowControlsPadding { left: number; right: number; top: number; -}; +} type WindowControlsPaddingRole = | "sidebar" diff --git a/packages/app/src/utils/markdown-list.ts b/packages/app/src/utils/markdown-list.ts index 7221652a9..2334e05f1 100644 --- a/packages/app/src/utils/markdown-list.ts +++ b/packages/app/src/utils/markdown-list.ts @@ -1,4 +1,4 @@ -type MarkdownNode = { +interface MarkdownNode { type?: string; index?: number; markup?: string; @@ -6,7 +6,7 @@ type MarkdownNode = { start?: number | string; }; children?: MarkdownNode[]; -}; +} const LIST_BULLET = "•"; const DEFAULT_ORDERED_LIST_MARKUP = "."; diff --git a/packages/app/src/utils/os-notifications.test.ts b/packages/app/src/utils/os-notifications.test.ts index 2b6207eab..5dcfdb84d 100644 --- a/packages/app/src/utils/os-notifications.test.ts +++ b/packages/app/src/utils/os-notifications.test.ts @@ -1,25 +1,25 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -type MockNotificationOptions = { +interface MockNotificationOptions { body?: string; data?: Record; icon?: string; -}; +} -type MockNotificationInstance = { +interface MockNotificationInstance { title: string; options?: MockNotificationOptions; onclick: ((event: Event) => void) | null; close: ReturnType; -}; +} -type GlobalSnapshot = { +interface GlobalSnapshot { Notification: unknown; CustomEvent: unknown; dispatchEvent: unknown; focus: unknown; location: unknown; -}; +} const originalGlobals: GlobalSnapshot = { Notification: (globalThis as { Notification?: unknown }).Notification, diff --git a/packages/app/src/utils/os-notifications.ts b/packages/app/src/utils/os-notifications.ts index 33765e4a1..16bff8c30 100644 --- a/packages/app/src/utils/os-notifications.ts +++ b/packages/app/src/utils/os-notifications.ts @@ -3,19 +3,19 @@ import { getDesktopHost } from "@/desktop/host"; import { buildNotificationRoute, resolveNotificationTarget } from "./notification-routing"; import { isNative } from "@/constants/platform"; -type OsNotificationPayload = { +interface OsNotificationPayload { title: string; body?: string; data?: Record; -}; +} -export type WebNotificationClickDetail = { +export interface WebNotificationClickDetail { data?: Record; -}; +} -type WebNotificationInstance = { +interface WebNotificationInstance { onclick?: ((event: Event) => void) | null; -}; +} export const WEB_NOTIFICATION_CLICK_EVENT = "paseo:web-notification-click"; diff --git a/packages/app/src/utils/pending-create-images.ts b/packages/app/src/utils/pending-create-images.ts index a2b034c08..c84f1ff42 100644 --- a/packages/app/src/utils/pending-create-images.ts +++ b/packages/app/src/utils/pending-create-images.ts @@ -1,10 +1,10 @@ import type { StreamItem, UserMessageImageAttachment } from "@/types/stream"; -type MergePendingCreateImagesParams = { +interface MergePendingCreateImagesParams { streamItems: StreamItem[]; clientMessageId: string; images?: UserMessageImageAttachment[]; -}; +} export function mergePendingCreateImages({ streamItems, diff --git a/packages/app/src/utils/terminal-keys.ts b/packages/app/src/utils/terminal-keys.ts index bafd5d2e8..4ce6cf6cf 100644 --- a/packages/app/src/utils/terminal-keys.ts +++ b/packages/app/src/utils/terminal-keys.ts @@ -1,8 +1,8 @@ -export type PendingTerminalModifiers = { +export interface PendingTerminalModifiers { ctrl: boolean; shift: boolean; alt: boolean; -}; +} const MODIFIER_DOM_KEYS = new Set(["Control", "Shift", "Alt", "Meta", "AltGraph", "OS"]); diff --git a/packages/app/src/utils/tool-call-parsers.ts b/packages/app/src/utils/tool-call-parsers.ts index 57f0b6f17..5ed71f0d7 100644 --- a/packages/app/src/utils/tool-call-parsers.ts +++ b/packages/app/src/utils/tool-call-parsers.ts @@ -1,15 +1,15 @@ import { z } from "zod"; -export type DiffSegment = { +export interface DiffSegment { text: string; changed: boolean; -}; +} -export type DiffLine = { +export interface DiffLine { type: "add" | "remove" | "context" | "header"; content: string; segments?: DiffSegment[]; -}; +} function splitIntoLines(text: string): string[] { if (!text) { @@ -257,11 +257,11 @@ export function parseUnifiedDiff(diffText?: string): DiffLine[] { export type TaskStatus = "pending" | "in_progress" | "completed"; -export type TaskEntry = { +export interface TaskEntry { text: string; status: TaskStatus; completed: boolean; -}; +} const TaskStatusSchema = z.enum(["pending", "in_progress", "completed"]); diff --git a/packages/app/src/utils/web-focus.ts b/packages/app/src/utils/web-focus.ts index 6b940afec..02350fdcd 100644 --- a/packages/app/src/utils/web-focus.ts +++ b/packages/app/src/utils/web-focus.ts @@ -1,10 +1,10 @@ -type FocusWithRetriesOptions = { +interface FocusWithRetriesOptions { focus: () => void; isFocused: () => boolean; timeoutMs?: number; onSuccess?: () => void; onTimeout?: () => void; -}; +} export function focusWithRetries({ focus, diff --git a/packages/app/src/utils/workspace-execution.ts b/packages/app/src/utils/workspace-execution.ts index 0595539eb..a135a7ee6 100644 --- a/packages/app/src/utils/workspace-execution.ts +++ b/packages/app/src/utils/workspace-execution.ts @@ -1,11 +1,11 @@ import type { WorkspaceDescriptor } from "@/stores/session-store"; import { normalizeWorkspaceOpaqueId, normalizeWorkspacePath } from "@/utils/workspace-identity"; -export type WorkspaceAuthorityResult = { +export interface WorkspaceAuthorityResult { workspaceId: string; workspaceDirectory: string; workspace: WorkspaceDescriptor; -}; +} export type WorkspaceExecutionAuthorityFailureReason = | "workspace_id_missing" diff --git a/packages/app/src/utils/workspace-script-links.ts b/packages/app/src/utils/workspace-script-links.ts index 5d096c876..177213961 100644 --- a/packages/app/src/utils/workspace-script-links.ts +++ b/packages/app/src/utils/workspace-script-links.ts @@ -2,10 +2,10 @@ import { parseHostPort } from "@server/shared/daemon-endpoints"; import type { WorkspaceScriptPayload } from "@server/shared/messages"; import type { ActiveConnection } from "@/runtime/host-runtime"; -export type ResolvedWorkspaceScriptLink = { +export interface ResolvedWorkspaceScriptLink { openUrl: string | null; labelUrl: string | null; -}; +} function isLoopbackHost(host: string): boolean { const normalizedHost = host.trim().toLowerCase(); diff --git a/packages/app/src/voice/voice-runtime.ts b/packages/app/src/voice/voice-runtime.ts index 30c48cfa4..073154371 100644 --- a/packages/app/src/voice/voice-runtime.ts +++ b/packages/app/src/voice/voice-runtime.ts @@ -85,13 +85,13 @@ interface RuntimeState { type AudioOutputPayload = Extract["payload"]; -type StreamingPlaybackChunk = { +interface StreamingPlaybackChunk { id: string; chunkIndex: number; source: { arrayBuffer(): Promise; size: number; type: string }; -}; +} -type StreamingPlaybackGroup = { +interface StreamingPlaybackGroup { groupId: string; isVoiceMode: boolean; shouldPlay: boolean; @@ -100,7 +100,7 @@ type StreamingPlaybackGroup = { finalChunkIndex: number | null; started: boolean; ackedChunkIds: Set; -}; +} interface RuntimePlaybackState { groups: Map; diff --git a/packages/cli/src/commands/daemon/local-daemon.ts b/packages/cli/src/commands/daemon/local-daemon.ts index 812a48ae4..3369dd106 100644 --- a/packages/cli/src/commands/daemon/local-daemon.ts +++ b/packages/cli/src/commands/daemon/local-daemon.ts @@ -54,11 +54,11 @@ export interface StopLocalDaemonResult { message: string; } -type ProcessExitDetails = { +interface ProcessExitDetails { code: number | null; signal: NodeJS.Signals | null; error?: Error; -}; +} type DetachedStartupResult = { exitedEarly: false } | ({ exitedEarly: true } & ProcessExitDetails); diff --git a/packages/cli/src/commands/daemon/status.ts b/packages/cli/src/commands/daemon/status.ts index a019f5855..bee4841d1 100644 --- a/packages/cli/src/commands/daemon/status.ts +++ b/packages/cli/src/commands/daemon/status.ts @@ -44,9 +44,9 @@ interface StatusRow { value: string; } -type CliPackageJson = { +interface CliPackageJson { version?: unknown; -}; +} const require = createRequire(import.meta.url); diff --git a/packages/cli/src/commands/onboard.ts b/packages/cli/src/commands/onboard.ts index 480e857a7..977a830bc 100644 --- a/packages/cli/src/commands/onboard.ts +++ b/packages/cli/src/commands/onboard.ts @@ -165,10 +165,10 @@ async function resolveVoiceSelection(mode: OnboardOptions["voice"]): Promise { const pidPath = join(paseoHome, "paseo.pid"); @@ -68,10 +68,10 @@ function readProcessCommand(pid: number): string | null { return command.length > 0 ? command : null; } -type DaemonStatus = { +interface DaemonStatus { localDaemon: string | null; pid: number | null; -}; +} async function readDaemonStatus(paseoHome: string): Promise { const result = diff --git a/packages/cli/tests/23-daemon-sigint-supervisor.test.ts b/packages/cli/tests/23-daemon-sigint-supervisor.test.ts index 76875c55a..1b76bc6b1 100644 --- a/packages/cli/tests/23-daemon-sigint-supervisor.test.ts +++ b/packages/cli/tests/23-daemon-sigint-supervisor.test.ts @@ -61,10 +61,10 @@ function signalProcessGroup(pid: number, signal: NodeJS.Signals): boolean { } } -type DaemonStatus = { +interface DaemonStatus { localDaemon: string | null; pid: number | null; -}; +} async function readDaemonStatus(paseoHome: string): Promise { const result = @@ -103,10 +103,10 @@ async function waitFor( throw new Error(message); } -type ExitResult = { +interface ExitResult { code: number | null; signal: NodeJS.Signals | null; -}; +} function waitForProcessExit(processRef: ChildProcess, timeoutMs: number): Promise { return new Promise((resolve, reject) => { diff --git a/packages/cli/tests/25-daemon-restart-supervisor.test.ts b/packages/cli/tests/25-daemon-restart-supervisor.test.ts index f3ff2db31..905146999 100644 --- a/packages/cli/tests/25-daemon-restart-supervisor.test.ts +++ b/packages/cli/tests/25-daemon-restart-supervisor.test.ts @@ -69,10 +69,10 @@ function readWorkerPid(supervisorPid: number): number | null { return null; } -type DaemonStatus = { +interface DaemonStatus { localDaemon: string | null; pid: number | null; -}; +} async function readDaemonStatus(paseoHome: string): Promise { const result = diff --git a/packages/cli/tests/26-daemon-restart-unsupervised.test.ts b/packages/cli/tests/26-daemon-restart-unsupervised.test.ts index d2f1f1d6a..d29e8c16d 100644 --- a/packages/cli/tests/26-daemon-restart-unsupervised.test.ts +++ b/packages/cli/tests/26-daemon-restart-unsupervised.test.ts @@ -54,10 +54,10 @@ async function waitFor( throw new Error(message); } -type ExitResult = { +interface ExitResult { code: number | null; signal: NodeJS.Signals | null; -}; +} function waitForProcessExit(processRef: ChildProcess, timeoutMs: number): Promise { return new Promise((resolve, reject) => { diff --git a/packages/cli/tests/helpers/test-daemon.ts b/packages/cli/tests/helpers/test-daemon.ts index ec48a3ebd..cbc127bf1 100644 --- a/packages/cli/tests/helpers/test-daemon.ts +++ b/packages/cli/tests/helpers/test-daemon.ts @@ -50,10 +50,10 @@ const TEST_OUTPUT_CAPTURE_LIMIT = Number.parseInt( 10, ); -type OutputCapture = { +interface OutputCapture { value: string; truncated: boolean; -}; +} function createOutputCapture(): OutputCapture { return { value: "", truncated: false }; diff --git a/packages/cli/tests/run-all.ts b/packages/cli/tests/run-all.ts index 6ed80d1fa..dcd7f0f08 100644 --- a/packages/cli/tests/run-all.ts +++ b/packages/cli/tests/run-all.ts @@ -36,7 +36,10 @@ for (let i = 0; i < args.length; i++) { $.verbose = false; -type Failure = { test: string; error: string }; +interface Failure { + test: string; + error: string; +} async function runCommand(label: string, command: string): Promise { console.log(`\n${"─".repeat(50)}`); diff --git a/packages/desktop/src/daemon/daemon-manager.ts b/packages/desktop/src/daemon/daemon-manager.ts index 62d35a347..a5ddc7460 100644 --- a/packages/desktop/src/daemon/daemon-manager.ts +++ b/packages/desktop/src/daemon/daemon-manager.ts @@ -44,7 +44,7 @@ const DETACHED_STARTUP_GRACE_MS = 1200; type DesktopDaemonState = "starting" | "running" | "stopped" | "errored"; -type DesktopDaemonStatus = { +interface DesktopDaemonStatus { serverId: string; status: DesktopDaemonState; listen: string | null; @@ -54,18 +54,18 @@ type DesktopDaemonStatus = { version: string | null; desktopManaged: boolean; error: string | null; -}; +} -type DesktopDaemonLogs = { +interface DesktopDaemonLogs { logPath: string; contents: string; -}; +} -type DesktopPairingOffer = { +interface DesktopPairingOffer { relayEnabled: boolean; url: string | null; qr: string | null; -}; +} type DesktopCommandHandler = (args?: Record) => Promise | unknown; diff --git a/packages/desktop/src/daemon/local-transport.ts b/packages/desktop/src/daemon/local-transport.ts index d63b6998f..d13364618 100644 --- a/packages/desktop/src/daemon/local-transport.ts +++ b/packages/desktop/src/daemon/local-transport.ts @@ -1,12 +1,12 @@ import { BrowserWindow } from "electron"; import WebSocket from "ws"; -type TransportTarget = { +interface TransportTarget { transportType: "socket" | "pipe"; transportPath: string; -}; +} -type TransportEventPayload = { +interface TransportEventPayload { sessionId: string; kind: "open" | "message" | "close" | "error"; text?: string | null; @@ -14,13 +14,13 @@ type TransportEventPayload = { code?: number | null; reason?: string | null; error?: string | null; -}; +} -type Session = { +interface Session { id: string; ws: WebSocket; state: "opening" | "open" | "closing" | "closed"; -}; +} const WS_ENDPOINT_PATH = "/ws"; diff --git a/packages/desktop/src/daemon/node-entrypoint-launcher.ts b/packages/desktop/src/daemon/node-entrypoint-launcher.ts index 06975f418..1a6068101 100644 --- a/packages/desktop/src/daemon/node-entrypoint-launcher.ts +++ b/packages/desktop/src/daemon/node-entrypoint-launcher.ts @@ -2,20 +2,20 @@ const IGNORED_ARG_PREFIXES = ["-psn_", "--no-sandbox"]; export const DESKTOP_CLI_ENV = "PASEO_DESKTOP_CLI"; -export type NodeEntrypointSpec = { +export interface NodeEntrypointSpec { entryPath: string; execArgv: string[]; -}; +} -export type NodeEntrypointInvocation = { +export interface NodeEntrypointInvocation { command: string; args: string[]; env: NodeJS.ProcessEnv; -}; +} export type NodeEntrypointArgvMode = "bare" | "node-script"; -type CreateNodeEntrypointInvocationInput = { +interface CreateNodeEntrypointInvocationInput { execPath: string; isPackaged: boolean; packagedRunnerPath: string | null; @@ -23,13 +23,13 @@ type CreateNodeEntrypointInvocationInput = { argvMode: NodeEntrypointArgvMode; args: string[]; baseEnv: NodeJS.ProcessEnv; -}; +} -type ParseCliPassthroughArgsFromArgvInput = { +interface ParseCliPassthroughArgsFromArgvInput { argv: string[]; isDefaultApp: boolean; forceCli: boolean; -}; +} export function createElectronNodeEnv( baseEnv: NodeJS.ProcessEnv, diff --git a/packages/desktop/src/daemon/runtime-paths.ts b/packages/desktop/src/daemon/runtime-paths.ts index d719123a3..ee3722882 100644 --- a/packages/desktop/src/daemon/runtime-paths.ts +++ b/packages/desktop/src/daemon/runtime-paths.ts @@ -18,9 +18,9 @@ const CLI_PACKAGE_NAME = "@getpaseo/cli"; const SERVER_PACKAGE_NAME = "@getpaseo/server"; const CLI_BIN_ENTRY = `${CLI_PACKAGE_NAME}/bin/paseo`; -type PackageInfo = { +interface PackageInfo { root: string; -}; +} const esmRequire = createRequire(__filename); diff --git a/packages/desktop/src/features/attachments.ts b/packages/desktop/src/features/attachments.ts index 8b56d91e8..da4336c92 100644 --- a/packages/desktop/src/features/attachments.ts +++ b/packages/desktop/src/features/attachments.ts @@ -6,10 +6,10 @@ const ATTACHMENTS_DIRNAME = "desktop-attachments"; const ATTACHMENT_ID_PATTERN = /^[A-Za-z0-9_-]+$/; const EXTENSION_PATTERN = /^\.[A-Za-z0-9]{1,16}$/; -type AttachmentFileResult = { +interface AttachmentFileResult { path: string; byteSize: number; -}; +} function attachmentsDirPath(): string { return path.join(resolvePaseoHome(process.env), ATTACHMENTS_DIRNAME); diff --git a/packages/desktop/src/features/auto-updater.ts b/packages/desktop/src/features/auto-updater.ts index 455677334..23a3064f9 100644 --- a/packages/desktop/src/features/auto-updater.ts +++ b/packages/desktop/src/features/auto-updater.ts @@ -5,20 +5,20 @@ import { autoUpdater, type UpdateInfo } from "electron-updater"; // Types // --------------------------------------------------------------------------- -export type AppUpdateCheckResult = { +export interface AppUpdateCheckResult { hasUpdate: boolean; readyToInstall: boolean; currentVersion: string; latestVersion: string; body: string | null; date: string | null; -}; +} -export type AppUpdateInstallResult = { +export interface AppUpdateInstallResult { installed: boolean; version: string | null; message: string; -}; +} export type AppReleaseChannel = "stable" | "beta"; diff --git a/packages/desktop/src/features/dialogs.ts b/packages/desktop/src/features/dialogs.ts index 1fe13e88b..4227cd3e1 100644 --- a/packages/desktop/src/features/dialogs.ts +++ b/packages/desktop/src/features/dialogs.ts @@ -1,19 +1,19 @@ import { dialog, ipcMain, BrowserWindow } from "electron"; -type AskOptions = { +interface AskOptions { title?: string; okLabel?: string; cancelLabel?: string; kind?: "info" | "warning" | "error"; -}; +} -type OpenOptions = { +interface OpenOptions { title?: string; defaultPath?: string; directory?: boolean; multiple?: boolean; filters?: Array<{ name: string; extensions: string[] }>; -}; +} export function registerDialogHandlers(): void { ipcMain.handle("paseo:dialog:ask", async (event, message: string, options?: AskOptions) => { diff --git a/packages/desktop/src/features/menu.ts b/packages/desktop/src/features/menu.ts index 0ccb119a9..71b06b536 100644 --- a/packages/desktop/src/features/menu.ts +++ b/packages/desktop/src/features/menu.ts @@ -1,9 +1,9 @@ import { app, Menu, BrowserWindow, ipcMain } from "electron"; -type ShowContextMenuInput = { +interface ShowContextMenuInput { kind?: "terminal"; hasSelection?: boolean; -}; +} function withBrowserWindow( callback: (win: BrowserWindow) => void, diff --git a/packages/desktop/src/features/notifications.ts b/packages/desktop/src/features/notifications.ts index 3d32c26d7..3b23e2e12 100644 --- a/packages/desktop/src/features/notifications.ts +++ b/packages/desktop/src/features/notifications.ts @@ -2,15 +2,15 @@ import path from "node:path"; import { existsSync } from "node:fs"; import { app, BrowserWindow, Notification, ipcMain, nativeImage } from "electron"; -type NotificationInput = { +interface NotificationInput { title?: unknown; body?: unknown; data?: unknown; -}; +} -type NotificationClickPayload = { +interface NotificationClickPayload { data?: Record; -}; +} const activeNotifications = new Set(); diff --git a/packages/desktop/src/features/react-devtools.ts b/packages/desktop/src/features/react-devtools.ts index 19f453406..5a3267523 100644 --- a/packages/desktop/src/features/react-devtools.ts +++ b/packages/desktop/src/features/react-devtools.ts @@ -5,18 +5,18 @@ import { app, session, net } from "electron"; const REACT_DEVTOOLS_EXTENSION_ID = "fmkadmapgofadopljbjfkapdkoienihi"; -type ReactDevToolsContentScript = { +interface ReactDevToolsContentScript { matches: string[]; js: string[]; run_at: "document_start" | "document_end"; world?: "MAIN"; -}; +} -type ReactDevToolsManifest = { +interface ReactDevToolsManifest { version?: string; manifest_version?: number; content_scripts?: ReactDevToolsContentScript[]; -}; +} const ELECTRON_COMPATIBLE_CONTENT_SCRIPTS: ReactDevToolsContentScript[] = [ { diff --git a/packages/desktop/src/window/window-manager.ts b/packages/desktop/src/window/window-manager.ts index 329a67d2a..8b44662eb 100644 --- a/packages/desktop/src/window/window-manager.ts +++ b/packages/desktop/src/window/window-manager.ts @@ -9,17 +9,17 @@ export function readBadgeCount(input: unknown): number { } export type WindowTheme = "light" | "dark"; -export type WindowControlsOverlayUpdate = { +export interface WindowControlsOverlayUpdate { height?: number; backgroundColor?: string; foregroundColor?: string; -}; +} -export type WindowControlsOverlayState = { +export interface WindowControlsOverlayState { height: number; backgroundColor?: string; foregroundColor?: string; -}; +} export function readWindowTheme(input: unknown): WindowTheme | null { if (input === "light" || input === "dark") { diff --git a/packages/expo-two-way-audio/src/events.ts b/packages/expo-two-way-audio/src/events.ts index 6e592aaa8..c3fb0176a 100644 --- a/packages/expo-two-way-audio/src/events.ts +++ b/packages/expo-two-way-audio/src/events.ts @@ -1,20 +1,20 @@ import ExpoTwoWayAudioModule from "./ExpoTwoWayAudioModule"; -export type MicrophoneDataEvent = { +export interface MicrophoneDataEvent { data: Uint8Array; -}; +} -export type VolumeLevelEvent = { +export interface VolumeLevelEvent { data: number; -}; +} -export type RecordingChangeEvent = { +export interface RecordingChangeEvent { data: boolean; -}; +} -export type AudioInterruptionEvent = { +export interface AudioInterruptionEvent { data: string; -}; +} export interface ExpoTwoWayAudioEventMap { onMicrophoneData: MicrophoneDataEvent; diff --git a/packages/relay/src/cloudflare-adapter.ts b/packages/relay/src/cloudflare-adapter.ts index ecc47885c..656edd966 100644 --- a/packages/relay/src/cloudflare-adapter.ts +++ b/packages/relay/src/cloudflare-adapter.ts @@ -34,10 +34,10 @@ function resolveRelayVersion(rawValue: string | null): RelayProtocolVersion | nu return null; } -type WebSocketPair = { +interface WebSocketPair { 0: WebSocket; 1: WebSocket; -}; +} interface DurableObjectState { acceptWebSocket(ws: WebSocket, tags?: string[]): void; diff --git a/packages/relay/src/crypto.ts b/packages/relay/src/crypto.ts index 8ad4487bd..979079895 100644 --- a/packages/relay/src/crypto.ts +++ b/packages/relay/src/crypto.ts @@ -15,10 +15,10 @@ import nacl from "tweetnacl"; import { fromByteArray, toByteArray } from "base64-js"; -export type KeyPair = { +export interface KeyPair { publicKey: Uint8Array; // 32 bytes secretKey: Uint8Array; // 32 bytes -}; +} export type SharedKey = Uint8Array; // 32 bytes (box.before) diff --git a/packages/relay/src/encrypted-channel.ts b/packages/relay/src/encrypted-channel.ts index 09b2826dd..06273b3b1 100644 --- a/packages/relay/src/encrypted-channel.ts +++ b/packages/relay/src/encrypted-channel.ts @@ -35,7 +35,7 @@ export interface EncryptedChannelEvents { type ChannelState = "connecting" | "handshaking" | "open" | "closed"; -type EncryptedChannelOptions = { +interface EncryptedChannelOptions { /** * If set, the channel can validate repeated plaintext `{type:"e2ee_hello"}` * messages even after it is open. @@ -45,7 +45,7 @@ type EncryptedChannelOptions = { * the daemon should re-send `{type:"e2ee_ready"}` without changing keys. */ daemonKeyPair?: KeyPair; -}; +} interface E2EEHelloMessage { type: "e2ee_hello"; diff --git a/packages/server/scripts/generate-sherpa-tts-matrix.ts b/packages/server/scripts/generate-sherpa-tts-matrix.ts index 7c03f6071..14bc4a396 100644 --- a/packages/server/scripts/generate-sherpa-tts-matrix.ts +++ b/packages/server/scripts/generate-sherpa-tts-matrix.ts @@ -19,22 +19,22 @@ import { loadSherpaOnnxNode } from "../src/server/speech/providers/local/sherpa/ const DEFAULT_SAMPLE_TEXT = "Paseo keeps your coding agents in your pocket, with fast local speech and reliable remote control."; -type ScriptOptions = { +interface ScriptOptions { modelsDir: string; outputDir: string; text: string; speed: number; modelIds: LocalTtsModelId[]; -}; +} -type GeneratedSample = { +interface GeneratedSample { modelId: LocalTtsModelId; voiceLabel: string; speakerId: number | null; sampleRate: number; durationSeconds: number; relativePath: string; -}; +} function usage(): string { return [ diff --git a/packages/server/scripts/supervisor-entrypoint.ts b/packages/server/scripts/supervisor-entrypoint.ts index 73934b0c2..feea4c6fc 100644 --- a/packages/server/scripts/supervisor-entrypoint.ts +++ b/packages/server/scripts/supervisor-entrypoint.ts @@ -11,10 +11,10 @@ import { resolvePaseoHome } from "../src/server/paseo-home.js"; import { runSupervisor } from "./supervisor.js"; import { applySherpaLoaderEnv } from "../src/server/speech/providers/local/sherpa/sherpa-runtime-env.js"; -type DaemonRunnerConfig = { +interface DaemonRunnerConfig { devMode: boolean; workerArgs: string[]; -}; +} function parseConfig(argv: string[]): DaemonRunnerConfig { let devMode = false; diff --git a/packages/server/scripts/supervisor.ts b/packages/server/scripts/supervisor.ts index 5a99234e5..d37712ff3 100644 --- a/packages/server/scripts/supervisor.ts +++ b/packages/server/scripts/supervisor.ts @@ -13,7 +13,7 @@ type WorkerLifecycleMessage = reason?: string; }; -type SupervisorOptions = { +interface SupervisorOptions { name: string; startupMessage: string; resolveWorkerEntry: () => string; @@ -28,7 +28,7 @@ type SupervisorOptions = { onWorkerReady?: (message: { listen: string }) => Promise | void; restartOnCrash?: boolean; onSupervisorExit?: () => Promise | void; -}; +} function describeExit(code: number | null, signal: NodeJS.Signals | null): string { return signal ?? (typeof code === "number" ? `code ${code}` : "unknown"); diff --git a/packages/server/scripts/test-mcp-inject.ts b/packages/server/scripts/test-mcp-inject.ts index beccc1bd2..8d91ec284 100644 --- a/packages/server/scripts/test-mcp-inject.ts +++ b/packages/server/scripts/test-mcp-inject.ts @@ -23,17 +23,17 @@ function collectAssistantText(entries: Array<{ item: { type: string; text?: stri .join("\n"); } -type ToolCallRecord = { +interface ToolCallRecord { name: string; status: string; -}; +} -type ProviderRunResult = { +interface ProviderRunResult { provider: "claude" | "codex"; agentId: string; assistantText: string; toolCalls: ToolCallRecord[]; -}; +} async function verifyInjectedMcpForProvider( client: DaemonClient, diff --git a/packages/server/scripts/transcribe-local-wav.ts b/packages/server/scripts/transcribe-local-wav.ts index 6533b1262..b25347fd0 100644 --- a/packages/server/scripts/transcribe-local-wav.ts +++ b/packages/server/scripts/transcribe-local-wav.ts @@ -13,12 +13,12 @@ import { import { initializeLocalSpeechServices } from "../src/server/speech/providers/local/runtime.js"; import type { RequestedSpeechProviders } from "../src/server/speech/speech-types.js"; -type CliOptions = { +interface CliOptions { wavPath: string; outPath?: string; model: LocalSttModelId; modelsDir: string; -}; +} function usage(): string { return [ diff --git a/packages/server/scripts/voice-main-daemon-e2e.ts b/packages/server/scripts/voice-main-daemon-e2e.ts index 77edd1b54..27ca9d247 100644 --- a/packages/server/scripts/voice-main-daemon-e2e.ts +++ b/packages/server/scripts/voice-main-daemon-e2e.ts @@ -5,11 +5,11 @@ import { DaemonClient } from "../src/server/test-utils/daemon-client.js"; import { OpenAITTS } from "../src/server/speech/providers/openai/tts.js"; import { withTimeout } from "../src/utils/promise-timeout.js"; -type RoundTripResult = { +interface RoundTripResult { voiceAgentId: string; speakToolCalls: number; audioChunks: number; -}; +} async function streamToBuffer(stream: AsyncIterable): Promise { const chunks: Buffer[] = []; diff --git a/packages/server/src/client/daemon-client-runtime-metrics.ts b/packages/server/src/client/daemon-client-runtime-metrics.ts index 23053b31d..2a71008ae 100644 --- a/packages/server/src/client/daemon-client-runtime-metrics.ts +++ b/packages/server/src/client/daemon-client-runtime-metrics.ts @@ -1,16 +1,16 @@ import type { SessionOutboundMessage } from "../shared/messages.js"; -type RuntimeMetricsLogger = { +interface RuntimeMetricsLogger { info(obj: object, msg?: string): void; -}; +} -type RuntimeMetricsHandlerTiming = { +interface RuntimeMetricsHandlerTiming { count: number; totalMs: number; maxMs: number; -}; +} -type RuntimeMetricsBucket = { +interface RuntimeMetricsBucket { inboundMessageCounts: Map; inboundMessageBytes: Map; inboundMessageHandlerMs: Map; @@ -18,17 +18,17 @@ type RuntimeMetricsBucket = { inboundAgentStreamByAgentCounts: Map; inboundBinaryFrameCounts: Map; endedAt: number; -}; +} -type RuntimeMetricsContext = { +interface RuntimeMetricsContext { connectionPath: "direct" | "relay"; serverId: string | null; getConnectionStatus: () => string; -}; +} -type RuntimeMetricsOptions = { +interface RuntimeMetricsOptions { windowMs?: number; -}; +} const DEFAULT_ROLLING_WINDOW_MS = 60_000; diff --git a/packages/server/src/client/daemon-client-transport-types.ts b/packages/server/src/client/daemon-client-transport-types.ts index ba74ad075..8820c13df 100644 --- a/packages/server/src/client/daemon-client-transport-types.ts +++ b/packages/server/src/client/daemon-client-transport-types.ts @@ -1,11 +1,11 @@ -export type DaemonTransport = { +export interface DaemonTransport { send: (data: string | Uint8Array | ArrayBuffer) => void; close: (code?: number, reason?: string) => void; onMessage: (handler: (data: unknown) => void) => () => void; onOpen: (handler: () => void) => () => void; onClose: (handler: (event?: unknown) => void) => () => void; onError: (handler: (event?: unknown) => void) => () => void; -}; +} export type DaemonTransportFactory = (options: { url: string; @@ -17,7 +17,7 @@ export type WebSocketFactory = ( options?: { headers?: Record }, ) => WebSocketLike; -export type WebSocketLike = { +export interface WebSocketLike { readyState: number; send: (data: string | Uint8Array | ArrayBuffer) => void; close: (code?: number, reason?: string) => void; @@ -31,7 +31,7 @@ export type WebSocketLike = { onclose?: ((event: any) => void) | null; onerror?: ((event: any) => void) | null; onmessage?: ((event: any) => void) | null; -}; +} export interface TransportLogger { warn(obj: object, msg?: string): void; diff --git a/packages/server/src/client/daemon-client.ts b/packages/server/src/client/daemon-client.ts index 3fa079ee7..9f11adc7c 100644 --- a/packages/server/src/client/daemon-client.ts +++ b/packages/server/src/client/daemon-client.ts @@ -183,7 +183,7 @@ export type DaemonEvent = export type DaemonEventHandler = (event: DaemonEvent) => void; -export type DaemonClientConfig = { +export interface DaemonClientConfig { url: string; clientId: string; clientType?: "mobile" | "browser" | "cli" | "mcp"; @@ -206,13 +206,13 @@ export type DaemonClientConfig = { }; runtimeMetricsIntervalMs?: number; runtimeMetricsWindowMs?: number; -}; +} -export type SendMessageOptions = { +export interface SendMessageOptions { messageId?: string; images?: Array<{ data: string; mimeType: string }>; attachments?: SendAgentMessageRequest["attachments"]; -}; +} type AgentConfigOverrides = Partial>; @@ -279,10 +279,10 @@ type ListCommandsDraftConfig = Pick< AgentSessionConfig, "provider" | "cwd" | "modeId" | "model" | "thinkingOptionId" | "featureValues" >; -type ListCommandsOptions = { +interface ListCommandsOptions { requestId?: string; draftConfig?: ListCommandsDraftConfig; -}; +} type SetVoiceModePayload = Extract< SessionOutboundMessage, { type: "set_voice_mode_response" } @@ -355,13 +355,13 @@ export type FetchAgentTimelinePayload = FetchAgentTimelineResponseMessage["paylo export type FetchAgentTimelineDirection = FetchAgentTimelinePayload["direction"]; export type FetchAgentTimelineProjection = FetchAgentTimelinePayload["projection"]; export type FetchAgentTimelineCursor = NonNullable; -export type FetchAgentTimelineOptions = { +export interface FetchAgentTimelineOptions { direction?: FetchAgentTimelineDirection; cursor?: FetchAgentTimelineCursor; limit?: number; projection?: FetchAgentTimelineProjection; requestId?: string; -}; +} type AgentRefreshedStatusPayload = z.infer; type RestartRequestedStatusPayload = z.infer; @@ -399,40 +399,40 @@ export type FetchWorkspacesOptions = Omit = { +interface Waiter { predicate: (msg: SessionOutboundMessage) => T | null; resolve: (value: T) => void; reject: (error: Error) => void; timeoutHandle: ReturnType | null; -}; +} -type WaitHandle = { +interface WaitHandle { promise: Promise; cancel: (error: Error) => void; -}; +} type RpcWaitResult = { kind: "ok"; value: T } | { kind: "error"; error: DaemonRpcError }; type GetDaemonConfigResponse = Extract< diff --git a/packages/server/src/server/agent-attention-policy.ts b/packages/server/src/server/agent-attention-policy.ts index 353886844..b56d705d0 100644 --- a/packages/server/src/server/agent-attention-policy.ts +++ b/packages/server/src/server/agent-attention-policy.ts @@ -13,12 +13,12 @@ export interface NotificationPlan { shouldPush: boolean; } -type ComputeNotificationPlanInput = { +interface ComputeNotificationPlanInput { allStates: ClientPresenceState[]; agentId: string; reason: AgentAttentionReason; nowMs: number; -}; +} export function computeNotificationPlan({ allStates, diff --git a/packages/server/src/server/agent/agent-manager-stream-coalescing.test.ts b/packages/server/src/server/agent/agent-manager-stream-coalescing.test.ts index b5aeed002..7f8128dfa 100644 --- a/packages/server/src/server/agent/agent-manager-stream-coalescing.test.ts +++ b/packages/server/src/server/agent/agent-manager-stream-coalescing.test.ts @@ -226,13 +226,13 @@ class TestAgentClient implements AgentClient { } } -type Harness = { +interface Harness { manager: AgentManager; client: TestAgentClient; events: AgentManagerEvent[]; workdir: string; cleanup: () => void; -}; +} function createHarness(options?: { provider?: AgentProvider }): Harness { const workdir = mkdtempSync(join(tmpdir(), "agent-manager-stream-coalescing-")); diff --git a/packages/server/src/server/agent/agent-manager.test.ts b/packages/server/src/server/agent/agent-manager.test.ts index dc8ca9f3f..9f02765e0 100644 --- a/packages/server/src/server/agent/agent-manager.test.ts +++ b/packages/server/src/server/agent/agent-manager.test.ts @@ -19,11 +19,11 @@ import type { AgentTimelineItem, } from "./agent-sdk-types.js"; -type Deferred = { +interface Deferred { promise: Promise; resolve: (value: T) => void; reject: (reason?: unknown) => void; -}; +} function deferred(): Deferred { let resolve!: (value: T) => void; diff --git a/packages/server/src/server/agent/agent-manager.ts b/packages/server/src/server/agent/agent-manager.ts index fdb9ac41b..bc5227b23 100644 --- a/packages/server/src/server/agent/agent-manager.ts +++ b/packages/server/src/server/agent/agent-manager.ts @@ -55,11 +55,11 @@ const INTERRUPT_SESSION_TIMEOUT_MS = 2_000; type TimeoutResult = "completed" | "timed_out"; -type TimeoutOptions = { +interface TimeoutOptions { operation: Promise; timeoutMs: number; onLateError?: (error: unknown) => void; -}; +} export { AGENT_LIFECYCLE_STATUSES, type AgentLifecycleStatus }; export type { @@ -83,10 +83,10 @@ export type AgentManagerEvent = export type AgentSubscriber = (event: AgentManagerEvent) => void; -export type SubscribeOptions = { +export interface SubscribeOptions { agentId?: string; replayState?: boolean; -}; +} export type PersistedAgentQueryOptions = ListPersistedAgentsOptions & { provider?: AgentProvider; @@ -98,18 +98,18 @@ export type AgentAttentionCallback = (params: { reason: "finished" | "error" | "permission"; }) => void; -export type ProviderAvailability = { +export interface ProviderAvailability { provider: AgentProvider; available: boolean; error: string | null; -}; +} -type AgentManagerRescueTimeouts = { +interface AgentManagerRescueTimeouts { reloadSessionCloseMs?: number; interruptSessionMs?: number; -}; +} -export type AgentManagerOptions = { +export interface AgentManagerOptions { clients?: Partial>; idFactory?: () => string; registry?: AgentStorage; @@ -120,22 +120,22 @@ export type AgentManagerOptions = { agentStreamCoalesceWindowMs?: number; rescueTimeouts?: AgentManagerRescueTimeouts; logger: Logger; -}; +} -export type WaitForAgentOptions = { +export interface WaitForAgentOptions { signal?: AbortSignal; waitForActive?: boolean; -}; +} -export type WaitForAgentResult = { +export interface WaitForAgentResult { status: AgentLifecycleStatus; permission: AgentPermissionRequest | null; lastMessage: string | null; -}; +} -export type WaitForAgentStartOptions = { +export interface WaitForAgentStartOptions { signal?: AbortSignal; -}; +} type AttentionState = | { requiresAttention: false } @@ -145,23 +145,23 @@ type AttentionState = attentionTimestamp: Date; }; -type ForegroundTurnWaiter = { +interface ForegroundTurnWaiter { turnId: string; callback: (event: AgentStreamEvent) => void; settled: boolean; settledPromise: Promise; resolveSettled: () => void; -}; +} -type PendingForegroundRun = { +interface PendingForegroundRun { token: string; started: boolean; settled: boolean; settledPromise: Promise; resolveSettled: () => void; -}; +} -type ManagedAgentBase = { +interface ManagedAgentBase { id: string; provider: AgentProvider; cwd: string; @@ -197,7 +197,7 @@ type ManagedAgentBase = { * User-defined labels for categorizing agents (e.g., { surface: "workspace" }). */ labels: Record; -}; +} type ManagedAgentWithSession = ManagedAgentBase & { session: AgentSession; @@ -273,10 +273,10 @@ function attachPersistenceCwd( }; } -type SubscriptionRecord = { +interface SubscriptionRecord { callback: AgentSubscriber; agentId: string | null; -}; +} const BUSY_STATUSES: Set = new Set(["initializing", "running"]); const AgentIdSchema = z.string().uuid(); diff --git a/packages/server/src/server/agent/agent-mcp.e2e.test.ts b/packages/server/src/server/agent/agent-mcp.e2e.test.ts index ffc79e8ff..800b7941c 100644 --- a/packages/server/src/server/agent/agent-mcp.e2e.test.ts +++ b/packages/server/src/server/agent/agent-mcp.e2e.test.ts @@ -12,17 +12,19 @@ import { withTimeout } from "../../utils/promise-timeout.js"; import { createPaseoDaemon, type PaseoDaemonConfig } from "../bootstrap.js"; import { createTestAgentClients } from "../test-utils/fake-agent-client.js"; -type StructuredContent = { [key: string]: unknown }; +interface StructuredContent { + [key: string]: unknown; +} -type McpToolResult = { +interface McpToolResult { structuredContent?: StructuredContent; content?: Array<{ structuredContent?: StructuredContent } | StructuredContent>; -}; +} -type McpClient = { +interface McpClient { callTool: (input: { name: string; args?: StructuredContent }) => Promise; close: () => Promise; -}; +} async function waitForPathExists(options: { targetPath: string; diff --git a/packages/server/src/server/agent/agent-metadata-generator.ts b/packages/server/src/server/agent/agent-metadata-generator.ts index 15ca9b15f..595da51ff 100644 --- a/packages/server/src/server/agent/agent-metadata-generator.ts +++ b/packages/server/src/server/agent/agent-metadata-generator.ts @@ -14,13 +14,13 @@ import { renameCurrentBranch } from "../../utils/checkout-git.js"; import { MAX_AUTO_AGENT_TITLE_CHARS } from "./agent-title-limits.js"; import type { WorkspaceGitRuntimeSnapshot, WorkspaceGitService } from "../workspace-git-service.js"; -export type AgentMetadataGeneratorDeps = { +export interface AgentMetadataGeneratorDeps { generateStructuredAgentResponseWithFallback?: typeof generateStructuredAgentResponseWithFallback; renameCurrentBranch?: typeof renameCurrentBranch; workspaceGitService?: Pick; -}; +} -export type AgentMetadataGenerationOptions = { +export interface AgentMetadataGenerationOptions { agentManager: AgentManager; agentId: string; cwd: string; @@ -29,13 +29,13 @@ export type AgentMetadataGenerationOptions = { paseoHome?: string; logger: Logger; deps?: AgentMetadataGeneratorDeps; -}; +} -type AgentMetadataNeeds = { +interface AgentMetadataNeeds { prompt: string | null; needsTitle: boolean; needsBranch: boolean; -}; +} function hasExplicitTitle(title?: string | null): boolean { return Boolean(title && title.trim().length > 0); diff --git a/packages/server/src/server/agent/agent-projections.ts b/packages/server/src/server/agent/agent-projections.ts index da4cf9afd..ab63bc5d2 100644 --- a/packages/server/src/server/agent/agent-projections.ts +++ b/packages/server/src/server/agent/agent-projections.ts @@ -19,11 +19,11 @@ import { coerceAgentProvider, toAgentPersistenceHandle } from "../persistence-ho export type { ManagedAgent }; -type ProjectionOptions = { +interface ProjectionOptions { title?: string | null; createdAt?: string; internal?: boolean; -}; +} function normalizeThinkingOptionId(value: string | null | undefined): string | null { if (typeof value !== "string") return null; diff --git a/packages/server/src/server/agent/agent-response-loop.e2e.test.ts b/packages/server/src/server/agent/agent-response-loop.e2e.test.ts index bd08682b9..1d8fb1106 100644 --- a/packages/server/src/server/agent/agent-response-loop.e2e.test.ts +++ b/packages/server/src/server/agent/agent-response-loop.e2e.test.ts @@ -23,10 +23,10 @@ const hasClaudeCredentials = !!process.env.CLAUDE_CODE_OAUTH_TOKEN || !!process.env.ANTHROPIC_API_KEY; const shouldRun = !process.env.CI && (hasOpenAICredentials || hasClaudeCredentials); -type AgentMcpServerHandle = { +interface AgentMcpServerHandle { url: string; close: () => Promise; -}; +} async function startAgentMcpServer(logger: pino.Logger): Promise { const app = express(); diff --git a/packages/server/src/server/agent/agent-response-loop.ts b/packages/server/src/server/agent/agent-response-loop.ts index f7ac9615f..7d9ab500a 100644 --- a/packages/server/src/server/agent/agent-response-loop.ts +++ b/packages/server/src/server/agent/agent-response-loop.ts @@ -21,18 +21,18 @@ export class StructuredAgentResponseError extends Error { } } -export type StructuredGenerationProvider = { +export interface StructuredGenerationProvider { provider: AgentProvider; model?: string; thinkingOptionId?: string; -}; +} -export type StructuredGenerationAttempt = { +export interface StructuredGenerationAttempt { provider: AgentProvider; model: string | null; available: boolean; error: string | null; -}; +} export class StructuredAgentFallbackError extends Error { readonly attempts: StructuredGenerationAttempt[]; diff --git a/packages/server/src/server/agent/agent-sdk-types.ts b/packages/server/src/server/agent/agent-sdk-types.ts index 3e2b7dbbc..08d56e705 100644 --- a/packages/server/src/server/agent/agent-sdk-types.ts +++ b/packages/server/src/server/agent/agent-sdk-types.ts @@ -3,7 +3,9 @@ import type { AgentAttachment } from "../../shared/messages.js"; export type AgentProvider = string; -export type AgentMetadata = { [key: string]: unknown }; +export interface AgentMetadata { + [key: string]: unknown; +} /** * Stdio-based MCP server (spawns a subprocess). @@ -40,17 +42,17 @@ export interface McpSseServerConfig { */ export type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig | McpSseServerConfig; -export type AgentMode = { +export interface AgentMode { id: string; label: string; description?: string; icon?: string; colorTier?: string; -}; +} export type ProviderStatus = "ready" | "loading" | "error" | "unavailable"; -export type AgentModelDefinition = { +export interface AgentModelDefinition { provider: AgentProvider; id: string; label: string; @@ -59,15 +61,15 @@ export type AgentModelDefinition = { metadata?: AgentMetadata; thinkingOptions?: AgentSelectOption[]; defaultThinkingOptionId?: string; -}; +} -export type AgentSelectOption = { +export interface AgentSelectOption { id: string; label: string; description?: string; isDefault?: boolean; metadata?: AgentMetadata; -}; +} export interface ProviderSnapshotEntry { provider: AgentProvider; @@ -81,7 +83,7 @@ export interface ProviderSnapshotEntry { defaultModeId?: string | null; } -export type AgentFeatureToggle = { +export interface AgentFeatureToggle { type: "toggle"; id: string; label: string; @@ -89,9 +91,9 @@ export type AgentFeatureToggle = { tooltip?: string; icon?: string; value: boolean; -}; +} -export type AgentFeatureSelect = { +export interface AgentFeatureSelect { type: "select"; id: string; label: string; @@ -100,26 +102,26 @@ export type AgentFeatureSelect = { icon?: string; value: string | null; options: AgentSelectOption[]; -}; +} export type AgentFeature = AgentFeatureToggle | AgentFeatureSelect; -export type AgentCapabilityFlags = { +export interface AgentCapabilityFlags { supportsStreaming: boolean; supportsSessionPersistence: boolean; supportsDynamicModes: boolean; supportsMcpServers: boolean; supportsReasoningStream: boolean; supportsToolInvocations: boolean; -}; +} -export type AgentPersistenceHandle = { +export interface AgentPersistenceHandle { provider: AgentProvider; sessionId: string; /** Provider specific handle (Codex thread id, Claude resume token, etc). */ nativeHandle?: string; metadata?: AgentMetadata; -}; +} export type AgentPromptContentBlock = | { type: "text"; text: string } @@ -128,20 +130,20 @@ export type AgentPromptContentBlock = export type AgentPromptInput = string | AgentPromptContentBlock[]; -export type AgentRunOptions = { +export interface AgentRunOptions { outputSchema?: unknown; resumeFrom?: AgentPersistenceHandle; maxThinkingTokens?: number; -}; +} -export type AgentUsage = { +export interface AgentUsage { inputTokens?: number; cachedInputTokens?: number; outputTokens?: number; totalCostUsd?: number; contextWindowMaxTokens?: number; contextWindowUsedTokens?: number; -}; +} export const TOOL_CALL_ICON_NAMES = [ "wrench", @@ -255,13 +257,13 @@ export type ToolCallDetail = output: unknown | null; }; -type ToolCallBase = { +interface ToolCallBase { type: "tool_call"; callId: string; name: string; detail: ToolCallDetail; metadata?: Record; -}; +} type ToolCallRunningTimelineItem = ToolCallBase & { status: "running"; @@ -289,12 +291,12 @@ export type ToolCallTimelineItem = | ToolCallFailedTimelineItem | ToolCallCanceledTimelineItem; -export type CompactionTimelineItem = { +export interface CompactionTimelineItem { type: "compaction"; status: "loading" | "completed"; trigger?: "auto" | "manual"; preTokens?: number; -}; +} export type AgentTimelineItem = | { type: "user_message"; text: string; messageId?: string } @@ -344,15 +346,15 @@ export type AgentPermissionRequestKind = "tool" | "plan" | "question" | "mode" | export type AgentPermissionUpdate = AgentMetadata; -export type AgentPermissionAction = { +export interface AgentPermissionAction { id: string; label: string; behavior: "allow" | "deny"; variant?: "primary" | "secondary" | "danger"; intent?: "implement" | "implement_resume" | "dismiss"; -}; +} -export type AgentPermissionRequest = { +export interface AgentPermissionRequest { id: string; provider: AgentProvider; name: string; @@ -364,7 +366,7 @@ export type AgentPermissionRequest = { suggestions?: AgentPermissionUpdate[]; actions?: AgentPermissionAction[]; metadata?: AgentMetadata; -}; +} export type AgentPermissionResponse = | { @@ -380,38 +382,38 @@ export type AgentPermissionResponse = interrupt?: boolean; }; -export type AgentRunResult = { +export interface AgentRunResult { sessionId: string; finalText: string; usage?: AgentUsage; timeline: AgentTimelineItem[]; canceled?: boolean; -}; +} -export type AgentRuntimeInfo = { +export interface AgentRuntimeInfo { provider: AgentProvider; sessionId: string | null; model?: string | null; thinkingOptionId?: string | null; modeId?: string | null; extra?: AgentMetadata; -}; +} /** * Represents a slash command available in an agent session. * Commands are executed by sending them as prompts with / prefix. */ -export type AgentSlashCommand = { +export interface AgentSlashCommand { name: string; description: string; argumentHint: string; -}; +} -export type ListPersistedAgentsOptions = { +export interface ListPersistedAgentsOptions { limit?: number; -}; +} -export type PersistedAgentDescriptor = { +export interface PersistedAgentDescriptor { provider: AgentProvider; sessionId: string; cwd: string; @@ -419,9 +421,9 @@ export type PersistedAgentDescriptor = { lastActivityAt: Date; persistence: AgentPersistenceHandle; timeline: AgentTimelineItem[]; -}; +} -export type AgentSessionConfig = { +export interface AgentSessionConfig { provider: AgentProvider; cwd: string; /** @@ -448,7 +450,7 @@ export type AgentSessionConfig = { * They are used for ephemeral system tasks like commit/PR generation. */ internal?: boolean; -}; +} export interface AgentLaunchContext { env?: Record; diff --git a/packages/server/src/server/agent/agent-stream-coalescer.ts b/packages/server/src/server/agent/agent-stream-coalescer.ts index 60ca89bcf..78fd3e45f 100644 --- a/packages/server/src/server/agent/agent-stream-coalescer.ts +++ b/packages/server/src/server/agent/agent-stream-coalescer.ts @@ -10,48 +10,48 @@ type CoalescableTimelineEvent = Extract item: CoalescableTimelineItem; }; -export type AgentStreamCoalescerTimers = { +export interface AgentStreamCoalescerTimers { setTimeout: typeof setTimeout; clearTimeout: typeof clearTimeout; -}; +} -export type AgentStreamCoalescerFlush = { +export interface AgentStreamCoalescerFlush { agentId: string; item: CoalescableTimelineItem; provider: AgentProvider; turnId?: string; -}; +} -export type AgentStreamCoalescerOptions = { +export interface AgentStreamCoalescerOptions { windowMs?: number; timers: AgentStreamCoalescerTimers; onFlush: (payload: AgentStreamCoalescerFlush) => void; -}; +} -type PendingTextEntry = { +interface PendingTextEntry { kind: "text"; item: CoalescableTextItem; text: string; provider: AgentProvider; turnId?: string; -}; +} -type PendingToolCallEntry = { +interface PendingToolCallEntry { kind: "tool_call"; item: Extract; provider: AgentProvider; turnId?: string; -}; +} type PendingAgentStreamEntry = PendingTextEntry | PendingToolCallEntry; -type PendingAgentStreamBuffer = { +interface PendingAgentStreamBuffer { agentId: string; entries: PendingAgentStreamEntry[]; toolCallEntryIndexes: Map; timer: ReturnType | null; flushing: boolean; -}; +} function isCoalescableTimelineEvent(event: AgentStreamEvent): event is CoalescableTimelineEvent { return ( diff --git a/packages/server/src/server/agent/agent-timeline-store-types.ts b/packages/server/src/server/agent/agent-timeline-store-types.ts index 55774d6fc..9ff325bcc 100644 --- a/packages/server/src/server/agent/agent-timeline-store-types.ts +++ b/packages/server/src/server/agent/agent-timeline-store-types.ts @@ -1,19 +1,19 @@ import type { AgentTimelineItem } from "./agent-sdk-types.js"; -export type AgentTimelineRow = { +export interface AgentTimelineRow { seq: number; timestamp: string; item: AgentTimelineItem; -}; +} -export type AgentTimelineCursor = { +export interface AgentTimelineCursor { epoch: string; seq: number; -}; +} export type AgentTimelineFetchDirection = "tail" | "before" | "after"; -export type AgentTimelineFetchOptions = { +export interface AgentTimelineFetchOptions { direction?: AgentTimelineFetchDirection; cursor?: AgentTimelineCursor; /** @@ -22,15 +22,15 @@ export type AgentTimelineFetchOptions = { * - 0: all rows in the selected window */ limit?: number; -}; +} -export type AgentTimelineWindow = { +export interface AgentTimelineWindow { minSeq: number; maxSeq: number; nextSeq: number; -}; +} -export type AgentTimelineFetchResult = { +export interface AgentTimelineFetchResult { epoch: string; direction: AgentTimelineFetchDirection; reset: boolean; @@ -40,7 +40,7 @@ export type AgentTimelineFetchResult = { hasOlder: boolean; hasNewer: boolean; rows: AgentTimelineRow[]; -}; +} export interface AgentTimelineStore { appendCommitted( diff --git a/packages/server/src/server/agent/agent-timeline-store.ts b/packages/server/src/server/agent/agent-timeline-store.ts index 53248d4db..9e6a1be65 100644 --- a/packages/server/src/server/agent/agent-timeline-store.ts +++ b/packages/server/src/server/agent/agent-timeline-store.ts @@ -6,19 +6,19 @@ import type { AgentTimelineRow, } from "./agent-timeline-store-types.js"; -export type SeedAgentTimelineOptions = { +export interface SeedAgentTimelineOptions { items?: readonly AgentTimelineItem[]; rows?: readonly AgentTimelineRow[]; epoch?: string; nextSeq?: number; timestamp?: string; -}; +} -type AgentTimelineState = { +interface AgentTimelineState { epoch: string; rows: AgentTimelineRow[]; nextSeq: number; -}; +} const DEFAULT_TIMELINE_FETCH_LIMIT = 200; diff --git a/packages/server/src/server/agent/mcp-parity.e2e.test.ts b/packages/server/src/server/agent/mcp-parity.e2e.test.ts index d0f48fdf6..077462e0d 100644 --- a/packages/server/src/server/agent/mcp-parity.e2e.test.ts +++ b/packages/server/src/server/agent/mcp-parity.e2e.test.ts @@ -9,18 +9,20 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/ import { AGENT_WAIT_TIMEOUT_MS } from "./mcp-shared.js"; import { createTestPaseoDaemon, type TestPaseoDaemon } from "../test-utils/paseo-daemon.js"; -type StructuredContent = { [key: string]: unknown }; +interface StructuredContent { + [key: string]: unknown; +} -type McpToolResult = { +interface McpToolResult { structuredContent?: StructuredContent; content?: Array<{ structuredContent?: StructuredContent } | StructuredContent>; isError?: boolean; -}; +} -type McpClient = { +interface McpClient { callTool: (input: { name: string; args?: StructuredContent }) => Promise; close: () => Promise; -}; +} function formatHostForHttpUrl(host: string): string { return host.includes(":") && !host.startsWith("[") ? `[${host}]` : host; diff --git a/packages/server/src/server/agent/mcp-server.test.ts b/packages/server/src/server/agent/mcp-server.test.ts index 484220128..2ab984283 100644 --- a/packages/server/src/server/agent/mcp-server.test.ts +++ b/packages/server/src/server/agent/mcp-server.test.ts @@ -21,14 +21,14 @@ import { createWorktreeCoreDeps } from "../worktree-core.js"; import { WorkspaceGitServiceImpl } from "../workspace-git-service.js"; import type { GitHubService } from "../../services/github-service.js"; -type TestDeps = { +interface TestDeps { agentManager: AgentManager; agentStorage: AgentStorage; spies: { agentManager: Record; agentStorage: Record; }; -}; +} function createTestDeps(): TestDeps { const agentManagerSpies = { diff --git a/packages/server/src/server/agent/mcp-shared.ts b/packages/server/src/server/agent/mcp-shared.ts index a910e74ed..286e5a5b7 100644 --- a/packages/server/src/server/agent/mcp-shared.ts +++ b/packages/server/src/server/agent/mcp-shared.ts @@ -88,10 +88,10 @@ export function resolveRequiredProviderModel( }; } -export type StartAgentRunOptions = { +export interface StartAgentRunOptions { replaceRunning?: boolean; runOptions?: AgentRunOptions; -}; +} /** * Wraps agentManager.waitForAgentEvent with a self-imposed timeout. diff --git a/packages/server/src/server/agent/model-resolver.ts b/packages/server/src/server/agent/model-resolver.ts index cb850c192..ac24aeb2c 100644 --- a/packages/server/src/server/agent/model-resolver.ts +++ b/packages/server/src/server/agent/model-resolver.ts @@ -4,12 +4,12 @@ import type { AgentProvider } from "./agent-sdk-types.js"; import { expandTilde } from "../../utils/path.js"; import type { Logger } from "pino"; -type ResolveAgentModelOptions = { +interface ResolveAgentModelOptions { provider: AgentProvider; requestedModel?: string | null; cwd?: string; logger: Logger; -}; +} export async function resolveAgentModel( options: ResolveAgentModelOptions, diff --git a/packages/server/src/server/agent/provider-launch-config.ts b/packages/server/src/server/agent/provider-launch-config.ts index 49867ac59..89e8514af 100644 --- a/packages/server/src/server/agent/provider-launch-config.ts +++ b/packages/server/src/server/agent/provider-launch-config.ts @@ -87,10 +87,10 @@ export type AgentProviderRuntimeSettingsMap = Partial< Record >; -export type ProviderCommandPrefix = { +export interface ProviderCommandPrefix { command: string; args: string[]; -}; +} export async function resolveProviderCommandPrefix( commandConfig: ProviderCommand | undefined, diff --git a/packages/server/src/server/agent/provider-registry.test.ts b/packages/server/src/server/agent/provider-registry.test.ts index fddc8e995..e4f83929a 100644 --- a/packages/server/src/server/agent/provider-registry.test.ts +++ b/packages/server/src/server/agent/provider-registry.test.ts @@ -4,9 +4,9 @@ import { createTestLogger } from "../../test-utils/test-logger.js"; import type { AgentModelDefinition } from "./agent-sdk-types.js"; const mockState = vi.hoisted(() => { - type ConstructorEntry = { + interface ConstructorEntry { runtimeSettings?: unknown; - }; + } return { constructorArgs: { diff --git a/packages/server/src/server/agent/provider-registry.ts b/packages/server/src/server/agent/provider-registry.ts index 482db8aa6..92826b61d 100644 --- a/packages/server/src/server/agent/provider-registry.ts +++ b/packages/server/src/server/agent/provider-registry.ts @@ -46,12 +46,12 @@ export interface ProviderDefinition extends AgentProviderDefinition { fetchModes: (options: ListModesOptions) => Promise; } -export type BuildProviderRegistryOptions = { +export interface BuildProviderRegistryOptions { runtimeSettings?: AgentProviderRuntimeSettingsMap; providerOverrides?: Record; workspaceGitService?: Pick; isDev?: boolean; -}; +} type ProviderClientFactory = ( logger: Logger, @@ -59,14 +59,14 @@ type ProviderClientFactory = ( options?: Pick, ) => AgentClient; -type ResolvedProvider = { +interface ResolvedProvider { definition: AgentProviderDefinition; runtimeSettings?: ProviderRuntimeSettings; profileModels: ProviderProfileModel[]; additionalModels: ProviderProfileModel[]; enabled: boolean; createBaseClient: (logger: Logger) => AgentClient; -}; +} const PROVIDER_CLIENT_FACTORIES: Record = { claude: (logger, runtimeSettings) => diff --git a/packages/server/src/server/agent/provider-snapshot-manager.test.ts b/packages/server/src/server/agent/provider-snapshot-manager.test.ts index f51f267de..149f0f900 100644 --- a/packages/server/src/server/agent/provider-snapshot-manager.test.ts +++ b/packages/server/src/server/agent/provider-snapshot-manager.test.ts @@ -15,13 +15,13 @@ import type { import type { ProviderDefinition } from "./provider-registry.js"; import { ProviderSnapshotManager } from "./provider-snapshot-manager.js"; -type Deferred = { +interface Deferred { promise: Promise; resolve: (value: T) => void; reject: (reason?: unknown) => void; -}; +} -type MockProviderOptions = { +interface MockProviderOptions { provider: AgentProvider; label?: string; description?: string; @@ -29,14 +29,14 @@ type MockProviderOptions = { isAvailable?: () => Promise; fetchModels?: (cwd: string, force: boolean) => Promise; fetchModes?: (cwd: string, force: boolean) => Promise; -}; +} -type MockProviderHandle = { +interface MockProviderHandle { definition: ProviderDefinition; isAvailable: ReturnType; fetchModels: ReturnType; fetchModes: ReturnType; -}; +} const TEST_CAPABILITIES = { supportsStreaming: false, diff --git a/packages/server/src/server/agent/provider-snapshot-manager.ts b/packages/server/src/server/agent/provider-snapshot-manager.ts index f2509ecd9..97ce7787d 100644 --- a/packages/server/src/server/agent/provider-snapshot-manager.ts +++ b/packages/server/src/server/agent/provider-snapshot-manager.ts @@ -12,23 +12,23 @@ const DEFAULT_SNAPSHOT_TTL_MS = 300_000; const DEFAULT_REFRESH_TIMEOUT_MS = 30_000; type ProviderSnapshotChangeListener = (entries: ProviderSnapshotEntry[], cwd: string) => void; -type ProviderSnapshotManagerOptions = { +interface ProviderSnapshotManagerOptions { ttlMs?: number; refreshTimeoutMs?: number; now?: () => number; -}; -type ProviderSnapshotRefreshOptions = { +} +interface ProviderSnapshotRefreshOptions { cwd: string; providers?: AgentProvider[]; -}; -type ProviderLoadOptions = { +} +interface ProviderLoadOptions { cwd: string; providers: AgentProvider[]; force: boolean; -}; -type ProviderLoad = { +} +interface ProviderLoad { promise: Promise; -}; +} export class ProviderSnapshotManager { private readonly snapshots = new Map>(); diff --git a/packages/server/src/server/agent/providers/acp-agent.ts b/packages/server/src/server/agent/providers/acp-agent.ts index 5244af210..ccc36f37c 100644 --- a/packages/server/src/server/agent/providers/acp-agent.ts +++ b/packages/server/src/server/agent/providers/acp-agent.ts @@ -182,7 +182,7 @@ export function createLoggedNdJsonStream( return { readable, writable }; } -type ACPAgentClientOptions = { +interface ACPAgentClientOptions { provider: string; logger: Logger; runtimeSettings?: ProviderRuntimeSettings; @@ -199,9 +199,9 @@ type ACPAgentClientOptions = { capabilities?: AgentCapabilityFlags; waitForInitialCommands?: boolean; initialCommandsWaitTimeoutMs?: number; -}; +} -type ACPAgentSessionOptions = { +interface ACPAgentSessionOptions { provider: string; logger: Logger; runtimeSettings?: ProviderRuntimeSettings; @@ -220,15 +220,15 @@ type ACPAgentSessionOptions = { launchEnv?: Record; waitForInitialCommands?: boolean; initialCommandsWaitTimeoutMs?: number; -}; +} -export type SpawnedACPProcess = { +export interface SpawnedACPProcess { child: ChildProcessWithoutNullStreams; connection: ClientSideConnection; initialize: InitializeResponse; -}; +} -export type ACPToolSnapshot = { +export interface ACPToolSnapshot { toolCallId: string; title: string; kind?: ToolKind | null; @@ -237,28 +237,28 @@ export type ACPToolSnapshot = { locations?: ToolCallLocation[] | null; rawInput?: unknown; rawOutput?: unknown; -}; +} -type PendingPermission = { +interface PendingPermission { request: AgentPermissionRequest; options: PermissionOption[]; resolve: (response: RequestPermissionResponse) => void; reject: (error: Error) => void; turnId: string | null; -}; +} -type MessageAssemblyState = { +interface MessageAssemblyState { text: string; -}; +} export type SessionStateResponse = NewSessionResponse | LoadSessionResponse | ResumeSessionResponse; -type TerminalExit = { +interface TerminalExit { exitCode?: number | null; signal?: string | null; -}; +} -type TerminalEntry = { +interface TerminalEntry { id: string; child: ChildProcess; output: string; @@ -268,15 +268,15 @@ type TerminalEntry = { waitForExit: Promise; resolveExit: (exit: TerminalExit) => void; rejectExit: (error: Error) => void; -}; +} -type ConfigOptionSelector = { +interface ConfigOptionSelector { id: string; label: string; description?: string; isDefault?: boolean; metadata?: AgentMetadata; -}; +} export function mapACPUsage(usage: Usage | null | undefined): AgentUsage | undefined { if (!usage) { diff --git a/packages/server/src/server/agent/providers/claude-agent.interrupt-restart-regression.test.ts b/packages/server/src/server/agent/providers/claude-agent.interrupt-restart-regression.test.ts index 2a23ef455..e28eb1e1a 100644 --- a/packages/server/src/server/agent/providers/claude-agent.interrupt-restart-regression.test.ts +++ b/packages/server/src/server/agent/providers/claude-agent.interrupt-restart-regression.test.ts @@ -5,7 +5,7 @@ import { ClaudeAgentClient } from "./claude-agent.js"; import { streamSession } from "./test-utils/session-stream-adapter.js"; import type { AgentStreamEvent } from "../agent-sdk-types.js"; -type QueryMock = { +interface QueryMock { next: ReturnType; interrupt: ReturnType; return: ReturnType; @@ -16,18 +16,18 @@ type QueryMock = { supportedCommands: ReturnType; rewindFiles: ReturnType; [Symbol.asyncIterator]: () => AsyncIterator, void>; -}; +} -type PromptRecord = { +interface PromptRecord { text: string; uuid: string | null; -}; +} -type AsyncQueue = { +interface AsyncQueue { push: (value: T) => void; next: () => Promise>; end: () => void; -}; +} type ScriptedQuery = QueryMock & { emit: (message: Record) => void; diff --git a/packages/server/src/server/agent/providers/claude-agent.redesign.test.ts b/packages/server/src/server/agent/providers/claude-agent.redesign.test.ts index cdbc1a696..2db189fa2 100644 --- a/packages/server/src/server/agent/providers/claude-agent.redesign.test.ts +++ b/packages/server/src/server/agent/providers/claude-agent.redesign.test.ts @@ -6,7 +6,7 @@ import { ClaudeAgentClient, readEventIdentifiers } from "./claude-agent.js"; import { streamSession } from "./test-utils/session-stream-adapter.js"; import type { AgentStreamEvent, AgentTimelineItem } from "../agent-sdk-types.js"; -type QueryMock = { +interface QueryMock { next: ReturnType; interrupt: ReturnType; return: ReturnType; @@ -17,7 +17,7 @@ type QueryMock = { supportedCommands: ReturnType; rewindFiles: ReturnType; [Symbol.asyncIterator]: () => AsyncIterator, void>; -}; +} function buildUsage() { return { @@ -85,10 +85,10 @@ function createSessionWithLogger(logger: Logger) { const sdkQueryFactory = vi.fn(); -type CapturedLog = { +interface CapturedLog { level: "debug" | "info" | "warn" | "error"; args: unknown[]; -}; +} function createSpyLogger(): { logger: Logger; diff --git a/packages/server/src/server/agent/providers/claude-agent.sub-agent-sidechain.test.ts b/packages/server/src/server/agent/providers/claude-agent.sub-agent-sidechain.test.ts index 118fb2b57..977defec0 100644 --- a/packages/server/src/server/agent/providers/claude-agent.sub-agent-sidechain.test.ts +++ b/packages/server/src/server/agent/providers/claude-agent.sub-agent-sidechain.test.ts @@ -15,7 +15,7 @@ vi.mock("@anthropic-ai/claude-agent-sdk", () => ({ query: sdkMocks.query, })); -type QueryMock = { +interface QueryMock { next: ReturnType; interrupt: ReturnType; return: ReturnType; @@ -26,7 +26,7 @@ type QueryMock = { supportedCommands: ReturnType; rewindFiles: ReturnType; [Symbol.asyncIterator]: () => AsyncIterator, void>; -}; +} function buildQueryMock(events: unknown[]): QueryMock { let index = 0; diff --git a/packages/server/src/server/agent/providers/claude-agent.ts b/packages/server/src/server/agent/providers/claude-agent.ts index ae938aed1..47b97fb82 100644 --- a/packages/server/src/server/agent/providers/claude-agent.ts +++ b/packages/server/src/server/agent/providers/claude-agent.ts @@ -83,21 +83,21 @@ const CLAUDE_SETTING_SOURCES: NonNullable = ["user", type TurnState = "idle" | "foreground" | "autonomous"; -type EventIdentifiers = { +interface EventIdentifiers { taskId: string | null; parentMessageId: string | null; messageId: string | null; -}; +} -type AutonomousTurnState = { +interface AutonomousTurnState { id: string; -}; +} -type AsyncMessageInput = { +interface AsyncMessageInput { push: (item: T) => void; end: () => void; iterable: AsyncIterable; -}; +} const CLAUDE_CAPABILITIES: AgentCapabilityFlags = { supportsStreaming: true, @@ -144,34 +144,37 @@ const INTERRUPT_PLACEHOLDER_PATTERN = /^\[Request interrupted by user(?:[^\]]*)\ const NO_RESPONSE_REQUESTED_PLACEHOLDER = "No response requested."; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; -type SlashCommandInvocation = { +interface SlashCommandInvocation { commandName: string; args?: string; rawInput: string; -}; +} // Orchestrator instructions moved to shared module. type ClaudeAgentConfig = AgentSessionConfig & { provider: "claude" }; -export type ClaudeContentChunk = { type: string; [key: string]: any }; +export interface ClaudeContentChunk { + type: string; + [key: string]: any; +} type ClaudeOptions = Options; -type ClaudeAgentClientOptions = { +interface ClaudeAgentClientOptions { defaults?: { agents?: Record }; logger: Logger; runtimeSettings?: ProviderRuntimeSettings; queryFactory?: typeof query; -}; +} -type ClaudeAgentSessionOptions = { +interface ClaudeAgentSessionOptions { defaults?: { agents?: Record }; runtimeSettings?: ProviderRuntimeSettings; handle?: AgentPersistenceHandle; launchEnv?: Record; logger: Logger; queryFactory?: typeof query; -}; +} type ClaudeThinkingEffort = "low" | "medium" | "high" | "xhigh" | "max"; @@ -253,7 +256,7 @@ function sanitizeClaudeProjectPath(cwd: string): string { return cwd.replace(/[\\/._:]/g, "-"); } -type ClaudeOptionsLogSummary = { +interface ClaudeOptionsLogSummary { cwd: string | null; permissionMode: string | null; model: string | null; @@ -272,7 +275,7 @@ type ClaudeOptionsLogSummary = { hasSpawnOverride: boolean; hasStderrHandler: boolean; pathToClaudeCodeExecutable: string | null; -}; +} const MAX_RECENT_STDERR_CHARS = 4000; const STDERR_FLUSH_WAIT_MS = 150; @@ -511,15 +514,15 @@ export function extractUserMessageText(content: unknown): string | null { return combined.length > 0 ? combined : null; } -type PendingPermission = { +interface PendingPermission { request: AgentPermissionRequest; resolve: (result: PermissionResult) => void; reject: (error: Error) => void; cleanup?: () => void; -}; +} type ToolUseClassification = "generic" | "command" | "file_change"; -type ToolUseCacheEntry = { +interface ToolUseCacheEntry { id: string; name: string; server: string; @@ -528,7 +531,7 @@ type ToolUseCacheEntry = { commandText?: string; files?: { path: string; kind: string }[]; input?: AgentMetadata | null; -}; +} function isMetadata(value: unknown): value is AgentMetadata { return typeof value === "object" && value !== null; } @@ -720,19 +723,19 @@ function buildClaudePlanPermissionActions( return actions; } -type TimelineFragment = { +interface TimelineFragment { kind: "assistant" | "reasoning"; text: string; -}; +} -type TimelineMessageState = { +interface TimelineMessageState { id: string; assistantText: string; reasoningText: string; emittedAssistantLength: number; emittedReasoningLength: number; stopped: boolean; -}; +} class TimelineAssembler { private readonly messages = new Map(); @@ -4090,10 +4093,10 @@ function createAsyncMessageInput(): AsyncMessageInput { }; } -type ClaudeSessionCandidate = { +interface ClaudeSessionCandidate { path: string; mtime: Date; -}; +} async function pathExists(target: string): Promise { try { diff --git a/packages/server/src/server/agent/providers/claude/partial-json.ts b/packages/server/src/server/agent/providers/claude/partial-json.ts index 8e8ef3451..09756b1ee 100644 --- a/packages/server/src/server/agent/providers/claude/partial-json.ts +++ b/packages/server/src/server/agent/providers/claude/partial-json.ts @@ -1,8 +1,8 @@ -type PartialParseResult = { +interface PartialParseResult { value: T; nextIndex: number; complete: boolean; -}; +} function skipWhitespace(input: string, index: number): number { let currentIndex = index; diff --git a/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts b/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts index 028170ce5..f79cfc20a 100644 --- a/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts +++ b/packages/server/src/server/agent/providers/claude/sidechain-tracker.ts @@ -5,28 +5,31 @@ import { buildToolCallDisplayModel } from "../../../../shared/tool-call-display. import type { AgentMetadata, AgentStreamEvent, AgentTimelineItem } from "../../agent-sdk-types.js"; -type ClaudeContentChunk = { type: string; [key: string]: unknown }; +interface ClaudeContentChunk { + type: string; + [key: string]: unknown; +} -type SubAgentActionEntry = { +interface SubAgentActionEntry { index: number; toolName: string; summary?: string; -}; +} -type SubAgentActivityState = { +interface SubAgentActivityState { subAgentType?: string; description?: string; actions: SubAgentActionEntry[]; actionKeys: string[]; nextActionIndex: number; actionIndexByKey: Map; -}; +} -type SubAgentActionCandidate = { +interface SubAgentActionCandidate { key: string; toolName: string; input: unknown; -}; +} const MAX_SUB_AGENT_LOG_ENTRIES = 200; const MAX_SUB_AGENT_SUMMARY_CHARS = 160; diff --git a/packages/server/src/server/agent/providers/claude/task-notification-tool-call.ts b/packages/server/src/server/agent/providers/claude/task-notification-tool-call.ts index 6ac8db6c6..2b9d84494 100644 --- a/packages/server/src/server/agent/providers/claude/task-notification-tool-call.ts +++ b/packages/server/src/server/agent/providers/claude/task-notification-tool-call.ts @@ -65,7 +65,7 @@ type TaskNotificationLifecycle = | { status: "failed"; error: unknown } | { status: "canceled"; error: null }; -export type TaskNotificationSystemMessageLike = { +export interface TaskNotificationSystemMessageLike { type: "system"; subtype: "task_notification"; uuid?: string; @@ -74,17 +74,17 @@ export type TaskNotificationSystemMessageLike = { summary?: string; output_file?: string; content?: string; -}; +} -type ReadTaskNotificationTagInput = { +interface ReadTaskNotificationTagInput { text: string; tagName: string; -}; +} -type BuildTaskNotificationStatusInput = { +interface BuildTaskNotificationStatusInput { status: string | null; summary: string | null; -}; +} type TaskNotificationToolCallItem = Extract; diff --git a/packages/server/src/server/agent/providers/claude/tool-call-mapper.ts b/packages/server/src/server/agent/providers/claude/tool-call-mapper.ts index 51fd746c6..5bf1875cf 100644 --- a/packages/server/src/server/agent/providers/claude/tool-call-mapper.ts +++ b/packages/server/src/server/agent/providers/claude/tool-call-mapper.ts @@ -4,13 +4,13 @@ import type { ToolCallTimelineItem } from "../../agent-sdk-types.js"; import { isSpeakToolName } from "../../tool-name-normalization.js"; import { deriveClaudeToolDetail } from "./tool-call-detail-parser.js"; -type MapperParams = { +interface MapperParams { callId?: string | null; name: string; input?: unknown; output?: unknown; metadata?: Record; -}; +} const ClaudeToolCallStatusSchema = z.enum(["running", "completed", "failed", "canceled"]); diff --git a/packages/server/src/server/agent/providers/codex-app-server-agent.ts b/packages/server/src/server/agent/providers/codex-app-server-agent.ts index d0b80ad8c..c20928e44 100644 --- a/packages/server/src/server/agent/providers/codex-app-server-agent.ts +++ b/packages/server/src/server/agent/providers/codex-app-server-agent.ts @@ -95,9 +95,9 @@ const CODEX_MODES: AgentMode[] = [ const DEFAULT_CODEX_MODE_ID = "auto"; -type CodexAppServerAgentDeps = { +interface CodexAppServerAgentDeps { workspaceGitService?: Pick; -}; +} const MODE_PRESETS: Record< string, @@ -217,10 +217,10 @@ function normalizeCodexOutputSchema(schema: unknown): Record { return normalized; } -type CodexConfiguredDefaults = { +interface CodexConfiguredDefaults { model?: string; thinkingOptionId?: string; -}; +} function mergeCodexConfiguredDefaults( primary: CodexConfiguredDefaults, @@ -509,30 +509,30 @@ function toCodexMcpConfig(config: McpServerConfig): CodexMcpServerConfig { }; } } -type JsonRpcRequest = { +interface JsonRpcRequest { id: number; method: string; params?: unknown; -}; +} -type JsonRpcResponse = { +interface JsonRpcResponse { id: number; result?: unknown; error?: { code?: number; message: string }; -}; +} -type JsonRpcNotification = { +interface JsonRpcNotification { method: string; params?: unknown; -}; +} type JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification; -type PendingRequest = { +interface PendingRequest { resolve: (value: unknown) => void; reject: (error: Error) => void; timer: ReturnType; -}; +} type RequestHandler = (params: unknown) => Promise | unknown; @@ -922,12 +922,12 @@ function buildCodexPlanImplementationPrompt(planText: string): string { ].join("\n\n"); } -type CodexQuestionOption = { +interface CodexQuestionOption { label: string; description?: string; -}; +} -type CodexQuestionPrompt = { +interface CodexQuestionPrompt { id: string; header: string; question: string; @@ -935,7 +935,7 @@ type CodexQuestionPrompt = { multiSelect?: boolean; isOther?: boolean; isSecret?: boolean; -}; +} function normalizeCodexQuestionPrompts(raw: unknown): CodexQuestionPrompt[] { if (!Array.isArray(raw)) { @@ -1103,11 +1103,11 @@ function mapCodexQuestionResponseByHeader(params: { return Object.keys(answers).length > 0 ? answers : null; } -type CodexPatchFileChange = { +interface CodexPatchFileChange { path: string; kind?: string; content?: string; -}; +} function extractPatchLikeText(value: unknown): string | undefined { if (!value || typeof value !== "object") { @@ -1546,7 +1546,10 @@ function getImageExtension(mimeType: string): string { } } -type ImageDataPayload = { mimeType: string; data: string }; +interface ImageDataPayload { + mimeType: string; + data: string; +} function normalizeImageData(mimeType: string, data: string): ImageDataPayload { if (data.startsWith("data:")) { diff --git a/packages/server/src/server/agent/providers/codex-rollout-timeline.ts b/packages/server/src/server/agent/providers/codex-rollout-timeline.ts index b7a40a445..cebc7e742 100644 --- a/packages/server/src/server/agent/providers/codex-rollout-timeline.ts +++ b/packages/server/src/server/agent/providers/codex-rollout-timeline.ts @@ -582,10 +582,10 @@ export async function parseRolloutFile(filePath: string): Promise; cwd?: string | null; -}; +} const CodexNormalizedToolCallPass1Schema = z .object({ @@ -300,10 +302,10 @@ function looksLikeUnifiedDiff(text: string): boolean { ); } -type CodexApplyPatchDirective = { +interface CodexApplyPatchDirective { kind: "add" | "update" | "delete"; path: string; -}; +} function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); @@ -628,11 +630,11 @@ function mapCommandExecutionItem( }; } -type CodexFileChangeEntry = { +interface CodexFileChangeEntry { path: string; kind?: string; diff?: string; -}; +} function parseFileChangePath( entry: Record, diff --git a/packages/server/src/server/agent/providers/copilot-acp-agent.ts b/packages/server/src/server/agent/providers/copilot-acp-agent.ts index a0f4ddd5f..53fec5e3f 100644 --- a/packages/server/src/server/agent/providers/copilot-acp-agent.ts +++ b/packages/server/src/server/agent/providers/copilot-acp-agent.ts @@ -40,10 +40,10 @@ const COPILOT_MODES: AgentMode[] = [ }, ]; -type CopilotACPAgentClientOptions = { +interface CopilotACPAgentClientOptions { logger: Logger; runtimeSettings?: ProviderRuntimeSettings; -}; +} export class CopilotACPAgentClient extends ACPAgentClient { constructor(options: CopilotACPAgentClientOptions) { diff --git a/packages/server/src/server/agent/providers/diagnostic-utils.ts b/packages/server/src/server/agent/providers/diagnostic-utils.ts index a21f54bea..b266df525 100644 --- a/packages/server/src/server/agent/providers/diagnostic-utils.ts +++ b/packages/server/src/server/agent/providers/diagnostic-utils.ts @@ -1,10 +1,10 @@ import type { ProviderRuntimeSettings } from "../provider-launch-config.js"; import { execCommand } from "../../../utils/spawn.js"; -type DiagnosticEntry = { +interface DiagnosticEntry { label: string; value: string; -}; +} export function formatProviderDiagnostic(providerName: string, entries: DiagnosticEntry[]): string { return [providerName, ...entries.map((entry) => ` ${entry.label}: ${entry.value}`)].join("\n"); diff --git a/packages/server/src/server/agent/providers/generic-acp-agent.ts b/packages/server/src/server/agent/providers/generic-acp-agent.ts index 53b2f0f1c..14ef3de73 100644 --- a/packages/server/src/server/agent/providers/generic-acp-agent.ts +++ b/packages/server/src/server/agent/providers/generic-acp-agent.ts @@ -3,11 +3,11 @@ import type { Logger } from "pino"; import { isCommandAvailable } from "../../../utils/executable.js"; import { ACPAgentClient } from "./acp-agent.js"; -type GenericACPAgentClientOptions = { +interface GenericACPAgentClientOptions { logger: Logger; command: string[]; env?: Record; -}; +} export class GenericACPAgentClient extends ACPAgentClient { private readonly command: [string, ...string[]]; diff --git a/packages/server/src/server/agent/providers/mock-load-test-agent.ts b/packages/server/src/server/agent/providers/mock-load-test-agent.ts index fc3b92cad..bbaf005ea 100644 --- a/packages/server/src/server/agent/providers/mock-load-test-agent.ts +++ b/packages/server/src/server/agent/providers/mock-load-test-agent.ts @@ -77,7 +77,7 @@ const MODELS: AgentModelDefinition[] = [ }, ]; -type ActiveTurn = { +interface ActiveTurn { turnId: string; prompt: AgentPromptInput; startedAt: number; @@ -87,17 +87,17 @@ type ActiveTurn = { timer: ReturnType | null; resolve: (result: AgentRunResult) => void; completed: Promise; -}; +} -type LargeAgentStreamPayloadRequest = { +interface LargeAgentStreamPayloadRequest { bytes: number; kind: "diff" | "file" | "image"; -}; +} -type AgentStreamStressRequest = { +interface AgentStreamStressRequest { count: number; coalesced: boolean; -}; +} function resolveModelProfile(modelId: string | null | undefined): { modelId: string; diff --git a/packages/server/src/server/agent/providers/opencode-agent.ts b/packages/server/src/server/agent/providers/opencode-agent.ts index 1fa98298b..8e34da8dc 100644 --- a/packages/server/src/server/agent/providers/opencode-agent.ts +++ b/packages/server/src/server/agent/providers/opencode-agent.ts @@ -939,13 +939,13 @@ export class OpenCodeServerManager { } } -type OpenCodeServerGeneration = { +interface OpenCodeServerGeneration { process: ChildProcess; port: number; url: string; refCount: number; retired: boolean; -}; +} export class OpenCodeAgentClient implements AgentClient { readonly provider = "opencode" as const; @@ -1242,7 +1242,7 @@ export class OpenCodeAgentClient implements AgentClient { } } -export type OpenCodeEventTranslationState = { +export interface OpenCodeEventTranslationState { sessionId: string; messageRoles: Map; accumulatedUsage: AgentUsage; @@ -1252,7 +1252,7 @@ export type OpenCodeEventTranslationState = { partTypes: Map; modelContextWindowsByModelKey?: ReadonlyMap; onAssistantModelContextWindowResolved?: (contextWindowMaxTokens: number) => void; -}; +} function stringifyStructuredAssistantMessage(value: unknown): string | null { if (value === undefined) { diff --git a/packages/server/src/server/agent/providers/opencode-server-manager.test.ts b/packages/server/src/server/agent/providers/opencode-server-manager.test.ts index 32b35b9c1..29e6efa8c 100644 --- a/packages/server/src/server/agent/providers/opencode-server-manager.test.ts +++ b/packages/server/src/server/agent/providers/opencode-server-manager.test.ts @@ -9,13 +9,13 @@ type FakeServerProcess = EventEmitter & { kill: ReturnType; }; -type FakeGeneration = { +interface FakeGeneration { process: FakeServerProcess; port: number; url: string; refCount: number; retired: boolean; -}; +} describe("OpenCodeServerManager generations", () => { test("rotation creates a new current server without killing a referenced old server", async () => { diff --git a/packages/server/src/server/agent/providers/opencode/tool-call-mapper.ts b/packages/server/src/server/agent/providers/opencode/tool-call-mapper.ts index 929440ad0..29702b2da 100644 --- a/packages/server/src/server/agent/providers/opencode/tool-call-mapper.ts +++ b/packages/server/src/server/agent/providers/opencode/tool-call-mapper.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import type { ToolCallTimelineItem } from "../../agent-sdk-types.js"; import { deriveOpencodeToolDetail } from "./tool-call-detail-parser.js"; -type OpencodeToolCallParams = { +interface OpencodeToolCallParams { toolName: string; callId?: string | null; status?: unknown; @@ -11,7 +11,7 @@ type OpencodeToolCallParams = { output?: unknown; error?: unknown; metadata?: Record; -}; +} const FAILED_STATUSES = new Set(["error", "failed", "failure"]); const CANCELED_STATUSES = new Set(["canceled", "cancelled", "aborted", "interrupted"]); diff --git a/packages/server/src/server/agent/providers/provider-windows-launch.test.ts b/packages/server/src/server/agent/providers/provider-windows-launch.test.ts index 72dff9f96..f67389910 100644 --- a/packages/server/src/server/agent/providers/provider-windows-launch.test.ts +++ b/packages/server/src/server/agent/providers/provider-windows-launch.test.ts @@ -7,20 +7,20 @@ import { afterEach, describe, expect, test } from "vitest"; import { findExecutable } from "../../../utils/executable.js"; import { spawnProcess } from "../../../utils/spawn.js"; -type SpawnResult = { +interface SpawnResult { code: number | null; signal: NodeJS.Signals | null; stdout: string; stderr: string; error: Error | null; -}; +} -type ProviderLaunchCase = { +interface ProviderLaunchCase { provider: "claude" | "codex" | "opencode" | "generic-acp"; binaryName: string; args: string[]; shell?: boolean; -}; +} const JSON_ARG = '{"mcpServers":{"paseo":{"type":"http","url":"http://127.0.0.1:6767/mcp"}}}'; const tempDirs: string[] = []; diff --git a/packages/server/src/server/agent/providers/tool-call-detail-primitives.ts b/packages/server/src/server/agent/providers/tool-call-detail-primitives.ts index c59ca9136..be41dd81c 100644 --- a/packages/server/src/server/agent/providers/tool-call-detail-primitives.ts +++ b/packages/server/src/server/agent/providers/tool-call-detail-primitives.ts @@ -329,10 +329,10 @@ const ToolReadOutputPathSchema = z.union([ })), ]); -type ToolReadOutputValue = { +interface ToolReadOutputValue { filePath?: string; content?: string; -}; +} export const ToolReadOutputSchema: z.ZodType = ToolReadOutputContentSchema; diff --git a/packages/server/src/server/agent/providers/tool-call-mapper-utils.ts b/packages/server/src/server/agent/providers/tool-call-mapper-utils.ts index 6cbc0a2cf..66cb68070 100644 --- a/packages/server/src/server/agent/providers/tool-call-mapper-utils.ts +++ b/packages/server/src/server/agent/providers/tool-call-mapper-utils.ts @@ -1,8 +1,8 @@ -type ReadChunkLike = { +interface ReadChunkLike { text?: string; content?: string; output?: string; -}; +} export function nonEmptyString(value: unknown): string | undefined { return typeof value === "string" && value.length > 0 ? value : undefined; diff --git a/packages/server/src/server/agent/timeline-projection.ts b/packages/server/src/server/agent/timeline-projection.ts index bac08fd69..0956ad452 100644 --- a/packages/server/src/server/agent/timeline-projection.ts +++ b/packages/server/src/server/agent/timeline-projection.ts @@ -3,15 +3,15 @@ import type { AgentTimelineRow } from "./agent-manager.js"; export type TimelineProjectionMode = "canonical" | "projected"; -export type TimelineSeqRange = { +export interface TimelineSeqRange { startSeq: number; endSeq: number; -}; +} export type TimelineProjectionKind = "assistant_merge" | "tool_lifecycle"; export type TimelineLimitDirection = "tail" | "before" | "after"; -export type TimelineProjectionEntry = { +export interface TimelineProjectionEntry { provider: AgentProvider; item: AgentTimelineItem; timestamp: string; @@ -19,15 +19,15 @@ export type TimelineProjectionEntry = { seqEnd: number; sourceSeqRanges: TimelineSeqRange[]; collapsed: TimelineProjectionKind[]; -}; +} type WorkingEntry = TimelineProjectionEntry; -type ProjectedWindowSelection = { +interface ProjectedWindowSelection { projectedEntries: TimelineProjectionEntry[]; selectedRows: AgentTimelineRow[]; minSeq: number | null; maxSeq: number | null; -}; +} function appendSeqToRanges(ranges: TimelineSeqRange[], seq: number): TimelineSeqRange[] { if (ranges.length === 0) { diff --git a/packages/server/src/server/agent/tts-manager.ts b/packages/server/src/server/agent/tts-manager.ts index 32b0a3236..3a7f39058 100644 --- a/packages/server/src/server/agent/tts-manager.ts +++ b/packages/server/src/server/agent/tts-manager.ts @@ -12,10 +12,10 @@ interface PendingPlayback { streamEnded: boolean; } -type TtsSegment = { +interface TtsSegment { index: number; text: string; -}; +} type PreparedTtsSegment = TtsSegment & { format: string; diff --git a/packages/server/src/server/bootstrap.ts b/packages/server/src/server/bootstrap.ts index b40c1d4f8..a6651368c 100644 --- a/packages/server/src/server/bootstrap.ts +++ b/packages/server/src/server/bootstrap.ts @@ -154,10 +154,10 @@ function createAgentMcpBaseUrl(listenTarget: ListenTarget | null): string | null export type PaseoOpenAIConfig = OpenAiSpeechProviderConfig; export type PaseoLocalSpeechConfig = LocalSpeechProviderConfig; -export type PaseoSpeechConfig = { +export interface PaseoSpeechConfig { providers: RequestedSpeechProviders; local?: PaseoLocalSpeechConfig; -}; +} export type DaemonLifecycleIntent = | { @@ -172,7 +172,7 @@ export type DaemonLifecycleIntent = reason?: string; }; -export type PaseoDaemonConfig = { +export interface PaseoDaemonConfig { listen: string; paseoHome: string; corsAllowedOrigins: string[]; @@ -199,7 +199,7 @@ export type PaseoDaemonConfig = { agentProviderSettings?: AgentProviderRuntimeSettingsMap; providerOverrides?: Record; onLifecycleIntent?: (intent: DaemonLifecycleIntent) => void; -}; +} export interface PaseoDaemon { config: PaseoDaemonConfig; diff --git a/packages/server/src/server/chat/chat-service.ts b/packages/server/src/server/chat/chat-service.ts index bdee71dc8..ede92ad10 100644 --- a/packages/server/src/server/chat/chat-service.ts +++ b/packages/server/src/server/chat/chat-service.ts @@ -54,13 +54,13 @@ export class ChatServiceError extends Error { } } -type Waiter = { +interface Waiter { roomId: string; afterMessageId: string | null; resolve: (messages: ChatMessage[]) => void; reject: (error: Error) => void; timeout: ReturnType | null; -}; +} export interface CreateChatRoomInput { name: string; diff --git a/packages/server/src/server/checkout-diff-manager.ts b/packages/server/src/server/checkout-diff-manager.ts index 64a45c60e..65f445bbf 100644 --- a/packages/server/src/server/checkout-diff-manager.ts +++ b/packages/server/src/server/checkout-diff-manager.ts @@ -13,14 +13,14 @@ export type CheckoutDiffSnapshotPayload = Omit< "subscriptionId" >; -export type CheckoutDiffMetrics = { +export interface CheckoutDiffMetrics { checkoutDiffTargetCount: number; checkoutDiffSubscriptionCount: number; checkoutDiffWatcherCount: number; checkoutDiffFallbackRefreshTargetCount: number; -}; +} -type CheckoutDiffWatchTarget = { +interface CheckoutDiffWatchTarget { key: string; cwd: string; diffCwd: string; @@ -32,7 +32,7 @@ type CheckoutDiffWatchTarget = { refreshQueued: boolean; latestPayload: CheckoutDiffSnapshotPayload | null; latestFingerprint: string | null; -}; +} export class CheckoutDiffManager { private readonly workspaceGitService: WorkspaceGitService; diff --git a/packages/server/src/server/checkout-git-utils.ts b/packages/server/src/server/checkout-git-utils.ts index 9c2c2e1e3..c5dcd9e73 100644 --- a/packages/server/src/server/checkout-git-utils.ts +++ b/packages/server/src/server/checkout-git-utils.ts @@ -12,10 +12,10 @@ export const READ_ONLY_GIT_ENV: NodeJS.ProcessEnv = { export type CheckoutErrorCode = "NOT_GIT_REPO" | "NOT_ALLOWED" | "MERGE_CONFLICT" | "UNKNOWN"; -export type CheckoutErrorPayload = { +export interface CheckoutErrorPayload { code: CheckoutErrorCode; message: string; -}; +} export async function resolveCheckoutGitDir(cwd: string): Promise { try { diff --git a/packages/server/src/server/connection-offer.ts b/packages/server/src/server/connection-offer.ts index 987ffc64e..3b8b76b2a 100644 --- a/packages/server/src/server/connection-offer.ts +++ b/packages/server/src/server/connection-offer.ts @@ -2,10 +2,10 @@ import os from "node:os"; import { ConnectionOfferV2Schema, type ConnectionOffer } from "../shared/connection-offer.js"; -type BuildOfferEndpointsArgs = { +interface BuildOfferEndpointsArgs { listenHost: string; port: number; -}; +} export function buildOfferEndpoints({ listenHost, port }: BuildOfferEndpointsArgs): string[] { const endpoints: string[] = []; diff --git a/packages/server/src/server/daemon-config-store.ts b/packages/server/src/server/daemon-config-store.ts index 33f5b17ce..4bed2ba61 100644 --- a/packages/server/src/server/daemon-config-store.ts +++ b/packages/server/src/server/daemon-config-store.ts @@ -10,10 +10,10 @@ export type { MutableDaemonConfig, MutableDaemonConfigPatch } from "../shared/me type MutableDaemonConfig = import("../shared/messages.js").MutableDaemonConfig; type MutableDaemonConfigPatch = import("../shared/messages.js").MutableDaemonConfigPatch; -type LoggerLike = { +interface LoggerLike { child(bindings: Record): LoggerLike; info(...args: any[]): void; -}; +} type ConfigListener = (config: MutableDaemonConfig) => void; type FieldChangeHandler = (value: unknown) => void; diff --git a/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts b/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts index 15fd9d2c8..98f941411 100644 --- a/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/claude-autonomous-wake.real.e2e.test.ts @@ -61,13 +61,13 @@ function resolveClaudeTranscriptPath(params: { cwd: string; sessionId: string }) ); } -type ClaudeTranscriptLine = { +interface ClaudeTranscriptLine { type?: unknown; timestamp?: unknown; uuid?: unknown; parentUuid?: unknown; message?: { content?: unknown } | null; -}; +} function readTranscriptLines(pathname: string): ClaudeTranscriptLine[] { if (!existsSync(pathname)) { @@ -158,10 +158,10 @@ function parseTimestamp(line: ClaudeTranscriptLine): number { return Number.isFinite(parsed) ? parsed : 0; } -type TranscriptRaceEvidence = { +interface TranscriptRaceEvidence { helloAssistantText: string; notificationOutcomeAssistantText: string; -}; +} function extractTranscriptRaceEvidence( lines: ClaudeTranscriptLine[], diff --git a/packages/server/src/server/daemon-e2e/ui-action-stress.real.e2e.test.ts b/packages/server/src/server/daemon-e2e/ui-action-stress.real.e2e.test.ts index 7829efb65..794adf0ba 100644 --- a/packages/server/src/server/daemon-e2e/ui-action-stress.real.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/ui-action-stress.real.e2e.test.ts @@ -71,15 +71,15 @@ type UiAction = label: string; }; -type UiScenario = { +interface UiScenario { name: string; actions: UiAction[]; -}; +} -type QueuedPrompt = { +interface QueuedPrompt { id: string; prompt: string; -}; +} function tmpCwd(): string { return mkdtempSync(path.join(tmpdir(), "daemon-real-ui-action-stress-")); diff --git a/packages/server/src/server/daemon-keypair.ts b/packages/server/src/server/daemon-keypair.ts index 236958f7d..9b42627bd 100644 --- a/packages/server/src/server/daemon-keypair.ts +++ b/packages/server/src/server/daemon-keypair.ts @@ -22,10 +22,10 @@ type StoredKeyPair = z.infer; const KEYPAIR_FILENAME = "daemon-keypair.json"; -export type DaemonKeyPairBundle = { +export interface DaemonKeyPairBundle { keyPair: KeyPair; publicKeyB64: string; -}; +} export async function loadOrCreateDaemonKeyPair( paseoHome: string, diff --git a/packages/server/src/server/dictation/dictation-stream-manager.ts b/packages/server/src/server/dictation/dictation-stream-manager.ts index 69d1d58c7..c87047ea1 100644 --- a/packages/server/src/server/dictation/dictation-stream-manager.ts +++ b/packages/server/src/server/dictation/dictation-stream-manager.ts @@ -67,7 +67,7 @@ function convertPCMToWavBuffer( return wavBuffer; } -type DictationStreamState = { +interface DictationStreamState { dictationId: string; sessionId: string; inputFormat: string; @@ -92,7 +92,7 @@ type DictationStreamState = { finishSealed: boolean; finalSeq: number | null; finalTimeout: ReturnType | null; -}; +} export type DictationStreamOutboundMessage = | { type: "dictation_stream_ack"; payload: { dictationId: string; ackSeq: number } } diff --git a/packages/server/src/server/editor-targets.ts b/packages/server/src/server/editor-targets.ts index 91fb36380..5774fc35e 100644 --- a/packages/server/src/server/editor-targets.ts +++ b/packages/server/src/server/editor-targets.ts @@ -8,18 +8,18 @@ import type { } from "../shared/messages.js"; import { findExecutable, quoteWindowsArgument, quoteWindowsCommand } from "../utils/executable.js"; -type EditorTargetDefinition = { +interface EditorTargetDefinition { id: KnownEditorTargetId; label: string; command: string; platforms?: readonly NodeJS.Platform[]; excludedPlatforms?: readonly NodeJS.Platform[]; -}; +} -type ListAvailableEditorTargetsDependencies = { +interface ListAvailableEditorTargetsDependencies { platform?: NodeJS.Platform; findExecutable?: (command: string) => string | null | Promise; -}; +} type OpenInEditorTargetDependencies = ListAvailableEditorTargetsDependencies & { existsSync?: typeof existsSync; @@ -89,10 +89,10 @@ export async function listAvailableEditorTargets( return results; } -type Launch = { +interface Launch { command: string; args: string[]; -}; +} async function resolveEditorLaunch(input: { editorId: EditorTargetId; diff --git a/packages/server/src/server/file-download/token-store.ts b/packages/server/src/server/file-download/token-store.ts index da0fb6c45..7b82f3fc6 100644 --- a/packages/server/src/server/file-download/token-store.ts +++ b/packages/server/src/server/file-download/token-store.ts @@ -1,6 +1,6 @@ import { randomUUID } from "node:crypto"; -export type DownloadTokenEntry = { +export interface DownloadTokenEntry { token: string; path: string; absolutePath: string; @@ -8,12 +8,12 @@ export type DownloadTokenEntry = { mimeType: string; size: number; expiresAt: number; -}; +} -type DownloadTokenStoreOptions = { +interface DownloadTokenStoreOptions { ttlMs: number; now?: () => number; -}; +} export class DownloadTokenStore { private readonly ttlMs: number; diff --git a/packages/server/src/server/logger.ts b/packages/server/src/server/logger.ts index a6506e1dd..91f1a41c3 100644 --- a/packages/server/src/server/logger.ts +++ b/packages/server/src/server/logger.ts @@ -25,17 +25,17 @@ export interface ResolvedLogConfig { }; } -type LegacyLogConfig = { +interface LegacyLogConfig { level?: LogLevel; format?: LogFormat; -}; +} type LoggerConfigInput = PersistedConfig | LegacyLogConfig | undefined; -type ResolveLogConfigOptions = { +interface ResolveLogConfigOptions { paseoHome?: string; env?: NodeJS.ProcessEnv; -}; +} const LOG_LEVELS: Set = new Set(["trace", "debug", "info", "warn", "error", "fatal"]); const LOG_FORMATS: Set = new Set(["pretty", "json"]); diff --git a/packages/server/src/server/package-version.ts b/packages/server/src/server/package-version.ts index 1b5beefe9..b83b076f8 100644 --- a/packages/server/src/server/package-version.ts +++ b/packages/server/src/server/package-version.ts @@ -2,15 +2,15 @@ import { existsSync, readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -type ResolvePackageVersionParams = { +interface ResolvePackageVersionParams { moduleUrl?: string; packageName: string; -}; +} -type PackageJson = { +interface PackageJson { name?: unknown; version?: unknown; -}; +} export class PackageVersionResolutionError extends Error { constructor(params: { moduleUrl: string; packageName: string }) { diff --git a/packages/server/src/server/pairing-offer.ts b/packages/server/src/server/pairing-offer.ts index 2b23291a4..be6fdb64f 100644 --- a/packages/server/src/server/pairing-offer.ts +++ b/packages/server/src/server/pairing-offer.ts @@ -5,11 +5,11 @@ import { loadOrCreateDaemonKeyPair } from "./daemon-keypair.js"; import { renderPairingQr } from "./pairing-qr.js"; import { getOrCreateServerId } from "./server-id.js"; -export type LocalPairingOffer = { +export interface LocalPairingOffer { relayEnabled: boolean; url: string | null; qr: string | null; -}; +} export async function generateLocalPairingOffer(args: { paseoHome: string; diff --git a/packages/server/src/server/paseo-worktree-archive-service.ts b/packages/server/src/server/paseo-worktree-archive-service.ts index 914b79fb3..efe1590b2 100644 --- a/packages/server/src/server/paseo-worktree-archive-service.ts +++ b/packages/server/src/server/paseo-worktree-archive-service.ts @@ -11,7 +11,7 @@ import type { TerminalManager } from "../terminal/terminal-manager.js"; type EmitSessionMessage = (message: SessionOutboundMessage) => void; -export type ArchivePaseoWorktreeDependencies = { +export interface ArchivePaseoWorktreeDependencies { paseoHome?: string; github: GitHubService; workspaceGitService: Pick; @@ -23,15 +23,15 @@ export type ArchivePaseoWorktreeDependencies = { isPathWithinRoot: (rootPath: string, candidatePath: string) => boolean; killTerminalsUnderPath: (rootPath: string) => Promise; sessionLogger?: Logger; -}; +} -export type KillTerminalsUnderPathDependencies = { +export interface KillTerminalsUnderPathDependencies { isPathWithinRoot: (rootPath: string, candidatePath: string) => boolean; killTrackedTerminal: (terminalId: string, options?: { emitExit: boolean }) => void; detachTerminalStream?: (terminalId: string, options: { emitExit: boolean }) => void; sessionLogger: Logger; terminalManager: TerminalManager | null; -}; +} export async function archivePaseoWorktree( dependencies: ArchivePaseoWorktreeDependencies, diff --git a/packages/server/src/server/persisted-config.ts b/packages/server/src/server/persisted-config.ts index a96ef7f69..c966457a2 100644 --- a/packages/server/src/server/persisted-config.ts +++ b/packages/server/src/server/persisted-config.ts @@ -310,10 +310,10 @@ const DEFAULT_PERSISTED_CONFIG = PersistedConfigSchema.parse({ }, }) as PersistedConfig; -type LoggerLike = { +interface LoggerLike { child(bindings: Record): LoggerLike; info(...args: any[]): void; -}; +} function getConfigPath(paseoHome: string): string { return path.join(paseoHome, CONFIG_FILENAME); diff --git a/packages/server/src/server/persistence-hooks.ts b/packages/server/src/server/persistence-hooks.ts index bf1085d6b..7ad60748b 100644 --- a/packages/server/src/server/persistence-hooks.ts +++ b/packages/server/src/server/persistence-hooks.ts @@ -7,11 +7,11 @@ import type { import type { AgentStorage, StoredAgentRecord } from "./agent/agent-storage.js"; import { buildProviderRegistry } from "./agent/provider-registry.js"; -type LoggerLike = { +interface LoggerLike { child(bindings: Record): LoggerLike; error(...args: any[]): void; warn(...args: any[]): void; -}; +} const DEFAULT_AGENT_PROVIDER = "claude"; @@ -22,10 +22,10 @@ function getLogger(logger: LoggerLike): LoggerLike { type AgentStoragePersistence = Pick; type AgentManagerStateSource = Pick; -type BuildSessionConfigOptions = { +interface BuildSessionConfigOptions { validProviders?: Iterable; logger?: LoggerLike; -}; +} type RegisteredProviders = ReturnType | Iterable; diff --git a/packages/server/src/server/relay-transport.ts b/packages/server/src/server/relay-transport.ts index 4e6059200..1d7fa069a 100644 --- a/packages/server/src/server/relay-transport.ts +++ b/packages/server/src/server/relay-transport.ts @@ -11,25 +11,25 @@ import { import { buildRelayWebSocketUrl } from "../shared/daemon-endpoints.js"; import type { ExternalSocketMetadata } from "./websocket-server.js"; -type RelayTransportOptions = { +interface RelayTransportOptions { logger: pino.Logger; attachSocket: (ws: RelaySocketLike, metadata?: ExternalSocketMetadata) => Promise; relayEndpoint: string; // "host:port" serverId: string; daemonKeyPair?: KeyPair; -}; +} -export type RelayTransportController = { +export interface RelayTransportController { stop: () => Promise; -}; +} -type RelaySocketLike = { +interface RelaySocketLike { readyState: number; send: (data: string | Uint8Array | ArrayBuffer) => void; close: (code?: number, reason?: string) => void; on: (event: "message" | "close" | "error", listener: (...args: any[]) => void) => void; once: (event: "close" | "error", listener: (...args: any[]) => void) => void; -}; +} type ControlMessage = | { type: "sync"; connectionIds: string[] } diff --git a/packages/server/src/server/script-health-monitor.test.ts b/packages/server/src/server/script-health-monitor.test.ts index 9bf9bde4d..c27c34b20 100644 --- a/packages/server/src/server/script-health-monitor.test.ts +++ b/packages/server/src/server/script-health-monitor.test.ts @@ -10,10 +10,10 @@ import { ScriptHealthMonitor, type ScriptHealthEntry } from "./script-health-mon import { spawnWorkspaceScript } from "./worktree-bootstrap.js"; import { WorkspaceScriptRuntimeStore } from "./workspace-script-runtime-store.js"; -type TcpServerHandle = { +interface TcpServerHandle { port: number; server: net.Server; -}; +} function createWorkspaceRepo(options?: { branchName?: string; diff --git a/packages/server/src/server/script-health-monitor.ts b/packages/server/src/server/script-health-monitor.ts index 38332d902..738e61303 100644 --- a/packages/server/src/server/script-health-monitor.ts +++ b/packages/server/src/server/script-health-monitor.ts @@ -10,12 +10,12 @@ export interface ScriptHealthEntry { health: ScriptHealthState; } -type RouteHealthState = { +interface RouteHealthState { workspaceId: string; health: ScriptHealthState; consecutiveFailures: number; registeredAt: number; -}; +} export class ScriptHealthMonitor { private readonly routeStore: ScriptRouteStore; diff --git a/packages/server/src/server/script-status-projection.ts b/packages/server/src/server/script-status-projection.ts index bb1676187..95a6aa0b4 100644 --- a/packages/server/src/server/script-status-projection.ts +++ b/packages/server/src/server/script-status-projection.ts @@ -10,11 +10,11 @@ import type { ScriptHealthEntry, ScriptHealthState } from "./script-health-monit import type { ScriptRouteStore } from "./script-proxy.js"; import type { WorkspaceScriptRuntimeStore } from "./workspace-script-runtime-store.js"; -type SessionEmitter = { +interface SessionEmitter { emit(message: SessionOutboundMessage): void; -}; +} -type BuildWorkspaceScriptPayloadsOptions = { +interface BuildWorkspaceScriptPayloadsOptions { workspaceId: string; workspaceDirectory: string; routeStore: ScriptRouteStore; @@ -25,7 +25,7 @@ type BuildWorkspaceScriptPayloadsOptions = { currentBranch: string | null; }; resolveHealth?: (hostname: string) => ScriptHealthState | null; -}; +} function resolveDaemonPort(daemonPort: number | null | (() => number | null)): number | null { if (typeof daemonPort === "function") { diff --git a/packages/server/src/server/server-id.ts b/packages/server/src/server/server-id.ts index fef9f0a9d..ba06929ac 100644 --- a/packages/server/src/server/server-id.ts +++ b/packages/server/src/server/server-id.ts @@ -2,11 +2,11 @@ import path from "node:path"; import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { randomBytes } from "node:crypto"; -type LoggerLike = { +interface LoggerLike { child(bindings: Record): LoggerLike; info(...args: any[]): void; warn(...args: any[]): void; -}; +} const SERVER_ID_FILENAME = "server-id"; diff --git a/packages/server/src/server/session.test.ts b/packages/server/src/server/session.test.ts index 71c1d8d32..53588c41f 100644 --- a/packages/server/src/server/session.test.ts +++ b/packages/server/src/server/session.test.ts @@ -45,11 +45,11 @@ const paseoWorktreeServiceMocks = vi.hoisted(() => ({ createPaseoWorktree: vi.fn(), })); -type Deferred = { +interface Deferred { promise: Promise; resolve: (value: T) => void; reject: (reason?: unknown) => void; -}; +} const TEST_CAPABILITIES = { supportsStreaming: false, diff --git a/packages/server/src/server/session.ts b/packages/server/src/server/session.ts index c32fb1dac..4f7d7a6ed 100644 --- a/packages/server/src/server/session.ts +++ b/packages/server/src/server/session.ts @@ -320,7 +320,7 @@ export function resolveWaitForFinishError(options: { type ProcessingPhase = "idle" | "transcribing"; -type WorkspaceGitWatchTarget = { +interface WorkspaceGitWatchTarget { cwd: string; watchers: FSWatcher[]; debounceTimer: ReturnType | null; @@ -328,22 +328,22 @@ type WorkspaceGitWatchTarget = { refreshQueued: boolean; latestDescriptorStateKey: string | null; lastBranchName: string | null; -}; +} -type ActiveTerminalStream = { +interface ActiveTerminalStream { terminalId: string; slot: number; unsubscribe: () => void; needsSnapshot: boolean; outputCoalescer: TerminalOutputCoalescer; -}; +} -export type SessionRuntimeMetrics = { +export interface SessionRuntimeMetrics { terminalDirectorySubscriptionCount: number; terminalSubscriptionCount: number; inflightRequests: number; peakInflightRequests: number; -}; +} type FetchAgentsRequestMessage = Extract; type FetchAgentHistoryRequestMessage = Extract< @@ -361,17 +361,17 @@ type FetchAgentsResponseEntry = FetchAgentsResponsePayload["entries"][number]; type FetchAgentsResponsePageInfo = FetchAgentsResponsePayload["pageInfo"]; type AgentUpdatePayload = Extract["payload"]; type AgentUpdatesFilter = FetchAgentsRequestFilter; -type AgentUpdatesSubscriptionState = { +interface AgentUpdatesSubscriptionState { subscriptionId: string; filter?: AgentUpdatesFilter; isBootstrapping: boolean; pendingUpdatesByAgentId: Map; -}; -type FetchAgentsCursor = { +} +interface FetchAgentsCursor { sort: FetchAgentsRequestSort[]; values: Record; id: string; -}; +} type FetchWorkspacesRequestMessage = Extract< SessionInboundMessage, { type: "fetch_workspaces_request" } @@ -389,18 +389,18 @@ type WorkspaceUpdatePayload = Extract< { type: "workspace_update" } >["payload"]; type WorkspaceUpdatesFilter = FetchWorkspacesRequestFilter; -type WorkspaceUpdatesSubscriptionState = { +interface WorkspaceUpdatesSubscriptionState { subscriptionId: string; filter?: WorkspaceUpdatesFilter; isBootstrapping: boolean; pendingUpdatesByWorkspaceId: Map; lastEmittedByWorkspaceId: Map; -}; -type FetchWorkspacesCursor = { +} +interface FetchWorkspacesCursor { sort: FetchWorkspacesRequestSort[]; values: Record; id: string; -}; +} function summarizeFetchWorkspacesEntries(entries: Iterable): { count: number; @@ -461,9 +461,9 @@ const VOICE_INTERRUPT_CONFIRMATION_MS = 500; const AVAILABLE_EDITOR_TARGETS_CACHE_TTL_MS = 60_000; const AVAILABLE_EDITOR_TARGETS_CACHE_KEY = "available"; -type VoiceModeBaseConfig = { +interface VoiceModeBaseConfig { systemPrompt?: string; -}; +} interface AudioBufferState { chunks: Buffer[]; @@ -475,7 +475,7 @@ interface AudioBufferState { // Stub types for features under development (modules not yet available) type AgentMcpTransportFactory = () => Promise; -type VoiceTranscriptionResultPayload = { +interface VoiceTranscriptionResultPayload { text: string; requestId: string; language?: string; @@ -485,9 +485,9 @@ type VoiceTranscriptionResultPayload = { byteLength?: number; format?: string; debugRecordingPath?: string; -}; +} -export type SessionOptions = { +export interface SessionOptions { clientId: string; appVersion?: string | null; onMessage: (msg: SessionOutboundMessage) => void; @@ -542,7 +542,7 @@ export type SessionOptions = { agentProviderRuntimeSettings?: AgentProviderRuntimeSettingsMap; providerOverrides?: Record; isDev?: boolean; -}; +} export type SessionLifecycleIntent = | { @@ -568,18 +568,18 @@ type PullRequestTimelinePayload = Extract< >["payload"]; type PullRequestTimelinePayloadItem = PullRequestTimelinePayload["items"][number]; -type VoiceFeatureUnavailableContext = { +interface VoiceFeatureUnavailableContext { reasonCode: SpeechReadinessSnapshot["voiceFeature"]["reasonCode"]; message: string; retryable: boolean; missingModelIds: LocalSpeechModelId[]; -}; +} -type VoiceFeatureUnavailableResponseMetadata = { +interface VoiceFeatureUnavailableResponseMetadata { reasonCode?: SpeechReadinessSnapshot["voiceFeature"]["reasonCode"]; retryable?: boolean; missingModelIds?: LocalSpeechModelId[]; -}; +} class VoiceFeatureUnavailableError extends Error { readonly reasonCode: SpeechReadinessSnapshot["voiceFeature"]["reasonCode"]; diff --git a/packages/server/src/server/speech/providers/local/config.ts b/packages/server/src/server/speech/providers/local/config.ts index bf432b040..0a158c77d 100644 --- a/packages/server/src/server/speech/providers/local/config.ts +++ b/packages/server/src/server/speech/providers/local/config.ts @@ -14,22 +14,22 @@ import { type LocalTtsModelId, } from "./models.js"; -export type LocalSpeechModelConfig = { +export interface LocalSpeechModelConfig { dictationStt: LocalSttModelId; voiceStt: LocalSttModelId; voiceTts: LocalTtsModelId; voiceTtsSpeakerId?: number; voiceTtsSpeed?: number; -}; +} -export type LocalSpeechProviderConfig = { +export interface LocalSpeechProviderConfig { modelsDir: string; models: LocalSpeechModelConfig; -}; +} -export type ResolvedLocalSpeechConfig = { +export interface ResolvedLocalSpeechConfig { local: LocalSpeechProviderConfig | undefined; -}; +} export type { LocalSpeechModelId, LocalSttModelId, LocalTtsModelId }; diff --git a/packages/server/src/server/speech/providers/local/pocket/pocket-tts-onnx.ts b/packages/server/src/server/speech/providers/local/pocket/pocket-tts-onnx.ts index 194095b0f..4487dec73 100644 --- a/packages/server/src/server/speech/providers/local/pocket/pocket-tts-onnx.ts +++ b/packages/server/src/server/speech/providers/local/pocket/pocket-tts-onnx.ts @@ -16,11 +16,11 @@ type OrtModule = typeof import("onnxruntime-node"); type OrtSession = import("onnxruntime-node").InferenceSession; type OrtTensor = import("onnxruntime-node").Tensor; -type SentencePieceProcessor = { +interface SentencePieceProcessor { encodeIds: (text: string) => number[]; load?: (modelPath: string) => unknown; Load?: (modelPath: string) => unknown; -}; +} function assertFileExists(filePath: string, label: string): void { if (!existsSync(filePath)) { @@ -194,7 +194,7 @@ function tensorDataFloat32(t: OrtTensor): Float32Array { throw new Error("Unexpected tensor data type (expected Float32Array)"); } -export type PocketTtsOnnxConfig = { +export interface PocketTtsOnnxConfig { modelDir: string; precision?: "int8" | "fp32"; device?: "auto" | "cpu" | "cuda"; @@ -206,7 +206,7 @@ export type PocketTtsOnnxConfig = { maxChunkFrames?: number; targetChunkMs?: number; referenceAudioFile?: string; -}; +} class PocketTtsOnnxEngine { static readonly SAMPLE_RATE = 24000; diff --git a/packages/server/src/server/speech/providers/local/runtime.ts b/packages/server/src/server/speech/providers/local/runtime.ts index 0abfe2630..1b7d5c080 100644 --- a/packages/server/src/server/speech/providers/local/runtime.ts +++ b/packages/server/src/server/speech/providers/local/runtime.ts @@ -31,18 +31,18 @@ type LocalSttEngine = | { kind: "offline"; engine: SherpaOfflineRecognizerEngine } | { kind: "online"; engine: SherpaOnlineRecognizerEngine }; -type ResolvedLocalModels = { +interface ResolvedLocalModels { dictationLocalSttModel: LocalSttModelId; voiceLocalSttModel: LocalSttModelId; voiceLocalTtsModel: LocalTtsModelId; -}; +} -type LocalSpeechAvailability = { +interface LocalSpeechAvailability { configured: boolean; modelsDir: string | null; -}; +} -export type InitializedLocalSpeech = { +export interface InitializedLocalSpeech { turnDetectionService: TurnDetectionProvider | null; sttService: SpeechToTextProvider | null; ttsService: TextToSpeechProvider | null; @@ -54,7 +54,7 @@ export type InitializedLocalSpeech = { } | null; availability: LocalSpeechAvailability; cleanup: () => void; -}; +} function buildModelDownloadHint(modelId: LocalSpeechModelId): string { return `Use 'paseo speech download --model ${modelId}' to download this model.`; diff --git a/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts b/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts index 2b7e05b68..1ac6e2126 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/model-catalog.ts @@ -4,7 +4,7 @@ export type SherpaOnnxModelKind = "stt-online" | "stt-offline" | "tts"; type DefaultModelRole = "stt" | "tts"; -type SherpaOnnxCatalogEntry = { +interface SherpaOnnxCatalogEntry { kind: SherpaOnnxModelKind; archiveUrl?: string; downloadFiles?: Array<{ url: string; relPath: string }>; @@ -13,7 +13,7 @@ type SherpaOnnxCatalogEntry = { description: string; aliases?: readonly string[]; defaultFor?: DefaultModelRole; -}; +} export const SHERPA_ONNX_MODEL_CATALOG = { "zipformer-bilingual-zh-en-2023-02-20": { diff --git a/packages/server/src/server/speech/providers/local/sherpa/model-downloader.ts b/packages/server/src/server/speech/providers/local/sherpa/model-downloader.ts index d8430d487..5430a229e 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/model-downloader.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/model-downloader.ts @@ -8,11 +8,11 @@ import type pino from "pino"; import { getSherpaOnnxModelSpec, type SherpaOnnxModelId } from "./model-catalog.js"; -export type EnsureSherpaOnnxModelOptions = { +export interface EnsureSherpaOnnxModelOptions { modelsDir: string; modelId: SherpaOnnxModelId; logger: pino.Logger; -}; +} export function getSherpaOnnxModelDir(modelsDir: string, modelId: SherpaOnnxModelId): string { const spec = getSherpaOnnxModelSpec(modelId); @@ -38,10 +38,10 @@ async function hasRequiredFiles(modelDir: string, requiredFiles: string[]): Prom return true; } -type DownloadToFileOptions = { +interface DownloadToFileOptions { url: string; outputPath: string; -}; +} async function downloadToFile(options: DownloadToFileOptions): Promise { const { url, outputPath } = options; diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.ts index af75d1c8e..f0f339f6d 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-offline-recognizer.ts @@ -9,15 +9,15 @@ function assertFileExists(filePath: string, label: string): void { } } -export type SherpaOfflineRecognizerModel = { +export interface SherpaOfflineRecognizerModel { kind: "nemo_transducer"; encoder: string; decoder: string; joiner: string; tokens: string; -}; +} -export type SherpaOfflineRecognizerConfig = { +export interface SherpaOfflineRecognizerConfig { model: SherpaOfflineRecognizerModel; numThreads?: number; provider?: "cpu"; @@ -26,7 +26,7 @@ export type SherpaOfflineRecognizerConfig = { featureDim?: number; decodingMethod?: "greedy_search"; maxActivePaths?: number; -}; +} export class SherpaOfflineRecognizerEngine { public readonly recognizer: any; diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.ts index d124eba61..0794a2841 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-online-recognizer.ts @@ -19,7 +19,7 @@ export type SherpaOnlineRecognizerModel = tokens: string; }; -export type SherpaOnlineRecognizerConfig = { +export interface SherpaOnlineRecognizerConfig { model: SherpaOnlineRecognizerModel; numThreads?: number; provider?: "cpu"; @@ -32,7 +32,7 @@ export type SherpaOnlineRecognizerConfig = { rule1MinTrailingSilence?: number; rule2MinTrailingSilence?: number; rule3MinUtteranceLength?: number; -}; +} function assertFileExists(filePath: string, label: string): void { if (!existsSync(filePath)) { diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.ts index f90df65ee..89189e53e 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-loader.ts @@ -1,10 +1,10 @@ import { createRequire } from "node:module"; -export type SherpaOnnxModule = { +export interface SherpaOnnxModule { createOnlineRecognizer: (config: any) => any; createOfflineRecognizer: (config: any) => any; createOfflineTts: (config: any) => any; -}; +} let cached: SherpaOnnxModule | null = null; diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts index 4be421861..44a9ad0d6 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts @@ -8,20 +8,20 @@ import { sherpaPlatformPackageName, } from "./sherpa-runtime-env.js"; -export type SherpaOnnxNodeModule = { +export interface SherpaOnnxNodeModule { OfflineRecognizer: new (config: any) => any; OnlineRecognizer?: new (config: any) => any; OfflineTts?: new (config: any) => any; Vad?: new (config: any, bufferSizeInSeconds: number) => any; CircularBuffer?: new (capacity: number) => any; -}; +} let cached: SherpaOnnxNodeModule | null = null; -type LoadAttempt = { +interface LoadAttempt { target: string; error: unknown; -}; +} function appendAttempt(attempts: LoadAttempt[], target: string, error: unknown): void { attempts.push({ target, error }); diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.ts index bba9f70c8..bd6492caa 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-parakeet-stt.ts @@ -16,10 +16,10 @@ import { } from "../../../audio.js"; import { SherpaOfflineRecognizerEngine } from "./sherpa-offline-recognizer.js"; -export type SherpaParakeetSttConfig = { +export interface SherpaParakeetSttConfig { engine: SherpaOfflineRecognizerEngine; silencePeakThreshold?: number; -}; +} export class SherpaOnnxParakeetSTT implements SpeechToTextProvider { private readonly engine: SherpaOfflineRecognizerEngine; diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts index 83844cc7f..ee596d120 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts @@ -3,11 +3,11 @@ import path from "node:path"; export type SherpaLoaderEnvKey = "LD_LIBRARY_PATH" | "DYLD_LIBRARY_PATH" | "PATH"; -export type SherpaLoaderEnvResolution = { +export interface SherpaLoaderEnvResolution { key: SherpaLoaderEnvKey; libDir: string; packageName: string; -}; +} export function sherpaPlatformArch( platform: NodeJS.Platform = process.platform, diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-stt.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-stt.ts index 1226f85fe..1c4afa21c 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-stt.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-stt.ts @@ -16,11 +16,11 @@ import { } from "../../../audio.js"; import { SherpaOnlineRecognizerEngine } from "./sherpa-online-recognizer.js"; -export type SherpaSttConfig = { +export interface SherpaSttConfig { engine: SherpaOnlineRecognizerEngine; silencePeakThreshold?: number; tailPaddingMs?: number; -}; +} export class SherpaOnnxSTT implements SpeechToTextProvider { private readonly engine: SherpaOnlineRecognizerEngine; diff --git a/packages/server/src/server/speech/providers/local/sherpa/sherpa-tts.ts b/packages/server/src/server/speech/providers/local/sherpa/sherpa-tts.ts index 4a4c71a26..fa33e8a23 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/sherpa-tts.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/sherpa-tts.ts @@ -8,14 +8,14 @@ import { loadSherpaOnnxNode } from "./sherpa-onnx-node-loader.js"; export type SherpaTtsPreset = "kokoro-en-v0_19" | "kitten-nano-en-v0_1-fp16"; -export type SherpaTtsConfig = { +export interface SherpaTtsConfig { preset: SherpaTtsPreset; modelDir: string; speakerId?: number; speed?: number; lengthScale?: number; numThreads?: number; -}; +} function assertFileExists(filePath: string, label: string): void { if (!existsSync(filePath)) { diff --git a/packages/server/src/server/speech/providers/local/sherpa/silero-vad-session.ts b/packages/server/src/server/speech/providers/local/sherpa/silero-vad-session.ts index 3129a6f68..16c248b9d 100644 --- a/packages/server/src/server/speech/providers/local/sherpa/silero-vad-session.ts +++ b/packages/server/src/server/speech/providers/local/sherpa/silero-vad-session.ts @@ -19,27 +19,27 @@ const SILERO_MIN_SPEECH_DURATION = 0.1; const DEFAULT_CONFIRM_MS = 800; const DEFAULT_SILENCE_MS = 1000; -type SherpaVadHandle = { +interface SherpaVadHandle { acceptWaveform(samples: Float32Array): void; isDetected(): boolean; isEmpty(): boolean; flush(): void; reset(): void; -}; +} -type SherpaCircularBufferHandle = { +interface SherpaCircularBufferHandle { push(samples: Float32Array): void; get(startIndex: number, n: number, enableExternalBuffer?: boolean): Float32Array; pop(n: number): void; size(): number; head(): number; reset(): void; -}; +} -type SherpaVadModule = { +interface SherpaVadModule { Vad: new (config: Record, bufferSizeInSeconds: number) => SherpaVadHandle; CircularBuffer: new (capacity: number) => SherpaCircularBufferHandle; -}; +} export function resolveBundledSileroVadModelPath(): string { return fileURLToPath(new URL("./assets/silero_vad.onnx", import.meta.url)); diff --git a/packages/server/src/server/speech/providers/openai/config.ts b/packages/server/src/server/speech/providers/openai/config.ts index 02f85e841..3b70763a8 100644 --- a/packages/server/src/server/speech/providers/openai/config.ts +++ b/packages/server/src/server/speech/providers/openai/config.ts @@ -8,12 +8,12 @@ import type { TTSConfig } from "./tts.js"; export const DEFAULT_OPENAI_REALTIME_TRANSCRIPTION_MODEL = "gpt-4o-transcribe"; export const DEFAULT_OPENAI_TTS_MODEL = "tts-1"; -export type OpenAiSpeechProviderConfig = { +export interface OpenAiSpeechProviderConfig { apiKey?: string; stt?: Partial & { apiKey?: string }; tts?: Partial & { apiKey?: string }; realtimeTranscriptionModel?: string; -}; +} const OpenAiTtsVoiceSchema = z.enum(["alloy", "echo", "fable", "onyx", "nova", "shimmer"]); diff --git a/packages/server/src/server/speech/providers/openai/runtime.ts b/packages/server/src/server/speech/providers/openai/runtime.ts index 81f4fb6c5..e9d49605c 100644 --- a/packages/server/src/server/speech/providers/openai/runtime.ts +++ b/packages/server/src/server/speech/providers/openai/runtime.ts @@ -12,24 +12,24 @@ import { OpenAIRealtimeTranscriptionSession } from "./realtime-transcription-ses import { OpenAISTT } from "./stt.js"; import { OpenAITTS } from "./tts.js"; -type OpenAiCredentialState = { +interface OpenAiCredentialState { openaiSttApiKey: string | undefined; openaiTtsApiKey: string | undefined; openaiDictationApiKey: string | undefined; -}; +} -export type OpenAiSpeechAvailability = { +export interface OpenAiSpeechAvailability { stt: boolean; tts: boolean; dictationStt: boolean; -}; +} -export type SpeechServices = { +export interface SpeechServices { turnDetectionService: TurnDetectionProvider | null; sttService: SpeechToTextProvider | null; ttsService: TextToSpeechProvider | null; dictationSttService: SpeechToTextProvider | null; -}; +} function resolveOpenAiCredentials( openaiConfig: OpenAiSpeechProviderConfig | undefined, diff --git a/packages/server/src/server/speech/speech-provider.ts b/packages/server/src/server/speech/speech-provider.ts index 1ae58b175..6321e8b35 100644 --- a/packages/server/src/server/speech/speech-provider.ts +++ b/packages/server/src/server/speech/speech-provider.ts @@ -31,7 +31,7 @@ export interface StreamingTranscriptionEvent { isLowConfidence?: boolean; } -export type StreamingTranscriptionSession = { +export interface StreamingTranscriptionSession { /** * Required PCM16LE sample rate for `appendPcm16()`. * Callers are responsible for resampling before appending. @@ -47,7 +47,7 @@ export type StreamingTranscriptionSession = { on(event: "committed", handler: (payload: StreamingTranscriptionCommittedEvent) => void): unknown; on(event: "transcript", handler: (payload: StreamingTranscriptionEvent) => void): unknown; on(event: "error", handler: (err: unknown) => void): unknown; -}; +} export interface SpeechToTextProvider { id: "openai" | "local" | (string & {}); diff --git a/packages/server/src/server/speech/speech-runtime.ts b/packages/server/src/server/speech/speech-runtime.ts index c56c19296..c0f0e8554 100644 --- a/packages/server/src/server/speech/speech-runtime.ts +++ b/packages/server/src/server/speech/speech-runtime.ts @@ -31,16 +31,16 @@ export type SpeechReadinessReasonCode = | "stt_unavailable" | "tts_unavailable"; -export type SpeechReadinessState = { +export interface SpeechReadinessState { enabled: boolean; available: boolean; reasonCode: SpeechReadinessReasonCode; message: string; retryable: boolean; missingModelIds: LocalSpeechModelId[]; -}; +} -export type SpeechReadinessSnapshot = { +export interface SpeechReadinessSnapshot { generatedAt: string; requiredLocalModelIds: LocalSpeechModelId[]; missingLocalModelIds: LocalSpeechModelId[]; @@ -51,7 +51,7 @@ export type SpeechReadinessSnapshot = { realtimeVoice: SpeechReadinessState; dictation: SpeechReadinessState; voiceFeature: SpeechReadinessState; -}; +} function resolveRequestedSpeechProviders( speechConfig: PaseoSpeechConfig | null, @@ -336,7 +336,7 @@ function resolveEffectiveProviderIds(params: { }; } -export type SpeechService = { +export interface SpeechService { resolveStt: () => SpeechToTextProvider | null; resolveTts: () => TextToSpeechProvider | null; resolveTurnDetection: () => TurnDetectionProvider | null; @@ -346,7 +346,7 @@ export type SpeechService = { start: () => void; stop: () => void; ready: Promise; -}; +} export function createSpeechService(params: { logger: Logger; diff --git a/packages/server/src/server/speech/speech-types.ts b/packages/server/src/server/speech/speech-types.ts index 797b5e3f1..12baacd83 100644 --- a/packages/server/src/server/speech/speech-types.ts +++ b/packages/server/src/server/speech/speech-types.ts @@ -10,9 +10,9 @@ export const RequestedSpeechProviderSchema = z.object({ }); export type RequestedSpeechProvider = z.infer; -export type RequestedSpeechProviders = { +export interface RequestedSpeechProviders { dictationStt: RequestedSpeechProvider; voiceTurnDetection: RequestedSpeechProvider; voiceStt: RequestedSpeechProvider; voiceTts: RequestedSpeechProvider; -}; +} diff --git a/packages/server/src/server/speech/turn-detection-provider.ts b/packages/server/src/server/speech/turn-detection-provider.ts index d25501833..d301c673d 100644 --- a/packages/server/src/server/speech/turn-detection-provider.ts +++ b/packages/server/src/server/speech/turn-detection-provider.ts @@ -1,6 +1,6 @@ import type pino from "pino"; -export type TurnDetectionSession = { +export interface TurnDetectionSession { /** * Required PCM16LE sample rate for `appendPcm16()`. * Callers are responsible for resampling before appending. @@ -16,7 +16,7 @@ export type TurnDetectionSession = { on(event: "speech_started", handler: () => void): unknown; on(event: "speech_stopped", handler: () => void): unknown; on(event: "error", handler: (err: unknown) => void): unknown; -}; +} export interface TurnDetectionProvider { id: "openai" | "local" | (string & {}); diff --git a/packages/server/src/server/test-utils/fake-agent-client.ts b/packages/server/src/server/test-utils/fake-agent-client.ts index a92e362e9..0e690dbba 100644 --- a/packages/server/src/server/test-utils/fake-agent-client.ts +++ b/packages/server/src/server/test-utils/fake-agent-client.ts @@ -32,11 +32,11 @@ const TEST_CAPABILITIES: AgentCapabilityFlags = { supportsToolInvocations: true, }; -type Deferred = { +interface Deferred { promise: Promise; resolve: (value: T) => void; reject: (err: unknown) => void; -}; +} function createDeferred(): Deferred { let resolve!: (value: T) => void; diff --git a/packages/server/src/server/test-utils/paseo-daemon.ts b/packages/server/src/server/test-utils/paseo-daemon.ts index c34fa0a3d..85edde9c5 100644 --- a/packages/server/src/server/test-utils/paseo-daemon.ts +++ b/packages/server/src/server/test-utils/paseo-daemon.ts @@ -12,7 +12,7 @@ import { import type { AgentClient, AgentProvider } from "../agent/agent-sdk-types.js"; import { createTestAgentClients } from "./fake-agent-client.js"; -type TestPaseoDaemonOptions = { +interface TestPaseoDaemonOptions { downloadTokenTtlMs?: number; corsAllowedOrigins?: string[]; listen?: string; @@ -29,16 +29,16 @@ type TestPaseoDaemonOptions = { voiceLlmProviderExplicit?: boolean; voiceLlmModel?: string | null; dictationFinalTimeoutMs?: number; -}; +} -export type TestPaseoDaemon = { +export interface TestPaseoDaemon { config: PaseoDaemonConfig; daemon: Awaited>; port: number; paseoHome: string; staticDir: string; close: () => Promise; -}; +} const TEST_DAEMON_START_TIMEOUT_MS = 20_000; diff --git a/packages/server/src/server/voice-types.ts b/packages/server/src/server/voice-types.ts index 14c78ceb6..9533b10c3 100644 --- a/packages/server/src/server/voice-types.ts +++ b/packages/server/src/server/voice-types.ts @@ -4,9 +4,9 @@ export type VoiceSpeakHandler = (params: { signal?: AbortSignal; }) => Promise; -export type VoiceCallerContext = { +export interface VoiceCallerContext { childAgentDefaultLabels?: Record; lockedCwd?: string; allowCustomCwd?: boolean; enableVoiceTools?: boolean; -}; +} diff --git a/packages/server/src/server/websocket-server.runtime-metrics.test.ts b/packages/server/src/server/websocket-server.runtime-metrics.test.ts index bf225adee..e49c5d3a1 100644 --- a/packages/server/src/server/websocket-server.runtime-metrics.test.ts +++ b/packages/server/src/server/websocket-server.runtime-metrics.test.ts @@ -28,7 +28,7 @@ vi.mock("ws", () => ({ import { VoiceAssistantWebSocketServer } from "./websocket-server.js"; import { wrapSessionMessage } from "./messages.js"; -type RuntimeMetricsLog = { +interface RuntimeMetricsLog { outboundMessageTypesTop: Array<[string, number]>; outboundSessionMessageTypesTop: Array<[string, number]>; outboundAgentStreamTypesTop: Array<[string, number]>; @@ -38,9 +38,9 @@ type RuntimeMetricsLog = { p95: number; max: number; }; -}; +} -type TestSocket = { +interface TestSocket { readyState: number; bufferedAmount: number; sent: Array; @@ -49,7 +49,7 @@ type TestSocket = { close: () => void; on: () => void; once: () => void; -}; +} function createLogger() { const logger = { diff --git a/packages/server/src/server/websocket-server.ts b/packages/server/src/server/websocket-server.ts index 96f2e289d..08a416a9c 100644 --- a/packages/server/src/server/websocket-server.ts +++ b/packages/server/src/server/websocket-server.ts @@ -51,20 +51,20 @@ import { } from "../shared/agent-attention-notification.js"; import { createGitHubService, type GitHubService } from "../services/github-service.js"; -export type ExternalSocketMetadata = { +export interface ExternalSocketMetadata { transport: "relay"; externalSessionKey?: string; -}; +} -type PendingConnection = { +interface PendingConnection { connectionLogger: pino.Logger; helloTimeout: ReturnType | null; -}; +} -type WebSocketServerConfig = { +interface WebSocketServerConfig { allowedOrigins: Set; hostnames?: HostnamesConfig; -}; +} type WebSocketRuntimeMetrics = SessionRuntimeMetrics & CheckoutDiffMetrics; @@ -232,25 +232,25 @@ function bufferFromWsData(data: Buffer | ArrayBuffer | Buffer[] | string): Buffe return Buffer.from(data as ArrayBuffer); } -type WebSocketLike = { +interface WebSocketLike { readyState: number; bufferedAmount?: number; send: (data: string | Uint8Array | ArrayBuffer) => void; close: (code?: number, reason?: string) => void; on: (event: "message" | "close" | "error", listener: (...args: any[]) => void) => void; once: (event: "close" | "error", listener: (...args: any[]) => void) => void; -}; +} -type SessionConnection = { +interface SessionConnection { session: Session; clientId: string; appVersion: string | null; connectionLogger: pino.Logger; sockets: Set; externalDisconnectCleanupTimeout: ReturnType | null; -}; +} -type WebSocketRuntimeCounters = { +interface WebSocketRuntimeCounters { connectedAwaitingHello: number; helloResumed: number; helloNew: number; @@ -266,7 +266,7 @@ type WebSocketRuntimeCounters = { relayExternalSocketAttached: number; originRejected: number; hostRejected: number; -}; +} const SLOW_REQUEST_THRESHOLD_MS = 500; const EXTERNAL_SESSION_DISCONNECT_GRACE_MS = 90_000; @@ -1612,12 +1612,12 @@ export class VoiceAssistantWebSocketServer { } } -type SocketRequestMetadata = { +interface SocketRequestMetadata { host?: string; origin?: string; userAgent?: string; remoteAddress?: string; -}; +} function extractSocketRequestMetadata(request: unknown): SocketRequestMetadata { if (!request || typeof request !== "object") { diff --git a/packages/server/src/server/workspace-git-metadata.ts b/packages/server/src/server/workspace-git-metadata.ts index 1793c79b1..c3480b6e8 100644 --- a/packages/server/src/server/workspace-git-metadata.ts +++ b/packages/server/src/server/workspace-git-metadata.ts @@ -1,7 +1,7 @@ import { basename } from "path"; import { slugify } from "../utils/worktree.js"; -export type WorkspaceGitMetadata = { +export interface WorkspaceGitMetadata { projectKind: "git" | "directory"; projectDisplayName: string; workspaceDisplayName: string; @@ -11,7 +11,7 @@ export type WorkspaceGitMetadata = { repoRoot: string | null; currentBranch: string | null; remoteUrl: string | null; -}; +} export function parseGitHubRepoFromRemote(remoteUrl: string): string | null { let cleaned = remoteUrl.trim(); diff --git a/packages/server/src/server/workspace-git-service.ts b/packages/server/src/server/workspace-git-service.ts index 6335cd308..816f4f3a8 100644 --- a/packages/server/src/server/workspace-git-service.ts +++ b/packages/server/src/server/workspace-git-service.ts @@ -38,7 +38,7 @@ const WORKSPACE_GIT_CONSUMER_TTL_MS = 15_000; // Non-forced refresh triggers share this minimum gap to absorb watcher/self-heal bursts; force bypasses it. const WORKSPACE_GIT_INTERNAL_MIN_GAP_MS = 2_000; -export type WorkspaceGitRuntimeSnapshot = { +export interface WorkspaceGitRuntimeSnapshot { cwd: string; git: { isGit: boolean; @@ -80,7 +80,7 @@ export type WorkspaceGitRuntimeSnapshot = { } | null; error: { message: string } | null; }; -}; +} export interface WorkspaceGitService { registerWorkspace( @@ -136,9 +136,9 @@ export interface WorkspaceGitService { export type WorkspaceGitListener = (snapshot: WorkspaceGitRuntimeSnapshot) => void; -export type WorkspaceGitSubscription = { +export interface WorkspaceGitSubscription { unsubscribe: () => void; -}; +} export type WorkspaceGitReadOptions = | { diff --git a/packages/server/src/server/workspace-reconciliation-service.ts b/packages/server/src/server/workspace-reconciliation-service.ts index 38f4d01f2..3e71788bb 100644 --- a/packages/server/src/server/workspace-reconciliation-service.ts +++ b/packages/server/src/server/workspace-reconciliation-service.ts @@ -26,19 +26,19 @@ export type ReconciliationChange = fields: Partial>; }; -export type ReconciliationResult = { +export interface ReconciliationResult { changesApplied: ReconciliationChange[]; durationMs: number; -}; +} -export type WorkspaceReconciliationServiceOptions = { +export interface WorkspaceReconciliationServiceOptions { projectRegistry: ProjectRegistry; workspaceRegistry: WorkspaceRegistry; logger: pino.Logger; intervalMs?: number; onChanges?: (changes: ReconciliationChange[]) => void; workspaceGitService?: Pick; -}; +} export class WorkspaceReconciliationService { private readonly projectRegistry: ProjectRegistry; diff --git a/packages/server/src/server/workspace-registry-model.ts b/packages/server/src/server/workspace-registry-model.ts index 976f9edc6..5062fdcd9 100644 --- a/packages/server/src/server/workspace-registry-model.ts +++ b/packages/server/src/server/workspace-registry-model.ts @@ -7,10 +7,10 @@ import type { PersistedWorkspaceRecord } from "./workspace-registry.js"; export type PersistedProjectKind = "git" | "non_git"; export type PersistedWorkspaceKind = "local_checkout" | "worktree" | "directory"; -export type DetectStaleWorkspacesInput = { +export interface DetectStaleWorkspacesInput { activeWorkspaces: PersistedWorkspaceRecord[]; checkDirectoryExists: (cwd: string) => Promise; -}; +} export function normalizeWorkspaceId(cwd: string): string { const trimmed = cwd.trim(); diff --git a/packages/server/src/server/workspace-script-runtime-store.ts b/packages/server/src/server/workspace-script-runtime-store.ts index 8f46980f0..a2f48199b 100644 --- a/packages/server/src/server/workspace-script-runtime-store.ts +++ b/packages/server/src/server/workspace-script-runtime-store.ts @@ -7,10 +7,10 @@ export interface ScriptRuntimeEntry { exitCode: number | null; } -type RuntimeEntryKey = { +interface RuntimeEntryKey { workspaceId: string; scriptName: string; -}; +} export class WorkspaceScriptRuntimeStore { private readonly entries = new Map(); diff --git a/packages/server/src/server/worktree-bootstrap.ts b/packages/server/src/server/worktree-bootstrap.ts index e78f6d24f..47ebb8f8b 100644 --- a/packages/server/src/server/worktree-bootstrap.ts +++ b/packages/server/src/server/worktree-bootstrap.ts @@ -51,18 +51,18 @@ const MAX_WORKTREE_SETUP_COMMAND_OUTPUT_BYTES = 64 * 1024; const WORKTREE_SETUP_TRUNCATION_MARKER = "\n......\n"; const WORKTREE_BOOTSTRAP_TERMINAL_READY_TIMEOUT_MS = 1_500; -type MiddleTruncationAccumulator = { +interface MiddleTruncationAccumulator { totalBytes: number; head: string; tail: string; truncated: boolean; -}; +} export type WorktreeSetupOutputAccumulator = MiddleTruncationAccumulator; -export type WorktreeSetupProgressAccumulator = { +export interface WorktreeSetupProgressAccumulator { resultsByIndex: Map; outputAccumulatorsByIndex: Map; -}; +} function byteLength(text: string): number { return Buffer.byteLength(text, "utf8"); diff --git a/packages/server/src/server/worktree-session.ts b/packages/server/src/server/worktree-session.ts index 77c9ae5f5..1180eae23 100644 --- a/packages/server/src/server/worktree-session.ts +++ b/packages/server/src/server/worktree-session.ts @@ -62,7 +62,7 @@ export interface NormalizedGitOptions { type EmitSessionMessage = (message: SessionOutboundMessage) => void; -type BuildAgentSessionConfigDependencies = { +interface BuildAgentSessionConfigDependencies { paseoHome?: string; sessionLogger: Logger; workspaceGitService?: WorkspaceGitService; @@ -79,9 +79,9 @@ type BuildAgentSessionConfigDependencies = { newBranchName: string; }) => Promise; github?: Pick; -}; +} -type CreatePaseoWorktreeInBackgroundDependencies = { +interface CreatePaseoWorktreeInBackgroundDependencies { paseoHome?: string; emitWorkspaceUpdateForCwd: (cwd: string, options?: { dedupeGitState?: boolean }) => Promise; cacheWorkspaceSetupSnapshot: (workspaceId: string, snapshot: WorkspaceSetupSnapshot) => void; @@ -94,14 +94,14 @@ type CreatePaseoWorktreeInBackgroundDependencies = { getDaemonTcpPort: (() => number | null) | null; getDaemonTcpHost: (() => string | null) | null; onScriptsChanged: ((workspaceId: string, workspaceDirectory: string) => void) | null; -}; +} -type HandleWorkspaceSetupStatusRequestDependencies = { +interface HandleWorkspaceSetupStatusRequestDependencies { emit: EmitSessionMessage; workspaceSetupSnapshots: ReadonlyMap; -}; +} -type HandleCreatePaseoWorktreeRequestDependencies = { +interface HandleCreatePaseoWorktreeRequestDependencies { paseoHome?: string; describeWorkspaceRecord: ( result: CreatePaseoWorktreeResult, @@ -119,7 +119,7 @@ type HandleCreatePaseoWorktreeRequestDependencies = { slug: string; worktreePath: string; }) => Promise; -}; +} export async function buildAgentSessionConfig( dependencies: BuildAgentSessionConfigDependencies, diff --git a/packages/server/src/shared/agent-attention-notification.ts b/packages/server/src/shared/agent-attention-notification.ts index c258bb7b7..14b660868 100644 --- a/packages/server/src/shared/agent-attention-notification.ts +++ b/packages/server/src/shared/agent-attention-notification.ts @@ -2,27 +2,27 @@ const NOTIFICATION_PREVIEW_LIMIT = 220; export type AgentAttentionReason = "finished" | "error" | "permission"; -export type AgentAttentionNotificationData = { +export interface AgentAttentionNotificationData { serverId: string; agentId: string; reason: AgentAttentionReason; -}; +} -export type AgentAttentionNotificationPayload = { +export interface AgentAttentionNotificationPayload { title: string; body: string; data: AgentAttentionNotificationData; -}; +} -type BuildAgentAttentionNotificationPayloadInput = { +interface BuildAgentAttentionNotificationPayloadInput { reason: AgentAttentionReason; serverId: string; agentId: string; assistantMessage?: string | null; permissionRequest?: NotificationPermissionRequest | null; -}; +} -export type NotificationPermissionRequest = { +export interface NotificationPermissionRequest { id: string; provider: string; name: string; @@ -31,7 +31,7 @@ export type NotificationPermissionRequest = { description?: string; input?: Record; metadata?: Record; -}; +} export type AssistantTimelineItem = | { type: "assistant_message"; text: string } diff --git a/packages/server/src/shared/daemon-endpoints.ts b/packages/server/src/shared/daemon-endpoints.ts index b1eddf94c..c720fa7e5 100644 --- a/packages/server/src/shared/daemon-endpoints.ts +++ b/packages/server/src/shared/daemon-endpoints.ts @@ -1,8 +1,8 @@ -export type HostPortParts = { +export interface HostPortParts { host: string; port: number; isIpv6: boolean; -}; +} export type RelayRole = "server" | "client"; export type RelayProtocolVersion = "1" | "2"; diff --git a/packages/server/src/shared/terminal-stream-protocol.ts b/packages/server/src/shared/terminal-stream-protocol.ts index 6970b9620..10314242e 100644 --- a/packages/server/src/shared/terminal-stream-protocol.ts +++ b/packages/server/src/shared/terminal-stream-protocol.ts @@ -17,11 +17,11 @@ export const TerminalStreamOpcode = { export type TerminalStreamOpcode = (typeof TerminalStreamOpcode)[keyof typeof TerminalStreamOpcode]; -export type TerminalStreamFrame = { +export interface TerminalStreamFrame { opcode: TerminalStreamOpcode; slot: number; payload: Uint8Array; -}; +} export function asUint8Array(data: unknown): Uint8Array | null { if (typeof data === "string") { diff --git a/packages/server/src/shared/tool-call-display.ts b/packages/server/src/shared/tool-call-display.ts index a407d34b4..2cadd2d65 100644 --- a/packages/server/src/shared/tool-call-display.ts +++ b/packages/server/src/shared/tool-call-display.ts @@ -9,16 +9,16 @@ export type ToolCallDisplayInput = Pick< cwd?: string; }; -export type ToolCallDisplayModel = { +export interface ToolCallDisplayModel { displayName: string; summary?: string; errorText?: string; -}; +} -type DetailDisplay = { +interface DetailDisplay { displayName?: string; summary?: string; -}; +} function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); diff --git a/packages/server/src/terminal/terminal-output-coalescer.ts b/packages/server/src/terminal/terminal-output-coalescer.ts index 37bfc2531..f7ef2ed68 100644 --- a/packages/server/src/terminal/terminal-output-coalescer.ts +++ b/packages/server/src/terminal/terminal-output-coalescer.ts @@ -1,19 +1,19 @@ -export type TerminalOutputCoalescerTimers = { +export interface TerminalOutputCoalescerTimers { setTimeout: typeof setTimeout; clearTimeout: typeof clearTimeout; -}; +} -export type TerminalOutputCoalescerFlush = { +export interface TerminalOutputCoalescerFlush { payload: Buffer; chars: number; bytes: number; -}; +} -export type TerminalOutputCoalescerOptions = { +export interface TerminalOutputCoalescerOptions { timers: TerminalOutputCoalescerTimers; flushDelayMs?: number; onFlush: (payload: TerminalOutputCoalescerFlush) => void; -}; +} const DEFAULT_FLUSH_DELAY_MS = 5; diff --git a/packages/server/src/terminal/terminal.ts b/packages/server/src/terminal/terminal.ts index ee1833de6..7a7c83f7b 100644 --- a/packages/server/src/terminal/terminal.ts +++ b/packages/server/src/terminal/terminal.ts @@ -98,12 +98,12 @@ export interface CaptureTerminalLinesResult { totalLines: number; } -type EnsureNodePtySpawnHelperExecutableOptions = { +interface EnsureNodePtySpawnHelperExecutableOptions { packageRoot?: string; platform?: NodeJS.Platform; arch?: string; force?: boolean; -}; +} function resolveNodePtyPackageRoot(): string | null { try { diff --git a/packages/server/src/utils/checkout-git.ts b/packages/server/src/utils/checkout-git.ts index 519993539..faa3dc4ec 100644 --- a/packages/server/src/utils/checkout-git.ts +++ b/packages/server/src/utils/checkout-git.ts @@ -115,20 +115,20 @@ export function __setCheckoutShortstatCacheTtlForTests(ttlMs: number): void { shortstatInFlight.clear(); } -type CheckoutFileChange = { +interface CheckoutFileChange { path: string; oldPath?: string; status: string; isNew: boolean; isDeleted: boolean; isUntracked?: boolean; -}; +} -type CheckoutDiffRefs = { +interface CheckoutDiffRefs { baseRef: string; targetRef?: string; includeUntracked: boolean; -}; +} function getCheckoutDiffRefArgs(refs: CheckoutDiffRefs): string[] { return [refs.baseRef, ...(refs.targetRef ? [refs.targetRef] : [])]; @@ -640,7 +640,7 @@ export interface CheckoutStatus { isGit: false; } -export type CheckoutStatusGitNonPaseo = { +export interface CheckoutStatusGitNonPaseo { isGit: true; repoRoot: string; currentBranch: string | null; @@ -652,9 +652,9 @@ export type CheckoutStatusGitNonPaseo = { hasRemote: boolean; remoteUrl: string | null; isPaseoOwnedWorktree: false; -}; +} -export type CheckoutStatusGitPaseo = { +export interface CheckoutStatusGitPaseo { isGit: true; repoRoot: string; mainRepoRoot: string; @@ -667,7 +667,7 @@ export type CheckoutStatusGitPaseo = { hasRemote: boolean; remoteUrl: string | null; isPaseoOwnedWorktree: true; -}; +} export type CheckoutStatusGit = CheckoutStatusGitNonPaseo | CheckoutStatusGitPaseo; @@ -696,9 +696,9 @@ export interface MergeFromBaseOptions { requireCleanTarget?: boolean; } -export type CheckoutContext = { +export interface CheckoutContext { paseoHome?: string; -}; +} function isGitError(error: unknown): boolean { if (!(error instanceof Error)) { @@ -788,11 +788,11 @@ export async function getMainRepoRoot(cwd: string): Promise { return mainChild?.path ?? childrenOfBareRepo[0]?.path ?? nonBareNonPaseo[0]?.path ?? normalized; } -export type GitWorktreeEntry = { +export interface GitWorktreeEntry { path: string; branchRef?: string; isBare?: boolean; -}; +} /** Check whether a path contains a `.paseo/worktrees/` segment (both `/` and `\`). */ export function isPaseoWorktreePath(p: string): boolean { @@ -1218,12 +1218,12 @@ async function getBehindOfOrigin(cwd: string, currentBranch: string): Promise(); const workspaceEntryListCache = new Map(); @@ -112,14 +112,14 @@ export async function searchHomeDirectories( }); } -type RankedWorkspaceEntry = { +interface RankedWorkspaceEntry { relativePath: string; kind: WorkspaceSuggestionKind; matchTier: number; segmentIndex: number; matchOffset: number; depth: number; -}; +} export async function searchWorkspaceEntries( options: SearchWorkspaceEntriesOptions, diff --git a/packages/server/src/utils/promise-timeout.ts b/packages/server/src/utils/promise-timeout.ts index 1ae9c2b89..54829b38a 100644 --- a/packages/server/src/utils/promise-timeout.ts +++ b/packages/server/src/utils/promise-timeout.ts @@ -1,8 +1,8 @@ -type TimeoutOptions = { +interface TimeoutOptions { promise: Promise; timeoutMs: number; label: string; -}; +} export function withTimeout(promise: Promise, timeoutMs: number, message: string): Promise; export function withTimeout(options: TimeoutOptions): Promise; diff --git a/packages/server/src/utils/script-hostname.ts b/packages/server/src/utils/script-hostname.ts index 15a271b5a..f9d3d9fda 100644 --- a/packages/server/src/utils/script-hostname.ts +++ b/packages/server/src/utils/script-hostname.ts @@ -1,10 +1,10 @@ import { slugify } from "./worktree.js"; -type BuildScriptHostnameOptions = { +interface BuildScriptHostnameOptions { projectSlug: string; branchName: string | null; scriptName: string; -}; +} function toHostnameLabel(value: string): string { return slugify(value) || "untitled"; diff --git a/packages/server/src/utils/spawn.launch-regression.test.ts b/packages/server/src/utils/spawn.launch-regression.test.ts index 079cf78dc..fcf474962 100644 --- a/packages/server/src/utils/spawn.launch-regression.test.ts +++ b/packages/server/src/utils/spawn.launch-regression.test.ts @@ -7,13 +7,13 @@ import { afterEach, describe, expect, test } from "vitest"; import { findExecutable } from "./executable.js"; import { spawnProcess } from "./spawn.js"; -type SpawnResult = { +interface SpawnResult { code: number | null; signal: NodeJS.Signals | null; stdout: string; stderr: string; error: Error | null; -}; +} const tempDirs: string[] = []; const JSON_ARG = '{"key":"value with spaces","nested":{"quote":"\\"yes\\""}}'; diff --git a/packages/server/src/utils/worktree.ts b/packages/server/src/utils/worktree.ts index bdb3a0aba..87a223b6c 100644 --- a/packages/server/src/utils/worktree.ts +++ b/packages/server/src/utils/worktree.ts @@ -47,22 +47,22 @@ export interface WorktreeConfig { worktreePath: string; } -export type WorktreeRuntimeEnv = { +export interface WorktreeRuntimeEnv { PASEO_SOURCE_CHECKOUT_PATH: string; PASEO_ROOT_PATH: string; PASEO_WORKTREE_PATH: string; PASEO_BRANCH_NAME: string; PASEO_WORKTREE_PORT: string; -}; +} -export type WorktreeSetupCommandResult = { +export interface WorktreeSetupCommandResult { command: string; cwd: string; stdout: string; stderr: string; exitCode: number | null; durationMs: number; -}; +} export type WorktreeSetupCommandProgressEvent = | { @@ -145,12 +145,12 @@ export interface PaseoWorktreeInfo { head?: string; } -export type PaseoWorktreeOwnership = { +export interface PaseoWorktreeOwnership { allowed: boolean; repoRoot?: string; worktreeRoot?: string; worktreePath?: string; -}; +} export type WorktreeSource = | { kind: "branch-off"; baseBranch: string; newBranchName: string } diff --git a/packages/website/src/components/hero-mockup.tsx b/packages/website/src/components/hero-mockup.tsx index 9746143e2..09c1ac6c0 100644 --- a/packages/website/src/components/hero-mockup.tsx +++ b/packages/website/src/components/hero-mockup.tsx @@ -73,20 +73,20 @@ const CHAT: ChatItem[] = [ // ── Sidebar data ──────────────────────────────────────── -type SidebarWorkspace = { +interface SidebarWorkspace { name: string; kind: "checkout" | "worktree"; status: "running" | "done" | "idle" | "syncing"; selected?: boolean; diffStat?: { additions: number; deletions: number }; pr?: { number: number; state: "open" | "merged" | "closed" }; -}; +} -type SidebarProject = { +interface SidebarProject { initial: string; name: string; workspaces: SidebarWorkspace[]; -}; +} const SIDEBAR_PROJECTS: SidebarProject[] = [ { @@ -144,12 +144,12 @@ const SIDEBAR_PROJECTS: SidebarProject[] = [ // ── Tab data ───────────────────────────────────────────── -type TabDef = { +interface TabDef { name: string; provider: "claude" | "codex" | "terminal"; done: boolean; active?: boolean; -}; +} const TABS: TabDef[] = [ { name: "Orchestrator", provider: "claude", done: false, active: true }, @@ -160,12 +160,12 @@ const TABS: TabDef[] = [ // ── Diff data ────────────────────────────────────────── type DiffLineType = "add" | "remove" | "context" | "header"; -type DiffLine = { +interface DiffLine { type: DiffLineType; ln: string | null; content?: string; tokens?: Array<{ text: string; cls: string }>; -}; +} const DIFF_LINES: DiffLine[] = [ {