feat: 完成一大波类型修复, 虽然 any 很多

This commit is contained in:
claude-code-best
2026-03-31 23:43:39 +08:00
parent dd9cd782a7
commit 91f77ea571
55 changed files with 156 additions and 81 deletions

View File

@@ -18,14 +18,14 @@ export type CliHighlight = {
// faulted in.
let cliHighlightPromise: Promise<CliHighlight | null> | undefined
let loadedGetLanguage: typeof import('highlight.js').getLanguage | undefined
let loadedGetLanguage: any
async function loadCliHighlight(): Promise<CliHighlight | null> {
try {
const cliHighlight = await import('cli-highlight')
// cache hit — cli-highlight already loaded highlight.js
const highlightJs = await import('highlight.js')
loadedGetLanguage = highlightJs.getLanguage
loadedGetLanguage = (highlightJs as any).getLanguage
return {
highlight: cliHighlight.highlight,
supportsLanguage: cliHighlight.supportsLanguage,

View File

@@ -18,7 +18,7 @@ let pump: ReturnType<typeof setInterval> | undefined
let pending = 0
function drainTick(cu: ReturnType<typeof requireComputerUseSwift>): void {
cu._drainMainRunLoop()
;(cu as any)._drainMainRunLoop()
}
function retain(): void {

View File

@@ -25,7 +25,7 @@ let registered = false
export function registerEscHotkey(onEscape: () => void): boolean {
if (registered) return true
const cu = requireComputerUseSwift()
if (!cu.hotkey.registerEscape(onEscape)) {
if (!(cu as any).hotkey.registerEscape(onEscape)) {
// CGEvent.tapCreate failed — typically missing Accessibility permission.
// CU still works, just without ESC abort. Mirrors Cowork's escAbort.ts:81.
logForDebugging('[cu-esc] registerEscape returned false', { level: 'warn' })
@@ -40,7 +40,7 @@ export function registerEscHotkey(onEscape: () => void): boolean {
export function unregisterEscHotkey(): void {
if (!registered) return
try {
requireComputerUseSwift().hotkey.unregister()
(requireComputerUseSwift() as any).hotkey.unregister()
} finally {
releasePump()
registered = false
@@ -50,5 +50,5 @@ export function unregisterEscHotkey(): void {
export function notifyExpectedEscape(): void {
if (!registered) return
requireComputerUseSwift().hotkey.notifyExpectedEscape()
(requireComputerUseSwift() as any).hotkey.notifyExpectedEscape()
}

View File

@@ -46,8 +46,8 @@ export function getComputerUseHostAdapter(): ComputerUseHostAdapter {
}),
ensureOsPermissions: async () => {
const cu = requireComputerUseSwift()
const accessibility = cu.tcc.checkAccessibility()
const screenRecording = cu.tcc.checkScreenRecording()
const accessibility = (cu as any).tcc.checkAccessibility()
const screenRecording = (cu as any).tcc.checkScreenRecording()
return accessibility && screenRecording
? { granted: true }
: { granted: false, accessibility, screenRecording }

View File

@@ -93,11 +93,11 @@ export async function handleUrlSchemeLaunch(): Promise<number | null> {
try {
const { waitForUrlEvent } = await import('url-handler-napi')
const url = waitForUrlEvent(5000)
const url = (waitForUrlEvent as any)(5000)
if (!url) {
return null
}
return await handleDeepLinkUri(url)
return await handleDeepLinkUri(await url as string)
} catch {
// NAPI module not available, or handleDeepLinkUri rejected — not a URL launch
return null

View File

@@ -283,7 +283,7 @@ export function getDefaultEffortForModel(
const config = getAntModelOverrideConfig()
const isDefaultModel =
config?.defaultModel !== undefined &&
model.toLowerCase() === config.defaultModel.toLowerCase()
model.toLowerCase() === (config.defaultModel as string).toLowerCase()
if (isDefaultModel && config?.defaultModelEffortLevel) {
return config.defaultModelEffortLevel
}

View File

@@ -69,7 +69,7 @@ export function execSyncWithDefaults_DEPRECATED(
abortSignal?.throwIfAborted()
using _ = slowLogging`exec: ${command.slice(0, 200)}`
try {
const result = execaSync(command, {
const result = (execaSync as any)(command, {
env: process.env,
maxBuffer: 1_000_000,
timeout: finalTimeout,

View File

@@ -61,7 +61,7 @@ export async function* all<A>(
promises.add(next(generator))
// TODO: Clean this up
if (value !== undefined) {
yield value
yield value as Awaited<A>
}
} else if (waiting.length > 0) {
// Start a new generator when one finishes

View File

@@ -75,7 +75,7 @@ export function registerPendingAsyncHook({
pluginId,
command,
startTime: Date.now(),
timeout,
timeout: timeout as number,
responseAttachmentSent: false,
shellCommand,
stopProgressInterval,

View File

@@ -211,9 +211,9 @@ When done, return your result using the ${SYNTHETIC_OUTPUT_TOOL_NAME} tool with:
// Check for structured output in attachments
if (
message.type === 'attachment' &&
message.attachment.type === 'structured_output'
(message as any).attachment.type === 'structured_output'
) {
const parsed = hookResponseSchema().safeParse(message.attachment.data)
const parsed = hookResponseSchema().safeParse((message as any).attachment.data)
if (parsed.success) {
structuredOutputResult = parsed.data
logForDebugging(

View File

@@ -3,4 +3,3 @@ export type HookEvent = any;
export type AsyncHookJSONOutput = any;
export type SyncHookJSONOutput = any;
export type HOOK_EVENTS = any;
export type HookEvent = any;

View File

@@ -106,7 +106,7 @@ export async function hasImageInClipboard(): Promise<boolean> {
// as an unhandled rejection in useClipboardImageHint's setTimeout.
try {
const { getNativeModule } = await import('image-processor-napi')
const hasImage = getNativeModule()?.hasClipboardImage
const hasImage = getNativeModule()!?.hasClipboardImage
if (hasImage) {
return hasImage()
}
@@ -135,7 +135,7 @@ export async function getImageFromClipboard(): Promise<ImageWithDimensions | nul
) {
try {
const { getNativeModule } = await import('image-processor-napi')
const readClipboard = getNativeModule()?.readClipboardImage
const readClipboard = getNativeModule()!?.readClipboardImage
if (!readClipboard) {
throw new Error('native clipboard reader unavailable')
}

View File

@@ -231,14 +231,14 @@ export async function getErrorLogByIndex(
async function loadLogList(path: string): Promise<LogOption[]> {
let files: Awaited<ReturnType<typeof readdir>>
try {
files = await readdir(path, { withFileTypes: true })
files = await readdir(path, { withFileTypes: true }) as any
} catch {
logError(new Error(`No logs found at ${path}`))
return []
}
const logData = await Promise.all(
files.map(async (file, i) => {
const fullPath = join(path, file.name)
const fullPath = join(path, file.name as string)
const content = await readFile(fullPath, { encoding: 'utf8' })
const messages = jsonParse(content) as SerializedMessage[]
const firstMessage = messages[0]

View File

@@ -65,8 +65,8 @@ export function getMcpInstructionsDelta(
attachmentCount++
if (msg.attachment.type !== 'mcp_instructions_delta') continue
midCount++
for (const n of msg.attachment.addedNames) announced.add(n)
for (const n of msg.attachment.removedNames) announced.delete(n)
for (const n of (msg.attachment as any).addedNames) announced.add(n)
for (const n of (msg.attachment as any).removedNames) announced.delete(n)
}
const connected = mcpClients.filter(

View File

@@ -368,7 +368,7 @@ export function isQueuedCommandEditable(cmd: QueuedCommand): boolean {
export function isQueuedCommandVisible(cmd: QueuedCommand): boolean {
if (
(feature('KAIROS') || feature('KAIROS_CHANNELS')) &&
cmd.origin?.kind === 'channel'
(cmd as any).origin?.kind === 'channel'
)
return true
return isQueuedCommandEditable(cmd)

View File

@@ -179,7 +179,7 @@ export function getDefaultMainLoopModelSetting(): ModelName | ModelAlias {
// Ants default to defaultModel from flag config, or Opus 1M if not configured
if (process.env.USER_TYPE === 'ant') {
return (
getAntModelOverrideConfig()?.defaultModel ??
(getAntModelOverrideConfig()?.defaultModel as string) ??
getDefaultOpusModel() + '[1m]'
)
}

View File

@@ -367,14 +367,14 @@ export async function persistFileSnapshotIfRemote(): Promise<void> {
// Snapshot plan file
const plan = getPlan()
if (plan) {
snapshotFiles.push({
(snapshotFiles as any[]).push({
key: 'plan',
path: getPlanFilePath(),
content: plan,
})
}
if (snapshotFiles.length === 0) {
if ((snapshotFiles as any[]).length === 0) {
return
}

View File

@@ -188,7 +188,7 @@ export function getDeclaredMarketplaces(): Record<string, DeclaredMarketplace> {
...implicit,
...getAddDirExtraMarketplaces(),
...(getInitialSettings().extraKnownMarketplaces ?? {}),
}
} as any
}
/**

View File

@@ -1,7 +1,7 @@
import type {
McpbManifest,
McpbUserConfigurationOption,
McpbManifestAny as McpbManifest,
} from '@anthropic-ai/mcpb'
type McpbUserConfigurationOption = any
import axios from 'axios'
import { createHash } from 'crypto'
import { chmod, writeFile } from 'fs/promises'

View File

@@ -166,7 +166,7 @@ export async function refreshActivePlugins(
sum +
Object.values(p.hooksConfig).reduce(
(s, matchers) =>
s + (matchers?.reduce((h, m) => h + m.hooks.length, 0) ?? 0),
s + ((matchers as any)?.reduce((h: number, m: any) => h + m.hooks.length, 0) ?? 0),
0,
)
)

View File

@@ -151,8 +151,8 @@ async function handleSessionFileAccess(
if (input.hook_event_name !== 'PostToolUse') return {}
const fileType = getSessionFileTypeFromInput(
input.tool_name,
input.tool_input,
input.tool_name as string,
input.tool_input as string,
)
const subagentName = getSubagentLogName()
@@ -165,7 +165,7 @@ async function handleSessionFileAccess(
}
// Memdir access tracking
const filePath = getFilePathFromInput(input.tool_name, input.tool_input)
const filePath = getFilePathFromInput(input.tool_name as string, input.tool_input as string)
if (filePath && isAutoMemFile(filePath)) {
logEvent('tengu_memdir_accessed', {
tool: input.tool_name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,

View File

@@ -78,7 +78,7 @@ function extractTodosFromTranscript(messages: Message[]): TodoList {
for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i]
if (msg?.type !== 'assistant') continue
const toolUse = msg.message.content.find(
const toolUse = (msg.message.content as any[]).find(
block => block.type === 'tool_use' && block.name === TODO_WRITE_TOOL_NAME,
)
if (!toolUse || toolUse.type !== 'tool_use') continue

View File

@@ -35,7 +35,7 @@ export function extractConversationText(messages: Message[]): string {
for (const msg of messages) {
if (msg.type !== 'user' && msg.type !== 'assistant') continue
if ('isMeta' in msg && msg.isMeta) continue
if ('origin' in msg && msg.origin && msg.origin.kind !== 'human') continue
if ('origin' in msg && (msg as any).origin && (msg as any).origin.kind !== 'human') continue
const content = msg.message.content
if (typeof content === 'string') {
parts.push(content)
@@ -111,7 +111,7 @@ export async function generateSessionTitle(
},
})
const text = extractTextContent(result.message.content)
const text = extractTextContent(result.message.content as any)
const parsed = titleSchema().safeParse(safeParseJSON(text))
const title = parsed.success ? parsed.data.title.trim() || null : null

View File

@@ -36,7 +36,7 @@ export function validateInputForSettingsFileEdit(
if (!afterValidation.isValid) {
return {
result: false,
message: `Claude Code settings.json validation failed after edit:\n${afterValidation.error}\n\nFull schema:\n${afterValidation.fullSchema}\nIMPORTANT: Do not update the env unless explicitly instructed to do so.`,
message: `Claude Code settings.json validation failed after edit:\n${(afterValidation as any).error}\n\nFull schema:\n${(afterValidation as any).fullSchema}\nIMPORTANT: Do not update the env unless explicitly instructed to do so.`,
errorCode: 10,
}
}

View File

@@ -1,4 +1,3 @@
// Auto-generated type stub — replace with real implementation
export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = any;
export type logEvent = any;
export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = any;

View File

@@ -128,14 +128,14 @@ class HighlightSegmenter {
this.tokenIdx++
} else {
const charsNeeded = targetVisiblePos - this.visiblePos
const charsAvailable = token.value.length - this.charIdx
const charsAvailable = (token as any).value.length - this.charIdx
const charsToTake = Math.min(charsNeeded, charsAvailable)
this.stringPos += charsToTake
this.visiblePos += charsToTake
this.charIdx += charsToTake
if (this.charIdx >= token.value.length) {
if (this.charIdx >= (token as any).value.length) {
this.tokenIdx++
this.charIdx = 0
}

View File

@@ -97,7 +97,7 @@ function computeSearchText(msg: RenderableMessage): string {
raw =
typeof p === 'string'
? p
: p.flatMap(b => (b.type === 'text' ? [b.text] : [])).join('\n')
: (p as any[]).flatMap(b => (b.type === 'text' ? [b.text] : [])).join('\n')
}
break
}

View File

@@ -101,7 +101,7 @@ export class ExitPlanModeScanner {
ingest(newEvents: SDKMessage[]): ScanResult {
for (const m of newEvents) {
if (m.type === 'assistant') {
for (const block of m.message.content) {
for (const block of (m as any).message.content) {
if (block.type !== 'tool_use') continue
const tu = block as ToolUseBlock
if (tu.name === EXIT_PLAN_MODE_V2_TOOL_NAME) {
@@ -109,7 +109,7 @@ export class ExitPlanModeScanner {
}
}
} else if (m.type === 'user') {
const content = m.message.content
const content = (m as any).message.content
if (!Array.isArray(content)) continue
for (const block of content) {
if (block.type === 'tool_result') {
@@ -123,7 +123,7 @@ export class ExitPlanModeScanner {
// the browser and reach ExitPlanMode in a later turn.
// Only error subtypes (error_during_execution, error_max_turns,
// etc.) mean the session is actually dead.
this.terminated = { subtype: m.subtype }
this.terminated = { subtype: m.subtype as string }
}
}

View File

@@ -1293,7 +1293,7 @@ export async function execIntoTmuxWorktree(args: string[]): Promise<{
if (!result.existed) {
// biome-ignore lint/suspicious/noConsole: intentional console output
console.log(
`Created worktree: ${worktreeDir} (based on ${result.baseBranch})`,
`Created worktree: ${worktreeDir} (based on ${(result as any).baseBranch})`,
)
await performPostCreationSetup(repoRoot, worktreeDir)
}