11import { DurableObject } from "cloudflare:workers"
22import { randomUUID } from "node:crypto"
3+ import { Base64 } from "js-base64"
34
45type Env = {
56 SYNC_SERVER : DurableObjectNamespace < SyncServer >
@@ -180,8 +181,12 @@ export default {
180181 return new Response ( "Error: Share ID is required" , { status : 400 } )
181182 const stub = env . SYNC_SERVER . get ( env . SYNC_SERVER . idFromName ( id ) )
182183 const data = await stub . getData ( )
184+
183185 let info
184- const messages = { }
186+ const messages : Record < string , any > = { }
187+ let cost = 0
188+ const models : Set < string > = new Set ( )
189+ const version = "v0.1.1"
185190 data . forEach ( ( d ) => {
186191 const [ root , type , ...splits ] = d . key . split ( "/" )
187192 if ( root !== "session" ) return
@@ -192,12 +197,36 @@ export default {
192197 if ( type === "message" ) {
193198 const [ , messageID ] = splits
194199 messages [ messageID ] = d . content
200+
201+ const assistant = d . content . metadata ?. assistant
202+ if ( assistant ) {
203+ cost += assistant . cost
204+ models . add ( assistant . modelID )
205+ }
195206 }
196207 } )
197208
198- return new Response ( JSON . stringify ( { info, messages } ) , {
199- headers : { "Content-Type" : "application/json" } ,
200- } )
209+ const encodedTitle = encodeURIComponent (
210+ Base64 . encode (
211+ // Convert to ASCII
212+ encodeURIComponent (
213+ // Truncate to fit S3's max key size
214+ info . title . substring ( 0 , 700 ) ,
215+ ) ,
216+ ) ,
217+ )
218+ const encodedCost = encodeURIComponent ( `$${ cost . toFixed ( 2 ) } ` )
219+
220+ return new Response (
221+ JSON . stringify ( {
222+ info,
223+ messages,
224+ ogImage : `https://social-cards.sst.dev/opencode-share/${ encodedTitle } .png?cost=${ encodedCost } &model=${ Array . from ( models ) . join ( "," ) } &version=${ version } &id=${ id } ` ,
225+ } ) ,
226+ {
227+ headers : { "Content-Type" : "application/json" } ,
228+ } ,
229+ )
201230 }
202231 } ,
203232}
0 commit comments