mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-19 06:45:50 +00:00
更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)
* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-2): 格式化 commands (79 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-5): 格式化 components其余 + hooks + tools (232 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files) 纯格式化:移除分号、React Compiler import、import 多行展开。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md - README.md: 大幅重写,更详细版本历史和配置示例 - Run.ps1: 新增 Windows 启动脚本 - TODO.md: 新增包完成清单 - V6.md: 删除(架构重构规划已不适用) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复以前的问题 * fix: 修复 login 面板的问题 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,203 +1,354 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { feature } from 'bun:bundle';
|
||||
import { APIUserAbortError } from '@anthropic-ai/sdk';
|
||||
import * as React from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js';
|
||||
import { sanitizeToolNameForAnalytics } from 'src/services/analytics/metadata.js';
|
||||
import type { ToolUseConfirm } from '../components/permissions/PermissionRequest.js';
|
||||
import { Text } from '../ink.js';
|
||||
import type { ToolPermissionContext, Tool as ToolType, ToolUseContext } from '../Tool.js';
|
||||
import { consumeSpeculativeClassifierCheck, peekSpeculativeClassifierCheck } from '../tools/BashTool/bashPermissions.js';
|
||||
import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js';
|
||||
import type { AssistantMessage } from '../types/message.js';
|
||||
import { recordAutoModeDenial } from '../utils/autoModeDenials.js';
|
||||
import { clearClassifierChecking, setClassifierApproval, setYoloClassifierApproval } from '../utils/classifierApprovals.js';
|
||||
import { logForDebugging } from '../utils/debug.js';
|
||||
import { AbortError } from '../utils/errors.js';
|
||||
import { logError } from '../utils/log.js';
|
||||
import type { PermissionDecision } from '../utils/permissions/PermissionResult.js';
|
||||
import { hasPermissionsToUseTool } from '../utils/permissions/permissions.js';
|
||||
import { jsonStringify } from '../utils/slowOperations.js';
|
||||
import { handleCoordinatorPermission } from './toolPermission/handlers/coordinatorHandler.js';
|
||||
import { handleInteractivePermission } from './toolPermission/handlers/interactiveHandler.js';
|
||||
import { handleSwarmWorkerPermission } from './toolPermission/handlers/swarmWorkerHandler.js';
|
||||
import { createPermissionContext, createPermissionQueueOps } from './toolPermission/PermissionContext.js';
|
||||
import { logPermissionDecision } from './toolPermission/permissionLogging.js';
|
||||
export type CanUseToolFn<Input extends Record<string, unknown> = Record<string, unknown>> = (tool: ToolType, input: Input, toolUseContext: ToolUseContext, assistantMessage: AssistantMessage, toolUseID: string, forceDecision?: PermissionDecision<Input>) => Promise<PermissionDecision<Input>>;
|
||||
function useCanUseTool(setToolUseConfirmQueue, setToolPermissionContext) {
|
||||
const $ = _c(3);
|
||||
let t0;
|
||||
if ($[0] !== setToolPermissionContext || $[1] !== setToolUseConfirmQueue) {
|
||||
t0 = async (tool, input, toolUseContext, assistantMessage, toolUseID, forceDecision) => new Promise(resolve => {
|
||||
const ctx = createPermissionContext(tool, input, toolUseContext, assistantMessage, toolUseID, setToolPermissionContext, createPermissionQueueOps(setToolUseConfirmQueue));
|
||||
if (ctx.resolveIfAborted(resolve)) {
|
||||
return;
|
||||
}
|
||||
const decisionPromise = forceDecision !== undefined ? Promise.resolve(forceDecision) : hasPermissionsToUseTool(tool, input, toolUseContext, assistantMessage, toolUseID);
|
||||
return decisionPromise.then(async result => {
|
||||
if (result.behavior === "allow") {
|
||||
if (ctx.resolveIfAborted(resolve)) {
|
||||
return;
|
||||
}
|
||||
if (feature("TRANSCRIPT_CLASSIFIER") && result.decisionReason?.type === "classifier" && result.decisionReason.classifier === "auto-mode") {
|
||||
setYoloClassifierApproval(toolUseID, result.decisionReason.reason);
|
||||
}
|
||||
ctx.logDecision({
|
||||
decision: "accept",
|
||||
source: "config"
|
||||
});
|
||||
resolve(ctx.buildAllow(result.updatedInput ?? input, {
|
||||
decisionReason: result.decisionReason
|
||||
}));
|
||||
return;
|
||||
}
|
||||
const appState = toolUseContext.getAppState();
|
||||
const description = await tool.description(input as never, {
|
||||
isNonInteractiveSession: toolUseContext.options.isNonInteractiveSession,
|
||||
toolPermissionContext: appState.toolPermissionContext,
|
||||
tools: toolUseContext.options.tools
|
||||
});
|
||||
if (ctx.resolveIfAborted(resolve)) {
|
||||
return;
|
||||
}
|
||||
switch (result.behavior) {
|
||||
case "deny":
|
||||
{
|
||||
logPermissionDecision({
|
||||
import { feature } from 'bun:bundle'
|
||||
import { APIUserAbortError } from '@anthropic-ai/sdk'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from 'src/services/analytics/index.js'
|
||||
import { sanitizeToolNameForAnalytics } from 'src/services/analytics/metadata.js'
|
||||
import type { ToolUseConfirm } from '../components/permissions/PermissionRequest.js'
|
||||
import { Text } from '../ink.js'
|
||||
import type {
|
||||
ToolPermissionContext,
|
||||
Tool as ToolType,
|
||||
ToolUseContext,
|
||||
} from '../Tool.js'
|
||||
import {
|
||||
consumeSpeculativeClassifierCheck,
|
||||
peekSpeculativeClassifierCheck,
|
||||
} from '../tools/BashTool/bashPermissions.js'
|
||||
import { BASH_TOOL_NAME } from '../tools/BashTool/toolName.js'
|
||||
import type { AssistantMessage } from '../types/message.js'
|
||||
import { recordAutoModeDenial } from '../utils/autoModeDenials.js'
|
||||
import {
|
||||
clearClassifierChecking,
|
||||
setClassifierApproval,
|
||||
setYoloClassifierApproval,
|
||||
} from '../utils/classifierApprovals.js'
|
||||
import { logForDebugging } from '../utils/debug.js'
|
||||
import { AbortError } from '../utils/errors.js'
|
||||
import { logError } from '../utils/log.js'
|
||||
import type { PermissionDecision } from '../utils/permissions/PermissionResult.js'
|
||||
import { hasPermissionsToUseTool } from '../utils/permissions/permissions.js'
|
||||
import { jsonStringify } from '../utils/slowOperations.js'
|
||||
import { handleCoordinatorPermission } from './toolPermission/handlers/coordinatorHandler.js'
|
||||
import { handleInteractivePermission } from './toolPermission/handlers/interactiveHandler.js'
|
||||
import { handleSwarmWorkerPermission } from './toolPermission/handlers/swarmWorkerHandler.js'
|
||||
import {
|
||||
createPermissionContext,
|
||||
createPermissionQueueOps,
|
||||
} from './toolPermission/PermissionContext.js'
|
||||
import { logPermissionDecision } from './toolPermission/permissionLogging.js'
|
||||
|
||||
export type CanUseToolFn<
|
||||
Input extends Record<string, unknown> = Record<string, unknown>,
|
||||
> = (
|
||||
tool: ToolType,
|
||||
input: Input,
|
||||
toolUseContext: ToolUseContext,
|
||||
assistantMessage: AssistantMessage,
|
||||
toolUseID: string,
|
||||
forceDecision?: PermissionDecision<Input>,
|
||||
) => Promise<PermissionDecision<Input>>
|
||||
|
||||
function useCanUseTool(
|
||||
setToolUseConfirmQueue: React.Dispatch<
|
||||
React.SetStateAction<ToolUseConfirm[]>
|
||||
>,
|
||||
setToolPermissionContext: (context: ToolPermissionContext) => void,
|
||||
): CanUseToolFn {
|
||||
return useCallback<CanUseToolFn>(
|
||||
async (
|
||||
tool,
|
||||
input,
|
||||
toolUseContext,
|
||||
assistantMessage,
|
||||
toolUseID,
|
||||
forceDecision,
|
||||
) => {
|
||||
return new Promise(resolve => {
|
||||
const ctx = createPermissionContext(
|
||||
tool,
|
||||
input,
|
||||
toolUseContext,
|
||||
assistantMessage,
|
||||
toolUseID,
|
||||
setToolPermissionContext,
|
||||
createPermissionQueueOps(setToolUseConfirmQueue),
|
||||
)
|
||||
|
||||
if (ctx.resolveIfAborted(resolve)) return
|
||||
|
||||
const decisionPromise =
|
||||
forceDecision !== undefined
|
||||
? Promise.resolve(forceDecision)
|
||||
: hasPermissionsToUseTool(
|
||||
tool,
|
||||
input,
|
||||
toolUseContext,
|
||||
messageId: ctx.messageId,
|
||||
toolUseID
|
||||
}, {
|
||||
decision: "reject",
|
||||
source: "config"
|
||||
});
|
||||
if (feature("TRANSCRIPT_CLASSIFIER") && result.decisionReason?.type === "classifier" && result.decisionReason.classifier === "auto-mode") {
|
||||
recordAutoModeDenial({
|
||||
toolName: tool.name,
|
||||
display: description,
|
||||
reason: result.decisionReason.reason ?? "",
|
||||
timestamp: Date.now()
|
||||
});
|
||||
toolUseContext.addNotification?.({
|
||||
key: "auto-mode-denied",
|
||||
priority: "immediate",
|
||||
jsx: <><Text color="error">{tool.userFacingName(input).toLowerCase()} denied by auto mode</Text><Text dimColor={true}> · /permissions</Text></>
|
||||
});
|
||||
}
|
||||
resolve(result);
|
||||
return;
|
||||
assistantMessage,
|
||||
toolUseID,
|
||||
)
|
||||
|
||||
return decisionPromise
|
||||
.then(async result => {
|
||||
// [ANT-ONLY] Log all tool permission decisions with tool name and args
|
||||
if (process.env.USER_TYPE === 'ant') {
|
||||
logEvent('tengu_internal_tool_permission_decision', {
|
||||
toolName: sanitizeToolNameForAnalytics(tool.name),
|
||||
behavior:
|
||||
result.behavior as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
// Note: input contains code/filepaths, only log for ants
|
||||
input: jsonStringify(
|
||||
input,
|
||||
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
messageID:
|
||||
ctx.messageId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
isMcp: tool.isMcp ?? false,
|
||||
})
|
||||
}
|
||||
case "ask":
|
||||
{
|
||||
if (appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog) {
|
||||
const coordinatorDecision = await handleCoordinatorPermission({
|
||||
|
||||
// Has permissions to use tool, granted in config
|
||||
if (result.behavior === 'allow') {
|
||||
if (ctx.resolveIfAborted(resolve)) return
|
||||
// Track auto mode classifier approvals for UI display
|
||||
if (
|
||||
feature('TRANSCRIPT_CLASSIFIER') &&
|
||||
result.decisionReason?.type === 'classifier' &&
|
||||
result.decisionReason.classifier === 'auto-mode'
|
||||
) {
|
||||
setYoloClassifierApproval(
|
||||
toolUseID,
|
||||
result.decisionReason.reason,
|
||||
)
|
||||
}
|
||||
|
||||
ctx.logDecision({ decision: 'accept', source: 'config' })
|
||||
|
||||
resolve(
|
||||
ctx.buildAllow(result.updatedInput ?? input, {
|
||||
decisionReason: result.decisionReason,
|
||||
}),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const appState = toolUseContext.getAppState()
|
||||
const description = await tool.description(input as never, {
|
||||
isNonInteractiveSession:
|
||||
toolUseContext.options.isNonInteractiveSession,
|
||||
toolPermissionContext: appState.toolPermissionContext,
|
||||
tools: toolUseContext.options.tools,
|
||||
})
|
||||
|
||||
if (ctx.resolveIfAborted(resolve)) return
|
||||
|
||||
// Does not have permissions to use tool, check the behavior
|
||||
switch (result.behavior) {
|
||||
case 'deny': {
|
||||
logPermissionDecision(
|
||||
{
|
||||
tool,
|
||||
input,
|
||||
toolUseContext,
|
||||
messageId: ctx.messageId,
|
||||
toolUseID,
|
||||
},
|
||||
{ decision: 'reject', source: 'config' },
|
||||
)
|
||||
if (
|
||||
feature('TRANSCRIPT_CLASSIFIER') &&
|
||||
result.decisionReason?.type === 'classifier' &&
|
||||
result.decisionReason.classifier === 'auto-mode'
|
||||
) {
|
||||
recordAutoModeDenial({
|
||||
toolName: tool.name,
|
||||
display: description,
|
||||
reason: result.decisionReason.reason ?? '',
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
toolUseContext.addNotification?.({
|
||||
key: 'auto-mode-denied',
|
||||
priority: 'immediate',
|
||||
jsx: (
|
||||
<>
|
||||
<Text color="error">
|
||||
{tool.userFacingName(input).toLowerCase()} denied by
|
||||
auto mode
|
||||
</Text>
|
||||
<Text dimColor> · /permissions</Text>
|
||||
</>
|
||||
),
|
||||
})
|
||||
}
|
||||
resolve(result)
|
||||
return
|
||||
}
|
||||
|
||||
case 'ask': {
|
||||
// For coordinator workers, await automated checks before showing dialog.
|
||||
// Background workers should only interrupt the user when automated checks can't decide.
|
||||
if (
|
||||
appState.toolPermissionContext
|
||||
.awaitAutomatedChecksBeforeDialog
|
||||
) {
|
||||
const coordinatorDecision = await handleCoordinatorPermission(
|
||||
{
|
||||
ctx,
|
||||
...(feature('BASH_CLASSIFIER')
|
||||
? {
|
||||
pendingClassifierCheck:
|
||||
result.pendingClassifierCheck,
|
||||
}
|
||||
: {}),
|
||||
updatedInput: result.updatedInput,
|
||||
suggestions: result.suggestions,
|
||||
permissionMode: appState.toolPermissionContext.mode,
|
||||
},
|
||||
)
|
||||
if (coordinatorDecision) {
|
||||
resolve(coordinatorDecision)
|
||||
return
|
||||
}
|
||||
// null means neither automated check resolved -- fall through to dialog below.
|
||||
// Hooks already ran, classifier already consumed.
|
||||
}
|
||||
|
||||
// After awaiting automated checks, verify the request wasn't aborted
|
||||
// while we were waiting. Without this check, a stale dialog could appear.
|
||||
if (ctx.resolveIfAborted(resolve)) return
|
||||
|
||||
// For swarm workers, try classifier auto-approval then
|
||||
// forward permission requests to the leader via mailbox.
|
||||
const swarmDecision = await handleSwarmWorkerPermission({
|
||||
ctx,
|
||||
...(feature("BASH_CLASSIFIER") ? {
|
||||
pendingClassifierCheck: result.pendingClassifierCheck
|
||||
} : {}),
|
||||
description,
|
||||
...(feature('BASH_CLASSIFIER')
|
||||
? {
|
||||
pendingClassifierCheck: result.pendingClassifierCheck,
|
||||
}
|
||||
: {}),
|
||||
updatedInput: result.updatedInput,
|
||||
suggestions: result.suggestions,
|
||||
permissionMode: appState.toolPermissionContext.mode
|
||||
});
|
||||
if (coordinatorDecision) {
|
||||
resolve(coordinatorDecision);
|
||||
return;
|
||||
})
|
||||
if (swarmDecision) {
|
||||
resolve(swarmDecision)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (ctx.resolveIfAborted(resolve)) {
|
||||
return;
|
||||
}
|
||||
const swarmDecision = await handleSwarmWorkerPermission({
|
||||
ctx,
|
||||
description,
|
||||
...(feature("BASH_CLASSIFIER") ? {
|
||||
pendingClassifierCheck: result.pendingClassifierCheck
|
||||
} : {}),
|
||||
updatedInput: result.updatedInput,
|
||||
suggestions: result.suggestions
|
||||
});
|
||||
if (swarmDecision) {
|
||||
resolve(swarmDecision);
|
||||
return;
|
||||
}
|
||||
if (feature("BASH_CLASSIFIER") && result.pendingClassifierCheck && tool.name === BASH_TOOL_NAME && !appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog) {
|
||||
const speculativePromise = peekSpeculativeClassifierCheck((input as {
|
||||
command: string;
|
||||
}).command);
|
||||
if (speculativePromise) {
|
||||
const raceResult = await Promise.race([speculativePromise.then(_temp), new Promise(_temp2)]);
|
||||
if (ctx.resolveIfAborted(resolve)) {
|
||||
return;
|
||||
}
|
||||
if ((raceResult as any).type === "result" && (raceResult as any).result.matches && (raceResult as any).result.confidence === "high" && feature("BASH_CLASSIFIER")) {
|
||||
consumeSpeculativeClassifierCheck((input as {
|
||||
command: string;
|
||||
}).command);
|
||||
const matchedRule = (raceResult as any).result.matchedDescription ?? undefined;
|
||||
if (matchedRule) {
|
||||
setClassifierApproval(toolUseID, matchedRule);
|
||||
|
||||
// Grace period: wait up to 2s for speculative classifier
|
||||
// to resolve before showing the dialog (main agent only)
|
||||
if (
|
||||
feature('BASH_CLASSIFIER') &&
|
||||
result.pendingClassifierCheck &&
|
||||
tool.name === BASH_TOOL_NAME &&
|
||||
!appState.toolPermissionContext
|
||||
.awaitAutomatedChecksBeforeDialog
|
||||
) {
|
||||
const speculativePromise = peekSpeculativeClassifierCheck(
|
||||
(input as { command: string }).command,
|
||||
)
|
||||
if (speculativePromise) {
|
||||
const raceResult = await Promise.race([
|
||||
speculativePromise.then(r => ({
|
||||
type: 'result' as const,
|
||||
result: r,
|
||||
})),
|
||||
new Promise<{ type: 'timeout' }>(res =>
|
||||
// eslint-disable-next-line no-restricted-syntax -- resolves with a value, not void
|
||||
setTimeout(res, 2000, { type: 'timeout' as const }),
|
||||
),
|
||||
])
|
||||
|
||||
if (ctx.resolveIfAborted(resolve)) return
|
||||
|
||||
if (
|
||||
raceResult.type === 'result' &&
|
||||
raceResult.result.matches &&
|
||||
raceResult.result.confidence === 'high' &&
|
||||
feature('BASH_CLASSIFIER')
|
||||
) {
|
||||
// Classifier approved within grace period — skip dialog
|
||||
void consumeSpeculativeClassifierCheck(
|
||||
(input as { command: string }).command,
|
||||
)
|
||||
|
||||
const matchedRule =
|
||||
raceResult.result.matchedDescription ?? undefined
|
||||
if (matchedRule) {
|
||||
setClassifierApproval(toolUseID, matchedRule)
|
||||
}
|
||||
|
||||
ctx.logDecision({
|
||||
decision: 'accept',
|
||||
source: { type: 'classifier' },
|
||||
})
|
||||
resolve(
|
||||
ctx.buildAllow(
|
||||
result.updatedInput ??
|
||||
(input as Record<string, unknown>),
|
||||
{
|
||||
decisionReason: {
|
||||
type: 'classifier' as const,
|
||||
classifier: 'bash_allow' as const,
|
||||
reason: `Allowed by prompt rule: "${raceResult.result.matchedDescription}"`,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
ctx.logDecision({
|
||||
decision: "accept",
|
||||
source: {
|
||||
type: "classifier"
|
||||
}
|
||||
});
|
||||
resolve(ctx.buildAllow(result.updatedInput ?? input as Record<string, unknown>, {
|
||||
decisionReason: {
|
||||
type: "classifier" as const,
|
||||
classifier: "bash_allow" as const,
|
||||
reason: `Allowed by prompt rule: "${(raceResult as any).result.matchedDescription}"`
|
||||
}
|
||||
}));
|
||||
return;
|
||||
// Timeout or no match — fall through to show dialog
|
||||
}
|
||||
}
|
||||
|
||||
// Show dialog and start hooks/classifier in background
|
||||
handleInteractivePermission(
|
||||
{
|
||||
ctx,
|
||||
description,
|
||||
result,
|
||||
awaitAutomatedChecksBeforeDialog:
|
||||
appState.toolPermissionContext
|
||||
.awaitAutomatedChecksBeforeDialog,
|
||||
bridgeCallbacks: feature('BRIDGE_MODE')
|
||||
? appState.replBridgePermissionCallbacks
|
||||
: undefined,
|
||||
channelCallbacks:
|
||||
feature('KAIROS') || feature('KAIROS_CHANNELS')
|
||||
? appState.channelPermissionCallbacks
|
||||
: undefined,
|
||||
},
|
||||
resolve,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
handleInteractivePermission({
|
||||
ctx,
|
||||
description,
|
||||
result,
|
||||
awaitAutomatedChecksBeforeDialog: appState.toolPermissionContext.awaitAutomatedChecksBeforeDialog,
|
||||
bridgeCallbacks: feature("BRIDGE_MODE") ? appState.replBridgePermissionCallbacks : undefined,
|
||||
channelCallbacks: feature("KAIROS") || feature("KAIROS_CHANNELS") ? appState.channelPermissionCallbacks : undefined
|
||||
}, resolve);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
if (error instanceof AbortError || error instanceof APIUserAbortError) {
|
||||
logForDebugging(`Permission check threw ${error.constructor.name} for tool=${tool.name}: ${error.message}`);
|
||||
ctx.logCancelled();
|
||||
resolve(ctx.cancelAndAbort(undefined, true));
|
||||
} else {
|
||||
logError(error);
|
||||
resolve(ctx.cancelAndAbort(undefined, true));
|
||||
}
|
||||
}).finally(() => {
|
||||
clearClassifierChecking(toolUseID);
|
||||
});
|
||||
});
|
||||
$[0] = setToolPermissionContext;
|
||||
$[1] = setToolUseConfirmQueue;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
})
|
||||
.catch(error => {
|
||||
if (
|
||||
error instanceof AbortError ||
|
||||
error instanceof APIUserAbortError
|
||||
) {
|
||||
logForDebugging(
|
||||
`Permission check threw ${error.constructor.name} for tool=${tool.name}: ${error.message}`,
|
||||
)
|
||||
ctx.logCancelled()
|
||||
resolve(ctx.cancelAndAbort(undefined, true))
|
||||
} else {
|
||||
logError(error)
|
||||
resolve(ctx.cancelAndAbort(undefined, true))
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
clearClassifierChecking(toolUseID)
|
||||
})
|
||||
})
|
||||
},
|
||||
[setToolUseConfirmQueue, setToolPermissionContext],
|
||||
)
|
||||
}
|
||||
function _temp2(res) {
|
||||
return setTimeout(res, 2000, {
|
||||
type: "timeout" as const
|
||||
});
|
||||
}
|
||||
function _temp(r) {
|
||||
return {
|
||||
type: "result" as const,
|
||||
result: r
|
||||
};
|
||||
}
|
||||
export default useCanUseTool;
|
||||
|
||||
export default useCanUseTool
|
||||
|
||||
Reference in New Issue
Block a user