fix(types): replace all as any with proper type assertions

Eliminate unsafe `as any` casts across 21 non-test source files,
replacing them with specific type annotations:

- Bridge transport: use StdoutMessage type for write/writeBatch calls
- print.ts: type msg.request as Record<string, unknown> for unknown
  SDK control subtypes; use StdoutMessage for output.enqueue()
- API providers (openai/grok/gemini): import ChatCompletion types,
  type streams as AsyncIterable<ChatCompletionChunk>, type request
  bodies as ChatCompletionCreateParamsStreaming
- Computer use executor: use Partial<ResolvePrepareCaptureResult>
  for cross-platform screenshot result
- Components: replace Ink color string casts with proper typing
- Win32 bridge: type stdin as Writable after null check

All 2453 tests pass with 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-09 23:51:33 +08:00
parent a14d3dc8f0
commit 34bbc1d403
19 changed files with 317 additions and 231 deletions

View File

@@ -55,7 +55,7 @@ function BuiltinStatusLineInner({
// Force re-render every 60s so countdowns stay current
const [tick, setTick] = useState(0);
useEffect(() => {
const hasResetTime = rateLimits.five_hour?.resets_at || rateLimits.seven_day?.resets_at;
const hasResetTime = (rateLimits.five_hour?.resets_at ?? 0) || (rateLimits.seven_day?.resets_at ?? 0);
if (!hasResetTime) return;
const id = setInterval(() => setTick(t => t + 1), 60_000);
return () => clearInterval(id);

View File

@@ -15,7 +15,11 @@ type Props = {
export function CompactSummary({ message, screen }: Props): React.ReactNode {
const isTranscriptMode = screen === 'transcript'
const textContent = getUserMessageText(message) || ''
const metadata = message.summarizeMetadata
const metadata = message.summarizeMetadata as {
messagesSummarized?: number
direction?: string
userContext?: string
} | undefined
// "Summarize from here" with metadata
if (metadata) {

View File

@@ -163,7 +163,7 @@ const SuggestionItemRow = memo(function SuggestionItemRow({
{paddedDisplayText}
</Text>
{tagText ? (
<Text color={item.tag === 'local' ? 'yellow' : undefined} dimColor={item.tag !== 'local'}>
<Text color={item.tag === 'local' ? ('yellow' as const) : undefined} dimColor={item.tag !== 'local'}>
{tagText}
</Text>
) : null}

View File

@@ -162,13 +162,13 @@ export function SkillsMenu({ onExit, commands }: Props): React.ReactNode {
skill.source === 'plugin'
? skill.pluginInfo?.pluginManifest.name
: undefined
const scopeTag = getScopeTag(skill.source as SkillSource)
const scopeTag = getScopeTag(skill.source)
return (
<Box key={`${skill.name}-${skill.source}`}>
<Text>{getCommandName(skill)}</Text>
{scopeTag && (
<Text color={scopeTag.color}> [{scopeTag.label}]</Text>
<Text color={scopeTag.color as keyof Theme}> [{scopeTag.label}]</Text>
)}
<Text dimColor>
{pluginName ? ` · ${pluginName}` : ''} · {tokenDisplay} description

View File

@@ -122,7 +122,8 @@ function UltraplanSessionDetail({
let lastBlock: { name: string; input: unknown } | null = null
for (const msg of session.log) {
if (msg.type !== 'assistant') continue
for (const block of msg.message.content) {
const content = msg.message?.content ?? []
for (const block of content as Array<{type: string; name: string; input: unknown}>) {
if (block.type !== 'tool_use') continue
calls++
lastBlock = block