187 lines
5.3 KiB
Swift
187 lines
5.3 KiB
Swift
import Foundation
|
|
|
|
public protocol AIService: Sendable {
|
|
func generateSongProject(from request: SongProjectGenerationRequest) async throws -> SongProjectGenerationResult
|
|
func discussSongProject(from request: SongProjectDiscussionRequest) async throws -> SongProjectDiscussionResult
|
|
func reviseLyrics(from request: LyricsRevisionRequest) async throws -> LyricsRevisionResult
|
|
func proposeProjectUpdate(from request: SongProjectUpdateRequest) async throws -> SongProjectUpdateResult
|
|
}
|
|
|
|
public extension AIService {
|
|
func discussSongProject(from request: SongProjectDiscussionRequest) async throws -> SongProjectDiscussionResult {
|
|
throw AIServiceCapabilityError.discussionNotSupported
|
|
}
|
|
}
|
|
|
|
public enum AIServiceCapabilityError: Error, Equatable, Sendable {
|
|
case discussionNotSupported
|
|
}
|
|
|
|
public struct AIConversationMessage: Equatable, Identifiable, Sendable {
|
|
public let id: String
|
|
public var role: AIConversationRole
|
|
public var content: String
|
|
|
|
public init(
|
|
id: String = UUID().uuidString,
|
|
role: AIConversationRole,
|
|
content: String
|
|
) {
|
|
self.id = id
|
|
self.role = role
|
|
self.content = content
|
|
}
|
|
}
|
|
|
|
public enum AIConversationRole: String, Equatable, Sendable {
|
|
case user
|
|
case assistant
|
|
case system
|
|
}
|
|
|
|
public struct AIRequestContext: Equatable, Sendable {
|
|
public var userInstruction: String
|
|
public var conversation: [AIConversationMessage]
|
|
public var localeIdentifier: String?
|
|
internal var privateApplicationRules: PrivateApplicationRules?
|
|
|
|
public init(
|
|
userInstruction: String,
|
|
conversation: [AIConversationMessage] = [],
|
|
localeIdentifier: String? = nil
|
|
) {
|
|
self.userInstruction = userInstruction
|
|
self.conversation = conversation
|
|
self.localeIdentifier = localeIdentifier
|
|
self.privateApplicationRules = nil
|
|
}
|
|
|
|
internal mutating func injectPrivateApplicationRules(_ rules: PrivateApplicationRules?) {
|
|
privateApplicationRules = rules
|
|
}
|
|
}
|
|
|
|
public struct SongProjectGenerationRequest: Equatable, Sendable {
|
|
public var context: AIRequestContext
|
|
public var seedProject: SongProject?
|
|
public var discussionMode: ConversationMode
|
|
|
|
public init(
|
|
context: AIRequestContext,
|
|
seedProject: SongProject? = nil,
|
|
discussionMode: ConversationMode = .auto
|
|
) {
|
|
self.context = context
|
|
self.seedProject = seedProject
|
|
self.discussionMode = discussionMode
|
|
}
|
|
}
|
|
|
|
public struct SongProjectGenerationResult: Equatable, Sendable {
|
|
public var project: SongProject
|
|
public var notes: [String]
|
|
public var followUpQuestions: [String]
|
|
|
|
public init(
|
|
project: SongProject,
|
|
notes: [String] = [],
|
|
followUpQuestions: [String] = []
|
|
) {
|
|
self.project = project
|
|
self.notes = notes
|
|
self.followUpQuestions = followUpQuestions
|
|
}
|
|
}
|
|
|
|
public struct SongProjectDiscussionRequest: Equatable, Sendable {
|
|
public var context: AIRequestContext
|
|
public var project: SongProject
|
|
|
|
public init(context: AIRequestContext, project: SongProject) {
|
|
self.context = context
|
|
self.project = project
|
|
}
|
|
}
|
|
|
|
public struct SongProjectDiscussionResult: Equatable, Sendable {
|
|
public var questions: [String]
|
|
public var notes: [String]
|
|
|
|
public init(questions: [String], notes: [String] = []) {
|
|
self.questions = questions
|
|
self.notes = notes
|
|
}
|
|
}
|
|
|
|
public struct LyricsRevisionRequest: Equatable, Sendable {
|
|
public var context: AIRequestContext
|
|
public var project: SongProject
|
|
public var sourceLyrics: Lyrics
|
|
public var mode: LyricsRevisionMode
|
|
|
|
public init(
|
|
context: AIRequestContext,
|
|
project: SongProject,
|
|
sourceLyrics: Lyrics,
|
|
mode: LyricsRevisionMode
|
|
) {
|
|
self.context = context
|
|
self.project = project
|
|
self.sourceLyrics = sourceLyrics
|
|
self.mode = mode
|
|
}
|
|
}
|
|
|
|
public enum LyricsRevisionMode: String, Equatable, Sendable {
|
|
case writeFromIdea
|
|
case correct
|
|
case improve
|
|
case restructure
|
|
case complete
|
|
}
|
|
|
|
public struct LyricsRevisionResult: Equatable, Sendable {
|
|
public var lyrics: Lyrics
|
|
public var notes: [String]
|
|
|
|
public init(lyrics: Lyrics, notes: [String] = []) {
|
|
self.lyrics = lyrics
|
|
self.notes = notes
|
|
}
|
|
}
|
|
|
|
public struct SongProjectUpdateRequest: Equatable, Sendable {
|
|
public var context: AIRequestContext
|
|
public var project: SongProject
|
|
public var allowedScopes: [SongProjectUpdateScope]
|
|
|
|
public init(
|
|
context: AIRequestContext,
|
|
project: SongProject,
|
|
allowedScopes: [SongProjectUpdateScope]
|
|
) {
|
|
self.context = context
|
|
self.project = project
|
|
self.allowedScopes = allowedScopes
|
|
}
|
|
}
|
|
|
|
public struct SongProjectUpdateResult: Equatable, Sendable {
|
|
public var project: SongProject
|
|
public var changedScopes: [SongProjectUpdateScope]
|
|
public var notes: [String]
|
|
public var followUpQuestions: [String]
|
|
|
|
public init(
|
|
project: SongProject,
|
|
changedScopes: [SongProjectUpdateScope] = [],
|
|
notes: [String] = [],
|
|
followUpQuestions: [String] = []
|
|
) {
|
|
self.project = project
|
|
self.changedScopes = changedScopes
|
|
self.notes = notes
|
|
self.followUpQuestions = followUpQuestions
|
|
}
|
|
}
|