init claude-code
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from '../../../services/analytics/index.js'
|
||||
import { sanitizeToolNameForAnalytics } from '../../../services/analytics/metadata.js'
|
||||
import type { ToolPermissionContext } from '../../../Tool.js'
|
||||
import {
|
||||
CLAUDE_FOLDER_PERMISSION_PATTERN,
|
||||
FILE_EDIT_TOOL_NAME,
|
||||
GLOBAL_CLAUDE_FOLDER_PERMISSION_PATTERN,
|
||||
} from '../../../tools/FileEditTool/constants.js'
|
||||
import { env } from '../../../utils/env.js'
|
||||
import { generateSuggestions } from '../../../utils/permissions/filesystem.js'
|
||||
import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js'
|
||||
import {
|
||||
type CompletionType,
|
||||
logUnaryEvent,
|
||||
} from '../../../utils/unaryLogging.js'
|
||||
import type { ToolUseConfirm } from '../PermissionRequest.js'
|
||||
import type {
|
||||
FileOperationType,
|
||||
PermissionOption,
|
||||
} from './permissionOptions.js'
|
||||
|
||||
function logPermissionEvent(
|
||||
event: 'accept' | 'reject',
|
||||
completionType: CompletionType,
|
||||
languageName: string | Promise<string>,
|
||||
messageId: string,
|
||||
hasFeedback?: boolean,
|
||||
): void {
|
||||
void logUnaryEvent({
|
||||
completion_type: completionType,
|
||||
event,
|
||||
metadata: {
|
||||
language_name: languageName,
|
||||
message_id: messageId,
|
||||
platform: env.platform,
|
||||
hasFeedback: hasFeedback ?? false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export type PermissionHandlerParams = {
|
||||
messageId: string
|
||||
path: string | null
|
||||
toolUseConfirm: ToolUseConfirm
|
||||
toolPermissionContext: ToolPermissionContext
|
||||
onDone: () => void
|
||||
onReject: () => void
|
||||
completionType: CompletionType
|
||||
languageName: string | Promise<string>
|
||||
operationType: FileOperationType
|
||||
}
|
||||
|
||||
export type PermissionHandlerOptions = {
|
||||
hasFeedback?: boolean
|
||||
feedback?: string
|
||||
enteredFeedbackMode?: boolean
|
||||
scope?: 'claude-folder' | 'global-claude-folder'
|
||||
}
|
||||
|
||||
function handleAcceptOnce(
|
||||
params: PermissionHandlerParams,
|
||||
options?: PermissionHandlerOptions,
|
||||
): void {
|
||||
const { messageId, toolUseConfirm, onDone, completionType, languageName } =
|
||||
params
|
||||
|
||||
logPermissionEvent('accept', completionType, languageName, messageId)
|
||||
|
||||
// Log accept submission with feedback context
|
||||
logEvent('tengu_accept_submitted', {
|
||||
toolName: sanitizeToolNameForAnalytics(
|
||||
toolUseConfirm.tool.name,
|
||||
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
isMcp: toolUseConfirm.tool.isMcp ?? false,
|
||||
has_instructions: !!options?.feedback,
|
||||
instructions_length: options?.feedback?.length ?? 0,
|
||||
entered_feedback_mode: options?.enteredFeedbackMode ?? false,
|
||||
})
|
||||
|
||||
onDone()
|
||||
toolUseConfirm.onAllow(toolUseConfirm.input, [], options?.feedback)
|
||||
}
|
||||
|
||||
function handleAcceptSession(
|
||||
params: PermissionHandlerParams,
|
||||
options?: PermissionHandlerOptions,
|
||||
): void {
|
||||
const {
|
||||
messageId,
|
||||
path,
|
||||
toolUseConfirm,
|
||||
toolPermissionContext,
|
||||
onDone,
|
||||
completionType,
|
||||
languageName,
|
||||
operationType,
|
||||
} = params
|
||||
|
||||
logPermissionEvent('accept', completionType, languageName, messageId)
|
||||
|
||||
// For claude-folder scope, grant session-level access to all .claude/ files
|
||||
if (
|
||||
options?.scope === 'claude-folder' ||
|
||||
options?.scope === 'global-claude-folder'
|
||||
) {
|
||||
const pattern =
|
||||
options.scope === 'global-claude-folder'
|
||||
? GLOBAL_CLAUDE_FOLDER_PERMISSION_PATTERN
|
||||
: CLAUDE_FOLDER_PERMISSION_PATTERN
|
||||
const suggestions: PermissionUpdate[] = [
|
||||
{
|
||||
type: 'addRules',
|
||||
rules: [
|
||||
{
|
||||
toolName: FILE_EDIT_TOOL_NAME,
|
||||
ruleContent: pattern,
|
||||
},
|
||||
],
|
||||
behavior: 'allow',
|
||||
destination: 'session',
|
||||
},
|
||||
]
|
||||
onDone()
|
||||
toolUseConfirm.onAllow(toolUseConfirm.input, suggestions)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate permission updates if path is provided
|
||||
const suggestions = path
|
||||
? generateSuggestions(path, operationType, toolPermissionContext)
|
||||
: []
|
||||
|
||||
onDone()
|
||||
// Pass permission updates directly to onAllow
|
||||
toolUseConfirm.onAllow(toolUseConfirm.input, suggestions)
|
||||
}
|
||||
|
||||
function handleReject(
|
||||
params: PermissionHandlerParams,
|
||||
options?: PermissionHandlerOptions,
|
||||
): void {
|
||||
const {
|
||||
messageId,
|
||||
toolUseConfirm,
|
||||
onDone,
|
||||
onReject,
|
||||
completionType,
|
||||
languageName,
|
||||
} = params
|
||||
|
||||
logPermissionEvent(
|
||||
'reject',
|
||||
completionType,
|
||||
languageName,
|
||||
messageId,
|
||||
options?.hasFeedback,
|
||||
)
|
||||
|
||||
// Log reject submission with feedback context
|
||||
logEvent('tengu_reject_submitted', {
|
||||
toolName: sanitizeToolNameForAnalytics(
|
||||
toolUseConfirm.tool.name,
|
||||
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
isMcp: toolUseConfirm.tool.isMcp ?? false,
|
||||
has_instructions: !!options?.feedback,
|
||||
instructions_length: options?.feedback?.length ?? 0,
|
||||
entered_feedback_mode: options?.enteredFeedbackMode ?? false,
|
||||
})
|
||||
|
||||
onDone()
|
||||
onReject()
|
||||
toolUseConfirm.onReject(options?.feedback)
|
||||
}
|
||||
|
||||
export const PERMISSION_HANDLERS: Record<
|
||||
PermissionOption['type'],
|
||||
(params: PermissionHandlerParams, options?: PermissionHandlerOptions) => void
|
||||
> = {
|
||||
'accept-once': handleAcceptOnce,
|
||||
'accept-session': handleAcceptSession,
|
||||
reject: handleReject,
|
||||
}
|
||||
Reference in New Issue
Block a user