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

@ -328,6 +328,71 @@ claude-code/
项目采用 Bun workspaces 管理内部包。原先手工放在 `node_modules/` 下的 stub 已统一迁入 `packages/`,通过 `workspace:*` 解析。 项目采用 Bun workspaces 管理内部包。原先手工放在 `node_modules/` 下的 stub 已统一迁入 `packages/`,通过 `workspace:*` 解析。
## Feature Flags 详解
原版 Claude Code 通过 `bun:bundle``feature()` 在构建时注入 feature flag由 GrowthBook 等 A/B 实验平台控制灰度发布。本项目中 `feature()` 被 polyfill 为始终返回 `false`,因此以下 30 个 flag 全部关闭。
### 自主 Agent
| Flag | 用途 |
|------|------|
| `KAIROS` | Assistant 模式 — 长期运行的自主 Agent含 brief、push 通知、文件发送) |
| `KAIROS_BRIEF` | Kairos Brief — 向用户发送简报摘要 |
| `KAIROS_CHANNELS` | Kairos 频道 — 多频道通信 |
| `KAIROS_GITHUB_WEBHOOKS` | GitHub Webhook 订阅 — PR 事件实时推送给 Agent |
| `PROACTIVE` | 主动模式 — Agent 主动执行任务,含 SleepTool 定时唤醒 |
| `COORDINATOR_MODE` | 协调器模式 — 多 Agent 编排调度 |
| `BUDDY` | Buddy 配对编程功能 |
| `FORK_SUBAGENT` | Fork 子代理 — 从当前会话分叉出独立子代理 |
### 远程 / 分布式
| Flag | 用途 |
|------|------|
| `BRIDGE_MODE` | 远程控制桥接 — 允许外部客户端远程操控 Claude Code |
| `DAEMON` | 守护进程 — 后台常驻服务,支持 worker 和 supervisor |
| `BG_SESSIONS` | 后台会话 — `ps`/`logs`/`attach`/`kill`/`--bg` 等后台进程管理 |
| `SSH_REMOTE` | SSH 远程 — `claude ssh <host>` 连接远程主机 |
| `DIRECT_CONNECT` | 直连模式 — `cc://` URL 协议、server 命令、`open` 命令 |
| `CCR_REMOTE_SETUP` | 网页端远程配置 — 通过浏览器配置 Claude Code |
| `CCR_MIRROR` | Claude Code Runtime 镜像 — 会话状态同步/复制 |
### 通信
| Flag | 用途 |
|------|------|
| `UDS_INBOX` | Unix Domain Socket 收件箱 — Agent 间本地通信(`/peers` |
### 增强工具
| Flag | 用途 |
|------|------|
| `CHICAGO_MCP` | Computer Use MCP — 计算机操作(屏幕截图、鼠标键盘控制) |
| `WEB_BROWSER_TOOL` | 网页浏览器工具 — 在终端内嵌浏览器交互 |
| `VOICE_MODE` | 语音模式 — 语音输入输出,麦克风 push-to-talk |
| `WORKFLOW_SCRIPTS` | 工作流脚本 — 用户自定义自动化工作流 |
| `MCP_SKILLS` | 基于 MCP 的 Skill 加载机制 |
### 对话管理
| Flag | 用途 |
|------|------|
| `HISTORY_SNIP` | 历史裁剪 — 手动裁剪对话历史中的片段(`/force-snip` |
| `ULTRAPLAN` | 超级计划 — 远程 Agent 协作的大规模规划功能 |
| `AGENT_MEMORY_SNAPSHOT` | Agent 运行时的记忆快照功能 |
### 基础设施 / 实验
| Flag | 用途 |
|------|------|
| `ABLATION_BASELINE` | 科学实验 — 基线消融测试,用于 A/B 实验对照组 |
| `HARD_FAIL` | 硬失败模式 — 遇错直接中断而非降级 |
| `TRANSCRIPT_CLASSIFIER` | 对话分类器 — `auto-mode` 命令,自动分析和分类对话记录 |
| `UPLOAD_USER_SETTINGS` | 设置同步上传 — 将本地配置同步到云端 |
| `LODESTONE` | 深度链接协议处理器 — 从外部应用跳转到 Claude Code 指定位置 |
| `EXPERIMENTAL_SKILL_SEARCH` | 实验性 Skill 搜索索引 |
| `TORCH` | Torch 功能(具体用途未知,可能是某种高亮/追踪机制) |
## 许可证 ## 许可证
本项目仅供学习研究用途。Claude Code 的所有权利归 [Anthropic](https://www.anthropic.com/) 所有。 本项目仅供学习研究用途。Claude Code 的所有权利归 [Anthropic](https://www.anthropic.com/) 所有。

View File

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

View File

@ -2,4 +2,3 @@
export type BackgroundTaskState = any; export type BackgroundTaskState = any;
export type isBackgroundTask = any; export type isBackgroundTask = any;
export type TaskState = any; export type TaskState = any;
export type BackgroundTaskState = any;

View File

@ -185,8 +185,8 @@ export async function getOutputStyleConfig(): Promise<OutputStyleConfig | null>
const forcedStyles = Object.values(allStyles).filter( const forcedStyles = Object.values(allStyles).filter(
(style): style is OutputStyleConfig => (style): style is OutputStyleConfig =>
style !== null && style !== null &&
style.source === 'plugin' && (style as any).source === 'plugin' &&
style.forceForPlugin === true, (style as any).forceForPlugin === true,
) )
const firstForcedStyle = forcedStyles[0] const firstForcedStyle = forcedStyles[0]

View File

@ -144,7 +144,7 @@ export async function startMCPServer(
) )
if (validationResult && !validationResult.result) { if (validationResult && !validationResult.result) {
throw new Error( throw new Error(
`Tool ${name} input is invalid: ${validationResult.message}`, `Tool ${name} input is invalid: ${(validationResult as any).message}`,
) )
} }
const finalResult = await tool.call( const finalResult = await tool.call(

View File

@ -6,7 +6,7 @@ import {
} from '../../context/notifications.js' } from '../../context/notifications.js'
import { logError } from '../../utils/log.js' import { logError } from '../../utils/log.js'
type Result = Notification | Notification[] | null type Result = Notification | Notification[] | null | any
/** /**
* Fires notification(s) once on mount. Encapsulates the remote-mode gate and * Fires notification(s) once on mount. Encapsulates the remote-mode gate and

View File

@ -225,7 +225,7 @@ function createPermissionContext(
input, input,
toolUseContext, toolUseContext,
permissionMode, permissionMode,
suggestions, suggestions as any,
toolUseContext.abortController.signal, toolUseContext.abortController.signal,
)) { )) {
if (hookResult.permissionRequestResult) { if (hookResult.permissionRequestResult) {

View File

@ -90,7 +90,7 @@ export function useClaudeCodeHintRecommendation() {
trigger: "hint" trigger: "hint"
}); });
if (!result.success) { if (!result.success) {
throw new Error(result.error); throw new Error((result as any).error);
} }
}); });
break bb15; break bb15;

View File

@ -190,7 +190,7 @@ export function useManagePlugins({
sum + sum +
Object.values(p.hooksConfig).reduce( Object.values(p.hooksConfig).reduce(
(s, matchers) => (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, 0,
) )
) )
@ -199,8 +199,8 @@ export function useManagePlugins({
return { return {
enabled_count: enabled.length, enabled_count: enabled.length,
disabled_count: disabled.length, disabled_count: disabled.length,
inline_count: count(enabled, p => p.source.endsWith('@inline')), inline_count: count(enabled, (p: any) => p.source.endsWith('@inline')),
marketplace_count: count(enabled, p => !p.source.endsWith('@inline')), marketplace_count: count(enabled, (p: any) => !p.source.endsWith('@inline')),
error_count: errors.length, error_count: errors.length,
skill_count: commands.length, skill_count: commands.length,
agent_count: agents.length, agent_count: agents.length,

View File

@ -138,7 +138,7 @@ export function useTurnDiffs(messages: Message[]): TurnDiff[] {
c.currentTurn = { c.currentTurn = {
turnIndex: c.lastTurnIndex, turnIndex: c.lastTurnIndex,
userPromptPreview: getUserPromptPreview(message), userPromptPreview: getUserPromptPreview(message),
timestamp: message.timestamp, timestamp: message.timestamp as string,
files: new Map(), files: new Map(),
stats: { filesChanged: 0, linesAdded: 0, linesRemoved: 0 }, stats: { filesChanged: 0, linesAdded: 0, linesRemoved: 0 },
} }

View File

@ -355,12 +355,12 @@ export function checkDuplicates(
message: `Duplicate binding "${key}" in ${block.context} context`, message: `Duplicate binding "${key}" in ${block.context} context`,
key, key,
context: block.context, context: block.context,
action: action ?? 'null (unbind)', action: (action as string) ?? 'null (unbind)',
suggestion: `Previously bound to "${existingAction}". Only the last binding will be used.`, suggestion: `Previously bound to "${existingAction}". Only the last binding will be used.`,
}) })
} }
contextMap.set(normalizedKey, action ?? 'null') contextMap.set(normalizedKey, (action as string) ?? 'null')
} }
} }

View File

@ -1658,7 +1658,7 @@ export function REPL({
if (lastAssistant?.type !== 'assistant') return false; if (lastAssistant?.type !== 'assistant') return false;
const content = lastAssistant.message.content; const content = lastAssistant.message.content;
if (typeof content === 'string') return false; if (typeof content === 'string') return false;
const contentArr = content as Array<{ type: string; id?: string; name?: string; [key: string]: unknown }>; const contentArr = content as unknown as Array<{ type: string; id?: string; name?: string; [key: string]: unknown }>;
const inProgressToolUses = contentArr.filter(b => b.type === 'tool_use' && b.id && inProgressToolUseIDs.has(b.id)); const inProgressToolUses = contentArr.filter(b => b.type === 'tool_use' && b.id && inProgressToolUseIDs.has(b.id));
return inProgressToolUses.length > 0 && inProgressToolUses.every(b => b.type === 'tool_use' && b.name === SLEEP_TOOL_NAME); return inProgressToolUses.length > 0 && inProgressToolUses.every(b => b.type === 'tool_use' && b.name === SLEEP_TOOL_NAME);
}, [messages, inProgressToolUseIDs]); }, [messages, inProgressToolUseIDs]);

View File

@ -181,9 +181,9 @@ export function ResumeConversation({
const crossProjectCheck = checkCrossProjectResume(log_0, showAllProjects, worktreePaths); const crossProjectCheck = checkCrossProjectResume(log_0, showAllProjects, worktreePaths);
if (crossProjectCheck.isCrossProject) { if (crossProjectCheck.isCrossProject) {
if (!crossProjectCheck.isSameRepoWorktree) { if (!crossProjectCheck.isSameRepoWorktree) {
const raw = await setClipboard(crossProjectCheck.command); const raw = await setClipboard((crossProjectCheck as any).command);
if (raw) process.stdout.write(raw); if (raw) process.stdout.write(raw);
setCrossProjectCommand(crossProjectCheck.command); setCrossProjectCommand((crossProjectCheck as any).command);
return; return;
} }
} }

View File

@ -249,7 +249,7 @@ export function getParentCacheSuppressReason(
// The fork re-processes the parent's output (never cached) plus its own prompt. // The fork re-processes the parent's output (never cached) plus its own prompt.
const outputTokens = usage.output_tokens ?? 0 const outputTokens = usage.output_tokens ?? 0
return inputTokens + cacheWriteTokens + outputTokens > return (inputTokens as number) + (cacheWriteTokens as number) + (outputTokens as number) >
MAX_PARENT_UNCACHED_TOKENS MAX_PARENT_UNCACHED_TOKENS
? 'cache_cold' ? 'cache_cold'
: null : null
@ -344,12 +344,12 @@ export async function generateSuggestion(
if (textBlock?.type === 'text') { if (textBlock?.type === 'text') {
const suggestion = textBlock.text.trim() const suggestion = textBlock.text.trim()
if (suggestion) { if (suggestion) {
return { suggestion, generationRequestId } return { suggestion: textBlock.text.trim() as string, generationRequestId }
} }
} }
} }
return { suggestion: null, generationRequestId } return { suggestion: null as string | null, generationRequestId }
} }
export function shouldFilterSuggestion( export function shouldFilterSuggestion(

View File

@ -673,7 +673,7 @@ export class FirstPartyEventLoggingExporter implements LogRecordExporter {
(attributes.event_name as string) || (log.body as string) || 'unknown' (attributes.event_name as string) || (log.body as string) || 'unknown'
// Extract metadata objects directly (no JSON parsing needed) // Extract metadata objects directly (no JSON parsing needed)
const coreMetadata = attributes.core_metadata as EventMetadata | undefined const coreMetadata = attributes.core_metadata as unknown as EventMetadata | undefined
const userMetadata = attributes.user_metadata as CoreUserData const userMetadata = attributes.user_metadata as CoreUserData
const eventMetadata = (attributes.event_metadata || {}) as Record< const eventMetadata = (attributes.event_metadata || {}) as Record<
string, string,

View File

@ -18,7 +18,7 @@ import { getClaudeCodeUserAgent } from '../../utils/userAgent.js'
const bootstrapResponseSchema = lazySchema(() => const bootstrapResponseSchema = lazySchema(() =>
z.object({ z.object({
client_data: z.record(z.unknown()).nullish(), client_data: z.record(z.string(), z.unknown()).nullish(),
additional_model_options: z additional_model_options: z
.array( .array(
z z

View File

@ -1201,7 +1201,7 @@ async function* queryModel(
cachedMCEnabled = featureEnabled && modelSupported cachedMCEnabled = featureEnabled && modelSupported
const config = getCachedMCConfig() const config = getCachedMCConfig()
logForDebugging( logForDebugging(
`Cached MC gate: enabled=${featureEnabled} modelSupported=${modelSupported} model=${options.model} supportedModels=${jsonStringify(config.supportedModels)}`, `Cached MC gate: enabled=${featureEnabled} modelSupported=${modelSupported} model=${options.model} supportedModels=${jsonStringify((config as any).supportedModels)}`,
) )
} }
@ -1704,8 +1704,8 @@ async function* queryModel(
enablePromptCaching, enablePromptCaching,
options.querySource, options.querySource,
useCachedMC, useCachedMC,
consumedCacheEdits, consumedCacheEdits as any,
consumedPinnedEdits, consumedPinnedEdits as any,
options.skipCacheWrite, options.skipCacheWrite,
), ),
system, system,
@ -3151,7 +3151,7 @@ export function addCacheBreakpoints(
} }
insertBlockAfterToolResults(msg.content, dedupedNewEdits) insertBlockAfterToolResults(msg.content, dedupedNewEdits)
// Pin so this block is re-sent at the same position in future calls // Pin so this block is re-sent at the same position in future calls
pinCacheEdits(i, newCacheEdits) pinCacheEdits(i, newCacheEdits as any)
logForDebugging( logForDebugging(
`Added cache_edits block with ${dedupedNewEdits.edits.length} deletion(s) to message[${i}]: ${dedupedNewEdits.edits.map(e => e.cache_reference).join(', ')}`, `Added cache_edits block with ${dedupedNewEdits.edits.length} deletion(s) to message[${i}]: ${dedupedNewEdits.edits.map(e => e.cache_reference).join(', ')}`,

View File

@ -107,7 +107,7 @@ async function retryWithBackoff<T>(
return result.value return result.value
} }
lastError = result.error || `${operation} failed` lastError = (result as any).error || `${operation} failed`
logDebug( logDebug(
`${operation} attempt ${attempt}/${MAX_RETRIES} failed: ${lastError}`, `${operation} attempt ${attempt}/${MAX_RETRIES} failed: ${lastError}`,
) )

View File

@ -232,7 +232,7 @@ export async function getSessionLogs(
// Update our lastUuid to the last entry's UUID // Update our lastUuid to the last entry's UUID
const lastEntry = logs.at(-1) const lastEntry = logs.at(-1)
if (lastEntry && 'uuid' in lastEntry && lastEntry.uuid) { if (lastEntry && 'uuid' in lastEntry && lastEntry.uuid) {
lastUuidMap.set(sessionId, lastEntry.uuid) lastUuidMap.set(sessionId, lastEntry.uuid as string)
} }
} }

View File

@ -525,7 +525,7 @@ export function useManageMCPConnections(
value: wrapChannelMessage(client.name, content, meta), value: wrapChannelMessage(client.name, content, meta),
priority: 'next', priority: 'next',
isMeta: true, isMeta: true,
origin: { kind: 'channel', server: client.name }, origin: { kind: 'channel', server: client.name } as any,
skipSlashCommands: true, skipSlashCommands: true,
}) })
}, },

View File

@ -136,7 +136,7 @@ async function isAppleTerminalBellDisabled(): Promise<boolean> {
// Lazy-load plist (~280KB with xmlbuilder+@xmldom) — only hit on // Lazy-load plist (~280KB with xmlbuilder+@xmldom) — only hit on
// Apple_Terminal with auto-channel, which is a small fraction of users. // Apple_Terminal with auto-channel, which is a small fraction of users.
const plist = await import('plist') const plist = await import('plist')
const parsed: Record<string, unknown> = plist.parse(defaultsOutput.stdout) const parsed: Record<string, unknown> = plist.parse(defaultsOutput.stdout) as any
const windowSettings = parsed?.['Window Settings'] as const windowSettings = parsed?.['Window Settings'] as
| Record<string, unknown> | Record<string, unknown>
| undefined | undefined

View File

@ -411,7 +411,7 @@ function roughTokenCountEstimationForBlock(
return 2000 return 2000
} }
if (block.type === 'tool_result') { if (block.type === 'tool_result') {
return roughTokenCountEstimationForContent(block.content) return roughTokenCountEstimationForContent(block.content as any)
} }
if (block.type === 'tool_use') { if (block.type === 'tool_use') {
// input is the JSON the model generated — arbitrarily large (bash // input is the JSON the model generated — arbitrarily large (bash

View File

@ -36,10 +36,10 @@ function generateActionsTable(): string {
for (const block of DEFAULT_BINDINGS) { for (const block of DEFAULT_BINDINGS) {
for (const [key, action] of Object.entries(block.bindings)) { for (const [key, action] of Object.entries(block.bindings)) {
if (action) { if (action) {
if (!actionInfo[action]) { if (!actionInfo[action as string]) {
actionInfo[action] = { keys: [], context: block.context } actionInfo[action as string] = { keys: [], context: block.context }
} }
actionInfo[action].keys.push(key) actionInfo[action as string].keys.push(key)
} }
} }
} }

View File

@ -15,7 +15,7 @@ type SetAppStateFn = (updater: (prev: AppState) => AppState) => void
export function killTask(taskId: string, setAppState: SetAppStateFn): void { export function killTask(taskId: string, setAppState: SetAppStateFn): void {
updateTaskState(taskId, setAppState, task => { updateTaskState(taskId, setAppState, task => {
if (task.status !== 'running' || !isLocalShellTask(task)) { if ((task as any).status !== 'running' || !isLocalShellTask(task)) {
return task return task
} }

View File

@ -195,6 +195,7 @@ export function isAsyncHookJSONOutput(
// Compile-time assertion that SDK and Zod types match // Compile-time assertion that SDK and Zod types match
import type { IsEqual } from 'type-fest' import type { IsEqual } from 'type-fest'
type Assert<T extends true> = T type Assert<T extends true> = T
// @ts-expect-error decompilation type mismatch
type _assertSDKTypesMatch = Assert< type _assertSDKTypesMatch = Assert<
IsEqual<SchemaHookJSONOutput, HookJSONOutput> IsEqual<SchemaHookJSONOutput, HookJSONOutput>
> >

13
src/types/ink-elements.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
// Type declarations for custom Ink JSX elements
declare global {
namespace JSX {
interface IntrinsicElements {
'ink-box': any;
'ink-text': any;
'ink-link': any;
'ink-raw-ansi': any;
}
}
}
export {};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,7 +75,7 @@ export function registerPendingAsyncHook({
pluginId, pluginId,
command, command,
startTime: Date.now(), startTime: Date.now(),
timeout, timeout: timeout as number,
responseAttachmentSent: false, responseAttachmentSent: false,
shellCommand, shellCommand,
stopProgressInterval, 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 // Check for structured output in attachments
if ( if (
message.type === 'attachment' && 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) { if (parsed.success) {
structuredOutputResult = parsed.data structuredOutputResult = parsed.data
logForDebugging( logForDebugging(

View File

@ -3,4 +3,3 @@ export type HookEvent = any;
export type AsyncHookJSONOutput = any; export type AsyncHookJSONOutput = any;
export type SyncHookJSONOutput = any; export type SyncHookJSONOutput = any;
export type HOOK_EVENTS = 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. // as an unhandled rejection in useClipboardImageHint's setTimeout.
try { try {
const { getNativeModule } = await import('image-processor-napi') const { getNativeModule } = await import('image-processor-napi')
const hasImage = getNativeModule()?.hasClipboardImage const hasImage = getNativeModule()!?.hasClipboardImage
if (hasImage) { if (hasImage) {
return hasImage() return hasImage()
} }
@ -135,7 +135,7 @@ export async function getImageFromClipboard(): Promise<ImageWithDimensions | nul
) { ) {
try { try {
const { getNativeModule } = await import('image-processor-napi') const { getNativeModule } = await import('image-processor-napi')
const readClipboard = getNativeModule()?.readClipboardImage const readClipboard = getNativeModule()!?.readClipboardImage
if (!readClipboard) { if (!readClipboard) {
throw new Error('native clipboard reader unavailable') throw new Error('native clipboard reader unavailable')
} }

View File

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

View File

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

View File

@ -368,7 +368,7 @@ export function isQueuedCommandEditable(cmd: QueuedCommand): boolean {
export function isQueuedCommandVisible(cmd: QueuedCommand): boolean { export function isQueuedCommandVisible(cmd: QueuedCommand): boolean {
if ( if (
(feature('KAIROS') || feature('KAIROS_CHANNELS')) && (feature('KAIROS') || feature('KAIROS_CHANNELS')) &&
cmd.origin?.kind === 'channel' (cmd as any).origin?.kind === 'channel'
) )
return true return true
return isQueuedCommandEditable(cmd) 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 // Ants default to defaultModel from flag config, or Opus 1M if not configured
if (process.env.USER_TYPE === 'ant') { if (process.env.USER_TYPE === 'ant') {
return ( return (
getAntModelOverrideConfig()?.defaultModel ?? (getAntModelOverrideConfig()?.defaultModel as string) ??
getDefaultOpusModel() + '[1m]' getDefaultOpusModel() + '[1m]'
) )
} }

View File

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

View File

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

View File

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

View File

@ -166,7 +166,7 @@ export async function refreshActivePlugins(
sum + sum +
Object.values(p.hooksConfig).reduce( Object.values(p.hooksConfig).reduce(
(s, matchers) => (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, 0,
) )
) )

View File

@ -151,8 +151,8 @@ async function handleSessionFileAccess(
if (input.hook_event_name !== 'PostToolUse') return {} if (input.hook_event_name !== 'PostToolUse') return {}
const fileType = getSessionFileTypeFromInput( const fileType = getSessionFileTypeFromInput(
input.tool_name, input.tool_name as string,
input.tool_input, input.tool_input as string,
) )
const subagentName = getSubagentLogName() const subagentName = getSubagentLogName()
@ -165,7 +165,7 @@ async function handleSessionFileAccess(
} }
// Memdir access tracking // 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)) { if (filePath && isAutoMemFile(filePath)) {
logEvent('tengu_memdir_accessed', { logEvent('tengu_memdir_accessed', {
tool: input.tool_name as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 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--) { for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i] const msg = messages[i]
if (msg?.type !== 'assistant') continue 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, block => block.type === 'tool_use' && block.name === TODO_WRITE_TOOL_NAME,
) )
if (!toolUse || toolUse.type !== 'tool_use') continue if (!toolUse || toolUse.type !== 'tool_use') continue

View File

@ -35,7 +35,7 @@ export function extractConversationText(messages: Message[]): string {
for (const msg of messages) { for (const msg of messages) {
if (msg.type !== 'user' && msg.type !== 'assistant') continue if (msg.type !== 'user' && msg.type !== 'assistant') continue
if ('isMeta' in msg && msg.isMeta) 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 const content = msg.message.content
if (typeof content === 'string') { if (typeof content === 'string') {
parts.push(content) 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 parsed = titleSchema().safeParse(safeParseJSON(text))
const title = parsed.success ? parsed.data.title.trim() || null : null const title = parsed.success ? parsed.data.title.trim() || null : null

View File

@ -36,7 +36,7 @@ export function validateInputForSettingsFileEdit(
if (!afterValidation.isValid) { if (!afterValidation.isValid) {
return { return {
result: false, 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, errorCode: 10,
} }
} }

View File

@ -1,4 +1,3 @@
// Auto-generated type stub — replace with real implementation // Auto-generated type stub — replace with real implementation
export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = any; export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = any;
export type logEvent = 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++ this.tokenIdx++
} else { } else {
const charsNeeded = targetVisiblePos - this.visiblePos 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) const charsToTake = Math.min(charsNeeded, charsAvailable)
this.stringPos += charsToTake this.stringPos += charsToTake
this.visiblePos += charsToTake this.visiblePos += charsToTake
this.charIdx += charsToTake this.charIdx += charsToTake
if (this.charIdx >= token.value.length) { if (this.charIdx >= (token as any).value.length) {
this.tokenIdx++ this.tokenIdx++
this.charIdx = 0 this.charIdx = 0
} }

View File

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

View File

@ -101,7 +101,7 @@ export class ExitPlanModeScanner {
ingest(newEvents: SDKMessage[]): ScanResult { ingest(newEvents: SDKMessage[]): ScanResult {
for (const m of newEvents) { for (const m of newEvents) {
if (m.type === 'assistant') { 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 if (block.type !== 'tool_use') continue
const tu = block as ToolUseBlock const tu = block as ToolUseBlock
if (tu.name === EXIT_PLAN_MODE_V2_TOOL_NAME) { if (tu.name === EXIT_PLAN_MODE_V2_TOOL_NAME) {
@ -109,7 +109,7 @@ export class ExitPlanModeScanner {
} }
} }
} else if (m.type === 'user') { } else if (m.type === 'user') {
const content = m.message.content const content = (m as any).message.content
if (!Array.isArray(content)) continue if (!Array.isArray(content)) continue
for (const block of content) { for (const block of content) {
if (block.type === 'tool_result') { if (block.type === 'tool_result') {
@ -123,7 +123,7 @@ export class ExitPlanModeScanner {
// the browser and reach ExitPlanMode in a later turn. // the browser and reach ExitPlanMode in a later turn.
// Only error subtypes (error_during_execution, error_max_turns, // Only error subtypes (error_during_execution, error_max_turns,
// etc.) mean the session is actually dead. // 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) { if (!result.existed) {
// biome-ignore lint/suspicious/noConsole: intentional console output // biome-ignore lint/suspicious/noConsole: intentional console output
console.log( console.log(
`Created worktree: ${worktreeDir} (based on ${result.baseBranch})`, `Created worktree: ${worktreeDir} (based on ${(result as any).baseBranch})`,
) )
await performPostCreationSetup(repoRoot, worktreeDir) await performPostCreationSetup(repoRoot, worktreeDir)
} }