Add JSON schema support

This commit is contained in:
世界
2026-07-24 18:15:14 +08:00
parent 0b54f57725
commit 58affa1c6d
87 changed files with 19320 additions and 305 deletions
+12
View File
@@ -2,12 +2,16 @@ package main
import (
"context"
"reflect"
"time"
"github.com/sagernet/sing-box/common/networkquality"
"github.com/sagernet/sing-box/common/stun"
"github.com/sagernet/sing-box/daemon"
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/schema"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -38,6 +42,14 @@ func (s *applicationService) FormatConfig(ctx context.Context, request *ConfigCo
return &ConfigContent{Content: content}, nil
}
func (s *applicationService) GenerateConfigSchema(ctx context.Context, request *emptypb.Empty) (*ConfigContent, error) {
content, err := schema.Generate(include.Context(context.Background()), reflect.TypeFor[option.Options]())
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return &ConfigContent{Content: string(content)}, nil
}
func (s *applicationService) EncodeProfile(ctx context.Context, request *ProfileContent) (*ProfileData, error) {
content := libbox.ProfileContent{
Name: request.Name,
+40 -38
View File
@@ -6,7 +6,6 @@ import (
unsafe "unsafe"
daemon "github.com/sagernet/sing-box/daemon"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
@@ -1743,10 +1742,11 @@ const file_experimental_boxdd_desktop_service_proto_rawDesc = "" +
"\x13DeleteAllOOMReports\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12P\n" +
"\rInstallUpdate\x12\x1d.desktop.InstallUpdateRequest\x1a\x1e.desktop.InstallUpdateResponse\"\x00\x12J\n" +
"\x13GetSecuritySettings\x12\x16.google.protobuf.Empty\x1a\x19.desktop.SecuritySettings\"\x00\x12Z\n" +
"\x16SetInsecureModeEnabled\x12&.desktop.SetInsecureModeEnabledRequest\x1a\x16.google.protobuf.Empty\"\x002\xbd\x04\n" +
"\x16SetInsecureModeEnabled\x12&.desktop.SetInsecureModeEnabledRequest\x1a\x16.google.protobuf.Empty\"\x002\x87\x05\n" +
"\x12ApplicationService\x12?\n" +
"\vCheckConfig\x12\x16.desktop.ConfigContent\x1a\x16.google.protobuf.Empty\"\x00\x12@\n" +
"\fFormatConfig\x12\x16.desktop.ConfigContent\x1a\x16.desktop.ConfigContent\"\x00\x12@\n" +
"\fFormatConfig\x12\x16.desktop.ConfigContent\x1a\x16.desktop.ConfigContent\"\x00\x12H\n" +
"\x14GenerateConfigSchema\x12\x16.google.protobuf.Empty\x1a\x16.desktop.ConfigContent\"\x00\x12@\n" +
"\rEncodeProfile\x12\x17.desktop.ProfileContent\x1a\x14.desktop.ProfileData\"\x00\x12@\n" +
"\rDecodeProfile\x12\x14.desktop.ProfileData\x1a\x17.desktop.ProfileContent\"\x00\x12H\n" +
"\rArchiveReport\x12\x1d.desktop.ArchiveReportRequest\x1a\x16.google.protobuf.Empty\"\x00\x12y\n" +
@@ -1837,41 +1837,43 @@ var file_experimental_boxdd_desktop_service_proto_depIdxs = []int32{
27, // 28: desktop.DesktopService.SetInsecureModeEnabled:input_type -> desktop.SetInsecureModeEnabledRequest
9, // 29: desktop.ApplicationService.CheckConfig:input_type -> desktop.ConfigContent
9, // 30: desktop.ApplicationService.FormatConfig:input_type -> desktop.ConfigContent
10, // 31: desktop.ApplicationService.EncodeProfile:input_type -> desktop.ProfileContent
11, // 32: desktop.ApplicationService.DecodeProfile:input_type -> desktop.ProfileData
3, // 33: desktop.ApplicationService.ArchiveReport:input_type -> desktop.ArchiveReportRequest
4, // 34: desktop.ApplicationService.StartStandaloneNetworkQualityTest:input_type -> desktop.StandaloneNetworkQualityTestRequest
5, // 35: desktop.ApplicationService.StartStandaloneSTUNTest:input_type -> desktop.StandaloneSTUNTestRequest
6, // 36: desktop.DesktopService.GetDaemonInfo:output_type -> desktop.DaemonInfo
30, // 37: desktop.DesktopService.ClaimService:output_type -> google.protobuf.Empty
30, // 38: desktop.DesktopService.TakeOverService:output_type -> google.protobuf.Empty
30, // 39: desktop.DesktopService.StartService:output_type -> google.protobuf.Empty
12, // 40: desktop.DesktopService.GetWorkingDirectory:output_type -> desktop.WorkingDirectoryInfo
30, // 41: desktop.DesktopService.DestroyWorkingDirectory:output_type -> google.protobuf.Empty
13, // 42: desktop.DesktopService.ListCrashReports:output_type -> desktop.CrashReportList
17, // 43: desktop.DesktopService.ReadCrashReport:output_type -> desktop.CrashReportContent
30, // 44: desktop.DesktopService.MarkCrashReportRead:output_type -> google.protobuf.Empty
19, // 45: desktop.DesktopService.ExportCrashReport:output_type -> desktop.CrashReportArchive
30, // 46: desktop.DesktopService.DeleteCrashReport:output_type -> google.protobuf.Empty
30, // 47: desktop.DesktopService.DeleteAllCrashReports:output_type -> google.protobuf.Empty
20, // 48: desktop.DesktopService.ListOOMReports:output_type -> desktop.OOMReportList
24, // 49: desktop.DesktopService.ReadOOMReport:output_type -> desktop.OOMReportContent
30, // 50: desktop.DesktopService.MarkOOMReportRead:output_type -> google.protobuf.Empty
19, // 51: desktop.DesktopService.ExportOOMReport:output_type -> desktop.CrashReportArchive
30, // 52: desktop.DesktopService.DeleteOOMReport:output_type -> google.protobuf.Empty
30, // 53: desktop.DesktopService.DeleteAllOOMReports:output_type -> google.protobuf.Empty
29, // 54: desktop.DesktopService.InstallUpdate:output_type -> desktop.InstallUpdateResponse
26, // 55: desktop.DesktopService.GetSecuritySettings:output_type -> desktop.SecuritySettings
30, // 56: desktop.DesktopService.SetInsecureModeEnabled:output_type -> google.protobuf.Empty
30, // 57: desktop.ApplicationService.CheckConfig:output_type -> google.protobuf.Empty
9, // 58: desktop.ApplicationService.FormatConfig:output_type -> desktop.ConfigContent
11, // 59: desktop.ApplicationService.EncodeProfile:output_type -> desktop.ProfileData
10, // 60: desktop.ApplicationService.DecodeProfile:output_type -> desktop.ProfileContent
30, // 61: desktop.ApplicationService.ArchiveReport:output_type -> google.protobuf.Empty
31, // 62: desktop.ApplicationService.StartStandaloneNetworkQualityTest:output_type -> daemon.NetworkQualityTestProgress
32, // 63: desktop.ApplicationService.StartStandaloneSTUNTest:output_type -> daemon.STUNTestProgress
36, // [36:64] is the sub-list for method output_type
8, // [8:36] is the sub-list for method input_type
30, // 31: desktop.ApplicationService.GenerateConfigSchema:input_type -> google.protobuf.Empty
10, // 32: desktop.ApplicationService.EncodeProfile:input_type -> desktop.ProfileContent
11, // 33: desktop.ApplicationService.DecodeProfile:input_type -> desktop.ProfileData
3, // 34: desktop.ApplicationService.ArchiveReport:input_type -> desktop.ArchiveReportRequest
4, // 35: desktop.ApplicationService.StartStandaloneNetworkQualityTest:input_type -> desktop.StandaloneNetworkQualityTestRequest
5, // 36: desktop.ApplicationService.StartStandaloneSTUNTest:input_type -> desktop.StandaloneSTUNTestRequest
6, // 37: desktop.DesktopService.GetDaemonInfo:output_type -> desktop.DaemonInfo
30, // 38: desktop.DesktopService.ClaimService:output_type -> google.protobuf.Empty
30, // 39: desktop.DesktopService.TakeOverService:output_type -> google.protobuf.Empty
30, // 40: desktop.DesktopService.StartService:output_type -> google.protobuf.Empty
12, // 41: desktop.DesktopService.GetWorkingDirectory:output_type -> desktop.WorkingDirectoryInfo
30, // 42: desktop.DesktopService.DestroyWorkingDirectory:output_type -> google.protobuf.Empty
13, // 43: desktop.DesktopService.ListCrashReports:output_type -> desktop.CrashReportList
17, // 44: desktop.DesktopService.ReadCrashReport:output_type -> desktop.CrashReportContent
30, // 45: desktop.DesktopService.MarkCrashReportRead:output_type -> google.protobuf.Empty
19, // 46: desktop.DesktopService.ExportCrashReport:output_type -> desktop.CrashReportArchive
30, // 47: desktop.DesktopService.DeleteCrashReport:output_type -> google.protobuf.Empty
30, // 48: desktop.DesktopService.DeleteAllCrashReports:output_type -> google.protobuf.Empty
20, // 49: desktop.DesktopService.ListOOMReports:output_type -> desktop.OOMReportList
24, // 50: desktop.DesktopService.ReadOOMReport:output_type -> desktop.OOMReportContent
30, // 51: desktop.DesktopService.MarkOOMReportRead:output_type -> google.protobuf.Empty
19, // 52: desktop.DesktopService.ExportOOMReport:output_type -> desktop.CrashReportArchive
30, // 53: desktop.DesktopService.DeleteOOMReport:output_type -> google.protobuf.Empty
30, // 54: desktop.DesktopService.DeleteAllOOMReports:output_type -> google.protobuf.Empty
29, // 55: desktop.DesktopService.InstallUpdate:output_type -> desktop.InstallUpdateResponse
26, // 56: desktop.DesktopService.GetSecuritySettings:output_type -> desktop.SecuritySettings
30, // 57: desktop.DesktopService.SetInsecureModeEnabled:output_type -> google.protobuf.Empty
30, // 58: desktop.ApplicationService.CheckConfig:output_type -> google.protobuf.Empty
9, // 59: desktop.ApplicationService.FormatConfig:output_type -> desktop.ConfigContent
9, // 60: desktop.ApplicationService.GenerateConfigSchema:output_type -> desktop.ConfigContent
11, // 61: desktop.ApplicationService.EncodeProfile:output_type -> desktop.ProfileData
10, // 62: desktop.ApplicationService.DecodeProfile:output_type -> desktop.ProfileContent
30, // 63: desktop.ApplicationService.ArchiveReport:output_type -> google.protobuf.Empty
31, // 64: desktop.ApplicationService.StartStandaloneNetworkQualityTest:output_type -> daemon.NetworkQualityTestProgress
32, // 65: desktop.ApplicationService.StartStandaloneSTUNTest:output_type -> daemon.STUNTestProgress
37, // [37:66] is the sub-list for method output_type
8, // [8:37] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
+1
View File
@@ -33,6 +33,7 @@ service DesktopService {
service ApplicationService {
rpc CheckConfig(ConfigContent) returns (google.protobuf.Empty) {}
rpc FormatConfig(ConfigContent) returns (ConfigContent) {}
rpc GenerateConfigSchema(google.protobuf.Empty) returns (ConfigContent) {}
rpc EncodeProfile(ProfileContent) returns (ProfileData) {}
rpc DecodeProfile(ProfileData) returns (ProfileContent) {}
rpc ArchiveReport(ArchiveReportRequest) returns (google.protobuf.Empty) {}
+39 -1
View File
@@ -4,7 +4,6 @@ import (
context "context"
daemon "github.com/sagernet/sing-box/daemon"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -901,6 +900,7 @@ var DesktopService_ServiceDesc = grpc.ServiceDesc{
const (
ApplicationService_CheckConfig_FullMethodName = "/desktop.ApplicationService/CheckConfig"
ApplicationService_FormatConfig_FullMethodName = "/desktop.ApplicationService/FormatConfig"
ApplicationService_GenerateConfigSchema_FullMethodName = "/desktop.ApplicationService/GenerateConfigSchema"
ApplicationService_EncodeProfile_FullMethodName = "/desktop.ApplicationService/EncodeProfile"
ApplicationService_DecodeProfile_FullMethodName = "/desktop.ApplicationService/DecodeProfile"
ApplicationService_ArchiveReport_FullMethodName = "/desktop.ApplicationService/ArchiveReport"
@@ -914,6 +914,7 @@ const (
type ApplicationServiceClient interface {
CheckConfig(ctx context.Context, in *ConfigContent, opts ...grpc.CallOption) (*emptypb.Empty, error)
FormatConfig(ctx context.Context, in *ConfigContent, opts ...grpc.CallOption) (*ConfigContent, error)
GenerateConfigSchema(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigContent, error)
EncodeProfile(ctx context.Context, in *ProfileContent, opts ...grpc.CallOption) (*ProfileData, error)
DecodeProfile(ctx context.Context, in *ProfileData, opts ...grpc.CallOption) (*ProfileContent, error)
ArchiveReport(ctx context.Context, in *ArchiveReportRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
@@ -949,6 +950,16 @@ func (c *applicationServiceClient) FormatConfig(ctx context.Context, in *ConfigC
return out, nil
}
func (c *applicationServiceClient) GenerateConfigSchema(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigContent, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ConfigContent)
err := c.cc.Invoke(ctx, ApplicationService_GenerateConfigSchema_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *applicationServiceClient) EncodeProfile(ctx context.Context, in *ProfileContent, opts ...grpc.CallOption) (*ProfileData, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ProfileData)
@@ -1023,6 +1034,7 @@ type ApplicationService_StartStandaloneSTUNTestClient = grpc.ServerStreamingClie
type ApplicationServiceServer interface {
CheckConfig(context.Context, *ConfigContent) (*emptypb.Empty, error)
FormatConfig(context.Context, *ConfigContent) (*ConfigContent, error)
GenerateConfigSchema(context.Context, *emptypb.Empty) (*ConfigContent, error)
EncodeProfile(context.Context, *ProfileContent) (*ProfileData, error)
DecodeProfile(context.Context, *ProfileData) (*ProfileContent, error)
ArchiveReport(context.Context, *ArchiveReportRequest) (*emptypb.Empty, error)
@@ -1046,6 +1058,10 @@ func (UnimplementedApplicationServiceServer) FormatConfig(context.Context, *Conf
return nil, status.Error(codes.Unimplemented, "method FormatConfig not implemented")
}
func (UnimplementedApplicationServiceServer) GenerateConfigSchema(context.Context, *emptypb.Empty) (*ConfigContent, error) {
return nil, status.Error(codes.Unimplemented, "method GenerateConfigSchema not implemented")
}
func (UnimplementedApplicationServiceServer) EncodeProfile(context.Context, *ProfileContent) (*ProfileData, error) {
return nil, status.Error(codes.Unimplemented, "method EncodeProfile not implemented")
}
@@ -1122,6 +1138,24 @@ func _ApplicationService_FormatConfig_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler)
}
func _ApplicationService_GenerateConfigSchema_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApplicationServiceServer).GenerateConfigSchema(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ApplicationService_GenerateConfigSchema_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApplicationServiceServer).GenerateConfigSchema(ctx, req.(*emptypb.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _ApplicationService_EncodeProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ProfileContent)
if err := dec(in); err != nil {
@@ -1213,6 +1247,10 @@ var ApplicationService_ServiceDesc = grpc.ServiceDesc{
MethodName: "FormatConfig",
Handler: _ApplicationService_FormatConfig_Handler,
},
{
MethodName: "GenerateConfigSchema",
Handler: _ApplicationService_GenerateConfigSchema_Handler,
},
{
MethodName: "EncodeProfile",
Handler: _ApplicationService_EncodeProfile_Handler,