Compare commits

...

7 Commits

32 changed files with 2874 additions and 83 deletions

View File

@ -78,3 +78,23 @@ func ApplyUploadAction(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, resp)
}
// RecordFileInfo .
// @router /api/common/record_file_info [POST]
func RecordFileInfo(ctx context.Context, c *app.RequestContext) {
var err error
var req upload.RecordFileInfoRequest
err = c.BindAndValidate(&req)
if err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp, err := uploadSVC.SVC.RecordFileInfo(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}

View File

@ -2454,7 +2454,7 @@ func TestStartNodeDefaultValues(t *testing.T) {
result, _ := r.openapiSyncRun(idStr, input)
assert.Equal(t, result, map[string]any{
"ts": "2025-07-09 21:43:34",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image?x-wf-file_name=20250317-154742.jpeg",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image",
"str": "str",
"object": map[string]any{
"a": "1",
@ -2478,7 +2478,7 @@ func TestStartNodeDefaultValues(t *testing.T) {
result, _ := r.openapiSyncRun(idStr, input)
assert.Equal(t, result, map[string]any{
"ts": "2025-07-09 21:43:34",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image?x-wf-file_name=20250317-154742.jpeg",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image",
"str": "str",
"object": map[string]any{
"a": "1",
@ -2503,7 +2503,7 @@ func TestStartNodeDefaultValues(t *testing.T) {
result, _ := r.openapiSyncRun(idStr, input)
assert.Equal(t, result, map[string]any{
"ts": "2025-07-09 21:43:34",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image?x-wf-file_name=20250317-154742.jpeg",
"files": "http://imagex.fanlv.fun/tos-cn-i-1heqlfnr21/e81acc11277f421390770618e24e01ce.jpeg~tplv-1heqlfnr21-image.image",
"str": "value",
"object": map[string]any{
"a": "1",

View File

@ -1,3 +1,19 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Code generated by thriftgo (0.4.1). DO NOT EDIT.
package upload
@ -6,6 +22,7 @@ import (
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"github.com/coze-dev/coze-studio/backend/api/model/base"
)
type CommonUploadRequest struct {
@ -4592,10 +4609,575 @@ func (p *ApplyUploadActionResponse) String() string {
}
type RecordFileInfoRequest struct {
FileURI string `thrift:"FileURI,1,required" form:"FileURI,required" json:"FileURI,required" query:"FileURI,required"`
FileName string `thrift:"FileName,2,required" form:"FileName,required" json:"FileName,required" query:"FileName,required"`
FileSize *string `thrift:"FileSize,3,optional" form:"FileSize" json:"FileSize,omitempty" query:"FileSize"`
FileExtension *string `thrift:"FileExtension,4,optional" form:"FileExtension" json:"FileExtension,omitempty" query:"FileExtension"`
}
func NewRecordFileInfoRequest() *RecordFileInfoRequest {
return &RecordFileInfoRequest{}
}
func (p *RecordFileInfoRequest) InitDefault() {
}
func (p *RecordFileInfoRequest) GetFileURI() (v string) {
return p.FileURI
}
func (p *RecordFileInfoRequest) GetFileName() (v string) {
return p.FileName
}
var RecordFileInfoRequest_FileSize_DEFAULT string
func (p *RecordFileInfoRequest) GetFileSize() (v string) {
if !p.IsSetFileSize() {
return RecordFileInfoRequest_FileSize_DEFAULT
}
return *p.FileSize
}
var RecordFileInfoRequest_FileExtension_DEFAULT string
func (p *RecordFileInfoRequest) GetFileExtension() (v string) {
if !p.IsSetFileExtension() {
return RecordFileInfoRequest_FileExtension_DEFAULT
}
return *p.FileExtension
}
var fieldIDToName_RecordFileInfoRequest = map[int16]string{
1: "FileURI",
2: "FileName",
3: "FileSize",
4: "FileExtension",
}
func (p *RecordFileInfoRequest) IsSetFileSize() bool {
return p.FileSize != nil
}
func (p *RecordFileInfoRequest) IsSetFileExtension() bool {
return p.FileExtension != nil
}
func (p *RecordFileInfoRequest) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
var issetFileURI bool = false
var issetFileName bool = false
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
issetFileURI = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.STRING {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
issetFileName = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 3:
if fieldTypeId == thrift.STRING {
if err = p.ReadField3(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 4:
if fieldTypeId == thrift.STRING {
if err = p.ReadField4(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
if !issetFileURI {
fieldId = 1
goto RequiredFieldNotSetError
}
if !issetFileName {
fieldId = 2
goto RequiredFieldNotSetError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_RecordFileInfoRequest[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
RequiredFieldNotSetError:
return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("required field %s is not set", fieldIDToName_RecordFileInfoRequest[fieldId]))
}
func (p *RecordFileInfoRequest) ReadField1(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.FileURI = _field
return nil
}
func (p *RecordFileInfoRequest) ReadField2(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.FileName = _field
return nil
}
func (p *RecordFileInfoRequest) ReadField3(iprot thrift.TProtocol) error {
var _field *string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = &v
}
p.FileSize = _field
return nil
}
func (p *RecordFileInfoRequest) ReadField4(iprot thrift.TProtocol) error {
var _field *string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = &v
}
p.FileExtension = _field
return nil
}
func (p *RecordFileInfoRequest) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("RecordFileInfoRequest"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField3(oprot); err != nil {
fieldId = 3
goto WriteFieldError
}
if err = p.writeField4(oprot); err != nil {
fieldId = 4
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *RecordFileInfoRequest) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("FileURI", thrift.STRING, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.FileURI); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *RecordFileInfoRequest) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("FileName", thrift.STRING, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.FileName); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *RecordFileInfoRequest) writeField3(oprot thrift.TProtocol) (err error) {
if p.IsSetFileSize() {
if err = oprot.WriteFieldBegin("FileSize", thrift.STRING, 3); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(*p.FileSize); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
}
func (p *RecordFileInfoRequest) writeField4(oprot thrift.TProtocol) (err error) {
if p.IsSetFileExtension() {
if err = oprot.WriteFieldBegin("FileExtension", thrift.STRING, 4); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(*p.FileExtension); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 end error: ", p), err)
}
func (p *RecordFileInfoRequest) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("RecordFileInfoRequest(%+v)", *p)
}
type RecordFileInfoResponse struct {
Code int64 `thrift:"code,253,required" form:"code,required" json:"code,required" query:"code,required"`
Msg string `thrift:"msg,254,required" form:"msg,required" json:"msg,required" query:"msg,required"`
BaseResp *base.BaseResp `thrift:"BaseResp,255,optional" form:"-" json:"-" query:"-"`
}
func NewRecordFileInfoResponse() *RecordFileInfoResponse {
return &RecordFileInfoResponse{}
}
func (p *RecordFileInfoResponse) InitDefault() {
}
func (p *RecordFileInfoResponse) GetCode() (v int64) {
return p.Code
}
func (p *RecordFileInfoResponse) GetMsg() (v string) {
return p.Msg
}
var RecordFileInfoResponse_BaseResp_DEFAULT *base.BaseResp
func (p *RecordFileInfoResponse) GetBaseResp() (v *base.BaseResp) {
if !p.IsSetBaseResp() {
return RecordFileInfoResponse_BaseResp_DEFAULT
}
return p.BaseResp
}
var fieldIDToName_RecordFileInfoResponse = map[int16]string{
253: "code",
254: "msg",
255: "BaseResp",
}
func (p *RecordFileInfoResponse) IsSetBaseResp() bool {
return p.BaseResp != nil
}
func (p *RecordFileInfoResponse) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
var issetCode bool = false
var issetMsg bool = false
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 253:
if fieldTypeId == thrift.I64 {
if err = p.ReadField253(iprot); err != nil {
goto ReadFieldError
}
issetCode = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 254:
if fieldTypeId == thrift.STRING {
if err = p.ReadField254(iprot); err != nil {
goto ReadFieldError
}
issetMsg = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 255:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField255(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
if !issetCode {
fieldId = 253
goto RequiredFieldNotSetError
}
if !issetMsg {
fieldId = 254
goto RequiredFieldNotSetError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_RecordFileInfoResponse[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
RequiredFieldNotSetError:
return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("required field %s is not set", fieldIDToName_RecordFileInfoResponse[fieldId]))
}
func (p *RecordFileInfoResponse) ReadField253(iprot thrift.TProtocol) error {
var _field int64
if v, err := iprot.ReadI64(); err != nil {
return err
} else {
_field = v
}
p.Code = _field
return nil
}
func (p *RecordFileInfoResponse) ReadField254(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Msg = _field
return nil
}
func (p *RecordFileInfoResponse) ReadField255(iprot thrift.TProtocol) error {
_field := base.NewBaseResp()
if err := _field.Read(iprot); err != nil {
return err
}
p.BaseResp = _field
return nil
}
func (p *RecordFileInfoResponse) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("RecordFileInfoResponse"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField253(oprot); err != nil {
fieldId = 253
goto WriteFieldError
}
if err = p.writeField254(oprot); err != nil {
fieldId = 254
goto WriteFieldError
}
if err = p.writeField255(oprot); err != nil {
fieldId = 255
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *RecordFileInfoResponse) writeField253(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("code", thrift.I64, 253); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteI64(p.Code); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 253 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 253 end error: ", p), err)
}
func (p *RecordFileInfoResponse) writeField254(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("msg", thrift.STRING, 254); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Msg); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 254 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 254 end error: ", p), err)
}
func (p *RecordFileInfoResponse) writeField255(oprot thrift.TProtocol) (err error) {
if p.IsSetBaseResp() {
if err = oprot.WriteFieldBegin("BaseResp", thrift.STRUCT, 255); err != nil {
goto WriteFieldBeginError
}
if err := p.BaseResp.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 end error: ", p), err)
}
func (p *RecordFileInfoResponse) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("RecordFileInfoResponse(%+v)", *p)
}
type UploadService interface {
CommonUpload(ctx context.Context, request *CommonUploadRequest) (r *CommonUploadResponse, err error)
ApplyUploadAction(ctx context.Context, request *ApplyUploadActionRequest) (r *ApplyUploadActionResponse, err error)
RecordFileInfo(ctx context.Context, request *RecordFileInfoRequest) (r *RecordFileInfoResponse, err error)
}
type UploadServiceClient struct {
@ -4642,6 +5224,15 @@ func (p *UploadServiceClient) ApplyUploadAction(ctx context.Context, request *Ap
}
return _result.GetSuccess(), nil
}
func (p *UploadServiceClient) RecordFileInfo(ctx context.Context, request *RecordFileInfoRequest) (r *RecordFileInfoResponse, err error) {
var _args UploadServiceRecordFileInfoArgs
_args.Request = request
var _result UploadServiceRecordFileInfoResult
if err = p.Client_().Call(ctx, "RecordFileInfo", &_args, &_result); err != nil {
return
}
return _result.GetSuccess(), nil
}
type UploadServiceProcessor struct {
processorMap map[string]thrift.TProcessorFunction
@ -4665,6 +5256,7 @@ func NewUploadServiceProcessor(handler UploadService) *UploadServiceProcessor {
self := &UploadServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self.AddToProcessorMap("CommonUpload", &uploadServiceProcessorCommonUpload{handler: handler})
self.AddToProcessorMap("ApplyUploadAction", &uploadServiceProcessorApplyUploadAction{handler: handler})
self.AddToProcessorMap("RecordFileInfo", &uploadServiceProcessorRecordFileInfo{handler: handler})
return self
}
func (p *UploadServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
@ -4781,6 +5373,54 @@ func (p *uploadServiceProcessorApplyUploadAction) Process(ctx context.Context, s
return true, err
}
type uploadServiceProcessorRecordFileInfo struct {
handler UploadService
}
func (p *uploadServiceProcessorRecordFileInfo) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := UploadServiceRecordFileInfoArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("RecordFileInfo", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, err
}
iprot.ReadMessageEnd()
var err2 error
result := UploadServiceRecordFileInfoResult{}
var retval *RecordFileInfoResponse
if retval, err2 = p.handler.RecordFileInfo(ctx, args.Request); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing RecordFileInfo: "+err2.Error())
oprot.WriteMessageBegin("RecordFileInfo", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("RecordFileInfo", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
type UploadServiceCommonUploadArgs struct {
Request *CommonUploadRequest `thrift:"request,1"`
}
@ -5364,3 +6004,295 @@ func (p *UploadServiceApplyUploadActionResult) String() string {
return fmt.Sprintf("UploadServiceApplyUploadActionResult(%+v)", *p)
}
type UploadServiceRecordFileInfoArgs struct {
Request *RecordFileInfoRequest `thrift:"request,1"`
}
func NewUploadServiceRecordFileInfoArgs() *UploadServiceRecordFileInfoArgs {
return &UploadServiceRecordFileInfoArgs{}
}
func (p *UploadServiceRecordFileInfoArgs) InitDefault() {
}
var UploadServiceRecordFileInfoArgs_Request_DEFAULT *RecordFileInfoRequest
func (p *UploadServiceRecordFileInfoArgs) GetRequest() (v *RecordFileInfoRequest) {
if !p.IsSetRequest() {
return UploadServiceRecordFileInfoArgs_Request_DEFAULT
}
return p.Request
}
var fieldIDToName_UploadServiceRecordFileInfoArgs = map[int16]string{
1: "request",
}
func (p *UploadServiceRecordFileInfoArgs) IsSetRequest() bool {
return p.Request != nil
}
func (p *UploadServiceRecordFileInfoArgs) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_UploadServiceRecordFileInfoArgs[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoArgs) ReadField1(iprot thrift.TProtocol) error {
_field := NewRecordFileInfoRequest()
if err := _field.Read(iprot); err != nil {
return err
}
p.Request = _field
return nil
}
func (p *UploadServiceRecordFileInfoArgs) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("RecordFileInfo_args"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("request", thrift.STRUCT, 1); err != nil {
goto WriteFieldBeginError
}
if err := p.Request.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("UploadServiceRecordFileInfoArgs(%+v)", *p)
}
type UploadServiceRecordFileInfoResult struct {
Success *RecordFileInfoResponse `thrift:"success,0,optional"`
}
func NewUploadServiceRecordFileInfoResult() *UploadServiceRecordFileInfoResult {
return &UploadServiceRecordFileInfoResult{}
}
func (p *UploadServiceRecordFileInfoResult) InitDefault() {
}
var UploadServiceRecordFileInfoResult_Success_DEFAULT *RecordFileInfoResponse
func (p *UploadServiceRecordFileInfoResult) GetSuccess() (v *RecordFileInfoResponse) {
if !p.IsSetSuccess() {
return UploadServiceRecordFileInfoResult_Success_DEFAULT
}
return p.Success
}
var fieldIDToName_UploadServiceRecordFileInfoResult = map[int16]string{
0: "success",
}
func (p *UploadServiceRecordFileInfoResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *UploadServiceRecordFileInfoResult) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 0:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField0(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_UploadServiceRecordFileInfoResult[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoResult) ReadField0(iprot thrift.TProtocol) error {
_field := NewRecordFileInfoResponse()
if err := _field.Read(iprot); err != nil {
return err
}
p.Success = _field
return nil
}
func (p *UploadServiceRecordFileInfoResult) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("RecordFileInfo_result"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField0(oprot); err != nil {
fieldId = 0
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err = oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
goto WriteFieldBeginError
}
if err := p.Success.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 0 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 0 end error: ", p), err)
}
func (p *UploadServiceRecordFileInfoResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("UploadServiceRecordFileInfoResult(%+v)", *p)
}

View File

@ -42,6 +42,7 @@ func Register(r *server.Hertz) {
}
{
_common := _api.Group("/common", _commonMw()...)
_common.POST("/record_file_info", append(_recordfileinfoMw(), coze.RecordFileInfo)...)
{
_upload := _common.Group("/upload", _uploadMw()...)
_upload.GET("/apply_upload_action", append(_applyuploadactionMw(), coze.ApplyUploadAction)...)

View File

@ -1570,3 +1570,8 @@ func _getonlineappdataMw() []app.HandlerFunc {
// your code...
return nil
}
func _recordfileinfoMw() []app.HandlerFunc {
// your code...
return nil
}

View File

@ -22,6 +22,7 @@ import (
"encoding/xml"
"errors"
"fmt"
"hash/crc32"
"image"
_ "image/gif"
@ -279,6 +280,7 @@ func stringToMap(input string) map[string]string {
return result
}
func (u *UploadService) UploadFileCommon(ctx context.Context, req *upload.CommonUploadRequest, fullPath string) (*upload.CommonUploadResponse, error) {
var err error
resp := upload.NewCommonUploadResponse()
re := regexp.MustCompile(consts.UploadURI + `/([^?]+)`)
match := re.FindStringSubmatch(fullPath)
@ -321,13 +323,13 @@ func (u *UploadService) UploadFileCommon(ctx context.Context, req *upload.Common
resp.Payload = &upload.Payload{Key: uuid.NewString()}
return resp, nil
}
var err error
opts := make([]storage.PutOptFn, 0, 2)
contentType := getContentType(objKey)
if len(contentType) != 0 {
err = u.oss.PutObject(ctx, objKey, req.ByteData, storage.WithContentType(contentType))
} else {
err = u.oss.PutObject(ctx, objKey, req.ByteData)
opts = append(opts, storage.WithContentType(contentType))
}
err = u.oss.PutObject(ctx, objKey, req.ByteData, opts...)
if err != nil {
return resp, errorx.New(errno.ErrUploadSystemErrorCode, errorx.KV("msg", err.Error()))
}
@ -738,3 +740,16 @@ func (u *UploadService) CommitImageUpload(ctx context.Context, req *upload.Apply
return &resp, nil
}
func (u *UploadService) RecordFileInfo(ctx context.Context, req *upload.RecordFileInfoRequest) (*upload.RecordFileInfoResponse, error) {
err := u.oss.PutObjectTagging(ctx, req.GetFileURI(), map[string]string{
"filename": req.GetFileName(),
"file_ext": req.GetFileExtension(),
})
if err != nil {
return nil, err
}
return &upload.RecordFileInfoResponse{}, nil
}

View File

@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"net/url"
"runtime/debug"
"strconv"
"strings"
@ -764,6 +765,87 @@ func (w *ApplicationService) GetProcess(ctx context.Context, req *workflow.GetWo
return resp, nil
}
func collectFileFields(ctx context.Context, workflowID int64) (map[string]bool, error) {
wf, err := GetWorkflowDomainSVC().Get(ctx, &vo.GetPolicy{
ID: workflowID,
QType: workflowModel.FromDraft,
})
if err != nil {
return nil, err
}
canvas := &vo.Canvas{}
err = sonic.UnmarshalString(wf.Canvas, canvas)
if err != nil {
return nil, err
}
var startNode *vo.Node
for _, n := range canvas.Nodes {
if n.ID == "100001" {
startNode = n
break
}
}
if startNode == nil {
return nil, fmt.Errorf("workflow invalid, not found start node")
}
fileFields := make(map[string]bool)
for _, v := range startNode.Data.Outputs {
v, err := vo.ParseVariable(v)
if err != nil {
return nil, err
}
if v.AssistType >= vo.AssistTypeDefault && v.AssistType <= vo.AssistTypeVoice {
fileFields[v.Name] = true
}
}
return fileFields, nil
}
func (w *ApplicationService) adaptorInputFileFields(ctx context.Context, workflowID int64, input string) (string, error) {
fileFields, err := collectFileFields(ctx, workflowID)
inputMap := make(map[string]any)
err = sonic.UnmarshalString(input, &inputMap)
if err != nil {
return "", err
}
appendQueryFileName := func(v string) (string, error) {
u, err := url.Parse(v)
if err != nil {
return "", err
}
filename := u.Query().Get("x-wf-file_name")
if len(filename) > 0 {
return u.String(), nil
}
fileURI := strings.TrimPrefix(u.Path, "/opencoze")
tagging, err := w.TosClient.GetObjectTagging(ctx, fileURI)
if err != nil {
logs.CtxWarnf(ctx, fmt.Sprintf("GetObjectTagging failed: %v", err))
return input, nil
}
if fName, ok := tagging["filename"]; ok {
query := u.Query()
query.Set("x-wf-file_name", fName)
u.RawQuery = query.Encode()
}
return u.String(), nil
}
for k, v := range inputMap {
if fileFields[k] {
v, err = appendQueryFileName(v.(string))
if err != nil {
return "", err
}
inputMap[k] = v
}
}
input, _ = sonic.MarshalString(inputMap)
return input, nil
}
func (w *ApplicationService) GetNodeExecuteHistory(ctx context.Context, req *workflow.GetNodeExecuteHistoryRequest) (
_ *workflow.GetNodeExecuteHistoryResponse, err error,
) {
@ -807,6 +889,11 @@ func (w *ApplicationService) GetNodeExecuteHistory(ctx context.Context, req *wor
return nil, err
}
result.Input, err = w.adaptorInputFileFields(ctx, mustParseInt64(req.GetWorkflowID()), result.Input)
if err != nil {
return nil, err
}
return &workflow.GetNodeExecuteHistoryResponse{
Data: result,
}, nil

View File

@ -24,8 +24,10 @@ import (
var defaultSVC Uploader
//go:generate mockgen -destination uploadmock/upload_mock.go --package uploadmock -source upload.go
type Uploader interface {
GetFile(ctx context.Context, req *service.GetFileRequest) (resp *service.GetFileResponse, err error)
GetFileTagging(ctx context.Context, req *service.GetFileTaggingRequest) (resp *service.GetFileTaggingResponse, err error)
}
func SetDefaultSVC(s Uploader) {

View File

@ -0,0 +1,88 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Code generated by MockGen. DO NOT EDIT.
// Source: upload.go
//
// Generated by this command:
//
// mockgen -destination uploadmock/upload_mock.go --package uploadmock -source upload.go
//
// Package uploadmock is a generated GoMock package.
package uploadmock
import (
context "context"
reflect "reflect"
service "github.com/coze-dev/coze-studio/backend/domain/upload/service"
gomock "go.uber.org/mock/gomock"
)
// MockUploader is a mock of Uploader interface.
type MockUploader struct {
ctrl *gomock.Controller
recorder *MockUploaderMockRecorder
isgomock struct{}
}
// MockUploaderMockRecorder is the mock recorder for MockUploader.
type MockUploaderMockRecorder struct {
mock *MockUploader
}
// NewMockUploader creates a new mock instance.
func NewMockUploader(ctrl *gomock.Controller) *MockUploader {
mock := &MockUploader{ctrl: ctrl}
mock.recorder = &MockUploaderMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockUploader) EXPECT() *MockUploaderMockRecorder {
return m.recorder
}
// GetFile mocks base method.
func (m *MockUploader) GetFile(ctx context.Context, req *service.GetFileRequest) (*service.GetFileResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFile", ctx, req)
ret0, _ := ret[0].(*service.GetFileResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetFile indicates an expected call of GetFile.
func (mr *MockUploaderMockRecorder) GetFile(ctx, req any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFile", reflect.TypeOf((*MockUploader)(nil).GetFile), ctx, req)
}
// GetFileTagging mocks base method.
func (m *MockUploader) GetFileTagging(ctx context.Context, req *service.GetFileTaggingRequest) (*service.GetFileTaggingResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFileTagging", ctx, req)
ret0, _ := ret[0].(*service.GetFileTaggingResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetFileTagging indicates an expected call of GetFileTagging.
func (mr *MockUploaderMockRecorder) GetFileTagging(ctx, req any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFileTagging", reflect.TypeOf((*MockUploader)(nil).GetFileTagging), ctx, req)
}

View File

@ -40,3 +40,6 @@ func InitDomainService(c service.UploadService) crossupload.Uploader {
func (c *impl) GetFile(ctx context.Context, req *service.GetFileRequest) (resp *service.GetFileResponse, err error) {
return c.DomainSVC.GetFile(ctx, req)
}
func (c *impl) GetFileTagging(ctx context.Context, req *service.GetFileTaggingRequest) (resp *service.GetFileTaggingResponse, err error) {
return c.DomainSVC.GetFileTagging(ctx, req)
}

View File

@ -1208,8 +1208,10 @@ func (d databaseService) executeSelectSQL(ctx context.Context, req *ExecuteSQLRe
}
selectReq.Fields = fields
}
var complexCond *rdb.ComplexCondition
var (
finallyComplexCond *rdb.ComplexCondition
complexCond *rdb.ComplexCondition
)
var err error
if req.Condition != nil {
complexCond, err = convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
@ -1219,24 +1221,32 @@ func (d databaseService) executeSelectSQL(ctx context.Context, req *ExecuteSQLRe
}
// add rw mode
var extraCondition *rdb.ComplexCondition
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
extraCondition = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
}
if complexCond != nil {
selectReq.Where = complexCond
if extraCondition != nil {
finallyComplexCond = &rdb.ComplexCondition{
NestedConditions: []*rdb.ComplexCondition{
complexCond,
extraCondition,
},
Operator: entity3.AND,
}
} else {
finallyComplexCond = complexCond
}
if finallyComplexCond != nil {
selectReq.Where = finallyComplexCond
}
if len(req.OrderByList) > 0 {
@ -1377,32 +1387,47 @@ func (d databaseService) executeUpdateSQL(ctx context.Context, req *ExecuteSQLRe
}
condParams := req.SQLParams[index:]
complexCond, err := convertCondition(ctx, req.Condition, fieldNameToPhysical, condParams)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
var (
finallyComplexCond *rdb.ComplexCondition
complexCond *rdb.ComplexCondition
)
var err error
if req.Condition != nil {
complexCond, err = convertCondition(ctx, req.Condition, fieldNameToPhysical, condParams)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
}
}
// add rw mode
var extraCondition *rdb.ComplexCondition
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
extraCondition = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
}
if extraCondition != nil {
finallyComplexCond = &rdb.ComplexCondition{
NestedConditions: []*rdb.ComplexCondition{
complexCond,
extraCondition,
},
Operator: entity3.AND,
}
} else {
finallyComplexCond = complexCond
}
updateResp, err := d.rdb.UpdateData(ctx, &rdb.UpdateDataRequest{
TableName: physicalTableName,
Data: updateData,
Where: complexCond,
Where: finallyComplexCond,
Limit: int64PtrToIntPtr(req.Limit),
})
if err != nil {
@ -1417,31 +1442,46 @@ func (d databaseService) executeDeleteSQL(ctx context.Context, req *ExecuteSQLRe
return -1, fmt.Errorf("missing delete condition")
}
complexCond, err := convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
var (
finallyComplexCond *rdb.ComplexCondition
complexCond *rdb.ComplexCondition
)
var err error
if req.Condition != nil {
complexCond, err = convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
}
}
// add rw mode
var extraCondition *rdb.ComplexCondition
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
extraCondition = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
}
if extraCondition != nil {
finallyComplexCond = &rdb.ComplexCondition{
NestedConditions: []*rdb.ComplexCondition{
complexCond,
extraCondition,
},
Operator: entity3.AND,
}
} else {
finallyComplexCond = complexCond
}
deleteResp, err := d.rdb.DeleteData(ctx, &rdb.DeleteDataRequest{
TableName: physicalTableName,
Where: complexCond,
Where: finallyComplexCond,
Limit: int64PtrToIntPtr(req.Limit),
})
if err != nil {

View File

@ -27,6 +27,7 @@ type UploadService interface {
UploadFiles(ctx context.Context, req *UploadFilesRequest) (resp *UploadFilesResponse, err error)
GetFiles(ctx context.Context, req *GetFilesRequest) (resp *GetFilesResponse, err error)
GetFile(ctx context.Context, req *GetFileRequest) (resp *GetFileResponse, err error)
GetFileTagging(ctx context.Context, req *GetFileTaggingRequest) (resp *GetFileTaggingResponse, err error)
}
type UploadFileRequest struct {
@ -58,3 +59,10 @@ type GetFileRequest struct {
type GetFileResponse struct {
File *entity.File `json:"file"`
}
type GetFileTaggingRequest struct {
FileURI string `json:"file_uri"`
}
type GetFileTaggingResponse struct {
Tagging map[string]string `json:"tagging"`
}

View File

@ -95,3 +95,14 @@ func (u *uploadSVC) GetFile(ctx context.Context, req *GetFileRequest) (resp *Get
}
return
}
func (u *uploadSVC) GetFileTagging(ctx context.Context, req *GetFileTaggingRequest) (resp *GetFileTaggingResponse, err error) {
tagging, err := u.oss.GetObjectTagging(ctx, req.FileURI)
if err != nil {
return nil, errorx.WrapByCode(err, errno.ErrUploadSystemErrorCode)
}
return &GetFileTaggingResponse{
Tagging: tagging,
}, nil
}

View File

@ -45,7 +45,10 @@ import (
mockmodel "github.com/coze-dev/coze-studio/backend/crossdomain/contract/modelmgr/modelmock"
crossplugin "github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/plugin/pluginmock"
crossupload "github.com/coze-dev/coze-studio/backend/crossdomain/contract/upload"
"github.com/coze-dev/coze-studio/backend/crossdomain/contract/upload/uploadmock"
"github.com/coze-dev/coze-studio/backend/crossdomain/impl/code"
"github.com/coze-dev/coze-studio/backend/domain/upload/service"
userentity "github.com/coze-dev/coze-studio/backend/domain/user/entity"
"github.com/coze-dev/coze-studio/backend/domain/workflow"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
@ -709,7 +712,14 @@ func TestKnowledgeDeleter(t *testing.T) {
assert.NoError(t, err)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockUpload := uploadmock.NewMockUploader(ctrl)
mockUpload.EXPECT().GetFileTagging(gomock.Any(), gomock.Any()).Return(&service.GetFileTaggingResponse{
Tagging: map[string]string{
"filename": "1706.03762v7.pdf",
"file_ext": ".pdf",
},
}, nil)
crossupload.SetDefaultSVC(mockUpload)
mockKnowledgeOperator := knowledgemock.NewMockKnowledge(ctrl)
crossknowledge.SetDefaultSVC(mockKnowledgeOperator)

View File

@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"net/url"
"strconv"
"strings"
@ -166,10 +167,24 @@ func convert(ctx context.Context, in any, path string, t *vo.TypeInfo, options *
if in == nil { // nil is valid for ALL types
return nil, nil, nil
}
switch t.Type {
case vo.DataTypeString, vo.DataTypeFile, vo.DataTypeTime:
case vo.DataTypeString, vo.DataTypeTime:
return convertToString(ctx, in, path, options)
case vo.DataTypeFile:
ret, warns, err := convertToString(ctx, in, path, options)
if err != nil {
return nil, nil, err
}
if warns != nil {
return ret, warns, nil
}
fileURL, err := adaptorFileURL(ret.(string))
if err != nil {
return nil, nil, err
}
return fileURL, nil, nil
case vo.DataTypeInteger:
return convertToInt64(ctx, in, path, options)
case vo.DataTypeNumber:
@ -215,7 +230,16 @@ func convertToString(_ context.Context, in any, path string, options *convertOpt
return nil, newWarnings(path, vo.DataTypeString, fmt.Errorf("unsupported type to convert to string: %T", in)), nil
}
}
func adaptorFileURL(in string) (string, error) {
u, err := url.Parse(in)
if err != nil {
return "", err
}
query := u.Query()
query.Del("x-wf-file_name")
u.RawQuery = query.Encode()
return u.String(), nil
}
func convertToInt64(_ context.Context, in any, path string, options *convertOptions) (any, *ConversionWarnings, error) {
switch in.(type) {
case int64:

View File

@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"net/url"
"path/filepath"
"strings"
@ -28,12 +29,15 @@ import (
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/knowledge"
crossknowledge "github.com/coze-dev/coze-studio/backend/crossdomain/contract/knowledge"
crossupload "github.com/coze-dev/coze-studio/backend/crossdomain/contract/upload"
"github.com/coze-dev/coze-studio/backend/domain/upload/service"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/canvas/convert"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
"github.com/coze-dev/coze-studio/backend/infra/contract/document/parser"
"github.com/coze-dev/coze-studio/backend/pkg/logs"
)
type IndexerConfig struct {
@ -125,7 +129,7 @@ func (k *Indexer) Invoke(ctx context.Context, input map[string]any) (map[string]
return nil, errors.New("knowledge is required")
}
fileName, ext, err := parseToFileNameAndFileExtension(fileURL)
fileName, ext, err := parseToFileNameAndFileExtension(ctx, fileURL)
if err != nil {
return nil, err
@ -153,23 +157,52 @@ func (k *Indexer) Invoke(ctx context.Context, input map[string]any) (map[string]
return result, nil
}
func parseToFileNameAndFileExtension(fileURL string) (string, parser.FileExtension, error) {
func parseToFileNameAndFileExtension(ctx context.Context, fileURL string) (string, parser.FileExtension, error) {
u, err := url.Parse(fileURL)
if err != nil {
return "", "", err
}
uris := make([]string, 0)
ap := false
for _, path := range strings.Split(u.Path, "/") {
if path == "tos-cn-i-v4nquku3lp" {
ap = true
}
if ap {
uris = append(uris, path)
}
}
fileURI := strings.Join(uris, "/")
response, err := crossupload.DefaultSVC().GetFileTagging(context.Background(), &service.GetFileTaggingRequest{
FileURI: fileURI,
})
fileName := u.Query().Get("x-wf-file_name")
if len(fileName) == 0 {
return "", "", errors.New("file name is required")
if err != nil {
logs.CtxWarnf(ctx, "GetFileTagging failed for uri %s", fileURI)
fileExt := strings.ToLower(strings.TrimPrefix(filepath.Ext(fileURI), "."))
ext, support := parser.ValidateFileExtension(fileExt)
if !support {
return "", "", fmt.Errorf("unsupported file type: %s", fileExt)
}
return fileURI, ext, nil
}
fileExt := strings.ToLower(strings.TrimPrefix(filepath.Ext(fileName), "."))
filename, ok := response.Tagging["filename"]
if !ok {
return "", "", fmt.Errorf("failed to get file tagging filename")
}
ext, support := parser.ValidateFileExtension(fileExt)
fileExt, ok := response.Tagging["file_ext"]
if !ok {
logs.CtxWarnf(ctx, "failed to get file tagging file ext")
fileExt = strings.TrimPrefix(filepath.Ext(fileURI), ".")
}
if len(fileExt) == 0 {
fileExt = strings.TrimPrefix(filepath.Ext(fileURI), ".")
}
ext, support := parser.ValidateFileExtension(strings.TrimPrefix(fileExt, "."))
if !support {
return "", "", fmt.Errorf("unsupported file type: %s", fileExt)
}
return fileName, ext, nil
return filename, ext, nil
}

View File

@ -30,6 +30,10 @@ type Storage interface {
PutObjectWithReader(ctx context.Context, objectKey string, content io.Reader, opts ...PutOptFn) error
// GetObject returns the object with the specified key.
GetObject(ctx context.Context, objectKey string) ([]byte, error)
// GetObjectTagging returns object tagging
GetObjectTagging(ctx context.Context, objectKey string) (map[string]string, error)
// PutObjectTagging update the tag of the object in full
PutObjectTagging(ctx context.Context, objectKey string, ts map[string]string) error
// DeleteObject deletes the object with the specified key.
DeleteObject(ctx context.Context, objectKey string) error
// GetObjectUrl returns a presigned URL for the object.

View File

@ -930,14 +930,23 @@ func (m *mysqlService) buildWhereClause(condition *rdb.ComplexCondition) (string
if condition == nil {
return "", nil, nil
}
if condition.Operator == "" {
condition.Operator = entity2.AND
}
if len(condition.NestedConditions) > 0 {
return m.buildNestedConditions(condition)
} else if len(condition.Conditions) > 0 {
whereClauseString, values, err := m.buildWhereCondition(condition)
return "WHERE " + whereClauseString, values, err
} else {
return "", nil, fmt.Errorf("condddd")
}
}
func (m *mysqlService) buildWhereCondition(condition *rdb.ComplexCondition) (string, []interface{}, error) {
var whereClause strings.Builder
values := make([]interface{}, 0)
for i, cond := range condition.Conditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", condition.Operator))
@ -971,25 +980,35 @@ func (m *mysqlService) buildWhereClause(condition *rdb.ComplexCondition) (string
values = append(values, cond.Value)
}
}
if len(condition.NestedConditions) > 0 {
whereClause.WriteString(" AND (")
for i, nested := range condition.NestedConditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", nested.Operator))
}
nestedClause, nestedValues, err := m.buildWhereClause(nested)
if err != nil {
return "", nil, err
}
whereClause.WriteString(nestedClause)
values = append(values, nestedValues...)
}
whereClause.WriteString(")")
}
if whereClause.Len() > 0 {
return " WHERE " + whereClause.String(), values, nil
return whereClause.String(), values, nil
}
return "", values, nil
}
func (m *mysqlService) buildNestedConditions(condition *rdb.ComplexCondition) (string, []interface{}, error) {
var whereClause strings.Builder
values := make([]interface{}, 0)
whereClause.WriteString(" WHERE (")
for i, nested := range condition.NestedConditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", nested.Operator))
}
nestedClause, nestedValues, err := m.buildWhereCondition(nested)
if err != nil {
return "", nil, err
}
whereClause.WriteString(nestedClause)
if i < len(condition.NestedConditions)-1 {
whereClause.WriteString(" " + string(condition.Operator))
}
values = append(values, nestedValues...)
}
whereClause.WriteString(")")
if whereClause.Len() > 0 {
return whereClause.String(), values, nil
}
return "", values, nil
}

View File

@ -19,7 +19,9 @@ package minio
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"io"
"math/rand"
"net/url"
@ -27,6 +29,7 @@ import (
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/tags"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/internal/fileutil"
@ -183,8 +186,12 @@ func (m *minioClient) PutObjectWithReader(ctx context.Context, objectKey string,
minioOpts.Expires = *option.Expires
}
tagging := make(map[string]string, len(option.Tagging))
for k, v := range option.Tagging {
tagging[k] = base64.StdEncoding.EncodeToString([]byte(v))
}
if option.Tagging != nil {
minioOpts.UserTags = option.Tagging
minioOpts.UserTags = tagging
}
_, err := m.client.PutObject(ctx, m.bucketName, objectKey,
@ -293,12 +300,20 @@ func (m *minioClient) ListAllObjects(ctx context.Context, prefix string, opts ..
return nil, object.Err
}
tagging := make(map[string]string, len(object.UserTags))
for k, v := range object.UserTags {
valBs, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return nil, err
}
tagging[k] = string(valBs)
}
files = append(files, &storage.FileInfo{
Key: object.Key,
LastModified: object.LastModified,
ETag: object.ETag,
Size: object.Size,
Tagging: object.UserTags,
Tagging: tagging,
})
logs.CtxDebugf(ctx, "key = %s, lastModified = %s, eTag = %s, size = %d, tagging = %v",
@ -331,12 +346,11 @@ func (m *minioClient) HeadObject(ctx context.Context, objectKey string, opts ...
}
if option.WithTagging {
tags, err := m.client.GetObjectTagging(ctx, m.bucketName, objectKey, minio.GetObjectTaggingOptions{})
objTags, err := m.GetObjectTagging(ctx, objectKey)
if err != nil {
return nil, err
}
f.Tagging = tags.ToMap()
f.Tagging = objTags
}
if option.WithURL {
@ -348,3 +362,33 @@ func (m *minioClient) HeadObject(ctx context.Context, objectKey string, opts ...
return f, nil
}
func (m *minioClient) GetObjectTagging(ctx context.Context, objectKey string) (map[string]string, error) {
response, err := m.client.GetObjectTagging(ctx, m.bucketName, objectKey, minio.GetObjectTaggingOptions{})
if err != nil {
return nil, fmt.Errorf("GetObjectTagging failed: %v", err)
}
rst := make(map[string]string)
for k, v := range response.ToMap() {
valBs, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return nil, fmt.Errorf("QueryUnescape failed: %v", err)
}
rst[k] = string(valBs)
}
return rst, nil
}
func (m *minioClient) PutObjectTagging(ctx context.Context, objectKey string, ts map[string]string) error {
saveTags := make(map[string]string)
for k, v := range ts {
saveTags[k] = base64.StdEncoding.EncodeToString([]byte(v))
}
t, err := tags.NewTags(saveTags, false)
if err != nil {
return err
}
return m.client.PutObjectTagging(ctx, m.bucketName, objectKey, t, minio.PutObjectTaggingOptions{})
}

View File

@ -21,6 +21,7 @@ import (
"context"
"errors"
"fmt"
"io"
"time"
@ -29,6 +30,7 @@ import (
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
"github.com/coze-dev/coze-studio/backend/infra/contract/storage"
"github.com/coze-dev/coze-studio/backend/infra/impl/storage/internal/fileutil"
@ -151,7 +153,6 @@ func (t *s3Client) PutObject(ctx context.Context, objectKey string, content []by
func (t *s3Client) PutObjectWithReader(ctx context.Context, objectKey string, content io.Reader, opts ...storage.PutOptFn) error {
client := t.client
bucket := t.bucketName
option := storage.PutOption{}
for _, opt := range opts {
opt(&option)
@ -440,3 +441,38 @@ func tagsToMap(tags []types.Tag) map[string]string {
}
return m
}
func (t *s3Client) GetObjectTagging(ctx context.Context, objectKey string) (map[string]string, error) {
response, err := t.client.GetObjectTagging(ctx, &s3.GetObjectTaggingInput{
Bucket: aws.String(t.bucketName),
Key: aws.String(objectKey),
})
if err != nil {
return nil, err
}
return slices.ToMap(response.TagSet, func(e types.Tag) (string, string) {
return *e.Key, *e.Value
}), err
}
func (t *s3Client) PutObjectTagging(ctx context.Context, objectKey string, ts map[string]string) error {
tags := make([]types.Tag, 0, len(ts))
for k, v := range ts {
tags = append(tags, types.Tag{
Key: aws.String(k),
Value: aws.String(v),
})
}
_, err := t.client.PutObjectTagging(ctx, &s3.PutObjectTaggingInput{
Bucket: aws.String(t.bucketName),
Key: aws.String(objectKey),
Tagging: &types.Tagging{
TagSet: tags,
},
})
if err != nil {
return err
}
return nil
}

View File

@ -25,6 +25,7 @@ import (
"strings"
"time"
"github.com/coze-dev/coze-studio/backend/pkg/lang/slices"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
@ -441,3 +442,36 @@ func tagsToMap(tags []tos.Tag) map[string]string {
return m
}
func (t *tosClient) GetObjectTagging(ctx context.Context, objectKey string) (map[string]string, error) {
response, err := t.client.GetObjectTagging(ctx, &tos.GetObjectTaggingInput{
Bucket: t.bucketName,
Key: objectKey,
})
if err != nil {
return nil, err
}
return slices.ToMap(response.TagSet.Tags, func(e tos.Tag) (string, string) {
return e.Key, e.Value
}), nil
}
func (t *tosClient) PutObjectTagging(ctx context.Context, objectKey string, ts map[string]string) error {
tags := make([]tos.Tag, 0, len(ts))
for k, v := range ts {
tags = append(tags, tos.Tag{Key: k, Value: v})
}
_, err := t.client.PutObjectTagging(ctx, &tos.PutObjectTaggingInput{
Bucket: t.bucketName,
Key: objectKey,
TagSet: tos.TagSet{
Tags: tags,
},
})
if err != nil {
return err
}
return nil
}

View File

@ -71,6 +71,21 @@ func (mr *MockStorageMockRecorder) GetObject(ctx, objectKey any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetObject", reflect.TypeOf((*MockStorage)(nil).GetObject), ctx, objectKey)
}
// GetObjectTagging mocks base method.
func (m *MockStorage) GetObjectTagging(ctx context.Context, objectKey string) (map[string]string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetObjectTagging", ctx, objectKey)
ret0, _ := ret[0].(map[string]string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetObjectTagging indicates an expected call of GetObjectTagging.
func (mr *MockStorageMockRecorder) GetObjectTagging(ctx, objectKey any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetObjectTagging", reflect.TypeOf((*MockStorage)(nil).GetObjectTagging), ctx, objectKey)
}
// GetObjectUrl mocks base method.
func (m *MockStorage) GetObjectUrl(ctx context.Context, objectKey string, opts ...storage.GetOptFn) (string, error) {
m.ctrl.T.Helper()
@ -170,6 +185,20 @@ func (mr *MockStorageMockRecorder) PutObject(ctx, objectKey, content any, opts .
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutObject", reflect.TypeOf((*MockStorage)(nil).PutObject), varargs...)
}
// PutObjectTagging mocks base method.
func (m *MockStorage) PutObjectTagging(ctx context.Context, objectKey string, ts map[string]string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PutObjectTagging", ctx, objectKey, ts)
ret0, _ := ret[0].(error)
return ret0
}
// PutObjectTagging indicates an expected call of PutObjectTagging.
func (mr *MockStorageMockRecorder) PutObjectTagging(ctx, objectKey, ts any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutObjectTagging", reflect.TypeOf((*MockStorage)(nil).PutObjectTagging), ctx, objectKey, ts)
}
// PutObjectWithReader mocks base method.
func (m *MockStorage) PutObjectWithReader(ctx context.Context, objectKey string, content io.Reader, opts ...storage.PutOptFn) error {
m.ctrl.T.Helper()

View File

@ -22340,6 +22340,9 @@ importers:
'@coze-project-ide/framework':
specifier: workspace:*
version: link:../../project-ide/framework
'@coze-studio/api-schema':
specifier: workspace:*
version: link:../../arch/api-schema
'@coze-studio/bot-detail-store':
specifier: workspace:*
version: link:../../studio/stores/bot-detail

View File

@ -24,6 +24,7 @@ const config = [
entries: {
passport: './idl/passport/passport.thrift', // Entry service name and path
explore: './idl/marketplace/public_api.thrift',
upload: './idl/upload/upload.thrift',
},
commonCodePath: path.resolve(__dirname, './src/api/config.ts'), // custom profile
output: './src', // Product location

View File

@ -8,7 +8,8 @@
"exports": {
".": "./src/index.ts",
"./passport": "./src/idl/passport/passport.ts",
"./marketplace": "./src/idl/marketplace/public_api.ts"
"./marketplace": "./src/idl/marketplace/public_api.ts",
"./upload": "./src/idl/upload/upload.ts"
},
"main": "src/index.ts",
"typesVersions": {
@ -18,6 +19,9 @@
],
"marketplace": [
"./src/idl/marketplace/public_api.ts"
],
"upload": [
"./src/idl/upload/upload.ts"
]
}
},

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as bot_common from './../app/bot_common';
export { bot_common };
import * as base from './../base';
export { base };
import { createAPI } from './../../api/config';
export interface CommonUploadRequest {
ByteData?: Blob,
uploadID?: string,
partNumber?: string,
}
export interface Error {
code: number,
error: string,
error_code: number,
message: string,
}
export interface Payload {
hash: string,
key: string,
uploadID: string,
}
export interface CommonUploadResponse {
Version: string,
success: number,
error: Error,
payload: Payload,
}
export interface ApplyUploadActionRequest {
Action?: string,
Version?: string,
ServiceId?: string,
FileExtension?: string,
FileSize?: string,
s?: string,
ByteData?: Blob,
}
export interface ResponseMetadata {
RequestId: string,
Action: string,
Version: string,
Service: string,
Region: string,
}
export interface StoreInfo {
StoreUri: string,
Auth: string,
UploadID: string,
}
export interface UploadAddress {
StoreInfos: StoreInfo[],
UploadHosts: string[],
UploadHeader?: {
[key: string | number]: string
},
SessionKey: string,
Cloud: string,
}
export interface UploadNode {
StoreInfos: StoreInfo[],
UploadHost: string,
UploadHeader?: {
[key: string | number]: string
},
SessionKey: string,
}
export interface InnerUploadAddress {
UploadNodes: UploadNode[]
}
export interface UploadResult {
Uri: string,
UriStatus: number,
}
export interface PluginResult {
FileName: string,
SourceUri: string,
ImageUri: string,
ImageWidth: number,
ImageHeight: number,
ImageMd5: string,
ImageFormat: string,
ImageSize: number,
FrameCnt: number,
}
export interface ApplyUploadActionResult {
UploadAddress?: UploadAddress,
FallbackUploadAddress?: UploadAddress,
InnerUploadAddress?: InnerUploadAddress,
RequestId?: string,
SDKParam?: string,
Results?: UploadResult[],
PluginResult?: PluginResult[],
}
export interface ApplyUploadActionResponse {
ResponseMetadata: ResponseMetadata,
Result: ApplyUploadActionResult,
}
export interface RecordFileInfoRequest {
FileURI: string,
FileName: string,
FileSize?: string,
FileExtension?: string,
}
export interface RecordFileInfoResponse {}
export const CommonUpload = /*#__PURE__*/createAPI<CommonUploadRequest, CommonUploadResponse>({
"url": "/api/common/upload/*tos_uri",
"method": "POST",
"name": "CommonUpload",
"reqType": "CommonUploadRequest",
"reqMapping": {
"raw_body": [],
"query": ["uploadID", "partNumber"]
},
"resType": "CommonUploadResponse",
"schemaRoot": "api://schemas/idl_upload_upload",
"service": "upload"
});
export const ApplyUploadAction = /*#__PURE__*/createAPI<ApplyUploadActionRequest, ApplyUploadActionResponse>({
"url": "/api/common/upload/apply_upload_action",
"method": "POST",
"name": "ApplyUploadAction",
"reqType": "ApplyUploadActionRequest",
"reqMapping": {
"query": ["Action", "Version", "ServiceId", "FileExtension", "FileSize", "s"],
"raw_body": []
},
"resType": "ApplyUploadActionResponse",
"schemaRoot": "api://schemas/idl_upload_upload",
"service": "upload"
});
export const RecordFileInfo = /*#__PURE__*/createAPI<RecordFileInfoRequest, RecordFileInfoResponse>({
"url": "/api/common/record_file_info",
"method": "POST",
"name": "RecordFileInfo",
"reqType": "RecordFileInfoRequest",
"reqMapping": {
"body": ["FileURI", "FileName", "FileSize", "FileExtension"]
},
"resType": "RecordFileInfoResponse",
"schemaRoot": "api://schemas/idl_upload_upload",
"service": "upload"
});

View File

@ -16,3 +16,4 @@
export * as passport from './idl/passport/passport';
export * as explore from './idl/marketplace/public_api';
export * as upload from './idl/upload/upload';

View File

@ -92,6 +92,7 @@
"@coze-foundation/layout": "workspace:*",
"@coze-foundation/local-storage": "workspace:*",
"@coze-project-ide/framework": "workspace:*",
"@coze-studio/api-schema": "workspace:*",
"@coze-studio/bot-detail-store": "workspace:*",
"@coze-studio/components": "workspace:*",
"@coze-studio/open-chat": "workspace:*",

View File

@ -20,10 +20,11 @@ import { useState } from 'react';
import { nanoid } from 'nanoid';
import { workflowApi } from '@coze-workflow/base/api';
import { type ViewVariableType } from '@coze-workflow/base';
import { upload as uploadAPI } from '@coze-studio/api-schema';
import { I18n } from '@coze-arch/i18n';
import { Toast } from '@coze-arch/coze-design';
import { upLoadFile } from '@coze-arch/bot-utils';
import { CustomError } from '@coze-arch/bot-error';
import { Toast } from '@coze-arch/coze-design';
import { validate } from './validate';
import { FileItemStatus, type FileItem } from './types';
@ -101,7 +102,10 @@ export const useUpload = (props?: UploadConfig) => {
// Upload complete, clear timeout timer
clearTimeout(progressTimer);
await uploadAPI.RecordFileInfo({
FileURI: uri,
FileName: file.name,
});
// Add uri and get the url.
const { url } = await workflowApi.SignImageURL(
{
@ -134,7 +138,8 @@ export const useUpload = (props?: UploadConfig) => {
const validateFile = async (file: FileItem): Promise<string | undefined> => {
const validateMsg = await validate(file, {
customValidate,
maxSize: maxSize ?? fileType === 'image' ? MAX_IMAGE_SIZE : MAX_FILE_SIZE,
maxSize:
(maxSize ?? fileType === 'image') ? MAX_IMAGE_SIZE : MAX_FILE_SIZE,
accept,
});
if (validateMsg) {

View File

@ -53,6 +53,9 @@
{
"path": "../../agent-ide/space-bot/tsconfig.build.json"
},
{
"path": "../../arch/api-schema/tsconfig.build.json"
},
{
"path": "../../arch/bot-api/tsconfig.build.json"
},

View File

@ -88,7 +88,22 @@ struct ApplyUploadActionResponse {
1: required ResponseMetadata ResponseMetadata,
2: required ApplyUploadActionResult Result
}
struct RecordFileInfoRequest {
1: required string FileURI
2: required string FileName
3: optional string FileSize
4: optional string FileExtension
}
struct RecordFileInfoResponse {
253: required i64 code,
254: required string msg,
255: optional base.BaseResp BaseResp (api.none="true")
}
service UploadService {
CommonUploadResponse CommonUpload(1: CommonUploadRequest request)(api.post = '/api/common/upload/*tos_uri', api.category="upload", api.gen_path="upload")
ApplyUploadActionResponse ApplyUploadAction(1: ApplyUploadActionRequest request)(api.get='/api/common/upload/apply_upload_action', api.post='/api/common/upload/apply_upload_action', api.category="common", api.gen_path="common")
RecordFileInfoResponse RecordFileInfo(1: RecordFileInfoRequest request)( api.post='/api/common/record_file_info', api.category="common", api.gen_path="common")
}