fix: resolve tsc errors (remaining upstream type fixes)
This commit is contained in:
parent
fe7fcf7dad
commit
ed197502af
|
|
@ -2149,7 +2149,7 @@ async function handleScreenshot(
|
|||
|
||||
const monitorNote = await buildMonitorNote(
|
||||
adapter,
|
||||
shot.displayId,
|
||||
shot.displayId ?? 0,
|
||||
overrides.lastScreenshot?.displayId,
|
||||
overrides.onDisplayPinned !== undefined,
|
||||
);
|
||||
|
|
@ -2218,7 +2218,7 @@ async function handleScreenshot(
|
|||
|
||||
const monitorNote = await buildMonitorNote(
|
||||
adapter,
|
||||
shot.displayId,
|
||||
shot.displayId ?? 0,
|
||||
overrides.lastScreenshot?.displayId,
|
||||
overrides.onDisplayPinned !== undefined,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
*/
|
||||
import bidiFactory from 'bidi-js'
|
||||
|
||||
type BidiInstance = {
|
||||
getEmbeddingLevels: (text: string, defaultDirection?: string) => { paragraphLevel: number; levels: Uint8Array }
|
||||
getReorderSegments: (text: string, embeddingLevels: { paragraphLevel: number; levels: Uint8Array }, start?: number, end?: number) => [number, number][]
|
||||
getVisualOrder: (reorderSegments: [number, number][]) => number[]
|
||||
}
|
||||
|
||||
type ClusteredChar = {
|
||||
value: string
|
||||
width: number
|
||||
|
|
@ -23,7 +29,7 @@ type ClusteredChar = {
|
|||
hyperlink: string | undefined
|
||||
}
|
||||
|
||||
let bidiInstance: ReturnType<typeof bidiFactory> | undefined
|
||||
let bidiInstance: BidiInstance | undefined
|
||||
let needsSoftwareBidi: boolean | undefined
|
||||
|
||||
function needsBidi(): boolean {
|
||||
|
|
@ -38,7 +44,7 @@ function needsBidi(): boolean {
|
|||
|
||||
function getBidi() {
|
||||
if (!bidiInstance) {
|
||||
bidiInstance = bidiFactory()
|
||||
bidiInstance = (bidiFactory as unknown as () => BidiInstance)()
|
||||
}
|
||||
return bidiInstance
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1883,8 +1883,8 @@ export default class Ink {
|
|||
let reentered = false
|
||||
const intercept = (
|
||||
chunk: Uint8Array | string,
|
||||
encodingOrCb?: BufferEncoding | ((err?: Error) => void),
|
||||
cb?: (err?: Error) => void,
|
||||
encodingOrCb?: BufferEncoding | ((err?: Error | null) => void),
|
||||
cb?: (err?: Error | null) => void,
|
||||
): boolean => {
|
||||
const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb
|
||||
// Reentrancy guard: logger.debug → writeToStderr → here. Pass
|
||||
|
|
|
|||
|
|
@ -564,16 +564,16 @@ export class QueryEngine {
|
|||
for (const msg of messagesFromUserInput) {
|
||||
if (
|
||||
msg.type === 'user' &&
|
||||
typeof msg.message.content === 'string' &&
|
||||
(msg.message.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) ||
|
||||
msg.message.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`) ||
|
||||
typeof msg.message!.content === 'string' &&
|
||||
(msg.message!.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) ||
|
||||
msg.message!.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`) ||
|
||||
msg.isCompactSummary)
|
||||
) {
|
||||
yield {
|
||||
type: 'user',
|
||||
message: {
|
||||
...msg.message,
|
||||
content: stripAnsi(msg.message.content),
|
||||
content: stripAnsi(msg.message!.content),
|
||||
},
|
||||
session_id: getSessionId(),
|
||||
parent_tool_use_id: null,
|
||||
|
|
@ -1090,7 +1090,7 @@ export class QueryEngine {
|
|||
const edeResultType = result?.type ?? 'undefined'
|
||||
const edeLastContentType =
|
||||
result?.type === 'assistant'
|
||||
? (last(result.message.content)?.type ?? 'none')
|
||||
? (last(result.message!.content as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlock[])?.type ?? 'none')
|
||||
: 'n/a'
|
||||
|
||||
// Flush buffered transcript writes before yielding result.
|
||||
|
|
@ -1148,7 +1148,7 @@ export class QueryEngine {
|
|||
let isApiError = false
|
||||
|
||||
if (result.type === 'assistant') {
|
||||
const lastContent = last(result.message.content)
|
||||
const lastContent = last(result.message!.content as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlock[])
|
||||
if (
|
||||
lastContent?.type === 'text' &&
|
||||
!SYNTHETIC_MESSAGES.has(lastContent.text)
|
||||
|
|
|
|||
|
|
@ -1429,7 +1429,7 @@ export function registerHookCallbacks(
|
|||
if (!STATE.registeredHooks[eventKey]) {
|
||||
STATE.registeredHooks[eventKey] = []
|
||||
}
|
||||
STATE.registeredHooks[eventKey]!.push(...matchers)
|
||||
STATE.registeredHooks[eventKey]!.push(...(matchers ?? []))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1451,7 +1451,7 @@ export function clearRegisteredPluginHooks(): void {
|
|||
const filtered: Partial<Record<HookEvent, RegisteredHookMatcher[]>> = {}
|
||||
for (const [event, matchers] of Object.entries(STATE.registeredHooks)) {
|
||||
// Keep only callback hooks (those without pluginRoot)
|
||||
const callbackHooks = matchers.filter(m => !('pluginRoot' in m))
|
||||
const callbackHooks = (matchers ?? []).filter(m => !('pluginRoot' in m))
|
||||
if (callbackHooks.length > 0) {
|
||||
filtered[event as HookEvent] = callbackHooks
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,12 +105,12 @@ export function extractTitleText(m: Message): string | undefined {
|
|||
if (m.type !== 'user' || m.isMeta || m.toolUseResult || m.isCompactSummary)
|
||||
return undefined
|
||||
if (m.origin && (m.origin as { kind?: string }).kind !== 'human') return undefined
|
||||
const content = m.message.content
|
||||
const content = m.message!.content
|
||||
let raw: string | undefined
|
||||
if (typeof content === 'string') {
|
||||
raw = content
|
||||
} else {
|
||||
for (const block of content) {
|
||||
for (const block of content ?? []) {
|
||||
if (block.type === 'text') {
|
||||
raw = block.text
|
||||
break
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {
|
|||
waitForPolicyLimitsToLoad,
|
||||
} from '../services/policyLimits/index.js'
|
||||
import type { Message } from '../types/message.js'
|
||||
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/index.js'
|
||||
import {
|
||||
checkAndRefreshOAuthTokenIfNeeded,
|
||||
getClaudeAIOAuthTokens,
|
||||
|
|
@ -289,7 +290,7 @@ export async function initReplBridge(
|
|||
isSyntheticMessage(msg)
|
||||
)
|
||||
continue
|
||||
const rawContent = getContentText(msg.message.content)
|
||||
const rawContent = getContentText(msg.message!.content as string | ContentBlockParam[])
|
||||
if (!rawContent) continue
|
||||
const derived = deriveTitle(rawContent)
|
||||
if (!derived) continue
|
||||
|
|
|
|||
|
|
@ -74,13 +74,15 @@ import type { SDKResultSuccess } from '../entrypoints/sdk/coreTypes.js'
|
|||
import type { PermissionMode } from '../utils/permissions/PermissionMode.js'
|
||||
|
||||
/**
|
||||
* StdoutMessage with session_id added. The transport layer adds session_id
|
||||
* to messages at runtime, but the Zod schemas don't include it. This type
|
||||
* makes it explicit that we're adding session_id to each message variant.
|
||||
* StdoutMessage with optional session_id. The transport layer accepts
|
||||
* StdoutMessage but we add session_id at runtime. Using optional because
|
||||
* the type system can't verify that adding session_id to a union type
|
||||
* is always valid, even though it is at runtime.
|
||||
*
|
||||
* We need to use 'as StdoutMessage' when passing to transport because
|
||||
* TypeScript can't verify that objects with session_id are valid StdoutMessage.
|
||||
*/
|
||||
type StdoutMessageWithSession = StdoutMessage extends infer T
|
||||
? T & { session_id: string }
|
||||
: never
|
||||
type TransportMessage = StdoutMessage & { session_id?: string }
|
||||
|
||||
const ANTHROPIC_VERSION = '2023-06-01'
|
||||
|
||||
|
|
@ -619,17 +621,17 @@ export async function initEnvLessBridgeCore(
|
|||
const msgs = flushGate.end()
|
||||
if (msgs.length === 0) return
|
||||
for (const msg of msgs) recentPostedUUIDs.add(msg.uuid)
|
||||
const events: StdoutMessageWithSession[] = toSDKMessages(msgs).map(m => ({
|
||||
const events: TransportMessage[] = toSDKMessages(msgs).map(m => ({
|
||||
...m,
|
||||
session_id: sessionId,
|
||||
}))
|
||||
})) as TransportMessage[]
|
||||
if (msgs.some(m => m.type === 'user')) {
|
||||
transport.reportState('running')
|
||||
}
|
||||
logForDebugging(
|
||||
`[remote-bridge] Drained ${msgs.length} queued message(s) after flush`,
|
||||
)
|
||||
void transport.writeBatch(events)
|
||||
void transport.writeBatch(events as StdoutMessage[])
|
||||
}
|
||||
|
||||
async function flushHistory(msgs: Message[]): Promise<void> {
|
||||
|
|
@ -647,10 +649,10 @@ export async function initEnvLessBridgeCore(
|
|||
`[remote-bridge] Capped initial flush: ${eligible.length} -> ${capped.length} (cap=${initialHistoryCap})`,
|
||||
)
|
||||
}
|
||||
const events: StdoutMessageWithSession[] = toSDKMessages(capped).map(m => ({
|
||||
const events: TransportMessage[] = toSDKMessages(capped).map(m => ({
|
||||
...m,
|
||||
session_id: sessionId,
|
||||
}))
|
||||
})) as TransportMessage[]
|
||||
if (events.length === 0) return
|
||||
// Mid-turn init: if Remote Control is enabled while a query is running,
|
||||
// the last eligible message is a user prompt or tool_result (both 'user'
|
||||
|
|
@ -663,7 +665,7 @@ export async function initEnvLessBridgeCore(
|
|||
transport.reportState('running')
|
||||
}
|
||||
logForDebugging(`[remote-bridge] Flushing ${events.length} history events`)
|
||||
await transport.writeBatch(events)
|
||||
await transport.writeBatch(events as StdoutMessage[])
|
||||
}
|
||||
|
||||
// ── 9. Teardown ───────────────────────────────────────────────────────────
|
||||
|
|
@ -686,11 +688,11 @@ export async function initEnvLessBridgeCore(
|
|||
// explicit sleep. close() sets closed=true which interrupts drain at the
|
||||
// next while-check, so close-before-archive drops the result.
|
||||
transport.reportState('idle')
|
||||
const resultMsg: StdoutMessageWithSession = {
|
||||
const resultMsg = {
|
||||
...makeResultMessage(sessionId),
|
||||
session_id: sessionId,
|
||||
}
|
||||
void transport.write(resultMsg)
|
||||
} as unknown as TransportMessage
|
||||
void transport.write(resultMsg as StdoutMessage)
|
||||
let token = getAccessToken()
|
||||
let status = await archiveSession(
|
||||
sessionId,
|
||||
|
|
@ -809,10 +811,10 @@ export async function initEnvLessBridgeCore(
|
|||
}
|
||||
|
||||
for (const msg of filtered) recentPostedUUIDs.add(msg.uuid)
|
||||
const events: StdoutMessageWithSession[] = toSDKMessages(filtered).map(m => ({
|
||||
const events: TransportMessage[] = toSDKMessages(filtered).map(m => ({
|
||||
...m,
|
||||
session_id: sessionId,
|
||||
}))
|
||||
})) as TransportMessage[]
|
||||
// v2 does not derive worker_status from events server-side (unlike v1
|
||||
// session-ingress session_status_updater.go). Push it from here so the
|
||||
// CCR web session list shows Running instead of stuck on Idle. A user
|
||||
|
|
@ -822,7 +824,7 @@ export async function initEnvLessBridgeCore(
|
|||
transport.reportState('running')
|
||||
}
|
||||
logForDebugging(`[remote-bridge] Sending ${filtered.length} message(s)`)
|
||||
void transport.writeBatch(events)
|
||||
void transport.writeBatch(events as StdoutMessage[])
|
||||
},
|
||||
writeSdkMessages(messages: SDKMessage[]) {
|
||||
const filtered = messages.filter(
|
||||
|
|
@ -842,11 +844,11 @@ export async function initEnvLessBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = { ...request, session_id: sessionId }
|
||||
const event: TransportMessage = { ...request, session_id: sessionId } as TransportMessage
|
||||
if ((request as { request?: { subtype?: string } }).request?.subtype === 'can_use_tool') {
|
||||
transport.reportState('requires_action')
|
||||
}
|
||||
void transport.write(event)
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging(
|
||||
`[remote-bridge] Sent control_request request_id=${request.request_id}`,
|
||||
)
|
||||
|
|
@ -858,9 +860,9 @@ export async function initEnvLessBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = { ...response, session_id: sessionId }
|
||||
const event: TransportMessage = { ...response, session_id: sessionId } as TransportMessage
|
||||
transport.reportState('running')
|
||||
void transport.write(event)
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging('[remote-bridge] Sent control_response')
|
||||
},
|
||||
sendControlCancelRequest(requestId: string) {
|
||||
|
|
@ -870,16 +872,16 @@ export async function initEnvLessBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = {
|
||||
const event: TransportMessage = {
|
||||
type: 'control_cancel_request' as const,
|
||||
request_id: requestId,
|
||||
session_id: sessionId,
|
||||
}
|
||||
} as TransportMessage
|
||||
// Hook/classifier/channel/recheck resolved the permission locally —
|
||||
// interactiveHandler calls only cancelRequest (no sendResponse) on
|
||||
// those paths, so without this the server stays on requires_action.
|
||||
transport.reportState('running')
|
||||
void transport.write(event)
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging(
|
||||
`[remote-bridge] Sent control_cancel_request request_id=${requestId}`,
|
||||
)
|
||||
|
|
@ -890,11 +892,11 @@ export async function initEnvLessBridgeCore(
|
|||
return
|
||||
}
|
||||
transport.reportState('idle')
|
||||
const resultMsg: StdoutMessageWithSession = {
|
||||
const resultMsg = {
|
||||
...makeResultMessage(sessionId),
|
||||
session_id: sessionId,
|
||||
}
|
||||
void transport.write(resultMsg)
|
||||
} as unknown as TransportMessage
|
||||
void transport.write(resultMsg as StdoutMessage)
|
||||
logForDebugging(`[remote-bridge] Sent result`)
|
||||
},
|
||||
async teardown() {
|
||||
|
|
|
|||
|
|
@ -57,13 +57,15 @@ import type { StdoutMessage } from '../entrypoints/sdk/controlTypes.js'
|
|||
import type { SDKResultSuccess } from '../entrypoints/sdk/coreTypes.js'
|
||||
|
||||
/**
|
||||
* StdoutMessage with session_id added. The transport layer adds session_id
|
||||
* to messages at runtime, but the Zod schemas don't include it. This type
|
||||
* makes it explicit that we're adding session_id to each message variant.
|
||||
* StdoutMessage with optional session_id. The transport layer accepts
|
||||
* StdoutMessage but we add session_id at runtime. Using optional because
|
||||
* the type system can't verify that adding session_id to a union type
|
||||
* is always valid, even though it is at runtime.
|
||||
*
|
||||
* We need to use 'as StdoutMessage' when passing to transport because
|
||||
* TypeScript can't verify that objects with session_id are valid StdoutMessage.
|
||||
*/
|
||||
type StdoutMessageWithSession = StdoutMessage extends infer T
|
||||
? T & { session_id: string }
|
||||
: never
|
||||
type TransportMessage = StdoutMessage & { session_id?: string }
|
||||
import { createCapacityWake, type CapacitySignal } from './capacityWake.js'
|
||||
import { FlushGate } from './flushGate.js'
|
||||
import {
|
||||
|
|
@ -876,14 +878,14 @@ export async function initBridgeCore(
|
|||
recentPostedUUIDs.add(msg.uuid)
|
||||
}
|
||||
const sdkMessages = toSDKMessages(msgs)
|
||||
const events: StdoutMessageWithSession[] = sdkMessages.map(sdkMsg => ({
|
||||
const events: TransportMessage[] = sdkMessages.map(sdkMsg => ({
|
||||
...sdkMsg,
|
||||
session_id: currentSessionId,
|
||||
}))
|
||||
})) as TransportMessage[]
|
||||
logForDebugging(
|
||||
`[bridge:repl] Drained ${msgs.length} pending message(s) after flush`,
|
||||
)
|
||||
void transport.writeBatch(events)
|
||||
void transport.writeBatch(events as StdoutMessage[])
|
||||
}
|
||||
|
||||
// Teardown reference — set after definition below. All callers are async
|
||||
|
|
@ -1296,13 +1298,13 @@ export async function initBridgeCore(
|
|||
logForDebugging(
|
||||
`[bridge:repl] Flushing ${sdkMessages.length} initial message(s) via transport`,
|
||||
)
|
||||
const events: StdoutMessageWithSession[] = sdkMessages.map(sdkMsg => ({
|
||||
const events: TransportMessage[] = sdkMessages.map(sdkMsg => ({
|
||||
...sdkMsg,
|
||||
session_id: currentSessionId,
|
||||
}))
|
||||
})) as TransportMessage[]
|
||||
const dropsBefore = newTransport.droppedBatchCount
|
||||
void newTransport
|
||||
.writeBatch(events)
|
||||
.writeBatch(events as StdoutMessage[])
|
||||
.then(() => {
|
||||
// If any batch was dropped during this flush (SI down for
|
||||
// maxConsecutiveFailures attempts), flush() still resolved
|
||||
|
|
@ -1666,11 +1668,11 @@ export async function initBridgeCore(
|
|||
transport = null
|
||||
flushGate.drop()
|
||||
if (teardownTransport) {
|
||||
const resultMsg: StdoutMessageWithSession = {
|
||||
const resultMsg = {
|
||||
...makeResultMessage(currentSessionId),
|
||||
session_id: currentSessionId,
|
||||
}
|
||||
void teardownTransport.write(resultMsg)
|
||||
} as unknown as TransportMessage
|
||||
void teardownTransport.write(resultMsg as StdoutMessage)
|
||||
}
|
||||
|
||||
const stopWorkP = currentWorkId
|
||||
|
|
@ -1793,11 +1795,11 @@ export async function initBridgeCore(
|
|||
// Convert to SDK format and send via HTTP POST (HybridTransport).
|
||||
// The web UI receives them via the subscribe WebSocket.
|
||||
const sdkMessages = toSDKMessages(filtered)
|
||||
const events: StdoutMessageWithSession[] = sdkMessages.map(sdkMsg => ({
|
||||
const events: TransportMessage[] = sdkMessages.map(sdkMsg => ({
|
||||
...sdkMsg,
|
||||
session_id: currentSessionId,
|
||||
}))
|
||||
void transport.writeBatch(events)
|
||||
})) as TransportMessage[]
|
||||
void transport.writeBatch(events as StdoutMessage[])
|
||||
},
|
||||
writeSdkMessages(messages) {
|
||||
// Daemon path: query() already yields SDKMessage, skip conversion.
|
||||
|
|
@ -1818,8 +1820,8 @@ export async function initBridgeCore(
|
|||
for (const msg of filtered) {
|
||||
if (msg.uuid) recentPostedUUIDs.add(msg.uuid as string)
|
||||
}
|
||||
const events: StdoutMessageWithSession[] = filtered.map(m => ({ ...m, session_id: currentSessionId }))
|
||||
void transport.writeBatch(events)
|
||||
const events: TransportMessage[] = filtered.map(m => ({ ...m, session_id: currentSessionId })) as TransportMessage[]
|
||||
void transport.writeBatch(events as StdoutMessage[])
|
||||
},
|
||||
sendControlRequest(request: SDKControlRequest) {
|
||||
if (!transport) {
|
||||
|
|
@ -1828,8 +1830,8 @@ export async function initBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = { ...request, session_id: currentSessionId }
|
||||
void transport.write(event)
|
||||
const event: TransportMessage = { ...request, session_id: currentSessionId } as TransportMessage
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging(
|
||||
`[bridge:repl] Sent control_request request_id=${request.request_id}`,
|
||||
)
|
||||
|
|
@ -1841,8 +1843,8 @@ export async function initBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = { ...response, session_id: currentSessionId }
|
||||
void transport.write(event)
|
||||
const event: TransportMessage = { ...response, session_id: currentSessionId } as TransportMessage
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging('[bridge:repl] Sent control_response')
|
||||
},
|
||||
sendControlCancelRequest(requestId: string) {
|
||||
|
|
@ -1852,12 +1854,12 @@ export async function initBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const event: StdoutMessageWithSession = {
|
||||
const event: TransportMessage = {
|
||||
type: 'control_cancel_request' as const,
|
||||
request_id: requestId,
|
||||
session_id: currentSessionId,
|
||||
}
|
||||
void transport.write(event)
|
||||
} as TransportMessage
|
||||
void transport.write(event as StdoutMessage)
|
||||
logForDebugging(
|
||||
`[bridge:repl] Sent control_cancel_request request_id=${requestId}`,
|
||||
)
|
||||
|
|
@ -1869,11 +1871,11 @@ export async function initBridgeCore(
|
|||
)
|
||||
return
|
||||
}
|
||||
const resultMsg: StdoutMessageWithSession = {
|
||||
const resultMsg = {
|
||||
...makeResultMessage(currentSessionId),
|
||||
session_id: currentSessionId,
|
||||
}
|
||||
void transport.write(resultMsg)
|
||||
} as unknown as TransportMessage
|
||||
void transport.write(resultMsg as StdoutMessage)
|
||||
logForDebugging(
|
||||
`[bridge:repl] Sent result for session=${currentSessionId}`,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ export function getCompanionIntroAttachment(
|
|||
// Skip if already announced for this companion.
|
||||
for (const msg of messages ?? []) {
|
||||
if (msg.type !== 'attachment') continue
|
||||
if (msg.attachment.type !== 'companion_intro') continue
|
||||
if (msg.attachment.name === companion.name) return []
|
||||
if (msg.attachment!.type !== 'companion_intro') continue
|
||||
if (msg.attachment!.name === companion.name) return []
|
||||
}
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -1180,7 +1180,7 @@ function runHeadlessStreaming(
|
|||
removeInterruptedMessage(mutableMessages, turnInterruptionState.message)
|
||||
enqueue({
|
||||
mode: 'prompt',
|
||||
value: turnInterruptionState.message.message.content,
|
||||
value: turnInterruptionState.message.message!.content as string | ContentBlockParam[],
|
||||
uuid: randomUUID(),
|
||||
})
|
||||
}
|
||||
|
|
@ -1231,13 +1231,13 @@ function runHeadlessStreaming(
|
|||
output.enqueue({
|
||||
type: 'user',
|
||||
content: crumb.message.content,
|
||||
message: crumb.message,
|
||||
message: crumb.message as unknown,
|
||||
session_id: getSessionId(),
|
||||
parent_tool_use_id: null,
|
||||
uuid: crumb.uuid,
|
||||
timestamp: crumb.timestamp,
|
||||
isReplay: true,
|
||||
} as SDKUserMessageReplay as StdoutMessage)
|
||||
} as unknown as StdoutMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1969,12 +1969,12 @@ function runHeadlessStreaming(
|
|||
output.enqueue({
|
||||
type: 'user',
|
||||
content: c.value,
|
||||
message: { role: 'user', content: c.value },
|
||||
message: { role: 'user', content: c.value } as unknown,
|
||||
session_id: getSessionId(),
|
||||
parent_tool_use_id: null,
|
||||
uuid: c.uuid as string,
|
||||
isReplay: true,
|
||||
} as SDKUserMessageReplay as StdoutMessage)
|
||||
} as unknown as StdoutMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4090,13 +4090,13 @@ function runHeadlessStreaming(
|
|||
output.enqueue({
|
||||
type: 'user',
|
||||
content: (userMsg.message as { content?: string })?.content ?? '',
|
||||
message: userMsg.message as { role: string; content: unknown },
|
||||
message: userMsg.message as unknown,
|
||||
session_id: sessionId,
|
||||
parent_tool_use_id: null,
|
||||
uuid: userMsg.uuid as string,
|
||||
timestamp: (userMsg as { timestamp?: string }).timestamp,
|
||||
isReplay: true,
|
||||
} as unknown as SDKUserMessageReplay as StdoutMessage)
|
||||
} as unknown as StdoutMessage)
|
||||
}
|
||||
// Historical dup = transcript already has this turn's output, so it
|
||||
// ran but its lifecycle was never closed (interrupted before ack).
|
||||
|
|
@ -4554,7 +4554,7 @@ async function handleRewindFiles(
|
|||
)
|
||||
return {
|
||||
canRewind: true,
|
||||
filesChanged: diffStats?.filesChanged,
|
||||
filesChanged: diffStats?.filesChanged ?? [],
|
||||
insertions: diffStats?.insertions,
|
||||
deletions: diffStats?.deletions,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,8 +463,8 @@ const loadAllCommands = memoize(async (cwd: string): Promise<Command[]> => {
|
|||
...bundledSkills,
|
||||
...builtinPluginSkills,
|
||||
...skillDirCommands,
|
||||
...workflowCommands,
|
||||
...pluginCommands,
|
||||
...(workflowCommands as Command[]),
|
||||
...(pluginCommands as Command[]),
|
||||
...pluginSkills,
|
||||
...COMMANDS(),
|
||||
]
|
||||
|
|
|
|||
3
src/commands/ant-trace/index.d.ts
vendored
Normal file
3
src/commands/ant-trace/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/autofix-pr/index.d.ts
vendored
Normal file
3
src/commands/autofix-pr/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/backfill-sessions/index.d.ts
vendored
Normal file
3
src/commands/backfill-sessions/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -44,7 +44,7 @@ export function deriveFirstPrompt(
|
|||
typeof content === 'string'
|
||||
? content
|
||||
: content.find(
|
||||
(block): block is { type: 'text'; text: string } =>
|
||||
(block: { type: string; text?: string }): block is { type: 'text'; text: string } =>
|
||||
block.type === 'text',
|
||||
)?.text
|
||||
if (!raw) return 'Branched conversation'
|
||||
|
|
|
|||
3
src/commands/break-cache/index.d.ts
vendored
Normal file
3
src/commands/break-cache/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -154,7 +154,7 @@ function BridgeDisconnectDialog({ onDone }: Props): React.ReactNode {
|
|||
type: 'utf8',
|
||||
errorCorrectionLevel: 'L',
|
||||
small: true,
|
||||
})
|
||||
} as Parameters<typeof qrToString>[1])
|
||||
.then(setQrText)
|
||||
.catch(() => setQrText(''))
|
||||
}, [showQR, displayUrl])
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ function BtwSideQuestion({
|
|||
*/
|
||||
function stripInProgressAssistantMessage(messages: Message[]): Message[] {
|
||||
const last = messages.at(-1)
|
||||
if (last?.type === 'assistant' && last.message.stop_reason === null) {
|
||||
if (last?.type === 'assistant' && last.message!.stop_reason === null) {
|
||||
return messages.slice(0, -1)
|
||||
}
|
||||
return messages
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export async function call(
|
|||
return React.createElement(CompanionCard, {
|
||||
companion,
|
||||
lastReaction,
|
||||
onDone,
|
||||
onDone: onDone as unknown as Parameters<typeof CompanionCard>[0]['onDone'],
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
3
src/commands/bughunter/index.d.ts
vendored
Normal file
3
src/commands/bughunter/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { feature } from 'bun:bundle'
|
||||
import chalk from 'chalk'
|
||||
import type { SDKStatus } from '../../entrypoints/agentSdkTypes.js'
|
||||
import { markPostCompaction } from 'src/bootstrap/state.js'
|
||||
import { getSystemPrompt } from '../../constants/prompts.js'
|
||||
import { getSystemContext, getUserContext } from '../../context.js'
|
||||
|
|
@ -223,7 +224,7 @@ async function compactViaReactive(
|
|||
context.setStreamMode?.('requesting')
|
||||
context.setResponseLength?.(() => 0)
|
||||
context.onCompactProgress?.({ type: 'compact_end' })
|
||||
context.setSDKStatus?.(null)
|
||||
context.setSDKStatus?.("" as SDKStatus)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
src/commands/ctx_viz/index.d.ts
vendored
Normal file
3
src/commands/ctx_viz/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/debug-tool-call/index.d.ts
vendored
Normal file
3
src/commands/debug-tool-call/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/env/index.d.ts
vendored
Normal file
3
src/commands/env/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/good-claude/index.d.ts
vendored
Normal file
3
src/commands/good-claude/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -1,4 +1,30 @@
|
|||
// Auto-generated stub — replace with real implementation
|
||||
export type Workflow = any;
|
||||
export type State = any;
|
||||
export type Warning = any;
|
||||
export type Workflow = 'claude' | 'claude-review' | string
|
||||
|
||||
export type Warning = {
|
||||
title: string
|
||||
message: string
|
||||
instructions: string[]
|
||||
}
|
||||
|
||||
export type State = {
|
||||
step: string
|
||||
selectedRepoName: string
|
||||
currentRepo: string
|
||||
useCurrentRepo: boolean
|
||||
apiKeyOrOAuthToken: string
|
||||
useExistingKey: boolean
|
||||
currentWorkflowInstallStep: number
|
||||
warnings: Warning[]
|
||||
secretExists: boolean
|
||||
secretName: string
|
||||
useExistingSecret: boolean
|
||||
workflowExists: boolean
|
||||
selectedWorkflows: Workflow[]
|
||||
selectedApiKeyOption: 'existing' | 'new' | 'oauth'
|
||||
authType: 'api_key' | 'oauth_token'
|
||||
workflowAction?: string
|
||||
error?: string
|
||||
errorReason?: string
|
||||
errorInstructions?: string[]
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
|
|
|||
3
src/commands/issue/index.d.ts
vendored
Normal file
3
src/commands/issue/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/mock-limits/index.d.ts
vendored
Normal file
3
src/commands/mock-limits/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/oauth-refresh/index.d.ts
vendored
Normal file
3
src/commands/oauth-refresh/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/onboarding/index.d.ts
vendored
Normal file
3
src/commands/onboarding/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/perf-issue/index.d.ts
vendored
Normal file
3
src/commands/perf-issue/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -25,7 +25,9 @@ function getEnvVarForProvider(provider: string): string {
|
|||
// Get merged env: process.env + settings.env (from userSettings)
|
||||
function getMergedEnv(): Record<string, string> {
|
||||
const settings = getSettings_DEPRECATED()
|
||||
const merged = { ...process.env }
|
||||
const merged: Record<string, string> = Object.fromEntries(
|
||||
Object.entries(process.env).filter((e): e is [string, string] => e[1] !== undefined)
|
||||
)
|
||||
if (settings?.env) {
|
||||
Object.assign(merged, settings.env)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { BRIDGE_LOGIN_INSTRUCTION } from '../../bridge/types.js';
|
|||
import { Dialog } from '../../components/design-system/Dialog.js';
|
||||
import { ListItem } from '../../components/design-system/ListItem.js';
|
||||
import { useRegisterOverlay } from '../../context/overlayContext.js';
|
||||
import { Box, Text } from '../../ink.js';
|
||||
import { Box, Text } from '@anthropic/ink';
|
||||
import { useKeybindings } from '../../keybindings/useKeybinding.js';
|
||||
import type { ToolUseContext } from '../../Tool.js';
|
||||
import type { LocalJSXCommandContext, LocalJSXCommandOnDone } from '../../types/command.js';
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import {
|
|||
formatPreconditionError,
|
||||
getRemoteTaskSessionUrl,
|
||||
registerRemoteAgentTask,
|
||||
type BackgroundRemoteSessionPrecondition,
|
||||
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
||||
import { isEnterpriseSubscriber, isTeamSubscriber } from '../../utils/auth.js'
|
||||
import { detectCurrentRepositoryWithHost } from '../../utils/detectRepository.js'
|
||||
|
|
@ -147,7 +148,7 @@ export async function launchRemoteReview(
|
|||
',',
|
||||
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
const reasons = blockers.map(formatPreconditionError).join('\n')
|
||||
const reasons = (blockers as BackgroundRemoteSessionPrecondition[]).map(formatPreconditionError).join('\n')
|
||||
return [
|
||||
{
|
||||
type: 'text',
|
||||
|
|
|
|||
3
src/commands/share/index.d.ts
vendored
Normal file
3
src/commands/share/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/summary/index.d.ts
vendored
Normal file
3
src/commands/summary/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
3
src/commands/teleport/index.d.ts
vendored
Normal file
3
src/commands/teleport/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { Command } from '../../types/command.js'
|
||||
declare const _default: Command
|
||||
export default _default
|
||||
|
|
@ -64,7 +64,7 @@ export function BridgeDialog({ onDone }: Props): React.ReactNode {
|
|||
return
|
||||
}
|
||||
qrToString(displayUrl, {
|
||||
type: 'utf8',
|
||||
type: 'terminal',
|
||||
errorCorrectionLevel: 'L',
|
||||
small: true,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ async function generateTitle(
|
|||
},
|
||||
})
|
||||
|
||||
const _firstBlock = response.message.content[0] as unknown as Record<string, unknown> | undefined
|
||||
const _firstBlock = response?.message?.content?.[0] as unknown as Record<string, unknown> | undefined
|
||||
const title =
|
||||
_firstBlock?.type === 'text'
|
||||
? (_firstBlock.text as string)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ function hasMemoryFileRead(messages: Message[]): boolean {
|
|||
if (message.type !== 'assistant') {
|
||||
continue
|
||||
}
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,8 +242,8 @@ export function countUnseenAssistantTurns(
|
|||
|
||||
function assistantHasVisibleText(m: Message): boolean {
|
||||
if (m.type !== 'assistant') return false
|
||||
if (!Array.isArray(m.message.content)) return false
|
||||
for (const b of m.message.content) {
|
||||
if (!Array.isArray(m.message!.content)) return false
|
||||
for (const b of m.message!.content) {
|
||||
if (typeof b !== 'string' && b.type === 'text' && b.text.trim() !== '') return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -748,9 +748,9 @@ function UserMessageOption({
|
|||
)
|
||||
}
|
||||
|
||||
const content = userMessage.message.content
|
||||
const content = userMessage.message!.content
|
||||
const lastBlock =
|
||||
typeof content === 'string' ? null : content[content.length - 1]
|
||||
typeof content === 'string' ? null : content![content!.length - 1]
|
||||
const rawMessageText =
|
||||
typeof content === 'string'
|
||||
? content.trim()
|
||||
|
|
@ -897,8 +897,8 @@ export function selectableUserMessagesFilter(
|
|||
return false
|
||||
}
|
||||
if (
|
||||
Array.isArray(message.message.content) &&
|
||||
message.message.content[0]?.type === 'tool_result'
|
||||
Array.isArray(message.message!.content) &&
|
||||
message.message!.content[0]?.type === 'tool_result'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -912,9 +912,9 @@ export function selectableUserMessagesFilter(
|
|||
return false
|
||||
}
|
||||
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
const lastBlock =
|
||||
typeof content === 'string' ? null : content[content.length - 1]
|
||||
typeof content === 'string' ? null : content![content!.length - 1]
|
||||
const messageText =
|
||||
typeof content === 'string'
|
||||
? content.trim()
|
||||
|
|
@ -960,7 +960,7 @@ export function messagesAfterAreOnlySynthetic(
|
|||
|
||||
// Assistant with actual content = meaningful
|
||||
if (msg.type === 'assistant') {
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
const hasMeaningfulContent = content.some(
|
||||
block =>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export function MessageTimestamp({
|
|||
isTranscriptMode &&
|
||||
message.timestamp &&
|
||||
message.type === 'assistant' &&
|
||||
(Array.isArray(message.message.content) ? (message.message.content as {type: string}[]).some(c => c.type === 'text') : false)
|
||||
(Array.isArray(message.message!.content) ? (message.message!.content as {type: string}[]).some(c => c.type === 'text') : false)
|
||||
|
||||
if (!shouldShowTimestamp) {
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ const MessagesImpl = ({
|
|||
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
||||
const msg = normalizedMessages[i]
|
||||
if (msg?.type === 'assistant') {
|
||||
const content = msg.message.content as Array<{ type: string }>
|
||||
const content = msg.message!.content as Array<{ type: string }>
|
||||
// Find the last thinking block in this message
|
||||
for (let j = content.length - 1; j >= 0; j--) {
|
||||
if (content[j]?.type === 'thinking') {
|
||||
|
|
@ -468,7 +468,7 @@ const MessagesImpl = ({
|
|||
}
|
||||
}
|
||||
} else if (msg?.type === 'user') {
|
||||
const content = msg.message.content as Array<{ type: string }>
|
||||
const content = msg.message!.content as Array<{ type: string }>
|
||||
const hasToolResult = content.some(
|
||||
block => block.type === 'tool_result',
|
||||
)
|
||||
|
|
@ -488,7 +488,7 @@ const MessagesImpl = ({
|
|||
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
||||
const msg = normalizedMessages[i]
|
||||
if (msg?.type === 'user') {
|
||||
const content = msg.message.content as Array<{ type: string; text?: string }>
|
||||
const content = msg.message!.content as Array<{ type: string; text?: string }>
|
||||
// Check if any text content is bash output
|
||||
for (const block of content) {
|
||||
if (block.type === 'text') {
|
||||
|
|
@ -741,7 +741,8 @@ const MessagesImpl = ({
|
|||
(msg: RenderableMessage): boolean => {
|
||||
if (msg.type === 'collapsed_read_search') return true
|
||||
if (msg.type === 'assistant') {
|
||||
const b = msg.message.content[0] as unknown as AdvisorBlock | undefined
|
||||
const content = msg.message!.content
|
||||
const b = (Array.isArray(content) ? content[0] : undefined) as unknown as AdvisorBlock | undefined
|
||||
return (
|
||||
b != null &&
|
||||
isAdvisorBlock(b) &&
|
||||
|
|
@ -750,11 +751,11 @@ const MessagesImpl = ({
|
|||
)
|
||||
}
|
||||
if (msg.type !== 'user') return false
|
||||
const b = (msg.message.content as Array<{ type: string; tool_use_id?: string; is_error?: boolean; [key: string]: unknown }>)[0]
|
||||
const b = (msg.message!.content as Array<{ type: string; tool_use_id?: string; is_error?: boolean; [key: string]: unknown }>)[0]
|
||||
if (b?.type !== 'tool_result' || b.is_error || !msg.toolUseResult)
|
||||
return false
|
||||
const name = lookupsRef.current.toolUseByToolUseID.get(
|
||||
b.tool_use_id,
|
||||
b.tool_use_id ?? '',
|
||||
)?.name
|
||||
const tool = name ? findToolByName(tools, name) : undefined
|
||||
return tool?.isResultTruncated?.(msg.toolUseResult as never) ?? false
|
||||
|
|
@ -1111,7 +1112,7 @@ export function shouldRenderStatically(
|
|||
case 'user':
|
||||
case 'assistant': {
|
||||
if (message.type === 'assistant') {
|
||||
const block = (message.message.content as Array<{ type: string; id?: string }>)[0]
|
||||
const block = (message.message!.content as Array<{ type: string; id?: string }>)[0]
|
||||
if (block?.type === 'server_tool_use') {
|
||||
return lookups.resolvedToolUseIDs.has(block.id!)
|
||||
}
|
||||
|
|
@ -1142,7 +1143,7 @@ export function shouldRenderStatically(
|
|||
}
|
||||
case 'grouped_tool_use': {
|
||||
const allResolved = message.messages.every(msg => {
|
||||
const content = (msg.message.content as Array<{ type: string; id?: string }>)[0]
|
||||
const content = (msg.message!.content as Array<{ type: string; id?: string }>)[0]
|
||||
return (
|
||||
content?.type === 'tool_use' &&
|
||||
lookups.resolvedToolUseIDs.has(content.id!)
|
||||
|
|
@ -1155,5 +1156,7 @@ export function shouldRenderStatically(
|
|||
// (In transcript mode, we already returned true at the top of this function)
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3140,8 +3140,8 @@ function getInitialPasteId(messages: Message[]): number {
|
|||
}
|
||||
}
|
||||
// Check text paste references in message content
|
||||
if (Array.isArray(message.message.content)) {
|
||||
for (const block of message.message.content) {
|
||||
if (Array.isArray(message.message!.content)) {
|
||||
for (const block of message.message!.content) {
|
||||
if (block.type === 'text') {
|
||||
const refs = parseReferences(block.text)
|
||||
for (const ref of refs) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { CustomAgentDefinition } from '@claude-code-best/builtin-tools/tools/AgentTool/loadAgentsDir.js'
|
||||
import type { AgentMemoryScope } from '@claude-code-best/builtin-tools/tools/AgentTool/agentMemory.js'
|
||||
import type { AgentMemoryScope } from '../../../tools/AgentTool/agentMemory.js'
|
||||
import type { CustomAgentDefinition } from '../../../tools/AgentTool/loadAgentsDir.js'
|
||||
import type { SettingSource } from '../../../utils/settings/constants.js'
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ export function isNavigableMessage(msg: NavigableMessage): boolean {
|
|||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PrimaryInput = {
|
||||
|
|
@ -395,6 +396,7 @@ export function copyTextOf(msg: NavigableMessage): string {
|
|||
return `[${a.type}]`
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function toolResultText(r: NormalizedUserMessage): string {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,6 @@ export function isNullRenderingAttachment(
|
|||
): boolean {
|
||||
return (
|
||||
msg.type === 'attachment' &&
|
||||
NULL_RENDERING_ATTACHMENT_TYPES.has(msg.attachment.type as Attachment['type'])
|
||||
NULL_RENDERING_ATTACHMENT_TYPES.has(msg.attachment!.type as Attachment['type'])
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export function FallbackPermissionRequest({
|
|||
event: 'accept',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -66,7 +66,7 @@ export function FallbackPermissionRequest({
|
|||
event: 'accept',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -92,7 +92,7 @@ export function FallbackPermissionRequest({
|
|||
event: 'reject',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -111,7 +111,7 @@ export function FallbackPermissionRequest({
|
|||
event: 'reject',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export function useFilePermissionDialog<T extends ToolInput>({
|
|||
const onChange = useCallback(
|
||||
(option: PermissionOption, input: T, feedback?: string) => {
|
||||
const params: PermissionHandlerParams = {
|
||||
messageId: toolUseConfirm.assistantMessage.message.id,
|
||||
messageId: toolUseConfirm.assistantMessage.message.id!,
|
||||
path: filePath,
|
||||
toolUseConfirm,
|
||||
toolPermissionContext,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import * as React from 'react'
|
|||
import { Suspense, use, useMemo } from 'react'
|
||||
import { Box, NoSelect, Text } from '@anthropic/ink'
|
||||
import type {
|
||||
NotebookCell,
|
||||
NotebookCellType,
|
||||
NotebookContent,
|
||||
} from '../../../types/notebook.js'
|
||||
|
|
@ -79,7 +80,7 @@ function NotebookEditToolDiffInner({
|
|||
}
|
||||
return ''
|
||||
}
|
||||
const cell = notebookData.cells.find(cell => cell.id === cell_id)
|
||||
const cell = notebookData.cells.find((cell: NotebookCell) => cell.id === cell_id)
|
||||
if (!cell) {
|
||||
return ''
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ export function SkillPermissionRequest(
|
|||
event: 'accept',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -142,7 +142,7 @@ export function SkillPermissionRequest(
|
|||
event: 'accept',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -169,7 +169,7 @@ export function SkillPermissionRequest(
|
|||
event: 'accept',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -201,7 +201,7 @@ export function SkillPermissionRequest(
|
|||
event: 'reject',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
@ -220,7 +220,7 @@ export function SkillPermissionRequest(
|
|||
event: 'reject',
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ export function usePermissionRequestLogging(
|
|||
event: 'response',
|
||||
metadata: {
|
||||
language_name: unaryEvent.language_name,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
||||
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||
platform: env.platform,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
// eslint-disable-next-line custom-rules/prefer-use-keybindings -- 'r' is a view-specific key, not a global keybinding
|
||||
import { Box, Text, useInput } from '@anthropic/ink'
|
||||
import { Box, Text, useInput, useTabHeaderFocus } from '@anthropic/ink'
|
||||
import {
|
||||
type AutoModeDenial,
|
||||
getAutoModeDenials,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useCallback, useEffect } from 'react'
|
|||
import { getOriginalCwd } from '../../../bootstrap/state.js'
|
||||
import type { CommandResultDisplay } from '../../../commands.js'
|
||||
import { Select } from '../../../components/CustomSelect/select.js'
|
||||
import { Box, Text } from '@anthropic/ink'
|
||||
import { Box, Text, useTabHeaderFocus } from '@anthropic/ink'
|
||||
import type { ToolPermissionContext } from '../../../Tool.js'
|
||||
|
||||
type Props = {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export function logUnaryPermissionEvent(
|
|||
event,
|
||||
metadata: {
|
||||
language_name: 'none',
|
||||
message_id,
|
||||
message_id: message_id!,
|
||||
platform: getHostPlatformForAnalytics(),
|
||||
hasFeedback: hasFeedback ?? false,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { feature } from 'bun:bundle'
|
||||
import figures from 'figures'
|
||||
import type { AgentId } from '../../types/ids.js'
|
||||
import React, {
|
||||
type ReactNode,
|
||||
useEffect,
|
||||
|
|
@ -535,12 +536,12 @@ export function BackgroundTasksDialog({
|
|||
}
|
||||
onSkipAgent={
|
||||
task.status === 'running' && skipWorkflowAgent
|
||||
? agentId => skipWorkflowAgent(task.id, agentId, setAppState)
|
||||
? (agentId: AgentId) => skipWorkflowAgent(task.id, agentId, setAppState)
|
||||
: undefined
|
||||
}
|
||||
onRetryAgent={
|
||||
task.status === 'running' && retryWorkflowAgent
|
||||
? agentId => retryWorkflowAgent(task.id, agentId, setAppState)
|
||||
? (agentId: AgentId) => retryWorkflowAgent(task.id, agentId, setAppState)
|
||||
: undefined
|
||||
}
|
||||
onBack={goBackToList}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export function WizardProvider<T extends Record<string, unknown>>({
|
|||
initialData?: T;
|
||||
onComplete: (data: T) => void;
|
||||
onCancel: () => void;
|
||||
children: ReactNode;
|
||||
children?: ReactNode;
|
||||
title: string;
|
||||
showStepCounter?: boolean;
|
||||
}): ReactNode {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export async function launchAssistantSessionChooser(
|
|||
return showSetupDialog<string | null>(root, done => (
|
||||
<AssistantSessionChooser
|
||||
sessions={props.sessions}
|
||||
onSelect={id => done(id)}
|
||||
onSelect={(id: string) => done(id)}
|
||||
onCancel={() => done(null)}
|
||||
/>
|
||||
))
|
||||
|
|
|
|||
|
|
@ -336,14 +336,22 @@ export const PermissionResultSchema = lazySchema(() =>
|
|||
|
||||
export const PermissionModeSchema = lazySchema(() =>
|
||||
z
|
||||
.enum(['default', 'acceptEdits', 'bypassPermissions', 'plan', 'dontAsk'])
|
||||
.enum([
|
||||
'default',
|
||||
'acceptEdits',
|
||||
'bypassPermissions',
|
||||
'plan',
|
||||
'dontAsk',
|
||||
'auto',
|
||||
])
|
||||
.describe(
|
||||
'Permission mode for controlling how tool executions are handled. ' +
|
||||
"'default' - Standard behavior, prompts for dangerous operations. " +
|
||||
"'acceptEdits' - Auto-accept file edit operations. " +
|
||||
"'bypassPermissions' - Bypass all permission checks (requires allowDangerouslySkipPermissions). " +
|
||||
"'plan' - Planning mode, no actual tool execution. " +
|
||||
"'dontAsk' - Don't prompt for permissions, deny if not pre-approved.",
|
||||
"'dontAsk' - Don't prompt for permissions, deny if not pre-approved. " +
|
||||
"'auto' - Automatic mode (transcript classifier).",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ function createPermissionContext(
|
|||
setToolPermissionContext: (context: ToolPermissionContext) => void,
|
||||
queueOps?: PermissionQueueOps,
|
||||
) {
|
||||
const messageId = assistantMessage.message.id
|
||||
const messageId = assistantMessage.message.id!
|
||||
const ctx = {
|
||||
tool,
|
||||
input,
|
||||
|
|
@ -234,7 +234,7 @@ function createPermissionContext(
|
|||
const finalInput = decision.updatedInput ?? updatedInput ?? input
|
||||
return await this.handleHookAllow(
|
||||
finalInput,
|
||||
decision.updatedPermissions ?? [],
|
||||
(decision.updatedPermissions ?? []) as unknown as import('../../types/permissions.js').PermissionUpdate[],
|
||||
permissionPromptStartTimeMs,
|
||||
)
|
||||
} else if (decision.behavior === 'deny') {
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ function useCanUseTool(
|
|||
tool,
|
||||
input,
|
||||
toolUseContext,
|
||||
messageId: ctx.messageId,
|
||||
messageId: ctx.messageId!,
|
||||
toolUseID,
|
||||
},
|
||||
{ decision: 'reject', source: 'config' },
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export function isSessionContainerCompatible(messages: Message[]): boolean {
|
|||
if (msg.type !== 'assistant') {
|
||||
continue
|
||||
}
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ function countHunkLines(hunks: StructuredPatchHunk[]): {
|
|||
|
||||
function getUserPromptPreview(message: Message): string {
|
||||
if (message.type !== 'user') return ''
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
const text = typeof content === 'string' ? content : ''
|
||||
// Truncate to ~30 chars
|
||||
if (text.length <= 30) return text
|
||||
|
|
@ -124,8 +124,8 @@ export function useTurnDiffs(messages: Message[]): TurnDiff[] {
|
|||
// Check if this is a user prompt (not a tool result)
|
||||
const isToolResult =
|
||||
message.toolUseResult ||
|
||||
(Array.isArray(message.message.content) &&
|
||||
message.message.content[0]?.type === 'tool_result')
|
||||
(Array.isArray(message.message!.content) &&
|
||||
message.message!.content[0]?.type === 'tool_result')
|
||||
|
||||
if (!isToolResult && !message.isMeta) {
|
||||
// Start a new turn on user prompt
|
||||
|
|
|
|||
|
|
@ -4460,7 +4460,7 @@ async function run(): Promise<CommanderCommand> {
|
|||
...(uploaderReady && {
|
||||
onTurnComplete: (messages: MessageType[]) => {
|
||||
void uploaderReady.then((uploader) =>
|
||||
uploader?.(messages),
|
||||
(uploader as ((msgs: MessageType[]) => void) | null)?.(messages),
|
||||
);
|
||||
},
|
||||
}),
|
||||
|
|
@ -4618,13 +4618,13 @@ async function run(): Promise<CommanderCommand> {
|
|||
createLocalSSHSession,
|
||||
SSHSessionError,
|
||||
} = await import("./ssh/createSSHSession.js");
|
||||
let sshSession;
|
||||
let sshSession: import('./ssh/createSSHSession.js').SSHSession | undefined;
|
||||
try {
|
||||
if (_pendingSSH.local) {
|
||||
process.stderr.write(
|
||||
"Starting local ssh-proxy test session...\n",
|
||||
);
|
||||
sshSession = createLocalSSHSession({
|
||||
sshSession = await createLocalSSHSession({
|
||||
cwd: _pendingSSH.cwd,
|
||||
permissionMode: _pendingSSH.permissionMode,
|
||||
dangerouslySkipPermissions:
|
||||
|
|
@ -4651,7 +4651,7 @@ async function run(): Promise<CommanderCommand> {
|
|||
},
|
||||
isTTY
|
||||
? {
|
||||
onProgress: (msg) => {
|
||||
onProgress: (msg: string) => {
|
||||
hadProgress = true;
|
||||
process.stderr.write(
|
||||
`\r ${msg}\x1b[K`,
|
||||
|
|
|
|||
10
src/query.ts
10
src/query.ts
|
|
@ -803,7 +803,7 @@ async function* queryLoop(
|
|||
if (
|
||||
contextCollapse?.isWithheldPromptTooLong(
|
||||
message as Message,
|
||||
isPromptTooLongMessage,
|
||||
isPromptTooLongMessage as (msg: Message) => boolean,
|
||||
querySource,
|
||||
)
|
||||
) {
|
||||
|
|
@ -1084,7 +1084,7 @@ async function* queryLoop(
|
|||
// prevents a spiral and the error surfaces.
|
||||
const isWithheldMedia =
|
||||
mediaRecoveryEnabled &&
|
||||
reactiveCompact?.isWithheldMediaSizeError(lastMessage)
|
||||
reactiveCompact?.isWithheldMediaSizeError(lastMessage as Message)
|
||||
if (isWithheld413) {
|
||||
// First: drain all staged context-collapses. Gated on the PREVIOUS
|
||||
// transition not being collapse_drain_retry — if we already drained
|
||||
|
|
@ -1173,8 +1173,8 @@ async function* queryLoop(
|
|||
// so hooks have nothing meaningful to evaluate. Running stop hooks
|
||||
// on prompt-too-long creates a death spiral: error → hook blocking
|
||||
// → retry → error → … (the hook injects more tokens each cycle).
|
||||
yield lastMessage
|
||||
void executeStopFailureHooks(lastMessage, toolUseContext)
|
||||
yield lastMessage!
|
||||
void executeStopFailureHooks(lastMessage!, toolUseContext)
|
||||
return { reason: isWithheldMedia ? 'image_error' : 'prompt_too_long' }
|
||||
} else if (feature('CONTEXT_COLLAPSE') && isWithheld413) {
|
||||
// reactiveCompact compiled out but contextCollapse withheld and
|
||||
|
|
@ -1390,7 +1390,7 @@ async function* queryLoop(
|
|||
|
||||
if (
|
||||
update.message.type === 'attachment' &&
|
||||
update.message.attachment.type === 'hook_stopped_continuation'
|
||||
update.message.attachment!.type === 'hook_stopped_continuation'
|
||||
) {
|
||||
shouldPreventContinuation = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ export async function* handleStopHooks(
|
|||
// but before gracefulShutdownSync (see drainPendingExtraction).
|
||||
void extractMemoriesModule!.executeExtractMemories(
|
||||
stopHookContext,
|
||||
toolUseContext.appendSystemMessage,
|
||||
toolUseContext.appendSystemMessage as ((msg: import('../types/message.js').SystemMessage) => void) | undefined,
|
||||
)
|
||||
}
|
||||
if (!toolUseContext.agentId) {
|
||||
|
|
@ -215,7 +215,7 @@ export async function* handleStopHooks(
|
|||
}
|
||||
// Track errors and output from attachments
|
||||
if (result.message.type === 'attachment') {
|
||||
const attachment = result.message.attachment
|
||||
const attachment = result.message.attachment!
|
||||
if (
|
||||
'hookEvent' in attachment &&
|
||||
(attachment.hookEvent === 'Stop' ||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ import { createUserMessage } from '../utils/messages.js'
|
|||
function convertAssistantMessage(msg: SDKAssistantMessage): AssistantMessage {
|
||||
return {
|
||||
type: 'assistant',
|
||||
message: msg.message,
|
||||
uuid: msg.uuid,
|
||||
message: msg.message!,
|
||||
uuid: msg.uuid!,
|
||||
requestId: undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
error: msg.error,
|
||||
|
|
@ -64,7 +64,7 @@ function convertResultMessage(msg: SDKResultMessage): SystemMessage {
|
|||
subtype: 'informational',
|
||||
content,
|
||||
level: isError ? 'warning' : 'info',
|
||||
uuid: msg.uuid,
|
||||
uuid: msg.uuid!,
|
||||
timestamp: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +78,7 @@ function convertInitMessage(msg: SDKSystemMessage): SystemMessage {
|
|||
subtype: 'informational',
|
||||
content: `Remote session initialized (model: ${msg.model})`,
|
||||
level: 'info',
|
||||
uuid: msg.uuid,
|
||||
uuid: msg.uuid!,
|
||||
timestamp: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ function convertStatusMessage(msg: SDKStatusMessage): SystemMessage | null {
|
|||
? 'Compacting conversation…'
|
||||
: `Status: ${msg.status}`,
|
||||
level: 'info',
|
||||
uuid: msg.uuid,
|
||||
uuid: msg.uuid!,
|
||||
timestamp: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ function convertToolProgressMessage(
|
|||
subtype: 'informational',
|
||||
content: `Tool ${msg.tool_name} running for ${msg.elapsed_time_seconds}s…`,
|
||||
level: 'info',
|
||||
uuid: msg.uuid,
|
||||
uuid: msg.uuid!,
|
||||
timestamp: new Date().toISOString(),
|
||||
toolUseID: msg.tool_use_id,
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ function convertCompactBoundaryMessage(
|
|||
subtype: 'compact_boundary',
|
||||
content: 'Conversation compacted',
|
||||
level: 'info',
|
||||
uuid: msg.uuid,
|
||||
uuid: msg.uuid!,
|
||||
timestamp: new Date().toISOString(),
|
||||
compactMetadata: fromSDKCompactMetadata(msg.compact_metadata),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2978,11 +2978,11 @@ export function REPL({
|
|||
for (const m of messagesRef.current) {
|
||||
if (
|
||||
m.type === 'attachment' &&
|
||||
m.attachment.type === 'queued_command' &&
|
||||
m.attachment.commandMode === 'task-notification' &&
|
||||
typeof m.attachment.prompt === 'string'
|
||||
m.attachment!.type === 'queued_command' &&
|
||||
m.attachment!.commandMode === 'task-notification' &&
|
||||
typeof m.attachment!.prompt === 'string'
|
||||
) {
|
||||
existingPrompts.add(m.attachment.prompt);
|
||||
existingPrompts.add(m.attachment!.prompt);
|
||||
}
|
||||
}
|
||||
const uniqueNotifications = notificationMessages.filter(
|
||||
|
|
@ -3160,7 +3160,7 @@ export function REPL({
|
|||
// title silently fell through to the "Claude Code" default.
|
||||
if (!titleDisabled && !sessionTitle && !agentTitle && !haikuTitleAttemptedRef.current) {
|
||||
const firstUserMessage = newMessages.find(m => m.type === 'user' && !m.isMeta);
|
||||
const text = firstUserMessage?.type === 'user' ? getContentText(firstUserMessage.message.content) : null;
|
||||
const text = firstUserMessage?.type === 'user' ? getContentText(firstUserMessage.message!.content as string | ContentBlockParam[]) : null;
|
||||
// Skip synthetic breadcrumbs — slash-command output, prompt-skill
|
||||
// expansions (/commit → <command-message>), local-command headers
|
||||
// (/help → <command-name>), and bash-mode (!cmd → <bash-input>).
|
||||
|
|
@ -3423,7 +3423,7 @@ export function REPL({
|
|||
// replayed as user-visible text.
|
||||
newMessages
|
||||
.filter((m): m is UserMessage => m.type === 'user' && !m.isMeta)
|
||||
.map(_ => getContentText(_.message.content))
|
||||
.map(_ => getContentText(_.message.content as string | ContentBlockParam[]))
|
||||
.filter(_ => _ !== null)
|
||||
.forEach((msg, i) => {
|
||||
enqueue({ value: msg, mode: 'prompt' });
|
||||
|
|
@ -3662,13 +3662,13 @@ export function REPL({
|
|||
...prev,
|
||||
initialMessage: null,
|
||||
toolPermissionContext: updatedToolPermissionContext,
|
||||
...(shouldStorePlanForVerification && {
|
||||
...(shouldStorePlanForVerification ? {
|
||||
pendingPlanVerification: {
|
||||
plan: initialMsg.message.planContent as string,
|
||||
verificationStarted: false,
|
||||
verificationCompleted: false,
|
||||
},
|
||||
}),
|
||||
} : {}),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -4385,7 +4385,7 @@ export function REPL({
|
|||
const newPastedContents: Record<number, PastedContent> = {};
|
||||
imageBlocks.forEach((block, index) => {
|
||||
if (block.source.type === 'base64') {
|
||||
const id = message.imagePasteIds?.[index] ?? index + 1;
|
||||
const id = (message.imagePasteIds as number[] | undefined)?.[index] ?? index + 1;
|
||||
newPastedContents[id] = {
|
||||
id,
|
||||
type: 'image',
|
||||
|
|
@ -4884,7 +4884,7 @@ export function REPL({
|
|||
// Count completed hooks
|
||||
const completedCount = count(messages, m => {
|
||||
if (m.type !== 'attachment') return false;
|
||||
const attachment = m.attachment;
|
||||
const attachment = m.attachment!;
|
||||
return (
|
||||
'hookEvent' in attachment &&
|
||||
(attachment.hookEvent === 'Stop' || attachment.hookEvent === 'SubagentStop') &&
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ export function startAgentSummarization(
|
|||
)
|
||||
continue
|
||||
}
|
||||
const contentArr = Array.isArray(msg.message.content) ? msg.message.content : []
|
||||
const contentArr = Array.isArray(msg.message!.content) ? msg.message!.content : []
|
||||
const textBlock = contentArr.find(b => b.type === 'text')
|
||||
if (textBlock?.type === 'text' && textBlock.text.trim()) {
|
||||
const summaryText = textBlock.text.trim()
|
||||
|
|
|
|||
|
|
@ -243,11 +243,11 @@ export function getParentCacheSuppressReason(
|
|||
): string | null {
|
||||
if (!lastAssistantMessage) return null
|
||||
|
||||
const usage = lastAssistantMessage.message.usage
|
||||
const inputTokens = usage.input_tokens ?? 0
|
||||
const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0
|
||||
const usage = lastAssistantMessage.message!.usage
|
||||
const inputTokens = usage!.input_tokens ?? 0
|
||||
const cacheWriteTokens = usage!.cache_creation_input_tokens ?? 0
|
||||
// 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 as number) + (cacheWriteTokens as number) + (outputTokens as number) >
|
||||
MAX_PARENT_UNCACHED_TOKENS
|
||||
|
|
@ -339,7 +339,7 @@ export async function generateSuggestion(
|
|||
|
||||
for (const msg of result.messages) {
|
||||
if (msg.type !== 'assistant') continue
|
||||
const contentArr = Array.isArray(msg.message.content) ? msg.message.content as Array<{ type: string; text?: string }> : []
|
||||
const contentArr = Array.isArray(msg.message!.content) ? msg.message!.content as Array<{ type: string; text?: string }> : []
|
||||
const textBlock = contentArr.find(b => b.type === 'text')
|
||||
if (textBlock?.type === 'text' && typeof textBlock.text === 'string') {
|
||||
const suggestion = textBlock.text.trim()
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ function getBoundaryDetail(
|
|||
function isUserMessageWithArrayContent(
|
||||
m: Message,
|
||||
): m is Message & { message: { content: unknown[] } } {
|
||||
return m.type === 'user' && 'message' in m && Array.isArray(m.message.content)
|
||||
return m.type === 'user' && 'message' in m && Array.isArray(m.message?.content)
|
||||
}
|
||||
|
||||
export function prepareMessagesForInjection(messages: Message[]): Message[] {
|
||||
|
|
@ -254,9 +254,9 @@ export function prepareMessagesForInjection(messages: Message[]): Message[] {
|
|||
|
||||
return messages
|
||||
.map(msg => {
|
||||
if (!('message' in msg) || !Array.isArray(msg.message.content)) return msg
|
||||
const content = msg.message.content.filter(keep)
|
||||
if (content.length === msg.message.content.length) return msg
|
||||
if (!('message' in msg) || !Array.isArray(msg.message?.content)) return msg
|
||||
const content = msg.message!.content.filter(keep)
|
||||
if (content.length === msg.message!.content.length) return msg
|
||||
if (content.length === 0) return null
|
||||
// Drop messages where all remaining blocks are whitespace-only text
|
||||
// (API rejects these with 400: "text content blocks must contain non-whitespace text")
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ function countToolCallsSince(
|
|||
}
|
||||
|
||||
if (message.type === 'assistant') {
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
toolCallCount += count(content, block => block.type === 'tool_use')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -599,13 +599,13 @@ export function userMessageToMessageParam(
|
|||
querySource?: QuerySource,
|
||||
): MessageParam {
|
||||
if (addCache) {
|
||||
if (typeof message.message.content === 'string') {
|
||||
if (typeof message.message!.content === 'string') {
|
||||
return {
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: message.message.content,
|
||||
text: message.message!.content,
|
||||
...(enablePromptCaching && {
|
||||
cache_control: getCacheControl({ querySource }),
|
||||
}),
|
||||
|
|
@ -615,9 +615,9 @@ export function userMessageToMessageParam(
|
|||
} else {
|
||||
return {
|
||||
role: 'user',
|
||||
content: message.message.content.map((_, i) => ({
|
||||
content: message.message!.content!.map((_, i) => ({
|
||||
..._,
|
||||
...(i === message.message.content.length - 1
|
||||
...(i === message.message!.content!.length - 1
|
||||
? enablePromptCaching
|
||||
? { cache_control: getCacheControl({ querySource }) }
|
||||
: {}
|
||||
|
|
@ -631,9 +631,9 @@ export function userMessageToMessageParam(
|
|||
// to addCacheBreakpoints share the same array and each splices in duplicate cache_edits.
|
||||
return {
|
||||
role: 'user',
|
||||
content: Array.isArray(message.message.content)
|
||||
? [...message.message.content]
|
||||
: message.message.content,
|
||||
content: (Array.isArray(message.message!.content)
|
||||
? [...message.message!.content]
|
||||
: message.message!.content) as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlockParam[],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -644,13 +644,13 @@ export function assistantMessageToMessageParam(
|
|||
querySource?: QuerySource,
|
||||
): MessageParam {
|
||||
if (addCache) {
|
||||
if (typeof message.message.content === 'string') {
|
||||
if (typeof message.message!.content === 'string') {
|
||||
return {
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: message.message.content,
|
||||
text: message.message!.content,
|
||||
...(enablePromptCaching && {
|
||||
cache_control: getCacheControl({ querySource }),
|
||||
}),
|
||||
|
|
@ -660,11 +660,11 @@ export function assistantMessageToMessageParam(
|
|||
} else {
|
||||
return {
|
||||
role: 'assistant',
|
||||
content: message.message.content.map((_, i) => {
|
||||
content: message.message!.content!.map((_, i) => {
|
||||
const contentBlock = stripGeminiProviderMetadata(_)
|
||||
return {
|
||||
...contentBlock,
|
||||
...(i === message.message.content.length - 1 &&
|
||||
...(i === message.message!.content!.length - 1 &&
|
||||
contentBlock.type !== 'thinking' &&
|
||||
contentBlock.type !== 'redacted_thinking' &&
|
||||
(feature('CONNECTOR_TEXT')
|
||||
|
|
@ -682,9 +682,9 @@ export function assistantMessageToMessageParam(
|
|||
return {
|
||||
role: 'assistant',
|
||||
content:
|
||||
typeof message.message.content === 'string'
|
||||
? message.message.content
|
||||
: message.message.content.map(stripGeminiProviderMetadata) as BetaContentBlockParam[],
|
||||
typeof message.message!.content === 'string'
|
||||
? message.message!.content
|
||||
: message.message!.content!.map(stripGeminiProviderMetadata) as BetaContentBlockParam[],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -992,8 +992,8 @@ export function stripExcessMediaItems(
|
|||
): (UserMessage | AssistantMessage)[] {
|
||||
let toRemove = 0
|
||||
for (const msg of messages) {
|
||||
if (!Array.isArray(msg.message.content)) continue
|
||||
for (const block of msg.message.content) {
|
||||
if (!Array.isArray(msg.message!.content)) continue
|
||||
for (const block of msg.message!.content) {
|
||||
if (isMedia(block)) toRemove++
|
||||
if (isToolResult(block) && Array.isArray(block.content)) {
|
||||
for (const nested of block.content) {
|
||||
|
|
@ -1007,7 +1007,7 @@ export function stripExcessMediaItems(
|
|||
|
||||
return messages.map(msg => {
|
||||
if (toRemove <= 0) return msg
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (!Array.isArray(content)) return msg
|
||||
|
||||
const before = toRemove
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export function isPromptTooLongMessage(msg: AssistantMessage): boolean {
|
|||
if (!msg.isApiErrorMessage) {
|
||||
return false
|
||||
}
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ function logToolUseToolResultMismatch(
|
|||
for (let i = 0; i < messagesForAPI.length; i++) {
|
||||
const msg = messagesForAPI[i]
|
||||
if (!msg) continue
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
for (const block of content) {
|
||||
if (
|
||||
|
|
@ -252,7 +252,7 @@ function logToolUseToolResultMismatch(
|
|||
const msg = messages[i]
|
||||
if (!msg) continue
|
||||
if (msg.type === 'assistant' && 'message' in msg) {
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
for (const block of content) {
|
||||
if (
|
||||
|
|
@ -274,10 +274,10 @@ function logToolUseToolResultMismatch(
|
|||
for (let i = normalizedIndex + 1; i < messagesForAPI.length; i++) {
|
||||
const msg = messagesForAPI[i]
|
||||
if (!msg) continue
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
for (const block of content) {
|
||||
const role = msg.message.role
|
||||
const role = msg.message!.role
|
||||
if (block.type === 'tool_use' && 'id' in block) {
|
||||
normalizedSeq.push(`${role}:tool_use:${block.id}`)
|
||||
} else if (block.type === 'tool_result' && 'tool_use_id' in block) {
|
||||
|
|
@ -307,10 +307,10 @@ function logToolUseToolResultMismatch(
|
|||
case 'user':
|
||||
case 'assistant': {
|
||||
if ('message' in msg) {
|
||||
const content = msg.message.content
|
||||
const content = msg.message!.content
|
||||
if (Array.isArray(content)) {
|
||||
for (const block of content) {
|
||||
const role = msg.message.role
|
||||
const role = msg.message!.role
|
||||
if (block.type === 'tool_use' && 'id' in block) {
|
||||
preNormalizedSeq.push(`${role}:tool_use:${block.id}`)
|
||||
} else if (
|
||||
|
|
@ -331,14 +331,14 @@ function logToolUseToolResultMismatch(
|
|||
}
|
||||
}
|
||||
} else if (typeof content === 'string') {
|
||||
preNormalizedSeq.push(`${msg.message.role}:string_content`)
|
||||
preNormalizedSeq.push(`${msg.message!.role}:string_content`)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'attachment':
|
||||
if ('attachment' in msg) {
|
||||
preNormalizedSeq.push(`attachment:${msg.attachment.type}`)
|
||||
preNormalizedSeq.push(`attachment:${msg.attachment!.type}`)
|
||||
}
|
||||
break
|
||||
case 'system':
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ function convertInternalUserMessage(
|
|||
return {
|
||||
role: 'user',
|
||||
parts: content.flatMap(block =>
|
||||
convertUserContentBlockToGeminiParts(block, toolNamesById),
|
||||
convertUserContentBlockToGeminiParts(block as unknown as string | Record<string, unknown>, toolNamesById),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,8 @@ export async function* adaptGeminiStreamToAnthropic(
|
|||
cache_read_input_tokens: 0,
|
||||
},
|
||||
},
|
||||
} as BetaRawMessageStreamEvent
|
||||
} as unknown as BetaRawMessageStreamEvent
|
||||
}
|
||||
|
||||
const candidate = chunk.candidates?.[0]
|
||||
const parts = candidate?.content?.parts ?? []
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ describe('buildOpenAIRequestBody — thinking params', () => {
|
|||
const body = buildOpenAIRequestBody({ ...baseParams, enableThinking: true })
|
||||
expect(body.thinking).toEqual({ type: 'enabled' })
|
||||
expect(body.enable_thinking).toBe(true)
|
||||
expect(body.chat_template_kwargs.thinking).toBe(true)
|
||||
expect(body.chat_template_kwargs!.thinking).toBe(true)
|
||||
})
|
||||
|
||||
test('does NOT include thinking params when disabled', () => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import type {
|
|||
SystemAPIErrorMessage,
|
||||
AssistantMessage,
|
||||
} from '../../../types/message.js'
|
||||
import type { AgentId } from '../../../types/ids.js'
|
||||
import type { Tools } from '../../../Tool.js'
|
||||
import type { Stream } from 'openai/streaming.mjs'
|
||||
import type {
|
||||
|
|
@ -362,4 +363,4 @@ export async function* queryModelOpenAI(
|
|||
error: (error instanceof Error ? error : new Error(String(error))) as unknown as SDKAssistantMessageError,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,9 +97,10 @@ export async function* adaptOpenAIStreamToAnthropic(
|
|||
cache_read_input_tokens: cachedTokens,
|
||||
},
|
||||
},
|
||||
} as BetaRawMessageStreamEvent
|
||||
} as unknown as BetaRawMessageStreamEvent
|
||||
}
|
||||
|
||||
// Skip chunks that carry only usage data (no delta content)
|
||||
if (!delta) continue
|
||||
|
||||
// Handle reasoning_content → Anthropic thinking block.
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ function makeDreamProgressWatcher(
|
|||
let text = ''
|
||||
let toolUseCount = 0
|
||||
const touchedPaths: string[] = []
|
||||
const contentBlocks = msg.message.content as ContentBlockParam[]
|
||||
const contentBlocks = msg.message!.content as ContentBlockParam[]
|
||||
for (const block of contentBlocks) {
|
||||
if (block.type === 'text') {
|
||||
text += block.text
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ describe("groupMessagesByApiRound", () => {
|
|||
test("preserves message order within groups", () => {
|
||||
const messages = [makeMsg("assistant", "a1"), makeMsg("user", "u2")];
|
||||
const groups = groupMessagesByApiRound(messages);
|
||||
expect(groups[0][0].message.id).toBe("a1");
|
||||
expect(groups[0][1].message.id).toBe("u2");
|
||||
expect(groups[0]![0]!.message!.id).toBe("a1");
|
||||
expect(groups[0]![1]!.message!.id).toBe("u2");
|
||||
});
|
||||
|
||||
test("handles system messages", () => {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import {
|
|||
getAgentListingDeltaAttachment,
|
||||
getDeferredToolsDeltaAttachment,
|
||||
getMcpInstructionsDeltaAttachment,
|
||||
type Attachment,
|
||||
} from '../../utils/attachments.js'
|
||||
import { getMemoryPath } from '../../utils/config.js'
|
||||
import { COMPACT_MAX_OUTPUT_TOKENS } from '../../utils/context.js'
|
||||
|
|
@ -114,6 +115,7 @@ import {
|
|||
roughTokenCountEstimation,
|
||||
roughTokenCountEstimationForMessages,
|
||||
} from '../tokenEstimation.js'
|
||||
import type { SDKStatus } from '../../entrypoints/agentSdkTypes.js'
|
||||
import { groupMessagesByApiRound } from './grouping.js'
|
||||
import {
|
||||
getCompactPrompt,
|
||||
|
|
@ -150,7 +152,7 @@ export function stripImagesFromMessages(messages: Message[]): Message[] {
|
|||
return message
|
||||
}
|
||||
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
return message
|
||||
}
|
||||
|
|
@ -216,8 +218,8 @@ export function stripReinjectedAttachments(messages: Message[]): Message[] {
|
|||
m =>
|
||||
!(
|
||||
m.type === 'attachment' &&
|
||||
(m.attachment.type === 'skill_discovery' ||
|
||||
m.attachment.type === 'skill_listing')
|
||||
(m.attachment!.type === 'skill_discovery' ||
|
||||
m.attachment!.type === 'skill_listing')
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -251,8 +253,8 @@ export function truncateHeadForPTLRetry(
|
|||
// (drops only the marker, re-adds it, zero progress on retry 2+).
|
||||
const input =
|
||||
messages[0]?.type === 'user' &&
|
||||
messages[0].isMeta &&
|
||||
messages[0].message.content === PTL_RETRY_MARKER
|
||||
messages[0]?.isMeta &&
|
||||
messages[0]?.message?.content === PTL_RETRY_MARKER
|
||||
? messages.slice(1)
|
||||
: messages
|
||||
|
||||
|
|
@ -760,7 +762,7 @@ export async function compactConversation(
|
|||
context.setStreamMode?.('requesting')
|
||||
context.setResponseLength?.(() => 0)
|
||||
context.onCompactProgress?.({ type: 'compact_end' })
|
||||
context.setSDKStatus?.(null)
|
||||
context.setSDKStatus?.("" as SDKStatus)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1103,7 +1105,7 @@ export async function partialCompactConversation(
|
|||
context.setStreamMode?.('requesting')
|
||||
context.setResponseLength?.(() => 0)
|
||||
context.onCompactProgress?.({ type: 'compact_end' })
|
||||
context.setSDKStatus?.(null)
|
||||
context.setSDKStatus?.("" as SDKStatus)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1453,7 +1455,7 @@ export async function createPostCompactFileAttachments(
|
|||
)
|
||||
|
||||
let usedTokens = 0
|
||||
return results.filter((result): result is AttachmentMessage => {
|
||||
return results.filter((result): result is AttachmentMessage<Attachment> => {
|
||||
if (result === null) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1613,10 +1615,10 @@ export async function createAsyncAgentAttachmentsIfNeeded(
|
|||
function collectReadToolFilePaths(messages: Message[]): Set<string> {
|
||||
const stubIds = new Set<string>()
|
||||
for (const message of messages) {
|
||||
if (message.type !== 'user' || !Array.isArray(message.message.content)) {
|
||||
if (message.type !== 'user' || !Array.isArray(message.message!.content)) {
|
||||
continue
|
||||
}
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (
|
||||
block.type === 'tool_result' &&
|
||||
typeof block.content === 'string' &&
|
||||
|
|
@ -1631,11 +1633,11 @@ function collectReadToolFilePaths(messages: Message[]): Set<string> {
|
|||
for (const message of messages) {
|
||||
if (
|
||||
message.type !== 'assistant' ||
|
||||
!Array.isArray(message.message.content)
|
||||
!Array.isArray(message.message!.content)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (
|
||||
block.type !== 'tool_use' ||
|
||||
block.name !== FILE_READ_TOOL_NAME ||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export function groupMessagesByApiRound(messages: Message[]): Message[][] {
|
|||
for (const msg of messages) {
|
||||
if (
|
||||
msg.type === 'assistant' &&
|
||||
msg.message.id !== lastAssistantId &&
|
||||
msg.message!.id !== lastAssistantId &&
|
||||
current.length > 0
|
||||
) {
|
||||
groups.push(current)
|
||||
|
|
@ -52,7 +52,7 @@ export function groupMessagesByApiRound(messages: Message[]): Message[][] {
|
|||
current.push(msg)
|
||||
}
|
||||
if (msg.type === 'assistant') {
|
||||
lastAssistantId = msg.message.id
|
||||
lastAssistantId = msg.message!.id
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -169,11 +169,11 @@ export function estimateMessageTokens(messages: Message[]): number {
|
|||
continue
|
||||
}
|
||||
|
||||
if (!Array.isArray(message.message.content)) {
|
||||
if (!Array.isArray(message.message!.content)) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (block.type === 'text') {
|
||||
totalTokens += roughTokenCountEstimation(block.text)
|
||||
} else if (block.type === 'tool_result') {
|
||||
|
|
@ -228,9 +228,9 @@ function collectCompactableToolIds(messages: Message[]): string[] {
|
|||
for (const message of messages) {
|
||||
if (
|
||||
message.type === 'assistant' &&
|
||||
Array.isArray(message.message.content)
|
||||
Array.isArray(message.message!.content)
|
||||
) {
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (block.type === 'tool_use' && COMPACTABLE_TOOLS.has(block.name)) {
|
||||
ids.push(block.id)
|
||||
}
|
||||
|
|
@ -313,9 +313,9 @@ async function cachedMicrocompactPath(
|
|||
const compactableToolIds = new Set(collectCompactableToolIds(messages))
|
||||
// Second pass: register tool results grouped by user message
|
||||
for (const message of messages) {
|
||||
if (message.type === 'user' && Array.isArray(message.message.content)) {
|
||||
if (message.type === 'user' && Array.isArray(message.message!.content)) {
|
||||
const groupIds: string[] = []
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (
|
||||
block.type === 'tool_result' &&
|
||||
compactableToolIds.has(block.tool_use_id) &&
|
||||
|
|
@ -375,7 +375,7 @@ async function cachedMicrocompactPath(
|
|||
const baseline =
|
||||
lastAsst?.type === 'assistant'
|
||||
? ((
|
||||
lastAsst.message.usage as unknown as Record<
|
||||
lastAsst.message!.usage as unknown as Record<
|
||||
string,
|
||||
number | undefined
|
||||
>
|
||||
|
|
@ -468,11 +468,11 @@ function maybeTimeBasedMicrocompact(
|
|||
|
||||
let tokensSaved = 0
|
||||
const result: Message[] = messages.map(message => {
|
||||
if (message.type !== 'user' || !Array.isArray(message.message.content)) {
|
||||
if (message.type !== 'user' || !Array.isArray(message.message!.content)) {
|
||||
return message
|
||||
}
|
||||
let touched = false
|
||||
const newContent = message.message.content.map(block => {
|
||||
const newContent = message.message!.content.map(block => {
|
||||
if (
|
||||
block.type === 'tool_result' &&
|
||||
clearSet.has(block.tool_use_id) &&
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { clearClassifierApprovals } from '../../utils/classifierApprovals.js'
|
|||
import { resetGetMemoryFilesCache } from '../../utils/claudemd.js'
|
||||
import { clearSessionMessagesCache } from '../../utils/sessionStorage.js'
|
||||
import { clearBetaTracingState } from '../../utils/telemetry/betaSessionTracing.js'
|
||||
import { logError } from '../../utils/log.js'
|
||||
import { resetMicrocompactState } from './microCompact.js'
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -134,11 +134,11 @@ async function initSessionMemoryCompactConfig(): Promise<void> {
|
|||
*/
|
||||
export function hasTextBlocks(message: Message): boolean {
|
||||
if (message.type === 'assistant') {
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
return Array.isArray(content) && content.some(block => block.type === 'text')
|
||||
}
|
||||
if (message.type === 'user') {
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (typeof content === 'string') {
|
||||
return content.length > 0
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ function getToolResultIds(message: Message): string[] {
|
|||
if (message.type !== 'user') {
|
||||
return []
|
||||
}
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
return []
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ function hasToolUseWithIds(message: Message, toolUseIds: Set<string>): boolean {
|
|||
if (message.type !== 'assistant') {
|
||||
return false
|
||||
}
|
||||
const content = message.message.content
|
||||
const content = message.message!.content
|
||||
if (!Array.isArray(content)) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -251,8 +251,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||
const toolUseIdsInKeptRange = new Set<string>()
|
||||
for (let i = adjustedIndex; i < messages.length; i++) {
|
||||
const msg = messages[i]!
|
||||
if (msg.type === 'assistant' && Array.isArray(msg.message.content)) {
|
||||
for (const block of msg.message.content) {
|
||||
if (msg.type === 'assistant' && Array.isArray(msg.message!.content)) {
|
||||
for (const block of msg.message!.content) {
|
||||
if (block.type === 'tool_use') {
|
||||
toolUseIdsInKeptRange.add(block.id)
|
||||
}
|
||||
|
|
@ -273,9 +273,9 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||
// Remove found tool_use_ids from the set
|
||||
if (
|
||||
message.type === 'assistant' &&
|
||||
Array.isArray(message.message.content)
|
||||
Array.isArray(message.message!.content)
|
||||
) {
|
||||
for (const block of message.message.content) {
|
||||
for (const block of message.message!.content) {
|
||||
if (block.type === 'tool_use' && neededToolUseIds.has(block.id)) {
|
||||
neededToolUseIds.delete(block.id)
|
||||
}
|
||||
|
|
@ -290,8 +290,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||
const messageIdsInKeptRange = new Set<string>()
|
||||
for (let i = adjustedIndex; i < messages.length; i++) {
|
||||
const msg = messages[i]!
|
||||
if (msg.type === 'assistant' && msg.message.id) {
|
||||
messageIdsInKeptRange.add(msg.message.id)
|
||||
if (msg.type === 'assistant' && msg.message!.id) {
|
||||
messageIdsInKeptRange.add(msg.message!.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,8 +301,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||
const message = messages[i]!
|
||||
if (
|
||||
message.type === 'assistant' &&
|
||||
message.message.id &&
|
||||
messageIdsInKeptRange.has(message.message.id)
|
||||
message.message!.id &&
|
||||
messageIdsInKeptRange.has(message.message!.id)
|
||||
) {
|
||||
// This message has the same message.id as one in the kept range
|
||||
// Include it so thinking blocks can be properly merged
|
||||
|
|
|
|||
|
|
@ -346,8 +346,8 @@ export class StreamingToolExecutor {
|
|||
|
||||
const isErrorResult =
|
||||
update.message.type === 'user' &&
|
||||
Array.isArray(update.message.message.content) &&
|
||||
update.message.message.content.some(
|
||||
Array.isArray(update.message.message!.content) &&
|
||||
update.message.message!.content.some(
|
||||
_ => _.type === 'tool_result' && _.is_error === true,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ async function checkPermissionsAndCallTool(
|
|||
tool,
|
||||
processedInput,
|
||||
toolUseID,
|
||||
assistantMessage.message.id,
|
||||
assistantMessage.message.id!,
|
||||
requestId,
|
||||
mcpServerType,
|
||||
mcpServerBaseUrl,
|
||||
|
|
@ -1497,7 +1497,7 @@ async function checkPermissionsAndCallTool(
|
|||
toolUseContext,
|
||||
tool,
|
||||
toolUseID,
|
||||
assistantMessage.message.id,
|
||||
assistantMessage.message.id!,
|
||||
processedInput,
|
||||
toolOutput,
|
||||
requestId,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export async function* runPostToolUseHooks<Input extends AnyObject, Output>(
|
|||
// IMPORTANT: We emit a cancelled event per hook
|
||||
if (
|
||||
result.message?.type === 'attachment' &&
|
||||
result.message.attachment.type === 'hook_cancelled'
|
||||
result.message.attachment!.type === 'hook_cancelled'
|
||||
) {
|
||||
logEvent('tengu_post_tool_hooks_cancelled', {
|
||||
toolName: sanitizeToolNameForAnalytics(tool.name),
|
||||
|
|
@ -96,7 +96,7 @@ export async function* runPostToolUseHooks<Input extends AnyObject, Output>(
|
|||
result.message &&
|
||||
!(
|
||||
result.message.type === 'attachment' &&
|
||||
result.message.attachment.type === 'hook_blocking_error'
|
||||
result.message.attachment!.type === 'hook_blocking_error'
|
||||
)
|
||||
) {
|
||||
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
||||
|
|
@ -223,7 +223,7 @@ export async function* runPostToolUseFailureHooks<Input extends AnyObject>(
|
|||
// Check if we were aborted during hook execution
|
||||
if (
|
||||
result.message?.type === 'attachment' &&
|
||||
result.message.attachment.type === 'hook_cancelled'
|
||||
result.message.attachment!.type === 'hook_cancelled'
|
||||
) {
|
||||
logEvent('tengu_post_tool_failure_hooks_cancelled', {
|
||||
toolName: sanitizeToolNameForAnalytics(tool.name),
|
||||
|
|
@ -248,7 +248,7 @@ export async function* runPostToolUseFailureHooks<Input extends AnyObject>(
|
|||
result.message &&
|
||||
!(
|
||||
result.message.type === 'attachment' &&
|
||||
result.message.attachment.type === 'hook_blocking_error'
|
||||
result.message.attachment!.type === 'hook_blocking_error'
|
||||
)
|
||||
) {
|
||||
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ function mapMessages(
|
|||
if (typeof _ === 'string') {
|
||||
return f(_)
|
||||
}
|
||||
return _.map(_ => {
|
||||
return _!.map(_ => {
|
||||
switch (_.type) {
|
||||
case 'tool_result':
|
||||
if (typeof _.content === 'string') {
|
||||
|
|
|
|||
|
|
@ -106,14 +106,14 @@ export function updateProgressFromMessage(
|
|||
if (message.type !== 'assistant') {
|
||||
return
|
||||
}
|
||||
const usage = message.message.usage as BetaUsage
|
||||
const usage = message.message!.usage as BetaUsage
|
||||
// Keep latest input (it's cumulative in the API), sum outputs
|
||||
tracker.latestInputTokens =
|
||||
(usage.input_tokens as number) +
|
||||
(usage.cache_creation_input_tokens ?? 0) +
|
||||
(usage.cache_read_input_tokens ?? 0)
|
||||
tracker.cumulativeOutputTokens += usage.output_tokens as number
|
||||
for (const content of (message.message.content ?? []) as Array<{ type: string; name?: string; input?: unknown }>) {
|
||||
for (const content of (message.message!.content ?? []) as Array<{ type: string; name?: string; input?: unknown }>) {
|
||||
if (content.type === 'tool_use') {
|
||||
tracker.toolUseCount++
|
||||
// Omit StructuredOutput from preview - it's an internal tool
|
||||
|
|
|
|||
|
|
@ -423,11 +423,11 @@ export function startBackgroundSession({
|
|||
const contentBlocks = (msg.message?.content ?? []) as Array<{ type: string; text?: string; name?: string; input?: unknown }>
|
||||
for (const block of contentBlocks) {
|
||||
if (block.type === 'text') {
|
||||
tokenCount += roughTokenCountEstimation(block.text)
|
||||
tokenCount += roughTokenCountEstimation(block.text ?? '')
|
||||
} else if (block.type === 'tool_use') {
|
||||
toolCount++
|
||||
const activity: ToolActivity = {
|
||||
toolName: block.name,
|
||||
toolName: block.name ?? '',
|
||||
input: block.input as Record<string, unknown>,
|
||||
}
|
||||
recentActivities.push(activity)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import {
|
|||
type BackgroundRemoteSessionPrecondition,
|
||||
checkBackgroundRemoteSessionEligibility,
|
||||
} from '../../utils/background/remote/remoteSession.js'
|
||||
export type { BackgroundRemoteSessionPrecondition }
|
||||
import { logForDebugging } from '../../utils/debug.js'
|
||||
import { logError } from '../../utils/log.js'
|
||||
import { enqueuePendingNotification } from '../../utils/messageQueueManager.js'
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import {
|
|||
formatPreconditionError,
|
||||
getRemoteTaskSessionUrl,
|
||||
registerRemoteAgentTask,
|
||||
type BackgroundRemoteSessionPrecondition,
|
||||
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
||||
import { assembleToolPool } from '../../tools.js'
|
||||
import { asAgentId } from '../../types/ids.js'
|
||||
|
|
@ -668,7 +669,7 @@ export const AgentTool = buildTool({
|
|||
if (process.env.USER_TYPE === 'ant' && effectiveIsolation === 'remote') {
|
||||
const eligibility = await checkRemoteAgentEligibility()
|
||||
if (!eligibility.eligible) {
|
||||
const reasons = (eligibility as { eligible: false; errors: Array<{ type: string; message?: string }> }).errors
|
||||
const reasons = (eligibility as { eligible: false; errors: BackgroundRemoteSessionPrecondition[] }).errors
|
||||
.map(formatPreconditionError)
|
||||
.join('\n')
|
||||
throw new Error(`Cannot launch remote agent:\n${reasons}`)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import type {
|
||||
ContentBlock,
|
||||
ToolResultBlockParam,
|
||||
ToolUseBlockParam,
|
||||
} from '@anthropic-ai/sdk/resources/index.mjs'
|
||||
type BetaContentBlock = ContentBlock | ToolResultBlockParam
|
||||
import * as React from 'react'
|
||||
import { ConfigurableShortcutHint } from 'src/components/ConfigurableShortcutHint.js'
|
||||
import {
|
||||
|
|
@ -555,7 +557,7 @@ export function renderToolUseProgressMessage(
|
|||
}
|
||||
const message = msg.data.message
|
||||
return message.message.content.some(
|
||||
content => content.type === 'tool_use',
|
||||
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -630,7 +632,7 @@ export function renderToolUseProgressMessage(
|
|||
return false
|
||||
}
|
||||
return data.message.message.content.some(
|
||||
content => content.type === 'tool_use',
|
||||
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -799,7 +801,7 @@ function calculateAgentStats(progressMessages: ProgressMessage<Progress>[]): {
|
|||
const message = msg.data.message
|
||||
return (
|
||||
message.type === 'user' &&
|
||||
message.message.content.some(content => content.type === 'tool_result')
|
||||
message.message.content.some((content: BetaContentBlock) => content.type === 'tool_result')
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -1078,14 +1080,14 @@ export function extractLastToolInfo(
|
|||
const message = msg.data.message
|
||||
return (
|
||||
message.type === 'user' &&
|
||||
message.message.content.some(c => c.type === 'tool_result')
|
||||
message.message.content.some((c: BetaContentBlock) => c.type === 'tool_result')
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
if (lastToolResult?.data.message.type === 'user') {
|
||||
const toolResultBlock = lastToolResult.data.message.message.content.find(
|
||||
c => c.type === 'tool_result',
|
||||
(c: BetaContentBlock) => c.type === 'tool_result',
|
||||
)
|
||||
|
||||
if (toolResultBlock?.type === 'tool_result') {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ export const FORK_AGENT = {
|
|||
export function isInForkChild(messages: MessageType[]): boolean {
|
||||
return messages.some(m => {
|
||||
if (m.type !== 'user') return false
|
||||
const content = m.message.content
|
||||
const content = m.message!.content
|
||||
if (!Array.isArray(content)) return false
|
||||
return content.some(
|
||||
block =>
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ export const NotebookEditTool = buildTool({
|
|||
}
|
||||
} else {
|
||||
// First try to find the cell by its actual ID
|
||||
const cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
||||
const cellIndex = notebook.cells.findIndex((cell: NotebookCell) => cell.id === cell_id)
|
||||
|
||||
if (cellIndex === -1) {
|
||||
// If not found, try to parse as a numeric index (cell-N format)
|
||||
|
|
@ -352,7 +352,7 @@ export const NotebookEditTool = buildTool({
|
|||
cellIndex = 0 // Default to inserting at the beginning if no cell_id is provided
|
||||
} else {
|
||||
// First try to find the cell by its actual ID
|
||||
cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
||||
cellIndex = notebook.cells.findIndex((cell: NotebookCell) => cell.id === cell_id)
|
||||
|
||||
// If not found, try to parse as a numeric index (cell-N format)
|
||||
if (cellIndex === -1) {
|
||||
|
|
|
|||
|
|
@ -430,7 +430,13 @@ export async function getURLMarkdownContent(
|
|||
// This lets GC reclaim up to MAX_HTTP_CONTENT_LENGTH (10MB) before Turndown
|
||||
// builds its DOM tree (which can be 3-5x the HTML size).
|
||||
;(response as { data: unknown }).data = null
|
||||
const contentType = response.headers['content-type'] ?? ''
|
||||
const contentTypeHeader = response.headers['content-type']
|
||||
const contentType =
|
||||
typeof contentTypeHeader === 'string'
|
||||
? contentTypeHeader
|
||||
: contentTypeHeader === undefined || contentTypeHeader === null
|
||||
? ''
|
||||
: String(contentTypeHeader)
|
||||
|
||||
// Binary content: save raw bytes to disk with a proper extension so Claude
|
||||
// can inspect the file later. We still fall through to the utf-8 decode +
|
||||
|
|
@ -519,9 +525,9 @@ export async function applyPromptToMarkdown(
|
|||
throw new AbortError()
|
||||
}
|
||||
|
||||
const { content } = assistantMessage.message
|
||||
if (content.length > 0) {
|
||||
const contentBlock = content[0]
|
||||
const { content } = assistantMessage.message!
|
||||
if (content!.length > 0) {
|
||||
const contentBlock = content![0]
|
||||
if (contentBlock && typeof contentBlock === 'object' && 'text' in contentBlock) {
|
||||
return (contentBlock as { text: string }).text
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user