Files
orca/src/shared/source-control-ai-command-template.ts
T

115 lines
3.7 KiB
TypeScript

import { CUSTOM_AGENT_ID, isCustomAgentId, type CustomAgentId } from './commit-message-agent-spec'
import type { CommitMessageAiSettings } from './commit-message-ai-types'
import {
DEFAULT_SOURCE_CONTROL_ACTION_COMMAND_TEMPLATES,
readSourceControlActionDefault,
type SourceControlActionRecipe
} from './source-control-ai-actions'
import type { SourceControlAiOperation, SourceControlAiSettings } from './source-control-ai-types'
import type { TuiAgent } from './tui-agent'
export function commandTemplateFromInstruction(instruction: string | null | undefined): string {
const trimmed = instruction?.trim()
return trimmed ? ['{basePrompt}', '', trimmed].join('\n') : '{basePrompt}'
}
export function commandTemplateFromOperationInstruction(
operation: SourceControlAiOperation,
instruction: string | null | undefined
): string {
const trimmed = instruction?.trim()
if (!trimmed) {
return '{basePrompt}'
}
return operation === 'branchName'
? [trimmed, '', '{basePrompt}'].join('\n')
: commandTemplateFromInstruction(trimmed)
}
export function isLegacyBranchInstructionTemplate(
operation: SourceControlAiOperation,
instruction: string | null | undefined,
template: string | null | undefined
): boolean {
return (
operation === 'branchName' &&
Boolean(instruction?.trim()) &&
template === commandTemplateFromInstruction(instruction)
)
}
export function actionRecipeFromLegacyCommitMessageAi(legacy: CommitMessageAiSettings): {
agentId?: TuiAgent | CustomAgentId | null
commandInputTemplate: string
} {
return {
...(legacy.agentId === null
? { agentId: null }
: isCustomAgentId(legacy.agentId)
? { agentId: CUSTOM_AGENT_ID }
: legacy.agentId
? { agentId: legacy.agentId }
: {}),
commandInputTemplate: commandTemplateFromInstruction(legacy.customPrompt)
}
}
export function legacyPromptFromCommandTemplate(
template: string | undefined,
fallback: string | undefined
): string {
const trimmed = template?.trim()
if (!trimmed || trimmed === '{basePrompt}') {
return fallback ?? ''
}
return trimmed.startsWith('{basePrompt}') ? trimmed.slice('{basePrompt}'.length).trim() : trimmed
}
export function hasActionAgentRecipe(recipe: {
agentId?: TuiAgent | CustomAgentId | null
}): recipe is { agentId: TuiAgent | CustomAgentId | null } {
return Object.hasOwn(recipe, 'agentId')
}
export function applyLegacyAgentToActionRecipe(
recipe: SourceControlActionRecipe | undefined,
agentId: CommitMessageAiSettings['agentId']
): SourceControlActionRecipe {
const next = { ...recipe }
if (agentId === null) {
next.agentId = null
} else if (isCustomAgentId(agentId)) {
next.agentId = CUSTOM_AGENT_ID
} else if (agentId) {
next.agentId = agentId
} else {
delete next.agentId
}
return next
}
export function shouldImportLegacyBranchPrompt(
base: SourceControlAiSettings,
projectedLegacy: CommitMessageAiSettings
): boolean {
const branchRecipe = readSourceControlActionDefault(base.actions, 'branchName')
const projectedTemplate = commandTemplateFromOperationInstruction(
'branchName',
projectedLegacy.customPrompt
)
return (
branchRecipe.commandInputTemplate === undefined ||
branchRecipe.commandInputTemplate ===
DEFAULT_SOURCE_CONTROL_ACTION_COMMAND_TEMPLATES.branchName ||
branchRecipe.commandInputTemplate === projectedTemplate
)
}
export function shouldImportLegacyBranchAgent(
base: SourceControlAiSettings,
projectedLegacy: CommitMessageAiSettings
): boolean {
const branchRecipe = readSourceControlActionDefault(base.actions, 'branchName')
return !hasActionAgentRecipe(branchRecipe) || branchRecipe.agentId === projectedLegacy.agentId
}