🌳
pt0/gamesapp/serverF/addAiDrawingsToStacksAI.mts
9export const findStacksNeedingAiDrawing = ({existingGame}: {existingGame: any}) => {
10 const {hiddenState} = existingGame
11 const {paperStacks} = hiddenState || {}
12 if (!paperStacks) return []
14 const stacksNeedingDrawing = []
16 for (const [stackName, stack] of Object.entries(paperStacks) as [string, any][]) {
17 const {responses} = stack
18 if (!responses || responses.length === 0) continue
20 // Skip if stack already has AI drawing (from mid-game aiDrawingAfterFirstHumanDescript)
21 if (responses.some((r: any) => r.isAiGenerated)) continue
23 const lastResp = responses[responses.length - 1]
24 if (lastResp?.lastDescription && !respHasDrawing(lastResp)) {
25 stacksNeedingDrawing.push({
26 stackName,
27 descriptionText: lastResp.lastDescription,
28 })
29 }
30 }
32 return stacksNeedingDrawing
35export const addAiDrawingsToStacks = async ({existingGame}: {existingGame: any}) => {
36 if (existingGame.settings && !existingGame.settings.aiDrawEnabled) return []
38 const stacksNeedingDrawing = findStacksNeedingAiDrawing({existingGame})
39 if (stacksNeedingDrawing.length === 0) return []
41 const {hiddenState} = existingGame
42 const {paperStacks} = hiddenState
44 const results = await Promise.all(
45 stacksNeedingDrawing.map(async ({stackName, descriptionText}) => {
46 const triedModels = [defaultAiDrawModel, ...fallbackAiDrawModels]
47 const result = await tryWithModelFallback({
48 candidates: triedModels,
49 callFn: (model) => aiDrawDescription({descriptionText, model}),
50 context: 'addAiDrawingsToStacks',
51 })
52 if (!result) {
53 await noThrowNotifErr('aiDrawAllModelsExhausted', {stackName, triedModels})
54 }
55 return {stackName, descriptionText, result}
56 })
57 )
59 const successCount = results.filter(r => r.result).length
60 if (successCount < stacksNeedingDrawing.length) {
61 betLog('addAiDrawingsToStacks partial failure', {attempted: stacksNeedingDrawing.length, succeeded: successCount})
62 }
64 const aiActionHistA = []
66 for (const {stackName, descriptionText, result} of results) {
67 if (!result) continue
69 const {ipfsCid, model, costUsd, genTimeMs} = result
70 const modelDerivedAlias = model === 'mock' ? 'mock' : (getShortModelName(model) || 'ai')
71 const displayAlias = existingGame.settings?.aiDrawerUsername || modelDerivedAlias
73 const stack = paperStacks[stackName]
74 stack.responses.push({
75 lastIpfsCid: ipfsCid,
76 playerAlias: displayAlias,
77 aiModelAlias: modelDerivedAlias,
78 isAiGenerated: true,
79 aiCostUsd: costUsd,
80 aiGenTimeMs: genTimeMs,
81 })
83 aiActionHistA.push({
84 sessId: `ai-${model}`,
85 actionAtMs: Date.now(),
86 playerAction: 'submitDrawing',
87 ipfsCid,
88 assignedStackName: stackName,
89 isAiGenerated: true,
90 aiModel: model,
91 aiPrompt: descriptionText,
92 aiCostUsd: costUsd,
93 aiGenTimeMs: genTimeMs,
94 })
95 }
97 return aiActionHistA