chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,106 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import type { ChatInteraction } from '../src/shared/conversation'
|
||||
import { ToolCallRenderer } from '../src/renderer/src/workbuddy/conversation/ToolCallRenderer'
|
||||
import {
|
||||
findToolApproval,
|
||||
hasSourcePermissionRequest,
|
||||
isActiveToolApproval,
|
||||
sourcePermissionMetadata,
|
||||
toolApprovalOption
|
||||
} from '../src/renderer/src/workbuddy/conversation/tool-approval'
|
||||
import type { ConversationToolCall } from '../src/renderer/src/workbuddy/conversation/types'
|
||||
|
||||
const permissionOptions = [
|
||||
{ optionId: 'always', kind: 'allow_always' },
|
||||
{ optionId: 'once', kind: 'allow_once' },
|
||||
{ optionId: 'allow', kind: 'allow' },
|
||||
{ optionId: 'reject', kind: 'reject' },
|
||||
{ optionId: 'reject-once', kind: 'reject_once' }
|
||||
]
|
||||
|
||||
assert.equal(toolApprovalOption(permissionOptions, 'allow')?.optionId, 'once', 'once takes priority over allow_always and allow')
|
||||
assert.equal(toolApprovalOption([permissionOptions[0]], 'allow'), undefined, 'allow_always is never used by the source action')
|
||||
assert.equal(toolApprovalOption([permissionOptions[2]], 'allow')?.optionId, 'allow')
|
||||
assert.equal(toolApprovalOption(permissionOptions, 'reject')?.optionId, 'reject-once')
|
||||
assert.equal(toolApprovalOption([permissionOptions[3]], 'reject')?.optionId, 'reject')
|
||||
|
||||
const firstApproval = {
|
||||
id: 'approval-1', runId: 'run', toolCallId: 'file-call', title: 'Authorize file write', status: 'pending',
|
||||
kind: 'approval', requestId: 'request-1', options: permissionOptions
|
||||
} satisfies ChatInteraction
|
||||
const latestApproval = {
|
||||
...firstApproval, id: 'approval-2', requestId: 'request-2', status: 'responding'
|
||||
} satisfies ChatInteraction
|
||||
const unrelatedApproval = { ...firstApproval, id: 'approval-other', toolCallId: 'other-call' } satisfies ChatInteraction
|
||||
assert.equal(findToolApproval([firstApproval, unrelatedApproval, latestApproval], 'file-call'), latestApproval)
|
||||
assert.equal(findToolApproval([firstApproval], 'missing'), undefined)
|
||||
assert.equal(isActiveToolApproval(firstApproval as Extract<ChatInteraction, { kind: 'approval' }>), true)
|
||||
assert.equal(isActiveToolApproval(latestApproval as Extract<ChatInteraction, { kind: 'approval' }>), true)
|
||||
assert.equal(isActiveToolApproval({ ...latestApproval, status: 'answered' } as Extract<ChatInteraction, { kind: 'approval' }>), false)
|
||||
|
||||
const request = { requestId: 'request-file', permissionOptions: [{ optionId: 'once', name: 'Allow once', kind: 'allow_once' }] }
|
||||
const fileTool: ConversationToolCall = {
|
||||
id: 'file-call', name: 'edit_file', status: 'pending', args: { filePath: 'src/file.ts', oldContent: 'before', content: 'after' },
|
||||
metaData: { acp_request_permission: request }
|
||||
}
|
||||
const commandTool: ConversationToolCall = {
|
||||
id: 'command-call', name: 'execute_command', status: 'pending', args: { command: 'npm test' },
|
||||
metadata: { acp_request_permission: { ...request, requestId: 'request-command' } }
|
||||
}
|
||||
assert.equal(hasSourcePermissionRequest(fileTool), true)
|
||||
assert.equal(hasSourcePermissionRequest(commandTool), true)
|
||||
assert.equal(hasSourcePermissionRequest({ ...fileTool, metaData: undefined, metadata: fileTool.metaData }), true)
|
||||
assert.equal(hasSourcePermissionRequest({ ...fileTool, metaData: { acp_request_permission: { permissionOptions: request.permissionOptions } } }), false)
|
||||
assert.equal(hasSourcePermissionRequest({ ...fileTool, metaData: { acp_request_permission: { requestId: 'empty-options', permissionOptions: [] } } }), false)
|
||||
assert.equal(hasSourcePermissionRequest({ ...fileTool, metaData: undefined, metadata: undefined }), false)
|
||||
|
||||
const mergedMetadata = sourcePermissionMetadata({ source: 'kept', acp_request_permission: { scope: 'local', requestId: 'old' } }, latestApproval as Extract<ChatInteraction, { kind: 'approval' }>)
|
||||
assert.deepEqual(mergedMetadata, {
|
||||
source: 'kept',
|
||||
acp_request_permission: { scope: 'local', requestId: 'request-2', permissionOptions: permissionOptions }
|
||||
})
|
||||
|
||||
const pendingControl = { status: 'pending' as const, onDecision: () => undefined }
|
||||
const respondingControl = { status: 'responding' as const, onDecision: () => undefined }
|
||||
const rendered = (tool: ConversationToolCall, control = pendingControl) => renderToStaticMarkup(<ToolCallRenderer tool={tool} approval={control} />)
|
||||
const extractActions = (markup: string) => [...markup.matchAll(/<button\b(?=[^>]*data-tool-decision="([^"]+)")(?=[^>]*class="[^"]*cr-tool-btn--([\w-]+)[^"]*")([^>]*)>([\s\S]*?)<\/button>/g)].map((match) => ({
|
||||
decision: match[1],
|
||||
variant: match[2],
|
||||
disabled: /\sdisabled(?:="")?(?:\s|$)/.test(match[3]),
|
||||
busy: /aria-busy="true"/.test(match[3]),
|
||||
label: match[4].replace(/<[^>]*>/g, '')
|
||||
}))
|
||||
|
||||
const pendingFile = rendered(fileTool)
|
||||
assert.deepEqual(extractActions(pendingFile).map(({ decision, variant, label }) => ({ decision, variant, label })), [
|
||||
{ decision: 'allow', variant: 'primary', label: '接受' },
|
||||
{ decision: 'reject', variant: 'danger', label: '拒绝' }
|
||||
])
|
||||
|
||||
const pendingCommand = rendered(commandTool)
|
||||
assert.match(pendingCommand, /确认执行命令?/)
|
||||
assert.deepEqual(extractActions(pendingCommand).map(({ decision, variant, label }) => ({ decision, variant, label })), [
|
||||
{ decision: 'allow', variant: 'primary', label: '运行' },
|
||||
{ decision: 'skip', variant: 'default', label: '跳过' },
|
||||
{ decision: 'reject', variant: 'danger', label: '拒绝' }
|
||||
])
|
||||
|
||||
for (const tool of [
|
||||
{ ...fileTool, status: 'running' as const },
|
||||
{ ...commandTool, status: 'running' as const },
|
||||
{ ...fileTool, metaData: undefined, metadata: undefined },
|
||||
{ ...commandTool, metaData: undefined, metadata: undefined },
|
||||
{ ...fileTool, metaData: { acp_request_permission: { requestId: 'empty', permissionOptions: [] } } }
|
||||
]) {
|
||||
assert.deepEqual(extractActions(rendered(tool)).length, 0)
|
||||
}
|
||||
|
||||
const respondingCommand = extractActions(rendered(commandTool, respondingControl))
|
||||
assert.deepEqual(respondingCommand.map(({ decision, disabled, busy }) => ({ decision, disabled, busy })), [
|
||||
{ decision: 'allow', disabled: true, busy: true },
|
||||
{ decision: 'skip', disabled: true, busy: true },
|
||||
{ decision: 'reject', disabled: true, busy: true }
|
||||
])
|
||||
|
||||
console.log('Tool approval helper and inline source markup regression checks passed.')
|
||||
Reference in new issue
Block a user