Batch A: Fix high-priority 'any' types in core files (vibe-kanban) (#1310)

* Perfect! All type checks pass. Here's a summary of the completed fixes:

##  Batch A Complete: Fixed all 'any' types in 7 core files

### Summary of Changes

**1. useLogStream.ts** - Typed WebSocket patches
- `patches.forEach((patch: any)` → `const patches = data.JsonPatch as Array<{ value?: PatchType }>`

**2. api.ts** - Typed request body
- `const requestBody: any = {}` → `const requestBody: { editor_type?: EditorType } = {}`

**3. NextActionCard.tsx** - Used proper domain type
- `task?: any` → `task?: TaskWithAttemptStatus`

**4. PendingApprovalEntry.tsx** - Safe error handling
- `catch (e: any)` → `catch (e: unknown)` with proper narrowing

**5. useProfiles.ts** - Typed JSON values
- `parsedProfiles: any | null` → `parsedProfiles: JsonValue | null`
- `queryClient.setQueryData(['profiles'], (old: any)` → typed with `<{ content: string; path: string }>`

**6. useProcessRetry.ts** - Typed executor actions
- `const typ: any = details?.executor_action?.typ as any` → `const typ: ExecutorActionType | undefined`
- Removed unnecessary `as any` cast on version field

**7. DisplayConversationEntry.tsx** - Created ActionLike helper type
- Removed local `type JsonValue = any`
- Imported `JsonValue` and `TaskWithAttemptStatus` from shared/types
- Created minimal `ActionLike` type for ToolCallCard compatibility
- Typed all component props and variables properly

All changes passed frontend and backend type checks ✓

* Cleanup script changes for task attempt 1b9207c2-6291-4bea-b06d-b4702f99f9ee

* Perfect! Updated the `ActionLike` type to use `CommandRunResult` from shared types, which is cleaner and more aligned with the domain model. All type checks pass ✓

* Excellent! All checks pass. Let me create a summary of what we accomplished:

##  Refactor Complete: Simplified ToolCallCard by Passing Full Entry

### Summary of Changes

**Removed the ActionLike workaround** and made the code significantly simpler and more readable:

### Before (Complex with ActionLike bridge):
```typescript
// Helper type to bridge ExecutorAction and ActionType
type ActionLike = Partial<{
  action: string;
  arguments: JsonValue;
  result: CommandRunResult;
  tool_name: string;
  message: string;
  summary: string;
}>;

// Multiple props with conversions at call sites
<ToolCallCard
  entryType={toolEntry}
  entryContent={entry.content}
  defaultExpanded={defaultExpanded}
  statusAppearance={statusAppearance}
  forceExpanded={isPendingApproval}
  linkifyUrls={isGithubCliSetup}
/>
```

### After (Simple with unified entry):
```typescript
// Just pass the entry - ToolCallCard handles everything
<ToolCallCard
  entry={entry}
  expansionKey={expansionKey}
  forceExpanded={isPendingApproval}
/>
```

### Key Improvements

1. **Simpler Props**: Changed from 8+ props to just 3 (`entry`, `expansionKey`, `forceExpanded`)
2. **Removed ActionLike**: Eliminated the bridge type that was papering over type differences
3. **Centralized Logic**: All normalization logic now lives inside ToolCallCard where it belongs
4. **Type Safety**: Uses proper type narrowing (`'entry_type' in entry`) instead of type casts
5. **Better Readability**: Call sites are now trivial - just pass the entry

### Files Changed
- `DisplayConversationEntry.tsx`:
  - Removed ActionLike helper type
  - Updated ToolCallCard component to accept unified entry prop
  - Simplified both call sites (ProcessStartPayload and NormalizedEntry)
  - Moved linkifyUrls, defaultExpanded logic into ToolCallCard

All type checks pass ✓

* Cleanup script changes for task attempt 1b9207c2-6291-4bea-b06d-b4702f99f9ee
This commit is contained in:
Louis Knight-Webb
2025-11-17 22:19:44 +00:00
committed by GitHub
parent 5e7742da2a
commit 870a166c38
7 changed files with 71 additions and 73 deletions

View File

@@ -52,8 +52,8 @@ export const useLogStream = (processId: string): UseLogStreamResult => {
// Handle different message types based on LogMsg enum
if ('JsonPatch' in data) {
const patches = data.JsonPatch;
patches.forEach((patch: any) => {
const patches = data.JsonPatch as Array<{ value?: PatchType }>;
patches.forEach((patch) => {
const value = patch?.value;
if (!value || !value.type) return;

View File

@@ -3,7 +3,11 @@ import { useCallback, useState } from 'react';
import { useAttemptExecution } from '@/hooks/useAttemptExecution';
import { useBranchStatus } from '@/hooks/useBranchStatus';
import { attemptsApi, executionProcessesApi } from '@/lib/api';
import type { ExecutionProcess, TaskAttempt } from 'shared/types';
import type {
ExecutionProcess,
TaskAttempt,
ExecutorActionType,
} from 'shared/types';
/**
* Reusable hook to retry a process given its executionProcessId and a new prompt.
@@ -64,13 +68,14 @@ export function useProcessRetry(attempt: TaskAttempt | undefined) {
try {
const details =
await executionProcessesApi.getDetails(executionProcessId);
const typ: any = details?.executor_action?.typ as any;
const typ: ExecutorActionType | undefined =
details?.executor_action?.typ;
if (
typ &&
(typ.type === 'CodingAgentInitialRequest' ||
typ.type === 'CodingAgentFollowUpRequest')
) {
variant = (typ.executor_profile_id?.variant as string | null) ?? null;
variant = typ.executor_profile_id?.variant ?? null;
}
} catch {
/* ignore */
@@ -83,7 +88,7 @@ export function useProcessRetry(attempt: TaskAttempt | undefined) {
prompt: newPrompt,
variant,
image_ids: [],
version: null as any,
version: null,
});
} finally {
setBusy(false);

View File

@@ -1,11 +1,12 @@
import { useMemo } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { profilesApi } from '@/lib/api';
import type { JsonValue } from 'shared/types';
export type UseProfilesReturn = {
// data
profilesContent: string;
parsedProfiles: any | null;
parsedProfiles: JsonValue | null;
profilesPath: string;
// status
@@ -33,8 +34,9 @@ export function useProfiles(): UseProfilesReturn {
mutationFn: (content: string) => profilesApi.save(content),
onSuccess: (_, content) => {
// Optimistically update cache with new content
queryClient.setQueryData(['profiles'], (old: any) =>
old ? { ...old, content } : old
queryClient.setQueryData<{ content: string; path: string }>(
['profiles'],
(old) => (old ? { ...old, content } : old)
);
},
});