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

159 lines
5.9 KiB
TypeScript

import { isCustomAgentId } from './commit-message-agent-spec'
import type { CommitMessageAiSettings } from './commit-message-ai-types'
import {
DEFAULT_SOURCE_CONTROL_ACTION_COMMAND_TEMPLATES,
SOURCE_CONTROL_ACTION_IDS,
SOURCE_CONTROL_TEXT_ACTION_IDS,
normalizeSourceControlAiActionDefaults,
readSourceControlActionDefault
} from './source-control-ai-actions'
import {
actionRecipeFromLegacyCommitMessageAi,
commandTemplateFromOperationInstruction,
isLegacyBranchInstructionTemplate
} from './source-control-ai-command-template'
import type {
SourceControlAiPrCreationDefaults,
SourceControlAiSettings
} from './source-control-ai-types'
export const DEFAULT_SOURCE_CONTROL_AI_PR_CREATION_DEFAULTS: Required<SourceControlAiPrCreationDefaults> =
{
draft: false,
useTemplate: false,
generateDetailsOnOpen: false,
openAfterCreate: false
}
function copyRecord<T>(value: T | undefined): T | undefined {
return value === undefined ? undefined : structuredClone(value)
}
export function getDefaultSourceControlAiSettings(): SourceControlAiSettings {
return {
enabled: true,
actions: Object.fromEntries(
SOURCE_CONTROL_ACTION_IDS.map((actionId) => [
actionId,
{ commandInputTemplate: DEFAULT_SOURCE_CONTROL_ACTION_COMMAND_TEMPLATES[actionId] }
])
) as SourceControlAiSettings['actions'],
agentId: null,
selectedModelByAgent: {},
selectedModelByAgentByHost: {},
discoveredModelsByAgent: {},
discoveredModelsByAgentByHost: {},
selectedThinkingByModel: {},
customAgentCommand: '',
instructionsByOperation: { commitMessage: '', pullRequest: '', branchName: '' },
prCreationDefaults: { ...DEFAULT_SOURCE_CONTROL_AI_PR_CREATION_DEFAULTS },
launchActionDefaults: {}
}
}
export function sourceControlAiSettingsFromLegacy(
legacy: CommitMessageAiSettings | null | undefined
): SourceControlAiSettings {
const defaults = getDefaultSourceControlAiSettings()
if (!legacy) {
return defaults
}
const legacyActionRecipe = actionRecipeFromLegacyCommitMessageAi(legacy)
return {
...defaults,
enabled: legacy.enabled,
agentId: legacy.agentId,
selectedModelByAgent: { ...legacy.selectedModelByAgent },
selectedModelByAgentByHost: copyRecord(legacy.selectedModelByAgentByHost) ?? {},
discoveredModelsByAgent: copyRecord(legacy.discoveredModelsByAgent) ?? {},
discoveredModelsByAgentByHost: copyRecord(legacy.discoveredModelsByAgentByHost) ?? {},
selectedThinkingByModel: { ...legacy.selectedThinkingByModel },
customAgentCommand: legacy.customAgentCommand,
instructionsByOperation: {
commitMessage: legacy.customPrompt ?? '',
pullRequest: '',
branchName: legacy.customPrompt ?? ''
},
actions: {
...defaults.actions,
commitMessage: legacyActionRecipe,
branchName: {
...legacyActionRecipe,
commandInputTemplate: commandTemplateFromOperationInstruction(
'branchName',
legacy.customPrompt
)
}
}
}
}
export function normalizeSourceControlAiSettings(
value: SourceControlAiSettings | null | undefined,
legacy?: CommitMessageAiSettings | null
): SourceControlAiSettings {
const base = value ?? sourceControlAiSettingsFromLegacy(legacy)
const defaults = getDefaultSourceControlAiSettings()
const normalizedLaunchActionDefaults = normalizeSourceControlAiActionDefaults(
base.launchActionDefaults
)
const normalizedActions = {
...normalizedLaunchActionDefaults,
...normalizeSourceControlAiActionDefaults(base.actions)
}
const migratedTextActions = Object.fromEntries(
SOURCE_CONTROL_TEXT_ACTION_IDS.map((actionId) => {
const existing = readSourceControlActionDefault(normalizedActions, actionId)
const instruction = base.instructionsByOperation?.[actionId]
const legacyInstruction = actionId === 'commitMessage' ? legacy?.customPrompt : undefined
const resolvedInstruction = instruction ?? legacyInstruction
const instructionTemplate =
instruction || legacyInstruction
? commandTemplateFromOperationInstruction(actionId, resolvedInstruction)
: undefined
const shouldApplyInstructionTemplate =
instructionTemplate !== undefined &&
(existing.commandInputTemplate === undefined ||
existing.commandInputTemplate ===
DEFAULT_SOURCE_CONTROL_ACTION_COMMAND_TEMPLATES[actionId] ||
isLegacyBranchInstructionTemplate(
actionId,
resolvedInstruction,
existing.commandInputTemplate
))
return [
actionId,
{
...defaults.actions?.[actionId],
...(base.agentId && !isCustomAgentId(base.agentId) ? { agentId: base.agentId } : {}),
...existing,
...(shouldApplyInstructionTemplate ? { commandInputTemplate: instructionTemplate } : {})
}
]
})
) as SourceControlAiSettings['actions']
return {
...defaults,
...base,
selectedModelByAgent: { ...defaults.selectedModelByAgent, ...base.selectedModelByAgent },
selectedModelByAgentByHost:
copyRecord(base.selectedModelByAgentByHost) ?? defaults.selectedModelByAgentByHost,
discoveredModelsByAgent:
copyRecord(base.discoveredModelsByAgent) ?? defaults.discoveredModelsByAgent,
discoveredModelsByAgentByHost:
copyRecord(base.discoveredModelsByAgentByHost) ?? defaults.discoveredModelsByAgentByHost,
selectedThinkingByModel: {
...defaults.selectedThinkingByModel,
...base.selectedThinkingByModel
},
instructionsByOperation: {
...defaults.instructionsByOperation,
...base.instructionsByOperation
},
modelOverridesByOperation: copyRecord(base.modelOverridesByOperation),
prCreationDefaults: { ...defaults.prCreationDefaults, ...base.prCreationDefaults },
actions: { ...defaults.actions, ...normalizedActions, ...migratedTextActions },
launchActionDefaults: normalizedLaunchActionDefaults ?? defaults.launchActionDefaults
}
}