@shareai-lab/kode 1.1.13 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entrypoints/cli.js +2 -1
- package/dist/entrypoints/cli.js.map +2 -2
- package/dist/index.js +5 -26
- package/dist/package.json +4 -1
- package/package.json +9 -104
- package/dist/test/testAdapters.js +0 -88
- package/dist/test/testAdapters.js.map +0 -1
- package/src/ProjectOnboarding.tsx +0 -198
- package/src/Tool.ts +0 -83
- package/src/commands/agents.tsx +0 -3416
- package/src/commands/approvedTools.ts +0 -53
- package/src/commands/bug.tsx +0 -20
- package/src/commands/clear.ts +0 -43
- package/src/commands/compact.ts +0 -120
- package/src/commands/config.tsx +0 -19
- package/src/commands/cost.ts +0 -18
- package/src/commands/ctx_viz.ts +0 -209
- package/src/commands/doctor.ts +0 -24
- package/src/commands/help.tsx +0 -19
- package/src/commands/init.ts +0 -37
- package/src/commands/listen.ts +0 -42
- package/src/commands/login.tsx +0 -51
- package/src/commands/logout.tsx +0 -40
- package/src/commands/mcp.ts +0 -41
- package/src/commands/model.tsx +0 -40
- package/src/commands/modelstatus.tsx +0 -20
- package/src/commands/onboarding.tsx +0 -34
- package/src/commands/pr_comments.ts +0 -59
- package/src/commands/refreshCommands.ts +0 -54
- package/src/commands/release-notes.ts +0 -34
- package/src/commands/resume.tsx +0 -31
- package/src/commands/review.ts +0 -49
- package/src/commands/terminalSetup.ts +0 -221
- package/src/commands.ts +0 -139
- package/src/components/ApproveApiKey.tsx +0 -93
- package/src/components/AsciiLogo.tsx +0 -13
- package/src/components/AutoUpdater.tsx +0 -148
- package/src/components/Bug.tsx +0 -367
- package/src/components/Config.tsx +0 -293
- package/src/components/ConsoleOAuthFlow.tsx +0 -327
- package/src/components/Cost.tsx +0 -23
- package/src/components/CostThresholdDialog.tsx +0 -46
- package/src/components/CustomSelect/option-map.ts +0 -42
- package/src/components/CustomSelect/select-option.tsx +0 -78
- package/src/components/CustomSelect/select.tsx +0 -152
- package/src/components/CustomSelect/theme.ts +0 -45
- package/src/components/CustomSelect/use-select-state.ts +0 -414
- package/src/components/CustomSelect/use-select.ts +0 -35
- package/src/components/FallbackToolUseRejectedMessage.tsx +0 -15
- package/src/components/FileEditToolUpdatedMessage.tsx +0 -66
- package/src/components/Help.tsx +0 -215
- package/src/components/HighlightedCode.tsx +0 -33
- package/src/components/InvalidConfigDialog.tsx +0 -113
- package/src/components/Link.tsx +0 -32
- package/src/components/LogSelector.tsx +0 -86
- package/src/components/Logo.tsx +0 -170
- package/src/components/MCPServerApprovalDialog.tsx +0 -100
- package/src/components/MCPServerDialogCopy.tsx +0 -25
- package/src/components/MCPServerMultiselectDialog.tsx +0 -109
- package/src/components/Message.tsx +0 -221
- package/src/components/MessageResponse.tsx +0 -15
- package/src/components/MessageSelector.tsx +0 -211
- package/src/components/ModeIndicator.tsx +0 -88
- package/src/components/ModelConfig.tsx +0 -301
- package/src/components/ModelListManager.tsx +0 -227
- package/src/components/ModelSelector.tsx +0 -3387
- package/src/components/ModelStatusDisplay.tsx +0 -230
- package/src/components/Onboarding.tsx +0 -274
- package/src/components/PressEnterToContinue.tsx +0 -11
- package/src/components/PromptInput.tsx +0 -760
- package/src/components/SentryErrorBoundary.ts +0 -39
- package/src/components/Spinner.tsx +0 -129
- package/src/components/StickerRequestForm.tsx +0 -16
- package/src/components/StructuredDiff.tsx +0 -191
- package/src/components/TextInput.tsx +0 -259
- package/src/components/TodoItem.tsx +0 -47
- package/src/components/TokenWarning.tsx +0 -31
- package/src/components/ToolUseLoader.tsx +0 -40
- package/src/components/TrustDialog.tsx +0 -106
- package/src/components/binary-feedback/BinaryFeedback.tsx +0 -63
- package/src/components/binary-feedback/BinaryFeedbackOption.tsx +0 -111
- package/src/components/binary-feedback/BinaryFeedbackView.tsx +0 -172
- package/src/components/binary-feedback/utils.ts +0 -220
- package/src/components/messages/AssistantBashOutputMessage.tsx +0 -22
- package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +0 -49
- package/src/components/messages/AssistantRedactedThinkingMessage.tsx +0 -19
- package/src/components/messages/AssistantTextMessage.tsx +0 -144
- package/src/components/messages/AssistantThinkingMessage.tsx +0 -40
- package/src/components/messages/AssistantToolUseMessage.tsx +0 -132
- package/src/components/messages/TaskProgressMessage.tsx +0 -32
- package/src/components/messages/TaskToolMessage.tsx +0 -58
- package/src/components/messages/UserBashInputMessage.tsx +0 -28
- package/src/components/messages/UserCommandMessage.tsx +0 -30
- package/src/components/messages/UserKodingInputMessage.tsx +0 -28
- package/src/components/messages/UserPromptMessage.tsx +0 -35
- package/src/components/messages/UserTextMessage.tsx +0 -39
- package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +0 -12
- package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +0 -36
- package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +0 -31
- package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +0 -57
- package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +0 -35
- package/src/components/messages/UserToolResultMessage/utils.tsx +0 -56
- package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +0 -121
- package/src/components/permissions/FallbackPermissionRequest.tsx +0 -153
- package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +0 -182
- package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +0 -77
- package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +0 -164
- package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +0 -83
- package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +0 -240
- package/src/components/permissions/PermissionRequest.tsx +0 -101
- package/src/components/permissions/PermissionRequestTitle.tsx +0 -69
- package/src/components/permissions/hooks.ts +0 -44
- package/src/components/permissions/toolUseOptions.ts +0 -59
- package/src/components/permissions/utils.ts +0 -23
- package/src/constants/betas.ts +0 -5
- package/src/constants/claude-asterisk-ascii-art.tsx +0 -238
- package/src/constants/figures.ts +0 -4
- package/src/constants/keys.ts +0 -3
- package/src/constants/macros.ts +0 -11
- package/src/constants/modelCapabilities.ts +0 -179
- package/src/constants/models.ts +0 -1025
- package/src/constants/oauth.ts +0 -18
- package/src/constants/product.ts +0 -17
- package/src/constants/prompts.ts +0 -168
- package/src/constants/releaseNotes.ts +0 -7
- package/src/context/PermissionContext.tsx +0 -149
- package/src/context.ts +0 -278
- package/src/cost-tracker.ts +0 -84
- package/src/entrypoints/cli.tsx +0 -1561
- package/src/entrypoints/mcp.ts +0 -175
- package/src/history.ts +0 -25
- package/src/hooks/useApiKeyVerification.ts +0 -59
- package/src/hooks/useArrowKeyHistory.ts +0 -55
- package/src/hooks/useCanUseTool.ts +0 -138
- package/src/hooks/useCancelRequest.ts +0 -39
- package/src/hooks/useDoublePress.ts +0 -41
- package/src/hooks/useExitOnCtrlCD.ts +0 -31
- package/src/hooks/useInterval.ts +0 -25
- package/src/hooks/useLogMessages.ts +0 -16
- package/src/hooks/useLogStartupTime.ts +0 -12
- package/src/hooks/useNotifyAfterTimeout.ts +0 -65
- package/src/hooks/usePermissionRequestLogging.ts +0 -44
- package/src/hooks/useTerminalSize.ts +0 -49
- package/src/hooks/useTextInput.ts +0 -317
- package/src/hooks/useUnifiedCompletion.ts +0 -1405
- package/src/index.ts +0 -34
- package/src/messages.ts +0 -38
- package/src/permissions.ts +0 -268
- package/src/query.ts +0 -720
- package/src/screens/ConfigureNpmPrefix.tsx +0 -197
- package/src/screens/Doctor.tsx +0 -219
- package/src/screens/LogList.tsx +0 -68
- package/src/screens/REPL.tsx +0 -813
- package/src/screens/ResumeConversation.tsx +0 -68
- package/src/services/adapters/base.ts +0 -38
- package/src/services/adapters/chatCompletions.ts +0 -90
- package/src/services/adapters/responsesAPI.ts +0 -170
- package/src/services/browserMocks.ts +0 -66
- package/src/services/claude.ts +0 -2197
- package/src/services/customCommands.ts +0 -704
- package/src/services/fileFreshness.ts +0 -377
- package/src/services/gpt5ConnectionTest.ts +0 -340
- package/src/services/mcpClient.ts +0 -564
- package/src/services/mcpServerApproval.tsx +0 -50
- package/src/services/mentionProcessor.ts +0 -273
- package/src/services/modelAdapterFactory.ts +0 -69
- package/src/services/notifier.ts +0 -40
- package/src/services/oauth.ts +0 -357
- package/src/services/openai.ts +0 -1359
- package/src/services/responseStateManager.ts +0 -90
- package/src/services/sentry.ts +0 -3
- package/src/services/statsig.ts +0 -172
- package/src/services/statsigStorage.ts +0 -86
- package/src/services/systemReminder.ts +0 -507
- package/src/services/vcr.ts +0 -161
- package/src/test/testAdapters.ts +0 -96
- package/src/tools/ArchitectTool/ArchitectTool.tsx +0 -135
- package/src/tools/ArchitectTool/prompt.ts +0 -15
- package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +0 -576
- package/src/tools/BashTool/BashTool.tsx +0 -243
- package/src/tools/BashTool/BashToolResultMessage.tsx +0 -38
- package/src/tools/BashTool/OutputLine.tsx +0 -49
- package/src/tools/BashTool/prompt.ts +0 -174
- package/src/tools/BashTool/utils.ts +0 -56
- package/src/tools/FileEditTool/FileEditTool.tsx +0 -319
- package/src/tools/FileEditTool/prompt.ts +0 -51
- package/src/tools/FileEditTool/utils.ts +0 -58
- package/src/tools/FileReadTool/FileReadTool.tsx +0 -404
- package/src/tools/FileReadTool/prompt.ts +0 -7
- package/src/tools/FileWriteTool/FileWriteTool.tsx +0 -301
- package/src/tools/FileWriteTool/prompt.ts +0 -10
- package/src/tools/GlobTool/GlobTool.tsx +0 -119
- package/src/tools/GlobTool/prompt.ts +0 -8
- package/src/tools/GrepTool/GrepTool.tsx +0 -147
- package/src/tools/GrepTool/prompt.ts +0 -11
- package/src/tools/MCPTool/MCPTool.tsx +0 -107
- package/src/tools/MCPTool/prompt.ts +0 -3
- package/src/tools/MemoryReadTool/MemoryReadTool.tsx +0 -127
- package/src/tools/MemoryReadTool/prompt.ts +0 -3
- package/src/tools/MemoryWriteTool/MemoryWriteTool.tsx +0 -89
- package/src/tools/MemoryWriteTool/prompt.ts +0 -3
- package/src/tools/MultiEditTool/MultiEditTool.tsx +0 -388
- package/src/tools/MultiEditTool/prompt.ts +0 -45
- package/src/tools/NotebookEditTool/NotebookEditTool.tsx +0 -298
- package/src/tools/NotebookEditTool/prompt.ts +0 -3
- package/src/tools/NotebookReadTool/NotebookReadTool.tsx +0 -258
- package/src/tools/NotebookReadTool/prompt.ts +0 -3
- package/src/tools/StickerRequestTool/StickerRequestTool.tsx +0 -107
- package/src/tools/StickerRequestTool/prompt.ts +0 -19
- package/src/tools/TaskTool/TaskTool.tsx +0 -438
- package/src/tools/TaskTool/constants.ts +0 -1
- package/src/tools/TaskTool/prompt.ts +0 -92
- package/src/tools/ThinkTool/ThinkTool.tsx +0 -54
- package/src/tools/ThinkTool/prompt.ts +0 -12
- package/src/tools/TodoWriteTool/TodoWriteTool.tsx +0 -313
- package/src/tools/TodoWriteTool/prompt.ts +0 -63
- package/src/tools/URLFetcherTool/URLFetcherTool.tsx +0 -178
- package/src/tools/URLFetcherTool/cache.ts +0 -55
- package/src/tools/URLFetcherTool/htmlToMarkdown.ts +0 -55
- package/src/tools/URLFetcherTool/prompt.ts +0 -17
- package/src/tools/WebSearchTool/WebSearchTool.tsx +0 -103
- package/src/tools/WebSearchTool/prompt.ts +0 -13
- package/src/tools/WebSearchTool/searchProviders.ts +0 -66
- package/src/tools/lsTool/lsTool.tsx +0 -272
- package/src/tools/lsTool/prompt.ts +0 -2
- package/src/tools.ts +0 -67
- package/src/types/PermissionMode.ts +0 -120
- package/src/types/RequestContext.ts +0 -72
- package/src/types/common.d.ts +0 -2
- package/src/types/conversation.ts +0 -51
- package/src/types/logs.ts +0 -58
- package/src/types/modelCapabilities.ts +0 -64
- package/src/types/notebook.ts +0 -87
- package/src/utils/Cursor.ts +0 -436
- package/src/utils/PersistentShell.ts +0 -552
- package/src/utils/advancedFuzzyMatcher.ts +0 -290
- package/src/utils/agentLoader.ts +0 -278
- package/src/utils/agentStorage.ts +0 -97
- package/src/utils/array.ts +0 -3
- package/src/utils/ask.tsx +0 -99
- package/src/utils/auth.ts +0 -13
- package/src/utils/autoCompactCore.ts +0 -223
- package/src/utils/autoUpdater.ts +0 -458
- package/src/utils/betas.ts +0 -20
- package/src/utils/browser.ts +0 -14
- package/src/utils/cleanup.ts +0 -72
- package/src/utils/commands.ts +0 -261
- package/src/utils/commonUnixCommands.ts +0 -161
- package/src/utils/config.ts +0 -945
- package/src/utils/conversationRecovery.ts +0 -55
- package/src/utils/debugLogger.ts +0 -1235
- package/src/utils/diff.ts +0 -42
- package/src/utils/env.ts +0 -57
- package/src/utils/errors.ts +0 -21
- package/src/utils/exampleCommands.ts +0 -109
- package/src/utils/execFileNoThrow.ts +0 -51
- package/src/utils/expertChatStorage.ts +0 -136
- package/src/utils/file.ts +0 -405
- package/src/utils/fileRecoveryCore.ts +0 -71
- package/src/utils/format.tsx +0 -44
- package/src/utils/fuzzyMatcher.ts +0 -328
- package/src/utils/generators.ts +0 -62
- package/src/utils/git.ts +0 -92
- package/src/utils/globalLogger.ts +0 -77
- package/src/utils/http.ts +0 -10
- package/src/utils/imagePaste.ts +0 -38
- package/src/utils/json.ts +0 -13
- package/src/utils/log.ts +0 -382
- package/src/utils/markdown.ts +0 -213
- package/src/utils/messageContextManager.ts +0 -294
- package/src/utils/messages.tsx +0 -945
- package/src/utils/model.ts +0 -914
- package/src/utils/permissions/filesystem.ts +0 -127
- package/src/utils/responseState.ts +0 -23
- package/src/utils/ripgrep.ts +0 -167
- package/src/utils/secureFile.ts +0 -564
- package/src/utils/sessionState.ts +0 -49
- package/src/utils/state.ts +0 -25
- package/src/utils/style.ts +0 -29
- package/src/utils/terminal.ts +0 -50
- package/src/utils/theme.ts +0 -127
- package/src/utils/thinking.ts +0 -144
- package/src/utils/todoStorage.ts +0 -431
- package/src/utils/tokens.ts +0 -43
- package/src/utils/toolExecutionController.ts +0 -163
- package/src/utils/unaryLogging.ts +0 -26
- package/src/utils/user.ts +0 -37
- package/src/utils/validate.ts +0 -165
package/src/query.ts
DELETED
|
@@ -1,720 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Message as APIAssistantMessage,
|
|
3
|
-
MessageParam,
|
|
4
|
-
ToolUseBlock,
|
|
5
|
-
} from '@anthropic-ai/sdk/resources/index.mjs'
|
|
6
|
-
import type { UUID } from './types/common'
|
|
7
|
-
import type { Tool, ToolUseContext } from './Tool'
|
|
8
|
-
import {
|
|
9
|
-
messagePairValidForBinaryFeedback,
|
|
10
|
-
shouldUseBinaryFeedback,
|
|
11
|
-
} from './components/binary-feedback/utils.js'
|
|
12
|
-
import { CanUseToolFn } from './hooks/useCanUseTool'
|
|
13
|
-
import {
|
|
14
|
-
formatSystemPromptWithContext,
|
|
15
|
-
queryLLM,
|
|
16
|
-
queryModel,
|
|
17
|
-
} from './services/claude.js'
|
|
18
|
-
import { emitReminderEvent } from './services/systemReminder'
|
|
19
|
-
import { logEvent } from './services/statsig'
|
|
20
|
-
import { all } from './utils/generators'
|
|
21
|
-
import { logError } from './utils/log'
|
|
22
|
-
import {
|
|
23
|
-
debug as debugLogger,
|
|
24
|
-
markPhase,
|
|
25
|
-
getCurrentRequest,
|
|
26
|
-
logUserFriendly,
|
|
27
|
-
} from './utils/debugLogger'
|
|
28
|
-
import { getModelManager } from './utils/model.js'
|
|
29
|
-
import {
|
|
30
|
-
createAssistantMessage,
|
|
31
|
-
createProgressMessage,
|
|
32
|
-
createToolResultStopMessage,
|
|
33
|
-
createUserMessage,
|
|
34
|
-
FullToolUseResult,
|
|
35
|
-
INTERRUPT_MESSAGE,
|
|
36
|
-
INTERRUPT_MESSAGE_FOR_TOOL_USE,
|
|
37
|
-
NormalizedMessage,
|
|
38
|
-
normalizeMessagesForAPI,
|
|
39
|
-
} from './utils/messages.js'
|
|
40
|
-
import { createToolExecutionController } from './utils/toolExecutionController'
|
|
41
|
-
import { BashTool } from './tools/BashTool/BashTool'
|
|
42
|
-
import { getCwd } from './utils/state'
|
|
43
|
-
import { checkAutoCompact } from './utils/autoCompactCore'
|
|
44
|
-
|
|
45
|
-
// Extended ToolUseContext for query functions
|
|
46
|
-
interface ExtendedToolUseContext extends ToolUseContext {
|
|
47
|
-
abortController: AbortController
|
|
48
|
-
options: {
|
|
49
|
-
commands: any[]
|
|
50
|
-
forkNumber: number
|
|
51
|
-
messageLogName: string
|
|
52
|
-
tools: Tool[]
|
|
53
|
-
verbose: boolean
|
|
54
|
-
safeMode: boolean
|
|
55
|
-
maxThinkingTokens: number
|
|
56
|
-
isKodingRequest?: boolean
|
|
57
|
-
model?: string | import('./utils/config').ModelPointerType
|
|
58
|
-
}
|
|
59
|
-
readFileTimestamps: { [filename: string]: number }
|
|
60
|
-
setToolJSX: (jsx: any) => void
|
|
61
|
-
requestId?: string
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export type Response = { costUSD: number; response: string }
|
|
65
|
-
export type UserMessage = {
|
|
66
|
-
message: MessageParam
|
|
67
|
-
type: 'user'
|
|
68
|
-
uuid: UUID
|
|
69
|
-
toolUseResult?: FullToolUseResult
|
|
70
|
-
options?: {
|
|
71
|
-
isKodingRequest?: boolean
|
|
72
|
-
kodingContext?: string
|
|
73
|
-
isCustomCommand?: boolean
|
|
74
|
-
commandName?: string
|
|
75
|
-
commandArgs?: string
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type AssistantMessage = {
|
|
80
|
-
costUSD: number
|
|
81
|
-
durationMs: number
|
|
82
|
-
message: APIAssistantMessage
|
|
83
|
-
type: 'assistant'
|
|
84
|
-
uuid: UUID
|
|
85
|
-
isApiErrorMessage?: boolean
|
|
86
|
-
responseId?: string // For GPT-5 Responses API state management
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export type BinaryFeedbackResult =
|
|
90
|
-
| { message: AssistantMessage | null; shouldSkipPermissionCheck: false }
|
|
91
|
-
| { message: AssistantMessage; shouldSkipPermissionCheck: true }
|
|
92
|
-
|
|
93
|
-
export type ProgressMessage = {
|
|
94
|
-
content: AssistantMessage
|
|
95
|
-
normalizedMessages: NormalizedMessage[]
|
|
96
|
-
siblingToolUseIDs: Set<string>
|
|
97
|
-
tools: Tool[]
|
|
98
|
-
toolUseID: string
|
|
99
|
-
type: 'progress'
|
|
100
|
-
uuid: UUID
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Each array item is either a single message or a message-and-response pair
|
|
104
|
-
export type Message = UserMessage | AssistantMessage | ProgressMessage
|
|
105
|
-
|
|
106
|
-
const MAX_TOOL_USE_CONCURRENCY = 10
|
|
107
|
-
|
|
108
|
-
// Returns a message if we got one, or `null` if the user cancelled
|
|
109
|
-
async function queryWithBinaryFeedback(
|
|
110
|
-
toolUseContext: ExtendedToolUseContext,
|
|
111
|
-
getAssistantResponse: () => Promise<AssistantMessage>,
|
|
112
|
-
getBinaryFeedbackResponse?: (
|
|
113
|
-
m1: AssistantMessage,
|
|
114
|
-
m2: AssistantMessage,
|
|
115
|
-
) => Promise<BinaryFeedbackResult>,
|
|
116
|
-
): Promise<BinaryFeedbackResult> {
|
|
117
|
-
if (
|
|
118
|
-
process.env.USER_TYPE !== 'ant' ||
|
|
119
|
-
!getBinaryFeedbackResponse ||
|
|
120
|
-
!(await shouldUseBinaryFeedback())
|
|
121
|
-
) {
|
|
122
|
-
const assistantMessage = await getAssistantResponse()
|
|
123
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
124
|
-
return { message: null, shouldSkipPermissionCheck: false }
|
|
125
|
-
}
|
|
126
|
-
return { message: assistantMessage, shouldSkipPermissionCheck: false }
|
|
127
|
-
}
|
|
128
|
-
const [m1, m2] = await Promise.all([
|
|
129
|
-
getAssistantResponse(),
|
|
130
|
-
getAssistantResponse(),
|
|
131
|
-
])
|
|
132
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
133
|
-
return { message: null, shouldSkipPermissionCheck: false }
|
|
134
|
-
}
|
|
135
|
-
if (m2.isApiErrorMessage) {
|
|
136
|
-
// If m2 is an error, we might as well return m1, even if it's also an error --
|
|
137
|
-
// the UI will display it as an error as it would in the non-feedback path.
|
|
138
|
-
return { message: m1, shouldSkipPermissionCheck: false }
|
|
139
|
-
}
|
|
140
|
-
if (m1.isApiErrorMessage) {
|
|
141
|
-
return { message: m2, shouldSkipPermissionCheck: false }
|
|
142
|
-
}
|
|
143
|
-
if (!messagePairValidForBinaryFeedback(m1, m2)) {
|
|
144
|
-
return { message: m1, shouldSkipPermissionCheck: false }
|
|
145
|
-
}
|
|
146
|
-
return await getBinaryFeedbackResponse(m1, m2)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* The rules of thinking are lengthy and fortuitous. They require plenty of thinking
|
|
151
|
-
* of most long duration and deep meditation for a wizard to wrap one's noggin around.
|
|
152
|
-
*
|
|
153
|
-
* The rules follow:
|
|
154
|
-
* 1. A message that contains a thinking or redacted_thinking block must be part of a query whose max_thinking_length > 0
|
|
155
|
-
* 2. A thinking block may not be the last message in a block
|
|
156
|
-
* 3. Thinking blocks must be preserved for the duration of an assistant trajectory (a single turn, or if that turn includes a tool_use block then also its subsequent tool_result and the following assistant message)
|
|
157
|
-
*
|
|
158
|
-
* Heed these rules well, young wizard. For they are the rules of thinking, and
|
|
159
|
-
* the rules of thinking are the rules of the universe. If ye does not heed these
|
|
160
|
-
* rules, ye will be punished with an entire day of debugging and hair pulling.
|
|
161
|
-
*/
|
|
162
|
-
export async function* query(
|
|
163
|
-
messages: Message[],
|
|
164
|
-
systemPrompt: string[],
|
|
165
|
-
context: { [k: string]: string },
|
|
166
|
-
canUseTool: CanUseToolFn,
|
|
167
|
-
toolUseContext: ExtendedToolUseContext,
|
|
168
|
-
getBinaryFeedbackResponse?: (
|
|
169
|
-
m1: AssistantMessage,
|
|
170
|
-
m2: AssistantMessage,
|
|
171
|
-
) => Promise<BinaryFeedbackResult>,
|
|
172
|
-
): AsyncGenerator<Message, void> {
|
|
173
|
-
const currentRequest = getCurrentRequest()
|
|
174
|
-
|
|
175
|
-
markPhase('QUERY_INIT')
|
|
176
|
-
|
|
177
|
-
// Auto-compact check
|
|
178
|
-
const { messages: processedMessages, wasCompacted } = await checkAutoCompact(
|
|
179
|
-
messages,
|
|
180
|
-
toolUseContext,
|
|
181
|
-
)
|
|
182
|
-
if (wasCompacted) {
|
|
183
|
-
messages = processedMessages
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
markPhase('SYSTEM_PROMPT_BUILD')
|
|
187
|
-
|
|
188
|
-
const { systemPrompt: fullSystemPrompt, reminders } =
|
|
189
|
-
formatSystemPromptWithContext(systemPrompt, context, toolUseContext.agentId)
|
|
190
|
-
|
|
191
|
-
// Emit session startup event
|
|
192
|
-
emitReminderEvent('session:startup', {
|
|
193
|
-
agentId: toolUseContext.agentId,
|
|
194
|
-
messages: messages.length,
|
|
195
|
-
timestamp: Date.now(),
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
// Inject reminders into the latest user message
|
|
199
|
-
if (reminders && messages.length > 0) {
|
|
200
|
-
// Find the last user message
|
|
201
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
202
|
-
const msg = messages[i]
|
|
203
|
-
if (msg?.type === 'user') {
|
|
204
|
-
const lastUserMessage = msg as UserMessage
|
|
205
|
-
messages[i] = {
|
|
206
|
-
...lastUserMessage,
|
|
207
|
-
message: {
|
|
208
|
-
...lastUserMessage.message,
|
|
209
|
-
content:
|
|
210
|
-
typeof lastUserMessage.message.content === 'string'
|
|
211
|
-
? reminders + lastUserMessage.message.content
|
|
212
|
-
: [
|
|
213
|
-
...(Array.isArray(lastUserMessage.message.content)
|
|
214
|
-
? lastUserMessage.message.content
|
|
215
|
-
: []),
|
|
216
|
-
{ type: 'text', text: reminders },
|
|
217
|
-
],
|
|
218
|
-
},
|
|
219
|
-
}
|
|
220
|
-
break
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
markPhase('LLM_PREPARATION')
|
|
226
|
-
|
|
227
|
-
function getAssistantResponse() {
|
|
228
|
-
return queryLLM(
|
|
229
|
-
normalizeMessagesForAPI(messages),
|
|
230
|
-
fullSystemPrompt,
|
|
231
|
-
toolUseContext.options.maxThinkingTokens,
|
|
232
|
-
toolUseContext.options.tools,
|
|
233
|
-
toolUseContext.abortController.signal,
|
|
234
|
-
{
|
|
235
|
-
safeMode: toolUseContext.options.safeMode ?? false,
|
|
236
|
-
model: toolUseContext.options.model || 'main',
|
|
237
|
-
prependCLISysprompt: true,
|
|
238
|
-
toolUseContext: toolUseContext,
|
|
239
|
-
},
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const result = await queryWithBinaryFeedback(
|
|
244
|
-
toolUseContext,
|
|
245
|
-
getAssistantResponse,
|
|
246
|
-
getBinaryFeedbackResponse,
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
// If request was cancelled, return immediately with interrupt message
|
|
250
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
251
|
-
yield createAssistantMessage(INTERRUPT_MESSAGE)
|
|
252
|
-
return
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (result.message === null) {
|
|
256
|
-
yield createAssistantMessage(INTERRUPT_MESSAGE)
|
|
257
|
-
return
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const assistantMessage = result.message
|
|
261
|
-
const shouldSkipPermissionCheck = result.shouldSkipPermissionCheck
|
|
262
|
-
|
|
263
|
-
yield assistantMessage
|
|
264
|
-
|
|
265
|
-
// @see https://docs.anthropic.com/en/docs/build-with-claude/tool-use
|
|
266
|
-
// Note: stop_reason === 'tool_use' is unreliable -- it's not always set correctly
|
|
267
|
-
const toolUseMessages = assistantMessage.message.content.filter(
|
|
268
|
-
_ => _.type === 'tool_use',
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
// If there's no more tool use, we're done
|
|
272
|
-
if (!toolUseMessages.length) {
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const toolResults: UserMessage[] = []
|
|
277
|
-
|
|
278
|
-
// Simple concurrency check like original system
|
|
279
|
-
const canRunConcurrently = toolUseMessages.every(msg =>
|
|
280
|
-
toolUseContext.options.tools.find(t => t.name === msg.name)?.isReadOnly(),
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
if (canRunConcurrently) {
|
|
284
|
-
for await (const message of runToolsConcurrently(
|
|
285
|
-
toolUseMessages,
|
|
286
|
-
assistantMessage,
|
|
287
|
-
canUseTool,
|
|
288
|
-
toolUseContext,
|
|
289
|
-
shouldSkipPermissionCheck,
|
|
290
|
-
)) {
|
|
291
|
-
yield message
|
|
292
|
-
// progress messages are not sent to the server, so don't need to be accumulated for the next turn
|
|
293
|
-
if (message.type === 'user') {
|
|
294
|
-
toolResults.push(message)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
} else {
|
|
298
|
-
for await (const message of runToolsSerially(
|
|
299
|
-
toolUseMessages,
|
|
300
|
-
assistantMessage,
|
|
301
|
-
canUseTool,
|
|
302
|
-
toolUseContext,
|
|
303
|
-
shouldSkipPermissionCheck,
|
|
304
|
-
)) {
|
|
305
|
-
yield message
|
|
306
|
-
// progress messages are not sent to the server, so don't need to be accumulated for the next turn
|
|
307
|
-
if (message.type === 'user') {
|
|
308
|
-
toolResults.push(message)
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
314
|
-
yield createAssistantMessage(INTERRUPT_MESSAGE_FOR_TOOL_USE)
|
|
315
|
-
return
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Sort toolResults to match the order of toolUseMessages
|
|
319
|
-
const orderedToolResults = toolResults.sort((a, b) => {
|
|
320
|
-
const aIndex = toolUseMessages.findIndex(
|
|
321
|
-
tu => tu.id === (a.message.content[0] as ToolUseBlock).id,
|
|
322
|
-
)
|
|
323
|
-
const bIndex = toolUseMessages.findIndex(
|
|
324
|
-
tu => tu.id === (b.message.content[0] as ToolUseBlock).id,
|
|
325
|
-
)
|
|
326
|
-
return aIndex - bIndex
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
// Recursive query
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
yield* await query(
|
|
333
|
-
[...messages, assistantMessage, ...orderedToolResults],
|
|
334
|
-
systemPrompt,
|
|
335
|
-
context,
|
|
336
|
-
canUseTool,
|
|
337
|
-
toolUseContext,
|
|
338
|
-
getBinaryFeedbackResponse,
|
|
339
|
-
)
|
|
340
|
-
} catch (error) {
|
|
341
|
-
// Re-throw the error to maintain the original behavior
|
|
342
|
-
throw error
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
async function* runToolsConcurrently(
|
|
347
|
-
toolUseMessages: ToolUseBlock[],
|
|
348
|
-
assistantMessage: AssistantMessage,
|
|
349
|
-
canUseTool: CanUseToolFn,
|
|
350
|
-
toolUseContext: ExtendedToolUseContext,
|
|
351
|
-
shouldSkipPermissionCheck?: boolean,
|
|
352
|
-
): AsyncGenerator<Message, void> {
|
|
353
|
-
yield* all(
|
|
354
|
-
toolUseMessages.map(toolUse =>
|
|
355
|
-
runToolUse(
|
|
356
|
-
toolUse,
|
|
357
|
-
new Set(toolUseMessages.map(_ => _.id)),
|
|
358
|
-
assistantMessage,
|
|
359
|
-
canUseTool,
|
|
360
|
-
toolUseContext,
|
|
361
|
-
shouldSkipPermissionCheck,
|
|
362
|
-
),
|
|
363
|
-
),
|
|
364
|
-
MAX_TOOL_USE_CONCURRENCY,
|
|
365
|
-
)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
async function* runToolsSerially(
|
|
369
|
-
toolUseMessages: ToolUseBlock[],
|
|
370
|
-
assistantMessage: AssistantMessage,
|
|
371
|
-
canUseTool: CanUseToolFn,
|
|
372
|
-
toolUseContext: ExtendedToolUseContext,
|
|
373
|
-
shouldSkipPermissionCheck?: boolean,
|
|
374
|
-
): AsyncGenerator<Message, void> {
|
|
375
|
-
for (const toolUse of toolUseMessages) {
|
|
376
|
-
yield* runToolUse(
|
|
377
|
-
toolUse,
|
|
378
|
-
new Set(toolUseMessages.map(_ => _.id)),
|
|
379
|
-
assistantMessage,
|
|
380
|
-
canUseTool,
|
|
381
|
-
toolUseContext,
|
|
382
|
-
shouldSkipPermissionCheck,
|
|
383
|
-
)
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export async function* runToolUse(
|
|
388
|
-
toolUse: ToolUseBlock,
|
|
389
|
-
siblingToolUseIDs: Set<string>,
|
|
390
|
-
assistantMessage: AssistantMessage,
|
|
391
|
-
canUseTool: CanUseToolFn,
|
|
392
|
-
toolUseContext: ExtendedToolUseContext,
|
|
393
|
-
shouldSkipPermissionCheck?: boolean,
|
|
394
|
-
): AsyncGenerator<Message, void> {
|
|
395
|
-
const currentRequest = getCurrentRequest()
|
|
396
|
-
|
|
397
|
-
// 🔍 Debug: 工具调用开始
|
|
398
|
-
debugLogger.flow('TOOL_USE_START', {
|
|
399
|
-
toolName: toolUse.name,
|
|
400
|
-
toolUseID: toolUse.id,
|
|
401
|
-
inputSize: JSON.stringify(toolUse.input).length,
|
|
402
|
-
siblingToolCount: siblingToolUseIDs.size,
|
|
403
|
-
shouldSkipPermissionCheck: !!shouldSkipPermissionCheck,
|
|
404
|
-
requestId: currentRequest?.id,
|
|
405
|
-
})
|
|
406
|
-
|
|
407
|
-
logUserFriendly(
|
|
408
|
-
'TOOL_EXECUTION',
|
|
409
|
-
{
|
|
410
|
-
toolName: toolUse.name,
|
|
411
|
-
action: 'Starting',
|
|
412
|
-
target: toolUse.input ? Object.keys(toolUse.input).join(', ') : '',
|
|
413
|
-
},
|
|
414
|
-
currentRequest?.id,
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
logEvent('tengu_tool_use_start', {
|
|
419
|
-
toolName: toolUse.name,
|
|
420
|
-
toolUseID: toolUse.id,
|
|
421
|
-
})
|
|
422
|
-
|
|
423
|
-
const toolName = toolUse.name
|
|
424
|
-
const tool = toolUseContext.options.tools.find(t => t.name === toolName)
|
|
425
|
-
|
|
426
|
-
// Check if the tool exists
|
|
427
|
-
if (!tool) {
|
|
428
|
-
debugLogger.error('TOOL_NOT_FOUND', {
|
|
429
|
-
requestedTool: toolName,
|
|
430
|
-
availableTools: toolUseContext.options.tools.map(t => t.name),
|
|
431
|
-
toolUseID: toolUse.id,
|
|
432
|
-
requestId: currentRequest?.id,
|
|
433
|
-
})
|
|
434
|
-
|
|
435
|
-
logEvent('tengu_tool_use_error', {
|
|
436
|
-
error: `No such tool available: ${toolName}`,
|
|
437
|
-
messageID: assistantMessage.message.id,
|
|
438
|
-
toolName,
|
|
439
|
-
toolUseID: toolUse.id,
|
|
440
|
-
})
|
|
441
|
-
|
|
442
|
-
yield createUserMessage([
|
|
443
|
-
{
|
|
444
|
-
type: 'tool_result',
|
|
445
|
-
content: `Error: No such tool available: ${toolName}`,
|
|
446
|
-
is_error: true,
|
|
447
|
-
tool_use_id: toolUse.id,
|
|
448
|
-
},
|
|
449
|
-
])
|
|
450
|
-
return
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const toolInput = toolUse.input as { [key: string]: string }
|
|
454
|
-
|
|
455
|
-
debugLogger.flow('TOOL_VALIDATION_START', {
|
|
456
|
-
toolName: tool.name,
|
|
457
|
-
toolUseID: toolUse.id,
|
|
458
|
-
inputKeys: Object.keys(toolInput),
|
|
459
|
-
requestId: currentRequest?.id,
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
try {
|
|
463
|
-
// 🔧 Check for cancellation before starting tool execution
|
|
464
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
465
|
-
debugLogger.flow('TOOL_USE_CANCELLED_BEFORE_START', {
|
|
466
|
-
toolName: tool.name,
|
|
467
|
-
toolUseID: toolUse.id,
|
|
468
|
-
abortReason: 'AbortController signal',
|
|
469
|
-
requestId: currentRequest?.id,
|
|
470
|
-
})
|
|
471
|
-
|
|
472
|
-
logEvent('tengu_tool_use_cancelled', {
|
|
473
|
-
toolName: tool.name,
|
|
474
|
-
toolUseID: toolUse.id,
|
|
475
|
-
})
|
|
476
|
-
|
|
477
|
-
const message = createUserMessage([
|
|
478
|
-
createToolResultStopMessage(toolUse.id),
|
|
479
|
-
])
|
|
480
|
-
yield message
|
|
481
|
-
return
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Track if any progress messages were yielded
|
|
485
|
-
let hasProgressMessages = false
|
|
486
|
-
|
|
487
|
-
for await (const message of checkPermissionsAndCallTool(
|
|
488
|
-
tool,
|
|
489
|
-
toolUse.id,
|
|
490
|
-
siblingToolUseIDs,
|
|
491
|
-
toolInput,
|
|
492
|
-
toolUseContext,
|
|
493
|
-
canUseTool,
|
|
494
|
-
assistantMessage,
|
|
495
|
-
shouldSkipPermissionCheck,
|
|
496
|
-
)) {
|
|
497
|
-
// 🔧 Check for cancellation during tool execution
|
|
498
|
-
if (toolUseContext.abortController.signal.aborted) {
|
|
499
|
-
debugLogger.flow('TOOL_USE_CANCELLED_DURING_EXECUTION', {
|
|
500
|
-
toolName: tool.name,
|
|
501
|
-
toolUseID: toolUse.id,
|
|
502
|
-
hasProgressMessages,
|
|
503
|
-
abortReason: 'AbortController signal during execution',
|
|
504
|
-
requestId: currentRequest?.id,
|
|
505
|
-
})
|
|
506
|
-
|
|
507
|
-
// If we yielded progress messages but got cancelled, yield a cancellation result
|
|
508
|
-
if (hasProgressMessages && message.type === 'progress') {
|
|
509
|
-
yield message // yield the last progress message first
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// Always yield a tool result message for cancellation to clear UI state
|
|
513
|
-
const cancelMessage = createUserMessage([
|
|
514
|
-
createToolResultStopMessage(toolUse.id),
|
|
515
|
-
])
|
|
516
|
-
yield cancelMessage
|
|
517
|
-
return
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
if (message.type === 'progress') {
|
|
521
|
-
hasProgressMessages = true
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
yield message
|
|
525
|
-
}
|
|
526
|
-
} catch (e) {
|
|
527
|
-
logError(e)
|
|
528
|
-
|
|
529
|
-
// 🔧 Even on error, ensure we yield a tool result to clear UI state
|
|
530
|
-
const errorMessage = createUserMessage([
|
|
531
|
-
{
|
|
532
|
-
type: 'tool_result',
|
|
533
|
-
content: `Tool execution failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
534
|
-
is_error: true,
|
|
535
|
-
tool_use_id: toolUse.id,
|
|
536
|
-
},
|
|
537
|
-
])
|
|
538
|
-
yield errorMessage
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// TODO: Generalize this to all tools
|
|
543
|
-
export function normalizeToolInput(
|
|
544
|
-
tool: Tool,
|
|
545
|
-
input: { [key: string]: boolean | string | number },
|
|
546
|
-
): { [key: string]: boolean | string | number } {
|
|
547
|
-
switch (tool) {
|
|
548
|
-
case BashTool: {
|
|
549
|
-
const { command, timeout } = BashTool.inputSchema.parse(input) // already validated upstream, won't throw
|
|
550
|
-
return {
|
|
551
|
-
command: command.replace(`cd ${getCwd()} && `, ''),
|
|
552
|
-
...(timeout ? { timeout } : {}),
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
default:
|
|
556
|
-
return input
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
async function* checkPermissionsAndCallTool(
|
|
561
|
-
tool: Tool,
|
|
562
|
-
toolUseID: string,
|
|
563
|
-
siblingToolUseIDs: Set<string>,
|
|
564
|
-
input: { [key: string]: boolean | string | number },
|
|
565
|
-
context: ToolUseContext,
|
|
566
|
-
canUseTool: CanUseToolFn,
|
|
567
|
-
assistantMessage: AssistantMessage,
|
|
568
|
-
shouldSkipPermissionCheck?: boolean,
|
|
569
|
-
): AsyncGenerator<UserMessage | ProgressMessage, void> {
|
|
570
|
-
// Validate input types with zod
|
|
571
|
-
// (surprisingly, the model is not great at generating valid input)
|
|
572
|
-
const isValidInput = tool.inputSchema.safeParse(input)
|
|
573
|
-
if (!isValidInput.success) {
|
|
574
|
-
// Create a more helpful error message for common cases
|
|
575
|
-
let errorMessage = `InputValidationError: ${isValidInput.error.message}`
|
|
576
|
-
|
|
577
|
-
// Special handling for the "View" tool (FileReadTool) being called with empty parameters
|
|
578
|
-
if (tool.name === 'View' && Object.keys(input).length === 0) {
|
|
579
|
-
errorMessage = `Error: The View tool requires a 'file_path' parameter to specify which file to read. Please provide the absolute path to the file you want to view. For example: {"file_path": "/path/to/file.txt"}`
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
logEvent('tengu_tool_use_error', {
|
|
583
|
-
error: errorMessage,
|
|
584
|
-
messageID: assistantMessage.message.id,
|
|
585
|
-
toolName: tool.name,
|
|
586
|
-
toolInput: JSON.stringify(input).slice(0, 200),
|
|
587
|
-
})
|
|
588
|
-
yield createUserMessage([
|
|
589
|
-
{
|
|
590
|
-
type: 'tool_result',
|
|
591
|
-
content: errorMessage,
|
|
592
|
-
is_error: true,
|
|
593
|
-
tool_use_id: toolUseID,
|
|
594
|
-
},
|
|
595
|
-
])
|
|
596
|
-
return
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
const normalizedInput = normalizeToolInput(tool, input)
|
|
600
|
-
|
|
601
|
-
// Validate input values. Each tool has its own validation logic
|
|
602
|
-
const isValidCall = await tool.validateInput?.(
|
|
603
|
-
normalizedInput as never,
|
|
604
|
-
context,
|
|
605
|
-
)
|
|
606
|
-
if (isValidCall?.result === false) {
|
|
607
|
-
logEvent('tengu_tool_use_error', {
|
|
608
|
-
error: isValidCall?.message.slice(0, 2000),
|
|
609
|
-
messageID: assistantMessage.message.id,
|
|
610
|
-
toolName: tool.name,
|
|
611
|
-
toolInput: JSON.stringify(input).slice(0, 200),
|
|
612
|
-
...(isValidCall?.meta ?? {}),
|
|
613
|
-
})
|
|
614
|
-
yield createUserMessage([
|
|
615
|
-
{
|
|
616
|
-
type: 'tool_result',
|
|
617
|
-
content: isValidCall!.message,
|
|
618
|
-
is_error: true,
|
|
619
|
-
tool_use_id: toolUseID,
|
|
620
|
-
},
|
|
621
|
-
])
|
|
622
|
-
return
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// Check whether we have permission to use the tool,
|
|
626
|
-
// and ask the user for permission if we don't
|
|
627
|
-
const permissionResult = shouldSkipPermissionCheck
|
|
628
|
-
? ({ result: true } as const)
|
|
629
|
-
: await canUseTool(tool, normalizedInput, context, assistantMessage)
|
|
630
|
-
if (permissionResult.result === false) {
|
|
631
|
-
yield createUserMessage([
|
|
632
|
-
{
|
|
633
|
-
type: 'tool_result',
|
|
634
|
-
content: permissionResult.message,
|
|
635
|
-
is_error: true,
|
|
636
|
-
tool_use_id: toolUseID,
|
|
637
|
-
},
|
|
638
|
-
])
|
|
639
|
-
return
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// Call the tool
|
|
643
|
-
try {
|
|
644
|
-
const generator = tool.call(normalizedInput as never, context)
|
|
645
|
-
for await (const result of generator) {
|
|
646
|
-
switch (result.type) {
|
|
647
|
-
case 'result':
|
|
648
|
-
logEvent('tengu_tool_use_success', {
|
|
649
|
-
messageID: assistantMessage.message.id,
|
|
650
|
-
toolName: tool.name,
|
|
651
|
-
})
|
|
652
|
-
yield createUserMessage(
|
|
653
|
-
[
|
|
654
|
-
{
|
|
655
|
-
type: 'tool_result',
|
|
656
|
-
content: result.resultForAssistant || String(result.data),
|
|
657
|
-
tool_use_id: toolUseID,
|
|
658
|
-
},
|
|
659
|
-
],
|
|
660
|
-
{
|
|
661
|
-
data: result.data,
|
|
662
|
-
resultForAssistant: result.resultForAssistant || String(result.data),
|
|
663
|
-
},
|
|
664
|
-
)
|
|
665
|
-
return
|
|
666
|
-
case 'progress':
|
|
667
|
-
logEvent('tengu_tool_use_progress', {
|
|
668
|
-
messageID: assistantMessage.message.id,
|
|
669
|
-
toolName: tool.name,
|
|
670
|
-
})
|
|
671
|
-
yield createProgressMessage(
|
|
672
|
-
toolUseID,
|
|
673
|
-
siblingToolUseIDs,
|
|
674
|
-
result.content,
|
|
675
|
-
result.normalizedMessages || [],
|
|
676
|
-
result.tools || [],
|
|
677
|
-
)
|
|
678
|
-
break
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
} catch (error) {
|
|
682
|
-
const content = formatError(error)
|
|
683
|
-
logError(error)
|
|
684
|
-
logEvent('tengu_tool_use_error', {
|
|
685
|
-
error: content.slice(0, 2000),
|
|
686
|
-
messageID: assistantMessage.message.id,
|
|
687
|
-
toolName: tool.name,
|
|
688
|
-
toolInput: JSON.stringify(input).slice(0, 1000),
|
|
689
|
-
})
|
|
690
|
-
yield createUserMessage([
|
|
691
|
-
{
|
|
692
|
-
type: 'tool_result',
|
|
693
|
-
content,
|
|
694
|
-
is_error: true,
|
|
695
|
-
tool_use_id: toolUseID,
|
|
696
|
-
},
|
|
697
|
-
])
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
function formatError(error: unknown): string {
|
|
702
|
-
if (!(error instanceof Error)) {
|
|
703
|
-
return String(error)
|
|
704
|
-
}
|
|
705
|
-
const parts = [error.message]
|
|
706
|
-
if ('stderr' in error && typeof error.stderr === 'string') {
|
|
707
|
-
parts.push(error.stderr)
|
|
708
|
-
}
|
|
709
|
-
if ('stdout' in error && typeof error.stdout === 'string') {
|
|
710
|
-
parts.push(error.stdout)
|
|
711
|
-
}
|
|
712
|
-
const fullMessage = parts.filter(Boolean).join('\n')
|
|
713
|
-
if (fullMessage.length <= 10000) {
|
|
714
|
-
return fullMessage
|
|
715
|
-
}
|
|
716
|
-
const halfLength = 5000
|
|
717
|
-
const start = fullMessage.slice(0, halfLength)
|
|
718
|
-
const end = fullMessage.slice(-halfLength)
|
|
719
|
-
return `${start}\n\n... [${fullMessage.length - 10000} characters truncated] ...\n\n${end}`
|
|
720
|
-
}
|