@@ -578,6 +578,7 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
578578 } ) ;
579579
580580 process . env . OPEN_DESIGN_OBJECT_RELAY_URL = 'https://telemetry.open-design.ai/api/objects/batch' ;
581+ process . env . OPEN_DESIGN_TELEMETRY_RELAY_URL = 'https://telemetry.open-design.ai/api/langfuse' ;
581582 process . env . LANGFUSE_PUBLIC_KEY = 'pk' ;
582583 process . env . LANGFUSE_SECRET_KEY = 'sk' ;
583584 try {
@@ -613,14 +614,17 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
613614 } ) ;
614615 } finally {
615616 delete process . env . OPEN_DESIGN_OBJECT_RELAY_URL ;
617+ delete process . env . OPEN_DESIGN_TELEMETRY_RELAY_URL ;
616618 delete process . env . LANGFUSE_PUBLIC_KEY ;
617619 delete process . env . LANGFUSE_SECRET_KEY ;
618620 }
619621
620- expect ( fetchSpy ) . toHaveBeenCalledTimes ( 3 ) ;
621- expect ( fetchSpy . mock . calls [ 0 ] ! [ 0 ] ) . toContain ( '/api/objects/authorize' ) ;
622- expect ( fetchSpy . mock . calls [ 1 ] ! [ 0 ] ) . toContain ( '/api/objects/batch' ) ;
623- const langfuseInit = fetchSpy . mock . calls [ 2 ] ! [ 1 ] as RequestInit ;
622+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 4 ) ;
623+ expect ( fetchSpy . mock . calls [ 0 ] ! [ 0 ] ) . toContain ( '/api/langfuse' ) ;
624+ expect ( fetchSpy . mock . calls [ 1 ] ! [ 0 ] ) . toContain ( '/api/objects/authorize' ) ;
625+ expect ( fetchSpy . mock . calls [ 2 ] ! [ 0 ] ) . toContain ( '/api/objects/batch' ) ;
626+ expect ( fetchSpy . mock . calls [ 3 ] ! [ 0 ] ) . toContain ( '/api/langfuse' ) ;
627+ const langfuseInit = fetchSpy . mock . calls [ 3 ] ! [ 1 ] as RequestInit ;
624628 const langfuseBody = langfuseInit . body as string ;
625629 expect ( langfuseBody ) . not . toContain ( 'attachment body should stay out of langfuse' ) ;
626630 expect ( langfuseBody ) . not . toContain ( '<!doctype html><h1>artifact body</h1>' ) ;
@@ -658,6 +662,88 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
658662 ) ;
659663 } ) ;
660664
665+ it ( 'registers object upload authority through the object relay when traces use direct Langfuse' , async ( ) => {
666+ await writeAppCfg ( {
667+ installationId : 'install-uuid-1' ,
668+ telemetry : { metrics : true , content : true , artifactManifest : true } ,
669+ } ) ;
670+ const projectDir = path . join ( dataDir , 'projects' , 'proj-1' ) ;
671+ await mkdir ( projectDir , { recursive : true } ) ;
672+ await writeFile ( path . join ( projectDir , 'index.html' ) , '<!doctype html><h1>artifact body</h1>' ) ;
673+ const fetchSpy = vi . fn ( async ( url : string , init : RequestInit ) => {
674+ if ( url . includes ( '/api/objects/authorize' ) ) {
675+ const parsed = JSON . parse ( init . body as string ) as {
676+ objects : Array < { storage_ref : string ; object_class : string } > ;
677+ } ;
678+ expect ( parsed . objects ) . toHaveLength ( 1 ) ;
679+ expect ( parsed . objects [ 0 ] ) . toMatchObject ( { object_class : 'artifact' } ) ;
680+ return new Response ( JSON . stringify ( { upload_token : 'upload-token' } ) , { status : 200 } ) ;
681+ }
682+ if ( url . includes ( '/api/objects/batch' ) ) {
683+ const parsed = JSON . parse ( init . body as string ) as {
684+ objects : Array < { storage_ref : string ; content_base64 : string } > ;
685+ } ;
686+ return new Response (
687+ JSON . stringify ( {
688+ objects : parsed . objects . map ( ( object ) => ( {
689+ storage_ref : object . storage_ref ,
690+ status : 'available' ,
691+ size_bytes : Buffer . from ( object . content_base64 , 'base64' ) . byteLength ,
692+ sha256 : 'sha256:uploaded-artifact' ,
693+ } ) ) ,
694+ } ) ,
695+ { status : 200 } ,
696+ ) ;
697+ }
698+ return new Response ( '{}' , { status : 207 } ) ;
699+ } ) ;
700+
701+ process . env . OPEN_DESIGN_OBJECT_RELAY_URL = 'https://telemetry.open-design.ai/api/objects/batch' ;
702+ process . env . LANGFUSE_PUBLIC_KEY = 'pk' ;
703+ process . env . LANGFUSE_SECRET_KEY = 'sk' ;
704+ try {
705+ await reportRunCompletedFromDaemon ( {
706+ db : makeDbWithListMessages ( {
707+ 'conv-1' : [
708+ { id : 'user-1' , role : 'user' , content : 'Build it.' } ,
709+ {
710+ id : 'msg-1' ,
711+ role : 'assistant' ,
712+ content : 'done' ,
713+ producedFiles : [ { name : 'index.html' , kind : 'html' , size : 35 } ] ,
714+ } ,
715+ ] ,
716+ } ) ,
717+ dataDir,
718+ run : makeRun ( ) as any ,
719+ fetchImpl : fetchSpy as any ,
720+ } ) ;
721+ } finally {
722+ delete process . env . OPEN_DESIGN_OBJECT_RELAY_URL ;
723+ delete process . env . LANGFUSE_PUBLIC_KEY ;
724+ delete process . env . LANGFUSE_SECRET_KEY ;
725+ }
726+
727+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 4 ) ;
728+ expect ( fetchSpy . mock . calls [ 0 ] ! [ 0 ] ) . toBe ( 'https://telemetry.open-design.ai/api/langfuse' ) ;
729+ expect ( fetchSpy . mock . calls [ 1 ] ! [ 0 ] ) . toBe ( 'https://telemetry.open-design.ai/api/objects/authorize' ) ;
730+ expect ( fetchSpy . mock . calls [ 2 ] ! [ 0 ] ) . toBe ( 'https://telemetry.open-design.ai/api/objects/batch' ) ;
731+ expect ( fetchSpy . mock . calls [ 3 ] ! [ 0 ] ) . toBe ( 'https://us.cloud.langfuse.com/api/public/ingestion' ) ;
732+ const registrationBatch = JSON . parse ( fetchSpy . mock . calls [ 0 ] ! [ 1 ] ! . body as string ) . batch as any [ ] ;
733+ const finalBatch = JSON . parse ( fetchSpy . mock . calls [ 3 ] ! [ 1 ] ! . body as string ) . batch as any [ ] ;
734+ expect ( registrationBatch [ 0 ] . body . metadata . artifact_manifest [ 0 ] ) . toMatchObject ( {
735+ object_class : 'artifact' ,
736+ storage_ref : expect . stringContaining (
737+ 'od://objects/workspaces/unknown/projects/proj-1/runs/run-id-1/artifact/' ,
738+ ) ,
739+ } ) ;
740+ expect ( finalBatch [ 0 ] . body . metadata . artifact_manifest [ 0 ] ) . toMatchObject ( {
741+ object_class : 'artifact' ,
742+ status : 'ok' ,
743+ stored_in_open_design : true ,
744+ } ) ;
745+ } ) ;
746+
661747 it ( 'derives manifest completeness from merged uploaded and fallback manifests' , async ( ) => {
662748 await writeAppCfg ( {
663749 installationId : 'install-uuid-1' ,
@@ -695,6 +781,7 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
695781 } ) ;
696782
697783 process . env . OPEN_DESIGN_OBJECT_RELAY_URL = 'https://telemetry.open-design.ai/api/objects/batch' ;
784+ process . env . OPEN_DESIGN_TELEMETRY_RELAY_URL = 'https://telemetry.open-design.ai/api/langfuse' ;
698785 process . env . LANGFUSE_PUBLIC_KEY = 'pk' ;
699786 process . env . LANGFUSE_SECRET_KEY = 'sk' ;
700787 try {
@@ -721,12 +808,16 @@ describe('langfuse-bridge.reportRunCompletedFromDaemon', () => {
721808 } ) ;
722809 } finally {
723810 delete process . env . OPEN_DESIGN_OBJECT_RELAY_URL ;
811+ delete process . env . OPEN_DESIGN_TELEMETRY_RELAY_URL ;
724812 delete process . env . LANGFUSE_PUBLIC_KEY ;
725813 delete process . env . LANGFUSE_SECRET_KEY ;
726814 }
727815
728- expect ( fetchSpy ) . toHaveBeenCalledTimes ( 3 ) ;
729- const langfuseInit = fetchSpy . mock . calls [ 2 ] ! [ 1 ] as RequestInit ;
816+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 4 ) ;
817+ expect ( fetchSpy . mock . calls [ 0 ] ! [ 0 ] ) . toContain ( '/api/langfuse' ) ;
818+ expect ( fetchSpy . mock . calls [ 1 ] ! [ 0 ] ) . toContain ( '/api/objects/authorize' ) ;
819+ expect ( fetchSpy . mock . calls [ 2 ] ! [ 0 ] ) . toContain ( '/api/objects/batch' ) ;
820+ const langfuseInit = fetchSpy . mock . calls [ 3 ] ! [ 1 ] as RequestInit ;
730821 const batch = JSON . parse ( langfuseInit . body as string ) . batch as any [ ] ;
731822 const trace = batch [ 0 ] . body ;
732823 expect ( trace . metadata . manifest_completeness ) . toBe ( 'partial' ) ;
0 commit comments