mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 05:45:51 +00:00
feat: 问就是封包
This commit is contained in:
@@ -553,8 +553,8 @@ export function buildMissedTaskNotification(missed: CronTask[]): string {
|
||||
// Use a fence one longer than any backtick run in the prompt so a
|
||||
// prompt containing ``` cannot close the fence early and un-wrap the
|
||||
// trailing text (CommonMark fence-matching rule).
|
||||
const longestRun = (t.prompt.match(/`+/g) ?? []).reduce(
|
||||
(max, run) => Math.max(max, run.length),
|
||||
const longestRun = (t.prompt.match(/`+/g) ?? ([] as string[])).reduce(
|
||||
(max: number, run: string) => Math.max(max, run.length),
|
||||
0,
|
||||
)
|
||||
const fence = '`'.repeat(Math.max(3, longestRun + 1))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { McpbManifest } from '@anthropic-ai/mcpb'
|
||||
import type { McpbManifestAny } from '@anthropic-ai/mcpb'
|
||||
import { errorMessage } from '../errors.js'
|
||||
import { jsonParse } from '../slowOperations.js'
|
||||
|
||||
@@ -12,15 +12,15 @@ import { jsonParse } from '../slowOperations.js'
|
||||
*/
|
||||
export async function validateManifest(
|
||||
manifestJson: unknown,
|
||||
): Promise<McpbManifest> {
|
||||
const { McpbManifestSchema } = await import('@anthropic-ai/mcpb')
|
||||
const parseResult = McpbManifestSchema.safeParse(manifestJson)
|
||||
): Promise<McpbManifestAny> {
|
||||
const { vAny } = await import('@anthropic-ai/mcpb')
|
||||
const parseResult = vAny.McpbManifestSchema.safeParse(manifestJson)
|
||||
|
||||
if (!parseResult.success) {
|
||||
const errors = parseResult.error.flatten()
|
||||
const errorMessages = [
|
||||
...Object.entries(errors.fieldErrors).map(
|
||||
([field, errs]) => `${field}: ${errs?.join(', ')}`,
|
||||
([field, errs]) => `${field}: ${(errs as any)?.join(', ')}`,
|
||||
),
|
||||
...(errors.formErrors || []),
|
||||
]
|
||||
@@ -38,7 +38,7 @@ export async function validateManifest(
|
||||
*/
|
||||
export async function parseAndValidateManifestFromText(
|
||||
manifestText: string,
|
||||
): Promise<McpbManifest> {
|
||||
): Promise<McpbManifestAny> {
|
||||
let manifestJson: unknown
|
||||
|
||||
try {
|
||||
@@ -55,7 +55,7 @@ export async function parseAndValidateManifestFromText(
|
||||
*/
|
||||
export async function parseAndValidateManifestFromBytes(
|
||||
manifestData: Uint8Array,
|
||||
): Promise<McpbManifest> {
|
||||
): Promise<McpbManifestAny> {
|
||||
const manifestText = new TextDecoder().decode(manifestData)
|
||||
return parseAndValidateManifestFromText(manifestText)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export async function parseAndValidateManifestFromBytes(
|
||||
* Uses the same algorithm as the directory backend for consistency.
|
||||
*/
|
||||
export function generateExtensionId(
|
||||
manifest: McpbManifest,
|
||||
manifest: McpbManifestAny,
|
||||
prefix?: 'local.unpacked' | 'local.dxt',
|
||||
): string {
|
||||
const sanitize = (str: string) =>
|
||||
|
||||
@@ -64,12 +64,12 @@ export async function findModifiedFiles(
|
||||
outputsDir: string,
|
||||
): Promise<string[]> {
|
||||
// Use recursive flag to get all entries in one call
|
||||
let entries: Awaited<ReturnType<typeof fs.readdir>>
|
||||
let entries: Awaited<ReturnType<typeof fs.readdir>> | any[]
|
||||
try {
|
||||
entries = await fs.readdir(outputsDir, {
|
||||
withFileTypes: true,
|
||||
recursive: true,
|
||||
})
|
||||
}) as any[]
|
||||
} catch {
|
||||
// Directory doesn't exist or is not accessible
|
||||
return []
|
||||
@@ -113,7 +113,7 @@ export async function findModifiedFiles(
|
||||
// Filter to files modified since turn start
|
||||
const modifiedFiles: string[] = []
|
||||
for (const result of statResults) {
|
||||
if (result && result.mtimeMs >= turnStartTime) {
|
||||
if (result && result.mtimeMs >= (turnStartTime as any as number)) {
|
||||
modifiedFiles.push(result.filePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,10 +558,10 @@ export async function runForkedAgent({
|
||||
if (message.type === 'stream_event') {
|
||||
if (
|
||||
'event' in message &&
|
||||
message.event?.type === 'message_delta' &&
|
||||
message.event.usage
|
||||
(message as any).event?.type === 'message_delta' &&
|
||||
(message as any).event.usage
|
||||
) {
|
||||
const turnUsage = updateUsage({ ...EMPTY_USAGE }, message.event.usage)
|
||||
const turnUsage = updateUsage({ ...EMPTY_USAGE }, (message as any).event.usage)
|
||||
totalUsage = accumulateUsage(totalUsage, turnUsage)
|
||||
}
|
||||
continue
|
||||
|
||||
@@ -1325,14 +1325,15 @@ export function checkWritePermissionForTool<Input extends AnyObject>(
|
||||
},
|
||||
]
|
||||
: generateSuggestions(path, 'write', toolPermissionContext, pathsToCheck)
|
||||
const failedCheck = safetyCheck as { safe: false; message: string; classifierApprovable: boolean }
|
||||
return {
|
||||
behavior: 'ask',
|
||||
message: safetyCheck.message,
|
||||
message: failedCheck.message,
|
||||
suggestions: safetySuggestions,
|
||||
decisionReason: {
|
||||
type: 'safetyCheck',
|
||||
reason: safetyCheck.message,
|
||||
classifierApprovable: safetyCheck.classifierApprovable,
|
||||
reason: failedCheck.message,
|
||||
classifierApprovable: failedCheck.classifierApprovable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ export function isPathInSandboxWriteAllowlist(resolvedPath: string): boolean {
|
||||
// their resolution to avoid N × config.length redundant syscalls per
|
||||
// command with N write targets (matching getResolvedWorkingDirPaths).
|
||||
const pathsToCheck = getPathsForPermissionCheck(resolvedPath)
|
||||
const resolvedAllow = allowOnly.flatMap(getResolvedSandboxConfigPath)
|
||||
const resolvedDeny = denyWithinAllow.flatMap(getResolvedSandboxConfigPath)
|
||||
const resolvedAllow = allowOnly.flatMap(getResolvedSandboxConfigPath) as string[]
|
||||
const resolvedDeny = denyWithinAllow.flatMap(getResolvedSandboxConfigPath) as string[]
|
||||
return pathsToCheck.every(p => {
|
||||
for (const denyPath of resolvedDeny) {
|
||||
if (pathInWorkingPath(p, denyPath)) return false
|
||||
@@ -184,12 +184,13 @@ export function isPathAllowed(
|
||||
precomputedPathsToCheck,
|
||||
)
|
||||
if (!safetyCheck.safe) {
|
||||
const failedCheck = safetyCheck as { safe: false; message: string; classifierApprovable: boolean }
|
||||
return {
|
||||
allowed: false,
|
||||
decisionReason: {
|
||||
type: 'safetyCheck',
|
||||
reason: safetyCheck.message,
|
||||
classifierApprovable: safetyCheck.classifierApprovable,
|
||||
reason: failedCheck.message,
|
||||
classifierApprovable: failedCheck.classifierApprovable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ async function runPermissionRequestHooksForHeadlessAgent(
|
||||
input,
|
||||
context,
|
||||
permissionMode,
|
||||
suggestions,
|
||||
suggestions as any,
|
||||
context.abortController.signal,
|
||||
)) {
|
||||
if (!hookResult.permissionRequestResult) {
|
||||
@@ -423,12 +423,12 @@ async function runPermissionRequestHooksForHeadlessAgent(
|
||||
const finalInput = decision.updatedInput ?? input
|
||||
// Persist permission updates if provided
|
||||
if (decision.updatedPermissions?.length) {
|
||||
persistPermissionUpdates(decision.updatedPermissions)
|
||||
persistPermissionUpdates(decision.updatedPermissions as any)
|
||||
context.setAppState(prev => ({
|
||||
...prev,
|
||||
toolPermissionContext: applyPermissionUpdates(
|
||||
prev.toolPermissionContext,
|
||||
decision.updatedPermissions!,
|
||||
decision.updatedPermissions as any,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -251,12 +251,12 @@ export async function processUserInput({
|
||||
...hookResult.message,
|
||||
attachment: {
|
||||
...hookResult.message.attachment,
|
||||
content: applyTruncation(hookResult.message.attachment.content),
|
||||
content: applyTruncation(hookResult.message.attachment.content as string),
|
||||
},
|
||||
})
|
||||
} as AttachmentMessage)
|
||||
break
|
||||
default:
|
||||
result.messages.push(hookResult.message)
|
||||
result.messages.push(hookResult.message as AttachmentMessage)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ ${question}`
|
||||
function extractSideQuestionResponse(messages: Message[]): string | null {
|
||||
// Flatten all assistant content blocks across the per-block messages.
|
||||
const assistantBlocks = messages.flatMap(m =>
|
||||
m.type === 'assistant' ? m.message.content : [],
|
||||
m.type === 'assistant' ? (m.message.content as unknown as Array<{ type: string; [key: string]: unknown }>) : [],
|
||||
)
|
||||
|
||||
if (assistantBlocks.length > 0) {
|
||||
@@ -136,7 +136,7 @@ function extractSideQuestionResponse(messages: Message[]): string | null {
|
||||
// No text — check if the model tried to call a tool despite instructions.
|
||||
const toolUse = assistantBlocks.find(b => b.type === 'tool_use')
|
||||
if (toolUse) {
|
||||
const toolName = 'name' in toolUse ? toolUse.name : 'a tool'
|
||||
const toolName = 'name' in toolUse ? (toolUse as any).name : 'a tool'
|
||||
return `(The model tried to call ${toolName} instead of answering directly. Try rephrasing or ask in the main conversation.)`
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ function extractSideQuestionResponse(messages: Message[]): string | null {
|
||||
m.type === 'system' && 'subtype' in m && m.subtype === 'api_error',
|
||||
)
|
||||
if (apiErr) {
|
||||
return `(API error: ${formatAPIError(apiErr.error)})`
|
||||
return `(API error: ${formatAPIError(apiErr.error as any)})`
|
||||
}
|
||||
|
||||
return null
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function sliceAnsi(
|
||||
// pass start/end in display cells (via stringWidth), so position must
|
||||
// track the same units.
|
||||
const width =
|
||||
token.type === 'ansi' ? 0 : token.fullWidth ? 2 : stringWidth(token.value)
|
||||
token.type === 'ansi' ? 0 : token.type === 'char' ? (token.fullWidth ? 2 : stringWidth(token.value)) : 0
|
||||
|
||||
// Break AFTER trailing zero-width marks — a combining mark attaches to
|
||||
// the preceding base char, so "भा" (भ + ा, 1 display cell) sliced at
|
||||
@@ -77,7 +77,7 @@ export default function sliceAnsi(
|
||||
}
|
||||
|
||||
if (include) {
|
||||
result += token.value
|
||||
result += (token as any).value
|
||||
}
|
||||
|
||||
position += width
|
||||
|
||||
@@ -231,16 +231,17 @@ export async function createAndUploadGitBundle(
|
||||
)
|
||||
|
||||
if (!bundle.ok) {
|
||||
logForDebugging(`[gitBundle] ${bundle.error}`)
|
||||
const failedBundle = bundle as { ok: false; error: string; failReason: BundleFailReason }
|
||||
logForDebugging(`[gitBundle] ${failedBundle.error}`)
|
||||
logEvent('tengu_ccr_bundle_upload', {
|
||||
outcome:
|
||||
bundle.failReason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
failedBundle.failReason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
max_bytes: maxBytes,
|
||||
})
|
||||
return {
|
||||
success: false,
|
||||
error: bundle.error,
|
||||
failReason: bundle.failReason,
|
||||
error: failedBundle.error,
|
||||
failReason: failedBundle.failReason,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +255,7 @@ export async function createAndUploadGitBundle(
|
||||
outcome:
|
||||
'failed' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
return { success: false, error: upload.error }
|
||||
return { success: false, error: (upload as { success: false; error: string }).error }
|
||||
}
|
||||
|
||||
logForDebugging(
|
||||
|
||||
@@ -551,7 +551,7 @@ export function extractDiscoveredToolNames(messages: Message[]): Set<string> {
|
||||
// check rather than isCompactBoundaryMessage — utils/messages.ts imports
|
||||
// from this file, so importing back would be circular.
|
||||
if (msg.type === 'system' && msg.subtype === 'compact_boundary') {
|
||||
const carried = msg.compactMetadata?.preCompactDiscoveredTools
|
||||
const carried = (msg as any).compactMetadata?.preCompactDiscoveredTools as string[] | undefined
|
||||
if (carried) {
|
||||
for (const name of carried) discoveredTools.add(name)
|
||||
carriedFromBoundary += carried.length
|
||||
@@ -658,8 +658,8 @@ export function getDeferredToolsDelta(
|
||||
attachmentTypesSeen.add(msg.attachment.type)
|
||||
if (msg.attachment.type !== 'deferred_tools_delta') continue
|
||||
dtdCount++
|
||||
for (const n of msg.attachment.addedNames) announced.add(n)
|
||||
for (const n of msg.attachment.removedNames) announced.delete(n)
|
||||
for (const n of (msg.attachment as any).addedNames) announced.add(n)
|
||||
for (const n of (msg.attachment as any).removedNames) announced.delete(n)
|
||||
}
|
||||
|
||||
const deferred: Tool[] = tools.filter(isDeferredTool)
|
||||
|
||||
Reference in New Issue
Block a user