From 165e3680082a850f3198ea7cae9717ae574d3de3 Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 13:14:46 -0500 Subject: [PATCH 01/40] unreviewed: refactor(proto): share the parameter definition with engines --- .../gen/dotcore/catalog/v1/application_pb.ts | 59 ++---- .../dotcore/catalog/v1/engine_release_pb.ts | 193 +----------------- .../src/gen/dotcore/catalog/v1/model_pb.ts | 10 +- .../gen/dotcore/catalog/v1/parameter_pb.ts | 82 +++++++- .../src/gen/dotcore/model/v1/deployment_pb.ts | 10 +- .../src/gen/dotcore/model/v1/service_pb.ts | 18 +- proto/dotcore/catalog/v1/application.proto | 14 +- proto/dotcore/catalog/v1/engine_release.proto | 66 +----- proto/dotcore/catalog/v1/model.proto | 3 +- proto/dotcore/catalog/v1/parameter.proto | 29 ++- proto/dotcore/model/v1/deployment.proto | 3 +- proto/dotcore/model/v1/service.proto | 8 +- .../telemetry/v1/workload_resource.proto | 4 +- 13 files changed, 162 insertions(+), 337 deletions(-) diff --git a/frontend/src/gen/dotcore/catalog/v1/application_pb.ts b/frontend/src/gen/dotcore/catalog/v1/application_pb.ts index 2866da95..3b34fb91 100644 --- a/frontend/src/gen/dotcore/catalog/v1/application_pb.ts +++ b/frontend/src/gen/dotcore/catalog/v1/application_pb.ts @@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/catalog/v1/application.proto. */ export const file_dotcore_catalog_v1_application: GenFile = /*@__PURE__*/ - fileDesc("CiRkb3Rjb3JlL2NhdGFsb2cvdjEvYXBwbGljYXRpb24ucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSKlAQoLQXBwbGljYXRpb24SFgoOYXBwbGljYXRpb25faWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAUgASgJEg0KBW5vdGVzGAYgASgJEg8KB3ZlcnNpb24YAyABKAkSMwoFZ3JhcGgYBCABKAsyJC5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25HcmFwaCLUAQoQQXBwbGljYXRpb25HcmFwaBI4CghzZXJ2aWNlcxgBIAMoCzImLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2USSAoQcHJpbWFyeV9lbmRwb2ludBgCIAEoCzIuLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblByaW1hcnlFbmRwb2ludBI8CgpwYXJhbWV0ZXJzGAMgAygLMiguZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uUGFyYW1ldGVyImUKFEFwcGxpY2F0aW9uUGFyYW1ldGVyEjsKCmRlZmluaXRpb24YASABKAsyJy5kb3Rjb3JlLmNhdGFsb2cudjEuUGFyYW1ldGVyRGVmaW5pdGlvbhIQCghhZHZhbmNlZBgCIAEoCCKxBAoSQXBwbGljYXRpb25TZXJ2aWNlEhQKDHNlcnZpY2VfbmFtZRgBIAEoCRJACghhcnRpZmFjdBgCIAEoCzIuLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2VBcnRpZmFjdBIPCgdjb21tYW5kGAMgAygJEhEKCWFyZ3VtZW50cxgEIAMoCRI5CgVwb3J0cxgFIAMoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2VQb3J0ElMKFmNvbmZpZ3VyYXRpb25fYmluZGluZ3MYBiADKAsyMy5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25Db25maWd1cmF0aW9uQmluZGluZxI8ChBzdG9yYWdlX2JpbmRpbmdzGAcgAygLMiIuZG90Y29yZS5jYXRhbG9nLnYxLlN0b3JhZ2VCaW5kaW5nEkUKD3NlY3JldF9iaW5kaW5ncxgIIAMoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlY3JldEJpbmRpbmcSRgoMZGVwZW5kZW5jaWVzGAkgAygLMjAuZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uU2VydmljZURlcGVuZGVuY3kSQgoJcmVhZGluZXNzGAogASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uU2VydmljZVJlYWRpbmVzcyLIAQoaQXBwbGljYXRpb25TZXJ2aWNlQXJ0aWZhY3QSNAoDb2NpGAEgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLk9jaUltYWdlUmVmZXJlbmNlSAASLgoDbml4GAMgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk5peEFydGlmYWN0SAASPAoTc3VwcG9ydGVkX3BsYXRmb3JtcxgCIAMoCzIfLmRvdGNvcmUuY2F0YWxvZy52MS5PY2lQbGF0Zm9ybUIGCgRraW5kIkAKFkFwcGxpY2F0aW9uU2VydmljZVBvcnQSEQoJcG9ydF9uYW1lGAEgASgJEhMKC3BvcnRfbnVtYmVyGAIgASgNInsKHEFwcGxpY2F0aW9uU2VydmljZURlcGVuZGVuY3kSFAoMc2VydmljZV9uYW1lGAEgASgJEkUKCWNvbmRpdGlvbhgCIAEoDjIyLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvbkRlcGVuZGVuY3lDb25kaXRpb24iaAobQXBwbGljYXRpb25TZXJ2aWNlUmVhZGluZXNzEkAKCGh0dHBfZ2V0GAEgASgLMiwuZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uSHR0cFJlYWRpbmVzc0gAQgcKBWNoZWNrIjsKGEFwcGxpY2F0aW9uSHR0cFJlYWRpbmVzcxIRCglwb3J0X25hbWUYASABKAkSDAoEcGF0aBgCIAEoCSLuAQofQXBwbGljYXRpb25Db25maWd1cmF0aW9uQmluZGluZxIUCgxiaW5kaW5nX25hbWUYASABKAkSHAoUZW52aXJvbm1lbnRfdmFyaWFibGUYAiABKAkSFwoNbGl0ZXJhbF92YWx1ZRgDIAEoCUgAEh0KE3Jlc29sdmVkX3ZhbHVlX25hbWUYBCABKAlIABIWCgxwYXJhbWV0ZXJfaWQYBiABKAlIABI9CgVpbnB1dBgFIAEoCzIuLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvbkRlcGxveW1lbnRJbnB1dEIICgZzb3VyY2UicwoaQXBwbGljYXRpb25EZXBsb3ltZW50SW5wdXQSTQoPaW5mZXJlbmNlX3JvdXRlGAIgASgLMjIuZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uSW5mZXJlbmNlUm91dGVJbnB1dEgAQgYKBGtpbmQibQoeQXBwbGljYXRpb25JbmZlcmVuY2VSb3V0ZUlucHV0EksKCnByb2plY3Rpb24YASABKA4yNy5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25JbmZlcmVuY2VSb3V0ZVByb2plY3Rpb24iTgoYQXBwbGljYXRpb25TZWNyZXRCaW5kaW5nEhQKDGJpbmRpbmdfbmFtZRgBIAEoCRIcChRlbnZpcm9ubWVudF92YXJpYWJsZRgCIAEoCSKIAQoaQXBwbGljYXRpb25QcmltYXJ5RW5kcG9pbnQSFAoMc2VydmljZV9uYW1lGAEgASgJEhEKCXBvcnRfbmFtZRgCIAEoCRJBCghwcm90b2NvbBgDIAEoDjIvLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvbkVuZHBvaW50UHJvdG9jb2wqlAEKI0FwcGxpY2F0aW9uSW5mZXJlbmNlUm91dGVQcm9qZWN0aW9uEjYKMkFQUExJQ0FUSU9OX0lORkVSRU5DRV9ST1VURV9QUk9KRUNUSU9OX1VOU1BFQ0lGSUVEEAASNQoxQVBQTElDQVRJT05fSU5GRVJFTkNFX1JPVVRFX1BST0pFQ1RJT05fUk9VVEVfTkFNRRABKqwBCh5BcHBsaWNhdGlvbkRlcGVuZGVuY3lDb25kaXRpb24SMAosQVBQTElDQVRJT05fREVQRU5ERU5DWV9DT05ESVRJT05fVU5TUEVDSUZJRUQQABIsCihBUFBMSUNBVElPTl9ERVBFTkRFTkNZX0NPTkRJVElPTl9TVEFSVEVEEAESKgomQVBQTElDQVRJT05fREVQRU5ERU5DWV9DT05ESVRJT05fUkVBRFkQAip0ChtBcHBsaWNhdGlvbkVuZHBvaW50UHJvdG9jb2wSLQopQVBQTElDQVRJT05fRU5EUE9JTlRfUFJPVE9DT0xfVU5TUEVDSUZJRUQQABImCiJBUFBMSUNBVElPTl9FTkRQT0lOVF9QUk9UT0NPTF9IVFRQEAFiBnByb3RvMw", [file_dotcore_catalog_v1_nix, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_parameter, file_dotcore_catalog_v1_storage]); + fileDesc("CiRkb3Rjb3JlL2NhdGFsb2cvdjEvYXBwbGljYXRpb24ucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSKlAQoLQXBwbGljYXRpb24SFgoOYXBwbGljYXRpb25faWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAUgASgJEg0KBW5vdGVzGAYgASgJEg8KB3ZlcnNpb24YAyABKAkSMwoFZ3JhcGgYBCABKAsyJC5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25HcmFwaCLTAQoQQXBwbGljYXRpb25HcmFwaBI4CghzZXJ2aWNlcxgBIAMoCzImLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2USSAoQcHJpbWFyeV9lbmRwb2ludBgCIAEoCzIuLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblByaW1hcnlFbmRwb2ludBI7CgpwYXJhbWV0ZXJzGAMgAygLMicuZG90Y29yZS5jYXRhbG9nLnYxLlBhcmFtZXRlckRlZmluaXRpb24isQQKEkFwcGxpY2F0aW9uU2VydmljZRIUCgxzZXJ2aWNlX25hbWUYASABKAkSQAoIYXJ0aWZhY3QYAiABKAsyLi5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25TZXJ2aWNlQXJ0aWZhY3QSDwoHY29tbWFuZBgDIAMoCRIRCglhcmd1bWVudHMYBCADKAkSOQoFcG9ydHMYBSADKAsyKi5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25TZXJ2aWNlUG9ydBJTChZjb25maWd1cmF0aW9uX2JpbmRpbmdzGAYgAygLMjMuZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uQ29uZmlndXJhdGlvbkJpbmRpbmcSPAoQc3RvcmFnZV9iaW5kaW5ncxgHIAMoCzIiLmRvdGNvcmUuY2F0YWxvZy52MS5TdG9yYWdlQmluZGluZxJFCg9zZWNyZXRfYmluZGluZ3MYCCADKAsyLC5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25TZWNyZXRCaW5kaW5nEkYKDGRlcGVuZGVuY2llcxgJIAMoCzIwLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2VEZXBlbmRlbmN5EkIKCXJlYWRpbmVzcxgKIAEoCzIvLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvblNlcnZpY2VSZWFkaW5lc3MiyAEKGkFwcGxpY2F0aW9uU2VydmljZUFydGlmYWN0EjQKA29jaRgBIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5PY2lJbWFnZVJlZmVyZW5jZUgAEi4KA25peBgDIAEoCzIfLmRvdGNvcmUuY2F0YWxvZy52MS5OaXhBcnRpZmFjdEgAEjwKE3N1cHBvcnRlZF9wbGF0Zm9ybXMYAiADKAsyHy5kb3Rjb3JlLmNhdGFsb2cudjEuT2NpUGxhdGZvcm1CBgoEa2luZCJAChZBcHBsaWNhdGlvblNlcnZpY2VQb3J0EhEKCXBvcnRfbmFtZRgBIAEoCRITCgtwb3J0X251bWJlchgCIAEoDSJ7ChxBcHBsaWNhdGlvblNlcnZpY2VEZXBlbmRlbmN5EhQKDHNlcnZpY2VfbmFtZRgBIAEoCRJFCgljb25kaXRpb24YAiABKA4yMi5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25EZXBlbmRlbmN5Q29uZGl0aW9uImgKG0FwcGxpY2F0aW9uU2VydmljZVJlYWRpbmVzcxJACghodHRwX2dldBgBIAEoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvbkh0dHBSZWFkaW5lc3NIAEIHCgVjaGVjayI7ChhBcHBsaWNhdGlvbkh0dHBSZWFkaW5lc3MSEQoJcG9ydF9uYW1lGAEgASgJEgwKBHBhdGgYAiABKAki7gEKH0FwcGxpY2F0aW9uQ29uZmlndXJhdGlvbkJpbmRpbmcSFAoMYmluZGluZ19uYW1lGAEgASgJEhwKFGVudmlyb25tZW50X3ZhcmlhYmxlGAIgASgJEhcKDWxpdGVyYWxfdmFsdWUYAyABKAlIABIdChNyZXNvbHZlZF92YWx1ZV9uYW1lGAQgASgJSAASFgoMcGFyYW1ldGVyX2lkGAYgASgJSAASPQoFaW5wdXQYBSABKAsyLi5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25EZXBsb3ltZW50SW5wdXRCCAoGc291cmNlInMKGkFwcGxpY2F0aW9uRGVwbG95bWVudElucHV0Ek0KD2luZmVyZW5jZV9yb3V0ZRgCIAEoCzIyLmRvdGNvcmUuY2F0YWxvZy52MS5BcHBsaWNhdGlvbkluZmVyZW5jZVJvdXRlSW5wdXRIAEIGCgRraW5kIm0KHkFwcGxpY2F0aW9uSW5mZXJlbmNlUm91dGVJbnB1dBJLCgpwcm9qZWN0aW9uGAEgASgOMjcuZG90Y29yZS5jYXRhbG9nLnYxLkFwcGxpY2F0aW9uSW5mZXJlbmNlUm91dGVQcm9qZWN0aW9uIk4KGEFwcGxpY2F0aW9uU2VjcmV0QmluZGluZxIUCgxiaW5kaW5nX25hbWUYASABKAkSHAoUZW52aXJvbm1lbnRfdmFyaWFibGUYAiABKAkiiAEKGkFwcGxpY2F0aW9uUHJpbWFyeUVuZHBvaW50EhQKDHNlcnZpY2VfbmFtZRgBIAEoCRIRCglwb3J0X25hbWUYAiABKAkSQQoIcHJvdG9jb2wYAyABKA4yLy5kb3Rjb3JlLmNhdGFsb2cudjEuQXBwbGljYXRpb25FbmRwb2ludFByb3RvY29sKpQBCiNBcHBsaWNhdGlvbkluZmVyZW5jZVJvdXRlUHJvamVjdGlvbhI2CjJBUFBMSUNBVElPTl9JTkZFUkVOQ0VfUk9VVEVfUFJPSkVDVElPTl9VTlNQRUNJRklFRBAAEjUKMUFQUExJQ0FUSU9OX0lORkVSRU5DRV9ST1VURV9QUk9KRUNUSU9OX1JPVVRFX05BTUUQASqsAQoeQXBwbGljYXRpb25EZXBlbmRlbmN5Q29uZGl0aW9uEjAKLEFQUExJQ0FUSU9OX0RFUEVOREVOQ1lfQ09ORElUSU9OX1VOU1BFQ0lGSUVEEAASLAooQVBQTElDQVRJT05fREVQRU5ERU5DWV9DT05ESVRJT05fU1RBUlRFRBABEioKJkFQUExJQ0FUSU9OX0RFUEVOREVOQ1lfQ09ORElUSU9OX1JFQURZEAIqdAobQXBwbGljYXRpb25FbmRwb2ludFByb3RvY29sEi0KKUFQUExJQ0FUSU9OX0VORFBPSU5UX1BST1RPQ09MX1VOU1BFQ0lGSUVEEAASJgoiQVBQTElDQVRJT05fRU5EUE9JTlRfUFJPVE9DT0xfSFRUUBABYgZwcm90bzM", [file_dotcore_catalog_v1_nix, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_parameter, file_dotcore_catalog_v1_storage]); /** * An immutable artifact-manager catalog declaration for an approved application release. @@ -97,11 +97,12 @@ export type ApplicationGraph = Message<"dotcore.catalog.v1.ApplicationGraph"> & primaryEndpoint?: ApplicationPrimaryEndpoint; /** - * Typed parameters operators may set at deployment creation, in display order. + * Typed parameters operators may set at deployment creation, in display order; each declares a + * default and is basic or advanced. * - * @generated from field: repeated dotcore.catalog.v1.ApplicationParameter parameters = 3; + * @generated from field: repeated dotcore.catalog.v1.ParameterDefinition parameters = 3; */ - parameters: ApplicationParameter[]; + parameters: ParameterDefinition[]; }; /** @@ -111,34 +112,6 @@ export type ApplicationGraph = Message<"dotcore.catalog.v1.ApplicationGraph"> & export const ApplicationGraphSchema: GenMessage = /*@__PURE__*/ messageDesc(file_dotcore_catalog_v1_application, 1); -/** - * One typed application parameter and how the console shows it. - * - * @generated from message dotcore.catalog.v1.ApplicationParameter - */ -export type ApplicationParameter = Message<"dotcore.catalog.v1.ApplicationParameter"> & { - /** - * Typed definition; application parameters always declare a default. - * - * @generated from field: dotcore.catalog.v1.ParameterDefinition definition = 1; - */ - definition?: ParameterDefinition; - - /** - * Whether the console shows this parameter only in its advanced view. - * - * @generated from field: bool advanced = 2; - */ - advanced: boolean; -}; - -/** - * Describes the message dotcore.catalog.v1.ApplicationParameter. - * Use `create(ApplicationParameterSchema)` to create a new message. - */ -export const ApplicationParameterSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 2); - /** * One named service in an immutable application graph. * @@ -222,7 +195,7 @@ export type ApplicationService = Message<"dotcore.catalog.v1.ApplicationService" * Use `create(ApplicationServiceSchema)` to create a new message. */ export const ApplicationServiceSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 3); + messageDesc(file_dotcore_catalog_v1_application, 2); /** * One immutable artifact of an application service and the platforms it approves. @@ -266,7 +239,7 @@ export type ApplicationServiceArtifact = Message<"dotcore.catalog.v1.Application * Use `create(ApplicationServiceArtifactSchema)` to create a new message. */ export const ApplicationServiceArtifactSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 4); + messageDesc(file_dotcore_catalog_v1_application, 3); /** * One named internal TCP port served by an application service. @@ -294,7 +267,7 @@ export type ApplicationServicePort = Message<"dotcore.catalog.v1.ApplicationServ * Use `create(ApplicationServicePortSchema)` to create a new message. */ export const ApplicationServicePortSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 5); + messageDesc(file_dotcore_catalog_v1_application, 4); /** * One dependency on a named service in the same application graph. @@ -322,7 +295,7 @@ export type ApplicationServiceDependency = Message<"dotcore.catalog.v1.Applicati * Use `create(ApplicationServiceDependencySchema)` to create a new message. */ export const ApplicationServiceDependencySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 6); + messageDesc(file_dotcore_catalog_v1_application, 5); /** * Declares one protocol readiness check for an application service. @@ -349,7 +322,7 @@ export type ApplicationServiceReadiness = Message<"dotcore.catalog.v1.Applicatio * Use `create(ApplicationServiceReadinessSchema)` to create a new message. */ export const ApplicationServiceReadinessSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 7); + messageDesc(file_dotcore_catalog_v1_application, 6); /** * Declares an HTTP readiness request without asserting current readiness. @@ -377,7 +350,7 @@ export type ApplicationHttpReadiness = Message<"dotcore.catalog.v1.ApplicationHt * Use `create(ApplicationHttpReadinessSchema)` to create a new message. */ export const ApplicationHttpReadinessSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 8); + messageDesc(file_dotcore_catalog_v1_application, 7); /** * Declares one non-secret configuration source and its environment destination. @@ -441,7 +414,7 @@ export type ApplicationConfigurationBinding = Message<"dotcore.catalog.v1.Applic * Use `create(ApplicationConfigurationBindingSchema)` to create a new message. */ export const ApplicationConfigurationBindingSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 9); + messageDesc(file_dotcore_catalog_v1_application, 8); /** * Describes one deployment input projected into a configuration binding. @@ -468,7 +441,7 @@ export type ApplicationDeploymentInput = Message<"dotcore.catalog.v1.Application * Use `create(ApplicationDeploymentInputSchema)` to create a new message. */ export const ApplicationDeploymentInputSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 10); + messageDesc(file_dotcore_catalog_v1_application, 9); /** * Identifies a deployment input projected from an optionally linked inference route. @@ -489,7 +462,7 @@ export type ApplicationInferenceRouteInput = Message<"dotcore.catalog.v1.Applica * Use `create(ApplicationInferenceRouteInputSchema)` to create a new message. */ export const ApplicationInferenceRouteInputSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 11); + messageDesc(file_dotcore_catalog_v1_application, 10); /** * Declares a named unresolved secret reference and its environment destination. @@ -517,7 +490,7 @@ export type ApplicationSecretBinding = Message<"dotcore.catalog.v1.ApplicationSe * Use `create(ApplicationSecretBindingSchema)` to create a new message. */ export const ApplicationSecretBindingSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 12); + messageDesc(file_dotcore_catalog_v1_application, 11); /** * Selects the one declared service port that can become the primary endpoint. @@ -552,7 +525,7 @@ export type ApplicationPrimaryEndpoint = Message<"dotcore.catalog.v1.Application * Use `create(ApplicationPrimaryEndpointSchema)` to create a new message. */ export const ApplicationPrimaryEndpointSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_application, 13); + messageDesc(file_dotcore_catalog_v1_application, 12); /** * One application-neutral value projected from a linked inference route. diff --git a/frontend/src/gen/dotcore/catalog/v1/engine_release_pb.ts b/frontend/src/gen/dotcore/catalog/v1/engine_release_pb.ts index 5a833ebb..2f46de42 100644 --- a/frontend/src/gen/dotcore/catalog/v1/engine_release_pb.ts +++ b/frontend/src/gen/dotcore/catalog/v1/engine_release_pb.ts @@ -8,6 +8,8 @@ import type { NixArtifact } from "./nix_pb"; import { file_dotcore_catalog_v1_nix } from "./nix_pb"; import type { OciImageReference } from "./oci_pb"; import { file_dotcore_catalog_v1_oci } from "./oci_pb"; +import type { ParameterDefinition } from "./parameter_pb"; +import { file_dotcore_catalog_v1_parameter } from "./parameter_pb"; import type { Selector } from "./selector_pb"; import { file_dotcore_catalog_v1_selector } from "./selector_pb"; import type { StorageBinding } from "./storage_pb"; @@ -20,7 +22,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/catalog/v1/engine_release.proto. */ export const file_dotcore_catalog_v1_engine_release: GenFile = /*@__PURE__*/ - fileDesc("Cidkb3Rjb3JlL2NhdGFsb2cvdjEvZW5naW5lX3JlbGVhc2UucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSKpAgoNRW5naW5lUmVsZWFzZRIZChFlbmdpbmVfcmVsZWFzZV9pZBgBIAEoCRIyCgtlbmdpbmVfa2luZBgCIAEoDjIdLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZUtpbmQSDwoHdmVyc2lvbhgDIAEoCRI1CglhcnRpZmFjdHMYBCADKAsyIi5kb3Rjb3JlLmNhdGFsb2cudjEuRW5naW5lQXJ0aWZhY3QSQwoQcGFyYW1ldGVyX3NjaGVtYRgFIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJTY2hlbWESPAoQc3RvcmFnZV9iaW5kaW5ncxgGIAMoCzIiLmRvdGNvcmUuY2F0YWxvZy52MS5TdG9yYWdlQmluZGluZyLEAQoORW5naW5lQXJ0aWZhY3QSEwoLYXJ0aWZhY3RfaWQYASABKAkSNAoDb2NpGAIgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLk9jaUltYWdlUmVmZXJlbmNlSAASLgoDbml4GAQgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk5peEFydGlmYWN0SAASLwoJc2VsZWN0b3JzGAMgAygLMhwuZG90Y29yZS5jYXRhbG9nLnYxLlNlbGVjdG9yQgYKBGtpbmQiUAoXRW5naW5lQXJ0aWZhY3RSZWZlcmVuY2USGQoRZW5naW5lX3JlbGVhc2VfaWQYASABKAkSGgoSZW5naW5lX2FydGlmYWN0X2lkGAIgASgJIm0KFUVuZ2luZVBhcmFtZXRlclNjaGVtYRIRCglzY2hlbWFfaWQYASABKAkSQQoKcGFyYW1ldGVycxgCIAMoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJEZWZpbml0aW9uIpoCChlFbmdpbmVQYXJhbWV0ZXJEZWZpbml0aW9uEhQKDHBhcmFtZXRlcl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSVAoQdW5zaWduZWRfaW50ZWdlchgDIAEoCzI4LmRvdGNvcmUuY2F0YWxvZy52MS5VbnNpZ25lZEludGVnZXJFbmdpbmVQYXJhbWV0ZXJTY2hlbWFIABJDCgdib29sZWFuGAQgASgLMjAuZG90Y29yZS5jYXRhbG9nLnYxLkJvb2xlYW5FbmdpbmVQYXJhbWV0ZXJTY2hlbWFIABIPCgdleHBvc2VkGAUgASgIEhMKC2Rlc2NyaXB0aW9uGAYgASgJQhAKDnBhcmFtZXRlcl90eXBlIh4KHEJvb2xlYW5FbmdpbmVQYXJhbWV0ZXJTY2hlbWEihAEKJFVuc2lnbmVkSW50ZWdlckVuZ2luZVBhcmFtZXRlclNjaGVtYRIPCgdtaW5pbXVtGAEgASgEEg8KB21heGltdW0YAiABKAQSDAoEdW5pdBgDIAEoCRIaCg1kZWZhdWx0X3ZhbHVlGAQgASgESACIAQFCEAoOX2RlZmF1bHRfdmFsdWUiUQoVRW5naW5lUGFyYW1ldGVyVmFsdWVzEjgKBnZhbHVlcxgBIAMoCzIoLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJWYWx1ZSJkChRFbmdpbmVQYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSGgoQdW5zaWduZWRfaW50ZWdlchgCIAEoBEgAEhEKB2Jvb2xlYW4YAyABKAhIAEIHCgV2YWx1ZWIGcHJvdG8z", [file_dotcore_catalog_v1_nix, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_selector, file_dotcore_catalog_v1_storage, file_dotcore_engine_v1_engine]); + fileDesc("Cidkb3Rjb3JlL2NhdGFsb2cvdjEvZW5naW5lX3JlbGVhc2UucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSKpAgoNRW5naW5lUmVsZWFzZRIZChFlbmdpbmVfcmVsZWFzZV9pZBgBIAEoCRIyCgtlbmdpbmVfa2luZBgCIAEoDjIdLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZUtpbmQSDwoHdmVyc2lvbhgDIAEoCRI1CglhcnRpZmFjdHMYBCADKAsyIi5kb3Rjb3JlLmNhdGFsb2cudjEuRW5naW5lQXJ0aWZhY3QSQwoQcGFyYW1ldGVyX3NjaGVtYRgFIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJTY2hlbWESPAoQc3RvcmFnZV9iaW5kaW5ncxgGIAMoCzIiLmRvdGNvcmUuY2F0YWxvZy52MS5TdG9yYWdlQmluZGluZyLEAQoORW5naW5lQXJ0aWZhY3QSEwoLYXJ0aWZhY3RfaWQYASABKAkSNAoDb2NpGAIgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLk9jaUltYWdlUmVmZXJlbmNlSAASLgoDbml4GAQgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk5peEFydGlmYWN0SAASLwoJc2VsZWN0b3JzGAMgAygLMhwuZG90Y29yZS5jYXRhbG9nLnYxLlNlbGVjdG9yQgYKBGtpbmQiUAoXRW5naW5lQXJ0aWZhY3RSZWZlcmVuY2USGQoRZW5naW5lX3JlbGVhc2VfaWQYASABKAkSGgoSZW5naW5lX2FydGlmYWN0X2lkGAIgASgJImcKFUVuZ2luZVBhcmFtZXRlclNjaGVtYRIRCglzY2hlbWFfaWQYASABKAkSOwoKcGFyYW1ldGVycxgCIAMoCzInLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJEZWZpbml0aW9uYgZwcm90bzM", [file_dotcore_catalog_v1_nix, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_parameter, file_dotcore_catalog_v1_selector, file_dotcore_catalog_v1_storage, file_dotcore_engine_v1_engine]); /** * An immutable artifact-manager catalog declaration for reusable engine @@ -172,11 +174,11 @@ export type EngineParameterSchema = Message<"dotcore.catalog.v1.EngineParameterS schemaId: string; /** - * Supported typed engine parameters. + * Supported typed engine parameters, in display order. * - * @generated from field: repeated dotcore.catalog.v1.EngineParameterDefinition parameters = 2; + * @generated from field: repeated dotcore.catalog.v1.ParameterDefinition parameters = 2; */ - parameters: EngineParameterDefinition[]; + parameters: ParameterDefinition[]; }; /** @@ -186,186 +188,3 @@ export type EngineParameterSchema = Message<"dotcore.catalog.v1.EngineParameterS export const EngineParameterSchemaSchema: GenMessage = /*@__PURE__*/ messageDesc(file_dotcore_catalog_v1_engine_release, 3); -/** - * Defines one typed engine parameter and its validation constraints. - * - * @generated from message dotcore.catalog.v1.EngineParameterDefinition - */ -export type EngineParameterDefinition = Message<"dotcore.catalog.v1.EngineParameterDefinition"> & { - /** - * Stable engine parameter identity. - * - * @generated from field: string parameter_id = 1; - */ - parameterId: string; - - /** - * Human-readable parameter label. - * - * @generated from field: string display_name = 2; - */ - displayName: string; - - /** - * @generated from oneof dotcore.catalog.v1.EngineParameterDefinition.parameter_type - */ - parameterType: { - /** - * Unsigned-integer constraints for this parameter. - * - * @generated from field: dotcore.catalog.v1.UnsignedIntegerEngineParameterSchema unsigned_integer = 3; - */ - value: UnsignedIntegerEngineParameterSchema; - case: "unsignedInteger"; - } | { - /** - * Boolean type for this parameter. - * - * @generated from field: dotcore.catalog.v1.BooleanEngineParameterSchema boolean = 4; - */ - value: BooleanEngineParameterSchema; - case: "boolean"; - } | { case: undefined; value?: undefined }; - - /** - * Whether the console exposes this parameter by default. - * - * @generated from field: bool exposed = 5; - */ - exposed: boolean; - - /** - * Optional practical guidance shown with this parameter. - * - * @generated from field: string description = 6; - */ - description: string; -}; - -/** - * Describes the message dotcore.catalog.v1.EngineParameterDefinition. - * Use `create(EngineParameterDefinitionSchema)` to create a new message. - */ -export const EngineParameterDefinitionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_engine_release, 4); - -/** - * Defines a boolean engine parameter. - * - * @generated from message dotcore.catalog.v1.BooleanEngineParameterSchema - */ -export type BooleanEngineParameterSchema = Message<"dotcore.catalog.v1.BooleanEngineParameterSchema"> & { -}; - -/** - * Describes the message dotcore.catalog.v1.BooleanEngineParameterSchema. - * Use `create(BooleanEngineParameterSchemaSchema)` to create a new message. - */ -export const BooleanEngineParameterSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_engine_release, 5); - -/** - * Defines the inclusive range for an unsigned-integer engine parameter. - * - * @generated from message dotcore.catalog.v1.UnsignedIntegerEngineParameterSchema - */ -export type UnsignedIntegerEngineParameterSchema = Message<"dotcore.catalog.v1.UnsignedIntegerEngineParameterSchema"> & { - /** - * Inclusive minimum accepted value. - * - * @generated from field: uint64 minimum = 1; - */ - minimum: bigint; - - /** - * Inclusive maximum accepted value. - * - * @generated from field: uint64 maximum = 2; - */ - maximum: bigint; - - /** - * Human-readable unit label for this value. - * - * @generated from field: string unit = 3; - */ - unit: string; - - /** - * Value used when neither the deployment nor its profile supplies one, within the range. - * - * @generated from field: optional uint64 default_value = 4; - */ - defaultValue?: bigint; -}; - -/** - * Describes the message dotcore.catalog.v1.UnsignedIntegerEngineParameterSchema. - * Use `create(UnsignedIntegerEngineParameterSchemaSchema)` to create a new message. - */ -export const UnsignedIntegerEngineParameterSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_engine_release, 6); - -/** - * Supplies a complete set of exact typed engine parameter values. - * - * @generated from message dotcore.catalog.v1.EngineParameterValues - */ -export type EngineParameterValues = Message<"dotcore.catalog.v1.EngineParameterValues"> & { - /** - * Exact values keyed by stable parameter identity. - * - * @generated from field: repeated dotcore.catalog.v1.EngineParameterValue values = 1; - */ - values: EngineParameterValue[]; -}; - -/** - * Describes the message dotcore.catalog.v1.EngineParameterValues. - * Use `create(EngineParameterValuesSchema)` to create a new message. - */ -export const EngineParameterValuesSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_engine_release, 7); - -/** - * Supplies one exact typed engine parameter value. - * - * @generated from message dotcore.catalog.v1.EngineParameterValue - */ -export type EngineParameterValue = Message<"dotcore.catalog.v1.EngineParameterValue"> & { - /** - * Stable engine parameter identity. - * - * @generated from field: string parameter_id = 1; - */ - parameterId: string; - - /** - * @generated from oneof dotcore.catalog.v1.EngineParameterValue.value - */ - value: { - /** - * Exact unsigned-integer value. - * - * @generated from field: uint64 unsigned_integer = 2; - */ - value: bigint; - case: "unsignedInteger"; - } | { - /** - * Exact boolean value, preserving false presence. - * - * @generated from field: bool boolean = 3; - */ - value: boolean; - case: "boolean"; - } | { case: undefined; value?: undefined }; -}; - -/** - * Describes the message dotcore.catalog.v1.EngineParameterValue. - * Use `create(EngineParameterValueSchema)` to create a new message. - */ -export const EngineParameterValueSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_engine_release, 8); - diff --git a/frontend/src/gen/dotcore/catalog/v1/model_pb.ts b/frontend/src/gen/dotcore/catalog/v1/model_pb.ts index d858eafa..d865b4ae 100644 --- a/frontend/src/gen/dotcore/catalog/v1/model_pb.ts +++ b/frontend/src/gen/dotcore/catalog/v1/model_pb.ts @@ -4,7 +4,7 @@ import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; -import type { EngineArtifactReference, EngineParameterValues } from "./engine_release_pb"; +import type { EngineArtifactReference } from "./engine_release_pb"; import { file_dotcore_catalog_v1_engine_release } from "./engine_release_pb"; import type { ModelParallelShape } from "./execution_pb"; import { file_dotcore_catalog_v1_execution } from "./execution_pb"; @@ -12,6 +12,8 @@ import type { HardwareRequirements } from "./hardware_class_pb"; import { file_dotcore_catalog_v1_hardware_class } from "./hardware_class_pb"; import type { InferenceRequestKind, ModelInputCapabilities } from "./model_capabilities_pb"; import { file_dotcore_catalog_v1_model_capabilities } from "./model_capabilities_pb"; +import type { ParameterValues } from "./parameter_pb"; +import { file_dotcore_catalog_v1_parameter } from "./parameter_pb"; import type { EngineModelConfiguration } from "../../engine/v1/engine_pb"; import { file_dotcore_engine_v1_engine } from "../../engine/v1/engine_pb"; import type { Message } from "@bufbuild/protobuf"; @@ -20,7 +22,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/catalog/v1/model.proto. */ export const file_dotcore_catalog_v1_model: GenFile = /*@__PURE__*/ - fileDesc("Ch5kb3Rjb3JlL2NhdGFsb2cvdjEvbW9kZWwucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSL2AwoFTW9kZWwSEAoIbW9kZWxfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSHgoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgMIAEoDRI0CglhcnRpZmFjdHMYBCADKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBIyCghwcm9maWxlcxgFIAMoCzIgLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFByb2ZpbGUSRwoTYXV4aWxpYXJ5X2FydGlmYWN0cxgHIAMoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEF1eGlsaWFyeUFydGlmYWN0EkQKDmNvbmZpZ3VyYXRpb25zGAggAygLMiwuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRW5naW5lQ29uZmlndXJhdGlvbhIwCgdvcHRpb25zGAkgAygLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uEjsKDGludGVsbGlnZW5jZRgKIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5JbnRlbGxpZ2VuY2VTY29yZRIsCgdsaWNlbnNlGAsgASgLMhsuZG90Y29yZS5jYXRhbG9nLnYxLkxpY2Vuc2UiJAoRSW50ZWxsaWdlbmNlU2NvcmUSDwoHb3ZlcmFsbBgBIAEoASIoCgdMaWNlbnNlEgoKAmlkGAEgASgJEhEKCXRlcm1zX3VybBgCIAEoCSKAAQoNTW9kZWxBcnRpZmFjdBI9CgZzb3VyY2UYASABKAsyLS5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VBcnRpZmFjdFNvdXJjZRITCgthcnRpZmFjdF9pZBgCIAEoCRIbChN3ZWlnaHRfcXVhbnRpemF0aW9uGAMgASgJInYKFk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSHQoVYXV4aWxpYXJ5X2FydGlmYWN0X2lkGAEgASgJEj0KBnNvdXJjZRgCIAEoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUFydGlmYWN0U291cmNlIs4BChlIdWdnaW5nRmFjZUFydGlmYWN0U291cmNlEhIKCnJlcG9zaXRvcnkYASABKAkSEAoIcmV2aXNpb24YAiABKAkSOwoEZmlsZRgDIAEoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUZpbGVBcnRpZmFjdEgAEkMKCHNuYXBzaG90GAQgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkh1Z2dpbmdGYWNlU25hcHNob3RBcnRpZmFjdEgAQgkKB2NvbnRlbnQiQgoXSHVnZ2luZ0ZhY2VGaWxlQXJ0aWZhY3QSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSJZChtIdWdnaW5nRmFjZVNuYXBzaG90QXJ0aWZhY3QSOgoFZmlsZXMYASADKAsyKy5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUiQgoXSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSKiBQoYTW9kZWxFbmdpbmVDb25maWd1cmF0aW9uEhgKEGNvbmZpZ3VyYXRpb25faWQYASABKAkSRQoQZW5naW5lX2FydGlmYWN0cxgCIAMoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVBcnRpZmFjdFJlZmVyZW5jZRJDChFhcnRpZmFjdF9iaW5kaW5ncxgDIAMoCzIoLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEFydGlmYWN0QmluZGluZxI9ChBoYXJkd2FyZV9zdXBwb3J0GAkgAygLMiMuZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlU3VwcG9ydBJJChRlbmdpbmVfY29uZmlndXJhdGlvbhgFIAEoCzIrLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZU1vZGVsQ29uZmlndXJhdGlvbhJOChZleGVjdXRpb25fY2FwYWJpbGl0aWVzGAYgASgLMi4uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRXhlY3V0aW9uQ2FwYWJpbGl0aWVzEkYKEmlucHV0X2NhcGFiaWxpdGllcxgHIAEoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbElucHV0Q2FwYWJpbGl0aWVzEj8KDXJlcXVlc3Rfa2luZHMYCyADKA4yKC5kb3Rjb3JlLmNhdGFsb2cudjEuSW5mZXJlbmNlUmVxdWVzdEtpbmQSPQoHb3B0aW9ucxgIIAMoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbENvbmZpZ3VyYXRpb25PcHRpb24SIwoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgKIAEoDUgAiAEBQhkKF19tYXhpbXVtX2NvbnRleHRfdG9rZW5zImUKFE1vZGVsQXJ0aWZhY3RCaW5kaW5nEhIKCmJpbmRpbmdfaWQYASABKAkSGQoRbW9kZWxfYXJ0aWZhY3RfaWQYAiABKAkSHgoWYXV4aWxpYXJ5X2FydGlmYWN0X2lkcxgDIAMoCSK/AgoMTW9kZWxQcm9maWxlEhIKCnByb2ZpbGVfaWQYASABKAkSGAoQY29uZmlndXJhdGlvbl9pZBgCIAEoCRIpCiFkZWZhdWx0X21vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYAyABKAkSTAoZZW5naW5lX3BhcmFtZXRlcl9kZWZhdWx0cxgEIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJWYWx1ZXMSFAoMZGlzcGxheV9uYW1lGAUgASgJEhMKC2Rlc2NyaXB0aW9uGAYgASgJEj4KD29wdGlvbl9kZWZhdWx0cxgHIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVleHBvc2VkX3BhcmFtZXRlcl9pZHMYCCADKAkimgIKC01vZGVsT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSNwoGdmlzaW9uGAMgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLlZpc2lvbk1vZGVsT3B0aW9uSAASUgoUc3BlY3VsYXRpdmVfZGVjb2RpbmcYBCABKAsyMi5kb3Rjb3JlLmNhdGFsb2cudjEuU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uSAASTQoSa3ZfY2FjaGVfcHJlY2lzaW9uGAUgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkt2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbkgAQgYKBGtpbmQiEwoRVmlzaW9uTW9kZWxPcHRpb24iXwoeU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uEj0KBm1ldGhvZBgBIAEoDjItLmRvdGNvcmUuY2F0YWxvZy52MS5TcGVjdWxhdGl2ZURlY29kaW5nTWV0aG9kIh0KG0t2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbiLsAQoYTW9kZWxDb25maWd1cmF0aW9uT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRJGCgpwYXJhbWV0ZXJzGAIgAygLMjIuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyRGVmaW5pdGlvbhI9Cg5kZWZhdWx0X3ZhbHVlcxgDIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVzdXBwb3J0ZWRfYmluZGluZ19pZHMYBCADKAkSFwoPY29tcGF0aWJsZV93aGVuGAUgASgJItQCCh5Nb2RlbE9wdGlvblBhcmFtZXRlckRlZmluaXRpb24SFAoMcGFyYW1ldGVyX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRJICgdib29sZWFuGAMgASgLMjUuZG90Y29yZS5jYXRhbG9nLnYxLkJvb2xlYW5Nb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYUgAElkKEHVuc2lnbmVkX2ludGVnZXIYBCABKAsyPS5kb3Rjb3JlLmNhdGFsb2cudjEuVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIABJPCgtzdHJpbmdfZW51bRgFIAEoCzI4LmRvdGNvcmUuY2F0YWxvZy52MS5TdHJpbmdFbnVtTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIAEIQCg5wYXJhbWV0ZXJfdHlwZSIjCiFCb29sZWFuTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWEiWwopVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWESDwoHbWluaW11bRgBIAEoBBIPCgdtYXhpbXVtGAIgASgEEgwKBHVuaXQYAyABKAkiNgokU3RyaW5nRW51bU1vZGVsT3B0aW9uUGFyYW1ldGVyU2NoZW1hEg4KBnZhbHVlcxgBIAMoCSJlChFNb2RlbE9wdGlvblZhbHVlcxIRCglvcHRpb25faWQYASABKAkSPQoGdmFsdWVzGAIgAygLMi0uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyVmFsdWUiewoZTW9kZWxPcHRpb25QYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSEQoHYm9vbGVhbhgCIAEoCEgAEhoKEHVuc2lnbmVkX2ludGVnZXIYAyABKARIABIQCgZzdHJpbmcYBCABKAlIAEIHCgV2YWx1ZSJnChpNb2RlbEV4ZWN1dGlvbkNhcGFiaWxpdGllcxJJChlzdXBwb3J0ZWRfcGFyYWxsZWxfc2hhcGVzGAEgAygOMiYuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsUGFyYWxsZWxTaGFwZSJ1Cg9IYXJkd2FyZVN1cHBvcnQSGQoRaGFyZHdhcmVfY2xhc3NfaWQYASABKAkSRwoVaGFyZHdhcmVfcmVxdWlyZW1lbnRzGAIgASgLMiguZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlUmVxdWlyZW1lbnRzKm0KGVNwZWN1bGF0aXZlRGVjb2RpbmdNZXRob2QSKwonU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX1VOU1BFQ0lGSUVEEAASIwofU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX01UUBABYgZwcm90bzM", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model_capabilities, file_dotcore_engine_v1_engine]); + fileDesc("Ch5kb3Rjb3JlL2NhdGFsb2cvdjEvbW9kZWwucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSL2AwoFTW9kZWwSEAoIbW9kZWxfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSHgoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgMIAEoDRI0CglhcnRpZmFjdHMYBCADKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBIyCghwcm9maWxlcxgFIAMoCzIgLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFByb2ZpbGUSRwoTYXV4aWxpYXJ5X2FydGlmYWN0cxgHIAMoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEF1eGlsaWFyeUFydGlmYWN0EkQKDmNvbmZpZ3VyYXRpb25zGAggAygLMiwuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRW5naW5lQ29uZmlndXJhdGlvbhIwCgdvcHRpb25zGAkgAygLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uEjsKDGludGVsbGlnZW5jZRgKIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5JbnRlbGxpZ2VuY2VTY29yZRIsCgdsaWNlbnNlGAsgASgLMhsuZG90Y29yZS5jYXRhbG9nLnYxLkxpY2Vuc2UiJAoRSW50ZWxsaWdlbmNlU2NvcmUSDwoHb3ZlcmFsbBgBIAEoASIoCgdMaWNlbnNlEgoKAmlkGAEgASgJEhEKCXRlcm1zX3VybBgCIAEoCSKAAQoNTW9kZWxBcnRpZmFjdBI9CgZzb3VyY2UYASABKAsyLS5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VBcnRpZmFjdFNvdXJjZRITCgthcnRpZmFjdF9pZBgCIAEoCRIbChN3ZWlnaHRfcXVhbnRpemF0aW9uGAMgASgJInYKFk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSHQoVYXV4aWxpYXJ5X2FydGlmYWN0X2lkGAEgASgJEj0KBnNvdXJjZRgCIAEoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUFydGlmYWN0U291cmNlIs4BChlIdWdnaW5nRmFjZUFydGlmYWN0U291cmNlEhIKCnJlcG9zaXRvcnkYASABKAkSEAoIcmV2aXNpb24YAiABKAkSOwoEZmlsZRgDIAEoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUZpbGVBcnRpZmFjdEgAEkMKCHNuYXBzaG90GAQgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkh1Z2dpbmdGYWNlU25hcHNob3RBcnRpZmFjdEgAQgkKB2NvbnRlbnQiQgoXSHVnZ2luZ0ZhY2VGaWxlQXJ0aWZhY3QSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSJZChtIdWdnaW5nRmFjZVNuYXBzaG90QXJ0aWZhY3QSOgoFZmlsZXMYASADKAsyKy5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUiQgoXSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSKiBQoYTW9kZWxFbmdpbmVDb25maWd1cmF0aW9uEhgKEGNvbmZpZ3VyYXRpb25faWQYASABKAkSRQoQZW5naW5lX2FydGlmYWN0cxgCIAMoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVBcnRpZmFjdFJlZmVyZW5jZRJDChFhcnRpZmFjdF9iaW5kaW5ncxgDIAMoCzIoLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEFydGlmYWN0QmluZGluZxI9ChBoYXJkd2FyZV9zdXBwb3J0GAkgAygLMiMuZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlU3VwcG9ydBJJChRlbmdpbmVfY29uZmlndXJhdGlvbhgFIAEoCzIrLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZU1vZGVsQ29uZmlndXJhdGlvbhJOChZleGVjdXRpb25fY2FwYWJpbGl0aWVzGAYgASgLMi4uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRXhlY3V0aW9uQ2FwYWJpbGl0aWVzEkYKEmlucHV0X2NhcGFiaWxpdGllcxgHIAEoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbElucHV0Q2FwYWJpbGl0aWVzEj8KDXJlcXVlc3Rfa2luZHMYCyADKA4yKC5kb3Rjb3JlLmNhdGFsb2cudjEuSW5mZXJlbmNlUmVxdWVzdEtpbmQSPQoHb3B0aW9ucxgIIAMoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbENvbmZpZ3VyYXRpb25PcHRpb24SIwoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgKIAEoDUgAiAEBQhkKF19tYXhpbXVtX2NvbnRleHRfdG9rZW5zImUKFE1vZGVsQXJ0aWZhY3RCaW5kaW5nEhIKCmJpbmRpbmdfaWQYASABKAkSGQoRbW9kZWxfYXJ0aWZhY3RfaWQYAiABKAkSHgoWYXV4aWxpYXJ5X2FydGlmYWN0X2lkcxgDIAMoCSK5AgoMTW9kZWxQcm9maWxlEhIKCnByb2ZpbGVfaWQYASABKAkSGAoQY29uZmlndXJhdGlvbl9pZBgCIAEoCRIpCiFkZWZhdWx0X21vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYAyABKAkSRgoZZW5naW5lX3BhcmFtZXRlcl9kZWZhdWx0cxgEIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSFAoMZGlzcGxheV9uYW1lGAUgASgJEhMKC2Rlc2NyaXB0aW9uGAYgASgJEj4KD29wdGlvbl9kZWZhdWx0cxgHIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVleHBvc2VkX3BhcmFtZXRlcl9pZHMYCCADKAkimgIKC01vZGVsT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSNwoGdmlzaW9uGAMgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLlZpc2lvbk1vZGVsT3B0aW9uSAASUgoUc3BlY3VsYXRpdmVfZGVjb2RpbmcYBCABKAsyMi5kb3Rjb3JlLmNhdGFsb2cudjEuU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uSAASTQoSa3ZfY2FjaGVfcHJlY2lzaW9uGAUgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkt2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbkgAQgYKBGtpbmQiEwoRVmlzaW9uTW9kZWxPcHRpb24iXwoeU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uEj0KBm1ldGhvZBgBIAEoDjItLmRvdGNvcmUuY2F0YWxvZy52MS5TcGVjdWxhdGl2ZURlY29kaW5nTWV0aG9kIh0KG0t2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbiLsAQoYTW9kZWxDb25maWd1cmF0aW9uT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRJGCgpwYXJhbWV0ZXJzGAIgAygLMjIuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyRGVmaW5pdGlvbhI9Cg5kZWZhdWx0X3ZhbHVlcxgDIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVzdXBwb3J0ZWRfYmluZGluZ19pZHMYBCADKAkSFwoPY29tcGF0aWJsZV93aGVuGAUgASgJItQCCh5Nb2RlbE9wdGlvblBhcmFtZXRlckRlZmluaXRpb24SFAoMcGFyYW1ldGVyX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRJICgdib29sZWFuGAMgASgLMjUuZG90Y29yZS5jYXRhbG9nLnYxLkJvb2xlYW5Nb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYUgAElkKEHVuc2lnbmVkX2ludGVnZXIYBCABKAsyPS5kb3Rjb3JlLmNhdGFsb2cudjEuVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIABJPCgtzdHJpbmdfZW51bRgFIAEoCzI4LmRvdGNvcmUuY2F0YWxvZy52MS5TdHJpbmdFbnVtTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIAEIQCg5wYXJhbWV0ZXJfdHlwZSIjCiFCb29sZWFuTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWEiWwopVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWESDwoHbWluaW11bRgBIAEoBBIPCgdtYXhpbXVtGAIgASgEEgwKBHVuaXQYAyABKAkiNgokU3RyaW5nRW51bU1vZGVsT3B0aW9uUGFyYW1ldGVyU2NoZW1hEg4KBnZhbHVlcxgBIAMoCSJlChFNb2RlbE9wdGlvblZhbHVlcxIRCglvcHRpb25faWQYASABKAkSPQoGdmFsdWVzGAIgAygLMi0uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyVmFsdWUiewoZTW9kZWxPcHRpb25QYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSEQoHYm9vbGVhbhgCIAEoCEgAEhoKEHVuc2lnbmVkX2ludGVnZXIYAyABKARIABIQCgZzdHJpbmcYBCABKAlIAEIHCgV2YWx1ZSJnChpNb2RlbEV4ZWN1dGlvbkNhcGFiaWxpdGllcxJJChlzdXBwb3J0ZWRfcGFyYWxsZWxfc2hhcGVzGAEgAygOMiYuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsUGFyYWxsZWxTaGFwZSJ1Cg9IYXJkd2FyZVN1cHBvcnQSGQoRaGFyZHdhcmVfY2xhc3NfaWQYASABKAkSRwoVaGFyZHdhcmVfcmVxdWlyZW1lbnRzGAIgASgLMiguZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlUmVxdWlyZW1lbnRzKm0KGVNwZWN1bGF0aXZlRGVjb2RpbmdNZXRob2QSKwonU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX1VOU1BFQ0lGSUVEEAASIwofU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX01UUBABYgZwcm90bzM", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model_capabilities, file_dotcore_catalog_v1_parameter, file_dotcore_engine_v1_engine]); /** * An immutable artifact-manager catalog declaration. The inference controller @@ -510,9 +512,9 @@ export type ModelProfile = Message<"dotcore.catalog.v1.ModelProfile"> & { /** * Typed engine parameter defaults for this profile, overlaid on the engine defaults. * - * @generated from field: dotcore.catalog.v1.EngineParameterValues engine_parameter_defaults = 4; + * @generated from field: dotcore.catalog.v1.ParameterValues engine_parameter_defaults = 4; */ - engineParameterDefaults?: EngineParameterValues; + engineParameterDefaults?: ParameterValues; /** * Optional human-readable name for this profile. diff --git a/frontend/src/gen/dotcore/catalog/v1/parameter_pb.ts b/frontend/src/gen/dotcore/catalog/v1/parameter_pb.ts index 0028fa5b..8632aef4 100644 --- a/frontend/src/gen/dotcore/catalog/v1/parameter_pb.ts +++ b/frontend/src/gen/dotcore/catalog/v1/parameter_pb.ts @@ -2,19 +2,20 @@ // @generated from file dotcore/catalog/v1/parameter.proto (package dotcore.catalog.v1, syntax proto3) /* eslint-disable */ -import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; -import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; +import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; +import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file dotcore/catalog/v1/parameter.proto. */ export const file_dotcore_catalog_v1_parameter: GenFile = /*@__PURE__*/ - fileDesc("CiJkb3Rjb3JlL2NhdGFsb2cvdjEvcGFyYW1ldGVyLnByb3RvEhJkb3Rjb3JlLmNhdGFsb2cudjEivQIKE1BhcmFtZXRlckRlZmluaXRpb24SFAoMcGFyYW1ldGVyX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRI9Cgdib29sZWFuGAQgASgLMiouZG90Y29yZS5jYXRhbG9nLnYxLkJvb2xlYW5QYXJhbWV0ZXJTY2hlbWFIABJOChB1bnNpZ25lZF9pbnRlZ2VyGAUgASgLMjIuZG90Y29yZS5jYXRhbG9nLnYxLlVuc2lnbmVkSW50ZWdlclBhcmFtZXRlclNjaGVtYUgAEkQKC3N0cmluZ19lbnVtGAYgASgLMi0uZG90Y29yZS5jYXRhbG9nLnYxLlN0cmluZ0VudW1QYXJhbWV0ZXJTY2hlbWFIAEIQCg5wYXJhbWV0ZXJfdHlwZSJGChZCb29sZWFuUGFyYW1ldGVyU2NoZW1hEhoKDWRlZmF1bHRfdmFsdWUYASABKAhIAIgBAUIQCg5fZGVmYXVsdF92YWx1ZSJ+Ch5VbnNpZ25lZEludGVnZXJQYXJhbWV0ZXJTY2hlbWESDwoHbWluaW11bRgBIAEoBBIPCgdtYXhpbXVtGAIgASgEEgwKBHVuaXQYAyABKAkSGgoNZGVmYXVsdF92YWx1ZRgEIAEoBEgAiAEBQhAKDl9kZWZhdWx0X3ZhbHVlIlkKGVN0cmluZ0VudW1QYXJhbWV0ZXJTY2hlbWESDgoGdmFsdWVzGAEgAygJEhoKDWRlZmF1bHRfdmFsdWUYAiABKAlIAIgBAUIQCg5fZGVmYXVsdF92YWx1ZSJwCg5QYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSEQoHYm9vbGVhbhgCIAEoCEgAEhoKEHVuc2lnbmVkX2ludGVnZXIYAyABKARIABIQCgZzdHJpbmcYBCABKAlIAEIHCgV2YWx1ZWIGcHJvdG8z"); + fileDesc("CiJkb3Rjb3JlL2NhdGFsb2cvdjEvcGFyYW1ldGVyLnByb3RvEhJkb3Rjb3JlLmNhdGFsb2cudjEi+gIKE1BhcmFtZXRlckRlZmluaXRpb24SFAoMcGFyYW1ldGVyX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRI7Cgp2aXNpYmlsaXR5GAcgASgOMicuZG90Y29yZS5jYXRhbG9nLnYxLlBhcmFtZXRlclZpc2liaWxpdHkSPQoHYm9vbGVhbhgEIAEoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Cb29sZWFuUGFyYW1ldGVyU2NoZW1hSAASTgoQdW5zaWduZWRfaW50ZWdlchgFIAEoCzIyLmRvdGNvcmUuY2F0YWxvZy52MS5VbnNpZ25lZEludGVnZXJQYXJhbWV0ZXJTY2hlbWFIABJECgtzdHJpbmdfZW51bRgGIAEoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5TdHJpbmdFbnVtUGFyYW1ldGVyU2NoZW1hSABCEAoOcGFyYW1ldGVyX3R5cGUiRgoWQm9vbGVhblBhcmFtZXRlclNjaGVtYRIaCg1kZWZhdWx0X3ZhbHVlGAEgASgISACIAQFCEAoOX2RlZmF1bHRfdmFsdWUifgoeVW5zaWduZWRJbnRlZ2VyUGFyYW1ldGVyU2NoZW1hEg8KB21pbmltdW0YASABKAQSDwoHbWF4aW11bRgCIAEoBBIMCgR1bml0GAMgASgJEhoKDWRlZmF1bHRfdmFsdWUYBCABKARIAIgBAUIQCg5fZGVmYXVsdF92YWx1ZSJZChlTdHJpbmdFbnVtUGFyYW1ldGVyU2NoZW1hEg4KBnZhbHVlcxgBIAMoCRIaCg1kZWZhdWx0X3ZhbHVlGAIgASgJSACIAQFCEAoOX2RlZmF1bHRfdmFsdWUiRQoPUGFyYW1ldGVyVmFsdWVzEjIKBnZhbHVlcxgBIAMoCzIiLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZSJwCg5QYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSEQoHYm9vbGVhbhgCIAEoCEgAEhoKEHVuc2lnbmVkX2ludGVnZXIYAyABKARIABIQCgZzdHJpbmcYBCABKAlIAEIHCgV2YWx1ZSqfAQoTUGFyYW1ldGVyVmlzaWJpbGl0eRIkCiBQQVJBTUVURVJfVklTSUJJTElUWV9VTlNQRUNJRklFRBAAEh4KGlBBUkFNRVRFUl9WSVNJQklMSVRZX0JBU0lDEAESIQodUEFSQU1FVEVSX1ZJU0lCSUxJVFlfQURWQU5DRUQQAhIfChtQQVJBTUVURVJfVklTSUJJTElUWV9ISURERU4QA2IGcHJvdG8z"); /** - * Defines one owner-neutral typed parameter: its identity, label, guidance, and value constraints. - * Owners decide whether a default is required and how the parameter is shown. + * Defines one owner-neutral typed parameter: its identity, label, guidance, visibility and value + * constraints. Owners decide which types and visibilities they accept and whether a default is + * required. * * @generated from message dotcore.catalog.v1.ParameterDefinition */ @@ -40,6 +41,13 @@ export type ParameterDefinition = Message<"dotcore.catalog.v1.ParameterDefinitio */ description: string; + /** + * Where the console shows this parameter. + * + * @generated from field: dotcore.catalog.v1.ParameterVisibility visibility = 7; + */ + visibility: ParameterVisibility; + /** * @generated from oneof dotcore.catalog.v1.ParameterDefinition.parameter_type */ @@ -168,6 +176,27 @@ export type StringEnumParameterSchema = Message<"dotcore.catalog.v1.StringEnumPa export const StringEnumParameterSchemaSchema: GenMessage = /*@__PURE__*/ messageDesc(file_dotcore_catalog_v1_parameter, 3); +/** + * Supplies a set of exact typed parameter values. + * + * @generated from message dotcore.catalog.v1.ParameterValues + */ +export type ParameterValues = Message<"dotcore.catalog.v1.ParameterValues"> & { + /** + * Exact values keyed by stable parameter identity. + * + * @generated from field: repeated dotcore.catalog.v1.ParameterValue values = 1; + */ + values: ParameterValue[]; +}; + +/** + * Describes the message dotcore.catalog.v1.ParameterValues. + * Use `create(ParameterValuesSchema)` to create a new message. + */ +export const ParameterValuesSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_dotcore_catalog_v1_parameter, 4); + /** * Supplies one exact typed parameter value. * @@ -216,5 +245,46 @@ export type ParameterValue = Message<"dotcore.catalog.v1.ParameterValue"> & { * Use `create(ParameterValueSchema)` to create a new message. */ export const ParameterValueSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_parameter, 4); + messageDesc(file_dotcore_catalog_v1_parameter, 5); + +/** + * Where the console shows a parameter. + * + * @generated from enum dotcore.catalog.v1.ParameterVisibility + */ +export enum ParameterVisibility { + /** + * Invalid; every parameter declares its visibility. + * + * @generated from enum value: PARAMETER_VISIBILITY_UNSPECIFIED = 0; + */ + UNSPECIFIED = 0, + + /** + * Shown in the main view. + * + * @generated from enum value: PARAMETER_VISIBILITY_BASIC = 1; + */ + BASIC = 1, + + /** + * Shown only in the advanced view. + * + * @generated from enum value: PARAMETER_VISIBILITY_ADVANCED = 2; + */ + ADVANCED = 2, + + /** + * Never shown; the value comes from its default, a profile or sizing. + * + * @generated from enum value: PARAMETER_VISIBILITY_HIDDEN = 3; + */ + HIDDEN = 3, +} + +/** + * Describes the enum dotcore.catalog.v1.ParameterVisibility. + */ +export const ParameterVisibilitySchema: GenEnum = /*@__PURE__*/ + enumDesc(file_dotcore_catalog_v1_parameter, 0); diff --git a/frontend/src/gen/dotcore/model/v1/deployment_pb.ts b/frontend/src/gen/dotcore/model/v1/deployment_pb.ts index 28ac4d22..a705e6f8 100644 --- a/frontend/src/gen/dotcore/model/v1/deployment_pb.ts +++ b/frontend/src/gen/dotcore/model/v1/deployment_pb.ts @@ -4,7 +4,7 @@ import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; -import type { EngineArtifact, EngineParameterSchema, EngineParameterValues } from "../../catalog/v1/engine_release_pb"; +import type { EngineArtifact, EngineParameterSchema } from "../../catalog/v1/engine_release_pb"; import { file_dotcore_catalog_v1_engine_release } from "../../catalog/v1/engine_release_pb"; import type { ModelParallelShape } from "../../catalog/v1/execution_pb"; import { file_dotcore_catalog_v1_execution } from "../../catalog/v1/execution_pb"; @@ -16,6 +16,8 @@ import type { InferenceRequestKind, ModelInputCapabilities } from "../../catalog import { file_dotcore_catalog_v1_model_capabilities } from "../../catalog/v1/model_capabilities_pb"; import type { OciPlatform } from "../../catalog/v1/oci_pb"; import { file_dotcore_catalog_v1_oci } from "../../catalog/v1/oci_pb"; +import type { ParameterValues } from "../../catalog/v1/parameter_pb"; +import { file_dotcore_catalog_v1_parameter } from "../../catalog/v1/parameter_pb"; import type { Selector } from "../../catalog/v1/selector_pb"; import { file_dotcore_catalog_v1_selector } from "../../catalog/v1/selector_pb"; import type { StorageBinding } from "../../catalog/v1/storage_pb"; @@ -42,7 +44,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/model/v1/deployment.proto. */ export const file_dotcore_model_v1_deployment: GenFile = /*@__PURE__*/ - fileDesc("CiFkb3Rjb3JlL21vZGVsL3YxL2RlcGxveW1lbnQucHJvdG8SEGRvdGNvcmUubW9kZWwudjEirwUKGk1vZGVsRGVwbG95bWVudERlY2xhcmF0aW9uEhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkSOAoJcGxhY2VtZW50GAIgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkgKGHJlcXVlc3RlZF9wYXJhbGxlbF9zaGFwZRgDIAEoDjImLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFBhcmFsbGVsU2hhcGUSOwoIc25hcHNob3QYBCABKAsyKS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudFNuYXBzaG90EkQKDWRlc2lyZWRfc3RhdGUYBSABKA4yLS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudERlc2lyZWRTdGF0ZRJbCh51cHN0cmVhbV9kZXNpcmVkX2NvbmZpZ3VyYXRpb24YBiABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLlVwc3RyZWFtTW9kZWxEZXNpcmVkQ29uZmlndXJhdGlvbhIdChVtb2RlbF9kZXBsb3ltZW50X25hbWUYByABKAkSHAoUbGlmZWN5Y2xlX2dlbmVyYXRpb24YCCABKAQSUgoUbGlmZWN5Y2xlX3RyYW5zaXRpb24YCSABKA4yNC5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudExpZmVjeWNsZVRyYW5zaXRpb24SIwobbGlmZWN5Y2xlX3JlY292ZXJ5X3JlcXVpcmVkGAogASgIEloKH25vZGVfcmVzb2x2ZWRfbGF1bmNoX2lkZW50aXRpZXMYCyADKAsyMS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuTm9kZVJlc29sdmVkTGF1bmNoSWRlbnRpdHkiygQKD01vZGVsRGVwbG95bWVudBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJEjcKBmludGVudBgCIAEoCzInLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50SW50ZW50EjsKCHNuYXBzaG90GAMgASgLMikuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnRTbmFwc2hvdBI1CgVzdGF0ZRgEIAEoCzImLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50U3RhdGUSRAoNZGVzaXJlZF9zdGF0ZRgFIAEoDjItLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50RGVzaXJlZFN0YXRlElsKHnVwc3RyZWFtX2Rlc2lyZWRfY29uZmlndXJhdGlvbhgGIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uEh0KFW1vZGVsX2RlcGxveW1lbnRfbmFtZRgHIAEoCRJPChJhY2NlbGVyYXRvcl9tZW1vcnkYCCABKAsyMy5kb3Rjb3JlLmRlcGxveW1lbnQudjEuQWNjZWxlcmF0b3JNZW1vcnlPYnNlcnZhdGlvbhJaCh9ub2RlX3Jlc29sdmVkX2xhdW5jaF9pZGVudGl0aWVzGAkgAygLMjEuZG90Y29yZS5kZXBsb3ltZW50LnYxLk5vZGVSZXNvbHZlZExhdW5jaElkZW50aXR5IpsBChVNb2RlbERlcGxveW1lbnRJbnRlbnQSOAoJcGxhY2VtZW50GAEgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkgKGHJlcXVlc3RlZF9wYXJhbGxlbF9zaGFwZRgCIAEoDjImLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFBhcmFsbGVsU2hhcGUiswEKF01vZGVsRGVwbG95bWVudFNuYXBzaG90EkcKBWxvY2FsGAEgASgLMjYuZG90Y29yZS5tb2RlbC52MS5SZXNvbHZlZExvY2FsTW9kZWxEZXBsb3ltZW50U25hcHNob3RIABJFCgh1cHN0cmVhbRgEIAEoCzIxLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlcGxveW1lbnRTbmFwc2hvdEgAQggKBnNvdXJjZSKkCQokUmVzb2x2ZWRMb2NhbE1vZGVsRGVwbG95bWVudFNuYXBzaG90EhAKCG1vZGVsX2lkGAEgASgJEhoKEm1vZGVsX2Rpc3BsYXlfbmFtZRgCIAEoCRIVCg1tb2RlbF92ZXJzaW9uGAMgASgJEhgKEGNvbmZpZ3VyYXRpb25faWQYBCABKAkSEgoKcHJvZmlsZV9pZBgFIAEoCRJBCg9lbmdpbmVfYXJ0aWZhY3QYBiABKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlJlc29sdmVkRW5naW5lQXJ0aWZhY3QSOQoObW9kZWxfYXJ0aWZhY3QYByABKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBJHChNhdXhpbGlhcnlfYXJ0aWZhY3RzGAggAygLMiouZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSQwoQaGFyZHdhcmVfc3VwcG9ydBgVIAEoCzIpLmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRIYXJkd2FyZVN1cHBvcnQSSgoVcmVzb2x2ZWRfZW5naW5lX3N0YXRlGAogASgLMisuZG90Y29yZS5lbmdpbmUudjEuUmVzb2x2ZWRFbmdpbmVNb2RlbFN0YXRlEk4KFmV4ZWN1dGlvbl9jYXBhYmlsaXRpZXMYCyABKAsyLi5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxFeGVjdXRpb25DYXBhYmlsaXRpZXMSRgoSaW5wdXRfY2FwYWJpbGl0aWVzGAwgASgLMiouZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsSW5wdXRDYXBhYmlsaXRpZXMSPwoNcmVxdWVzdF9raW5kcxgWIAMoDjIoLmRvdGNvcmUuY2F0YWxvZy52MS5JbmZlcmVuY2VSZXF1ZXN0S2luZBJKChdlbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgNIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJWYWx1ZXMSIgoaZW5naW5lX3BhcmFtZXRlcl9zY2hlbWFfaWQYDiABKAkSSgoXZW5naW5lX3BhcmFtZXRlcl9zY2hlbWEYDyABKAsyKS5kb3Rjb3JlLmNhdGFsb2cudjEuRW5naW5lUGFyYW1ldGVyU2NoZW1hEkYKE2Rlc2lyZWRfbGF1bmNoX3BsYW4YECABKAsyKS5kb3Rjb3JlLm1vZGVsLnYxLlBvcnRhYmxlTW9kZWxMYXVuY2hQbGFuEh4KFmN1c3RvbV9hcmd1bWVudF90b2tlbnMYESADKAkSPwoQcmVzb2x2ZWRfb3B0aW9ucxgSIAMoCzIlLmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRNb2RlbE9wdGlvbhJBCg9zZWxlY3RlZF90YXJnZXQYEyABKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlJlc29sdmVkU2VsZWN0ZWRUYXJnZXQSMAoGc2l6aW5nGBQgASgLMiAuZG90Y29yZS5tb2RlbC52MS5SZXNvbHZlZFNpemluZyJMChNSZXNvbHZlZE1vZGVsT3B0aW9uEjUKBnZhbHVlcxgBIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcyKtAQoXUmVzb2x2ZWRIYXJkd2FyZVN1cHBvcnQSGQoRaGFyZHdhcmVfY2xhc3NfaWQYASABKAkSLgoIc2VsZWN0b3IYAiABKAsyHC5kb3Rjb3JlLmNhdGFsb2cudjEuU2VsZWN0b3ISRwoVaGFyZHdhcmVfcmVxdWlyZW1lbnRzGAMgASgLMiguZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlUmVxdWlyZW1lbnRzItIBChZSZXNvbHZlZFNlbGVjdGVkVGFyZ2V0El4KH2FjY2VsZXJhdG9yX21lbW9yeV9hcmNoaXRlY3R1cmUYASABKA4yNS5kb3Rjb3JlLm9ic2VydmF0aW9uLnYxLkFjY2VsZXJhdG9yTWVtb3J5QXJjaGl0ZWN0dXJlEjAKI2FjY2VsZXJhdG9yX21lbW9yeV9wb29sX3RvdGFsX2J5dGVzGAIgASgESACIAQFCJgokX2FjY2VsZXJhdG9yX21lbW9yeV9wb29sX3RvdGFsX2J5dGVzIrABCg5SZXNvbHZlZFNpemluZxIlChhhY2NlbGVyYXRvcl9tZW1vcnlfYnl0ZXMYASABKARIAIgBARIkChxkZXJpdmVkX2VuZ2luZV9wYXJhbWV0ZXJfaWRzGAIgAygJEh4KEWhvc3RfbWVtb3J5X2J5dGVzGAMgASgESAGIAQFCGwoZX2FjY2VsZXJhdG9yX21lbW9yeV9ieXRlc0IUChJfaG9zdF9tZW1vcnlfYnl0ZXMizwMKFlJlc29sdmVkRW5naW5lQXJ0aWZhY3QSGQoRZW5naW5lX3JlbGVhc2VfaWQYASABKAkSMgoLZW5naW5lX2tpbmQYAiABKA4yHS5kb3Rjb3JlLmVuZ2luZS52MS5FbmdpbmVLaW5kEhYKDmVuZ2luZV92ZXJzaW9uGAMgASgJEjQKCGFydGlmYWN0GAQgASgLMiIuZG90Y29yZS5jYXRhbG9nLnYxLkVuZ2luZUFydGlmYWN0EjEKCHBsYXRmb3JtGAcgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEhMKC2FjY2VsZXJhdG9yGAggASgJEisKI21pbmltdW1fbnZpZGlhX2RyaXZlcl9tYWpvcl92ZXJzaW9uGAkgASgNEkwKEnByZXBhcmF0aW9uX3BvbGljeRgFIAEoDjIwLmRvdGNvcmUuZGVwbG95bWVudC52MS5BcnRpZmFjdFByZXBhcmF0aW9uUG9saWN5EhcKD2xhdW5jaF9pZGVudGl0eRgGIAEoCRI8ChBzdG9yYWdlX2JpbmRpbmdzGAogAygLMiIuZG90Y29yZS5jYXRhbG9nLnYxLlN0b3JhZ2VCaW5kaW5nIsMBChdQb3J0YWJsZU1vZGVsTGF1bmNoUGxhbhJFCglhcmd1bWVudHMYASADKAsyMi5kb3Rjb3JlLm1vZGVsLnYxLlBvcnRhYmxlTW9kZWxMYXVuY2hBcmd1bWVudFRva2VuEhYKDmZvcm1hdF92ZXJzaW9uGAIgASgNEkkKEWFydGlmYWN0X2JpbmRpbmdzGAMgAygLMi4uZG90Y29yZS5tb2RlbC52MS5Qb3J0YWJsZU1vZGVsQXJ0aWZhY3RCaW5kaW5nIsIBCiBQb3J0YWJsZU1vZGVsTGF1bmNoQXJndW1lbnRUb2tlbhIRCgdsaXRlcmFsGAEgASgJSAASHQoTYXJ0aWZhY3RfYmluZGluZ19pZBgCIAEoCUgAEjMKEWVuZ2luZV9leGVjdXRhYmxlGAMgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SAASFgoMc2VydmljZV9ob3N0GAQgASgJSAASFgoMc2VydmljZV9wb3J0GAUgASgJSABCBwoFdmFsdWUijwEKHFBvcnRhYmxlTW9kZWxBcnRpZmFjdEJpbmRpbmcSEgoKYmluZGluZ19pZBgBIAEoCRIbChFtb2RlbF9hcnRpZmFjdF9pZBgCIAEoCUgAEh8KFWF1eGlsaWFyeV9hcnRpZmFjdF9pZBgDIAEoCUgAEhEKCXJlYWRfb25seRgFIAEoCEIKCghhcnRpZmFjdCJtCh9VcHN0cmVhbU1vZGVsRGVwbG95bWVudFNuYXBzaG90EkoKF3Vwc3RyZWFtX21vZGVsX3RlbXBsYXRlGAEgASgLMikuZG90Y29yZS5jYXRhbG9nLnYxLlVwc3RyZWFtTW9kZWxUZW1wbGF0ZSKlAgohVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uEhkKEXVwc3RyZWFtX21vZGVsX2lkGAEgASgJEg8KB2FwaV9rZXkYAiABKAkSTAoSaW5wdXRfY2FwYWJpbGl0aWVzGAQgASgLMjAuZG90Y29yZS5tb2RlbC52MS5VcHN0cmVhbU1vZGVsSW5wdXRDYXBhYmlsaXRpZXMSSQoIZW5kcG9pbnQYBSABKAsyNy5kb3Rjb3JlLm1vZGVsLnYxLk9wZW5BaUNvbXBhdGlibGVFbmRwb2ludENvbmZpZ3VyYXRpb24SOwoIYm91bmRhcnkYBiABKAsyKS5kb3Rjb3JlLmNhdGFsb2cudjEuVXBzdHJlYW1Nb2RlbEJvdW5kYXJ5Ik8KHlVwc3RyZWFtTW9kZWxJbnB1dENhcGFiaWxpdGllcxIVCg1zdXBwb3J0c190ZXh0GAEgASgIEhYKDnN1cHBvcnRzX2ltYWdlGAIgASgIIlYKJU9wZW5BaUNvbXBhdGlibGVFbmRwb2ludENvbmZpZ3VyYXRpb24SEAoIYmFzZV91cmwYASABKAkSGwoTYWxsb3dfaW5zZWN1cmVfaHR0cBgCIAEoCCqkAgoiTW9kZWxEZXBsb3ltZW50TGlmZWN5Y2xlVHJhbnNpdGlvbhI1CjFNT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1VOU1BFQ0lGSUVEEAASMAosTU9ERUxfREVQTE9ZTUVOVF9MSUZFQ1lDTEVfVFJBTlNJVElPTl9DUkVBVEUQARIvCitNT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1BBVVNFEAISMAosTU9ERUxfREVQTE9ZTUVOVF9MSUZFQ1lDTEVfVFJBTlNJVElPTl9SRVNVTUUQAxIyCi5NT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1RFQVJET1dOEAQq0QEKG01vZGVsRGVwbG95bWVudERlc2lyZWRTdGF0ZRIuCipNT0RFTF9ERVBMT1lNRU5UX0RFU0lSRURfU1RBVEVfVU5TUEVDSUZJRUQQABIqCiZNT0RFTF9ERVBMT1lNRU5UX0RFU0lSRURfU1RBVEVfUFJFU0VOVBABEisKJ01PREVMX0RFUExPWU1FTlRfREVTSVJFRF9TVEFURV9URUFSRE9XThACEikKJU1PREVMX0RFUExPWU1FTlRfREVTSVJFRF9TVEFURV9QQVVTRUQQA2IGcHJvdG8z", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model, file_dotcore_catalog_v1_model_capabilities, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_selector, file_dotcore_catalog_v1_storage, file_dotcore_catalog_v1_upstream_model_template, file_dotcore_deployment_v1_accelerator_memory, file_dotcore_deployment_v1_artifact, file_dotcore_deployment_v1_placement, file_dotcore_engine_v1_engine, file_dotcore_model_v1_state, file_dotcore_observation_v1_observation, file_google_protobuf_empty]); + fileDesc("CiFkb3Rjb3JlL21vZGVsL3YxL2RlcGxveW1lbnQucHJvdG8SEGRvdGNvcmUubW9kZWwudjEirwUKGk1vZGVsRGVwbG95bWVudERlY2xhcmF0aW9uEhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkSOAoJcGxhY2VtZW50GAIgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkgKGHJlcXVlc3RlZF9wYXJhbGxlbF9zaGFwZRgDIAEoDjImLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFBhcmFsbGVsU2hhcGUSOwoIc25hcHNob3QYBCABKAsyKS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudFNuYXBzaG90EkQKDWRlc2lyZWRfc3RhdGUYBSABKA4yLS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudERlc2lyZWRTdGF0ZRJbCh51cHN0cmVhbV9kZXNpcmVkX2NvbmZpZ3VyYXRpb24YBiABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLlVwc3RyZWFtTW9kZWxEZXNpcmVkQ29uZmlndXJhdGlvbhIdChVtb2RlbF9kZXBsb3ltZW50X25hbWUYByABKAkSHAoUbGlmZWN5Y2xlX2dlbmVyYXRpb24YCCABKAQSUgoUbGlmZWN5Y2xlX3RyYW5zaXRpb24YCSABKA4yNC5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudExpZmVjeWNsZVRyYW5zaXRpb24SIwobbGlmZWN5Y2xlX3JlY292ZXJ5X3JlcXVpcmVkGAogASgIEloKH25vZGVfcmVzb2x2ZWRfbGF1bmNoX2lkZW50aXRpZXMYCyADKAsyMS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuTm9kZVJlc29sdmVkTGF1bmNoSWRlbnRpdHkiygQKD01vZGVsRGVwbG95bWVudBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJEjcKBmludGVudBgCIAEoCzInLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50SW50ZW50EjsKCHNuYXBzaG90GAMgASgLMikuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnRTbmFwc2hvdBI1CgVzdGF0ZRgEIAEoCzImLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50U3RhdGUSRAoNZGVzaXJlZF9zdGF0ZRgFIAEoDjItLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50RGVzaXJlZFN0YXRlElsKHnVwc3RyZWFtX2Rlc2lyZWRfY29uZmlndXJhdGlvbhgGIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uEh0KFW1vZGVsX2RlcGxveW1lbnRfbmFtZRgHIAEoCRJPChJhY2NlbGVyYXRvcl9tZW1vcnkYCCABKAsyMy5kb3Rjb3JlLmRlcGxveW1lbnQudjEuQWNjZWxlcmF0b3JNZW1vcnlPYnNlcnZhdGlvbhJaCh9ub2RlX3Jlc29sdmVkX2xhdW5jaF9pZGVudGl0aWVzGAkgAygLMjEuZG90Y29yZS5kZXBsb3ltZW50LnYxLk5vZGVSZXNvbHZlZExhdW5jaElkZW50aXR5IpsBChVNb2RlbERlcGxveW1lbnRJbnRlbnQSOAoJcGxhY2VtZW50GAEgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkgKGHJlcXVlc3RlZF9wYXJhbGxlbF9zaGFwZRgCIAEoDjImLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFBhcmFsbGVsU2hhcGUiswEKF01vZGVsRGVwbG95bWVudFNuYXBzaG90EkcKBWxvY2FsGAEgASgLMjYuZG90Y29yZS5tb2RlbC52MS5SZXNvbHZlZExvY2FsTW9kZWxEZXBsb3ltZW50U25hcHNob3RIABJFCgh1cHN0cmVhbRgEIAEoCzIxLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlcGxveW1lbnRTbmFwc2hvdEgAQggKBnNvdXJjZSKeCQokUmVzb2x2ZWRMb2NhbE1vZGVsRGVwbG95bWVudFNuYXBzaG90EhAKCG1vZGVsX2lkGAEgASgJEhoKEm1vZGVsX2Rpc3BsYXlfbmFtZRgCIAEoCRIVCg1tb2RlbF92ZXJzaW9uGAMgASgJEhgKEGNvbmZpZ3VyYXRpb25faWQYBCABKAkSEgoKcHJvZmlsZV9pZBgFIAEoCRJBCg9lbmdpbmVfYXJ0aWZhY3QYBiABKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlJlc29sdmVkRW5naW5lQXJ0aWZhY3QSOQoObW9kZWxfYXJ0aWZhY3QYByABKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBJHChNhdXhpbGlhcnlfYXJ0aWZhY3RzGAggAygLMiouZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSQwoQaGFyZHdhcmVfc3VwcG9ydBgVIAEoCzIpLmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRIYXJkd2FyZVN1cHBvcnQSSgoVcmVzb2x2ZWRfZW5naW5lX3N0YXRlGAogASgLMisuZG90Y29yZS5lbmdpbmUudjEuUmVzb2x2ZWRFbmdpbmVNb2RlbFN0YXRlEk4KFmV4ZWN1dGlvbl9jYXBhYmlsaXRpZXMYCyABKAsyLi5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxFeGVjdXRpb25DYXBhYmlsaXRpZXMSRgoSaW5wdXRfY2FwYWJpbGl0aWVzGAwgASgLMiouZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsSW5wdXRDYXBhYmlsaXRpZXMSPwoNcmVxdWVzdF9raW5kcxgWIAMoDjIoLmRvdGNvcmUuY2F0YWxvZy52MS5JbmZlcmVuY2VSZXF1ZXN0S2luZBJEChdlbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgNIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSIgoaZW5naW5lX3BhcmFtZXRlcl9zY2hlbWFfaWQYDiABKAkSSgoXZW5naW5lX3BhcmFtZXRlcl9zY2hlbWEYDyABKAsyKS5kb3Rjb3JlLmNhdGFsb2cudjEuRW5naW5lUGFyYW1ldGVyU2NoZW1hEkYKE2Rlc2lyZWRfbGF1bmNoX3BsYW4YECABKAsyKS5kb3Rjb3JlLm1vZGVsLnYxLlBvcnRhYmxlTW9kZWxMYXVuY2hQbGFuEh4KFmN1c3RvbV9hcmd1bWVudF90b2tlbnMYESADKAkSPwoQcmVzb2x2ZWRfb3B0aW9ucxgSIAMoCzIlLmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRNb2RlbE9wdGlvbhJBCg9zZWxlY3RlZF90YXJnZXQYEyABKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlJlc29sdmVkU2VsZWN0ZWRUYXJnZXQSMAoGc2l6aW5nGBQgASgLMiAuZG90Y29yZS5tb2RlbC52MS5SZXNvbHZlZFNpemluZyJMChNSZXNvbHZlZE1vZGVsT3B0aW9uEjUKBnZhbHVlcxgBIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcyKtAQoXUmVzb2x2ZWRIYXJkd2FyZVN1cHBvcnQSGQoRaGFyZHdhcmVfY2xhc3NfaWQYASABKAkSLgoIc2VsZWN0b3IYAiABKAsyHC5kb3Rjb3JlLmNhdGFsb2cudjEuU2VsZWN0b3ISRwoVaGFyZHdhcmVfcmVxdWlyZW1lbnRzGAMgASgLMiguZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlUmVxdWlyZW1lbnRzItIBChZSZXNvbHZlZFNlbGVjdGVkVGFyZ2V0El4KH2FjY2VsZXJhdG9yX21lbW9yeV9hcmNoaXRlY3R1cmUYASABKA4yNS5kb3Rjb3JlLm9ic2VydmF0aW9uLnYxLkFjY2VsZXJhdG9yTWVtb3J5QXJjaGl0ZWN0dXJlEjAKI2FjY2VsZXJhdG9yX21lbW9yeV9wb29sX3RvdGFsX2J5dGVzGAIgASgESACIAQFCJgokX2FjY2VsZXJhdG9yX21lbW9yeV9wb29sX3RvdGFsX2J5dGVzIrABCg5SZXNvbHZlZFNpemluZxIlChhhY2NlbGVyYXRvcl9tZW1vcnlfYnl0ZXMYASABKARIAIgBARIkChxkZXJpdmVkX2VuZ2luZV9wYXJhbWV0ZXJfaWRzGAIgAygJEh4KEWhvc3RfbWVtb3J5X2J5dGVzGAMgASgESAGIAQFCGwoZX2FjY2VsZXJhdG9yX21lbW9yeV9ieXRlc0IUChJfaG9zdF9tZW1vcnlfYnl0ZXMizwMKFlJlc29sdmVkRW5naW5lQXJ0aWZhY3QSGQoRZW5naW5lX3JlbGVhc2VfaWQYASABKAkSMgoLZW5naW5lX2tpbmQYAiABKA4yHS5kb3Rjb3JlLmVuZ2luZS52MS5FbmdpbmVLaW5kEhYKDmVuZ2luZV92ZXJzaW9uGAMgASgJEjQKCGFydGlmYWN0GAQgASgLMiIuZG90Y29yZS5jYXRhbG9nLnYxLkVuZ2luZUFydGlmYWN0EjEKCHBsYXRmb3JtGAcgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEhMKC2FjY2VsZXJhdG9yGAggASgJEisKI21pbmltdW1fbnZpZGlhX2RyaXZlcl9tYWpvcl92ZXJzaW9uGAkgASgNEkwKEnByZXBhcmF0aW9uX3BvbGljeRgFIAEoDjIwLmRvdGNvcmUuZGVwbG95bWVudC52MS5BcnRpZmFjdFByZXBhcmF0aW9uUG9saWN5EhcKD2xhdW5jaF9pZGVudGl0eRgGIAEoCRI8ChBzdG9yYWdlX2JpbmRpbmdzGAogAygLMiIuZG90Y29yZS5jYXRhbG9nLnYxLlN0b3JhZ2VCaW5kaW5nIsMBChdQb3J0YWJsZU1vZGVsTGF1bmNoUGxhbhJFCglhcmd1bWVudHMYASADKAsyMi5kb3Rjb3JlLm1vZGVsLnYxLlBvcnRhYmxlTW9kZWxMYXVuY2hBcmd1bWVudFRva2VuEhYKDmZvcm1hdF92ZXJzaW9uGAIgASgNEkkKEWFydGlmYWN0X2JpbmRpbmdzGAMgAygLMi4uZG90Y29yZS5tb2RlbC52MS5Qb3J0YWJsZU1vZGVsQXJ0aWZhY3RCaW5kaW5nIsIBCiBQb3J0YWJsZU1vZGVsTGF1bmNoQXJndW1lbnRUb2tlbhIRCgdsaXRlcmFsGAEgASgJSAASHQoTYXJ0aWZhY3RfYmluZGluZ19pZBgCIAEoCUgAEjMKEWVuZ2luZV9leGVjdXRhYmxlGAMgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SAASFgoMc2VydmljZV9ob3N0GAQgASgJSAASFgoMc2VydmljZV9wb3J0GAUgASgJSABCBwoFdmFsdWUijwEKHFBvcnRhYmxlTW9kZWxBcnRpZmFjdEJpbmRpbmcSEgoKYmluZGluZ19pZBgBIAEoCRIbChFtb2RlbF9hcnRpZmFjdF9pZBgCIAEoCUgAEh8KFWF1eGlsaWFyeV9hcnRpZmFjdF9pZBgDIAEoCUgAEhEKCXJlYWRfb25seRgFIAEoCEIKCghhcnRpZmFjdCJtCh9VcHN0cmVhbU1vZGVsRGVwbG95bWVudFNuYXBzaG90EkoKF3Vwc3RyZWFtX21vZGVsX3RlbXBsYXRlGAEgASgLMikuZG90Y29yZS5jYXRhbG9nLnYxLlVwc3RyZWFtTW9kZWxUZW1wbGF0ZSKlAgohVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uEhkKEXVwc3RyZWFtX21vZGVsX2lkGAEgASgJEg8KB2FwaV9rZXkYAiABKAkSTAoSaW5wdXRfY2FwYWJpbGl0aWVzGAQgASgLMjAuZG90Y29yZS5tb2RlbC52MS5VcHN0cmVhbU1vZGVsSW5wdXRDYXBhYmlsaXRpZXMSSQoIZW5kcG9pbnQYBSABKAsyNy5kb3Rjb3JlLm1vZGVsLnYxLk9wZW5BaUNvbXBhdGlibGVFbmRwb2ludENvbmZpZ3VyYXRpb24SOwoIYm91bmRhcnkYBiABKAsyKS5kb3Rjb3JlLmNhdGFsb2cudjEuVXBzdHJlYW1Nb2RlbEJvdW5kYXJ5Ik8KHlVwc3RyZWFtTW9kZWxJbnB1dENhcGFiaWxpdGllcxIVCg1zdXBwb3J0c190ZXh0GAEgASgIEhYKDnN1cHBvcnRzX2ltYWdlGAIgASgIIlYKJU9wZW5BaUNvbXBhdGlibGVFbmRwb2ludENvbmZpZ3VyYXRpb24SEAoIYmFzZV91cmwYASABKAkSGwoTYWxsb3dfaW5zZWN1cmVfaHR0cBgCIAEoCCqkAgoiTW9kZWxEZXBsb3ltZW50TGlmZWN5Y2xlVHJhbnNpdGlvbhI1CjFNT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1VOU1BFQ0lGSUVEEAASMAosTU9ERUxfREVQTE9ZTUVOVF9MSUZFQ1lDTEVfVFJBTlNJVElPTl9DUkVBVEUQARIvCitNT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1BBVVNFEAISMAosTU9ERUxfREVQTE9ZTUVOVF9MSUZFQ1lDTEVfVFJBTlNJVElPTl9SRVNVTUUQAxIyCi5NT0RFTF9ERVBMT1lNRU5UX0xJRkVDWUNMRV9UUkFOU0lUSU9OX1RFQVJET1dOEAQq0QEKG01vZGVsRGVwbG95bWVudERlc2lyZWRTdGF0ZRIuCipNT0RFTF9ERVBMT1lNRU5UX0RFU0lSRURfU1RBVEVfVU5TUEVDSUZJRUQQABIqCiZNT0RFTF9ERVBMT1lNRU5UX0RFU0lSRURfU1RBVEVfUFJFU0VOVBABEisKJ01PREVMX0RFUExPWU1FTlRfREVTSVJFRF9TVEFURV9URUFSRE9XThACEikKJU1PREVMX0RFUExPWU1FTlRfREVTSVJFRF9TVEFURV9QQVVTRUQQA2IGcHJvdG8z", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model, file_dotcore_catalog_v1_model_capabilities, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_parameter, file_dotcore_catalog_v1_selector, file_dotcore_catalog_v1_storage, file_dotcore_catalog_v1_upstream_model_template, file_dotcore_deployment_v1_accelerator_memory, file_dotcore_deployment_v1_artifact, file_dotcore_deployment_v1_placement, file_dotcore_engine_v1_engine, file_dotcore_model_v1_state, file_dotcore_observation_v1_observation, file_google_protobuf_empty]); /** * Declarative active model deployment in a desired site. It is written only by @@ -381,9 +383,9 @@ export type ResolvedLocalModelDeploymentSnapshot = Message<"dotcore.model.v1.Res /** * Complete exact resolved typed engine parameter values. * - * @generated from field: dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 13; + * @generated from field: dotcore.catalog.v1.ParameterValues engine_parameter_values = 13; */ - engineParameterValues?: EngineParameterValues; + engineParameterValues?: ParameterValues; /** * Engine parameter schema identity used for resolution. diff --git a/frontend/src/gen/dotcore/model/v1/service_pb.ts b/frontend/src/gen/dotcore/model/v1/service_pb.ts index ebc6738e..75607c74 100644 --- a/frontend/src/gen/dotcore/model/v1/service_pb.ts +++ b/frontend/src/gen/dotcore/model/v1/service_pb.ts @@ -6,12 +6,12 @@ import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobu import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { PlacementPreview } from "../../capacity/v1/placement_preview_pb"; import { file_dotcore_capacity_v1_placement_preview } from "../../capacity/v1/placement_preview_pb"; -import type { EngineParameterValues } from "../../catalog/v1/engine_release_pb"; -import { file_dotcore_catalog_v1_engine_release } from "../../catalog/v1/engine_release_pb"; import type { ModelOptionValues } from "../../catalog/v1/model_pb"; import { file_dotcore_catalog_v1_model } from "../../catalog/v1/model_pb"; import type { OciPlatform } from "../../catalog/v1/oci_pb"; import { file_dotcore_catalog_v1_oci } from "../../catalog/v1/oci_pb"; +import type { ParameterValues } from "../../catalog/v1/parameter_pb"; +import { file_dotcore_catalog_v1_parameter } from "../../catalog/v1/parameter_pb"; import type { UseCase } from "../../catalog/v1/recommendation_pb"; import { file_dotcore_catalog_v1_recommendation } from "../../catalog/v1/recommendation_pb"; import type { Selector } from "../../catalog/v1/selector_pb"; @@ -30,7 +30,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/model/v1/service.proto. */ export const file_dotcore_model_v1_service: GenFile = /*@__PURE__*/ - fileDesc("Ch5kb3Rjb3JlL21vZGVsL3YxL3NlcnZpY2UucHJvdG8SEGRvdGNvcmUubW9kZWwudjEiHQobTGlzdE1vZGVsRGVwbG95bWVudHNSZXF1ZXN0IlYKHExpc3RNb2RlbERlcGxveW1lbnRzUmVzcG9uc2USNgoLZGVwbG95bWVudHMYASADKAsyIS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudCK1AgocQ3JlYXRlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBJECgVsb2NhbBgBIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0SAASSgoIdXBzdHJlYW0YAiABKAsyNi5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZVVwc3RyZWFtTW9kZWxEZXBsb3ltZW50UmVxdWVzdEgAEjsKCGV4cG9zdXJlGAMgASgLMikuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnRFeHBvc3VyZRIiChVtb2RlbF9kZXBsb3ltZW50X25hbWUYBCABKAlIAYgBAUIICgZzb3VyY2VCGAoWX21vZGVsX2RlcGxveW1lbnRfbmFtZSLPAQohQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0EhAKCG1vZGVsX2lkGAEgASgJEhIKCnByb2ZpbGVfaWQYAiABKAkSOAoJcGxhY2VtZW50GAMgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkoKDWNvbmZpZ3VyYXRpb24YBCABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLkxvY2FsTW9kZWxEZXBsb3ltZW50Q29uZmlndXJhdGlvbiLzAQohTG9jYWxNb2RlbERlcGxveW1lbnRDb25maWd1cmF0aW9uEiEKGW1vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYASABKAkSSgoXZW5naW5lX3BhcmFtZXRlcl92YWx1ZXMYAiABKAsyKS5kb3Rjb3JlLmNhdGFsb2cudjEuRW5naW5lUGFyYW1ldGVyVmFsdWVzEh4KFmN1c3RvbV9hcmd1bWVudF90b2tlbnMYAyADKAkSPwoQb3B0aW9uX292ZXJyaWRlcxgEIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcyKeAQokQ3JlYXRlVXBzdHJlYW1Nb2RlbERlcGxveW1lbnRSZXF1ZXN0EiIKGnVwc3RyZWFtX21vZGVsX3RlbXBsYXRlX2lkGAEgASgJElIKFWRlc2lyZWRfY29uZmlndXJhdGlvbhgCIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uIpgBChdNb2RlbERlcGxveW1lbnRFeHBvc3VyZRI3CgZkaXJlY3QYASABKAsyJS5kb3Rjb3JlLm1vZGVsLnYxLkRpcmVjdFJvdXRlRXhwb3N1cmVIABI8CgZoaWRkZW4YAiABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLkhpZGRlbkRlcGxveW1lbnRFeHBvc3VyZUgAQgYKBGtpbmQiKQoTRGlyZWN0Um91dGVFeHBvc3VyZRISCgpyb3V0ZV9uYW1lGAEgASgJIhoKGEhpZGRlbkRlcGxveW1lbnRFeHBvc3VyZSJWCh1DcmVhdGVNb2RlbERlcGxveW1lbnRSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiaAoiUHJldmlld0xvY2FsTW9kZWxEZXBsb3ltZW50UmVxdWVzdBJCCgVsb2NhbBgBIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0IrwBCiNQcmV2aWV3TG9jYWxNb2RlbERlcGxveW1lbnRSZXNwb25zZRJRChFyZXNvbHZlZF9zbmFwc2hvdBgBIAEoCzI2LmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRMb2NhbE1vZGVsRGVwbG95bWVudFNuYXBzaG90EkIKCmFkdmlzb3JpZXMYAiADKA4yLi5kb3Rjb3JlLm1vZGVsLnYxLkxvY2FsTW9kZWxEZXBsb3ltZW50QWR2aXNvcnki0AEKIkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1JlcXVlc3QSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRJKCg1jb25maWd1cmF0aW9uGAMgASgLMjMuZG90Y29yZS5tb2RlbC52MS5Mb2NhbE1vZGVsRGVwbG95bWVudENvbmZpZ3VyYXRpb24SOAoJcGxhY2VtZW50GAQgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50IroBCiNFc3RpbWF0ZUxvY2FsTW9kZWxSZXNvdXJjZXNSZXNwb25zZRJRChhoYXJkd2FyZV9jbGFzc19lc3RpbWF0ZXMYASADKAsyLy5kb3Rjb3JlLm1vZGVsLnYxLkhhcmR3YXJlQ2xhc3NSZXNvdXJjZUVzdGltYXRlEkAKEXBsYWNlbWVudF9wcmV2aWV3GAIgASgLMiUuZG90Y29yZS5jYXBhY2l0eS52MS5QbGFjZW1lbnRQcmV2aWV3Iv8BCh1IYXJkd2FyZUNsYXNzUmVzb3VyY2VFc3RpbWF0ZRIZChFoYXJkd2FyZV9jbGFzc19pZBgBIAEoCRI7Cgllc3RpbWF0ZXMYAiADKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlNjYWxhclJlc291cmNlRXN0aW1hdGUSUgofZGVyaXZlZF9lbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgDIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJWYWx1ZXMSHQoQbGF1bmNoX3JlamVjdGlvbhgEIAEoCUgAiAEBQhMKEV9sYXVuY2hfcmVqZWN0aW9uIkcKFlNjYWxhclJlc291cmNlRXN0aW1hdGUSEAoIcmVzb3VyY2UYASABKAkSDQoFdmFsdWUYAiABKAQSDAoEdW5pdBgDIAEoCSK1AQokTGlzdE1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHlSZXF1ZXN0EhUKCG1vZGVsX2lkGAEgASgJSACIAQESNQoGdGFyZ2V0GAIgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EjIKCHNjZW5hcmlvGAMgASgLMiAuZG90Y29yZS5tb2RlbC52MS5TaXppbmdTY2VuYXJpb0ILCglfbW9kZWxfaWQidgoOU2l6aW5nU2NlbmFyaW8SHAoUdG90YWxfY29udGV4dF90b2tlbnMYASABKA0SJwoaY29udGV4dF90b2tlbnNfcGVyX3JlcXVlc3QYAiABKA1IAIgBAUIdChtfY29udGV4dF90b2tlbnNfcGVyX3JlcXVlc3Qi1QEKJUxpc3RNb2RlbFByb2ZpbGVDb21wYXRpYmlsaXR5UmVzcG9uc2USNgoHdGFyZ2V0cxgBIAMoCzIlLmRvdGNvcmUubW9kZWwudjEuVGFyZ2V0Q29tcGF0aWJpbGl0eRI8CgdlbnRyaWVzGAIgAygLMisuZG90Y29yZS5tb2RlbC52MS5Nb2RlbFByb2ZpbGVDb21wYXRpYmlsaXR5EjYKCHByb2ZpbGVzGAMgAygLMiQuZG90Y29yZS5tb2RlbC52MS5Nb2RlbFByb2ZpbGVTaXppbmciUQofTGlzdE1vZGVsUmVjb21tZW5kYXRpb25zUmVxdWVzdBIuCgl1c2VfY2FzZXMYASADKA4yGy5kb3Rjb3JlLmNhdGFsb2cudjEuVXNlQ2FzZSJkCiBMaXN0TW9kZWxSZWNvbW1lbmRhdGlvbnNSZXNwb25zZRJACgl1c2VfY2FzZXMYASADKAsyLS5kb3Rjb3JlLm1vZGVsLnYxLlVzZUNhc2VNb2RlbFJlY29tbWVuZGF0aW9ucyKFAQobVXNlQ2FzZU1vZGVsUmVjb21tZW5kYXRpb25zEi0KCHVzZV9jYXNlGAEgASgOMhsuZG90Y29yZS5jYXRhbG9nLnYxLlVzZUNhc2USNwoEcm93cxgCIAMoCzIpLmRvdGNvcmUubW9kZWwudjEuUmVjb21tZW5kZWRNb2RlbFByb2ZpbGUifAoXUmVjb21tZW5kZWRNb2RlbFByb2ZpbGUSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRI7Cgd0YXJnZXRzGAMgAygLMiouZG90Y29yZS5tb2RlbC52MS5SZWNvbW1lbmRlZFByb2ZpbGVUYXJnZXQi6AEKGFJlY29tbWVuZGVkUHJvZmlsZVRhcmdldBI1CgZ0YXJnZXQYASABKAsyJS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuRXhhY3RQbGFjZW1lbnQSNQoDZml0GAIgASgOMiguZG90Y29yZS5tb2RlbC52MS5Nb2RlbFJlY29tbWVuZGF0aW9uRml0EhAKCGRlcGxveWVkGAMgASgIEioKHXN0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zGAQgASgESACIAQFCIAoeX3N0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zIvUBChNUYXJnZXRDb21wYXRpYmlsaXR5EjUKBnRhcmdldBgBIAEoCzIlLmRvdGNvcmUuZGVwbG95bWVudC52MS5FeGFjdFBsYWNlbWVudBI6CgZzdGF0dXMYAiABKA4yKi5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsQ29tcGF0aWJpbGl0eVN0YXR1cxI6CgZyZWFzb24YAyABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsQ29tcGF0aWJpbGl0eVJlYXNvbhIvCgtvYnNlcnZlZF9hdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAi/gUKGU1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHkSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRI1CgZ0YXJnZXQYAyABKAsyJS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuRXhhY3RQbGFjZW1lbnQSOgoGc3RhdHVzGAQgASgOMiouZG90Y29yZS5tb2RlbC52MS5Nb2RlbENvbXBhdGliaWxpdHlTdGF0dXMSOgoGcmVhc29uGAUgASgLMiouZG90Y29yZS5tb2RlbC52MS5Nb2RlbENvbXBhdGliaWxpdHlSZWFzb24SQgoKYWR2aXNvcmllcxgGIAMoDjIuLmRvdGNvcmUubW9kZWwudjEuTG9jYWxNb2RlbERlcGxveW1lbnRBZHZpc29yeRIZChFoYXJkd2FyZV9jbGFzc19pZBgHIAEoCRI0CgptZW1vcnlfZml0GAggASgOMiAuZG90Y29yZS5kZXBsb3ltZW50LnYxLk1lbW9yeUZpdBI5Cg9mcmVlX21lbW9yeV9maXQYCyABKA4yIC5kb3Rjb3JlLmRlcGxveW1lbnQudjEuTWVtb3J5Rml0Ek0KEnVuc3VwcG9ydGVkX3JlYXNvbhgJIAEoDjIxLmRvdGNvcmUubW9kZWwudjEuU2l6aW5nU2NlbmFyaW9VbnN1cHBvcnRlZFJlYXNvbhIpChxsYXJnZXN0X3RvdGFsX2NvbnRleHRfdG9rZW5zGAogASgNSACIAQESKgodc3RhcnRpbmdfdG90YWxfY29udGV4dF90b2tlbnMYDCABKA1IAYgBARJTCh1zdGFydGluZ190b3RhbF9jb250ZXh0X3NvdXJjZRgNIAEoDjIsLmRvdGNvcmUubW9kZWwudjEuU3RhcnRpbmdUb3RhbENvbnRleHRTb3VyY2VCHwodX2xhcmdlc3RfdG90YWxfY29udGV4dF90b2tlbnNCIAoeX3N0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zItACChJNb2RlbFByb2ZpbGVTaXppbmcSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRJKChdlbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgDIAEoCzIpLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVQYXJhbWV0ZXJWYWx1ZXMSUQoYaGFyZHdhcmVfY2xhc3NfZXN0aW1hdGVzGAQgAygLMi8uZG90Y29yZS5tb2RlbC52MS5IYXJkd2FyZUNsYXNzUmVzb3VyY2VFc3RpbWF0ZRJNChJ1bnN1cHBvcnRlZF9yZWFzb24YBSABKA4yMS5kb3Rjb3JlLm1vZGVsLnYxLlNpemluZ1NjZW5hcmlvVW5zdXBwb3J0ZWRSZWFzb24SJgoedW5zdXBwb3J0ZWRfaGFyZHdhcmVfY2xhc3NfaWRzGAYgAygJIrUDChhNb2RlbENvbXBhdGliaWxpdHlSZWFzb24SPAoEY29kZRgBIAEoDjIuLmRvdGNvcmUubW9kZWwudjEuTW9kZWxDb21wYXRpYmlsaXR5UmVhc29uQ29kZRI8ChNjb25maWd1cmVkX3BsYXRmb3JtGAIgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEjoKEW9ic2VydmVkX3BsYXRmb3JtGAMgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEjkKE3N1cHBvcnRlZF9zZWxlY3RvcnMYBCADKAsyHC5kb3Rjb3JlLmNhdGFsb2cudjEuU2VsZWN0b3ISKwojbWluaW11bV9udmlkaWFfZHJpdmVyX21ham9yX3ZlcnNpb24YBSABKA0SLAokb2JzZXJ2ZWRfbnZpZGlhX2RyaXZlcl9tYWpvcl92ZXJzaW9uGAYgASgNEiAKGGFjY2VsZXJhdG9yX2RldmljZV9jb3VudBgHIAEoDRIpCiFyZXF1aXJlZF9hY2NlbGVyYXRvcl9kZXZpY2VfY291bnQYCCABKA0imAEKHFVwZGF0ZU1vZGVsRGVwbG95bWVudFJlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRJbCh51cHN0cmVhbV9kZXNpcmVkX2NvbmZpZ3VyYXRpb24YAiABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLlVwc3RyZWFtTW9kZWxEZXNpcmVkQ29uZmlndXJhdGlvbiJWCh1VcGRhdGVNb2RlbERlcGxveW1lbnRSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiOwocUmVtb3ZlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJIlYKHVJlbW92ZU1vZGVsRGVwbG95bWVudFJlc3BvbnNlEjUKCmRlcGxveW1lbnQYASABKAsyIS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudCIwChFQYXVzZU1vZGVsUmVxdWVzdBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJIksKElBhdXNlTW9kZWxSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiMQoSUmVzdW1lTW9kZWxSZXF1ZXN0EhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkiTAoTUmVzdW1lTW9kZWxSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQisQEKGVJlYWREZXBsb3ltZW50TG9nc1JlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRIUCgxzb3VyY2VfbmFtZXMYAiADKAkSEQoJcGFnZV9zaXplGAMgASgNEjkKEGJlZm9yZV90aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSACIAQFCEwoRX2JlZm9yZV90aW1lc3RhbXAijgMKGlJlYWREZXBsb3ltZW50TG9nc1Jlc3BvbnNlEjYKB3NvdXJjZXMYASADKAsyJS5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dTb3VyY2USNQoHZW50cmllcxgCIAMoCzIkLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ0VudHJ5Ej4KFW5leHRfYmVmb3JlX3RpbWVzdGFtcBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARJCCg1oaXN0b3J5X3N0YXRlGAQgASgOMisuZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nSGlzdG9yeVN0YXRlEhoKEnJlc3BvbnNlX3RydW5jYXRlZBgFIAEoCBJHChBsYXRlc3RfcG9zaXRpb25zGAYgAygLMi0uZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nUmVzdW1lUG9zaXRpb25CGAoWX25leHRfYmVmb3JlX3RpbWVzdGFtcCKZAQobRm9sbG93RGVwbG95bWVudExvZ3NSZXF1ZXN0EhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkSFAoMc291cmNlX25hbWVzGAIgAygJEkcKEHJlc3VtZV9wb3NpdGlvbnMYAyADKAsyLS5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dSZXN1bWVQb3NpdGlvbiKiAQocRm9sbG93RGVwbG95bWVudExvZ3NSZXNwb25zZRJCCgxzb3VyY2VfZXZlbnQYASABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dTb3VyY2VFdmVudEgAEjUKBWVudHJ5GAIgASgLMiQuZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nRW50cnlIAEIHCgVldmVudCJ7ChNEZXBsb3ltZW50TG9nU291cmNlEhMKC3NvdXJjZV9uYW1lGAEgASgJEhQKDHNvdXJjZV9sYWJlbBgCIAEoCRI5CgVzdGF0ZRgDIAEoDjIqLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1NvdXJjZVN0YXRlIskBChJEZXBsb3ltZW50TG9nRW50cnkSEwoLc291cmNlX25hbWUYASABKAkSFAoMc291cmNlX2xhYmVsGAIgASgJEjUKBnN0cmVhbRgDIAEoDjIlLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1N0cmVhbRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg8KB2NvbnRlbnQYBSABKAwSEQoJdHJ1bmNhdGVkGAYgASgIImgKG0RlcGxveW1lbnRMb2dSZXN1bWVQb3NpdGlvbhITCgtzb3VyY2VfbmFtZRgBIAEoCRI0ChBsYXRlc3RfdGltZXN0YW1wGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKAAQoYRGVwbG95bWVudExvZ1NvdXJjZUV2ZW50EhMKC3NvdXJjZV9uYW1lGAEgASgJEhQKDHNvdXJjZV9sYWJlbBgCIAEoCRI5CgVzdGF0ZRgDIAEoDjIqLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1NvdXJjZVN0YXRlIrEBCiRVcGRhdGVNb2RlbERlcGxveW1lbnRNZXRhZGF0YVJlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRI7CghtZXRhZGF0YRgCIAEoCzIpLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50TWV0YWRhdGESLwoLdXBkYXRlX21hc2sYAyABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrIkUKF01vZGVsRGVwbG95bWVudE1ldGFkYXRhEhkKDGRpc3BsYXlfbmFtZRgBIAEoCUgAiAEBQg8KDV9kaXNwbGF5X25hbWUiXgolVXBkYXRlTW9kZWxEZXBsb3ltZW50TWV0YWRhdGFSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQq4AEKHExvY2FsTW9kZWxEZXBsb3ltZW50QWR2aXNvcnkSLworTE9DQUxfTU9ERUxfREVQTE9ZTUVOVF9BRFZJU09SWV9VTlNQRUNJRklFRBAAEkEKPUxPQ0FMX01PREVMX0RFUExPWU1FTlRfQURWSVNPUllfSE9TVF9LVl9PRkZMT0FEX1NIQVJFU19NRU1PUlkQARJMCkhMT0NBTF9NT0RFTF9ERVBMT1lNRU5UX0FEVklTT1JZX1VOSUZJRURfTUVNT1JZX1BPT0xfQkVMT1dfREVWSUNFX01JTklNVU0QAirqAQoWTW9kZWxSZWNvbW1lbmRhdGlvbkZpdBIoCiRNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfVU5TUEVDSUZJRUQQABIlCiFNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfRklUU19OT1cQARIvCitNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfTkVFRFNfTUVNT1JZX0ZSRUVEEAISJAogTU9ERUxfUkVDT01NRU5EQVRJT05fRklUX1VOS05PV04QAxIoCiRNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfVU5SRUFDSEFCTEUQBCq+AQoYTW9kZWxDb21wYXRpYmlsaXR5U3RhdHVzEioKJk1PREVMX0NPTVBBVElCSUxJVFlfU1RBVFVTX1VOU1BFQ0lGSUVEEAASIwofTU9ERUxfQ09NUEFUSUJJTElUWV9TVEFUVVNfUlVOUxABEikKJU1PREVMX0NPTVBBVElCSUxJVFlfU1RBVFVTX0NBTk5PVF9SVU4QAhImCiJNT0RFTF9DT01QQVRJQklMSVRZX1NUQVRVU19VTktOT1dOEAMq8AUKHE1vZGVsQ29tcGF0aWJpbGl0eVJlYXNvbkNvZGUSLworTU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9VTlNQRUNJRklFRBAAEjgKNE1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfVEFSR0VUX05PVF9SRVBPUlRJTkcQARI5CjVNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX05WSURJQV9EUklWRVJfVU5LTk9XThACEj4KOk1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfQUNDRUxFUkFUT1JfTUVNT1JZX1VOS05PV04QAxI7CjdNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX1RBUkdFVF9QTEFURk9STV9JTlZBTElEEAQSNQoxTU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9QTEFURk9STV9NSVNNQVRDSBAFEjIKLk1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfTk9fQUNDRUxFUkFUT1IQBhI/CjtNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX05PX01BVENISU5HX0VOR0lORV9BUlRJRkFDVBAHEj8KO01PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfTk9fU1VQUE9SVEVEX0hBUkRXQVJFX0NMQVNTEAsSPwo7TU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9OVklESUFfRFJJVkVSX0JFTE9XX01JTklNVU0QCBJFCkFNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX0FDQ0VMRVJBVE9SX0RFVklDRV9DT1VOVF9NSVNNQVRDSBAJEjgKNE1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfUFJPRklMRV9VTlJFU09MVkFCTEUQCiqZAgofU2l6aW5nU2NlbmFyaW9VbnN1cHBvcnRlZFJlYXNvbhIyCi5TSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX1VOU1BFQ0lGSUVEEAASPAo4U0laSU5HX1NDRU5BUklPX1VOU1VQUE9SVEVEX1JFQVNPTl9DT05URVhUX0FCT1ZFX01BWElNVU0QARI9CjlTSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX1BBUkFNRVRFUl9PVVRfT0ZfUkFOR0UQAxJFCkFTSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX0RFUklWRURfUEFSQU1FVEVSX09VVF9PRl9SQU5HRRAEKq0BChpTdGFydGluZ1RvdGFsQ29udGV4dFNvdXJjZRItCilTVEFSVElOR19UT1RBTF9DT05URVhUX1NPVVJDRV9VTlNQRUNJRklFRBAAEi0KKVNUQVJUSU5HX1RPVEFMX0NPTlRFWFRfU09VUkNFX0xBUkdFU1RfRklUEAESMQotU1RBUlRJTkdfVE9UQUxfQ09OVEVYVF9TT1VSQ0VfUFJPRklMRV9ERUZBVUxUEAIqvgEKGURlcGxveW1lbnRMb2dIaXN0b3J5U3RhdGUSLAooREVQTE9ZTUVOVF9MT0dfSElTVE9SWV9TVEFURV9VTlNQRUNJRklFRBAAEjgKNERFUExPWU1FTlRfTE9HX0hJU1RPUllfU1RBVEVfT0xERVJfT1VUUFVUX01BWV9SRU1BSU4QARI5CjVERVBMT1lNRU5UX0xPR19ISVNUT1JZX1NUQVRFX05PX09MREVSX09VVFBVVF9PQlNFUlZFRBACKsYBChhEZXBsb3ltZW50TG9nU291cmNlU3RhdGUSKwonREVQTE9ZTUVOVF9MT0dfU09VUkNFX1NUQVRFX1VOU1BFQ0lGSUVEEAASKQolREVQTE9ZTUVOVF9MT0dfU09VUkNFX1NUQVRFX0FWQUlMQUJMRRABEisKJ0RFUExPWU1FTlRfTE9HX1NPVVJDRV9TVEFURV9VTkFWQUlMQUJMRRACEiUKIURFUExPWU1FTlRfTE9HX1NPVVJDRV9TVEFURV9FTkRFRBADKoABChNEZXBsb3ltZW50TG9nU3RyZWFtEiUKIURFUExPWU1FTlRfTE9HX1NUUkVBTV9VTlNQRUNJRklFRBAAEiAKHERFUExPWU1FTlRfTE9HX1NUUkVBTV9TVERPVVQQARIgChxERVBMT1lNRU5UX0xPR19TVFJFQU1fU1RERVJSEAIy4AwKFk1vZGVsRGVwbG95bWVudFNlcnZpY2USdQoUTGlzdE1vZGVsRGVwbG95bWVudHMSLS5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbERlcGxveW1lbnRzUmVxdWVzdBouLmRvdGNvcmUubW9kZWwudjEuTGlzdE1vZGVsRGVwbG95bWVudHNSZXNwb25zZRJ4ChVDcmVhdGVNb2RlbERlcGxveW1lbnQSLi5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZU1vZGVsRGVwbG95bWVudFJlcXVlc3QaLy5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZU1vZGVsRGVwbG95bWVudFJlc3BvbnNlEooBChtQcmV2aWV3TG9jYWxNb2RlbERlcGxveW1lbnQSNC5kb3Rjb3JlLm1vZGVsLnYxLlByZXZpZXdMb2NhbE1vZGVsRGVwbG95bWVudFJlcXVlc3QaNS5kb3Rjb3JlLm1vZGVsLnYxLlByZXZpZXdMb2NhbE1vZGVsRGVwbG95bWVudFJlc3BvbnNlEooBChtFc3RpbWF0ZUxvY2FsTW9kZWxSZXNvdXJjZXMSNC5kb3Rjb3JlLm1vZGVsLnYxLkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1JlcXVlc3QaNS5kb3Rjb3JlLm1vZGVsLnYxLkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1Jlc3BvbnNlEpABCh1MaXN0TW9kZWxQcm9maWxlQ29tcGF0aWJpbGl0eRI2LmRvdGNvcmUubW9kZWwudjEuTGlzdE1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHlSZXF1ZXN0GjcuZG90Y29yZS5tb2RlbC52MS5MaXN0TW9kZWxQcm9maWxlQ29tcGF0aWJpbGl0eVJlc3BvbnNlEoEBChhMaXN0TW9kZWxSZWNvbW1lbmRhdGlvbnMSMS5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbFJlY29tbWVuZGF0aW9uc1JlcXVlc3QaMi5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbFJlY29tbWVuZGF0aW9uc1Jlc3BvbnNlEngKFVVwZGF0ZU1vZGVsRGVwbG95bWVudBIuLmRvdGNvcmUubW9kZWwudjEuVXBkYXRlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBovLmRvdGNvcmUubW9kZWwudjEuVXBkYXRlTW9kZWxEZXBsb3ltZW50UmVzcG9uc2USeAoVUmVtb3ZlTW9kZWxEZXBsb3ltZW50Ei4uZG90Y29yZS5tb2RlbC52MS5SZW1vdmVNb2RlbERlcGxveW1lbnRSZXF1ZXN0Gi8uZG90Y29yZS5tb2RlbC52MS5SZW1vdmVNb2RlbERlcGxveW1lbnRSZXNwb25zZRJXCgpQYXVzZU1vZGVsEiMuZG90Y29yZS5tb2RlbC52MS5QYXVzZU1vZGVsUmVxdWVzdBokLmRvdGNvcmUubW9kZWwudjEuUGF1c2VNb2RlbFJlc3BvbnNlEloKC1Jlc3VtZU1vZGVsEiQuZG90Y29yZS5tb2RlbC52MS5SZXN1bWVNb2RlbFJlcXVlc3QaJS5kb3Rjb3JlLm1vZGVsLnYxLlJlc3VtZU1vZGVsUmVzcG9uc2USbwoSUmVhZERlcGxveW1lbnRMb2dzEisuZG90Y29yZS5tb2RlbC52MS5SZWFkRGVwbG95bWVudExvZ3NSZXF1ZXN0GiwuZG90Y29yZS5tb2RlbC52MS5SZWFkRGVwbG95bWVudExvZ3NSZXNwb25zZRJ3ChRGb2xsb3dEZXBsb3ltZW50TG9ncxItLmRvdGNvcmUubW9kZWwudjEuRm9sbG93RGVwbG95bWVudExvZ3NSZXF1ZXN0Gi4uZG90Y29yZS5tb2RlbC52MS5Gb2xsb3dEZXBsb3ltZW50TG9nc1Jlc3BvbnNlMAESkAEKHVVwZGF0ZU1vZGVsRGVwbG95bWVudE1ldGFkYXRhEjYuZG90Y29yZS5tb2RlbC52MS5VcGRhdGVNb2RlbERlcGxveW1lbnRNZXRhZGF0YVJlcXVlc3QaNy5kb3Rjb3JlLm1vZGVsLnYxLlVwZGF0ZU1vZGVsRGVwbG95bWVudE1ldGFkYXRhUmVzcG9uc2ViBnByb3RvMw", [file_dotcore_capacity_v1_placement_preview, file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_model, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_recommendation, file_dotcore_catalog_v1_selector, file_dotcore_deployment_v1_memory_fit, file_dotcore_deployment_v1_placement, file_dotcore_model_v1_deployment, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); + fileDesc("Ch5kb3Rjb3JlL21vZGVsL3YxL3NlcnZpY2UucHJvdG8SEGRvdGNvcmUubW9kZWwudjEiHQobTGlzdE1vZGVsRGVwbG95bWVudHNSZXF1ZXN0IlYKHExpc3RNb2RlbERlcGxveW1lbnRzUmVzcG9uc2USNgoLZGVwbG95bWVudHMYASADKAsyIS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudCK1AgocQ3JlYXRlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBJECgVsb2NhbBgBIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0SAASSgoIdXBzdHJlYW0YAiABKAsyNi5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZVVwc3RyZWFtTW9kZWxEZXBsb3ltZW50UmVxdWVzdEgAEjsKCGV4cG9zdXJlGAMgASgLMikuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnRFeHBvc3VyZRIiChVtb2RlbF9kZXBsb3ltZW50X25hbWUYBCABKAlIAYgBAUIICgZzb3VyY2VCGAoWX21vZGVsX2RlcGxveW1lbnRfbmFtZSLPAQohQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0EhAKCG1vZGVsX2lkGAEgASgJEhIKCnByb2ZpbGVfaWQYAiABKAkSOAoJcGxhY2VtZW50GAMgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EkoKDWNvbmZpZ3VyYXRpb24YBCABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLkxvY2FsTW9kZWxEZXBsb3ltZW50Q29uZmlndXJhdGlvbiLtAQohTG9jYWxNb2RlbERlcGxveW1lbnRDb25maWd1cmF0aW9uEiEKGW1vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYASABKAkSRAoXZW5naW5lX3BhcmFtZXRlcl92YWx1ZXMYAiABKAsyIy5kb3Rjb3JlLmNhdGFsb2cudjEuUGFyYW1ldGVyVmFsdWVzEh4KFmN1c3RvbV9hcmd1bWVudF90b2tlbnMYAyADKAkSPwoQb3B0aW9uX292ZXJyaWRlcxgEIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcyKeAQokQ3JlYXRlVXBzdHJlYW1Nb2RlbERlcGxveW1lbnRSZXF1ZXN0EiIKGnVwc3RyZWFtX21vZGVsX3RlbXBsYXRlX2lkGAEgASgJElIKFWRlc2lyZWRfY29uZmlndXJhdGlvbhgCIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuVXBzdHJlYW1Nb2RlbERlc2lyZWRDb25maWd1cmF0aW9uIpgBChdNb2RlbERlcGxveW1lbnRFeHBvc3VyZRI3CgZkaXJlY3QYASABKAsyJS5kb3Rjb3JlLm1vZGVsLnYxLkRpcmVjdFJvdXRlRXhwb3N1cmVIABI8CgZoaWRkZW4YAiABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLkhpZGRlbkRlcGxveW1lbnRFeHBvc3VyZUgAQgYKBGtpbmQiKQoTRGlyZWN0Um91dGVFeHBvc3VyZRISCgpyb3V0ZV9uYW1lGAEgASgJIhoKGEhpZGRlbkRlcGxveW1lbnRFeHBvc3VyZSJWCh1DcmVhdGVNb2RlbERlcGxveW1lbnRSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiaAoiUHJldmlld0xvY2FsTW9kZWxEZXBsb3ltZW50UmVxdWVzdBJCCgVsb2NhbBgBIAEoCzIzLmRvdGNvcmUubW9kZWwudjEuQ3JlYXRlTG9jYWxNb2RlbERlcGxveW1lbnRSZXF1ZXN0IrwBCiNQcmV2aWV3TG9jYWxNb2RlbERlcGxveW1lbnRSZXNwb25zZRJRChFyZXNvbHZlZF9zbmFwc2hvdBgBIAEoCzI2LmRvdGNvcmUubW9kZWwudjEuUmVzb2x2ZWRMb2NhbE1vZGVsRGVwbG95bWVudFNuYXBzaG90EkIKCmFkdmlzb3JpZXMYAiADKA4yLi5kb3Rjb3JlLm1vZGVsLnYxLkxvY2FsTW9kZWxEZXBsb3ltZW50QWR2aXNvcnki0AEKIkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1JlcXVlc3QSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRJKCg1jb25maWd1cmF0aW9uGAMgASgLMjMuZG90Y29yZS5tb2RlbC52MS5Mb2NhbE1vZGVsRGVwbG95bWVudENvbmZpZ3VyYXRpb24SOAoJcGxhY2VtZW50GAQgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50IroBCiNFc3RpbWF0ZUxvY2FsTW9kZWxSZXNvdXJjZXNSZXNwb25zZRJRChhoYXJkd2FyZV9jbGFzc19lc3RpbWF0ZXMYASADKAsyLy5kb3Rjb3JlLm1vZGVsLnYxLkhhcmR3YXJlQ2xhc3NSZXNvdXJjZUVzdGltYXRlEkAKEXBsYWNlbWVudF9wcmV2aWV3GAIgASgLMiUuZG90Y29yZS5jYXBhY2l0eS52MS5QbGFjZW1lbnRQcmV2aWV3IvkBCh1IYXJkd2FyZUNsYXNzUmVzb3VyY2VFc3RpbWF0ZRIZChFoYXJkd2FyZV9jbGFzc19pZBgBIAEoCRI7Cgllc3RpbWF0ZXMYAiADKAsyKC5kb3Rjb3JlLm1vZGVsLnYxLlNjYWxhclJlc291cmNlRXN0aW1hdGUSTAofZGVyaXZlZF9lbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgDIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSHQoQbGF1bmNoX3JlamVjdGlvbhgEIAEoCUgAiAEBQhMKEV9sYXVuY2hfcmVqZWN0aW9uIkcKFlNjYWxhclJlc291cmNlRXN0aW1hdGUSEAoIcmVzb3VyY2UYASABKAkSDQoFdmFsdWUYAiABKAQSDAoEdW5pdBgDIAEoCSK1AQokTGlzdE1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHlSZXF1ZXN0EhUKCG1vZGVsX2lkGAEgASgJSACIAQESNQoGdGFyZ2V0GAIgASgLMiUuZG90Y29yZS5kZXBsb3ltZW50LnYxLkV4YWN0UGxhY2VtZW50EjIKCHNjZW5hcmlvGAMgASgLMiAuZG90Y29yZS5tb2RlbC52MS5TaXppbmdTY2VuYXJpb0ILCglfbW9kZWxfaWQidgoOU2l6aW5nU2NlbmFyaW8SHAoUdG90YWxfY29udGV4dF90b2tlbnMYASABKA0SJwoaY29udGV4dF90b2tlbnNfcGVyX3JlcXVlc3QYAiABKA1IAIgBAUIdChtfY29udGV4dF90b2tlbnNfcGVyX3JlcXVlc3Qi1QEKJUxpc3RNb2RlbFByb2ZpbGVDb21wYXRpYmlsaXR5UmVzcG9uc2USNgoHdGFyZ2V0cxgBIAMoCzIlLmRvdGNvcmUubW9kZWwudjEuVGFyZ2V0Q29tcGF0aWJpbGl0eRI8CgdlbnRyaWVzGAIgAygLMisuZG90Y29yZS5tb2RlbC52MS5Nb2RlbFByb2ZpbGVDb21wYXRpYmlsaXR5EjYKCHByb2ZpbGVzGAMgAygLMiQuZG90Y29yZS5tb2RlbC52MS5Nb2RlbFByb2ZpbGVTaXppbmciUQofTGlzdE1vZGVsUmVjb21tZW5kYXRpb25zUmVxdWVzdBIuCgl1c2VfY2FzZXMYASADKA4yGy5kb3Rjb3JlLmNhdGFsb2cudjEuVXNlQ2FzZSJkCiBMaXN0TW9kZWxSZWNvbW1lbmRhdGlvbnNSZXNwb25zZRJACgl1c2VfY2FzZXMYASADKAsyLS5kb3Rjb3JlLm1vZGVsLnYxLlVzZUNhc2VNb2RlbFJlY29tbWVuZGF0aW9ucyKFAQobVXNlQ2FzZU1vZGVsUmVjb21tZW5kYXRpb25zEi0KCHVzZV9jYXNlGAEgASgOMhsuZG90Y29yZS5jYXRhbG9nLnYxLlVzZUNhc2USNwoEcm93cxgCIAMoCzIpLmRvdGNvcmUubW9kZWwudjEuUmVjb21tZW5kZWRNb2RlbFByb2ZpbGUifAoXUmVjb21tZW5kZWRNb2RlbFByb2ZpbGUSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRI7Cgd0YXJnZXRzGAMgAygLMiouZG90Y29yZS5tb2RlbC52MS5SZWNvbW1lbmRlZFByb2ZpbGVUYXJnZXQi6AEKGFJlY29tbWVuZGVkUHJvZmlsZVRhcmdldBI1CgZ0YXJnZXQYASABKAsyJS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuRXhhY3RQbGFjZW1lbnQSNQoDZml0GAIgASgOMiguZG90Y29yZS5tb2RlbC52MS5Nb2RlbFJlY29tbWVuZGF0aW9uRml0EhAKCGRlcGxveWVkGAMgASgIEioKHXN0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zGAQgASgESACIAQFCIAoeX3N0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zIvUBChNUYXJnZXRDb21wYXRpYmlsaXR5EjUKBnRhcmdldBgBIAEoCzIlLmRvdGNvcmUuZGVwbG95bWVudC52MS5FeGFjdFBsYWNlbWVudBI6CgZzdGF0dXMYAiABKA4yKi5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsQ29tcGF0aWJpbGl0eVN0YXR1cxI6CgZyZWFzb24YAyABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsQ29tcGF0aWJpbGl0eVJlYXNvbhIvCgtvYnNlcnZlZF9hdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAi/gUKGU1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHkSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRI1CgZ0YXJnZXQYAyABKAsyJS5kb3Rjb3JlLmRlcGxveW1lbnQudjEuRXhhY3RQbGFjZW1lbnQSOgoGc3RhdHVzGAQgASgOMiouZG90Y29yZS5tb2RlbC52MS5Nb2RlbENvbXBhdGliaWxpdHlTdGF0dXMSOgoGcmVhc29uGAUgASgLMiouZG90Y29yZS5tb2RlbC52MS5Nb2RlbENvbXBhdGliaWxpdHlSZWFzb24SQgoKYWR2aXNvcmllcxgGIAMoDjIuLmRvdGNvcmUubW9kZWwudjEuTG9jYWxNb2RlbERlcGxveW1lbnRBZHZpc29yeRIZChFoYXJkd2FyZV9jbGFzc19pZBgHIAEoCRI0CgptZW1vcnlfZml0GAggASgOMiAuZG90Y29yZS5kZXBsb3ltZW50LnYxLk1lbW9yeUZpdBI5Cg9mcmVlX21lbW9yeV9maXQYCyABKA4yIC5kb3Rjb3JlLmRlcGxveW1lbnQudjEuTWVtb3J5Rml0Ek0KEnVuc3VwcG9ydGVkX3JlYXNvbhgJIAEoDjIxLmRvdGNvcmUubW9kZWwudjEuU2l6aW5nU2NlbmFyaW9VbnN1cHBvcnRlZFJlYXNvbhIpChxsYXJnZXN0X3RvdGFsX2NvbnRleHRfdG9rZW5zGAogASgNSACIAQESKgodc3RhcnRpbmdfdG90YWxfY29udGV4dF90b2tlbnMYDCABKA1IAYgBARJTCh1zdGFydGluZ190b3RhbF9jb250ZXh0X3NvdXJjZRgNIAEoDjIsLmRvdGNvcmUubW9kZWwudjEuU3RhcnRpbmdUb3RhbENvbnRleHRTb3VyY2VCHwodX2xhcmdlc3RfdG90YWxfY29udGV4dF90b2tlbnNCIAoeX3N0YXJ0aW5nX3RvdGFsX2NvbnRleHRfdG9rZW5zIsoCChJNb2RlbFByb2ZpbGVTaXppbmcSEAoIbW9kZWxfaWQYASABKAkSEgoKcHJvZmlsZV9pZBgCIAEoCRJEChdlbmdpbmVfcGFyYW1ldGVyX3ZhbHVlcxgDIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSUQoYaGFyZHdhcmVfY2xhc3NfZXN0aW1hdGVzGAQgAygLMi8uZG90Y29yZS5tb2RlbC52MS5IYXJkd2FyZUNsYXNzUmVzb3VyY2VFc3RpbWF0ZRJNChJ1bnN1cHBvcnRlZF9yZWFzb24YBSABKA4yMS5kb3Rjb3JlLm1vZGVsLnYxLlNpemluZ1NjZW5hcmlvVW5zdXBwb3J0ZWRSZWFzb24SJgoedW5zdXBwb3J0ZWRfaGFyZHdhcmVfY2xhc3NfaWRzGAYgAygJIrUDChhNb2RlbENvbXBhdGliaWxpdHlSZWFzb24SPAoEY29kZRgBIAEoDjIuLmRvdGNvcmUubW9kZWwudjEuTW9kZWxDb21wYXRpYmlsaXR5UmVhc29uQ29kZRI8ChNjb25maWd1cmVkX3BsYXRmb3JtGAIgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEjoKEW9ic2VydmVkX3BsYXRmb3JtGAMgASgLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk9jaVBsYXRmb3JtEjkKE3N1cHBvcnRlZF9zZWxlY3RvcnMYBCADKAsyHC5kb3Rjb3JlLmNhdGFsb2cudjEuU2VsZWN0b3ISKwojbWluaW11bV9udmlkaWFfZHJpdmVyX21ham9yX3ZlcnNpb24YBSABKA0SLAokb2JzZXJ2ZWRfbnZpZGlhX2RyaXZlcl9tYWpvcl92ZXJzaW9uGAYgASgNEiAKGGFjY2VsZXJhdG9yX2RldmljZV9jb3VudBgHIAEoDRIpCiFyZXF1aXJlZF9hY2NlbGVyYXRvcl9kZXZpY2VfY291bnQYCCABKA0imAEKHFVwZGF0ZU1vZGVsRGVwbG95bWVudFJlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRJbCh51cHN0cmVhbV9kZXNpcmVkX2NvbmZpZ3VyYXRpb24YAiABKAsyMy5kb3Rjb3JlLm1vZGVsLnYxLlVwc3RyZWFtTW9kZWxEZXNpcmVkQ29uZmlndXJhdGlvbiJWCh1VcGRhdGVNb2RlbERlcGxveW1lbnRSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiOwocUmVtb3ZlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJIlYKHVJlbW92ZU1vZGVsRGVwbG95bWVudFJlc3BvbnNlEjUKCmRlcGxveW1lbnQYASABKAsyIS5kb3Rjb3JlLm1vZGVsLnYxLk1vZGVsRGVwbG95bWVudCIwChFQYXVzZU1vZGVsUmVxdWVzdBIbChNtb2RlbF9kZXBsb3ltZW50X2lkGAEgASgJIksKElBhdXNlTW9kZWxSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQiMQoSUmVzdW1lTW9kZWxSZXF1ZXN0EhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkiTAoTUmVzdW1lTW9kZWxSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQisQEKGVJlYWREZXBsb3ltZW50TG9nc1JlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRIUCgxzb3VyY2VfbmFtZXMYAiADKAkSEQoJcGFnZV9zaXplGAMgASgNEjkKEGJlZm9yZV90aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSACIAQFCEwoRX2JlZm9yZV90aW1lc3RhbXAijgMKGlJlYWREZXBsb3ltZW50TG9nc1Jlc3BvbnNlEjYKB3NvdXJjZXMYASADKAsyJS5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dTb3VyY2USNQoHZW50cmllcxgCIAMoCzIkLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ0VudHJ5Ej4KFW5leHRfYmVmb3JlX3RpbWVzdGFtcBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARJCCg1oaXN0b3J5X3N0YXRlGAQgASgOMisuZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nSGlzdG9yeVN0YXRlEhoKEnJlc3BvbnNlX3RydW5jYXRlZBgFIAEoCBJHChBsYXRlc3RfcG9zaXRpb25zGAYgAygLMi0uZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nUmVzdW1lUG9zaXRpb25CGAoWX25leHRfYmVmb3JlX3RpbWVzdGFtcCKZAQobRm9sbG93RGVwbG95bWVudExvZ3NSZXF1ZXN0EhsKE21vZGVsX2RlcGxveW1lbnRfaWQYASABKAkSFAoMc291cmNlX25hbWVzGAIgAygJEkcKEHJlc3VtZV9wb3NpdGlvbnMYAyADKAsyLS5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dSZXN1bWVQb3NpdGlvbiKiAQocRm9sbG93RGVwbG95bWVudExvZ3NSZXNwb25zZRJCCgxzb3VyY2VfZXZlbnQYASABKAsyKi5kb3Rjb3JlLm1vZGVsLnYxLkRlcGxveW1lbnRMb2dTb3VyY2VFdmVudEgAEjUKBWVudHJ5GAIgASgLMiQuZG90Y29yZS5tb2RlbC52MS5EZXBsb3ltZW50TG9nRW50cnlIAEIHCgVldmVudCJ7ChNEZXBsb3ltZW50TG9nU291cmNlEhMKC3NvdXJjZV9uYW1lGAEgASgJEhQKDHNvdXJjZV9sYWJlbBgCIAEoCRI5CgVzdGF0ZRgDIAEoDjIqLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1NvdXJjZVN0YXRlIskBChJEZXBsb3ltZW50TG9nRW50cnkSEwoLc291cmNlX25hbWUYASABKAkSFAoMc291cmNlX2xhYmVsGAIgASgJEjUKBnN0cmVhbRgDIAEoDjIlLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1N0cmVhbRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg8KB2NvbnRlbnQYBSABKAwSEQoJdHJ1bmNhdGVkGAYgASgIImgKG0RlcGxveW1lbnRMb2dSZXN1bWVQb3NpdGlvbhITCgtzb3VyY2VfbmFtZRgBIAEoCRI0ChBsYXRlc3RfdGltZXN0YW1wGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKAAQoYRGVwbG95bWVudExvZ1NvdXJjZUV2ZW50EhMKC3NvdXJjZV9uYW1lGAEgASgJEhQKDHNvdXJjZV9sYWJlbBgCIAEoCRI5CgVzdGF0ZRgDIAEoDjIqLmRvdGNvcmUubW9kZWwudjEuRGVwbG95bWVudExvZ1NvdXJjZVN0YXRlIrEBCiRVcGRhdGVNb2RlbERlcGxveW1lbnRNZXRhZGF0YVJlcXVlc3QSGwoTbW9kZWxfZGVwbG95bWVudF9pZBgBIAEoCRI7CghtZXRhZGF0YRgCIAEoCzIpLmRvdGNvcmUubW9kZWwudjEuTW9kZWxEZXBsb3ltZW50TWV0YWRhdGESLwoLdXBkYXRlX21hc2sYAyABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrIkUKF01vZGVsRGVwbG95bWVudE1ldGFkYXRhEhkKDGRpc3BsYXlfbmFtZRgBIAEoCUgAiAEBQg8KDV9kaXNwbGF5X25hbWUiXgolVXBkYXRlTW9kZWxEZXBsb3ltZW50TWV0YWRhdGFSZXNwb25zZRI1CgpkZXBsb3ltZW50GAEgASgLMiEuZG90Y29yZS5tb2RlbC52MS5Nb2RlbERlcGxveW1lbnQq4AEKHExvY2FsTW9kZWxEZXBsb3ltZW50QWR2aXNvcnkSLworTE9DQUxfTU9ERUxfREVQTE9ZTUVOVF9BRFZJU09SWV9VTlNQRUNJRklFRBAAEkEKPUxPQ0FMX01PREVMX0RFUExPWU1FTlRfQURWSVNPUllfSE9TVF9LVl9PRkZMT0FEX1NIQVJFU19NRU1PUlkQARJMCkhMT0NBTF9NT0RFTF9ERVBMT1lNRU5UX0FEVklTT1JZX1VOSUZJRURfTUVNT1JZX1BPT0xfQkVMT1dfREVWSUNFX01JTklNVU0QAirqAQoWTW9kZWxSZWNvbW1lbmRhdGlvbkZpdBIoCiRNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfVU5TUEVDSUZJRUQQABIlCiFNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfRklUU19OT1cQARIvCitNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfTkVFRFNfTUVNT1JZX0ZSRUVEEAISJAogTU9ERUxfUkVDT01NRU5EQVRJT05fRklUX1VOS05PV04QAxIoCiRNT0RFTF9SRUNPTU1FTkRBVElPTl9GSVRfVU5SRUFDSEFCTEUQBCq+AQoYTW9kZWxDb21wYXRpYmlsaXR5U3RhdHVzEioKJk1PREVMX0NPTVBBVElCSUxJVFlfU1RBVFVTX1VOU1BFQ0lGSUVEEAASIwofTU9ERUxfQ09NUEFUSUJJTElUWV9TVEFUVVNfUlVOUxABEikKJU1PREVMX0NPTVBBVElCSUxJVFlfU1RBVFVTX0NBTk5PVF9SVU4QAhImCiJNT0RFTF9DT01QQVRJQklMSVRZX1NUQVRVU19VTktOT1dOEAMq8AUKHE1vZGVsQ29tcGF0aWJpbGl0eVJlYXNvbkNvZGUSLworTU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9VTlNQRUNJRklFRBAAEjgKNE1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfVEFSR0VUX05PVF9SRVBPUlRJTkcQARI5CjVNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX05WSURJQV9EUklWRVJfVU5LTk9XThACEj4KOk1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfQUNDRUxFUkFUT1JfTUVNT1JZX1VOS05PV04QAxI7CjdNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX1RBUkdFVF9QTEFURk9STV9JTlZBTElEEAQSNQoxTU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9QTEFURk9STV9NSVNNQVRDSBAFEjIKLk1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfTk9fQUNDRUxFUkFUT1IQBhI/CjtNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX05PX01BVENISU5HX0VOR0lORV9BUlRJRkFDVBAHEj8KO01PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfTk9fU1VQUE9SVEVEX0hBUkRXQVJFX0NMQVNTEAsSPwo7TU9ERUxfQ09NUEFUSUJJTElUWV9SRUFTT05fQ09ERV9OVklESUFfRFJJVkVSX0JFTE9XX01JTklNVU0QCBJFCkFNT0RFTF9DT01QQVRJQklMSVRZX1JFQVNPTl9DT0RFX0FDQ0VMRVJBVE9SX0RFVklDRV9DT1VOVF9NSVNNQVRDSBAJEjgKNE1PREVMX0NPTVBBVElCSUxJVFlfUkVBU09OX0NPREVfUFJPRklMRV9VTlJFU09MVkFCTEUQCiqZAgofU2l6aW5nU2NlbmFyaW9VbnN1cHBvcnRlZFJlYXNvbhIyCi5TSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX1VOU1BFQ0lGSUVEEAASPAo4U0laSU5HX1NDRU5BUklPX1VOU1VQUE9SVEVEX1JFQVNPTl9DT05URVhUX0FCT1ZFX01BWElNVU0QARI9CjlTSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX1BBUkFNRVRFUl9PVVRfT0ZfUkFOR0UQAxJFCkFTSVpJTkdfU0NFTkFSSU9fVU5TVVBQT1JURURfUkVBU09OX0RFUklWRURfUEFSQU1FVEVSX09VVF9PRl9SQU5HRRAEKq0BChpTdGFydGluZ1RvdGFsQ29udGV4dFNvdXJjZRItCilTVEFSVElOR19UT1RBTF9DT05URVhUX1NPVVJDRV9VTlNQRUNJRklFRBAAEi0KKVNUQVJUSU5HX1RPVEFMX0NPTlRFWFRfU09VUkNFX0xBUkdFU1RfRklUEAESMQotU1RBUlRJTkdfVE9UQUxfQ09OVEVYVF9TT1VSQ0VfUFJPRklMRV9ERUZBVUxUEAIqvgEKGURlcGxveW1lbnRMb2dIaXN0b3J5U3RhdGUSLAooREVQTE9ZTUVOVF9MT0dfSElTVE9SWV9TVEFURV9VTlNQRUNJRklFRBAAEjgKNERFUExPWU1FTlRfTE9HX0hJU1RPUllfU1RBVEVfT0xERVJfT1VUUFVUX01BWV9SRU1BSU4QARI5CjVERVBMT1lNRU5UX0xPR19ISVNUT1JZX1NUQVRFX05PX09MREVSX09VVFBVVF9PQlNFUlZFRBACKsYBChhEZXBsb3ltZW50TG9nU291cmNlU3RhdGUSKwonREVQTE9ZTUVOVF9MT0dfU09VUkNFX1NUQVRFX1VOU1BFQ0lGSUVEEAASKQolREVQTE9ZTUVOVF9MT0dfU09VUkNFX1NUQVRFX0FWQUlMQUJMRRABEisKJ0RFUExPWU1FTlRfTE9HX1NPVVJDRV9TVEFURV9VTkFWQUlMQUJMRRACEiUKIURFUExPWU1FTlRfTE9HX1NPVVJDRV9TVEFURV9FTkRFRBADKoABChNEZXBsb3ltZW50TG9nU3RyZWFtEiUKIURFUExPWU1FTlRfTE9HX1NUUkVBTV9VTlNQRUNJRklFRBAAEiAKHERFUExPWU1FTlRfTE9HX1NUUkVBTV9TVERPVVQQARIgChxERVBMT1lNRU5UX0xPR19TVFJFQU1fU1RERVJSEAIy4AwKFk1vZGVsRGVwbG95bWVudFNlcnZpY2USdQoUTGlzdE1vZGVsRGVwbG95bWVudHMSLS5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbERlcGxveW1lbnRzUmVxdWVzdBouLmRvdGNvcmUubW9kZWwudjEuTGlzdE1vZGVsRGVwbG95bWVudHNSZXNwb25zZRJ4ChVDcmVhdGVNb2RlbERlcGxveW1lbnQSLi5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZU1vZGVsRGVwbG95bWVudFJlcXVlc3QaLy5kb3Rjb3JlLm1vZGVsLnYxLkNyZWF0ZU1vZGVsRGVwbG95bWVudFJlc3BvbnNlEooBChtQcmV2aWV3TG9jYWxNb2RlbERlcGxveW1lbnQSNC5kb3Rjb3JlLm1vZGVsLnYxLlByZXZpZXdMb2NhbE1vZGVsRGVwbG95bWVudFJlcXVlc3QaNS5kb3Rjb3JlLm1vZGVsLnYxLlByZXZpZXdMb2NhbE1vZGVsRGVwbG95bWVudFJlc3BvbnNlEooBChtFc3RpbWF0ZUxvY2FsTW9kZWxSZXNvdXJjZXMSNC5kb3Rjb3JlLm1vZGVsLnYxLkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1JlcXVlc3QaNS5kb3Rjb3JlLm1vZGVsLnYxLkVzdGltYXRlTG9jYWxNb2RlbFJlc291cmNlc1Jlc3BvbnNlEpABCh1MaXN0TW9kZWxQcm9maWxlQ29tcGF0aWJpbGl0eRI2LmRvdGNvcmUubW9kZWwudjEuTGlzdE1vZGVsUHJvZmlsZUNvbXBhdGliaWxpdHlSZXF1ZXN0GjcuZG90Y29yZS5tb2RlbC52MS5MaXN0TW9kZWxQcm9maWxlQ29tcGF0aWJpbGl0eVJlc3BvbnNlEoEBChhMaXN0TW9kZWxSZWNvbW1lbmRhdGlvbnMSMS5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbFJlY29tbWVuZGF0aW9uc1JlcXVlc3QaMi5kb3Rjb3JlLm1vZGVsLnYxLkxpc3RNb2RlbFJlY29tbWVuZGF0aW9uc1Jlc3BvbnNlEngKFVVwZGF0ZU1vZGVsRGVwbG95bWVudBIuLmRvdGNvcmUubW9kZWwudjEuVXBkYXRlTW9kZWxEZXBsb3ltZW50UmVxdWVzdBovLmRvdGNvcmUubW9kZWwudjEuVXBkYXRlTW9kZWxEZXBsb3ltZW50UmVzcG9uc2USeAoVUmVtb3ZlTW9kZWxEZXBsb3ltZW50Ei4uZG90Y29yZS5tb2RlbC52MS5SZW1vdmVNb2RlbERlcGxveW1lbnRSZXF1ZXN0Gi8uZG90Y29yZS5tb2RlbC52MS5SZW1vdmVNb2RlbERlcGxveW1lbnRSZXNwb25zZRJXCgpQYXVzZU1vZGVsEiMuZG90Y29yZS5tb2RlbC52MS5QYXVzZU1vZGVsUmVxdWVzdBokLmRvdGNvcmUubW9kZWwudjEuUGF1c2VNb2RlbFJlc3BvbnNlEloKC1Jlc3VtZU1vZGVsEiQuZG90Y29yZS5tb2RlbC52MS5SZXN1bWVNb2RlbFJlcXVlc3QaJS5kb3Rjb3JlLm1vZGVsLnYxLlJlc3VtZU1vZGVsUmVzcG9uc2USbwoSUmVhZERlcGxveW1lbnRMb2dzEisuZG90Y29yZS5tb2RlbC52MS5SZWFkRGVwbG95bWVudExvZ3NSZXF1ZXN0GiwuZG90Y29yZS5tb2RlbC52MS5SZWFkRGVwbG95bWVudExvZ3NSZXNwb25zZRJ3ChRGb2xsb3dEZXBsb3ltZW50TG9ncxItLmRvdGNvcmUubW9kZWwudjEuRm9sbG93RGVwbG95bWVudExvZ3NSZXF1ZXN0Gi4uZG90Y29yZS5tb2RlbC52MS5Gb2xsb3dEZXBsb3ltZW50TG9nc1Jlc3BvbnNlMAESkAEKHVVwZGF0ZU1vZGVsRGVwbG95bWVudE1ldGFkYXRhEjYuZG90Y29yZS5tb2RlbC52MS5VcGRhdGVNb2RlbERlcGxveW1lbnRNZXRhZGF0YVJlcXVlc3QaNy5kb3Rjb3JlLm1vZGVsLnYxLlVwZGF0ZU1vZGVsRGVwbG95bWVudE1ldGFkYXRhUmVzcG9uc2ViBnByb3RvMw", [file_dotcore_capacity_v1_placement_preview, file_dotcore_catalog_v1_model, file_dotcore_catalog_v1_oci, file_dotcore_catalog_v1_parameter, file_dotcore_catalog_v1_recommendation, file_dotcore_catalog_v1_selector, file_dotcore_deployment_v1_memory_fit, file_dotcore_deployment_v1_placement, file_dotcore_model_v1_deployment, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); /** * Requests the controller-owned model deployments. @@ -176,9 +176,9 @@ export type LocalModelDeploymentConfiguration = Message<"dotcore.model.v1.LocalM /** * Exact typed engine parameter values when supplied, an empty set deriving from sizing; the profile's defaults when absent, even with a supplied binding. * - * @generated from field: dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 2; + * @generated from field: dotcore.catalog.v1.ParameterValues engine_parameter_values = 2; */ - engineParameterValues?: EngineParameterValues; + engineParameterValues?: ParameterValues; /** * Exact ordered custom engine argv tokens appended without interpretation. @@ -469,9 +469,9 @@ export type HardwareClassResourceEstimate = Message<"dotcore.model.v1.HardwareCl /** * Engine parameter values derived from catalog sizing because the configuration omitted them. * - * @generated from field: dotcore.catalog.v1.EngineParameterValues derived_engine_parameter_values = 3; + * @generated from field: dotcore.catalog.v1.ParameterValues derived_engine_parameter_values = 3; */ - derivedEngineParameterValues?: EngineParameterValues; + derivedEngineParameterValues?: ParameterValues; /** * Operator-readable reason a launch would reject these values; absent when it wouldn't. @@ -942,9 +942,9 @@ export type ModelProfileSizing = Message<"dotcore.model.v1.ModelProfileSizing"> /** * Profile and engine parameter defaults with the scenario's values and the filled context per request, without sizing-derived values; absent when unsupported. * - * @generated from field: dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 3; + * @generated from field: dotcore.catalog.v1.ParameterValues engine_parameter_values = 3; */ - engineParameterValues?: EngineParameterValues; + engineParameterValues?: ParameterValues; /** * Estimates per supported hardware class in declaration order, omitting unsupported classes and classes whose sizing fails. diff --git a/proto/dotcore/catalog/v1/application.proto b/proto/dotcore/catalog/v1/application.proto index 06387a96..5ed0c51f 100644 --- a/proto/dotcore/catalog/v1/application.proto +++ b/proto/dotcore/catalog/v1/application.proto @@ -36,17 +36,9 @@ message ApplicationGraph { // The one service port that can be projected as the primary endpoint. ApplicationPrimaryEndpoint primary_endpoint = 2; - // Typed parameters operators may set at deployment creation, in display order. - repeated ApplicationParameter parameters = 3; -} - -// One typed application parameter and how the console shows it. -message ApplicationParameter { - // Typed definition; application parameters always declare a default. - ParameterDefinition definition = 1; - - // Whether the console shows this parameter only in its advanced view. - bool advanced = 2; + // Typed parameters operators may set at deployment creation, in display order; each declares a + // default and is basic or advanced. + repeated ParameterDefinition parameters = 3; } // One named service in an immutable application graph. diff --git a/proto/dotcore/catalog/v1/engine_release.proto b/proto/dotcore/catalog/v1/engine_release.proto index 175eaf38..6e787775 100644 --- a/proto/dotcore/catalog/v1/engine_release.proto +++ b/proto/dotcore/catalog/v1/engine_release.proto @@ -4,6 +4,7 @@ package dotcore.catalog.v1; import "dotcore/catalog/v1/nix.proto"; import "dotcore/catalog/v1/oci.proto"; +import "dotcore/catalog/v1/parameter.proto"; import "dotcore/catalog/v1/selector.proto"; import "dotcore/catalog/v1/storage.proto"; import "dotcore/engine/v1/engine.proto"; @@ -62,67 +63,6 @@ message EngineParameterSchema { // Stable schema identity retained with resolved deployments. string schema_id = 1; - // Supported typed engine parameters. - repeated EngineParameterDefinition parameters = 2; -} - -// Defines one typed engine parameter and its validation constraints. -message EngineParameterDefinition { - // Stable engine parameter identity. - string parameter_id = 1; - - // Human-readable parameter label. - string display_name = 2; - - oneof parameter_type { - // Unsigned-integer constraints for this parameter. - UnsignedIntegerEngineParameterSchema unsigned_integer = 3; - - // Boolean type for this parameter. - BooleanEngineParameterSchema boolean = 4; - } - - // Whether the console exposes this parameter by default. - bool exposed = 5; - - // Optional practical guidance shown with this parameter. - string description = 6; -} - -// Defines a boolean engine parameter. -message BooleanEngineParameterSchema {} - -// Defines the inclusive range for an unsigned-integer engine parameter. -message UnsignedIntegerEngineParameterSchema { - // Inclusive minimum accepted value. - uint64 minimum = 1; - - // Inclusive maximum accepted value. - uint64 maximum = 2; - - // Human-readable unit label for this value. - string unit = 3; - - // Value used when neither the deployment nor its profile supplies one, within the range. - optional uint64 default_value = 4; -} - -// Supplies a complete set of exact typed engine parameter values. -message EngineParameterValues { - // Exact values keyed by stable parameter identity. - repeated EngineParameterValue values = 1; -} - -// Supplies one exact typed engine parameter value. -message EngineParameterValue { - // Stable engine parameter identity. - string parameter_id = 1; - - oneof value { - // Exact unsigned-integer value. - uint64 unsigned_integer = 2; - - // Exact boolean value, preserving false presence. - bool boolean = 3; - } + // Supported typed engine parameters, in display order. + repeated ParameterDefinition parameters = 2; } diff --git a/proto/dotcore/catalog/v1/model.proto b/proto/dotcore/catalog/v1/model.proto index a54371b8..a2e57c3f 100644 --- a/proto/dotcore/catalog/v1/model.proto +++ b/proto/dotcore/catalog/v1/model.proto @@ -6,6 +6,7 @@ import "dotcore/catalog/v1/engine_release.proto"; import "dotcore/catalog/v1/execution.proto"; import "dotcore/catalog/v1/hardware_class.proto"; import "dotcore/catalog/v1/model_capabilities.proto"; +import "dotcore/catalog/v1/parameter.proto"; import "dotcore/engine/v1/engine.proto"; // An immutable artifact-manager catalog declaration. The inference controller @@ -188,7 +189,7 @@ message ModelProfile { string default_model_artifact_binding_id = 3; // Typed engine parameter defaults for this profile, overlaid on the engine defaults. - EngineParameterValues engine_parameter_defaults = 4; + ParameterValues engine_parameter_defaults = 4; // Optional human-readable name for this profile. string display_name = 5; diff --git a/proto/dotcore/catalog/v1/parameter.proto b/proto/dotcore/catalog/v1/parameter.proto index e5adf393..70a466be 100644 --- a/proto/dotcore/catalog/v1/parameter.proto +++ b/proto/dotcore/catalog/v1/parameter.proto @@ -2,8 +2,9 @@ syntax = "proto3"; package dotcore.catalog.v1; -// Defines one owner-neutral typed parameter: its identity, label, guidance, and value constraints. -// Owners decide whether a default is required and how the parameter is shown. +// Defines one owner-neutral typed parameter: its identity, label, guidance, visibility and value +// constraints. Owners decide which types and visibilities they accept and whether a default is +// required. message ParameterDefinition { // Stable parameter identity, unique within its declaring owner. string parameter_id = 1; @@ -14,6 +15,9 @@ message ParameterDefinition { // Optional practical guidance shown with this parameter. string description = 3; + // Where the console shows this parameter. + ParameterVisibility visibility = 7; + oneof parameter_type { // Boolean type for this parameter. BooleanParameterSchema boolean = 4; @@ -56,6 +60,12 @@ message StringEnumParameterSchema { optional string default_value = 2; } +// Supplies a set of exact typed parameter values. +message ParameterValues { + // Exact values keyed by stable parameter identity. + repeated ParameterValue values = 1; +} + // Supplies one exact typed parameter value. message ParameterValue { // Stable parameter identity. @@ -72,3 +82,18 @@ message ParameterValue { string string = 4; } } + +// Where the console shows a parameter. +enum ParameterVisibility { + // Invalid; every parameter declares its visibility. + PARAMETER_VISIBILITY_UNSPECIFIED = 0; + + // Shown in the main view. + PARAMETER_VISIBILITY_BASIC = 1; + + // Shown only in the advanced view. + PARAMETER_VISIBILITY_ADVANCED = 2; + + // Never shown; the value comes from its default, a profile or sizing. + PARAMETER_VISIBILITY_HIDDEN = 3; +} diff --git a/proto/dotcore/model/v1/deployment.proto b/proto/dotcore/model/v1/deployment.proto index 270fc85a..c209c97f 100644 --- a/proto/dotcore/model/v1/deployment.proto +++ b/proto/dotcore/model/v1/deployment.proto @@ -8,6 +8,7 @@ import "dotcore/catalog/v1/hardware_class.proto"; import "dotcore/catalog/v1/model.proto"; import "dotcore/catalog/v1/model_capabilities.proto"; import "dotcore/catalog/v1/oci.proto"; +import "dotcore/catalog/v1/parameter.proto"; import "dotcore/catalog/v1/selector.proto"; import "dotcore/catalog/v1/storage.proto"; import "dotcore/catalog/v1/upstream_model_template.proto"; @@ -153,7 +154,7 @@ message ResolvedLocalModelDeploymentSnapshot { repeated dotcore.catalog.v1.InferenceRequestKind request_kinds = 22; // Complete exact resolved typed engine parameter values. - dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 13; + dotcore.catalog.v1.ParameterValues engine_parameter_values = 13; // Engine parameter schema identity used for resolution. string engine_parameter_schema_id = 14; diff --git a/proto/dotcore/model/v1/service.proto b/proto/dotcore/model/v1/service.proto index a9fe1466..394ff0a9 100644 --- a/proto/dotcore/model/v1/service.proto +++ b/proto/dotcore/model/v1/service.proto @@ -3,9 +3,9 @@ syntax = "proto3"; package dotcore.model.v1; import "dotcore/capacity/v1/placement_preview.proto"; -import "dotcore/catalog/v1/engine_release.proto"; import "dotcore/catalog/v1/model.proto"; import "dotcore/catalog/v1/oci.proto"; +import "dotcore/catalog/v1/parameter.proto"; import "dotcore/catalog/v1/recommendation.proto"; import "dotcore/catalog/v1/selector.proto"; import "dotcore/deployment/v1/memory_fit.proto"; @@ -91,7 +91,7 @@ message LocalModelDeploymentConfiguration { string model_artifact_binding_id = 1; // Exact typed engine parameter values when supplied, an empty set deriving from sizing; the profile's defaults when absent, even with a supplied binding. - dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 2; + dotcore.catalog.v1.ParameterValues engine_parameter_values = 2; // Exact ordered custom engine argv tokens appended without interpretation. repeated string custom_argument_tokens = 3; @@ -200,7 +200,7 @@ message HardwareClassResourceEstimate { repeated ScalarResourceEstimate estimates = 2; // Engine parameter values derived from catalog sizing because the configuration omitted them. - dotcore.catalog.v1.EngineParameterValues derived_engine_parameter_values = 3; + dotcore.catalog.v1.ParameterValues derived_engine_parameter_values = 3; // Operator-readable reason a launch would reject these values; absent when it wouldn't. optional string launch_rejection = 4; @@ -387,7 +387,7 @@ message ModelProfileSizing { string profile_id = 2; // Profile and engine parameter defaults with the scenario's values and the filled context per request, without sizing-derived values; absent when unsupported. - dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 3; + dotcore.catalog.v1.ParameterValues engine_parameter_values = 3; // Estimates per supported hardware class in declaration order, omitting unsupported classes and classes whose sizing fails. repeated HardwareClassResourceEstimate hardware_class_estimates = 4; diff --git a/proto/dotcore/telemetry/v1/workload_resource.proto b/proto/dotcore/telemetry/v1/workload_resource.proto index 43d30454..0754c061 100644 --- a/proto/dotcore/telemetry/v1/workload_resource.proto +++ b/proto/dotcore/telemetry/v1/workload_resource.proto @@ -2,8 +2,8 @@ syntax = "proto3"; package dotcore.telemetry.v1; -import "dotcore/catalog/v1/engine_release.proto"; import "dotcore/catalog/v1/model.proto"; +import "dotcore/catalog/v1/parameter.proto"; import "dotcore/observation/v1/observation.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; @@ -87,7 +87,7 @@ message WorkloadResourceInputs { string engine_artifact_reference = 8; // Complete resolved engine parameter values. - dotcore.catalog.v1.EngineParameterValues engine_parameter_values = 9; + dotcore.catalog.v1.ParameterValues engine_parameter_values = 9; // Complete resolved option values. repeated dotcore.catalog.v1.ModelOptionValues option_values = 10; From 1e005092c0b91080a4ae77d4d921e7f79738b957 Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 13:38:10 -0500 Subject: [PATCH 02/40] unreviewed: refactor(backend): move engines onto the shared parameter definition Upgrading: site files keep deployment snapshots with the old parameter fields and fail to load after this change. Tear down model and ComfyUI deployments before upgrading, and upgrade every node of a cluster together. --- backend/catalog/src/lib.rs | 53 ++++---- backend/catalog/src/shared_parameters.rs | 87 ++++++++----- backend/catalog/src/sizing/mod.rs | 74 +++++------ backend/catalog/src/test_support.rs | 21 ++-- backend/catalog/src/typed_parameters.rs | 32 +++-- backend/catalog/src/validation/application.rs | 69 ++++++---- .../catalog/src/validation/engine_release.rs | 115 +++++++++++------ backend/catalog/src/validation/graph.rs | 22 ++-- backend/catalog/src/validation/mod.rs | 14 +-- backend/catalog/src/validation/model.rs | 119 ++++++++++++------ backend/cli/src/workload/mod.rs | 39 +++--- .../src/application/controller/parameters.rs | 7 +- .../application/controller/test_support.rs | 50 ++++---- backend/core/src/application/repository.rs | 28 ++--- backend/core/src/development/mod.rs | 4 +- backend/core/src/model/engine/declaration.rs | 16 +-- backend/core/src/model/engine/definition.rs | 22 ++-- .../src/model/engine/llama_cpp/declaration.rs | 47 ++++--- .../core/src/model/engine/llama_cpp/mod.rs | 8 +- .../core/src/model/engine/llama_cpp/plan.rs | 14 +-- backend/core/src/model/engine/mod.rs | 8 +- .../src/model/engine/ninfer/declaration.rs | 28 ++--- backend/core/src/model/engine/ninfer/mod.rs | 6 +- backend/core/src/model/engine/ninfer/plan.rs | 6 +- .../src/model/engine/strata/declaration.rs | 39 +++--- backend/core/src/model/engine/strata/mod.rs | 12 +- backend/core/src/model/engine/strata/plan.rs | 6 +- .../core/src/model/engine/vllm/declaration.rs | 34 ++--- backend/core/src/model/engine/vllm/plan.rs | 12 +- .../core/src/model/recommendation/tests.rs | 8 +- backend/core/src/model/repository.rs | 21 ++-- backend/core/src/model/resolution.rs | 101 ++++++++------- backend/core/src/model/resolved.rs | 6 +- backend/core/src/model/sizing_scenario/mod.rs | 18 +-- .../core/src/model/sizing_scenario/tests.rs | 30 ++--- backend/core/src/route_manager/projection.rs | 4 +- backend/core/src/telemetry/fit/mod.rs | 10 +- backend/core/src/telemetry/fit/tests.rs | 8 +- backend/core/src/telemetry/mod.rs | 10 +- backend/core/src/test_support/mod.rs | 8 +- backend/core/src/test_support/ninfer.rs | 51 ++++---- backend/core/src/test_support/nix.rs | 5 +- backend/core/src/test_support/strata.rs | 43 +++---- .../core/tests/backend/backend_integration.rs | 16 +-- .../core/tests/backend/catalog_contracts.rs | 64 +++++----- .../tests/gated/apple_hardware_integration.rs | 4 +- backend/core/tests/gated/decision_requests.rs | 4 +- .../core/tests/gated/nvidia_qualification.rs | 8 +- .../multi_node/remote_model_lifecycle.rs | 7 +- backend/core/tests/support/mod.rs | 17 ++- backend/domain/src/test_support/model.rs | 31 ++--- .../development-catalog/engines/fixture.yaml | 7 +- .../recommendation-catalog/engines/llama.yaml | 8 +- .../catalog/engines/fixture.yaml | 7 +- .../catalog/engines/fixture.yaml | 7 +- .../engines/llama-cpp-linux-2026-10-19.yaml | 7 +- backend/proto/tests/model_contract.rs | 92 ++++++++------ backend/proto/tests/site_contract.rs | 29 ++--- 58 files changed, 887 insertions(+), 736 deletions(-) diff --git a/backend/catalog/src/lib.rs b/backend/catalog/src/lib.rs index 3ea5813f..82799ec2 100644 --- a/backend/catalog/src/lib.rs +++ b/backend/catalog/src/lib.rs @@ -16,9 +16,9 @@ compile_error!("Dotcore supports only Linux and macOS targets"); use std::{collections::BTreeMap, error::Error as StdError, fmt, path::Path}; use dotcore_proto::dotcore::catalog::v1::{ - Application, EngineArtifact, EngineParameterValues, EngineRelease, HardwareClass, - HardwareClassRecommendations, HardwareRequirements, Model, ModelArtifact, ModelArtifactBinding, - ModelEngineConfiguration, ModelOptionValues, ModelProfile, UpstreamModelTemplate, + Application, EngineArtifact, EngineRelease, HardwareClass, HardwareClassRecommendations, + HardwareRequirements, Model, ModelArtifact, ModelArtifactBinding, ModelEngineConfiguration, + ModelOptionValues, ModelProfile, ParameterValues, UpstreamModelTemplate, }; #[cfg(test)] use dotcore_proto::dotcore::model::v1::ResolvedLocalModelDeploymentSnapshot; @@ -219,7 +219,7 @@ impl Catalog { &self, model_id: &CatalogModelId, profile_id: &str, - ) -> Option<(String, EngineParameterValues)> { + ) -> Option<(String, ParameterValues)> { let (model, profile) = self.selected_model_profile(model_id, profile_id)?; let engine_defaults = self .engine_defaults @@ -357,7 +357,7 @@ impl Catalog { configuration_id: &str, hardware_class_id: &str, binding_id: &str, - engine_parameter_values: &EngineParameterValues, + engine_parameter_values: &ParameterValues, option_values: &[ModelOptionValues], ) -> Result, SizingError> { let key = SizingKey { @@ -383,7 +383,7 @@ impl Catalog { binding_id: &str, resolved_model_artifact_id: Option<&str>, resolved_auxiliary_artifact_ids: &[String], - engine_parameter_values: &EngineParameterValues, + engine_parameter_values: &ParameterValues, option_values: &[ModelOptionValues], ) -> Result, SizingError> { let key = SizingKey { @@ -960,9 +960,8 @@ mod tests { use dotcore_domain::test_support::oci::ServiceArtifactOci as _; use dotcore_proto::dotcore::{ catalog::v1::{ - ApplicationDependencyCondition, ApplicationServiceDependency, EngineParameterValue, - EngineParameterValues, EngineRelease, UpstreamWireProtocol, UseCase, - engine_parameter_value::Value as ParameterValue, + ApplicationDependencyCondition, ApplicationServiceDependency, EngineRelease, + ParameterValue, ParameterValues, UpstreamWireProtocol, UseCase, parameter_value::Value, }, engine::v1::EngineKind, model::v1::ResolvedLocalModelDeploymentSnapshot, @@ -1089,18 +1088,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: {{ minimum: "1024", maximum: "131072", unit: "tokens", defaultValue: "32768" }} - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: {{ minimum: "1024", maximum: "131072", unit: "tokens" }} - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: {{ minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" }} - parameterId: "cache-mib" displayName: "Cache" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: {{ minimum: "0", maximum: "{cache_maximum}", unit: "MiB" }} artifacts: - artifactId: "linux-amd64" @@ -1375,10 +1375,10 @@ artifacts: "Catalog sizing evaluation: resolved local selection does not match sizing binding" ); - let expanded = EngineParameterValues { - values: vec![EngineParameterValue { + let expanded = ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), - value: Some(ParameterValue::UnsignedInteger(50_177)), + value: Some(Value::UnsignedInteger(50_177)), }], }; let expanded_local = resolved_fixture_snapshot("sized-weights", "nvidia", expanded); @@ -1786,7 +1786,7 @@ artifacts: "local", "nvidia", "second", - &EngineParameterValues::default(), + &ParameterValues::default(), &[], ) .expect("derivation evaluates"), @@ -2575,9 +2575,7 @@ useCases: .expect("parameter defaults") .values[0] .value = Some( - dotcore_proto::dotcore::catalog::v1::engine_parameter_value::Value::UnsignedInteger( - 1_000_000, - ), + dotcore_proto::dotcore::catalog::v1::parameter_value::Value::UnsignedInteger(1_000_000), ); model.profiles.push(duplicate); @@ -2910,18 +2908,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: {{ minimum: "1024", maximum: "131072", unit: "tokens", defaultValue: "32768" }} - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: {{ minimum: "1024", maximum: "131072", unit: "tokens" }} - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: {{ minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" }} - parameterId: "cache-mib" displayName: "Cache" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: {{ minimum: "0", maximum: "{cache_maximum}", unit: "MiB" }} artifacts: - artifactId: "{id}-artifact" @@ -3011,13 +3010,13 @@ profiles: ) } - fn unsigned_values(values: &[(&str, u64)]) -> EngineParameterValues { - EngineParameterValues { + fn unsigned_values(values: &[(&str, u64)]) -> ParameterValues { + ParameterValues { values: values .iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: (*parameter_id).to_owned(), - value: Some(ParameterValue::UnsignedInteger(*value)), + value: Some(Value::UnsignedInteger(*value)), }) .collect(), } @@ -3035,7 +3034,7 @@ profiles: fn resolved_fixture_snapshot( model_artifact_id: &str, hardware_class_id: &str, - engine_parameter_values: EngineParameterValues, + engine_parameter_values: ParameterValues, ) -> ResolvedLocalModelDeploymentSnapshot { ResolvedLocalModelDeploymentSnapshot { model_id: "fixture-model".to_owned(), diff --git a/backend/catalog/src/shared_parameters.rs b/backend/catalog/src/shared_parameters.rs index f7db621d..c0fcc8d2 100644 --- a/backend/catalog/src/shared_parameters.rs +++ b/backend/catalog/src/shared_parameters.rs @@ -1,15 +1,15 @@ //! The engine parameters every engine release shares: total context, context per request and //! parallel requests. //! -//! The catalog owns their ids and their fixed shape, so controllers, adapters and the console -//! name them the same way on every engine, while each release sets its own maxima, default values +//! The catalog owns their ids and their fixed shape and visibility, so controllers, adapters and +//! the console name and place them the same way on every engine, while each release sets its own maxima, default values //! and descriptions. It also fills the context per request a deployment leaves out, from the //! maximum context and the total context. use dotcore_proto::dotcore::catalog::v1::{ - EngineParameterDefinition, EngineParameterSchema, EngineParameterValue, EngineParameterValues, - Model, ModelEngineConfiguration, engine_parameter_definition::ParameterType, - engine_parameter_value::Value, + EngineParameterSchema, Model, ModelEngineConfiguration, ParameterDefinition, ParameterValue, + ParameterValues, ParameterVisibility, parameter_definition::ParameterType, + parameter_value::Value, }; /// Id of the total context: the KV pool an engine holds at start, shared by active requests. @@ -49,9 +49,9 @@ pub fn maximum_context_tokens(model: &Model, configuration: &ModelEngineConfigur /// values already supply one, or they hold no total context to bound it. pub fn filled_context_per_request( schema: &EngineParameterSchema, - values: &EngineParameterValues, + values: &ParameterValues, maximum_context_tokens: u32, -) -> Option { +) -> Option { let declared = schema .parameters .iter() @@ -73,7 +73,7 @@ pub fn filled_context_per_request( _ => None, } })?; - Some(EngineParameterValue { + Some(ParameterValue { parameter_id: CONTEXT_PER_REQUEST_PARAMETER_ID.to_owned(), value: Some(Value::UnsignedInteger( total_context.min(u64::from(maximum_context_tokens)), @@ -125,6 +125,7 @@ const SHARED_PARAMETERS: [SharedParameter; 3] = [ display_name: "Total context", unit: "tokens", minimum: MINIMUM_CONTEXT_TOKENS, + visibility: ParameterVisibility::Basic, engine_default: true, profile_default: false, }, @@ -133,6 +134,7 @@ const SHARED_PARAMETERS: [SharedParameter; 3] = [ display_name: "Context per request", unit: "tokens", minimum: MINIMUM_CONTEXT_TOKENS, + visibility: ParameterVisibility::Basic, engine_default: false, profile_default: false, }, @@ -141,17 +143,20 @@ const SHARED_PARAMETERS: [SharedParameter; 3] = [ display_name: "Parallel requests", unit: "requests", minimum: 1, + visibility: ParameterVisibility::Advanced, engine_default: true, profile_default: true, }, ]; -/// One shared parameter's fixed shape. Every shared parameter is an exposed unsigned integer. +/// One shared parameter's fixed shape. Every shared parameter is an unsigned integer the console +/// shows: the contexts in its main view, the parallel requests in its advanced view. struct SharedParameter { parameter_id: &'static str, display_name: &'static str, unit: &'static str, minimum: u64, + visibility: ParameterVisibility, /// Whether every release must declare an engine default; otherwise none may. engine_default: bool, @@ -162,15 +167,15 @@ struct SharedParameter { impl SharedParameter { /// Returns how a declared definition departs from the fixed shape, or none when it matches. - fn shape_problem(&self, definition: &EngineParameterDefinition) -> Option { + fn shape_problem(&self, definition: &ParameterDefinition) -> Option { let Some(ParameterType::UnsignedInteger(range)) = definition.parameter_type.as_ref() else { return Some("must be an unsigned integer".to_owned()); }; if definition.display_name != self.display_name { return Some(format!("must be named {:?}", self.display_name)); } - if !definition.exposed { - return Some("must be exposed".to_owned()); + if definition.visibility() != self.visibility { + return Some(format!("must be {}", visibility_name(self.visibility))); } if range.unit != self.unit { return Some(format!("must be in {:?}", self.unit)); @@ -186,9 +191,19 @@ impl SharedParameter { } } +/// Returns the visibility's lowercase name, for messages. +fn visibility_name(visibility: ParameterVisibility) -> &'static str { + match visibility { + ParameterVisibility::Unspecified => "unspecified", + ParameterVisibility::Basic => "basic", + ParameterVisibility::Advanced => "advanced", + ParameterVisibility::Hidden => "hidden", + } +} + #[cfg(test)] mod tests { - use dotcore_proto::dotcore::catalog::v1::UnsignedIntegerEngineParameterSchema; + use dotcore_proto::dotcore::catalog::v1::UnsignedIntegerParameterSchema; use super::*; @@ -214,7 +229,7 @@ mod tests { #[test] fn a_shared_parameter_in_the_wrong_shape_is_rejected() { - let cases: [(&str, ShapeChange, &str); 7] = [ + let cases: [(&str, ShapeChange, &str); 9] = [ ( TOTAL_CONTEXT_PARAMETER_ID, |definition| { @@ -229,8 +244,18 @@ mod tests { ), ( PARALLEL_REQUESTS_PARAMETER_ID, - |definition| definition.exposed = false, - "must be exposed", + |definition| definition.set_visibility(ParameterVisibility::Hidden), + "must be advanced", + ), + ( + TOTAL_CONTEXT_PARAMETER_ID, + |definition| definition.set_visibility(ParameterVisibility::Advanced), + "must be basic", + ), + ( + CONTEXT_PER_REQUEST_PARAMETER_ID, + |definition| definition.set_visibility(ParameterVisibility::Hidden), + "must be basic", ), ( PARALLEL_REQUESTS_PARAMETER_ID, @@ -340,7 +365,7 @@ mod tests { None ); assert_eq!( - filled_context_per_request(&schema, &EngineParameterValues::default(), 262_144), + filled_context_per_request(&schema, &ParameterValues::default(), 262_144), None ); } @@ -371,7 +396,7 @@ mod tests { } /// Edits one shared parameter definition away from its fixed shape. - type ShapeChange = fn(&mut EngineParameterDefinition); + type ShapeChange = fn(&mut ParameterDefinition); fn messages(schema: &EngineParameterSchema) -> Vec { validate_shared_parameters(schema) @@ -415,43 +440,45 @@ mod tests { unit: &str, minimum: u64, default_value: Option, - ) -> EngineParameterDefinition { - EngineParameterDefinition { + ) -> ParameterDefinition { + ParameterDefinition { parameter_id: parameter_id.to_owned(), display_name: display_name.to_owned(), parameter_type: Some(ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum, maximum: 16_777_216, unit: unit.to_owned(), default_value, }, )), - exposed: true, + visibility: SHARED_PARAMETERS + .iter() + .find(|shared| shared.parameter_id == parameter_id) + .map_or(ParameterVisibility::Advanced, |shared| shared.visibility) + as i32, description: String::new(), } } - fn range( - definition: &mut EngineParameterDefinition, - ) -> &mut UnsignedIntegerEngineParameterSchema { + fn range(definition: &mut ParameterDefinition) -> &mut UnsignedIntegerParameterSchema { match definition.parameter_type.as_mut() { Some(ParameterType::UnsignedInteger(range)) => range, _ => panic!("unsigned shared parameter"), } } - fn total(value: u64) -> EngineParameterValues { - EngineParameterValues { - values: vec![EngineParameterValue { + fn total(value: u64) -> ParameterValues { + ParameterValues { + values: vec![ParameterValue { parameter_id: TOTAL_CONTEXT_PARAMETER_ID.to_owned(), value: Some(Value::UnsignedInteger(value)), }], } } - fn context_per_request(value: u64) -> EngineParameterValue { - EngineParameterValue { + fn context_per_request(value: u64) -> ParameterValue { + ParameterValue { parameter_id: CONTEXT_PER_REQUEST_PARAMETER_ID.to_owned(), value: Some(Value::UnsignedInteger(value)), } diff --git a/backend/catalog/src/sizing/mod.rs b/backend/catalog/src/sizing/mod.rs index fbf74561..84e687c5 100644 --- a/backend/catalog/src/sizing/mod.rs +++ b/backend/catalog/src/sizing/mod.rs @@ -7,12 +7,11 @@ use std::collections::{BTreeMap, BTreeSet}; use dotcore_proto::dotcore::catalog::v1::{ - EngineParameterSchema, EngineParameterValues, ModelEngineConfiguration, - ModelOptionParameterValue, ModelOptionValues, - engine_parameter_definition::ParameterType as EngineParameterType, - engine_parameter_value::Value as EngineParameterValue, - model_option_parameter_definition::ParameterType as OptionParameterType, + EngineParameterSchema, ModelEngineConfiguration, ModelOptionParameterValue, ModelOptionValues, + ParameterValues, model_option_parameter_definition::ParameterType as OptionParameterType, model_option_parameter_value::Value as OptionParameterValue, + parameter_definition::ParameterType as EngineParameterType, + parameter_value::Value as EngineParameterValueKind, }; use serde::Deserialize; @@ -79,7 +78,7 @@ impl CompiledSizing { /// parameter id order. Supplied values always take precedence over a derivation. pub(super) fn derive( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], ) -> Result, SizingError> { let values = self.symbol_values(engine_values, option_values)?; @@ -114,7 +113,7 @@ impl CompiledSizing { /// Evaluates available results in deterministic resource-name order. pub(super) fn evaluate( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], ) -> Result, SizingError> { let values = self.symbol_values(engine_values, option_values)?; @@ -230,7 +229,7 @@ impl CompiledSizing { fn symbol_values( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], ) -> Result, SizingError> { let mut values = self @@ -534,7 +533,7 @@ impl SizingFitModel { /// Evaluates one point's constant and coefficients, or none when the estimate is unavailable. pub fn point( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], extra_values: &BTreeMap, ) -> Result, SizingError> { @@ -574,7 +573,7 @@ impl SizingFitModel { pub fn predict( &self, parameters: &BTreeMap, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], extra_values: &BTreeMap, ) -> Result { @@ -588,7 +587,7 @@ impl SizingFitModel { /// appear in an allowance, so it needs only the point's values. pub fn allowance( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], extra_values: &BTreeMap, ) -> Result { @@ -603,7 +602,7 @@ impl SizingFitModel { fn values( &self, - engine_values: &EngineParameterValues, + engine_values: &ParameterValues, option_values: &[ModelOptionValues], extra_values: &BTreeMap, parameters: Option<&BTreeMap>, @@ -842,16 +841,17 @@ fn option_symbols( fn insert_engine_values( symbols: &mut BTreeMap, - values: &EngineParameterValues, + values: &ParameterValues, ) -> Result<(), SizingError> { for parameter in &values.values { match parameter.value.as_ref() { - Some(EngineParameterValue::UnsignedInteger(value)) => insert_value( + Some(EngineParameterValueKind::UnsignedInteger(value)) => insert_value( symbols, parameter.parameter_id.clone(), expression::Value::Unsigned(*value), )?, - Some(EngineParameterValue::Boolean(_)) => {} + // Sizing references integers only. + Some(EngineParameterValueKind::Boolean(_) | EngineParameterValueKind::String(_)) => {} None => { return Err(SizingError::evaluation(format!( "Engine parameter {:?} has no value", @@ -918,15 +918,15 @@ mod tests { use std::collections::{BTreeMap, BTreeSet}; use dotcore_proto::dotcore::catalog::v1::{ - BooleanEngineParameterSchema, BooleanModelOptionParameterSchema, EngineParameterDefinition, - EngineParameterSchema, EngineParameterValue, EngineParameterValues, + BooleanModelOptionParameterSchema, BooleanParameterSchema, EngineParameterSchema, ModelConfigurationOption, ModelEngineConfiguration, ModelOptionParameterDefinition, - ModelOptionParameterValue, ModelOptionValues, StringEnumModelOptionParameterSchema, - UnsignedIntegerEngineParameterSchema, UnsignedIntegerModelOptionParameterSchema, - engine_parameter_definition::ParameterType as EngineParameterType, - engine_parameter_value::Value as EngineParameterValueKind, + ModelOptionParameterValue, ModelOptionValues, ParameterDefinition, ParameterValue, + ParameterValues, ParameterVisibility, StringEnumModelOptionParameterSchema, + UnsignedIntegerModelOptionParameterSchema, UnsignedIntegerParameterSchema, model_option_parameter_definition::ParameterType as OptionParameterType, model_option_parameter_value::Value as OptionParameterValueKind, + parameter_definition::ParameterType as EngineParameterType, + parameter_value::Value as EngineParameterValueKind, }; use super::{EstimateSource, ScalarResourceEstimate, SizingSource, compile}; @@ -934,18 +934,18 @@ mod tests { fn schema() -> EngineParameterSchema { EngineParameterSchema { schema_id: "test-schema".to_owned(), - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: "total-context".to_owned(), display_name: "Total context".to_owned(), parameter_type: Some(EngineParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1, maximum: 131_072, unit: "tokens".to_owned(), default_value: None, }, )), - exposed: true, + visibility: ParameterVisibility::Basic as i32, description: "Maximum context.".to_owned(), }], } @@ -1014,18 +1014,18 @@ mod tests { } } - fn engine_values(total_context: u64) -> EngineParameterValues { - EngineParameterValues { - values: vec![EngineParameterValue { + fn engine_values(total_context: u64) -> ParameterValues { + ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(total_context)), }], } } - fn engine_values_with_boolean(total_context: u64, enabled: bool) -> EngineParameterValues { + fn engine_values_with_boolean(total_context: u64, enabled: bool) -> ParameterValues { let mut values = engine_values(total_context); - values.values.push(EngineParameterValue { + values.values.push(ParameterValue { parameter_id: "feature-enabled".to_owned(), value: Some(EngineParameterValueKind::Boolean(enabled)), }); @@ -1574,27 +1574,27 @@ mod tests { fn derived_schema() -> EngineParameterSchema { let mut schema = schema(); - schema.parameters.push(EngineParameterDefinition { + schema.parameters.push(ParameterDefinition { parameter_id: "cache-bytes".to_owned(), display_name: "Cache bytes".to_owned(), parameter_type: Some(EngineParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1, maximum: u64::MAX, unit: "bytes".to_owned(), default_value: None, }, )), - exposed: false, + visibility: ParameterVisibility::Hidden as i32, description: "Cache size.".to_owned(), }); - schema.parameters.push(EngineParameterDefinition { + schema.parameters.push(ParameterDefinition { parameter_id: "feature-enabled".to_owned(), display_name: "Feature".to_owned(), parameter_type: Some(EngineParameterType::Boolean( - BooleanEngineParameterSchema {}, + BooleanParameterSchema::default(), )), - exposed: false, + visibility: ParameterVisibility::Hidden as i32, description: "Feature toggle.".to_owned(), }); schema @@ -1609,8 +1609,8 @@ mod tests { declaration } - fn cache_bytes_value(value: u64) -> EngineParameterValue { - EngineParameterValue { + fn cache_bytes_value(value: u64) -> ParameterValue { + ParameterValue { parameter_id: "cache-bytes".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(value)), } diff --git a/backend/catalog/src/test_support.rs b/backend/catalog/src/test_support.rs index 6fd2a2d2..48d8706d 100644 --- a/backend/catalog/src/test_support.rs +++ b/backend/catalog/src/test_support.rs @@ -8,10 +8,10 @@ use std::{collections::BTreeMap, fs, path::PathBuf}; use dotcore_domain::test_support::{canonical_temp_dir, unique_suffix}; use dotcore_proto::dotcore::catalog::v1::{ - Application, EngineParameterValue, EngineRelease, HardwareClass, HardwareSupport, Model, - ModelEngineConfiguration, ModelOptionParameterValue, ModelOptionValues, ModelProfile, Selector, - UpstreamModelTemplate, UpstreamWireProtocol, engine_parameter_value, - model_option_parameter_definition, model_option_parameter_value, + Application, EngineRelease, HardwareClass, HardwareSupport, Model, ModelEngineConfiguration, + ModelOptionParameterValue, ModelOptionValues, ModelProfile, ParameterValue, Selector, + UpstreamModelTemplate, UpstreamWireProtocol, model_option_parameter_definition, + model_option_parameter_value, parameter_value, }; use crate::{ @@ -290,7 +290,7 @@ pub fn write_sizing_engine(root: &std::path::Path) { parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: minimum: "1024" maximum: "16777216" @@ -298,14 +298,14 @@ pub fn write_sizing_engine(root: &std::path::Path) { defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: minimum: "1024" maximum: "16777216" unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: minimum: "1" maximum: "64" @@ -313,6 +313,7 @@ pub fn write_sizing_engine(root: &std::path::Path) { defaultValue: "4" - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: minimum: "0" maximum: "65536" @@ -578,9 +579,9 @@ fn choice_combinations( combinations } -fn unsigned_value(parameter_id: &str, value: u64) -> EngineParameterValue { - EngineParameterValue { +fn unsigned_value(parameter_id: &str, value: u64) -> ParameterValue { + ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), } } diff --git a/backend/catalog/src/typed_parameters.rs b/backend/catalog/src/typed_parameters.rs index 42e1fe2a..70b725fd 100644 --- a/backend/catalog/src/typed_parameters.rs +++ b/backend/catalog/src/typed_parameters.rs @@ -1,20 +1,21 @@ -//! Owner-neutral typed parameters: definition validation, value checks against a definition, -//! and the canonical text form a value takes when projected into configuration. +//! Owner-neutral typed parameters: definition validation, defaults, value checks against a +//! definition, and the canonical text form a value takes when projected into configuration. //! -//! Application graphs use these definitions today; the model lane keeps its own engine and -//! option parameter schemas until it adopts this one. Owners layer their own rules on top, -//! such as whether a default is required. +//! Application graphs and engine releases declare their parameters with these definitions. Owners +//! layer their own rules on top, such as which types and visibilities they accept and whether a +//! default is required. use std::collections::BTreeSet; use anyhow::anyhow; use dotcore_domain::valid_id; use dotcore_proto::dotcore::catalog::v1::{ - ParameterDefinition, ParameterValue, parameter_definition::ParameterType, + ParameterDefinition, ParameterValue, ParameterVisibility, parameter_definition::ParameterType, parameter_value::Value, }; -/// Validates one definition's identity, label, and type constraints, including any default. +/// Validates one definition's identity, label, visibility and type constraints, including any +/// default. pub(crate) fn validate_parameter_definition( definition: &ParameterDefinition, ) -> Vec { @@ -28,6 +29,16 @@ pub(crate) fn validate_parameter_definition( if definition.display_name.trim().is_empty() { errors.push(anyhow!("parameter {id:?} requires a display name")); } + if !matches!( + ParameterVisibility::try_from(definition.visibility), + Ok(ParameterVisibility::Basic + | ParameterVisibility::Advanced + | ParameterVisibility::Hidden) + ) { + errors.push(anyhow!( + "parameter {id:?} requires a basic, advanced or hidden visibility" + )); + } match definition.parameter_type.as_ref() { Some(ParameterType::Boolean(_)) => {} Some(ParameterType::UnsignedInteger(range)) if range.minimum > range.maximum => { @@ -208,6 +219,12 @@ mod tests { let mut untyped = enum_definition(&["auto"], None); untyped.parameter_type = None; assert_errors(&untyped, &["parameter \"mode\" requires a type"]); + let mut unplaced = enum_definition(&["auto"], Some("auto")); + unplaced.visibility = ParameterVisibility::Unspecified as i32; + assert_errors( + &unplaced, + &["parameter \"mode\" requires a basic, advanced or hidden visibility"], + ); assert!( validate_parameter_definition(&enum_definition(&["auto"], Some("auto"))).is_empty() ); @@ -233,6 +250,7 @@ mod tests { parameter_id: "mode".into(), display_name: "Mode".into(), description: String::new(), + visibility: ParameterVisibility::Basic as i32, parameter_type: Some(parameter_type), } } diff --git a/backend/catalog/src/validation/application.rs b/backend/catalog/src/validation/application.rs index 4a73f6cf..ed845117 100644 --- a/backend/catalog/src/validation/application.rs +++ b/backend/catalog/src/validation/application.rs @@ -59,10 +59,10 @@ mod tests { Application, ApplicationConfigurationBinding, ApplicationDependencyCondition, ApplicationDeploymentInput, ApplicationEndpointProtocol, ApplicationGraph, ApplicationHttpReadiness, ApplicationInferenceRouteInput, - ApplicationInferenceRouteProjection, ApplicationParameter, ApplicationPrimaryEndpoint, - ApplicationSecretBinding, ApplicationService, ApplicationServiceDependency, - ApplicationServicePort, ApplicationServiceReadiness, BooleanParameterSchema, NixArtifact, - NixDockerImage, NixSystemStorePath, OciPlatform, ParameterDefinition, StorageBinding, + ApplicationInferenceRouteProjection, ApplicationPrimaryEndpoint, ApplicationSecretBinding, + ApplicationService, ApplicationServiceDependency, ApplicationServicePort, + ApplicationServiceReadiness, BooleanParameterSchema, NixArtifact, NixDockerImage, + NixSystemStorePath, OciPlatform, ParameterDefinition, ParameterVisibility, StorageBinding, StorageKind, StorageScope, StringEnumParameterSchema, UnsignedIntegerParameterSchema, application_configuration_binding, application_service_artifact::Kind as ServiceArtifactKind, nix_artifact::Provides, @@ -636,6 +636,28 @@ mod tests { ), "application parameter \"debug\" is not used by any configuration binding", ), + ( + parameterized_application( + vec![parameter_with_visibility( + "mode", + string_enum(&["auto"], Some("auto")), + ParameterVisibility::Hidden, + )], + &["mode"], + ), + "application parameter \"mode\" must be basic or advanced, not hidden", + ), + ( + parameterized_application( + vec![parameter_with_visibility( + "mode", + string_enum(&["auto"], Some("auto")), + ParameterVisibility::Unspecified, + )], + &["mode"], + ), + "parameter \"mode\" requires a basic, advanced or hidden visibility", + ), ]; for (application, expected) in cases { @@ -682,13 +704,12 @@ mod tests { fn application_yaml_declares_parameters_and_parameter_bindings() { let graph = dotcore_proto::yaml::from_str::( r#"parameters: - - advanced: true - definition: - parameterId: "mode" - displayName: "mode" - stringEnum: - values: ["auto", "highvram"] - defaultValue: "auto" + - parameterId: "mode" + displayName: "mode" + visibility: "PARAMETER_VISIBILITY_ADVANCED" + stringEnum: + values: ["auto", "highvram"] + defaultValue: "auto" services: - configurationBindings: - bindingName: "mode" @@ -703,7 +724,7 @@ services: [parameter_with_visibility( "mode", string_enum(&["auto", "highvram"], Some("auto")), - true + ParameterVisibility::Advanced )] ); assert_eq!( @@ -747,7 +768,7 @@ services: } fn parameterized_application( - parameters: Vec, + parameters: Vec, bound_ids: &[&str], ) -> Application { let mut application = application(); @@ -768,23 +789,21 @@ services: application } - fn parameter(id: &str, parameter_type: ParameterType) -> ApplicationParameter { - parameter_with_visibility(id, parameter_type, false) + fn parameter(id: &str, parameter_type: ParameterType) -> ParameterDefinition { + parameter_with_visibility(id, parameter_type, ParameterVisibility::Basic) } fn parameter_with_visibility( id: &str, parameter_type: ParameterType, - advanced: bool, - ) -> ApplicationParameter { - ApplicationParameter { - definition: Some(ParameterDefinition { - parameter_id: id.to_owned(), - display_name: id.to_owned(), - description: String::new(), - parameter_type: Some(parameter_type), - }), - advanced, + visibility: ParameterVisibility, + ) -> ParameterDefinition { + ParameterDefinition { + parameter_id: id.to_owned(), + display_name: id.to_owned(), + description: String::new(), + visibility: visibility as i32, + parameter_type: Some(parameter_type), } } diff --git a/backend/catalog/src/validation/engine_release.rs b/backend/catalog/src/validation/engine_release.rs index 1f64cb81..061692b1 100644 --- a/backend/catalog/src/validation/engine_release.rs +++ b/backend/catalog/src/validation/engine_release.rs @@ -9,14 +9,17 @@ use std::collections::BTreeSet; use dotcore_domain::{Accelerator, valid_id}; use dotcore_proto::dotcore::catalog::v1::{ - EngineArtifact, EngineParameterDefinition, EngineParameterSchema, EngineRelease, Selector, - engine_artifact::Kind as EngineArtifactKind, engine_parameter_definition::ParameterType, + EngineArtifact, EngineParameterSchema, EngineRelease, ParameterDefinition, Selector, + engine_artifact::Kind as EngineArtifactKind, parameter_definition::ParameterType, }; use super::common::{valid_selector_memory_architecture, validate_oci_reference}; use super::nix::{AcceptedProvides, nix_systems, validate_nix_artifact}; use super::storage::{StorageOwner, validate_storage_bindings}; -use crate::{OciArtifactPolicy, shared_parameters::validate_shared_parameters}; +use crate::{ + OciArtifactPolicy, shared_parameters::validate_shared_parameters, + typed_parameters::validate_parameter_definition as validate_shared_definition, +}; pub fn validate_engine_release_with_policy( engine: &EngineRelease, @@ -229,37 +232,26 @@ fn validate_parameter_schema( errors.extend(validate_shared_parameters(schema)); } +/// Validates one engine parameter definition: the shared definition rules, a unique id, and the +/// engine owner rule that parameters are booleans or unsigned integers with a unit. fn validate_parameter_definition( - definition: &EngineParameterDefinition, + definition: &ParameterDefinition, ids: &mut BTreeSet, errors: &mut Vec, ) { - if !ids.insert(definition.parameter_id.clone()) - || !valid_id(&definition.parameter_id) - || definition.display_name.trim().is_empty() - { - errors.push(anyhow::anyhow!( - "engine parameter requires a unique valid ID and display name" - )); + let id = &definition.parameter_id; + if !ids.insert(id.clone()) { + errors.push(anyhow::anyhow!("duplicate engine parameter {id:?}")); } - if definition - .parameter_type - .as_ref() - .is_none_or(|kind| match kind { - ParameterType::UnsignedInteger(schema) => { - schema.minimum > schema.maximum - || schema.unit.trim().is_empty() - || schema.default_value.is_some_and(|default| { - !(schema.minimum..=schema.maximum).contains(&default) - }) - } - ParameterType::Boolean(_) => false, - }) - { - errors.push(anyhow::anyhow!( - "engine parameter {:?} requires a valid typed range holding its default", - definition.parameter_id - )); + errors.extend(validate_shared_definition(definition)); + match definition.parameter_type.as_ref() { + Some(ParameterType::UnsignedInteger(schema)) if schema.unit.trim().is_empty() => { + errors.push(anyhow::anyhow!("engine parameter {id:?} requires a unit")); + } + Some(ParameterType::StringEnum(_)) => errors.push(anyhow::anyhow!( + "engine parameter {id:?} must be a boolean or an unsigned integer" + )), + Some(ParameterType::Boolean(_) | ParameterType::UnsignedInteger(_)) | None => {} } } @@ -267,8 +259,8 @@ fn validate_parameter_definition( mod tests { use dotcore_proto::dotcore::{ catalog::v1::{ - NixArtifact, NixDockerImage, StorageBinding, StorageKind, StorageScope, - nix_artifact::Provides, + NixArtifact, NixDockerImage, ParameterVisibility, StorageBinding, StorageKind, + StorageScope, nix_artifact::Provides, }, observation::v1::AcceleratorMemoryArchitecture, }; @@ -403,18 +395,18 @@ mod tests { #[test] fn parameter_schemas_reject_an_out_of_range_default_and_a_missing_shared_parameter() { let unsigned = |parameter_id: &str, display_name: &str, unit: &str, default_value| { - EngineParameterDefinition { + ParameterDefinition { parameter_id: parameter_id.to_owned(), display_name: display_name.to_owned(), parameter_type: Some(ParameterType::UnsignedInteger( - dotcore_proto::dotcore::catalog::v1::UnsignedIntegerEngineParameterSchema { + dotcore_proto::dotcore::catalog::v1::UnsignedIntegerParameterSchema { minimum: 1024, maximum: 65_536, unit: unit.to_owned(), default_value, }, )), - exposed: true, + visibility: ParameterVisibility::Basic as i32, description: String::new(), } }; @@ -432,12 +424,65 @@ mod tests { assert_eq!( errors.iter().map(ToString::to_string).collect::>(), [ - "engine parameter \"total-context\" requires a valid typed range holding its default", + "parameter \"total-context\" default is invalid: 131072 is outside 1024..=65536", "engine parameter schema \"fixture-shared\" must declare the shared parameter \"parallel-requests\"", ] ); } + #[test] + fn engine_parameters_are_booleans_or_unsigned_integers_with_a_unit() { + let definition = |parameter_type| ParameterDefinition { + parameter_id: "feature".to_owned(), + display_name: "Feature".to_owned(), + description: String::new(), + visibility: ParameterVisibility::Advanced as i32, + parameter_type: Some(parameter_type), + }; + let errors = |definition: &ParameterDefinition| { + let mut errors = Vec::new(); + validate_parameter_definition(definition, &mut BTreeSet::new(), &mut errors); + errors.iter().map(ToString::to_string).collect::>() + }; + let unsigned = |unit: &str| { + ParameterType::UnsignedInteger( + dotcore_proto::dotcore::catalog::v1::UnsignedIntegerParameterSchema { + minimum: 0, + maximum: 8, + unit: unit.to_owned(), + default_value: Some(4), + }, + ) + }; + let boolean = ParameterType::Boolean( + dotcore_proto::dotcore::catalog::v1::BooleanParameterSchema { + default_value: Some(true), + }, + ); + + assert_eq!(errors(&definition(boolean.clone())), Vec::::new()); + assert_eq!(errors(&definition(unsigned("MiB"))), Vec::::new()); + assert_eq!( + errors(&definition(unsigned(" "))), + ["engine parameter \"feature\" requires a unit"] + ); + assert_eq!( + errors(&definition(ParameterType::StringEnum( + dotcore_proto::dotcore::catalog::v1::StringEnumParameterSchema { + values: vec!["on".to_owned()], + default_value: Some("on".to_owned()), + }, + ))), + ["engine parameter \"feature\" must be a boolean or an unsigned integer"] + ); + let mut unplaced = definition(boolean); + unplaced.visibility = ParameterVisibility::Unspecified as i32; + assert_eq!( + errors(&unplaced), + ["parameter \"feature\" requires a basic, advanced or hidden visibility"] + ); + } + #[test] fn engine_storage_requires_engine_scopes_cache_kind_and_container_artifacts() { let mut image = nix("self"); diff --git a/backend/catalog/src/validation/graph.rs b/backend/catalog/src/validation/graph.rs index 15633580..388f92c4 100644 --- a/backend/catalog/src/validation/graph.rs +++ b/backend/catalog/src/validation/graph.rs @@ -5,7 +5,8 @@ use std::collections::{BTreeMap, BTreeSet}; use dotcore_domain::valid_id; use dotcore_proto::dotcore::catalog::v1::{ ApplicationDependencyCondition, ApplicationEndpointProtocol, ApplicationGraph, - ApplicationService, application_configuration_binding, parameter_definition::ParameterType, + ApplicationService, ParameterVisibility, application_configuration_binding, + parameter_definition::ParameterType, }; use super::application::valid_configuration_value; @@ -179,17 +180,12 @@ fn validate_primary_endpoint( } } -/// Checks parameter definitions and that bindings and parameters reference each other exactly: -/// every binding names a declared parameter and every parameter supplies at least one binding. +/// Checks parameter definitions, each with a default and shown as basic or advanced, and that +/// bindings and parameters reference each other exactly: every binding names a declared parameter +/// and every parameter supplies at least one binding. fn validate_parameters(graph: &ApplicationGraph, errors: &mut Vec) { let mut parameter_ids = BTreeSet::new(); - for parameter in &graph.parameters { - let Some(definition) = parameter.definition.as_ref() else { - errors.push(anyhow::anyhow!( - "application parameter requires a definition" - )); - continue; - }; + for definition in &graph.parameters { let id = &definition.parameter_id; if !parameter_ids.insert(id.as_str()) { errors.push(anyhow::anyhow!("duplicate application parameter {id:?}")); @@ -202,6 +198,12 @@ fn validate_parameters(graph: &ApplicationGraph, errors: &mut Vec "application parameter {id:?} requires a default" )); } + // A value the operator never sees belongs in the graph as a literal. + if definition.visibility() == ParameterVisibility::Hidden { + errors.push(anyhow::anyhow!( + "application parameter {id:?} must be basic or advanced, not hidden" + )); + } // Enum values are projected verbatim into environment variables. if let Some(ParameterType::StringEnum(schema)) = definition.parameter_type.as_ref() && !schema diff --git a/backend/catalog/src/validation/mod.rs b/backend/catalog/src/validation/mod.rs index 3631a63d..76d53eb6 100644 --- a/backend/catalog/src/validation/mod.rs +++ b/backend/catalog/src/validation/mod.rs @@ -10,8 +10,8 @@ use std::collections::{BTreeMap, BTreeSet}; use dotcore_proto::dotcore::catalog::v1::{ - Application, EngineParameterDefinition, EngineParameterValues, EngineRelease, HardwareClass, - HardwareClassRecommendations, Model, ModelEngineConfiguration, UpstreamModelTemplate, + Application, EngineRelease, HardwareClass, HardwareClassRecommendations, Model, + ModelEngineConfiguration, ParameterDefinition, ParameterValues, UpstreamModelTemplate, }; use super::{ @@ -72,8 +72,8 @@ pub trait EngineDeclarationValidator: Send + Sync { _model: &Model, _configuration: &ModelEngineConfiguration, _engine: &EngineRelease, - ) -> EngineParameterValues { - EngineParameterValues::default() + ) -> ParameterValues { + ParameterValues::default() } } @@ -218,7 +218,7 @@ pub(super) fn validate_catalog( } /// Engine parameter defaults of each configuration, keyed by model and configuration id. -pub(super) type ConfigurationEngineDefaults = BTreeMap<(String, String), EngineParameterValues>; +pub(super) type ConfigurationEngineDefaults = BTreeMap<(String, String), ParameterValues>; pub(super) struct ValidatedCatalog { pub(super) models: BTreeMap, @@ -479,9 +479,9 @@ fn validate_sizing_coverage( } fn parameter_definition<'a>( - parameters: &'a [EngineParameterDefinition], + parameters: &'a [ParameterDefinition], parameter_id: &str, -) -> Option<&'a EngineParameterDefinition> { +) -> Option<&'a ParameterDefinition> { parameters .iter() .find(|parameter| parameter.parameter_id == parameter_id) diff --git a/backend/catalog/src/validation/model.rs b/backend/catalog/src/validation/model.rs index b6e3cd8a..04882982 100644 --- a/backend/catalog/src/validation/model.rs +++ b/backend/catalog/src/validation/model.rs @@ -11,15 +11,15 @@ use std::collections::{BTreeMap, BTreeSet}; use dotcore_domain::valid_id; use dotcore_proto::dotcore::catalog::v1::{ - EngineArtifact, EngineParameterValue, EngineParameterValues, EngineRelease, HardwareClass, - HuggingFaceArtifactSource, InferenceRequestKind, IntelligenceScore, License, Model, - ModelArtifact, ModelConfigurationOption, ModelEngineConfiguration, ModelInputCapabilities, - ModelInputModality, ModelOptionParameterDefinition, SpeculativeDecodingMethod, - engine_parameter_definition::ParameterType as EngineParameterType, - engine_parameter_value::Value as EngineParameterValueKind, + EngineArtifact, EngineRelease, HardwareClass, HuggingFaceArtifactSource, InferenceRequestKind, + IntelligenceScore, License, Model, ModelArtifact, ModelConfigurationOption, + ModelEngineConfiguration, ModelInputCapabilities, ModelInputModality, + ModelOptionParameterDefinition, ParameterValue, ParameterValues, SpeculativeDecodingMethod, hugging_face_artifact_source::Content as HuggingFaceContent, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, + parameter_definition::ParameterType as EngineParameterType, + parameter_value::Value as EngineParameterValueKind, }; use super::common::lower_hex; @@ -31,6 +31,7 @@ use crate::{ }, selector::{SelectorRelation, selector_relation}, shared_parameters::profile_may_default, + typed_parameters::default_value, validation::{EngineDeclarationValidator, configuration_engine_release}, }; @@ -891,7 +892,7 @@ fn validate_profile_option_defaults( /// Validates a complete set of engine parameter values against the engine schema. pub fn validate_parameter_values( - values: &EngineParameterValues, + values: &ParameterValues, engine: &EngineRelease, profile_id: &str, errors: &mut Vec, @@ -910,7 +911,7 @@ pub fn validate_parameter_values( /// Validates supplied engine parameter values, which may omit parameters that sizing derives. /// Completeness is checked once derivations are known. pub fn validate_supplied_parameter_values( - values: &EngineParameterValues, + values: &ParameterValues, engine: &EngineRelease, profile_id: &str, errors: &mut Vec, @@ -962,9 +963,9 @@ pub fn validate_supplied_parameter_values( /// Overlays defaults on supplied engine parameter values, per parameter: the supplied values /// keep their order, followed by each default whose parameter they leave out. pub fn overlay_parameter_defaults( - values: &EngineParameterValues, - defaults: &EngineParameterValues, -) -> EngineParameterValues { + values: &ParameterValues, + defaults: &ParameterValues, +) -> ParameterValues { let mut overlaid = values.clone(); overlaid.values.extend( defaults @@ -982,30 +983,24 @@ pub fn overlay_parameter_defaults( } /// Engine defaults the release declares for its parameters, in schema order. -pub(super) fn engine_default_values(engine: &EngineRelease) -> EngineParameterValues { - EngineParameterValues { +pub(super) fn engine_default_values(engine: &EngineRelease) -> ParameterValues { + ParameterValues { values: engine .parameter_schema .iter() .flat_map(|schema| &schema.parameters) - .filter_map(|definition| match definition.parameter_type.as_ref() { - Some(EngineParameterType::UnsignedInteger(range)) => { - range.default_value.map(|default| EngineParameterValue { - parameter_id: definition.parameter_id.clone(), - value: Some(EngineParameterValueKind::UnsignedInteger(default)), - }) - } - _ => None, + .filter_map(|definition| { + default_value(definition).map(|default| ParameterValue { + parameter_id: definition.parameter_id.clone(), + value: Some(default), + }) }) .collect(), } } /// Engine schema parameter ids without a supplied value, in schema order. -pub fn missing_parameter_ids( - values: &EngineParameterValues, - engine: &EngineRelease, -) -> Vec { +pub fn missing_parameter_ids(values: &ParameterValues, engine: &EngineRelease) -> Vec { engine .parameter_schema .as_ref() @@ -1133,23 +1128,73 @@ mod tests { use std::collections::{BTreeMap, BTreeSet}; use dotcore_proto::dotcore::catalog::v1::{ - BooleanModelOptionParameterSchema, EngineArtifact, EngineArtifactReference, - EngineParameterValues, EngineRelease, HardwareClass, InferenceRequestKind, - KvCachePrecisionModelOption, Model, ModelArtifactBinding, ModelConfigurationOption, - ModelEngineConfiguration, ModelOption, ModelOptionParameterDefinition, - ModelOptionParameterValue, ModelOptionValues, ModelProfile, OciPlatform, Selector, - SpeculativeDecodingMethod, SpeculativeDecodingModelOption, - StringEnumModelOptionParameterSchema, UnsignedIntegerModelOptionParameterSchema, - model_option, model_option_parameter_definition::ParameterType, - model_option_parameter_value::Value, + BooleanModelOptionParameterSchema, EngineArtifact, EngineArtifactReference, EngineRelease, + HardwareClass, InferenceRequestKind, KvCachePrecisionModelOption, Model, + ModelArtifactBinding, ModelConfigurationOption, ModelEngineConfiguration, ModelOption, + ModelOptionParameterDefinition, ModelOptionParameterValue, ModelOptionValues, ModelProfile, + OciPlatform, ParameterValues, Selector, SpeculativeDecodingMethod, + SpeculativeDecodingModelOption, StringEnumModelOptionParameterSchema, + UnsignedIntegerModelOptionParameterSchema, model_option, + model_option_parameter_definition::ParameterType, model_option_parameter_value::Value, }; use super::{ - overlapping_artifacts, valid_request_kinds, validate_class_artifact_coverage, - validate_configuration_options, validate_model_options, validate_profiles, + engine_default_values, overlapping_artifacts, valid_request_kinds, + validate_class_artifact_coverage, validate_configuration_options, validate_model_options, + validate_profiles, }; use crate::test_support::vendor_hardware_class; + #[test] + fn engine_defaults_cover_every_parameter_declaring_one_booleans_included() { + use dotcore_proto::dotcore::catalog::v1::{ + BooleanParameterSchema, EngineParameterSchema, ParameterDefinition, ParameterValue, + UnsignedIntegerParameterSchema, parameter_definition::ParameterType as Type, + parameter_value::Value as ParameterValueKind, + }; + + let definition = |parameter_id: &str, parameter_type| ParameterDefinition { + parameter_id: parameter_id.to_owned(), + parameter_type: Some(parameter_type), + ..Default::default() + }; + let unsigned = |default_value| { + Type::UnsignedInteger(UnsignedIntegerParameterSchema { + minimum: 0, + maximum: 64, + unit: "requests".to_owned(), + default_value, + }) + }; + let boolean = |default_value| Type::Boolean(BooleanParameterSchema { default_value }); + let engine = EngineRelease { + parameter_schema: Some(EngineParameterSchema { + schema_id: "fixture".to_owned(), + parameters: vec![ + definition("parallel-requests", unsigned(Some(4))), + definition("flash-attention", boolean(Some(false))), + definition("cache-mib", unsigned(None)), + definition("mlock", boolean(None)), + ], + }), + ..Default::default() + }; + let value = |parameter_id: &str, value| ParameterValue { + parameter_id: parameter_id.to_owned(), + value: Some(value), + }; + + assert_eq!( + engine_default_values(&engine), + ParameterValues { + values: vec![ + value("parallel-requests", ParameterValueKind::UnsignedInteger(4)), + value("flash-attention", ParameterValueKind::Boolean(false)), + ], + } + ); + } + #[test] fn request_kinds_must_be_non_empty_known_and_unique() { let chat = InferenceRequestKind::Chat as i32; @@ -1601,7 +1646,7 @@ mod tests { profile_id: "balanced".to_owned(), configuration_id: "local".to_owned(), default_model_artifact_binding_id: "weights".to_owned(), - engine_parameter_defaults: Some(EngineParameterValues::default()), + engine_parameter_defaults: Some(ParameterValues::default()), ..Default::default() }], ..Default::default() diff --git a/backend/cli/src/workload/mod.rs b/backend/cli/src/workload/mod.rs index b4a5f87d..1a3c3187 100644 --- a/backend/cli/src/workload/mod.rs +++ b/backend/cli/src/workload/mod.rs @@ -31,8 +31,8 @@ use dotcore_node_hardware::vram::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValue, EngineParameterValues, ModelOptionParameterValue, ModelOptionValues, - engine_parameter_value, model_option_parameter_value, + ModelOptionParameterValue, ModelOptionValues, ParameterValue, ParameterValues, + model_option_parameter_value, parameter_value, }, telemetry::v1::WorkloadResourceRecord, }; @@ -290,7 +290,7 @@ async fn launch(paths: &RootPathArgs, args: LaunchArgs) -> Result<()> { merge_parameter_overrides( configuration .engine_parameter_values - .get_or_insert_with(EngineParameterValues::default), + .get_or_insert_with(ParameterValues::default), args.engine_parameter .into_iter() .map(parse_parameter) @@ -831,10 +831,7 @@ fn accelerator_device_ids( ] } -fn merge_parameter_overrides( - defaults: &mut EngineParameterValues, - overrides: Vec, -) { +fn merge_parameter_overrides(defaults: &mut ParameterValues, overrides: Vec) { for parameter in overrides { match defaults .values @@ -926,7 +923,7 @@ fn merge_option_overrides( } } -fn parse_parameter(value: String) -> Result { +fn parse_parameter(value: String) -> Result { let (id, typed) = value .split_once('=') .ok_or_else(|| anyhow::anyhow!("engine parameter must be ID=TYPE:VALUE"))?; @@ -934,12 +931,12 @@ fn parse_parameter(value: String) -> Result { .split_once(':') .ok_or_else(|| anyhow::anyhow!("engine parameter must be ID=TYPE:VALUE"))?; let value = match kind { - "unsigned" => engine_parameter_value::Value::UnsignedInteger( + "unsigned" => parameter_value::Value::UnsignedInteger( raw.parse().context("invalid unsigned parameter")?, ), _ => bail!("unsupported engine parameter type: {kind}"), }; - Ok(EngineParameterValue { + Ok(ParameterValue { parameter_id: id.to_owned(), value: Some(value), }) @@ -972,8 +969,8 @@ mod tests { }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValue, EngineParameterValues, ModelOptionParameterValue, - ModelOptionValues, engine_parameter_value, model_option_parameter_value, + ModelOptionParameterValue, ModelOptionValues, ParameterValue, ParameterValues, + model_option_parameter_value, parameter_value, }, telemetry::v1::WorkloadResourceRecord, }; @@ -982,7 +979,7 @@ mod tests { use super::{ CommonArgs, DevSubcommand, HandleArgs, Runtime, Transport, WorkloadAction, accelerator_device_ids, accounting_payload, gpu_memory_payload, handle_root, - merge_option_overrides, merge_parameter_overrides, parse_option_overrides, + merge_option_overrides, merge_parameter_overrides, parse_option_overrides, parse_parameter, record_measurement, resolve_handle, vram_payload, write_log_content_to, }; use crate::RootPathArgs; @@ -1508,16 +1505,16 @@ mod tests { #[test] fn explicit_parameter_values_override_profile_defaults() { - let mut values = EngineParameterValues { + let mut values = ParameterValues { values: vec![unsigned_parameter("total-context", 30_000)], }; merge_parameter_overrides( &mut values, - vec![ - unsigned_parameter("total-context", 8_192), - unsigned_parameter("new-parameter", 7), - ], + ["total-context=unsigned:8192", "new-parameter=unsigned:7"] + .into_iter() + .map(|flag| parse_parameter(flag.to_owned()).expect("engine parameter flag")) + .collect(), ); assert_eq!( @@ -1566,10 +1563,10 @@ mod tests { } } - fn unsigned_parameter(id: &str, value: u64) -> EngineParameterValue { - EngineParameterValue { + fn unsigned_parameter(id: &str, value: u64) -> ParameterValue { + ParameterValue { parameter_id: id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), } } } diff --git a/backend/core/src/application/controller/parameters.rs b/backend/core/src/application/controller/parameters.rs index 21a5017e..ef9b7f7c 100644 --- a/backend/core/src/application/controller/parameters.rs +++ b/backend/core/src/application/controller/parameters.rs @@ -29,7 +29,6 @@ pub(super) fn resolve_parameter_values( let definition = graph .parameters .iter() - .filter_map(|parameter| parameter.definition.as_ref()) .find(|definition| definition.parameter_id == value.parameter_id) .ok_or_else(|| reject(ParameterRejection::Unknown))?; let inner = value @@ -43,11 +42,7 @@ pub(super) fn resolve_parameter_values( graph .parameters .iter() - .map(|parameter| { - let definition = parameter - .definition - .as_ref() - .ok_or_else(|| configuration("Application parameter definition is missing"))?; + .map(|definition| { let value = match supplied .iter() .find(|value| value.parameter_id == definition.parameter_id) diff --git a/backend/core/src/application/controller/test_support.rs b/backend/core/src/application/controller/test_support.rs index e2c76ba4..9d13dab7 100644 --- a/backend/core/src/application/controller/test_support.rs +++ b/backend/core/src/application/controller/test_support.rs @@ -2948,40 +2948,36 @@ pub(super) fn application_with_route_input() -> Application { /// an environment variable of its web service. pub(super) fn application_with_parameters() -> Application { use dotcore_proto::dotcore::catalog::v1::{ - ApplicationParameter, ParameterDefinition, StringEnumParameterSchema, + ParameterDefinition, ParameterVisibility, StringEnumParameterSchema, UnsignedIntegerParameterSchema, parameter_definition::ParameterType, }; let mut application = application(); let graph = application.graph.as_mut().expect("graph"); graph.parameters = vec![ - ApplicationParameter { - definition: Some(ParameterDefinition { - parameter_id: "mode".to_owned(), - display_name: "Mode".to_owned(), - description: String::new(), - parameter_type: Some(ParameterType::StringEnum(StringEnumParameterSchema { - values: vec!["auto".to_owned(), "highvram".to_owned()], - default_value: Some("auto".to_owned()), - })), - }), - advanced: true, + ParameterDefinition { + parameter_id: "mode".to_owned(), + display_name: "Mode".to_owned(), + description: String::new(), + parameter_type: Some(ParameterType::StringEnum(StringEnumParameterSchema { + values: vec!["auto".to_owned(), "highvram".to_owned()], + default_value: Some("auto".to_owned()), + })), + visibility: ParameterVisibility::Advanced as i32, }, - ApplicationParameter { - definition: Some(ParameterDefinition { - parameter_id: "workers".to_owned(), - display_name: "Workers".to_owned(), - description: String::new(), - parameter_type: Some(ParameterType::UnsignedInteger( - UnsignedIntegerParameterSchema { - minimum: 1, - maximum: 8, - unit: String::new(), - default_value: Some(2), - }, - )), - }), - advanced: false, + ParameterDefinition { + parameter_id: "workers".to_owned(), + display_name: "Workers".to_owned(), + description: String::new(), + parameter_type: Some(ParameterType::UnsignedInteger( + UnsignedIntegerParameterSchema { + minimum: 1, + maximum: 8, + unit: String::new(), + default_value: Some(2), + }, + )), + visibility: ParameterVisibility::Basic as i32, }, ]; graph.services[0].configuration_bindings = ["mode", "workers"] diff --git a/backend/core/src/application/repository.rs b/backend/core/src/application/repository.rs index 09818443..8acb5d9e 100644 --- a/backend/core/src/application/repository.rs +++ b/backend/core/src/application/repository.rs @@ -1052,10 +1052,10 @@ mod tests { }, catalog::v1::{ Application, ApplicationConfigurationBinding, ApplicationEndpointProtocol, - ApplicationGraph, ApplicationParameter, ApplicationPrimaryEndpoint, ApplicationService, - ApplicationServicePort, ParameterDefinition, ParameterValue, StringEnumParameterSchema, - application_configuration_binding, parameter_definition::ParameterType, - parameter_value, + ApplicationGraph, ApplicationPrimaryEndpoint, ApplicationService, + ApplicationServicePort, ParameterDefinition, ParameterValue, ParameterVisibility, + StringEnumParameterSchema, application_configuration_binding, + parameter_definition::ParameterType, parameter_value, }, deployment::v1::{ArtifactPreparationPolicy, NodeResolvedLaunchIdentity}, }; @@ -1234,17 +1234,15 @@ mod tests { let mut deployment = valid_deployment(); let snapshot = deployment.snapshot.as_mut().expect("snapshot"); let graph = snapshot.graph.as_mut().expect("graph"); - graph.parameters = vec![ApplicationParameter { - definition: Some(ParameterDefinition { - parameter_id: "mode".to_owned(), - display_name: "Mode".to_owned(), - description: String::new(), - parameter_type: Some(ParameterType::StringEnum(StringEnumParameterSchema { - values: vec!["auto".to_owned(), "highvram".to_owned()], - default_value: Some("auto".to_owned()), - })), - }), - advanced: true, + graph.parameters = vec![ParameterDefinition { + parameter_id: "mode".to_owned(), + display_name: "Mode".to_owned(), + description: String::new(), + parameter_type: Some(ParameterType::StringEnum(StringEnumParameterSchema { + values: vec!["auto".to_owned(), "highvram".to_owned()], + default_value: Some("auto".to_owned()), + })), + visibility: ParameterVisibility::Advanced as i32, }]; graph.services[0].configuration_bindings = vec![ApplicationConfigurationBinding { binding_name: "mode".to_owned(), diff --git a/backend/core/src/development/mod.rs b/backend/core/src/development/mod.rs index 4a41c1d6..0d8c1659 100644 --- a/backend/core/src/development/mod.rs +++ b/backend/core/src/development/mod.rs @@ -36,7 +36,7 @@ use dotcore_domain::{ }; use dotcore_node_hardware::hardware::SystemHardwareSnapshotCollector; use dotcore_proto::dotcore::{ - catalog::v1::{EngineParameterValues, engine_artifact::Kind as EngineArtifactKind}, + catalog::v1::{ParameterValues, engine_artifact::Kind as EngineArtifactKind}, engine::v1::EngineKind, model::v1::{ LocalModelDeploymentConfiguration, PortableModelLaunchPlan, @@ -1386,7 +1386,7 @@ pub struct DevelopmentLaunchFacts { pub model_artifact_id: String, pub auxiliary_artifact_ids: Vec, pub resolved_options: Vec, - pub engine_parameter_values: EngineParameterValues, + pub engine_parameter_values: ParameterValues, pub engine_release_id: String, pub engine_artifact_id: String, pub engine_version: String, diff --git a/backend/core/src/model/engine/declaration.rs b/backend/core/src/model/engine/declaration.rs index d3663081..10d53e60 100644 --- a/backend/core/src/model/engine/declaration.rs +++ b/backend/core/src/model/engine/declaration.rs @@ -6,8 +6,8 @@ use dotcore_catalog::{ }; use dotcore_domain::Accelerator; use dotcore_proto::dotcore::catalog::v1::{ - EngineParameterValues, EngineRelease, HardwareClass, InferenceRequestKind, Model, - ModelEngineConfiguration, model_option, + EngineRelease, HardwareClass, InferenceRequestKind, Model, ModelEngineConfiguration, + ParameterValues, model_option, }; use super::definition::{definition, unsigned_parameter_maximum}; @@ -67,7 +67,7 @@ impl EngineDeclarationValidator for EngineFacade { model: &Model, configuration: &ModelEngineConfiguration, engine: &EngineRelease, - ) -> EngineParameterValues { + ) -> ParameterValues { definition(engine.engine_kind) .map(|definition| definition.parameter_defaults(model, configuration)) .unwrap_or_default() @@ -185,9 +185,9 @@ mod tests { }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterDefinition, EngineParameterSchema, EngineRelease, InferenceRequestKind, - Model, ModelEngineConfiguration, UnsignedIntegerEngineParameterSchema, - engine_parameter_definition::ParameterType, + EngineParameterSchema, EngineRelease, InferenceRequestKind, Model, + ModelEngineConfiguration, ParameterDefinition, UnsignedIntegerParameterSchema, + parameter_definition::ParameterType, }, engine::v1::{EngineKind, EngineModelConfiguration}, }; @@ -202,10 +202,10 @@ mod tests { }; let release = EngineRelease { parameter_schema: Some(EngineParameterSchema { - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: CONTEXT_PER_REQUEST_PARAMETER_ID.to_owned(), parameter_type: Some(ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1024, maximum: 131_072, unit: "tokens".to_owned(), diff --git a/backend/core/src/model/engine/definition.rs b/backend/core/src/model/engine/definition.rs index 823f4028..17416e75 100644 --- a/backend/core/src/model/engine/definition.rs +++ b/backend/core/src/model/engine/definition.rs @@ -13,9 +13,9 @@ use dotcore_catalog::shared_parameters; use dotcore_domain::WorkloadArtifactKind; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterSchema, EngineParameterValue, EngineParameterValues, EngineRelease, - HardwareClass, InferenceRequestKind, Model, ModelArtifactBinding, ModelEngineConfiguration, - ModelOptionValues, engine_parameter_definition, engine_parameter_value, + EngineParameterSchema, EngineRelease, HardwareClass, InferenceRequestKind, Model, + ModelArtifactBinding, ModelEngineConfiguration, ModelOptionValues, ParameterValue, + ParameterValues, parameter_definition, parameter_value, }, engine::v1::{EngineKind, ResolvedEngineModelState}, model::v1::{PortableModelLaunchPlan, ResolvedLocalModelDeploymentSnapshot}, @@ -74,8 +74,8 @@ pub(crate) trait EngineDefinition: Send + Sync { &self, _model: &Model, _configuration: &ModelEngineConfiguration, - ) -> EngineParameterValues { - EngineParameterValues::default() + ) -> ParameterValues { + ParameterValues::default() } /// Context per request for values that leave it out, which counts as derived. By default it is @@ -84,9 +84,9 @@ pub(crate) trait EngineDefinition: Send + Sync { fn filled_context_per_request( &self, schema: &EngineParameterSchema, - values: &EngineParameterValues, + values: &ParameterValues, maximum_context_tokens: u32, - ) -> Option { + ) -> Option { shared_parameters::filled_context_per_request(schema, values, maximum_context_tokens) } @@ -97,7 +97,7 @@ pub(crate) trait EngineDefinition: Send + Sync { &self, _model: &Model, _configuration: &ModelEngineConfiguration, - _values: &EngineParameterValues, + _values: &ParameterValues, ) -> anyhow::Result<()> { Ok(()) } @@ -195,7 +195,7 @@ pub(crate) fn definition(kind: i32) -> Option<&'static dyn EngineDefinition> { /// Returns the unsigned value of one engine parameter, or none when it is absent or not unsigned. pub(crate) fn unsigned_parameter_value( - values: &EngineParameterValues, + values: &ParameterValues, parameter_id: &str, ) -> Option { values @@ -203,7 +203,7 @@ pub(crate) fn unsigned_parameter_value( .iter() .find(|value| value.parameter_id == parameter_id) .and_then(|value| match value.value { - Some(engine_parameter_value::Value::UnsignedInteger(value)) => Some(value), + Some(parameter_value::Value::UnsignedInteger(value)) => Some(value), _ => None, }) } @@ -229,7 +229,7 @@ pub(crate) fn unsigned_parameter_range( .iter() .find(|definition| definition.parameter_id == parameter_id) .and_then(|definition| match definition.parameter_type.as_ref() { - Some(engine_parameter_definition::ParameterType::UnsignedInteger(range)) => { + Some(parameter_definition::ParameterType::UnsignedInteger(range)) => { Some(range.minimum..=range.maximum) } _ => None, diff --git a/backend/core/src/model/engine/llama_cpp/declaration.rs b/backend/core/src/model/engine/llama_cpp/declaration.rs index 8cfae5a8..5c3e1a87 100644 --- a/backend/core/src/model/engine/llama_cpp/declaration.rs +++ b/backend/core/src/model/engine/llama_cpp/declaration.rs @@ -12,13 +12,12 @@ use dotcore_catalog::{ use dotcore_domain::Accelerator; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterDefinition, EngineParameterValue, EngineParameterValues, EngineRelease, - HardwareClass, Model, ModelConfigurationOption, ModelEngineConfiguration, - ModelInputModality, SpeculativeDecodingMethod, engine_parameter_definition::ParameterType, - engine_parameter_value::Value as EngineParameterValueKind, - hugging_face_artifact_source::Content as HuggingFaceContent, + EngineRelease, HardwareClass, Model, ModelConfigurationOption, ModelEngineConfiguration, + ModelInputModality, ParameterDefinition, ParameterValue, ParameterValues, + SpeculativeDecodingMethod, hugging_face_artifact_source::Content as HuggingFaceContent, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, + parameter_definition::ParameterType, parameter_value::Value as EngineParameterValueKind, }, engine::{ llama_cpp::v1::{ @@ -130,12 +129,12 @@ pub(crate) fn validate_hardware_support( pub(crate) fn parameter_defaults( model: &Model, configuration: &ModelEngineConfiguration, -) -> EngineParameterValues { +) -> ParameterValues { if !uses_single_micro_batch(configuration) { - return EngineParameterValues::default(); + return ParameterValues::default(); } - EngineParameterValues { - values: vec![EngineParameterValue { + ParameterValues { + values: vec![ParameterValue { parameter_id: TOTAL_CONTEXT_PARAMETER_ID.to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(u64::from( maximum_context_tokens(model, configuration), @@ -176,7 +175,7 @@ pub(crate) fn validate_total_context_default( pub(crate) fn validate_parameter_values( model: &Model, configuration: &ModelEngineConfiguration, - values: &EngineParameterValues, + values: &ParameterValues, ) -> anyhow::Result<()> { if !uses_single_micro_batch(configuration) { return Ok(()); @@ -661,7 +660,7 @@ pub(crate) enum LlamaCppSamplingError { /// Accepts a shared parameter bounded by llama.cpp's own limit. The bound on the total context is /// high enough that a large pool exceeds memory before it exceeds the bound. -fn is_bounded(definition: &EngineParameterDefinition, parameter_id: &str, maximum: u64) -> bool { +fn is_bounded(definition: &ParameterDefinition, parameter_id: &str, maximum: u64) -> bool { definition.parameter_id == parameter_id && matches!( definition.parameter_type.as_ref(), @@ -669,7 +668,7 @@ fn is_bounded(definition: &EngineParameterDefinition, parameter_id: &str, maximu ) } -fn is_prompt_cache_memory(definition: &EngineParameterDefinition) -> bool { +fn is_prompt_cache_memory(definition: &ParameterDefinition) -> bool { definition.parameter_id == PROMPT_CACHE_MEMORY_PARAMETER_ID && definition.display_name == "Prompt cache memory" && matches!( @@ -686,12 +685,12 @@ mod tests { use dotcore_catalog::{Catalog, OciArtifactPolicy, test_support::vendor_hardware_class}; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterDefinition, HuggingFaceArtifactSource, HuggingFaceFileArtifact, - HuggingFaceSnapshotArtifact, HuggingFaceSnapshotFile, Model, ModelArtifact, - ModelArtifactBinding, ModelAuxiliaryArtifact, ModelConfigurationOption, - ModelEngineConfiguration, SpeculativeDecodingMethod, SpeculativeDecodingModelOption, - VisionModelOption, engine_parameter_definition::ParameterType, - hugging_face_artifact_source::Content as HuggingFaceContent, model_option, + HuggingFaceArtifactSource, HuggingFaceFileArtifact, HuggingFaceSnapshotArtifact, + HuggingFaceSnapshotFile, Model, ModelArtifact, ModelArtifactBinding, + ModelAuxiliaryArtifact, ModelConfigurationOption, ModelEngineConfiguration, + ParameterDefinition, SpeculativeDecodingMethod, SpeculativeDecodingModelOption, + VisionModelOption, hugging_face_artifact_source::Content as HuggingFaceContent, + model_option, parameter_definition::ParameterType, }, engine::{ llama_cpp::v1::{ @@ -837,7 +836,7 @@ mod tests { .find(|release| release.engine_kind == EngineKind::LlamaCpp as i32) .expect("llama.cpp release"); assert!(validate_engine_release(&release).is_empty()); - let rejection = |edit: &dyn Fn(&mut Vec)| { + let rejection = |edit: &dyn Fn(&mut Vec)| { let mut release = release.clone(); edit( &mut release @@ -851,7 +850,7 @@ mod tests { .map(ToString::to_string) .collect::>() }; - let maximum = |parameters: &mut Vec, index: usize, value| { + let maximum = |parameters: &mut Vec, index: usize, value| { if let Some(ParameterType::UnsignedInteger(range)) = parameters[index].parameter_type.as_mut() { @@ -1252,9 +1251,7 @@ mod tests { #[test] fn a_single_micro_batch_maximum_context_must_be_a_valid_total_context() { use dotcore_proto::dotcore::{ - catalog::v1::{ - EngineParameterSchema, EngineRelease, UnsignedIntegerEngineParameterSchema, - }, + catalog::v1::{EngineParameterSchema, EngineRelease, UnsignedIntegerParameterSchema}, engine::{ llama_cpp::v1::{LlamaCppFixedModelSettings, LlamaCppModelConfiguration}, v1::EngineModelConfiguration, @@ -1267,10 +1264,10 @@ mod tests { }; let engine = EngineRelease { parameter_schema: Some(EngineParameterSchema { - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: "total-context".to_owned(), parameter_type: Some(ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1024, maximum: 8192, ..Default::default() diff --git a/backend/core/src/model/engine/llama_cpp/mod.rs b/backend/core/src/model/engine/llama_cpp/mod.rs index b8d1272f..ae414be6 100644 --- a/backend/core/src/model/engine/llama_cpp/mod.rs +++ b/backend/core/src/model/engine/llama_cpp/mod.rs @@ -17,8 +17,8 @@ use dotcore_artifact::PreparedModelArtifacts; use dotcore_domain::WorkloadArtifactKind; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValues, EngineRelease, HardwareClass, InferenceRequestKind, Model, - ModelArtifactBinding, ModelEngineConfiguration, ModelOptionValues, + EngineRelease, HardwareClass, InferenceRequestKind, Model, ModelArtifactBinding, + ModelEngineConfiguration, ModelOptionValues, ParameterValues, }, engine::v1::{EngineKind, ResolvedEngineModelState}, model::v1::{PortableModelLaunchPlan, ResolvedLocalModelDeploymentSnapshot}, @@ -82,7 +82,7 @@ impl EngineDefinition for LlamaCpp { &self, model: &Model, configuration: &ModelEngineConfiguration, - ) -> EngineParameterValues { + ) -> ParameterValues { declaration::parameter_defaults(model, configuration) } @@ -90,7 +90,7 @@ impl EngineDefinition for LlamaCpp { &self, model: &Model, configuration: &ModelEngineConfiguration, - values: &EngineParameterValues, + values: &ParameterValues, ) -> anyhow::Result<()> { declaration::validate_parameter_values(model, configuration, values) } diff --git a/backend/core/src/model/engine/llama_cpp/plan.rs b/backend/core/src/model/engine/llama_cpp/plan.rs index 213137f1..9bcbc7c6 100644 --- a/backend/core/src/model/engine/llama_cpp/plan.rs +++ b/backend/core/src/model/engine/llama_cpp/plan.rs @@ -14,7 +14,7 @@ use dotcore_catalog::{ }; use dotcore_proto::{ dotcore::{ - catalog::v1::{ModelOptionValues, engine_parameter_value::Value as EngineParameterValue}, + catalog::v1::{ModelOptionValues, parameter_value::Value as EngineParameterValueKind}, engine::{ llama_cpp::v1::{ LlamaCppFixedModelSettings, LlamaCppResolvedModelState, LlamaCppSpeculativeMethod, @@ -431,7 +431,7 @@ fn unsigned_parameter( .find(|value| value.parameter_id == parameter_id) }) .and_then(|value| match value.value.as_ref() { - Some(EngineParameterValue::UnsignedInteger(value)) => Some(*value), + Some(EngineParameterValueKind::UnsignedInteger(value)) => Some(*value), _ => None, }) } @@ -628,7 +628,7 @@ pub(crate) enum LlamaCppPlanError { #[cfg(test)] mod tests { use dotcore_proto::dotcore::catalog::v1::{ - EngineParameterDefinition, EngineParameterValue as EngineParameterValueMessage, + ParameterDefinition, ParameterValue as EngineParameterValueMessage, ParameterVisibility, }; use super::*; @@ -910,7 +910,7 @@ mod tests { .retain(|value| value.parameter_id != PROMPT_CACHE_MEMORY_PARAMETER_ID); values.values.push(EngineParameterValueMessage { parameter_id: PROMPT_CACHE_MEMORY_PARAMETER_ID.to_owned(), - value: Some(EngineParameterValue::UnsignedInteger(mib)), + value: Some(EngineParameterValueKind::UnsignedInteger(mib)), }); assert_eq!( @@ -951,11 +951,11 @@ mod tests { .as_mut() .expect("engine parameter schema") .parameters - .push(EngineParameterDefinition { + .push(ParameterDefinition { parameter_id: PROMPT_CACHE_MEMORY_PARAMETER_ID.to_owned(), display_name: "Prompt cache memory".to_owned(), parameter_type: None, - exposed: true, + visibility: ParameterVisibility::Advanced as i32, description: String::new(), }); for token in tokens { @@ -1753,7 +1753,7 @@ mod tests { .retain(|value| value.parameter_id != parameter_id); values.values.push(EngineParameterValueMessage { parameter_id: parameter_id.to_owned(), - value: Some(EngineParameterValue::UnsignedInteger(value)), + value: Some(EngineParameterValueKind::UnsignedInteger(value)), }); } diff --git a/backend/core/src/model/engine/mod.rs b/backend/core/src/model/engine/mod.rs index c7cac54a..a13a6143 100644 --- a/backend/core/src/model/engine/mod.rs +++ b/backend/core/src/model/engine/mod.rs @@ -54,9 +54,9 @@ pub(crate) fn engine_artifact_kinds(kind: i32) -> &'static [dotcore_domain::Work pub(crate) fn filled_context_per_request( kind: i32, schema: &dotcore_proto::dotcore::catalog::v1::EngineParameterSchema, - values: &dotcore_proto::dotcore::catalog::v1::EngineParameterValues, + values: &dotcore_proto::dotcore::catalog::v1::ParameterValues, maximum_context_tokens: u32, -) -> Option { +) -> Option { match definition::definition(kind) { Some(engine) => engine.filled_context_per_request(schema, values, maximum_context_tokens), None => dotcore_catalog::shared_parameters::filled_context_per_request( @@ -74,7 +74,7 @@ pub(crate) fn validate_parameter_values( kind: i32, model: &dotcore_proto::dotcore::catalog::v1::Model, configuration: &dotcore_proto::dotcore::catalog::v1::ModelEngineConfiguration, - values: &dotcore_proto::dotcore::catalog::v1::EngineParameterValues, + values: &dotcore_proto::dotcore::catalog::v1::ParameterValues, ) -> anyhow::Result<()> { validate_context_within_total(values)?; definition::definition(kind).map_or(Ok(()), |engine| { @@ -85,7 +85,7 @@ pub(crate) fn validate_parameter_values( /// Rejects a context per request above the total context every request shares, since no request /// could use it. fn validate_context_within_total( - values: &dotcore_proto::dotcore::catalog::v1::EngineParameterValues, + values: &dotcore_proto::dotcore::catalog::v1::ParameterValues, ) -> anyhow::Result<()> { use dotcore_catalog::shared_parameters::{ CONTEXT_PER_REQUEST_PARAMETER_ID, TOTAL_CONTEXT_PARAMETER_ID, diff --git a/backend/core/src/model/engine/ninfer/declaration.rs b/backend/core/src/model/engine/ninfer/declaration.rs index 797e4923..bb6e3f63 100644 --- a/backend/core/src/model/engine/ninfer/declaration.rs +++ b/backend/core/src/model/engine/ninfer/declaration.rs @@ -19,12 +19,12 @@ use dotcore_catalog::{ use dotcore_domain::Accelerator; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValues, EngineRelease, HardwareClass, Model, ModelConfigurationOption, - ModelEngineConfiguration, ModelInputModality, ModelParallelShape, - SpeculativeDecodingMethod, engine_parameter_definition::ParameterType, + EngineRelease, HardwareClass, Model, ModelConfigurationOption, ModelEngineConfiguration, + ModelInputModality, ModelParallelShape, ParameterValues, SpeculativeDecodingMethod, hugging_face_artifact_source::Content as HuggingFaceContent, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, + parameter_definition::ParameterType, }, engine::{ ninfer::v1::{ @@ -52,7 +52,7 @@ const MODEL_FILE_EXTENSION: &str = ".ninfer"; /// Rejects a total context ninfer refuses at startup: above what the parallel requests use at /// their full context per request, so part of it could never hold a request. -pub(crate) fn validate_parameter_values(values: &EngineParameterValues) -> anyhow::Result<()> { +pub(crate) fn validate_parameter_values(values: &ParameterValues) -> anyhow::Result<()> { let (Some(total_context), Some(context_per_request), Some(parallel_requests)) = ( unsigned_parameter_value(values, TOTAL_CONTEXT_PARAMETER_ID), unsigned_parameter_value(values, CONTEXT_PER_REQUEST_PARAMETER_ID), @@ -460,9 +460,9 @@ mod tests { use dotcore_domain::ExecutionPlatform; use dotcore_proto::dotcore::{ catalog::v1::{ - BooleanEngineParameterSchema, EngineParameterDefinition, HuggingFaceArtifactSource, - HuggingFaceFileArtifact, HuggingFaceSnapshotArtifact, SpeculativeDecodingModelOption, - UnsignedIntegerEngineParameterSchema, + BooleanParameterSchema, HuggingFaceArtifactSource, HuggingFaceFileArtifact, + HuggingFaceSnapshotArtifact, ParameterDefinition, SpeculativeDecodingModelOption, + UnsignedIntegerParameterSchema, }, model::v1::{ LocalModelDeploymentConfiguration, ResolvedLocalModelDeploymentSnapshot, @@ -506,7 +506,7 @@ mod tests { .as_mut() .expect("schema") .parameters[3] - .parameter_type = Some(ParameterType::Boolean(BooleanEngineParameterSchema {})); + .parameter_type = Some(ParameterType::Boolean(BooleanParameterSchema::default())); assert_eq!( messages(validate_engine_release(&boolean)), ["ninfer engine release requires non-empty unsigned-integer parameter definitions"] @@ -578,7 +578,7 @@ mod tests { .as_mut() .expect("schema") .parameters - .push(EngineParameterDefinition { + .push(ParameterDefinition { parameter_id: "prefill-chunk".to_owned(), parameter_type: Some(unsigned(128, 8192, "tokens")), ..Default::default() @@ -996,10 +996,10 @@ version: "1" parameterSchema: schemaId: "fixture-ninfer-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, description: "total-context", unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, description: "context-per-request", unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, description: "parallel-requests", unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "4" } } - - { parameterId: "host-context-mib", displayName: "Host context memory", exposed: true, description: "host-context-mib", unsignedInteger: { minimum: "0", maximum: "1048576", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", description: "total-context", unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", description: "context-per-request", unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", description: "parallel-requests", unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "4" } } + - { parameterId: "host-context-mib", displayName: "Host context memory", visibility: "PARAMETER_VISIBILITY_ADVANCED", description: "host-context-mib", unsignedInteger: { minimum: "0", maximum: "1048576", unit: "MiB" } } artifacts: - artifactId: "linux-amd64-cuda" oci: @@ -1192,7 +1192,7 @@ profiles: } fn unsigned(minimum: u64, maximum: u64, unit: &str) -> ParameterType { - ParameterType::UnsignedInteger(UnsignedIntegerEngineParameterSchema { + ParameterType::UnsignedInteger(UnsignedIntegerParameterSchema { minimum, maximum, unit: unit.to_owned(), diff --git a/backend/core/src/model/engine/ninfer/mod.rs b/backend/core/src/model/engine/ninfer/mod.rs index 0011bf23..4bdaa16d 100644 --- a/backend/core/src/model/engine/ninfer/mod.rs +++ b/backend/core/src/model/engine/ninfer/mod.rs @@ -16,8 +16,8 @@ use dotcore_artifact::PreparedModelArtifacts; use dotcore_domain::WorkloadArtifactKind; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValues, EngineRelease, HardwareClass, InferenceRequestKind, Model, - ModelArtifactBinding, ModelEngineConfiguration, ModelOptionValues, + EngineRelease, HardwareClass, InferenceRequestKind, Model, ModelArtifactBinding, + ModelEngineConfiguration, ModelOptionValues, ParameterValues, }, engine::v1::{EngineKind, ResolvedEngineModelState}, model::v1::{PortableModelLaunchPlan, ResolvedLocalModelDeploymentSnapshot}, @@ -78,7 +78,7 @@ impl EngineDefinition for Ninfer { &self, _model: &Model, _configuration: &ModelEngineConfiguration, - values: &EngineParameterValues, + values: &ParameterValues, ) -> anyhow::Result<()> { declaration::validate_parameter_values(values) } diff --git a/backend/core/src/model/engine/ninfer/plan.rs b/backend/core/src/model/engine/ninfer/plan.rs index bd8f2064..9ddb9d36 100644 --- a/backend/core/src/model/engine/ninfer/plan.rs +++ b/backend/core/src/model/engine/ninfer/plan.rs @@ -16,7 +16,7 @@ use dotcore_catalog::{ }, }; use dotcore_proto::dotcore::{ - catalog::v1::{ModelOptionValues, engine_parameter_value::Value as EngineParameterValue}, + catalog::v1::{ModelOptionValues, parameter_value::Value as EngineParameterValueKind}, engine::{ ninfer::v1::{ NinferFixedModelSettings, NinferKvCacheDataType, NinferResolvedModelState, @@ -367,7 +367,7 @@ fn parameter( .find(|value| value.parameter_id == parameter_id) }) .and_then(|value| match value.value.as_ref() { - Some(EngineParameterValue::UnsignedInteger(value)) => Some(*value), + Some(EngineParameterValueKind::UnsignedInteger(value)) => Some(*value), _ => None, }) .ok_or_else(|| NinferPlanError::ParameterNotConfigured(parameter_id.to_owned())) @@ -711,7 +711,7 @@ mod tests { .iter_mut() .find(|value| value.parameter_id == parameter_id) .expect("parameter") - .value = Some(EngineParameterValue::UnsignedInteger(0)); + .value = Some(EngineParameterValueKind::UnsignedInteger(0)); assert_eq!( translate(&local).expect_err("zero parameter").to_string(), diff --git a/backend/core/src/model/engine/strata/declaration.rs b/backend/core/src/model/engine/strata/declaration.rs index c338e096..497de4c1 100644 --- a/backend/core/src/model/engine/strata/declaration.rs +++ b/backend/core/src/model/engine/strata/declaration.rs @@ -16,12 +16,11 @@ use dotcore_catalog::shared_parameters::{ use dotcore_domain::Accelerator; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterSchema, EngineParameterValue, EngineParameterValues, EngineRelease, - HardwareClass, HuggingFaceArtifactSource, Model, ModelEngineConfiguration, - ModelInputModality, ModelParallelShape, StorageScope, - engine_parameter_definition::ParameterType, - engine_parameter_value::Value as EngineParameterValueKind, + EngineParameterSchema, EngineRelease, HardwareClass, HuggingFaceArtifactSource, Model, + ModelEngineConfiguration, ModelInputModality, ModelParallelShape, ParameterValue, + ParameterValues, StorageScope, hugging_face_artifact_source::Content as HuggingFaceContent, + parameter_definition::ParameterType, parameter_value::Value as EngineParameterValueKind, }, engine::{ strata::v1::{ @@ -54,9 +53,9 @@ const READY_PACK_FILES: [&str; 2] = ["native_experts.txt", "tokenizer/vocab.json /// for each of them. Returns none when the shared rule would fill nothing. pub(crate) fn filled_context_per_request( schema: &EngineParameterSchema, - values: &EngineParameterValues, + values: &ParameterValues, maximum_context_tokens: u32, -) -> Option { +) -> Option { // The shared rule with no maximum yields the total context, or none when it fills nothing. let total_context = shared_parameters::filled_context_per_request(schema, values, u32::MAX) .and_then(|filled| match filled.value { @@ -66,7 +65,7 @@ pub(crate) fn filled_context_per_request( let parallel_requests = unsigned_parameter_value(values, PARALLEL_REQUESTS_PARAMETER_ID) .unwrap_or(1) .max(1); - Some(EngineParameterValue { + Some(ParameterValue { parameter_id: CONTEXT_PER_REQUEST_PARAMETER_ID.to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger( (total_context / parallel_requests).min(u64::from(maximum_context_tokens)), @@ -80,7 +79,7 @@ pub(crate) fn filled_context_per_request( pub(crate) fn validate_parameter_values( model: &Model, configuration: &ModelEngineConfiguration, - values: &EngineParameterValues, + values: &ParameterValues, ) -> anyhow::Result<()> { let (Some(total_context), Some(context_per_request), Some(parallel_requests)) = ( unsigned_parameter_value(values, TOTAL_CONTEXT_PARAMETER_ID), @@ -454,9 +453,9 @@ mod tests { use dotcore_domain::ExecutionPlatform; use dotcore_proto::dotcore::{ catalog::v1::{ - BooleanEngineParameterSchema, EngineParameterDefinition, HuggingFaceArtifactSource, - HuggingFaceFileArtifact, ModelConfigurationOption, ModelImageInputCapacity, - UnsignedIntegerEngineParameterSchema, + BooleanParameterSchema, HuggingFaceArtifactSource, HuggingFaceFileArtifact, + ModelConfigurationOption, ModelImageInputCapacity, ParameterDefinition, + UnsignedIntegerParameterSchema, }, model::v1::{ LocalModelDeploymentConfiguration, ResolvedLocalModelDeploymentSnapshot, @@ -514,7 +513,7 @@ mod tests { let mut boolean = release(); parameter(&mut boolean, EXPERT_VRAM_MIB_PARAMETER_ID).parameter_type = - Some(ParameterType::Boolean(BooleanEngineParameterSchema {})); + Some(ParameterType::Boolean(BooleanParameterSchema::default())); assert_eq!( messages(validate_engine_release(&boolean)), ["Strata engine release requires non-empty unsigned-integer parameter definitions"] @@ -609,7 +608,7 @@ mod tests { .as_mut() .expect("schema") .parameters - .push(EngineParameterDefinition { + .push(ParameterDefinition { parameter_id: "kv-bits".to_owned(), parameter_type: Some(unsigned(4, 16, "bits")), ..Default::default() @@ -1015,10 +1014,10 @@ version: "1" parameterSchema: schemaId: "fixture-strata-v1" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, description: "total-context", unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, description: "context-per-request", unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, description: "parallel-requests", unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "1" } } - - { parameterId: "expert-vram-mib", displayName: "Expert accelerator memory", exposed: true, description: "expert-vram-mib", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", description: "total-context", unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", description: "context-per-request", unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", description: "parallel-requests", unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "1" } } + - { parameterId: "expert-vram-mib", displayName: "Expert accelerator memory", visibility: "PARAMETER_VISIBILITY_ADVANCED", description: "expert-vram-mib", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "MiB" } } storageBindings: - { bindingName: "data", mountPath: "/data", kind: "STORAGE_KIND_CACHE", scope: "STORAGE_SCOPE_DEPLOYMENT" } artifacts: @@ -1184,7 +1183,7 @@ profiles: fn parameter<'a>( release: &'a mut EngineRelease, parameter_id: &str, - ) -> &'a mut EngineParameterDefinition { + ) -> &'a mut ParameterDefinition { release .parameter_schema .as_mut() @@ -1196,7 +1195,7 @@ profiles: } fn unsigned(minimum: u64, maximum: u64, unit: &str) -> ParameterType { - ParameterType::UnsignedInteger(UnsignedIntegerEngineParameterSchema { + ParameterType::UnsignedInteger(UnsignedIntegerParameterSchema { minimum, maximum, unit: unit.to_owned(), diff --git a/backend/core/src/model/engine/strata/mod.rs b/backend/core/src/model/engine/strata/mod.rs index 73c05eb5..662812ed 100644 --- a/backend/core/src/model/engine/strata/mod.rs +++ b/backend/core/src/model/engine/strata/mod.rs @@ -20,9 +20,9 @@ use dotcore_artifact::PreparedModelArtifacts; use dotcore_domain::WorkloadArtifactKind; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterSchema, EngineParameterValue, EngineParameterValues, EngineRelease, - HardwareClass, InferenceRequestKind, Model, ModelArtifactBinding, ModelEngineConfiguration, - ModelOptionValues, + EngineParameterSchema, EngineRelease, HardwareClass, InferenceRequestKind, Model, + ModelArtifactBinding, ModelEngineConfiguration, ModelOptionValues, ParameterValue, + ParameterValues, }, engine::{ strata::v1::{StrataFixedModelSettings, strata_fixed_model_settings::ModelFiles}, @@ -91,9 +91,9 @@ impl EngineDefinition for Strata { fn filled_context_per_request( &self, schema: &EngineParameterSchema, - values: &EngineParameterValues, + values: &ParameterValues, maximum_context_tokens: u32, - ) -> Option { + ) -> Option { declaration::filled_context_per_request(schema, values, maximum_context_tokens) } @@ -101,7 +101,7 @@ impl EngineDefinition for Strata { &self, model: &Model, configuration: &ModelEngineConfiguration, - values: &EngineParameterValues, + values: &ParameterValues, ) -> anyhow::Result<()> { declaration::validate_parameter_values(model, configuration, values) } diff --git a/backend/core/src/model/engine/strata/plan.rs b/backend/core/src/model/engine/strata/plan.rs index 5b811693..450b4479 100644 --- a/backend/core/src/model/engine/strata/plan.rs +++ b/backend/core/src/model/engine/strata/plan.rs @@ -12,7 +12,7 @@ use dotcore_catalog::shared_parameters::{ CONTEXT_PER_REQUEST_PARAMETER_ID, PARALLEL_REQUESTS_PARAMETER_ID, }; use dotcore_proto::dotcore::{ - catalog::v1::engine_parameter_value::Value as EngineParameterValue, + catalog::v1::parameter_value::Value as EngineParameterValueKind, engine::{ strata::v1::{StrataResolvedModelState, strata_fixed_model_settings::ModelFiles}, v1::{EngineKind, resolved_engine_model_state::State}, @@ -213,7 +213,7 @@ fn positive_parameter( .find(|value| value.parameter_id == parameter_id) }) .and_then(|value| match value.value.as_ref() { - Some(EngineParameterValue::UnsignedInteger(value)) => Some(*value), + Some(EngineParameterValueKind::UnsignedInteger(value)) => Some(*value), _ => None, }) .filter(|value| *value > 0) @@ -591,7 +591,7 @@ mod tests { .iter_mut() .find(|value| value.parameter_id == parameter_id) .expect("parameter") - .value = Some(EngineParameterValue::UnsignedInteger(0)); + .value = Some(EngineParameterValueKind::UnsignedInteger(0)); let mut missing = local("qwen3-6-35b-a3b"); missing .engine_parameter_values diff --git a/backend/core/src/model/engine/vllm/declaration.rs b/backend/core/src/model/engine/vllm/declaration.rs index 5c881920..84263805 100644 --- a/backend/core/src/model/engine/vllm/declaration.rs +++ b/backend/core/src/model/engine/vllm/declaration.rs @@ -17,10 +17,10 @@ use dotcore_proto::dotcore::{ catalog::v1::{ EngineRelease, HardwareClass, Model, ModelConfigurationOption, ModelEngineConfiguration, ModelInputModality, ModelParallelShape, SpeculativeDecodingMethod, - engine_parameter_definition::ParameterType, hugging_face_artifact_source::Content as HuggingFaceContent, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, + parameter_definition::ParameterType, }, engine::{ v1::engine_model_configuration::Configuration, @@ -62,7 +62,7 @@ pub(crate) fn validate_engine_release(engine: &EngineRelease) -> Vec= range.minimum && !range.unit.is_empty() } Some(ParameterType::Boolean(_)) => true, - None => false, + Some(ParameterType::StringEnum(_)) | None => false, } }) }); @@ -431,10 +431,10 @@ mod tests { use dotcore_proto::dotcore::{ catalog::v1::{ - BooleanEngineParameterSchema, EngineParameterDefinition, EngineParameterSchema, - EngineRelease, HuggingFaceArtifactSource, Model, ModelArtifactBinding, - ModelAuxiliaryArtifact, ModelExecutionCapabilities, SpeculativeDecodingModelOption, - UnsignedIntegerEngineParameterSchema, + BooleanParameterSchema, EngineParameterSchema, EngineRelease, + HuggingFaceArtifactSource, Model, ModelArtifactBinding, ModelAuxiliaryArtifact, + ModelExecutionCapabilities, ParameterDefinition, SpeculativeDecodingModelOption, + UnsignedIntegerParameterSchema, }, engine::v1::{ EngineKind, EngineModelConfiguration, engine_model_configuration::Configuration, @@ -461,10 +461,10 @@ mod tests { }; fn release(kind: EngineKind) -> EngineRelease { - let unsigned = |parameter_id: &str, maximum: u64, unit: &str| EngineParameterDefinition { + let unsigned = |parameter_id: &str, maximum: u64, unit: &str| ParameterDefinition { parameter_id: parameter_id.to_owned(), parameter_type: Some(ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1, maximum, unit: unit.to_owned(), @@ -497,10 +497,10 @@ mod tests { .as_mut() .expect("schema") .parameters - .push(EngineParameterDefinition { + .push(ParameterDefinition { parameter_id: "feature-enabled".to_owned(), display_name: "Feature enabled".to_owned(), - parameter_type: Some(ParameterType::Boolean(BooleanEngineParameterSchema {})), + parameter_type: Some(ParameterType::Boolean(BooleanParameterSchema::default())), ..Default::default() }); assert!(validate_engine_release(&with_boolean).is_empty()); @@ -1041,13 +1041,13 @@ version: "1" parameterSchema: schemaId: "fixture-vllm-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "1048576", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "1024", unit: "requests", defaultValue: "4" } } - - { parameterId: "maximum-batched-tokens", displayName: "Maximum batched tokens", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "tokens" } } - - { parameterId: "maximum-cudagraph-capture-size", displayName: "Maximum CUDA graph capture size", unsignedInteger: { minimum: "1", maximum: "1024", unit: "sequences" } } - - { parameterId: "kv-cache-memory-bytes", displayName: "KV cache memory", unsignedInteger: { minimum: "1", maximum: "1099511627776", unit: "bytes" } } - - { parameterId: "kv-offloading-size-gib", displayName: "KV offloading size", exposed: true, unsignedInteger: { minimum: "0", maximum: "1024", unit: "GiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "1048576", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "1024", unit: "requests", defaultValue: "4" } } + - { parameterId: "maximum-batched-tokens", displayName: "Maximum batched tokens", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "tokens" } } + - { parameterId: "maximum-cudagraph-capture-size", displayName: "Maximum CUDA graph capture size", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "1024", unit: "sequences" } } + - { parameterId: "kv-cache-memory-bytes", displayName: "KV cache memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "1099511627776", unit: "bytes" } } + - { parameterId: "kv-offloading-size-gib", displayName: "KV offloading size", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "0", maximum: "1024", unit: "GiB" } } artifacts: - artifactId: "linux-amd64-cuda" oci: diff --git a/backend/core/src/model/engine/vllm/plan.rs b/backend/core/src/model/engine/vllm/plan.rs index ce737dc3..044c5d63 100644 --- a/backend/core/src/model/engine/vllm/plan.rs +++ b/backend/core/src/model/engine/vllm/plan.rs @@ -12,7 +12,7 @@ use dotcore_catalog::{ shared_parameters::{CONTEXT_PER_REQUEST_PARAMETER_ID, PARALLEL_REQUESTS_PARAMETER_ID}, }; use dotcore_proto::dotcore::{ - catalog::v1::engine_parameter_value::Value as EngineParameterValue, + catalog::v1::parameter_value::Value as EngineParameterValueKind, engine::{ v1::{EngineKind, resolved_engine_model_state::State}, vllm::v1::{ @@ -443,7 +443,7 @@ fn unsigned_integer_parameter( .find(|value| value.parameter_id == parameter_id) }) .and_then(|value| match value.value.as_ref() { - Some(EngineParameterValue::UnsignedInteger(value)) => Some(*value), + Some(EngineParameterValueKind::UnsignedInteger(value)) => Some(*value), _ => None, }) .ok_or_else(|| VllmPlanError::ParameterNotConfigured(parameter_id.to_owned())) @@ -595,8 +595,8 @@ pub(crate) enum VllmPlanError { mod tests { use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValue, EngineParameterValues, ModelArtifact, ModelAuxiliaryArtifact, - ModelOptionParameterValue, ModelOptionValues, engine_parameter_value::Value, + ModelArtifact, ModelAuxiliaryArtifact, ModelOptionParameterValue, ModelOptionValues, + ParameterValue, ParameterValues, parameter_value::Value, }, engine::v1::{ResolvedEngineModelState, resolved_engine_model_state::State}, engine::vllm::v1::{ @@ -657,7 +657,7 @@ mod tests { semantics_version: super::super::realization::SEMANTICS_VERSION, state: Some(State::Vllm(state)), }), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [ ("bytes", 7000_u64), (PARALLEL_REQUESTS_PARAMETER_ID, 8), @@ -667,7 +667,7 @@ mod tests { (CONTEXT_PER_REQUEST_PARAMETER_ID, 32768), ] .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), value: Some(Value::UnsignedInteger(value)), }) diff --git a/backend/core/src/model/recommendation/tests.rs b/backend/core/src/model/recommendation/tests.rs index 7366e95f..64fdd470 100644 --- a/backend/core/src/model/recommendation/tests.rs +++ b/backend/core/src/model/recommendation/tests.rs @@ -910,10 +910,10 @@ version: "1" parameterSchema: schemaId: "llama-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } - - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } + - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } artifacts: - artifactId: "linux-amd64" oci: diff --git a/backend/core/src/model/repository.rs b/backend/core/src/model/repository.rs index ab7767fa..ff8ce628 100644 --- a/backend/core/src/model/repository.rs +++ b/backend/core/src/model/repository.rs @@ -1022,9 +1022,9 @@ mod tests { ResolvedApplicationDeploymentSnapshot, }, catalog::v1::{ - EngineParameterValue, EngineParameterValues, OciPlatform, UpstreamModelBoundary, + OciPlatform, ParameterValue, ParameterValues, UpstreamModelBoundary, UpstreamModelDataEgressClass, UpstreamModelLocality, - engine_parameter_value::Value as EngineParameterValueKind, + parameter_value::Value as EngineParameterValueKind, }, deployment::v1::ExactPlacement, inference::v1::{FallbackGroup, FallbackGroupSelection, InferenceRoute}, @@ -3120,7 +3120,7 @@ mod tests { /// Engine parameter values for a llama.cpp deployment: the total context, the prompt cache and /// the parallel requests that sizing never derives. - fn engine_values(total_context: u64) -> EngineParameterValues { + fn engine_values(total_context: u64) -> ParameterValues { unsigned_values(&[ ("total-context", total_context), ("prompt-cache-memory-mib", 0), @@ -3130,7 +3130,7 @@ mod tests { /// The fixture profile's engine parameter defaults: its prompt cache, then the engine defaults /// of the total context and the parallel requests. - fn profile_default_values() -> EngineParameterValues { + fn profile_default_values() -> ParameterValues { unsigned_values(&[ ("prompt-cache-memory-mib", 0), ("total-context", 32_768), @@ -3140,28 +3140,25 @@ mod tests { /// The context per request resolution fills from the total context, within the fixture /// model's maximum context. - fn filled_context_per_request(total_context: u64) -> EngineParameterValues { + fn filled_context_per_request(total_context: u64) -> ParameterValues { unsigned_values(&[("context-per-request", total_context.min(262_144))]) } /// Values in the given order, followed by the filled context per request, as a resolved /// snapshot retains them. - fn resolved_values( - mut values: EngineParameterValues, - total_context: u64, - ) -> EngineParameterValues { + fn resolved_values(mut values: ParameterValues, total_context: u64) -> ParameterValues { values .values .extend(filled_context_per_request(total_context).values); values } - fn unsigned_values(values: &[(&str, u64)]) -> EngineParameterValues { - EngineParameterValues { + fn unsigned_values(values: &[(&str, u64)]) -> ParameterValues { + ParameterValues { values: values .iter() .copied() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(value)), }) diff --git a/backend/core/src/model/resolution.rs b/backend/core/src/model/resolution.rs index b553c2c2..144db35e 100644 --- a/backend/core/src/model/resolution.rs +++ b/backend/core/src/model/resolution.rs @@ -13,12 +13,12 @@ use dotcore_catalog::{ use dotcore_domain::deployment::artifact::immutable_remote_launch_identity; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineArtifact, EngineParameterSchema, EngineParameterValue, EngineParameterValues, - EngineRelease, Model, ModelArtifact, ModelArtifactBinding, ModelEngineConfiguration, - ModelOptionValues, ModelProfile, NixArtifact, engine_artifact::Kind as EngineArtifactKind, - engine_parameter_definition::ParameterType as EngineParameterType, - engine_parameter_value::Value as EngineParameterValueKind, + EngineArtifact, EngineParameterSchema, EngineRelease, Model, ModelArtifact, + ModelArtifactBinding, ModelEngineConfiguration, ModelOptionValues, ModelProfile, + NixArtifact, ParameterValue, ParameterValues, engine_artifact::Kind as EngineArtifactKind, model_option_parameter_value::Value as OptionParameterValueKind, + parameter_definition::ParameterType as EngineParameterType, + parameter_value::Value as EngineParameterValueKind, }, deployment::v1::ArtifactPreparationPolicy, model::v1::{ @@ -53,8 +53,8 @@ use crate::{ /// Only resource estimates keep values a launch would reject, with the reason beside them. pub(crate) struct ResolvedLocalModelValues { pub(crate) selection: LocalModelSelection, - pub(crate) engine_parameter_values: EngineParameterValues, - pub(crate) derived_engine_parameter_values: EngineParameterValues, + pub(crate) engine_parameter_values: ParameterValues, + pub(crate) derived_engine_parameter_values: ParameterValues, pub(crate) engine_parameter_schema: EngineParameterSchema, pub(crate) engine_parameter_schema_id: String, pub(crate) option_values: Vec, @@ -753,14 +753,14 @@ fn evaluate_selected_values( ) .map_err(|error| sizing_unavailable(anyhow::Error::new(error)))? .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id, value: Some(EngineParameterValueKind::UnsignedInteger(value)), }) .chain(filled_context_per_request) .collect::>(); derived_values.sort_by(|left, right| left.parameter_id.cmp(&right.parameter_id)); - let derived_engine_parameter_values = EngineParameterValues { + let derived_engine_parameter_values = ParameterValues { values: derived_values, }; validate_derived_ranges(&derived_engine_parameter_values, &schema)?; @@ -1055,7 +1055,7 @@ impl ModelLaunchResolutionError { /// Rejects complete engine parameter values, each in range, that a launch can't start together. fn validate_launch_values( selection: &LocalModelSelection, - values: &EngineParameterValues, + values: &ParameterValues, ) -> Result<(), ModelLaunchResolutionError> { validate_context_per_request(selection, values)?; crate::model::engine::validate_parameter_values( @@ -1071,7 +1071,7 @@ fn validate_launch_values( /// maximum context: the model's maximum context, or the configuration's lower maximum. fn validate_context_per_request( selection: &LocalModelSelection, - values: &EngineParameterValues, + values: &ParameterValues, ) -> Result<(), ModelLaunchResolutionError> { let Some(context_tokens) = crate::model::engine::unsigned_parameter_value( values, @@ -1094,7 +1094,7 @@ fn validate_context_per_request( /// Rejects derived values outside their unsigned schema range with the offending value. fn validate_derived_ranges( - derived: &EngineParameterValues, + derived: &ParameterValues, schema: &EngineParameterSchema, ) -> Result<(), ModelLaunchResolutionError> { for value in &derived.values { @@ -1163,10 +1163,9 @@ mod tests { }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterValue, EngineParameterValues, HardwareRequirements, - ModelOptionParameterValue, ModelOptionValues, NixSystemStorePath, Selector, - StorageBinding, StorageEnvironmentVariable, StorageKind, StorageScope, - engine_parameter_value, model_option_parameter_value, + HardwareRequirements, ModelOptionParameterValue, ModelOptionValues, NixSystemStorePath, + ParameterValue, ParameterValues, Selector, StorageBinding, StorageEnvironmentVariable, + StorageKind, StorageScope, model_option_parameter_value, parameter_value, }, engine::{ llama_cpp::v1::LlamaCppResolvedModelState, v1::resolved_engine_model_state::State, @@ -1199,7 +1198,7 @@ mod tests { "fixture-profile", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "fixture-artifact".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1261,7 +1260,7 @@ mod tests { "fixture-profile", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "fixture-artifact".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1295,7 +1294,7 @@ mod tests { "fixture-profile", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "fixture-artifact".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1365,7 +1364,7 @@ mod tests { "fixture-profile", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "fixture-artifact".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1422,7 +1421,7 @@ mod tests { ); let configuration = LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: context_and_request_values(), }), custom_argument_tokens: vec!["--verbose".to_owned()], @@ -1443,7 +1442,7 @@ mod tests { resolve_local_values(&catalog, &derived_model_id(), "balanced", &configuration) .expect("derived values"); - let expected_values = EngineParameterValues { + let expected_values = ParameterValues { values: context_and_request_values() .into_iter() .chain([filled_context_per_request(), prompt_cache_value(4096)]) @@ -1467,7 +1466,7 @@ mod tests { assert_eq!(values.engine_parameter_values, expected_values); assert_eq!( values.derived_engine_parameter_values, - EngineParameterValues { + ParameterValues { values: vec![filled_context_per_request(), prompt_cache_value(4096)], } ); @@ -1720,7 +1719,7 @@ mod tests { "balanced", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1736,7 +1735,7 @@ mod tests { assert_eq!( snapshot.engine_parameter_values, - Some(EngineParameterValues { + Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1772,7 +1771,7 @@ mod tests { "balanced", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: context_and_request_values(), }), ..Default::default() @@ -1803,7 +1802,7 @@ mod tests { completed, LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1815,7 +1814,7 @@ mod tests { ); assert_eq!( values.engine_parameter_values, - EngineParameterValues { + ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -1825,7 +1824,7 @@ mod tests { ); assert_eq!( values.derived_engine_parameter_values, - EngineParameterValues { + ParameterValues { values: vec![filled_context_per_request()], } ); @@ -1841,7 +1840,7 @@ mod tests { let complete = LocalModelDeploymentConfiguration { model_artifact_binding_id: "second".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(8)] .into_iter() .chain(context_and_request_values()) @@ -1852,7 +1851,7 @@ mod tests { assert_eq!(completed(complete.clone()), complete); let partial = completed(LocalModelDeploymentConfiguration { - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: vec![prompt_cache_value(8)], }), ..Default::default() @@ -1861,7 +1860,7 @@ mod tests { partial, LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(8)] .into_iter() .chain(context_and_request_values()) @@ -1874,7 +1873,7 @@ mod tests { resolve_local_values(&catalog, &derived_model_id(), "balanced", &partial) .expect("overlaid values") .derived_engine_parameter_values, - EngineParameterValues { + ParameterValues { values: vec![filled_context_per_request()], } ); @@ -2081,7 +2080,7 @@ mod tests { assert_eq!(values.selection.binding.binding_id, "second"); assert_eq!( values.engine_parameter_values, - EngineParameterValues { + ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -2136,7 +2135,7 @@ mod tests { "fixture-profile", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "fixture-artifact".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [prompt_cache_value(30_000)] .into_iter() .chain(context_and_request_values()) @@ -2712,7 +2711,7 @@ mod tests { "balanced", &LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: context_and_request_values(), }), ..Default::default() @@ -2799,7 +2798,7 @@ mod tests { fn context_and_request_configuration() -> LocalModelDeploymentConfiguration { LocalModelDeploymentConfiguration { model_artifact_binding_id: "sized".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: context_and_request_values(), }), ..Default::default() @@ -2926,7 +2925,7 @@ mod tests { .iter() .find(|value| value.parameter_id == TOTAL_CONTEXT_PARAMETER_ID) .and_then(|value| match value.value { - Some(engine_parameter_value::Value::UnsignedInteger(value)) => Some(value), + Some(parameter_value::Value::UnsignedInteger(value)) => Some(value), _ => None, }) .expect("resolved total context")) @@ -2969,13 +2968,13 @@ mod tests { root } - fn unsigned_values(values: &[(&str, u64)]) -> EngineParameterValues { - EngineParameterValues { + fn unsigned_values(values: &[(&str, u64)]) -> ParameterValues { + ParameterValues { values: values .iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: (*parameter_id).to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(*value)), + value: Some(parameter_value::Value::UnsignedInteger(*value)), }) .collect(), } @@ -2985,29 +2984,29 @@ mod tests { CatalogModelId("fixture-model".to_owned()) } - fn prompt_cache_value(value: u64) -> EngineParameterValue { - EngineParameterValue { + fn prompt_cache_value(value: u64) -> ParameterValue { + ParameterValue { parameter_id: "prompt-cache-memory-mib".to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), } } /// The context per request resolution fills from the fixtures' total context. - fn filled_context_per_request() -> EngineParameterValue { - EngineParameterValue { + fn filled_context_per_request() -> ParameterValue { + ParameterValue { parameter_id: "context-per-request".to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(32_768)), + value: Some(parameter_value::Value::UnsignedInteger(32_768)), } } /// Total context and parallel request values the derivation fixtures supply, since their /// sizing derives the prompt cache instead. - fn context_and_request_values() -> Vec { + fn context_and_request_values() -> Vec { [("total-context", 32_768), ("parallel-requests", 4)] .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), }) .collect() } diff --git a/backend/core/src/model/resolved.rs b/backend/core/src/model/resolved.rs index cc8fe061..a4578415 100644 --- a/backend/core/src/model/resolved.rs +++ b/backend/core/src/model/resolved.rs @@ -16,8 +16,8 @@ use dotcore_domain::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineArtifact, EngineParameterValues, EngineRelease, HardwareRequirements, - HuggingFaceArtifactSource, ModelInputCapabilities, StorageBinding, + EngineArtifact, EngineRelease, HardwareRequirements, HuggingFaceArtifactSource, + ModelInputCapabilities, ParameterValues, StorageBinding, engine_artifact::Kind as EngineArtifactKind, hugging_face_artifact_source::Content as HuggingFaceContent, nix_artifact::Provides, }, @@ -624,7 +624,7 @@ pub(crate) fn selected_target_memory_architecture( /// Requires every derived parameter id to name one retained engine parameter value. fn validate_sizing( sizing: Option<&ResolvedSizing>, - values: &EngineParameterValues, + values: &ParameterValues, ) -> Result<(), CatalogError> { let Some(sizing) = sizing else { return Ok(()); diff --git a/backend/core/src/model/sizing_scenario/mod.rs b/backend/core/src/model/sizing_scenario/mod.rs index 8969b702..e6d31163 100644 --- a/backend/core/src/model/sizing_scenario/mod.rs +++ b/backend/core/src/model/sizing_scenario/mod.rs @@ -19,8 +19,8 @@ use dotcore_catalog::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterSchema, EngineParameterValue, EngineParameterValues, HardwareRequirements, - Model, ModelProfile, engine_parameter_value::Value as EngineParameterValueKind, + EngineParameterSchema, HardwareRequirements, Model, ModelProfile, ParameterValue, + ParameterValues, parameter_value::Value as EngineParameterValueKind, }, deployment::v1::MemoryFit, model::v1::{ @@ -406,7 +406,7 @@ fn largest_fitting_total_context( set_unsigned_value( configuration .engine_parameter_values - .get_or_insert_with(EngineParameterValues::default), + .get_or_insert_with(ParameterValues::default), TOTAL_CONTEXT_PARAMETER_ID, total_context, ); @@ -559,7 +559,7 @@ fn with_scenario_values( let values = configuration .engine_parameter_values - .get_or_insert_with(EngineParameterValues::default); + .get_or_insert_with(ParameterValues::default); set_unsigned_value( values, TOTAL_CONTEXT_PARAMETER_ID, @@ -579,8 +579,8 @@ fn with_scenario_values( /// values are the ones a launch would resolve before sizing derivations. fn with_filled_context_per_request( declarations: &CatalogLocalModelDeclarations, - mut values: EngineParameterValues, -) -> EngineParameterValues { + mut values: ParameterValues, +) -> ParameterValues { if let Some(schema) = engine_parameter_schema(declarations) { let filled = crate::model::engine::filled_context_per_request( declarations.engine_kind, @@ -599,7 +599,7 @@ fn with_filled_context_per_request( fn accepts_context_values( declarations: &CatalogLocalModelDeclarations, schema: &EngineParameterSchema, - complete: &EngineParameterValues, + complete: &ParameterValues, ) -> Option { let mut in_range = true; for parameter_id in [TOTAL_CONTEXT_PARAMETER_ID, CONTEXT_PER_REQUEST_PARAMETER_ID] { @@ -658,8 +658,8 @@ fn engine_parameter_schema( } /// Replaces the value of one parameter, or adds it when the values leave it out. -fn set_unsigned_value(values: &mut EngineParameterValues, parameter_id: &str, value: u64) { - let value = EngineParameterValue { +fn set_unsigned_value(values: &mut ParameterValues, parameter_id: &str, value: u64) { + let value = ParameterValue { parameter_id: parameter_id.to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(value)), }; diff --git a/backend/core/src/model/sizing_scenario/tests.rs b/backend/core/src/model/sizing_scenario/tests.rs index 5ff3346a..b685d0e3 100644 --- a/backend/core/src/model/sizing_scenario/tests.rs +++ b/backend/core/src/model/sizing_scenario/tests.rs @@ -1491,10 +1491,10 @@ version: "1" parameterSchema: schemaId: "llama-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } - - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } + - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } artifacts: - artifactId: "linux" oci: @@ -1601,13 +1601,13 @@ version: "1" parameterSchema: schemaId: "vllm-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "1048576", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "1024", unit: "requests", defaultValue: "4" } } - - { parameterId: "maximum-batched-tokens", displayName: "Maximum batched tokens", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "tokens" } } - - { parameterId: "maximum-cudagraph-capture-size", displayName: "Maximum CUDA graph capture size", unsignedInteger: { minimum: "1", maximum: "1024", unit: "sequences" } } - - { parameterId: "kv-cache-memory-bytes", displayName: "KV cache memory", unsignedInteger: { minimum: "1", maximum: "68719476736", unit: "bytes" } } - - { parameterId: "kv-offloading-size-gib", displayName: "KV offloading size", unsignedInteger: { minimum: "0", maximum: "1024", unit: "GiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "1048576", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "1024", unit: "requests", defaultValue: "4" } } + - { parameterId: "maximum-batched-tokens", displayName: "Maximum batched tokens", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "1048576", unit: "tokens" } } + - { parameterId: "maximum-cudagraph-capture-size", displayName: "Maximum CUDA graph capture size", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "1024", unit: "sequences" } } + - { parameterId: "kv-cache-memory-bytes", displayName: "KV cache memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "1", maximum: "68719476736", unit: "bytes" } } + - { parameterId: "kv-offloading-size-gib", displayName: "KV offloading size", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "0", maximum: "1024", unit: "GiB" } } artifacts: - artifactId: "linux" oci: @@ -1695,10 +1695,10 @@ version: "1" parameterSchema: schemaId: "ninfer-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "4" } } - - { parameterId: "host-context-mib", displayName: "Host context memory", unsignedInteger: { minimum: "0", maximum: "1048576", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "2097152", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "262144", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "8", unit: "requests", defaultValue: "4" } } + - { parameterId: "host-context-mib", displayName: "Host context memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "0", maximum: "1048576", unit: "MiB" } } artifacts: - artifactId: "linux" oci: diff --git a/backend/core/src/route_manager/projection.rs b/backend/core/src/route_manager/projection.rs index 38dd58a6..5e33261b 100644 --- a/backend/core/src/route_manager/projection.rs +++ b/backend/core/src/route_manager/projection.rs @@ -248,7 +248,7 @@ fn modalities(supports_text: bool, supports_image: bool) -> Vec { #[cfg(test)] mod tests { use dotcore_proto::dotcore::{ - catalog::v1::engine_parameter_value, + catalog::v1::parameter_value, inference::v1::{FallbackGroup, FallbackGroupSelection, InferenceRoute}, model::v1::ModelDeploymentSnapshot, }; @@ -394,7 +394,7 @@ mod tests { .expect("fixture parameter values"); for value in &mut values.values { if value.parameter_id == CONTEXT_PER_REQUEST_PARAMETER_ID { - value.value = Some(engine_parameter_value::Value::UnsignedInteger(context)); + value.value = Some(parameter_value::Value::UnsignedInteger(context)); } } ModelDeploymentDeclaration { diff --git a/backend/core/src/telemetry/fit/mod.rs b/backend/core/src/telemetry/fit/mod.rs index 1f92c589..ee677ef2 100644 --- a/backend/core/src/telemetry/fit/mod.rs +++ b/backend/core/src/telemetry/fit/mod.rs @@ -26,9 +26,7 @@ use dotcore_catalog::{ shared_parameters::TOTAL_CONTEXT_PARAMETER_ID, }; use dotcore_proto::dotcore::{ - catalog::v1::{ - EngineParameterValues, ModelEngineConfiguration, ModelOptionValues, engine_parameter_value, - }, + catalog::v1::{ModelEngineConfiguration, ModelOptionValues, ParameterValues, parameter_value}, telemetry::v1::{ VllmStartupFacts, WorkloadResourceObservationKind, WorkloadResourceRecord, workload_resource_observation::EngineFacts, @@ -134,7 +132,7 @@ impl ObservedQuantity { .iter() .find(|value| &value.parameter_id == parameter) .and_then(|value| match value.value { - Some(engine_parameter_value::Value::UnsignedInteger(value)) => Some(value), + Some(parameter_value::Value::UnsignedInteger(value)) => Some(value), _ => None, }), } @@ -934,7 +932,7 @@ fn predict( fn record_inputs( configuration: &ModelEngineConfiguration, record: &WorkloadResourceRecord, -) -> (EngineParameterValues, Vec) { +) -> (ParameterValues, Vec) { let (engine_values, mut option_values) = record .inputs .as_ref() @@ -1113,7 +1111,7 @@ fn total_context(record: &WorkloadResourceRecord) -> Option { .iter() .find(|value| value.parameter_id == TOTAL_CONTEXT_PARAMETER_ID) .and_then(|value| match value.value { - Some(engine_parameter_value::Value::UnsignedInteger(value)) => Some(value), + Some(parameter_value::Value::UnsignedInteger(value)) => Some(value), _ => None, }) } diff --git a/backend/core/src/telemetry/fit/tests.rs b/backend/core/src/telemetry/fit/tests.rs index c1bb56b8..8ae3e18d 100644 --- a/backend/core/src/telemetry/fit/tests.rs +++ b/backend/core/src/telemetry/fit/tests.rs @@ -5,7 +5,7 @@ use dotcore_catalog::test_support::{ use dotcore_proto::{ dotcore::{ catalog::v1::{ - EngineParameterValue, ModelOptionParameterValue, ModelOptionValues, + ModelOptionParameterValue, ModelOptionValues, ParameterValue, model_option_parameter_value, }, telemetry::v1::{ @@ -1466,10 +1466,10 @@ fn record( model_artifact_id: "sized-weights".to_owned(), engine_release_id: "fixture-engine".to_owned(), engine_artifact_id: "linux-amd64".to_owned(), - engine_parameter_values: Some(EngineParameterValues { - values: vec![EngineParameterValue { + engine_parameter_values: Some(ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(context_size)), + value: Some(parameter_value::Value::UnsignedInteger(context_size)), }], }), ..WorkloadResourceInputs::default() diff --git a/backend/core/src/telemetry/mod.rs b/backend/core/src/telemetry/mod.rs index d8fbb3bb..bf453c7a 100644 --- a/backend/core/src/telemetry/mod.rs +++ b/backend/core/src/telemetry/mod.rs @@ -187,9 +187,9 @@ mod tests { use dotcore_proto::{ dotcore::{ catalog::v1::{ - EngineParameterValue, EngineParameterValues, ModelOptionParameterValue, - ModelOptionValues, engine_parameter_value::Value as EngineValue, + ModelOptionParameterValue, ModelOptionValues, ParameterValue, ParameterValues, model_option_parameter_value::Value as OptionValue, + parameter_value::Value as EngineValue, }, observation::v1::AcceleratorMemoryArchitecture, telemetry::v1::{ @@ -339,13 +339,13 @@ mod tests { engine_release_id: "vllm-v0-32-0".to_owned(), engine_artifact_id: "linux-amd64-cuda".to_owned(), engine_artifact_reference: "docker.io/vllm/vllm-openai@sha256:d392".to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: vec![ - EngineParameterValue { + ParameterValue { parameter_id: "kv-cache-memory-bytes".to_owned(), value: Some(EngineValue::UnsignedInteger(6_000_000_000)), }, - EngineParameterValue { + ParameterValue { parameter_id: "prefix-caching".to_owned(), value: Some(EngineValue::Boolean(false)), }, diff --git a/backend/core/src/test_support/mod.rs b/backend/core/src/test_support/mod.rs index 1eca75c4..0232e50e 100644 --- a/backend/core/src/test_support/mod.rs +++ b/backend/core/src/test_support/mod.rs @@ -37,15 +37,15 @@ pub(crate) fn host_process_load_guard() -> std::sync::MutexGuard<'static, ()> { /// Unsigned engine parameter values for the given parameter and value pairs, in order. pub(crate) fn unsigned_parameter_values<'a>( values: impl IntoIterator, -) -> dotcore_proto::dotcore::catalog::v1::EngineParameterValues { +) -> dotcore_proto::dotcore::catalog::v1::ParameterValues { use dotcore_proto::dotcore::catalog::v1::{ - EngineParameterValue, EngineParameterValues, engine_parameter_value::Value, + ParameterValue, ParameterValues, parameter_value::Value, }; - EngineParameterValues { + ParameterValues { values: values .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), value: Some(Value::UnsignedInteger(value)), }) diff --git a/backend/core/src/test_support/ninfer.rs b/backend/core/src/test_support/ninfer.rs index db974f00..bca2ced1 100644 --- a/backend/core/src/test_support/ninfer.rs +++ b/backend/core/src/test_support/ninfer.rs @@ -14,18 +14,18 @@ use dotcore_catalog::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - BooleanModelOptionParameterSchema, EngineParameterDefinition, EngineParameterSchema, - EngineParameterValue, EngineParameterValues, EngineRelease, HardwareRequirements, - HardwareSupport, HuggingFaceArtifactSource, HuggingFaceFileArtifact, InferenceRequestKind, - Model, ModelArtifact, ModelArtifactBinding, ModelConfigurationOption, + BooleanModelOptionParameterSchema, EngineParameterSchema, EngineRelease, + HardwareRequirements, HardwareSupport, HuggingFaceArtifactSource, HuggingFaceFileArtifact, + InferenceRequestKind, Model, ModelArtifact, ModelArtifactBinding, ModelConfigurationOption, ModelEngineConfiguration, ModelExecutionCapabilities, ModelImageDetail, ModelImageInputCapacity, ModelImageMediaType, ModelInputCapabilities, ModelInputModality, ModelOption, ModelOptionParameterDefinition, ModelOptionParameterValue, ModelOptionValues, - ModelParallelShape, SpeculativeDecodingMethod, SpeculativeDecodingModelOption, - UnsignedIntegerEngineParameterSchema, UnsignedIntegerModelOptionParameterSchema, - VisionModelOption, engine_parameter_definition, engine_parameter_value, - hugging_face_artifact_source, model_option, model_option_parameter_definition, - model_option_parameter_value, + ModelParallelShape, ParameterDefinition, ParameterValue, ParameterValues, + ParameterVisibility, SpeculativeDecodingMethod, SpeculativeDecodingModelOption, + UnsignedIntegerModelOptionParameterSchema, UnsignedIntegerParameterSchema, + VisionModelOption, hugging_face_artifact_source, model_option, + model_option_parameter_definition, model_option_parameter_value, parameter_definition, + parameter_value, }, engine::{ ninfer::v1::{ @@ -116,13 +116,13 @@ pub(crate) fn refresh_launch_plan(local: &mut ResolvedLocalModelDeploymentSnapsh } /// Returns ninfer engine parameter values for the given pairs. -pub(crate) fn parameter_values(values: [(&str, u64); N]) -> EngineParameterValues { - EngineParameterValues { +pub(crate) fn parameter_values(values: [(&str, u64); N]) -> ParameterValues { + ParameterValues { values: values .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), }) .collect(), } @@ -173,20 +173,21 @@ pub(crate) fn release() -> EngineRelease { .into_iter() .map( |(parameter_id, display_name, minimum, maximum, unit, default_value)| { - EngineParameterDefinition { + ParameterDefinition { parameter_id: parameter_id.to_owned(), display_name: display_name.to_owned(), - parameter_type: Some( - engine_parameter_definition::ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { - minimum, - maximum, - unit: unit.to_owned(), - default_value, - }, - ), - ), - exposed: true, + parameter_type: Some(parameter_definition::ParameterType::UnsignedInteger( + UnsignedIntegerParameterSchema { + minimum, + maximum, + unit: unit.to_owned(), + default_value, + }, + )), + visibility: match parameter_id { + "total-context" | "context-per-request" => ParameterVisibility::Basic, + _ => ParameterVisibility::Advanced, + } as i32, description: parameter_id.to_owned(), } }, diff --git a/backend/core/src/test_support/nix.rs b/backend/core/src/test_support/nix.rs index 1271206f..b94b99b5 100644 --- a/backend/core/src/test_support/nix.rs +++ b/backend/core/src/test_support/nix.rs @@ -6,8 +6,7 @@ use dotcore_domain::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineArtifact, NixArtifact, engine_artifact::Kind as EngineArtifactKind, - engine_parameter_value, + EngineArtifact, NixArtifact, engine_artifact::Kind as EngineArtifactKind, parameter_value, }, deployment::v1::ArtifactPreparationPolicy, engine::v1::resolved_engine_model_state, @@ -78,7 +77,7 @@ pub(crate) fn apple_metal_snapshot(model_id: &str) -> ModelDeploymentSnapshot { .iter_mut() .find(|value| value.parameter_id == "prompt-cache-memory-mib") .expect("prompt cache value") - .value = Some(engine_parameter_value::Value::UnsignedInteger(2048)); + .value = Some(parameter_value::Value::UnsignedInteger(2048)); local.desired_launch_plan = Some( crate::model::engine::EngineIntegrationRegistry::production() diff --git a/backend/core/src/test_support/strata.rs b/backend/core/src/test_support/strata.rs index 4e0091d9..c3be6bc9 100644 --- a/backend/core/src/test_support/strata.rs +++ b/backend/core/src/test_support/strata.rs @@ -11,14 +11,14 @@ use dotcore_catalog::shared_parameters::{ }; use dotcore_proto::dotcore::{ catalog::v1::{ - EngineParameterDefinition, EngineParameterSchema, EngineParameterValue, - EngineParameterValues, EngineRelease, HardwareRequirements, HardwareSupport, + EngineParameterSchema, EngineRelease, HardwareRequirements, HardwareSupport, HuggingFaceArtifactSource, HuggingFaceFileArtifact, HuggingFaceSnapshotArtifact, HuggingFaceSnapshotFile, InferenceRequestKind, Model, ModelArtifact, ModelArtifactBinding, ModelAuxiliaryArtifact, ModelEngineConfiguration, ModelExecutionCapabilities, - ModelInputCapabilities, ModelInputModality, ModelParallelShape, StorageBinding, - StorageKind, StorageScope, UnsignedIntegerEngineParameterSchema, - engine_parameter_definition, engine_parameter_value, hugging_face_artifact_source, + ModelInputCapabilities, ModelInputModality, ModelParallelShape, ParameterDefinition, + ParameterValue, ParameterValues, ParameterVisibility, StorageBinding, StorageKind, + StorageScope, UnsignedIntegerParameterSchema, hugging_face_artifact_source, + parameter_definition, parameter_value, }, engine::{ strata::v1::{ @@ -109,13 +109,13 @@ pub(crate) fn refresh_launch_plan(local: &mut ResolvedLocalModelDeploymentSnapsh } /// Returns Strata engine parameter values for the given pairs. -pub(crate) fn parameter_values(values: [(&str, u64); N]) -> EngineParameterValues { - EngineParameterValues { +pub(crate) fn parameter_values(values: [(&str, u64); N]) -> ParameterValues { + ParameterValues { values: values .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), }) .collect(), } @@ -166,20 +166,21 @@ pub(crate) fn release() -> EngineRelease { .into_iter() .map( |(parameter_id, display_name, minimum, maximum, unit, default_value)| { - EngineParameterDefinition { + ParameterDefinition { parameter_id: parameter_id.to_owned(), display_name: display_name.to_owned(), - parameter_type: Some( - engine_parameter_definition::ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { - minimum, - maximum, - unit: unit.to_owned(), - default_value, - }, - ), - ), - exposed: true, + parameter_type: Some(parameter_definition::ParameterType::UnsignedInteger( + UnsignedIntegerParameterSchema { + minimum, + maximum, + unit: unit.to_owned(), + default_value, + }, + )), + visibility: match parameter_id { + "total-context" | "context-per-request" => ParameterVisibility::Basic, + _ => ParameterVisibility::Advanced, + } as i32, description: parameter_id.to_owned(), } }, diff --git a/backend/core/tests/backend/backend_integration.rs b/backend/core/tests/backend/backend_integration.rs index 7c9bf21a..8590b00d 100644 --- a/backend/core/tests/backend/backend_integration.rs +++ b/backend/core/tests/backend/backend_integration.rs @@ -30,9 +30,9 @@ use dotcore_proto::dotcore::{ application_deployment_service_server::ApplicationDeploymentService as ApplicationServiceContract, }, catalog::v1::{ - EngineParameterValue, EngineParameterValues, ListApplicationsRequest, - ListEngineReleasesRequest, ListModelsRequest, UseCase, - catalog_service_server::CatalogService as CatalogServiceContract, engine_parameter_value, + ListApplicationsRequest, ListEngineReleasesRequest, ListModelsRequest, ParameterValue, + ParameterValues, UseCase, catalog_service_server::CatalogService as CatalogServiceContract, + parameter_value, }, deployment::v1::MemoryFit, inference::v1::{DeleteRouteRequest, InferenceRoute, ListRoutesRequest, ReplaceRouteRequest}, @@ -4897,7 +4897,7 @@ async fn profile_compatibility_sizes_a_scenario_against_the_simulated_target_mem .collect::>(), [( "fixture-profile", - Some(EngineParameterValues { + Some(ParameterValues { values: [ ("prompt-cache-memory-mib", 0), ("total-context", total_context), @@ -4905,9 +4905,9 @@ async fn profile_compatibility_sizes_a_scenario_against_the_simulated_target_mem ("context-per-request", context_per_request), ] .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), }) .collect(), }), @@ -5198,9 +5198,9 @@ async fn rejected_local_configurations_return_their_reason_through_the_model_ser .values; for (parameter_id, value) in values { parameters.retain(|parameter| parameter.parameter_id != *parameter_id); - parameters.push(EngineParameterValue { + parameters.push(ParameterValue { parameter_id: (*parameter_id).to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(*value)), + value: Some(parameter_value::Value::UnsignedInteger(*value)), }); } CreateLocalModelDeploymentRequest { diff --git a/backend/core/tests/backend/catalog_contracts.rs b/backend/core/tests/backend/catalog_contracts.rs index 1d8e1e38..ccfad32c 100644 --- a/backend/core/tests/backend/catalog_contracts.rs +++ b/backend/core/tests/backend/catalog_contracts.rs @@ -30,9 +30,9 @@ use dotcore_proto::dotcore::{ EngineArtifactReference, EngineRelease, HardwareSupport, HuggingFaceSnapshotArtifact, HuggingFaceSnapshotFile, IntelligenceScore, License, ListEngineReleasesRequest, ListModelsRequest, ListUpstreamModelTemplatesRequest, Model, NixSystemStorePath, - OciPlatform, Selector, UpstreamModelTemplate, UpstreamWireProtocol, - engine_artifact::Kind as EngineArtifactKind, engine_parameter_value, - hugging_face_artifact_source::Content as HuggingFaceContent, + OciPlatform, ParameterVisibility, Selector, UpstreamModelTemplate, UpstreamWireProtocol, + engine_artifact::Kind as EngineArtifactKind, + hugging_face_artifact_source::Content as HuggingFaceContent, parameter_value, }, deployment::v1::ArtifactPreparationPolicy, engine::v1::EngineKind, @@ -678,7 +678,7 @@ fn catalog_sizing_resolves_estimates_into_the_deployment_snapshot() { .iter_mut() .find(|default| default.parameter_id == *parameter_id) .unwrap_or_else(|| panic!("{parameter_id} default")) - .value = Some(engine_parameter_value::Value::UnsignedInteger(*value)); + .value = Some(parameter_value::Value::UnsignedInteger(*value)); } resolve_local_launch_with_placeholder_identity( &catalog, @@ -2127,11 +2127,11 @@ fn catalog_rejects_invalid_parameters_and_unsupported_bindings() { let catalog = synthetic_local_catalog(); let model_id = CatalogModelId("fixture-model".to_owned()); let (target, inventory) = target_capabilities(ExecutionPlatform::linux_amd64()); - let invalid = dotcore_proto::dotcore::catalog::v1::EngineParameterValues { - values: vec![dotcore_proto::dotcore::catalog::v1::EngineParameterValue { + let invalid = dotcore_proto::dotcore::catalog::v1::ParameterValues { + values: vec![dotcore_proto::dotcore::catalog::v1::ParameterValue { parameter_id: "total-context".to_owned(), value: Some( - dotcore_proto::dotcore::catalog::v1::engine_parameter_value::Value::UnsignedInteger( + dotcore_proto::dotcore::catalog::v1::parameter_value::Value::UnsignedInteger( 16_777_217, ), ), @@ -2218,8 +2218,8 @@ fn llama_cpp_launch_rejects_a_context_per_request_above_the_model_maximum() { .iter() .find(|value| value.parameter_id == "context-per-request") }) - .and_then(|value| value.value), - Some(engine_parameter_value::Value::UnsignedInteger(262_144)) + .and_then(|value| value.value.clone()), + Some(parameter_value::Value::UnsignedInteger(262_144)) ); let arguments = filled .desired_launch_plan @@ -2424,7 +2424,7 @@ fn catalog_retains_boolean_engine_parameters_and_their_schema() { .iter() .find(|value| value.parameter_id == "feature-enabled") .and_then(|value| value.value.as_ref()), - Some(&dotcore_proto::dotcore::catalog::v1::engine_parameter_value::Value::Boolean(false)) + Some(&dotcore_proto::dotcore::catalog::v1::parameter_value::Value::Boolean(false)) ); assert_eq!( snapshot @@ -2449,9 +2449,8 @@ fn catalog_rejects_mismatched_boolean_values_and_invalid_profile_exposure() { .iter_mut() .find(|value| value.parameter_id == "feature-enabled") .expect("feature-enabled default") - .value = Some( - dotcore_proto::dotcore::catalog::v1::engine_parameter_value::Value::UnsignedInteger(1), - ); + .value = + Some(dotcore_proto::dotcore::catalog::v1::parameter_value::Value::UnsignedInteger(1)); let error = catalog_builder() .engine_validator(&ACCEPT_ENGINE_DECLARATIONS) .engine_release("engine.yaml", synthetic_boolean_engine_release()) @@ -2539,7 +2538,7 @@ fn lowest_total_context(catalog: &Catalog, model: &Model, profile_id: &str) -> ( use dotcore_catalog::shared_parameters::{ CONTEXT_PER_REQUEST_PARAMETER_ID, TOTAL_CONTEXT_PARAMETER_ID, }; - use dotcore_proto::dotcore::catalog::v1::engine_parameter_definition::ParameterType; + use dotcore_proto::dotcore::catalog::v1::parameter_definition::ParameterType; let profile = model .profiles @@ -2575,7 +2574,7 @@ fn lowest_total_context(catalog: &Catalog, model: &Model, profile_id: &str) -> ( .flat_map(|defaults| &defaults.values) .find(|value| value.parameter_id == CONTEXT_PER_REQUEST_PARAMETER_ID) .and_then(|value| match value.value { - Some(engine_parameter_value::Value::UnsignedInteger(tokens)) => Some(tokens), + Some(parameter_value::Value::UnsignedInteger(tokens)) => Some(tokens), _ => None, }); let lowest = context_per_request.map_or(smallest_total, |tokens| tokens.max(smallest_total)); @@ -3022,18 +3021,16 @@ fn repository_catalog_root() -> std::path::PathBuf { } /// Builds unsigned engine parameter values from parameter id and value pairs. -fn unsigned_values( - values: &[(&str, u64)], -) -> dotcore_proto::dotcore::catalog::v1::EngineParameterValues { - dotcore_proto::dotcore::catalog::v1::EngineParameterValues { +fn unsigned_values(values: &[(&str, u64)]) -> dotcore_proto::dotcore::catalog::v1::ParameterValues { + dotcore_proto::dotcore::catalog::v1::ParameterValues { values: values .iter() - .map(|(parameter_id, value)| { - dotcore_proto::dotcore::catalog::v1::EngineParameterValue { + .map( + |(parameter_id, value)| dotcore_proto::dotcore::catalog::v1::ParameterValue { parameter_id: (*parameter_id).to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(*value)), - } - }) + value: Some(parameter_value::Value::UnsignedInteger(*value)), + }, + ) .collect(), } } @@ -3183,15 +3180,15 @@ fn synthetic_boolean_engine_release() -> EngineRelease { .as_mut() .expect("fixture schema") .parameters - .push(dotcore_proto::dotcore::catalog::v1::EngineParameterDefinition { + .push(dotcore_proto::dotcore::catalog::v1::ParameterDefinition { parameter_id: "feature-enabled".to_owned(), display_name: "Feature enabled".to_owned(), parameter_type: Some( - dotcore_proto::dotcore::catalog::v1::engine_parameter_definition::ParameterType::Boolean( - dotcore_proto::dotcore::catalog::v1::BooleanEngineParameterSchema {}, + dotcore_proto::dotcore::catalog::v1::parameter_definition::ParameterType::Boolean( + dotcore_proto::dotcore::catalog::v1::BooleanParameterSchema::default(), ), ), - exposed: true, + visibility: ParameterVisibility::Advanced as i32, description: "Enables the synthetic feature.".to_owned(), }); engine @@ -3205,10 +3202,10 @@ fn synthetic_boolean_model() -> Model { .as_mut() .expect("fixture defaults") .values - .push(dotcore_proto::dotcore::catalog::v1::EngineParameterValue { + .push(dotcore_proto::dotcore::catalog::v1::ParameterValue { parameter_id: "feature-enabled".to_owned(), value: Some( - dotcore_proto::dotcore::catalog::v1::engine_parameter_value::Value::Boolean(false), + dotcore_proto::dotcore::catalog::v1::parameter_value::Value::Boolean(false), ), }); profile.exposed_parameter_ids = vec!["total-context".to_owned(), "feature-enabled".to_owned()]; @@ -3225,7 +3222,7 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: minimum: "1024" maximum: "16777216" @@ -3233,14 +3230,14 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: minimum: "1024" maximum: "16777216" unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: minimum: "1" maximum: "64" @@ -3248,6 +3245,7 @@ parameterSchema: defaultValue: "4" - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: minimum: "0" maximum: "65536" diff --git a/backend/core/tests/gated/apple_hardware_integration.rs b/backend/core/tests/gated/apple_hardware_integration.rs index 06e82b13..4a21cb6c 100644 --- a/backend/core/tests/gated/apple_hardware_integration.rs +++ b/backend/core/tests/gated/apple_hardware_integration.rs @@ -25,7 +25,7 @@ use dotcore_node_hardware::{ hardware::{SystemHardwareSnapshotCollector, SystemNvidiaAcceleratorAdapter}, }; use dotcore_proto::dotcore::{ - catalog::v1::engine_parameter_value, + catalog::v1::parameter_value, deployment::v1::accelerator_memory_observation, model::v1::{ CreateLocalModelDeploymentRequest, CreateModelDeploymentRequest, DirectRouteExposure, @@ -646,7 +646,7 @@ fn model_configuration() -> LocalModelDeploymentConfiguration { .iter_mut() .find(|value| value.parameter_id == "prompt-cache-memory-mib") .expect("prompt cache parameter value"); - prompt_cache.value = Some(engine_parameter_value::Value::UnsignedInteger( + prompt_cache.value = Some(parameter_value::Value::UnsignedInteger( PROMPT_CACHE_MEMORY_MIB, )); configuration diff --git a/backend/core/tests/gated/decision_requests.rs b/backend/core/tests/gated/decision_requests.rs index 5a857b2c..294ecea0 100644 --- a/backend/core/tests/gated/decision_requests.rs +++ b/backend/core/tests/gated/decision_requests.rs @@ -5,7 +5,7 @@ //! and check the response structure and error shapes. Model probabilities are never asserted. use dotcore_proto::dotcore::{ - catalog::v1::engine_parameter_value, model::v1::LocalModelDeploymentConfiguration, + catalog::v1::parameter_value, model::v1::LocalModelDeploymentConfiguration, }; use serde_json::{Value, json}; @@ -39,7 +39,7 @@ pub fn decision_model_configuration() -> LocalModelDeploymentConfiguration { .iter_mut() .find(|value| value.parameter_id == "parallel-requests") .expect("parallel requests parameter value") - .value = Some(engine_parameter_value::Value::UnsignedInteger(1)); + .value = Some(parameter_value::Value::UnsignedInteger(1)); configuration } diff --git a/backend/core/tests/gated/nvidia_qualification.rs b/backend/core/tests/gated/nvidia_qualification.rs index b048dd42..a49ddc0e 100644 --- a/backend/core/tests/gated/nvidia_qualification.rs +++ b/backend/core/tests/gated/nvidia_qualification.rs @@ -46,8 +46,8 @@ use dotcore_node_hardware::hardware::{ use dotcore_proto::dotcore::{ capacity::v1::{MemoryPoolKind, MemorySegmentSource}, catalog::v1::{ - EngineArtifact, EngineParameterValue, engine_artifact::Kind as EngineArtifactKind, - engine_parameter_value, nix_artifact::Provides, + EngineArtifact, ParameterValue, engine_artifact::Kind as EngineArtifactKind, + nix_artifact::Provides, parameter_value, }, deployment::v1::{ ArtifactPreparationPolicy, ExactPlacement, NodeResolvedLaunchIdentity, @@ -959,9 +959,9 @@ fn configuration_at( values .values .retain(|value| value.parameter_id != "total-context"); - values.values.push(EngineParameterValue { + values.values.push(ParameterValue { parameter_id: "total-context".to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(u64::from( + value: Some(parameter_value::Value::UnsignedInteger(u64::from( total_context, ))), }); diff --git a/backend/core/tests/multi_node/remote_model_lifecycle.rs b/backend/core/tests/multi_node/remote_model_lifecycle.rs index 07bf820a..f0aafb98 100644 --- a/backend/core/tests/multi_node/remote_model_lifecycle.rs +++ b/backend/core/tests/multi_node/remote_model_lifecycle.rs @@ -1645,18 +1645,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } artifacts: - artifactId: "fixture-dev-linux" diff --git a/backend/core/tests/support/mod.rs b/backend/core/tests/support/mod.rs index a38c2c73..3bdc577f 100644 --- a/backend/core/tests/support/mod.rs +++ b/backend/core/tests/support/mod.rs @@ -35,9 +35,7 @@ use dotcore_domain::{ use dotcore_node_hardware::MachineDescription; use dotcore_proto::{ dotcore::{ - catalog::v1::{ - EngineParameterValue, EngineParameterValues, OciImageReference, engine_parameter_value, - }, + catalog::v1::{OciImageReference, ParameterValue, ParameterValues, parameter_value}, inference::v1::{ListRoutesRequest, route_service_client::RouteServiceClient}, model::v1::{ CreateLocalModelDeploymentRequest, CreateModelDeploymentRequest, DirectRouteExposure, @@ -142,16 +140,16 @@ pub fn local_model_configuration( ) -> dotcore_proto::dotcore::model::v1::LocalModelDeploymentConfiguration { dotcore_proto::dotcore::model::v1::LocalModelDeploymentConfiguration { model_artifact_binding_id: binding_id.to_owned(), - engine_parameter_values: Some(EngineParameterValues { + engine_parameter_values: Some(ParameterValues { values: [ ("total-context", total_context), ("prompt-cache-memory-mib", 0), ("parallel-requests", 4), ] .into_iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: parameter_id.to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(value)), + value: Some(parameter_value::Value::UnsignedInteger(value)), }) .collect(), }), @@ -2918,18 +2916,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } artifacts: - artifactId: "fixture-metal" diff --git a/backend/domain/src/test_support/model.rs b/backend/domain/src/test_support/model.rs index acbbb95f..9d7ed1aa 100644 --- a/backend/domain/src/test_support/model.rs +++ b/backend/domain/src/test_support/model.rs @@ -3,12 +3,12 @@ use dotcore_proto::dotcore::{ catalog::v1::{ - EngineArtifact, EngineParameterDefinition, EngineParameterSchema, EngineParameterValue, - EngineParameterValues, HardwareRequirements, HuggingFaceArtifactSource, + EngineArtifact, EngineParameterSchema, HardwareRequirements, HuggingFaceArtifactSource, HuggingFaceFileArtifact, InferenceRequestKind, ModelArtifact, ModelExecutionCapabilities, - ModelInputCapabilities, ModelInputModality, ModelParallelShape, OciPlatform, Selector, - UnsignedIntegerEngineParameterSchema, engine_parameter_definition, engine_parameter_value, - hugging_face_artifact_source, + ModelInputCapabilities, ModelInputModality, ModelParallelShape, OciPlatform, + ParameterDefinition, ParameterValue, ParameterValues, ParameterVisibility, Selector, + UnsignedIntegerParameterSchema, hugging_face_artifact_source, parameter_definition, + parameter_value, }, deployment::v1::ArtifactPreparationPolicy, engine::{ @@ -217,13 +217,13 @@ pub fn local_model_configuration() -> LocalModelDeploymentConfiguration { } } -fn unsigned_values(values: &[(&str, u64)]) -> EngineParameterValues { - EngineParameterValues { +fn unsigned_values(values: &[(&str, u64)]) -> ParameterValues { + ParameterValues { values: values .iter() - .map(|(parameter_id, value)| EngineParameterValue { + .map(|(parameter_id, value)| ParameterValue { parameter_id: (*parameter_id).to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(*value)), + value: Some(parameter_value::Value::UnsignedInteger(*value)), }) .collect(), } @@ -255,19 +255,22 @@ fn unsigned_parameter( minimum: u64, maximum: u64, unit: &str, -) -> EngineParameterDefinition { - EngineParameterDefinition { +) -> ParameterDefinition { + ParameterDefinition { parameter_id: parameter_id.to_owned(), display_name: display_name.to_owned(), - parameter_type: Some(engine_parameter_definition::ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + parameter_type: Some(parameter_definition::ParameterType::UnsignedInteger( + UnsignedIntegerParameterSchema { minimum, maximum, unit: unit.to_owned(), default_value: None, }, )), - exposed: true, + visibility: match parameter_id { + "total-context" | "context-per-request" => ParameterVisibility::Basic, + _ => ParameterVisibility::Advanced, + } as i32, description: String::new(), } } diff --git a/backend/fixtures/development-catalog/engines/fixture.yaml b/backend/fixtures/development-catalog/engines/fixture.yaml index e883bed8..0a2855f2 100644 --- a/backend/fixtures/development-catalog/engines/fixture.yaml +++ b/backend/fixtures/development-catalog/engines/fixture.yaml @@ -6,18 +6,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } storageBindings: - bindingName: "compile-cache" diff --git a/backend/fixtures/recommendation-catalog/engines/llama.yaml b/backend/fixtures/recommendation-catalog/engines/llama.yaml index d8fedf34..8fba6adb 100644 --- a/backend/fixtures/recommendation-catalog/engines/llama.yaml +++ b/backend/fixtures/recommendation-catalog/engines/llama.yaml @@ -4,10 +4,10 @@ version: "1" parameterSchema: schemaId: "llama-v2" parameters: - - { parameterId: "total-context", displayName: "Total context", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } - - { parameterId: "context-per-request", displayName: "Context per request", exposed: true, unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } - - { parameterId: "parallel-requests", displayName: "Parallel requests", exposed: true, unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } - - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } + - { parameterId: "total-context", displayName: "Total context", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } } + - { parameterId: "context-per-request", displayName: "Context per request", visibility: "PARAMETER_VISIBILITY_BASIC", unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } } + - { parameterId: "parallel-requests", displayName: "Parallel requests", visibility: "PARAMETER_VISIBILITY_ADVANCED", unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } } + - { parameterId: "prompt-cache-memory-mib", displayName: "Prompt cache memory", visibility: "PARAMETER_VISIBILITY_HIDDEN", unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } } artifacts: - artifactId: "linux-amd64" oci: diff --git a/backend/fixtures/simulated-docker-site/catalog/engines/fixture.yaml b/backend/fixtures/simulated-docker-site/catalog/engines/fixture.yaml index c71c03dc..7d8a5cb4 100644 --- a/backend/fixtures/simulated-docker-site/catalog/engines/fixture.yaml +++ b/backend/fixtures/simulated-docker-site/catalog/engines/fixture.yaml @@ -6,18 +6,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } artifacts: - artifactId: "fixture-linux" diff --git a/backend/fixtures/simulated-site/catalog/engines/fixture.yaml b/backend/fixtures/simulated-site/catalog/engines/fixture.yaml index c71c03dc..7d8a5cb4 100644 --- a/backend/fixtures/simulated-site/catalog/engines/fixture.yaml +++ b/backend/fixtures/simulated-site/catalog/engines/fixture.yaml @@ -6,18 +6,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "4" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } artifacts: - artifactId: "fixture-linux" diff --git a/backend/fixtures/sizing-fit/catalog/engines/llama-cpp-linux-2026-10-19.yaml b/backend/fixtures/sizing-fit/catalog/engines/llama-cpp-linux-2026-10-19.yaml index 38aeae74..147f0e2d 100644 --- a/backend/fixtures/sizing-fit/catalog/engines/llama-cpp-linux-2026-10-19.yaml +++ b/backend/fixtures/sizing-fit/catalog/engines/llama-cpp-linux-2026-10-19.yaml @@ -7,18 +7,19 @@ parameterSchema: parameters: - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens", defaultValue: "32768" } - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1024", maximum: "16777216", unit: "tokens" } - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" unsignedInteger: { minimum: "1", maximum: "64", unit: "requests", defaultValue: "1" } - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" + visibility: "PARAMETER_VISIBILITY_HIDDEN" unsignedInteger: { minimum: "0", maximum: "65536", unit: "MiB" } artifacts: - artifactId: "cuda13" diff --git a/backend/proto/tests/model_contract.rs b/backend/proto/tests/model_contract.rs index e7d72a5c..02753841 100644 --- a/backend/proto/tests/model_contract.rs +++ b/backend/proto/tests/model_contract.rs @@ -15,20 +15,19 @@ use dotcore_proto::{ }, catalog::v1::{ ApplicationServiceArtifact, BooleanModelOptionParameterSchema, EngineArtifact, - EngineArtifactReference, EngineParameterDefinition, EngineParameterSchema, - EngineParameterValue, EngineParameterValues, EngineRelease, Model, ModelArtifact, + EngineArtifactReference, EngineParameterSchema, EngineRelease, Model, ModelArtifact, ModelArtifactBinding, ModelAuxiliaryArtifact, ModelConfigurationOption, ModelEngineConfiguration, ModelExecutionCapabilities, ModelInputCapabilities, ModelInputModality, ModelOption, ModelOptionParameterDefinition, ModelOptionParameterValue, ModelOptionValues, ModelParallelShape, ModelProfile, - OciImageReference, OciPlatform, Selector, StringEnumModelOptionParameterSchema, - UnsignedIntegerEngineParameterSchema, UnsignedIntegerModelOptionParameterSchema, - VisionModelOption, engine_artifact, - engine_parameter_definition::ParameterType as EngineParameterType, - engine_parameter_value::Value as EngineParameterValueKind, - model_option::Kind as ModelOptionKind, + OciImageReference, OciPlatform, ParameterDefinition, ParameterValue, ParameterValues, + ParameterVisibility, Selector, StringEnumModelOptionParameterSchema, + UnsignedIntegerModelOptionParameterSchema, UnsignedIntegerParameterSchema, + VisionModelOption, engine_artifact, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, model_option_parameter_value::Value as ModelOptionValueKind, + parameter_definition::ParameterType as EngineParameterType, + parameter_value::Value as EngineParameterValueKind, }, deployment::v1::{ArtifactPreparationPolicy, MemoryFit}, engine::{ @@ -238,8 +237,8 @@ fn generated_bindings_preserve_typed_status_and_byte_progress() { #[test] fn generated_bindings_preserve_exact_ordered_custom_argument_tokens_in_preview_and_snapshot() { - let context_values = EngineParameterValues { - values: vec![EngineParameterValue { + let context_values = ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(30_000)), }], @@ -337,18 +336,18 @@ fn generated_bindings_preserve_exact_ordered_custom_argument_tokens_in_preview_a engine_parameter_schema_id: "llama-cpp-b10156-v1".to_owned(), engine_parameter_schema: Some(EngineParameterSchema { schema_id: "llama-cpp-b10156-v1".to_owned(), - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: "total-context".to_owned(), display_name: "Total context".to_owned(), parameter_type: Some(EngineParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 1, maximum: 131_072, unit: "tokens".to_owned(), default_value: None, }, )), - exposed: true, + visibility: ParameterVisibility::Basic as i32, description: "Maximum prompt and generation context.".to_owned(), }], }), @@ -427,8 +426,8 @@ fn generated_bindings_preserve_exact_ordered_custom_argument_tokens_in_preview_a fn generated_bindings_preserve_minimal_generic_resource_estimates() { let configuration = dotcore_proto::dotcore::model::v1::LocalModelDeploymentConfiguration { model_artifact_binding_id: "q4-k-m".to_owned(), - engine_parameter_values: Some(EngineParameterValues { - values: vec![EngineParameterValue { + engine_parameter_values: Some(ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(30_000)), }], @@ -466,8 +465,8 @@ fn generated_bindings_preserve_minimal_generic_resource_estimates() { unit: "bytes".to_owned(), }, ], - derived_engine_parameter_values: Some(EngineParameterValues { - values: vec![EngineParameterValue { + derived_engine_parameter_values: Some(ParameterValues { + values: vec![ParameterValue { parameter_id: "kv-cache-memory-bytes".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(5_443_884_300)), }], @@ -532,18 +531,18 @@ fn generated_bindings_preserve_minimal_generic_resource_estimates() { fn generated_bindings_round_trip_model_configurations_and_typed_context_schema() { let schema = EngineParameterSchema { schema_id: "llama-cpp-b10156-v1".to_owned(), - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: "total-context".to_owned(), display_name: "Total context".to_owned(), parameter_type: Some(EngineParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + UnsignedIntegerParameterSchema { minimum: 512, maximum: 131_072, unit: "tokens".to_owned(), default_value: None, }, )), - exposed: true, + visibility: ParameterVisibility::Basic as i32, description: "Maximum prompt and generation context.".to_owned(), }], }; @@ -581,8 +580,8 @@ fn generated_bindings_round_trip_model_configurations_and_typed_context_schema() profile_id: "fast-start".to_owned(), configuration_id: "cuda".to_owned(), default_model_artifact_binding_id: "q4-k-m".to_owned(), - engine_parameter_defaults: Some(EngineParameterValues { - values: vec![EngineParameterValue { + engine_parameter_defaults: Some(ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), value: Some(EngineParameterValueKind::UnsignedInteger(30_000)), }], @@ -867,6 +866,7 @@ parameterSchema: parameters: - parameterId: total-context displayName: Total context + visibility: "PARAMETER_VISIBILITY_BASIC" unsignedInteger: { minimum: "1", maximum: "2", unit: tokens } "#, ) @@ -928,6 +928,7 @@ fn model_descriptors_define_typed_configuration_and_resolved_plan_contracts() { .expect("the generated descriptor set must decode"); let application = descriptor_file(&descriptor, "dotcore/catalog/v1/application.proto"); let engine = descriptor_file(&descriptor, "dotcore/catalog/v1/engine_release.proto"); + let parameter = descriptor_file(&descriptor, "dotcore/catalog/v1/parameter.proto"); let nix = descriptor_file(&descriptor, "dotcore/catalog/v1/nix.proto"); let selector = descriptor_file(&descriptor, "dotcore/catalog/v1/selector.proto"); let catalog = descriptor_file(&descriptor, "dotcore/catalog/v1/model.proto"); @@ -996,34 +997,40 @@ fn model_descriptors_define_typed_configuration_and_resolved_plan_contracts() { field_layout(engine, "EngineParameterSchema"), [ ("schema_id", 1, "TYPE_STRING"), - ( - "parameters", - 2, - ".dotcore.catalog.v1.EngineParameterDefinition" - ), + ("parameters", 2, ".dotcore.catalog.v1.ParameterDefinition"), ] ); assert_eq!( - field_layout(engine, "EngineParameterDefinition"), + field_layout(parameter, "ParameterDefinition"), [ ("parameter_id", 1, "TYPE_STRING"), ("display_name", 2, "TYPE_STRING"), + ("description", 3, "TYPE_STRING"), + ("visibility", 7, ".dotcore.catalog.v1.ParameterVisibility"), + ("boolean", 4, ".dotcore.catalog.v1.BooleanParameterSchema"), ( "unsigned_integer", - 3, - ".dotcore.catalog.v1.UnsignedIntegerEngineParameterSchema" + 5, + ".dotcore.catalog.v1.UnsignedIntegerParameterSchema" ), ( - "boolean", - 4, - ".dotcore.catalog.v1.BooleanEngineParameterSchema", + "string_enum", + 6, + ".dotcore.catalog.v1.StringEnumParameterSchema" ), - ("exposed", 5, "TYPE_BOOL"), - ("description", 6, "TYPE_STRING"), ] ); assert_eq!( - field_numbers(engine, "UnsignedIntegerEngineParameterSchema"), + enum_values(parameter, "ParameterVisibility"), + [ + ("PARAMETER_VISIBILITY_UNSPECIFIED", 0), + ("PARAMETER_VISIBILITY_BASIC", 1), + ("PARAMETER_VISIBILITY_ADVANCED", 2), + ("PARAMETER_VISIBILITY_HIDDEN", 3), + ] + ); + assert_eq!( + field_numbers(parameter, "UnsignedIntegerParameterSchema"), [ ("minimum", 1), ("maximum", 2), @@ -1032,11 +1039,16 @@ fn model_descriptors_define_typed_configuration_and_resolved_plan_contracts() { ] ); assert_eq!( - field_layout(engine, "EngineParameterValue"), + field_layout(parameter, "ParameterValues"), + [("values", 1, ".dotcore.catalog.v1.ParameterValue")] + ); + assert_eq!( + field_layout(parameter, "ParameterValue"), [ ("parameter_id", 1, "TYPE_STRING"), - ("unsigned_integer", 2, "TYPE_UINT64"), - ("boolean", 3, "TYPE_BOOL"), + ("boolean", 2, "TYPE_BOOL"), + ("unsigned_integer", 3, "TYPE_UINT64"), + ("string", 4, "TYPE_STRING"), ] ); @@ -1439,7 +1451,7 @@ fn model_descriptors_define_typed_configuration_and_resolved_plan_contracts() { ( "engine_parameter_values", 3, - ".dotcore.catalog.v1.EngineParameterValues" + ".dotcore.catalog.v1.ParameterValues" ), ( "hardware_class_estimates", diff --git a/backend/proto/tests/site_contract.rs b/backend/proto/tests/site_contract.rs index 5671f938..611ce75a 100644 --- a/backend/proto/tests/site_contract.rs +++ b/backend/proto/tests/site_contract.rs @@ -19,14 +19,15 @@ use dotcore_proto::{ ApplicationEndpointProtocol, ApplicationGraph, ApplicationHttpReadiness, ApplicationPrimaryEndpoint, ApplicationService, ApplicationServiceArtifact, ApplicationServiceDependency, ApplicationServicePort, ApplicationServiceReadiness, - EngineArtifact, EngineParameterDefinition, EngineParameterSchema, EngineParameterValue, - EngineParameterValues, HuggingFaceArtifactSource, HuggingFaceFileArtifact, - ModelArtifact, ModelExecutionCapabilities, ModelInputCapabilities, ModelInputModality, - ModelParallelShape, OciDigest, OciImageReference, OciPlatform, OciRegistryLocation, - OciRepository, Selector, StorageBinding, StorageEnvironmentVariable, StorageKind, - StorageScope, UnsignedIntegerEngineParameterSchema, application_configuration_binding, + EngineArtifact, EngineParameterSchema, HuggingFaceArtifactSource, + HuggingFaceFileArtifact, ModelArtifact, ModelExecutionCapabilities, + ModelInputCapabilities, ModelInputModality, ModelParallelShape, OciDigest, + OciImageReference, OciPlatform, OciRegistryLocation, OciRepository, + ParameterDefinition, ParameterValue, ParameterValues, ParameterVisibility, Selector, + StorageBinding, StorageEnvironmentVariable, StorageKind, StorageScope, + UnsignedIntegerParameterSchema, application_configuration_binding, application_service_artifact, application_service_readiness, engine_artifact, - engine_parameter_definition, engine_parameter_value, hugging_face_artifact_source, + hugging_face_artifact_source, parameter_definition, parameter_value, }, deployment::v1::{ArtifactPreparationPolicy, NodeResolvedLaunchIdentity}, engine::{ @@ -450,21 +451,21 @@ fn complete_model_snapshot() -> ModelDeploymentSnapshot { supported_modalities: vec![ModelInputModality::Text as i32], image_input_capacity: None, }), - engine_parameter_values: Some(EngineParameterValues { - values: vec![EngineParameterValue { + engine_parameter_values: Some(ParameterValues { + values: vec![ParameterValue { parameter_id: "total-context".to_owned(), - value: Some(engine_parameter_value::Value::UnsignedInteger(8_192)), + value: Some(parameter_value::Value::UnsignedInteger(8_192)), }], }), engine_parameter_schema_id: "schema-one".to_owned(), engine_parameter_schema: Some(EngineParameterSchema { schema_id: "schema-one".to_owned(), - parameters: vec![EngineParameterDefinition { + parameters: vec![ParameterDefinition { parameter_id: "total-context".to_owned(), display_name: "Total context".to_owned(), parameter_type: Some( - engine_parameter_definition::ParameterType::UnsignedInteger( - UnsignedIntegerEngineParameterSchema { + parameter_definition::ParameterType::UnsignedInteger( + UnsignedIntegerParameterSchema { minimum: 1, maximum: 131_072, unit: "tokens".to_owned(), @@ -472,7 +473,7 @@ fn complete_model_snapshot() -> ModelDeploymentSnapshot { }, ), ), - exposed: true, + visibility: ParameterVisibility::Basic as i32, description: "Maximum prompt and generation context.".to_owned(), }], }), From f40398bbc25d7bf7dc7031084fc54039103c9bd4 Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 13:38:15 -0500 Subject: [PATCH 03/40] unreviewed: refactor(catalog): declare engine parameter visibility --- catalog/applications/comfyui.yaml | 15 +++++++-------- catalog/engines/llama-cpp-macos.yaml | 8 ++++---- catalog/engines/llama-cpp.yaml | 8 ++++---- catalog/engines/ninfer.yaml | 8 ++++---- catalog/engines/strata.yaml | 8 ++++---- catalog/engines/vllm.yaml | 14 +++++++------- 6 files changed, 30 insertions(+), 31 deletions(-) diff --git a/catalog/applications/comfyui.yaml b/catalog/applications/comfyui.yaml index be1cf7ec..f9a6a363 100644 --- a/catalog/applications/comfyui.yaml +++ b/catalog/applications/comfyui.yaml @@ -12,14 +12,13 @@ notes: |- version: "0.42.5" graph: parameters: - - advanced: true - definition: - parameterId: "vram-mode" - displayName: "VRAM mode" - description: "How ComfyUI keeps models in GPU memory. Auto loads and offloads on demand; modes other than auto need a GPU target." - stringEnum: - values: ["auto", "highvram", "gpu-only", "novram"] - defaultValue: "auto" + - parameterId: "vram-mode" + displayName: "VRAM mode" + visibility: "PARAMETER_VISIBILITY_ADVANCED" + description: "How ComfyUI keeps models in GPU memory. Auto loads and offloads on demand; modes other than auto need a GPU target." + stringEnum: + values: ["auto", "highvram", "gpu-only", "novram"] + defaultValue: "auto" services: - serviceName: "comfyui" # The image and its digests are pinned by `apps/comfyui/docker-image.nix`. diff --git a/catalog/engines/llama-cpp-macos.yaml b/catalog/engines/llama-cpp-macos.yaml index 0e96f028..63520d32 100644 --- a/catalog/engines/llama-cpp-macos.yaml +++ b/catalog/engines/llama-cpp-macos.yaml @@ -11,7 +11,7 @@ parameterSchema: # Shared parameters: the engine adapter in backend/core/src/model/engine/ maps them to flags. - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Context memory the server holds from the start and shares among the requests it generates at once. Each active request stores its own tokens in it, even when requests start with the same prompt. When it fills, the server frees idle requests first, then fails the active ones." unsignedInteger: minimum: "1024" @@ -20,7 +20,7 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the start of an earlier prompt from an idle request or the prompt cache, but not from requests running at the same time." unsignedInteger: minimum: "1024" @@ -28,7 +28,7 @@ parameterSchema: unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Requests the server generates at the same time; further requests wait in a queue. All of them share the total context, so each added request only adds its own small state." unsignedInteger: minimum: "1" @@ -37,7 +37,7 @@ parameterSchema: defaultValue: "4" - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Memory kept to reuse repeated prompts, such as agent system prompts, without processing them again. Idle conversations move here and free their accelerator memory. It uses host memory, which unified-memory machines share with the model; 0 turns the cache off." unsignedInteger: minimum: "0" diff --git a/catalog/engines/llama-cpp.yaml b/catalog/engines/llama-cpp.yaml index 1420bc33..31b2ddb1 100644 --- a/catalog/engines/llama-cpp.yaml +++ b/catalog/engines/llama-cpp.yaml @@ -10,7 +10,7 @@ parameterSchema: # Shared parameters: the engine adapter in backend/core/src/model/engine/ maps them to flags. - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Context memory the server holds from the start and shares among the requests it generates at once. Each active request stores its own tokens in it, even when requests start with the same prompt. When it fills, the server frees idle requests first, then fails the active ones." unsignedInteger: minimum: "1024" @@ -19,7 +19,7 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the start of an earlier prompt from an idle request or the prompt cache, but not from requests running at the same time." unsignedInteger: minimum: "1024" @@ -27,7 +27,7 @@ parameterSchema: unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Requests the server generates at the same time; further requests wait in a queue. All of them share the total context, so each added request only adds its own small state." unsignedInteger: minimum: "1" @@ -36,7 +36,7 @@ parameterSchema: defaultValue: "4" - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Memory kept to reuse repeated prompts, such as agent system prompts, without processing them again. Idle conversations move here and free their accelerator memory. It uses host memory, which unified-memory machines share with the model; 0 turns the cache off." unsignedInteger: minimum: "0" diff --git a/catalog/engines/ninfer.yaml b/catalog/engines/ninfer.yaml index db8acab2..45337575 100644 --- a/catalog/engines/ninfer.yaml +++ b/catalog/engines/ninfer.yaml @@ -10,7 +10,7 @@ parameterSchema: # Shared parameters: the engine adapter in backend/core/src/model/engine/ maps them to flags. - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Context memory the server holds from the start and shares among the requests it generates at once. Requests that start with the same prompt share its memory instead of holding their own copy. When it fills, the server first moves cached prompts to host memory, then pauses the newest requests until memory frees up." unsignedInteger: minimum: "1024" @@ -19,7 +19,7 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the memory of a matching prompt start, from a running request, an idle conversation or the host context." unsignedInteger: minimum: "1024" @@ -27,7 +27,7 @@ parameterSchema: unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Requests the server generates at the same time; further requests wait in a queue, and the server refuses new ones once the queue is full. Each added request also adds its own state on the accelerator." unsignedInteger: minimum: "1" @@ -36,7 +36,7 @@ parameterSchema: defaultValue: "4" - parameterId: "host-context-mib" displayName: "Host context memory" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Host memory where idle conversations and paused requests are kept, so they resume without processing their prompt again. 0 turns it off." unsignedInteger: minimum: "0" diff --git a/catalog/engines/strata.yaml b/catalog/engines/strata.yaml index 007e2364..50fb61bc 100644 --- a/catalog/engines/strata.yaml +++ b/catalog/engines/strata.yaml @@ -10,7 +10,7 @@ parameterSchema: # Shared parameters: the engine adapter in backend/core/src/model/engine/ maps them to flags. - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Context memory the server holds from the start. Each parallel request keeps its own part of it, as large as the context per request, so it is always the parallel requests times the context per request." unsignedInteger: minimum: "1024" @@ -19,7 +19,7 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Largest context one request may use. The server holds this much context for each parallel request from the start, whether a request uses it or not." unsignedInteger: minimum: "1024" @@ -27,7 +27,7 @@ parameterSchema: unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Requests the server generates at the same time; further requests wait for a free one. Each one holds its own context per request." unsignedInteger: minimum: "1" @@ -36,7 +36,7 @@ parameterSchema: defaultValue: "1" - parameterId: "expert-vram-mib" displayName: "Expert accelerator memory" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Accelerator memory the model's experts may use; the experts that don't fit stay in host memory. The model's sizing sets it unless you do." unsignedInteger: minimum: "1" diff --git a/catalog/engines/vllm.yaml b/catalog/engines/vllm.yaml index 7a0d09e9..ce4dfe10 100644 --- a/catalog/engines/vllm.yaml +++ b/catalog/engines/vllm.yaml @@ -10,7 +10,7 @@ parameterSchema: # Shared parameters: the engine adapter in backend/core/src/model/engine/ maps them to flags. - parameterId: "total-context" displayName: "Total context" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Context memory the server holds from the start and shares among the requests it generates at once. Requests that start with the same prompt share its memory instead of holding their own copy. When it fills, the server pauses the newest requests and processes them again once memory frees up." unsignedInteger: minimum: "1024" @@ -19,7 +19,7 @@ parameterSchema: defaultValue: "32768" - parameterId: "context-per-request" displayName: "Context per request" - exposed: true + visibility: "PARAMETER_VISIBILITY_BASIC" description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the memory of a matching prompt start, from a running request, a finished one still held in the total context, or the KV offloading memory." unsignedInteger: minimum: "1024" @@ -27,7 +27,7 @@ parameterSchema: unit: "tokens" - parameterId: "parallel-requests" displayName: "Parallel requests" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Requests the server generates at the same time; further requests wait in a queue. They share the total context, and each one also holds model state of its own, so every added request adds memory." unsignedInteger: minimum: "1" @@ -36,7 +36,7 @@ parameterSchema: defaultValue: "4" - parameterId: "maximum-batched-tokens" displayName: "Maximum batched tokens" - exposed: false + visibility: "PARAMETER_VISIBILITY_HIDDEN" description: "Maximum tokens processed across one scheduled batch." unsignedInteger: minimum: "1" @@ -44,7 +44,7 @@ parameterSchema: unit: "tokens" - parameterId: "maximum-cudagraph-capture-size" displayName: "Maximum CUDA graph capture size" - exposed: false + visibility: "PARAMETER_VISIBILITY_HIDDEN" description: "Largest sequence batch captured in a CUDA graph." unsignedInteger: minimum: "1" @@ -52,7 +52,7 @@ parameterSchema: unit: "sequences" - parameterId: "kv-cache-memory-bytes" displayName: "KV cache memory" - exposed: false + visibility: "PARAMETER_VISIBILITY_HIDDEN" description: "Accelerator memory reserved for the total context, in bytes." unsignedInteger: minimum: "1" @@ -60,7 +60,7 @@ parameterSchema: unit: "bytes" - parameterId: "kv-offloading-size-gib" displayName: "KV offloading size" - exposed: true + visibility: "PARAMETER_VISIBILITY_ADVANCED" description: "Host memory where context evicted from the total context is kept, so a later request with the same prompt start reuses it instead of processing it again, in GiB. 0 turns it off." unsignedInteger: minimum: "0" From 5a800b3afe70a24e6fc674da647fe92906c5d230 Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 13:40:27 -0500 Subject: [PATCH 04/40] unreviewed: refactor(frontend): read engine parameters through the shared definition --- .../application-deploy-dialog.test.tsx | 39 ++++---- .../application-inspector.test.tsx | 24 +++-- .../applications/application-parameters.ts | 21 +++-- .../catalog/catalog-table-test-support.ts | 6 +- .../catalog/model-catalog-page.test.tsx | 3 +- .../deploy/model-deploy-context-step.tsx | 16 ++-- .../deploy/model-deploy-dialog.test.tsx | 6 +- .../models/deploy/model-deploy-launch.ts | 12 +-- .../deploy/model-deploy-runtime-step.tsx | 10 +- .../deploy/model-deploy-scenario.test.tsx | 6 +- .../models/deploy/use-model-deploy-form.ts | 21 ++--- .../deploy/use-model-deploy-memory-preview.ts | 13 +-- .../deploy/use-resource-estimate.test.tsx | 4 +- .../models/inspector/deployment-overview.tsx | 4 +- .../models/inspector/model-inspector.test.tsx | 8 +- .../src/features/models/model-test-support.ts | 9 +- .../models/profiles/profile-compatibility.ts | 4 +- .../models/runtime/context-size-field.tsx | 8 +- .../runtime/engine-parameter-values.test.ts | 77 +++++++++++++++- .../models/runtime/engine-parameter-values.ts | 92 +++++++++++-------- .../models/runtime/engine-parameters.tsx | 17 ++-- .../runtime/local-deployment-configuration.ts | 13 +-- .../runtime/runtime-schema-test-support.ts | 3 +- 23 files changed, 243 insertions(+), 173 deletions(-) diff --git a/frontend/src/features/applications/application-deploy-dialog.test.tsx b/frontend/src/features/applications/application-deploy-dialog.test.tsx index f16236ed..dffc4a45 100644 --- a/frontend/src/features/applications/application-deploy-dialog.test.tsx +++ b/frontend/src/features/applications/application-deploy-dialog.test.tsx @@ -13,7 +13,6 @@ import { ApplicationConfigurationBindingSchema, ApplicationDeploymentInputSchema, ApplicationGraphSchema, - ApplicationParameterSchema, ApplicationSchema, ApplicationServiceSchema, } from "@/gen/dotcore/catalog/v1/application_pb"; @@ -24,6 +23,7 @@ import { import { ParameterDefinitionSchema, ParameterValueSchema, + ParameterVisibility, } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { InferenceRouteAvailabilitySchema, @@ -1372,27 +1372,24 @@ describe("Application deployment dialog parameters", () => { version: "1.0.0", graph: create(ApplicationGraphSchema, { parameters: [ - create(ApplicationParameterSchema, { - advanced: true, - definition: create(ParameterDefinitionSchema, { - parameterId: "vram-mode", - displayName: "VRAM mode", - description: "How models stay in GPU memory.", - parameterType: { - case: "stringEnum", - value: { values: ["auto", "highvram"], defaultValue: "auto" }, - }, - }), + create(ParameterDefinitionSchema, { + parameterId: "vram-mode", + displayName: "VRAM mode", + description: "How models stay in GPU memory.", + visibility: ParameterVisibility.ADVANCED, + parameterType: { + case: "stringEnum", + value: { values: ["auto", "highvram"], defaultValue: "auto" }, + }, }), - create(ApplicationParameterSchema, { - definition: create(ParameterDefinitionSchema, { - parameterId: "workers", - displayName: "Workers", - parameterType: { - case: "unsignedInteger", - value: { minimum: 1n, maximum: 8n, unit: "", defaultValue: 2n }, - }, - }), + create(ParameterDefinitionSchema, { + parameterId: "workers", + displayName: "Workers", + visibility: ParameterVisibility.BASIC, + parameterType: { + case: "unsignedInteger", + value: { minimum: 1n, maximum: 8n, unit: "", defaultValue: 2n }, + }, }), ], }), diff --git a/frontend/src/features/applications/application-inspector.test.tsx b/frontend/src/features/applications/application-inspector.test.tsx index 3489016c..d352ed88 100644 --- a/frontend/src/features/applications/application-inspector.test.tsx +++ b/frontend/src/features/applications/application-inspector.test.tsx @@ -26,6 +26,7 @@ import { ApplicationSchema, ApplicationServiceSchema, } from "@/gen/dotcore/catalog/v1/application_pb"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { type AcceleratorMemoryObservation, AcceleratorMemoryObservationSchema, @@ -516,22 +517,19 @@ describe("Application deployment dialog", () => { graph: create(ApplicationGraphSchema, { parameters: [ { - advanced: true, - definition: { - parameterId: "vram-mode", - displayName: "VRAM mode", - parameterType: { - case: "stringEnum", - value: { values: ["auto", "highvram"], defaultValue: "auto" }, - }, + parameterId: "vram-mode", + displayName: "VRAM mode", + visibility: ParameterVisibility.ADVANCED, + parameterType: { + case: "stringEnum", + value: { values: ["auto", "highvram"], defaultValue: "auto" }, }, }, { - definition: { - parameterId: "preview", - displayName: "Previews", - parameterType: { case: "boolean", value: { defaultValue: false } }, - }, + parameterId: "preview", + displayName: "Previews", + visibility: ParameterVisibility.BASIC, + parameterType: { case: "boolean", value: { defaultValue: false } }, }, ], }), diff --git a/frontend/src/features/applications/application-parameters.ts b/frontend/src/features/applications/application-parameters.ts index 5d298a0c..aa2bb832 100644 --- a/frontend/src/features/applications/application-parameters.ts +++ b/frontend/src/features/applications/application-parameters.ts @@ -2,8 +2,12 @@ import { create } from "@bufbuild/protobuf"; import type { ParameterView, ParameterViewValue } from "@/components/parameters/parameter-view"; import type { ResolvedApplicationDeploymentSnapshot } from "@/gen/dotcore/application/v1/deployment_pb"; -import type { ApplicationParameter } from "@/gen/dotcore/catalog/v1/application_pb"; -import { type ParameterValue, ParameterValueSchema } from "@/gen/dotcore/catalog/v1/parameter_pb"; +import { + type ParameterDefinition, + type ParameterValue, + ParameterValueSchema, + ParameterVisibility, +} from "@/gen/dotcore/catalog/v1/parameter_pb"; /** One application parameter as the deploy dialog shows it, with its catalog default. */ export interface ApplicationParameterField { @@ -14,18 +18,17 @@ export interface ApplicationParameterField { /** The application's parameters in declaration order; malformed declarations are skipped. */ export function applicationParameterFields( - parameters: readonly ApplicationParameter[] | undefined, + parameters: readonly ParameterDefinition[] | undefined, ): ApplicationParameterField[] { - return (parameters ?? []).flatMap((parameter): ApplicationParameterField[] => { - const definition = parameter.definition; - if (!definition) return []; + return (parameters ?? []).flatMap((definition): ApplicationParameterField[] => { + const advanced = definition.visibility === ParameterVisibility.ADVANCED; const base = { id: definition.parameterId, label: definition.displayName }; const type = definition.parameterType; switch (type.case) { case "boolean": return [ { - advanced: parameter.advanced, + advanced, defaultValue: type.value.defaultValue, view: { ...base, hint: definition.description, type: { kind: "boolean" } }, }, @@ -35,7 +38,7 @@ export function applicationParameterFields( const range = `${minimum}–${maximum}${unit ? ` ${unit}` : ""}`; return [ { - advanced: parameter.advanced, + advanced, defaultValue, view: { ...base, @@ -48,7 +51,7 @@ export function applicationParameterFields( case "stringEnum": return [ { - advanced: parameter.advanced, + advanced, defaultValue: type.value.defaultValue, view: { ...base, diff --git a/frontend/src/features/models/catalog/catalog-table-test-support.ts b/frontend/src/features/models/catalog/catalog-table-test-support.ts index b8093285..9bcef1ba 100644 --- a/frontend/src/features/models/catalog/catalog-table-test-support.ts +++ b/frontend/src/features/models/catalog/catalog-table-test-support.ts @@ -18,6 +18,7 @@ import { ModelSchema, SpeculativeDecodingMethod, } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { EngineKind } from "@/gen/dotcore/engine/v1/engine_pb"; /** @@ -95,14 +96,14 @@ function engineArtifact(artifactId: string, architecture: string) { }; } -// The engine exposes its total context to the profile only when `exposed` is set. +// The engine shows its total context to the profile only when `exposed` is set. function contextParameterSchema(schemaId: string, exposed: boolean): ParameterSchemaInit { return { parameters: [ { displayName: "Total context", - exposed, parameterId: "total-context", + visibility: exposed ? ParameterVisibility.BASIC : ParameterVisibility.HIDDEN, parameterType: { case: "unsignedInteger" as const, value: { maximum: 262144n, minimum: 1024n, unit: "tokens" }, @@ -111,6 +112,7 @@ function contextParameterSchema(schemaId: string, exposed: boolean): ParameterSc { displayName: "Prefix caching", parameterId: "prefix-caching", + visibility: ParameterVisibility.HIDDEN, parameterType: { case: "boolean" as const, value: {} }, }, ], diff --git a/frontend/src/features/models/catalog/model-catalog-page.test.tsx b/frontend/src/features/models/catalog/model-catalog-page.test.tsx index 0af1eb25..85ccda91 100644 --- a/frontend/src/features/models/catalog/model-catalog-page.test.tsx +++ b/frontend/src/features/models/catalog/model-catalog-page.test.tsx @@ -24,6 +24,7 @@ import { driverTooOld, targetCompatibility, } from "@/features/models/profiles/profile-compatibility-test-support"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { ModelDeploymentIntentSchema, ModelDeploymentSchema, @@ -362,7 +363,7 @@ describe("ModelCatalogPage deploy", () => { it("shows the service's reason when it rejects the total context", async () => { const user = setupUser(); const release = llamaRelease(); - release.parameterSchema!.parameters[0].exposed = true; + release.parameterSchema!.parameters[0].visibility = ParameterVisibility.BASIC; const { client } = renderModelsSection({ engineReleases: [release], initialEntry: "/models/catalog", diff --git a/frontend/src/features/models/deploy/model-deploy-context-step.tsx b/frontend/src/features/models/deploy/model-deploy-context-step.tsx index 65eb31a0..a33db7bb 100644 --- a/frontend/src/features/models/deploy/model-deploy-context-step.tsx +++ b/frontend/src/features/models/deploy/model-deploy-context-step.tsx @@ -15,8 +15,8 @@ import { maximumContext, runtimeParameterGroups, } from "@/features/models/runtime/engine-parameter-values"; -import type { EngineParameterDefinition } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { Model, ModelProfile } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterDefinition } from "@/gen/dotcore/catalog/v1/parameter_pb"; import type { FieldErrors } from "@/lib/form-validation"; import { formatCompactCount } from "@/lib/format"; @@ -25,7 +25,7 @@ interface ModelDeployContextStepProps { contextHint?: string; disabled: boolean; engineParameterRefs: RefObject>; - exposedParameters: readonly EngineParameterDefinition[]; + exposedParameters: readonly ParameterDefinition[]; fieldErrors: FieldErrors; /** The context per request the backend fills while the input is empty, from the latest estimate. */ filledContextPerRequest?: number; @@ -33,13 +33,9 @@ interface ModelDeployContextStepProps { /** The largest total context that fits the selected target, offered as the total's last chip. */ largestFit?: ContextSizeLargestFit; model: Model; - onParameterBlur: (parameter: EngineParameterDefinition) => void; + onParameterBlur: (parameter: ParameterDefinition) => void; /** Receives each change, and whether it is settled, as a slider or preset is, or typed. */ - onParameterChange: ( - parameter: EngineParameterDefinition, - input: string, - settled?: boolean, - ) => void; + onParameterChange: (parameter: ParameterDefinition, input: string, settled?: boolean) => void; profile?: ModelProfile; } @@ -73,7 +69,7 @@ export function ModelDeployContextStep({ // Total context and context per request follow each other, so their sliders share one scale. const sliderRange = contextSliderRange([totalContext, contextPerRequest]); const contextField = ( - parameter: EngineParameterDefinition, + parameter: ParameterDefinition, field: { emptyValue?: number; help?: ReactNode; @@ -137,7 +133,7 @@ export function ModelDeployContextStep({ /** The range spanning every given context size parameter's schema range, if any is present. */ function contextSliderRange( - parameters: readonly (EngineParameterDefinition | undefined)[], + parameters: readonly (ParameterDefinition | undefined)[], ): ContextSizeRange | undefined { const ranges = parameters.flatMap((parameter) => parameter?.parameterType.case === "unsignedInteger" diff --git a/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx b/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx index f836813b..46c66b29 100644 --- a/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx +++ b/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx @@ -44,10 +44,10 @@ import { } from "@/features/models/runtime/runtime-schema-test-support"; import { EngineArtifactReferenceSchema, - EngineParameterValueSchema, EngineReleaseSchema, } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { ModelSchema } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterValueSchema } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { MemoryFit } from "@/gen/dotcore/deployment/v1/memory_fit_pb"; import { ExactPlacementSchema } from "@/gen/dotcore/deployment/v1/placement_pb"; import { @@ -1884,11 +1884,11 @@ describe("ModelDeployDialog", () => { engineParameterValues: { values: [ { parameterId: "total-context", value: { case: "unsignedInteger", value: 65536n } }, - create(EngineParameterValueSchema, { + create(ParameterValueSchema, { parameterId: "parallel-requests", value: { case: "unsignedInteger", value: 4n }, }), - create(EngineParameterValueSchema, { + create(ParameterValueSchema, { parameterId: "kv-cache-memory-bytes", value: { case: "unsignedInteger", value: 7400000000n }, }), diff --git a/frontend/src/features/models/deploy/model-deploy-launch.ts b/frontend/src/features/models/deploy/model-deploy-launch.ts index 9422b676..ada91e04 100644 --- a/frontend/src/features/models/deploy/model-deploy-launch.ts +++ b/frontend/src/features/models/deploy/model-deploy-launch.ts @@ -19,11 +19,9 @@ import { TOTAL_CONTEXT_PARAMETER_ID, } from "@/features/models/runtime/engine-parameter-values"; import { defaultSpeculativeChoice } from "@/features/models/runtime/speculative-choice"; -import { - type EngineParameterValues, - type EngineRelease, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import { type EngineRelease } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { type Model, type ModelProfile } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { type ExactPlacement, ExactPlacementSchema, @@ -73,7 +71,7 @@ export const launchRejectionField = "launchRejection"; * context follows the starting value of the target's largest fit until chosen. */ export function useLaunchEngineValues( - scenarioValues: EngineParameterValues | undefined, + scenarioValues: ParameterValues | undefined, engineRelease: EngineRelease | undefined, profile: ModelProfile | undefined, edits: ReadonlyMap, @@ -133,9 +131,9 @@ export function scenarioInput(parameterId: string): ScenarioInput | undefined { } export function withoutUnsetContextPerRequest( - values: EngineParameterValues | undefined, + values: ParameterValues | undefined, scenario: SizingScenario | undefined, -): EngineParameterValues | undefined { +): ParameterValues | undefined { if (!values || scenario?.contextTokensPerRequest !== undefined) return values; return { diff --git a/frontend/src/features/models/deploy/model-deploy-runtime-step.tsx b/frontend/src/features/models/deploy/model-deploy-runtime-step.tsx index 3b73b1d6..b52d5550 100644 --- a/frontend/src/features/models/deploy/model-deploy-runtime-step.tsx +++ b/frontend/src/features/models/deploy/model-deploy-runtime-step.tsx @@ -22,12 +22,12 @@ import type { KvCachePrecisionOption } from "@/features/models/runtime/kv-cache- import { KvCachePrecisionField } from "@/features/models/runtime/kv-cache-precision-field"; import type { SpeculativeChoice } from "@/features/models/runtime/speculative-choice"; import { SpeculativeDecodingField } from "@/features/models/runtime/speculative-decoding-field"; -import type { EngineParameterDefinition } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { Model, ModelEngineConfiguration, ModelProfile, } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterDefinition } from "@/gen/dotcore/catalog/v1/parameter_pb"; import type { FieldErrors } from "@/lib/form-validation"; interface ModelDeployRuntimeStepProps { @@ -45,7 +45,7 @@ interface ModelDeployRuntimeStepProps { engineParameterRefs: RefObject>; /** The engine releases the deployment may run: the target's selected one, or every approved one. */ engineReleases: readonly string[]; - exposedParameters: readonly EngineParameterDefinition[]; + exposedParameters: readonly ParameterDefinition[]; fieldErrors: FieldErrors; inputs: ReadonlyMap; /** Warns that host KV offload shares the accelerator's memory pool on this target. */ @@ -59,8 +59,8 @@ interface ModelDeployRuntimeStepProps { model: Model; onArtifactBlur: () => void; onArtifactChange: (bindingId: string) => void; - onParameterBlur: (parameter: EngineParameterDefinition) => void; - onParameterChange: (parameter: EngineParameterDefinition, input: string) => void; + onParameterBlur: (parameter: ParameterDefinition) => void; + onParameterChange: (parameter: ParameterDefinition, input: string) => void; onPreview: () => void; previewButtonRef: RefObject; previewDisabled: boolean; @@ -122,7 +122,7 @@ export function ModelDeployRuntimeStep({ (candidate) => candidate.artifactId === binding?.modelArtifactId, ); const groups = runtimeParameterGroups(exposedParameters, configuration); - const parametersForm = (parameters: readonly EngineParameterDefinition[]) => ( + const parametersForm = (parameters: readonly ParameterDefinition[]) => ( [value.parameterId, value.value.value]); } diff --git a/frontend/src/features/models/deploy/use-model-deploy-form.ts b/frontend/src/features/models/deploy/use-model-deploy-form.ts index 2881bf1d..36271e99 100644 --- a/frontend/src/features/models/deploy/use-model-deploy-form.ts +++ b/frontend/src/features/models/deploy/use-model-deploy-form.ts @@ -74,13 +74,10 @@ import { speculativeOptionOverrides, } from "@/features/models/runtime/speculative-choice"; import type { ApplicationDeployment } from "@/gen/dotcore/application/v1/deployment_pb"; -import { - type EngineParameterDefinition, - type EngineParameterValues, - type EngineRelease, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import { type EngineRelease } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { HardwareClass } from "@/gen/dotcore/catalog/v1/hardware_class_pb"; import type { Model } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterDefinition, ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import type { ExactPlacement } from "@/gen/dotcore/deployment/v1/placement_pb"; import { type ModelDeployment, @@ -287,9 +284,7 @@ export function useModelDeployForm({ : withoutUnsetContextPerRequest(defaultReadValues, undefined); // The values of a profile's first read under each scenario stay for the dialog's life, so later // reads never swap them under the operator; a new "Sized for" starts from its own read. - const [frozenValues, setFrozenValues] = useState>( - new Map(), - ); + const [frozenValues, setFrozenValues] = useState>(new Map()); const frozenKey = profile ? `${profile.profileId}\0${sizingScenarioKey(scenario)}` : undefined; if (frozenKey && readValues && !frozenValues.has(frozenKey)) setFrozenValues(new Map(frozenValues).set(frozenKey, readValues)); @@ -538,11 +533,7 @@ export function useModelDeployForm({ // chosen ones, starting from what the step shows. A settled change, from a slider or preset, also // moves the other of the two to keep the edited one, and sizes "Sized for" when valid; typing // waits until the input is left. - const changeContext = ( - parameter: EngineParameterDefinition, - nextInput: string, - settled?: boolean, - ) => { + const changeContext = (parameter: ParameterDefinition, nextInput: string, settled?: boolean) => { const edited = scenarioInput(parameter.parameterId); if (!edited) return; @@ -579,7 +570,7 @@ export function useModelDeployForm({ invalidatePreview(); }; // A typed context settles once left, as a settled change does. - const blurContext = (parameter: EngineParameterDefinition) => { + const blurContext = (parameter: ParameterDefinition) => { if (!dirtyFields.isDirty(parameter.parameterId)) return; const edited = scenarioInput(parameter.parameterId); if (edited) setContext((previous) => settledContext(previous, edited)); @@ -605,7 +596,7 @@ export function useModelDeployForm({ const validateRoute = (values = exposureValues, deploymentName = name): string | undefined => validateDeploymentExposure(values, deploymentName, existingRouteNames); const parameterErrors = ( - parameters: readonly EngineParameterDefinition[], + parameters: readonly ParameterDefinition[], ): [string, string | undefined][] => parameters.map((parameter) => [ parameter.parameterId, diff --git a/frontend/src/features/models/deploy/use-model-deploy-memory-preview.ts b/frontend/src/features/models/deploy/use-model-deploy-memory-preview.ts index d4be3eb2..c24bb9f7 100644 --- a/frontend/src/features/models/deploy/use-model-deploy-memory-preview.ts +++ b/frontend/src/features/models/deploy/use-model-deploy-memory-preview.ts @@ -20,11 +20,7 @@ import { speculativeOptionOverrides, } from "@/features/models/runtime/speculative-choice"; import type { ApplicationDeployment } from "@/gen/dotcore/application/v1/deployment_pb"; -import { - type EngineParameterDefinition, - type EngineParameterValues, - type EngineRelease, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import { type EngineRelease } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { Model, ModelArtifactBinding, @@ -32,6 +28,7 @@ import type { ModelOptionValues, ModelProfile, } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterDefinition, ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import type { ExactPlacement } from "@/gen/dotcore/deployment/v1/placement_pb"; import type { ModelDeployment } from "@/gen/dotcore/model/v1/deployment_pb"; import { LocalModelDeploymentAdvisory } from "@/gen/dotcore/model/v1/service_pb"; @@ -276,14 +273,14 @@ export interface ModelDeployMemoryPreviewOptions { compatibilityRead?: ProfileCompatibility; configuration?: ModelEngineConfiguration; customArgumentTokens: string[]; - declaredValues?: EngineParameterValues; + declaredValues?: ParameterValues; deployments?: readonly ModelDeployment[]; /** Parameters catalog sizing derives for the profile, which an empty input leaves to it. */ derivedParameterIds: ReadonlySet; engineParameterInputs: ReadonlyMap; engineRelease?: EngineRelease; engineReleases: readonly EngineRelease[]; - exposedParameters: readonly EngineParameterDefinition[]; + exposedParameters: readonly ParameterDefinition[]; launchValuesPending: boolean; model: Model; name: string; @@ -298,7 +295,7 @@ export interface ModelDeployMemoryPreviewOptions { storedSpeculativeChoice: SpeculativeChoice; targetsLoading: boolean; targetsLoadingPresentation: boolean; - values?: EngineParameterValues; + values?: ParameterValues; } export interface LocalMemoryPreviewValues extends LocalResourceEstimateValues { diff --git a/frontend/src/features/models/deploy/use-resource-estimate.test.tsx b/frontend/src/features/models/deploy/use-resource-estimate.test.tsx index 5dd16c2c..852a1145 100644 --- a/frontend/src/features/models/deploy/use-resource-estimate.test.tsx +++ b/frontend/src/features/models/deploy/use-resource-estimate.test.tsx @@ -6,7 +6,7 @@ import { dedicatedPreview, gib, } from "@/features/models/deploy/memory/model-deploy-memory-test-support"; -import { EngineParameterValuesSchema } from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import { ParameterValuesSchema } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { type ExactPlacement, ExactPlacementSchema, @@ -146,7 +146,7 @@ function request(key: string, target?: string): ResourceEstimateRequest { values: { configuration: { customArgumentTokens: [], - engineParameterValues: create(EngineParameterValuesSchema), + engineParameterValues: create(ParameterValuesSchema), modelArtifactBindingId: `binding-${key}`, optionOverrides: [], }, diff --git a/frontend/src/features/models/inspector/deployment-overview.tsx b/frontend/src/features/models/inspector/deployment-overview.tsx index 61868f19..3c763fe0 100644 --- a/frontend/src/features/models/inspector/deployment-overview.tsx +++ b/frontend/src/features/models/inspector/deployment-overview.tsx @@ -29,8 +29,8 @@ import { TOTAL_CONTEXT_PARAMETER_ID, } from "@/features/models/runtime/engine-parameter-values"; import { deploymentKvCachePrecisionLabel } from "@/features/models/runtime/kv-cache-precision"; -import { type EngineParameterValues } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { type Model } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { type ModelDeployment, type ResolvedLocalModelDeploymentSnapshot, @@ -332,7 +332,7 @@ function ContextDetail({ } function resolvedEngineParameterValue( - values: EngineParameterValues | undefined, + values: ParameterValues | undefined, parameterId: string, ): bigint | undefined { const parameter = values?.values.find( diff --git a/frontend/src/features/models/inspector/model-inspector.test.tsx b/frontend/src/features/models/inspector/model-inspector.test.tsx index 430ac766..1eb10cca 100644 --- a/frontend/src/features/models/inspector/model-inspector.test.tsx +++ b/frontend/src/features/models/inspector/model-inspector.test.tsx @@ -13,8 +13,8 @@ import { } from "@/features/models/model-test-support"; import { projectModelRows } from "@/features/models/profiles/model-row"; import { modelWithKvCachePrecision } from "@/features/models/runtime/runtime-schema-test-support"; -import { EngineParameterValuesSchema } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { ModelSchema, SpeculativeDecodingMethod } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterValuesSchema } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { type ModelDeployment, ModelDeploymentDesiredState, @@ -186,7 +186,7 @@ describe("model inspectors", () => { const withOffload = create(ResolvedLocalModelDeploymentSnapshotSchema, { ...snapshot, engineParameterSchema: kvOffloadReleases[0].parameterSchema, - engineParameterValues: create(EngineParameterValuesSchema, { + engineParameterValues: create(ParameterValuesSchema, { values: [ { parameterId: "total-context", value: { case: "unsignedInteger", value: 8192n } }, { parameterId: "kv-offloading-size-gib", value: { case: "unsignedInteger", value: 16n } }, @@ -235,7 +235,7 @@ describe("model inspectors", () => { const withBoolean = create(ResolvedLocalModelDeploymentSnapshotSchema, { ...snapshot, engineParameterSchema: multiParameterReleases[0].parameterSchema, - engineParameterValues: create(EngineParameterValuesSchema, { + engineParameterValues: create(ParameterValuesSchema, { values: [ { parameterId: "total-context", value: { case: "unsignedInteger", value: 8192n } }, { @@ -570,7 +570,7 @@ describe("model inspectors", () => { ({ derived, perRequest, shown }) => { const resolved = create(ResolvedLocalModelDeploymentSnapshotSchema, { ...snapshot, - engineParameterValues: create(EngineParameterValuesSchema, { + engineParameterValues: create(ParameterValuesSchema, { values: [ { parameterId: "total-context", value: { case: "unsignedInteger", value: 131072n } }, { diff --git a/frontend/src/features/models/model-test-support.ts b/frontend/src/features/models/model-test-support.ts index c10b16dc..32b87c51 100644 --- a/frontend/src/features/models/model-test-support.ts +++ b/frontend/src/features/models/model-test-support.ts @@ -2,6 +2,7 @@ import { create } from "@bufbuild/protobuf"; import { EngineReleaseSchema } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { ModelSchema } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { EngineKind } from "@/gen/dotcore/engine/v1/engine_pb"; import { ResolvedLocalModelDeploymentSnapshotSchema } from "@/gen/dotcore/model/v1/deployment_pb"; import { ScalarResourceEstimateSchema } from "@/gen/dotcore/model/v1/service_pb"; @@ -76,7 +77,7 @@ export const releases = [ { parameterId: "total-context", displayName: "Total context", - exposed: true, + visibility: ParameterVisibility.BASIC, parameterType: { case: "unsignedInteger", value: { minimum: 1024n, maximum: 32768n, unit: "tokens" }, @@ -96,7 +97,7 @@ export const multiParameterReleases = [ { parameterId: "total-context", displayName: "Total context", - exposed: true, + visibility: ParameterVisibility.BASIC, parameterType: { case: "unsignedInteger", value: { minimum: 1024n, maximum: 131072n, unit: "tokens" }, @@ -183,7 +184,7 @@ export const kvOffloadReleases = [ { parameterId: "total-context", displayName: "Total context", - exposed: true, + visibility: ParameterVisibility.BASIC, parameterType: { case: "unsignedInteger", value: { minimum: 1024n, maximum: 131072n, unit: "tokens" }, @@ -191,7 +192,7 @@ export const kvOffloadReleases = [ }, { parameterId: "kv-offloading-size-gib", - exposed: true, + visibility: ParameterVisibility.ADVANCED, displayName: "KV offloading size", parameterType: { case: "unsignedInteger", diff --git a/frontend/src/features/models/profiles/profile-compatibility.ts b/frontend/src/features/models/profiles/profile-compatibility.ts index d77cff53..319fa035 100644 --- a/frontend/src/features/models/profiles/profile-compatibility.ts +++ b/frontend/src/features/models/profiles/profile-compatibility.ts @@ -1,6 +1,6 @@ import { executionTargetKey } from "@/domain/execution-target"; import { CONTEXT_PER_REQUEST_PARAMETER_ID } from "@/features/models/runtime/engine-parameter-values"; -import type { EngineParameterValues } from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { MemoryFit as ProtoMemoryFit } from "@/gen/dotcore/deployment/v1/memory_fit_pb"; import { type ListModelProfileCompatibilityResponse, @@ -90,7 +90,7 @@ export interface ProfileCompatibility { * read for a scenario, hidden parameters included and derived values left out. A profile the * scenario can't serve has no entry. */ - engineValues: ReadonlyMap; + engineValues: ReadonlyMap; /** Evaluated configured model execution targets, ordered by node then target. */ targets: readonly TargetIdentity[]; entries: ReadonlyMap; diff --git a/frontend/src/features/models/runtime/context-size-field.tsx b/frontend/src/features/models/runtime/context-size-field.tsx index 9090de8d..29717800 100644 --- a/frontend/src/features/models/runtime/context-size-field.tsx +++ b/frontend/src/features/models/runtime/context-size-field.tsx @@ -1,7 +1,7 @@ import type { ReactNode, RefObject } from "react"; import { FieldError } from "@/components/ui/field-error"; -import type { EngineParameterDefinition } from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { ParameterDefinition } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { ContextSizeInput, @@ -22,11 +22,11 @@ interface ContextSizeFieldProps { inputRefs: RefObject>; /** The largest size that fits the selected target, offered as the input's last chip. */ largestFit?: ContextSizeLargestFit; - onBlur: (parameter: EngineParameterDefinition) => void; + onBlur: (parameter: ParameterDefinition) => void; /** Receives each change, and whether it is settled rather than typing in progress. */ - onChange: (parameter: EngineParameterDefinition, input: string, settled: boolean) => void; + onChange: (parameter: ParameterDefinition, input: string, settled: boolean) => void; /** An unsigned-integer context size parameter; its schema range bounds every control. */ - parameter: EngineParameterDefinition; + parameter: ParameterDefinition; /** The range the slider is drawn over, shared with other context fields so they line up. */ sliderRange?: ContextSizeRange; } diff --git a/frontend/src/features/models/runtime/engine-parameter-values.test.ts b/frontend/src/features/models/runtime/engine-parameter-values.test.ts index fd8867c0..fde68253 100644 --- a/frontend/src/features/models/runtime/engine-parameter-values.test.ts +++ b/frontend/src/features/models/runtime/engine-parameter-values.test.ts @@ -3,12 +3,14 @@ import { describe, expect, it } from "vitest"; import { EngineReleaseSchema } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import { ModelProfileSchema } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { engineKindLabel } from "../profiles/model-row"; import { effectiveEngineParameters, engineParameterError, engineParameterValues, + profileStartingValues, } from "./engine-parameter-values"; describe("engineKindLabel", () => { @@ -21,7 +23,7 @@ describe("sizing-derived parameters", () => { const unsigned = (parameterId: string, defaultValue?: bigint) => ({ parameterId, displayName: parameterId, - exposed: true, + visibility: ParameterVisibility.ADVANCED, parameterType: { case: "unsignedInteger" as const, value: { minimum: 1n, maximum: 1000n, unit: "MiB", defaultValue }, @@ -68,3 +70,76 @@ describe("sizing-derived parameters", () => { ).toBeUndefined(); }); }); + +describe("starting values", () => { + const release = create(EngineReleaseSchema, { + parameterSchema: { + parameters: [ + { + parameterId: "total-context", + displayName: "Total context", + visibility: ParameterVisibility.BASIC, + parameterType: { + case: "unsignedInteger", + value: { minimum: 1n, maximum: 1000n, unit: "tokens", defaultValue: 100n }, + }, + }, + { + parameterId: "prefix-caching", + displayName: "Prefix caching", + visibility: ParameterVisibility.HIDDEN, + parameterType: { case: "boolean", value: { defaultValue: true } }, + }, + { + parameterId: "flash-attention", + displayName: "Flash attention", + visibility: ParameterVisibility.ADVANCED, + parameterType: { case: "boolean", value: { defaultValue: false } }, + }, + { + parameterId: "no-default", + displayName: "No default", + visibility: ParameterVisibility.ADVANCED, + parameterType: { case: "boolean", value: {} }, + }, + ], + }, + }); + + it("takes the engine default of every typed parameter, booleans included, in schema order", () => { + const values = profileStartingValues(release, create(ModelProfileSchema, {})); + + expect(values?.values.map(({ parameterId, value }) => [parameterId, value])).toEqual([ + ["total-context", { case: "unsignedInteger", value: 100n }], + ["prefix-caching", { case: "boolean", value: true }], + ["flash-attention", { case: "boolean", value: false }], + ]); + }); + + it("keeps a profile's own value over the engine default", () => { + const profile = create(ModelProfileSchema, { + engineParameterDefaults: { + values: [{ parameterId: "prefix-caching", value: { case: "boolean", value: false } }], + }, + }); + + expect( + profileStartingValues(release, profile)?.values.map(({ parameterId, value }) => [ + parameterId, + value, + ]), + ).toEqual([ + ["prefix-caching", { case: "boolean", value: false }], + ["total-context", { case: "unsignedInteger", value: 100n }], + ["flash-attention", { case: "boolean", value: false }], + ]); + }); + + it("shows every parameter that isn't hidden", () => { + expect( + effectiveEngineParameters(release, create(ModelProfileSchema, {})).map( + (parameter) => parameter.parameterId, + ), + ).toEqual(["total-context", "flash-attention", "no-default"]); + }); +}); diff --git a/frontend/src/features/models/runtime/engine-parameter-values.ts b/frontend/src/features/models/runtime/engine-parameter-values.ts index 3c2eefd1..40cc5228 100644 --- a/frontend/src/features/models/runtime/engine-parameter-values.ts +++ b/frontend/src/features/models/runtime/engine-parameter-values.ts @@ -1,14 +1,15 @@ -import type { - EngineParameterDefinition, - EngineParameterValue, - EngineParameterValues, - EngineRelease, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { EngineRelease } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { Model, ModelEngineConfiguration, ModelProfile, } from "@/gen/dotcore/catalog/v1/model_pb"; +import { + type ParameterDefinition, + type ParameterValue, + type ParameterValues, + ParameterVisibility, +} from "@/gen/dotcore/catalog/v1/parameter_pb"; /** The shared engine parameter that sets the total context in tokens, declared by every engine. */ export const TOTAL_CONTEXT_PARAMETER_ID = "total-context"; @@ -36,15 +37,15 @@ export const CONTEXT_PARAMETER_IDS: ReadonlySet = new Set([ */ export interface RuntimeParameterGroups { context: ContextParameterGroup; - hostMemory: EngineParameterDefinition[]; - other: EngineParameterDefinition[]; - parallelRequests?: EngineParameterDefinition; + hostMemory: ParameterDefinition[]; + other: ParameterDefinition[]; + parallelRequests?: ParameterDefinition; } /** The context size parameters a profile exposes; every engine declares both. */ export interface ContextParameterGroup { - contextPerRequest?: EngineParameterDefinition; - totalContext?: EngineParameterDefinition; + contextPerRequest?: ParameterDefinition; + totalContext?: ParameterDefinition; } /** @@ -54,7 +55,7 @@ export interface ContextParameterGroup { * generic group. */ export function runtimeParameterGroups( - parameters: readonly EngineParameterDefinition[], + parameters: readonly ParameterDefinition[], configuration: ModelEngineConfiguration | undefined, ): RuntimeParameterGroups { const hostMemoryIds = hostMemoryParameterIds(configuration); @@ -95,10 +96,10 @@ export function maximumContext( export function effectiveEngineParameters( release: EngineRelease | undefined, profile: ModelProfile | undefined, -): EngineParameterDefinition[] { +): ParameterDefinition[] { const parameters = release?.parameterSchema?.parameters ?? []; if (!profile?.exposedParameterIds.length) - return parameters.filter((parameter) => parameter.exposed); + return parameters.filter((parameter) => parameter.visibility !== ParameterVisibility.HIDDEN); return profile.exposedParameterIds.flatMap((parameterId) => { const parameter = parameters.find((candidate) => candidate.parameterId === parameterId); @@ -113,31 +114,23 @@ export function effectiveEngineParameters( export function profileStartingValues( release: EngineRelease | undefined, profile: ModelProfile | undefined, -): EngineParameterValues | undefined { +): ParameterValues | undefined { if (!profile) return undefined; const values = [...(profile.engineParameterDefaults?.values ?? [])]; for (const parameter of release?.parameterSchema?.parameters ?? []) { - const engineDefault = - parameter.parameterType.case === "unsignedInteger" - ? parameter.parameterType.value.defaultValue - : undefined; + const engineDefault = parameterDefaultValue(parameter); if ( engineDefault !== undefined && !values.some((value) => value.parameterId === parameter.parameterId) ) { - values.push({ - parameterId: parameter.parameterId, - value: { case: "unsignedInteger", value: engineDefault }, - } as EngineParameterValue); + values.push({ parameterId: parameter.parameterId, value: engineDefault } as ParameterValue); } } - return { values } as EngineParameterValues; + return { values } as ParameterValues; } -export function engineParameterInputs( - values: EngineParameterValues | undefined, -): Map { +export function engineParameterInputs(values: ParameterValues | undefined): Map { return new Map( (values?.values ?? []).flatMap((parameter): Array<[string, string]> => { switch (parameter.value.case) { @@ -152,11 +145,11 @@ export function engineParameterInputs( } export function engineParameterValues( - declared: EngineParameterValues | undefined, - parameters: readonly EngineParameterDefinition[], + declared: ParameterValues | undefined, + parameters: readonly ParameterDefinition[], inputs: ReadonlyMap, derived: ReadonlySet = noDerivedParameters, -): EngineParameterValues | undefined { +): ParameterValues | undefined { if (parameters.some((parameter) => engineParameterError(parameter, inputs, derived))) return undefined; @@ -178,7 +171,7 @@ export function engineParameterValues( if (index < 0) values.push(entry!); else values[index] = entry!; } - return { values } as EngineParameterValues; + return { values } as ParameterValues; } /** @@ -187,7 +180,7 @@ export function engineParameterValues( * in `derived` is valid. */ export function engineParameterError( - parameter: EngineParameterDefinition, + parameter: ParameterDefinition, inputs: ReadonlyMap, derived: ReadonlySet = noDerivedParameters, ): string | undefined { @@ -215,7 +208,7 @@ export function engineParameterError( * declares; undefined for the others, whose unit the field shows. The schema description * documents the engine and stays out of the field. */ -export function engineParameterHelp(parameter: EngineParameterDefinition): string | undefined { +export function engineParameterHelp(parameter: ParameterDefinition): string | undefined { return sharedParameterHelp.get(parameter.parameterId); } @@ -242,7 +235,7 @@ const noDerivedParameters: ReadonlySet = new Set(); // An empty context per request or sizing-derived parameter is left out rather than rejected. function omitsOptionalValue( - parameter: EngineParameterDefinition, + parameter: ParameterDefinition, input: string, derived: ReadonlySet, ): boolean { @@ -254,16 +247,16 @@ function omitsOptionalValue( } function editedEngineParameterValue( - parameter: EngineParameterDefinition, + parameter: ParameterDefinition, input: string, -): EngineParameterValue | undefined { +): ParameterValue | undefined { switch (parameter.parameterType.case) { case "boolean": return input === "true" || input === "false" ? ({ parameterId: parameter.parameterId, value: { case: "boolean", value: input === "true" }, - } as EngineParameterValue) + } as ParameterValue) : undefined; case "unsignedInteger": { if (!/^\d+$/.test(input)) return undefined; @@ -273,10 +266,33 @@ function editedEngineParameterValue( ? ({ parameterId: parameter.parameterId, value: { case: "unsignedInteger", value }, - } as EngineParameterValue) + } as ParameterValue) : undefined; } default: return undefined; } } + +// The catalog default of a parameter, mirroring the backend helper; undefined when it declares none. +function parameterDefaultValue( + parameter: ParameterDefinition, +): ParameterValue["value"] | undefined { + const type = parameter.parameterType; + switch (type.case) { + case "boolean": + return type.value.defaultValue === undefined + ? undefined + : { case: "boolean", value: type.value.defaultValue }; + case "unsignedInteger": + return type.value.defaultValue === undefined + ? undefined + : { case: "unsignedInteger", value: type.value.defaultValue }; + case "stringEnum": + return type.value.defaultValue === undefined + ? undefined + : { case: "string", value: type.value.defaultValue }; + default: + return undefined; + } +} diff --git a/frontend/src/features/models/runtime/engine-parameters.tsx b/frontend/src/features/models/runtime/engine-parameters.tsx index c099c46d..6386d7eb 100644 --- a/frontend/src/features/models/runtime/engine-parameters.tsx +++ b/frontend/src/features/models/runtime/engine-parameters.tsx @@ -2,11 +2,8 @@ import type { RefObject } from "react"; import type { ParameterView, ParameterViewValue } from "@/components/parameters/parameter-view"; import { ParametersDetails, ParametersForm } from "@/components/parameters/parameters"; -import type { - EngineParameterDefinition, - EngineParameterSchema, - EngineParameterValues, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { EngineParameterSchema } from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { ParameterDefinition, ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { engineParameterHelp } from "./engine-parameter-values"; @@ -14,9 +11,9 @@ interface EngineParametersFormProps { errors: ReadonlyMap; inputs: ReadonlyMap; inputRefs: RefObject>; - onBlur: (parameter: EngineParameterDefinition) => void; - onChange: (parameter: EngineParameterDefinition, input: string) => void; - parameters: readonly EngineParameterDefinition[]; + onBlur: (parameter: ParameterDefinition) => void; + onChange: (parameter: ParameterDefinition, input: string) => void; + parameters: readonly ParameterDefinition[]; } export function EngineParametersForm({ @@ -53,7 +50,7 @@ export function EngineParametersDetails({ values, }: { schema: EngineParameterSchema | undefined; - values: EngineParameterValues | undefined; + values: ParameterValues | undefined; }) { if (!schema || !values) return null; @@ -66,7 +63,7 @@ export function EngineParametersDetails({ ); } -function engineParameterViews(parameters: readonly EngineParameterDefinition[]): ParameterView[] { +function engineParameterViews(parameters: readonly ParameterDefinition[]): ParameterView[] { return parameters.flatMap((parameter): ParameterView[] => { const base = { hint: engineParameterHelp(parameter), diff --git a/frontend/src/features/models/runtime/local-deployment-configuration.ts b/frontend/src/features/models/runtime/local-deployment-configuration.ts index 87cebffa..b5291412 100644 --- a/frontend/src/features/models/runtime/local-deployment-configuration.ts +++ b/frontend/src/features/models/runtime/local-deployment-configuration.ts @@ -1,9 +1,6 @@ -import type { - EngineParameterDefinition, - EngineParameterValues, - EngineRelease, -} from "@/gen/dotcore/catalog/v1/engine_release_pb"; +import type { EngineRelease } from "@/gen/dotcore/catalog/v1/engine_release_pb"; import type { Model, ModelOptionValues, ModelProfile } from "@/gen/dotcore/catalog/v1/model_pb"; +import type { ParameterDefinition, ParameterValues } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { formatQuantity } from "@/lib/format"; import { @@ -19,7 +16,7 @@ import { /** The configuration of one local model deployment, as the create, preview, and estimate requests carry it. */ export interface LocalDeploymentConfigurationValues { customArgumentTokens: string[]; - engineParameterValues: EngineParameterValues; + engineParameterValues: ParameterValues; modelArtifactBindingId: string; /** Sparse option values layered over the profile's option defaults. */ optionOverrides: ModelOptionValues[]; @@ -30,7 +27,7 @@ export interface LocalDeploymentConfigurationEdits { bindingId: string; customArgumentTokens?: string[]; /** Engine parameter values replacing the profile's defaults, such as those of a sizing scenario. */ - declaredValues?: EngineParameterValues; + declaredValues?: ParameterValues; /** Parameters catalog sizing derives for the profile, which an empty input leaves to it. */ derivedParameterIds?: ReadonlySet; inputs: ReadonlyMap; @@ -197,7 +194,7 @@ function editedParameterLabels( // Formats valid values and keeps an invalid input as typed, so a summary never rounds a value the // form still rejects into a plausible one. function engineParameterInputLabel( - parameter: EngineParameterDefinition, + parameter: ParameterDefinition, inputs: ReadonlyMap, ): string { const input = inputs.get(parameter.parameterId) ?? ""; diff --git a/frontend/src/features/models/runtime/runtime-schema-test-support.ts b/frontend/src/features/models/runtime/runtime-schema-test-support.ts index dfdc7e0c..bb3bccc1 100644 --- a/frontend/src/features/models/runtime/runtime-schema-test-support.ts +++ b/frontend/src/features/models/runtime/runtime-schema-test-support.ts @@ -8,6 +8,7 @@ import { ModelSchema, SpeculativeDecodingMethod, } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { EngineKind } from "@/gen/dotcore/engine/v1/engine_pb"; // Engine releases and a model mirroring the master catalog `catalog/engines/{llama-cpp,vllm,ninfer}.yaml` @@ -333,7 +334,7 @@ function unsignedParameter( return { parameterId, displayName, - exposed, + visibility: exposed ? ParameterVisibility.ADVANCED : ParameterVisibility.HIDDEN, description, parameterType: { case: "unsignedInteger" as const, From a344d5ab5717d454821ebf2c141874e868e9e08b Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 13:51:46 -0500 Subject: [PATCH 05/40] unreviewed: feat(proto): add profile visibility overrides for engine parameters --- .../src/gen/dotcore/catalog/v1/model_pb.ts | 73 +++++++++++++------ proto/dotcore/catalog/v1/model.proto | 14 +++- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/frontend/src/gen/dotcore/catalog/v1/model_pb.ts b/frontend/src/gen/dotcore/catalog/v1/model_pb.ts index d865b4ae..a5cad620 100644 --- a/frontend/src/gen/dotcore/catalog/v1/model_pb.ts +++ b/frontend/src/gen/dotcore/catalog/v1/model_pb.ts @@ -12,7 +12,7 @@ import type { HardwareRequirements } from "./hardware_class_pb"; import { file_dotcore_catalog_v1_hardware_class } from "./hardware_class_pb"; import type { InferenceRequestKind, ModelInputCapabilities } from "./model_capabilities_pb"; import { file_dotcore_catalog_v1_model_capabilities } from "./model_capabilities_pb"; -import type { ParameterValues } from "./parameter_pb"; +import type { ParameterValues, ParameterVisibility } from "./parameter_pb"; import { file_dotcore_catalog_v1_parameter } from "./parameter_pb"; import type { EngineModelConfiguration } from "../../engine/v1/engine_pb"; import { file_dotcore_engine_v1_engine } from "../../engine/v1/engine_pb"; @@ -22,7 +22,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file dotcore/catalog/v1/model.proto. */ export const file_dotcore_catalog_v1_model: GenFile = /*@__PURE__*/ - fileDesc("Ch5kb3Rjb3JlL2NhdGFsb2cvdjEvbW9kZWwucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSL2AwoFTW9kZWwSEAoIbW9kZWxfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSHgoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgMIAEoDRI0CglhcnRpZmFjdHMYBCADKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBIyCghwcm9maWxlcxgFIAMoCzIgLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFByb2ZpbGUSRwoTYXV4aWxpYXJ5X2FydGlmYWN0cxgHIAMoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEF1eGlsaWFyeUFydGlmYWN0EkQKDmNvbmZpZ3VyYXRpb25zGAggAygLMiwuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRW5naW5lQ29uZmlndXJhdGlvbhIwCgdvcHRpb25zGAkgAygLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uEjsKDGludGVsbGlnZW5jZRgKIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5JbnRlbGxpZ2VuY2VTY29yZRIsCgdsaWNlbnNlGAsgASgLMhsuZG90Y29yZS5jYXRhbG9nLnYxLkxpY2Vuc2UiJAoRSW50ZWxsaWdlbmNlU2NvcmUSDwoHb3ZlcmFsbBgBIAEoASIoCgdMaWNlbnNlEgoKAmlkGAEgASgJEhEKCXRlcm1zX3VybBgCIAEoCSKAAQoNTW9kZWxBcnRpZmFjdBI9CgZzb3VyY2UYASABKAsyLS5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VBcnRpZmFjdFNvdXJjZRITCgthcnRpZmFjdF9pZBgCIAEoCRIbChN3ZWlnaHRfcXVhbnRpemF0aW9uGAMgASgJInYKFk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSHQoVYXV4aWxpYXJ5X2FydGlmYWN0X2lkGAEgASgJEj0KBnNvdXJjZRgCIAEoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUFydGlmYWN0U291cmNlIs4BChlIdWdnaW5nRmFjZUFydGlmYWN0U291cmNlEhIKCnJlcG9zaXRvcnkYASABKAkSEAoIcmV2aXNpb24YAiABKAkSOwoEZmlsZRgDIAEoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUZpbGVBcnRpZmFjdEgAEkMKCHNuYXBzaG90GAQgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkh1Z2dpbmdGYWNlU25hcHNob3RBcnRpZmFjdEgAQgkKB2NvbnRlbnQiQgoXSHVnZ2luZ0ZhY2VGaWxlQXJ0aWZhY3QSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSJZChtIdWdnaW5nRmFjZVNuYXBzaG90QXJ0aWZhY3QSOgoFZmlsZXMYASADKAsyKy5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUiQgoXSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSKiBQoYTW9kZWxFbmdpbmVDb25maWd1cmF0aW9uEhgKEGNvbmZpZ3VyYXRpb25faWQYASABKAkSRQoQZW5naW5lX2FydGlmYWN0cxgCIAMoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVBcnRpZmFjdFJlZmVyZW5jZRJDChFhcnRpZmFjdF9iaW5kaW5ncxgDIAMoCzIoLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEFydGlmYWN0QmluZGluZxI9ChBoYXJkd2FyZV9zdXBwb3J0GAkgAygLMiMuZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlU3VwcG9ydBJJChRlbmdpbmVfY29uZmlndXJhdGlvbhgFIAEoCzIrLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZU1vZGVsQ29uZmlndXJhdGlvbhJOChZleGVjdXRpb25fY2FwYWJpbGl0aWVzGAYgASgLMi4uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRXhlY3V0aW9uQ2FwYWJpbGl0aWVzEkYKEmlucHV0X2NhcGFiaWxpdGllcxgHIAEoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbElucHV0Q2FwYWJpbGl0aWVzEj8KDXJlcXVlc3Rfa2luZHMYCyADKA4yKC5kb3Rjb3JlLmNhdGFsb2cudjEuSW5mZXJlbmNlUmVxdWVzdEtpbmQSPQoHb3B0aW9ucxgIIAMoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbENvbmZpZ3VyYXRpb25PcHRpb24SIwoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgKIAEoDUgAiAEBQhkKF19tYXhpbXVtX2NvbnRleHRfdG9rZW5zImUKFE1vZGVsQXJ0aWZhY3RCaW5kaW5nEhIKCmJpbmRpbmdfaWQYASABKAkSGQoRbW9kZWxfYXJ0aWZhY3RfaWQYAiABKAkSHgoWYXV4aWxpYXJ5X2FydGlmYWN0X2lkcxgDIAMoCSK5AgoMTW9kZWxQcm9maWxlEhIKCnByb2ZpbGVfaWQYASABKAkSGAoQY29uZmlndXJhdGlvbl9pZBgCIAEoCRIpCiFkZWZhdWx0X21vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYAyABKAkSRgoZZW5naW5lX3BhcmFtZXRlcl9kZWZhdWx0cxgEIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSFAoMZGlzcGxheV9uYW1lGAUgASgJEhMKC2Rlc2NyaXB0aW9uGAYgASgJEj4KD29wdGlvbl9kZWZhdWx0cxgHIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVleHBvc2VkX3BhcmFtZXRlcl9pZHMYCCADKAkimgIKC01vZGVsT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSNwoGdmlzaW9uGAMgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLlZpc2lvbk1vZGVsT3B0aW9uSAASUgoUc3BlY3VsYXRpdmVfZGVjb2RpbmcYBCABKAsyMi5kb3Rjb3JlLmNhdGFsb2cudjEuU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uSAASTQoSa3ZfY2FjaGVfcHJlY2lzaW9uGAUgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkt2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbkgAQgYKBGtpbmQiEwoRVmlzaW9uTW9kZWxPcHRpb24iXwoeU3BlY3VsYXRpdmVEZWNvZGluZ01vZGVsT3B0aW9uEj0KBm1ldGhvZBgBIAEoDjItLmRvdGNvcmUuY2F0YWxvZy52MS5TcGVjdWxhdGl2ZURlY29kaW5nTWV0aG9kIh0KG0t2Q2FjaGVQcmVjaXNpb25Nb2RlbE9wdGlvbiLsAQoYTW9kZWxDb25maWd1cmF0aW9uT3B0aW9uEhEKCW9wdGlvbl9pZBgBIAEoCRJGCgpwYXJhbWV0ZXJzGAIgAygLMjIuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyRGVmaW5pdGlvbhI9Cg5kZWZhdWx0X3ZhbHVlcxgDIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcxIdChVzdXBwb3J0ZWRfYmluZGluZ19pZHMYBCADKAkSFwoPY29tcGF0aWJsZV93aGVuGAUgASgJItQCCh5Nb2RlbE9wdGlvblBhcmFtZXRlckRlZmluaXRpb24SFAoMcGFyYW1ldGVyX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRJICgdib29sZWFuGAMgASgLMjUuZG90Y29yZS5jYXRhbG9nLnYxLkJvb2xlYW5Nb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYUgAElkKEHVuc2lnbmVkX2ludGVnZXIYBCABKAsyPS5kb3Rjb3JlLmNhdGFsb2cudjEuVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIABJPCgtzdHJpbmdfZW51bRgFIAEoCzI4LmRvdGNvcmUuY2F0YWxvZy52MS5TdHJpbmdFbnVtTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWFIAEIQCg5wYXJhbWV0ZXJfdHlwZSIjCiFCb29sZWFuTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWEiWwopVW5zaWduZWRJbnRlZ2VyTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWESDwoHbWluaW11bRgBIAEoBBIPCgdtYXhpbXVtGAIgASgEEgwKBHVuaXQYAyABKAkiNgokU3RyaW5nRW51bU1vZGVsT3B0aW9uUGFyYW1ldGVyU2NoZW1hEg4KBnZhbHVlcxgBIAMoCSJlChFNb2RlbE9wdGlvblZhbHVlcxIRCglvcHRpb25faWQYASABKAkSPQoGdmFsdWVzGAIgAygLMi0uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uUGFyYW1ldGVyVmFsdWUiewoZTW9kZWxPcHRpb25QYXJhbWV0ZXJWYWx1ZRIUCgxwYXJhbWV0ZXJfaWQYASABKAkSEQoHYm9vbGVhbhgCIAEoCEgAEhoKEHVuc2lnbmVkX2ludGVnZXIYAyABKARIABIQCgZzdHJpbmcYBCABKAlIAEIHCgV2YWx1ZSJnChpNb2RlbEV4ZWN1dGlvbkNhcGFiaWxpdGllcxJJChlzdXBwb3J0ZWRfcGFyYWxsZWxfc2hhcGVzGAEgAygOMiYuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsUGFyYWxsZWxTaGFwZSJ1Cg9IYXJkd2FyZVN1cHBvcnQSGQoRaGFyZHdhcmVfY2xhc3NfaWQYASABKAkSRwoVaGFyZHdhcmVfcmVxdWlyZW1lbnRzGAIgASgLMiguZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlUmVxdWlyZW1lbnRzKm0KGVNwZWN1bGF0aXZlRGVjb2RpbmdNZXRob2QSKwonU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX1VOU1BFQ0lGSUVEEAASIwofU1BFQ1VMQVRJVkVfREVDT0RJTkdfTUVUSE9EX01UUBABYgZwcm90bzM", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model_capabilities, file_dotcore_catalog_v1_parameter, file_dotcore_engine_v1_engine]); + fileDesc("Ch5kb3Rjb3JlL2NhdGFsb2cvdjEvbW9kZWwucHJvdG8SEmRvdGNvcmUuY2F0YWxvZy52MSL2AwoFTW9kZWwSEAoIbW9kZWxfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSHgoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgMIAEoDRI0CglhcnRpZmFjdHMYBCADKAsyIS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxBcnRpZmFjdBIyCghwcm9maWxlcxgFIAMoCzIgLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbFByb2ZpbGUSRwoTYXV4aWxpYXJ5X2FydGlmYWN0cxgHIAMoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEF1eGlsaWFyeUFydGlmYWN0EkQKDmNvbmZpZ3VyYXRpb25zGAggAygLMiwuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRW5naW5lQ29uZmlndXJhdGlvbhIwCgdvcHRpb25zGAkgAygLMh8uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uEjsKDGludGVsbGlnZW5jZRgKIAEoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5JbnRlbGxpZ2VuY2VTY29yZRIsCgdsaWNlbnNlGAsgASgLMhsuZG90Y29yZS5jYXRhbG9nLnYxLkxpY2Vuc2UiJAoRSW50ZWxsaWdlbmNlU2NvcmUSDwoHb3ZlcmFsbBgBIAEoASIoCgdMaWNlbnNlEgoKAmlkGAEgASgJEhEKCXRlcm1zX3VybBgCIAEoCSKAAQoNTW9kZWxBcnRpZmFjdBI9CgZzb3VyY2UYASABKAsyLS5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VBcnRpZmFjdFNvdXJjZRITCgthcnRpZmFjdF9pZBgCIAEoCRIbChN3ZWlnaHRfcXVhbnRpemF0aW9uGAMgASgJInYKFk1vZGVsQXV4aWxpYXJ5QXJ0aWZhY3QSHQoVYXV4aWxpYXJ5X2FydGlmYWN0X2lkGAEgASgJEj0KBnNvdXJjZRgCIAEoCzItLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUFydGlmYWN0U291cmNlIs4BChlIdWdnaW5nRmFjZUFydGlmYWN0U291cmNlEhIKCnJlcG9zaXRvcnkYASABKAkSEAoIcmV2aXNpb24YAiABKAkSOwoEZmlsZRgDIAEoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5IdWdnaW5nRmFjZUZpbGVBcnRpZmFjdEgAEkMKCHNuYXBzaG90GAQgASgLMi8uZG90Y29yZS5jYXRhbG9nLnYxLkh1Z2dpbmdGYWNlU25hcHNob3RBcnRpZmFjdEgAQgkKB2NvbnRlbnQiQgoXSHVnZ2luZ0ZhY2VGaWxlQXJ0aWZhY3QSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSJZChtIdWdnaW5nRmFjZVNuYXBzaG90QXJ0aWZhY3QSOgoFZmlsZXMYASADKAsyKy5kb3Rjb3JlLmNhdGFsb2cudjEuSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUiQgoXSHVnZ2luZ0ZhY2VTbmFwc2hvdEZpbGUSDAoEcGF0aBgBIAEoCRIZChFwcm92ZW5hbmNlX2RpZ2VzdBgCIAEoCSKiBQoYTW9kZWxFbmdpbmVDb25maWd1cmF0aW9uEhgKEGNvbmZpZ3VyYXRpb25faWQYASABKAkSRQoQZW5naW5lX2FydGlmYWN0cxgCIAMoCzIrLmRvdGNvcmUuY2F0YWxvZy52MS5FbmdpbmVBcnRpZmFjdFJlZmVyZW5jZRJDChFhcnRpZmFjdF9iaW5kaW5ncxgDIAMoCzIoLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbEFydGlmYWN0QmluZGluZxI9ChBoYXJkd2FyZV9zdXBwb3J0GAkgAygLMiMuZG90Y29yZS5jYXRhbG9nLnYxLkhhcmR3YXJlU3VwcG9ydBJJChRlbmdpbmVfY29uZmlndXJhdGlvbhgFIAEoCzIrLmRvdGNvcmUuZW5naW5lLnYxLkVuZ2luZU1vZGVsQ29uZmlndXJhdGlvbhJOChZleGVjdXRpb25fY2FwYWJpbGl0aWVzGAYgASgLMi4uZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsRXhlY3V0aW9uQ2FwYWJpbGl0aWVzEkYKEmlucHV0X2NhcGFiaWxpdGllcxgHIAEoCzIqLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbElucHV0Q2FwYWJpbGl0aWVzEj8KDXJlcXVlc3Rfa2luZHMYCyADKA4yKC5kb3Rjb3JlLmNhdGFsb2cudjEuSW5mZXJlbmNlUmVxdWVzdEtpbmQSPQoHb3B0aW9ucxgIIAMoCzIsLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbENvbmZpZ3VyYXRpb25PcHRpb24SIwoWbWF4aW11bV9jb250ZXh0X3Rva2VucxgKIAEoDUgAiAEBQhkKF19tYXhpbXVtX2NvbnRleHRfdG9rZW5zImUKFE1vZGVsQXJ0aWZhY3RCaW5kaW5nEhIKCmJpbmRpbmdfaWQYASABKAkSGQoRbW9kZWxfYXJ0aWZhY3RfaWQYAiABKAkSHgoWYXV4aWxpYXJ5X2FydGlmYWN0X2lkcxgDIAMoCSL6AgoMTW9kZWxQcm9maWxlEhIKCnByb2ZpbGVfaWQYASABKAkSGAoQY29uZmlndXJhdGlvbl9pZBgCIAEoCRIpCiFkZWZhdWx0X21vZGVsX2FydGlmYWN0X2JpbmRpbmdfaWQYAyABKAkSRgoZZW5naW5lX3BhcmFtZXRlcl9kZWZhdWx0cxgEIAEoCzIjLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWYWx1ZXMSXgolZW5naW5lX3BhcmFtZXRlcl92aXNpYmlsaXR5X292ZXJyaWRlcxgJIAMoCzIvLmRvdGNvcmUuY2F0YWxvZy52MS5QYXJhbWV0ZXJWaXNpYmlsaXR5T3ZlcnJpZGUSFAoMZGlzcGxheV9uYW1lGAUgASgJEhMKC2Rlc2NyaXB0aW9uGAYgASgJEj4KD29wdGlvbl9kZWZhdWx0cxgHIAMoCzIlLmRvdGNvcmUuY2F0YWxvZy52MS5Nb2RlbE9wdGlvblZhbHVlcyJwChtQYXJhbWV0ZXJWaXNpYmlsaXR5T3ZlcnJpZGUSFAoMcGFyYW1ldGVyX2lkGAEgASgJEjsKCnZpc2liaWxpdHkYAiABKA4yJy5kb3Rjb3JlLmNhdGFsb2cudjEuUGFyYW1ldGVyVmlzaWJpbGl0eSKaAgoLTW9kZWxPcHRpb24SEQoJb3B0aW9uX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRI3CgZ2aXNpb24YAyABKAsyJS5kb3Rjb3JlLmNhdGFsb2cudjEuVmlzaW9uTW9kZWxPcHRpb25IABJSChRzcGVjdWxhdGl2ZV9kZWNvZGluZxgEIAEoCzIyLmRvdGNvcmUuY2F0YWxvZy52MS5TcGVjdWxhdGl2ZURlY29kaW5nTW9kZWxPcHRpb25IABJNChJrdl9jYWNoZV9wcmVjaXNpb24YBSABKAsyLy5kb3Rjb3JlLmNhdGFsb2cudjEuS3ZDYWNoZVByZWNpc2lvbk1vZGVsT3B0aW9uSABCBgoEa2luZCITChFWaXNpb25Nb2RlbE9wdGlvbiJfCh5TcGVjdWxhdGl2ZURlY29kaW5nTW9kZWxPcHRpb24SPQoGbWV0aG9kGAEgASgOMi0uZG90Y29yZS5jYXRhbG9nLnYxLlNwZWN1bGF0aXZlRGVjb2RpbmdNZXRob2QiHQobS3ZDYWNoZVByZWNpc2lvbk1vZGVsT3B0aW9uIuwBChhNb2RlbENvbmZpZ3VyYXRpb25PcHRpb24SEQoJb3B0aW9uX2lkGAEgASgJEkYKCnBhcmFtZXRlcnMYAiADKAsyMi5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxPcHRpb25QYXJhbWV0ZXJEZWZpbml0aW9uEj0KDmRlZmF1bHRfdmFsdWVzGAMgASgLMiUuZG90Y29yZS5jYXRhbG9nLnYxLk1vZGVsT3B0aW9uVmFsdWVzEh0KFXN1cHBvcnRlZF9iaW5kaW5nX2lkcxgEIAMoCRIXCg9jb21wYXRpYmxlX3doZW4YBSABKAki1AIKHk1vZGVsT3B0aW9uUGFyYW1ldGVyRGVmaW5pdGlvbhIUCgxwYXJhbWV0ZXJfaWQYASABKAkSFAoMZGlzcGxheV9uYW1lGAIgASgJEkgKB2Jvb2xlYW4YAyABKAsyNS5kb3Rjb3JlLmNhdGFsb2cudjEuQm9vbGVhbk1vZGVsT3B0aW9uUGFyYW1ldGVyU2NoZW1hSAASWQoQdW5zaWduZWRfaW50ZWdlchgEIAEoCzI9LmRvdGNvcmUuY2F0YWxvZy52MS5VbnNpZ25lZEludGVnZXJNb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYUgAEk8KC3N0cmluZ19lbnVtGAUgASgLMjguZG90Y29yZS5jYXRhbG9nLnYxLlN0cmluZ0VudW1Nb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYUgAQhAKDnBhcmFtZXRlcl90eXBlIiMKIUJvb2xlYW5Nb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYSJbCilVbnNpZ25lZEludGVnZXJNb2RlbE9wdGlvblBhcmFtZXRlclNjaGVtYRIPCgdtaW5pbXVtGAEgASgEEg8KB21heGltdW0YAiABKAQSDAoEdW5pdBgDIAEoCSI2CiRTdHJpbmdFbnVtTW9kZWxPcHRpb25QYXJhbWV0ZXJTY2hlbWESDgoGdmFsdWVzGAEgAygJImUKEU1vZGVsT3B0aW9uVmFsdWVzEhEKCW9wdGlvbl9pZBgBIAEoCRI9CgZ2YWx1ZXMYAiADKAsyLS5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxPcHRpb25QYXJhbWV0ZXJWYWx1ZSJ7ChlNb2RlbE9wdGlvblBhcmFtZXRlclZhbHVlEhQKDHBhcmFtZXRlcl9pZBgBIAEoCRIRCgdib29sZWFuGAIgASgISAASGgoQdW5zaWduZWRfaW50ZWdlchgDIAEoBEgAEhAKBnN0cmluZxgEIAEoCUgAQgcKBXZhbHVlImcKGk1vZGVsRXhlY3V0aW9uQ2FwYWJpbGl0aWVzEkkKGXN1cHBvcnRlZF9wYXJhbGxlbF9zaGFwZXMYASADKA4yJi5kb3Rjb3JlLmNhdGFsb2cudjEuTW9kZWxQYXJhbGxlbFNoYXBlInUKD0hhcmR3YXJlU3VwcG9ydBIZChFoYXJkd2FyZV9jbGFzc19pZBgBIAEoCRJHChVoYXJkd2FyZV9yZXF1aXJlbWVudHMYAiABKAsyKC5kb3Rjb3JlLmNhdGFsb2cudjEuSGFyZHdhcmVSZXF1aXJlbWVudHMqbQoZU3BlY3VsYXRpdmVEZWNvZGluZ01ldGhvZBIrCidTUEVDVUxBVElWRV9ERUNPRElOR19NRVRIT0RfVU5TUEVDSUZJRUQQABIjCh9TUEVDVUxBVElWRV9ERUNPRElOR19NRVRIT0RfTVRQEAFiBnByb3RvMw", [file_dotcore_catalog_v1_engine_release, file_dotcore_catalog_v1_execution, file_dotcore_catalog_v1_hardware_class, file_dotcore_catalog_v1_model_capabilities, file_dotcore_catalog_v1_parameter, file_dotcore_engine_v1_engine]); /** * An immutable artifact-manager catalog declaration. The inference controller @@ -516,6 +516,13 @@ export type ModelProfile = Message<"dotcore.catalog.v1.ModelProfile"> & { */ engineParameterDefaults?: ParameterValues; + /** + * Engine parameters this profile shows differently from the engine, at most one per parameter. + * + * @generated from field: repeated dotcore.catalog.v1.ParameterVisibilityOverride engine_parameter_visibility_overrides = 9; + */ + engineParameterVisibilityOverrides: ParameterVisibilityOverride[]; + /** * Optional human-readable name for this profile. * @@ -536,13 +543,6 @@ export type ModelProfile = Message<"dotcore.catalog.v1.ModelProfile"> & { * @generated from field: repeated dotcore.catalog.v1.ModelOptionValues option_defaults = 7; */ optionDefaults: ModelOptionValues[]; - - /** - * Exact ordered engine parameters exposed by this profile; empty uses engine defaults. - * - * @generated from field: repeated string exposed_parameter_ids = 8; - */ - exposedParameterIds: string[]; }; /** @@ -552,6 +552,35 @@ export type ModelProfile = Message<"dotcore.catalog.v1.ModelProfile"> & { export const ModelProfileSchema: GenMessage = /*@__PURE__*/ messageDesc(file_dotcore_catalog_v1_model, 11); +/** + * Sets where the console shows one engine parameter for a profile, in place of the engine's + * visibility. + * + * @generated from message dotcore.catalog.v1.ParameterVisibilityOverride + */ +export type ParameterVisibilityOverride = Message<"dotcore.catalog.v1.ParameterVisibilityOverride"> & { + /** + * Engine parameter identity. + * + * @generated from field: string parameter_id = 1; + */ + parameterId: string; + + /** + * Visibility the profile gives the parameter. + * + * @generated from field: dotcore.catalog.v1.ParameterVisibility visibility = 2; + */ + visibility: ParameterVisibility; +}; + +/** + * Describes the message dotcore.catalog.v1.ParameterVisibilityOverride. + * Use `create(ParameterVisibilityOverrideSchema)` to create a new message. + */ +export const ParameterVisibilityOverrideSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_dotcore_catalog_v1_model, 12); + /** * Declares one stable semantic option that configurations may implement. * @@ -607,7 +636,7 @@ export type ModelOption = Message<"dotcore.catalog.v1.ModelOption"> & { * Use `create(ModelOptionSchema)` to create a new message. */ export const ModelOptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 12); + messageDesc(file_dotcore_catalog_v1_model, 13); /** * Identifies the semantic vision option kind. @@ -622,7 +651,7 @@ export type VisionModelOption = Message<"dotcore.catalog.v1.VisionModelOption"> * Use `create(VisionModelOptionSchema)` to create a new message. */ export const VisionModelOptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 13); + messageDesc(file_dotcore_catalog_v1_model, 14); /** * Identifies the semantic speculative-decoding option kind and the draft method it uses. Its @@ -644,7 +673,7 @@ export type SpeculativeDecodingModelOption = Message<"dotcore.catalog.v1.Specula * Use `create(SpeculativeDecodingModelOptionSchema)` to create a new message. */ export const SpeculativeDecodingModelOptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 14); + messageDesc(file_dotcore_catalog_v1_model, 15); /** * Identifies the semantic KV cache precision option kind. Its configuration options declare one @@ -660,7 +689,7 @@ export type KvCachePrecisionModelOption = Message<"dotcore.catalog.v1.KvCachePre * Use `create(KvCachePrecisionModelOptionSchema)` to create a new message. */ export const KvCachePrecisionModelOptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 15); + messageDesc(file_dotcore_catalog_v1_model, 16); /** * Defines one option as implemented by a model-local engine configuration. @@ -709,7 +738,7 @@ export type ModelConfigurationOption = Message<"dotcore.catalog.v1.ModelConfigur * Use `create(ModelConfigurationOptionSchema)` to create a new message. */ export const ModelConfigurationOptionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 16); + messageDesc(file_dotcore_catalog_v1_model, 17); /** * Defines one typed configuration-local option parameter. @@ -766,7 +795,7 @@ export type ModelOptionParameterDefinition = Message<"dotcore.catalog.v1.ModelOp * Use `create(ModelOptionParameterDefinitionSchema)` to create a new message. */ export const ModelOptionParameterDefinitionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 17); + messageDesc(file_dotcore_catalog_v1_model, 18); /** * Defines a boolean option parameter. @@ -781,7 +810,7 @@ export type BooleanModelOptionParameterSchema = Message<"dotcore.catalog.v1.Bool * Use `create(BooleanModelOptionParameterSchemaSchema)` to create a new message. */ export const BooleanModelOptionParameterSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 18); + messageDesc(file_dotcore_catalog_v1_model, 19); /** * Defines bounds and units for an unsigned-integer option parameter. @@ -816,7 +845,7 @@ export type UnsignedIntegerModelOptionParameterSchema = Message<"dotcore.catalog * Use `create(UnsignedIntegerModelOptionParameterSchemaSchema)` to create a new message. */ export const UnsignedIntegerModelOptionParameterSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 19); + messageDesc(file_dotcore_catalog_v1_model, 20); /** * Defines the exact accepted values for a constrained string parameter. @@ -837,7 +866,7 @@ export type StringEnumModelOptionParameterSchema = Message<"dotcore.catalog.v1.S * Use `create(StringEnumModelOptionParameterSchemaSchema)` to create a new message. */ export const StringEnumModelOptionParameterSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 20); + messageDesc(file_dotcore_catalog_v1_model, 21); /** * Supplies typed values for one model option. @@ -865,7 +894,7 @@ export type ModelOptionValues = Message<"dotcore.catalog.v1.ModelOptionValues"> * Use `create(ModelOptionValuesSchema)` to create a new message. */ export const ModelOptionValuesSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 21); + messageDesc(file_dotcore_catalog_v1_model, 22); /** * Supplies one typed option parameter value. @@ -915,7 +944,7 @@ export type ModelOptionParameterValue = Message<"dotcore.catalog.v1.ModelOptionP * Use `create(ModelOptionParameterValueSchema)` to create a new message. */ export const ModelOptionParameterValueSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 22); + messageDesc(file_dotcore_catalog_v1_model, 23); /** * Execution shapes that a model profile supports. @@ -936,7 +965,7 @@ export type ModelExecutionCapabilities = Message<"dotcore.catalog.v1.ModelExecut * Use `create(ModelExecutionCapabilitiesSchema)` to create a new message. */ export const ModelExecutionCapabilitiesSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 23); + messageDesc(file_dotcore_catalog_v1_model, 24); /** * Declares that a configuration runs on one shared hardware class. The class selector supplies the @@ -965,7 +994,7 @@ export type HardwareSupport = Message<"dotcore.catalog.v1.HardwareSupport"> & { * Use `create(HardwareSupportSchema)` to create a new message. */ export const HardwareSupportSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_dotcore_catalog_v1_model, 24); + messageDesc(file_dotcore_catalog_v1_model, 25); /** * Draft methods that propose tokens for speculative decoding. diff --git a/proto/dotcore/catalog/v1/model.proto b/proto/dotcore/catalog/v1/model.proto index a2e57c3f..01d2d39a 100644 --- a/proto/dotcore/catalog/v1/model.proto +++ b/proto/dotcore/catalog/v1/model.proto @@ -191,6 +191,9 @@ message ModelProfile { // Typed engine parameter defaults for this profile, overlaid on the engine defaults. ParameterValues engine_parameter_defaults = 4; + // Engine parameters this profile shows differently from the engine, at most one per parameter. + repeated ParameterVisibilityOverride engine_parameter_visibility_overrides = 9; + // Optional human-readable name for this profile. string display_name = 5; @@ -199,9 +202,16 @@ message ModelProfile { // Sparse option defaults overlaid on configuration defaults. repeated ModelOptionValues option_defaults = 7; +} + +// Sets where the console shows one engine parameter for a profile, in place of the engine's +// visibility. +message ParameterVisibilityOverride { + // Engine parameter identity. + string parameter_id = 1; - // Exact ordered engine parameters exposed by this profile; empty uses engine defaults. - repeated string exposed_parameter_ids = 8; + // Visibility the profile gives the parameter. + ParameterVisibility visibility = 2; } // Declares one stable semantic option that configurations may implement. From 0fce17a41b6eeda5c3311bfeef5faa37134a910f Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 14:00:44 -0500 Subject: [PATCH 06/40] unreviewed: feat(backend): validate profile visibility overrides --- backend/catalog/src/lib.rs | 51 +++++++++++++++ backend/catalog/src/shared_parameters.rs | 53 +++++++++++++++ .../catalog/src/validation/engine_release.rs | 30 +++++++-- backend/catalog/src/validation/mod.rs | 26 +++++++- backend/catalog/src/validation/model.rs | 63 ++++++++++++------ .../core/tests/backend/catalog_contracts.rs | 64 ++++++++++++++++--- backend/proto/tests/model_contract.rs | 21 ++++-- 7 files changed, 265 insertions(+), 43 deletions(-) diff --git a/backend/catalog/src/lib.rs b/backend/catalog/src/lib.rs index 82799ec2..52b86e36 100644 --- a/backend/catalog/src/lib.rs +++ b/backend/catalog/src/lib.rs @@ -1794,6 +1794,57 @@ artifacts: ); } + #[test] + fn a_profile_hides_only_parameters_with_a_default_or_a_derivation_on_every_binding() { + let hidden = r#" engineParameterVisibilityOverrides: + - { parameterId: "prompt-cache-memory-mib", visibility: "PARAMETER_VISIBILITY_HIDDEN" } +"#; + let load = |case: &str, sizing: &str, binding_sizing: &str, values: &str| { + let root = temporary_catalog_root().join(case); + create_empty_catalog_source(&root); + write_sizing_engine(&root); + write_sizing_model_with(&root, sizing, binding_sizing, &format!("{values}{hidden}")); + Catalog::load_with_policy( + &root, + OciArtifactPolicy::Development, + &ACCEPT_ENGINE_DECLARATIONS, + ) + }; + + let error = load("unset", "", "", " values: []\n") + .expect_err("a hidden parameter without a value must reject") + .to_string(); + assert!( + error.contains( + "profile \"balanced\" hides engine parameter \"prompt-cache-memory-mib\", which has no default and which sizing does not derive on every binding and hardware class" + ), + "{error}" + ); + assert!(!error.contains("omits engine parameter"), "{error}"); + + load( + "defaulted", + "", + "", + &format!(" values:\n{}", SIZING_ENGINE_CACHE_DEFAULT), + ) + .expect("a profile default gives the hidden parameter its value"); + load( + "derived", + r#" sizing: + derivedParameters: + prompt-cache-memory-mib: "4096" + estimates: + acceleratorMemory: + unit: bytes + equation: "${prompt-cache-memory-mib}" +"#, + UNPARAMETERIZED_BINDING_SIZING, + " values: []\n", + ) + .expect("sizing gives the hidden parameter its value on every binding"); + } + #[test] fn profile_defaults_overlay_the_engine_defaults_per_parameter() { let load = |profile_defaults: &str| { diff --git a/backend/catalog/src/shared_parameters.rs b/backend/catalog/src/shared_parameters.rs index c0fcc8d2..46925b43 100644 --- a/backend/catalog/src/shared_parameters.rs +++ b/backend/catalog/src/shared_parameters.rs @@ -90,6 +90,33 @@ pub(crate) fn profile_may_default(parameter_id: &str) -> bool { .is_none_or(|shared| shared.profile_default) } +/// Whether the parameter belongs to the main view: the context parameters do, and no other +/// parameter may be shown there by an engine or a profile. +pub(crate) fn in_main_view(parameter_id: &str) -> bool { + SHARED_PARAMETERS.iter().any(|shared| { + shared.parameter_id == parameter_id && shared.visibility == ParameterVisibility::Basic + }) +} + +/// Returns why a profile may not give the parameter this visibility, or none when it may. The +/// context parameters belong to the main view: a profile may hide them but not move them to the +/// advanced view. Every other parameter stays out of the main view, so a profile may show it as +/// advanced or hide it. +pub(crate) fn profile_visibility_problem( + parameter_id: &str, + visibility: ParameterVisibility, +) -> Option<&'static str> { + let main_view = in_main_view(parameter_id); + match visibility { + ParameterVisibility::Unspecified => Some("requires a basic, advanced or hidden visibility"), + ParameterVisibility::Advanced if main_view => Some("may be hidden but not advanced"), + ParameterVisibility::Basic if !main_view => Some("may be advanced or hidden but not basic"), + ParameterVisibility::Basic + | ParameterVisibility::Advanced + | ParameterVisibility::Hidden => None, + } +} + /// Checks that an engine parameter schema declares every shared parameter with its fixed shape, /// returning one error per problem. Engine payloads are left to the engine's own validation. pub(crate) fn validate_shared_parameters(schema: &EngineParameterSchema) -> Vec { @@ -331,6 +358,32 @@ mod tests { assert!(profile_may_default("prompt-cache-memory-mib")); } + #[test] + fn profiles_may_hide_any_parameter_but_keep_the_contexts_basic_and_the_rest_out_of_basic() { + use ParameterVisibility::{Advanced, Basic, Hidden, Unspecified}; + + for parameter_id in [TOTAL_CONTEXT_PARAMETER_ID, CONTEXT_PER_REQUEST_PARAMETER_ID] { + assert_eq!(profile_visibility_problem(parameter_id, Basic), None); + assert_eq!(profile_visibility_problem(parameter_id, Hidden), None); + assert_eq!( + profile_visibility_problem(parameter_id, Advanced), + Some("may be hidden but not advanced") + ); + } + for parameter_id in [PARALLEL_REQUESTS_PARAMETER_ID, "prompt-cache-memory-mib"] { + assert_eq!(profile_visibility_problem(parameter_id, Advanced), None); + assert_eq!(profile_visibility_problem(parameter_id, Hidden), None); + assert_eq!( + profile_visibility_problem(parameter_id, Basic), + Some("may be advanced or hidden but not basic") + ); + } + assert_eq!( + profile_visibility_problem(TOTAL_CONTEXT_PARAMETER_ID, Unspecified), + Some("requires a basic, advanced or hidden visibility") + ); + } + #[test] fn the_omitted_context_per_request_is_the_smaller_of_the_maximum_and_the_total_context() { let schema = shared_schema(); diff --git a/backend/catalog/src/validation/engine_release.rs b/backend/catalog/src/validation/engine_release.rs index 061692b1..0634824d 100644 --- a/backend/catalog/src/validation/engine_release.rs +++ b/backend/catalog/src/validation/engine_release.rs @@ -9,15 +9,16 @@ use std::collections::BTreeSet; use dotcore_domain::{Accelerator, valid_id}; use dotcore_proto::dotcore::catalog::v1::{ - EngineArtifact, EngineParameterSchema, EngineRelease, ParameterDefinition, Selector, - engine_artifact::Kind as EngineArtifactKind, parameter_definition::ParameterType, + EngineArtifact, EngineParameterSchema, EngineRelease, ParameterDefinition, ParameterVisibility, + Selector, engine_artifact::Kind as EngineArtifactKind, parameter_definition::ParameterType, }; use super::common::{valid_selector_memory_architecture, validate_oci_reference}; use super::nix::{AcceptedProvides, nix_systems, validate_nix_artifact}; use super::storage::{StorageOwner, validate_storage_bindings}; use crate::{ - OciArtifactPolicy, shared_parameters::validate_shared_parameters, + OciArtifactPolicy, + shared_parameters::{in_main_view, validate_shared_parameters}, typed_parameters::validate_parameter_definition as validate_shared_definition, }; @@ -233,7 +234,8 @@ fn validate_parameter_schema( } /// Validates one engine parameter definition: the shared definition rules, a unique id, and the -/// engine owner rule that parameters are booleans or unsigned integers with a unit. +/// engine owner rules that parameters are booleans or unsigned integers with a unit, and that only +/// the context parameters are basic. fn validate_parameter_definition( definition: &ParameterDefinition, ids: &mut BTreeSet, @@ -253,14 +255,20 @@ fn validate_parameter_definition( )), Some(ParameterType::Boolean(_) | ParameterType::UnsignedInteger(_)) | None => {} } + // The shared parameter check reports a context parameter in the wrong view. + if definition.visibility() == ParameterVisibility::Basic && !in_main_view(id) { + errors.push(anyhow::anyhow!( + "engine parameter {id:?} must be advanced or hidden; only the context parameters are basic" + )); + } } #[cfg(test)] mod tests { use dotcore_proto::dotcore::{ catalog::v1::{ - NixArtifact, NixDockerImage, ParameterVisibility, StorageBinding, StorageKind, - StorageScope, nix_artifact::Provides, + NixArtifact, NixDockerImage, StorageBinding, StorageKind, StorageScope, + nix_artifact::Provides, }, observation::v1::AcceleratorMemoryArchitecture, }; @@ -431,7 +439,7 @@ mod tests { } #[test] - fn engine_parameters_are_booleans_or_unsigned_integers_with_a_unit() { + fn engine_parameters_are_non_basic_booleans_or_unsigned_integers_with_a_unit() { let definition = |parameter_type| ParameterDefinition { parameter_id: "feature".to_owned(), display_name: "Feature".to_owned(), @@ -475,6 +483,14 @@ mod tests { ))), ["engine parameter \"feature\" must be a boolean or an unsigned integer"] ); + let mut basic = definition(boolean.clone()); + basic.visibility = ParameterVisibility::Basic as i32; + assert_eq!( + errors(&basic), + [ + "engine parameter \"feature\" must be advanced or hidden; only the context parameters are basic" + ] + ); let mut unplaced = definition(boolean); unplaced.visibility = ParameterVisibility::Unspecified as i32; assert_eq!( diff --git a/backend/catalog/src/validation/mod.rs b/backend/catalog/src/validation/mod.rs index 76d53eb6..b02129d2 100644 --- a/backend/catalog/src/validation/mod.rs +++ b/backend/catalog/src/validation/mod.rs @@ -11,7 +11,8 @@ use std::collections::{BTreeMap, BTreeSet}; use dotcore_proto::dotcore::catalog::v1::{ Application, EngineRelease, HardwareClass, HardwareClassRecommendations, Model, - ModelEngineConfiguration, ParameterDefinition, ParameterValues, UpstreamModelTemplate, + ModelEngineConfiguration, ParameterDefinition, ParameterValues, ParameterVisibility, + UpstreamModelTemplate, }; use super::{ @@ -458,6 +459,29 @@ fn validate_sizing_coverage( .into_iter() .filter(|parameter_id| parameter_id != CONTEXT_PER_REQUEST_PARAMETER_ID) { + let hidden = profile.engine_parameter_visibility_overrides.iter().any( + |visibility_override| { + visibility_override.parameter_id == parameter_id + && visibility_override.visibility() == ParameterVisibility::Hidden + }, + ); + // A hidden parameter is one the operator can never set, so it needs a value + // on every binding and class. + if hidden + && class_bindings().any(|(hardware_class_id, binding)| { + !binding_sizing(hardware_class_id, &binding.binding_id) + .is_some_and(|sizing| sizing.derives(¶meter_id)) + }) + { + diagnostics.push(CatalogDiagnostic::new( + &location, + anyhow::anyhow!( + "profile {:?} hides engine parameter {parameter_id:?}, which has no default and which sizing does not derive on every binding and hardware class", + profile.profile_id + ), + )); + continue; + } for (hardware_class_id, binding) in class_bindings() { if !binding_sizing(hardware_class_id, &binding.binding_id) .is_some_and(|sizing| sizing.derives(¶meter_id)) diff --git a/backend/catalog/src/validation/model.rs b/backend/catalog/src/validation/model.rs index 04882982..3e46398b 100644 --- a/backend/catalog/src/validation/model.rs +++ b/backend/catalog/src/validation/model.rs @@ -14,8 +14,8 @@ use dotcore_proto::dotcore::catalog::v1::{ EngineArtifact, EngineRelease, HardwareClass, HuggingFaceArtifactSource, InferenceRequestKind, IntelligenceScore, License, Model, ModelArtifact, ModelConfigurationOption, ModelEngineConfiguration, ModelInputCapabilities, ModelInputModality, - ModelOptionParameterDefinition, ParameterValue, ParameterValues, SpeculativeDecodingMethod, - hugging_face_artifact_source::Content as HuggingFaceContent, + ModelOptionParameterDefinition, ModelProfile, ParameterValue, ParameterValues, + SpeculativeDecodingMethod, hugging_face_artifact_source::Content as HuggingFaceContent, model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, parameter_definition::ParameterType as EngineParameterType, @@ -30,7 +30,7 @@ use crate::{ valid_option_values, }, selector::{SelectorRelation, selector_relation}, - shared_parameters::profile_may_default, + shared_parameters::{profile_may_default, profile_visibility_problem}, typed_parameters::default_value, validation::{EngineDeclarationValidator, configuration_engine_release}, }; @@ -819,24 +819,7 @@ fn validate_profiles( let Some(engine) = configuration_engine_release(configuration, engines) else { continue; }; - if !profile.exposed_parameter_ids.is_empty() { - let mut exposed_ids = BTreeSet::new(); - let schema = engine.parameter_schema.as_ref(); - if profile.exposed_parameter_ids.iter().any(|parameter_id| { - !exposed_ids.insert(parameter_id) - || schema.is_none_or(|schema| { - !schema - .parameters - .iter() - .any(|definition| definition.parameter_id == *parameter_id) - }) - }) { - errors.push(anyhow::anyhow!( - "profile {:?} has invalid exposed engine parameters", - profile.profile_id - )); - } - } + validate_visibility_overrides(profile, engine, errors); match profile.engine_parameter_defaults.as_ref() { Some(values) => { validate_supplied_parameter_values(values, engine, &profile.profile_id, errors); @@ -868,6 +851,44 @@ fn validate_profiles( } } +/// Validates a profile's engine parameter visibility overrides: each names a parameter of the +/// engine release once, with a visibility the shared parameter rules allow for profiles. +fn validate_visibility_overrides( + profile: &ModelProfile, + engine: &EngineRelease, + errors: &mut Vec, +) { + let profile_id = &profile.profile_id; + let mut ids = BTreeSet::new(); + for visibility_override in &profile.engine_parameter_visibility_overrides { + let parameter_id = &visibility_override.parameter_id; + if !engine + .parameter_schema + .iter() + .flat_map(|schema| &schema.parameters) + .any(|definition| &definition.parameter_id == parameter_id) + { + errors.push(anyhow::anyhow!( + "profile {profile_id:?} overrides the visibility of engine parameter {parameter_id:?}, which is not a parameter of the engine release" + )); + continue; + } + if !ids.insert(parameter_id) { + errors.push(anyhow::anyhow!( + "profile {profile_id:?} overrides the visibility of engine parameter {parameter_id:?} more than once" + )); + continue; + } + if let Some(problem) = + profile_visibility_problem(parameter_id, visibility_override.visibility()) + { + errors.push(anyhow::anyhow!( + "profile {profile_id:?} engine parameter {parameter_id:?} {problem}" + )); + } + } +} + fn validate_profile_option_defaults( profile: &dotcore_proto::dotcore::catalog::v1::ModelProfile, configuration: &ModelEngineConfiguration, diff --git a/backend/core/tests/backend/catalog_contracts.rs b/backend/core/tests/backend/catalog_contracts.rs index ccfad32c..146855f1 100644 --- a/backend/core/tests/backend/catalog_contracts.rs +++ b/backend/core/tests/backend/catalog_contracts.rs @@ -2439,7 +2439,7 @@ fn catalog_retains_boolean_engine_parameters_and_their_schema() { } #[test] -fn catalog_rejects_mismatched_boolean_values_and_invalid_profile_exposure() { +fn catalog_rejects_mismatched_boolean_values_and_invalid_visibility_overrides() { let mut mismatched = synthetic_boolean_model(); mismatched.profiles[0] .engine_parameter_defaults @@ -2465,24 +2465,55 @@ fn catalog_rejects_mismatched_boolean_values_and_invalid_profile_exposure() { "unexpected validation error: {error}" ); - for exposed_parameter_ids in [ - vec!["total-context".to_owned(), "missing".to_owned()], - vec!["total-context".to_owned(), "total-context".to_owned()], + use ParameterVisibility::{Advanced, Basic, Hidden}; + + for (overrides, expected) in [ + ( + vec![("missing", Hidden)], + "profile \"balanced\" overrides the visibility of engine parameter \"missing\", which is not a parameter of the engine release", + ), + ( + vec![("feature-enabled", Hidden), ("feature-enabled", Advanced)], + "profile \"balanced\" overrides the visibility of engine parameter \"feature-enabled\" more than once", + ), + ( + vec![("total-context", Advanced)], + "profile \"balanced\" engine parameter \"total-context\" may be hidden but not advanced", + ), + ( + vec![("context-per-request", Advanced)], + "profile \"balanced\" engine parameter \"context-per-request\" may be hidden but not advanced", + ), + ( + vec![("feature-enabled", Basic)], + "profile \"balanced\" engine parameter \"feature-enabled\" may be advanced or hidden but not basic", + ), ] { let mut invalid = synthetic_boolean_model(); - invalid.profiles[0].exposed_parameter_ids = exposed_parameter_ids; + invalid.profiles[0].engine_parameter_visibility_overrides = + visibility_overrides(&overrides); let error = catalog_builder() .engine_validator(&ACCEPT_ENGINE_DECLARATIONS) .engine_release("engine.yaml", synthetic_boolean_engine_release()) .model("model.yaml", invalid) .build() - .expect_err("invalid profile exposure") + .expect_err("invalid visibility override") .to_string(); assert!( - error.contains("profile \"balanced\" has invalid exposed engine parameters"), + error.contains(expected), "unexpected validation error: {error}" ); } + + // A profile may hide the contexts, which the engine and resolution fill, and a parameter it + // defaults. + let mut valid = synthetic_boolean_model(); + valid.profiles[0].engine_parameter_visibility_overrides = visibility_overrides(&[ + ("total-context", Hidden), + ("context-per-request", Hidden), + ("feature-enabled", Hidden), + ]); + synthetic_boolean_catalog(valid); } /// Returns a fresh target of the production runtime kind for `platform`: Docker with an NVIDIA @@ -3150,7 +3181,8 @@ fn synthetic_sizing_catalog() -> Catalog { "#, &format!( r#" values: -{SIZING_ENGINE_CACHE_DEFAULT} exposedParameterIds: ["total-context", "prompt-cache-memory-mib", "parallel-requests"] +{SIZING_ENGINE_CACHE_DEFAULT} engineParameterVisibilityOverrides: + - {{ parameterId: "prompt-cache-memory-mib", visibility: "PARAMETER_VISIBILITY_ADVANCED" }} "# ), ); @@ -3208,10 +3240,24 @@ fn synthetic_boolean_model() -> Model { dotcore_proto::dotcore::catalog::v1::parameter_value::Value::Boolean(false), ), }); - profile.exposed_parameter_ids = vec!["total-context".to_owned(), "feature-enabled".to_owned()]; model } +/// Builds profile visibility overrides from parameter id and visibility pairs. +fn visibility_overrides( + overrides: &[(&str, ParameterVisibility)], +) -> Vec { + overrides + .iter() + .map(|(parameter_id, visibility)| { + dotcore_proto::dotcore::catalog::v1::ParameterVisibilityOverride { + parameter_id: (*parameter_id).to_owned(), + visibility: *visibility as i32, + } + }) + .collect() +} + fn synthetic_engine_release() -> EngineRelease { dotcore_proto::yaml::from_str( r#"engineReleaseId: "fixture-engine" diff --git a/backend/proto/tests/model_contract.rs b/backend/proto/tests/model_contract.rs index 02753841..023e9ac6 100644 --- a/backend/proto/tests/model_contract.rs +++ b/backend/proto/tests/model_contract.rs @@ -21,9 +21,10 @@ use dotcore_proto::{ ModelInputModality, ModelOption, ModelOptionParameterDefinition, ModelOptionParameterValue, ModelOptionValues, ModelParallelShape, ModelProfile, OciImageReference, OciPlatform, ParameterDefinition, ParameterValue, ParameterValues, - ParameterVisibility, Selector, StringEnumModelOptionParameterSchema, - UnsignedIntegerModelOptionParameterSchema, UnsignedIntegerParameterSchema, - VisionModelOption, engine_artifact, model_option::Kind as ModelOptionKind, + ParameterVisibility, ParameterVisibilityOverride, Selector, + StringEnumModelOptionParameterSchema, UnsignedIntegerModelOptionParameterSchema, + UnsignedIntegerParameterSchema, VisionModelOption, engine_artifact, + model_option::Kind as ModelOptionKind, model_option_parameter_definition::ParameterType as ModelOptionParameterType, model_option_parameter_value::Value as ModelOptionValueKind, parameter_definition::ParameterType as EngineParameterType, @@ -589,7 +590,10 @@ fn generated_bindings_round_trip_model_configurations_and_typed_context_schema() display_name: "Fast start".to_owned(), description: "Balances model quality and startup speed with Q4 weights.".to_owned(), option_defaults: Vec::new(), - exposed_parameter_ids: vec!["total-context".to_owned()], + engine_parameter_visibility_overrides: vec![ParameterVisibilityOverride { + parameter_id: "total-context".to_owned(), + visibility: ParameterVisibility::Hidden as i32, + }], }; let model = Model { model_id: "gemma-4-e2b".to_owned(), @@ -1153,10 +1157,17 @@ fn model_descriptors_define_typed_configuration_and_resolved_plan_contracts() { ("configuration_id", 2), ("default_model_artifact_binding_id", 3), ("engine_parameter_defaults", 4), + ("engine_parameter_visibility_overrides", 9), ("display_name", 5), ("description", 6), ("option_defaults", 7), - ("exposed_parameter_ids", 8), + ] + ); + assert_eq!( + field_layout(catalog, "ParameterVisibilityOverride"), + [ + ("parameter_id", 1, "TYPE_STRING"), + ("visibility", 2, ".dotcore.catalog.v1.ParameterVisibility"), ] ); assert_eq!( From 72e43bc026c4518f6719d9dd151743577760a2ce Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 14:01:53 -0500 Subject: [PATCH 07/40] unreviewed: feat(frontend): apply profile visibility overrides to engine parameters --- .../deploy/model-deploy-dialog.test.tsx | 28 ++++++++- .../src/features/models/model-test-support.ts | 4 +- .../runtime/engine-parameter-values.test.ts | 59 +++++++++++++++++++ .../models/runtime/engine-parameter-values.ts | 21 ++++--- .../test/catalog-model-site-contract.test.ts | 2 +- 5 files changed, 103 insertions(+), 11 deletions(-) diff --git a/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx b/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx index 46c66b29..c4f875c7 100644 --- a/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx +++ b/frontend/src/features/models/deploy/model-deploy-dialog.test.tsx @@ -46,8 +46,8 @@ import { EngineArtifactReferenceSchema, EngineReleaseSchema, } from "@/gen/dotcore/catalog/v1/engine_release_pb"; -import { ModelSchema } from "@/gen/dotcore/catalog/v1/model_pb"; -import { ParameterValueSchema } from "@/gen/dotcore/catalog/v1/parameter_pb"; +import { ModelSchema, type ParameterVisibilityOverride } from "@/gen/dotcore/catalog/v1/model_pb"; +import { ParameterValueSchema, ParameterVisibility } from "@/gen/dotcore/catalog/v1/parameter_pb"; import { MemoryFit } from "@/gen/dotcore/deployment/v1/memory_fit_pb"; import { ExactPlacementSchema } from "@/gen/dotcore/deployment/v1/placement_pb"; import { @@ -240,6 +240,30 @@ describe("ModelDeployDialog", () => { ); }); + it("follows the profile's visibility overrides on the Context and Runtime steps", async () => { + const user = setupUser(); + const overridden = clone(ModelSchema, multiParameterModel); + overridden.profiles[0].engineParameterVisibilityOverrides = [ + { parameterId: "total-context", visibility: ParameterVisibility.HIDDEN }, + { parameterId: "parallel-requests", visibility: ParameterVisibility.ADVANCED }, + { parameterId: "enable-prefix-caching", visibility: ParameterVisibility.HIDDEN }, + ] as ParameterVisibilityOverride[]; + renderDialog({ engineReleases: multiParameterReleases, model: overridden }); + + await screen.findByText("Step 1 of 3 — Profile"); + await enableAdvanced(user); + await user.click(screen.getByRole("button", { name: "Next" })); + await user.click(screen.getByRole("button", { name: "Next" })); + expect(screen.getByText("Step 3 of 5 — Context")).toBeVisible(); + expect(screen.getByText("This profile sets its context itself.")).toBeVisible(); + expect(screen.queryByText("Total context")).not.toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: "Next" })); + expect(screen.getByText("Step 4 of 5 — Runtime")).toBeVisible(); + expect(screen.getByRole("textbox", { name: "Parallel requests" })).toHaveValue("4"); + expect(screen.queryByText(/Other parameters/)).not.toBeInTheDocument(); + }); + it("reveals invalid parallel requests with Advanced instead of deploying", async () => { const user = setupUser(); const onSubmit = vi.fn(); diff --git a/frontend/src/features/models/model-test-support.ts b/frontend/src/features/models/model-test-support.ts index 32b87c51..a3ea00dd 100644 --- a/frontend/src/features/models/model-test-support.ts +++ b/frontend/src/features/models/model-test-support.ts @@ -105,6 +105,7 @@ export const multiParameterReleases = [ }, { parameterId: "parallel-requests", + visibility: ParameterVisibility.HIDDEN, displayName: "Parallel requests", parameterType: { case: "unsignedInteger", @@ -113,6 +114,7 @@ export const multiParameterReleases = [ }, { parameterId: "kv-cache-memory-bytes", + visibility: ParameterVisibility.HIDDEN, displayName: "KV cache memory", parameterType: { case: "unsignedInteger", @@ -121,6 +123,7 @@ export const multiParameterReleases = [ }, { parameterId: "enable-prefix-caching", + visibility: ParameterVisibility.ADVANCED, displayName: "Prefix caching", description: "Caches reusable prompt prefixes.", parameterType: { case: "boolean", value: {} }, @@ -159,7 +162,6 @@ export const multiParameterModel = create(ModelSchema, { description: "Runs the model through vLLM for text inference.", configurationId: "vllm-cuda", defaultModelArtifactBindingId: "nvfp4-binding", - exposedParameterIds: ["enable-prefix-caching", "total-context"], engineParameterDefaults: { values: [ { parameterId: "total-context", value: { case: "unsignedInteger", value: 32768n } }, diff --git a/frontend/src/features/models/runtime/engine-parameter-values.test.ts b/frontend/src/features/models/runtime/engine-parameter-values.test.ts index fde68253..3bc3cdb6 100644 --- a/frontend/src/features/models/runtime/engine-parameter-values.test.ts +++ b/frontend/src/features/models/runtime/engine-parameter-values.test.ts @@ -143,3 +143,62 @@ describe("starting values", () => { ).toEqual(["total-context", "flash-attention", "no-default"]); }); }); + +describe("effective visibility", () => { + const parameter = (parameterId: string, visibility: ParameterVisibility) => ({ + parameterId, + displayName: parameterId, + visibility, + parameterType: { + case: "unsignedInteger" as const, + value: { minimum: 1n, maximum: 10n, unit: "" }, + }, + }); + const release = create(EngineReleaseSchema, { + parameterSchema: { + parameters: [ + parameter("total-context", ParameterVisibility.BASIC), + parameter("parallel-requests", ParameterVisibility.ADVANCED), + parameter("kv-offload", ParameterVisibility.HIDDEN), + parameter("cache", ParameterVisibility.ADVANCED), + ], + }, + }); + const shown = (overrides: Array<[string, ParameterVisibility]>) => + effectiveEngineParameters( + release, + create(ModelProfileSchema, { + engineParameterVisibilityOverrides: overrides.map(([parameterId, visibility]) => ({ + parameterId, + visibility, + })), + }), + ).map((candidate) => candidate.parameterId); + + it("shows the engine's basic and advanced parameters in schema order", () => { + expect(shown([])).toEqual(["total-context", "parallel-requests", "cache"]); + }); + + it("lets a profile hide an advanced parameter", () => { + expect(shown([["parallel-requests", ParameterVisibility.HIDDEN]])).toEqual([ + "total-context", + "cache", + ]); + }); + + it("lets a profile show a hidden parameter, in schema order", () => { + expect(shown([["kv-offload", ParameterVisibility.ADVANCED]])).toEqual([ + "total-context", + "parallel-requests", + "kv-offload", + "cache", + ]); + }); + + it("lets a profile hide the total context", () => { + expect(shown([["total-context", ParameterVisibility.HIDDEN]])).toEqual([ + "parallel-requests", + "cache", + ]); + }); +}); diff --git a/frontend/src/features/models/runtime/engine-parameter-values.ts b/frontend/src/features/models/runtime/engine-parameter-values.ts index 40cc5228..1bdce73f 100644 --- a/frontend/src/features/models/runtime/engine-parameter-values.ts +++ b/frontend/src/features/models/runtime/engine-parameter-values.ts @@ -93,18 +93,25 @@ export function maximumContext( return known.length ? Math.min(...known) : undefined; } +/** + * The engine parameters the deploy dialog shows for `profile`, in schema order: each parameter's + * visibility is the engine's unless the profile overrides it, and hidden ones are left out. + */ export function effectiveEngineParameters( release: EngineRelease | undefined, profile: ModelProfile | undefined, ): ParameterDefinition[] { - const parameters = release?.parameterSchema?.parameters ?? []; - if (!profile?.exposedParameterIds.length) - return parameters.filter((parameter) => parameter.visibility !== ParameterVisibility.HIDDEN); + const overrides = new Map( + (profile?.engineParameterVisibilityOverrides ?? []).map((override) => [ + override.parameterId, + override.visibility, + ]), + ); - return profile.exposedParameterIds.flatMap((parameterId) => { - const parameter = parameters.find((candidate) => candidate.parameterId === parameterId); - return parameter ? [parameter] : []; - }); + return (release?.parameterSchema?.parameters ?? []).filter( + (parameter) => + (overrides.get(parameter.parameterId) ?? parameter.visibility) !== ParameterVisibility.HIDDEN, + ); } /** diff --git a/frontend/src/test/catalog-model-site-contract.test.ts b/frontend/src/test/catalog-model-site-contract.test.ts index 1a2f7e1f..332a7750 100644 --- a/frontend/src/test/catalog-model-site-contract.test.ts +++ b/frontend/src/test/catalog-model-site-contract.test.ts @@ -418,10 +418,10 @@ describe("desired site and current-state contracts", () => { "configuration_id", "default_model_artifact_binding_id", "engine_parameter_defaults", + "engine_parameter_visibility_overrides", "display_name", "description", "option_defaults", - "exposed_parameter_ids", ]); expect(ModelParallelShape.ONE).toBe(1); From 94bb3d38ee6e26337d29a82171bcdaa213cef126 Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 14:04:22 -0500 Subject: [PATCH 08/40] unreviewed: test(backend): expect the reported apple gpu model From 7e3cffda54debdf3bbce3a4602b31b30a626abfb Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 15:13:48 -0500 Subject: [PATCH 09/40] unreviewed: docs(catalog): describe shared parameter visibility and profile overrides --- AGENTS.md | 4 ++-- docs/specs/catalog.md | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 301d223f..2118c0ca 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -200,8 +200,8 @@ in the same change that adds, removes or renames a folder it lists. apart from site or development additions. - **model-local engine configuration**: one model's launch recipe on one engine (artifact bindings, approved engine artifacts, request kinds, sizing, hardware support). -- **model profile**: a preset of defaults for one engine configuration; never holds total context - or context per request. +- **model profile**: a preset of defaults and engine parameter visibility overrides for one engine + configuration; never holds a total context or context per request value. - **engine release**: one version of an engine (llama.cpp, vLLM) and the parameters it exposes. An **engine artifact** is one runnable build of it. - **hardware class**: a kind of execution hardware, nothing model-specific. **Hardware support** is diff --git a/docs/specs/catalog.md b/docs/specs/catalog.md index e9aea477..52f7e665 100644 --- a/docs/specs/catalog.md +++ b/docs/specs/catalog.md @@ -129,14 +129,16 @@ A preset of defaults for one engine configuration. - Supplies defaults, never ongoing deployment authority. - Supplies no default for total context or context per request. +- May override the default and the visibility of its engine's parameters. It may hide total context + and context per request, never make them advanced. - Carries no platform. The hardware class follows from the exact placement, so one profile serves every hardware class its configuration supports. ### Engine release - Declares the shared engine parameters (total context, context per request, parallel requests), - exposed, with a default on total context and parallel requests and none on context per request. - Each release sets its own bounds, defaults and descriptions. + with fixed visibilities, a default on total context and parallel requests and none on context per + request. Each release sets its own bounds, defaults and descriptions. - May declare parameter defaults within their bounds. A default on a parameter that sizing derives is rejected. @@ -169,7 +171,8 @@ minimums. ### App graph - Carries the app's portable artifact, configuration, storage, secret, dependency, readiness and - endpoint requirements, and its typed deployment parameters, shown as basic or advanced. + endpoint requirements, and its typed deployment parameters, shown as basic or advanced, never + hidden. - Engine releases and apps declare the storage they need. Deployments keep that declaration ([runtime](runtime.md)). @@ -182,7 +185,8 @@ The artifact manager also owns artifact bytes ([storage](storage.md)). #### Responsibilities - Own the immutable catalog declarations and their lifecycle. -- Own the shape of the shared engine parameters. +- Own the typed parameter definition engine releases and apps share, with its basic, advanced or + hidden visibility, and the shape of the shared engine parameters. - Validate catalogs as described above. #### Boundaries From 50d35e56eeb6a187c27cf83351540d9a3d7b36eb Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 17:14:54 -0500 Subject: [PATCH 10/40] unreviewed: docs(catalog): write operator-facing parameter descriptions --- catalog/applications/comfyui.yaml | 2 +- catalog/engines/llama-cpp-macos.yaml | 8 ++++---- catalog/engines/llama-cpp.yaml | 8 ++++---- catalog/engines/ninfer.yaml | 8 ++++---- catalog/engines/strata.yaml | 8 ++++---- catalog/engines/vllm.yaml | 14 +++++++------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/catalog/applications/comfyui.yaml b/catalog/applications/comfyui.yaml index f9a6a363..5dab581f 100644 --- a/catalog/applications/comfyui.yaml +++ b/catalog/applications/comfyui.yaml @@ -15,7 +15,7 @@ graph: - parameterId: "vram-mode" displayName: "VRAM mode" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "How ComfyUI keeps models in GPU memory. Auto loads and offloads on demand; modes other than auto need a GPU target." + description: "How ComfyUI keeps models in GPU memory. Leave it on auto to load and offload on demand; use another mode to force models to stay on the GPU or to save GPU memory, which needs a GPU target." stringEnum: values: ["auto", "highvram", "gpu-only", "novram"] defaultValue: "auto" diff --git a/catalog/engines/llama-cpp-macos.yaml b/catalog/engines/llama-cpp-macos.yaml index 63520d32..7b1cbbd6 100644 --- a/catalog/engines/llama-cpp-macos.yaml +++ b/catalog/engines/llama-cpp-macos.yaml @@ -12,7 +12,7 @@ parameterSchema: - parameterId: "total-context" displayName: "Total context" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Context memory the server holds from the start and shares among the requests it generates at once. Each active request stores its own tokens in it, even when requests start with the same prompt. When it fills, the server frees idle requests first, then fails the active ones." + description: "Memory the model holds for all requests at once; each active request stores its tokens in it, even when prompts start the same. Raise it to serve longer or more simultaneous conversations; when it fills, idle requests are dropped first, then active ones fail." unsignedInteger: minimum: "1024" maximum: "16777216" @@ -21,7 +21,7 @@ parameterSchema: - parameterId: "context-per-request" displayName: "Context per request" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the start of an earlier prompt from an idle request or the prompt cache, but not from requests running at the same time." + description: "Largest context one request may use. It reserves nothing: requests draw from the total context as they grow. Lower it to stop one long request from filling the total context." unsignedInteger: minimum: "1024" maximum: "16777216" @@ -29,7 +29,7 @@ parameterSchema: - parameterId: "parallel-requests" displayName: "Parallel requests" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Requests the server generates at the same time; further requests wait in a queue. All of them share the total context, so each added request only adds its own small state." + description: "Requests generated at once; more wait in a queue. They share the total context, so raising it adds little memory; raise it when several people or agents use the model together." unsignedInteger: minimum: "1" maximum: "64" @@ -38,7 +38,7 @@ parameterSchema: - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Memory kept to reuse repeated prompts, such as agent system prompts, without processing them again. Idle conversations move here and free their accelerator memory. It uses host memory, which unified-memory machines share with the model; 0 turns the cache off." + description: "Host memory used to reuse repeated prompts, such as agent system prompts, without processing them again. Raise it if the same long prompts come back often; on unified-memory machines it competes with the model, and 0 turns it off." unsignedInteger: minimum: "0" maximum: "65536" diff --git a/catalog/engines/llama-cpp.yaml b/catalog/engines/llama-cpp.yaml index 31b2ddb1..762c7ea1 100644 --- a/catalog/engines/llama-cpp.yaml +++ b/catalog/engines/llama-cpp.yaml @@ -11,7 +11,7 @@ parameterSchema: - parameterId: "total-context" displayName: "Total context" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Context memory the server holds from the start and shares among the requests it generates at once. Each active request stores its own tokens in it, even when requests start with the same prompt. When it fills, the server frees idle requests first, then fails the active ones." + description: "Memory the model holds for all requests at once; each active request stores its tokens in it, even when prompts start the same. Raise it to serve longer or more simultaneous conversations; when it fills, idle requests are dropped first, then active ones fail." unsignedInteger: minimum: "1024" maximum: "16777216" @@ -20,7 +20,7 @@ parameterSchema: - parameterId: "context-per-request" displayName: "Context per request" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the start of an earlier prompt from an idle request or the prompt cache, but not from requests running at the same time." + description: "Largest context one request may use. It reserves nothing: requests draw from the total context as they grow. Lower it to stop one long request from filling the total context." unsignedInteger: minimum: "1024" maximum: "16777216" @@ -28,7 +28,7 @@ parameterSchema: - parameterId: "parallel-requests" displayName: "Parallel requests" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Requests the server generates at the same time; further requests wait in a queue. All of them share the total context, so each added request only adds its own small state." + description: "Requests generated at once; more wait in a queue. They share the total context, so raising it adds little memory; raise it when several people or agents use the model together." unsignedInteger: minimum: "1" maximum: "64" @@ -37,7 +37,7 @@ parameterSchema: - parameterId: "prompt-cache-memory-mib" displayName: "Prompt cache memory" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Memory kept to reuse repeated prompts, such as agent system prompts, without processing them again. Idle conversations move here and free their accelerator memory. It uses host memory, which unified-memory machines share with the model; 0 turns the cache off." + description: "Host memory used to reuse repeated prompts, such as agent system prompts, without processing them again. Raise it if the same long prompts come back often; on unified-memory machines it competes with the model, and 0 turns it off." unsignedInteger: minimum: "0" maximum: "65536" diff --git a/catalog/engines/ninfer.yaml b/catalog/engines/ninfer.yaml index 45337575..8b97faf2 100644 --- a/catalog/engines/ninfer.yaml +++ b/catalog/engines/ninfer.yaml @@ -11,7 +11,7 @@ parameterSchema: - parameterId: "total-context" displayName: "Total context" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Context memory the server holds from the start and shares among the requests it generates at once. Requests that start with the same prompt share its memory instead of holding their own copy. When it fills, the server first moves cached prompts to host memory, then pauses the newest requests until memory frees up." + description: "Memory the model holds for all requests at once; requests that start with the same prompt share it. Raise it to serve longer or more simultaneous conversations; when it fills, cached prompts move to host memory, then the newest requests pause." unsignedInteger: minimum: "1024" maximum: "2097152" @@ -20,7 +20,7 @@ parameterSchema: - parameterId: "context-per-request" displayName: "Context per request" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the memory of a matching prompt start, from a running request, an idle conversation or the host context." + description: "Largest context one request may use. It reserves nothing: requests draw from the total context as they grow. Lower it to stop one long request from filling the total context." unsignedInteger: minimum: "1024" maximum: "262144" @@ -28,7 +28,7 @@ parameterSchema: - parameterId: "parallel-requests" displayName: "Parallel requests" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Requests the server generates at the same time; further requests wait in a queue, and the server refuses new ones once the queue is full. Each added request also adds its own state on the accelerator." + description: "Requests generated at once; more wait in a queue, and new ones are refused when the queue is full. Each added request uses some extra accelerator memory, so raise it only when several callers use the model together." unsignedInteger: minimum: "1" maximum: "8" @@ -37,7 +37,7 @@ parameterSchema: - parameterId: "host-context-mib" displayName: "Host context memory" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Host memory where idle conversations and paused requests are kept, so they resume without processing their prompt again. 0 turns it off." + description: "Host memory that keeps idle conversations and paused requests so they resume without processing their prompt again. Raise it for many long conversations that come back; 0 turns it off." unsignedInteger: minimum: "0" maximum: "1048576" diff --git a/catalog/engines/strata.yaml b/catalog/engines/strata.yaml index 50fb61bc..5cf5f06e 100644 --- a/catalog/engines/strata.yaml +++ b/catalog/engines/strata.yaml @@ -11,7 +11,7 @@ parameterSchema: - parameterId: "total-context" displayName: "Total context" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Context memory the server holds from the start. Each parallel request keeps its own part of it, as large as the context per request, so it is always the parallel requests times the context per request." + description: "Memory the model holds for all requests at once. Each parallel request gets its own share as large as the context per request, so it is always the parallel requests times the context per request; change those two instead." unsignedInteger: minimum: "1024" maximum: "2097152" @@ -20,7 +20,7 @@ parameterSchema: - parameterId: "context-per-request" displayName: "Context per request" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Largest context one request may use. The server holds this much context for each parallel request from the start, whether a request uses it or not." + description: "Largest context one request may use. The server sets this much aside for every parallel request from the start, used or not, so keep it as small as your longest request needs." unsignedInteger: minimum: "1024" maximum: "262144" @@ -28,7 +28,7 @@ parameterSchema: - parameterId: "parallel-requests" displayName: "Parallel requests" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Requests the server generates at the same time; further requests wait for a free one. Each one holds its own context per request." + description: "Requests generated at once; more wait for a free one. Each holds its own context per request, so raising it multiplies the memory used; raise it only when several callers use the model together." unsignedInteger: minimum: "1" maximum: "8" @@ -37,7 +37,7 @@ parameterSchema: - parameterId: "expert-vram-mib" displayName: "Expert accelerator memory" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Accelerator memory the model's experts may use; the experts that don't fit stay in host memory. The model's sizing sets it unless you do." + description: "Accelerator memory the model's experts may use; experts that don't fit stay in host memory and run slower. The model's sizing sets it; raise it to speed up generation if memory allows, or lower it to free accelerator memory." unsignedInteger: minimum: "1" maximum: "1048576" diff --git a/catalog/engines/vllm.yaml b/catalog/engines/vllm.yaml index ce4dfe10..053a0a38 100644 --- a/catalog/engines/vllm.yaml +++ b/catalog/engines/vllm.yaml @@ -11,7 +11,7 @@ parameterSchema: - parameterId: "total-context" displayName: "Total context" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Context memory the server holds from the start and shares among the requests it generates at once. Requests that start with the same prompt share its memory instead of holding their own copy. When it fills, the server pauses the newest requests and processes them again once memory frees up." + description: "Memory the model holds for all requests at once; requests that start with the same prompt share it. Raise it to serve longer or more simultaneous conversations; when it fills, the newest requests pause and are processed again once memory frees up." unsignedInteger: minimum: "1024" maximum: "16777216" @@ -20,7 +20,7 @@ parameterSchema: - parameterId: "context-per-request" displayName: "Context per request" visibility: "PARAMETER_VISIBILITY_BASIC" - description: "Largest context one request may use from the total context. It reserves nothing: requests take memory from the total context as they grow. A new request reuses the memory of a matching prompt start, from a running request, a finished one still held in the total context, or the KV offloading memory." + description: "Largest context one request may use. It reserves nothing: requests draw from the total context as they grow. Lower it to stop one long request from filling the total context." unsignedInteger: minimum: "1024" maximum: "1048576" @@ -28,7 +28,7 @@ parameterSchema: - parameterId: "parallel-requests" displayName: "Parallel requests" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Requests the server generates at the same time; further requests wait in a queue. They share the total context, and each one also holds model state of its own, so every added request adds memory." + description: "Requests generated at once; more wait in a queue. Each one also holds model state of its own, so every added request uses more memory; raise it when several callers use the model together." unsignedInteger: minimum: "1" maximum: "1024" @@ -37,7 +37,7 @@ parameterSchema: - parameterId: "maximum-batched-tokens" displayName: "Maximum batched tokens" visibility: "PARAMETER_VISIBILITY_HIDDEN" - description: "Maximum tokens processed across one scheduled batch." + description: "Most tokens processed in one step across all requests. Higher values read long prompts faster but use more memory; lower them if the model runs out of memory while reading prompts." unsignedInteger: minimum: "1" maximum: "1048576" @@ -45,7 +45,7 @@ parameterSchema: - parameterId: "maximum-cudagraph-capture-size" displayName: "Maximum CUDA graph capture size" visibility: "PARAMETER_VISIBILITY_HIDDEN" - description: "Largest sequence batch captured in a CUDA graph." + description: "Largest group of requests whose GPU work is recorded ahead of time for faster generation. Lower it to save a little memory and start-up time if you never run that many requests at once." unsignedInteger: minimum: "1" maximum: "1024" @@ -53,7 +53,7 @@ parameterSchema: - parameterId: "kv-cache-memory-bytes" displayName: "KV cache memory" visibility: "PARAMETER_VISIBILITY_HIDDEN" - description: "Accelerator memory reserved for the total context, in bytes." + description: "Accelerator memory set aside for the total context. The model's sizing sets it from the total context, so change it only to override that estimate." unsignedInteger: minimum: "1" maximum: "1099511627776" @@ -61,7 +61,7 @@ parameterSchema: - parameterId: "kv-offloading-size-gib" displayName: "KV offloading size" visibility: "PARAMETER_VISIBILITY_ADVANCED" - description: "Host memory where context evicted from the total context is kept, so a later request with the same prompt start reuses it instead of processing it again, in GiB. 0 turns it off." + description: "Host memory that keeps context evicted from the total context, so a later request with the same prompt start reuses it instead of processing it again. Raise it for long prompts that repeat; 0 turns it off." unsignedInteger: minimum: "0" maximum: "1024" From c7460b52bc4e95040342e2eda4e50cd488a926bc Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 17:17:56 -0500 Subject: [PATCH 11/40] unreviewed: feat(frontend): add a field primitive with a help popover --- .../src/components/parameters/parameters.tsx | 125 ++++++------- frontend/src/components/ui/field.test.tsx | 119 ++++++++++++ frontend/src/components/ui/field.tsx | 174 ++++++++++++++++++ .../application-deploy-dialog.test.tsx | 5 +- 4 files changed, 350 insertions(+), 73 deletions(-) create mode 100644 frontend/src/components/ui/field.test.tsx create mode 100644 frontend/src/components/ui/field.tsx diff --git a/frontend/src/components/parameters/parameters.tsx b/frontend/src/components/parameters/parameters.tsx index 48faaae7..802cda62 100644 --- a/frontend/src/components/parameters/parameters.tsx +++ b/frontend/src/components/parameters/parameters.tsx @@ -1,7 +1,7 @@ import type { RefObject } from "react"; import { Detail } from "@/components/ui/detail-list"; -import { FieldError } from "@/components/ui/field-error"; +import { Field } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select"; import { Switch } from "@/components/ui/switch"; @@ -37,100 +37,83 @@ export function ParametersForm({ parameters, }: ParametersFormProps) { return parameters.map((parameter) => { - const error = errors.get(parameter.id); const controlId = `${idPrefix}-${parameter.id}`; - const hintId = `${controlId}-description`; - const errorId = `${controlId}-error`; const unitId = `${controlId}-unit`; const unit = parameter.type.kind === "unsignedInteger" ? parameter.type.unit : ""; - const describedBy = - [parameter.hint ? hintId : "", unit ? unitId : "", error ? errorId : ""] - .filter(Boolean) - .join(" ") || undefined; + const field = { + controlId, + error: errors.get(parameter.id), + help: parameter.hint, + label: parameter.label, + }; const register = (control: HTMLElement | null) => { inputRefs.current.set(parameter.id, control); }; - const hint = parameter.hint ? ( - - {parameter.hint} - - ) : null; - const fieldError = error ? {error} : null; if (parameter.type.kind === "boolean") { return ( -
-
- + + {(control) => ( onBlur(parameter.id)} onCheckedChange={(checked) => onChange(parameter.id, String(checked))} ref={register} /> -
- {hint} - {fieldError} -
+ )} + ); } if (parameter.type.kind === "stringEnum") { + const { values } = parameter.type; return ( -
- - onBlur(parameter.id)} - onChange={(event) => onChange(parameter.id, event.target.value)} - ref={register} - value={inputs.get(parameter.id) ?? ""} - > - {parameter.type.values.map((value) => ( - - {value} - - ))} - - {hint} - {fieldError} -
+ + {(control) => ( + onBlur(parameter.id)} + onChange={(event) => onChange(parameter.id, event.target.value)} + ref={register} + value={inputs.get(parameter.id) ?? ""} + > + {values.map((value) => ( + + {value} + + ))} + + )} + ); } - const input = ( - onBlur(parameter.id)} - onChange={(event) => onChange(parameter.id, event.target.value)} - ref={register} - value={inputs.get(parameter.id) ?? ""} - /> - ); return ( -
- - {unit ? ( -
- {input} - - {unit} - -
- ) : ( - input - )} - {hint} - {fieldError} -
+ + {(control) => { + const input = ( + onBlur(parameter.id)} + onChange={(event) => onChange(parameter.id, event.target.value)} + ref={register} + value={inputs.get(parameter.id) ?? ""} + /> + ); + return unit ? ( +
+ {input} + + {unit} + +
+ ) : ( + input + ); + }} +
); }); } diff --git a/frontend/src/components/ui/field.test.tsx b/frontend/src/components/ui/field.test.tsx new file mode 100644 index 00000000..471cf918 --- /dev/null +++ b/frontend/src/components/ui/field.test.tsx @@ -0,0 +1,119 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; + +import { Field } from "@/components/ui/field"; +import { Input } from "@/components/ui/input"; +import { setTiming, timing } from "@/lib/timing"; +import { setupUser } from "@/test/user"; + +const help = "Requests generated at once; more wait in a queue."; + +function ParallelRequestsField({ error }: { error?: string }) { + return ( + <> + Use largest fit} + controlId="parallel" + error={error} + help={help} + label="Parallel requests" + > + {(control) => } + + + + ); +} + +function helpButton() { + return screen.getByRole("button", { name: "About Parallel requests" }); +} + +function helpPopover() { + return screen.queryByRole("dialog", { name: "About Parallel requests" }); +} + +describe("Field", () => { + it("names the control with its label and describes it with the help while the popover is closed", () => { + render(); + + const input = screen.getByRole("textbox", { name: "Parallel requests" }); + expect(helpPopover()).toBeNull(); + expect(input).toHaveAccessibleDescription(help); + expect(input).not.toHaveAttribute("aria-invalid"); + expect(screen.getByText(help)).not.toBeVisible(); + expect(screen.getByRole("button", { name: "Use largest fit" })).toBeVisible(); + }); + + it("describes an invalid control with its help, then its error", () => { + render(); + + const input = screen.getByRole("textbox", { name: "Parallel requests" }); + expect(input).toHaveAttribute("aria-invalid", "true"); + expect(input).toHaveAccessibleDescription(`${help} Enter a whole number.`); + expect(screen.getByRole("alert")).toHaveTextContent("Enter a whole number."); + }); + + it("opens the help on hover and closes it when the pointer leaves", async () => { + const user = setupUser(); + render(); + + await user.hover(helpButton()); + expect( + await screen.findByRole("dialog", { name: "About Parallel requests" }), + ).toHaveTextContent(help); + + await user.unhover(helpButton()); + await waitFor(() => expect(helpPopover()).toBeNull()); + }); + + it("opens the help on keyboard focus, keeps it on Enter and closes it on Tab away", async () => { + const user = setupUser(); + render(); + + await user.tab(); + expect(helpButton()).toHaveFocus(); + expect( + await screen.findByRole("dialog", { name: "About Parallel requests" }), + ).toHaveTextContent(help); + + await user.keyboard("{Enter}"); + expect(helpPopover()).not.toBeNull(); + expect(helpButton()).toHaveFocus(); + + await user.tab(); + expect(screen.getByRole("textbox", { name: "Parallel requests" })).toHaveFocus(); + await waitFor(() => expect(helpPopover()).toBeNull()); + }); + + it("opens the help on click and closes it on Escape", async () => { + // A hover delay longer than the test keeps the click the only way the help opens. + setTiming({ ...timing(), tooltipOpenMs: 60_000 }); + const user = setupUser(); + render(); + + await user.click(helpButton()); + expect( + await screen.findByRole("dialog", { name: "About Parallel requests" }), + ).toHaveTextContent(help); + + await user.keyboard("{Escape}"); + await waitFor(() => expect(helpPopover()).toBeNull()); + }); + + it("opens the help on tap and closes it on a tap outside", async () => { + const user = setupUser(); + render(); + + await user.pointer({ keys: "[TouchA]", target: helpButton() }); + expect( + await screen.findByRole("dialog", { name: "About Parallel requests" }), + ).toHaveTextContent(help); + + await user.pointer({ + keys: "[TouchA]", + target: screen.getByRole("button", { name: "Elsewhere" }), + }); + await waitFor(() => expect(helpPopover()).toBeNull()); + }); +}); diff --git a/frontend/src/components/ui/field.tsx b/frontend/src/components/ui/field.tsx new file mode 100644 index 00000000..ee9497b8 --- /dev/null +++ b/frontend/src/components/ui/field.tsx @@ -0,0 +1,174 @@ +import { CircleQuestionMark } from "lucide-react"; +import { type ReactNode, useRef, useState } from "react"; + +import { FieldError } from "@/components/ui/field-error"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; +import { timing } from "@/lib/timing"; +import { cn } from "@/lib/utils"; + +/** Props a field hands its control, so the label, help and error all point at it. */ +interface FieldControlProps { + "aria-describedby": string | undefined; + "aria-invalid": "true" | undefined; + id: string; +} + +interface FieldProps { + /** Buttons that change the value for the operator, shown under the control. */ + actions?: ReactNode; + /** Renders the control from the props it must carry. */ + children: (control: FieldControlProps) => ReactNode; + className?: string; + /** Element ID of the control; the description and error IDs derive from it. */ + controlId: string; + /** IDs of other elements describing the control, read after the help and before the error. */ + describedBy?: string; + error?: string; + /** What the field does and the facts that bound it, shown in the help popover. */ + help?: ReactNode; + label: string; + /** `inline` puts a compact control, such as a switch, on the label's row. */ + layout?: "inline" | "stacked"; +} + +/** + * One form field: its label with an optional help popover, the control, a validation error and + * buttons acting on the value. Help stays out of the layout; the control keeps it as its + * accessible description whether or not the popover is open. + */ +function Field({ + actions, + children, + className, + controlId, + describedBy, + error, + help, + label, + layout = "stacked", +}: FieldProps) { + const descriptionId = `${controlId}-description`; + const errorId = `${controlId}-error`; + const control = children({ + "aria-describedby": + [help ? descriptionId : "", describedBy ?? "", error ? errorId : ""] + .filter(Boolean) + .join(" ") || undefined, + "aria-invalid": error ? "true" : undefined, + id: controlId, + }); + const labelRow = ( +
+ + {help ? ( + + {help} + + ) : null} +
+ ); + + return ( +
+ {layout === "inline" ? ( +
+ {labelRow} + {control} +
+ ) : ( + <> + {labelRow} + {control} + + )} + {error ? {error} : null} + {actions ?
{actions}
: null} +
+ ); +} + +/** + * The `?` button beside a field label and its help popover. It opens on hover, keyboard focus, + * click and tap. Because the popover unmounts while closed, a hidden copy of the help carries + * `descriptionId` for the control's `aria-describedby`. + */ +function FieldHelp({ + children, + descriptionId, + label, +}: { + children: ReactNode; + descriptionId: string; + label: string; +}) { + const [open, setOpen] = useState(false); + const openedByFocus = useRef(false); + const pointerDown = useRef(false); + + const change = (nextOpen: boolean) => { + openedByFocus.current = false; + setOpen(nextOpen); + }; + + return ( + <> + { + // A press on a trigger that keyboard focus opened keeps the help open instead of + // toggling it shut. + if (!nextOpen && openedByFocus.current && details.reason === "trigger-press") { + openedByFocus.current = false; + return; + } + change(nextOpen); + }} + open={open} + > + { + pointerDown.current = false; + if (openedByFocus.current) change(false); + }} + onFocus={() => { + // A pointer press focuses the button too; its click opens the help instead. + if (pointerDown.current || open) return; + openedByFocus.current = true; + setOpen(true); + }} + onPointerDown={() => { + pointerDown.current = true; + }} + onPointerUp={() => { + pointerDown.current = false; + }} + onPointerCancel={() => { + pointerDown.current = false; + }} + openOnHover + type="button" + > + + + {children} + + + + + ); +} + +export { Field, FieldHelp }; +export type { FieldControlProps, FieldProps }; diff --git a/frontend/src/features/applications/application-deploy-dialog.test.tsx b/frontend/src/features/applications/application-deploy-dialog.test.tsx index dffc4a45..c000adca 100644 --- a/frontend/src/features/applications/application-deploy-dialog.test.tsx +++ b/frontend/src/features/applications/application-deploy-dialog.test.tsx @@ -1414,8 +1414,9 @@ describe("Application deployment dialog parameters", () => { const onSubmit = renderDialog(); const parameters = screen.getByRole("region", { name: "Parameters" }); - expect(within(parameters).getByRole("textbox", { name: "Workers" })).toHaveValue("2"); - expect(within(parameters).getByText("1–8")).toBeVisible(); + const workers = within(parameters).getByRole("textbox", { name: "Workers" }); + expect(workers).toHaveValue("2"); + expect(workers).toHaveAccessibleDescription("1–8"); expect(within(parameters).queryByRole("combobox", { name: "VRAM mode" })).toBeNull(); await user.click(screen.getByRole("checkbox", { name: "Advanced" })); From 3237f88b69ca092008bd33aea74ffac56b63a01a Mon Sep 17 00:00:00 2001 From: Andre-Philippe Paquet Date: Thu, 12 Nov 2026 17:26:04 -0500 Subject: [PATCH 12/40] unreviewed: feat(frontend): move deploy dialog help into field popovers --- .../components/parameters/parameter-view.ts | 4 +- .../components/parameters/parameters.test.tsx | 2 +- .../src/components/parameters/parameters.tsx | 25 +++-- frontend/src/components/ui/combobox.test.tsx | 32 +++++- frontend/src/components/ui/combobox.tsx | 72 ++++++++++--- frontend/src/components/ui/field.test.tsx | 22 ++++ frontend/src/components/ui/field.tsx | 22 ++-- frontend/src/components/ui/popover.tsx | 4 +- .../application-deploy-dialog.test.tsx | 6 +- .../application-deploy-dialog.tsx | 86 +++++++-------- .../applications/application-parameters.ts | 7 +- .../catalog/model-catalog-page.test.tsx | 6 +- .../deploy/model-deploy-context-step.tsx | 33 +++--- .../deploy/model-deploy-dialog.test.tsx | 41 +++++-- .../deploy/model-deploy-runtime-step.tsx | 5 - .../deploy/model-deploy-runtime.test.tsx | 41 +++++-- .../deploy/model-deploy-scenario.test.tsx | 53 +++++---- .../deploy/model-deploy-target-step.tsx | 2 +- .../models/deployment-exposure-fields.tsx | 15 ++- .../models/runtime/context-size-field.tsx | 102 +++++++++--------- .../models/runtime/engine-parameter-values.ts | 14 --- .../models/runtime/engine-parameters.tsx | 4 +- .../runtime/speculative-decoding-field.tsx | 98 +++++++++-------- .../upstream/upstream-endpoint-fields.tsx | 94 ++++++++-------- .../models/upstream/upstream-model.test.tsx | 37 ++++--- frontend/src/test/field-help.ts | 19 ++++ 26 files changed, 521 insertions(+), 325 deletions(-) create mode 100644 frontend/src/test/field-help.ts diff --git a/frontend/src/components/parameters/parameter-view.ts b/frontend/src/components/parameters/parameter-view.ts index 3ed8b17f..7611ea30 100644 --- a/frontend/src/components/parameters/parameter-view.ts +++ b/frontend/src/components/parameters/parameter-view.ts @@ -2,8 +2,8 @@ import { formatQuantity } from "@/lib/format"; /** One typed parameter as the shared form and details render it, independent of its owner. */ export interface ParameterView { - /** A short line under the field; absent when the label and value say enough. */ - hint?: string; + /** What the parameter does, shown in the field's help; absent when the label says enough. */ + description?: string; id: string; label: string; type: ParameterViewType; diff --git a/frontend/src/components/parameters/parameters.test.tsx b/frontend/src/components/parameters/parameters.test.tsx index 7d5d1259..e4e16b2d 100644 --- a/frontend/src/components/parameters/parameters.test.tsx +++ b/frontend/src/components/parameters/parameters.test.tsx @@ -38,7 +38,7 @@ describe("ParametersForm", () => { const cache = screen.getByRole("textbox", { name: "Prompt cache memory" }); expect(cache).toHaveValue("2048"); expect(cache.parentElement?.textContent).toBe("MiB"); - expect(cache).toHaveAccessibleDescription("MiB"); + expect(cache).not.toHaveAccessibleDescription(); const slots = screen.getByRole("textbox", { name: "Slots" }); expect(slots.parentElement?.textContent).toBe("Slots"); expect(slots).not.toHaveAccessibleDescription(); diff --git a/frontend/src/components/parameters/parameters.tsx b/frontend/src/components/parameters/parameters.tsx index 802cda62..01fb30d5 100644 --- a/frontend/src/components/parameters/parameters.tsx +++ b/frontend/src/components/parameters/parameters.tsx @@ -38,12 +38,11 @@ export function ParametersForm({ }: ParametersFormProps) { return parameters.map((parameter) => { const controlId = `${idPrefix}-${parameter.id}`; - const unitId = `${controlId}-unit`; const unit = parameter.type.kind === "unsignedInteger" ? parameter.type.unit : ""; const field = { controlId, error: errors.get(parameter.id), - help: parameter.hint, + help: parameter.description || undefined, label: parameter.label, }; const register = (control: HTMLElement | null) => { @@ -90,7 +89,13 @@ export function ParametersForm({ } return ( - + : null + } + key={parameter.id} + > {(control) => { const input = ( {input} - - {unit} - + {unit} ) : ( input @@ -118,6 +121,16 @@ export function ParametersForm({ }); } +/** The accepted range of a number parameter, with its unit when it has one. */ +function RangeFact({ type }: { type: { maximum: bigint; minimum: bigint; unit: string } }) { + return ( +

+ Range {`${type.minimum}–${type.maximum}`} + {type.unit ? ` ${type.unit}` : ""} +

+ ); +} + /** Detail rows for retained parameter values, in view order; a missing or mistyped value is skipped. */ export function ParametersDetails({ parameters, diff --git a/frontend/src/components/ui/combobox.test.tsx b/frontend/src/components/ui/combobox.test.tsx index f422c211..3748b2fe 100644 --- a/frontend/src/components/ui/combobox.test.tsx +++ b/frontend/src/components/ui/combobox.test.tsx @@ -38,7 +38,7 @@ function SingleCombobox({ loading={loading} loadingMessageVisible={loadingMessageVisible} searchable={searchable} - description="Choose one deployment." + help="Choose one deployment." /> {value ?? "none"} @@ -93,6 +93,36 @@ function MultipleCombobox({ } describe("Combobox", () => { + it("describes the input with its help and shows it in a popover beside the label", async () => { + const user = setupUser(); + render(); + + expect(screen.getByRole("combobox", { name: "Deployment" })).toHaveAccessibleDescription( + "Choose one deployment.", + ); + await user.click(screen.getByRole("button", { name: "About Deployment" })); + expect(await screen.findByRole("dialog", { name: "About Deployment" })).toHaveTextContent( + "Choose one deployment.", + ); + }); + + it("shows its status under the input and in the input's description", () => { + render( + {}} + options={options} + status="Loading deployments…" + value={null} + />, + ); + + expect(screen.getByText("Loading deployments…")).toBeVisible(); + expect(screen.getByRole("combobox", { name: "Deployment" })).toHaveAccessibleDescription( + "Loading deployments…", + ); + }); + it("filters options by label and stable ID", async () => { const user = setupUser(); render(); diff --git a/frontend/src/components/ui/combobox.tsx b/frontend/src/components/ui/combobox.tsx index 12ff9d66..0563af0a 100644 --- a/frontend/src/components/ui/combobox.tsx +++ b/frontend/src/components/ui/combobox.tsx @@ -2,6 +2,7 @@ import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox"; import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react"; import * as React from "react"; +import { FieldHelp } from "@/components/ui/field"; import { useInspectorFloatingLayerRegistration } from "@/components/ui/inspector-shell"; import { ResourceMarker } from "@/components/ui/resource-marker"; import { StatusDot } from "@/components/ui/status-badge"; @@ -31,9 +32,10 @@ type ComboboxSharedProps = { options: readonly ComboboxOption[]; ariaInvalid?: boolean; className?: string; - description?: string; disabled?: boolean; errorDescriptionId?: string; + /** What the field does, shown in a help popover beside the label. */ + help?: string; /** Keeps the label for assistive technology only, where the surrounding layout names the field. */ hideLabel?: boolean; inputRef?: React.Ref; @@ -41,6 +43,8 @@ type ComboboxSharedProps = { loadingMessageVisible?: boolean; onBlur?: React.FocusEventHandler; placeholder?: string; + /** The field's current state, such as that its options are loading, shown under the input. */ + status?: string; }; type SingleComboboxProps = ComboboxSharedProps & { @@ -77,9 +81,9 @@ function SingleCombobox({ ariaInvalid, className, clearable = true, - description, disabled, errorDescriptionId, + help, hideLabel = false, inputRef, label, @@ -90,12 +94,18 @@ function SingleCombobox({ options, placeholder, searchable = true, + status, value, }: SingleComboboxProps) { const descriptionId = React.useId(); const inputId = React.useId(); const labelId = React.useId(); - const describedBy = [description ? descriptionId : undefined, errorDescriptionId] + const statusId = React.useId(); + const describedBy = [ + help ? descriptionId : undefined, + status ? statusId : undefined, + errorDescriptionId, + ] .filter(Boolean) .join(" "); const registerFloatingLayer = useInspectorFloatingLayerRegistration(); @@ -111,7 +121,14 @@ function SingleCombobox({ value={value} >
-
@@ -152,9 +169,9 @@ function MultipleCombobox({ ariaInvalid, className, closeOnSelect = false, - description, disabled, errorDescriptionId, + help, hideLabel = false, inputRef, label, @@ -164,12 +181,18 @@ function MultipleCombobox({ onValueChange, options, placeholder = "Search options", + status, value, }: MultipleComboboxProps) { const descriptionId = React.useId(); const inputId = React.useId(); const labelId = React.useId(); - const describedBy = [description ? descriptionId : undefined, errorDescriptionId] + const statusId = React.useId(); + const describedBy = [ + help ? descriptionId : undefined, + status ? statusId : undefined, + errorDescriptionId, + ] .filter(Boolean) .join(" "); const optionLabel = createOptionLabel(options); @@ -206,7 +229,14 @@ function MultipleCombobox({ value={value} >
-
@@ -275,17 +305,21 @@ function MultipleCombobox({ * technology, label included, and only a label reference survives that hiding. */ function ComboboxLabel({ + descriptionId, + help, hidden, id, inputId, label, }: { + descriptionId: string; + help?: string; hidden: boolean; id: string; inputId: string; label: string; }) { - return ( + const labelElement = (