@@ -30,6 +30,7 @@ import (
3030 errorsx "github.com/instill-ai/x/errors"
3131 filetype "github.com/instill-ai/x/file"
3232 logx "github.com/instill-ai/x/log"
33+ "github.com/instill-ai/x/resource"
3334)
3435
3536// filterRequestWrapper implements filtering.Request interface to pass a custom filter string
@@ -63,6 +64,16 @@ func parseFileFromName(name string) (namespaceID, fileID string, err error) {
6364 return parts [1 ], parts [3 ], nil
6465}
6566
67+ // parseObjectIDFromResourceName parses an object resource name of format "namespaces/{namespace}/objects/{object_id}"
68+ // and returns the object_id
69+ func parseObjectIDFromResourceName (name string ) (objectID string , err error ) {
70+ parts := strings .Split (name , "/" )
71+ if len (parts ) != 4 || parts [0 ] != "namespaces" || parts [2 ] != "objects" {
72+ return "" , fmt .Errorf ("invalid object resource name format, expected namespaces/{namespace}/objects/{object_id}" )
73+ }
74+ return parts [3 ], nil
75+ }
76+
6677// CreateFile adds a file to a knowledge base (AIP-compliant version of UploadKnowledgeBaseFile).
6778// It handles file upload, validation, ACL checks, dual processing for staging/rollback KBs,
6879// and auto-triggers the processing workflow.
@@ -101,8 +112,11 @@ func (ph *PublicHandler) CreateFile(ctx context.Context, req *artifactpb.CreateF
101112 )
102113 }
103114 // ACL - check user's permission to write knowledge base
104- kbID := req .GetKnowledgeBaseId ()
115+ // Parse knowledge_base resource name: namespaces/{namespace}/knowledgeBases/{kb}
116+ kbResourceName := req .GetKnowledgeBase ()
117+ kbID := resource .ExtractResourceID (kbResourceName )
105118 logger .Debug ("CreateFile: looking up KB" ,
119+ zap .String ("knowledge_base" , kbResourceName ),
106120 zap .String ("knowledge_base_id" , kbID ),
107121 zap .String ("namespace_uid" , ns .NsUID .String ()),
108122 zap .String ("namespace_id" , ns .NsID ))
@@ -282,13 +296,27 @@ func (ph *PublicHandler) CreateFile(ctx context.Context, req *artifactpb.CreateF
282296
283297 kbFile .CreatorUID = creatorUID
284298 kbFile .StoragePath = destination
299+ // Store the object FK for the new AIP-compliant object reference
300+ objUID := types .ObjectUIDType (objectUID )
301+ kbFile .ObjectUID = & objUID
285302
286303 fileSize , _ := getFileSize (req .File .Content )
287304 kbFile .Size = fileSize
288305 } else {
289- obj , err := ph .service .Repository ().GetObjectByUID (ctx , uuid .FromStringOrNil (req .GetFile ().GetObjectUid ()))
306+ // Parse object resource name: namespaces/{namespace}/objects/{object_id}
307+ objectResourceName := req .GetFile ().GetObject ()
308+ objectID , err := parseObjectIDFromResourceName (objectResourceName )
309+ if err != nil {
310+ return nil , errorsx .AddMessage (
311+ fmt .Errorf ("parsing object resource name: %w" , err ),
312+ "Invalid object resource name. Expected format: namespaces/{namespace}/objects/{object_id}" ,
313+ )
314+ }
315+
316+ // Get object by hash-based ID
317+ obj , err := ph .service .Repository ().GetObjectByID (ctx , ns .NsUID , types .ObjectIDType (objectID ))
290318 if err != nil {
291- logger .Error ("failed to get knowledge base object with provided UID " , zap .Error (err ))
319+ logger .Error ("failed to get object by ID " , zap .Error (err ), zap . String ( "object_id" , objectID ))
292320 return nil , err
293321 }
294322
@@ -324,6 +352,8 @@ func (ph *PublicHandler) CreateFile(ctx context.Context, req *artifactpb.CreateF
324352 kbFile .CreatorUID = obj .CreatorUID
325353 kbFile .StoragePath = obj .StoragePath
326354 kbFile .Size = obj .Size
355+ // Store the object FK for the new AIP-compliant object reference
356+ kbFile .ObjectUID = & obj .UID
327357
328358 req .File .Type = determineFileType (obj .DisplayName )
329359
@@ -555,14 +585,23 @@ func (ph *PublicHandler) CreateFile(ctx context.Context, req *artifactpb.CreateF
555585 owner , _ := ph .service .FetchOwnerByNamespace (ctx , ns )
556586 creator , _ := ph .service .FetchUserByUID (ctx , res .CreatorUID .String ())
557587
588+ // Get object ID for AIP-122 compliant resource name
589+ objectResourceName := ""
590+ if res .ObjectUID != nil {
591+ obj , err := ph .service .Repository ().GetObjectByUID (ctx , * res .ObjectUID )
592+ if err == nil && obj != nil {
593+ objectResourceName = fmt .Sprintf ("namespaces/%s/objects/%s" , namespaceID , obj .ID )
594+ }
595+ }
596+
558597 return & artifactpb.CreateFileResponse {
559598 File : & artifactpb.File {
560599 Id : res .ID ,
561600 Slug : res .Slug ,
562601 OwnerName : ns .Name (),
563602 Owner : owner ,
564603 Creator : creator ,
565- KnowledgeBaseIds : []string {kb .ID }, // Initial KB association
604+ KnowledgeBases : []string {fmt . Sprintf ( "namespaces/%s/knowledgeBases/%s" , namespaceID , kb .ID ) }, // Initial KB association
566605 Name : fmt .Sprintf ("namespaces/%s/files/%s" , namespaceID , res .ID ),
567606 DisplayName : res .DisplayName ,
568607 Type : req .File .Type ,
@@ -573,10 +612,10 @@ func (ph *PublicHandler) CreateFile(ctx context.Context, req *artifactpb.CreateF
573612 TotalChunks : 0 ,
574613 TotalTokens : 0 ,
575614 ExternalMetadata : res .PublicExternalMetadataUnmarshal (),
576- ObjectUid : req . File . ObjectUid ,
615+ Object : objectResourceName ,
577616 ConvertingPipeline : res .ConvertingPipeline (),
578617 Tags : res .Tags ,
579- CollectionIds : extractCollectionUIDs (res .Tags ),
618+ Collections : extractCollectionUIDs (res .Tags ),
580619 },
581620 }, nil
582621}
@@ -906,13 +945,31 @@ func (ph *PublicHandler) ListFiles(ctx context.Context, req *artifactpb.ListFile
906945 knowledgeBaseIDs = fileToKBIDs [kbFile .UID ]
907946 }
908947
948+ // Get object ID for AIP-122 compliant resource name
949+ objectID := ""
950+ objectResourceName := ""
951+ if kbFile .ObjectUID != nil {
952+ obj , err := ph .service .Repository ().GetObjectByUID (ctx , * kbFile .ObjectUID )
953+ if err == nil && obj != nil {
954+ objectID = string (obj .ID )
955+ objectResourceName = fmt .Sprintf ("namespaces/%s/objects/%s" , namespaceID , objectID )
956+ }
957+ } else if objectUID != uuid .Nil {
958+ // Fallback: try to get object by UID parsed from storage path
959+ obj , err := ph .service .Repository ().GetObjectByUID (ctx , types .ObjectUIDType (objectUID ))
960+ if err == nil && obj != nil {
961+ objectID = string (obj .ID )
962+ objectResourceName = fmt .Sprintf ("namespaces/%s/objects/%s" , namespaceID , objectID )
963+ }
964+ }
965+
909966 file := & artifactpb.File {
910967 Id : fileID ,
911968 Slug : kbFile .Slug ,
912969 OwnerName : ns .Name (),
913970 Owner : owner ,
914971 Creator : creator ,
915- KnowledgeBaseIds : knowledgeBaseIDs ,
972+ KnowledgeBases : knowledgeBaseIDs ,
916973 Name : fmt .Sprintf ("namespaces/%s/files/%s" , namespaceID , fileID ),
917974 DisplayName : kbFile .DisplayName ,
918975 Type : artifactpb .File_Type (artifactpb .File_Type_value [kbFile .FileType ]),
@@ -923,11 +980,11 @@ func (ph *PublicHandler) ListFiles(ctx context.Context, req *artifactpb.ListFile
923980 ExternalMetadata : kbFile .PublicExternalMetadataUnmarshal (),
924981 TotalChunks : int32 (totalChunks [kbFile .UID ]),
925982 TotalTokens : int32 (totalTokens [kbFile .UID ]),
926- ObjectUid : objectUID . String () ,
983+ Object : objectResourceName ,
927984 DownloadUrl : downloadURL ,
928985 ConvertingPipeline : kbFile .ConvertingPipeline (),
929986 Tags : []string (kbFile .Tags ),
930- CollectionIds : extractCollectionUIDs (kbFile .Tags ),
987+ Collections : extractCollectionUIDs (kbFile .Tags ),
931988 }
932989
933990 // Include status message (error or success message)
@@ -1478,7 +1535,7 @@ func (ph *PublicHandler) DeleteFile(ctx context.Context, req *artifactpb.DeleteF
14781535 logger , _ := logx .GetZapLogger (ctx )
14791536
14801537 // Parse resource name to get namespace_id and file_id
1481- _ , fileID , err := parseFileFromName (req .GetName ())
1538+ namespaceID , fileID , err := parseFileFromName (req .GetName ())
14821539 if err != nil {
14831540 return nil , errorsx .AddMessage (
14841541 fmt .Errorf ("parsing file name: %w" , err ),
@@ -1772,7 +1829,7 @@ func (ph *PublicHandler) DeleteFile(ctx context.Context, req *artifactpb.DeleteF
17721829 }
17731830
17741831 return & artifactpb.DeleteFileResponse {
1775- FileId : fUID .String (),
1832+ Name : fmt . Sprintf ( "namespaces/%s/files/%s" , namespaceID , fUID .String () ),
17761833 }, nil
17771834
17781835}
@@ -1952,8 +2009,17 @@ func (ph *PublicHandler) UpdateFile(ctx context.Context, req *artifactpb.UpdateF
19522009 owner , _ := ph .service .FetchOwnerByNamespace (ctx , ns )
19532010 creator , _ := ph .service .FetchUserByUID (ctx , updatedFile .CreatorUID .String ())
19542011
2012+ // Get object ID if file has an associated object (for AIP-122 compliant resource reference)
2013+ objectID := ""
2014+ if updatedFile .ObjectUID != nil {
2015+ obj , err := ph .service .Repository ().GetObjectByUID (ctx , * updatedFile .ObjectUID )
2016+ if err == nil && obj != nil {
2017+ objectID = string (obj .ID )
2018+ }
2019+ }
2020+
19552021 // Convert to protobuf
1956- pbFile := convertKBFileToPB (updatedFile , ns , kb , owner , creator )
2022+ pbFile := convertKBFileToPB (updatedFile , ns , kb , owner , creator , objectID )
19572023
19582024 return & artifactpb.UpdateFileResponse {
19592025 File : pbFile ,
@@ -2117,8 +2183,17 @@ func (ph *PublicHandler) ReprocessFile(ctx context.Context, req *artifactpb.Repr
21172183 owner , _ := ph .service .FetchOwnerByNamespace (ctx , ns )
21182184 creator , _ := ph .service .FetchUserByUID (ctx , updatedFile .CreatorUID .String ())
21192185
2186+ // Get object ID if file has an associated object (for AIP-122 compliant resource reference)
2187+ objectID := ""
2188+ if updatedFile .ObjectUID != nil {
2189+ obj , err := ph .service .Repository ().GetObjectByUID (ctx , * updatedFile .ObjectUID )
2190+ if err == nil && obj != nil {
2191+ objectID = string (obj .ID )
2192+ }
2193+ }
2194+
21202195 // Convert to protobuf response with updated file status
2121- pbFile := convertKBFileToPB (& updatedFile , ns , kb , owner , creator )
2196+ pbFile := convertKBFileToPB (& updatedFile , ns , kb , owner , creator , objectID )
21222197
21232198 return & artifactpb.ReprocessFileResponse {
21242199 File : pbFile ,
@@ -2261,13 +2336,13 @@ func getPositionUnit(fileType artifactpb.File_Type) artifactpb.File_Position_Uni
22612336 return artifactpb .File_Position_UNIT_UNSPECIFIED
22622337}
22632338
2264- // Check if objectUID is provided, and all other required fields if not
2339+ // Check if object is provided, and all other required fields if not
22652340func checkUploadKnowledgeBaseFileRequest (req * artifactpb.CreateFileRequest ) (hasObject bool , _ error ) {
22662341 if req .GetParent () == "" {
22672342 return false , fmt .Errorf ("%w: parent is required" , errorsx .ErrInvalidArgument )
22682343 }
22692344
2270- if req .GetFile ().GetObjectUid () == "" {
2345+ if req .GetFile ().GetObject () == "" {
22712346 // File upload doesn't reference object, so request must contain the
22722347 // file contents.
22732348 if req .GetFile ().GetDisplayName () == "" {
0 commit comments