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
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ typecheck: node_modules/.installed src/version.ts ## Run TypeScript type checkin
"$(TSGO) --noEmit" \
"$(TSGO) --noEmit -p tsconfig.main.json"

check-deadcode: node_modules/.installed ## Check for potential dead code (manual only, not in static-check)
@echo "Checking for potential dead code with ts-prune..."
@echo "(Note: Some unused exports are legitimate - types, public APIs, entry points, etc.)"
@echo ""
@bun x ts-prune -i '(test|spec|mock|bench|debug|storybook)' \
| grep -v "used in module" \
| grep -v "src/App.tsx.*default" \
| grep -v "src/types/" \
| grep -v "telemetry/index.ts" \
|| echo "✓ No obvious dead code found"

## Testing
test-integration: node_modules/.installed ## Run all tests (unit + integration)
@bun test src
Expand Down
4 changes: 2 additions & 2 deletions scripts/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ ESLINT_PATTERN='src/**/*.{ts,tsx}'

if [ "$1" = "--fix" ]; then
echo "Running bun x eslint with --fix..."
bun x eslint --cache "$ESLINT_PATTERN" --fix
bun x eslint --cache --max-warnings 0 "$ESLINT_PATTERN" --fix
else
echo "Running eslint..."
bun x eslint --cache "$ESLINT_PATTERN"
bun x eslint --cache --max-warnings 0 "$ESLINT_PATTERN"
echo "ESLint checks passed!"
fi
23 changes: 13 additions & 10 deletions src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,21 +227,24 @@ export const ChatInput: React.FC<ChatInputProps> = ({
// Method to restore text to input (used by compaction cancel)
const restoreText = useCallback(
(text: string) => {
setInput(text);
setInput(() => text);
focusMessageInput();
},
[focusMessageInput]
[focusMessageInput, setInput]
);

// Method to append text to input (used by Code Review notes)
const appendText = useCallback((text: string) => {
setInput((prev) => {
// Add blank line before if there's existing content
const separator = prev.trim() ? "\n\n" : "";
return prev + separator + text;
});
// Don't focus - user wants to keep reviewing
}, []);
const appendText = useCallback(
(text: string) => {
setInput((prev) => {
// Add blank line before if there's existing content
const separator = prev.trim() ? "\n\n" : "";
return prev + separator + text;
});
// Don't focus - user wants to keep reviewing
},
[setInput]
);

// Provide API to parent via callback
useEffect(() => {
Expand Down
16 changes: 0 additions & 16 deletions src/components/Messages/MarkdownRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,3 @@ export const PlanMarkdownContainer = styled.div`
color: var(--color-plan-mode-hover);
}
`;

interface PlanMarkdownRendererProps {
content: string;
className?: string;
}

export const PlanMarkdownRenderer: React.FC<PlanMarkdownRendererProps> = ({
content,
className,
}) => {
return (
<PlanMarkdownContainer className={className}>
<MarkdownCore content={content} />
</PlanMarkdownContainer>
);
};
113 changes: 0 additions & 113 deletions src/components/Messages/TypewriterText.tsx

This file was deleted.

25 changes: 0 additions & 25 deletions src/components/RightSidebar/ToolsTab.tsx

This file was deleted.

93 changes: 0 additions & 93 deletions src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,99 +153,6 @@ export async function createWorktree(
}
}

export async function removeWorktree(
projectPath: string,
workspacePath: string,
options: { force: boolean } = { force: false }
): Promise<WorktreeResult> {
try {
// Remove the worktree (from the main repository context)
using proc = execAsync(
`git -C "${projectPath}" worktree remove "${workspacePath}" ${options.force ? "--force" : ""}`
);
await proc.result;
return { success: true };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return { success: false, error: message };
}
}

export async function pruneWorktrees(projectPath: string): Promise<WorktreeResult> {
try {
using proc = execAsync(`git -C "${projectPath}" worktree prune`);
await proc.result;
return { success: true };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return { success: false, error: message };
}
}

export async function moveWorktree(
projectPath: string,
oldPath: string,
newPath: string
): Promise<WorktreeResult> {
try {
// Check if new path already exists
if (fs.existsSync(newPath)) {
return {
success: false,
error: `Target path already exists: ${newPath}`,
};
}

// Create parent directory for new path if needed
const parentDir = path.dirname(newPath);
if (!fs.existsSync(parentDir)) {
fs.mkdirSync(parentDir, { recursive: true });
}

// Move the worktree using git (from the main repository context)
using proc = execAsync(`git -C "${projectPath}" worktree move "${oldPath}" "${newPath}"`);
await proc.result;
return { success: true, path: newPath };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return { success: false, error: message };
}
}

export async function listWorktrees(projectPath: string): Promise<string[]> {
try {
using proc = execAsync(`git -C "${projectPath}" worktree list --porcelain`);
const { stdout } = await proc.result;
const worktrees: string[] = [];
const lines = stdout.split("\n");

for (const line of lines) {
if (line.startsWith("worktree ")) {
const path = line.slice("worktree ".length);
if (path !== projectPath) {
// Exclude main worktree
worktrees.push(path);
}
}
}

return worktrees;
} catch (error) {
console.error("Error listing worktrees:", error);
return [];
}
}

export async function isGitRepository(projectPath: string): Promise<boolean> {
try {
using proc = execAsync(`git -C "${projectPath}" rev-parse --git-dir`);
await proc.result;
return true;
} catch {
return false;
}
}

/**
* Get the main repository path from a worktree path
* @param worktreePath Path to a git worktree
Expand Down
9 changes: 0 additions & 9 deletions src/services/tools/fileCommon.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as crypto from "crypto";
import type * as fs from "fs";
import * as path from "path";
import { createPatch } from "diff";
Expand All @@ -19,15 +18,7 @@ export const MAX_FILE_SIZE = 1024 * 1024; // 1MB
* Compute a 6-character hexadecimal lease from file content.
* The lease changes when file content is modified.
* Uses a deterministic hash so leases are consistent across processes.
*
* @param content - File content as string or Buffer
* @returns 6-character hexadecimal lease string
*/
export function leaseFromContent(content: string | Buffer): string {
// Use deterministic SHA-256 hash of content so leases are consistent
// across processes and restarts
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 6);
}

/**
* Generate a unified diff between old and new content using jsdiff.
Expand Down
3 changes: 2 additions & 1 deletion src/telemetry/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { VERSION } from "../version";
* Get base telemetry properties included with all events
*/
export function getBaseTelemetryProperties(): BaseTelemetryProperties {
const gitDescribe: string = VERSION.git_describe;
return {
version: VERSION.git_describe,
version: gitDescribe,
platform: window.api?.platform || "unknown",
electronVersion: window.api?.versions?.electron || "unknown",
};
Expand Down
16 changes: 0 additions & 16 deletions src/types/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,6 @@ export type SendMessageError =
| { type: "invalid_model_string"; message: string }
| { type: "unknown"; raw: string };

/**
* Type guard to check if error is an API key error
*/
export function isApiKeyError(
error: SendMessageError
): error is { type: "api_key_not_found"; provider: string } {
return error.type === "api_key_not_found";
}

/**
* Type guard to check if error is an unknown error
*/
export function isUnknownError(error: SendMessageError): error is { type: "unknown"; raw: string } {
return error.type === "unknown";
}

/**
* Stream error types - categorizes errors during AI streaming
* Used across backend (StreamManager) and frontend (StreamErrorMessage)
Expand Down
8 changes: 0 additions & 8 deletions src/types/toolParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,3 @@ export function isDynamicToolPart(part: unknown): part is DynamicToolPart {
typeof part === "object" && part !== null && "type" in part && part.type === "dynamic-tool"
);
}

export function isDynamicToolPartAvailable(part: unknown): part is DynamicToolPartAvailable {
return isDynamicToolPart(part) && part.state === "output-available";
}

export function isDynamicToolPartPending(part: unknown): part is DynamicToolPartPending {
return isDynamicToolPart(part) && part.state === "input-available";
}
Loading