fix(tsc): Phase 3a — fix 34 type errors in AgentTool/UI.tsx (175→141)
- Add local type assertions (AgentProgressMessage, AgentToolProgressData) - No as any used — all specific type narrowing - AgentTool tests: 40 pass, 0 fail
This commit is contained in:
parent
a648196c3c
commit
2c0a35d04b
|
|
@ -22,7 +22,7 @@ import { ToolUseLoader } from 'src/components/ToolUseLoader.js'
|
||||||
import { Box, Text } from '@anthropic/ink'
|
import { Box, Text } from '@anthropic/ink'
|
||||||
import { getDumpPromptsPath } from 'src/services/api/dumpPrompts.js'
|
import { getDumpPromptsPath } from 'src/services/api/dumpPrompts.js'
|
||||||
import { findToolByName, type Tools } from 'src/Tool.js'
|
import { findToolByName, type Tools } from 'src/Tool.js'
|
||||||
import type { Message, ProgressMessage } from 'src/types/message.js'
|
import type { AssistantMessage, Message, ProgressMessage, UserMessage } from 'src/types/message.js'
|
||||||
import type { AgentToolProgress } from 'src/types/tools.js'
|
import type { AgentToolProgress } from 'src/types/tools.js'
|
||||||
import { count } from 'src/utils/array.js'
|
import { count } from 'src/utils/array.js'
|
||||||
import {
|
import {
|
||||||
|
|
@ -68,6 +68,29 @@ function hasProgressMessage(data: Progress): data is AgentToolProgress {
|
||||||
return msg != null && typeof msg === 'object' && 'type' in msg
|
return msg != null && typeof msg === 'object' && 'type' in msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local type describing the actual runtime shape of a progress message's `message`
|
||||||
|
* field. AgentToolProgress is `Record<string, unknown>` so we need concrete types
|
||||||
|
* for property access without resorting to `as any`.
|
||||||
|
*/
|
||||||
|
type AgentProgressMessage = {
|
||||||
|
type: 'assistant' | 'user'
|
||||||
|
message: {
|
||||||
|
content: BetaContentBlock[]
|
||||||
|
usage?: BetaUsage
|
||||||
|
}
|
||||||
|
toolUseResult?: ToolResultBlockParam
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local type for AgentToolProgress data when it contains a progress message.
|
||||||
|
*/
|
||||||
|
type AgentToolProgressData = {
|
||||||
|
message: AgentProgressMessage
|
||||||
|
prompt?: string
|
||||||
|
agentId?: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a progress message is a search/read/REPL operation (tool use or result).
|
* Check if a progress message is a search/read/REPL operation (tool use or result).
|
||||||
* Returns { isSearch, isRead, isREPL } if it's a collapsible operation, null otherwise.
|
* Returns { isSearch, isRead, isREPL } if it's a collapsible operation, null otherwise.
|
||||||
|
|
@ -83,7 +106,7 @@ function getSearchOrReadInfo(
|
||||||
if (!hasProgressMessage(progressMessage.data)) {
|
if (!hasProgressMessage(progressMessage.data)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const message = progressMessage.data.message
|
const message = progressMessage.data.message as AgentProgressMessage
|
||||||
|
|
||||||
// Check tool_use (assistant message)
|
// Check tool_use (assistant message)
|
||||||
if (message.type === 'assistant') {
|
if (message.type === 'assistant') {
|
||||||
|
|
@ -132,7 +155,7 @@ function processProgressMessages(
|
||||||
return messages
|
return messages
|
||||||
.filter(
|
.filter(
|
||||||
(m): m is ProgressMessage<AgentToolProgress> =>
|
(m): m is ProgressMessage<AgentToolProgress> =>
|
||||||
hasProgressMessage(m.data) && m.data.message.type !== 'user',
|
hasProgressMessage(m.data) && (m.data as AgentToolProgressData).message.type !== 'user',
|
||||||
)
|
)
|
||||||
.map(m => ({ type: 'original', message: m }))
|
.map(m => ({ type: 'original', message: m }))
|
||||||
}
|
}
|
||||||
|
|
@ -172,8 +195,8 @@ function processProgressMessages(
|
||||||
const toolUseByID = new Map<string, ToolUseBlockParam>()
|
const toolUseByID = new Map<string, ToolUseBlockParam>()
|
||||||
for (const msg of agentMessages) {
|
for (const msg of agentMessages) {
|
||||||
// Track tool_use blocks as we see them
|
// Track tool_use blocks as we see them
|
||||||
if (msg.data.message.type === 'assistant') {
|
if ((msg.data as AgentToolProgressData).message.type === 'assistant') {
|
||||||
for (const c of msg.data.message.message.content) {
|
for (const c of (msg.data as AgentToolProgressData).message.message.content) {
|
||||||
if (c.type === 'tool_use') {
|
if (c.type === 'tool_use') {
|
||||||
toolUseByID.set(c.id, c as ToolUseBlockParam)
|
toolUseByID.set(c.id, c as ToolUseBlockParam)
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +215,7 @@ function processProgressMessages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only count tool_result messages (not tool_use) to avoid double counting
|
// Only count tool_result messages (not tool_use) to avoid double counting
|
||||||
if (msg.data.message.type === 'user') {
|
if ((msg.data as AgentToolProgressData).message.type === 'user') {
|
||||||
if (info.isSearch) {
|
if (info.isSearch) {
|
||||||
currentGroup.searchCount++
|
currentGroup.searchCount++
|
||||||
} else if (info.isREPL) {
|
} else if (info.isREPL) {
|
||||||
|
|
@ -207,7 +230,7 @@ function processProgressMessages(
|
||||||
// Skip user tool_result messages — subagent progress messages lack
|
// Skip user tool_result messages — subagent progress messages lack
|
||||||
// toolUseResult, so UserToolSuccessMessage returns null and the
|
// toolUseResult, so UserToolSuccessMessage returns null and the
|
||||||
// height=1 Box in renderToolUseProgressMessage shows as a blank line.
|
// height=1 Box in renderToolUseProgressMessage shows as a blank line.
|
||||||
if (msg.data.message.type !== 'user') {
|
if ((msg.data as AgentToolProgressData).message.type !== 'user') {
|
||||||
result.push({ type: 'original', message: msg })
|
result.push({ type: 'original', message: msg })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +303,7 @@ function VerboseAgentTranscript({
|
||||||
.filter((pm): pm is ProgressMessage<AgentToolProgress> =>
|
.filter((pm): pm is ProgressMessage<AgentToolProgress> =>
|
||||||
hasProgressMessage(pm.data),
|
hasProgressMessage(pm.data),
|
||||||
)
|
)
|
||||||
.map(pm => pm.data),
|
.map(pm => pm.data as unknown as { message: AssistantMessage | UserMessage }),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filter out user tool_result messages that lack toolUseResult.
|
// Filter out user tool_result messages that lack toolUseResult.
|
||||||
|
|
@ -292,7 +315,7 @@ function VerboseAgentTranscript({
|
||||||
if (!hasProgressMessage(pm.data)) {
|
if (!hasProgressMessage(pm.data)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const msg = pm.data.message
|
const msg = pm.data.message as AgentProgressMessage
|
||||||
if (msg.type === 'user' && msg.toolUseResult === undefined) {
|
if (msg.type === 'user' && msg.toolUseResult === undefined) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +328,7 @@ function VerboseAgentTranscript({
|
||||||
{filteredMessages.map(progressMessage => (
|
{filteredMessages.map(progressMessage => (
|
||||||
<MessageResponse key={progressMessage.uuid} height={1}>
|
<MessageResponse key={progressMessage.uuid} height={1}>
|
||||||
<MessageComponent
|
<MessageComponent
|
||||||
message={progressMessage.data.message}
|
message={progressMessage.data.message as unknown as AssistantMessage | UserMessage}
|
||||||
lookups={agentLookups}
|
lookups={agentLookups}
|
||||||
addMargin={false}
|
addMargin={false}
|
||||||
tools={tools}
|
tools={tools}
|
||||||
|
|
@ -555,7 +578,7 @@ export function renderToolUseProgressMessage(
|
||||||
if (!hasProgressMessage(msg.data)) {
|
if (!hasProgressMessage(msg.data)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const message = msg.data.message
|
const message = msg.data.message as AgentProgressMessage
|
||||||
return message.message.content.some(
|
return message.message.content.some(
|
||||||
(content: BetaContentBlock) => content.type === 'tool_use',
|
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||||
)
|
)
|
||||||
|
|
@ -563,12 +586,12 @@ export function renderToolUseProgressMessage(
|
||||||
|
|
||||||
const latestAssistant = progressMessages.findLast(
|
const latestAssistant = progressMessages.findLast(
|
||||||
(msg): msg is ProgressMessage<AgentToolProgress> =>
|
(msg): msg is ProgressMessage<AgentToolProgress> =>
|
||||||
hasProgressMessage(msg.data) && msg.data.message.type === 'assistant',
|
hasProgressMessage(msg.data) && (msg.data as AgentToolProgressData).message.type === 'assistant',
|
||||||
)
|
)
|
||||||
|
|
||||||
let tokens = null
|
let tokens = null
|
||||||
if (latestAssistant?.data.message.type === 'assistant') {
|
if ((latestAssistant?.data as AgentToolProgressData)?.message.type === 'assistant') {
|
||||||
const usage = latestAssistant.data.message.message.usage
|
const usage = (latestAssistant.data.message as AgentProgressMessage).message.usage
|
||||||
tokens =
|
tokens =
|
||||||
(usage.cache_creation_input_tokens ?? 0) +
|
(usage.cache_creation_input_tokens ?? 0) +
|
||||||
(usage.cache_read_input_tokens ?? 0) +
|
(usage.cache_read_input_tokens ?? 0) +
|
||||||
|
|
@ -631,14 +654,14 @@ export function renderToolUseProgressMessage(
|
||||||
if (!hasProgressMessage(data)) {
|
if (!hasProgressMessage(data)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return data.message.message.content.some(
|
return (data as AgentToolProgressData).message.message.content.some(
|
||||||
(content: BetaContentBlock) => content.type === 'tool_use',
|
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const firstData = progressMessages[0]?.data
|
const firstData = progressMessages[0]?.data
|
||||||
const prompt =
|
const prompt =
|
||||||
firstData && hasProgressMessage(firstData) ? firstData.prompt : undefined
|
firstData && hasProgressMessage(firstData) ? (firstData as AgentToolProgressData).prompt : undefined
|
||||||
|
|
||||||
// After grouping, displayedMessages can be empty when the only progress so
|
// After grouping, displayedMessages can be empty when the only progress so
|
||||||
// far is an assistant tool_use for a search/read op (grouped but not yet
|
// far is an assistant tool_use for a search/read op (grouped but not yet
|
||||||
|
|
@ -660,7 +683,7 @@ export function renderToolUseProgressMessage(
|
||||||
.filter((pm): pm is ProgressMessage<AgentToolProgress> =>
|
.filter((pm): pm is ProgressMessage<AgentToolProgress> =>
|
||||||
hasProgressMessage(pm.data),
|
hasProgressMessage(pm.data),
|
||||||
)
|
)
|
||||||
.map(pm => pm.data),
|
.map(pm => pm.data as unknown as { message: AssistantMessage | UserMessage }),
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -669,7 +692,7 @@ export function renderToolUseProgressMessage(
|
||||||
<SubAgentProvider>
|
<SubAgentProvider>
|
||||||
{isTranscriptMode && prompt && (
|
{isTranscriptMode && prompt && (
|
||||||
<Box marginBottom={1}>
|
<Box marginBottom={1}>
|
||||||
<AgentPromptDisplay prompt={prompt} />
|
<AgentPromptDisplay prompt={prompt as string} />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{displayedMessages.map(processed => {
|
{displayedMessages.map(processed => {
|
||||||
|
|
@ -694,7 +717,7 @@ export function renderToolUseProgressMessage(
|
||||||
return (
|
return (
|
||||||
<MessageComponent
|
<MessageComponent
|
||||||
key={processed.message.uuid}
|
key={processed.message.uuid}
|
||||||
message={processed.message.data.message}
|
message={processed.message.data.message as unknown as AssistantMessage | UserMessage}
|
||||||
lookups={subagentLookups}
|
lookups={subagentLookups}
|
||||||
addMargin={false}
|
addMargin={false}
|
||||||
tools={tools}
|
tools={tools}
|
||||||
|
|
@ -743,14 +766,14 @@ export function renderToolUseRejectedMessage(
|
||||||
// Get agentId from progress messages if available (agent was running before rejection)
|
// Get agentId from progress messages if available (agent was running before rejection)
|
||||||
const firstData = progressMessagesForMessage[0]?.data
|
const firstData = progressMessagesForMessage[0]?.data
|
||||||
const agentId =
|
const agentId =
|
||||||
firstData && hasProgressMessage(firstData) ? firstData.agentId : undefined
|
firstData && hasProgressMessage(firstData) ? (firstData as AgentToolProgressData).agentId : undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{process.env.USER_TYPE === 'ant' && agentId && (
|
{process.env.USER_TYPE === 'ant' && agentId && (
|
||||||
<MessageResponse>
|
<MessageResponse>
|
||||||
<Text color="warning">
|
<Text color="warning">
|
||||||
[ANT-ONLY] API calls: {getDisplayPath(getDumpPromptsPath(agentId))}
|
[ANT-ONLY] API calls: {getDisplayPath(getDumpPromptsPath(agentId as string))}
|
||||||
</Text>
|
</Text>
|
||||||
</MessageResponse>
|
</MessageResponse>
|
||||||
)}
|
)}
|
||||||
|
|
@ -798,7 +821,7 @@ function calculateAgentStats(progressMessages: ProgressMessage<Progress>[]): {
|
||||||
if (!hasProgressMessage(msg.data)) {
|
if (!hasProgressMessage(msg.data)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const message = msg.data.message
|
const message = msg.data.message as AgentProgressMessage
|
||||||
return (
|
return (
|
||||||
message.type === 'user' &&
|
message.type === 'user' &&
|
||||||
message.message.content.some((content: BetaContentBlock) => content.type === 'tool_result')
|
message.message.content.some((content: BetaContentBlock) => content.type === 'tool_result')
|
||||||
|
|
@ -807,12 +830,12 @@ function calculateAgentStats(progressMessages: ProgressMessage<Progress>[]): {
|
||||||
|
|
||||||
const latestAssistant = progressMessages.findLast(
|
const latestAssistant = progressMessages.findLast(
|
||||||
(msg): msg is ProgressMessage<AgentToolProgress> =>
|
(msg): msg is ProgressMessage<AgentToolProgress> =>
|
||||||
hasProgressMessage(msg.data) && msg.data.message.type === 'assistant',
|
hasProgressMessage(msg.data) && (msg.data as AgentToolProgressData).message.type === 'assistant',
|
||||||
)
|
)
|
||||||
|
|
||||||
let tokens = null
|
let tokens = null
|
||||||
if (latestAssistant?.data.message.type === 'assistant') {
|
if ((latestAssistant?.data as AgentToolProgressData)?.message.type === 'assistant') {
|
||||||
const usage = latestAssistant.data.message.message.usage
|
const usage = (latestAssistant.data.message as AgentProgressMessage).message.usage
|
||||||
tokens =
|
tokens =
|
||||||
(usage.cache_creation_input_tokens ?? 0) +
|
(usage.cache_creation_input_tokens ?? 0) +
|
||||||
(usage.cache_read_input_tokens ?? 0) +
|
(usage.cache_read_input_tokens ?? 0) +
|
||||||
|
|
@ -1035,8 +1058,8 @@ export function extractLastToolInfo(
|
||||||
if (!hasProgressMessage(pm.data)) {
|
if (!hasProgressMessage(pm.data)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (pm.data.message.type === 'assistant') {
|
if ((pm.data as AgentToolProgressData).message.type === 'assistant') {
|
||||||
for (const c of pm.data.message.message.content) {
|
for (const c of (pm.data as AgentToolProgressData).message.message.content) {
|
||||||
if (c.type === 'tool_use') {
|
if (c.type === 'tool_use') {
|
||||||
toolUseByID.set(c.id, c as ToolUseBlockParam)
|
toolUseByID.set(c.id, c as ToolUseBlockParam)
|
||||||
}
|
}
|
||||||
|
|
@ -1055,7 +1078,7 @@ export function extractLastToolInfo(
|
||||||
const info = getSearchOrReadInfo(msg, tools, toolUseByID)
|
const info = getSearchOrReadInfo(msg, tools, toolUseByID)
|
||||||
if (info && (info.isSearch || info.isRead)) {
|
if (info && (info.isSearch || info.isRead)) {
|
||||||
// Only count tool_result messages to avoid double counting
|
// Only count tool_result messages to avoid double counting
|
||||||
if (msg.data.message.type === 'user') {
|
if ((msg.data as AgentToolProgressData).message.type === 'user') {
|
||||||
if (info.isSearch) {
|
if (info.isSearch) {
|
||||||
searchCount++
|
searchCount++
|
||||||
} else if (info.isRead) {
|
} else if (info.isRead) {
|
||||||
|
|
@ -1077,7 +1100,7 @@ export function extractLastToolInfo(
|
||||||
if (!hasProgressMessage(msg.data)) {
|
if (!hasProgressMessage(msg.data)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const message = msg.data.message
|
const message = msg.data.message as AgentProgressMessage
|
||||||
return (
|
return (
|
||||||
message.type === 'user' &&
|
message.type === 'user' &&
|
||||||
message.message.content.some((c: BetaContentBlock) => c.type === 'tool_result')
|
message.message.content.some((c: BetaContentBlock) => c.type === 'tool_result')
|
||||||
|
|
@ -1085,8 +1108,8 @@ export function extractLastToolInfo(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if (lastToolResult?.data.message.type === 'user') {
|
if ((lastToolResult?.data.message as AgentProgressMessage)?.type === 'user') {
|
||||||
const toolResultBlock = lastToolResult.data.message.message.content.find(
|
const toolResultBlock = (lastToolResult.data.message as AgentProgressMessage).message.content.find(
|
||||||
(c: BetaContentBlock) => c.type === 'tool_result',
|
(c: BetaContentBlock) => c.type === 'tool_result',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user