From ac807aeb0871814dd0da4ec5a33840b111fe9c6c Mon Sep 17 00:00:00 2001 From: James Feng <47167674+GhostDragon124@users.noreply.github.com> Date: Sun, 7 Jun 2026 15:45:11 +0800 Subject: [PATCH] fix: remove runtime helper as-any casts --- src/buddy/companionReact.ts | 22 ++++++++--- src/constants/outputStyles.ts | 4 +- .../promptEngineeringAudit.runner.ts | 4 +- src/entrypoints/cli.tsx | 2 +- src/entrypoints/mcp.ts | 4 +- src/services/notifier.ts | 2 +- src/services/skillSearch/prefetch.ts | 4 +- src/services/skillSearch/signals.ts | 13 +++---- src/services/tokenEstimation.ts | 8 +++- src/services/vcr.ts | 27 ++++++++----- src/tasks/LocalShellTask/killShellTasks.ts | 2 +- src/types/global.d.ts | 39 ++++++++++++++++--- src/utils/auth.ts | 4 +- src/utils/swarm/inProcessRunner.ts | 13 ++++--- 14 files changed, 102 insertions(+), 46 deletions(-) diff --git a/src/buddy/companionReact.ts b/src/buddy/companionReact.ts index 021167e0d..7a66db7d5 100644 --- a/src/buddy/companionReact.ts +++ b/src/buddy/companionReact.ts @@ -10,7 +10,7 @@ import { getGlobalConfig } from '../utils/config.js' import { getClaudeAIOAuthTokens } from '../utils/auth.js' import { getOauthConfig } from '../constants/oauth.js' import { getUserAgent } from '../utils/http.js' -import type { Message } from '../types/message.js' +import type { ContentItem, Message } from '../types/message.js' // ─── Rate limiting ────────────────────────────────── @@ -64,6 +64,15 @@ export function triggerCompanionReaction( // ─── Helpers ──────────────────────────────────────── +function getMessageContent( + message: Message, +): string | ContentItem[] | undefined { + const content = message.message?.content + return typeof content === 'string' || Array.isArray(content) + ? content + : undefined +} + function isAddressed(messages: Message[], name: string): boolean { const pattern = new RegExp(`\\b${escapeRegex(name)}\\b`, 'i') for ( @@ -73,7 +82,7 @@ function isAddressed(messages: Message[], name: string): boolean { ) { const m = messages[i] if (m?.type !== 'user') continue - const content = (m as any).message?.content + const content = getMessageContent(m) if (typeof content === 'string' && pattern.test(content)) return true } return false @@ -89,14 +98,17 @@ function buildTranscript(messages: Message[]): string { .filter(m => m.type === 'user' || m.type === 'assistant') .map(m => { const role = m.type === 'user' ? 'user' : 'claude' - const content = (m as any).message?.content + const content = getMessageContent(m) const text = typeof content === 'string' ? content.slice(0, 300) : Array.isArray(content) ? content - .filter((b: any) => b?.type === 'text') - .map((b: any) => b.text) + .filter( + (b): b is Extract => + b.type === 'text', + ) + .map(b => b.text) .join(' ') .slice(0, 300) : '' diff --git a/src/constants/outputStyles.ts b/src/constants/outputStyles.ts index 01932903d..8776d0a06 100644 --- a/src/constants/outputStyles.ts +++ b/src/constants/outputStyles.ts @@ -185,8 +185,8 @@ export async function getOutputStyleConfig(): Promise const forcedStyles = Object.values(allStyles).filter( (style): style is OutputStyleConfig => style !== null && - (style as any).source === 'plugin' && - (style as any).forceForPlugin === true, + style.source === 'plugin' && + style.forceForPlugin === true, ) const firstForcedStyle = forcedStyles[0] diff --git a/src/constants/promptEngineeringAudit.runner.ts b/src/constants/promptEngineeringAudit.runner.ts index a501d39eb..45f17bfb0 100644 --- a/src/constants/promptEngineeringAudit.runner.ts +++ b/src/constants/promptEngineeringAudit.runner.ts @@ -12,7 +12,7 @@ import { describe, test, expect, mock, beforeEach } from 'bun:test' // --- MACRO 全局注入 (编译时 define 在测试中不可用) --- -;(globalThis as any).MACRO = { +globalThis.MACRO = { VERSION: '2.1.888', BUILD_TIME: '2026-04-22T00:00:00Z', FEEDBACK_CHANNEL: '', @@ -214,7 +214,7 @@ const standardTools: Tools = [ { name: 'Agent' }, { name: 'AskUserQuestion' }, { name: 'TaskCreate' }, -] as any +] as unknown as Tools async function getFullPrompt( tools: Tools = standardTools, diff --git a/src/entrypoints/cli.tsx b/src/entrypoints/cli.tsx index b0903920d..83f24c895 100644 --- a/src/entrypoints/cli.tsx +++ b/src/entrypoints/cli.tsx @@ -10,7 +10,7 @@ import { isEnvTruthy } from '../utils/envUtils.js'; // Runtime fallback for MACRO.* when not injected by build/dev defines. // This happens when running cli.tsx directly (not via `bun run dev` or built dist/). if (typeof globalThis.MACRO === 'undefined') { - (globalThis as any).MACRO = { + globalThis.MACRO = { VERSION: process.env.CLAUDE_CODE_VERSION || '2.1.888', BUILD_TIME: new Date().toISOString(), FEEDBACK_CHANNEL: '', diff --git a/src/entrypoints/mcp.ts b/src/entrypoints/mcp.ts index cbe36d5be..995d6a42d 100644 --- a/src/entrypoints/mcp.ts +++ b/src/entrypoints/mcp.ts @@ -142,9 +142,9 @@ export async function startMCPServer( (args as never) ?? {}, toolUseContext, ) - if (validationResult && !validationResult.result) { + if (validationResult?.result === false) { throw new Error( - `Tool ${name} input is invalid: ${(validationResult as any).message}`, + `Tool ${name} input is invalid: ${validationResult.message}`, ) } const finalResult = await tool.call( diff --git a/src/services/notifier.ts b/src/services/notifier.ts index 1eb8f99db..6fdde1d49 100644 --- a/src/services/notifier.ts +++ b/src/services/notifier.ts @@ -136,7 +136,7 @@ async function isAppleTerminalBellDisabled(): Promise { // Lazy-load plist (~280KB with xmlbuilder+@xmldom) — only hit on // Apple_Terminal with auto-channel, which is a small fraction of users. const plist = await import('plist') - const parsed: Record = plist.parse(defaultsOutput.stdout) as any + const parsed = plist.parse(defaultsOutput.stdout) as Record const windowSettings = parsed?.['Window Settings'] as | Record | undefined diff --git a/src/services/skillSearch/prefetch.ts b/src/services/skillSearch/prefetch.ts index ca4fb001b..769bb7a65 100644 --- a/src/services/skillSearch/prefetch.ts +++ b/src/services/skillSearch/prefetch.ts @@ -241,7 +241,7 @@ export async function startSkillDiscoveryPrefetch( durationMs: Date.now() - startedAt, indexSize: index.length, method: 'tfidf', - } as any + } logForDebugging( `[skill-search] prefetch found ${newResults.length} skills in ${signal.durationMs}ms`, @@ -306,7 +306,7 @@ export async function getTurnZeroSkillDiscovery( durationMs: Date.now() - startedAt, indexSize: index.length, method: 'tfidf', - } as any + } logForDebugging( `[skill-search] turn-zero found ${results.length} skills in ${signal.durationMs}ms`, diff --git a/src/services/skillSearch/signals.ts b/src/services/skillSearch/signals.ts index b2ca64afa..a1fff5c0c 100644 --- a/src/services/skillSearch/signals.ts +++ b/src/services/skillSearch/signals.ts @@ -1,9 +1,8 @@ -// STUB: 待补全 — 见 docs/devlog/02-tsc-stubs.md -// Skill search signal types — used by skill search prefetch and attachment utilities. -// DiscoverySignal represents the signal emitted when a skill is discovered during prefetch. - export type DiscoverySignal = { - type: 'skill_discovery' - skillId: string - [key: string]: unknown + trigger: 'assistant_turn' | 'user_input' + queryText: string + startedAt: number + durationMs: number + indexSize: number + method: 'tfidf' } diff --git a/src/services/tokenEstimation.ts b/src/services/tokenEstimation.ts index c761cdeac..afa8c4b46 100644 --- a/src/services/tokenEstimation.ts +++ b/src/services/tokenEstimation.ts @@ -479,7 +479,13 @@ function roughTokenCountEstimationForBlock( return 2000 } if (block.type === 'tool_result') { - return roughTokenCountEstimationForContent(block.content as any) + return roughTokenCountEstimationForContent( + block.content as + | string + | Array + | Array + | undefined, + ) } if (block.type === 'tool_use') { // input is the JSON the model generated — arbitrarily large (bash diff --git a/src/services/vcr.ts b/src/services/vcr.ts index 8ee060c1d..7708cd56b 100644 --- a/src/services/vcr.ts +++ b/src/services/vcr.ts @@ -1,4 +1,7 @@ -import type { BetaContentBlock, BetaUsage } from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs' +import type { + BetaContentBlock, + BetaUsage, +} from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs' import { createHash, randomUUID, type UUID } from 'crypto' import { mkdir, readFile, writeFile } from 'fs/promises' import isPlainObject from 'lodash-es/isPlainObject.js' @@ -9,6 +12,7 @@ import { calculateUSDCost } from 'src/utils/modelCost.js' import type { AssistantMessage, Message, + MessageContent, StreamEvent, SystemAPIErrorMessage, UserMessage, @@ -252,24 +256,27 @@ function mapAssistantMessage( message: { ...message.message, content: (message.message.content as BetaContentBlock[]) - .map(_ => { - switch (_.type) { + .map(block => { + switch (block.type) { case 'text': return { - ..._, - text: f(_.text) as string, - citations: _.citations || [], + ...block, + text: f(block.text) as string, + citations: block.citations || [], } // Ensure citations case 'tool_use': return { - ..._, - input: mapValuesDeep(_.input as Record, f), + ...block, + input: mapValuesDeep(block.input as Record, f), } default: - return _ // Handle other block types unchanged + return block // Handle other block types unchanged } }) - .filter(Boolean) as any, + .filter( + (block): block is NonNullable => + block !== null && block !== undefined, + ) as unknown as MessageContent, }, type: 'assistant', } diff --git a/src/tasks/LocalShellTask/killShellTasks.ts b/src/tasks/LocalShellTask/killShellTasks.ts index 121dbd9f4..aa36fd37e 100644 --- a/src/tasks/LocalShellTask/killShellTasks.ts +++ b/src/tasks/LocalShellTask/killShellTasks.ts @@ -15,7 +15,7 @@ type SetAppStateFn = (updater: (prev: AppState) => AppState) => void export function killTask(taskId: string, setAppState: SetAppStateFn): void { updateTaskState(taskId, setAppState, task => { - if ((task as any).status !== 'running' || !isLocalShellTask(task)) { + if (!isLocalShellTask(task) || task.status !== 'running') { return task } diff --git a/src/types/global.d.ts b/src/types/global.d.ts index c774e3862..e6e2bb480 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -16,12 +16,28 @@ declare namespace MACRO { export const VERSION_CHANGELOG: string } +interface GlobalThis { + MACRO: + | { + VERSION: string + BUILD_TIME: string + FEEDBACK_CHANNEL: string + ISSUES_EXPLAINER: string + NATIVE_PACKAGE_URL: string + PACKAGE_URL: string + VERSION_CHANGELOG: string + } + | undefined +} + // ============================================================================ // Internal Anthropic-only identifiers (dead-code eliminated in open-source) // These are referenced inside `MACRO(() => ...)` or `false && ...` blocks. // Model resolution (internal) -declare function resolveAntModel(model: string): import('../utils/model/antModels.js').AntModel | undefined +declare function resolveAntModel( + model: string, +): import('../utils/model/antModels.js').AntModel | undefined declare function getAntModels(): import('../utils/model/antModels.js').AntModel[] declare function getAntModelOverrideConfig(): { defaultSystemPromptSuffix?: string @@ -31,7 +47,13 @@ declare function getAntModelOverrideConfig(): { // Companion reactions handled by src/buddy/companionReact.ts (direct import) // Metrics (internal) -type ApiMetricEntry = { ttftMs: number; firstTokenTime: number; lastTokenTime: number; responseLengthBaseline: number; endResponseLength: number } +type ApiMetricEntry = { + ttftMs: number + firstTokenTime: number + lastTokenTime: number + responseLengthBaseline: number + endResponseLength: number +} declare const apiMetricsRef: React.RefObject | null declare function computeTtftText(metrics: ApiMetricEntry[]): string @@ -44,8 +66,12 @@ declare function ExperimentEnrollmentNotice(): JSX.Element | null declare const HOOK_TIMING_DISPLAY_THRESHOLD_MS: number // Ultraplan (internal) -declare function UltraplanChoiceDialog(props: Record): JSX.Element | null -declare function UltraplanLaunchDialog(props: Record): JSX.Element | null +declare function UltraplanChoiceDialog( + props: Record, +): JSX.Element | null +declare function UltraplanLaunchDialog( + props: Record, +): JSX.Element | null declare function launchUltraplan(...args: unknown[]): Promise // T — Generic type parameter leaked from React compiler output @@ -53,7 +79,10 @@ declare function launchUltraplan(...args: unknown[]): Promise declare type T = unknown // Tungsten (internal) -declare function TungstenPill(props?: { key?: string; selected?: boolean }): JSX.Element | null +declare function TungstenPill(props?: { + key?: string + selected?: boolean +}): JSX.Element | null // ============================================================================ // Build-time constants BUILD_TARGET/BUILD_ENV/INTERFACE_TYPE — removed (zero runtime usage) diff --git a/src/utils/auth.ts b/src/utils/auth.ts index 8012361f8..78838259d 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -117,8 +117,8 @@ export function isAnthropicAuthEnabled(): boolean { isEnvTruthy(process.env.CLAUDE_CODE_USE_BEDROCK) || isEnvTruthy(process.env.CLAUDE_CODE_USE_VERTEX) || isEnvTruthy(process.env.CLAUDE_CODE_USE_FOUNDRY) || - (settings as any).modelType === 'openai' || - (settings as any).modelType === 'gemini' || + settings.modelType === 'openai' || + settings.modelType === 'gemini' || !!process.env.OPENAI_BASE_URL || !!process.env.GEMINI_BASE_URL const apiKeyHelper = settings.apiKeyHelper diff --git a/src/utils/swarm/inProcessRunner.ts b/src/utils/swarm/inProcessRunner.ts index 1c4db3140..e2d296408 100644 --- a/src/utils/swarm/inProcessRunner.ts +++ b/src/utils/swarm/inProcessRunner.ts @@ -56,7 +56,7 @@ import { TASK_LIST_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/TaskL import { TASK_UPDATE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/TaskUpdateTool/constants.js' import { TEAM_CREATE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/TeamCreateTool/constants.js' import { TEAM_DELETE_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/TeamDeleteTool/constants.js' -import type { Message } from '../../types/message.js' +import type { ContentItem, Message } from '../../types/message.js' import type { PermissionDecision } from '../../types/permissions.js' import { createAssistantAPIErrorMessage, @@ -1449,13 +1449,16 @@ export async function runInProcessTeammate( for (let i = allMessages.length - 1; i >= 0; i--) { const m = allMessages[i]! if (m.type === 'assistant') { - const blocks = (m.message?.content ?? []) as any[] + const content = m.message?.content + const blocks: ContentItem[] = Array.isArray(content) ? content : [] for (const b of blocks) { - if (b?.type === 'tool_use') completionToolUseCount++ + if (b.type === 'tool_use') completionToolUseCount++ } - const textBlocks = blocks.filter((b: any) => b?.type === 'text') + const textBlocks = blocks.filter( + (b): b is Extract => b.type === 'text', + ) if (textBlocks.length > 0 && lastAssistantContent.length === 0) { - lastAssistantContent = textBlocks.map((b: any) => ({ + lastAssistantContent = textBlocks.map(b => ({ type: 'text' as const, text: b.text, }))