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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": true,
"singleQuote": false,
"tabWidth": 2,
Expand Down
55 changes: 47 additions & 8 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import tseslint from "typescript-eslint";

export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
export default defineConfig([
{
ignores: [
"dist/",
Expand All @@ -21,6 +19,9 @@ export default tseslint.config(
"src/main.tsx",
],
},
js.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
files: ["src/**/*.{ts,tsx}"],
languageOptions: {
Expand Down Expand Up @@ -50,7 +51,7 @@ export default tseslint.config(
},
},
plugins: {
react: react,
react,
"react-hooks": reactHooks,
},
settings: {
Expand Down Expand Up @@ -87,6 +88,44 @@ export default tseslint.config(
},
],

// Enforce shorthand array notation, e.g. Foo[] instead of Array<Foo>
"@typescript-eslint/array-type": [
"error",
{
default: "array-simple",
readonly: "array-simple",
},
],

// Keep type-only imports explicit to avoid runtime inclusion
"@typescript-eslint/consistent-type-imports": [
"error",
{
prefer: "type-imports",
disallowTypeAnnotations: true,
},
],

// Require handling Promises instead of letting them float
"@typescript-eslint/no-floating-promises": [
"error",
{
ignoreVoid: true,
ignoreIIFE: true,
},
],

// Highlight unnecessary assertions to keep code idiomatic
"@typescript-eslint/no-unnecessary-type-assertion": "error",

// Encourage readonly where possible to surface unintended mutations
"@typescript-eslint/prefer-readonly": [
"error",
{
onlyInlineLambdas: true,
},
],

// Prevent using any type at all
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
Expand Down Expand Up @@ -145,5 +184,5 @@ export default tseslint.config(
afterAll: "readonly",
},
},
}
);
},
]);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"lint": "eslint 'src/**/*.{ts,tsx}' && bun run typecheck && bun run typecheck:main",
"lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix",
"fmt": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\" \"*.{json,md}\"",
"fmt:shell": "shfmt -i 2 -ci -bn -w scripts",
"fmt:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json}\" \"*.{json,md}\"",
"test": "jest",
"test:watch": "jest --watch",
Expand Down
20 changes: 10 additions & 10 deletions scripts/update_vercel_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ DOCS_DIR="$PROJECT_ROOT/docs/vercel"
TEMP_DIR="$(mktemp -d)"

cleanup() {
rm -rf "$TEMP_DIR"
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT

Expand All @@ -18,25 +18,25 @@ cd "$TEMP_DIR"
git init -q
git remote add origin https://github.com/vercel/ai.git
git config core.sparseCheckout true
echo "content/*" > .git/info/sparse-checkout
echo "content/*" >.git/info/sparse-checkout

git fetch --depth=1 origin main
git checkout main

if [ -d "$DOCS_DIR" ]; then
echo "Removing existing docs/vercel directory..."
rm -rf "$DOCS_DIR"
echo "Removing existing docs/vercel directory..."
rm -rf "$DOCS_DIR"
fi

mkdir -p "$DOCS_DIR"

if [ -d "content" ]; then
echo "Copying documentation to $DOCS_DIR..."
cp -r content/* "$DOCS_DIR/"
echo "Documentation updated successfully!"
echo "Copying documentation to $DOCS_DIR..."
cp -r content/* "$DOCS_DIR/"
echo "Documentation updated successfully!"
else
echo "Error: content directory not found in repository"
exit 1
echo "Error: content directory not found in repository"
exit 1
fi

echo "Vercel AI SDK documentation has been updated in $DOCS_DIR"
echo "Vercel AI SDK documentation has been updated in $DOCS_DIR"
3 changes: 2 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import styled from "@emotion/styled";
import { Global, css } from "@emotion/react";
import { GlobalColors } from "./styles/colors";
import { GlobalFonts } from "./styles/fonts";
import ProjectSidebar, { ProjectConfig, WorkspaceSelection } from "./components/ProjectSidebar";
import type { ProjectConfig, WorkspaceSelection } from "./components/ProjectSidebar";
import ProjectSidebar from "./components/ProjectSidebar";
import NewWorkspaceModal from "./components/NewWorkspaceModal";
import { AIView } from "./components/AIView";
import { ErrorBoundary } from "./components/ErrorBoundary";
Expand Down
4 changes: 2 additions & 2 deletions src/components/AIView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { InterruptedBarrier } from "./Messages/InterruptedBarrier";
import { ChatInput } from "./ChatInput";
import { ErrorMessage } from "./ErrorMessage";
import { ChatMetaSidebar } from "./ChatMetaSidebar";
import { DisplayedMessage, CmuxMessage } from "../types/message";
import type { DisplayedMessage, CmuxMessage } from "../types/message";
import { StreamingMessageAggregator } from "../utils/StreamingMessageAggregator";
import { shouldShowInterruptedBarrier } from "../utils/messageUtils";
import { DebugProvider, useDebugMode } from "../contexts/DebugContext";
import { ChatProvider } from "../contexts/ChatContext";
import { ThinkingProvider } from "../contexts/ThinkingContext";
import type { WorkspaceChatMessage } from "../types/ipc";
import {
WorkspaceChatMessage,
isCaughtUpMessage,
isStreamError,
isStreamStart,
Expand Down
8 changes: 5 additions & 3 deletions src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useState, useRef, useCallback, useEffect } from "react";
import styled from "@emotion/styled";
import { CommandSuggestions, COMMAND_SUGGESTION_KEYS } from "./CommandSuggestions";
import { ChatInputToast, Toast, SolutionLabel } from "./ChatInputToast";
import { parseCommand, ParsedCommand } from "../utils/commandParser";
import { SendMessageError as SendMessageErrorType } from "../types/errors";
import type { Toast } from "./ChatInputToast";
import { ChatInputToast, SolutionLabel } from "./ChatInputToast";
import type { ParsedCommand } from "../utils/commandParser";
import { parseCommand } from "../utils/commandParser";
import type { SendMessageError as SendMessageErrorType } from "../types/errors";
import { usePersistedState } from "../hooks/usePersistedState";
import { ThinkingSliderComponent } from "./ThinkingSlider";
import { useThinkingLevel } from "../hooks/useThinkingLevel";
Expand Down
3 changes: 2 additions & 1 deletion src/components/ChatInputToast.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useEffect, useCallback, ReactNode } from "react";
import type { ReactNode } from "react";
import React, { useEffect, useCallback } from "react";
import styled from "@emotion/styled";
import { keyframes, css } from "@emotion/react";

Expand Down
2 changes: 1 addition & 1 deletion src/components/ChatMetaSidebar/CostsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ const formatCostWithDollar = (cost: number): string => {

type ViewMode = "last-request" | "session";

const VIEW_MODE_OPTIONS: ToggleOption<ViewMode>[] = [
const VIEW_MODE_OPTIONS: Array<ToggleOption<ViewMode>> = [
{ value: "last-request", label: "Last Request" },
{ value: "session", label: "Session" },
];
Expand Down
3 changes: 2 additions & 1 deletion src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { Component, ReactNode } from "react";
import type { ReactNode } from "react";
import React, { Component } from "react";
import styled from "@emotion/styled";

const ErrorContainer = styled.div`
Expand Down
5 changes: 3 additions & 2 deletions src/components/Messages/AssistantMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from "react";
import styled from "@emotion/styled";
import { DisplayedMessage } from "../../types/message";
import type { DisplayedMessage } from "../../types/message";
import { MarkdownRenderer } from "./MarkdownRenderer";
import { TypewriterMarkdown } from "./TypewriterMarkdown";
import { MessageWindow, ButtonConfig } from "./MessageWindow";
import type { ButtonConfig } from "./MessageWindow";
import { MessageWindow } from "./MessageWindow";

const RawContent = styled.pre`
font-family: var(--font-monospace);
Expand Down
3 changes: 2 additions & 1 deletion src/components/Messages/MarkdownComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { ReactNode } from "react";
import type { ReactNode } from "react";
import React from "react";

interface CodeProps {
node?: unknown;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Messages/MessageRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { DisplayedMessage } from "../../types/message";
import type { DisplayedMessage } from "../../types/message";
import { UserMessage } from "./UserMessage";
import { AssistantMessage } from "./AssistantMessage";
import { ToolMessage } from "./ToolMessage";
Expand Down
5 changes: 3 additions & 2 deletions src/components/Messages/MessageWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, ReactNode } from "react";
import type { ReactNode } from "react";
import React, { useState } from "react";
import styled from "@emotion/styled";
import { CmuxMessage, DisplayedMessage } from "../../types/message";
import type { CmuxMessage, DisplayedMessage } from "../../types/message";

const MessageBlock = styled.div<{ borderColor: string; backgroundColor?: string }>`
margin-bottom: 15px;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Messages/ReasoningMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import styled from "@emotion/styled";
import { DisplayedMessage } from "../../types/message";
import type { DisplayedMessage } from "../../types/message";
import { MarkdownRenderer } from "./MarkdownRenderer";
import { TypewriterMarkdown } from "./TypewriterMarkdown";

Expand Down
2 changes: 1 addition & 1 deletion src/components/Messages/ToolMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { DisplayedMessage } from "../../types/message";
import type { DisplayedMessage } from "../../types/message";
import { GenericToolCall } from "../tools/GenericToolCall";
import { BashToolCall } from "../tools/BashToolCall";
import type { BashToolArgs, BashToolResult } from "../../types/tools";
Expand Down
5 changes: 3 additions & 2 deletions src/components/Messages/UserMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState } from "react";
import styled from "@emotion/styled";
import { DisplayedMessage } from "../../types/message";
import { MessageWindow, ButtonConfig } from "./MessageWindow";
import type { DisplayedMessage } from "../../types/message";
import type { ButtonConfig } from "./MessageWindow";
import { MessageWindow } from "./MessageWindow";
import { TerminalOutput } from "./TerminalOutput";

const FormattedContent = styled.pre`
Expand Down
2 changes: 1 addition & 1 deletion src/components/ProjectSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ const WorkspaceRemoveBtn = styled(RemoveBtn)`

export interface ProjectConfig {
path: string;
workspaces: { branch: string; path: string }[];
workspaces: Array<{ branch: string; path: string }>;
}

export interface WorkspaceSelection {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ThinkingSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import styled from "@emotion/styled";
import { ThinkingLevel } from "../types/thinking";
import type { ThinkingLevel } from "../types/thinking";
import { useThinkingLevel } from "../hooks/useThinkingLevel";

const ThinkingSliderContainer = styled.div`
Expand Down
2 changes: 1 addition & 1 deletion src/components/ToggleGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface ToggleOption<T extends string> {
}

interface ToggleGroupProps<T extends string> {
options: ToggleOption<T>[];
options: Array<ToggleOption<T>>;
value: T;
onChange: (value: T) => void;
}
Expand Down
6 changes: 3 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function load_config_or_default(): Config {
// Config is stored as array of [path, config] pairs
if (parsed.projects && Array.isArray(parsed.projects)) {
const projectsMap = new Map<string, ProjectConfig>(
parsed.projects as [string, ProjectConfig][]
parsed.projects as Array<[string, ProjectConfig]>
);
return {
projects: projectsMap,
Expand Down Expand Up @@ -130,15 +130,15 @@ export function getSessionDir(workspaceId: string): string {
* This centralizes the logic for workspace discovery and metadata loading
*/
export async function getAllWorkspaceMetadata(): Promise<
{ workspaceId: string; metadata: WorkspaceMetadata }[]
Array<{ workspaceId: string; metadata: WorkspaceMetadata }>
> {
try {
// Scan sessions directory for workspace directories
await fsPromises.access(SESSIONS_DIR);
const entries = await fsPromises.readdir(SESSIONS_DIR, { withFileTypes: true });
const workspaceIds = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);

const workspaceMetadata: { workspaceId: string; metadata: WorkspaceMetadata }[] = [];
const workspaceMetadata: Array<{ workspaceId: string; metadata: WorkspaceMetadata }> = [];

for (const workspaceId of workspaceIds) {
try {
Expand Down
7 changes: 4 additions & 3 deletions src/contexts/ChatContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from "react";
import { CmuxMessage, DisplayedMessage } from "../types/message";
import { ChatStats } from "../types/chatStats";
import type { ReactNode } from "react";
import React, { createContext, useContext, useState, useEffect } from "react";
import type { CmuxMessage, DisplayedMessage } from "../types/message";
import type { ChatStats } from "../types/chatStats";
import { calculateTokenStats } from "../utils/tokenStatsCalculator";

interface ChatContextType {
Expand Down
3 changes: 2 additions & 1 deletion src/contexts/DebugContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { createContext, useContext, useState, ReactNode } from "react";
import type { ReactNode } from "react";
import React, { createContext, useContext, useState } from "react";

interface DebugContextType {
debugMode: boolean;
Expand Down
5 changes: 3 additions & 2 deletions src/contexts/ThinkingContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { createContext, useContext, ReactNode } from "react";
import { ThinkingLevel } from "../types/thinking";
import type { ReactNode } from "react";
import React, { createContext, useContext } from "react";
import type { ThinkingLevel } from "../types/thinking";
import { usePersistedState } from "../hooks/usePersistedState";

interface ThinkingContextType {
Expand Down
2 changes: 1 addition & 1 deletion src/debug/costs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as fs from "fs";
import * as path from "path";
import { getSessionDir } from "../config";
import { CmuxMessage } from "../types/message";
import type { CmuxMessage } from "../types/message";
import { calculateTokenStats } from "../utils/tokenStatsCalculator";

/**
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/usePersistedState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useCallback, Dispatch, SetStateAction } from "react";
import type { Dispatch, SetStateAction } from "react";
import { useState, useCallback } from "react";

type SetValue<T> = T | ((prev: T) => T);

Expand Down
8 changes: 4 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { app, BrowserWindow, ipcMain, dialog, Menu, MenuItemConstructorOptions } from "electron";
import type { MenuItemConstructorOptions } from "electron";
import { app, BrowserWindow, ipcMain, dialog, Menu } from "electron";
import * as path from "path";
import type { Config, ProjectConfig } from "./config";
import {
load_config_or_default,
save_config,
Config,
ProjectConfig,
getAllWorkspaceMetadata,
loadProvidersConfig,
saveProvidersConfig,
Expand Down Expand Up @@ -67,7 +67,7 @@ ipcMain.handle(IPC_CHANNELS.CONFIG_LOAD, () => {

ipcMain.handle(
IPC_CHANNELS.CONFIG_SAVE,
(_event, configData: { projects: [string, ProjectConfig][] }) => {
(_event, configData: { projects: Array<[string, ProjectConfig]> }) => {
const config: Config = {
projects: new Map(configData.projects),
};
Expand Down
Loading